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