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