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