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