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