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