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