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