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