18a1e22d6c8db217ae693e03a4a3ffccaa373d60
[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
797 static int map_parameter(const char *pszParmName);
798 static struct service *getservicebyname(const char *pszServiceName);
799 static void copy_service(struct service * pserviceDest,
800                          struct service * pserviceSource, int *pcopymapDest);
801 static bool service_ok(struct service *service);
802 static bool do_section(const char *pszSectionName, void *);
803 static void init_copymap(struct service * pservice);
804
805 /* This is a helper function for parametrical options support. */
806 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
807 /* Actual parametrical functions are quite simple */
808 const char *lp_get_parametric(struct service *service, const char *type, 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, separator);
933
934         return NULL;
935 }
936
937 /* Return parametric option from a given service. Type is a part of option before ':' */
938 /* Parametric option has following syntax: 'Type: option = value' */
939
940 int lp_parm_int(struct service *service, const char *type, const char *option, 
941                 int default_v)
942 {
943         const char *value = lp_get_parametric(service, type, option);
944         
945         if (value)
946                 return lp_int(value);
947
948         return default_v;
949 }
950
951 /* Return parametric option from a given service. Type is a part of
952  * option before ':'.
953  * Parametric option has following syntax: 'Type: option = value'.
954  */
955
956 int lp_parm_bytes(struct service *service, const char *type, 
957                   const char *option, int default_v)
958 {
959         uint64_t bval;
960
961         const char *value = lp_get_parametric(service, type, option);
962
963         if (value && conv_str_size(value, &bval)) {
964                 if (bval <= INT_MAX) {
965                         return (int)bval;
966                 }
967         }
968
969         return default_v;
970 }
971
972 /* Return parametric option from a given service. Type is a part of option before ':' */
973 /* Parametric option has following syntax: 'Type: option = value' */
974
975 unsigned long lp_parm_ulong(struct service *service, const char *type, 
976                             const char *option, unsigned long default_v)
977 {
978         const char *value = lp_get_parametric(service, type, option);
979         
980         if (value)
981                 return lp_ulong(value);
982
983         return default_v;
984 }
985
986
987 double lp_parm_double(struct service *service, const char *type, 
988                       const char *option, double default_v)
989 {
990         const char *value = lp_get_parametric(service, type, option);
991         
992         if (value)
993                 return lp_double(value);
994
995         return default_v;
996 }
997
998 /* Return parametric option from a given service. Type is a part of option before ':' */
999 /* Parametric option has following syntax: 'Type: option = value' */
1000
1001 bool lp_parm_bool(struct service *service, const char *type, 
1002                   const char *option, bool default_v)
1003 {
1004         const char *value = lp_get_parametric(service, type, option);
1005         
1006         if (value)
1007                 return lp_bool(value);
1008
1009         return default_v;
1010 }
1011
1012
1013 /***************************************************************************
1014  Initialise a service to the defaults.
1015 ***************************************************************************/
1016
1017 static struct service *init_service(TALLOC_CTX *mem_ctx)
1018 {
1019         struct service *pservice = talloc_zero(mem_ctx, struct service);
1020         copy_service(pservice, &sDefault, NULL);
1021         return pservice;
1022 }
1023
1024 void string_free(char **str)
1025 {
1026         if (str) {
1027                 talloc_free(*str);
1028                 *str = NULL;
1029         }
1030 }
1031
1032 /***************************************************************************
1033  Add a new service to the services array initialising it with the given 
1034  service. 
1035 ***************************************************************************/
1036
1037 static struct service *add_a_service(const struct service *pservice, const char *name)
1038 {
1039         int i;
1040         struct service tservice;
1041         int num_to_alloc = loadparm.iNumServices + 1;
1042         struct param_opt *data, *pdata;
1043
1044         tservice = *pservice;
1045
1046         /* it might already exist */
1047         if (name) {
1048                 struct service *service = getservicebyname(name);
1049                 if (service != NULL) {
1050                         /* Clean all parametric options for service */
1051                         /* They will be added during parsing again */
1052                         data = service->param_opt;
1053                         while (data) {
1054                                 pdata = data->next;
1055                                 talloc_free(data);
1056                                 data = pdata;
1057                         }
1058                         service->param_opt = NULL;
1059                         return service;
1060                 }
1061         }
1062
1063         /* find an invalid one */
1064         for (i = 0; i < loadparm.iNumServices; i++)
1065                 if (loadparm.ServicePtrs[i] == NULL)
1066                         break;
1067
1068         /* if not, then create one */
1069         if (i == loadparm.iNumServices) {
1070                 struct service **tsp;
1071                 
1072                 tsp = realloc_p(loadparm.ServicePtrs, struct service *, num_to_alloc);
1073                                            
1074                 if (!tsp) {
1075                         DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1076                         return NULL;
1077                 }
1078                 else {
1079                         loadparm.ServicePtrs = tsp;
1080                         loadparm.ServicePtrs[loadparm.iNumServices] = NULL;
1081                 }
1082
1083                 loadparm.iNumServices++;
1084         } 
1085
1086         loadparm.ServicePtrs[i] = init_service(talloc_autofree_context());
1087         if (loadparm.ServicePtrs[i] == NULL) {
1088                 DEBUG(0,("add_a_service: out of memory!\n"));
1089                 return NULL;
1090         }
1091         copy_service(loadparm.ServicePtrs[i], &tservice, NULL);
1092         if (name != NULL)
1093                 string_set(loadparm.ServicePtrs[i], &loadparm.ServicePtrs[i]->szService, name);
1094         return loadparm.ServicePtrs[i];
1095 }
1096
1097 /***************************************************************************
1098  Add a new home service, with the specified home directory, defaults coming 
1099  from service ifrom.
1100 ***************************************************************************/
1101
1102 bool lp_add_home(const char *pszHomename, struct service *default_service,
1103                  const char *user, const char *pszHomedir)
1104 {
1105         struct service *service;
1106         pstring newHomedir;
1107
1108         service = add_a_service(default_service, pszHomename);
1109
1110         if (service == NULL)
1111                 return false;
1112
1113         if (!(*(default_service->szPath))
1114             || strequal(default_service->szPath, sDefault.szPath)) {
1115                 pstrcpy(newHomedir, pszHomedir);
1116         } else {
1117                 pstrcpy(newHomedir, lp_pathname(default_service));
1118                 string_sub(newHomedir,"%H", pszHomedir, sizeof(newHomedir)); 
1119         }
1120
1121         string_set(service, &service->szPath, newHomedir);
1122
1123         if (!(*(service->comment))) {
1124                 service->comment = talloc_asprintf(service, "Home directory of %s", user);
1125         }
1126         service->bAvailable = default_service->bAvailable;
1127         service->bBrowseable = default_service->bBrowseable;
1128
1129         DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", 
1130                   pszHomename, user, newHomedir));
1131         
1132         return true;
1133 }
1134
1135 /***************************************************************************
1136  Add a new service, based on an old one.
1137 ***************************************************************************/
1138
1139 struct service *lp_add_service(const char *pszService, 
1140                                struct service *default_service)
1141 {
1142         return add_a_service(default_service, pszService);
1143 }
1144
1145 /***************************************************************************
1146  Add the IPC service.
1147 ***************************************************************************/
1148
1149 static bool lp_add_hidden(const char *name, const char *fstype)
1150 {
1151         struct service *service = add_a_service(&sDefault, name);
1152
1153         if (service == NULL)
1154                 return false;
1155
1156         string_set(service, &service->szPath, tmpdir());
1157
1158         service->comment = talloc_asprintf(service, "%s Service (%s)", 
1159                                 fstype, loadparm.Globals.szServerString);
1160         string_set(service, &service->fstype, fstype);
1161         service->iMaxConnections = -1;
1162         service->bAvailable = true;
1163         service->bRead_only = true;
1164         service->bPrint_ok = false;
1165         service->bBrowseable = false;
1166
1167         if (strcasecmp(fstype, "IPC") == 0) {
1168                 lp_do_service_parameter(service, "ntvfs handler", "default");
1169         }
1170
1171         DEBUG(3, ("adding hidden service %s\n", name));
1172
1173         return true;
1174 }
1175
1176 /***************************************************************************
1177  Add a new printer service, with defaults coming from service iFrom.
1178 ***************************************************************************/
1179
1180 bool lp_add_printer(const char *pszPrintername, struct service *default_service)
1181 {
1182         const char *comment = "From Printcap";
1183         struct service *service;
1184         service = add_a_service(default_service, pszPrintername);
1185
1186         if (service == NULL)
1187                 return false;
1188
1189         /* note that we do NOT default the availability flag to True - */
1190         /* we take it from the default service passed. This allows all */
1191         /* dynamic printers to be disabled by disabling the [printers] */
1192         /* entry (if/when the 'available' keyword is implemented!).    */
1193
1194         /* the printer name is set to the service name. */
1195         string_set(service, &service->szPrintername, pszPrintername);
1196         string_set(service, &service->comment, comment);
1197         service->bBrowseable = sDefault.bBrowseable;
1198         /* Printers cannot be read_only. */
1199         service->bRead_only = false;
1200         /* Printer services must be printable. */
1201         service->bPrint_ok = true;
1202
1203         DEBUG(3, ("adding printer service %s\n", pszPrintername));
1204
1205         return true;
1206 }
1207
1208 /***************************************************************************
1209  Map a parameter's string representation to something we can use. 
1210  Returns False if the parameter string is not recognised, else TRUE.
1211 ***************************************************************************/
1212
1213 static int map_parameter(const char *pszParmName)
1214 {
1215         int iIndex;
1216
1217         if (*pszParmName == '-')
1218                 return -1;
1219
1220         for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1221                 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1222                         return iIndex;
1223
1224         /* Warn only if it isn't parametric option */
1225         if (strchr(pszParmName, ':') == NULL)
1226                 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1227         /* We do return 'fail' for parametric options as well because they are
1228            stored in different storage
1229          */
1230         return -1;
1231 }
1232
1233
1234 /*
1235   return the parameter structure for a parameter
1236 */
1237 struct parm_struct *lp_parm_struct(const char *name)
1238 {
1239         int parmnum = map_parameter(name);
1240         if (parmnum == -1) return NULL;
1241         return &parm_table[parmnum];
1242 }
1243
1244 /*
1245   return the parameter pointer for a parameter
1246 */
1247 void *lp_parm_ptr(struct service *service, struct parm_struct *parm)
1248 {
1249         if (service == NULL)
1250                 return parm->ptr;
1251
1252         return ((char *)service) + PTR_DIFF(parm->ptr, &sDefault);
1253 }
1254
1255 /***************************************************************************
1256 Find a service by name. Otherwise works like get_service.
1257 ***************************************************************************/
1258
1259 static struct service *getservicebyname(const char *pszServiceName)
1260 {
1261         int iService;
1262
1263         for (iService = loadparm.iNumServices - 1; iService >= 0; iService--)
1264                 if (VALID(iService) &&
1265                     strwicmp(loadparm.ServicePtrs[iService]->szService, pszServiceName) == 0) {
1266                         return loadparm.ServicePtrs[iService];
1267                 }
1268
1269         return NULL;
1270 }
1271
1272 /***************************************************************************
1273  Copy a service structure to another.
1274  If pcopymapDest is NULL then copy all fields
1275 ***************************************************************************/
1276
1277 static void copy_service(struct service *pserviceDest, 
1278                          struct service *pserviceSource, 
1279                          int *pcopymapDest)
1280 {
1281         int i;
1282         bool bcopyall = (pcopymapDest == NULL);
1283         struct param_opt *data, *pdata, *paramo;
1284         bool not_added;
1285
1286         for (i = 0; parm_table[i].label; i++)
1287                 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1288                     (bcopyall || pcopymapDest[i])) {
1289                         void *def_ptr = parm_table[i].ptr;
1290                         void *src_ptr =
1291                                 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
1292                                                                     &sDefault);
1293                         void *dest_ptr =
1294                                 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
1295                                                                   &sDefault);
1296
1297                         switch (parm_table[i].type) {
1298                                 case P_BOOL:
1299                                         *(int *)dest_ptr = *(int *)src_ptr;
1300                                         break;
1301
1302                                 case P_INTEGER:
1303                                 case P_OCTAL:
1304                                 case P_ENUM:
1305                                         *(int *)dest_ptr = *(int *)src_ptr;
1306                                         break;
1307
1308                                 case P_STRING:
1309                                         string_set(pserviceDest, 
1310                                                    (char **)dest_ptr,
1311                                                    *(char **)src_ptr);
1312                                         break;
1313
1314                                 case P_USTRING:
1315                                         string_set(pserviceDest, 
1316                                                    (char **)dest_ptr,
1317                                                    *(char **)src_ptr);
1318                                         strupper(*(char **)dest_ptr);
1319                                         break;
1320                                 case P_LIST:
1321                                         *(const char ***)dest_ptr = str_list_copy(talloc_autofree_context(), 
1322                                                                                   *(const char ***)src_ptr);
1323                                         break;
1324                                 default:
1325                                         break;
1326                         }
1327                 }
1328
1329         if (bcopyall) {
1330                 init_copymap(pserviceDest);
1331                 if (pserviceSource->copymap)
1332                         memcpy((void *)pserviceDest->copymap,
1333                                (void *)pserviceSource->copymap,
1334                                sizeof(int) * NUMPARAMETERS);
1335         }
1336         
1337         data = pserviceSource->param_opt;
1338         while (data) {
1339                 not_added = true;
1340                 pdata = pserviceDest->param_opt;
1341                 /* Traverse destination */
1342                 while (pdata) {
1343                         /* If we already have same option, override it */
1344                         if (strcmp(pdata->key, data->key) == 0) {
1345                                 string_free(&pdata->value);
1346                                 pdata->value = talloc_reference(pdata, 
1347                                                              data->value);
1348                                 not_added = false;
1349                                 break;
1350                         }
1351                         pdata = pdata->next;
1352                 }
1353                 if (not_added) {
1354                         paramo = talloc(pserviceDest, struct param_opt);
1355                         if (paramo == NULL)
1356                                 smb_panic("OOM");
1357                         paramo->key = talloc_reference(paramo, data->key);
1358                         paramo->value = talloc_reference(paramo, data->value);
1359                         DLIST_ADD(pserviceDest->param_opt, paramo);
1360                 }
1361                 data = data->next;
1362         }
1363 }
1364
1365 /***************************************************************************
1366 Check a service for consistency. Return False if the service is in any way
1367 incomplete or faulty, else True.
1368 ***************************************************************************/
1369
1370 static bool service_ok(struct service *service)
1371 {
1372         bool bRetval;
1373
1374         bRetval = true;
1375         if (service->szService[0] == '\0') {
1376                 DEBUG(0, ("The following message indicates an internal error:\n"));
1377                 DEBUG(0, ("No service name in service entry.\n"));
1378                 bRetval = false;
1379         }
1380
1381         /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1382         /* I can't see why you'd want a non-printable printer service...        */
1383         if (strwicmp(service->szService, PRINTERS_NAME) == 0) {
1384                 if (!service->bPrint_ok) {
1385                         DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
1386                                service->szService));
1387                         service->bPrint_ok = true;
1388                 }
1389                 /* [printers] service must also be non-browsable. */
1390                 if (service->bBrowseable)
1391                         service->bBrowseable = false;
1392         }
1393
1394         /* If a service is flagged unavailable, log the fact at level 0. */
1395         if (!service->bAvailable)
1396                 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
1397                           service->szService));
1398
1399         return bRetval;
1400 }
1401
1402 static struct file_lists {
1403         struct file_lists *next;
1404         char *name;
1405         char *subfname;
1406         time_t modtime;
1407 } *file_lists = NULL;
1408
1409 /*******************************************************************
1410  Keep a linked list of all config files so we know when one has changed 
1411  it's date and needs to be reloaded.
1412 ********************************************************************/
1413
1414 static void add_to_file_list(const char *fname, const char *subfname)
1415 {
1416         struct file_lists *f = file_lists;
1417
1418         while (f) {
1419                 if (f->name && !strcmp(f->name, fname))
1420                         break;
1421                 f = f->next;
1422         }
1423
1424         if (!f) {
1425                 f = talloc(talloc_autofree_context(), struct file_lists);
1426                 if (!f)
1427                         return;
1428                 f->next = file_lists;
1429                 f->name = talloc_strdup(f, fname);
1430                 if (!f->name) {
1431                         talloc_free(f);
1432                         return;
1433                 }
1434                 f->subfname = talloc_strdup(f, subfname);
1435                 if (!f->subfname) {
1436                         talloc_free(f);
1437                         return;
1438                 }
1439                 file_lists = f;
1440                 f->modtime = file_modtime(subfname);
1441         } else {
1442                 time_t t = file_modtime(subfname);
1443                 if (t)
1444                         f->modtime = t;
1445         }
1446 }
1447
1448 /*******************************************************************
1449  Check if a config file has changed date.
1450 ********************************************************************/
1451
1452 bool lp_file_list_changed(void)
1453 {
1454         struct file_lists *f;
1455         DEBUG(6, ("lp_file_list_changed()\n"));
1456
1457         for (f = file_lists; f != NULL; f = f->next) {
1458                 char *n2;
1459                 time_t mod_time;
1460
1461                 n2 = standard_sub_basic(talloc_autofree_context(), f->name);
1462
1463                 DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
1464                              f->name, n2, ctime(&f->modtime)));
1465
1466                 mod_time = file_modtime(n2);
1467
1468                 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
1469                         DEBUGADD(6, ("file %s modified: %s\n", n2,
1470                                   ctime(&mod_time)));
1471                         f->modtime = mod_time;
1472                         talloc_free(f->subfname);
1473                         f->subfname = talloc_strdup(f, n2);
1474                         return true;
1475                 }
1476         }
1477         return false;
1478 }
1479
1480 /***************************************************************************
1481  Handle the include operation.
1482 ***************************************************************************/
1483
1484 static bool handle_include(const char *pszParmValue, char **ptr)
1485 {
1486         char *fname = standard_sub_basic(talloc_autofree_context(), 
1487                                          pszParmValue);
1488
1489         add_to_file_list(pszParmValue, fname);
1490
1491         string_set(talloc_autofree_context(), ptr, fname);
1492
1493         if (file_exist(fname))
1494                 return pm_process(fname, do_section, do_parameter, NULL);
1495
1496         DEBUG(2, ("Can't find include file %s\n", fname));
1497
1498         return false;
1499 }
1500
1501 /***************************************************************************
1502  Handle the interpretation of the copy parameter.
1503 ***************************************************************************/
1504
1505 static bool handle_copy(const char *pszParmValue, char **ptr)
1506 {
1507         bool bRetval;
1508         struct service *serviceTemp;
1509
1510         string_set(talloc_autofree_context(), ptr, pszParmValue);
1511
1512         bRetval = false;
1513
1514         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
1515
1516         if ((serviceTemp = getservicebyname(pszParmValue)) != NULL) {
1517                 if (serviceTemp == loadparm.currentService) {
1518                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
1519                 } else {
1520                         copy_service(loadparm.currentService,
1521                                      serviceTemp,
1522                                      loadparm.currentService->copymap);
1523                         bRetval = true;
1524                 }
1525         } else {
1526                 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
1527                 bRetval = false;
1528         }
1529
1530         return bRetval;
1531 }
1532
1533 /***************************************************************************
1534  Initialise a copymap.
1535 ***************************************************************************/
1536
1537 static void init_copymap(struct service *pservice)
1538 {
1539         int i;
1540         talloc_free(pservice->copymap);
1541         pservice->copymap = talloc_array(pservice, int, NUMPARAMETERS);
1542         if (pservice->copymap == NULL) {
1543                 DEBUG(0,
1544                       ("Couldn't allocate copymap!! (size %d)\n",
1545                        (int)NUMPARAMETERS));
1546                 return;
1547         }
1548         for (i = 0; i < NUMPARAMETERS; i++)
1549                 pservice->copymap[i] = true;
1550 }
1551
1552 #if 0 /* not used anywhere */
1553 /***************************************************************************
1554  Return the local pointer to a parameter given the service number and the 
1555  pointer into the default structure.
1556 ***************************************************************************/
1557
1558 void *lp_local_ptr(int snum, void *ptr)
1559 {
1560         return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
1561 }
1562 #endif
1563
1564 /***************************************************************************
1565  Process a parametric option
1566 ***************************************************************************/
1567 static bool lp_do_parameter_parametric(struct service *service, 
1568                                        const char *pszParmName, 
1569                                        const char *pszParmValue, int flags)
1570 {
1571         struct param_opt *paramo, *data;
1572         char *name;
1573         TALLOC_CTX *mem_ctx;
1574
1575         while (isspace((unsigned char)*pszParmName)) {
1576                 pszParmName++;
1577         }
1578
1579         name = strdup(pszParmName);
1580         if (!name) return false;
1581
1582         strlower(name);
1583
1584         if (service == NULL) {
1585                 data = loadparm.Globals.param_opt;
1586                 mem_ctx = talloc_autofree_context();
1587         } else {
1588                 data = service->param_opt;
1589                 mem_ctx = service;
1590         }
1591
1592         /* Traverse destination */
1593         for (paramo=data; paramo; paramo=paramo->next) {
1594                 /* If we already have the option set, override it unless
1595                    it was a command line option and the new one isn't */
1596                 if (strcmp(paramo->key, name) == 0) {
1597                         if ((paramo->flags & FLAG_CMDLINE) &&
1598                             !(flags & FLAG_CMDLINE)) {
1599                                 return true;
1600                         }
1601
1602                         talloc_free(paramo->value);
1603                         paramo->value = talloc_strdup(paramo, pszParmValue);
1604                         paramo->flags = flags;
1605                         free(name);
1606                         return true;
1607                 }
1608         }
1609
1610         paramo = talloc(mem_ctx, struct param_opt);
1611         if (!paramo)
1612                 smb_panic("OOM");
1613         paramo->key = talloc_strdup(paramo, name);
1614         paramo->value = talloc_strdup(paramo, pszParmValue);
1615         paramo->flags = flags;
1616         if (service == NULL) {
1617                 DLIST_ADD(loadparm.Globals.param_opt, paramo);
1618         } else {
1619                 DLIST_ADD(service->param_opt, paramo);
1620         }
1621
1622         free(name);
1623         
1624         return true;
1625 }
1626
1627 static bool set_variable(TALLOC_CTX *mem_ctx, int parmnum, void *parm_ptr, 
1628                          const char *pszParmName, const char *pszParmValue)
1629 {
1630         int i;
1631         /* if it is a special case then go ahead */
1632         if (parm_table[parmnum].special) {
1633                 parm_table[parmnum].special(pszParmValue, (char **)parm_ptr);
1634                 return true;
1635         }
1636
1637         /* now switch on the type of variable it is */
1638         switch (parm_table[parmnum].type)
1639         {
1640                 case P_BOOL: {
1641                         bool b;
1642                         if (!set_boolean(pszParmValue, &b)) {
1643                                 DEBUG(0,("lp_do_parameter(%s): value is not boolean!\n", pszParmValue));
1644                                 return false;
1645                         }
1646                         *(int *)parm_ptr = b;
1647                         }
1648                         break;
1649
1650                 case P_INTEGER:
1651                         *(int *)parm_ptr = atoi(pszParmValue);
1652                         break;
1653
1654                 case P_OCTAL:
1655                         *(int *)parm_ptr = strtol(pszParmValue, NULL, 8);
1656                         break;
1657
1658                 case P_BYTES:
1659                 {
1660                         uint64_t val;
1661                         if (conv_str_size(pszParmValue, &val)) {
1662                                 if (val <= INT_MAX) {
1663                                         *(int *)parm_ptr = (int)val;
1664                                         break;
1665                                 }
1666                         }
1667
1668                         DEBUG(0,("lp_do_parameter(%s): value is not "
1669                             "a valid size specifier!\n", pszParmValue));
1670                         return false;
1671                 }
1672
1673                 case P_LIST:
1674                         *(const char ***)parm_ptr = str_list_make(mem_ctx, 
1675                                                                   pszParmValue, NULL);
1676                         break;
1677
1678                 case P_STRING:
1679                         string_set(mem_ctx, (char **)parm_ptr, pszParmValue);
1680                         break;
1681
1682                 case P_USTRING:
1683                         string_set(mem_ctx, (char **)parm_ptr, pszParmValue);
1684                         strupper(*(char **)parm_ptr);
1685                         break;
1686
1687                 case P_ENUM:
1688                         for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
1689                                 if (strequal
1690                                     (pszParmValue,
1691                                      parm_table[parmnum].enum_list[i].name)) {
1692                                         *(int *)parm_ptr =
1693                                                 parm_table[parmnum].
1694                                                 enum_list[i].value;
1695                                         break;
1696                                 }
1697                         }
1698                         if (!parm_table[parmnum].enum_list[i].name) {
1699                                 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n", 
1700                                          pszParmValue, pszParmName));
1701                                 return false;
1702                         }
1703                         break;
1704                 case P_SEP:
1705                         break;
1706         }
1707
1708         if (parm_table[parmnum].flags & FLAG_DEFAULT) {
1709                 parm_table[parmnum].flags &= ~FLAG_DEFAULT;
1710                 /* we have to also unset FLAG_DEFAULT on aliases */
1711                 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1712                         parm_table[i].flags &= ~FLAG_DEFAULT;
1713                 }
1714                 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1715                         parm_table[i].flags &= ~FLAG_DEFAULT;
1716                 }
1717         }
1718         return true;
1719 }
1720
1721
1722 bool lp_do_global_parameter(struct loadparm_context *lp_ctx, 
1723                             const char *pszParmName, const char *pszParmValue)
1724 {
1725         int parmnum = map_parameter(pszParmName);
1726         void *parm_ptr;
1727
1728         if (parmnum < 0) {
1729                 if (strchr(pszParmName, ':')) {
1730                         return lp_do_parameter_parametric(NULL, pszParmName, pszParmValue, 0);
1731                 }
1732                 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1733                 return true;
1734         }
1735
1736         if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1737                 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1738                           pszParmName));
1739         }
1740
1741         /* if the flag has been set on the command line, then don't allow override,
1742            but don't report an error */
1743         if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1744                 return true;
1745         }
1746
1747         parm_ptr = parm_table[parmnum].ptr;
1748
1749         return set_variable(talloc_autofree_context(), parmnum, parm_ptr, 
1750                             pszParmName, pszParmValue);
1751 }
1752
1753 bool lp_do_service_parameter(struct service *service, 
1754                              const char *pszParmName, const char *pszParmValue)
1755 {
1756         void *def_ptr = NULL;
1757         void *parm_ptr;
1758         int i;
1759         int parmnum = map_parameter(pszParmName);
1760
1761         if (parmnum < 0) {
1762                 if (strchr(pszParmName, ':')) {
1763                         return lp_do_parameter_parametric(service, pszParmName, pszParmValue, 0);
1764                 }
1765                 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1766                 return true;
1767         }
1768
1769         if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1770                 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1771                           pszParmName));
1772         }
1773
1774         /* if the flag has been set on the command line, then don't allow override,
1775            but don't report an error */
1776         if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1777                 return true;
1778         }
1779
1780         def_ptr = parm_table[parmnum].ptr;
1781
1782         if (parm_table[parmnum].class == P_GLOBAL) {
1783                 DEBUG(0,
1784                       ("Global parameter %s found in service section!\n",
1785                        pszParmName));
1786                 return true;
1787         }
1788         parm_ptr = ((char *)service) + PTR_DIFF(def_ptr, &sDefault);
1789
1790         if (!service->copymap)
1791                 init_copymap(service);
1792
1793         /* this handles the aliases - set the copymap for other 
1794          * entries with the same data pointer */
1795         for (i = 0; parm_table[i].label; i++)
1796                 if (parm_table[i].ptr == parm_table[parmnum].ptr)
1797                         service->copymap[i] = false;
1798
1799         return set_variable(service, parmnum, parm_ptr, pszParmName, 
1800                             pszParmValue);
1801 }
1802
1803 /***************************************************************************
1804  Process a parameter for a particular service number. If snum < 0
1805  then assume we are in the globals.
1806 ***************************************************************************/
1807 bool lp_do_parameter(struct service *service, const char *pszParmName, 
1808                      const char *pszParmValue)
1809 {
1810         if (service == NULL) {
1811                 return lp_do_global_parameter(&loadparm, pszParmName, 
1812                                               pszParmValue);
1813         } else {
1814                 return lp_do_service_parameter(service,
1815                                         pszParmName, pszParmValue);
1816         }
1817         return true;
1818 }
1819
1820 /***************************************************************************
1821  Process a parameter.
1822 ***************************************************************************/
1823
1824 static bool do_parameter(const char *pszParmName, const char *pszParmValue, 
1825                          void *userdata)
1826 {
1827         if (loadparm.bInGlobalSection) 
1828                 return lp_do_global_parameter(&loadparm, pszParmName, 
1829                                               pszParmValue);
1830         else 
1831                 return lp_do_service_parameter(loadparm.currentService,
1832                                                pszParmName, pszParmValue);
1833 }
1834
1835 /*
1836   variable argument do parameter
1837 */
1838 bool lp_do_global_parameter_var(struct loadparm_context *lp_ctx, const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4);
1839 bool lp_do_global_parameter_var(struct loadparm_context *lp_ctx, 
1840                                 const char *pszParmName, const char *fmt, ...) 
1841 {
1842         char *s;
1843         bool ret;
1844         va_list ap;
1845
1846         va_start(ap, fmt);      
1847         s = talloc_vasprintf(NULL, fmt, ap);
1848         va_end(ap);
1849         ret = lp_do_global_parameter(lp_ctx, pszParmName, s);
1850         talloc_free(s);
1851         return ret;
1852 }
1853
1854
1855 /*
1856   set a parameter from the commandline - this is called from command line parameter
1857   parsing code. It sets the parameter then marks the parameter as unable to be modified
1858   by smb.conf processing
1859 */
1860 bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
1861 {
1862         int parmnum = map_parameter(pszParmName);
1863         int i;
1864
1865         while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
1866
1867
1868         if (parmnum < 0 && strchr(pszParmName, ':')) {
1869                 /* set a parametric option */
1870                 return lp_do_parameter_parametric(NULL, pszParmName, pszParmValue, FLAG_CMDLINE);
1871         }
1872
1873         if (parmnum < 0) {
1874                 DEBUG(0,("Unknown option '%s'\n", pszParmName));
1875                 return false;
1876         }
1877
1878         /* reset the CMDLINE flag in case this has been called before */
1879         parm_table[parmnum].flags &= ~FLAG_CMDLINE;
1880
1881         if (!lp_do_parameter(NULL, pszParmName, pszParmValue)) {
1882                 return false;
1883         }
1884
1885         parm_table[parmnum].flags |= FLAG_CMDLINE;
1886
1887         /* we have to also set FLAG_CMDLINE on aliases */
1888         for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1889                 parm_table[i].flags |= FLAG_CMDLINE;
1890         }
1891         for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1892                 parm_table[i].flags |= FLAG_CMDLINE;
1893         }
1894
1895         return true;
1896 }
1897
1898 /*
1899   set a option from the commandline in 'a=b' format. Use to support --option
1900 */
1901 bool lp_set_option(const char *option)
1902 {
1903         char *p, *s;
1904         bool ret;
1905
1906         s = strdup(option);
1907         if (!s) {
1908                 return false;
1909         }
1910
1911         p = strchr(s, '=');
1912         if (!p) {
1913                 free(s);
1914                 return false;
1915         }
1916
1917         *p = 0;
1918
1919         ret = lp_set_cmdline(s, p+1);
1920         free(s);
1921         return ret;
1922 }
1923
1924
1925 #define BOOLSTR(b) ((b) ? "Yes" : "No")
1926
1927 /***************************************************************************
1928  Print a parameter of the specified type.
1929 ***************************************************************************/
1930
1931 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
1932 {
1933         int i;
1934         switch (p->type)
1935         {
1936                 case P_ENUM:
1937                         for (i = 0; p->enum_list[i].name; i++) {
1938                                 if (*(int *)ptr == p->enum_list[i].value) {
1939                                         fprintf(f, "%s",
1940                                                 p->enum_list[i].name);
1941                                         break;
1942                                 }
1943                         }
1944                         break;
1945
1946                 case P_BOOL:
1947                         fprintf(f, "%s", BOOLSTR((bool)*(int *)ptr));
1948                         break;
1949
1950                 case P_INTEGER:
1951                 case P_BYTES:
1952                         fprintf(f, "%d", *(int *)ptr);
1953                         break;
1954
1955                 case P_OCTAL:
1956                         fprintf(f, "0%o", *(int *)ptr);
1957                         break;
1958
1959                 case P_LIST:
1960                         if ((char ***)ptr && *(char ***)ptr) {
1961                                 char **list = *(char ***)ptr;
1962                                 
1963                                 for (; *list; list++)
1964                                         fprintf(f, "%s%s", *list,
1965                                                 ((*(list+1))?", ":""));
1966                         }
1967                         break;
1968
1969                 case P_STRING:
1970                 case P_USTRING:
1971                         if (*(char **)ptr) {
1972                                 fprintf(f, "%s", *(char **)ptr);
1973                         }
1974                         break;
1975                 case P_SEP:
1976                         break;
1977         }
1978 }
1979
1980 /***************************************************************************
1981  Check if two parameters are equal.
1982 ***************************************************************************/
1983
1984 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
1985 {
1986         switch (type) {
1987                 case P_BOOL:
1988                         return (*((int *)ptr1) == *((int *)ptr2));
1989
1990                 case P_INTEGER:
1991                 case P_OCTAL:
1992                 case P_BYTES:
1993                 case P_ENUM:
1994                         return (*((int *)ptr1) == *((int *)ptr2));
1995
1996                 case P_LIST:
1997                         return str_list_equal((const char **)(*(char ***)ptr1), 
1998                                               (const char **)(*(char ***)ptr2));
1999
2000                 case P_STRING:
2001                 case P_USTRING:
2002                 {
2003                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
2004                         if (p1 && !*p1)
2005                                 p1 = NULL;
2006                         if (p2 && !*p2)
2007                                 p2 = NULL;
2008                         return (p1 == p2 || strequal(p1, p2));
2009                 }
2010                 case P_SEP:
2011                         break;
2012         }
2013         return false;
2014 }
2015
2016 /***************************************************************************
2017  Process a new section (service). At this stage all sections are services.
2018  Later we'll have special sections that permit server parameters to be set.
2019  Returns True on success, False on failure. 
2020 ***************************************************************************/
2021
2022 static bool do_section(const char *pszSectionName, void *userdata)
2023 {
2024         bool bRetval;
2025         bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2026                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2027         bRetval = false;
2028
2029         /* if we've just struck a global section, note the fact. */
2030         loadparm.bInGlobalSection = isglobal;
2031
2032         /* check for multiple global sections */
2033         if (loadparm.bInGlobalSection) {
2034                 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2035                 return true;
2036         }
2037
2038         /* if we have a current service, tidy it up before moving on */
2039         bRetval = true;
2040
2041         if (loadparm.currentService != NULL)
2042                 bRetval = service_ok(loadparm.currentService);
2043
2044         /* if all is still well, move to the next record in the services array */
2045         if (bRetval) {
2046                 /* We put this here to avoid an odd message order if messages are */
2047                 /* issued by the post-processing of a previous section. */
2048                 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2049
2050                 if ((loadparm.currentService = add_a_service(&sDefault, pszSectionName))
2051                     == NULL) {
2052                         DEBUG(0, ("Failed to add a new service\n"));
2053                         return false;
2054                 }
2055         }
2056
2057         return bRetval;
2058 }
2059
2060
2061 /***************************************************************************
2062  Determine if a partcular base parameter is currentl set to the default value.
2063 ***************************************************************************/
2064
2065 static bool is_default(int i)
2066 {
2067         if (!defaults_saved)
2068                 return false;
2069         switch (parm_table[i].type) {
2070                 case P_LIST:
2071                         return str_list_equal((const char **)parm_table[i].def.lvalue, 
2072                                               (const char **)(*(char ***)parm_table[i].ptr));
2073                 case P_STRING:
2074                 case P_USTRING:
2075                         return strequal(parm_table[i].def.svalue,
2076                                         *(char **)parm_table[i].ptr);
2077                 case P_BOOL:
2078                         return parm_table[i].def.bvalue ==
2079                                 *(int *)parm_table[i].ptr;
2080                 case P_INTEGER:
2081                 case P_OCTAL:
2082                 case P_BYTES:
2083                 case P_ENUM:
2084                         return parm_table[i].def.ivalue ==
2085                                 *(int *)parm_table[i].ptr;
2086                 case P_SEP:
2087                         break;
2088         }
2089         return false;
2090 }
2091
2092 /***************************************************************************
2093 Display the contents of the global structure.
2094 ***************************************************************************/
2095
2096 static void dump_globals(FILE *f, bool show_defaults)
2097 {
2098         int i;
2099         struct param_opt *data;
2100         
2101         fprintf(f, "# Global parameters\n[global]\n");
2102
2103         for (i = 0; parm_table[i].label; i++)
2104                 if (parm_table[i].class == P_GLOBAL &&
2105                     parm_table[i].ptr &&
2106                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2107                         if (!show_defaults && (parm_table[i].flags & FLAG_DEFAULT)) 
2108                                 continue;
2109                         fprintf(f, "\t%s = ", parm_table[i].label);
2110                         print_parameter(&parm_table[i], parm_table[i].ptr, f);
2111                         fprintf(f, "\n");
2112         }
2113         if (loadparm.Globals.param_opt != NULL) {
2114                 for (data = loadparm.Globals.param_opt; data; 
2115                      data = data->next) {
2116                         fprintf(f, "\t%s = %s\n", data->key, data->value);
2117                 }
2118         }
2119
2120 }
2121
2122 /***************************************************************************
2123  Display the contents of a single services record.
2124 ***************************************************************************/
2125
2126 static void dump_a_service(struct service * pService, FILE * f)
2127 {
2128         int i;
2129         struct param_opt *data;
2130         
2131         if (pService != &sDefault)
2132                 fprintf(f, "\n[%s]\n", pService->szService);
2133
2134         for (i = 0; parm_table[i].label; i++)
2135                 if (parm_table[i].class == P_LOCAL &&
2136                     parm_table[i].ptr &&
2137                     (*parm_table[i].label != '-') &&
2138                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2139                         int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
2140
2141                         if (pService == &sDefault) {
2142                                 if (defaults_saved && is_default(i))
2143                                         continue;
2144                         } else {
2145                                 if (equal_parameter(parm_table[i].type,
2146                                                     ((char *)pService) +
2147                                                     pdiff,
2148                                                     ((char *)&sDefault) +
2149                                                     pdiff))
2150                                         continue;
2151                         }
2152
2153                         fprintf(f, "\t%s = ", parm_table[i].label);
2154                         print_parameter(&parm_table[i],
2155                                         ((char *)pService) + pdiff, f);
2156                         fprintf(f, "\n");
2157         }
2158         if (pService->param_opt != NULL) {
2159                 for (data = pService->param_opt; data; data = data->next) {
2160                         fprintf(f, "\t%s = %s\n", data->key, data->value);
2161                 }
2162         }
2163 }
2164
2165 bool lp_dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
2166 {
2167         struct service * pService = loadparm.ServicePtrs[snum];
2168         struct parm_struct *parm;
2169         void *ptr;
2170         
2171         parm = lp_parm_struct(parm_name);
2172         if (!parm) {
2173                 return false;
2174         }
2175         
2176         if (isGlobal)
2177                 ptr = parm->ptr;
2178         else
2179                 ptr = ((char *)pService) +
2180                         PTR_DIFF(parm->ptr, &sDefault);
2181         
2182         print_parameter(parm,
2183                         ptr, f);
2184         fprintf(f, "\n");
2185         return true;
2186 }
2187
2188 /***************************************************************************
2189  Return info about the next service  in a service. snum==-1 gives the globals.
2190  Return NULL when out of parameters.
2191 ***************************************************************************/
2192
2193 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
2194 {
2195         if (snum == -1) {
2196                 /* do the globals */
2197                 for (; parm_table[*i].label; (*i)++) {
2198                         if (parm_table[*i].class == P_SEPARATOR)
2199                                 return &parm_table[(*i)++];
2200
2201                         if (!parm_table[*i].ptr
2202                             || (*parm_table[*i].label == '-'))
2203                                 continue;
2204
2205                         if ((*i) > 0
2206                             && (parm_table[*i].ptr ==
2207                                 parm_table[(*i) - 1].ptr))
2208                                 continue;
2209
2210                         return &parm_table[(*i)++];
2211                 }
2212         } else {
2213                 struct service *pService = loadparm.ServicePtrs[snum];
2214
2215                 for (; parm_table[*i].label; (*i)++) {
2216                         if (parm_table[*i].class == P_SEPARATOR)
2217                                 return &parm_table[(*i)++];
2218
2219                         if (parm_table[*i].class == P_LOCAL &&
2220                             parm_table[*i].ptr &&
2221                             (*parm_table[*i].label != '-') &&
2222                             ((*i) == 0 ||
2223                              (parm_table[*i].ptr !=
2224                               parm_table[(*i) - 1].ptr)))
2225                         {
2226                                 int pdiff =
2227                                         PTR_DIFF(parm_table[*i].ptr,
2228                                                  &sDefault);
2229
2230                                 if (allparameters ||
2231                                     !equal_parameter(parm_table[*i].type,
2232                                                      ((char *)pService) +
2233                                                      pdiff,
2234                                                      ((char *)&sDefault) +
2235                                                      pdiff))
2236                                 {
2237                                         return &parm_table[(*i)++];
2238                                 }
2239                         }
2240                 }
2241         }
2242
2243         return NULL;
2244 }
2245
2246
2247 /***************************************************************************
2248  Return TRUE if the passed service number is within range.
2249 ***************************************************************************/
2250
2251 bool lp_snum_ok(int iService)
2252 {
2253         return (LP_SNUM_OK(iService) && loadparm.ServicePtrs[iService]->bAvailable);
2254 }
2255
2256 /***************************************************************************
2257  Auto-load some home services.
2258 ***************************************************************************/
2259
2260 static void lp_add_auto_services(const char *str)
2261 {
2262         return;
2263 }
2264
2265 /***************************************************************************
2266  Have we loaded a services file yet?
2267 ***************************************************************************/
2268
2269 bool lp_loaded(void)
2270 {
2271         return bLoaded;
2272 }
2273
2274 /***************************************************************************
2275  Unload unused services.
2276 ***************************************************************************/
2277
2278 void lp_killunused(struct smbsrv_connection *smb, bool (*snumused) (struct smbsrv_connection *, int))
2279 {
2280         int i;
2281         for (i = 0; i < loadparm.iNumServices; i++) {
2282                 if (!VALID(i))
2283                         continue;
2284
2285                 if (!snumused || !snumused(smb, i)) {
2286                         talloc_free(loadparm.ServicePtrs[i]);
2287                         loadparm.ServicePtrs[i] = NULL;
2288                 }
2289         }
2290 }
2291
2292 /***************************************************************************
2293  Unload a service.
2294 ***************************************************************************/
2295
2296 void lp_killservice(int iServiceIn)
2297 {
2298         if (VALID(iServiceIn)) {
2299                 talloc_free(loadparm.ServicePtrs[iServiceIn]);
2300                 loadparm.ServicePtrs[iServiceIn] = NULL;
2301         }
2302 }
2303
2304 /***************************************************************************
2305  Initialise the global parameter structure.
2306 ***************************************************************************/
2307 bool loadparm_init(struct loadparm_context *lp_ctx)
2308 {
2309         int i;
2310         char *myname;
2311
2312         DEBUG(3, ("Initialising global parameters\n"));
2313
2314         for (i = 0; parm_table[i].label; i++) {
2315                 if ((parm_table[i].type == P_STRING ||
2316                      parm_table[i].type == P_USTRING) &&
2317                     parm_table[i].ptr &&
2318                     !(parm_table[i].flags & FLAG_CMDLINE)) {
2319                         string_set(talloc_autofree_context(), 
2320                                    (char **)parm_table[i].ptr, "");
2321                 }
2322         }
2323
2324         lp_do_global_parameter(lp_ctx, "config file", dyn_CONFIGFILE);
2325
2326         lp_do_global_parameter(lp_ctx, "share backend", "classic");
2327         
2328         lp_do_global_parameter(lp_ctx, "server role", "standalone");
2329
2330         /* options that can be set on the command line must be initialised via
2331            the slower lp_do_global_parameter() to ensure that FLAG_CMDLINE is obeyed */
2332 #ifdef TCP_NODELAY
2333         lp_do_global_parameter(lp_ctx, "socket options", "TCP_NODELAY");
2334 #endif
2335         lp_do_global_parameter(lp_ctx, "workgroup", DEFAULT_WORKGROUP);
2336         myname = get_myname();
2337         lp_do_global_parameter(lp_ctx, "netbios name", myname);
2338         SAFE_FREE(myname);
2339         lp_do_global_parameter(lp_ctx, "name resolve order", "lmhosts wins host bcast");
2340
2341         lp_do_global_parameter(lp_ctx, "fstype", FSTYPE_STRING);
2342         lp_do_global_parameter(lp_ctx, "ntvfs handler", "unixuid default");
2343         lp_do_global_parameter(lp_ctx, "max connections", "-1");
2344
2345         lp_do_global_parameter(lp_ctx, "dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup unixinfo");
2346         lp_do_global_parameter(lp_ctx, "server services", "smb rpc nbt wrepl ldap cldap web kdc drepl winbind");
2347         lp_do_global_parameter(lp_ctx, "ntptr providor", "simple_ldb");
2348         lp_do_global_parameter(lp_ctx, "auth methods:domain controller", "anonymous sam_ignoredomain");
2349         lp_do_global_parameter(lp_ctx, "auth methods:member server", "anonymous sam winbind");
2350         lp_do_global_parameter(lp_ctx, "auth methods:standalone", "anonymous sam_ignoredomain");
2351         lp_do_global_parameter(lp_ctx, "private dir", dyn_PRIVATE_DIR);
2352         lp_do_global_parameter(lp_ctx, "sam database", "sam.ldb");
2353         lp_do_global_parameter(lp_ctx, "secrets database", "secrets.ldb");
2354         lp_do_global_parameter(lp_ctx, "spoolss database", "spoolss.ldb");
2355         lp_do_global_parameter(lp_ctx, "wins config database", "wins_config.ldb");
2356         lp_do_global_parameter(lp_ctx, "wins database", "wins.ldb");
2357         lp_do_global_parameter(lp_ctx, "registry:HKEY_LOCAL_MACHINE", "hklm.ldb");
2358
2359         /* This hive should be dynamically generated by Samba using
2360            data from the sam, but for the moment leave it in a tdb to
2361            keep regedt32 from popping up an annoying dialog. */
2362         lp_do_global_parameter(lp_ctx, "registry:HKEY_USERS", "hku.ldb");
2363         
2364         /* using UTF8 by default allows us to support all chars */
2365         lp_do_global_parameter(lp_ctx, "unix charset", "UTF8");
2366
2367         /* Use codepage 850 as a default for the dos character set */
2368         lp_do_global_parameter(lp_ctx, "dos charset", "CP850");
2369
2370         /*
2371          * Allow the default PASSWD_CHAT to be overridden in local.h.
2372          */
2373         lp_do_global_parameter(lp_ctx, "passwd chat", DEFAULT_PASSWD_CHAT);
2374
2375         lp_do_global_parameter(lp_ctx, "pid directory", dyn_PIDDIR);
2376         lp_do_global_parameter(lp_ctx, "lock dir", dyn_LOCKDIR);
2377         lp_do_global_parameter(lp_ctx, "modules dir", dyn_MODULESDIR);
2378         lp_do_global_parameter(lp_ctx, "ncalrpc dir", dyn_NCALRPCDIR);
2379
2380         lp_do_global_parameter(lp_ctx, "socket address", "0.0.0.0");
2381         lp_do_global_parameter_var(lp_ctx, "server string", 
2382                                    "Samba %s", SAMBA_VERSION_STRING);
2383
2384         lp_do_global_parameter_var(lp_ctx, "announce version", "%d.%d", 
2385                          DEFAULT_MAJOR_VERSION,
2386                          DEFAULT_MINOR_VERSION);
2387
2388         lp_do_global_parameter(lp_ctx, "password server", "*");
2389
2390         lp_do_global_parameter(lp_ctx, "max mux", "50");
2391         lp_do_global_parameter(lp_ctx, "max xmit", "12288");
2392         lp_do_global_parameter(lp_ctx, "password level", "0");
2393         lp_do_global_parameter(lp_ctx, "LargeReadwrite", "True");
2394         lp_do_global_parameter(lp_ctx, "server min protocol", "CORE");
2395         lp_do_global_parameter(lp_ctx, "server max protocol", "NT1");
2396         lp_do_global_parameter(lp_ctx, "client min protocol", "CORE");
2397         lp_do_global_parameter(lp_ctx, "client max protocol", "NT1");
2398         lp_do_global_parameter(lp_ctx, "security", "USER");
2399         lp_do_global_parameter(lp_ctx, "paranoid server security", "True");
2400         lp_do_global_parameter(lp_ctx, "EncryptPasswords", "True");
2401         lp_do_global_parameter(lp_ctx, "ReadRaw", "True");
2402         lp_do_global_parameter(lp_ctx, "WriteRaw", "True");
2403         lp_do_global_parameter(lp_ctx, "NullPasswords", "False");
2404         lp_do_global_parameter(lp_ctx, "ObeyPamRestrictions", "False");
2405         lp_do_global_parameter(lp_ctx, "announce as", "NT SERVER");
2406
2407         lp_do_global_parameter(lp_ctx, "TimeServer", "False");
2408         lp_do_global_parameter(lp_ctx, "BindInterfacesOnly", "False");
2409         lp_do_global_parameter(lp_ctx, "Unicode", "True");
2410         lp_do_global_parameter(lp_ctx, "ClientLanManAuth", "True");
2411         lp_do_global_parameter(lp_ctx, "LanmanAuth", "True");
2412         lp_do_global_parameter(lp_ctx, "NTLMAuth", "True");
2413         lp_do_global_parameter(lp_ctx, "client use spnego principal", "False");
2414         
2415         lp_do_global_parameter(lp_ctx, "UnixExtensions", "False");
2416
2417         lp_do_global_parameter(lp_ctx, "PreferredMaster", "Auto");
2418         lp_do_global_parameter(lp_ctx, "LocalMaster", "True");
2419
2420         lp_do_global_parameter(lp_ctx, "wins support", "False");
2421         lp_do_global_parameter(lp_ctx, "dns proxy", "True");
2422
2423         lp_do_global_parameter(lp_ctx, "winbind separator", "\\");
2424         lp_do_global_parameter(lp_ctx, "winbind sealed pipes", "True");
2425         lp_do_global_parameter(lp_ctx, "winbindd socket directory", dyn_WINBINDD_SOCKET_DIR);
2426         lp_do_global_parameter(lp_ctx, "template shell", "/bin/false");
2427         lp_do_global_parameter(lp_ctx, "template homedir", "/home/%WORKGROUP%/%ACCOUNTNAME%");
2428
2429         lp_do_global_parameter(lp_ctx, "client signing", "Yes");
2430         lp_do_global_parameter(lp_ctx, "server signing", "auto");
2431
2432         lp_do_global_parameter(lp_ctx, "use spnego", "True");
2433
2434         lp_do_global_parameter(lp_ctx, "smb ports", "445 139");
2435         lp_do_global_parameter(lp_ctx, "nbt port", "137");
2436         lp_do_global_parameter(lp_ctx, "dgram port", "138");
2437         lp_do_global_parameter(lp_ctx, "cldap port", "389");
2438         lp_do_global_parameter(lp_ctx, "krb5 port", "88");
2439         lp_do_global_parameter(lp_ctx, "kpasswd port", "464");
2440         lp_do_global_parameter(lp_ctx, "web port", "901");
2441         lp_do_global_parameter(lp_ctx, "web application directory", dyn_WEBAPPSDIR);
2442         lp_do_global_parameter(lp_ctx, "jsonrpc services directory", dyn_SERVICESDIR);
2443
2444         lp_do_global_parameter(lp_ctx, "nt status support", "True");
2445
2446         lp_do_global_parameter(lp_ctx, "max wins ttl", "518400"); /* 6 days */
2447         lp_do_global_parameter(lp_ctx, "min wins ttl", "10");
2448
2449         lp_do_global_parameter(lp_ctx, "tls enabled", "True");
2450         lp_do_global_parameter(lp_ctx, "tls keyfile", "tls/key.pem");
2451         lp_do_global_parameter(lp_ctx, "tls certfile", "tls/cert.pem");
2452         lp_do_global_parameter(lp_ctx, "tls cafile", "tls/ca.pem");
2453         lp_do_global_parameter_var(lp_ctx, "js include", "%s", dyn_JSDIR);
2454         lp_do_global_parameter_var(lp_ctx, "setup directory", "%s", 
2455                                    dyn_SETUPDIR);
2456
2457         for (i = 0; parm_table[i].label; i++) {
2458                 if (!(parm_table[i].flags & FLAG_CMDLINE)) {
2459                         parm_table[i].flags |= FLAG_DEFAULT;
2460                 }
2461         }
2462
2463         return true;
2464 }
2465
2466 /***************************************************************************
2467  Load the services array from the services file. Return True on success, 
2468  False on failure.
2469 ***************************************************************************/
2470
2471 bool lp_load(void)
2472 {
2473         char *n2;
2474         bool bRetval;
2475         struct param_opt *data;
2476
2477         bRetval = false;
2478
2479         if (loadparm.Globals.param_opt != NULL) {
2480                 struct param_opt *next;
2481                 for (data=loadparm.Globals.param_opt; data; data=next) {
2482                         next = data->next;
2483                         if (data->flags & FLAG_CMDLINE) continue;
2484                         DLIST_REMOVE(loadparm.Globals.param_opt, data);
2485                         talloc_free(data);
2486                 }
2487         }
2488
2489         if (!loadparm_init(&loadparm))
2490                 return false;
2491         
2492         loadparm.bInGlobalSection = true;
2493         n2 = standard_sub_basic(talloc_autofree_context(), lp_configfile());
2494         DEBUG(2, ("lp_load: refreshing parameters from %s\n", n2));
2495         
2496         add_to_file_list(lp_configfile(), n2);
2497
2498         /* We get sections first, so have to start 'behind' to make up */
2499         loadparm.currentService = NULL;
2500         bRetval = pm_process(n2, do_section, do_parameter, NULL);
2501
2502         /* finish up the last section */
2503         DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
2504         if (bRetval)
2505                 if (loadparm.currentService != NULL)
2506                         bRetval = service_ok(loadparm.currentService);
2507
2508         lp_add_auto_services(lp_auto_services());
2509
2510         lp_add_hidden("IPC$", "IPC");
2511         lp_add_hidden("ADMIN$", "DISK");
2512
2513         bLoaded = true;
2514
2515         if (!loadparm.Globals.szWINSservers && loadparm.Globals.bWINSsupport) {
2516                 lp_do_parameter(NULL, "wins server", "127.0.0.1");
2517         }
2518
2519         init_iconv();
2520
2521         return bRetval;
2522 }
2523
2524 /***************************************************************************
2525  Return the max number of services.
2526 ***************************************************************************/
2527
2528 int lp_numservices(void)
2529 {
2530         return loadparm.iNumServices;
2531 }
2532
2533 /***************************************************************************
2534 Display the contents of the services array in human-readable form.
2535 ***************************************************************************/
2536
2537 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
2538 {
2539         int iService;
2540
2541         if (show_defaults)
2542                 defaults_saved = false;
2543
2544         dump_globals(f, show_defaults);
2545
2546         dump_a_service(&sDefault, f);
2547
2548         for (iService = 0; iService < maxtoprint; iService++)
2549                 lp_dump_one(f, show_defaults, loadparm.ServicePtrs[iService]);
2550 }
2551
2552 /***************************************************************************
2553 Display the contents of one service in human-readable form.
2554 ***************************************************************************/
2555
2556 void lp_dump_one(FILE *f, bool show_defaults, struct service *service)
2557 {
2558         if (service != NULL) {
2559                 if (service->szService[0] == '\0')
2560                         return;
2561                 dump_a_service(service, f);
2562         }
2563 }
2564
2565 struct service *lp_servicebynum(int snum)
2566 {
2567         return loadparm.ServicePtrs[snum];
2568 }
2569
2570 struct service *lp_service(const char *service_name)
2571 {
2572         int snum = lp_servicenumber(service_name);
2573         if (snum < 0)
2574                 return NULL;
2575         return loadparm.ServicePtrs[snum];
2576 }
2577
2578 /***************************************************************************
2579 Return the number of the service with the given name, or -1 if it doesn't
2580 exist. Note that this is a DIFFERENT ANIMAL from the internal function
2581 getservicebyname()! This works ONLY if all services have been loaded, and
2582 does not copy the found service.
2583 ***************************************************************************/
2584
2585 int lp_servicenumber(const char *pszServiceName)
2586 {
2587         int iService;
2588         char *serviceName;
2589  
2590  
2591         for (iService = loadparm.iNumServices - 1; iService >= 0; iService--) {
2592                 if (VALID(iService) && loadparm.ServicePtrs[iService]->szService) {
2593                         /*
2594                          * The substitution here is used to support %U is
2595                          * service names
2596                          */
2597                         serviceName = standard_sub_basic(loadparm.ServicePtrs[iService],
2598                                                          loadparm.ServicePtrs[iService]->szService);
2599                         if (strequal(serviceName, pszServiceName))
2600                                 break;
2601                 }
2602         }
2603
2604         if (iService < 0)
2605                 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
2606
2607         return iService;
2608 }
2609
2610 int lp_find_valid_service(const char *pszServiceName)
2611 {
2612         int iService;
2613
2614         iService = lp_servicenumber(pszServiceName);
2615
2616         if (iService >= 0 && !lp_snum_ok(iService)) {
2617                 DEBUG(0,("lp_find_valid_service: Invalid snum %d for '%s'\n",iService, pszServiceName));
2618                 iService = -1;
2619         }
2620
2621         if (iService == -1) {
2622                 DEBUG(3,("lp_find_valid_service: failed to find service '%s'\n", pszServiceName));
2623         }
2624
2625         return iService;
2626 }
2627
2628 /*******************************************************************
2629  A useful volume label function. 
2630 ********************************************************************/
2631 const char *volume_label(struct service *service)
2632 {
2633         const char *ret = lp_volume(service);
2634         if (!*ret)
2635                 return lp_servicename(service);
2636         return ret;
2637 }
2638
2639
2640 /***********************************************************
2641  If we are PDC then prefer us as DMB
2642 ************************************************************/
2643
2644 bool lp_domain_logons(void)
2645 {
2646         return (lp_server_role() == ROLE_DOMAIN_CONTROLLER);
2647 }
2648
2649 /*******************************************************************
2650  Remove a service.
2651 ********************************************************************/
2652
2653 void lp_remove_service(int snum)
2654 {
2655         loadparm.ServicePtrs[snum] = NULL;
2656 }
2657
2658 const char *lp_printername(struct service *service)
2659 {
2660         const char *ret = _lp_printername(service);
2661         if (ret == NULL || (ret != NULL && *ret == '\0'))
2662                 ret = lp_const_servicename(service);
2663
2664         return ret;
2665 }
2666
2667
2668 /*******************************************************************
2669  Return the max print jobs per queue.
2670 ********************************************************************/
2671
2672 int lp_maxprintjobs(int snum)
2673 {
2674         int maxjobs = LP_SNUM_OK(snum) ? loadparm.ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
2675         if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
2676                 maxjobs = PRINT_MAX_JOBID - 1;
2677
2678         return maxjobs;
2679 }