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