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