r1207: Add spoolss to the list of endpoint servers.
[samba.git] / source4 / param / loadparm.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Parameter loading functions
4    Copyright (C) Karl Auer 1993-1998
5
6    Largely re-written by Andrew Tridgell, September 1994
7
8    Copyright (C) Simo Sorce 2001
9    Copyright (C) Alexander Bokovoy 2002
10    Copyright (C) Stefan (metze) Metzmacher 2002
11    Copyright (C) Anthony Liguori 2003
12    Copyright (C) James Myers 2003 <myersjj@samba.org>
13    
14    This program is free software; you can redistribute it and/or modify
15    it under the terms of the GNU General Public License as published by
16    the Free Software Foundation; either version 2 of the License, or
17    (at your option) any later version.
18    
19    This program is distributed in the hope that it will be useful,
20    but WITHOUT ANY WARRANTY; without even the implied warranty of
21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22    GNU General Public License for more details.
23    
24    You should have received a copy of the GNU General Public License
25    along with this program; if not, write to the Free Software
26    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 */
28
29 /*
30  *  Load parameters.
31  *
32  *  This module provides suitable callback functions for the params
33  *  module. It builds the internal table of service details which is
34  *  then used by the rest of the server.
35  *
36  * To add a parameter:
37  *
38  * 1) add it to the global or service structure definition
39  * 2) add it to the parm_table
40  * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
41  * 4) If it's a global then initialise it in init_globals. If a local
42  *    (ie. service) parameter then initialise it in the sDefault structure
43  *  
44  *
45  * Notes:
46  *   The configuration file is processed sequentially for speed. It is NOT
47  *   accessed randomly as happens in 'real' Windows. For this reason, there
48  *   is a fair bit of sequence-dependent code here - ie., code which assumes
49  *   that certain things happen before others. In particular, the code which
50  *   happens at the boundary between sections is delicately poised, so be
51  *   careful!
52  *
53  */
54
55 #include "includes.h"
56
57 BOOL in_client = False;         /* Not in the client by default */
58 static BOOL bLoaded = False;
59
60 #ifndef GLOBAL_NAME
61 #define GLOBAL_NAME "global"
62 #endif
63
64 #ifndef PRINTERS_NAME
65 #define PRINTERS_NAME "printers"
66 #endif
67
68 #ifndef HOMES_NAME
69 #define HOMES_NAME "homes"
70 #endif
71
72 /* some helpful bits */
73 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && ServicePtrs[(i)]->valid)
74 #define VALID(i) ServicePtrs[i]->valid
75
76 static BOOL do_parameter(const char *, const char *);
77
78 static BOOL defaults_saved = False;
79
80 struct param_opt {
81         struct param_opt *prev, *next;
82         char *key;
83         char *value;
84         int flags;
85 };
86
87 /* 
88  * This structure describes global (ie., server-wide) parameters.
89  */
90 typedef struct
91 {
92         char *smb_ports;
93         char *dos_charset;
94         char *unix_charset;
95         char *display_charset;
96         char *szPrintcapname;
97         char *szLockDir;
98         char *szPidDir;
99         char *szRootdir;
100         char *szDefaultService;
101         char *szHostsEquiv;
102         char *szServerString;
103         char *szAutoServices;
104         char *szPasswdProgram;
105         char *szPasswdChat;
106         char *szLogFile;
107         char *szConfigFile;
108         char *szSMBPasswdFile;
109         char *szSAM_URL;
110         char *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 lsarpc spoolss", 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         string_set(&Globals.szGuestaccount, GUEST_ACCOUNT);
965
966         /* using UTF8 by default allows us to support all chars */
967         string_set(&Globals.unix_charset, "UTF8");
968
969         /* Use codepage 850 as a default for the dos character set */
970         string_set(&Globals.dos_charset, "CP850");
971
972         /*
973          * Allow the default PASSWD_CHAT to be overridden in local.h.
974          */
975         string_set(&Globals.szPasswdChat, DEFAULT_PASSWD_CHAT);
976         
977         string_set(&Globals.szPasswdProgram, "");
978         string_set(&Globals.szPrintcapname, PRINTCAP_NAME);
979         string_set(&Globals.szPidDir, dyn_PIDDIR);
980         string_set(&Globals.szLockDir, dyn_LOCKDIR);
981         string_set(&Globals.szSocketAddress, "0.0.0.0");
982         pstrcpy(s, "Samba ");
983         pstrcat(s, SAMBA_VERSION_STRING);
984         string_set(&Globals.szServerString, s);
985         slprintf(s, sizeof(s) - 1, "%d.%d", DEFAULT_MAJOR_VERSION,
986                  DEFAULT_MINOR_VERSION);
987         string_set(&Globals.szAnnounceVersion, s);
988
989         string_set(&Globals.szLogonDrive, "");
990         /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
991         string_set(&Globals.szLogonHome, "\\\\%N\\%U");
992         string_set(&Globals.szLogonPath, "\\\\%N\\%U\\profile");
993
994         string_set(&Globals.szPasswordServer, "*");
995
996         Globals.bLoadPrinters = True;
997         Globals.mangled_stack = 50;
998         Globals.max_mux = 50;   /* This is *needed* for profile support. */
999         Globals.max_xmit = 4356; /* the value w2k3 chooses */
1000         Globals.lpqcachetime = 10;
1001         Globals.bDisableSpoolss = False;
1002         Globals.pwordlevel = 0;
1003         Globals.unamelevel = 0;
1004         Globals.bLargeReadwrite = True;
1005         Globals.minprotocol = PROTOCOL_CORE;
1006         Globals.security = SEC_USER;
1007         Globals.paranoid_server_security = True;
1008         Globals.bEncryptPasswords = True;
1009         Globals.bUpdateEncrypt = False;
1010         Globals.bReadRaw = True;
1011         Globals.bWriteRaw = True;
1012         Globals.bNullPasswords = False;
1013         Globals.bObeyPamRestrictions = False;
1014         Globals.max_ttl = 60 * 60 * 24 * 3;     /* 3 days default. */
1015         Globals.max_wins_ttl = 60 * 60 * 24 * 6;        /* 6 days default. */
1016         Globals.min_wins_ttl = 60 * 60 * 6;     /* 6 hours default. */
1017         Globals.machine_password_timeout = 60 * 60 * 24 * 7;    /* 7 days default. */
1018         Globals.lm_announce = 2;        /* = Auto: send only if LM clients found */
1019         Globals.lm_interval = 60;
1020         Globals.announce_as = ANNOUNCE_AS_NT_SERVER;
1021
1022         Globals.bTimeServer = False;
1023         Globals.bBindInterfacesOnly = False;
1024         Globals.bUnixPasswdSync = False;
1025         Globals.bPamPasswordChange = False;
1026         Globals.bUnicode = True;        /* Do unicode on the wire by default */
1027         Globals.bNTStatusSupport = True; /* Use NT status by default. */
1028         Globals.restrict_anonymous = 0;
1029         Globals.bClientLanManAuth = True;       /* Do use the LanMan hash if it is available */
1030         Globals.bLanmanAuth = True;     /* Do use the LanMan hash if it is available */
1031         Globals.bNTLMAuth = True;       /* Do use NTLMv1 if it is available (otherwise NTLMv2) */
1032         
1033         Globals.enhanced_browsing = True; 
1034         Globals.iLockSpinCount = 3; /* Try 2 times. */
1035         Globals.iLockSpinTime = 10; /* usec. */
1036 #ifdef MMAP_BLACKLIST
1037         Globals.bUseMmap = False;
1038 #else
1039         Globals.bUseMmap = True;
1040 #endif
1041         Globals.bUnixExtensions = False;
1042
1043         /* hostname lookups can be very expensive and are broken on
1044            a large number of sites (tridge) */
1045         Globals.bHostnameLookups = False;
1046
1047 #ifdef WITH_LDAP_SAMCONFIG
1048         string_set(&Globals.szLdapServer, "localhost");
1049         Globals.ldap_port = 636;
1050         Globals.szPassdbBackend = str_list_make("ldapsam guest", NULL);
1051 #else
1052         Globals.szPassdbBackend = str_list_make("smbpasswd guest", NULL);
1053 #endif /* WITH_LDAP_SAMCONFIG */
1054
1055         string_set(&Globals.szLdapSuffix, "");
1056         string_set(&Globals.szLdapMachineSuffix, "");
1057         string_set(&Globals.szLdapUserSuffix, "");
1058
1059         string_set(&Globals.szLdapFilter, "(&(uid=%u)(objectclass=sambaAccount))");
1060         string_set(&Globals.szLdapAdminDn, "");
1061         Globals.ldap_ssl = LDAP_SSL_ON;
1062         Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
1063
1064 /* these parameters are set to defaults that are more appropriate
1065    for the increasing samba install base:
1066
1067    as a member of the workgroup, that will possibly become a
1068    _local_ master browser (lm = True).  this is opposed to a forced
1069    local master browser startup (pm = True).
1070
1071    doesn't provide WINS server service by default (wsupp = False),
1072    and doesn't provide domain master browser services by default, either.
1073
1074 */
1075
1076         Globals.bPreferredMaster = Auto;        /* depending on bDomainMaster */
1077         Globals.os_level = 20;
1078         Globals.bLocalMaster = True;
1079         Globals.bDomainMaster = Auto;   /* depending on bDomainLogons */
1080         Globals.bDomainLogons = False;
1081         Globals.bWINSsupport = False;
1082         Globals.bWINSproxy = False;
1083
1084         Globals.bDNSproxy = True;
1085
1086         Globals.bAllowTrustedDomains = True;
1087
1088         string_set(&Globals.szTemplateShell, "/bin/false");
1089         string_set(&Globals.szTemplateHomedir, "/home/%D/%U");
1090         string_set(&Globals.szWinbindSeparator, "\\");
1091
1092         Globals.winbind_cache_time = 15;
1093         Globals.bWinbindEnumUsers = True;
1094         Globals.bWinbindEnumGroups = True;
1095         Globals.bWinbindUseDefaultDomain = False;
1096
1097         string_set(&Globals.szIDMapBackend, "tdb");
1098
1099         Globals.name_cache_timeout = 660; /* In seconds */
1100
1101         Globals.bUseSpnego = True;
1102
1103         Globals.server_signing = False;
1104
1105         string_set(&Globals.smb_ports, SMB_PORTS);
1106 }
1107
1108 static TALLOC_CTX *lp_talloc;
1109
1110 /******************************************************************* a
1111  Free up temporary memory - called from the main loop.
1112 ********************************************************************/
1113
1114 void lp_talloc_free(void)
1115 {
1116         if (!lp_talloc)
1117                 return;
1118         talloc_destroy(lp_talloc);
1119         lp_talloc = NULL;
1120 }
1121
1122 /*******************************************************************
1123  Convenience routine to grab string parameters into temporary memory
1124  and run standard_sub_basic on them. The buffers can be written to by
1125  callers without affecting the source string.
1126 ********************************************************************/
1127
1128 static const char *lp_string(const char *s)
1129 {
1130 #if 0  /* until REWRITE done to make thread-safe */
1131         size_t len = s ? strlen(s) : 0;
1132         char *ret;
1133 #endif
1134
1135         /* The follow debug is useful for tracking down memory problems
1136            especially if you have an inner loop that is calling a lp_*()
1137            function that returns a string.  Perhaps this debug should be
1138            present all the time? */
1139
1140 #if 0
1141         DEBUG(10, ("lp_string(%s)\n", s));
1142 #endif
1143
1144 #if 0  /* until REWRITE done to make thread-safe */
1145         if (!lp_talloc)
1146                 lp_talloc = talloc_init("lp_talloc");
1147
1148         ret = (char *)talloc(lp_talloc, len + 100);     /* leave room for substitution */
1149
1150         if (!ret)
1151                 return NULL;
1152
1153         if (!s)
1154                 *ret = 0;
1155         else
1156                 StrnCpy(ret, s, len);
1157
1158         if (trim_string(ret, "\"", "\"")) {
1159                 if (strchr(ret,'"') != NULL)
1160                         StrnCpy(ret, s, len);
1161         }
1162
1163         standard_sub_basic(ret,len+100);
1164         return (ret);
1165 #endif
1166         return s;
1167 }
1168
1169 /*
1170    In this section all the functions that are used to access the 
1171    parameters from the rest of the program are defined 
1172 */
1173
1174 #define FN_GLOBAL_STRING(fn_name,ptr) \
1175  const char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
1176 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
1177  const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");}
1178 #define FN_GLOBAL_LIST(fn_name,ptr) \
1179  const char **fn_name(void) {return(*(const char ***)(ptr));}
1180 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1181  BOOL fn_name(void) {return(*(BOOL *)(ptr));}
1182 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1183  char fn_name(void) {return(*(char *)(ptr));}
1184 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1185  int fn_name(void) {return(*(int *)(ptr));}
1186
1187 #define FN_LOCAL_STRING(fn_name,val) \
1188  const char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
1189 #define FN_LOCAL_CONST_STRING(fn_name,val) \
1190  const char *fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1191 #define FN_LOCAL_LIST(fn_name,val) \
1192  const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1193 #define FN_LOCAL_BOOL(fn_name,val) \
1194  BOOL fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1195 #define FN_LOCAL_CHAR(fn_name,val) \
1196  char fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1197 #define FN_LOCAL_INTEGER(fn_name,val) \
1198  int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1199
1200 FN_GLOBAL_STRING(lp_smb_ports, &Globals.smb_ports)
1201 FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
1202 FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
1203 FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset)
1204 FN_GLOBAL_STRING(lp_logfile, &Globals.szLogFile)
1205 FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
1206 FN_GLOBAL_STRING(lp_smb_passwd_file, &Globals.szSMBPasswdFile)
1207 FN_GLOBAL_STRING(lp_sam_url, &Globals.szSAM_URL)
1208 FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
1209 FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
1210 FN_GLOBAL_STRING(lp_printcapname, &Globals.szPrintcapname)
1211 FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
1212 FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
1213 FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, &Globals.dcerpc_ep_servers)
1214 FN_GLOBAL_STRING(lp_rootdir, &Globals.szRootdir)
1215 FN_GLOBAL_STRING(lp_defaultservice, &Globals.szDefaultService)
1216 FN_GLOBAL_STRING(lp_hosts_equiv, &Globals.szHostsEquiv)
1217 FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
1218 FN_GLOBAL_STRING(lp_passwd_program, &Globals.szPasswdProgram)
1219 FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
1220 FN_GLOBAL_STRING(lp_passwordserver, &Globals.szPasswordServer)
1221 FN_GLOBAL_STRING(lp_name_resolve_order, &Globals.szNameResolveOrder)
1222 FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
1223 FN_GLOBAL_STRING(lp_ads_server, &Globals.szADSserver)
1224 FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
1225 FN_GLOBAL_STRING(lp_workgroup, &Globals.szWorkgroup)
1226 FN_GLOBAL_STRING(lp_netbios_name, &Globals.szNetbiosName)
1227 FN_GLOBAL_STRING(lp_netbios_scope, &Globals.szNetbiosScope)
1228 FN_GLOBAL_CONST_STRING(lp_logon_script, &Globals.szLogonScript)
1229 FN_GLOBAL_CONST_STRING(lp_logon_path, &Globals.szLogonPath)
1230 FN_GLOBAL_CONST_STRING(lp_logon_drive, &Globals.szLogonDrive)
1231 FN_GLOBAL_CONST_STRING(lp_logon_home, &Globals.szLogonHome)
1232 FN_GLOBAL_STRING(lp_remote_announce, &Globals.szRemoteAnnounce)
1233 FN_GLOBAL_STRING(lp_remote_browse_sync, &Globals.szRemoteBrowseSync)
1234 FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
1235 FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
1236 FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
1237 static FN_GLOBAL_STRING(lp_announce_version, &Globals.szAnnounceVersion)
1238 FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
1239 FN_GLOBAL_LIST(lp_passdb_backend, &Globals.szPassdbBackend)
1240 FN_GLOBAL_LIST(lp_preload_modules, &Globals.szPreloadModules)
1241 FN_GLOBAL_STRING(lp_panic_action, &Globals.szPanicAction)
1242 FN_GLOBAL_STRING(lp_adduser_script, &Globals.szAddUserScript)
1243
1244 FN_GLOBAL_CONST_STRING(lp_guestaccount, &Globals.szGuestaccount)
1245
1246 FN_GLOBAL_STRING(lp_addmachine_script, &Globals.szAddMachineScript)
1247
1248 FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
1249 FN_GLOBAL_STRING(lp_wins_partners, &Globals.szWINSPartners)
1250 FN_GLOBAL_STRING(lp_template_homedir, &Globals.szTemplateHomedir)
1251 FN_GLOBAL_STRING(lp_template_shell, &Globals.szTemplateShell)
1252 FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
1253 FN_GLOBAL_BOOL(lp_winbind_enum_users, &Globals.bWinbindEnumUsers)
1254 FN_GLOBAL_BOOL(lp_winbind_enum_groups, &Globals.bWinbindEnumGroups)
1255 FN_GLOBAL_BOOL(lp_winbind_use_default_domain, &Globals.bWinbindUseDefaultDomain)
1256 FN_GLOBAL_STRING(lp_idmap_backend, &Globals.szIDMapBackend)
1257
1258 #ifdef WITH_LDAP_SAMCONFIG
1259 FN_GLOBAL_STRING(lp_ldap_server, &Globals.szLdapServer)
1260 FN_GLOBAL_INTEGER(lp_ldap_port, &Globals.ldap_port)
1261 #endif
1262 FN_GLOBAL_STRING(lp_ldap_suffix, &Globals.szLdapSuffix)
1263 FN_GLOBAL_STRING(lp_ldap_machine_suffix, &Globals.szLdapMachineSuffix)
1264 FN_GLOBAL_STRING(lp_ldap_user_suffix, &Globals.szLdapUserSuffix)
1265 FN_GLOBAL_STRING(lp_ldap_filter, &Globals.szLdapFilter)
1266 FN_GLOBAL_STRING(lp_ldap_admin_dn, &Globals.szLdapAdminDn)
1267 FN_GLOBAL_INTEGER(lp_ldap_ssl, &Globals.ldap_ssl)
1268 FN_GLOBAL_INTEGER(lp_ldap_passwd_sync, &Globals.ldap_passwd_sync)
1269 FN_GLOBAL_BOOL(lp_ldap_trust_ids, &Globals.ldap_trust_ids)
1270
1271 FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
1272 FN_GLOBAL_BOOL(lp_dns_proxy, &Globals.bDNSproxy)
1273 FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
1274 FN_GLOBAL_BOOL(lp_we_are_a_wins_server, &Globals.bWINSsupport)
1275 FN_GLOBAL_BOOL(lp_wins_proxy, &Globals.bWINSproxy)
1276 FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
1277 FN_GLOBAL_BOOL(lp_domain_logons, &Globals.bDomainLogons)
1278 FN_GLOBAL_BOOL(lp_load_printers, &Globals.bLoadPrinters)
1279 FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
1280 FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
1281 FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw)
1282 FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords)
1283 FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions)
1284 FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
1285 FN_GLOBAL_BOOL(lp_update_encrypted, &Globals.bUpdateEncrypt)
1286 static FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
1287 FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
1288 FN_GLOBAL_BOOL(lp_pam_password_change, &Globals.bPamPasswordChange)
1289 FN_GLOBAL_BOOL(lp_unix_password_sync, &Globals.bUnixPasswdSync)
1290 FN_GLOBAL_BOOL(lp_unicode, &Globals.bUnicode)
1291 FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
1292 FN_GLOBAL_BOOL(lp_allow_trusted_domains, &Globals.bAllowTrustedDomains)
1293 FN_GLOBAL_INTEGER(lp_restrict_anonymous, &Globals.restrict_anonymous)
1294 FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
1295 FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
1296 FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
1297 FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
1298 FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
1299 FN_GLOBAL_BOOL(lp_enhanced_browsing, &Globals.enhanced_browsing)
1300 FN_GLOBAL_BOOL(lp_use_mmap, &Globals.bUseMmap)
1301 FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions)
1302 FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
1303 FN_GLOBAL_BOOL(lp_hostname_lookups, &Globals.bHostnameLookups)
1304 FN_GLOBAL_BOOL(lp_rpc_big_endian, &Globals.bRpcBigEndian)
1305 FN_GLOBAL_INTEGER(lp_os_level, &Globals.os_level)
1306 FN_GLOBAL_INTEGER(lp_max_ttl, &Globals.max_ttl)
1307 FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
1308 FN_GLOBAL_INTEGER(lp_min_wins_ttl, &Globals.min_wins_ttl)
1309 FN_GLOBAL_INTEGER(lp_time_offset, &Globals.time_offset)
1310 FN_GLOBAL_INTEGER(lp_maxmux, &Globals.max_mux)
1311 FN_GLOBAL_INTEGER(lp_max_xmit, &Globals.max_xmit)
1312 FN_GLOBAL_INTEGER(lp_passwordlevel, &Globals.pwordlevel)
1313 FN_GLOBAL_INTEGER(lp_usernamelevel, &Globals.unamelevel)
1314 FN_GLOBAL_INTEGER(lp_maxprotocol, &Globals.maxprotocol)
1315 FN_GLOBAL_INTEGER(lp_minprotocol, &Globals.minprotocol)
1316 FN_GLOBAL_INTEGER(lp_security, &Globals.security)
1317 FN_GLOBAL_LIST(lp_auth_methods, &Globals.AuthMethods)
1318 FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security)
1319 FN_GLOBAL_INTEGER(lp_lpqcachetime, &Globals.lpqcachetime)
1320 FN_GLOBAL_INTEGER(lp_disable_spoolss, &Globals.bDisableSpoolss)
1321 static FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as)
1322 FN_GLOBAL_INTEGER(lp_lm_announce, &Globals.lm_announce)
1323 FN_GLOBAL_INTEGER(lp_lm_interval, &Globals.lm_interval)
1324 FN_GLOBAL_INTEGER(lp_machine_password_timeout, &Globals.machine_password_timeout)
1325 FN_GLOBAL_INTEGER(lp_lock_spin_count, &Globals.iLockSpinCount)
1326 FN_GLOBAL_INTEGER(lp_lock_sleep_time, &Globals.iLockSpinTime)
1327 FN_LOCAL_STRING(lp_servicename, szService)
1328 FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
1329 FN_LOCAL_STRING(lp_pathname, szPath)
1330 FN_LOCAL_STRING(lp_username, szUsername)
1331 FN_LOCAL_LIST(lp_invalid_users, szInvalidUsers)
1332 FN_LOCAL_LIST(lp_valid_users, szValidUsers)
1333 FN_LOCAL_LIST(lp_admin_users, szAdminUsers)
1334 FN_LOCAL_STRING(lp_printcommand, szPrintcommand)
1335 FN_LOCAL_STRING(lp_lpqcommand, szLpqcommand)
1336 FN_LOCAL_STRING(lp_lprmcommand, szLprmcommand)
1337 FN_LOCAL_STRING(lp_lppausecommand, szLppausecommand)
1338 FN_LOCAL_STRING(lp_lpresumecommand, szLpresumecommand)
1339 FN_LOCAL_STRING(lp_queuepausecommand, szQueuepausecommand)
1340 FN_LOCAL_STRING(lp_queueresumecommand, szQueueresumecommand)
1341 static FN_LOCAL_STRING(_lp_printername, szPrintername)
1342 FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
1343 FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
1344 FN_LOCAL_STRING(lp_comment, comment)
1345 FN_LOCAL_STRING(lp_fstype, fstype)
1346 FN_LOCAL_STRING(lp_msdfs_proxy, szMSDfsProxy)
1347 static FN_LOCAL_STRING(lp_volume, volume)
1348 FN_LOCAL_STRING(lp_ntvfs_handler, ntvfs_handler)
1349 FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
1350 FN_LOCAL_BOOL(lp_autoloaded, autoloaded)
1351 FN_LOCAL_BOOL(lp_browseable, bBrowseable)
1352 FN_LOCAL_BOOL(lp_readonly, bRead_only)
1353 FN_LOCAL_BOOL(lp_guest_ok, bGuest_ok)
1354 FN_LOCAL_BOOL(lp_guest_only, bGuest_only)
1355 FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
1356 FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
1357 FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
1358 FN_LOCAL_BOOL(lp_locking, bLocking)
1359 FN_LOCAL_BOOL(lp_strict_locking, bStrictLocking)
1360 FN_LOCAL_BOOL(lp_posix_locking, bPosixLocking)
1361 FN_LOCAL_BOOL(lp_share_modes, bShareModes)
1362 FN_LOCAL_BOOL(lp_oplocks, bOpLocks)
1363 FN_LOCAL_BOOL(lp_level2_oplocks, bLevel2OpLocks)
1364 FN_LOCAL_BOOL(lp_onlyuser, bOnlyUser)
1365 FN_LOCAL_BOOL(lp_map_system, bMap_system)
1366 FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
1367 FN_LOCAL_INTEGER(lp_minprintspace, iMinPrintSpace)
1368 FN_LOCAL_INTEGER(lp_printing, iPrinting)
1369 FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
1370 FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time)
1371 FN_GLOBAL_BOOL(lp_hide_local_users, &Globals.bHideLocalUsers)
1372 FN_GLOBAL_INTEGER(lp_name_cache_timeout, &Globals.name_cache_timeout)
1373 FN_GLOBAL_INTEGER(lp_server_signing, &Globals.server_signing)
1374
1375 /* local prototypes */
1376
1377 static int map_parameter(const char *pszParmName);
1378 static BOOL set_boolean(BOOL *pb, const char *pszParmValue);
1379 static int getservicebyname(const char *pszServiceName,
1380                             service * pserviceDest);
1381 static void copy_service(service * pserviceDest,
1382                          service * pserviceSource, BOOL *pcopymapDest);
1383 static BOOL service_ok(int iService);
1384 static BOOL do_section(const char *pszSectionName);
1385 static void init_copymap(service * pservice);
1386
1387 /* This is a helper function for parametrical options support. */
1388 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
1389 /* Actual parametrical functions are quite simple */
1390 static const char *get_parametrics(int lookup_service, const char *type, const char *option)
1391 {
1392         char *vfskey;
1393         struct param_opt *data;
1394         
1395         if (lookup_service >= iNumServices) return NULL;
1396         
1397         data = (lookup_service < 0) ? 
1398                 Globals.param_opt : ServicePtrs[lookup_service]->param_opt;
1399     
1400         asprintf(&vfskey, "%s:%s", type, option);
1401         strlower(vfskey);
1402
1403         while (data) {
1404                 if (strcmp(data->key, vfskey) == 0) {
1405                         free(vfskey);
1406                         return data->value;
1407                 }
1408                 data = data->next;
1409         }
1410
1411         if (lookup_service >= 0) {
1412                 /* Try to fetch the same option but from globals */
1413                 /* but only if we are not already working with Globals */
1414                 data = Globals.param_opt;
1415                 while (data) {
1416                         if (strcmp(data->key, vfskey) == 0) {
1417                                 free(vfskey);
1418                                 return data->value;
1419                         }
1420                         data = data->next;
1421                 }
1422         }
1423
1424         free(vfskey);
1425         
1426         return NULL;
1427 }
1428
1429
1430 /*******************************************************************
1431 convenience routine to return int parameters.
1432 ********************************************************************/
1433 static int lp_int(const char *s)
1434 {
1435
1436         if (!s) {
1437                 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
1438                 return (-1);
1439         }
1440
1441         return atoi(s); 
1442 }
1443
1444 /*******************************************************************
1445 convenience routine to return unsigned long parameters.
1446 ********************************************************************/
1447 static int lp_ulong(const char *s)
1448 {
1449
1450         if (!s) {
1451                 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
1452                 return (-1);
1453         }
1454
1455         return strtoul(s, NULL, 10);
1456 }
1457
1458 /*******************************************************************
1459 convenience routine to return boolean parameters.
1460 ********************************************************************/
1461 static BOOL lp_bool(const char *s)
1462 {
1463         BOOL ret = False;
1464
1465         if (!s) {
1466                 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
1467                 return False;
1468         }
1469         
1470         if (!set_boolean(&ret,s)) {
1471                 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1472                 return False;
1473         }
1474
1475         return ret;
1476 }
1477
1478 /*******************************************************************
1479 convenience routine to return enum parameters.
1480 ********************************************************************/
1481 static int lp_enum(const char *s,const struct enum_list *_enum)
1482 {
1483         int i;
1484
1485         if (!s || !_enum) {
1486                 DEBUG(0,("lp_enum(%s,enum): is called with NULL!\n",s));
1487                 return False;
1488         }
1489         
1490         for (i=0; _enum[i].name; i++) {
1491                 if (strcasecmp(_enum[i].name,s)==0)
1492                         return _enum[i].value;
1493         }
1494
1495         DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
1496         return (-1);
1497 }
1498
1499 /* Return parametric option from a given service. Type is a part of option before ':' */
1500 /* Parametric option has following syntax: 'Type: option = value' */
1501 /* Returned value is allocated in 'lp_talloc' context */
1502
1503 const char *lp_parm_string(int lookup_service, const char *type, const char *option)
1504 {
1505         const char *value = get_parametrics(lookup_service, type, option);
1506         
1507         if (value)
1508                 return lp_string(value);
1509
1510         return NULL;
1511 }
1512
1513 /* Return parametric option from a given service. Type is a part of option before ':' */
1514 /* Parametric option has following syntax: 'Type: option = value' */
1515 /* Returned value is allocated in 'lp_talloc' context */
1516
1517 char **lp_parm_string_list(int lookup_service, const char *type, const char *option,
1518                            const char *separator)
1519 {
1520         const char *value = get_parametrics(lookup_service, type, option);
1521         
1522         if (value)
1523                 return str_list_make(value, separator);
1524
1525         return NULL;
1526 }
1527
1528 /* Return parametric option from a given service. Type is a part of option before ':' */
1529 /* Parametric option has following syntax: 'Type: option = value' */
1530
1531 int lp_parm_int(int lookup_service, const char *type, const char *option)
1532 {
1533         const char *value = get_parametrics(lookup_service, type, option);
1534         
1535         if (value)
1536                 return lp_int(value);
1537
1538         return (-1);
1539 }
1540
1541 /* Return parametric option from a given service. Type is a part of option before ':' */
1542 /* Parametric option has following syntax: 'Type: option = value' */
1543
1544 unsigned long lp_parm_ulong(int lookup_service, const char *type, const char *option)
1545 {
1546         const char *value = get_parametrics(lookup_service, type, option);
1547         
1548         if (value)
1549                 return lp_ulong(value);
1550
1551         return (0);
1552 }
1553
1554 /* Return parametric option from a given service. Type is a part of option before ':' */
1555 /* Parametric option has following syntax: 'Type: option = value' */
1556
1557 BOOL lp_parm_bool(int lookup_service, const char *type, const char *option, BOOL default_v)
1558 {
1559         const char *value = get_parametrics(lookup_service, type, option);
1560         
1561         if (value)
1562                 return lp_bool(value);
1563
1564         return default_v;
1565 }
1566
1567 /* Return parametric option from a given service. Type is a part of option before ':' */
1568 /* Parametric option has following syntax: 'Type: option = value' */
1569
1570 int lp_parm_enum(int lookup_service, const char *type, const char *option,
1571                  const struct enum_list *_enum)
1572 {
1573         const char *value = get_parametrics(lookup_service, type, option);
1574         
1575         if (value)
1576                 return lp_enum(value, _enum);
1577
1578         return (-1);
1579 }
1580
1581
1582 /***************************************************************************
1583  Initialise a service to the defaults.
1584 ***************************************************************************/
1585
1586 static void init_service(service * pservice)
1587 {
1588         memset((char *)pservice, '\0', sizeof(service));
1589         copy_service(pservice, &sDefault, NULL);
1590 }
1591
1592 /***************************************************************************
1593  Free the dynamically allocated parts of a service struct.
1594 ***************************************************************************/
1595
1596 static void free_service(service *pservice)
1597 {
1598         int i;
1599         struct param_opt *data, *pdata;
1600         if (!pservice)
1601                 return;
1602
1603         if (pservice->szService)
1604                 DEBUG(5, ("free_service: Freeing service %s\n",
1605                        pservice->szService));
1606
1607         string_free(&pservice->szService);
1608         SAFE_FREE(pservice->copymap);
1609
1610         for (i = 0; parm_table[i].label; i++) {
1611                 if ((parm_table[i].type == P_STRING ||
1612                      parm_table[i].type == P_USTRING) &&
1613                     parm_table[i].class == P_LOCAL)
1614                         string_free((char **)
1615                                     (((char *)pservice) +
1616                                      PTR_DIFF(parm_table[i].ptr, &sDefault)));
1617                 else if (parm_table[i].type == P_LIST &&
1618                          parm_table[i].class == P_LOCAL)
1619                              str_list_free((char ***)
1620                                             (((char *)pservice) +
1621                                              PTR_DIFF(parm_table[i].ptr, &sDefault)));
1622         }
1623                                 
1624         DEBUG(5,("Freeing parametrics:\n"));
1625         data = pservice->param_opt;
1626         while (data) {
1627                 DEBUG(5,("[%s = %s]\n", data->key, data->value));
1628                 string_free(&data->key);
1629                 string_free(&data->value);
1630                 pdata = data->next;
1631                 SAFE_FREE(data);
1632                 data = pdata;
1633         }
1634
1635         ZERO_STRUCTP(pservice);
1636 }
1637
1638 /***************************************************************************
1639  Add a new service to the services array initialising it with the given 
1640  service. 
1641 ***************************************************************************/
1642
1643 static int add_a_service(const service *pservice, const char *name)
1644 {
1645         int i;
1646         service tservice;
1647         int num_to_alloc = iNumServices + 1;
1648         struct param_opt *data, *pdata;
1649
1650         tservice = *pservice;
1651
1652         /* it might already exist */
1653         if (name) {
1654                 i = getservicebyname(name, NULL);
1655                 if (i >= 0) {
1656                         /* Clean all parametric options for service */
1657                         /* They will be added during parsing again */
1658                         data = ServicePtrs[i]->param_opt;
1659                         while (data) {
1660                                 string_free(&data->key);
1661                                 string_free(&data->value);
1662                                 pdata = data->next;
1663                                 SAFE_FREE(data);
1664                                 data = pdata;
1665                         }
1666                         ServicePtrs[i]->param_opt = NULL;
1667                         return (i);
1668                 }
1669         }
1670
1671         /* find an invalid one */
1672         for (i = 0; i < iNumServices; i++)
1673                 if (!ServicePtrs[i]->valid)
1674                         break;
1675
1676         /* if not, then create one */
1677         if (i == iNumServices) {
1678                 service **tsp;
1679                 
1680                 tsp = (service **) Realloc(ServicePtrs,
1681                                            sizeof(service *) *
1682                                            num_to_alloc);
1683                                            
1684                 if (!tsp) {
1685                         DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1686                         return (-1);
1687                 }
1688                 else {
1689                         ServicePtrs = tsp;
1690                         ServicePtrs[iNumServices] =
1691                                 (service *) malloc(sizeof(service));
1692                 }
1693                 if (!ServicePtrs[iNumServices]) {
1694                         DEBUG(0,("add_a_service: out of memory!\n"));
1695                         return (-1);
1696                 }
1697
1698                 iNumServices++;
1699         } else
1700                 free_service(ServicePtrs[i]);
1701
1702         ServicePtrs[i]->valid = True;
1703
1704         init_service(ServicePtrs[i]);
1705         copy_service(ServicePtrs[i], &tservice, NULL);
1706         if (name)
1707                 string_set(&ServicePtrs[i]->szService, name);
1708         return (i);
1709 }
1710
1711 /***************************************************************************
1712  Add a new home service, with the specified home directory, defaults coming 
1713  from service ifrom.
1714 ***************************************************************************/
1715
1716 BOOL lp_add_home(const char *pszHomename, int iDefaultService, 
1717                  const char *user, const char *pszHomedir)
1718 {
1719         int i;
1720         pstring newHomedir;
1721
1722         i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1723
1724         if (i < 0)
1725                 return (False);
1726
1727         if (!(*(ServicePtrs[iDefaultService]->szPath))
1728             || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(-1))) {
1729                 pstrcpy(newHomedir, pszHomedir);
1730         } else {
1731                 pstrcpy(newHomedir, lp_pathname(iDefaultService));
1732                 string_sub(newHomedir,"%H", pszHomedir, sizeof(newHomedir)); 
1733         }
1734
1735         string_set(&ServicePtrs[i]->szPath, newHomedir);
1736
1737         if (!(*(ServicePtrs[i]->comment))) {
1738                 pstring comment;
1739                 slprintf(comment, sizeof(comment) - 1,
1740                          "Home directory of %s", user);
1741                 string_set(&ServicePtrs[i]->comment, comment);
1742         }
1743         ServicePtrs[i]->bAvailable = sDefault.bAvailable;
1744         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1745
1746         DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename, 
1747                user, newHomedir));
1748         
1749         return (True);
1750 }
1751
1752 /***************************************************************************
1753  Add a new service, based on an old one.
1754 ***************************************************************************/
1755
1756 int lp_add_service(const char *pszService, int iDefaultService)
1757 {
1758         return (add_a_service(ServicePtrs[iDefaultService], pszService));
1759 }
1760
1761 /***************************************************************************
1762  Add the IPC service.
1763 ***************************************************************************/
1764
1765 static BOOL lp_add_ipc(const char *ipc_name, BOOL guest_ok)
1766 {
1767         pstring comment;
1768         int i = add_a_service(&sDefault, ipc_name);
1769
1770         if (i < 0)
1771                 return (False);
1772
1773         slprintf(comment, sizeof(comment) - 1,
1774                  "IPC Service (%s)", Globals.szServerString);
1775
1776         string_set(&ServicePtrs[i]->szPath, tmpdir());
1777         string_set(&ServicePtrs[i]->szUsername, "");
1778         string_set(&ServicePtrs[i]->comment, comment);
1779         string_set(&ServicePtrs[i]->fstype, "IPC");
1780         ServicePtrs[i]->iMaxConnections = 0;
1781         ServicePtrs[i]->bAvailable = True;
1782         ServicePtrs[i]->bRead_only = True;
1783         ServicePtrs[i]->bGuest_only = False;
1784         ServicePtrs[i]->bGuest_ok = guest_ok;
1785         ServicePtrs[i]->bPrint_ok = False;
1786         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1787
1788         DEBUG(3, ("adding IPC service\n"));
1789
1790         return (True);
1791 }
1792
1793 /***************************************************************************
1794  Add a new printer service, with defaults coming from service iFrom.
1795 ***************************************************************************/
1796
1797 BOOL lp_add_printer(const char *pszPrintername, int iDefaultService)
1798 {
1799         const char *comment = "From Printcap";
1800         int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1801
1802         if (i < 0)
1803                 return (False);
1804
1805         /* note that we do NOT default the availability flag to True - */
1806         /* we take it from the default service passed. This allows all */
1807         /* dynamic printers to be disabled by disabling the [printers] */
1808         /* entry (if/when the 'available' keyword is implemented!).    */
1809
1810         /* the printer name is set to the service name. */
1811         string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1812         string_set(&ServicePtrs[i]->comment, comment);
1813         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1814         /* Printers cannot be read_only. */
1815         ServicePtrs[i]->bRead_only = False;
1816         /* No share modes on printer services. */
1817         ServicePtrs[i]->bShareModes = False;
1818         /* No oplocks on printer services. */
1819         ServicePtrs[i]->bOpLocks = False;
1820         /* Printer services must be printable. */
1821         ServicePtrs[i]->bPrint_ok = True;
1822
1823         DEBUG(3, ("adding printer service %s\n", pszPrintername));
1824
1825         update_server_announce_as_printserver();
1826
1827         return (True);
1828 }
1829
1830 /***************************************************************************
1831  Map a parameter's string representation to something we can use. 
1832  Returns False if the parameter string is not recognised, else TRUE.
1833 ***************************************************************************/
1834
1835 static int map_parameter(const char *pszParmName)
1836 {
1837         int iIndex;
1838
1839         if (*pszParmName == '-')
1840                 return (-1);
1841
1842         for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1843                 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1844                         return (iIndex);
1845
1846         /* Warn only if it isn't parametric option */
1847         if (strchr(pszParmName, ':') == NULL)
1848                 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1849         /* We do return 'fail' for parametric options as well because they are
1850            stored in different storage
1851          */
1852         return (-1);
1853 }
1854
1855 /***************************************************************************
1856  Set a boolean variable from the text value stored in the passed string.
1857  Returns True in success, False if the passed string does not correctly 
1858  represent a boolean.
1859 ***************************************************************************/
1860
1861 static BOOL set_boolean(BOOL *pb, const char *pszParmValue)
1862 {
1863         BOOL bRetval;
1864
1865         bRetval = True;
1866         if (strwicmp(pszParmValue, "yes") == 0 ||
1867             strwicmp(pszParmValue, "true") == 0 ||
1868             strwicmp(pszParmValue, "1") == 0)
1869                 *pb = True;
1870         else if (strwicmp(pszParmValue, "no") == 0 ||
1871                     strwicmp(pszParmValue, "False") == 0 ||
1872                     strwicmp(pszParmValue, "0") == 0)
1873                 *pb = False;
1874         else {
1875                 DEBUG(0,
1876                       ("ERROR: Badly formed boolean in configuration file: \"%s\".\n",
1877                        pszParmValue));
1878                 bRetval = False;
1879         }
1880         return (bRetval);
1881 }
1882
1883 /***************************************************************************
1884 Find a service by name. Otherwise works like get_service.
1885 ***************************************************************************/
1886
1887 static int getservicebyname(const char *pszServiceName, service * pserviceDest)
1888 {
1889         int iService;
1890
1891         for (iService = iNumServices - 1; iService >= 0; iService--)
1892                 if (VALID(iService) &&
1893                     strwicmp(ServicePtrs[iService]->szService, pszServiceName) == 0) {
1894                         if (pserviceDest != NULL)
1895                                 copy_service(pserviceDest, ServicePtrs[iService], NULL);
1896                         break;
1897                 }
1898
1899         return (iService);
1900 }
1901
1902 /***************************************************************************
1903  Copy a service structure to another.
1904  If pcopymapDest is NULL then copy all fields
1905 ***************************************************************************/
1906
1907 static void copy_service(service * pserviceDest, service * pserviceSource, BOOL *pcopymapDest)
1908 {
1909         int i;
1910         BOOL bcopyall = (pcopymapDest == NULL);
1911         struct param_opt *data, *pdata, *paramo;
1912         BOOL not_added;
1913
1914         for (i = 0; parm_table[i].label; i++)
1915                 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1916                     (bcopyall || pcopymapDest[i])) {
1917                         void *def_ptr = parm_table[i].ptr;
1918                         void *src_ptr =
1919                                 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
1920                                                                     &sDefault);
1921                         void *dest_ptr =
1922                                 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
1923                                                                   &sDefault);
1924
1925                         switch (parm_table[i].type) {
1926                                 case P_BOOL:
1927                                 case P_BOOLREV:
1928                                         *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
1929                                         break;
1930
1931                                 case P_INTEGER:
1932                                 case P_ENUM:
1933                                 case P_OCTAL:
1934                                         *(int *)dest_ptr = *(int *)src_ptr;
1935                                         break;
1936
1937                                 case P_CHAR:
1938                                         *(char *)dest_ptr = *(char *)src_ptr;
1939                                         break;
1940
1941                                 case P_STRING:
1942                                         string_set(dest_ptr,
1943                                                    *(char **)src_ptr);
1944                                         break;
1945
1946                                 case P_USTRING:
1947                                         string_set(dest_ptr,
1948                                                    *(char **)src_ptr);
1949                                         strupper(*(char **)dest_ptr);
1950                                         break;
1951                                 case P_LIST:
1952                                         str_list_copy((char ***)dest_ptr, *(const char ***)src_ptr);
1953                                         break;
1954                                 default:
1955                                         break;
1956                         }
1957                 }
1958
1959         if (bcopyall) {
1960                 init_copymap(pserviceDest);
1961                 if (pserviceSource->copymap)
1962                         memcpy((void *)pserviceDest->copymap,
1963                                (void *)pserviceSource->copymap,
1964                                sizeof(BOOL) * NUMPARAMETERS);
1965         }
1966         
1967         data = pserviceSource->param_opt;
1968         while (data) {
1969                 not_added = True;
1970                 pdata = pserviceDest->param_opt;
1971                 /* Traverse destination */
1972                 while (pdata) {
1973                         /* If we already have same option, override it */
1974                         if (strcmp(pdata->key, data->key) == 0) {
1975                                 string_free(&pdata->value);
1976                                 pdata->value = strdup(data->value);
1977                                 not_added = False;
1978                                 break;
1979                         }
1980                         pdata = pdata->next;
1981                 }
1982                 if (not_added) {
1983                         paramo = smb_xmalloc(sizeof(*paramo));
1984                         paramo->key = strdup(data->key);
1985                         paramo->value = strdup(data->value);
1986                         DLIST_ADD(pserviceDest->param_opt, paramo);
1987                 }
1988                 data = data->next;
1989         }
1990 }
1991
1992 /***************************************************************************
1993 Check a service for consistency. Return False if the service is in any way
1994 incomplete or faulty, else True.
1995 ***************************************************************************/
1996
1997 static BOOL service_ok(int iService)
1998 {
1999         BOOL bRetval;
2000
2001         bRetval = True;
2002         if (ServicePtrs[iService]->szService[0] == '\0') {
2003                 DEBUG(0, ("The following message indicates an internal error:\n"));
2004                 DEBUG(0, ("No service name in service entry.\n"));
2005                 bRetval = False;
2006         }
2007
2008         /* The [printers] entry MUST be printable. I'm all for flexibility, but */
2009         /* I can't see why you'd want a non-printable printer service...        */
2010         if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
2011                 if (!ServicePtrs[iService]->bPrint_ok) {
2012                         DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
2013                                ServicePtrs[iService]->szService));
2014                         ServicePtrs[iService]->bPrint_ok = True;
2015                 }
2016                 /* [printers] service must also be non-browsable. */
2017                 if (ServicePtrs[iService]->bBrowseable)
2018                         ServicePtrs[iService]->bBrowseable = False;
2019         }
2020
2021         if (ServicePtrs[iService]->szPath[0] == '\0' &&
2022             strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0) {
2023                 DEBUG(0, ("No path in service %s - using %s\n",
2024                        ServicePtrs[iService]->szService, tmpdir()));
2025                 string_set(&ServicePtrs[iService]->szPath, tmpdir());
2026         }
2027
2028         /* If a service is flagged unavailable, log the fact at level 0. */
2029         if (!ServicePtrs[iService]->bAvailable)
2030                 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
2031                           ServicePtrs[iService]->szService));
2032
2033         return (bRetval);
2034 }
2035
2036 static struct file_lists {
2037         struct file_lists *next;
2038         char *name;
2039         char *subfname;
2040         time_t modtime;
2041 } *file_lists = NULL;
2042
2043 /*******************************************************************
2044  Keep a linked list of all config files so we know when one has changed 
2045  it's date and needs to be reloaded.
2046 ********************************************************************/
2047
2048 static void add_to_file_list(const char *fname, const char *subfname)
2049 {
2050         struct file_lists *f = file_lists;
2051
2052         while (f) {
2053                 if (f->name && !strcmp(f->name, fname))
2054                         break;
2055                 f = f->next;
2056         }
2057
2058         if (!f) {
2059                 f = (struct file_lists *)malloc(sizeof(file_lists[0]));
2060                 if (!f)
2061                         return;
2062                 f->next = file_lists;
2063                 f->name = strdup(fname);
2064                 if (!f->name) {
2065                         SAFE_FREE(f);
2066                         return;
2067                 }
2068                 f->subfname = strdup(subfname);
2069                 if (!f->subfname) {
2070                         SAFE_FREE(f);
2071                         return;
2072                 }
2073                 file_lists = f;
2074                 f->modtime = file_modtime(subfname);
2075         } else {
2076                 time_t t = file_modtime(subfname);
2077                 if (t)
2078                         f->modtime = t;
2079         }
2080 }
2081
2082 /*******************************************************************
2083  Check if a config file has changed date.
2084 ********************************************************************/
2085
2086 BOOL lp_file_list_changed(void)
2087 {
2088         struct file_lists *f = file_lists;
2089         DEBUG(6, ("lp_file_list_changed()\n"));
2090
2091         while (f) {
2092                 pstring n2;
2093                 time_t mod_time;
2094
2095                 pstrcpy(n2, f->name);
2096                 standard_sub_basic(n2,sizeof(n2));
2097
2098                 DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
2099                              f->name, n2, ctime(&f->modtime)));
2100
2101                 mod_time = file_modtime(n2);
2102
2103                 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
2104                         DEBUGADD(6,
2105                                  ("file %s modified: %s\n", n2,
2106                                   ctime(&mod_time)));
2107                         f->modtime = mod_time;
2108                         SAFE_FREE(f->subfname);
2109                         f->subfname = strdup(n2);
2110                         return (True);
2111                 }
2112                 f = f->next;
2113         }
2114         return (False);
2115 }
2116
2117 /***************************************************************************
2118  Handle the include operation.
2119 ***************************************************************************/
2120
2121 static BOOL handle_include(const char *pszParmValue, char **ptr)
2122 {
2123         pstring fname;
2124         pstrcpy(fname, pszParmValue);
2125
2126         standard_sub_basic(fname,sizeof(fname));
2127
2128         add_to_file_list(pszParmValue, fname);
2129
2130         string_set(ptr, fname);
2131
2132         if (file_exist(fname, NULL))
2133                 return (pm_process(fname, do_section, do_parameter));
2134
2135         DEBUG(2, ("Can't find include file %s\n", fname));
2136
2137         return (False);
2138 }
2139
2140 /***************************************************************************
2141  Handle the interpretation of the copy parameter.
2142 ***************************************************************************/
2143
2144 static BOOL handle_copy(const char *pszParmValue, char **ptr)
2145 {
2146         BOOL bRetval;
2147         int iTemp;
2148         service serviceTemp;
2149
2150         string_set(ptr, pszParmValue);
2151
2152         init_service(&serviceTemp);
2153
2154         bRetval = False;
2155
2156         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
2157
2158         if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
2159                 if (iTemp == iServiceIndex) {
2160                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
2161                 } else {
2162                         copy_service(ServicePtrs[iServiceIndex],
2163                                      &serviceTemp,
2164                                      ServicePtrs[iServiceIndex]->copymap);
2165                         bRetval = True;
2166                 }
2167         } else {
2168                 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
2169                 bRetval = False;
2170         }
2171
2172         free_service(&serviceTemp);
2173         return (bRetval);
2174 }
2175
2176 /***************************************************************************
2177  Handle winbind/non unix account uid and gid allocation parameters.  The format of these
2178  parameters is:
2179
2180  [global]
2181
2182         winbind uid = 1000-1999
2183         winbind gid = 700-899
2184
2185  We only do simple parsing checks here.  The strings are parsed into useful
2186  structures in the winbind daemon code.
2187
2188 ***************************************************************************/
2189
2190 /* Some lp_ routines to return winbind [ug]id information */
2191
2192 static uid_t winbind_uid_low, winbind_uid_high;
2193 static gid_t winbind_gid_low, winbind_gid_high;
2194 static uint32_t non_unix_account_low, non_unix_account_high;
2195
2196 BOOL lp_winbind_uid(uid_t *low, uid_t *high)
2197 {
2198         if (winbind_uid_low == 0 || winbind_uid_high == 0)
2199                 return False;
2200
2201         if (low)
2202                 *low = winbind_uid_low;
2203
2204         if (high)
2205                 *high = winbind_uid_high;
2206
2207         return True;
2208 }
2209
2210 BOOL lp_winbind_gid(gid_t *low, gid_t *high)
2211 {
2212         if (winbind_gid_low == 0 || winbind_gid_high == 0)
2213                 return False;
2214
2215         if (low)
2216                 *low = winbind_gid_low;
2217
2218         if (high)
2219                 *high = winbind_gid_high;
2220
2221         return True;
2222 }
2223
2224 BOOL lp_non_unix_account_range(uint32_t *low, uint32_t *high)
2225 {
2226         if (non_unix_account_low == 0 || non_unix_account_high == 0)
2227                 return False;
2228
2229         if (low)
2230                 *low = non_unix_account_low;
2231
2232         if (high)
2233                 *high = non_unix_account_high;
2234
2235         return True;
2236 }
2237
2238 /* Do some simple checks on "winbind [ug]id" parameter values */
2239
2240 static BOOL handle_winbind_uid(const char *pszParmValue, char **ptr)
2241 {
2242         uint32_t low, high;
2243
2244         if (sscanf(pszParmValue, "%u-%u", &low, &high) != 2 || high < low)
2245                 return False;
2246
2247         /* Parse OK */
2248
2249         string_set(ptr, pszParmValue);
2250
2251         winbind_uid_low = low;
2252         winbind_uid_high = high;
2253
2254         return True;
2255 }
2256
2257 static BOOL handle_winbind_gid(const char *pszParmValue, char **ptr)
2258 {
2259         uint32_t low, high;
2260
2261         if (sscanf(pszParmValue, "%u-%u", &low, &high) != 2 || high < low)
2262                 return False;
2263
2264         /* Parse OK */
2265
2266         string_set(ptr, pszParmValue);
2267
2268         winbind_gid_low = low;
2269         winbind_gid_high = high;
2270
2271         return True;
2272 }
2273
2274 /***************************************************************************
2275  Do some simple checks on "non unix account range" parameter values.
2276 ***************************************************************************/
2277
2278 static BOOL handle_non_unix_account_range(const char *pszParmValue, char **ptr)
2279 {
2280         uint32_t low, high;
2281
2282         if (sscanf(pszParmValue, "%u-%u", &low, &high) != 2 || high < low)
2283                 return False;
2284
2285         /* Parse OK */
2286
2287         string_set(ptr, pszParmValue);
2288
2289         non_unix_account_low = low;
2290         non_unix_account_high = high;
2291
2292         return True;
2293 }
2294
2295 /***************************************************************************
2296  Handle the ldap machine suffix option.
2297 ***************************************************************************/
2298
2299 static BOOL handle_ldap_machine_suffix( const char *pszParmValue, char **ptr)
2300 {
2301        pstring suffix;
2302        
2303        pstrcpy(suffix, pszParmValue);
2304
2305        if (! *Globals.szLdapSuffix ) {
2306                string_set( ptr, suffix );
2307                return True;
2308        }
2309
2310        if (! strstr(suffix, Globals.szLdapSuffix) ) {
2311                if ( *pszParmValue )
2312                        pstrcat(suffix, ",");
2313                pstrcat(suffix, Globals.szLdapSuffix);
2314        }
2315        string_set( ptr, suffix );
2316        return True;
2317 }
2318
2319 /***************************************************************************
2320  Handle the ldap user suffix option.
2321 ***************************************************************************/
2322
2323 static BOOL handle_ldap_user_suffix( const char *pszParmValue, char **ptr)
2324 {
2325        pstring suffix;
2326        
2327        pstrcpy(suffix, pszParmValue);
2328
2329        if (! *Globals.szLdapSuffix ) {
2330                string_set( ptr, suffix );
2331                return True;
2332        }
2333        
2334        if (! strstr(suffix, Globals.szLdapSuffix) ) {
2335                if ( *pszParmValue )
2336                        pstrcat(suffix, ",");
2337                pstrcat(suffix, Globals.szLdapSuffix);
2338        }
2339        string_set( ptr, suffix );
2340        return True;
2341 }
2342
2343 /***************************************************************************
2344  Handle setting ldap suffix and determines whether ldap machine suffix needs
2345  to be set as well.
2346 ***************************************************************************/
2347
2348 static BOOL handle_ldap_suffix( const char *pszParmValue, char **ptr)
2349 {
2350        pstring suffix;
2351        pstring user_suffix;
2352        pstring machine_suffix;  
2353                   
2354        pstrcpy(suffix, pszParmValue);
2355
2356        if (! *Globals.szLdapMachineSuffix )
2357                string_set(&Globals.szLdapMachineSuffix, suffix);
2358        if (! *Globals.szLdapUserSuffix ) 
2359                string_set(&Globals.szLdapUserSuffix, suffix);
2360          
2361        if (! strstr(Globals.szLdapMachineSuffix, suffix)) {
2362                pstrcpy(machine_suffix, Globals.szLdapMachineSuffix);
2363                if ( *Globals.szLdapMachineSuffix )
2364                        pstrcat(machine_suffix, ",");
2365                pstrcat(machine_suffix, suffix);
2366                string_set(&Globals.szLdapMachineSuffix, machine_suffix);       
2367        }
2368
2369        if (! strstr(Globals.szLdapUserSuffix, suffix)) {
2370                pstrcpy(user_suffix, Globals.szLdapUserSuffix);
2371                if ( *Globals.szLdapUserSuffix )
2372                        pstrcat(user_suffix, ",");
2373                pstrcat(user_suffix, suffix);   
2374                string_set(&Globals.szLdapUserSuffix, user_suffix);
2375        } 
2376
2377        string_set(ptr, suffix); 
2378
2379        return True;
2380 }
2381
2382 /***************************************************************************
2383  Initialise a copymap.
2384 ***************************************************************************/
2385
2386 static void init_copymap(service * pservice)
2387 {
2388         int i;
2389         SAFE_FREE(pservice->copymap);
2390         pservice->copymap = (BOOL *)malloc(sizeof(BOOL) * NUMPARAMETERS);
2391         if (!pservice->copymap)
2392                 DEBUG(0,
2393                       ("Couldn't allocate copymap!! (size %d)\n",
2394                        (int)NUMPARAMETERS));
2395         else
2396                 for (i = 0; i < NUMPARAMETERS; i++)
2397                         pservice->copymap[i] = True;
2398 }
2399
2400 /***************************************************************************
2401  Return the local pointer to a parameter given the service number and the 
2402  pointer into the default structure.
2403 ***************************************************************************/
2404
2405 void *lp_local_ptr(int snum, void *ptr)
2406 {
2407         return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
2408 }
2409
2410
2411 /***************************************************************************
2412  Process a parametric option
2413 ***************************************************************************/
2414 static BOOL lp_do_parameter_parametric(int snum, const char *pszParmName, const char *pszParmValue, int flags)
2415 {
2416         struct param_opt *paramo, *data;
2417         char *name;
2418
2419         while (isspace(*pszParmName)) {
2420                 pszParmName++;
2421         }
2422
2423         name = strdup(pszParmName);
2424         if (!name) return False;
2425
2426         strlower(name);
2427
2428         if (snum < 0) {
2429                 data = Globals.param_opt;
2430         } else {
2431                 data = ServicePtrs[snum]->param_opt;
2432         }
2433
2434         /* Traverse destination */
2435         for (paramo=data; paramo; paramo=paramo->next) {
2436                 /* If we already have the option set, override it unless
2437                    it was a command line option and the new one isn't */
2438                 if (strcmp(paramo->key, name) == 0) {
2439                         if ((paramo->flags & FLAG_CMDLINE) &&
2440                             !(flags & FLAG_CMDLINE)) {
2441                                 return True;
2442                         }
2443
2444                         free(paramo->value);
2445                         paramo->value = strdup(pszParmValue);
2446                         paramo->flags = flags;
2447                         free(name);
2448                         return True;
2449                 }
2450         }
2451
2452         paramo = smb_xmalloc(sizeof(*paramo));
2453         paramo->key = strdup(name);
2454         paramo->value = strdup(pszParmValue);
2455         paramo->flags = flags;
2456         if (snum < 0) {
2457                 DLIST_ADD(Globals.param_opt, paramo);
2458         } else {
2459                 DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
2460         }
2461
2462         free(name);
2463         
2464         return True;
2465 }
2466
2467 /***************************************************************************
2468  Process a parameter for a particular service number. If snum < 0
2469  then assume we are in the globals.
2470 ***************************************************************************/
2471 BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
2472 {
2473         int parmnum, i;
2474         void *parm_ptr = NULL;  /* where we are going to store the result */
2475         void *def_ptr = NULL;
2476
2477         parmnum = map_parameter(pszParmName);
2478
2479         if (parmnum < 0) {
2480                 if (strchr(pszParmName, ':')) {
2481                         return lp_do_parameter_parametric(snum, pszParmName, pszParmValue, 0);
2482                 }
2483                 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
2484                 return (True);
2485         }
2486
2487         if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
2488                 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
2489                           pszParmName));
2490         }
2491
2492         /* if the flag has been set on the command line, then don't allow override,
2493            but don't report an error */
2494         if (parm_table[parmnum].flags & FLAG_CMDLINE) {
2495                 return True;
2496         }
2497
2498         def_ptr = parm_table[parmnum].ptr;
2499
2500         /* we might point at a service, the default service or a global */
2501         if (snum < 0) {
2502                 parm_ptr = def_ptr;
2503         } else {
2504                 if (parm_table[parmnum].class == P_GLOBAL) {
2505                         DEBUG(0,
2506                               ("Global parameter %s found in service section!\n",
2507                                pszParmName));
2508                         return (True);
2509                 }
2510                 parm_ptr =
2511                         ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
2512                                                             &sDefault);
2513         }
2514
2515         if (snum >= 0) {
2516                 if (!ServicePtrs[snum]->copymap)
2517                         init_copymap(ServicePtrs[snum]);
2518
2519                 /* this handles the aliases - set the copymap for other entries with
2520                    the same data pointer */
2521                 for (i = 0; parm_table[i].label; i++)
2522                         if (parm_table[i].ptr == parm_table[parmnum].ptr)
2523                                 ServicePtrs[snum]->copymap[i] = False;
2524         }
2525
2526         /* if it is a special case then go ahead */
2527         if (parm_table[parmnum].special) {
2528                 parm_table[parmnum].special(pszParmValue, (char **)parm_ptr);
2529                 return (True);
2530         }
2531
2532         /* now switch on the type of variable it is */
2533         switch (parm_table[parmnum].type)
2534         {
2535                 case P_BOOL:
2536                         set_boolean(parm_ptr, pszParmValue);
2537                         break;
2538
2539                 case P_BOOLREV:
2540                         set_boolean(parm_ptr, pszParmValue);
2541                         *(BOOL *)parm_ptr = !*(BOOL *)parm_ptr;
2542                         break;
2543
2544                 case P_INTEGER:
2545                         *(int *)parm_ptr = atoi(pszParmValue);
2546                         break;
2547
2548                 case P_CHAR:
2549                         *(char *)parm_ptr = *pszParmValue;
2550                         break;
2551
2552                 case P_OCTAL:
2553                         sscanf(pszParmValue, "%o", (int *)parm_ptr);
2554                         break;
2555
2556                 case P_LIST:
2557                         *(char ***)parm_ptr = str_list_make(pszParmValue, NULL);
2558                         break;
2559
2560                 case P_STRING:
2561                         string_set(parm_ptr, pszParmValue);
2562                         break;
2563
2564                 case P_USTRING:
2565                         string_set(parm_ptr, pszParmValue);
2566                         strupper(*(char **)parm_ptr);
2567                         break;
2568
2569                 case P_ENUM:
2570                         for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
2571                                 if (strequal
2572                                     (pszParmValue,
2573                                      parm_table[parmnum].enum_list[i].name)) {
2574                                         *(int *)parm_ptr =
2575                                                 parm_table[parmnum].
2576                                                 enum_list[i].value;
2577                                         break;
2578                                 }
2579                         }
2580                         break;
2581                 case P_SEP:
2582                         break;
2583         }
2584
2585         return (True);
2586 }
2587
2588 /***************************************************************************
2589  Process a parameter.
2590 ***************************************************************************/
2591
2592 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue)
2593 {
2594         if (!bInGlobalSection && bGlobalOnly)
2595                 return (True);
2596
2597         DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
2598
2599         return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
2600                                 pszParmName, pszParmValue));
2601 }
2602
2603
2604 /*
2605   set a parameter from the commandline - this is called from command line parameter
2606   parsing code. It sets the parameter then marks the parameter as unable to be modified
2607   by smb.conf processing
2608 */
2609 BOOL lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
2610 {
2611         int parmnum = map_parameter(pszParmName);
2612
2613         if (parmnum < 0 && strchr(pszParmName, ':')) {
2614                 /* set a parametric option */
2615                 return lp_do_parameter_parametric(-1, pszParmName, pszParmValue, FLAG_CMDLINE);
2616         }
2617
2618         /* reset the CMDLINE flag in case this has been called before */
2619         parm_table[parmnum].flags &= ~FLAG_CMDLINE;
2620
2621         if (!lp_do_parameter(-2, pszParmName, pszParmValue)) {
2622                 return False;
2623         }
2624
2625         parm_table[parmnum].flags |= FLAG_CMDLINE;
2626         return True;
2627 }
2628
2629 /***************************************************************************
2630  Print a parameter of the specified type.
2631 ***************************************************************************/
2632
2633 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
2634 {
2635         int i;
2636         switch (p->type)
2637         {
2638                 case P_ENUM:
2639                         for (i = 0; p->enum_list[i].name; i++) {
2640                                 if (*(int *)ptr == p->enum_list[i].value) {
2641                                         fprintf(f, "%s",
2642                                                 p->enum_list[i].name);
2643                                         break;
2644                                 }
2645                         }
2646                         break;
2647
2648                 case P_BOOL:
2649                         fprintf(f, "%s", BOOLSTR(*(BOOL *)ptr));
2650                         break;
2651
2652                 case P_BOOLREV:
2653                         fprintf(f, "%s", BOOLSTR(!*(BOOL *)ptr));
2654                         break;
2655
2656                 case P_INTEGER:
2657                         fprintf(f, "%d", *(int *)ptr);
2658                         break;
2659
2660                 case P_CHAR:
2661                         fprintf(f, "%c", *(char *)ptr);
2662                         break;
2663
2664                 case P_OCTAL:
2665                         fprintf(f, "%s", octal_string(*(int *)ptr));
2666                         break;
2667
2668                 case P_LIST:
2669                         if ((char ***)ptr && *(char ***)ptr) {
2670                                 char **list = *(char ***)ptr;
2671                                 
2672                                 for (; *list; list++)
2673                                         fprintf(f, "%s%s", *list,
2674                                                 ((*(list+1))?", ":""));
2675                         }
2676                         break;
2677
2678                 case P_STRING:
2679                 case P_USTRING:
2680                         if (*(char **)ptr) {
2681                                 fprintf(f, "%s", *(char **)ptr);
2682                         }
2683                         break;
2684                 case P_SEP:
2685                         break;
2686         }
2687 }
2688
2689 /***************************************************************************
2690  Check if two parameters are equal.
2691 ***************************************************************************/
2692
2693 static BOOL equal_parameter(parm_type type, void *ptr1, void *ptr2)
2694 {
2695         switch (type) {
2696                 case P_BOOL:
2697                 case P_BOOLREV:
2698                         return (*((BOOL *)ptr1) == *((BOOL *)ptr2));
2699
2700                 case P_INTEGER:
2701                 case P_ENUM:
2702                 case P_OCTAL:
2703                         return (*((int *)ptr1) == *((int *)ptr2));
2704
2705                 case P_CHAR:
2706                         return (*((char *)ptr1) == *((char *)ptr2));
2707                 
2708                 case P_LIST:
2709                         return str_list_compare(*(char ***)ptr1, *(char ***)ptr2);
2710
2711                 case P_STRING:
2712                 case P_USTRING:
2713                 {
2714                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
2715                         if (p1 && !*p1)
2716                                 p1 = NULL;
2717                         if (p2 && !*p2)
2718                                 p2 = NULL;
2719                         return (p1 == p2 || strequal(p1, p2));
2720                 }
2721                 case P_SEP:
2722                         break;
2723         }
2724         return (False);
2725 }
2726
2727 /***************************************************************************
2728  Process a new section (service). At this stage all sections are services.
2729  Later we'll have special sections that permit server parameters to be set.
2730  Returns True on success, False on failure. 
2731 ***************************************************************************/
2732
2733 static BOOL do_section(const char *pszSectionName)
2734 {
2735         BOOL bRetval;
2736         BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2737                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2738         bRetval = False;
2739
2740         /* if we've just struck a global section, note the fact. */
2741         bInGlobalSection = isglobal;
2742
2743         /* check for multiple global sections */
2744         if (bInGlobalSection) {
2745                 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2746                 return (True);
2747         }
2748
2749         if (!bInGlobalSection && bGlobalOnly)
2750                 return (True);
2751
2752         /* if we have a current service, tidy it up before moving on */
2753         bRetval = True;
2754
2755         if (iServiceIndex >= 0)
2756                 bRetval = service_ok(iServiceIndex);
2757
2758         /* if all is still well, move to the next record in the services array */
2759         if (bRetval) {
2760                 /* We put this here to avoid an odd message order if messages are */
2761                 /* issued by the post-processing of a previous section. */
2762                 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2763
2764                 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
2765                     < 0) {
2766                         DEBUG(0, ("Failed to add a new service\n"));
2767                         return (False);
2768                 }
2769         }
2770
2771         return (bRetval);
2772 }
2773
2774
2775 /***************************************************************************
2776  Determine if a partcular base parameter is currentl set to the default value.
2777 ***************************************************************************/
2778
2779 static BOOL is_default(int i)
2780 {
2781         if (!defaults_saved)
2782                 return False;
2783         switch (parm_table[i].type) {
2784                 case P_LIST:
2785                         return str_list_compare (parm_table[i].def.lvalue, 
2786                                                 *(char ***)parm_table[i].ptr);
2787                 case P_STRING:
2788                 case P_USTRING:
2789                         return strequal(parm_table[i].def.svalue,
2790                                         *(char **)parm_table[i].ptr);
2791                 case P_BOOL:
2792                 case P_BOOLREV:
2793                         return parm_table[i].def.bvalue ==
2794                                 *(BOOL *)parm_table[i].ptr;
2795                 case P_CHAR:
2796                         return parm_table[i].def.cvalue ==
2797                                 *(char *)parm_table[i].ptr;
2798                 case P_INTEGER:
2799                 case P_OCTAL:
2800                 case P_ENUM:
2801                         return parm_table[i].def.ivalue ==
2802                                 *(int *)parm_table[i].ptr;
2803                 case P_SEP:
2804                         break;
2805         }
2806         return False;
2807 }
2808
2809 /***************************************************************************
2810 Display the contents of the global structure.
2811 ***************************************************************************/
2812
2813 static void dump_globals(FILE *f)
2814 {
2815         int i;
2816         struct param_opt *data;
2817         
2818         fprintf(f, "# Global parameters\n[global]\n");
2819
2820         for (i = 0; parm_table[i].label; i++)
2821                 if (parm_table[i].class == P_GLOBAL &&
2822                     parm_table[i].ptr &&
2823                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2824                         if (defaults_saved && is_default(i))
2825                                 continue;
2826                         fprintf(f, "\t%s = ", parm_table[i].label);
2827                         print_parameter(&parm_table[i], parm_table[i].ptr, f);
2828                         fprintf(f, "\n");
2829         }
2830         if (Globals.param_opt != NULL) {
2831                 data = Globals.param_opt;
2832                 while(data) {
2833                         fprintf(f, "\t%s = %s\n", data->key, data->value);
2834                         data = data->next;
2835                 }
2836         }
2837
2838 }
2839
2840 /***************************************************************************
2841  Return True if a local parameter is currently set to the global default.
2842 ***************************************************************************/
2843
2844 BOOL lp_is_default(int snum, struct parm_struct *parm)
2845 {
2846         int pdiff = PTR_DIFF(parm->ptr, &sDefault);
2847
2848         return equal_parameter(parm->type,
2849                                ((char *)ServicePtrs[snum]) + pdiff,
2850                                ((char *)&sDefault) + pdiff);
2851 }
2852
2853 /***************************************************************************
2854  Display the contents of a single services record.
2855 ***************************************************************************/
2856
2857 static void dump_a_service(service * pService, FILE * f)
2858 {
2859         int i;
2860         struct param_opt *data;
2861         
2862         if (pService != &sDefault)
2863                 fprintf(f, "\n[%s]\n", pService->szService);
2864
2865         for (i = 0; parm_table[i].label; i++)
2866                 if (parm_table[i].class == P_LOCAL &&
2867                     parm_table[i].ptr &&
2868                     (*parm_table[i].label != '-') &&
2869                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2870                         int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
2871
2872                         if (pService == &sDefault) {
2873                                 if (defaults_saved && is_default(i))
2874                                         continue;
2875                         } else {
2876                                 if (equal_parameter(parm_table[i].type,
2877                                                     ((char *)pService) +
2878                                                     pdiff,
2879                                                     ((char *)&sDefault) +
2880                                                     pdiff))
2881                                         continue;
2882                         }
2883
2884                         fprintf(f, "\t%s = ", parm_table[i].label);
2885                         print_parameter(&parm_table[i],
2886                                         ((char *)pService) + pdiff, f);
2887                         fprintf(f, "\n");
2888         }
2889         if (pService->param_opt != NULL) {
2890                 data = pService->param_opt;
2891                 while(data) {
2892                         fprintf(f, "\t%s = %s\n", data->key, data->value);
2893                         data = data->next;
2894                 }
2895         }
2896 }
2897
2898
2899 /***************************************************************************
2900  Return info about the next service  in a service. snum==-1 gives the globals.
2901  Return NULL when out of parameters.
2902 ***************************************************************************/
2903
2904 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
2905 {
2906         if (snum == -1) {
2907                 /* do the globals */
2908                 for (; parm_table[*i].label; (*i)++) {
2909                         if (parm_table[*i].class == P_SEPARATOR)
2910                                 return &parm_table[(*i)++];
2911
2912                         if (!parm_table[*i].ptr
2913                             || (*parm_table[*i].label == '-'))
2914                                 continue;
2915
2916                         if ((*i) > 0
2917                             && (parm_table[*i].ptr ==
2918                                 parm_table[(*i) - 1].ptr))
2919                                 continue;
2920
2921                         return &parm_table[(*i)++];
2922                 }
2923         } else {
2924                 service *pService = ServicePtrs[snum];
2925
2926                 for (; parm_table[*i].label; (*i)++) {
2927                         if (parm_table[*i].class == P_SEPARATOR)
2928                                 return &parm_table[(*i)++];
2929
2930                         if (parm_table[*i].class == P_LOCAL &&
2931                             parm_table[*i].ptr &&
2932                             (*parm_table[*i].label != '-') &&
2933                             ((*i) == 0 ||
2934                              (parm_table[*i].ptr !=
2935                               parm_table[(*i) - 1].ptr)))
2936                         {
2937                                 int pdiff =
2938                                         PTR_DIFF(parm_table[*i].ptr,
2939                                                  &sDefault);
2940
2941                                 if (allparameters ||
2942                                     !equal_parameter(parm_table[*i].type,
2943                                                      ((char *)pService) +
2944                                                      pdiff,
2945                                                      ((char *)&sDefault) +
2946                                                      pdiff))
2947                                 {
2948                                         return &parm_table[(*i)++];
2949                                 }
2950                         }
2951                 }
2952         }
2953
2954         return NULL;
2955 }
2956
2957
2958 #if 0
2959 /***************************************************************************
2960  Display the contents of a single copy structure.
2961 ***************************************************************************/
2962 static void dump_copy_map(BOOL *pcopymap)
2963 {
2964         int i;
2965         if (!pcopymap)
2966                 return;
2967
2968         printf("\n\tNon-Copied parameters:\n");
2969
2970         for (i = 0; parm_table[i].label; i++)
2971                 if (parm_table[i].class == P_LOCAL &&
2972                     parm_table[i].ptr && !pcopymap[i] &&
2973                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
2974                 {
2975                         printf("\t\t%s\n", parm_table[i].label);
2976                 }
2977 }
2978 #endif
2979
2980 /***************************************************************************
2981  Return TRUE if the passed service number is within range.
2982 ***************************************************************************/
2983
2984 BOOL lp_snum_ok(int iService)
2985 {
2986         return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
2987 }
2988
2989 /***************************************************************************
2990  Auto-load some home services.
2991 ***************************************************************************/
2992
2993 static void lp_add_auto_services(const char *str)
2994 {
2995         return;
2996 }
2997
2998 /***************************************************************************
2999  Auto-load one printer.
3000 ***************************************************************************/
3001
3002 void lp_add_one_printer(char *name, char *comment)
3003 {
3004         int printers = lp_servicenumber(PRINTERS_NAME);
3005         int i;
3006
3007         if (lp_servicenumber(name) < 0) {
3008                 lp_add_printer(name, printers);
3009                 if ((i = lp_servicenumber(name)) >= 0) {
3010                         string_set(&ServicePtrs[i]->comment, comment);
3011                         ServicePtrs[i]->autoloaded = True;
3012                 }
3013         }
3014 }
3015
3016 /***************************************************************************
3017  Announce ourselves as a print server.
3018 ***************************************************************************/
3019
3020 void update_server_announce_as_printserver(void)
3021 {
3022         default_server_announce |= SV_TYPE_PRINTQ_SERVER;       
3023 }
3024
3025 /***************************************************************************
3026  Have we loaded a services file yet?
3027 ***************************************************************************/
3028
3029 BOOL lp_loaded(void)
3030 {
3031         return (bLoaded);
3032 }
3033
3034 /***************************************************************************
3035  Unload unused services.
3036 ***************************************************************************/
3037
3038 void lp_killunused(struct server_context *smb, BOOL (*snumused) (struct server_context *, int))
3039 {
3040         int i;
3041         for (i = 0; i < iNumServices; i++) {
3042                 if (!VALID(i))
3043                         continue;
3044
3045                 if (!snumused || !snumused(smb, i)) {
3046                         ServicePtrs[i]->valid = False;
3047                         free_service(ServicePtrs[i]);
3048                 }
3049         }
3050 }
3051
3052 /***************************************************************************
3053  Unload a service.
3054 ***************************************************************************/
3055
3056 void lp_killservice(int iServiceIn)
3057 {
3058         if (VALID(iServiceIn)) {
3059                 ServicePtrs[iServiceIn]->valid = False;
3060                 free_service(ServicePtrs[iServiceIn]);
3061         }
3062 }
3063
3064 /***************************************************************************
3065  Save the curent values of all global and sDefault parameters into the 
3066  defaults union. This allows swat and testparm to show only the
3067  changed (ie. non-default) parameters.
3068 ***************************************************************************/
3069
3070 static void lp_save_defaults(void)
3071 {
3072         int i;
3073         for (i = 0; parm_table[i].label; i++) {
3074                 if (i > 0 && parm_table[i].ptr == parm_table[i - 1].ptr)
3075                         continue;
3076                 switch (parm_table[i].type) {
3077                         case P_LIST:
3078                                 str_list_copy(&(parm_table[i].def.lvalue),
3079                                             *(const char ***)parm_table[i].ptr);
3080                                 break;
3081                         case P_STRING:
3082                         case P_USTRING:
3083                                 if (parm_table[i].ptr) {
3084                                         parm_table[i].def.svalue = strdup(*(char **)parm_table[i].ptr);
3085                                 } else {
3086                                         parm_table[i].def.svalue = NULL;
3087                                 }
3088                                 break;
3089                         case P_BOOL:
3090                         case P_BOOLREV:
3091                                 parm_table[i].def.bvalue =
3092                                         *(BOOL *)parm_table[i].ptr;
3093                                 break;
3094                         case P_CHAR:
3095                                 parm_table[i].def.cvalue =
3096                                         *(char *)parm_table[i].ptr;
3097                                 break;
3098                         case P_INTEGER:
3099                         case P_OCTAL:
3100                         case P_ENUM:
3101                                 parm_table[i].def.ivalue =
3102                                         *(int *)parm_table[i].ptr;
3103                                 break;
3104                         case P_SEP:
3105                                 break;
3106                 }
3107         }
3108         defaults_saved = True;
3109 }
3110
3111 /*******************************************************************
3112  Set the server type we will announce as via nmbd.
3113 ********************************************************************/
3114
3115 static void set_server_role(void)
3116 {
3117         server_role = ROLE_STANDALONE;
3118
3119         switch (lp_security()) {
3120                 case SEC_SHARE:
3121                         if (lp_domain_logons())
3122                                 DEBUG(0, ("Server's Role (logon server) conflicts with share-level security\n"));
3123                         break;
3124                 case SEC_SERVER:
3125                 case SEC_DOMAIN:
3126                 case SEC_ADS:
3127                         if (lp_domain_logons()) {
3128                                 server_role = ROLE_DOMAIN_PDC;
3129                                 break;
3130                         }
3131                         server_role = ROLE_DOMAIN_MEMBER;
3132                         break;
3133                 case SEC_USER:
3134                         if (lp_domain_logons()) {
3135
3136                                 if (Globals.bDomainMaster) /* auto or yes */ 
3137                                         server_role = ROLE_DOMAIN_PDC;
3138                                 else
3139                                         server_role = ROLE_DOMAIN_BDC;
3140                         }
3141                         break;
3142                 default:
3143                         DEBUG(0, ("Server's Role undefined due to unknown security mode\n"));
3144                         break;
3145         }
3146
3147         DEBUG(10, ("set_server_role: role = "));
3148
3149         switch(server_role) {
3150         case ROLE_STANDALONE:
3151                 DEBUGADD(10, ("ROLE_STANDALONE\n"));
3152                 break;
3153         case ROLE_DOMAIN_MEMBER:
3154                 DEBUGADD(10, ("ROLE_DOMAIN_MEMBER\n"));
3155                 break;
3156         case ROLE_DOMAIN_BDC:
3157                 DEBUGADD(10, ("ROLE_DOMAIN_BDC\n"));
3158                 break;
3159         case ROLE_DOMAIN_PDC:
3160                 DEBUGADD(10, ("ROLE_DOMAIN_PDC\n"));
3161                 break;
3162         }
3163 }
3164
3165 /***************************************************************************
3166  Load the services array from the services file. Return True on success, 
3167  False on failure.
3168 ***************************************************************************/
3169
3170 BOOL lp_load(const char *pszFname, BOOL global_only, BOOL save_defaults,
3171              BOOL add_ipc)
3172 {
3173         pstring n2;
3174         BOOL bRetval;
3175         struct param_opt *data;
3176
3177         pstrcpy(n2, pszFname);
3178         standard_sub_basic(n2,sizeof(n2));
3179
3180         add_to_file_list(pszFname, n2);
3181
3182         bRetval = False;
3183
3184         DEBUG(2, ("lp_load: refreshing parameters from %s\n", pszFname));
3185         
3186         bInGlobalSection = True;
3187         bGlobalOnly = global_only;
3188
3189         init_globals();
3190
3191         if (save_defaults)
3192         {
3193                 lp_save_defaults();
3194         }
3195
3196         if (Globals.param_opt != NULL) {
3197                 struct param_opt *next;
3198                 for (data=Globals.param_opt; data; data=next) {
3199                         next = data->next;
3200                         if (data->flags & FLAG_CMDLINE) continue;
3201                         free(data->key);
3202                         free(data->value);
3203                         DLIST_REMOVE(Globals.param_opt, data);
3204                         free(data);
3205                 }
3206         }
3207         
3208         /* We get sections first, so have to start 'behind' to make up */
3209         iServiceIndex = -1;
3210         bRetval = pm_process(n2, do_section, do_parameter);
3211
3212         /* finish up the last section */
3213         DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
3214         if (bRetval)
3215                 if (iServiceIndex >= 0)
3216                         bRetval = service_ok(iServiceIndex);
3217
3218         lp_add_auto_services(lp_auto_services());
3219
3220         if (add_ipc) {
3221                 /* When 'restrict anonymous = 2' guest connections to ipc$
3222                    are denied */
3223                 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
3224                 lp_add_ipc("ADMIN$", False);
3225         }
3226
3227         set_server_role();
3228         set_default_server_announce_type();
3229
3230         bLoaded = True;
3231
3232         /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
3233         /* if bWINSsupport is true and we are in the client            */
3234         if (in_client && Globals.bWINSsupport) {
3235                 lp_do_parameter(-1, "wins server", "127.0.0.1");
3236         }
3237
3238         init_iconv();
3239
3240         return (bRetval);
3241 }
3242
3243 /***************************************************************************
3244  Reset the max number of services.
3245 ***************************************************************************/
3246
3247 void lp_resetnumservices(void)
3248 {
3249         iNumServices = 0;
3250 }
3251
3252 /***************************************************************************
3253  Return the max number of services.
3254 ***************************************************************************/
3255
3256 int lp_numservices(void)
3257 {
3258         return (iNumServices);
3259 }
3260
3261 /***************************************************************************
3262 Display the contents of the services array in human-readable form.
3263 ***************************************************************************/
3264
3265 void lp_dump(FILE *f, BOOL show_defaults, int maxtoprint)
3266 {
3267         int iService;
3268
3269         if (show_defaults)
3270                 defaults_saved = False;
3271
3272         dump_globals(f);
3273
3274         dump_a_service(&sDefault, f);
3275
3276         for (iService = 0; iService < maxtoprint; iService++)
3277                 lp_dump_one(f, show_defaults, iService);
3278 }
3279
3280 /***************************************************************************
3281 Display the contents of one service in human-readable form.
3282 ***************************************************************************/
3283
3284 void lp_dump_one(FILE * f, BOOL show_defaults, int snum)
3285 {
3286         if (VALID(snum)) {
3287                 if (ServicePtrs[snum]->szService[0] == '\0')
3288                         return;
3289                 dump_a_service(ServicePtrs[snum], f);
3290         }
3291 }
3292
3293 /***************************************************************************
3294 Return the number of the service with the given name, or -1 if it doesn't
3295 exist. Note that this is a DIFFERENT ANIMAL from the internal function
3296 getservicebyname()! This works ONLY if all services have been loaded, and
3297 does not copy the found service.
3298 ***************************************************************************/
3299
3300 int lp_servicenumber(const char *pszServiceName)
3301 {
3302         int iService;
3303         fstring serviceName;
3304  
3305  
3306         for (iService = iNumServices - 1; iService >= 0; iService--) {
3307                 if (VALID(iService) && ServicePtrs[iService]->szService) {
3308                         /*
3309                          * The substitution here is used to support %U is
3310                          * service names
3311                          */
3312                         fstrcpy(serviceName, ServicePtrs[iService]->szService);
3313                         standard_sub_basic(serviceName,sizeof(serviceName));
3314                         if (strequal(serviceName, pszServiceName))
3315                                 break;
3316                 }
3317         }
3318
3319         if (iService < 0)
3320                 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
3321
3322         return (iService);
3323 }
3324
3325 /*******************************************************************
3326  A useful volume label function. 
3327 ********************************************************************/
3328 const char *volume_label(int snum)
3329 {
3330         const char *ret = lp_volume(snum);
3331         if (!*ret)
3332                 return lp_servicename(snum);
3333         return (ret);
3334 }
3335
3336
3337 /*******************************************************************
3338  Set the server type we will announce as via nmbd.
3339 ********************************************************************/
3340
3341 static void set_default_server_announce_type(void)
3342 {
3343         default_server_announce = 0;
3344         default_server_announce |= SV_TYPE_WORKSTATION;
3345         default_server_announce |= SV_TYPE_SERVER;
3346         default_server_announce |= SV_TYPE_SERVER_UNIX;
3347
3348         switch (lp_announce_as()) {
3349                 case ANNOUNCE_AS_NT_SERVER:
3350                         default_server_announce |= SV_TYPE_SERVER_NT;
3351                         /* fall through... */
3352                 case ANNOUNCE_AS_NT_WORKSTATION:
3353                         default_server_announce |= SV_TYPE_NT;
3354                         break;
3355                 case ANNOUNCE_AS_WIN95:
3356                         default_server_announce |= SV_TYPE_WIN95_PLUS;
3357                         break;
3358                 case ANNOUNCE_AS_WFW:
3359                         default_server_announce |= SV_TYPE_WFW;
3360                         break;
3361                 default:
3362                         break;
3363         }
3364
3365         switch (lp_server_role()) {
3366                 case ROLE_DOMAIN_MEMBER:
3367                         default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
3368                         break;
3369                 case ROLE_DOMAIN_PDC:
3370                         default_server_announce |= SV_TYPE_DOMAIN_CTRL;
3371                         break;
3372                 case ROLE_DOMAIN_BDC:
3373                         default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
3374                         break;
3375                 case ROLE_STANDALONE:
3376                 default:
3377                         break;
3378         }
3379         if (lp_time_server())
3380                 default_server_announce |= SV_TYPE_TIME_SOURCE;
3381
3382         if (lp_host_msdfs())
3383                 default_server_announce |= SV_TYPE_DFS_SERVER;
3384 }
3385
3386 /***********************************************************
3387  returns role of Samba server
3388 ************************************************************/
3389
3390 int lp_server_role(void)
3391 {
3392         return server_role;
3393 }
3394
3395 /***********************************************************
3396  If we are PDC then prefer us as DMB
3397 ************************************************************/
3398
3399 BOOL lp_domain_master(void)
3400 {
3401         if (Globals.bDomainMaster == Auto)
3402                 return (lp_server_role() == ROLE_DOMAIN_PDC);
3403
3404         return Globals.bDomainMaster;
3405 }
3406
3407 /***********************************************************
3408  If we are DMB then prefer us as LMB
3409 ************************************************************/
3410
3411 BOOL lp_preferred_master(void)
3412 {
3413         if (Globals.bPreferredMaster == Auto)
3414                 return (lp_local_master() && lp_domain_master());
3415
3416         return Globals.bPreferredMaster;
3417 }
3418
3419 /*******************************************************************
3420  Remove a service.
3421 ********************************************************************/
3422
3423 void lp_remove_service(int snum)
3424 {
3425         ServicePtrs[snum]->valid = False;
3426 }
3427
3428 /*******************************************************************
3429  Copy a service.
3430 ********************************************************************/
3431
3432 void lp_copy_service(int snum, const char *new_name)
3433 {
3434         const char *oldname = lp_servicename(snum);
3435         do_section(new_name);
3436         if (snum >= 0) {
3437                 snum = lp_servicenumber(new_name);
3438                 if (snum >= 0)
3439                         lp_do_parameter(snum, "copy", oldname);
3440         }
3441 }
3442
3443
3444 /*******************************************************************
3445  Get the default server type we will announce as via nmbd.
3446 ********************************************************************/
3447
3448 int lp_default_server_announce(void)
3449 {
3450         return default_server_announce;
3451 }
3452
3453 /*******************************************************************
3454  Split the announce version into major and minor numbers.
3455 ********************************************************************/
3456
3457 int lp_major_announce_version(void)
3458 {
3459         static BOOL got_major = False;
3460         static int major_version = DEFAULT_MAJOR_VERSION;
3461         const char *vers;
3462         char *p;
3463
3464         if (got_major)
3465                 return major_version;
3466
3467         got_major = True;
3468         if ((vers = lp_announce_version()) == NULL)
3469                 return major_version;
3470
3471         if ((p = strchr_m(vers, '.')) == 0)
3472                 return major_version;
3473
3474         *p = '\0';
3475         major_version = atoi(vers);
3476         return major_version;
3477 }
3478
3479 int lp_minor_announce_version(void)
3480 {
3481         static BOOL got_minor = False;
3482         static int minor_version = DEFAULT_MINOR_VERSION;
3483         const char *vers;
3484         char *p;
3485
3486         if (got_minor)
3487                 return minor_version;
3488
3489         got_minor = True;
3490         if ((vers = lp_announce_version()) == NULL)
3491                 return minor_version;
3492
3493         if ((p = strchr_m(vers, '.')) == 0)
3494                 return minor_version;
3495
3496         p++;
3497         minor_version = atoi(p);
3498         return minor_version;
3499 }
3500
3501 const char *lp_printername(int snum)
3502 {
3503         const char *ret = _lp_printername(snum);
3504         if (ret == NULL || (ret != NULL && *ret == '\0'))
3505                 ret = lp_const_servicename(snum);
3506
3507         return ret;
3508 }
3509
3510
3511 /*******************************************************************
3512  Return the max print jobs per queue.
3513 ********************************************************************/
3514
3515 int lp_maxprintjobs(int snum)
3516 {
3517         int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
3518         if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
3519                 maxjobs = PRINT_MAX_JOBID - 1;
3520
3521         return maxjobs;
3522 }