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