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