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