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