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