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