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