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