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