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