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