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