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