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