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