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