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