r7912: make private_path() recognise a non-relative filename, so we can have
[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 #include "param/loadparm.h"
67
68 BOOL in_client = False;         /* Not in the client by default */
69 static BOOL bLoaded = False;
70
71 #ifndef GLOBAL_NAME
72 #define GLOBAL_NAME "global"
73 #endif
74
75 #ifndef PRINTERS_NAME
76 #define PRINTERS_NAME "printers"
77 #endif
78
79 #ifndef HOMES_NAME
80 #define HOMES_NAME "homes"
81 #endif
82
83 /* some helpful bits */
84 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && ServicePtrs[(i)]->valid)
85 #define VALID(i) ServicePtrs[i]->valid
86
87 static BOOL do_parameter(const char *, const char *);
88 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...);
89
90 static BOOL defaults_saved = False;
91
92
93 #define FLAG_BASIC      0x0001 /* fundamental options */
94 #define FLAG_SHARE      0x0002 /* file sharing options */
95 #define FLAG_PRINT      0x0004 /* printing options */
96 #define FLAG_GLOBAL     0x0008 /* local options that should be globally settable in SWAT */
97 #define FLAG_WIZARD     0x0010 /* Parameters that the wizard will operate on */
98 #define FLAG_ADVANCED   0x0020 /* Parameters that the wizard will operate on */
99 #define FLAG_DEVELOPER  0x0040 /* Parameters that the wizard will operate on */
100 #define FLAG_DEPRECATED 0x1000 /* options that should no longer be used */
101 #define FLAG_HIDE       0x2000 /* options that should be hidden in SWAT */
102 #define FLAG_DOS_STRING 0x4000 /* convert from UNIX to DOS codepage when reading this string. */
103 #define FLAG_CMDLINE    0x8000 /* this option was set from the command line */
104
105
106
107
108 struct param_opt {
109         struct param_opt *prev, *next;
110         char *key;
111         char *value;
112         int flags;
113 };
114
115 /* 
116  * This structure describes global (ie., server-wide) parameters.
117  */
118 typedef struct
119 {
120         char **smb_ports;
121         char *dos_charset;
122         char *unix_charset;
123         char *ncalrpc_dir;
124         char *display_charset;
125         char *szPrintcapname;
126         char *szLockDir;
127         char *szPidDir;
128         char *szRootdir;
129         char *szDefaultService;
130         char *szHostsEquiv;
131         char *szServerString;
132         char *szAutoServices;
133         char *szPasswdProgram;
134         char *szPasswdChat;
135         char *szLogFile;
136         char *szConfigFile;
137         char *szSMBPasswdFile;
138         char *szSAM_URL;
139         char *szSPOOLSS_URL;
140         char *szWINS_URL;
141         char *szPrivateDir;
142         char **szPreloadModules;
143         char **szPasswordServers;
144         char *szSocketOptions;
145         char *szRealm;
146         char *szADSserver;
147         char *szLogonScript;
148         char *szLogonPath;
149         char *szLogonDrive;
150         char *szLogonHome;
151         char **szWINSservers;
152         char **szInterfaces;
153         char *szRemoteAnnounce;
154         char *szRemoteBrowseSync;
155         char *szSocketAddress;
156         char *szAnnounceVersion;        /* This is initialised in init_globals */
157         char *szWorkgroup;
158         char *szNetbiosName;
159         char **szNetbiosAliases;
160         char *szNetbiosScope;
161         char *szDomainOtherSIDs;
162         char **szNameResolveOrder;
163         char *szPanicAction;
164         char *szAddUserScript; 
165         char *szAddMachineScript;
166         char *szWINSHook;
167         char *szWINSPartners;
168         char **dcerpc_ep_servers;
169         char **server_services;
170         char *ntptr_providor;
171         char *szWinbindUID;
172         char *szWinbindGID;
173         char *szNonUnixAccountRange;
174         char *szTemplateHomedir;
175         char *szTemplateShell;
176         char *szWinbindSeparator;
177         BOOL bWinbindEnumUsers;
178         BOOL bWinbindEnumGroups;
179         BOOL bWinbindUseDefaultDomain;
180         char *szIDMapBackend;
181         char *szGuestaccount;
182         char *swat_directory;
183         BOOL tls_enabled;
184         char *tls_keyfile;
185         char *tls_certfile;
186         char *tls_cafile;
187         char *tls_crlfile;
188         int max_mux;
189         int max_xmit;
190         int pwordlevel;
191         int unamelevel;
192         int maxprotocol;
193         int minprotocol;
194         int security;
195         char **AuthMethods;
196         BOOL paranoid_server_security;
197         int lpqcachetime;
198         BOOL bDisableSpoolss;
199         int os_level;
200         int enhanced_browsing;
201         int time_offset;
202         int max_ttl;
203         int max_wins_ttl;
204         int min_wins_ttl;
205         int lm_announce;
206         int lm_interval;
207         int announce_as;        /* This is initialised in init_globals */
208         int machine_password_timeout;
209         int winbind_cache_time;
210         int iLockSpinCount;
211         int iLockSpinTime;
212         int nbt_port;
213         int dgram_port;
214         int cldap_port;
215         int krb5_port;
216         int web_port;
217         char *socket_options;
218         BOOL bDNSproxy;
219         BOOL bWINSsupport;
220         BOOL bWINSproxy;
221         BOOL bLocalMaster;
222         BOOL bPreferredMaster;
223         BOOL bDomainMaster;
224         BOOL bDomainLogons;
225         BOOL bEncryptPasswords;
226         BOOL bNullPasswords;
227         BOOL bObeyPamRestrictions;
228         BOOL bLoadPrinters;
229         BOOL bLargeReadwrite;
230         BOOL bReadRaw;
231         BOOL bWriteRaw;
232         BOOL bTimeServer;
233         BOOL bBindInterfacesOnly;
234         BOOL bPamPasswordChange;
235         BOOL bNTSmbSupport;
236         BOOL bNTStatusSupport;
237         BOOL bAllowTrustedDomains;
238         BOOL bPlaintextAuth;
239         BOOL bLanmanAuth;
240         BOOL bNTLMAuth;
241         BOOL bUseSpnego;
242         int  server_signing;
243         int  client_signing;
244         BOOL bClientPlaintextAuth;
245         BOOL bClientLanManAuth;
246         BOOL bClientNTLMv2Auth;
247         BOOL bHostMSDfs;
248         BOOL bHideLocalUsers;
249         BOOL bUnicode;
250         BOOL bUseMmap;
251         BOOL bHostnameLookups;
252         BOOL bUnixExtensions;
253         BOOL bDisableNetbios;
254         BOOL bRpcBigEndian;
255         int restrict_anonymous;
256         int name_cache_timeout;
257         struct param_opt *param_opt;
258 }
259 global;
260
261 static global Globals;
262
263 /* 
264  * This structure describes a single service. 
265  */
266 typedef struct
267 {
268         BOOL valid;
269         BOOL autoloaded;
270         char *szService;
271         char *szPath;
272         char *szUsername;
273         char **szInvalidUsers;
274         char **szValidUsers;
275         char **szAdminUsers;
276         char *szCopy;
277         char *szInclude;
278         char *szPrintcommand;
279         char *szLpqcommand;
280         char *szLprmcommand;
281         char *szLppausecommand;
282         char *szLpresumecommand;
283         char *szQueuepausecommand;
284         char *szQueueresumecommand;
285         char *szPrintername;
286         char **szHostsallow;
287         char **szHostsdeny;
288         char *comment;
289         char *volume;
290         char *fstype;
291         char *szMSDfsProxy;
292         char **ntvfs_handler;
293         int iMinPrintSpace;
294         int iMaxPrintJobs;
295         int iMaxConnections;
296         int iPrinting;
297         int iCSCPolicy;
298         BOOL bAvailable;
299         BOOL bBrowseable;
300         BOOL bRead_only;
301         BOOL bPrint_ok;
302         BOOL bMap_system;
303         BOOL bMap_hidden;
304         BOOL bMap_archive;
305         BOOL bLocking;
306         BOOL bStrictLocking;
307         BOOL bPosixLocking;
308         BOOL bOpLocks;
309         BOOL bLevel2OpLocks;
310         BOOL bOnlyUser;
311         BOOL bGuest_only;
312         BOOL bGuest_ok;
313         BOOL *copymap;
314         BOOL bMSDfsRoot;
315         BOOL bShareModes;
316         BOOL bStrictSync;
317         BOOL bCIFileSystem;
318         struct param_opt *param_opt;
319
320         char dummy[3];          /* for alignment */
321 }
322 service;
323
324
325 /* This is a default service used to prime a services structure */
326 static service sDefault = {
327         True,                   /* valid */
328         False,                  /* not autoloaded */
329         NULL,                   /* szService */
330         NULL,                   /* szPath */
331         NULL,                   /* szUsername */
332         NULL,                   /* szInvalidUsers */
333         NULL,                   /* szValidUsers */
334         NULL,                   /* szAdminUsers */
335         NULL,                   /* szCopy */
336         NULL,                   /* szInclude */
337         NULL,                   /* szPrintcommand */
338         NULL,                   /* szLpqcommand */
339         NULL,                   /* szLprmcommand */
340         NULL,                   /* szLppausecommand */
341         NULL,                   /* szLpresumecommand */
342         NULL,                   /* szQueuepausecommand */
343         NULL,                   /* szQueueresumecommand */
344         NULL,                   /* szPrintername */
345         NULL,                   /* szHostsallow */
346         NULL,                   /* szHostsdeny */
347         NULL,                   /* comment */
348         NULL,                   /* volume */
349         NULL,                   /* fstype */
350         NULL,                   /* szMSDfsProxy */
351         NULL,                   /* ntvfs_handler */
352         0,                      /* iMinPrintSpace */
353         1000,                   /* iMaxPrintJobs */
354         0,                      /* iMaxConnections */
355         DEFAULT_PRINTING,       /* iPrinting */
356         0,                      /* iCSCPolicy */
357         True,                   /* bAvailable */
358         True,                   /* bBrowseable */
359         True,                   /* bRead_only */
360         False,                  /* bPrint_ok */
361         False,                  /* bMap_system */
362         False,                  /* bMap_hidden */
363         True,                   /* bMap_archive */
364         True,                   /* bLocking */
365         True,                   /* bStrictLocking */
366         True,                   /* bPosixLocking */
367         True,                   /* bOpLocks */
368         True,                   /* bLevel2OpLocks */
369         False,                  /* bOnlyUser */
370         False,                  /* bGuest_only */
371         False,                  /* bGuest_ok */
372         NULL,                   /* copymap */
373         False,                  /* bMSDfsRoot */
374         True,                   /* bShareModes */
375         False,                  /* bStrictSync */
376         False,                  /* bCIFileSystem */
377         NULL,                   /* Parametric options */
378
379         ""                      /* dummy */
380 };
381
382 /* local variables */
383 static service **ServicePtrs = NULL;
384 static int iNumServices = 0;
385 static int iServiceIndex = 0;
386 static BOOL bInGlobalSection = True;
387 static int server_role;
388 static int default_server_announce;
389
390 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
391
392 /* prototypes for the special type handlers */
393 static BOOL handle_include(const char *pszParmValue, char **ptr);
394 static BOOL handle_copy(const char *pszParmValue, char **ptr);
395 static BOOL handle_winbind_uid(const char *pszParmValue, char **ptr);
396 static BOOL handle_winbind_gid(const char *pszParmValue, char **ptr);
397 static BOOL handle_non_unix_account_range(const char *pszParmValue, char **ptr);
398
399 static void set_server_role(void);
400 static void set_default_server_announce_type(void);
401
402 static const struct enum_list enum_protocol[] = {
403         {PROTOCOL_NT1, "NT1"},
404         {PROTOCOL_LANMAN2, "LANMAN2"},
405         {PROTOCOL_LANMAN1, "LANMAN1"},
406         {PROTOCOL_CORE, "CORE"},
407         {PROTOCOL_COREPLUS, "COREPLUS"},
408         {PROTOCOL_COREPLUS, "CORE+"},
409         {-1, NULL}
410 };
411
412 static const struct enum_list enum_security[] = {
413         {SEC_SHARE, "SHARE"},
414         {SEC_USER, "USER"},
415         {SEC_SERVER, "SERVER"},
416         {SEC_DOMAIN, "DOMAIN"},
417 #ifdef HAVE_ADS
418         {SEC_ADS, "ADS"},
419 #endif
420         {-1, NULL}
421 };
422
423 static const struct enum_list enum_printing[] = {
424         {PRINT_SYSV, "sysv"},
425         {PRINT_AIX, "aix"},
426         {PRINT_HPUX, "hpux"},
427         {PRINT_BSD, "bsd"},
428         {PRINT_QNX, "qnx"},
429         {PRINT_PLP, "plp"},
430         {PRINT_LPRNG, "lprng"},
431         {PRINT_SOFTQ, "softq"},
432         {PRINT_CUPS, "cups"},
433         {PRINT_LPRNT, "nt"},
434         {PRINT_LPROS2, "os2"},
435 #ifdef DEVELOPER
436         {PRINT_TEST, "test"},
437         {PRINT_VLP, "vlp"},
438 #endif /* DEVELOPER */
439         {-1, NULL}
440 };
441
442 /* Types of machine we can announce as. */
443 #define ANNOUNCE_AS_NT_SERVER 1
444 #define ANNOUNCE_AS_WIN95 2
445 #define ANNOUNCE_AS_WFW 3
446 #define ANNOUNCE_AS_NT_WORKSTATION 4
447
448 static const struct enum_list enum_announce_as[] = {
449         {ANNOUNCE_AS_NT_SERVER, "NT"},
450         {ANNOUNCE_AS_NT_SERVER, "NT Server"},
451         {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"},
452         {ANNOUNCE_AS_WIN95, "win95"},
453         {ANNOUNCE_AS_WFW, "WfW"},
454         {-1, NULL}
455 };
456
457 static const struct enum_list enum_bool_auto[] = {
458         {False, "No"},
459         {False, "False"},
460         {False, "0"},
461         {True, "Yes"},
462         {True, "True"},
463         {True, "1"},
464         {Auto, "Auto"},
465         {-1, NULL}
466 };
467
468 /* Client-side offline caching policy types */
469 #define CSC_POLICY_MANUAL 0
470 #define CSC_POLICY_DOCUMENTS 1
471 #define CSC_POLICY_PROGRAMS 2
472 #define CSC_POLICY_DISABLE 3
473
474 static const struct enum_list enum_csc_policy[] = {
475         {CSC_POLICY_MANUAL, "manual"},
476         {CSC_POLICY_DOCUMENTS, "documents"},
477         {CSC_POLICY_PROGRAMS, "programs"},
478         {CSC_POLICY_DISABLE, "disable"},
479         {-1, NULL}
480 };
481
482 /* SMB signing types. */
483 static const struct enum_list enum_smb_signing_vals[] = {
484         {SMB_SIGNING_OFF, "No"},
485         {SMB_SIGNING_OFF, "False"},
486         {SMB_SIGNING_OFF, "0"},
487         {SMB_SIGNING_OFF, "Off"},
488         {SMB_SIGNING_OFF, "disabled"},
489         {SMB_SIGNING_SUPPORTED, "Yes"},
490         {SMB_SIGNING_SUPPORTED, "True"},
491         {SMB_SIGNING_SUPPORTED, "1"},
492         {SMB_SIGNING_SUPPORTED, "On"},
493         {SMB_SIGNING_SUPPORTED, "enabled"},
494         {SMB_SIGNING_REQUIRED, "required"},
495         {SMB_SIGNING_REQUIRED, "mandatory"},
496         {SMB_SIGNING_REQUIRED, "force"},
497         {SMB_SIGNING_REQUIRED, "forced"},
498         {SMB_SIGNING_REQUIRED, "enforced"},
499         {SMB_SIGNING_AUTO, "auto"},
500         {-1, NULL}
501 };
502
503
504 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
505  *
506  * Note: We have a flag called FLAG_DEVELOPER but is not used at this time, it
507  * is implied in current control logic. This may change at some later time. A
508  * flag value of 0 means - show as development option only.
509  *
510  * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
511  * screen in SWAT. This is used to exclude parameters as well as to squash all
512  * parameters that have been duplicated by pseudonyms.
513  */
514 static struct parm_struct parm_table[] = {
515         {"Base Options", P_SEP, P_SEPARATOR},
516
517         {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
518         {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
519         {"ncalrpc dir", P_STRING, P_GLOBAL, &Globals.ncalrpc_dir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
520         {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
521         {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
522         {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
523         {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE},
524         {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkgroup, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
525         {"realm", P_STRING, P_GLOBAL, &Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
526         {"ADS server", P_STRING, P_GLOBAL, &Globals.szADSserver, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
527         {"netbios name", P_USTRING, P_GLOBAL, &Globals.szNetbiosName, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
528         {"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
529         {"netbios scope", P_USTRING, P_GLOBAL, &Globals.szNetbiosScope, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
530         {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED  | FLAG_DEVELOPER},
531         {"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
532         {"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
533         {"ntvfs handler", P_LIST, P_LOCAL, &sDefault.ntvfs_handler, NULL, NULL, FLAG_ADVANCED},
534         {"ntptr providor", P_STRING, P_GLOBAL, &Globals.ntptr_providor, NULL, NULL, FLAG_ADVANCED},
535         {"dcerpc endpoint servers", P_LIST, P_GLOBAL, &Globals.dcerpc_ep_servers, NULL, NULL, FLAG_ADVANCED},
536         {"server services", P_LIST, P_GLOBAL, &Globals.server_services, NULL, NULL, FLAG_ADVANCED},
537
538         {"Security Options", P_SEP, P_SEPARATOR},
539         
540         {"security", P_ENUM, P_GLOBAL, &Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
541         {"auth methods", P_LIST, P_GLOBAL, &Globals.AuthMethods, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
542         {"encrypt passwords", P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
543         {"allow trusted domains", P_BOOL, P_GLOBAL, &Globals.bAllowTrustedDomains, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
544         {"hosts equiv", P_STRING, P_GLOBAL, &Globals.szHostsEquiv, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
545         {"idmap backend", P_STRING, P_GLOBAL, &Globals.szIDMapBackend, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
546         {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
547         {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
548         {"password server", P_LIST, P_GLOBAL, &Globals.szPasswordServers, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
549         {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
550         {"sam database", P_STRING, P_GLOBAL, &Globals.szSAM_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
551         {"spoolss database", P_STRING, P_GLOBAL, &Globals.szSPOOLSS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
552         {"wins database", P_STRING, P_GLOBAL, &Globals.szWINS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
553         {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
554         {"non unix account range", P_STRING, P_GLOBAL, &Globals.szNonUnixAccountRange, handle_non_unix_account_range, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
555         {"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
556         {"root dir", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
557         {"root", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_HIDE | FLAG_DEVELOPER},
558         {"guest account", P_STRING, P_GLOBAL, &Globals.szGuestaccount, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
559         
560         {"pam password change", P_BOOL, P_GLOBAL, &Globals.bPamPasswordChange, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
561         {"passwd program", P_STRING, P_GLOBAL, &Globals.szPasswdProgram, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
562         {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
563         {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
564         {"username level", P_INTEGER, P_GLOBAL, &Globals.unamelevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
565         {"restrict anonymous", P_INTEGER, P_GLOBAL, &Globals.restrict_anonymous, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
566         {"plaintext auth", P_BOOL, P_GLOBAL, &Globals.bPlaintextAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
567         {"lanman auth", P_BOOL, P_GLOBAL, &Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
568         {"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
569         {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
570         {"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
571         {"client plaintext auth", P_BOOL, P_GLOBAL, &Globals.bClientPlaintextAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
572         
573         {"username", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
574         {"user", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_HIDE},
575         {"users", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_HIDE},
576         
577         {"invalid users", P_LIST, P_LOCAL, &sDefault.szInvalidUsers, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
578         {"valid users", P_LIST, P_LOCAL, &sDefault.szValidUsers, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
579         {"admin users", P_LIST, P_LOCAL, &sDefault.szAdminUsers, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
580         
581         {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE},
582
583         {"guest only", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL, NULL, FLAG_SHARE},
584
585         {"guest ok", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
586
587         {"only user", P_BOOL, P_LOCAL, &sDefault.bOnlyUser, NULL, NULL, FLAG_SHARE},
588         {"hosts allow", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
589         {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
590         {"preload modules", P_LIST, P_GLOBAL, &Globals.szPreloadModules, NULL, NULL, FLAG_BASIC | FLAG_GLOBAL},
591
592         {"Logging Options", P_SEP, P_SEPARATOR},
593
594         {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
595         {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_HIDE},
596         {"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
597         
598         {"Protocol Options", P_SEP, P_SEPARATOR},
599         
600         {"smb ports", P_LIST, P_GLOBAL, &Globals.smb_ports, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
601         {"nbt port", P_INTEGER, P_GLOBAL, &Globals.nbt_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
602         {"dgram port", P_INTEGER, P_GLOBAL, &Globals.dgram_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
603         {"cldap port", P_INTEGER, P_GLOBAL, &Globals.cldap_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
604         {"krb5 port", P_INTEGER, P_GLOBAL, &Globals.krb5_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
605         {"web port", P_INTEGER, P_GLOBAL, &Globals.web_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
606         {"tls enabled", P_BOOL, P_GLOBAL, &Globals.tls_enabled, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
607         {"tls keyfile", P_STRING, P_GLOBAL, &Globals.tls_keyfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
608         {"tls certfile", P_STRING, P_GLOBAL, &Globals.tls_certfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
609         {"tls cafile", P_STRING, P_GLOBAL, &Globals.tls_cafile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
610         {"tls crlfile", P_STRING, P_GLOBAL, &Globals.tls_crlfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
611         {"swat directory", P_STRING, P_GLOBAL, &Globals.swat_directory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
612         {"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, FLAG_DEVELOPER},
613         {"max protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
614         {"min protocol", P_ENUM, P_GLOBAL, &Globals.minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
615         {"unicode", P_BOOL, P_GLOBAL, &Globals.bUnicode, NULL, NULL, FLAG_DEVELOPER},
616         {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL, NULL, FLAG_DEVELOPER},
617         {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL, NULL, FLAG_DEVELOPER},
618         {"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
619         
620         {"nt status support", P_BOOL, P_GLOBAL, &Globals.bNTStatusSupport, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
621
622         {"announce version", P_STRING, P_GLOBAL, &Globals.szAnnounceVersion, NULL, NULL, FLAG_DEVELOPER},
623         {"announce as", P_ENUM, P_GLOBAL, &Globals.announce_as, NULL, enum_announce_as, FLAG_DEVELOPER},
624         {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
625         {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
626
627         {"name resolve order", P_LIST, P_GLOBAL, &Globals.szNameResolveOrder, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
628         {"max ttl", P_INTEGER, P_GLOBAL, &Globals.max_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, 
629         {"max wins ttl", P_INTEGER, P_GLOBAL, &Globals.max_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
630         {"min wins ttl", P_INTEGER, P_GLOBAL, &Globals.min_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
631         {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
632         {"unix extensions", P_BOOL, P_GLOBAL, &Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
633         {"use spnego", P_BOOL, P_GLOBAL, &Globals.bUseSpnego, NULL, NULL, FLAG_DEVELOPER},
634         {"server signing", P_ENUM, P_GLOBAL, &Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED}, 
635         {"client signing", P_ENUM, P_GLOBAL, &Globals.client_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED}, 
636         {"rpc big endian", P_BOOL, P_GLOBAL, &Globals.bRpcBigEndian, NULL, NULL, FLAG_DEVELOPER},
637
638         {"Tuning Options", P_SEP, P_SEPARATOR},
639                 
640         {"lpq cache time", P_INTEGER, P_GLOBAL, &Globals.lpqcachetime, NULL, NULL, FLAG_DEVELOPER},
641         {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL, NULL, FLAG_SHARE},
642         {"paranoid server security", P_BOOL, P_GLOBAL, &Globals.paranoid_server_security, NULL, NULL, FLAG_DEVELOPER},
643         {"min print space", P_INTEGER, P_LOCAL, &sDefault.iMinPrintSpace, NULL, NULL, FLAG_PRINT},
644         
645         {"socket options", P_STRING, P_GLOBAL, &Globals.socket_options, NULL, NULL, FLAG_DEVELOPER},
646         {"use mmap", P_BOOL, P_GLOBAL, &Globals.bUseMmap, NULL, NULL, FLAG_DEVELOPER},
647         {"hostname lookups", P_BOOL, P_GLOBAL, &Globals.bHostnameLookups, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
648
649         {"name cache timeout", P_INTEGER, P_GLOBAL, &Globals.name_cache_timeout, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
650         {"strict sync", P_BOOL, P_LOCAL, &sDefault.bStrictSync, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
651         {"case insensitive filesystem", P_BOOL, P_LOCAL, &sDefault.bCIFileSystem, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
652
653         {"Printing Options", P_SEP, P_SEPARATOR},
654         
655         {"max print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxPrintJobs, NULL, NULL, FLAG_PRINT},
656         {"load printers", P_BOOL, P_GLOBAL, &Globals.bLoadPrinters, NULL, NULL, FLAG_PRINT},
657         {"printcap name", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL, NULL, FLAG_PRINT | FLAG_DEVELOPER},
658         {"printcap", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL, NULL, FLAG_HIDE},
659         {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_PRINT},
660         {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_HIDE},
661         {"printing", P_ENUM, P_LOCAL, &sDefault.iPrinting, NULL, enum_printing, FLAG_PRINT | FLAG_GLOBAL},
662         {"print command", P_STRING, P_LOCAL, &sDefault.szPrintcommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
663         {"disable spoolss", P_BOOL, P_GLOBAL, &Globals.bDisableSpoolss, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
664         {"lpq command", P_STRING, P_LOCAL, &sDefault.szLpqcommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
665         {"lprm command", P_STRING, P_LOCAL, &sDefault.szLprmcommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
666         {"lppause command", P_STRING, P_LOCAL, &sDefault.szLppausecommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
667         {"lpresume command", P_STRING, P_LOCAL, &sDefault.szLpresumecommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
668         {"queuepause command", P_STRING, P_LOCAL, &sDefault.szQueuepausecommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
669         {"queueresume command", P_STRING, P_LOCAL, &sDefault.szQueueresumecommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
670         
671         {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_PRINT},
672         {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_HIDE},
673
674         {"Filename Handling", P_SEP, P_SEPARATOR},
675         
676         {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
677         {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
678         {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
679
680         {"Domain Options", P_SEP, P_SEPARATOR},
681         
682         {"machine password timeout", P_INTEGER, P_GLOBAL, &Globals.machine_password_timeout, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
683
684         {"Logon Options", P_SEP, P_SEPARATOR},
685
686         {"add user script", P_STRING, P_GLOBAL, &Globals.szAddUserScript, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
687         {"add machine script", P_STRING, P_GLOBAL, &Globals.szAddMachineScript, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
688
689         {"logon script", P_STRING, P_GLOBAL, &Globals.szLogonScript, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
690         {"logon path", P_STRING, P_GLOBAL, &Globals.szLogonPath, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
691         {"logon drive", P_STRING, P_GLOBAL, &Globals.szLogonDrive, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
692         {"logon home", P_STRING, P_GLOBAL, &Globals.szLogonHome, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
693         {"domain logons", P_BOOL, P_GLOBAL, &Globals.bDomainLogons, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
694
695         {"Browse Options", P_SEP, P_SEPARATOR},
696         
697         {"os level", P_INTEGER, P_GLOBAL, &Globals.os_level, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
698         {"lm announce", P_ENUM, P_GLOBAL, &Globals.lm_announce, NULL, enum_bool_auto, FLAG_ADVANCED | FLAG_DEVELOPER},
699         {"lm interval", P_INTEGER, P_GLOBAL, &Globals.lm_interval, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
700         {"preferred master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
701         {"prefered master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_HIDE},
702         {"local master", P_BOOL, P_GLOBAL, &Globals.bLocalMaster, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
703         {"domain master", P_ENUM, P_GLOBAL, &Globals.bDomainMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
704         {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
705         {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_HIDE},
706         {"enhanced browsing", P_BOOL, P_GLOBAL, &Globals.enhanced_browsing, NULL, NULL, FLAG_DEVELOPER | FLAG_ADVANCED},
707
708         {"WINS Options", P_SEP, P_SEPARATOR},
709         {"dns proxy", P_BOOL, P_GLOBAL, &Globals.bDNSproxy, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
710         {"wins proxy", P_BOOL, P_GLOBAL, &Globals.bWINSproxy, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
711         
712         {"wins server", P_LIST, P_GLOBAL, &Globals.szWINSservers, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
713         {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
714         {"wins hook", P_STRING, P_GLOBAL, &Globals.szWINSHook, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
715         {"wins partners", P_STRING, P_GLOBAL, &Globals.szWINSPartners, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
716
717         {"Locking Options", P_SEP, P_SEPARATOR},
718         
719         {"csc policy", P_ENUM, P_LOCAL, &sDefault.iCSCPolicy, NULL, enum_csc_policy, FLAG_SHARE | FLAG_GLOBAL},
720         {"locking", P_BOOL, P_LOCAL, &sDefault.bLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
721         {"lock spin count", P_INTEGER, P_GLOBAL, &Globals.iLockSpinCount, NULL, NULL, FLAG_GLOBAL},
722         {"lock spin time", P_INTEGER, P_GLOBAL, &Globals.iLockSpinTime, NULL, NULL, FLAG_GLOBAL},
723         
724         {"oplocks", P_BOOL, P_LOCAL, &sDefault.bOpLocks, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
725         {"level2 oplocks", P_BOOL, P_LOCAL, &sDefault.bLevel2OpLocks, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
726         {"posix locking", P_BOOL, P_LOCAL, &sDefault.bPosixLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
727         {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
728         {"share modes", P_BOOL, P_LOCAL,  &sDefault.bShareModes, NULL, NULL, FLAG_SHARE|FLAG_GLOBAL},
729
730         {"Miscellaneous Options", P_SEP, P_SEPARATOR},
731         
732         {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE},
733         {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
734         {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
735         {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_HIDE}, 
736         {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
737         {"pid directory", P_STRING, P_GLOBAL, &Globals.szPidDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, 
738         
739         {"default service", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
740         {"default", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL, NULL,  FLAG_DEVELOPER},
741         {"remote announce", P_STRING, P_GLOBAL, &Globals.szRemoteAnnounce, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
742         {"remote browse sync", P_STRING, P_GLOBAL, &Globals.szRemoteBrowseSync, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
743         {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL, NULL, FLAG_DEVELOPER},
744         {"time offset", P_INTEGER, P_GLOBAL, &Globals.time_offset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
745         {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL, NULL, FLAG_HIDE},
746         
747         {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy, NULL, FLAG_HIDE},
748         {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include, NULL, FLAG_HIDE},
749         
750         {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
751         {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_SHARE },
752         {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_SHARE},
753
754         {"panic action", P_STRING, P_GLOBAL, &Globals.szPanicAction, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
755         {"hide local users", P_BOOL, P_GLOBAL, &Globals.bHideLocalUsers, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
756
757         {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_SHARE},
758         {"msdfs proxy", P_STRING, P_LOCAL, &sDefault.szMSDfsProxy, NULL, NULL, FLAG_SHARE},
759         {"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
760         {"Winbind options", P_SEP, P_SEPARATOR},
761
762         {"winbind uid", P_STRING, P_GLOBAL, &Globals.szWinbindUID, handle_winbind_uid, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
763         {"winbind gid", P_STRING, P_GLOBAL, &Globals.szWinbindGID, handle_winbind_gid, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
764         {"template homedir", P_STRING, P_GLOBAL, &Globals.szTemplateHomedir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
765         {"template shell", P_STRING, P_GLOBAL, &Globals.szTemplateShell, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
766         {"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
767         {"winbind cache time", P_INTEGER, P_GLOBAL, &Globals.winbind_cache_time, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
768         {"winbind enum users", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumUsers, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
769         {"winbind enum groups", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumGroups, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
770         {"winbind use default domain", P_BOOL, P_GLOBAL, &Globals.bWinbindUseDefaultDomain, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
771
772         {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
773 };
774
775 /***************************************************************************
776  Initialise the sDefault parameter structure for the printer values.
777 ***************************************************************************/
778
779 static void init_printer_values(void)
780 {
781         /* choose defaults depending on the type of printing */
782         switch (sDefault.iPrinting) {
783                 case PRINT_BSD:
784                 case PRINT_AIX:
785                 case PRINT_LPRNT:
786                 case PRINT_LPROS2:
787                         do_parameter("Lpqcommand", "lpq -P'%p'");
788                         do_parameter("Lprmcommand", "lprm -P'%p' %j");
789                         do_parameter("Printcommand",
790                                    "lpr -r -P'%p' %s");
791                         break;
792
793                 case PRINT_LPRNG:
794                 case PRINT_PLP:
795                         do_parameter("Lpqcommand", "lpq -P'%p'");
796                         do_parameter("Lprmcommand", "lprm -P'%p' %j");
797                         do_parameter("Printcommand",
798                                    "lpr -r -P'%p' %s");
799                         do_parameter("Queuepausecommand",
800                                    "lpc stop '%p'");
801                         do_parameter("Queueresumecommand",
802                                    "lpc start '%p'");
803                         do_parameter("Lppausecommand",
804                                    "lpc hold '%p' %j");
805                         do_parameter("Lpresumecommand",
806                                    "lpc release '%p' %j");
807                         break;
808
809                 case PRINT_CUPS:
810 #ifdef HAVE_CUPS
811                         do_parameter("Lpqcommand", "");
812                         do_parameter("Lprmcommand", "");
813                         do_parameter("Printcommand", "");
814                         do_parameter("Lppausecommand", "");
815                         do_parameter("Lpresumecommand", "");
816                         do_parameter("Queuepausecommand", "");
817                         do_parameter("Queueresumecommand", "");
818
819                         do_parameter("Printcapname", "cups");
820 #else
821                         do_parameter("Lpqcommand",
822                                    "/usr/bin/lpstat -o '%p'");
823                         do_parameter("Lprmcommand",
824                                    "/usr/bin/cancel '%p-%j'");
825                         do_parameter("Printcommand",
826                                    "/usr/bin/lp -d '%p' %s; rm %s");
827                         do_parameter("Lppausecommand",
828                                    "lp -i '%p-%j' -H hold");
829                         do_parameter("Lpresumecommand",
830                                    "lp -i '%p-%j' -H resume");
831                         do_parameter("Queuepausecommand",
832                                    "/usr/bin/disable '%p'");
833                         do_parameter("Queueresumecommand",
834                                    "/usr/bin/enable '%p'");
835                         do_parameter("Printcapname", "lpstat");
836 #endif /* HAVE_CUPS */
837                         break;
838
839                 case PRINT_SYSV:
840                 case PRINT_HPUX:
841                         do_parameter("Lpqcommand", "lpstat -o%p");
842                         do_parameter("Lprmcommand", "cancel %p-%j");
843                         do_parameter("Printcommand",
844                                    "lp -c -d%p %s; rm %s");
845                         do_parameter("Queuepausecommand",
846                                    "disable %p");
847                         do_parameter("Queueresumecommand",
848                                    "enable %p");
849 #ifndef HPUX
850                         do_parameter("Lppausecommand",
851                                    "lp -i %p-%j -H hold");
852                         do_parameter("Lpresumecommand",
853                                    "lp -i %p-%j -H resume");
854 #endif /* HPUX */
855                         break;
856
857                 case PRINT_QNX:
858                         do_parameter("Lpqcommand", "lpq -P%p");
859                         do_parameter("Lprmcommand", "lprm -P%p %j");
860                         do_parameter("Printcommand", "lp -r -P%p %s");
861                         break;
862
863                 case PRINT_SOFTQ:
864                         do_parameter("Lpqcommand", "qstat -l -d%p");
865                         do_parameter("Lprmcommand",
866                                    "qstat -s -j%j -c");
867                         do_parameter("Printcommand",
868                                    "lp -d%p -s %s; rm %s");
869                         do_parameter("Lppausecommand",
870                                    "qstat -s -j%j -h");
871                         do_parameter("Lpresumecommand",
872                                    "qstat -s -j%j -r");
873                         break;
874 #ifdef DEVELOPER
875         case PRINT_TEST:
876         case PRINT_VLP:
877                 do_parameter("Printcommand", "vlp print %p %s");
878                 do_parameter("Lpqcommand", "vlp lpq %p");
879                 do_parameter("Lprmcommand", "vlp lprm %p %j");
880                 do_parameter("Lppausecommand", "vlp lppause %p %j");
881                 do_parameter("Lpresumecommand", "vlp lpresum %p %j");
882                 do_parameter("Queuepausecommand", "vlp queuepause %p");
883                 do_parameter("Queueresumecommand", "vlp queueresume %p");
884                 break;
885 #endif /* DEVELOPER */
886
887         }
888 }
889
890
891 /***************************************************************************
892  Initialise the global parameter structure.
893 ***************************************************************************/
894 static void init_globals(void)
895 {
896         int i;
897         char *myname;
898
899         DEBUG(3, ("Initialising global parameters\n"));
900
901         for (i = 0; parm_table[i].label; i++) {
902                 if ((parm_table[i].type == P_STRING ||
903                      parm_table[i].type == P_USTRING) &&
904                     parm_table[i].ptr &&
905                     !(parm_table[i].flags & FLAG_CMDLINE)) {
906                         string_set(parm_table[i].ptr, "");
907                 }
908         }
909
910         /* options that can be set on the command line must be initialised via
911            the slower do_parameter() to ensure that FLAG_CMDLINE is obeyed */
912 #ifdef TCP_NODELAY
913         do_parameter("socket options", "TCP_NODELAY");
914 #endif
915         do_parameter("workgroup", DEFAULT_WORKGROUP);
916         myname = get_myname();
917         do_parameter("netbios name", myname);
918         SAFE_FREE(myname);
919         do_parameter("max protocol", "NT1");
920         do_parameter("name resolve order", "lmhosts wins host bcast");
921
922         init_printer_values();
923
924         do_parameter("fstype", FSTYPE_STRING);
925         do_parameter("ntvfs handler", "unixuid default");
926         do_parameter("max connections", "-1");
927
928         do_parameter("dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup");
929         do_parameter("server services", "smb rpc nbt ldap cldap web");
930         do_parameter("ntptr providor", "simple_ldb");
931         do_parameter("auth methods", "anonymous sam_ignoredomain");
932         do_parameter("smb passwd file", dyn_SMB_PASSWD_FILE);
933         do_parameter("private dir", dyn_PRIVATE_DIR);
934         do_parameter("sam database", "sam.ldb");
935         do_parameter("spoolss database", "spoolss.ldb");
936         do_parameter("wins database", "wins.ldb");
937         do_parameter("registry:HKEY_LOCAL_MACHINE", "hklm.ldb");
938         do_parameter("guest account", GUEST_ACCOUNT);
939
940         /* using UTF8 by default allows us to support all chars */
941         do_parameter("unix charset", "UTF8");
942
943         /* Use codepage 850 as a default for the dos character set */
944         do_parameter("dos charset", "CP850");
945
946         /*
947          * Allow the default PASSWD_CHAT to be overridden in local.h.
948          */
949         do_parameter("passwd chat", DEFAULT_PASSWD_CHAT);
950
951         do_parameter("passwd program", "");
952         do_parameter("printcap name", PRINTCAP_NAME);
953         
954         do_parameter("pid directory", dyn_PIDDIR);
955         do_parameter("lock dir", dyn_LOCKDIR);
956         do_parameter("ncalrpc dir", dyn_NCALRPCDIR);
957
958         do_parameter("socket address", "0.0.0.0");
959         do_parameter_var("server string", "Samba %s", SAMBA_VERSION_STRING);
960
961         do_parameter_var("announce version", "%d.%d", 
962                          DEFAULT_MAJOR_VERSION,
963                          DEFAULT_MINOR_VERSION);
964
965         do_parameter("logon drive", "");
966
967         do_parameter("logon home", "\\\\%N\\%U");
968         do_parameter("logon path", "\\\\%N\\%U\\profile");
969         do_parameter("password server", "*");
970
971         do_parameter("load printers", "True");
972
973         do_parameter("max mux", "50");
974         do_parameter("max xmit", "12288");
975         do_parameter("lpqcachetime", "10");
976         do_parameter("DisableSpoolss", "False");
977         do_parameter("password level", "0");
978         do_parameter("username level", "0");
979         do_parameter("LargeReadwrite", "True");
980         do_parameter("minprotocol", "CORE");
981         do_parameter("security", "USER");
982         do_parameter("paranoid server security", "True");
983         do_parameter("EncryptPasswords", "True");
984         do_parameter("ReadRaw", "True");
985         do_parameter("WriteRaw", "True");
986         do_parameter("NullPasswords", "False");
987         do_parameter("ObeyPamRestrictions", "False");
988         do_parameter("lm announce", "Auto");    
989         do_parameter("lm interval", "60");
990         do_parameter("announce as", "NT SERVER");
991
992         do_parameter("TimeServer", "False");
993         do_parameter("BindInterfacesOnly", "False");
994         do_parameter("PamPasswordChange", "False");
995         do_parameter("Unicode", "True");
996         do_parameter("restrict anonymous", "0");
997         do_parameter("ClientLanManAuth", "True");
998         do_parameter("LanmanAuth", "True");
999         do_parameter("NTLMAuth", "True");
1000         
1001         do_parameter("enhanced browsing", "True"); 
1002         do_parameter("LockSpinCount", "3");
1003         do_parameter("LockSpinTime", "10");
1004 #ifdef MMAP_BLACKLIST
1005         do_parameter("UseMmap", "False");
1006 #else
1007         do_parameter("UseMmap", "True");
1008 #endif
1009         do_parameter("UnixExtensions", "False");
1010
1011         /* hostname lookups can be very expensive and are broken on
1012            a large number of sites (tridge) */
1013         do_parameter("HostnameLookups", "False");
1014
1015         do_parameter("PreferredMaster", "Auto");
1016         do_parameter("os level", "20");
1017         do_parameter("LocalMaster", "True");
1018         do_parameter("DomainMaster", "Auto");   /* depending on bDomainLogons */
1019         do_parameter("DomainLogons", "False");
1020         do_parameter("WINSsupport", "False");
1021         do_parameter("WINSproxy", "False");
1022
1023         do_parameter("DNSproxy", "True");
1024
1025         do_parameter("AllowTrustedDomains", "True");
1026
1027         do_parameter("TemplateShell", "/bin/false");
1028         do_parameter("TemplateHomedir", "/home/%D/%U");
1029         do_parameter("WinbindSeparator", "\\");
1030
1031         do_parameter("winbind cache time", "15");
1032         do_parameter("WinbindEnumUsers", "True");
1033         do_parameter("WinbindEnumGroups", "True");
1034         do_parameter("WinbindUseDefaultDomain", "False");
1035
1036         do_parameter("IDMapBackend", "tdb");
1037
1038         do_parameter("name cache timeout", "660"); /* In seconds */
1039
1040         do_parameter("client signing", "Yes");
1041         do_parameter("server signing", "auto");
1042
1043         do_parameter("use spnego", "True");
1044
1045         do_parameter("smb ports", SMB_PORTS);
1046         do_parameter("nbt port", "137");
1047         do_parameter("dgram port", "138");
1048         do_parameter("cldap port", "389");
1049         do_parameter("krb5 port", "88");
1050         do_parameter("web port", "901");
1051         do_parameter("swat directory", dyn_SWATDIR);
1052
1053         do_parameter("nt status support", "True");
1054
1055         do_parameter("max wins ttl", "432000");
1056         do_parameter("min wins ttl", "10");
1057
1058         do_parameter("tls enabled", "True");
1059         do_parameter("tls keyfile", "tls/key.pem");
1060         do_parameter("tls certfile", "tls/cert.pem");
1061         do_parameter("tls cafile", "tls/ca.pem");
1062 }
1063
1064 static TALLOC_CTX *lp_talloc;
1065
1066 /******************************************************************* a
1067  Free up temporary memory - called from the main loop.
1068 ********************************************************************/
1069
1070 void lp_talloc_free(void)
1071 {
1072         if (!lp_talloc)
1073                 return;
1074         talloc_free(lp_talloc);
1075         lp_talloc = NULL;
1076 }
1077
1078 /*******************************************************************
1079  Convenience routine to grab string parameters into temporary memory
1080  and run standard_sub_basic on them. The buffers can be written to by
1081  callers without affecting the source string.
1082 ********************************************************************/
1083
1084 static const char *lp_string(const char *s)
1085 {
1086 #if 0  /* until REWRITE done to make thread-safe */
1087         size_t len = s ? strlen(s) : 0;
1088         char *ret;
1089 #endif
1090
1091         /* The follow debug is useful for tracking down memory problems
1092            especially if you have an inner loop that is calling a lp_*()
1093            function that returns a string.  Perhaps this debug should be
1094            present all the time? */
1095
1096 #if 0
1097         DEBUG(10, ("lp_string(%s)\n", s));
1098 #endif
1099
1100 #if 0  /* until REWRITE done to make thread-safe */
1101         if (!lp_talloc)
1102                 lp_talloc = talloc_init("lp_talloc");
1103
1104         ret = talloc_array(lp_talloc, char, len + 100); /* leave room for substitution */
1105
1106         if (!ret)
1107                 return NULL;
1108
1109         if (!s)
1110                 *ret = 0;
1111         else
1112                 StrnCpy(ret, s, len);
1113
1114         if (trim_string(ret, "\"", "\"")) {
1115                 if (strchr(ret,'"') != NULL)
1116                         StrnCpy(ret, s, len);
1117         }
1118
1119         standard_sub_basic(ret,len+100);
1120         return (ret);
1121 #endif
1122         return s;
1123 }
1124
1125 /*
1126    In this section all the functions that are used to access the 
1127    parameters from the rest of the program are defined 
1128 */
1129
1130 #define FN_GLOBAL_STRING(fn_name,ptr) \
1131  const char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
1132 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
1133  const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");}
1134 #define FN_GLOBAL_LIST(fn_name,ptr) \
1135  const char **fn_name(void) {return(*(const char ***)(ptr));}
1136 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1137  BOOL fn_name(void) {return(*(BOOL *)(ptr));}
1138 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1139  char fn_name(void) {return(*(char *)(ptr));}
1140 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1141  int fn_name(void) {return(*(int *)(ptr));}
1142
1143 #define FN_LOCAL_STRING(fn_name,val) \
1144  const char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
1145 #define FN_LOCAL_CONST_STRING(fn_name,val) \
1146  const char *fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1147 #define FN_LOCAL_LIST(fn_name,val) \
1148  const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1149 #define FN_LOCAL_BOOL(fn_name,val) \
1150  BOOL fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1151 #define FN_LOCAL_CHAR(fn_name,val) \
1152  char fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1153 #define FN_LOCAL_INTEGER(fn_name,val) \
1154  int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1155
1156 FN_GLOBAL_LIST(lp_smb_ports, &Globals.smb_ports)
1157 FN_GLOBAL_INTEGER(lp_nbt_port, &Globals.nbt_port)
1158 FN_GLOBAL_INTEGER(lp_dgram_port, &Globals.dgram_port)
1159 FN_GLOBAL_INTEGER(lp_cldap_port, &Globals.cldap_port)
1160 FN_GLOBAL_INTEGER(lp_krb5_port, &Globals.krb5_port)
1161 FN_GLOBAL_INTEGER(lp_web_port, &Globals.web_port)
1162 FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
1163 FN_GLOBAL_STRING(lp_swat_directory, &Globals.swat_directory)
1164 FN_GLOBAL_BOOL(lp_tls_enabled, &Globals.tls_enabled)
1165 FN_GLOBAL_STRING(lp_tls_keyfile, &Globals.tls_keyfile)
1166 FN_GLOBAL_STRING(lp_tls_certfile, &Globals.tls_certfile)
1167 FN_GLOBAL_STRING(lp_tls_cafile, &Globals.tls_cafile)
1168 FN_GLOBAL_STRING(lp_tls_crlfile, &Globals.tls_crlfile)
1169 FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
1170 FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset)
1171 FN_GLOBAL_STRING(lp_logfile, &Globals.szLogFile)
1172 FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
1173 FN_GLOBAL_STRING(lp_smb_passwd_file, &Globals.szSMBPasswdFile)
1174 FN_GLOBAL_STRING(lp_sam_url, &Globals.szSAM_URL)
1175 FN_GLOBAL_STRING(lp_spoolss_url, &Globals.szSPOOLSS_URL)
1176 FN_GLOBAL_STRING(lp_wins_url, &Globals.szWINS_URL)
1177 FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
1178 FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
1179 FN_GLOBAL_STRING(lp_printcapname, &Globals.szPrintcapname)
1180 FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
1181 FN_GLOBAL_STRING(lp_ncalrpc_dir, &Globals.ncalrpc_dir)
1182 FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
1183 FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, &Globals.dcerpc_ep_servers)
1184 FN_GLOBAL_LIST(lp_server_services, &Globals.server_services)
1185 FN_GLOBAL_STRING(lp_ntptr_providor, &Globals.ntptr_providor)
1186 FN_GLOBAL_STRING(lp_rootdir, &Globals.szRootdir)
1187 FN_GLOBAL_STRING(lp_defaultservice, &Globals.szDefaultService)
1188 FN_GLOBAL_STRING(lp_hosts_equiv, &Globals.szHostsEquiv)
1189 FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
1190 FN_GLOBAL_STRING(lp_passwd_program, &Globals.szPasswdProgram)
1191 FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
1192 FN_GLOBAL_LIST(lp_passwordserver, &Globals.szPasswordServers)
1193 FN_GLOBAL_LIST(lp_name_resolve_order, &Globals.szNameResolveOrder)
1194 FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
1195 FN_GLOBAL_STRING(lp_ads_server, &Globals.szADSserver)
1196 FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
1197 FN_GLOBAL_STRING(lp_workgroup, &Globals.szWorkgroup)
1198 FN_GLOBAL_STRING(lp_netbios_name, &Globals.szNetbiosName)
1199 FN_GLOBAL_STRING(lp_netbios_scope, &Globals.szNetbiosScope)
1200 FN_GLOBAL_CONST_STRING(lp_logon_script, &Globals.szLogonScript)
1201 FN_GLOBAL_CONST_STRING(lp_logon_path, &Globals.szLogonPath)
1202 FN_GLOBAL_CONST_STRING(lp_logon_drive, &Globals.szLogonDrive)
1203 FN_GLOBAL_CONST_STRING(lp_logon_home, &Globals.szLogonHome)
1204 FN_GLOBAL_STRING(lp_remote_announce, &Globals.szRemoteAnnounce)
1205 FN_GLOBAL_STRING(lp_remote_browse_sync, &Globals.szRemoteBrowseSync)
1206 FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
1207 FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
1208 FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
1209 FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
1210 FN_GLOBAL_LIST(lp_preload_modules, &Globals.szPreloadModules)
1211 FN_GLOBAL_STRING(lp_panic_action, &Globals.szPanicAction)
1212 FN_GLOBAL_STRING(lp_adduser_script, &Globals.szAddUserScript)
1213
1214 FN_GLOBAL_CONST_STRING(lp_guestaccount, &Globals.szGuestaccount)
1215
1216 FN_GLOBAL_STRING(lp_addmachine_script, &Globals.szAddMachineScript)
1217
1218 FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
1219 FN_GLOBAL_STRING(lp_wins_partners, &Globals.szWINSPartners)
1220 FN_GLOBAL_STRING(lp_template_homedir, &Globals.szTemplateHomedir)
1221 FN_GLOBAL_STRING(lp_template_shell, &Globals.szTemplateShell)
1222 FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
1223 FN_GLOBAL_BOOL(lp_winbind_enum_users, &Globals.bWinbindEnumUsers)
1224 FN_GLOBAL_BOOL(lp_winbind_enum_groups, &Globals.bWinbindEnumGroups)
1225 FN_GLOBAL_BOOL(lp_winbind_use_default_domain, &Globals.bWinbindUseDefaultDomain)
1226 FN_GLOBAL_STRING(lp_idmap_backend, &Globals.szIDMapBackend)
1227
1228 FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
1229 FN_GLOBAL_BOOL(lp_dns_proxy, &Globals.bDNSproxy)
1230 FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
1231 FN_GLOBAL_BOOL(lp_we_are_a_wins_server, &Globals.bWINSsupport)
1232 FN_GLOBAL_BOOL(lp_wins_proxy, &Globals.bWINSproxy)
1233 FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
1234 FN_GLOBAL_BOOL(lp_domain_logons, &Globals.bDomainLogons)
1235 FN_GLOBAL_BOOL(lp_load_printers, &Globals.bLoadPrinters)
1236 FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
1237 FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
1238 FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw)
1239 FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords)
1240 FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions)
1241 FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
1242 static FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
1243 FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
1244 FN_GLOBAL_BOOL(lp_pam_password_change, &Globals.bPamPasswordChange)
1245 FN_GLOBAL_BOOL(lp_unicode, &Globals.bUnicode)
1246 FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
1247 FN_GLOBAL_BOOL(lp_allow_trusted_domains, &Globals.bAllowTrustedDomains)
1248 FN_GLOBAL_INTEGER(lp_restrict_anonymous, &Globals.restrict_anonymous)
1249 FN_GLOBAL_BOOL(lp_plaintext_auth, &Globals.bPlaintextAuth)
1250 FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
1251 FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
1252 FN_GLOBAL_BOOL(lp_client_plaintext_auth, &Globals.bClientPlaintextAuth)
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 const char *lp_get_parametric(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 strtol(s, NULL, 0); 
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, 0);
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 = lp_get_parametric(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 = lp_get_parametric(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 = lp_get_parametric(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 = lp_get_parametric(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 = lp_get_parametric(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 /*
1786   return the parameter structure for a parameter
1787 */
1788 struct parm_struct *lp_parm_struct(const char *name)
1789 {
1790         int parmnum = map_parameter(name);
1791         if (parmnum == -1) return NULL;
1792         return &parm_table[parmnum];
1793 }
1794
1795 /*
1796   return the parameter pointer for a parameter
1797 */
1798 void *lp_parm_ptr(int snum, struct parm_struct *parm)
1799 {
1800         if (snum == -1) {
1801                 return parm->ptr;
1802         }
1803         return ((char *)ServicePtrs[snum]) + PTR_DIFF(parm->ptr, &sDefault);
1804 }
1805
1806 /***************************************************************************
1807  Set a boolean variable from the text value stored in the passed string.
1808  Returns True in success, False if the passed string does not correctly 
1809  represent a boolean.
1810 ***************************************************************************/
1811
1812 static BOOL set_boolean(BOOL *pb, const char *pszParmValue)
1813 {
1814         BOOL bRetval;
1815
1816         bRetval = True;
1817         if (strwicmp(pszParmValue, "yes") == 0 ||
1818             strwicmp(pszParmValue, "true") == 0 ||
1819             strwicmp(pszParmValue, "1") == 0)
1820                 *pb = True;
1821         else if (strwicmp(pszParmValue, "no") == 0 ||
1822                     strwicmp(pszParmValue, "False") == 0 ||
1823                     strwicmp(pszParmValue, "0") == 0)
1824                 *pb = False;
1825         else {
1826                 DEBUG(0,
1827                       ("ERROR: Badly formed boolean in configuration file: \"%s\".\n",
1828                        pszParmValue));
1829                 bRetval = False;
1830         }
1831         return (bRetval);
1832 }
1833
1834 /***************************************************************************
1835 Find a service by name. Otherwise works like get_service.
1836 ***************************************************************************/
1837
1838 static int getservicebyname(const char *pszServiceName, service * pserviceDest)
1839 {
1840         int iService;
1841
1842         for (iService = iNumServices - 1; iService >= 0; iService--)
1843                 if (VALID(iService) &&
1844                     strwicmp(ServicePtrs[iService]->szService, pszServiceName) == 0) {
1845                         if (pserviceDest != NULL)
1846                                 copy_service(pserviceDest, ServicePtrs[iService], NULL);
1847                         break;
1848                 }
1849
1850         return (iService);
1851 }
1852
1853 /***************************************************************************
1854  Copy a service structure to another.
1855  If pcopymapDest is NULL then copy all fields
1856 ***************************************************************************/
1857
1858 static void copy_service(service * pserviceDest, service * pserviceSource, BOOL *pcopymapDest)
1859 {
1860         int i;
1861         BOOL bcopyall = (pcopymapDest == NULL);
1862         struct param_opt *data, *pdata, *paramo;
1863         BOOL not_added;
1864
1865         for (i = 0; parm_table[i].label; i++)
1866                 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1867                     (bcopyall || pcopymapDest[i])) {
1868                         void *def_ptr = parm_table[i].ptr;
1869                         void *src_ptr =
1870                                 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
1871                                                                     &sDefault);
1872                         void *dest_ptr =
1873                                 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
1874                                                                   &sDefault);
1875
1876                         switch (parm_table[i].type) {
1877                                 case P_BOOL:
1878                                         *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
1879                                         break;
1880
1881                                 case P_INTEGER:
1882                                 case P_ENUM:
1883                                         *(int *)dest_ptr = *(int *)src_ptr;
1884                                         break;
1885
1886                                 case P_STRING:
1887                                         string_set(dest_ptr,
1888                                                    *(char **)src_ptr);
1889                                         break;
1890
1891                                 case P_USTRING:
1892                                         string_set(dest_ptr,
1893                                                    *(char **)src_ptr);
1894                                         strupper(*(char **)dest_ptr);
1895                                         break;
1896                                 case P_LIST:
1897                                         *(const char ***)dest_ptr = str_list_copy(talloc_autofree_context(), 
1898                                                                                   *(const char ***)src_ptr);
1899                                         break;
1900                                 default:
1901                                         break;
1902                         }
1903                 }
1904
1905         if (bcopyall) {
1906                 init_copymap(pserviceDest);
1907                 if (pserviceSource->copymap)
1908                         memcpy((void *)pserviceDest->copymap,
1909                                (void *)pserviceSource->copymap,
1910                                sizeof(BOOL) * NUMPARAMETERS);
1911         }
1912         
1913         data = pserviceSource->param_opt;
1914         while (data) {
1915                 not_added = True;
1916                 pdata = pserviceDest->param_opt;
1917                 /* Traverse destination */
1918                 while (pdata) {
1919                         /* If we already have same option, override it */
1920                         if (strcmp(pdata->key, data->key) == 0) {
1921                                 string_free(&pdata->value);
1922                                 pdata->value = strdup(data->value);
1923                                 not_added = False;
1924                                 break;
1925                         }
1926                         pdata = pdata->next;
1927                 }
1928                 if (not_added) {
1929                         paramo = smb_xmalloc_p(struct param_opt);
1930                         paramo->key = strdup(data->key);
1931                         paramo->value = strdup(data->value);
1932                         DLIST_ADD(pserviceDest->param_opt, paramo);
1933                 }
1934                 data = data->next;
1935         }
1936 }
1937
1938 /***************************************************************************
1939 Check a service for consistency. Return False if the service is in any way
1940 incomplete or faulty, else True.
1941 ***************************************************************************/
1942
1943 static BOOL service_ok(int iService)
1944 {
1945         BOOL bRetval;
1946
1947         bRetval = True;
1948         if (ServicePtrs[iService]->szService[0] == '\0') {
1949                 DEBUG(0, ("The following message indicates an internal error:\n"));
1950                 DEBUG(0, ("No service name in service entry.\n"));
1951                 bRetval = False;
1952         }
1953
1954         /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1955         /* I can't see why you'd want a non-printable printer service...        */
1956         if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
1957                 if (!ServicePtrs[iService]->bPrint_ok) {
1958                         DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
1959                                ServicePtrs[iService]->szService));
1960                         ServicePtrs[iService]->bPrint_ok = True;
1961                         update_server_announce_as_printserver();
1962                 }
1963                 /* [printers] service must also be non-browsable. */
1964                 if (ServicePtrs[iService]->bBrowseable)
1965                         ServicePtrs[iService]->bBrowseable = False;
1966         }
1967
1968         /* If a service is flagged unavailable, log the fact at level 0. */
1969         if (!ServicePtrs[iService]->bAvailable)
1970                 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
1971                           ServicePtrs[iService]->szService));
1972
1973         return (bRetval);
1974 }
1975
1976 static struct file_lists {
1977         struct file_lists *next;
1978         char *name;
1979         char *subfname;
1980         time_t modtime;
1981 } *file_lists = NULL;
1982
1983 /*******************************************************************
1984  Keep a linked list of all config files so we know when one has changed 
1985  it's date and needs to be reloaded.
1986 ********************************************************************/
1987
1988 static void add_to_file_list(const char *fname, const char *subfname)
1989 {
1990         struct file_lists *f = file_lists;
1991
1992         while (f) {
1993                 if (f->name && !strcmp(f->name, fname))
1994                         break;
1995                 f = f->next;
1996         }
1997
1998         if (!f) {
1999                 f = malloc_p(struct file_lists);
2000                 if (!f)
2001                         return;
2002                 f->next = file_lists;
2003                 f->name = strdup(fname);
2004                 if (!f->name) {
2005                         SAFE_FREE(f);
2006                         return;
2007                 }
2008                 f->subfname = strdup(subfname);
2009                 if (!f->subfname) {
2010                         SAFE_FREE(f);
2011                         return;
2012                 }
2013                 file_lists = f;
2014                 f->modtime = file_modtime(subfname);
2015         } else {
2016                 time_t t = file_modtime(subfname);
2017                 if (t)
2018                         f->modtime = t;
2019         }
2020 }
2021
2022 /*******************************************************************
2023  Check if a config file has changed date.
2024 ********************************************************************/
2025
2026 BOOL lp_file_list_changed(void)
2027 {
2028         struct file_lists *f = file_lists;
2029         DEBUG(6, ("lp_file_list_changed()\n"));
2030
2031         while (f) {
2032                 pstring n2;
2033                 time_t mod_time;
2034
2035                 pstrcpy(n2, f->name);
2036                 standard_sub_basic(n2,sizeof(n2));
2037
2038                 DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
2039                              f->name, n2, ctime(&f->modtime)));
2040
2041                 mod_time = file_modtime(n2);
2042
2043                 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
2044                         DEBUGADD(6,
2045                                  ("file %s modified: %s\n", n2,
2046                                   ctime(&mod_time)));
2047                         f->modtime = mod_time;
2048                         SAFE_FREE(f->subfname);
2049                         f->subfname = strdup(n2);
2050                         return (True);
2051                 }
2052                 f = f->next;
2053         }
2054         return (False);
2055 }
2056
2057 /***************************************************************************
2058  Handle the include operation.
2059 ***************************************************************************/
2060
2061 static BOOL handle_include(const char *pszParmValue, char **ptr)
2062 {
2063         pstring fname;
2064         pstrcpy(fname, pszParmValue);
2065
2066         standard_sub_basic(fname,sizeof(fname));
2067
2068         add_to_file_list(pszParmValue, fname);
2069
2070         string_set(ptr, fname);
2071
2072         if (file_exist(fname))
2073                 return (pm_process(fname, do_section, do_parameter));
2074
2075         DEBUG(2, ("Can't find include file %s\n", fname));
2076
2077         return (False);
2078 }
2079
2080 /***************************************************************************
2081  Handle the interpretation of the copy parameter.
2082 ***************************************************************************/
2083
2084 static BOOL handle_copy(const char *pszParmValue, char **ptr)
2085 {
2086         BOOL bRetval;
2087         int iTemp;
2088         service serviceTemp;
2089
2090         string_set(ptr, pszParmValue);
2091
2092         init_service(&serviceTemp);
2093
2094         bRetval = False;
2095
2096         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
2097
2098         if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
2099                 if (iTemp == iServiceIndex) {
2100                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
2101                 } else {
2102                         copy_service(ServicePtrs[iServiceIndex],
2103                                      &serviceTemp,
2104                                      ServicePtrs[iServiceIndex]->copymap);
2105                         bRetval = True;
2106                 }
2107         } else {
2108                 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
2109                 bRetval = False;
2110         }
2111
2112         free_service(&serviceTemp);
2113         return (bRetval);
2114 }
2115
2116 /***************************************************************************
2117  Handle winbind/non unix account uid and gid allocation parameters.  The format of these
2118  parameters is:
2119
2120  [global]
2121
2122         winbind uid = 1000-1999
2123         winbind gid = 700-899
2124
2125  We only do simple parsing checks here.  The strings are parsed into useful
2126  structures in the winbind daemon code.
2127
2128 ***************************************************************************/
2129
2130 /* Some lp_ routines to return winbind [ug]id information */
2131
2132 static uid_t winbind_uid_low, winbind_uid_high;
2133 static gid_t winbind_gid_low, winbind_gid_high;
2134 static uint32_t non_unix_account_low, non_unix_account_high;
2135
2136 BOOL lp_winbind_uid(uid_t *low, uid_t *high)
2137 {
2138         if (winbind_uid_low == 0 || winbind_uid_high == 0)
2139                 return False;
2140
2141         if (low)
2142                 *low = winbind_uid_low;
2143
2144         if (high)
2145                 *high = winbind_uid_high;
2146
2147         return True;
2148 }
2149
2150 BOOL lp_winbind_gid(gid_t *low, gid_t *high)
2151 {
2152         if (winbind_gid_low == 0 || winbind_gid_high == 0)
2153                 return False;
2154
2155         if (low)
2156                 *low = winbind_gid_low;
2157
2158         if (high)
2159                 *high = winbind_gid_high;
2160
2161         return True;
2162 }
2163
2164 BOOL lp_non_unix_account_range(uint32_t *low, uint32_t *high)
2165 {
2166         if (non_unix_account_low == 0 || non_unix_account_high == 0)
2167                 return False;
2168
2169         if (low)
2170                 *low = non_unix_account_low;
2171
2172         if (high)
2173                 *high = non_unix_account_high;
2174
2175         return True;
2176 }
2177
2178 /* Do some simple checks on "winbind [ug]id" parameter values */
2179
2180 static BOOL handle_winbind_uid(const char *pszParmValue, char **ptr)
2181 {
2182         uint32_t low, high;
2183
2184         if (sscanf(pszParmValue, "%u-%u", &low, &high) != 2 || high < low)
2185                 return False;
2186
2187         /* Parse OK */
2188
2189         string_set(ptr, pszParmValue);
2190
2191         winbind_uid_low = low;
2192         winbind_uid_high = high;
2193
2194         return True;
2195 }
2196
2197 static BOOL handle_winbind_gid(const char *pszParmValue, char **ptr)
2198 {
2199         uint32_t low, high;
2200
2201         if (sscanf(pszParmValue, "%u-%u", &low, &high) != 2 || high < low)
2202                 return False;
2203
2204         /* Parse OK */
2205
2206         string_set(ptr, pszParmValue);
2207
2208         winbind_gid_low = low;
2209         winbind_gid_high = high;
2210
2211         return True;
2212 }
2213
2214 /***************************************************************************
2215  Do some simple checks on "non unix account range" parameter values.
2216 ***************************************************************************/
2217
2218 static BOOL handle_non_unix_account_range(const char *pszParmValue, char **ptr)
2219 {
2220         uint32_t low, high;
2221
2222         if (sscanf(pszParmValue, "%u-%u", &low, &high) != 2 || high < low)
2223                 return False;
2224
2225         /* Parse OK */
2226
2227         string_set(ptr, pszParmValue);
2228
2229         non_unix_account_low = low;
2230         non_unix_account_high = high;
2231
2232         return True;
2233 }
2234
2235
2236 /***************************************************************************
2237  Initialise a copymap.
2238 ***************************************************************************/
2239
2240 static void init_copymap(service * pservice)
2241 {
2242         int i;
2243         SAFE_FREE(pservice->copymap);
2244         pservice->copymap = malloc_array_p(BOOL, NUMPARAMETERS);
2245         if (!pservice->copymap)
2246                 DEBUG(0,
2247                       ("Couldn't allocate copymap!! (size %d)\n",
2248                        (int)NUMPARAMETERS));
2249         else
2250                 for (i = 0; i < NUMPARAMETERS; i++)
2251                         pservice->copymap[i] = True;
2252 }
2253
2254 /***************************************************************************
2255  Return the local pointer to a parameter given the service number and the 
2256  pointer into the default structure.
2257 ***************************************************************************/
2258
2259 void *lp_local_ptr(int snum, void *ptr)
2260 {
2261         return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
2262 }
2263
2264
2265 /***************************************************************************
2266  Process a parametric option
2267 ***************************************************************************/
2268 static BOOL lp_do_parameter_parametric(int snum, const char *pszParmName, const char *pszParmValue, int flags)
2269 {
2270         struct param_opt *paramo, *data;
2271         char *name;
2272
2273         while (isspace(*pszParmName)) {
2274                 pszParmName++;
2275         }
2276
2277         name = strdup(pszParmName);
2278         if (!name) return False;
2279
2280         strlower(name);
2281
2282         if (snum < 0) {
2283                 data = Globals.param_opt;
2284         } else {
2285                 data = ServicePtrs[snum]->param_opt;
2286         }
2287
2288         /* Traverse destination */
2289         for (paramo=data; paramo; paramo=paramo->next) {
2290                 /* If we already have the option set, override it unless
2291                    it was a command line option and the new one isn't */
2292                 if (strcmp(paramo->key, name) == 0) {
2293                         if ((paramo->flags & FLAG_CMDLINE) &&
2294                             !(flags & FLAG_CMDLINE)) {
2295                                 return True;
2296                         }
2297
2298                         free(paramo->value);
2299                         paramo->value = strdup(pszParmValue);
2300                         paramo->flags = flags;
2301                         free(name);
2302                         return True;
2303                 }
2304         }
2305
2306         paramo = smb_xmalloc_p(struct param_opt);
2307         paramo->key = strdup(name);
2308         paramo->value = strdup(pszParmValue);
2309         paramo->flags = flags;
2310         if (snum < 0) {
2311                 DLIST_ADD(Globals.param_opt, paramo);
2312         } else {
2313                 DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
2314         }
2315
2316         free(name);
2317         
2318         return True;
2319 }
2320
2321 /***************************************************************************
2322  Process a parameter for a particular service number. If snum < 0
2323  then assume we are in the globals.
2324 ***************************************************************************/
2325 BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
2326 {
2327         int parmnum, i;
2328         void *parm_ptr = NULL;  /* where we are going to store the result */
2329         void *def_ptr = NULL;
2330
2331         parmnum = map_parameter(pszParmName);
2332
2333         if (parmnum < 0) {
2334                 if (strchr(pszParmName, ':')) {
2335                         return lp_do_parameter_parametric(snum, pszParmName, pszParmValue, 0);
2336                 }
2337                 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
2338                 return (True);
2339         }
2340
2341         if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
2342                 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
2343                           pszParmName));
2344         }
2345
2346         /* if the flag has been set on the command line, then don't allow override,
2347            but don't report an error */
2348         if (parm_table[parmnum].flags & FLAG_CMDLINE) {
2349                 return True;
2350         }
2351
2352         def_ptr = parm_table[parmnum].ptr;
2353
2354         /* we might point at a service, the default service or a global */
2355         if (snum < 0) {
2356                 parm_ptr = def_ptr;
2357         } else {
2358                 if (parm_table[parmnum].class == P_GLOBAL) {
2359                         DEBUG(0,
2360                               ("Global parameter %s found in service section!\n",
2361                                pszParmName));
2362                         return (True);
2363                 }
2364                 parm_ptr =
2365                         ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
2366                                                             &sDefault);
2367         }
2368
2369         if (snum >= 0) {
2370                 if (!ServicePtrs[snum]->copymap)
2371                         init_copymap(ServicePtrs[snum]);
2372
2373                 /* this handles the aliases - set the copymap for other entries with
2374                    the same data pointer */
2375                 for (i = 0; parm_table[i].label; i++)
2376                         if (parm_table[i].ptr == parm_table[parmnum].ptr)
2377                                 ServicePtrs[snum]->copymap[i] = False;
2378         }
2379
2380         /* if it is a special case then go ahead */
2381         if (parm_table[parmnum].special) {
2382                 parm_table[parmnum].special(pszParmValue, (char **)parm_ptr);
2383                 return (True);
2384         }
2385
2386         /* now switch on the type of variable it is */
2387         switch (parm_table[parmnum].type)
2388         {
2389                 case P_BOOL:
2390                         set_boolean(parm_ptr, pszParmValue);
2391                         break;
2392
2393                 case P_INTEGER:
2394                         *(int *)parm_ptr = atoi(pszParmValue);
2395                         break;
2396
2397                 case P_LIST:
2398                         *(const char ***)parm_ptr = str_list_make(talloc_autofree_context(), 
2399                                                                   pszParmValue, NULL);
2400                         break;
2401
2402                 case P_STRING:
2403                         string_set(parm_ptr, pszParmValue);
2404                         break;
2405
2406                 case P_USTRING:
2407                         string_set(parm_ptr, pszParmValue);
2408                         strupper(*(char **)parm_ptr);
2409                         break;
2410
2411                 case P_ENUM:
2412                         for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
2413                                 if (strequal
2414                                     (pszParmValue,
2415                                      parm_table[parmnum].enum_list[i].name)) {
2416                                         *(int *)parm_ptr =
2417                                                 parm_table[parmnum].
2418                                                 enum_list[i].value;
2419                                         break;
2420                                 }
2421                         }
2422                         if (!parm_table[parmnum].enum_list[i].name) {
2423                                 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n", 
2424                                          pszParmValue, pszParmName));
2425                                 return False;
2426                         }
2427                         break;
2428                 case P_SEP:
2429                         break;
2430         }
2431
2432         return (True);
2433 }
2434
2435 /***************************************************************************
2436  Process a parameter.
2437 ***************************************************************************/
2438
2439 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue)
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_INTEGER:
2561                         fprintf(f, "%d", *(int *)ptr);
2562                         break;
2563
2564                 case P_LIST:
2565                         if ((char ***)ptr && *(char ***)ptr) {
2566                                 char **list = *(char ***)ptr;
2567                                 
2568                                 for (; *list; list++)
2569                                         fprintf(f, "%s%s", *list,
2570                                                 ((*(list+1))?", ":""));
2571                         }
2572                         break;
2573
2574                 case P_STRING:
2575                 case P_USTRING:
2576                         if (*(char **)ptr) {
2577                                 fprintf(f, "%s", *(char **)ptr);
2578                         }
2579                         break;
2580                 case P_SEP:
2581                         break;
2582         }
2583 }
2584
2585 /***************************************************************************
2586  Check if two parameters are equal.
2587 ***************************************************************************/
2588
2589 static BOOL equal_parameter(parm_type type, void *ptr1, void *ptr2)
2590 {
2591         switch (type) {
2592                 case P_BOOL:
2593                         return (*((BOOL *)ptr1) == *((BOOL *)ptr2));
2594
2595                 case P_INTEGER:
2596                 case P_ENUM:
2597                         return (*((int *)ptr1) == *((int *)ptr2));
2598
2599                 case P_LIST:
2600                         return str_list_equal((const char **)(*(char ***)ptr1), 
2601                                               (const char **)(*(char ***)ptr2));
2602
2603                 case P_STRING:
2604                 case P_USTRING:
2605                 {
2606                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
2607                         if (p1 && !*p1)
2608                                 p1 = NULL;
2609                         if (p2 && !*p2)
2610                                 p2 = NULL;
2611                         return (p1 == p2 || strequal(p1, p2));
2612                 }
2613                 case P_SEP:
2614                         break;
2615         }
2616         return (False);
2617 }
2618
2619 /***************************************************************************
2620  Process a new section (service). At this stage all sections are services.
2621  Later we'll have special sections that permit server parameters to be set.
2622  Returns True on success, False on failure. 
2623 ***************************************************************************/
2624
2625 static BOOL do_section(const char *pszSectionName)
2626 {
2627         BOOL bRetval;
2628         BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2629                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2630         bRetval = False;
2631
2632         /* if we've just struck a global section, note the fact. */
2633         bInGlobalSection = isglobal;
2634
2635         /* check for multiple global sections */
2636         if (bInGlobalSection) {
2637                 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2638                 return (True);
2639         }
2640
2641         /* if we have a current service, tidy it up before moving on */
2642         bRetval = True;
2643
2644         if (iServiceIndex >= 0)
2645                 bRetval = service_ok(iServiceIndex);
2646
2647         /* if all is still well, move to the next record in the services array */
2648         if (bRetval) {
2649                 /* We put this here to avoid an odd message order if messages are */
2650                 /* issued by the post-processing of a previous section. */
2651                 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2652
2653                 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
2654                     < 0) {
2655                         DEBUG(0, ("Failed to add a new service\n"));
2656                         return (False);
2657                 }
2658         }
2659
2660         return (bRetval);
2661 }
2662
2663
2664 /***************************************************************************
2665  Determine if a partcular base parameter is currentl set to the default value.
2666 ***************************************************************************/
2667
2668 static BOOL is_default(int i)
2669 {
2670         if (!defaults_saved)
2671                 return False;
2672         switch (parm_table[i].type) {
2673                 case P_LIST:
2674                         return str_list_equal((const char **)parm_table[i].def.lvalue, 
2675                                               (const char **)(*(char ***)parm_table[i].ptr));
2676                 case P_STRING:
2677                 case P_USTRING:
2678                         return strequal(parm_table[i].def.svalue,
2679                                         *(char **)parm_table[i].ptr);
2680                 case P_BOOL:
2681                         return parm_table[i].def.bvalue ==
2682                                 *(BOOL *)parm_table[i].ptr;
2683                 case P_INTEGER:
2684                 case P_ENUM:
2685                         return parm_table[i].def.ivalue ==
2686                                 *(int *)parm_table[i].ptr;
2687                 case P_SEP:
2688                         break;
2689         }
2690         return False;
2691 }
2692
2693 /***************************************************************************
2694 Display the contents of the global structure.
2695 ***************************************************************************/
2696
2697 static void dump_globals(FILE *f)
2698 {
2699         int i;
2700         struct param_opt *data;
2701         
2702         fprintf(f, "# Global parameters\n[global]\n");
2703
2704         for (i = 0; parm_table[i].label; i++)
2705                 if (parm_table[i].class == P_GLOBAL &&
2706                     parm_table[i].ptr &&
2707                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2708                         if (defaults_saved && is_default(i))
2709                                 continue;
2710                         fprintf(f, "\t%s = ", parm_table[i].label);
2711                         print_parameter(&parm_table[i], parm_table[i].ptr, f);
2712                         fprintf(f, "\n");
2713         }
2714         if (Globals.param_opt != NULL) {
2715                 data = Globals.param_opt;
2716                 while(data) {
2717                         fprintf(f, "\t%s = %s\n", data->key, data->value);
2718                         data = data->next;
2719                 }
2720         }
2721
2722 }
2723
2724 /***************************************************************************
2725  Display the contents of a single services record.
2726 ***************************************************************************/
2727
2728 static void dump_a_service(service * pService, FILE * f)
2729 {
2730         int i;
2731         struct param_opt *data;
2732         
2733         if (pService != &sDefault)
2734                 fprintf(f, "\n[%s]\n", pService->szService);
2735
2736         for (i = 0; parm_table[i].label; i++)
2737                 if (parm_table[i].class == P_LOCAL &&
2738                     parm_table[i].ptr &&
2739                     (*parm_table[i].label != '-') &&
2740                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2741                         int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
2742
2743                         if (pService == &sDefault) {
2744                                 if (defaults_saved && is_default(i))
2745                                         continue;
2746                         } else {
2747                                 if (equal_parameter(parm_table[i].type,
2748                                                     ((char *)pService) +
2749                                                     pdiff,
2750                                                     ((char *)&sDefault) +
2751                                                     pdiff))
2752                                         continue;
2753                         }
2754
2755                         fprintf(f, "\t%s = ", parm_table[i].label);
2756                         print_parameter(&parm_table[i],
2757                                         ((char *)pService) + pdiff, f);
2758                         fprintf(f, "\n");
2759         }
2760         if (pService->param_opt != NULL) {
2761                 data = pService->param_opt;
2762                 while(data) {
2763                         fprintf(f, "\t%s = %s\n", data->key, data->value);
2764                         data = data->next;
2765                 }
2766         }
2767 }
2768
2769
2770 /***************************************************************************
2771  Return info about the next service  in a service. snum==-1 gives the globals.
2772  Return NULL when out of parameters.
2773 ***************************************************************************/
2774
2775 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
2776 {
2777         if (snum == -1) {
2778                 /* do the globals */
2779                 for (; parm_table[*i].label; (*i)++) {
2780                         if (parm_table[*i].class == P_SEPARATOR)
2781                                 return &parm_table[(*i)++];
2782
2783                         if (!parm_table[*i].ptr
2784                             || (*parm_table[*i].label == '-'))
2785                                 continue;
2786
2787                         if ((*i) > 0
2788                             && (parm_table[*i].ptr ==
2789                                 parm_table[(*i) - 1].ptr))
2790                                 continue;
2791
2792                         return &parm_table[(*i)++];
2793                 }
2794         } else {
2795                 service *pService = ServicePtrs[snum];
2796
2797                 for (; parm_table[*i].label; (*i)++) {
2798                         if (parm_table[*i].class == P_SEPARATOR)
2799                                 return &parm_table[(*i)++];
2800
2801                         if (parm_table[*i].class == P_LOCAL &&
2802                             parm_table[*i].ptr &&
2803                             (*parm_table[*i].label != '-') &&
2804                             ((*i) == 0 ||
2805                              (parm_table[*i].ptr !=
2806                               parm_table[(*i) - 1].ptr)))
2807                         {
2808                                 int pdiff =
2809                                         PTR_DIFF(parm_table[*i].ptr,
2810                                                  &sDefault);
2811
2812                                 if (allparameters ||
2813                                     !equal_parameter(parm_table[*i].type,
2814                                                      ((char *)pService) +
2815                                                      pdiff,
2816                                                      ((char *)&sDefault) +
2817                                                      pdiff))
2818                                 {
2819                                         return &parm_table[(*i)++];
2820                                 }
2821                         }
2822                 }
2823         }
2824
2825         return NULL;
2826 }
2827
2828
2829 /***************************************************************************
2830  Return TRUE if the passed service number is within range.
2831 ***************************************************************************/
2832
2833 BOOL lp_snum_ok(int iService)
2834 {
2835         return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
2836 }
2837
2838 /***************************************************************************
2839  Auto-load some home services.
2840 ***************************************************************************/
2841
2842 static void lp_add_auto_services(const char *str)
2843 {
2844         return;
2845 }
2846
2847 /***************************************************************************
2848  Auto-load one printer.
2849 ***************************************************************************/
2850
2851 void lp_add_one_printer(char *name, char *comment)
2852 {
2853         int printers = lp_servicenumber(PRINTERS_NAME);
2854         int i;
2855
2856         if (lp_servicenumber(name) < 0) {
2857                 lp_add_printer(name, printers);
2858                 if ((i = lp_servicenumber(name)) >= 0) {
2859                         string_set(&ServicePtrs[i]->comment, comment);
2860                         ServicePtrs[i]->autoloaded = True;
2861                 }
2862         }
2863 }
2864
2865 /***************************************************************************
2866  Announce ourselves as a print server.
2867 ***************************************************************************/
2868
2869 void update_server_announce_as_printserver(void)
2870 {
2871         default_server_announce |= SV_TYPE_PRINTQ_SERVER;       
2872 }
2873
2874 /***************************************************************************
2875  Have we loaded a services file yet?
2876 ***************************************************************************/
2877
2878 BOOL lp_loaded(void)
2879 {
2880         return (bLoaded);
2881 }
2882
2883 /***************************************************************************
2884  Unload unused services.
2885 ***************************************************************************/
2886
2887 void lp_killunused(struct smbsrv_connection *smb, BOOL (*snumused) (struct smbsrv_connection *, int))
2888 {
2889         int i;
2890         for (i = 0; i < iNumServices; i++) {
2891                 if (!VALID(i))
2892                         continue;
2893
2894                 if (!snumused || !snumused(smb, i)) {
2895                         ServicePtrs[i]->valid = False;
2896                         free_service(ServicePtrs[i]);
2897                 }
2898         }
2899 }
2900
2901 /***************************************************************************
2902  Unload a service.
2903 ***************************************************************************/
2904
2905 void lp_killservice(int iServiceIn)
2906 {
2907         if (VALID(iServiceIn)) {
2908                 ServicePtrs[iServiceIn]->valid = False;
2909                 free_service(ServicePtrs[iServiceIn]);
2910         }
2911 }
2912
2913 /*******************************************************************
2914  Set the server type we will announce as via nmbd.
2915 ********************************************************************/
2916
2917 static void set_server_role(void)
2918 {
2919         server_role = ROLE_STANDALONE;
2920
2921         switch (lp_security()) {
2922                 case SEC_SHARE:
2923                         if (lp_domain_logons())
2924                                 DEBUG(0, ("Server's Role (logon server) conflicts with share-level security\n"));
2925                         break;
2926                 case SEC_SERVER:
2927                 case SEC_DOMAIN:
2928                 case SEC_ADS:
2929                         if (lp_domain_logons()) {
2930                                 if (Globals.bDomainMaster) /* auto or yes */ 
2931                                         server_role = ROLE_DOMAIN_PDC;
2932                                 else
2933                                         server_role = ROLE_DOMAIN_BDC;
2934                                 break;
2935                         }
2936                         server_role = ROLE_DOMAIN_MEMBER;
2937                         break;
2938                 case SEC_USER:
2939                         if (lp_domain_logons()) {
2940
2941                                 if (Globals.bDomainMaster) /* auto or yes */ 
2942                                         server_role = ROLE_DOMAIN_PDC;
2943                                 else
2944                                         server_role = ROLE_DOMAIN_BDC;
2945                         }
2946                         break;
2947                 default:
2948                         DEBUG(0, ("Server's Role undefined due to unknown security mode\n"));
2949                         break;
2950         }
2951
2952         DEBUG(10, ("set_server_role: role = "));
2953
2954         switch(server_role) {
2955         case ROLE_STANDALONE:
2956                 DEBUGADD(10, ("ROLE_STANDALONE\n"));
2957                 break;
2958         case ROLE_DOMAIN_MEMBER:
2959                 DEBUGADD(10, ("ROLE_DOMAIN_MEMBER\n"));
2960                 break;
2961         case ROLE_DOMAIN_BDC:
2962                 DEBUGADD(10, ("ROLE_DOMAIN_BDC\n"));
2963                 break;
2964         case ROLE_DOMAIN_PDC:
2965                 DEBUGADD(10, ("ROLE_DOMAIN_PDC\n"));
2966                 break;
2967         }
2968 }
2969
2970 /***************************************************************************
2971  Load the services array from the services file. Return True on success, 
2972  False on failure.
2973 ***************************************************************************/
2974
2975 BOOL lp_load(const char *pszFname)
2976 {
2977         pstring n2;
2978         BOOL bRetval;
2979         struct param_opt *data;
2980
2981         pstrcpy(n2, pszFname);
2982         standard_sub_basic(n2,sizeof(n2));
2983
2984         add_to_file_list(pszFname, n2);
2985
2986         bRetval = False;
2987
2988         DEBUG(2, ("lp_load: refreshing parameters from %s\n", pszFname));
2989         
2990         bInGlobalSection = True;
2991
2992         if (Globals.param_opt != NULL) {
2993                 struct param_opt *next;
2994                 for (data=Globals.param_opt; data; data=next) {
2995                         next = data->next;
2996                         if (data->flags & FLAG_CMDLINE) continue;
2997                         free(data->key);
2998                         free(data->value);
2999                         DLIST_REMOVE(Globals.param_opt, data);
3000                         free(data);
3001                 }
3002         }
3003         
3004         init_globals();
3005
3006         /* We get sections first, so have to start 'behind' to make up */
3007         iServiceIndex = -1;
3008         bRetval = pm_process(n2, do_section, do_parameter);
3009
3010         /* finish up the last section */
3011         DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
3012         if (bRetval)
3013                 if (iServiceIndex >= 0)
3014                         bRetval = service_ok(iServiceIndex);
3015
3016         lp_add_auto_services(lp_auto_services());
3017
3018         /* When 'restrict anonymous = 2' guest connections to ipc$
3019            are denied */
3020         lp_add_hidden("IPC$", "IPC", (lp_restrict_anonymous() < 2));
3021         lp_add_hidden("ADMIN$", "DISK", False);
3022
3023         set_server_role();
3024         set_default_server_announce_type();
3025
3026         bLoaded = True;
3027
3028         /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
3029         /* if bWINSsupport is true and we are in the client            */
3030         if (in_client && Globals.bWINSsupport) {
3031                 lp_do_parameter(-1, "wins server", "127.0.0.1");
3032         }
3033
3034         init_iconv();
3035
3036         return (bRetval);
3037 }
3038
3039 /***************************************************************************
3040  Reset the max number of services.
3041 ***************************************************************************/
3042
3043 void lp_resetnumservices(void)
3044 {
3045         iNumServices = 0;
3046 }
3047
3048 /***************************************************************************
3049  Return the max number of services.
3050 ***************************************************************************/
3051
3052 int lp_numservices(void)
3053 {
3054         return (iNumServices);
3055 }
3056
3057 /***************************************************************************
3058 Display the contents of the services array in human-readable form.
3059 ***************************************************************************/
3060
3061 void lp_dump(FILE *f, BOOL show_defaults, int maxtoprint)
3062 {
3063         int iService;
3064
3065         if (show_defaults)
3066                 defaults_saved = False;
3067
3068         dump_globals(f);
3069
3070         dump_a_service(&sDefault, f);
3071
3072         for (iService = 0; iService < maxtoprint; iService++)
3073                 lp_dump_one(f, show_defaults, iService);
3074 }
3075
3076 /***************************************************************************
3077 Display the contents of one service in human-readable form.
3078 ***************************************************************************/
3079
3080 void lp_dump_one(FILE * f, BOOL show_defaults, int snum)
3081 {
3082         if (VALID(snum)) {
3083                 if (ServicePtrs[snum]->szService[0] == '\0')
3084                         return;
3085                 dump_a_service(ServicePtrs[snum], f);
3086         }
3087 }
3088
3089 /***************************************************************************
3090 Return the number of the service with the given name, or -1 if it doesn't
3091 exist. Note that this is a DIFFERENT ANIMAL from the internal function
3092 getservicebyname()! This works ONLY if all services have been loaded, and
3093 does not copy the found service.
3094 ***************************************************************************/
3095
3096 int lp_servicenumber(const char *pszServiceName)
3097 {
3098         int iService;
3099         fstring serviceName;
3100  
3101  
3102         for (iService = iNumServices - 1; iService >= 0; iService--) {
3103                 if (VALID(iService) && ServicePtrs[iService]->szService) {
3104                         /*
3105                          * The substitution here is used to support %U is
3106                          * service names
3107                          */
3108                         fstrcpy(serviceName, ServicePtrs[iService]->szService);
3109                         standard_sub_basic(serviceName,sizeof(serviceName));
3110                         if (strequal(serviceName, pszServiceName))
3111                                 break;
3112                 }
3113         }
3114
3115         if (iService < 0)
3116                 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
3117
3118         return (iService);
3119 }
3120
3121 /*******************************************************************
3122  A useful volume label function. 
3123 ********************************************************************/
3124 const char *volume_label(int snum)
3125 {
3126         const char *ret = lp_volume(snum);
3127         if (!*ret)
3128                 return lp_servicename(snum);
3129         return (ret);
3130 }
3131
3132
3133 /*******************************************************************
3134  Set the server type we will announce as via nmbd.
3135 ********************************************************************/
3136
3137 static void set_default_server_announce_type(void)
3138 {
3139         default_server_announce = 0;
3140         default_server_announce |= SV_TYPE_WORKSTATION;
3141         default_server_announce |= SV_TYPE_SERVER;
3142         default_server_announce |= SV_TYPE_SERVER_UNIX;
3143
3144         switch (lp_announce_as()) {
3145                 case ANNOUNCE_AS_NT_SERVER:
3146                         default_server_announce |= SV_TYPE_SERVER_NT;
3147                         /* fall through... */
3148                 case ANNOUNCE_AS_NT_WORKSTATION:
3149                         default_server_announce |= SV_TYPE_NT;
3150                         break;
3151                 case ANNOUNCE_AS_WIN95:
3152                         default_server_announce |= SV_TYPE_WIN95_PLUS;
3153                         break;
3154                 case ANNOUNCE_AS_WFW:
3155                         default_server_announce |= SV_TYPE_WFW;
3156                         break;
3157                 default:
3158                         break;
3159         }
3160
3161         switch (lp_server_role()) {
3162                 case ROLE_DOMAIN_MEMBER:
3163                         default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
3164                         break;
3165                 case ROLE_DOMAIN_PDC:
3166                         default_server_announce |= SV_TYPE_DOMAIN_CTRL;
3167                         break;
3168                 case ROLE_DOMAIN_BDC:
3169                         default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
3170                         break;
3171                 case ROLE_STANDALONE:
3172                 default:
3173                         break;
3174         }
3175         if (lp_time_server())
3176                 default_server_announce |= SV_TYPE_TIME_SOURCE;
3177
3178         if (lp_host_msdfs())
3179                 default_server_announce |= SV_TYPE_DFS_SERVER;
3180
3181         /* TODO: only announce us as print server when we are a print server */
3182         default_server_announce |= SV_TYPE_PRINTQ_SERVER;
3183 }
3184
3185 /***********************************************************
3186  returns role of Samba server
3187 ************************************************************/
3188
3189 int lp_server_role(void)
3190 {
3191         return server_role;
3192 }
3193
3194 /***********************************************************
3195  If we are PDC then prefer us as DMB
3196 ************************************************************/
3197
3198 BOOL lp_domain_master(void)
3199 {
3200         if (Globals.bDomainMaster == Auto)
3201                 return (lp_server_role() == ROLE_DOMAIN_PDC);
3202
3203         return Globals.bDomainMaster;
3204 }
3205
3206 /***********************************************************
3207  If we are DMB then prefer us as LMB
3208 ************************************************************/
3209
3210 BOOL lp_preferred_master(void)
3211 {
3212         if (Globals.bPreferredMaster == Auto)
3213                 return (lp_local_master() && lp_domain_master());
3214
3215         return Globals.bPreferredMaster;
3216 }
3217
3218 /*******************************************************************
3219  Remove a service.
3220 ********************************************************************/
3221
3222 void lp_remove_service(int snum)
3223 {
3224         ServicePtrs[snum]->valid = False;
3225 }
3226
3227 /*******************************************************************
3228  Copy a service.
3229 ********************************************************************/
3230
3231 void lp_copy_service(int snum, const char *new_name)
3232 {
3233         const char *oldname = lp_servicename(snum);
3234         do_section(new_name);
3235         if (snum >= 0) {
3236                 snum = lp_servicenumber(new_name);
3237                 if (snum >= 0)
3238                         lp_do_parameter(snum, "copy", oldname);
3239         }
3240 }
3241
3242
3243 /*******************************************************************
3244  Get the default server type we will announce as via nmbd.
3245 ********************************************************************/
3246 int lp_default_server_announce(void)
3247 {
3248         return default_server_announce;
3249 }
3250
3251 const char *lp_printername(int snum)
3252 {
3253         const char *ret = _lp_printername(snum);
3254         if (ret == NULL || (ret != NULL && *ret == '\0'))
3255                 ret = lp_const_servicename(snum);
3256
3257         return ret;
3258 }
3259
3260
3261 /*******************************************************************
3262  Return the max print jobs per queue.
3263 ********************************************************************/
3264
3265 int lp_maxprintjobs(int snum)
3266 {
3267         int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
3268         if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
3269                 maxjobs = PRINT_MAX_JOBID - 1;
3270
3271         return maxjobs;
3272 }