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