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