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