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