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