33026dd9e07d8cb1069d85c9db84a40bef007606
[samba.git] / source / param / loadparm.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Parameter loading functions
4    Copyright (C) Karl Auer 1993-1998
5
6    Largely re-written by Andrew Tridgell, September 1994
7
8    Copyright (C) Simo Sorce 2001
9    Copyright (C) Alexander Bokovoy 2002
10    Copyright (C) Stefan (metze) Metzmacher 2002
11    Copyright (C) Jim McDonough (jmcd@us.ibm.com)  2003.
12    Copyright (C) James Myers 2003 <myersjj@samba.org>
13    
14    This program is free software; you can redistribute it and/or modify
15    it under the terms of the GNU General Public License as published by
16    the Free Software Foundation; either version 2 of the License, or
17    (at your option) any later version.
18    
19    This program is distributed in the hope that it will be useful,
20    but WITHOUT ANY WARRANTY; without even the implied warranty of
21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22    GNU General Public License for more details.
23    
24    You should have received a copy of the GNU General Public License
25    along with this program; if not, write to the Free Software
26    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 */
28
29 /*
30  *  Load parameters.
31  *
32  *  This module provides suitable callback functions for the params
33  *  module. It builds the internal table of service details which is
34  *  then used by the rest of the server.
35  *
36  * To add a parameter:
37  *
38  * 1) add it to the global or service structure definition
39  * 2) add it to the parm_table
40  * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
41  * 4) If it's a global then initialise it in init_globals. If a local
42  *    (ie. service) parameter then initialise it in the sDefault structure
43  *  
44  *
45  * Notes:
46  *   The configuration file is processed sequentially for speed. It is NOT
47  *   accessed randomly as happens in 'real' Windows. For this reason, there
48  *   is a fair bit of sequence-dependent code here - ie., code which assumes
49  *   that certain things happen before others. In particular, the code which
50  *   happens at the boundary between sections is delicately poised, so be
51  *   careful!
52  *
53  */
54
55 #include "includes.h"
56 #include "version.h"
57 #include "dynconfig.h"
58 #include "system/time.h"
59 #include "system/iconv.h"
60 #include "system/network.h"
61 #include "system/printing.h"
62 #include "librpc/gen_ndr/ndr_svcctl.h"
63 #include "librpc/gen_ndr/ndr_samr.h"
64 #include "librpc/gen_ndr/ndr_nbt.h"
65 #include "dlinklist.h"
66
67 BOOL in_client = False;         /* Not in the client by default */
68 static BOOL bLoaded = False;
69
70 #ifndef GLOBAL_NAME
71 #define GLOBAL_NAME "global"
72 #endif
73
74 #ifndef PRINTERS_NAME
75 #define PRINTERS_NAME "printers"
76 #endif
77
78 #ifndef HOMES_NAME
79 #define HOMES_NAME "homes"
80 #endif
81
82 /* some helpful bits */
83 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && ServicePtrs[(i)]->valid)
84 #define VALID(i) ServicePtrs[i]->valid
85
86 static BOOL do_parameter(const char *, const char *);
87 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...);
88
89 static BOOL defaults_saved = False;
90
91
92 #define FLAG_BASIC      0x0001 /* fundamental options */
93 #define FLAG_SHARE      0x0002 /* file sharing options */
94 #define FLAG_PRINT      0x0004 /* printing options */
95 #define FLAG_GLOBAL     0x0008 /* local options that should be globally settable in SWAT */
96 #define FLAG_WIZARD     0x0010 /* Parameters that the wizard will operate on */
97 #define FLAG_ADVANCED   0x0020 /* Parameters that the wizard will operate on */
98 #define FLAG_DEVELOPER  0x0040 /* Parameters that the wizard will operate on */
99 #define FLAG_DEPRECATED 0x1000 /* options that should no longer be used */
100 #define FLAG_HIDE       0x2000 /* options that should be hidden in SWAT */
101 #define FLAG_DOS_STRING 0x4000 /* convert from UNIX to DOS codepage when reading this string. */
102 #define FLAG_CMDLINE    0x8000 /* this option was set from the command line */
103
104
105 /* the following are used by loadparm for option lists */
106 typedef enum
107 {
108   P_BOOL,P_BOOLREV,P_CHAR,P_INTEGER,P_OCTAL,P_LIST,
109   P_STRING,P_USTRING,P_ENUM,P_SEP
110 } parm_type;
111
112 typedef enum
113 {
114   P_LOCAL,P_GLOBAL,P_SEPARATOR,P_NONE
115 } parm_class;
116
117 struct enum_list {
118         int value;
119         const char *name;
120 };
121
122 struct parm_struct
123 {
124         const char *label;
125         parm_type type;
126         parm_class class;
127         void *ptr;
128         BOOL (*special)(const char *, char **);
129         const struct enum_list *enum_list;
130         uint_t flags;
131         union {
132                 BOOL bvalue;
133                 int ivalue;
134                 char *svalue;
135                 char cvalue;
136                 const char **lvalue;
137         } def;
138 };
139
140
141 struct param_opt {
142         struct param_opt *prev, *next;
143         char *key;
144         char *value;
145         int flags;
146 };
147
148 /* 
149  * This structure describes global (ie., server-wide) parameters.
150  */
151 typedef struct
152 {
153         char **smb_ports;
154         char *dos_charset;
155         char *unix_charset;
156         char *ncalrpc_dir;
157         char *display_charset;
158         char *szPrintcapname;
159         char *szLockDir;
160         char *szPidDir;
161         char *szRootdir;
162         char *szDefaultService;
163         char *szHostsEquiv;
164         char *szServerString;
165         char *szAutoServices;
166         char *szPasswdProgram;
167         char *szPasswdChat;
168         char *szLogFile;
169         char *szConfigFile;
170         char *szSMBPasswdFile;
171         char *szSAM_URL;
172         char *szSPOOLSS_URL;
173         char *szWINS_URL;
174         char *szPrivateDir;
175         char **szPreloadModules;
176         char **szPasswordServers;
177         char *szSocketOptions;
178         char *szRealm;
179         char *szADSserver;
180         char *szLogonScript;
181         char *szLogonPath;
182         char *szLogonDrive;
183         char *szLogonHome;
184         char **szWINSservers;
185         char **szInterfaces;
186         char *szRemoteAnnounce;
187         char *szRemoteBrowseSync;
188         char *szSocketAddress;
189         char *szAnnounceVersion;        /* This is initialised in init_globals */
190         char *szWorkgroup;
191         char *szNetbiosName;
192         char **szNetbiosAliases;
193         char *szNetbiosScope;
194         char *szDomainOtherSIDs;
195         char **szNameResolveOrder;
196         char *szPanicAction;
197         char *szAddUserScript; 
198         char *szAddMachineScript;
199         char *szWINSHook;
200         char *szWINSPartners;
201         char **dcerpc_ep_servers;
202         char **server_services;
203         char *szWinbindUID;
204         char *szWinbindGID;
205         char *szNonUnixAccountRange;
206         char *szTemplateHomedir;
207         char *szTemplateShell;
208         char *szWinbindSeparator;
209         BOOL bWinbindEnumUsers;
210         BOOL bWinbindEnumGroups;
211         BOOL bWinbindUseDefaultDomain;
212         char *szIDMapBackend;
213         char *szGuestaccount;
214         int max_mux;
215         int max_xmit;
216         int pwordlevel;
217         int unamelevel;
218         int maxprotocol;
219         int minprotocol;
220         int security;
221         char **AuthMethods;
222         BOOL paranoid_server_security;
223         int lpqcachetime;
224         BOOL bDisableSpoolss;
225         int os_level;
226         int enhanced_browsing;
227         int time_offset;
228         int max_ttl;
229         int max_wins_ttl;
230         int min_wins_ttl;
231         int lm_announce;
232         int lm_interval;
233         int announce_as;        /* This is initialised in init_globals */
234         int machine_password_timeout;
235         int winbind_cache_time;
236         int iLockSpinCount;
237         int iLockSpinTime;
238         int nbt_port;
239         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                         update_server_announce_as_printserver();
1930                 }
1931                 /* [printers] service must also be non-browsable. */
1932                 if (ServicePtrs[iService]->bBrowseable)
1933                         ServicePtrs[iService]->bBrowseable = False;
1934         }
1935
1936         /* If a service is flagged unavailable, log the fact at level 0. */
1937         if (!ServicePtrs[iService]->bAvailable)
1938                 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
1939                           ServicePtrs[iService]->szService));
1940
1941         return (bRetval);
1942 }
1943
1944 static struct file_lists {
1945         struct file_lists *next;
1946         char *name;
1947         char *subfname;
1948         time_t modtime;
1949 } *file_lists = NULL;
1950
1951 /*******************************************************************
1952  Keep a linked list of all config files so we know when one has changed 
1953  it's date and needs to be reloaded.
1954 ********************************************************************/
1955
1956 static void add_to_file_list(const char *fname, const char *subfname)
1957 {
1958         struct file_lists *f = file_lists;
1959
1960         while (f) {
1961                 if (f->name && !strcmp(f->name, fname))
1962                         break;
1963                 f = f->next;
1964         }
1965
1966         if (!f) {
1967                 f = malloc_p(struct file_lists);
1968                 if (!f)
1969                         return;
1970                 f->next = file_lists;
1971                 f->name = strdup(fname);
1972                 if (!f->name) {
1973                         SAFE_FREE(f);
1974                         return;
1975                 }
1976                 f->subfname = strdup(subfname);
1977                 if (!f->subfname) {
1978                         SAFE_FREE(f);
1979                         return;
1980                 }
1981                 file_lists = f;
1982                 f->modtime = file_modtime(subfname);
1983         } else {
1984                 time_t t = file_modtime(subfname);
1985                 if (t)
1986                         f->modtime = t;
1987         }
1988 }
1989
1990 /*******************************************************************
1991  Check if a config file has changed date.
1992 ********************************************************************/
1993
1994 BOOL lp_file_list_changed(void)
1995 {
1996         struct file_lists *f = file_lists;
1997         DEBUG(6, ("lp_file_list_changed()\n"));
1998
1999         while (f) {
2000                 pstring n2;
2001                 time_t mod_time;
2002
2003                 pstrcpy(n2, f->name);
2004                 standard_sub_basic(n2,sizeof(n2));
2005
2006                 DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
2007                              f->name, n2, ctime(&f->modtime)));
2008
2009                 mod_time = file_modtime(n2);
2010
2011                 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
2012                         DEBUGADD(6,
2013                                  ("file %s modified: %s\n", n2,
2014                                   ctime(&mod_time)));
2015                         f->modtime = mod_time;
2016                         SAFE_FREE(f->subfname);
2017                         f->subfname = strdup(n2);
2018                         return (True);
2019                 }
2020                 f = f->next;
2021         }
2022         return (False);
2023 }
2024
2025 /***************************************************************************
2026  Handle the include operation.
2027 ***************************************************************************/
2028
2029 static BOOL handle_include(const char *pszParmValue, char **ptr)
2030 {
2031         pstring fname;
2032         pstrcpy(fname, pszParmValue);
2033
2034         standard_sub_basic(fname,sizeof(fname));
2035
2036         add_to_file_list(pszParmValue, fname);
2037
2038         string_set(ptr, fname);
2039
2040         if (file_exist(fname))
2041                 return (pm_process(fname, do_section, do_parameter));
2042
2043         DEBUG(2, ("Can't find include file %s\n", fname));
2044
2045         return (False);
2046 }
2047
2048 /***************************************************************************
2049  Handle the interpretation of the copy parameter.
2050 ***************************************************************************/
2051
2052 static BOOL handle_copy(const char *pszParmValue, char **ptr)
2053 {
2054         BOOL bRetval;
2055         int iTemp;
2056         service serviceTemp;
2057
2058         string_set(ptr, pszParmValue);
2059
2060         init_service(&serviceTemp);
2061
2062         bRetval = False;
2063
2064         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
2065
2066         if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
2067                 if (iTemp == iServiceIndex) {
2068                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
2069                 } else {
2070                         copy_service(ServicePtrs[iServiceIndex],
2071                                      &serviceTemp,
2072                                      ServicePtrs[iServiceIndex]->copymap);
2073                         bRetval = True;
2074                 }
2075         } else {
2076                 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
2077                 bRetval = False;
2078         }
2079
2080         free_service(&serviceTemp);
2081         return (bRetval);
2082 }
2083
2084 /***************************************************************************
2085  Handle winbind/non unix account uid and gid allocation parameters.  The format of these
2086  parameters is:
2087
2088  [global]
2089
2090         winbind uid = 1000-1999
2091         winbind gid = 700-899
2092
2093  We only do simple parsing checks here.  The strings are parsed into useful
2094  structures in the winbind daemon code.
2095
2096 ***************************************************************************/
2097
2098 /* Some lp_ routines to return winbind [ug]id information */
2099
2100 static uid_t winbind_uid_low, winbind_uid_high;
2101 static gid_t winbind_gid_low, winbind_gid_high;
2102 static uint32_t non_unix_account_low, non_unix_account_high;
2103
2104 BOOL lp_winbind_uid(uid_t *low, uid_t *high)
2105 {
2106         if (winbind_uid_low == 0 || winbind_uid_high == 0)
2107                 return False;
2108
2109         if (low)
2110                 *low = winbind_uid_low;
2111
2112         if (high)
2113                 *high = winbind_uid_high;
2114
2115         return True;
2116 }
2117
2118 BOOL lp_winbind_gid(gid_t *low, gid_t *high)
2119 {
2120         if (winbind_gid_low == 0 || winbind_gid_high == 0)
2121                 return False;
2122
2123         if (low)
2124                 *low = winbind_gid_low;
2125
2126         if (high)
2127                 *high = winbind_gid_high;
2128
2129         return True;
2130 }
2131
2132 BOOL lp_non_unix_account_range(uint32_t *low, uint32_t *high)
2133 {
2134         if (non_unix_account_low == 0 || non_unix_account_high == 0)
2135                 return False;
2136
2137         if (low)
2138                 *low = non_unix_account_low;
2139
2140         if (high)
2141                 *high = non_unix_account_high;
2142
2143         return True;
2144 }
2145
2146 /* Do some simple checks on "winbind [ug]id" parameter values */
2147
2148 static BOOL handle_winbind_uid(const char *pszParmValue, char **ptr)
2149 {
2150         uint32_t low, high;
2151
2152         if (sscanf(pszParmValue, "%u-%u", &low, &high) != 2 || high < low)
2153                 return False;
2154
2155         /* Parse OK */
2156
2157         string_set(ptr, pszParmValue);
2158
2159         winbind_uid_low = low;
2160         winbind_uid_high = high;
2161
2162         return True;
2163 }
2164
2165 static BOOL handle_winbind_gid(const char *pszParmValue, char **ptr)
2166 {
2167         uint32_t low, high;
2168
2169         if (sscanf(pszParmValue, "%u-%u", &low, &high) != 2 || high < low)
2170                 return False;
2171
2172         /* Parse OK */
2173
2174         string_set(ptr, pszParmValue);
2175
2176         winbind_gid_low = low;
2177         winbind_gid_high = high;
2178
2179         return True;
2180 }
2181
2182 /***************************************************************************
2183  Do some simple checks on "non unix account range" parameter values.
2184 ***************************************************************************/
2185
2186 static BOOL handle_non_unix_account_range(const char *pszParmValue, char **ptr)
2187 {
2188         uint32_t low, high;
2189
2190         if (sscanf(pszParmValue, "%u-%u", &low, &high) != 2 || high < low)
2191                 return False;
2192
2193         /* Parse OK */
2194
2195         string_set(ptr, pszParmValue);
2196
2197         non_unix_account_low = low;
2198         non_unix_account_high = high;
2199
2200         return True;
2201 }
2202
2203
2204 /***************************************************************************
2205  Initialise a copymap.
2206 ***************************************************************************/
2207
2208 static void init_copymap(service * pservice)
2209 {
2210         int i;
2211         SAFE_FREE(pservice->copymap);
2212         pservice->copymap = malloc_array_p(BOOL, NUMPARAMETERS);
2213         if (!pservice->copymap)
2214                 DEBUG(0,
2215                       ("Couldn't allocate copymap!! (size %d)\n",
2216                        (int)NUMPARAMETERS));
2217         else
2218                 for (i = 0; i < NUMPARAMETERS; i++)
2219                         pservice->copymap[i] = True;
2220 }
2221
2222 /***************************************************************************
2223  Return the local pointer to a parameter given the service number and the 
2224  pointer into the default structure.
2225 ***************************************************************************/
2226
2227 void *lp_local_ptr(int snum, void *ptr)
2228 {
2229         return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
2230 }
2231
2232
2233 /***************************************************************************
2234  Process a parametric option
2235 ***************************************************************************/
2236 static BOOL lp_do_parameter_parametric(int snum, const char *pszParmName, const char *pszParmValue, int flags)
2237 {
2238         struct param_opt *paramo, *data;
2239         char *name;
2240
2241         while (isspace(*pszParmName)) {
2242                 pszParmName++;
2243         }
2244
2245         name = strdup(pszParmName);
2246         if (!name) return False;
2247
2248         strlower(name);
2249
2250         if (snum < 0) {
2251                 data = Globals.param_opt;
2252         } else {
2253                 data = ServicePtrs[snum]->param_opt;
2254         }
2255
2256         /* Traverse destination */
2257         for (paramo=data; paramo; paramo=paramo->next) {
2258                 /* If we already have the option set, override it unless
2259                    it was a command line option and the new one isn't */
2260                 if (strcmp(paramo->key, name) == 0) {
2261                         if ((paramo->flags & FLAG_CMDLINE) &&
2262                             !(flags & FLAG_CMDLINE)) {
2263                                 return True;
2264                         }
2265
2266                         free(paramo->value);
2267                         paramo->value = strdup(pszParmValue);
2268                         paramo->flags = flags;
2269                         free(name);
2270                         return True;
2271                 }
2272         }
2273
2274         paramo = smb_xmalloc_p(struct param_opt);
2275         paramo->key = strdup(name);
2276         paramo->value = strdup(pszParmValue);
2277         paramo->flags = flags;
2278         if (snum < 0) {
2279                 DLIST_ADD(Globals.param_opt, paramo);
2280         } else {
2281                 DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
2282         }
2283
2284         free(name);
2285         
2286         return True;
2287 }
2288
2289 /***************************************************************************
2290  Process a parameter for a particular service number. If snum < 0
2291  then assume we are in the globals.
2292 ***************************************************************************/
2293 BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
2294 {
2295         int parmnum, i;
2296         void *parm_ptr = NULL;  /* where we are going to store the result */
2297         void *def_ptr = NULL;
2298
2299         parmnum = map_parameter(pszParmName);
2300
2301         if (parmnum < 0) {
2302                 if (strchr(pszParmName, ':')) {
2303                         return lp_do_parameter_parametric(snum, pszParmName, pszParmValue, 0);
2304                 }
2305                 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
2306                 return (True);
2307         }
2308
2309         if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
2310                 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
2311                           pszParmName));
2312         }
2313
2314         /* if the flag has been set on the command line, then don't allow override,
2315            but don't report an error */
2316         if (parm_table[parmnum].flags & FLAG_CMDLINE) {
2317                 return True;
2318         }
2319
2320         def_ptr = parm_table[parmnum].ptr;
2321
2322         /* we might point at a service, the default service or a global */
2323         if (snum < 0) {
2324                 parm_ptr = def_ptr;
2325         } else {
2326                 if (parm_table[parmnum].class == P_GLOBAL) {
2327                         DEBUG(0,
2328                               ("Global parameter %s found in service section!\n",
2329                                pszParmName));
2330                         return (True);
2331                 }
2332                 parm_ptr =
2333                         ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
2334                                                             &sDefault);
2335         }
2336
2337         if (snum >= 0) {
2338                 if (!ServicePtrs[snum]->copymap)
2339                         init_copymap(ServicePtrs[snum]);
2340
2341                 /* this handles the aliases - set the copymap for other entries with
2342                    the same data pointer */
2343                 for (i = 0; parm_table[i].label; i++)
2344                         if (parm_table[i].ptr == parm_table[parmnum].ptr)
2345                                 ServicePtrs[snum]->copymap[i] = False;
2346         }
2347
2348         /* if it is a special case then go ahead */
2349         if (parm_table[parmnum].special) {
2350                 parm_table[parmnum].special(pszParmValue, (char **)parm_ptr);
2351                 return (True);
2352         }
2353
2354         /* now switch on the type of variable it is */
2355         switch (parm_table[parmnum].type)
2356         {
2357                 case P_BOOL:
2358                         set_boolean(parm_ptr, pszParmValue);
2359                         break;
2360
2361                 case P_BOOLREV:
2362                         set_boolean(parm_ptr, pszParmValue);
2363                         *(BOOL *)parm_ptr = !*(BOOL *)parm_ptr;
2364                         break;
2365
2366                 case P_INTEGER:
2367                         *(int *)parm_ptr = atoi(pszParmValue);
2368                         break;
2369
2370                 case P_CHAR:
2371                         *(char *)parm_ptr = *pszParmValue;
2372                         break;
2373
2374                 case P_OCTAL:
2375                         sscanf(pszParmValue, "%o", (int *)parm_ptr);
2376                         break;
2377
2378                 case P_LIST:
2379                         *(const char ***)parm_ptr = str_list_make(talloc_autofree_context(), 
2380                                                                   pszParmValue, NULL);
2381                         break;
2382
2383                 case P_STRING:
2384                         string_set(parm_ptr, pszParmValue);
2385                         break;
2386
2387                 case P_USTRING:
2388                         string_set(parm_ptr, pszParmValue);
2389                         strupper(*(char **)parm_ptr);
2390                         break;
2391
2392                 case P_ENUM:
2393                         for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
2394                                 if (strequal
2395                                     (pszParmValue,
2396                                      parm_table[parmnum].enum_list[i].name)) {
2397                                         *(int *)parm_ptr =
2398                                                 parm_table[parmnum].
2399                                                 enum_list[i].value;
2400                                         break;
2401                                 }
2402                         }
2403                         if (!parm_table[parmnum].enum_list[i].name) {
2404                                 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n", 
2405                                          pszParmValue, pszParmName));
2406                                 return False;
2407                         }
2408                         break;
2409                 case P_SEP:
2410                         break;
2411         }
2412
2413         return (True);
2414 }
2415
2416 /***************************************************************************
2417  Process a parameter.
2418 ***************************************************************************/
2419
2420 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue)
2421 {
2422         if (!bInGlobalSection && bGlobalOnly)
2423                 return (True);
2424
2425         return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
2426                                 pszParmName, pszParmValue));
2427 }
2428
2429 /*
2430   variable argument do parameter
2431 */
2432 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
2433
2434 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...)
2435 {
2436         char *s;
2437         BOOL ret;
2438         va_list ap;
2439
2440         va_start(ap, fmt);      
2441         s = talloc_vasprintf(NULL, fmt, ap);
2442         va_end(ap);
2443         ret = do_parameter(pszParmName, s);
2444         talloc_free(s);
2445         return ret;
2446 }
2447
2448
2449 /*
2450   set a parameter from the commandline - this is called from command line parameter
2451   parsing code. It sets the parameter then marks the parameter as unable to be modified
2452   by smb.conf processing
2453 */
2454 BOOL lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
2455 {
2456         int parmnum = map_parameter(pszParmName);
2457         int i;
2458
2459         while (isspace(*pszParmValue)) pszParmValue++;
2460
2461
2462         if (parmnum < 0 && strchr(pszParmName, ':')) {
2463                 /* set a parametric option */
2464                 return lp_do_parameter_parametric(-1, pszParmName, pszParmValue, FLAG_CMDLINE);
2465         }
2466
2467         if (parmnum < 0) {
2468                 DEBUG(0,("Unknown option '%s'\n", pszParmName));
2469                 return False;
2470         }
2471
2472         /* reset the CMDLINE flag in case this has been called before */
2473         parm_table[parmnum].flags &= ~FLAG_CMDLINE;
2474
2475         if (!lp_do_parameter(-2, pszParmName, pszParmValue)) {
2476                 return False;
2477         }
2478
2479         parm_table[parmnum].flags |= FLAG_CMDLINE;
2480
2481         /* we have to also set FLAG_CMDLINE on aliases */
2482         for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
2483                 parm_table[i].flags |= FLAG_CMDLINE;
2484         }
2485         for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
2486                 parm_table[i].flags |= FLAG_CMDLINE;
2487         }
2488
2489         return True;
2490 }
2491
2492 /*
2493   set a option from the commandline in 'a=b' format. Use to support --option
2494 */
2495 BOOL lp_set_option(const char *option)
2496 {
2497         char *p, *s;
2498         BOOL ret;
2499
2500         s = strdup(option);
2501         if (!s) {
2502                 return False;
2503         }
2504
2505         p = strchr(s, '=');
2506         if (!p) {
2507                 free(s);
2508                 return False;
2509         }
2510
2511         *p = 0;
2512
2513         ret = lp_set_cmdline(s, p+1);
2514         free(s);
2515         return ret;
2516 }
2517
2518
2519 #define BOOLSTR(b) ((b) ? "Yes" : "No")
2520
2521 /***************************************************************************
2522  Print a parameter of the specified type.
2523 ***************************************************************************/
2524
2525 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
2526 {
2527         int i;
2528         switch (p->type)
2529         {
2530                 case P_ENUM:
2531                         for (i = 0; p->enum_list[i].name; i++) {
2532                                 if (*(int *)ptr == p->enum_list[i].value) {
2533                                         fprintf(f, "%s",
2534                                                 p->enum_list[i].name);
2535                                         break;
2536                                 }
2537                         }
2538                         break;
2539
2540                 case P_BOOL:
2541                         fprintf(f, "%s", BOOLSTR(*(BOOL *)ptr));
2542                         break;
2543
2544                 case P_BOOLREV:
2545                         fprintf(f, "%s", BOOLSTR(!*(BOOL *)ptr));
2546                         break;
2547
2548                 case P_INTEGER:
2549                         fprintf(f, "%d", *(int *)ptr);
2550                         break;
2551
2552                 case P_CHAR:
2553                         fprintf(f, "%c", *(char *)ptr);
2554                         break;
2555
2556                 case P_OCTAL:
2557                         if (*(int *)ptr == -1) {
2558                                 fprintf(f, "-1");
2559                         } else {
2560                                 fprintf(f, "0%o", *(int *)ptr);
2561                         }
2562                         break;
2563
2564                 case P_LIST:
2565                         if ((char ***)ptr && *(char ***)ptr) {
2566                                 char **list = *(char ***)ptr;
2567                                 
2568                                 for (; *list; list++)
2569                                         fprintf(f, "%s%s", *list,
2570                                                 ((*(list+1))?", ":""));
2571                         }
2572                         break;
2573
2574                 case P_STRING:
2575                 case P_USTRING:
2576                         if (*(char **)ptr) {
2577                                 fprintf(f, "%s", *(char **)ptr);
2578                         }
2579                         break;
2580                 case P_SEP:
2581                         break;
2582         }
2583 }
2584
2585 /***************************************************************************
2586  Check if two parameters are equal.
2587 ***************************************************************************/
2588
2589 static BOOL equal_parameter(parm_type type, void *ptr1, void *ptr2)
2590 {
2591         switch (type) {
2592                 case P_BOOL:
2593                 case P_BOOLREV:
2594                         return (*((BOOL *)ptr1) == *((BOOL *)ptr2));
2595
2596                 case P_INTEGER:
2597                 case P_ENUM:
2598                 case P_OCTAL:
2599                         return (*((int *)ptr1) == *((int *)ptr2));
2600
2601                 case P_CHAR:
2602                         return (*((char *)ptr1) == *((char *)ptr2));
2603                 
2604                 case P_LIST:
2605                         return str_list_equal((const char **)(*(char ***)ptr1), 
2606                                               (const char **)(*(char ***)ptr2));
2607
2608                 case P_STRING:
2609                 case P_USTRING:
2610                 {
2611                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
2612                         if (p1 && !*p1)
2613                                 p1 = NULL;
2614                         if (p2 && !*p2)
2615                                 p2 = NULL;
2616                         return (p1 == p2 || strequal(p1, p2));
2617                 }
2618                 case P_SEP:
2619                         break;
2620         }
2621         return (False);
2622 }
2623
2624 /***************************************************************************
2625  Process a new section (service). At this stage all sections are services.
2626  Later we'll have special sections that permit server parameters to be set.
2627  Returns True on success, False on failure. 
2628 ***************************************************************************/
2629
2630 static BOOL do_section(const char *pszSectionName)
2631 {
2632         BOOL bRetval;
2633         BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2634                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2635         bRetval = False;
2636
2637         /* if we've just struck a global section, note the fact. */
2638         bInGlobalSection = isglobal;
2639
2640         /* check for multiple global sections */
2641         if (bInGlobalSection) {
2642                 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2643                 return (True);
2644         }
2645
2646         if (!bInGlobalSection && bGlobalOnly)
2647                 return (True);
2648
2649         /* if we have a current service, tidy it up before moving on */
2650         bRetval = True;
2651
2652         if (iServiceIndex >= 0)
2653                 bRetval = service_ok(iServiceIndex);
2654
2655         /* if all is still well, move to the next record in the services array */
2656         if (bRetval) {
2657                 /* We put this here to avoid an odd message order if messages are */
2658                 /* issued by the post-processing of a previous section. */
2659                 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2660
2661                 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
2662                     < 0) {
2663                         DEBUG(0, ("Failed to add a new service\n"));
2664                         return (False);
2665                 }
2666         }
2667
2668         return (bRetval);
2669 }
2670
2671
2672 /***************************************************************************
2673  Determine if a partcular base parameter is currentl set to the default value.
2674 ***************************************************************************/
2675
2676 static BOOL is_default(int i)
2677 {
2678         if (!defaults_saved)
2679                 return False;
2680         switch (parm_table[i].type) {
2681                 case P_LIST:
2682                         return str_list_equal((const char **)parm_table[i].def.lvalue, 
2683                                               (const char **)(*(char ***)parm_table[i].ptr));
2684                 case P_STRING:
2685                 case P_USTRING:
2686                         return strequal(parm_table[i].def.svalue,
2687                                         *(char **)parm_table[i].ptr);
2688                 case P_BOOL:
2689                 case P_BOOLREV:
2690                         return parm_table[i].def.bvalue ==
2691                                 *(BOOL *)parm_table[i].ptr;
2692                 case P_CHAR:
2693                         return parm_table[i].def.cvalue ==
2694                                 *(char *)parm_table[i].ptr;
2695                 case P_INTEGER:
2696                 case P_OCTAL:
2697                 case P_ENUM:
2698                         return parm_table[i].def.ivalue ==
2699                                 *(int *)parm_table[i].ptr;
2700                 case P_SEP:
2701                         break;
2702         }
2703         return False;
2704 }
2705
2706 /***************************************************************************
2707 Display the contents of the global structure.
2708 ***************************************************************************/
2709
2710 static void dump_globals(FILE *f)
2711 {
2712         int i;
2713         struct param_opt *data;
2714         
2715         fprintf(f, "# Global parameters\n[global]\n");
2716
2717         for (i = 0; parm_table[i].label; i++)
2718                 if (parm_table[i].class == P_GLOBAL &&
2719                     parm_table[i].ptr &&
2720                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2721                         if (defaults_saved && is_default(i))
2722                                 continue;
2723                         fprintf(f, "\t%s = ", parm_table[i].label);
2724                         print_parameter(&parm_table[i], parm_table[i].ptr, f);
2725                         fprintf(f, "\n");
2726         }
2727         if (Globals.param_opt != NULL) {
2728                 data = Globals.param_opt;
2729                 while(data) {
2730                         fprintf(f, "\t%s = %s\n", data->key, data->value);
2731                         data = data->next;
2732                 }
2733         }
2734
2735 }
2736
2737 /***************************************************************************
2738  Display the contents of a single services record.
2739 ***************************************************************************/
2740
2741 static void dump_a_service(service * pService, FILE * f)
2742 {
2743         int i;
2744         struct param_opt *data;
2745         
2746         if (pService != &sDefault)
2747                 fprintf(f, "\n[%s]\n", pService->szService);
2748
2749         for (i = 0; parm_table[i].label; i++)
2750                 if (parm_table[i].class == P_LOCAL &&
2751                     parm_table[i].ptr &&
2752                     (*parm_table[i].label != '-') &&
2753                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2754                         int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
2755
2756                         if (pService == &sDefault) {
2757                                 if (defaults_saved && is_default(i))
2758                                         continue;
2759                         } else {
2760                                 if (equal_parameter(parm_table[i].type,
2761                                                     ((char *)pService) +
2762                                                     pdiff,
2763                                                     ((char *)&sDefault) +
2764                                                     pdiff))
2765                                         continue;
2766                         }
2767
2768                         fprintf(f, "\t%s = ", parm_table[i].label);
2769                         print_parameter(&parm_table[i],
2770                                         ((char *)pService) + pdiff, f);
2771                         fprintf(f, "\n");
2772         }
2773         if (pService->param_opt != NULL) {
2774                 data = pService->param_opt;
2775                 while(data) {
2776                         fprintf(f, "\t%s = %s\n", data->key, data->value);
2777                         data = data->next;
2778                 }
2779         }
2780 }
2781
2782
2783 /***************************************************************************
2784  Return info about the next service  in a service. snum==-1 gives the globals.
2785  Return NULL when out of parameters.
2786 ***************************************************************************/
2787
2788 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
2789 {
2790         if (snum == -1) {
2791                 /* do the globals */
2792                 for (; parm_table[*i].label; (*i)++) {
2793                         if (parm_table[*i].class == P_SEPARATOR)
2794                                 return &parm_table[(*i)++];
2795
2796                         if (!parm_table[*i].ptr
2797                             || (*parm_table[*i].label == '-'))
2798                                 continue;
2799
2800                         if ((*i) > 0
2801                             && (parm_table[*i].ptr ==
2802                                 parm_table[(*i) - 1].ptr))
2803                                 continue;
2804
2805                         return &parm_table[(*i)++];
2806                 }
2807         } else {
2808                 service *pService = ServicePtrs[snum];
2809
2810                 for (; parm_table[*i].label; (*i)++) {
2811                         if (parm_table[*i].class == P_SEPARATOR)
2812                                 return &parm_table[(*i)++];
2813
2814                         if (parm_table[*i].class == P_LOCAL &&
2815                             parm_table[*i].ptr &&
2816                             (*parm_table[*i].label != '-') &&
2817                             ((*i) == 0 ||
2818                              (parm_table[*i].ptr !=
2819                               parm_table[(*i) - 1].ptr)))
2820                         {
2821                                 int pdiff =
2822                                         PTR_DIFF(parm_table[*i].ptr,
2823                                                  &sDefault);
2824
2825                                 if (allparameters ||
2826                                     !equal_parameter(parm_table[*i].type,
2827                                                      ((char *)pService) +
2828                                                      pdiff,
2829                                                      ((char *)&sDefault) +
2830                                                      pdiff))
2831                                 {
2832                                         return &parm_table[(*i)++];
2833                                 }
2834                         }
2835                 }
2836         }
2837
2838         return NULL;
2839 }
2840
2841
2842 /***************************************************************************
2843  Return TRUE if the passed service number is within range.
2844 ***************************************************************************/
2845
2846 BOOL lp_snum_ok(int iService)
2847 {
2848         return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
2849 }
2850
2851 /***************************************************************************
2852  Auto-load some home services.
2853 ***************************************************************************/
2854
2855 static void lp_add_auto_services(const char *str)
2856 {
2857         return;
2858 }
2859
2860 /***************************************************************************
2861  Auto-load one printer.
2862 ***************************************************************************/
2863
2864 void lp_add_one_printer(char *name, char *comment)
2865 {
2866         int printers = lp_servicenumber(PRINTERS_NAME);
2867         int i;
2868
2869         if (lp_servicenumber(name) < 0) {
2870                 lp_add_printer(name, printers);
2871                 if ((i = lp_servicenumber(name)) >= 0) {
2872                         string_set(&ServicePtrs[i]->comment, comment);
2873                         ServicePtrs[i]->autoloaded = True;
2874                 }
2875         }
2876 }
2877
2878 /***************************************************************************
2879  Announce ourselves as a print server.
2880 ***************************************************************************/
2881
2882 void update_server_announce_as_printserver(void)
2883 {
2884         default_server_announce |= SV_TYPE_PRINTQ_SERVER;       
2885 }
2886
2887 /***************************************************************************
2888  Have we loaded a services file yet?
2889 ***************************************************************************/
2890
2891 BOOL lp_loaded(void)
2892 {
2893         return (bLoaded);
2894 }
2895
2896 /***************************************************************************
2897  Unload unused services.
2898 ***************************************************************************/
2899
2900 void lp_killunused(struct smbsrv_connection *smb, BOOL (*snumused) (struct smbsrv_connection *, int))
2901 {
2902         int i;
2903         for (i = 0; i < iNumServices; i++) {
2904                 if (!VALID(i))
2905                         continue;
2906
2907                 if (!snumused || !snumused(smb, i)) {
2908                         ServicePtrs[i]->valid = False;
2909                         free_service(ServicePtrs[i]);
2910                 }
2911         }
2912 }
2913
2914 /***************************************************************************
2915  Unload a service.
2916 ***************************************************************************/
2917
2918 void lp_killservice(int iServiceIn)
2919 {
2920         if (VALID(iServiceIn)) {
2921                 ServicePtrs[iServiceIn]->valid = False;
2922                 free_service(ServicePtrs[iServiceIn]);
2923         }
2924 }
2925
2926 /***************************************************************************
2927  Save the curent values of all global and sDefault parameters into the 
2928  defaults union. This allows swat and testparm to show only the
2929  changed (ie. non-default) parameters.
2930 ***************************************************************************/
2931
2932 static void lp_save_defaults(void)
2933 {
2934         int i;
2935         for (i = 0; parm_table[i].label; i++) {
2936                 if (i > 0 && parm_table[i].ptr == parm_table[i - 1].ptr)
2937                         continue;
2938                 switch (parm_table[i].type) {
2939                         case P_LIST:
2940                                 parm_table[i].def.lvalue = str_list_copy(talloc_autofree_context(), 
2941                                                                          *(const char ***)parm_table[i].ptr);
2942                                 break;
2943                         case P_STRING:
2944                         case P_USTRING:
2945                                 if (parm_table[i].ptr) {
2946                                         parm_table[i].def.svalue = strdup(*(char **)parm_table[i].ptr);
2947                                 } else {
2948                                         parm_table[i].def.svalue = NULL;
2949                                 }
2950                                 break;
2951                         case P_BOOL:
2952                         case P_BOOLREV:
2953                                 parm_table[i].def.bvalue =
2954                                         *(BOOL *)parm_table[i].ptr;
2955                                 break;
2956                         case P_CHAR:
2957                                 parm_table[i].def.cvalue =
2958                                         *(char *)parm_table[i].ptr;
2959                                 break;
2960                         case P_INTEGER:
2961                         case P_OCTAL:
2962                         case P_ENUM:
2963                                 parm_table[i].def.ivalue =
2964                                         *(int *)parm_table[i].ptr;
2965                                 break;
2966                         case P_SEP:
2967                                 break;
2968                 }
2969         }
2970         defaults_saved = True;
2971 }
2972
2973 /*******************************************************************
2974  Set the server type we will announce as via nmbd.
2975 ********************************************************************/
2976
2977 static void set_server_role(void)
2978 {
2979         server_role = ROLE_STANDALONE;
2980
2981         switch (lp_security()) {
2982                 case SEC_SHARE:
2983                         if (lp_domain_logons())
2984                                 DEBUG(0, ("Server's Role (logon server) conflicts with share-level security\n"));
2985                         break;
2986                 case SEC_SERVER:
2987                 case SEC_DOMAIN:
2988                 case SEC_ADS:
2989                         if (lp_domain_logons()) {
2990                                 if (Globals.bDomainMaster) /* auto or yes */ 
2991                                         server_role = ROLE_DOMAIN_PDC;
2992                                 else
2993                                         server_role = ROLE_DOMAIN_BDC;
2994                                 break;
2995                         }
2996                         server_role = ROLE_DOMAIN_MEMBER;
2997                         break;
2998                 case SEC_USER:
2999                         if (lp_domain_logons()) {
3000
3001                                 if (Globals.bDomainMaster) /* auto or yes */ 
3002                                         server_role = ROLE_DOMAIN_PDC;
3003                                 else
3004                                         server_role = ROLE_DOMAIN_BDC;
3005                         }
3006                         break;
3007                 default:
3008                         DEBUG(0, ("Server's Role undefined due to unknown security mode\n"));
3009                         break;
3010         }
3011
3012         DEBUG(10, ("set_server_role: role = "));
3013
3014         switch(server_role) {
3015         case ROLE_STANDALONE:
3016                 DEBUGADD(10, ("ROLE_STANDALONE\n"));
3017                 break;
3018         case ROLE_DOMAIN_MEMBER:
3019                 DEBUGADD(10, ("ROLE_DOMAIN_MEMBER\n"));
3020                 break;
3021         case ROLE_DOMAIN_BDC:
3022                 DEBUGADD(10, ("ROLE_DOMAIN_BDC\n"));
3023                 break;
3024         case ROLE_DOMAIN_PDC:
3025                 DEBUGADD(10, ("ROLE_DOMAIN_PDC\n"));
3026                 break;
3027         }
3028 }
3029
3030 /***************************************************************************
3031  Load the services array from the services file. Return True on success, 
3032  False on failure.
3033 ***************************************************************************/
3034
3035 BOOL lp_load(const char *pszFname, BOOL global_only, BOOL save_defaults,
3036              BOOL add_ipc)
3037 {
3038         pstring n2;
3039         BOOL bRetval;
3040         struct param_opt *data;
3041
3042         pstrcpy(n2, pszFname);
3043         standard_sub_basic(n2,sizeof(n2));
3044
3045         add_to_file_list(pszFname, n2);
3046
3047         bRetval = False;
3048
3049         DEBUG(2, ("lp_load: refreshing parameters from %s\n", pszFname));
3050         
3051         bInGlobalSection = True;
3052         bGlobalOnly = global_only;
3053
3054         if (Globals.param_opt != NULL) {
3055                 struct param_opt *next;
3056                 for (data=Globals.param_opt; data; data=next) {
3057                         next = data->next;
3058                         if (data->flags & FLAG_CMDLINE) continue;
3059                         free(data->key);
3060                         free(data->value);
3061                         DLIST_REMOVE(Globals.param_opt, data);
3062                         free(data);
3063                 }
3064         }
3065         
3066         init_globals();
3067
3068         if (save_defaults)
3069         {
3070                 lp_save_defaults();
3071         }
3072
3073         /* We get sections first, so have to start 'behind' to make up */
3074         iServiceIndex = -1;
3075         bRetval = pm_process(n2, do_section, do_parameter);
3076
3077         /* finish up the last section */
3078         DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
3079         if (bRetval)
3080                 if (iServiceIndex >= 0)
3081                         bRetval = service_ok(iServiceIndex);
3082
3083         lp_add_auto_services(lp_auto_services());
3084
3085         if (add_ipc) {
3086                 /* When 'restrict anonymous = 2' guest connections to ipc$
3087                    are denied */
3088                 lp_add_hidden("IPC$", "IPC", (lp_restrict_anonymous() < 2));
3089                 lp_add_hidden("ADMIN$", "DISK", False);
3090         }
3091
3092         set_server_role();
3093         set_default_server_announce_type();
3094
3095         bLoaded = True;
3096
3097         /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
3098         /* if bWINSsupport is true and we are in the client            */
3099         if (in_client && Globals.bWINSsupport) {
3100                 lp_do_parameter(-1, "wins server", "127.0.0.1");
3101         }
3102
3103         init_iconv();
3104
3105         return (bRetval);
3106 }
3107
3108 /***************************************************************************
3109  Reset the max number of services.
3110 ***************************************************************************/
3111
3112 void lp_resetnumservices(void)
3113 {
3114         iNumServices = 0;
3115 }
3116
3117 /***************************************************************************
3118  Return the max number of services.
3119 ***************************************************************************/
3120
3121 int lp_numservices(void)
3122 {
3123         return (iNumServices);
3124 }
3125
3126 /***************************************************************************
3127 Display the contents of the services array in human-readable form.
3128 ***************************************************************************/
3129
3130 void lp_dump(FILE *f, BOOL show_defaults, int maxtoprint)
3131 {
3132         int iService;
3133
3134         if (show_defaults)
3135                 defaults_saved = False;
3136
3137         dump_globals(f);
3138
3139         dump_a_service(&sDefault, f);
3140
3141         for (iService = 0; iService < maxtoprint; iService++)
3142                 lp_dump_one(f, show_defaults, iService);
3143 }
3144
3145 /***************************************************************************
3146 Display the contents of one service in human-readable form.
3147 ***************************************************************************/
3148
3149 void lp_dump_one(FILE * f, BOOL show_defaults, int snum)
3150 {
3151         if (VALID(snum)) {
3152                 if (ServicePtrs[snum]->szService[0] == '\0')
3153                         return;
3154                 dump_a_service(ServicePtrs[snum], f);
3155         }
3156 }
3157
3158 /***************************************************************************
3159 Return the number of the service with the given name, or -1 if it doesn't
3160 exist. Note that this is a DIFFERENT ANIMAL from the internal function
3161 getservicebyname()! This works ONLY if all services have been loaded, and
3162 does not copy the found service.
3163 ***************************************************************************/
3164
3165 int lp_servicenumber(const char *pszServiceName)
3166 {
3167         int iService;
3168         fstring serviceName;
3169  
3170  
3171         for (iService = iNumServices - 1; iService >= 0; iService--) {
3172                 if (VALID(iService) && ServicePtrs[iService]->szService) {
3173                         /*
3174                          * The substitution here is used to support %U is
3175                          * service names
3176                          */
3177                         fstrcpy(serviceName, ServicePtrs[iService]->szService);
3178                         standard_sub_basic(serviceName,sizeof(serviceName));
3179                         if (strequal(serviceName, pszServiceName))
3180                                 break;
3181                 }
3182         }
3183
3184         if (iService < 0)
3185                 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
3186
3187         return (iService);
3188 }
3189
3190 /*******************************************************************
3191  A useful volume label function. 
3192 ********************************************************************/
3193 const char *volume_label(int snum)
3194 {
3195         const char *ret = lp_volume(snum);
3196         if (!*ret)
3197                 return lp_servicename(snum);
3198         return (ret);
3199 }
3200
3201
3202 /*******************************************************************
3203  Set the server type we will announce as via nmbd.
3204 ********************************************************************/
3205
3206 static void set_default_server_announce_type(void)
3207 {
3208         default_server_announce = 0;
3209         default_server_announce |= SV_TYPE_WORKSTATION;
3210         default_server_announce |= SV_TYPE_SERVER;
3211         default_server_announce |= SV_TYPE_SERVER_UNIX;
3212
3213         switch (lp_announce_as()) {
3214                 case ANNOUNCE_AS_NT_SERVER:
3215                         default_server_announce |= SV_TYPE_SERVER_NT;
3216                         /* fall through... */
3217                 case ANNOUNCE_AS_NT_WORKSTATION:
3218                         default_server_announce |= SV_TYPE_NT;
3219                         break;
3220                 case ANNOUNCE_AS_WIN95:
3221                         default_server_announce |= SV_TYPE_WIN95_PLUS;
3222                         break;
3223                 case ANNOUNCE_AS_WFW:
3224                         default_server_announce |= SV_TYPE_WFW;
3225                         break;
3226                 default:
3227                         break;
3228         }
3229
3230         switch (lp_server_role()) {
3231                 case ROLE_DOMAIN_MEMBER:
3232                         default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
3233                         break;
3234                 case ROLE_DOMAIN_PDC:
3235                         default_server_announce |= SV_TYPE_DOMAIN_CTRL;
3236                         break;
3237                 case ROLE_DOMAIN_BDC:
3238                         default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
3239                         break;
3240                 case ROLE_STANDALONE:
3241                 default:
3242                         break;
3243         }
3244         if (lp_time_server())
3245                 default_server_announce |= SV_TYPE_TIME_SOURCE;
3246
3247         if (lp_host_msdfs())
3248                 default_server_announce |= SV_TYPE_DFS_SERVER;
3249
3250         /* TODO: only announce us as print server when we are a print server */
3251         default_server_announce |= SV_TYPE_PRINTQ_SERVER;
3252 }
3253
3254 /***********************************************************
3255  returns role of Samba server
3256 ************************************************************/
3257
3258 int lp_server_role(void)
3259 {
3260         return server_role;
3261 }
3262
3263 /***********************************************************
3264  If we are PDC then prefer us as DMB
3265 ************************************************************/
3266
3267 BOOL lp_domain_master(void)
3268 {
3269         if (Globals.bDomainMaster == Auto)
3270                 return (lp_server_role() == ROLE_DOMAIN_PDC);
3271
3272         return Globals.bDomainMaster;
3273 }
3274
3275 /***********************************************************
3276  If we are DMB then prefer us as LMB
3277 ************************************************************/
3278
3279 BOOL lp_preferred_master(void)
3280 {
3281         if (Globals.bPreferredMaster == Auto)
3282                 return (lp_local_master() && lp_domain_master());
3283
3284         return Globals.bPreferredMaster;
3285 }
3286
3287 /*******************************************************************
3288  Remove a service.
3289 ********************************************************************/
3290
3291 void lp_remove_service(int snum)
3292 {
3293         ServicePtrs[snum]->valid = False;
3294 }
3295
3296 /*******************************************************************
3297  Copy a service.
3298 ********************************************************************/
3299
3300 void lp_copy_service(int snum, const char *new_name)
3301 {
3302         const char *oldname = lp_servicename(snum);
3303         do_section(new_name);
3304         if (snum >= 0) {
3305                 snum = lp_servicenumber(new_name);
3306                 if (snum >= 0)
3307                         lp_do_parameter(snum, "copy", oldname);
3308         }
3309 }
3310
3311
3312 /*******************************************************************
3313  Get the default server type we will announce as via nmbd.
3314 ********************************************************************/
3315 int lp_default_server_announce(void)
3316 {
3317         return default_server_announce;
3318 }
3319
3320 const char *lp_printername(int snum)
3321 {
3322         const char *ret = _lp_printername(snum);
3323         if (ret == NULL || (ret != NULL && *ret == '\0'))
3324                 ret = lp_const_servicename(snum);
3325
3326         return ret;
3327 }
3328
3329
3330 /*******************************************************************
3331  Return the max print jobs per queue.
3332 ********************************************************************/
3333
3334 int lp_maxprintjobs(int snum)
3335 {
3336         int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
3337         if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
3338                 maxjobs = PRINT_MAX_JOBID - 1;
3339
3340         return maxjobs;
3341 }