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