r1345: add extended security spnego support to the smb client
[samba.git] / source4 / param / loadparm.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Parameter loading functions
4    Copyright (C) Karl Auer 1993-1998
5
6    Largely re-written by Andrew Tridgell, September 1994
7
8    Copyright (C) Simo Sorce 2001
9    Copyright (C) Alexander Bokovoy 2002
10    Copyright (C) Stefan (metze) Metzmacher 2002
11    Copyright (C) Anthony Liguori 2003
12    Copyright (C) James Myers 2003 <myersjj@samba.org>
13    
14    This program is free software; you can redistribute it and/or modify
15    it under the terms of the GNU General Public License as published by
16    the Free Software Foundation; either version 2 of the License, or
17    (at your option) any later version.
18    
19    This program is distributed in the hope that it will be useful,
20    but WITHOUT ANY WARRANTY; without even the implied warranty of
21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22    GNU General Public License for more details.
23    
24    You should have received a copy of the GNU General Public License
25    along with this program; if not, write to the Free Software
26    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 */
28
29 /*
30  *  Load parameters.
31  *
32  *  This module provides suitable callback functions for the params
33  *  module. It builds the internal table of service details which is
34  *  then used by the rest of the server.
35  *
36  * To add a parameter:
37  *
38  * 1) add it to the global or service structure definition
39  * 2) add it to the parm_table
40  * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
41  * 4) If it's a global then initialise it in init_globals. If a local
42  *    (ie. service) parameter then initialise it in the sDefault structure
43  *  
44  *
45  * Notes:
46  *   The configuration file is processed sequentially for speed. It is NOT
47  *   accessed randomly as happens in 'real' Windows. For this reason, there
48  *   is a fair bit of sequence-dependent code here - ie., code which assumes
49  *   that certain things happen before others. In particular, the code which
50  *   happens at the boundary between sections is delicately poised, so be
51  *   careful!
52  *
53  */
54
55 #include "includes.h"
56
57 BOOL in_client = False;         /* Not in the client by default */
58 static BOOL bLoaded = False;
59
60 #ifndef GLOBAL_NAME
61 #define GLOBAL_NAME "global"
62 #endif
63
64 #ifndef PRINTERS_NAME
65 #define PRINTERS_NAME "printers"
66 #endif
67
68 #ifndef HOMES_NAME
69 #define HOMES_NAME "homes"
70 #endif
71
72 /* some helpful bits */
73 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && ServicePtrs[(i)]->valid)
74 #define VALID(i) ServicePtrs[i]->valid
75
76 static BOOL do_parameter(const char *, const char *);
77
78 static BOOL defaults_saved = False;
79
80 struct param_opt {
81         struct param_opt *prev, *next;
82         char *key;
83         char *value;
84         int flags;
85 };
86
87 /* 
88  * This structure describes global (ie., server-wide) parameters.
89  */
90 typedef struct
91 {
92         char *smb_ports;
93         char *dos_charset;
94         char *unix_charset;
95         char *display_charset;
96         char *szPrintcapname;
97         char *szLockDir;
98         char *szPidDir;
99         char *szRootdir;
100         char *szDefaultService;
101         char *szHostsEquiv;
102         char *szServerString;
103         char *szAutoServices;
104         char *szPasswdProgram;
105         char *szPasswdChat;
106         char *szLogFile;
107         char *szConfigFile;
108         char *szSMBPasswdFile;
109         char *szSAM_URL;
110         char *szSPOOLSS_URL;
111         char *szPrivateDir;
112         char **szPassdbBackend;
113         char **szPreloadModules;
114         char *szPasswordServer;
115         char *szSocketOptions;
116         char *szRealm;
117         char *szADSserver;
118         char *szLogonScript;
119         char *szLogonPath;
120         char *szLogonDrive;
121         char *szLogonHome;
122         char **szWINSservers;
123         char **szInterfaces;
124         char *szRemoteAnnounce;
125         char *szRemoteBrowseSync;
126         char *szSocketAddress;
127         char *szAnnounceVersion;        /* This is initialised in init_globals */
128         char *szWorkgroup;
129         char *szNetbiosName;
130         char **szNetbiosAliases;
131         char *szNetbiosScope;
132         char *szDomainOtherSIDs;
133         char *szNameResolveOrder;
134         char *szPanicAction;
135         char *szAddUserScript; 
136         char *szAddMachineScript;
137         char *szWINSHook;
138         char *szWINSPartners;
139         char **dcerpc_ep_servers;
140         char *szWinbindUID;
141         char *szWinbindGID;
142         char *szNonUnixAccountRange;
143         char *szTemplateHomedir;
144         char *szTemplateShell;
145         char *szWinbindSeparator;
146         BOOL bWinbindEnumUsers;
147         BOOL bWinbindEnumGroups;
148         BOOL bWinbindUseDefaultDomain;
149         char *szIDMapBackend;
150         char *szGuestaccount;
151         int mangled_stack;
152         int max_mux;
153         int max_xmit;
154         int pwordlevel;
155         int unamelevel;
156         int maxprotocol;
157         int minprotocol;
158         int security;
159         char **AuthMethods;
160         BOOL paranoid_server_security;
161         int lpqcachetime;
162         BOOL bDisableSpoolss;
163         int os_level;
164         int enhanced_browsing;
165         int time_offset;
166         int max_ttl;
167         int max_wins_ttl;
168         int min_wins_ttl;
169         int lm_announce;
170         int lm_interval;
171         int announce_as;        /* This is initialised in init_globals */
172         int machine_password_timeout;
173         int winbind_cache_time;
174         int iLockSpinCount;
175         int iLockSpinTime;
176         char *szLdapMachineSuffix;
177         char *szLdapUserSuffix;
178 #ifdef WITH_LDAP_SAMCONFIG
179         int ldap_port;
180         char *szLdapServer;
181 #endif
182         char *socket_options;
183         int ldap_ssl;
184         char *szLdapSuffix;
185         char *szLdapFilter;
186         char *szLdapAdminDn;
187         BOOL ldap_trust_ids;
188         int ldap_passwd_sync; 
189         BOOL bDNSproxy;
190         BOOL bWINSsupport;
191         BOOL bWINSproxy;
192         BOOL bLocalMaster;
193         BOOL bPreferredMaster;
194         BOOL bDomainMaster;
195         BOOL bDomainLogons;
196         BOOL bEncryptPasswords;
197         BOOL bUpdateEncrypt;
198         BOOL bNullPasswords;
199         BOOL bObeyPamRestrictions;
200         BOOL bLoadPrinters;
201         BOOL bLargeReadwrite;
202         BOOL bReadRaw;
203         BOOL bWriteRaw;
204         BOOL bTimeServer;
205         BOOL bBindInterfacesOnly;
206         BOOL bPamPasswordChange;
207         BOOL bUnixPasswdSync;
208         BOOL bNTSmbSupport;
209         BOOL bNTStatusSupport;
210         BOOL bAllowTrustedDomains;
211         BOOL bLanmanAuth;
212         BOOL bNTLMAuth;
213         BOOL bUseSpnego;
214         BOOL server_signing;
215         BOOL bClientLanManAuth;
216         BOOL bClientNTLMv2Auth;
217         BOOL bHostMSDfs;
218         BOOL bHideLocalUsers;
219         BOOL bUnicode;
220         BOOL bUseMmap;
221         BOOL bHostnameLookups;
222         BOOL bUnixExtensions;
223         BOOL bDisableNetbios;
224         BOOL bRpcBigEndian;
225         int restrict_anonymous;
226         int name_cache_timeout;
227         struct param_opt *param_opt;
228 }
229 global;
230
231 static global Globals;
232
233 /* 
234  * This structure describes a single service. 
235  */
236 typedef struct
237 {
238         BOOL valid;
239         BOOL autoloaded;
240         char *szService;
241         char *szPath;
242         char *szUsername;
243         char **szInvalidUsers;
244         char **szValidUsers;
245         char **szAdminUsers;
246         char *szCopy;
247         char *szInclude;
248         char *szPrintcommand;
249         char *szLpqcommand;
250         char *szLprmcommand;
251         char *szLppausecommand;
252         char *szLpresumecommand;
253         char *szQueuepausecommand;
254         char *szQueueresumecommand;
255         char *szPrintername;
256         char **szHostsallow;
257         char **szHostsdeny;
258         char *comment;
259         char *volume;
260         char *fstype;
261         char *szMSDfsProxy;
262         char *ntvfs_handler;
263         int iMinPrintSpace;
264         int iMaxPrintJobs;
265         int iMaxConnections;
266         int iPrinting;
267         int iCSCPolicy;
268         BOOL bAvailable;
269         BOOL bBrowseable;
270         BOOL bRead_only;
271         BOOL bPrint_ok;
272         BOOL bMap_system;
273         BOOL bMap_hidden;
274         BOOL bMap_archive;
275         BOOL bLocking;
276         BOOL bStrictLocking;
277         BOOL bPosixLocking;
278         BOOL bOpLocks;
279         BOOL bLevel2OpLocks;
280         BOOL bOnlyUser;
281         BOOL bGuest_only;
282         BOOL bGuest_ok;
283         BOOL *copymap;
284         BOOL bMSDfsRoot;
285         BOOL bShareModes;
286         struct param_opt *param_opt;
287
288         char dummy[3];          /* for alignment */
289 }
290 service;
291
292
293 /* This is a default service used to prime a services structure */
294 static service sDefault = {
295         True,                   /* valid */
296         False,                  /* not autoloaded */
297         NULL,                   /* szService */
298         NULL,                   /* szPath */
299         NULL,                   /* szUsername */
300         NULL,                   /* szInvalidUsers */
301         NULL,                   /* szValidUsers */
302         NULL,                   /* szAdminUsers */
303         NULL,                   /* szCopy */
304         NULL,                   /* szInclude */
305         NULL,                   /* szPrintcommand */
306         NULL,                   /* szLpqcommand */
307         NULL,                   /* szLprmcommand */
308         NULL,                   /* szLppausecommand */
309         NULL,                   /* szLpresumecommand */
310         NULL,                   /* szQueuepausecommand */
311         NULL,                   /* szQueueresumecommand */
312         NULL,                   /* szPrintername */
313         NULL,                   /* szHostsallow */
314         NULL,                   /* szHostsdeny */
315         NULL,                   /* comment */
316         NULL,                   /* volume */
317         NULL,                   /* fstype */
318         NULL,                   /* szMSDfsProxy */
319         NULL,                   /* ntvfs_handler */
320         0,                      /* iMinPrintSpace */
321         1000,                   /* iMaxPrintJobs */
322         0,                      /* iMaxConnections */
323         DEFAULT_PRINTING,       /* iPrinting */
324         0,                      /* iCSCPolicy */
325         True,                   /* bAvailable */
326         True,                   /* bBrowseable */
327         True,                   /* bRead_only */
328         False,                  /* bPrint_ok */
329         False,                  /* bMap_system */
330         False,                  /* bMap_hidden */
331         True,                   /* bMap_archive */
332         True,                   /* bLocking */
333         True,                   /* bStrictLocking */
334         True,                   /* bPosixLocking */
335         True,                   /* bOpLocks */
336         True,                   /* bLevel2OpLocks */
337         False,                  /* bOnlyUser */
338         False,                  /* bGuest_only */
339         False,                  /* bGuest_ok */
340         NULL,                   /* copymap */
341         False,                  /* bMSDfsRoot */
342         True,                   /* bShareModes */
343         NULL,                   /* Parametric options */
344
345         ""                      /* dummy */
346 };
347
348 /* local variables */
349 static service **ServicePtrs = NULL;
350 static int iNumServices = 0;
351 static int iServiceIndex = 0;
352 static BOOL bInGlobalSection = True;
353 static BOOL bGlobalOnly = False;
354 static int server_role;
355 static int default_server_announce;
356
357 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
358
359 /* prototypes for the special type handlers */
360 static BOOL handle_include(const char *pszParmValue, char **ptr);
361 static BOOL handle_copy(const char *pszParmValue, char **ptr);
362 static BOOL handle_winbind_uid(const char *pszParmValue, char **ptr);
363 static BOOL handle_winbind_gid(const char *pszParmValue, char **ptr);
364 static BOOL handle_non_unix_account_range(const char *pszParmValue, char **ptr);
365
366 static BOOL handle_ldap_machine_suffix ( const char *pszParmValue, char **ptr );
367 static BOOL handle_ldap_user_suffix ( const char *pszParmValue, char **ptr );
368 static BOOL handle_ldap_suffix ( const char *pszParmValue, char **ptr );
369
370 static void set_server_role(void);
371 static void set_default_server_announce_type(void);
372
373 static const struct enum_list enum_protocol[] = {
374         {PROTOCOL_NT1, "NT1"},
375         {PROTOCOL_LANMAN2, "LANMAN2"},
376         {PROTOCOL_LANMAN1, "LANMAN1"},
377         {PROTOCOL_CORE, "CORE"},
378         {PROTOCOL_COREPLUS, "COREPLUS"},
379         {PROTOCOL_COREPLUS, "CORE+"},
380         {-1, NULL}
381 };
382
383 static const struct enum_list enum_security[] = {
384         {SEC_SHARE, "SHARE"},
385         {SEC_USER, "USER"},
386         {SEC_SERVER, "SERVER"},
387         {SEC_DOMAIN, "DOMAIN"},
388 #ifdef HAVE_ADS
389         {SEC_ADS, "ADS"},
390 #endif
391         {-1, NULL}
392 };
393
394 static const struct enum_list enum_printing[] = {
395         {PRINT_SYSV, "sysv"},
396         {PRINT_AIX, "aix"},
397         {PRINT_HPUX, "hpux"},
398         {PRINT_BSD, "bsd"},
399         {PRINT_QNX, "qnx"},
400         {PRINT_PLP, "plp"},
401         {PRINT_LPRNG, "lprng"},
402         {PRINT_SOFTQ, "softq"},
403         {PRINT_CUPS, "cups"},
404         {PRINT_LPRNT, "nt"},
405         {PRINT_LPROS2, "os2"},
406 #ifdef DEVELOPER
407         {PRINT_TEST, "test"},
408         {PRINT_VLP, "vlp"},
409 #endif /* DEVELOPER */
410         {-1, NULL}
411 };
412
413 static const struct enum_list enum_ldap_ssl[] = {
414 #ifdef WITH_LDAP_SAMCONFIG
415         {LDAP_SSL_ON, "Yes"},
416         {LDAP_SSL_ON, "yes"},
417         {LDAP_SSL_ON, "on"},
418         {LDAP_SSL_ON, "On"},
419 #endif
420         {LDAP_SSL_OFF, "no"},
421         {LDAP_SSL_OFF, "No"},
422         {LDAP_SSL_OFF, "off"},
423         {LDAP_SSL_OFF, "Off"},
424         {LDAP_SSL_START_TLS, "start tls"},
425         {LDAP_SSL_START_TLS, "Start_tls"},
426         {-1, NULL}
427 };
428
429 static const struct enum_list enum_ldap_passwd_sync[] = {
430         {LDAP_PASSWD_SYNC_ON, "Yes"},
431         {LDAP_PASSWD_SYNC_ON, "yes"},
432         {LDAP_PASSWD_SYNC_ON, "on"},
433         {LDAP_PASSWD_SYNC_ON, "On"},
434         {LDAP_PASSWD_SYNC_OFF, "no"},
435         {LDAP_PASSWD_SYNC_OFF, "No"},
436         {LDAP_PASSWD_SYNC_OFF, "off"},
437         {LDAP_PASSWD_SYNC_OFF, "Off"},
438 #ifdef LDAP_EXOP_X_MODIFY_PASSWD        
439         {LDAP_PASSWD_SYNC_ONLY, "Only"},
440         {LDAP_PASSWD_SYNC_ONLY, "only"},
441 #endif /* LDAP_EXOP_X_MODIFY_PASSWD */  
442         {-1, NULL}
443 };
444
445 /* Types of machine we can announce as. */
446 #define ANNOUNCE_AS_NT_SERVER 1
447 #define ANNOUNCE_AS_WIN95 2
448 #define ANNOUNCE_AS_WFW 3
449 #define ANNOUNCE_AS_NT_WORKSTATION 4
450
451 static const struct enum_list enum_announce_as[] = {
452         {ANNOUNCE_AS_NT_SERVER, "NT"},
453         {ANNOUNCE_AS_NT_SERVER, "NT Server"},
454         {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"},
455         {ANNOUNCE_AS_WIN95, "win95"},
456         {ANNOUNCE_AS_WFW, "WfW"},
457         {-1, NULL}
458 };
459
460 static const struct enum_list enum_case[] = {
461         {CASE_LOWER, "lower"},
462         {CASE_UPPER, "upper"},
463         {-1, NULL}
464 };
465
466 static const struct enum_list enum_bool_auto[] = {
467         {False, "No"},
468         {False, "False"},
469         {False, "0"},
470         {True, "Yes"},
471         {True, "True"},
472         {True, "1"},
473         {Auto, "Auto"},
474         {-1, NULL}
475 };
476
477 /* Client-side offline caching policy types */
478 #define CSC_POLICY_MANUAL 0
479 #define CSC_POLICY_DOCUMENTS 1
480 #define CSC_POLICY_PROGRAMS 2
481 #define CSC_POLICY_DISABLE 3
482
483 static const struct enum_list enum_csc_policy[] = {
484         {CSC_POLICY_MANUAL, "manual"},
485         {CSC_POLICY_DOCUMENTS, "documents"},
486         {CSC_POLICY_PROGRAMS, "programs"},
487         {CSC_POLICY_DISABLE, "disable"},
488         {-1, NULL}
489 };
490
491 /* SMB signing types. */
492 static const struct enum_list enum_smb_signing_vals[] = {
493         {SMB_SIGNING_OFF, "No"},
494         {SMB_SIGNING_OFF, "False"},
495         {SMB_SIGNING_OFF, "0"},
496         {SMB_SIGNING_OFF, "Off"},
497         {SMB_SIGNING_OFF, "disabled"},
498         {SMB_SIGNING_SUPPORTED, "Yes"},
499         {SMB_SIGNING_SUPPORTED, "True"},
500         {SMB_SIGNING_SUPPORTED, "1"},
501         {SMB_SIGNING_SUPPORTED, "On"},
502         {SMB_SIGNING_SUPPORTED, "enabled"},
503         {SMB_SIGNING_SUPPORTED, "auto"},
504         {SMB_SIGNING_REQUIRED, "required"},
505         {SMB_SIGNING_REQUIRED, "mandatory"},
506         {SMB_SIGNING_REQUIRED, "force"},
507         {SMB_SIGNING_REQUIRED, "forced"},
508         {SMB_SIGNING_REQUIRED, "enforced"},
509         {-1, NULL}
510 };
511
512 /* 
513    Do you want session setups at user level security with a invalid
514    password to be rejected or allowed in as guest? WinNT rejects them
515    but it can be a pain as it means "net view" needs to use a password
516
517    You have 3 choices in the setting of map_to_guest:
518
519    "Never" means session setups with an invalid password
520    are rejected. This is the default.
521
522    "Bad User" means session setups with an invalid password
523    are rejected, unless the username does not exist, in which case it
524    is treated as a guest login
525
526    "Bad Password" means session setups with an invalid password
527    are treated as a guest login
528
529    Note that map_to_guest only has an effect in user or server
530    level security.
531 */
532
533 static const struct enum_list enum_map_to_guest[] = {
534         {NEVER_MAP_TO_GUEST, "Never"},
535         {MAP_TO_GUEST_ON_BAD_USER, "Bad User"},
536         {MAP_TO_GUEST_ON_BAD_PASSWORD, "Bad Password"},
537         {-1, NULL}
538 };
539
540 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
541  *
542  * Note: We have a flag called FLAG_DEVELOPER but is not used at this time, it
543  * is implied in current control logic. This may change at some later time. A
544  * flag value of 0 means - show as development option only.
545  *
546  * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
547  * screen in SWAT. This is used to exclude parameters as well as to squash all
548  * parameters that have been duplicated by pseudonyms.
549  */
550 static struct parm_struct parm_table[] = {
551         {"Base Options", P_SEP, P_SEPARATOR},
552
553         {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
554         {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
555         {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
556         {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
557         {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
558         {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE},
559         {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkgroup, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
560         {"realm", P_USTRING, P_GLOBAL, &Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
561         {"ADS server", P_STRING, P_GLOBAL, &Globals.szADSserver, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
562         {"netbios name", P_USTRING, P_GLOBAL, &Globals.szNetbiosName, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
563         {"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
564         {"netbios scope", P_USTRING, P_GLOBAL, &Globals.szNetbiosScope, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
565         {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED  | FLAG_DEVELOPER},
566         {"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
567         {"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
568         {"ntvfs handler", P_STRING, P_LOCAL, &sDefault.ntvfs_handler, NULL, NULL, FLAG_ADVANCED},
569         {"dcerpc endpoint servers", P_LIST, P_GLOBAL, &Globals.dcerpc_ep_servers, NULL, NULL, FLAG_ADVANCED},
570
571         {"Security Options", P_SEP, P_SEPARATOR},
572         
573         {"security", P_ENUM, P_GLOBAL, &Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
574         {"auth methods", P_LIST, P_GLOBAL, &Globals.AuthMethods, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
575         {"encrypt passwords", P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
576         {"update encrypted", P_BOOL, P_GLOBAL, &Globals.bUpdateEncrypt, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
577         {"allow trusted domains", P_BOOL, P_GLOBAL, &Globals.bAllowTrustedDomains, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
578         {"hosts equiv", P_STRING, P_GLOBAL, &Globals.szHostsEquiv, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
579         {"idmap backend", P_STRING, P_GLOBAL, &Globals.szIDMapBackend, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
580         {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
581         {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
582         {"password server", P_STRING, P_GLOBAL, &Globals.szPasswordServer, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
583         {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
584         {"sam database", P_STRING, P_GLOBAL, &Globals.szSAM_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
585         {"spoolss database", P_STRING, P_GLOBAL, &Globals.szSPOOLSS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
586         {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
587         {"passdb backend", P_LIST, P_GLOBAL, &Globals.szPassdbBackend, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
588         {"non unix account range", P_STRING, P_GLOBAL, &Globals.szNonUnixAccountRange, handle_non_unix_account_range, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
589         {"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
590         {"root dir", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
591         {"root", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_HIDE | FLAG_DEVELOPER},
592         {"guest account", P_STRING, P_GLOBAL, &Globals.szGuestaccount, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
593         
594         {"pam password change", P_BOOL, P_GLOBAL, &Globals.bPamPasswordChange, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
595         {"passwd program", P_STRING, P_GLOBAL, &Globals.szPasswdProgram, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
596         {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
597         {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
598         {"username level", P_INTEGER, P_GLOBAL, &Globals.unamelevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
599         {"unix password sync", P_BOOL, P_GLOBAL, &Globals.bUnixPasswdSync, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
600         {"restrict anonymous", P_INTEGER, P_GLOBAL, &Globals.restrict_anonymous, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
601         {"lanman auth", P_BOOL, P_GLOBAL, &Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
602         {"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
603         {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
604         {"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
605         
606         {"username", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
607         {"user", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_HIDE},
608         {"users", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_HIDE},
609         
610         {"invalid users", P_LIST, P_LOCAL, &sDefault.szInvalidUsers, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
611         {"valid users", P_LIST, P_LOCAL, &sDefault.szValidUsers, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
612         {"admin users", P_LIST, P_LOCAL, &sDefault.szAdminUsers, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
613         
614         {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE},
615
616         {"guest only", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL, NULL, FLAG_SHARE},
617
618         {"guest ok", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
619
620         {"only user", P_BOOL, P_LOCAL, &sDefault.bOnlyUser, NULL, NULL, FLAG_SHARE},
621         {"hosts allow", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
622         {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
623         {"preload modules", P_LIST, P_GLOBAL, &Globals.szPreloadModules, NULL, NULL, FLAG_BASIC | FLAG_GLOBAL},
624
625         {"Logging Options", P_SEP, P_SEPARATOR},
626
627         {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
628         {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_HIDE},
629         {"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
630         
631         {"Protocol Options", P_SEP, P_SEPARATOR},
632         
633         {"smb ports", P_STRING, P_GLOBAL, &Globals.smb_ports, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
634         {"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, FLAG_DEVELOPER},
635         {"max protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
636         {"min protocol", P_ENUM, P_GLOBAL, &Globals.minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
637         {"unicode", P_BOOL, P_GLOBAL, &Globals.bUnicode, NULL, NULL, FLAG_DEVELOPER},
638         {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL, NULL, FLAG_DEVELOPER},
639         {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL, NULL, FLAG_DEVELOPER},
640         {"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
641         
642         {"nt status support", P_BOOL, P_GLOBAL, &Globals.bNTStatusSupport, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
643
644         {"announce version", P_STRING, P_GLOBAL, &Globals.szAnnounceVersion, NULL, NULL, FLAG_DEVELOPER},
645         {"announce as", P_ENUM, P_GLOBAL, &Globals.announce_as, NULL, enum_announce_as, FLAG_DEVELOPER},
646         {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
647         {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
648
649         {"name resolve order", P_STRING, P_GLOBAL, &Globals.szNameResolveOrder, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
650         {"max ttl", P_INTEGER, P_GLOBAL, &Globals.max_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, 
651         {"max wins ttl", P_INTEGER, P_GLOBAL, &Globals.max_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
652         {"min wins ttl", P_INTEGER, P_GLOBAL, &Globals.min_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
653         {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
654         {"unix extensions", P_BOOL, P_GLOBAL, &Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
655         {"use spnego", P_BOOL, P_GLOBAL, &Globals.bUseSpnego, NULL, NULL, FLAG_DEVELOPER},
656         {"server signing", P_ENUM, P_GLOBAL, &Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED}, 
657         {"rpc big endian", P_BOOL, P_GLOBAL, &Globals.bRpcBigEndian, NULL, NULL, FLAG_DEVELOPER},
658
659         {"Tuning Options", P_SEP, P_SEPARATOR},
660                 
661         {"lpq cache time", P_INTEGER, P_GLOBAL, &Globals.lpqcachetime, NULL, NULL, FLAG_DEVELOPER},
662         {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL, NULL, FLAG_SHARE},
663         {"paranoid server security", P_BOOL, P_GLOBAL, &Globals.paranoid_server_security, NULL, NULL, FLAG_DEVELOPER},
664         {"min print space", P_INTEGER, P_LOCAL, &sDefault.iMinPrintSpace, NULL, NULL, FLAG_PRINT},
665         
666         {"socket options", P_STRING, P_GLOBAL, &Globals.socket_options, NULL, NULL, FLAG_DEVELOPER},
667         {"use mmap", P_BOOL, P_GLOBAL, &Globals.bUseMmap, NULL, NULL, FLAG_DEVELOPER},
668         {"hostname lookups", P_BOOL, P_GLOBAL, &Globals.bHostnameLookups, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
669
670         {"name cache timeout", P_INTEGER, P_GLOBAL, &Globals.name_cache_timeout, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
671
672         {"Printing Options", P_SEP, P_SEPARATOR},
673         
674         {"max print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxPrintJobs, NULL, NULL, FLAG_PRINT},
675         {"load printers", P_BOOL, P_GLOBAL, &Globals.bLoadPrinters, NULL, NULL, FLAG_PRINT},
676         {"printcap name", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL, NULL, FLAG_PRINT | FLAG_DEVELOPER},
677         {"printcap", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL, NULL, FLAG_HIDE},
678         {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_PRINT},
679         {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_HIDE},
680         {"printing", P_ENUM, P_LOCAL, &sDefault.iPrinting, NULL, enum_printing, FLAG_PRINT | FLAG_GLOBAL},
681         {"print command", P_STRING, P_LOCAL, &sDefault.szPrintcommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
682         {"disable spoolss", P_BOOL, P_GLOBAL, &Globals.bDisableSpoolss, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
683         {"lpq command", P_STRING, P_LOCAL, &sDefault.szLpqcommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
684         {"lprm command", P_STRING, P_LOCAL, &sDefault.szLprmcommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
685         {"lppause command", P_STRING, P_LOCAL, &sDefault.szLppausecommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
686         {"lpresume command", P_STRING, P_LOCAL, &sDefault.szLpresumecommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
687         {"queuepause command", P_STRING, P_LOCAL, &sDefault.szQueuepausecommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
688         {"queueresume command", P_STRING, P_LOCAL, &sDefault.szQueueresumecommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
689         
690         {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_PRINT},
691         {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_HIDE},
692
693         {"Filename Handling", P_SEP, P_SEPARATOR},
694         
695         {"mangled stack", P_INTEGER, P_GLOBAL, &Globals.mangled_stack, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
696         {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
697         {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
698         {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
699
700         {"Domain Options", P_SEP, P_SEPARATOR},
701         
702         {"machine password timeout", P_INTEGER, P_GLOBAL, &Globals.machine_password_timeout, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
703
704         {"Logon Options", P_SEP, P_SEPARATOR},
705
706         {"add user script", P_STRING, P_GLOBAL, &Globals.szAddUserScript, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
707         {"add machine script", P_STRING, P_GLOBAL, &Globals.szAddMachineScript, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
708
709         {"logon script", P_STRING, P_GLOBAL, &Globals.szLogonScript, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
710         {"logon path", P_STRING, P_GLOBAL, &Globals.szLogonPath, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
711         {"logon drive", P_STRING, P_GLOBAL, &Globals.szLogonDrive, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
712         {"logon home", P_STRING, P_GLOBAL, &Globals.szLogonHome, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
713         {"domain logons", P_BOOL, P_GLOBAL, &Globals.bDomainLogons, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
714
715         {"Browse Options", P_SEP, P_SEPARATOR},
716         
717         {"os level", P_INTEGER, P_GLOBAL, &Globals.os_level, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
718         {"lm announce", P_ENUM, P_GLOBAL, &Globals.lm_announce, NULL, enum_bool_auto, FLAG_ADVANCED | FLAG_DEVELOPER},
719         {"lm interval", P_INTEGER, P_GLOBAL, &Globals.lm_interval, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
720         {"preferred master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
721         {"prefered master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_HIDE},
722         {"local master", P_BOOL, P_GLOBAL, &Globals.bLocalMaster, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
723         {"domain master", P_ENUM, P_GLOBAL, &Globals.bDomainMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
724         {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
725         {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_HIDE},
726         {"enhanced browsing", P_BOOL, P_GLOBAL, &Globals.enhanced_browsing, NULL, NULL, FLAG_DEVELOPER | FLAG_ADVANCED},
727
728         {"WINS Options", P_SEP, P_SEPARATOR},
729         {"dns proxy", P_BOOL, P_GLOBAL, &Globals.bDNSproxy, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
730         {"wins proxy", P_BOOL, P_GLOBAL, &Globals.bWINSproxy, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
731         
732         {"wins server", P_LIST, P_GLOBAL, &Globals.szWINSservers, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
733         {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
734         {"wins hook", P_STRING, P_GLOBAL, &Globals.szWINSHook, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
735         {"wins partners", P_STRING, P_GLOBAL, &Globals.szWINSPartners, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
736
737         {"Locking Options", P_SEP, P_SEPARATOR},
738         
739         {"csc policy", P_ENUM, P_LOCAL, &sDefault.iCSCPolicy, NULL, enum_csc_policy, FLAG_SHARE | FLAG_GLOBAL},
740         {"locking", P_BOOL, P_LOCAL, &sDefault.bLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
741         {"lock spin count", P_INTEGER, P_GLOBAL, &Globals.iLockSpinCount, NULL, NULL, FLAG_GLOBAL},
742         {"lock spin time", P_INTEGER, P_GLOBAL, &Globals.iLockSpinTime, NULL, NULL, FLAG_GLOBAL},
743         
744         {"oplocks", P_BOOL, P_LOCAL, &sDefault.bOpLocks, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
745         {"level2 oplocks", P_BOOL, P_LOCAL, &sDefault.bLevel2OpLocks, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
746         {"posix locking", P_BOOL, P_LOCAL, &sDefault.bPosixLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
747         {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
748         {"share modes", P_BOOL, P_LOCAL,  &sDefault.bShareModes, NULL, NULL, FLAG_SHARE|FLAG_GLOBAL},
749
750         {"Ldap Options", P_SEP, P_SEPARATOR},
751         
752 #ifdef WITH_LDAP_SAMCONFIG
753         {"ldap server", P_STRING, P_GLOBAL, &Globals.szLdapServer, NULL, NULL, 0},
754         {"ldap port", P_INTEGER, P_GLOBAL, &Globals.ldap_port, NULL, NULL, 0}, 
755 #endif
756         {"ldap suffix", P_STRING, P_GLOBAL, &Globals.szLdapSuffix, handle_ldap_suffix, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
757         {"ldap machine suffix", P_STRING, P_GLOBAL, &Globals.szLdapMachineSuffix, handle_ldap_machine_suffix, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
758         {"ldap user suffix", P_STRING, P_GLOBAL, &Globals.szLdapUserSuffix, handle_ldap_user_suffix, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
759         {"ldap filter", P_STRING, P_GLOBAL, &Globals.szLdapFilter, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
760         {"ldap admin dn", P_STRING, P_GLOBAL, &Globals.szLdapAdminDn, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
761         {"ldap ssl", P_ENUM, P_GLOBAL, &Globals.ldap_ssl, NULL, enum_ldap_ssl, FLAG_ADVANCED | FLAG_DEVELOPER},
762         {"ldap passwd sync", P_ENUM, P_GLOBAL, &Globals.ldap_passwd_sync, NULL, enum_ldap_passwd_sync, FLAG_ADVANCED | FLAG_DEVELOPER},
763         {"ldap trust ids", P_BOOL, P_GLOBAL, &Globals.ldap_trust_ids, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
764
765         {"Miscellaneous Options", P_SEP, P_SEPARATOR},
766         
767         {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE},
768         {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
769         {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
770         {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_HIDE}, 
771         {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
772         {"pid directory", P_STRING, P_GLOBAL, &Globals.szPidDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, 
773         
774         {"default service", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
775         {"default", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL, NULL,  FLAG_DEVELOPER},
776         {"remote announce", P_STRING, P_GLOBAL, &Globals.szRemoteAnnounce, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
777         {"remote browse sync", P_STRING, P_GLOBAL, &Globals.szRemoteBrowseSync, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
778         {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL, NULL, FLAG_DEVELOPER},
779         {"time offset", P_INTEGER, P_GLOBAL, &Globals.time_offset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
780         {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL, NULL, FLAG_HIDE},
781         
782         {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy, NULL, FLAG_HIDE},
783         {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include, NULL, FLAG_HIDE},
784         
785         {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
786         {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_SHARE },
787         {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_SHARE},
788
789         {"panic action", P_STRING, P_GLOBAL, &Globals.szPanicAction, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
790         {"hide local users", P_BOOL, P_GLOBAL, &Globals.bHideLocalUsers, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
791
792         {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_SHARE},
793         {"msdfs proxy", P_STRING, P_LOCAL, &sDefault.szMSDfsProxy, NULL, NULL, FLAG_SHARE},
794         {"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
795         {"Winbind options", P_SEP, P_SEPARATOR},
796
797         {"winbind uid", P_STRING, P_GLOBAL, &Globals.szWinbindUID, handle_winbind_uid, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
798         {"winbind gid", P_STRING, P_GLOBAL, &Globals.szWinbindGID, handle_winbind_gid, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
799         {"template homedir", P_STRING, P_GLOBAL, &Globals.szTemplateHomedir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
800         {"template shell", P_STRING, P_GLOBAL, &Globals.szTemplateShell, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
801         {"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
802         {"winbind cache time", P_INTEGER, P_GLOBAL, &Globals.winbind_cache_time, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
803         {"winbind enum users", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumUsers, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
804         {"winbind enum groups", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumGroups, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
805         {"winbind use default domain", P_BOOL, P_GLOBAL, &Globals.bWinbindUseDefaultDomain, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
806
807         {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
808 };
809
810 /***************************************************************************
811  Initialise the sDefault parameter structure for the printer values.
812 ***************************************************************************/
813
814 static void init_printer_values(void)
815 {
816         /* choose defaults depending on the type of printing */
817         switch (sDefault.iPrinting) {
818                 case PRINT_BSD:
819                 case PRINT_AIX:
820                 case PRINT_LPRNT:
821                 case PRINT_LPROS2:
822                         string_set(&sDefault.szLpqcommand, "lpq -P'%p'");
823                         string_set(&sDefault.szLprmcommand, "lprm -P'%p' %j");
824                         string_set(&sDefault.szPrintcommand,
825                                    "lpr -r -P'%p' %s");
826                         break;
827
828                 case PRINT_LPRNG:
829                 case PRINT_PLP:
830                         string_set(&sDefault.szLpqcommand, "lpq -P'%p'");
831                         string_set(&sDefault.szLprmcommand, "lprm -P'%p' %j");
832                         string_set(&sDefault.szPrintcommand,
833                                    "lpr -r -P'%p' %s");
834                         string_set(&sDefault.szQueuepausecommand,
835                                    "lpc stop '%p'");
836                         string_set(&sDefault.szQueueresumecommand,
837                                    "lpc start '%p'");
838                         string_set(&sDefault.szLppausecommand,
839                                    "lpc hold '%p' %j");
840                         string_set(&sDefault.szLpresumecommand,
841                                    "lpc release '%p' %j");
842                         break;
843
844                 case PRINT_CUPS:
845 #ifdef HAVE_CUPS
846                         string_set(&sDefault.szLpqcommand, "");
847                         string_set(&sDefault.szLprmcommand, "");
848                         string_set(&sDefault.szPrintcommand, "");
849                         string_set(&sDefault.szLppausecommand, "");
850                         string_set(&sDefault.szLpresumecommand, "");
851                         string_set(&sDefault.szQueuepausecommand, "");
852                         string_set(&sDefault.szQueueresumecommand, "");
853
854                         string_set(&Globals.szPrintcapname, "cups");
855 #else
856                         string_set(&sDefault.szLpqcommand,
857                                    "/usr/bin/lpstat -o '%p'");
858                         string_set(&sDefault.szLprmcommand,
859                                    "/usr/bin/cancel '%p-%j'");
860                         string_set(&sDefault.szPrintcommand,
861                                    "/usr/bin/lp -d '%p' %s; rm %s");
862                         string_set(&sDefault.szLppausecommand,
863                                    "lp -i '%p-%j' -H hold");
864                         string_set(&sDefault.szLpresumecommand,
865                                    "lp -i '%p-%j' -H resume");
866                         string_set(&sDefault.szQueuepausecommand,
867                                    "/usr/bin/disable '%p'");
868                         string_set(&sDefault.szQueueresumecommand,
869                                    "/usr/bin/enable '%p'");
870                         string_set(&Globals.szPrintcapname, "lpstat");
871 #endif /* HAVE_CUPS */
872                         break;
873
874                 case PRINT_SYSV:
875                 case PRINT_HPUX:
876                         string_set(&sDefault.szLpqcommand, "lpstat -o%p");
877                         string_set(&sDefault.szLprmcommand, "cancel %p-%j");
878                         string_set(&sDefault.szPrintcommand,
879                                    "lp -c -d%p %s; rm %s");
880                         string_set(&sDefault.szQueuepausecommand,
881                                    "disable %p");
882                         string_set(&sDefault.szQueueresumecommand,
883                                    "enable %p");
884 #ifndef HPUX
885                         string_set(&sDefault.szLppausecommand,
886                                    "lp -i %p-%j -H hold");
887                         string_set(&sDefault.szLpresumecommand,
888                                    "lp -i %p-%j -H resume");
889 #endif /* HPUX */
890                         break;
891
892                 case PRINT_QNX:
893                         string_set(&sDefault.szLpqcommand, "lpq -P%p");
894                         string_set(&sDefault.szLprmcommand, "lprm -P%p %j");
895                         string_set(&sDefault.szPrintcommand, "lp -r -P%p %s");
896                         break;
897
898                 case PRINT_SOFTQ:
899                         string_set(&sDefault.szLpqcommand, "qstat -l -d%p");
900                         string_set(&sDefault.szLprmcommand,
901                                    "qstat -s -j%j -c");
902                         string_set(&sDefault.szPrintcommand,
903                                    "lp -d%p -s %s; rm %s");
904                         string_set(&sDefault.szLppausecommand,
905                                    "qstat -s -j%j -h");
906                         string_set(&sDefault.szLpresumecommand,
907                                    "qstat -s -j%j -r");
908                         break;
909 #ifdef DEVELOPER
910         case PRINT_TEST:
911         case PRINT_VLP:
912                 string_set(&sDefault.szPrintcommand, "vlp print %p %s");
913                 string_set(&sDefault.szLpqcommand, "vlp lpq %p");
914                 string_set(&sDefault.szLprmcommand, "vlp lprm %p %j");
915                 string_set(&sDefault.szLppausecommand, "vlp lppause %p %j");
916                 string_set(&sDefault.szLpresumecommand, "vlp lpresum %p %j");
917                 string_set(&sDefault.szQueuepausecommand, "vlp queuepause %p");
918                 string_set(&sDefault.szQueueresumecommand, "vlp queueresume %p");
919                 break;
920 #endif /* DEVELOPER */
921
922         }
923 }
924
925
926 /***************************************************************************
927  Initialise the global parameter structure.
928 ***************************************************************************/
929 static void init_globals(void)
930 {
931         pstring s;
932         int i;
933
934         DEBUG(3, ("Initialising global parameters\n"));
935
936         for (i = 0; parm_table[i].label; i++) {
937                 if ((parm_table[i].type == P_STRING ||
938                      parm_table[i].type == P_USTRING) &&
939                     parm_table[i].ptr &&
940                     !(parm_table[i].flags & FLAG_CMDLINE)) {
941                         string_set(parm_table[i].ptr, "");
942                 }
943         }
944
945         /* options that can be set on the command line must be initialised via
946            the slower do_parameter() to ensure that FLAG_CMDLINE is obeyed */
947         do_parameter("socket options", DEFAULT_SOCKET_OPTIONS);
948         do_parameter("workgroup", DEFAULT_WORKGROUP);
949         do_parameter("netbios name", get_myname());
950         do_parameter("max protocol", "NT1");
951         do_parameter("name resolve order", "lmhosts wins host bcast");
952
953         init_printer_values();
954
955         string_set(&sDefault.fstype, FSTYPE_STRING);
956         string_set(&sDefault.ntvfs_handler, "default");
957
958         Globals.dcerpc_ep_servers = str_list_make("epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss", NULL);
959
960         Globals.AuthMethods = str_list_make("guest sam_ignoredomain", NULL);
961
962         string_set(&Globals.szSMBPasswdFile, dyn_SMB_PASSWD_FILE);
963         string_set(&Globals.szPrivateDir, dyn_PRIVATE_DIR);
964         asprintf(&Globals.szSAM_URL, "tdb://%s/sam.ldb", dyn_PRIVATE_DIR);
965         asprintf(&Globals.szSPOOLSS_URL, "tdb://%s/spoolss.ldb", dyn_PRIVATE_DIR);
966
967         string_set(&Globals.szGuestaccount, GUEST_ACCOUNT);
968
969         /* using UTF8 by default allows us to support all chars */
970         string_set(&Globals.unix_charset, "UTF8");
971
972         /* Use codepage 850 as a default for the dos character set */
973         string_set(&Globals.dos_charset, "CP850");
974
975         /*
976          * Allow the default PASSWD_CHAT to be overridden in local.h.
977          */
978         string_set(&Globals.szPasswdChat, DEFAULT_PASSWD_CHAT);
979         
980         string_set(&Globals.szPasswdProgram, "");
981         string_set(&Globals.szPrintcapname, PRINTCAP_NAME);
982         string_set(&Globals.szPidDir, dyn_PIDDIR);
983         string_set(&Globals.szLockDir, dyn_LOCKDIR);
984         string_set(&Globals.szSocketAddress, "0.0.0.0");
985         pstrcpy(s, "Samba ");
986         pstrcat(s, SAMBA_VERSION_STRING);
987         string_set(&Globals.szServerString, s);
988         slprintf(s, sizeof(s) - 1, "%d.%d", DEFAULT_MAJOR_VERSION,
989                  DEFAULT_MINOR_VERSION);
990         string_set(&Globals.szAnnounceVersion, s);
991
992         string_set(&Globals.szLogonDrive, "");
993         /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
994         string_set(&Globals.szLogonHome, "\\\\%N\\%U");
995         string_set(&Globals.szLogonPath, "\\\\%N\\%U\\profile");
996
997         string_set(&Globals.szPasswordServer, "*");
998
999         Globals.bLoadPrinters = True;
1000         Globals.mangled_stack = 50;
1001         Globals.max_mux = 50;   /* This is *needed* for profile support. */
1002         Globals.max_xmit = 4356; /* the value w2k3 chooses */
1003         Globals.lpqcachetime = 10;
1004         Globals.bDisableSpoolss = False;
1005         Globals.pwordlevel = 0;
1006         Globals.unamelevel = 0;
1007         Globals.bLargeReadwrite = True;
1008         Globals.minprotocol = PROTOCOL_CORE;
1009         Globals.security = SEC_USER;
1010         Globals.paranoid_server_security = True;
1011         Globals.bEncryptPasswords = True;
1012         Globals.bUpdateEncrypt = False;
1013         Globals.bReadRaw = True;
1014         Globals.bWriteRaw = True;
1015         Globals.bNullPasswords = False;
1016         Globals.bObeyPamRestrictions = False;
1017         Globals.max_ttl = 60 * 60 * 24 * 3;     /* 3 days default. */
1018         Globals.max_wins_ttl = 60 * 60 * 24 * 6;        /* 6 days default. */
1019         Globals.min_wins_ttl = 60 * 60 * 6;     /* 6 hours default. */
1020         Globals.machine_password_timeout = 60 * 60 * 24 * 7;    /* 7 days default. */
1021         Globals.lm_announce = 2;        /* = Auto: send only if LM clients found */
1022         Globals.lm_interval = 60;
1023         Globals.announce_as = ANNOUNCE_AS_NT_SERVER;
1024
1025         Globals.bTimeServer = False;
1026         Globals.bBindInterfacesOnly = False;
1027         Globals.bUnixPasswdSync = False;
1028         Globals.bPamPasswordChange = False;
1029         Globals.bUnicode = True;        /* Do unicode on the wire by default */
1030         Globals.bNTStatusSupport = True; /* Use NT status by default. */
1031         Globals.restrict_anonymous = 0;
1032         Globals.bClientLanManAuth = True;       /* Do use the LanMan hash if it is available */
1033         Globals.bLanmanAuth = True;     /* Do use the LanMan hash if it is available */
1034         Globals.bNTLMAuth = True;       /* Do use NTLMv1 if it is available (otherwise NTLMv2) */
1035         
1036         Globals.enhanced_browsing = True; 
1037         Globals.iLockSpinCount = 3; /* Try 2 times. */
1038         Globals.iLockSpinTime = 10; /* usec. */
1039 #ifdef MMAP_BLACKLIST
1040         Globals.bUseMmap = False;
1041 #else
1042         Globals.bUseMmap = True;
1043 #endif
1044         Globals.bUnixExtensions = False;
1045
1046         /* hostname lookups can be very expensive and are broken on
1047            a large number of sites (tridge) */
1048         Globals.bHostnameLookups = False;
1049
1050 #ifdef WITH_LDAP_SAMCONFIG
1051         string_set(&Globals.szLdapServer, "localhost");
1052         Globals.ldap_port = 636;
1053         Globals.szPassdbBackend = str_list_make("ldapsam guest", NULL);
1054 #else
1055         Globals.szPassdbBackend = str_list_make("smbpasswd guest", NULL);
1056 #endif /* WITH_LDAP_SAMCONFIG */
1057
1058         string_set(&Globals.szLdapSuffix, "");
1059         string_set(&Globals.szLdapMachineSuffix, "");
1060         string_set(&Globals.szLdapUserSuffix, "");
1061
1062         string_set(&Globals.szLdapFilter, "(&(uid=%u)(objectclass=sambaAccount))");
1063         string_set(&Globals.szLdapAdminDn, "");
1064         Globals.ldap_ssl = LDAP_SSL_ON;
1065         Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
1066
1067 /* these parameters are set to defaults that are more appropriate
1068    for the increasing samba install base:
1069
1070    as a member of the workgroup, that will possibly become a
1071    _local_ master browser (lm = True).  this is opposed to a forced
1072    local master browser startup (pm = True).
1073
1074    doesn't provide WINS server service by default (wsupp = False),
1075    and doesn't provide domain master browser services by default, either.
1076
1077 */
1078
1079         Globals.bPreferredMaster = Auto;        /* depending on bDomainMaster */
1080         Globals.os_level = 20;
1081         Globals.bLocalMaster = True;
1082         Globals.bDomainMaster = Auto;   /* depending on bDomainLogons */
1083         Globals.bDomainLogons = False;
1084         Globals.bWINSsupport = False;
1085         Globals.bWINSproxy = False;
1086
1087         Globals.bDNSproxy = True;
1088
1089         Globals.bAllowTrustedDomains = True;
1090
1091         string_set(&Globals.szTemplateShell, "/bin/false");
1092         string_set(&Globals.szTemplateHomedir, "/home/%D/%U");
1093         string_set(&Globals.szWinbindSeparator, "\\");
1094
1095         Globals.winbind_cache_time = 15;
1096         Globals.bWinbindEnumUsers = True;
1097         Globals.bWinbindEnumGroups = True;
1098         Globals.bWinbindUseDefaultDomain = False;
1099
1100         string_set(&Globals.szIDMapBackend, "tdb");
1101
1102         Globals.name_cache_timeout = 660; /* In seconds */
1103
1104         Globals.bUseSpnego = False;
1105
1106         Globals.server_signing = False;
1107
1108         string_set(&Globals.smb_ports, SMB_PORTS);
1109 }
1110
1111 static TALLOC_CTX *lp_talloc;
1112
1113 /******************************************************************* a
1114  Free up temporary memory - called from the main loop.
1115 ********************************************************************/
1116
1117 void lp_talloc_free(void)
1118 {
1119         if (!lp_talloc)
1120                 return;
1121         talloc_destroy(lp_talloc);
1122         lp_talloc = NULL;
1123 }
1124
1125 /*******************************************************************
1126  Convenience routine to grab string parameters into temporary memory
1127  and run standard_sub_basic on them. The buffers can be written to by
1128  callers without affecting the source string.
1129 ********************************************************************/
1130
1131 static const char *lp_string(const char *s)
1132 {
1133 #if 0  /* until REWRITE done to make thread-safe */
1134         size_t len = s ? strlen(s) : 0;
1135         char *ret;
1136 #endif
1137
1138         /* The follow debug is useful for tracking down memory problems
1139            especially if you have an inner loop that is calling a lp_*()
1140            function that returns a string.  Perhaps this debug should be
1141            present all the time? */
1142
1143 #if 0
1144         DEBUG(10, ("lp_string(%s)\n", s));
1145 #endif
1146
1147 #if 0  /* until REWRITE done to make thread-safe */
1148         if (!lp_talloc)
1149                 lp_talloc = talloc_init("lp_talloc");
1150
1151         ret = (char *)talloc(lp_talloc, len + 100);     /* leave room for substitution */
1152
1153         if (!ret)
1154                 return NULL;
1155
1156         if (!s)
1157                 *ret = 0;
1158         else
1159                 StrnCpy(ret, s, len);
1160
1161         if (trim_string(ret, "\"", "\"")) {
1162                 if (strchr(ret,'"') != NULL)
1163                         StrnCpy(ret, s, len);
1164         }
1165
1166         standard_sub_basic(ret,len+100);
1167         return (ret);
1168 #endif
1169         return s;
1170 }
1171
1172 /*
1173    In this section all the functions that are used to access the 
1174    parameters from the rest of the program are defined 
1175 */
1176
1177 #define FN_GLOBAL_STRING(fn_name,ptr) \
1178  const char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
1179 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
1180  const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");}
1181 #define FN_GLOBAL_LIST(fn_name,ptr) \
1182  const char **fn_name(void) {return(*(const char ***)(ptr));}
1183 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1184  BOOL fn_name(void) {return(*(BOOL *)(ptr));}
1185 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1186  char fn_name(void) {return(*(char *)(ptr));}
1187 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1188  int fn_name(void) {return(*(int *)(ptr));}
1189
1190 #define FN_LOCAL_STRING(fn_name,val) \
1191  const char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
1192 #define FN_LOCAL_CONST_STRING(fn_name,val) \
1193  const char *fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1194 #define FN_LOCAL_LIST(fn_name,val) \
1195  const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1196 #define FN_LOCAL_BOOL(fn_name,val) \
1197  BOOL fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1198 #define FN_LOCAL_CHAR(fn_name,val) \
1199  char fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1200 #define FN_LOCAL_INTEGER(fn_name,val) \
1201  int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1202
1203 FN_GLOBAL_STRING(lp_smb_ports, &Globals.smb_ports)
1204 FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
1205 FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
1206 FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset)
1207 FN_GLOBAL_STRING(lp_logfile, &Globals.szLogFile)
1208 FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
1209 FN_GLOBAL_STRING(lp_smb_passwd_file, &Globals.szSMBPasswdFile)
1210 FN_GLOBAL_STRING(lp_sam_url, &Globals.szSAM_URL)
1211 FN_GLOBAL_STRING(lp_spoolss_url, &Globals.szSPOOLSS_URL)
1212 FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
1213 FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
1214 FN_GLOBAL_STRING(lp_printcapname, &Globals.szPrintcapname)
1215 FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
1216 FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
1217 FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, &Globals.dcerpc_ep_servers)
1218 FN_GLOBAL_STRING(lp_rootdir, &Globals.szRootdir)
1219 FN_GLOBAL_STRING(lp_defaultservice, &Globals.szDefaultService)
1220 FN_GLOBAL_STRING(lp_hosts_equiv, &Globals.szHostsEquiv)
1221 FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
1222 FN_GLOBAL_STRING(lp_passwd_program, &Globals.szPasswdProgram)
1223 FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
1224 FN_GLOBAL_STRING(lp_passwordserver, &Globals.szPasswordServer)
1225 FN_GLOBAL_STRING(lp_name_resolve_order, &Globals.szNameResolveOrder)
1226 FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
1227 FN_GLOBAL_STRING(lp_ads_server, &Globals.szADSserver)
1228 FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
1229 FN_GLOBAL_STRING(lp_workgroup, &Globals.szWorkgroup)
1230 FN_GLOBAL_STRING(lp_netbios_name, &Globals.szNetbiosName)
1231 FN_GLOBAL_STRING(lp_netbios_scope, &Globals.szNetbiosScope)
1232 FN_GLOBAL_CONST_STRING(lp_logon_script, &Globals.szLogonScript)
1233 FN_GLOBAL_CONST_STRING(lp_logon_path, &Globals.szLogonPath)
1234 FN_GLOBAL_CONST_STRING(lp_logon_drive, &Globals.szLogonDrive)
1235 FN_GLOBAL_CONST_STRING(lp_logon_home, &Globals.szLogonHome)
1236 FN_GLOBAL_STRING(lp_remote_announce, &Globals.szRemoteAnnounce)
1237 FN_GLOBAL_STRING(lp_remote_browse_sync, &Globals.szRemoteBrowseSync)
1238 FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
1239 FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
1240 FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
1241 static FN_GLOBAL_STRING(lp_announce_version, &Globals.szAnnounceVersion)
1242 FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
1243 FN_GLOBAL_LIST(lp_passdb_backend, &Globals.szPassdbBackend)
1244 FN_GLOBAL_LIST(lp_preload_modules, &Globals.szPreloadModules)
1245 FN_GLOBAL_STRING(lp_panic_action, &Globals.szPanicAction)
1246 FN_GLOBAL_STRING(lp_adduser_script, &Globals.szAddUserScript)
1247
1248 FN_GLOBAL_CONST_STRING(lp_guestaccount, &Globals.szGuestaccount)
1249
1250 FN_GLOBAL_STRING(lp_addmachine_script, &Globals.szAddMachineScript)
1251
1252 FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
1253 FN_GLOBAL_STRING(lp_wins_partners, &Globals.szWINSPartners)
1254 FN_GLOBAL_STRING(lp_template_homedir, &Globals.szTemplateHomedir)
1255 FN_GLOBAL_STRING(lp_template_shell, &Globals.szTemplateShell)
1256 FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
1257 FN_GLOBAL_BOOL(lp_winbind_enum_users, &Globals.bWinbindEnumUsers)
1258 FN_GLOBAL_BOOL(lp_winbind_enum_groups, &Globals.bWinbindEnumGroups)
1259 FN_GLOBAL_BOOL(lp_winbind_use_default_domain, &Globals.bWinbindUseDefaultDomain)
1260 FN_GLOBAL_STRING(lp_idmap_backend, &Globals.szIDMapBackend)
1261
1262 #ifdef WITH_LDAP_SAMCONFIG
1263 FN_GLOBAL_STRING(lp_ldap_server, &Globals.szLdapServer)
1264 FN_GLOBAL_INTEGER(lp_ldap_port, &Globals.ldap_port)
1265 #endif
1266 FN_GLOBAL_STRING(lp_ldap_suffix, &Globals.szLdapSuffix)
1267 FN_GLOBAL_STRING(lp_ldap_machine_suffix, &Globals.szLdapMachineSuffix)
1268 FN_GLOBAL_STRING(lp_ldap_user_suffix, &Globals.szLdapUserSuffix)
1269 FN_GLOBAL_STRING(lp_ldap_filter, &Globals.szLdapFilter)
1270 FN_GLOBAL_STRING(lp_ldap_admin_dn, &Globals.szLdapAdminDn)
1271 FN_GLOBAL_INTEGER(lp_ldap_ssl, &Globals.ldap_ssl)
1272 FN_GLOBAL_INTEGER(lp_ldap_passwd_sync, &Globals.ldap_passwd_sync)
1273 FN_GLOBAL_BOOL(lp_ldap_trust_ids, &Globals.ldap_trust_ids)
1274
1275 FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
1276 FN_GLOBAL_BOOL(lp_dns_proxy, &Globals.bDNSproxy)
1277 FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
1278 FN_GLOBAL_BOOL(lp_we_are_a_wins_server, &Globals.bWINSsupport)
1279 FN_GLOBAL_BOOL(lp_wins_proxy, &Globals.bWINSproxy)
1280 FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
1281 FN_GLOBAL_BOOL(lp_domain_logons, &Globals.bDomainLogons)
1282 FN_GLOBAL_BOOL(lp_load_printers, &Globals.bLoadPrinters)
1283 FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
1284 FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
1285 FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw)
1286 FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords)
1287 FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions)
1288 FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
1289 FN_GLOBAL_BOOL(lp_update_encrypted, &Globals.bUpdateEncrypt)
1290 static FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
1291 FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
1292 FN_GLOBAL_BOOL(lp_pam_password_change, &Globals.bPamPasswordChange)
1293 FN_GLOBAL_BOOL(lp_unix_password_sync, &Globals.bUnixPasswdSync)
1294 FN_GLOBAL_BOOL(lp_unicode, &Globals.bUnicode)
1295 FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
1296 FN_GLOBAL_BOOL(lp_allow_trusted_domains, &Globals.bAllowTrustedDomains)
1297 FN_GLOBAL_INTEGER(lp_restrict_anonymous, &Globals.restrict_anonymous)
1298 FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
1299 FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
1300 FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
1301 FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
1302 FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
1303 FN_GLOBAL_BOOL(lp_enhanced_browsing, &Globals.enhanced_browsing)
1304 FN_GLOBAL_BOOL(lp_use_mmap, &Globals.bUseMmap)
1305 FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions)
1306 FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
1307 FN_GLOBAL_BOOL(lp_hostname_lookups, &Globals.bHostnameLookups)
1308 FN_GLOBAL_BOOL(lp_rpc_big_endian, &Globals.bRpcBigEndian)
1309 FN_GLOBAL_INTEGER(lp_os_level, &Globals.os_level)
1310 FN_GLOBAL_INTEGER(lp_max_ttl, &Globals.max_ttl)
1311 FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
1312 FN_GLOBAL_INTEGER(lp_min_wins_ttl, &Globals.min_wins_ttl)
1313 FN_GLOBAL_INTEGER(lp_time_offset, &Globals.time_offset)
1314 FN_GLOBAL_INTEGER(lp_maxmux, &Globals.max_mux)
1315 FN_GLOBAL_INTEGER(lp_max_xmit, &Globals.max_xmit)
1316 FN_GLOBAL_INTEGER(lp_passwordlevel, &Globals.pwordlevel)
1317 FN_GLOBAL_INTEGER(lp_usernamelevel, &Globals.unamelevel)
1318 FN_GLOBAL_INTEGER(lp_maxprotocol, &Globals.maxprotocol)
1319 FN_GLOBAL_INTEGER(lp_minprotocol, &Globals.minprotocol)
1320 FN_GLOBAL_INTEGER(lp_security, &Globals.security)
1321 FN_GLOBAL_LIST(lp_auth_methods, &Globals.AuthMethods)
1322 FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security)
1323 FN_GLOBAL_INTEGER(lp_lpqcachetime, &Globals.lpqcachetime)
1324 FN_GLOBAL_INTEGER(lp_disable_spoolss, &Globals.bDisableSpoolss)
1325 static FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as)
1326 FN_GLOBAL_INTEGER(lp_lm_announce, &Globals.lm_announce)
1327 FN_GLOBAL_INTEGER(lp_lm_interval, &Globals.lm_interval)
1328 FN_GLOBAL_INTEGER(lp_machine_password_timeout, &Globals.machine_password_timeout)
1329 FN_GLOBAL_INTEGER(lp_lock_spin_count, &Globals.iLockSpinCount)
1330 FN_GLOBAL_INTEGER(lp_lock_sleep_time, &Globals.iLockSpinTime)
1331 FN_LOCAL_STRING(lp_servicename, szService)
1332 FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
1333 FN_LOCAL_STRING(lp_pathname, szPath)
1334 FN_LOCAL_STRING(lp_username, szUsername)
1335 FN_LOCAL_LIST(lp_invalid_users, szInvalidUsers)
1336 FN_LOCAL_LIST(lp_valid_users, szValidUsers)
1337 FN_LOCAL_LIST(lp_admin_users, szAdminUsers)
1338 FN_LOCAL_STRING(lp_printcommand, szPrintcommand)
1339 FN_LOCAL_STRING(lp_lpqcommand, szLpqcommand)
1340 FN_LOCAL_STRING(lp_lprmcommand, szLprmcommand)
1341 FN_LOCAL_STRING(lp_lppausecommand, szLppausecommand)
1342 FN_LOCAL_STRING(lp_lpresumecommand, szLpresumecommand)
1343 FN_LOCAL_STRING(lp_queuepausecommand, szQueuepausecommand)
1344 FN_LOCAL_STRING(lp_queueresumecommand, szQueueresumecommand)
1345 static FN_LOCAL_STRING(_lp_printername, szPrintername)
1346 FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
1347 FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
1348 FN_LOCAL_STRING(lp_comment, comment)
1349 FN_LOCAL_STRING(lp_fstype, fstype)
1350 FN_LOCAL_STRING(lp_msdfs_proxy, szMSDfsProxy)
1351 static FN_LOCAL_STRING(lp_volume, volume)
1352 FN_LOCAL_STRING(lp_ntvfs_handler, ntvfs_handler)
1353 FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
1354 FN_LOCAL_BOOL(lp_autoloaded, autoloaded)
1355 FN_LOCAL_BOOL(lp_browseable, bBrowseable)
1356 FN_LOCAL_BOOL(lp_readonly, bRead_only)
1357 FN_LOCAL_BOOL(lp_guest_ok, bGuest_ok)
1358 FN_LOCAL_BOOL(lp_guest_only, bGuest_only)
1359 FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
1360 FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
1361 FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
1362 FN_LOCAL_BOOL(lp_locking, bLocking)
1363 FN_LOCAL_BOOL(lp_strict_locking, bStrictLocking)
1364 FN_LOCAL_BOOL(lp_posix_locking, bPosixLocking)
1365 FN_LOCAL_BOOL(lp_share_modes, bShareModes)
1366 FN_LOCAL_BOOL(lp_oplocks, bOpLocks)
1367 FN_LOCAL_BOOL(lp_level2_oplocks, bLevel2OpLocks)
1368 FN_LOCAL_BOOL(lp_onlyuser, bOnlyUser)
1369 FN_LOCAL_BOOL(lp_map_system, bMap_system)
1370 FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
1371 FN_LOCAL_INTEGER(lp_minprintspace, iMinPrintSpace)
1372 FN_LOCAL_INTEGER(lp_printing, iPrinting)
1373 FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
1374 FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time)
1375 FN_GLOBAL_BOOL(lp_hide_local_users, &Globals.bHideLocalUsers)
1376 FN_GLOBAL_INTEGER(lp_name_cache_timeout, &Globals.name_cache_timeout)
1377 FN_GLOBAL_INTEGER(lp_server_signing, &Globals.server_signing)
1378
1379 /* local prototypes */
1380
1381 static int map_parameter(const char *pszParmName);
1382 static BOOL set_boolean(BOOL *pb, const char *pszParmValue);
1383 static int getservicebyname(const char *pszServiceName,
1384                             service * pserviceDest);
1385 static void copy_service(service * pserviceDest,
1386                          service * pserviceSource, BOOL *pcopymapDest);
1387 static BOOL service_ok(int iService);
1388 static BOOL do_section(const char *pszSectionName);
1389 static void init_copymap(service * pservice);
1390
1391 /* This is a helper function for parametrical options support. */
1392 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
1393 /* Actual parametrical functions are quite simple */
1394 static const char *get_parametrics(int lookup_service, const char *type, const char *option)
1395 {
1396         char *vfskey;
1397         struct param_opt *data;
1398         
1399         if (lookup_service >= iNumServices) return NULL;
1400         
1401         data = (lookup_service < 0) ? 
1402                 Globals.param_opt : ServicePtrs[lookup_service]->param_opt;
1403     
1404         asprintf(&vfskey, "%s:%s", type, option);
1405         strlower(vfskey);
1406
1407         while (data) {
1408                 if (strcmp(data->key, vfskey) == 0) {
1409                         free(vfskey);
1410                         return data->value;
1411                 }
1412                 data = data->next;
1413         }
1414
1415         if (lookup_service >= 0) {
1416                 /* Try to fetch the same option but from globals */
1417                 /* but only if we are not already working with Globals */
1418                 data = Globals.param_opt;
1419                 while (data) {
1420                         if (strcmp(data->key, vfskey) == 0) {
1421                                 free(vfskey);
1422                                 return data->value;
1423                         }
1424                         data = data->next;
1425                 }
1426         }
1427
1428         free(vfskey);
1429         
1430         return NULL;
1431 }
1432
1433
1434 /*******************************************************************
1435 convenience routine to return int parameters.
1436 ********************************************************************/
1437 static int lp_int(const char *s)
1438 {
1439
1440         if (!s) {
1441                 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
1442                 return (-1);
1443         }
1444
1445         return atoi(s); 
1446 }
1447
1448 /*******************************************************************
1449 convenience routine to return unsigned long parameters.
1450 ********************************************************************/
1451 static int lp_ulong(const char *s)
1452 {
1453
1454         if (!s) {
1455                 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
1456                 return (-1);
1457         }
1458
1459         return strtoul(s, NULL, 10);
1460 }
1461
1462 /*******************************************************************
1463 convenience routine to return boolean parameters.
1464 ********************************************************************/
1465 static BOOL lp_bool(const char *s)
1466 {
1467         BOOL ret = False;
1468
1469         if (!s) {
1470                 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
1471                 return False;
1472         }
1473         
1474         if (!set_boolean(&ret,s)) {
1475                 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1476                 return False;
1477         }
1478
1479         return ret;
1480 }
1481
1482 /*******************************************************************
1483 convenience routine to return enum parameters.
1484 ********************************************************************/
1485 static int lp_enum(const char *s,const struct enum_list *_enum)
1486 {
1487         int i;
1488
1489         if (!s || !_enum) {
1490                 DEBUG(0,("lp_enum(%s,enum): is called with NULL!\n",s));
1491                 return False;
1492         }
1493         
1494         for (i=0; _enum[i].name; i++) {
1495                 if (strcasecmp(_enum[i].name,s)==0)
1496                         return _enum[i].value;
1497         }
1498
1499         DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
1500         return (-1);
1501 }
1502
1503 /* Return parametric option from a given service. Type is a part of option before ':' */
1504 /* Parametric option has following syntax: 'Type: option = value' */
1505 /* Returned value is allocated in 'lp_talloc' context */
1506
1507 const char *lp_parm_string(int lookup_service, const char *type, const char *option)
1508 {
1509         const char *value = get_parametrics(lookup_service, type, option);
1510         
1511         if (value)
1512                 return lp_string(value);
1513
1514         return NULL;
1515 }
1516
1517 /* Return parametric option from a given service. Type is a part of option before ':' */
1518 /* Parametric option has following syntax: 'Type: option = value' */
1519 /* Returned value is allocated in 'lp_talloc' context */
1520
1521 char **lp_parm_string_list(int lookup_service, const char *type, const char *option,
1522                            const char *separator)
1523 {
1524         const char *value = get_parametrics(lookup_service, type, option);
1525         
1526         if (value)
1527                 return str_list_make(value, separator);
1528
1529         return NULL;
1530 }
1531
1532 /* Return parametric option from a given service. Type is a part of option before ':' */
1533 /* Parametric option has following syntax: 'Type: option = value' */
1534
1535 int lp_parm_int(int lookup_service, const char *type, const char *option)
1536 {
1537         const char *value = get_parametrics(lookup_service, type, option);
1538         
1539         if (value)
1540                 return lp_int(value);
1541
1542         return (-1);
1543 }
1544
1545 /* Return parametric option from a given service. Type is a part of option before ':' */
1546 /* Parametric option has following syntax: 'Type: option = value' */
1547
1548 unsigned long lp_parm_ulong(int lookup_service, const char *type, const char *option)
1549 {
1550         const char *value = get_parametrics(lookup_service, type, option);
1551         
1552         if (value)
1553                 return lp_ulong(value);
1554
1555         return (0);
1556 }
1557
1558 /* Return parametric option from a given service. Type is a part of option before ':' */
1559 /* Parametric option has following syntax: 'Type: option = value' */
1560
1561 BOOL lp_parm_bool(int lookup_service, const char *type, const char *option, BOOL default_v)
1562 {
1563         const char *value = get_parametrics(lookup_service, type, option);
1564         
1565         if (value)
1566                 return lp_bool(value);
1567
1568         return default_v;
1569 }
1570
1571 /* Return parametric option from a given service. Type is a part of option before ':' */
1572 /* Parametric option has following syntax: 'Type: option = value' */
1573
1574 int lp_parm_enum(int lookup_service, const char *type, const char *option,
1575                  const struct enum_list *_enum)
1576 {
1577         const char *value = get_parametrics(lookup_service, type, option);
1578         
1579         if (value)
1580                 return lp_enum(value, _enum);
1581
1582         return (-1);
1583 }
1584
1585
1586 /***************************************************************************
1587  Initialise a service to the defaults.
1588 ***************************************************************************/
1589
1590 static void init_service(service * pservice)
1591 {
1592         memset((char *)pservice, '\0', sizeof(service));
1593         copy_service(pservice, &sDefault, NULL);
1594 }
1595
1596 /***************************************************************************
1597  Free the dynamically allocated parts of a service struct.
1598 ***************************************************************************/
1599
1600 static void free_service(service *pservice)
1601 {
1602         int i;
1603         struct param_opt *data, *pdata;
1604         if (!pservice)
1605                 return;
1606
1607         if (pservice->szService)
1608                 DEBUG(5, ("free_service: Freeing service %s\n",
1609                        pservice->szService));
1610
1611         string_free(&pservice->szService);
1612         SAFE_FREE(pservice->copymap);
1613
1614         for (i = 0; parm_table[i].label; i++) {
1615                 if ((parm_table[i].type == P_STRING ||
1616                      parm_table[i].type == P_USTRING) &&
1617                     parm_table[i].class == P_LOCAL)
1618                         string_free((char **)
1619                                     (((char *)pservice) +
1620                                      PTR_DIFF(parm_table[i].ptr, &sDefault)));
1621                 else if (parm_table[i].type == P_LIST &&
1622                          parm_table[i].class == P_LOCAL)
1623                              str_list_free((char ***)
1624                                             (((char *)pservice) +
1625                                              PTR_DIFF(parm_table[i].ptr, &sDefault)));
1626         }
1627                                 
1628         DEBUG(5,("Freeing parametrics:\n"));
1629         data = pservice->param_opt;
1630         while (data) {
1631                 DEBUG(5,("[%s = %s]\n", data->key, data->value));
1632                 string_free(&data->key);
1633                 string_free(&data->value);
1634                 pdata = data->next;
1635                 SAFE_FREE(data);
1636                 data = pdata;
1637         }
1638
1639         ZERO_STRUCTP(pservice);
1640 }
1641
1642 /***************************************************************************
1643  Add a new service to the services array initialising it with the given 
1644  service. 
1645 ***************************************************************************/
1646
1647 static int add_a_service(const service *pservice, const char *name)
1648 {
1649         int i;
1650         service tservice;
1651         int num_to_alloc = iNumServices + 1;
1652         struct param_opt *data, *pdata;
1653
1654         tservice = *pservice;
1655
1656         /* it might already exist */
1657         if (name) {
1658                 i = getservicebyname(name, NULL);
1659                 if (i >= 0) {
1660                         /* Clean all parametric options for service */
1661                         /* They will be added during parsing again */
1662                         data = ServicePtrs[i]->param_opt;
1663                         while (data) {
1664                                 string_free(&data->key);
1665                                 string_free(&data->value);
1666                                 pdata = data->next;
1667                                 SAFE_FREE(data);
1668                                 data = pdata;
1669                         }
1670                         ServicePtrs[i]->param_opt = NULL;
1671                         return (i);
1672                 }
1673         }
1674
1675         /* find an invalid one */
1676         for (i = 0; i < iNumServices; i++)
1677                 if (!ServicePtrs[i]->valid)
1678                         break;
1679
1680         /* if not, then create one */
1681         if (i == iNumServices) {
1682                 service **tsp;
1683                 
1684                 tsp = (service **) Realloc(ServicePtrs,
1685                                            sizeof(service *) *
1686                                            num_to_alloc);
1687                                            
1688                 if (!tsp) {
1689                         DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1690                         return (-1);
1691                 }
1692                 else {
1693                         ServicePtrs = tsp;
1694                         ServicePtrs[iNumServices] =
1695                                 (service *) malloc(sizeof(service));
1696                 }
1697                 if (!ServicePtrs[iNumServices]) {
1698                         DEBUG(0,("add_a_service: out of memory!\n"));
1699                         return (-1);
1700                 }
1701
1702                 iNumServices++;
1703         } else
1704                 free_service(ServicePtrs[i]);
1705
1706         ServicePtrs[i]->valid = True;
1707
1708         init_service(ServicePtrs[i]);
1709         copy_service(ServicePtrs[i], &tservice, NULL);
1710         if (name)
1711                 string_set(&ServicePtrs[i]->szService, name);
1712         return (i);
1713 }
1714
1715 /***************************************************************************
1716  Add a new home service, with the specified home directory, defaults coming 
1717  from service ifrom.
1718 ***************************************************************************/
1719
1720 BOOL lp_add_home(const char *pszHomename, int iDefaultService, 
1721                  const char *user, const char *pszHomedir)
1722 {
1723         int i;
1724         pstring newHomedir;
1725
1726         i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1727
1728         if (i < 0)
1729                 return (False);
1730
1731         if (!(*(ServicePtrs[iDefaultService]->szPath))
1732             || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(-1))) {
1733                 pstrcpy(newHomedir, pszHomedir);
1734         } else {
1735                 pstrcpy(newHomedir, lp_pathname(iDefaultService));
1736                 string_sub(newHomedir,"%H", pszHomedir, sizeof(newHomedir)); 
1737         }
1738
1739         string_set(&ServicePtrs[i]->szPath, newHomedir);
1740
1741         if (!(*(ServicePtrs[i]->comment))) {
1742                 pstring comment;
1743                 slprintf(comment, sizeof(comment) - 1,
1744                          "Home directory of %s", user);
1745                 string_set(&ServicePtrs[i]->comment, comment);
1746         }
1747         ServicePtrs[i]->bAvailable = sDefault.bAvailable;
1748         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1749
1750         DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename, 
1751                user, newHomedir));
1752         
1753         return (True);
1754 }
1755
1756 /***************************************************************************
1757  Add a new service, based on an old one.
1758 ***************************************************************************/
1759
1760 int lp_add_service(const char *pszService, int iDefaultService)
1761 {
1762         return (add_a_service(ServicePtrs[iDefaultService], pszService));
1763 }
1764
1765 /***************************************************************************
1766  Add the IPC service.
1767 ***************************************************************************/
1768
1769 static BOOL lp_add_ipc(const char *ipc_name, BOOL guest_ok)
1770 {
1771         pstring comment;
1772         int i = add_a_service(&sDefault, ipc_name);
1773
1774         if (i < 0)
1775                 return (False);
1776
1777         slprintf(comment, sizeof(comment) - 1,
1778                  "IPC Service (%s)", Globals.szServerString);
1779
1780         string_set(&ServicePtrs[i]->szPath, tmpdir());
1781         string_set(&ServicePtrs[i]->szUsername, "");
1782         string_set(&ServicePtrs[i]->comment, comment);
1783         string_set(&ServicePtrs[i]->fstype, "IPC");
1784         ServicePtrs[i]->iMaxConnections = 0;
1785         ServicePtrs[i]->bAvailable = True;
1786         ServicePtrs[i]->bRead_only = True;
1787         ServicePtrs[i]->bGuest_only = False;
1788         ServicePtrs[i]->bGuest_ok = guest_ok;
1789         ServicePtrs[i]->bPrint_ok = False;
1790         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1791
1792         DEBUG(3, ("adding IPC service\n"));
1793
1794         return (True);
1795 }
1796
1797 /***************************************************************************
1798  Add a new printer service, with defaults coming from service iFrom.
1799 ***************************************************************************/
1800
1801 BOOL lp_add_printer(const char *pszPrintername, int iDefaultService)
1802 {
1803         const char *comment = "From Printcap";
1804         int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1805
1806         if (i < 0)
1807                 return (False);
1808
1809         /* note that we do NOT default the availability flag to True - */
1810         /* we take it from the default service passed. This allows all */
1811         /* dynamic printers to be disabled by disabling the [printers] */
1812         /* entry (if/when the 'available' keyword is implemented!).    */
1813
1814         /* the printer name is set to the service name. */
1815         string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1816         string_set(&ServicePtrs[i]->comment, comment);
1817         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1818         /* Printers cannot be read_only. */
1819         ServicePtrs[i]->bRead_only = False;
1820         /* No share modes on printer services. */
1821         ServicePtrs[i]->bShareModes = False;
1822         /* No oplocks on printer services. */
1823         ServicePtrs[i]->bOpLocks = False;
1824         /* Printer services must be printable. */
1825         ServicePtrs[i]->bPrint_ok = True;
1826
1827         DEBUG(3, ("adding printer service %s\n", pszPrintername));
1828
1829         update_server_announce_as_printserver();
1830
1831         return (True);
1832 }
1833
1834 /***************************************************************************
1835  Map a parameter's string representation to something we can use. 
1836  Returns False if the parameter string is not recognised, else TRUE.
1837 ***************************************************************************/
1838
1839 static int map_parameter(const char *pszParmName)
1840 {
1841         int iIndex;
1842
1843         if (*pszParmName == '-')
1844                 return (-1);
1845
1846         for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1847                 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1848                         return (iIndex);
1849
1850         /* Warn only if it isn't parametric option */
1851         if (strchr(pszParmName, ':') == NULL)
1852                 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1853         /* We do return 'fail' for parametric options as well because they are
1854            stored in different storage
1855          */
1856         return (-1);
1857 }
1858
1859 /***************************************************************************
1860  Set a boolean variable from the text value stored in the passed string.
1861  Returns True in success, False if the passed string does not correctly 
1862  represent a boolean.
1863 ***************************************************************************/
1864
1865 static BOOL set_boolean(BOOL *pb, const char *pszParmValue)
1866 {
1867         BOOL bRetval;
1868
1869         bRetval = True;
1870         if (strwicmp(pszParmValue, "yes") == 0 ||
1871             strwicmp(pszParmValue, "true") == 0 ||
1872             strwicmp(pszParmValue, "1") == 0)
1873                 *pb = True;
1874         else if (strwicmp(pszParmValue, "no") == 0 ||
1875                     strwicmp(pszParmValue, "False") == 0 ||
1876                     strwicmp(pszParmValue, "0") == 0)
1877                 *pb = False;
1878         else {
1879                 DEBUG(0,
1880                       ("ERROR: Badly formed boolean in configuration file: \"%s\".\n",
1881                        pszParmValue));
1882                 bRetval = False;
1883         }
1884         return (bRetval);
1885 }
1886
1887 /***************************************************************************
1888 Find a service by name. Otherwise works like get_service.
1889 ***************************************************************************/
1890
1891 static int getservicebyname(const char *pszServiceName, service * pserviceDest)
1892 {
1893         int iService;
1894
1895         for (iService = iNumServices - 1; iService >= 0; iService--)
1896                 if (VALID(iService) &&
1897                     strwicmp(ServicePtrs[iService]->szService, pszServiceName) == 0) {
1898                         if (pserviceDest != NULL)
1899                                 copy_service(pserviceDest, ServicePtrs[iService], NULL);
1900                         break;
1901                 }
1902
1903         return (iService);
1904 }
1905
1906 /***************************************************************************
1907  Copy a service structure to another.
1908  If pcopymapDest is NULL then copy all fields
1909 ***************************************************************************/
1910
1911 static void copy_service(service * pserviceDest, service * pserviceSource, BOOL *pcopymapDest)
1912 {
1913         int i;
1914         BOOL bcopyall = (pcopymapDest == NULL);
1915         struct param_opt *data, *pdata, *paramo;
1916         BOOL not_added;
1917
1918         for (i = 0; parm_table[i].label; i++)
1919                 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1920                     (bcopyall || pcopymapDest[i])) {
1921                         void *def_ptr = parm_table[i].ptr;
1922                         void *src_ptr =
1923                                 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
1924                                                                     &sDefault);
1925                         void *dest_ptr =
1926                                 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
1927                                                                   &sDefault);
1928
1929                         switch (parm_table[i].type) {
1930                                 case P_BOOL:
1931                                 case P_BOOLREV:
1932                                         *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
1933                                         break;
1934
1935                                 case P_INTEGER:
1936                                 case P_ENUM:
1937                                 case P_OCTAL:
1938                                         *(int *)dest_ptr = *(int *)src_ptr;
1939                                         break;
1940
1941                                 case P_CHAR:
1942                                         *(char *)dest_ptr = *(char *)src_ptr;
1943                                         break;
1944
1945                                 case P_STRING:
1946                                         string_set(dest_ptr,
1947                                                    *(char **)src_ptr);
1948                                         break;
1949
1950                                 case P_USTRING:
1951                                         string_set(dest_ptr,
1952                                                    *(char **)src_ptr);
1953                                         strupper(*(char **)dest_ptr);
1954                                         break;
1955                                 case P_LIST:
1956                                         str_list_copy((char ***)dest_ptr, *(const char ***)src_ptr);
1957                                         break;
1958                                 default:
1959                                         break;
1960                         }
1961                 }
1962
1963         if (bcopyall) {
1964                 init_copymap(pserviceDest);
1965                 if (pserviceSource->copymap)
1966                         memcpy((void *)pserviceDest->copymap,
1967                                (void *)pserviceSource->copymap,
1968                                sizeof(BOOL) * NUMPARAMETERS);
1969         }
1970         
1971         data = pserviceSource->param_opt;
1972         while (data) {
1973                 not_added = True;
1974                 pdata = pserviceDest->param_opt;
1975                 /* Traverse destination */
1976                 while (pdata) {
1977                         /* If we already have same option, override it */
1978                         if (strcmp(pdata->key, data->key) == 0) {
1979                                 string_free(&pdata->value);
1980                                 pdata->value = strdup(data->value);
1981                                 not_added = False;
1982                                 break;
1983                         }
1984                         pdata = pdata->next;
1985                 }
1986                 if (not_added) {
1987                         paramo = smb_xmalloc(sizeof(*paramo));
1988                         paramo->key = strdup(data->key);
1989                         paramo->value = strdup(data->value);
1990                         DLIST_ADD(pserviceDest->param_opt, paramo);
1991                 }
1992                 data = data->next;
1993         }
1994 }
1995
1996 /***************************************************************************
1997 Check a service for consistency. Return False if the service is in any way
1998 incomplete or faulty, else True.
1999 ***************************************************************************/
2000
2001 static BOOL service_ok(int iService)
2002 {
2003         BOOL bRetval;
2004
2005         bRetval = True;
2006         if (ServicePtrs[iService]->szService[0] == '\0') {
2007                 DEBUG(0, ("The following message indicates an internal error:\n"));
2008                 DEBUG(0, ("No service name in service entry.\n"));
2009                 bRetval = False;
2010         }
2011
2012         /* The [printers] entry MUST be printable. I'm all for flexibility, but */
2013         /* I can't see why you'd want a non-printable printer service...        */
2014         if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
2015                 if (!ServicePtrs[iService]->bPrint_ok) {
2016                         DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
2017                                ServicePtrs[iService]->szService));
2018                         ServicePtrs[iService]->bPrint_ok = True;
2019                 }
2020                 /* [printers] service must also be non-browsable. */
2021                 if (ServicePtrs[iService]->bBrowseable)
2022                         ServicePtrs[iService]->bBrowseable = False;
2023         }
2024
2025         if (ServicePtrs[iService]->szPath[0] == '\0' &&
2026             strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0) {
2027                 DEBUG(0, ("No path in service %s - using %s\n",
2028                        ServicePtrs[iService]->szService, tmpdir()));
2029                 string_set(&ServicePtrs[iService]->szPath, tmpdir());
2030         }
2031
2032         /* If a service is flagged unavailable, log the fact at level 0. */
2033         if (!ServicePtrs[iService]->bAvailable)
2034                 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
2035                           ServicePtrs[iService]->szService));
2036
2037         return (bRetval);
2038 }
2039
2040 static struct file_lists {
2041         struct file_lists *next;
2042         char *name;
2043         char *subfname;
2044         time_t modtime;
2045 } *file_lists = NULL;
2046
2047 /*******************************************************************
2048  Keep a linked list of all config files so we know when one has changed 
2049  it's date and needs to be reloaded.
2050 ********************************************************************/
2051
2052 static void add_to_file_list(const char *fname, const char *subfname)
2053 {
2054         struct file_lists *f = file_lists;
2055
2056         while (f) {
2057                 if (f->name && !strcmp(f->name, fname))
2058                         break;
2059                 f = f->next;
2060         }
2061
2062         if (!f) {
2063                 f = (struct file_lists *)malloc(sizeof(file_lists[0]));
2064                 if (!f)
2065                         return;
2066                 f->next = file_lists;
2067                 f->name = strdup(fname);
2068                 if (!f->name) {
2069                         SAFE_FREE(f);
2070                         return;
2071                 }
2072                 f->subfname = strdup(subfname);
2073                 if (!f->subfname) {
2074                         SAFE_FREE(f);
2075                         return;
2076                 }
2077                 file_lists = f;
2078                 f->modtime = file_modtime(subfname);
2079         } else {
2080                 time_t t = file_modtime(subfname);
2081                 if (t)
2082                         f->modtime = t;
2083         }
2084 }
2085
2086 /*******************************************************************
2087  Check if a config file has changed date.
2088 ********************************************************************/
2089
2090 BOOL lp_file_list_changed(void)
2091 {
2092         struct file_lists *f = file_lists;
2093         DEBUG(6, ("lp_file_list_changed()\n"));
2094
2095         while (f) {
2096                 pstring n2;
2097                 time_t mod_time;
2098
2099                 pstrcpy(n2, f->name);
2100                 standard_sub_basic(n2,sizeof(n2));
2101
2102                 DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
2103                              f->name, n2, ctime(&f->modtime)));
2104
2105                 mod_time = file_modtime(n2);
2106
2107                 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
2108                         DEBUGADD(6,
2109                                  ("file %s modified: %s\n", n2,
2110                                   ctime(&mod_time)));
2111                         f->modtime = mod_time;
2112                         SAFE_FREE(f->subfname);
2113                         f->subfname = strdup(n2);
2114                         return (True);
2115                 }
2116                 f = f->next;
2117         }
2118         return (False);
2119 }
2120
2121 /***************************************************************************
2122  Handle the include operation.
2123 ***************************************************************************/
2124
2125 static BOOL handle_include(const char *pszParmValue, char **ptr)
2126 {
2127         pstring fname;
2128         pstrcpy(fname, pszParmValue);
2129
2130         standard_sub_basic(fname,sizeof(fname));
2131
2132         add_to_file_list(pszParmValue, fname);
2133
2134         string_set(ptr, fname);
2135
2136         if (file_exist(fname, NULL))
2137                 return (pm_process(fname, do_section, do_parameter));
2138
2139         DEBUG(2, ("Can't find include file %s\n", fname));
2140
2141         return (False);
2142 }
2143
2144 /***************************************************************************
2145  Handle the interpretation of the copy parameter.
2146 ***************************************************************************/
2147
2148 static BOOL handle_copy(const char *pszParmValue, char **ptr)
2149 {
2150         BOOL bRetval;
2151         int iTemp;
2152         service serviceTemp;
2153
2154         string_set(ptr, pszParmValue);
2155
2156         init_service(&serviceTemp);
2157
2158         bRetval = False;
2159
2160         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
2161
2162         if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
2163                 if (iTemp == iServiceIndex) {
2164                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
2165                 } else {
2166                         copy_service(ServicePtrs[iServiceIndex],
2167                                      &serviceTemp,
2168                                      ServicePtrs[iServiceIndex]->copymap);
2169                         bRetval = True;
2170                 }
2171         } else {
2172                 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
2173                 bRetval = False;
2174         }
2175
2176         free_service(&serviceTemp);
2177         return (bRetval);
2178 }
2179
2180 /***************************************************************************
2181  Handle winbind/non unix account uid and gid allocation parameters.  The format of these
2182  parameters is:
2183
2184  [global]
2185
2186         winbind uid = 1000-1999
2187         winbind gid = 700-899
2188
2189  We only do simple parsing checks here.  The strings are parsed into useful
2190  structures in the winbind daemon code.
2191
2192 ***************************************************************************/
2193
2194 /* Some lp_ routines to return winbind [ug]id information */
2195
2196 static uid_t winbind_uid_low, winbind_uid_high;
2197 static gid_t winbind_gid_low, winbind_gid_high;
2198 static uint32_t non_unix_account_low, non_unix_account_high;
2199
2200 BOOL lp_winbind_uid(uid_t *low, uid_t *high)
2201 {
2202         if (winbind_uid_low == 0 || winbind_uid_high == 0)
2203                 return False;
2204
2205         if (low)
2206                 *low = winbind_uid_low;
2207
2208         if (high)
2209                 *high = winbind_uid_high;
2210
2211         return True;
2212 }
2213
2214 BOOL lp_winbind_gid(gid_t *low, gid_t *high)
2215 {
2216         if (winbind_gid_low == 0 || winbind_gid_high == 0)
2217                 return False;
2218
2219         if (low)
2220                 *low = winbind_gid_low;
2221
2222         if (high)
2223                 *high = winbind_gid_high;
2224
2225         return True;
2226 }
2227
2228 BOOL lp_non_unix_account_range(uint32_t *low, uint32_t *high)
2229 {
2230         if (non_unix_account_low == 0 || non_unix_account_high == 0)
2231                 return False;
2232
2233         if (low)
2234                 *low = non_unix_account_low;
2235
2236         if (high)
2237                 *high = non_unix_account_high;
2238
2239         return True;
2240 }
2241
2242 /* Do some simple checks on "winbind [ug]id" parameter values */
2243
2244 static BOOL handle_winbind_uid(const char *pszParmValue, char **ptr)
2245 {
2246         uint32_t low, high;
2247
2248         if (sscanf(pszParmValue, "%u-%u", &low, &high) != 2 || high < low)
2249                 return False;
2250
2251         /* Parse OK */
2252
2253         string_set(ptr, pszParmValue);
2254
2255         winbind_uid_low = low;
2256         winbind_uid_high = high;
2257
2258         return True;
2259 }
2260
2261 static BOOL handle_winbind_gid(const char *pszParmValue, char **ptr)
2262 {
2263         uint32_t low, high;
2264
2265         if (sscanf(pszParmValue, "%u-%u", &low, &high) != 2 || high < low)
2266                 return False;
2267
2268         /* Parse OK */
2269
2270         string_set(ptr, pszParmValue);
2271
2272         winbind_gid_low = low;
2273         winbind_gid_high = high;
2274
2275         return True;
2276 }
2277
2278 /***************************************************************************
2279  Do some simple checks on "non unix account range" parameter values.
2280 ***************************************************************************/
2281
2282 static BOOL handle_non_unix_account_range(const char *pszParmValue, char **ptr)
2283 {
2284         uint32_t low, high;
2285
2286         if (sscanf(pszParmValue, "%u-%u", &low, &high) != 2 || high < low)
2287                 return False;
2288
2289         /* Parse OK */
2290
2291         string_set(ptr, pszParmValue);
2292
2293         non_unix_account_low = low;
2294         non_unix_account_high = high;
2295
2296         return True;
2297 }
2298
2299 /***************************************************************************
2300  Handle the ldap machine suffix option.
2301 ***************************************************************************/
2302
2303 static BOOL handle_ldap_machine_suffix( const char *pszParmValue, char **ptr)
2304 {
2305        pstring suffix;
2306        
2307        pstrcpy(suffix, pszParmValue);
2308
2309        if (! *Globals.szLdapSuffix ) {
2310                string_set( ptr, suffix );
2311                return True;
2312        }
2313
2314        if (! strstr(suffix, Globals.szLdapSuffix) ) {
2315                if ( *pszParmValue )
2316                        pstrcat(suffix, ",");
2317                pstrcat(suffix, Globals.szLdapSuffix);
2318        }
2319        string_set( ptr, suffix );
2320        return True;
2321 }
2322
2323 /***************************************************************************
2324  Handle the ldap user suffix option.
2325 ***************************************************************************/
2326
2327 static BOOL handle_ldap_user_suffix( const char *pszParmValue, char **ptr)
2328 {
2329        pstring suffix;
2330        
2331        pstrcpy(suffix, pszParmValue);
2332
2333        if (! *Globals.szLdapSuffix ) {
2334                string_set( ptr, suffix );
2335                return True;
2336        }
2337        
2338        if (! strstr(suffix, Globals.szLdapSuffix) ) {
2339                if ( *pszParmValue )
2340                        pstrcat(suffix, ",");
2341                pstrcat(suffix, Globals.szLdapSuffix);
2342        }
2343        string_set( ptr, suffix );
2344        return True;
2345 }
2346
2347 /***************************************************************************
2348  Handle setting ldap suffix and determines whether ldap machine suffix needs
2349  to be set as well.
2350 ***************************************************************************/
2351
2352 static BOOL handle_ldap_suffix( const char *pszParmValue, char **ptr)
2353 {
2354        pstring suffix;
2355        pstring user_suffix;
2356        pstring machine_suffix;  
2357                   
2358        pstrcpy(suffix, pszParmValue);
2359
2360        if (! *Globals.szLdapMachineSuffix )
2361                string_set(&Globals.szLdapMachineSuffix, suffix);
2362        if (! *Globals.szLdapUserSuffix ) 
2363                string_set(&Globals.szLdapUserSuffix, suffix);
2364          
2365        if (! strstr(Globals.szLdapMachineSuffix, suffix)) {
2366                pstrcpy(machine_suffix, Globals.szLdapMachineSuffix);
2367                if ( *Globals.szLdapMachineSuffix )
2368                        pstrcat(machine_suffix, ",");
2369                pstrcat(machine_suffix, suffix);
2370                string_set(&Globals.szLdapMachineSuffix, machine_suffix);       
2371        }
2372
2373        if (! strstr(Globals.szLdapUserSuffix, suffix)) {
2374                pstrcpy(user_suffix, Globals.szLdapUserSuffix);
2375                if ( *Globals.szLdapUserSuffix )
2376                        pstrcat(user_suffix, ",");
2377                pstrcat(user_suffix, suffix);   
2378                string_set(&Globals.szLdapUserSuffix, user_suffix);
2379        } 
2380
2381        string_set(ptr, suffix); 
2382
2383        return True;
2384 }
2385
2386 /***************************************************************************
2387  Initialise a copymap.
2388 ***************************************************************************/
2389
2390 static void init_copymap(service * pservice)
2391 {
2392         int i;
2393         SAFE_FREE(pservice->copymap);
2394         pservice->copymap = (BOOL *)malloc(sizeof(BOOL) * NUMPARAMETERS);
2395         if (!pservice->copymap)
2396                 DEBUG(0,
2397                       ("Couldn't allocate copymap!! (size %d)\n",
2398                        (int)NUMPARAMETERS));
2399         else
2400                 for (i = 0; i < NUMPARAMETERS; i++)
2401                         pservice->copymap[i] = True;
2402 }
2403
2404 /***************************************************************************
2405  Return the local pointer to a parameter given the service number and the 
2406  pointer into the default structure.
2407 ***************************************************************************/
2408
2409 void *lp_local_ptr(int snum, void *ptr)
2410 {
2411         return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
2412 }
2413
2414
2415 /***************************************************************************
2416  Process a parametric option
2417 ***************************************************************************/
2418 static BOOL lp_do_parameter_parametric(int snum, const char *pszParmName, const char *pszParmValue, int flags)
2419 {
2420         struct param_opt *paramo, *data;
2421         char *name;
2422
2423         while (isspace(*pszParmName)) {
2424                 pszParmName++;
2425         }
2426
2427         name = strdup(pszParmName);
2428         if (!name) return False;
2429
2430         strlower(name);
2431
2432         if (snum < 0) {
2433                 data = Globals.param_opt;
2434         } else {
2435                 data = ServicePtrs[snum]->param_opt;
2436         }
2437
2438         /* Traverse destination */
2439         for (paramo=data; paramo; paramo=paramo->next) {
2440                 /* If we already have the option set, override it unless
2441                    it was a command line option and the new one isn't */
2442                 if (strcmp(paramo->key, name) == 0) {
2443                         if ((paramo->flags & FLAG_CMDLINE) &&
2444                             !(flags & FLAG_CMDLINE)) {
2445                                 return True;
2446                         }
2447
2448                         free(paramo->value);
2449                         paramo->value = strdup(pszParmValue);
2450                         paramo->flags = flags;
2451                         free(name);
2452                         return True;
2453                 }
2454         }
2455
2456         paramo = smb_xmalloc(sizeof(*paramo));
2457         paramo->key = strdup(name);
2458         paramo->value = strdup(pszParmValue);
2459         paramo->flags = flags;
2460         if (snum < 0) {
2461                 DLIST_ADD(Globals.param_opt, paramo);
2462         } else {
2463                 DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
2464         }
2465
2466         free(name);
2467         
2468         return True;
2469 }
2470
2471 /***************************************************************************
2472  Process a parameter for a particular service number. If snum < 0
2473  then assume we are in the globals.
2474 ***************************************************************************/
2475 BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
2476 {
2477         int parmnum, i;
2478         void *parm_ptr = NULL;  /* where we are going to store the result */
2479         void *def_ptr = NULL;
2480
2481         parmnum = map_parameter(pszParmName);
2482
2483         if (parmnum < 0) {
2484                 if (strchr(pszParmName, ':')) {
2485                         return lp_do_parameter_parametric(snum, pszParmName, pszParmValue, 0);
2486                 }
2487                 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
2488                 return (True);
2489         }
2490
2491         if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
2492                 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
2493                           pszParmName));
2494         }
2495
2496         /* if the flag has been set on the command line, then don't allow override,
2497            but don't report an error */
2498         if (parm_table[parmnum].flags & FLAG_CMDLINE) {
2499                 return True;
2500         }
2501
2502         def_ptr = parm_table[parmnum].ptr;
2503
2504         /* we might point at a service, the default service or a global */
2505         if (snum < 0) {
2506                 parm_ptr = def_ptr;
2507         } else {
2508                 if (parm_table[parmnum].class == P_GLOBAL) {
2509                         DEBUG(0,
2510                               ("Global parameter %s found in service section!\n",
2511                                pszParmName));
2512                         return (True);
2513                 }
2514                 parm_ptr =
2515                         ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
2516                                                             &sDefault);
2517         }
2518
2519         if (snum >= 0) {
2520                 if (!ServicePtrs[snum]->copymap)
2521                         init_copymap(ServicePtrs[snum]);
2522
2523                 /* this handles the aliases - set the copymap for other entries with
2524                    the same data pointer */
2525                 for (i = 0; parm_table[i].label; i++)
2526                         if (parm_table[i].ptr == parm_table[parmnum].ptr)
2527                                 ServicePtrs[snum]->copymap[i] = False;
2528         }
2529
2530         /* if it is a special case then go ahead */
2531         if (parm_table[parmnum].special) {
2532                 parm_table[parmnum].special(pszParmValue, (char **)parm_ptr);
2533                 return (True);
2534         }
2535
2536         /* now switch on the type of variable it is */
2537         switch (parm_table[parmnum].type)
2538         {
2539                 case P_BOOL:
2540                         set_boolean(parm_ptr, pszParmValue);
2541                         break;
2542
2543                 case P_BOOLREV:
2544                         set_boolean(parm_ptr, pszParmValue);
2545                         *(BOOL *)parm_ptr = !*(BOOL *)parm_ptr;
2546                         break;
2547
2548                 case P_INTEGER:
2549                         *(int *)parm_ptr = atoi(pszParmValue);
2550                         break;
2551
2552                 case P_CHAR:
2553                         *(char *)parm_ptr = *pszParmValue;
2554                         break;
2555
2556                 case P_OCTAL:
2557                         sscanf(pszParmValue, "%o", (int *)parm_ptr);
2558                         break;
2559
2560                 case P_LIST:
2561                         *(char ***)parm_ptr = str_list_make(pszParmValue, NULL);
2562                         break;
2563
2564                 case P_STRING:
2565                         string_set(parm_ptr, pszParmValue);
2566                         break;
2567
2568                 case P_USTRING:
2569                         string_set(parm_ptr, pszParmValue);
2570                         strupper(*(char **)parm_ptr);
2571                         break;
2572
2573                 case P_ENUM:
2574                         for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
2575                                 if (strequal
2576                                     (pszParmValue,
2577                                      parm_table[parmnum].enum_list[i].name)) {
2578                                         *(int *)parm_ptr =
2579                                                 parm_table[parmnum].
2580                                                 enum_list[i].value;
2581                                         break;
2582                                 }
2583                         }
2584                         break;
2585                 case P_SEP:
2586                         break;
2587         }
2588
2589         return (True);
2590 }
2591
2592 /***************************************************************************
2593  Process a parameter.
2594 ***************************************************************************/
2595
2596 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue)
2597 {
2598         if (!bInGlobalSection && bGlobalOnly)
2599                 return (True);
2600
2601         DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
2602
2603         return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
2604                                 pszParmName, pszParmValue));
2605 }
2606
2607
2608 /*
2609   set a parameter from the commandline - this is called from command line parameter
2610   parsing code. It sets the parameter then marks the parameter as unable to be modified
2611   by smb.conf processing
2612 */
2613 BOOL lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
2614 {
2615         int parmnum = map_parameter(pszParmName);
2616
2617         if (parmnum < 0 && strchr(pszParmName, ':')) {
2618                 /* set a parametric option */
2619                 return lp_do_parameter_parametric(-1, pszParmName, pszParmValue, FLAG_CMDLINE);
2620         }
2621
2622         /* reset the CMDLINE flag in case this has been called before */
2623         parm_table[parmnum].flags &= ~FLAG_CMDLINE;
2624
2625         if (!lp_do_parameter(-2, pszParmName, pszParmValue)) {
2626                 return False;
2627         }
2628
2629         parm_table[parmnum].flags |= FLAG_CMDLINE;
2630         return True;
2631 }
2632
2633 /***************************************************************************
2634  Print a parameter of the specified type.
2635 ***************************************************************************/
2636
2637 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
2638 {
2639         int i;
2640         switch (p->type)
2641         {
2642                 case P_ENUM:
2643                         for (i = 0; p->enum_list[i].name; i++) {
2644                                 if (*(int *)ptr == p->enum_list[i].value) {
2645                                         fprintf(f, "%s",
2646                                                 p->enum_list[i].name);
2647                                         break;
2648                                 }
2649                         }
2650                         break;
2651
2652                 case P_BOOL:
2653                         fprintf(f, "%s", BOOLSTR(*(BOOL *)ptr));
2654                         break;
2655
2656                 case P_BOOLREV:
2657                         fprintf(f, "%s", BOOLSTR(!*(BOOL *)ptr));
2658                         break;
2659
2660                 case P_INTEGER:
2661                         fprintf(f, "%d", *(int *)ptr);
2662                         break;
2663
2664                 case P_CHAR:
2665                         fprintf(f, "%c", *(char *)ptr);
2666                         break;
2667
2668                 case P_OCTAL:
2669                         fprintf(f, "%s", octal_string(*(int *)ptr));
2670                         break;
2671
2672                 case P_LIST:
2673                         if ((char ***)ptr && *(char ***)ptr) {
2674                                 char **list = *(char ***)ptr;
2675                                 
2676                                 for (; *list; list++)
2677                                         fprintf(f, "%s%s", *list,
2678                                                 ((*(list+1))?", ":""));
2679                         }
2680                         break;
2681
2682                 case P_STRING:
2683                 case P_USTRING:
2684                         if (*(char **)ptr) {
2685                                 fprintf(f, "%s", *(char **)ptr);
2686                         }
2687                         break;
2688                 case P_SEP:
2689                         break;
2690         }
2691 }
2692
2693 /***************************************************************************
2694  Check if two parameters are equal.
2695 ***************************************************************************/
2696
2697 static BOOL equal_parameter(parm_type type, void *ptr1, void *ptr2)
2698 {
2699         switch (type) {
2700                 case P_BOOL:
2701                 case P_BOOLREV:
2702                         return (*((BOOL *)ptr1) == *((BOOL *)ptr2));
2703
2704                 case P_INTEGER:
2705                 case P_ENUM:
2706                 case P_OCTAL:
2707                         return (*((int *)ptr1) == *((int *)ptr2));
2708
2709                 case P_CHAR:
2710                         return (*((char *)ptr1) == *((char *)ptr2));
2711                 
2712                 case P_LIST:
2713                         return str_list_compare(*(char ***)ptr1, *(char ***)ptr2);
2714
2715                 case P_STRING:
2716                 case P_USTRING:
2717                 {
2718                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
2719                         if (p1 && !*p1)
2720                                 p1 = NULL;
2721                         if (p2 && !*p2)
2722                                 p2 = NULL;
2723                         return (p1 == p2 || strequal(p1, p2));
2724                 }
2725                 case P_SEP:
2726                         break;
2727         }
2728         return (False);
2729 }
2730
2731 /***************************************************************************
2732  Process a new section (service). At this stage all sections are services.
2733  Later we'll have special sections that permit server parameters to be set.
2734  Returns True on success, False on failure. 
2735 ***************************************************************************/
2736
2737 static BOOL do_section(const char *pszSectionName)
2738 {
2739         BOOL bRetval;
2740         BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2741                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2742         bRetval = False;
2743
2744         /* if we've just struck a global section, note the fact. */
2745         bInGlobalSection = isglobal;
2746
2747         /* check for multiple global sections */
2748         if (bInGlobalSection) {
2749                 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2750                 return (True);
2751         }
2752
2753         if (!bInGlobalSection && bGlobalOnly)
2754                 return (True);
2755
2756         /* if we have a current service, tidy it up before moving on */
2757         bRetval = True;
2758
2759         if (iServiceIndex >= 0)
2760                 bRetval = service_ok(iServiceIndex);
2761
2762         /* if all is still well, move to the next record in the services array */
2763         if (bRetval) {
2764                 /* We put this here to avoid an odd message order if messages are */
2765                 /* issued by the post-processing of a previous section. */
2766                 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2767
2768                 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
2769                     < 0) {
2770                         DEBUG(0, ("Failed to add a new service\n"));
2771                         return (False);
2772                 }
2773         }
2774
2775         return (bRetval);
2776 }
2777
2778
2779 /***************************************************************************
2780  Determine if a partcular base parameter is currentl set to the default value.
2781 ***************************************************************************/
2782
2783 static BOOL is_default(int i)
2784 {
2785         if (!defaults_saved)
2786                 return False;
2787         switch (parm_table[i].type) {
2788                 case P_LIST:
2789                         return str_list_compare (parm_table[i].def.lvalue, 
2790                                                 *(char ***)parm_table[i].ptr);
2791                 case P_STRING:
2792                 case P_USTRING:
2793                         return strequal(parm_table[i].def.svalue,
2794                                         *(char **)parm_table[i].ptr);
2795                 case P_BOOL:
2796                 case P_BOOLREV:
2797                         return parm_table[i].def.bvalue ==
2798                                 *(BOOL *)parm_table[i].ptr;
2799                 case P_CHAR:
2800                         return parm_table[i].def.cvalue ==
2801                                 *(char *)parm_table[i].ptr;
2802                 case P_INTEGER:
2803                 case P_OCTAL:
2804                 case P_ENUM:
2805                         return parm_table[i].def.ivalue ==
2806                                 *(int *)parm_table[i].ptr;
2807                 case P_SEP:
2808                         break;
2809         }
2810         return False;
2811 }
2812
2813 /***************************************************************************
2814 Display the contents of the global structure.
2815 ***************************************************************************/
2816
2817 static void dump_globals(FILE *f)
2818 {
2819         int i;
2820         struct param_opt *data;
2821         
2822         fprintf(f, "# Global parameters\n[global]\n");
2823
2824         for (i = 0; parm_table[i].label; i++)
2825                 if (parm_table[i].class == P_GLOBAL &&
2826                     parm_table[i].ptr &&
2827                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2828                         if (defaults_saved && is_default(i))
2829                                 continue;
2830                         fprintf(f, "\t%s = ", parm_table[i].label);
2831                         print_parameter(&parm_table[i], parm_table[i].ptr, f);
2832                         fprintf(f, "\n");
2833         }
2834         if (Globals.param_opt != NULL) {
2835                 data = Globals.param_opt;
2836                 while(data) {
2837                         fprintf(f, "\t%s = %s\n", data->key, data->value);
2838                         data = data->next;
2839                 }
2840         }
2841
2842 }
2843
2844 /***************************************************************************
2845  Return True if a local parameter is currently set to the global default.
2846 ***************************************************************************/
2847
2848 BOOL lp_is_default(int snum, struct parm_struct *parm)
2849 {
2850         int pdiff = PTR_DIFF(parm->ptr, &sDefault);
2851
2852         return equal_parameter(parm->type,
2853                                ((char *)ServicePtrs[snum]) + pdiff,
2854                                ((char *)&sDefault) + pdiff);
2855 }
2856
2857 /***************************************************************************
2858  Display the contents of a single services record.
2859 ***************************************************************************/
2860
2861 static void dump_a_service(service * pService, FILE * f)
2862 {
2863         int i;
2864         struct param_opt *data;
2865         
2866         if (pService != &sDefault)
2867                 fprintf(f, "\n[%s]\n", pService->szService);
2868
2869         for (i = 0; parm_table[i].label; i++)
2870                 if (parm_table[i].class == P_LOCAL &&
2871                     parm_table[i].ptr &&
2872                     (*parm_table[i].label != '-') &&
2873                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2874                         int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
2875
2876                         if (pService == &sDefault) {
2877                                 if (defaults_saved && is_default(i))
2878                                         continue;
2879                         } else {
2880                                 if (equal_parameter(parm_table[i].type,
2881                                                     ((char *)pService) +
2882                                                     pdiff,
2883                                                     ((char *)&sDefault) +
2884                                                     pdiff))
2885                                         continue;
2886                         }
2887
2888                         fprintf(f, "\t%s = ", parm_table[i].label);
2889                         print_parameter(&parm_table[i],
2890                                         ((char *)pService) + pdiff, f);
2891                         fprintf(f, "\n");
2892         }
2893         if (pService->param_opt != NULL) {
2894                 data = pService->param_opt;
2895                 while(data) {
2896                         fprintf(f, "\t%s = %s\n", data->key, data->value);
2897                         data = data->next;
2898                 }
2899         }
2900 }
2901
2902
2903 /***************************************************************************
2904  Return info about the next service  in a service. snum==-1 gives the globals.
2905  Return NULL when out of parameters.
2906 ***************************************************************************/
2907
2908 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
2909 {
2910         if (snum == -1) {
2911                 /* do the globals */
2912                 for (; parm_table[*i].label; (*i)++) {
2913                         if (parm_table[*i].class == P_SEPARATOR)
2914                                 return &parm_table[(*i)++];
2915
2916                         if (!parm_table[*i].ptr
2917                             || (*parm_table[*i].label == '-'))
2918                                 continue;
2919
2920                         if ((*i) > 0
2921                             && (parm_table[*i].ptr ==
2922                                 parm_table[(*i) - 1].ptr))
2923                                 continue;
2924
2925                         return &parm_table[(*i)++];
2926                 }
2927         } else {
2928                 service *pService = ServicePtrs[snum];
2929
2930                 for (; parm_table[*i].label; (*i)++) {
2931                         if (parm_table[*i].class == P_SEPARATOR)
2932                                 return &parm_table[(*i)++];
2933
2934                         if (parm_table[*i].class == P_LOCAL &&
2935                             parm_table[*i].ptr &&
2936                             (*parm_table[*i].label != '-') &&
2937                             ((*i) == 0 ||
2938                              (parm_table[*i].ptr !=
2939                               parm_table[(*i) - 1].ptr)))
2940                         {
2941                                 int pdiff =
2942                                         PTR_DIFF(parm_table[*i].ptr,
2943                                                  &sDefault);
2944
2945                                 if (allparameters ||
2946                                     !equal_parameter(parm_table[*i].type,
2947                                                      ((char *)pService) +
2948                                                      pdiff,
2949                                                      ((char *)&sDefault) +
2950                                                      pdiff))
2951                                 {
2952                                         return &parm_table[(*i)++];
2953                                 }
2954                         }
2955                 }
2956         }
2957
2958         return NULL;
2959 }
2960
2961
2962 #if 0
2963 /***************************************************************************
2964  Display the contents of a single copy structure.
2965 ***************************************************************************/
2966 static void dump_copy_map(BOOL *pcopymap)
2967 {
2968         int i;
2969         if (!pcopymap)
2970                 return;
2971
2972         printf("\n\tNon-Copied parameters:\n");
2973
2974         for (i = 0; parm_table[i].label; i++)
2975                 if (parm_table[i].class == P_LOCAL &&
2976                     parm_table[i].ptr && !pcopymap[i] &&
2977                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
2978                 {
2979                         printf("\t\t%s\n", parm_table[i].label);
2980                 }
2981 }
2982 #endif
2983
2984 /***************************************************************************
2985  Return TRUE if the passed service number is within range.
2986 ***************************************************************************/
2987
2988 BOOL lp_snum_ok(int iService)
2989 {
2990         return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
2991 }
2992
2993 /***************************************************************************
2994  Auto-load some home services.
2995 ***************************************************************************/
2996
2997 static void lp_add_auto_services(const char *str)
2998 {
2999         return;
3000 }
3001
3002 /***************************************************************************
3003  Auto-load one printer.
3004 ***************************************************************************/
3005
3006 void lp_add_one_printer(char *name, char *comment)
3007 {
3008         int printers = lp_servicenumber(PRINTERS_NAME);
3009         int i;
3010
3011         if (lp_servicenumber(name) < 0) {
3012                 lp_add_printer(name, printers);
3013                 if ((i = lp_servicenumber(name)) >= 0) {
3014                         string_set(&ServicePtrs[i]->comment, comment);
3015                         ServicePtrs[i]->autoloaded = True;
3016                 }
3017         }
3018 }
3019
3020 /***************************************************************************
3021  Announce ourselves as a print server.
3022 ***************************************************************************/
3023
3024 void update_server_announce_as_printserver(void)
3025 {
3026         default_server_announce |= SV_TYPE_PRINTQ_SERVER;       
3027 }
3028
3029 /***************************************************************************
3030  Have we loaded a services file yet?
3031 ***************************************************************************/
3032
3033 BOOL lp_loaded(void)
3034 {
3035         return (bLoaded);
3036 }
3037
3038 /***************************************************************************
3039  Unload unused services.
3040 ***************************************************************************/
3041
3042 void lp_killunused(struct smbsrv_connection *smb, BOOL (*snumused) (struct smbsrv_connection *, int))
3043 {
3044         int i;
3045         for (i = 0; i < iNumServices; i++) {
3046                 if (!VALID(i))
3047                         continue;
3048
3049                 if (!snumused || !snumused(smb, i)) {
3050                         ServicePtrs[i]->valid = False;
3051                         free_service(ServicePtrs[i]);
3052                 }
3053         }
3054 }
3055
3056 /***************************************************************************
3057  Unload a service.
3058 ***************************************************************************/
3059
3060 void lp_killservice(int iServiceIn)
3061 {
3062         if (VALID(iServiceIn)) {
3063                 ServicePtrs[iServiceIn]->valid = False;
3064                 free_service(ServicePtrs[iServiceIn]);
3065         }
3066 }
3067
3068 /***************************************************************************
3069  Save the curent values of all global and sDefault parameters into the 
3070  defaults union. This allows swat and testparm to show only the
3071  changed (ie. non-default) parameters.
3072 ***************************************************************************/
3073
3074 static void lp_save_defaults(void)
3075 {
3076         int i;
3077         for (i = 0; parm_table[i].label; i++) {
3078                 if (i > 0 && parm_table[i].ptr == parm_table[i - 1].ptr)
3079                         continue;
3080                 switch (parm_table[i].type) {
3081                         case P_LIST:
3082                                 str_list_copy(&(parm_table[i].def.lvalue),
3083                                             *(const char ***)parm_table[i].ptr);
3084                                 break;
3085                         case P_STRING:
3086                         case P_USTRING:
3087                                 if (parm_table[i].ptr) {
3088                                         parm_table[i].def.svalue = strdup(*(char **)parm_table[i].ptr);
3089                                 } else {
3090                                         parm_table[i].def.svalue = NULL;
3091                                 }
3092                                 break;
3093                         case P_BOOL:
3094                         case P_BOOLREV:
3095                                 parm_table[i].def.bvalue =
3096                                         *(BOOL *)parm_table[i].ptr;
3097                                 break;
3098                         case P_CHAR:
3099                                 parm_table[i].def.cvalue =
3100                                         *(char *)parm_table[i].ptr;
3101                                 break;
3102                         case P_INTEGER:
3103                         case P_OCTAL:
3104                         case P_ENUM:
3105                                 parm_table[i].def.ivalue =
3106                                         *(int *)parm_table[i].ptr;
3107                                 break;
3108                         case P_SEP:
3109                                 break;
3110                 }
3111         }
3112         defaults_saved = True;
3113 }
3114
3115 /*******************************************************************
3116  Set the server type we will announce as via nmbd.
3117 ********************************************************************/
3118
3119 static void set_server_role(void)
3120 {
3121         server_role = ROLE_STANDALONE;
3122
3123         switch (lp_security()) {
3124                 case SEC_SHARE:
3125                         if (lp_domain_logons())
3126                                 DEBUG(0, ("Server's Role (logon server) conflicts with share-level security\n"));
3127                         break;
3128                 case SEC_SERVER:
3129                 case SEC_DOMAIN:
3130                 case SEC_ADS:
3131                         if (lp_domain_logons()) {
3132                                 server_role = ROLE_DOMAIN_PDC;
3133                                 break;
3134                         }
3135                         server_role = ROLE_DOMAIN_MEMBER;
3136                         break;
3137                 case SEC_USER:
3138                         if (lp_domain_logons()) {
3139
3140                                 if (Globals.bDomainMaster) /* auto or yes */ 
3141                                         server_role = ROLE_DOMAIN_PDC;
3142                                 else
3143                                         server_role = ROLE_DOMAIN_BDC;
3144                         }
3145                         break;
3146                 default:
3147                         DEBUG(0, ("Server's Role undefined due to unknown security mode\n"));
3148                         break;
3149         }
3150
3151         DEBUG(10, ("set_server_role: role = "));
3152
3153         switch(server_role) {
3154         case ROLE_STANDALONE:
3155                 DEBUGADD(10, ("ROLE_STANDALONE\n"));
3156                 break;
3157         case ROLE_DOMAIN_MEMBER:
3158                 DEBUGADD(10, ("ROLE_DOMAIN_MEMBER\n"));
3159                 break;
3160         case ROLE_DOMAIN_BDC:
3161                 DEBUGADD(10, ("ROLE_DOMAIN_BDC\n"));
3162                 break;
3163         case ROLE_DOMAIN_PDC:
3164                 DEBUGADD(10, ("ROLE_DOMAIN_PDC\n"));
3165                 break;
3166         }
3167 }
3168
3169 /***************************************************************************
3170  Load the services array from the services file. Return True on success, 
3171  False on failure.
3172 ***************************************************************************/
3173
3174 BOOL lp_load(const char *pszFname, BOOL global_only, BOOL save_defaults,
3175              BOOL add_ipc)
3176 {
3177         pstring n2;
3178         BOOL bRetval;
3179         struct param_opt *data;
3180
3181         pstrcpy(n2, pszFname);
3182         standard_sub_basic(n2,sizeof(n2));
3183
3184         add_to_file_list(pszFname, n2);
3185
3186         bRetval = False;
3187
3188         DEBUG(2, ("lp_load: refreshing parameters from %s\n", pszFname));
3189         
3190         bInGlobalSection = True;
3191         bGlobalOnly = global_only;
3192
3193         init_globals();
3194
3195         if (save_defaults)
3196         {
3197                 lp_save_defaults();
3198         }
3199
3200         if (Globals.param_opt != NULL) {
3201                 struct param_opt *next;
3202                 for (data=Globals.param_opt; data; data=next) {
3203                         next = data->next;
3204                         if (data->flags & FLAG_CMDLINE) continue;
3205                         free(data->key);
3206                         free(data->value);
3207                         DLIST_REMOVE(Globals.param_opt, data);
3208                         free(data);
3209                 }
3210         }
3211         
3212         /* We get sections first, so have to start 'behind' to make up */
3213         iServiceIndex = -1;
3214         bRetval = pm_process(n2, do_section, do_parameter);
3215
3216         /* finish up the last section */
3217         DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
3218         if (bRetval)
3219                 if (iServiceIndex >= 0)
3220                         bRetval = service_ok(iServiceIndex);
3221
3222         lp_add_auto_services(lp_auto_services());
3223
3224         if (add_ipc) {
3225                 /* When 'restrict anonymous = 2' guest connections to ipc$
3226                    are denied */
3227                 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
3228                 lp_add_ipc("ADMIN$", False);
3229         }
3230
3231         set_server_role();
3232         set_default_server_announce_type();
3233
3234         bLoaded = True;
3235
3236         /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
3237         /* if bWINSsupport is true and we are in the client            */
3238         if (in_client && Globals.bWINSsupport) {
3239                 lp_do_parameter(-1, "wins server", "127.0.0.1");
3240         }
3241
3242         init_iconv();
3243
3244         return (bRetval);
3245 }
3246
3247 /***************************************************************************
3248  Reset the max number of services.
3249 ***************************************************************************/
3250
3251 void lp_resetnumservices(void)
3252 {
3253         iNumServices = 0;
3254 }
3255
3256 /***************************************************************************
3257  Return the max number of services.
3258 ***************************************************************************/
3259
3260 int lp_numservices(void)
3261 {
3262         return (iNumServices);
3263 }
3264
3265 /***************************************************************************
3266 Display the contents of the services array in human-readable form.
3267 ***************************************************************************/
3268
3269 void lp_dump(FILE *f, BOOL show_defaults, int maxtoprint)
3270 {
3271         int iService;
3272
3273         if (show_defaults)
3274                 defaults_saved = False;
3275
3276         dump_globals(f);
3277
3278         dump_a_service(&sDefault, f);
3279
3280         for (iService = 0; iService < maxtoprint; iService++)
3281                 lp_dump_one(f, show_defaults, iService);
3282 }
3283
3284 /***************************************************************************
3285 Display the contents of one service in human-readable form.
3286 ***************************************************************************/
3287
3288 void lp_dump_one(FILE * f, BOOL show_defaults, int snum)
3289 {
3290         if (VALID(snum)) {
3291                 if (ServicePtrs[snum]->szService[0] == '\0')
3292                         return;
3293                 dump_a_service(ServicePtrs[snum], f);
3294         }
3295 }
3296
3297 /***************************************************************************
3298 Return the number of the service with the given name, or -1 if it doesn't
3299 exist. Note that this is a DIFFERENT ANIMAL from the internal function
3300 getservicebyname()! This works ONLY if all services have been loaded, and
3301 does not copy the found service.
3302 ***************************************************************************/
3303
3304 int lp_servicenumber(const char *pszServiceName)
3305 {
3306         int iService;
3307         fstring serviceName;
3308  
3309  
3310         for (iService = iNumServices - 1; iService >= 0; iService--) {
3311                 if (VALID(iService) && ServicePtrs[iService]->szService) {
3312                         /*
3313                          * The substitution here is used to support %U is
3314                          * service names
3315                          */
3316                         fstrcpy(serviceName, ServicePtrs[iService]->szService);
3317                         standard_sub_basic(serviceName,sizeof(serviceName));
3318                         if (strequal(serviceName, pszServiceName))
3319                                 break;
3320                 }
3321         }
3322
3323         if (iService < 0)
3324                 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
3325
3326         return (iService);
3327 }
3328
3329 /*******************************************************************
3330  A useful volume label function. 
3331 ********************************************************************/
3332 const char *volume_label(int snum)
3333 {
3334         const char *ret = lp_volume(snum);
3335         if (!*ret)
3336                 return lp_servicename(snum);
3337         return (ret);
3338 }
3339
3340
3341 /*******************************************************************
3342  Set the server type we will announce as via nmbd.
3343 ********************************************************************/
3344
3345 static void set_default_server_announce_type(void)
3346 {
3347         default_server_announce = 0;
3348         default_server_announce |= SV_TYPE_WORKSTATION;
3349         default_server_announce |= SV_TYPE_SERVER;
3350         default_server_announce |= SV_TYPE_SERVER_UNIX;
3351
3352         switch (lp_announce_as()) {
3353                 case ANNOUNCE_AS_NT_SERVER:
3354                         default_server_announce |= SV_TYPE_SERVER_NT;
3355                         /* fall through... */
3356                 case ANNOUNCE_AS_NT_WORKSTATION:
3357                         default_server_announce |= SV_TYPE_NT;
3358                         break;
3359                 case ANNOUNCE_AS_WIN95:
3360                         default_server_announce |= SV_TYPE_WIN95_PLUS;
3361                         break;
3362                 case ANNOUNCE_AS_WFW:
3363                         default_server_announce |= SV_TYPE_WFW;
3364                         break;
3365                 default:
3366                         break;
3367         }
3368
3369         switch (lp_server_role()) {
3370                 case ROLE_DOMAIN_MEMBER:
3371                         default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
3372                         break;
3373                 case ROLE_DOMAIN_PDC:
3374                         default_server_announce |= SV_TYPE_DOMAIN_CTRL;
3375                         break;
3376                 case ROLE_DOMAIN_BDC:
3377                         default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
3378                         break;
3379                 case ROLE_STANDALONE:
3380                 default:
3381                         break;
3382         }
3383         if (lp_time_server())
3384                 default_server_announce |= SV_TYPE_TIME_SOURCE;
3385
3386         if (lp_host_msdfs())
3387                 default_server_announce |= SV_TYPE_DFS_SERVER;
3388 }
3389
3390 /***********************************************************
3391  returns role of Samba server
3392 ************************************************************/
3393
3394 int lp_server_role(void)
3395 {
3396         return server_role;
3397 }
3398
3399 /***********************************************************
3400  If we are PDC then prefer us as DMB
3401 ************************************************************/
3402
3403 BOOL lp_domain_master(void)
3404 {
3405         if (Globals.bDomainMaster == Auto)
3406                 return (lp_server_role() == ROLE_DOMAIN_PDC);
3407
3408         return Globals.bDomainMaster;
3409 }
3410
3411 /***********************************************************
3412  If we are DMB then prefer us as LMB
3413 ************************************************************/
3414
3415 BOOL lp_preferred_master(void)
3416 {
3417         if (Globals.bPreferredMaster == Auto)
3418                 return (lp_local_master() && lp_domain_master());
3419
3420         return Globals.bPreferredMaster;
3421 }
3422
3423 /*******************************************************************
3424  Remove a service.
3425 ********************************************************************/
3426
3427 void lp_remove_service(int snum)
3428 {
3429         ServicePtrs[snum]->valid = False;
3430 }
3431
3432 /*******************************************************************
3433  Copy a service.
3434 ********************************************************************/
3435
3436 void lp_copy_service(int snum, const char *new_name)
3437 {
3438         const char *oldname = lp_servicename(snum);
3439         do_section(new_name);
3440         if (snum >= 0) {
3441                 snum = lp_servicenumber(new_name);
3442                 if (snum >= 0)
3443                         lp_do_parameter(snum, "copy", oldname);
3444         }
3445 }
3446
3447
3448 /*******************************************************************
3449  Get the default server type we will announce as via nmbd.
3450 ********************************************************************/
3451
3452 int lp_default_server_announce(void)
3453 {
3454         return default_server_announce;
3455 }
3456
3457 /*******************************************************************
3458  Split the announce version into major and minor numbers.
3459 ********************************************************************/
3460
3461 int lp_major_announce_version(void)
3462 {
3463         static BOOL got_major = False;
3464         static int major_version = DEFAULT_MAJOR_VERSION;
3465         const char *vers;
3466         char *p;
3467
3468         if (got_major)
3469                 return major_version;
3470
3471         got_major = True;
3472         if ((vers = lp_announce_version()) == NULL)
3473                 return major_version;
3474
3475         if ((p = strchr_m(vers, '.')) == 0)
3476                 return major_version;
3477
3478         *p = '\0';
3479         major_version = atoi(vers);
3480         return major_version;
3481 }
3482
3483 int lp_minor_announce_version(void)
3484 {
3485         static BOOL got_minor = False;
3486         static int minor_version = DEFAULT_MINOR_VERSION;
3487         const char *vers;
3488         char *p;
3489
3490         if (got_minor)
3491                 return minor_version;
3492
3493         got_minor = True;
3494         if ((vers = lp_announce_version()) == NULL)
3495                 return minor_version;
3496
3497         if ((p = strchr_m(vers, '.')) == 0)
3498                 return minor_version;
3499
3500         p++;
3501         minor_version = atoi(p);
3502         return minor_version;
3503 }
3504
3505 const char *lp_printername(int snum)
3506 {
3507         const char *ret = _lp_printername(snum);
3508         if (ret == NULL || (ret != NULL && *ret == '\0'))
3509                 ret = lp_const_servicename(snum);
3510
3511         return ret;
3512 }
3513
3514
3515 /*******************************************************************
3516  Return the max print jobs per queue.
3517 ********************************************************************/
3518
3519 int lp_maxprintjobs(int snum)
3520 {
3521         int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
3522         if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
3523                 maxjobs = PRINT_MAX_JOBID - 1;
3524
3525         return maxjobs;
3526 }