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