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