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