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