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