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