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