2 Unix SMB/CIFS implementation.
3 Parameter loading functions
4 Copyright (C) Karl Auer 1993-1998
6 Largely re-written by Andrew Tridgell, September 1994
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
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.
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.
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/>.
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.
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
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
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"
67 static bool bLoaded = false;
69 #define standard_sub_basic talloc_strdup
71 static bool do_parameter(const char *, const char *, void *);
72 static bool defaults_saved = false;
75 struct param_opt *prev, *next;
82 * This structure describes global (ie., server-wide) parameters.
84 struct loadparm_global
86 enum server_role server_role;
88 const char **smb_ports;
97 const char *szConfigFile;
102 char *szWINS_CONFIG_URL;
105 const char **jsInclude;
106 char *jsonrpcServicesDir;
107 const char **szPasswordServers;
108 char *szSocketOptions;
110 const char **szWINSservers;
111 const char **szInterfaces;
112 char *szSocketAddress;
113 char *szAnnounceVersion; /* This is initialised in init_globals */
116 const char **szNetbiosAliases;
117 char *szNetbiosScope;
118 char *szDomainOtherSIDs;
119 const char **szNameResolveOrder;
120 const char **dcerpc_ep_servers;
121 const char **server_services;
122 char *ntptr_providor;
123 char *szWinbindSeparator;
124 char *szWinbinddSocketDirectory;
125 char *szTemplateShell;
126 char *szTemplateHomedir;
127 int bWinbindSealedPipes;
128 char *swat_directory;
143 int paranoid_server_security;
146 int announce_as; /* This is initialised in init_globals */
153 char *socket_options;
158 int bPreferredMaster;
159 int bEncryptPasswords;
161 int bObeyPamRestrictions;
166 int bBindInterfacesOnly;
168 int bNTStatusSupport;
174 int bClientPlaintextAuth;
175 int bClientLanManAuth;
176 int bClientNTLMv2Auth;
177 int client_use_spnego_principal;
183 struct param_opt *param_opt;
188 * This structure describes a single service.
190 struct loadparm_service
202 char **ntvfs_handler;
215 int iCreate_force_mode;
222 struct param_opt *param_opt;
224 char dummy[3]; /* for alignment */
228 /* This is a default service used to prime a services structure */
229 static struct loadparm_service sDefault = {
234 .szPrintername = NULL,
235 .szHostsallow = NULL,
240 .ntvfs_handler = NULL,
241 .iMaxPrintJobs = 1000,
242 .iMaxConnections = 0,
248 .bMap_system = false,
249 .bMap_hidden = false,
250 .bMap_archive = true,
251 .bStrictLocking = true,
252 .iCreate_mask = 0744,
253 .iCreate_force_mode = 0000,
255 .iDir_force_mode = 0000,
258 .bStrictSync = false,
259 .bCIFileSystem = false,
262 /* local variables */
263 static struct loadparm_context {
264 struct loadparm_global Globals;
265 struct loadparm_service **ServicePtrs;
267 struct loadparm_service *currentService;
268 bool bInGlobalSection;
270 struct file_lists *next;
277 struct loadparm_context *global_loadparm = &loadparm;
279 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
281 /* prototypes for the special type handlers */
282 static bool handle_include(struct loadparm_context *lp_ctx,
283 const char *pszParmValue, char **ptr);
284 static bool handle_copy(struct loadparm_context *lp_ctx,
285 const char *pszParmValue, char **ptr);
287 static const struct enum_list enum_protocol[] = {
288 {PROTOCOL_SMB2, "SMB2"},
289 {PROTOCOL_NT1, "NT1"},
290 {PROTOCOL_LANMAN2, "LANMAN2"},
291 {PROTOCOL_LANMAN1, "LANMAN1"},
292 {PROTOCOL_CORE, "CORE"},
293 {PROTOCOL_COREPLUS, "COREPLUS"},
294 {PROTOCOL_COREPLUS, "CORE+"},
298 static const struct enum_list enum_security[] = {
299 {SEC_SHARE, "SHARE"},
304 static const struct enum_list enum_announce_as[] = {
305 {ANNOUNCE_AS_NT_SERVER, "NT"},
306 {ANNOUNCE_AS_NT_SERVER, "NT Server"},
307 {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"},
308 {ANNOUNCE_AS_WIN95, "win95"},
309 {ANNOUNCE_AS_WFW, "WfW"},
313 static const struct enum_list enum_bool_auto[] = {
324 /* Client-side offline caching policy types */
325 #define CSC_POLICY_MANUAL 0
326 #define CSC_POLICY_DOCUMENTS 1
327 #define CSC_POLICY_PROGRAMS 2
328 #define CSC_POLICY_DISABLE 3
330 static const struct enum_list enum_csc_policy[] = {
331 {CSC_POLICY_MANUAL, "manual"},
332 {CSC_POLICY_DOCUMENTS, "documents"},
333 {CSC_POLICY_PROGRAMS, "programs"},
334 {CSC_POLICY_DISABLE, "disable"},
338 /* SMB signing types. */
339 static const struct enum_list enum_smb_signing_vals[] = {
340 {SMB_SIGNING_OFF, "No"},
341 {SMB_SIGNING_OFF, "False"},
342 {SMB_SIGNING_OFF, "0"},
343 {SMB_SIGNING_OFF, "Off"},
344 {SMB_SIGNING_OFF, "disabled"},
345 {SMB_SIGNING_SUPPORTED, "Yes"},
346 {SMB_SIGNING_SUPPORTED, "True"},
347 {SMB_SIGNING_SUPPORTED, "1"},
348 {SMB_SIGNING_SUPPORTED, "On"},
349 {SMB_SIGNING_SUPPORTED, "enabled"},
350 {SMB_SIGNING_REQUIRED, "required"},
351 {SMB_SIGNING_REQUIRED, "mandatory"},
352 {SMB_SIGNING_REQUIRED, "force"},
353 {SMB_SIGNING_REQUIRED, "forced"},
354 {SMB_SIGNING_REQUIRED, "enforced"},
355 {SMB_SIGNING_AUTO, "auto"},
359 static const struct enum_list enum_server_role[] = {
360 {ROLE_STANDALONE, "standalone"},
361 {ROLE_DOMAIN_MEMBER, "member server"},
362 {ROLE_DOMAIN_CONTROLLER, "domain controller"},
367 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
369 * Note: We have a flag called FLAG_DEVELOPER but is not used at this time, it
370 * is implied in current control logic. This may change at some later time. A
371 * flag value of 0 means - show as development option only.
373 * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
374 * screen in SWAT. This is used to exclude parameters as well as to squash all
375 * parameters that have been duplicated by pseudonyms.
377 static struct parm_struct parm_table[] = {
378 {"Base Options", P_SEP, P_SEPARATOR},
380 {"config file", P_STRING, P_GLOBAL, &loadparm.Globals.szConfigFile, NULL, NULL, FLAG_HIDE},
382 {"server role", P_ENUM, P_GLOBAL, &loadparm.Globals.server_role, NULL, enum_server_role, FLAG_BASIC},
384 {"dos charset", P_STRING, P_GLOBAL, &dos_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
385 {"unix charset", P_STRING, P_GLOBAL, &unix_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
386 {"ncalrpc dir", P_STRING, P_GLOBAL, &loadparm.Globals.ncalrpc_dir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
387 {"display charset", P_STRING, P_GLOBAL, &display_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
388 {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
389 {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
390 {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE},
391 {"workgroup", P_USTRING, P_GLOBAL, &loadparm.Globals.szWorkgroup, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
392 {"realm", P_STRING, P_GLOBAL, &loadparm.Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
393 {"netbios name", P_USTRING, P_GLOBAL, &loadparm.Globals.szNetbiosName, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
394 {"netbios aliases", P_LIST, P_GLOBAL, &loadparm.Globals.szNetbiosAliases, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
395 {"netbios scope", P_USTRING, P_GLOBAL, &loadparm.Globals.szNetbiosScope, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
396 {"server string", P_STRING, P_GLOBAL, &loadparm.Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
397 {"interfaces", P_LIST, P_GLOBAL, &loadparm.Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
398 {"bind interfaces only", P_BOOL, P_GLOBAL, &loadparm.Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
399 {"ntvfs handler", P_LIST, P_LOCAL, &sDefault.ntvfs_handler, NULL, NULL, FLAG_ADVANCED},
400 {"ntptr providor", P_STRING, P_GLOBAL, &loadparm.Globals.ntptr_providor, NULL, NULL, FLAG_ADVANCED},
401 {"dcerpc endpoint servers", P_LIST, P_GLOBAL, &loadparm.Globals.dcerpc_ep_servers, NULL, NULL, FLAG_ADVANCED},
402 {"server services", P_LIST, P_GLOBAL, &loadparm.Globals.server_services, NULL, NULL, FLAG_ADVANCED},
404 {"Security Options", P_SEP, P_SEPARATOR},
406 {"security", P_ENUM, P_GLOBAL, &loadparm.Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
407 {"encrypt passwords", P_BOOL, P_GLOBAL, &loadparm.Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
408 {"null passwords", P_BOOL, P_GLOBAL, &loadparm.Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
409 {"obey pam restrictions", P_BOOL, P_GLOBAL, &loadparm.Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
410 {"password server", P_LIST, P_GLOBAL, &loadparm.Globals.szPasswordServers, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
411 {"sam database", P_STRING, P_GLOBAL, &loadparm.Globals.szSAM_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
412 {"secrets database", P_STRING, P_GLOBAL, &loadparm.Globals.szSECRETS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
413 {"spoolss database", P_STRING, P_GLOBAL, &loadparm.Globals.szSPOOLSS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
414 {"wins config database", P_STRING, P_GLOBAL, &loadparm.Globals.szWINS_CONFIG_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
415 {"wins database", P_STRING, P_GLOBAL, &loadparm.Globals.szWINS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
416 {"private dir", P_STRING, P_GLOBAL, &loadparm.Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
417 {"passwd chat", P_STRING, P_GLOBAL, &loadparm.Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
418 {"password level", P_INTEGER, P_GLOBAL, &loadparm.Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
419 {"lanman auth", P_BOOL, P_GLOBAL, &loadparm.Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
420 {"ntlm auth", P_BOOL, P_GLOBAL, &loadparm.Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
421 {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &loadparm.Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
422 {"client lanman auth", P_BOOL, P_GLOBAL, &loadparm.Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
423 {"client plaintext auth", P_BOOL, P_GLOBAL, &loadparm.Globals.bClientPlaintextAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
424 {"client use spnego principal", P_BOOL, P_GLOBAL, &loadparm.Globals.client_use_spnego_principal, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
426 {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE},
428 {"create mask", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
429 {"force create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
430 {"directory mask", P_OCTAL, P_LOCAL, &sDefault.iDir_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
431 {"force directory mode", P_OCTAL, P_LOCAL, &sDefault.iDir_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
433 {"hosts allow", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
434 {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
436 {"Logging Options", P_SEP, P_SEPARATOR},
438 {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
439 {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_HIDE},
440 {"log file", P_STRING, P_GLOBAL, &logfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
442 {"Protocol Options", P_SEP, P_SEPARATOR},
444 {"smb ports", P_LIST, P_GLOBAL, &loadparm.Globals.smb_ports, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
445 {"nbt port", P_INTEGER, P_GLOBAL, &loadparm.Globals.nbt_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
446 {"dgram port", P_INTEGER, P_GLOBAL, &loadparm.Globals.dgram_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
447 {"cldap port", P_INTEGER, P_GLOBAL, &loadparm.Globals.cldap_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
448 {"krb5 port", P_INTEGER, P_GLOBAL, &loadparm.Globals.krb5_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
449 {"kpasswd port", P_INTEGER, P_GLOBAL, &loadparm.Globals.kpasswd_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
450 {"web port", P_INTEGER, P_GLOBAL, &loadparm.Globals.web_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
451 {"tls enabled", P_BOOL, P_GLOBAL, &loadparm.Globals.tls_enabled, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
452 {"tls keyfile", P_STRING, P_GLOBAL, &loadparm.Globals.tls_keyfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
453 {"tls certfile", P_STRING, P_GLOBAL, &loadparm.Globals.tls_certfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
454 {"tls cafile", P_STRING, P_GLOBAL, &loadparm.Globals.tls_cafile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
455 {"tls crlfile", P_STRING, P_GLOBAL, &loadparm.Globals.tls_crlfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
456 {"tls dh params file", P_STRING, P_GLOBAL, &loadparm.Globals.tls_dhpfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
457 {"swat directory", P_STRING, P_GLOBAL, &loadparm.Globals.swat_directory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
458 {"large readwrite", P_BOOL, P_GLOBAL, &loadparm.Globals.bLargeReadwrite, NULL, NULL, FLAG_DEVELOPER},
459 {"server max protocol", P_ENUM, P_GLOBAL, &loadparm.Globals.srv_maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
460 {"server min protocol", P_ENUM, P_GLOBAL, &loadparm.Globals.srv_minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
461 {"client max protocol", P_ENUM, P_GLOBAL, &loadparm.Globals.cli_maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
462 {"client min protocol", P_ENUM, P_GLOBAL, &loadparm.Globals.cli_minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
463 {"unicode", P_BOOL, P_GLOBAL, &loadparm.Globals.bUnicode, NULL, NULL, FLAG_DEVELOPER},
464 {"read raw", P_BOOL, P_GLOBAL, &loadparm.Globals.bReadRaw, NULL, NULL, FLAG_DEVELOPER},
465 {"write raw", P_BOOL, P_GLOBAL, &loadparm.Globals.bWriteRaw, NULL, NULL, FLAG_DEVELOPER},
466 {"disable netbios", P_BOOL, P_GLOBAL, &loadparm.Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
468 {"nt status support", P_BOOL, P_GLOBAL, &loadparm.Globals.bNTStatusSupport, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
470 {"announce version", P_STRING, P_GLOBAL, &loadparm.Globals.szAnnounceVersion, NULL, NULL, FLAG_DEVELOPER},
471 {"announce as", P_ENUM, P_GLOBAL, &loadparm.Globals.announce_as, NULL, enum_announce_as, FLAG_DEVELOPER},
472 {"max mux", P_INTEGER, P_GLOBAL, &loadparm.Globals.max_mux, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
473 {"max xmit", P_BYTES, P_GLOBAL, &loadparm.Globals.max_xmit, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
475 {"name resolve order", P_LIST, P_GLOBAL, &loadparm.Globals.szNameResolveOrder, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
476 {"max wins ttl", P_INTEGER, P_GLOBAL, &loadparm.Globals.max_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
477 {"min wins ttl", P_INTEGER, P_GLOBAL, &loadparm.Globals.min_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
478 {"time server", P_BOOL, P_GLOBAL, &loadparm.Globals.bTimeServer, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
479 {"unix extensions", P_BOOL, P_GLOBAL, &loadparm.Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
480 {"use spnego", P_BOOL, P_GLOBAL, &loadparm.Globals.bUseSpnego, NULL, NULL, FLAG_DEVELOPER},
481 {"server signing", P_ENUM, P_GLOBAL, &loadparm.Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
482 {"client signing", P_ENUM, P_GLOBAL, &loadparm.Globals.client_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
483 {"rpc big endian", P_BOOL, P_GLOBAL, &loadparm.Globals.bRpcBigEndian, NULL, NULL, FLAG_DEVELOPER},
485 {"Tuning Options", P_SEP, P_SEPARATOR},
487 {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL, NULL, FLAG_SHARE},
488 {"paranoid server security", P_BOOL, P_GLOBAL, &loadparm.Globals.paranoid_server_security, NULL, NULL, FLAG_DEVELOPER},
489 {"socket options", P_STRING, P_GLOBAL, &loadparm.Globals.socket_options, NULL, NULL, FLAG_DEVELOPER},
491 {"strict sync", P_BOOL, P_LOCAL, &sDefault.bStrictSync, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
492 {"case insensitive filesystem", P_BOOL, P_LOCAL, &sDefault.bCIFileSystem, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
494 {"Printing Options", P_SEP, P_SEPARATOR},
496 {"max print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxPrintJobs, NULL, NULL, FLAG_PRINT},
497 {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_PRINT},
498 {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_HIDE},
500 {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_PRINT},
501 {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_HIDE},
503 {"Filename Handling", P_SEP, P_SEPARATOR},
505 {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
506 {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
507 {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
509 {"Domain Options", P_SEP, P_SEPARATOR},
511 {"Logon Options", P_SEP, P_SEPARATOR},
514 {"Browse Options", P_SEP, P_SEPARATOR},
516 {"preferred master", P_ENUM, P_GLOBAL, &loadparm.Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
517 {"prefered master", P_ENUM, P_GLOBAL, &loadparm.Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_HIDE},
518 {"local master", P_BOOL, P_GLOBAL, &loadparm.Globals.bLocalMaster, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
519 {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
520 {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_HIDE},
522 {"WINS Options", P_SEP, P_SEPARATOR},
524 {"wins server", P_LIST, P_GLOBAL, &loadparm.Globals.szWINSservers, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
525 {"wins support", P_BOOL, P_GLOBAL, &loadparm.Globals.bWINSsupport, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
526 {"dns proxy", P_BOOL, P_GLOBAL, &loadparm.Globals.bWINSdnsProxy, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
527 {"wins hook", P_STRING, P_GLOBAL, &loadparm.Globals.szWINSHook, NULL, NULL, FLAG_ADVANCED},
529 {"Locking Options", P_SEP, P_SEPARATOR},
531 {"csc policy", P_ENUM, P_LOCAL, &sDefault.iCSCPolicy, NULL, enum_csc_policy, FLAG_SHARE | FLAG_GLOBAL},
533 {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
535 {"Miscellaneous Options", P_SEP, P_SEPARATOR},
537 {"share backend", P_STRING, P_GLOBAL, &loadparm.Globals.szShareBackend, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
538 {"preload", P_STRING, P_GLOBAL, &loadparm.Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
539 {"auto services", P_STRING, P_GLOBAL, &loadparm.Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
540 {"lock dir", P_STRING, P_GLOBAL, &loadparm.Globals.szLockDir, NULL, NULL, FLAG_HIDE},
541 {"lock directory", P_STRING, P_GLOBAL, &loadparm.Globals.szLockDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
542 {"modules dir", P_STRING, P_GLOBAL, &loadparm.Globals.szModulesDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
543 {"pid directory", P_STRING, P_GLOBAL, &loadparm.Globals.szPidDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
544 {"js include", P_LIST, P_GLOBAL, &loadparm.Globals.jsInclude, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
545 {"setup directory", P_STRING, P_GLOBAL, &loadparm.Globals.szSetupDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
547 {"socket address", P_STRING, P_GLOBAL, &loadparm.Globals.szSocketAddress, NULL, NULL, FLAG_DEVELOPER},
548 {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy, NULL, FLAG_HIDE},
549 {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include, NULL, FLAG_HIDE},
551 {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
552 {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_SHARE },
553 {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_SHARE},
555 {"panic action", P_STRING, P_GLOBAL, &panic_action, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
557 {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_SHARE},
558 {"host msdfs", P_BOOL, P_GLOBAL, &loadparm.Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
559 {"winbind separator", P_STRING, P_GLOBAL, &loadparm.Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
560 {"winbindd socket directory", P_STRING, P_GLOBAL, &loadparm.Globals.szWinbinddSocketDirectory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
561 {"winbind sealed pipes", P_BOOL, P_GLOBAL, &loadparm.Globals.bWinbindSealedPipes, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
562 {"template shell", P_STRING, P_GLOBAL, &loadparm.Globals.szTemplateShell, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
563 {"template homedir", P_STRING, P_GLOBAL, &loadparm.Globals.szTemplateHomedir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
565 {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
570 return the parameter table
572 struct parm_struct *lp_parm_table(void)
577 static TALLOC_CTX *lp_talloc;
579 /******************************************************************* a
580 Free up temporary memory - called from the main loop.
581 ********************************************************************/
583 void lp_talloc_free(void)
587 talloc_free(lp_talloc);
591 /*******************************************************************
592 Convenience routine to grab string parameters into temporary memory
593 and run standard_sub_basic on them. The buffers can be written to by
594 callers without affecting the source string.
595 ********************************************************************/
597 static const char *lp_string(const char *s)
599 #if 0 /* until REWRITE done to make thread-safe */
600 size_t len = s ? strlen(s) : 0;
604 /* The follow debug is useful for tracking down memory problems
605 especially if you have an inner loop that is calling a lp_*()
606 function that returns a string. Perhaps this debug should be
607 present all the time? */
610 DEBUG(10, ("lp_string(%s)\n", s));
613 #if 0 /* until REWRITE done to make thread-safe */
615 lp_talloc = talloc_init("lp_talloc");
617 ret = talloc_array(lp_talloc, char, len + 100); /* leave room for substitution */
625 strlcpy(ret, s, len);
627 if (trim_string(ret, "\"", "\"")) {
628 if (strchr(ret,'"') != NULL)
629 strlcpy(ret, s, len);
632 standard_sub_basic(ret,len+100);
639 In this section all the functions that are used to access the
640 parameters from the rest of the program are defined
643 #define FN_GLOBAL_STRING(fn_name,var_name) \
644 const char *fn_name(struct loadparm_context *lp_ctx) {if (lp_ctx == NULL) return NULL; return lp_ctx->Globals.var_name ? lp_string(lp_ctx->Globals.var_name) : "";}
645 #define FN_GLOBAL_CONST_STRING(fn_name,var_name) \
646 const char *fn_name(struct loadparm_context *lp_ctx) {if (lp_ctx == NULL) return NULL; return lp_ctx->Globals.var_name ? lp_ctx->Globals.var_name : "";}
647 #define FN_GLOBAL_LIST(fn_name,var_name) \
648 const char **fn_name(struct loadparm_context *lp_ctx) {if (lp_ctx == NULL) return NULL; return lp_ctx->Globals.var_name;}
649 #define FN_GLOBAL_BOOL(fn_name,var_name) \
650 bool fn_name(struct loadparm_context *lp_ctx) {if (lp_ctx == NULL) return false; return lp_ctx->Globals.var_name;}
652 #define FN_GLOBAL_CHAR(fn_name,ptr) \
653 char fn_name(void) {return(*(char *)(ptr));}
655 #define FN_GLOBAL_INTEGER(fn_name,var_name) \
656 int fn_name(struct loadparm_context *lp_ctx) {if (lp_ctx == NULL) return 0; return lp_ctx->Globals.var_name;}
658 #define FN_LOCAL_STRING(fn_name,val) \
659 const char *fn_name(struct loadparm_service *service) {return(lp_string((const char *)((service != NULL && service->val != NULL) ? service->val : sDefault.val)));}
660 #define FN_LOCAL_CONST_STRING(fn_name,val) \
661 const char *fn_name(struct loadparm_service *service) {return (const char *)(service != NULL && service->val != NULL) ? service->val : sDefault.val;}
662 #define FN_LOCAL_LIST(fn_name,val) \
663 const char **fn_name(struct loadparm_service *service) {return(const char **)(service != NULL && service->val != NULL? service->val : sDefault.val);}
664 #define FN_LOCAL_BOOL(fn_name,val) \
665 bool fn_name(struct loadparm_service *service) {return((service != NULL)? service->val : sDefault.val);}
666 #define FN_LOCAL_INTEGER(fn_name,val) \
667 int fn_name(struct loadparm_service *service) {return((service != NULL)? service->val : sDefault.val);}
669 _PUBLIC_ FN_GLOBAL_INTEGER(lp_server_role, server_role)
670 _PUBLIC_ FN_GLOBAL_LIST(lp_smb_ports, smb_ports)
671 _PUBLIC_ FN_GLOBAL_INTEGER(lp_nbt_port, nbt_port)
672 _PUBLIC_ FN_GLOBAL_INTEGER(lp_dgram_port, dgram_port)
673 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cldap_port, cldap_port)
674 _PUBLIC_ FN_GLOBAL_INTEGER(lp_krb5_port, krb5_port)
675 _PUBLIC_ FN_GLOBAL_INTEGER(lp_kpasswd_port, kpasswd_port)
676 _PUBLIC_ FN_GLOBAL_INTEGER(lp_web_port, web_port)
677 _PUBLIC_ FN_GLOBAL_STRING(lp_swat_directory, swat_directory)
678 _PUBLIC_ FN_GLOBAL_BOOL(lp_tls_enabled, tls_enabled)
679 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_keyfile, tls_keyfile)
680 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_certfile, tls_certfile)
681 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_cafile, tls_cafile)
682 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_crlfile, tls_crlfile)
683 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_dhpfile, tls_dhpfile)
684 _PUBLIC_ FN_GLOBAL_STRING(lp_share_backend, szShareBackend)
685 _PUBLIC_ FN_GLOBAL_STRING(lp_sam_url, szSAM_URL)
686 _PUBLIC_ FN_GLOBAL_STRING(lp_secrets_url, szSECRETS_URL)
687 _PUBLIC_ FN_GLOBAL_STRING(lp_spoolss_url, szSPOOLSS_URL)
688 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_config_url, szWINS_CONFIG_URL)
689 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_url, szWINS_URL)
690 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_winbind_separator, szWinbindSeparator)
691 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_winbindd_socket_directory, szWinbinddSocketDirectory)
692 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_template_shell, szTemplateShell)
693 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_template_homedir, szTemplateHomedir)
694 _PUBLIC_ FN_GLOBAL_BOOL(lp_winbind_sealed_pipes, bWinbindSealedPipes)
695 _PUBLIC_ FN_GLOBAL_STRING(lp_private_dir, szPrivateDir)
696 _PUBLIC_ FN_GLOBAL_STRING(lp_serverstring, szServerString)
697 _PUBLIC_ FN_GLOBAL_STRING(lp_lockdir, szLockDir)
698 _PUBLIC_ FN_GLOBAL_STRING(lp_modulesdir, szModulesDir)
699 _PUBLIC_ FN_GLOBAL_STRING(lp_setupdir, szSetupDir)
700 _PUBLIC_ FN_GLOBAL_STRING(lp_ncalrpc_dir, ncalrpc_dir)
701 _PUBLIC_ FN_GLOBAL_STRING(lp_piddir, szPidDir)
702 _PUBLIC_ FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, dcerpc_ep_servers)
703 _PUBLIC_ FN_GLOBAL_LIST(lp_server_services, server_services)
704 _PUBLIC_ FN_GLOBAL_STRING(lp_ntptr_providor, ntptr_providor)
705 _PUBLIC_ FN_GLOBAL_STRING(lp_auto_services, szAutoServices)
706 _PUBLIC_ FN_GLOBAL_STRING(lp_passwd_chat, szPasswdChat)
707 _PUBLIC_ FN_GLOBAL_LIST(lp_passwordserver, szPasswordServers)
708 _PUBLIC_ FN_GLOBAL_LIST(lp_name_resolve_order, szNameResolveOrder)
709 _PUBLIC_ FN_GLOBAL_STRING(lp_realm, szRealm)
710 _PUBLIC_ FN_GLOBAL_STRING(lp_socket_options, socket_options)
711 _PUBLIC_ FN_GLOBAL_STRING(lp_workgroup, szWorkgroup)
712 _PUBLIC_ FN_GLOBAL_STRING(lp_netbios_name, szNetbiosName)
713 _PUBLIC_ FN_GLOBAL_STRING(lp_netbios_scope, szNetbiosScope)
714 _PUBLIC_ FN_GLOBAL_LIST(lp_wins_server_list, szWINSservers)
715 _PUBLIC_ FN_GLOBAL_LIST(lp_interfaces, szInterfaces)
716 _PUBLIC_ FN_GLOBAL_STRING(lp_socket_address, szSocketAddress)
717 _PUBLIC_ FN_GLOBAL_LIST(lp_netbios_aliases, szNetbiosAliases)
719 _PUBLIC_ FN_GLOBAL_BOOL(lp_disable_netbios, bDisableNetbios)
720 _PUBLIC_ FN_GLOBAL_BOOL(lp_wins_support, bWINSsupport)
721 _PUBLIC_ FN_GLOBAL_BOOL(lp_wins_dns_proxy, bWINSdnsProxy)
722 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_hook, szWINSHook)
723 _PUBLIC_ FN_GLOBAL_STRING(lp_configfile, szConfigFile)
724 _PUBLIC_ FN_GLOBAL_BOOL(lp_local_master, bLocalMaster)
725 _PUBLIC_ FN_GLOBAL_BOOL(lp_readraw, bReadRaw)
726 _PUBLIC_ FN_GLOBAL_BOOL(lp_large_readwrite, bLargeReadwrite)
727 _PUBLIC_ FN_GLOBAL_BOOL(lp_writeraw, bWriteRaw)
728 _PUBLIC_ FN_GLOBAL_BOOL(lp_null_passwords, bNullPasswords)
729 _PUBLIC_ FN_GLOBAL_BOOL(lp_obey_pam_restrictions, bObeyPamRestrictions)
730 _PUBLIC_ FN_GLOBAL_BOOL(lp_encrypted_passwords, bEncryptPasswords)
731 _PUBLIC_ FN_GLOBAL_BOOL(lp_time_server, bTimeServer)
732 _PUBLIC_ FN_GLOBAL_BOOL(lp_bind_interfaces_only, bBindInterfacesOnly)
733 _PUBLIC_ FN_GLOBAL_BOOL(lp_unicode, bUnicode)
734 _PUBLIC_ FN_GLOBAL_BOOL(lp_nt_status_support, bNTStatusSupport)
735 _PUBLIC_ FN_GLOBAL_BOOL(lp_lanman_auth, bLanmanAuth)
736 _PUBLIC_ FN_GLOBAL_BOOL(lp_ntlm_auth, bNTLMAuth)
737 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_plaintext_auth, bClientPlaintextAuth)
738 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_lanman_auth, bClientLanManAuth)
739 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, bClientNTLMv2Auth)
740 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_use_spnego_principal, client_use_spnego_principal)
741 _PUBLIC_ FN_GLOBAL_BOOL(lp_host_msdfs, bHostMSDfs)
742 _PUBLIC_ FN_GLOBAL_BOOL(lp_unix_extensions, bUnixExtensions)
743 _PUBLIC_ FN_GLOBAL_BOOL(lp_use_spnego, bUseSpnego)
744 _PUBLIC_ FN_GLOBAL_BOOL(lp_rpc_big_endian, bRpcBigEndian)
745 _PUBLIC_ FN_GLOBAL_INTEGER(lp_max_wins_ttl, max_wins_ttl)
746 _PUBLIC_ FN_GLOBAL_INTEGER(lp_min_wins_ttl, min_wins_ttl)
747 _PUBLIC_ FN_GLOBAL_INTEGER(lp_maxmux, max_mux)
748 _PUBLIC_ FN_GLOBAL_INTEGER(lp_max_xmit, max_xmit)
749 _PUBLIC_ FN_GLOBAL_INTEGER(lp_passwordlevel, pwordlevel)
750 _PUBLIC_ FN_GLOBAL_INTEGER(lp_srv_maxprotocol, srv_maxprotocol)
751 _PUBLIC_ FN_GLOBAL_INTEGER(lp_srv_minprotocol, srv_minprotocol)
752 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cli_maxprotocol, cli_maxprotocol)
753 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cli_minprotocol, cli_minprotocol)
754 _PUBLIC_ FN_GLOBAL_INTEGER(lp_security, security)
755 _PUBLIC_ FN_GLOBAL_BOOL(lp_paranoid_server_security, paranoid_server_security)
756 _PUBLIC_ FN_GLOBAL_INTEGER(lp_announce_as, announce_as)
757 _PUBLIC_ FN_GLOBAL_LIST(lp_js_include, jsInclude)
758 _PUBLIC_ FN_LOCAL_STRING(lp_servicename, szService)
759 _PUBLIC_ FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
760 _PUBLIC_ FN_LOCAL_STRING(lp_pathname, szPath)
761 static FN_LOCAL_STRING(_lp_printername, szPrintername)
762 _PUBLIC_ FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
763 _PUBLIC_ FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
764 _PUBLIC_ FN_LOCAL_STRING(lp_comment, comment)
765 _PUBLIC_ FN_LOCAL_STRING(lp_fstype, fstype)
766 static FN_LOCAL_STRING(lp_volume, volume)
767 _PUBLIC_ FN_LOCAL_LIST(lp_ntvfs_handler, ntvfs_handler)
768 _PUBLIC_ FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
769 _PUBLIC_ FN_LOCAL_BOOL(lp_browseable, bBrowseable)
770 _PUBLIC_ FN_LOCAL_BOOL(lp_readonly, bRead_only)
771 _PUBLIC_ FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
772 _PUBLIC_ FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
773 _PUBLIC_ FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
774 _PUBLIC_ FN_LOCAL_BOOL(lp_strict_locking, bStrictLocking)
775 _PUBLIC_ FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
776 _PUBLIC_ FN_LOCAL_BOOL(lp_ci_filesystem, bCIFileSystem)
777 _PUBLIC_ FN_LOCAL_BOOL(lp_map_system, bMap_system)
778 _PUBLIC_ FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
779 _PUBLIC_ FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
780 _PUBLIC_ FN_LOCAL_INTEGER(lp_create_mask, iCreate_mask)
781 _PUBLIC_ FN_LOCAL_INTEGER(lp_force_create_mode, iCreate_force_mode)
782 _PUBLIC_ FN_LOCAL_INTEGER(lp_dir_mask, iDir_mask)
783 _PUBLIC_ FN_LOCAL_INTEGER(lp_force_dir_mode, iDir_force_mode)
784 _PUBLIC_ FN_GLOBAL_INTEGER(lp_server_signing, server_signing)
785 _PUBLIC_ FN_GLOBAL_INTEGER(lp_client_signing, client_signing)
787 /* local prototypes */
788 static int map_parameter(const char *pszParmName);
789 static struct loadparm_service *getservicebyname(struct loadparm_context *lp_ctx,
790 const char *pszServiceName);
791 static void copy_service(struct loadparm_service *pserviceDest,
792 struct loadparm_service *pserviceSource,
794 static bool service_ok(struct loadparm_service *service);
795 static bool do_section(const char *pszSectionName, void *);
796 static void init_copymap(struct loadparm_service *pservice);
798 /* This is a helper function for parametrical options support. */
799 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
800 /* Actual parametrical functions are quite simple */
801 const char *lp_get_parametric(struct loadparm_service *service,
802 const char *type, const char *option)
805 struct param_opt *data;
807 data = (service == NULL ? loadparm.Globals.param_opt : service->param_opt);
809 asprintf(&vfskey, "%s:%s", type, option);
813 if (strcmp(data->key, vfskey) == 0) {
820 if (service != NULL) {
821 /* Try to fetch the same option but from globals */
822 /* but only if we are not already working with Globals */
823 for (data = loadparm.Globals.param_opt; data;
825 if (strcmp(data->key, vfskey) == 0) {
838 /*******************************************************************
839 convenience routine to return int parameters.
840 ********************************************************************/
841 static int lp_int(const char *s)
845 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
849 return strtol(s, NULL, 0);
852 /*******************************************************************
853 convenience routine to return unsigned long parameters.
854 ********************************************************************/
855 static int lp_ulong(const char *s)
859 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
863 return strtoul(s, NULL, 0);
866 /*******************************************************************
867 convenience routine to return unsigned long parameters.
868 ********************************************************************/
869 static double lp_double(const char *s)
873 DEBUG(0,("lp_double(%s): is called with NULL!\n",s));
877 return strtod(s, NULL);
880 /*******************************************************************
881 convenience routine to return boolean parameters.
882 ********************************************************************/
883 static bool lp_bool(const char *s)
888 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
892 if (!set_boolean(s, &ret)) {
893 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
901 /* Return parametric option from a given service. Type is a part of option before ':' */
902 /* Parametric option has following syntax: 'Type: option = value' */
903 /* Returned value is allocated in 'lp_talloc' context */
905 const char *lp_parm_string(struct loadparm_service *service, const char *type,
908 const char *value = lp_get_parametric(service, type, option);
911 return lp_string(value);
916 /* Return parametric option from a given service. Type is a part of option before ':' */
917 /* Parametric option has following syntax: 'Type: option = value' */
918 /* Returned value is allocated in 'lp_talloc' context */
920 const char **lp_parm_string_list(struct loadparm_service *service,
922 const char *option, const char *separator)
924 const char *value = lp_get_parametric(service, type, option);
927 return str_list_make(talloc_autofree_context(), value,
933 /* Return parametric option from a given service. Type is a part of option before ':' */
934 /* Parametric option has following syntax: 'Type: option = value' */
936 int lp_parm_int(struct loadparm_service *service, const char *type,
937 const char *option, int default_v)
939 const char *value = lp_get_parametric(service, type, option);
942 return lp_int(value);
947 /* Return parametric option from a given service. Type is a part of
949 * Parametric option has following syntax: 'Type: option = value'.
952 int lp_parm_bytes(struct loadparm_service *service, const char *type,
953 const char *option, int default_v)
957 const char *value = lp_get_parametric(service, type, option);
959 if (value && conv_str_size(value, &bval)) {
960 if (bval <= INT_MAX) {
968 /* Return parametric option from a given service. Type is a part of option before ':' */
969 /* Parametric option has following syntax: 'Type: option = value' */
971 unsigned long lp_parm_ulong(struct loadparm_service *service, const char *type,
972 const char *option, unsigned long default_v)
974 const char *value = lp_get_parametric(service, type, option);
977 return lp_ulong(value);
983 double lp_parm_double(struct loadparm_service *service, const char *type,
984 const char *option, double default_v)
986 const char *value = lp_get_parametric(service, type, option);
989 return lp_double(value);
994 /* Return parametric option from a given service. Type is a part of option before ':' */
995 /* Parametric option has following syntax: 'Type: option = value' */
997 bool lp_parm_bool(struct loadparm_service *service, const char *type,
998 const char *option, bool default_v)
1000 const char *value = lp_get_parametric(service, type, option);
1003 return lp_bool(value);
1009 /***************************************************************************
1010 Initialise a service to the defaults.
1011 ***************************************************************************/
1013 static struct loadparm_service *init_service(TALLOC_CTX *mem_ctx)
1015 struct loadparm_service *pservice =
1016 talloc_zero(mem_ctx, struct loadparm_service);
1017 copy_service(pservice, &sDefault, NULL);
1022 Set a string value, deallocating any existing space, and allocing the space
1025 static bool string_set(TALLOC_CTX *mem_ctx, char **dest, const char *src)
1032 *dest = talloc_strdup(mem_ctx, src);
1033 if ((*dest) == NULL) {
1034 DEBUG(0,("Out of memory in string_init\n"));
1043 /***************************************************************************
1044 Add a new service to the services array initialising it with the given
1046 ***************************************************************************/
1048 static struct loadparm_service *add_a_service(struct loadparm_context *lp_ctx,
1049 const struct loadparm_service *pservice,
1053 struct loadparm_service tservice;
1054 int num_to_alloc = lp_ctx->iNumServices + 1;
1055 struct param_opt *data, *pdata;
1057 tservice = *pservice;
1059 /* it might already exist */
1061 struct loadparm_service *service = getservicebyname(lp_ctx,
1063 if (service != NULL) {
1064 /* Clean all parametric options for service */
1065 /* They will be added during parsing again */
1066 data = service->param_opt;
1072 service->param_opt = NULL;
1077 /* find an invalid one */
1078 for (i = 0; i < lp_ctx->iNumServices; i++)
1079 if (lp_ctx->ServicePtrs[i] == NULL)
1082 /* if not, then create one */
1083 if (i == lp_ctx->iNumServices) {
1084 struct loadparm_service **tsp;
1086 tsp = realloc_p(lp_ctx->ServicePtrs, struct loadparm_service *,
1090 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1094 lp_ctx->ServicePtrs = tsp;
1095 lp_ctx->ServicePtrs[lp_ctx->iNumServices] = NULL;
1098 lp_ctx->iNumServices++;
1101 lp_ctx->ServicePtrs[i] = init_service(talloc_autofree_context());
1102 if (lp_ctx->ServicePtrs[i] == NULL) {
1103 DEBUG(0,("add_a_service: out of memory!\n"));
1106 copy_service(lp_ctx->ServicePtrs[i], &tservice, NULL);
1108 string_set(lp_ctx->ServicePtrs[i], &lp_ctx->ServicePtrs[i]->szService, name);
1109 return lp_ctx->ServicePtrs[i];
1112 /***************************************************************************
1113 Add a new home service, with the specified home directory, defaults coming
1115 ***************************************************************************/
1117 bool lp_add_home(struct loadparm_context *lp_ctx,
1118 const char *pszHomename,
1119 struct loadparm_service *default_service,
1120 const char *user, const char *pszHomedir)
1122 struct loadparm_service *service;
1124 service = add_a_service(lp_ctx, default_service, pszHomename);
1126 if (service == NULL)
1129 if (!(*(default_service->szPath))
1130 || strequal(default_service->szPath, sDefault.szPath)) {
1131 service->szPath = talloc_strdup(service, pszHomedir);
1133 service->szPath = string_sub_talloc(service, lp_pathname(default_service),"%H", pszHomedir);
1136 if (!(*(service->comment))) {
1137 service->comment = talloc_asprintf(service, "Home directory of %s", user);
1139 service->bAvailable = default_service->bAvailable;
1140 service->bBrowseable = default_service->bBrowseable;
1142 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n",
1143 pszHomename, user, service->szPath));
1148 /***************************************************************************
1149 Add a new service, based on an old one.
1150 ***************************************************************************/
1152 struct loadparm_service *lp_add_service(struct loadparm_context *lp_ctx,
1153 const char *pszService,
1154 struct loadparm_service *default_service)
1156 return add_a_service(lp_ctx, default_service, pszService);
1159 /***************************************************************************
1160 Add the IPC service.
1161 ***************************************************************************/
1163 static bool lp_add_hidden(struct loadparm_context *lp_ctx, const char *name,
1166 struct loadparm_service *service = add_a_service(lp_ctx, &sDefault, name);
1168 if (service == NULL)
1171 string_set(service, &service->szPath, tmpdir());
1173 service->comment = talloc_asprintf(service, "%s Service (%s)",
1174 fstype, lp_ctx->Globals.szServerString);
1175 string_set(service, &service->fstype, fstype);
1176 service->iMaxConnections = -1;
1177 service->bAvailable = true;
1178 service->bRead_only = true;
1179 service->bPrint_ok = false;
1180 service->bBrowseable = false;
1182 if (strcasecmp(fstype, "IPC") == 0) {
1183 lp_do_service_parameter(lp_ctx, service, "ntvfs handler",
1187 DEBUG(3, ("adding hidden service %s\n", name));
1192 /***************************************************************************
1193 Add a new printer service, with defaults coming from service iFrom.
1194 ***************************************************************************/
1196 bool lp_add_printer(struct loadparm_context *lp_ctx,
1197 const char *pszPrintername,
1198 struct loadparm_service *default_service)
1200 const char *comment = "From Printcap";
1201 struct loadparm_service *service;
1202 service = add_a_service(lp_ctx, default_service, pszPrintername);
1204 if (service == NULL)
1207 /* note that we do NOT default the availability flag to True - */
1208 /* we take it from the default service passed. This allows all */
1209 /* dynamic printers to be disabled by disabling the [printers] */
1210 /* entry (if/when the 'available' keyword is implemented!). */
1212 /* the printer name is set to the service name. */
1213 string_set(service, &service->szPrintername, pszPrintername);
1214 string_set(service, &service->comment, comment);
1215 service->bBrowseable = sDefault.bBrowseable;
1216 /* Printers cannot be read_only. */
1217 service->bRead_only = false;
1218 /* Printer services must be printable. */
1219 service->bPrint_ok = true;
1221 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1226 /***************************************************************************
1227 Map a parameter's string representation to something we can use.
1228 Returns False if the parameter string is not recognised, else TRUE.
1229 ***************************************************************************/
1231 static int map_parameter(const char *pszParmName)
1235 if (*pszParmName == '-')
1238 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1239 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1242 /* Warn only if it isn't parametric option */
1243 if (strchr(pszParmName, ':') == NULL)
1244 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1245 /* We do return 'fail' for parametric options as well because they are
1246 stored in different storage
1253 return the parameter structure for a parameter
1255 struct parm_struct *lp_parm_struct(const char *name)
1257 int parmnum = map_parameter(name);
1258 if (parmnum == -1) return NULL;
1259 return &parm_table[parmnum];
1263 return the parameter pointer for a parameter
1265 void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
1267 if (service == NULL)
1270 return ((char *)service) + PTR_DIFF(parm->ptr, &sDefault);
1273 /***************************************************************************
1274 Find a service by name. Otherwise works like get_service.
1275 ***************************************************************************/
1277 static struct loadparm_service *getservicebyname(struct loadparm_context *lp_ctx,
1278 const char *pszServiceName)
1282 for (iService = lp_ctx->iNumServices - 1; iService >= 0; iService--)
1283 if (lp_ctx->ServicePtrs[iService] != NULL &&
1284 strwicmp(lp_ctx->ServicePtrs[iService]->szService, pszServiceName) == 0) {
1285 return lp_ctx->ServicePtrs[iService];
1291 /***************************************************************************
1292 Copy a service structure to another.
1293 If pcopymapDest is NULL then copy all fields
1294 ***************************************************************************/
1296 static void copy_service(struct loadparm_service *pserviceDest,
1297 struct loadparm_service *pserviceSource,
1301 bool bcopyall = (pcopymapDest == NULL);
1302 struct param_opt *data, *pdata, *paramo;
1305 for (i = 0; parm_table[i].label; i++)
1306 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1307 (bcopyall || pcopymapDest[i])) {
1308 void *def_ptr = parm_table[i].ptr;
1310 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
1313 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
1316 switch (parm_table[i].type) {
1318 *(int *)dest_ptr = *(int *)src_ptr;
1324 *(int *)dest_ptr = *(int *)src_ptr;
1328 string_set(pserviceDest,
1334 string_set(pserviceDest,
1337 strupper(*(char **)dest_ptr);
1340 *(const char ***)dest_ptr = str_list_copy(talloc_autofree_context(),
1341 *(const char ***)src_ptr);
1349 init_copymap(pserviceDest);
1350 if (pserviceSource->copymap)
1351 memcpy((void *)pserviceDest->copymap,
1352 (void *)pserviceSource->copymap,
1353 sizeof(int) * NUMPARAMETERS);
1356 data = pserviceSource->param_opt;
1359 pdata = pserviceDest->param_opt;
1360 /* Traverse destination */
1362 /* If we already have same option, override it */
1363 if (strcmp(pdata->key, data->key) == 0) {
1364 talloc_free(pdata->value);
1365 pdata->value = talloc_reference(pdata,
1370 pdata = pdata->next;
1373 paramo = talloc(pserviceDest, struct param_opt);
1376 paramo->key = talloc_reference(paramo, data->key);
1377 paramo->value = talloc_reference(paramo, data->value);
1378 DLIST_ADD(pserviceDest->param_opt, paramo);
1384 /***************************************************************************
1385 Check a service for consistency. Return False if the service is in any way
1386 incomplete or faulty, else True.
1387 ***************************************************************************/
1389 static bool service_ok(struct loadparm_service *service)
1394 if (service->szService[0] == '\0') {
1395 DEBUG(0, ("The following message indicates an internal error:\n"));
1396 DEBUG(0, ("No service name in service entry.\n"));
1400 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1401 /* I can't see why you'd want a non-printable printer service... */
1402 if (strwicmp(service->szService, PRINTERS_NAME) == 0) {
1403 if (!service->bPrint_ok) {
1404 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
1405 service->szService));
1406 service->bPrint_ok = true;
1408 /* [printers] service must also be non-browsable. */
1409 if (service->bBrowseable)
1410 service->bBrowseable = false;
1413 /* If a service is flagged unavailable, log the fact at level 0. */
1414 if (!service->bAvailable)
1415 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
1416 service->szService));
1422 /*******************************************************************
1423 Keep a linked list of all config files so we know when one has changed
1424 it's date and needs to be reloaded.
1425 ********************************************************************/
1427 static void add_to_file_list(struct loadparm_context *lp_ctx,
1428 const char *fname, const char *subfname)
1430 struct file_lists *f = lp_ctx->file_lists;
1433 if (f->name && !strcmp(f->name, fname))
1439 f = talloc(talloc_autofree_context(), struct file_lists);
1442 f->next = lp_ctx->file_lists;
1443 f->name = talloc_strdup(f, fname);
1448 f->subfname = talloc_strdup(f, subfname);
1453 lp_ctx->file_lists = f;
1454 f->modtime = file_modtime(subfname);
1456 time_t t = file_modtime(subfname);
1462 /*******************************************************************
1463 Check if a config file has changed date.
1464 ********************************************************************/
1466 bool lp_file_list_changed(struct loadparm_context *lp_ctx)
1468 struct file_lists *f;
1469 DEBUG(6, ("lp_file_list_changed()\n"));
1471 for (f = lp_ctx->file_lists; f != NULL; f = f->next) {
1475 n2 = standard_sub_basic(talloc_autofree_context(), f->name);
1477 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
1478 f->name, n2, ctime(&f->modtime)));
1480 mod_time = file_modtime(n2);
1482 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
1483 DEBUGADD(6, ("file %s modified: %s\n", n2,
1485 f->modtime = mod_time;
1486 talloc_free(f->subfname);
1487 f->subfname = talloc_strdup(f, n2);
1494 /***************************************************************************
1495 Handle the include operation.
1496 ***************************************************************************/
1498 static bool handle_include(struct loadparm_context *lp_ctx,
1499 const char *pszParmValue, char **ptr)
1501 char *fname = standard_sub_basic(talloc_autofree_context(),
1504 add_to_file_list(lp_ctx, pszParmValue, fname);
1506 string_set(talloc_autofree_context(), ptr, fname);
1508 if (file_exist(fname))
1509 return pm_process(fname, do_section, do_parameter, lp_ctx);
1511 DEBUG(2, ("Can't find include file %s\n", fname));
1516 /***************************************************************************
1517 Handle the interpretation of the copy parameter.
1518 ***************************************************************************/
1520 static bool handle_copy(struct loadparm_context *lp_ctx,
1521 const char *pszParmValue, char **ptr)
1524 struct loadparm_service *serviceTemp;
1526 string_set(talloc_autofree_context(), ptr, pszParmValue);
1530 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
1532 if ((serviceTemp = getservicebyname(lp_ctx, pszParmValue)) != NULL) {
1533 if (serviceTemp == lp_ctx->currentService) {
1534 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
1536 copy_service(lp_ctx->currentService,
1538 lp_ctx->currentService->copymap);
1542 DEBUG(0, ("Unable to copy service - source not found: %s\n",
1550 /***************************************************************************
1551 Initialise a copymap.
1552 ***************************************************************************/
1554 static void init_copymap(struct loadparm_service *pservice)
1557 talloc_free(pservice->copymap);
1558 pservice->copymap = talloc_array(pservice, int, NUMPARAMETERS);
1559 if (pservice->copymap == NULL) {
1561 ("Couldn't allocate copymap!! (size %d)\n",
1562 (int)NUMPARAMETERS));
1565 for (i = 0; i < NUMPARAMETERS; i++)
1566 pservice->copymap[i] = true;
1569 /***************************************************************************
1570 Process a parametric option
1571 ***************************************************************************/
1572 static bool lp_do_parameter_parametric(struct loadparm_service *service,
1573 const char *pszParmName,
1574 const char *pszParmValue, int flags)
1576 struct param_opt *paramo, *data;
1578 TALLOC_CTX *mem_ctx;
1580 while (isspace((unsigned char)*pszParmName)) {
1584 name = strdup(pszParmName);
1585 if (!name) return false;
1589 if (service == NULL) {
1590 data = loadparm.Globals.param_opt;
1591 mem_ctx = talloc_autofree_context();
1593 data = service->param_opt;
1597 /* Traverse destination */
1598 for (paramo=data; paramo; paramo=paramo->next) {
1599 /* If we already have the option set, override it unless
1600 it was a command line option and the new one isn't */
1601 if (strcmp(paramo->key, name) == 0) {
1602 if ((paramo->flags & FLAG_CMDLINE) &&
1603 !(flags & FLAG_CMDLINE)) {
1607 talloc_free(paramo->value);
1608 paramo->value = talloc_strdup(paramo, pszParmValue);
1609 paramo->flags = flags;
1615 paramo = talloc(mem_ctx, struct param_opt);
1618 paramo->key = talloc_strdup(paramo, name);
1619 paramo->value = talloc_strdup(paramo, pszParmValue);
1620 paramo->flags = flags;
1621 if (service == NULL) {
1622 DLIST_ADD(loadparm.Globals.param_opt, paramo);
1624 DLIST_ADD(service->param_opt, paramo);
1632 static bool set_variable(TALLOC_CTX *mem_ctx, int parmnum, void *parm_ptr,
1633 const char *pszParmName, const char *pszParmValue,
1634 struct loadparm_context *lp_ctx)
1637 /* if it is a special case then go ahead */
1638 if (parm_table[parmnum].special) {
1639 parm_table[parmnum].special(lp_ctx, pszParmValue,
1644 /* now switch on the type of variable it is */
1645 switch (parm_table[parmnum].type)
1649 if (!set_boolean(pszParmValue, &b)) {
1650 DEBUG(0,("lp_do_parameter(%s): value is not boolean!\n", pszParmValue));
1653 *(int *)parm_ptr = b;
1658 *(int *)parm_ptr = atoi(pszParmValue);
1662 *(int *)parm_ptr = strtol(pszParmValue, NULL, 8);
1668 if (conv_str_size(pszParmValue, &val)) {
1669 if (val <= INT_MAX) {
1670 *(int *)parm_ptr = (int)val;
1675 DEBUG(0,("lp_do_parameter(%s): value is not "
1676 "a valid size specifier!\n", pszParmValue));
1681 *(const char ***)parm_ptr = str_list_make(mem_ctx,
1682 pszParmValue, NULL);
1686 string_set(mem_ctx, (char **)parm_ptr, pszParmValue);
1690 string_set(mem_ctx, (char **)parm_ptr, pszParmValue);
1691 strupper(*(char **)parm_ptr);
1695 for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
1698 parm_table[parmnum].enum_list[i].name)) {
1700 parm_table[parmnum].
1705 if (!parm_table[parmnum].enum_list[i].name) {
1706 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n",
1707 pszParmValue, pszParmName));
1715 if (parm_table[parmnum].flags & FLAG_DEFAULT) {
1716 parm_table[parmnum].flags &= ~FLAG_DEFAULT;
1717 /* we have to also unset FLAG_DEFAULT on aliases */
1718 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1719 parm_table[i].flags &= ~FLAG_DEFAULT;
1721 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1722 parm_table[i].flags &= ~FLAG_DEFAULT;
1729 bool lp_do_global_parameter(struct loadparm_context *lp_ctx,
1730 const char *pszParmName, const char *pszParmValue)
1732 int parmnum = map_parameter(pszParmName);
1736 if (strchr(pszParmName, ':')) {
1737 return lp_do_parameter_parametric(NULL, pszParmName, pszParmValue, 0);
1739 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1743 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1744 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1748 /* if the flag has been set on the command line, then don't allow override,
1749 but don't report an error */
1750 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1754 parm_ptr = parm_table[parmnum].ptr;
1756 return set_variable(talloc_autofree_context(), parmnum, parm_ptr,
1757 pszParmName, pszParmValue, lp_ctx);
1760 bool lp_do_service_parameter(struct loadparm_context *lp_ctx,
1761 struct loadparm_service *service,
1762 const char *pszParmName, const char *pszParmValue)
1764 void *def_ptr = NULL;
1767 int parmnum = map_parameter(pszParmName);
1770 if (strchr(pszParmName, ':')) {
1771 return lp_do_parameter_parametric(service, pszParmName, pszParmValue, 0);
1773 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1777 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1778 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1782 /* if the flag has been set on the command line, then don't allow override,
1783 but don't report an error */
1784 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1788 def_ptr = parm_table[parmnum].ptr;
1790 if (parm_table[parmnum].class == P_GLOBAL) {
1792 ("Global parameter %s found in service section!\n",
1796 parm_ptr = ((char *)service) + PTR_DIFF(def_ptr, &sDefault);
1798 if (!service->copymap)
1799 init_copymap(service);
1801 /* this handles the aliases - set the copymap for other
1802 * entries with the same data pointer */
1803 for (i = 0; parm_table[i].label; i++)
1804 if (parm_table[i].ptr == parm_table[parmnum].ptr)
1805 service->copymap[i] = false;
1807 return set_variable(service, parmnum, parm_ptr, pszParmName,
1808 pszParmValue, lp_ctx);
1811 /***************************************************************************
1812 Process a parameter.
1813 ***************************************************************************/
1815 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
1818 struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata;
1820 if (lp_ctx->bInGlobalSection)
1821 return lp_do_global_parameter(lp_ctx, pszParmName,
1824 return lp_do_service_parameter(lp_ctx, lp_ctx->currentService,
1825 pszParmName, pszParmValue);
1829 variable argument do parameter
1831 bool lp_do_global_parameter_var(struct loadparm_context *lp_ctx, const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4);
1832 bool lp_do_global_parameter_var(struct loadparm_context *lp_ctx,
1833 const char *pszParmName, const char *fmt, ...)
1840 s = talloc_vasprintf(NULL, fmt, ap);
1842 ret = lp_do_global_parameter(lp_ctx, pszParmName, s);
1849 set a parameter from the commandline - this is called from command line parameter
1850 parsing code. It sets the parameter then marks the parameter as unable to be modified
1851 by smb.conf processing
1853 bool lp_set_cmdline(struct loadparm_context *lp_ctx, const char *pszParmName,
1854 const char *pszParmValue)
1856 int parmnum = map_parameter(pszParmName);
1859 while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
1862 if (parmnum < 0 && strchr(pszParmName, ':')) {
1863 /* set a parametric option */
1864 return lp_do_parameter_parametric(NULL, pszParmName, pszParmValue, FLAG_CMDLINE);
1868 DEBUG(0,("Unknown option '%s'\n", pszParmName));
1872 /* reset the CMDLINE flag in case this has been called before */
1873 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
1875 if (!lp_do_global_parameter(lp_ctx, pszParmName, pszParmValue)) {
1879 parm_table[parmnum].flags |= FLAG_CMDLINE;
1881 /* we have to also set FLAG_CMDLINE on aliases */
1882 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1883 parm_table[i].flags |= FLAG_CMDLINE;
1885 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1886 parm_table[i].flags |= FLAG_CMDLINE;
1893 set a option from the commandline in 'a=b' format. Use to support --option
1895 bool lp_set_option(struct loadparm_context *lp_ctx, const char *option)
1913 ret = lp_set_cmdline(lp_ctx, s, p+1);
1919 #define BOOLSTR(b) ((b) ? "Yes" : "No")
1921 /***************************************************************************
1922 Print a parameter of the specified type.
1923 ***************************************************************************/
1925 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
1931 for (i = 0; p->enum_list[i].name; i++) {
1932 if (*(int *)ptr == p->enum_list[i].value) {
1934 p->enum_list[i].name);
1941 fprintf(f, "%s", BOOLSTR((bool)*(int *)ptr));
1946 fprintf(f, "%d", *(int *)ptr);
1950 fprintf(f, "0%o", *(int *)ptr);
1954 if ((char ***)ptr && *(char ***)ptr) {
1955 char **list = *(char ***)ptr;
1957 for (; *list; list++)
1958 fprintf(f, "%s%s", *list,
1959 ((*(list+1))?", ":""));
1965 if (*(char **)ptr) {
1966 fprintf(f, "%s", *(char **)ptr);
1974 /***************************************************************************
1975 Check if two parameters are equal.
1976 ***************************************************************************/
1978 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
1982 return (*((int *)ptr1) == *((int *)ptr2));
1988 return (*((int *)ptr1) == *((int *)ptr2));
1991 return str_list_equal((const char **)(*(char ***)ptr1),
1992 (const char **)(*(char ***)ptr2));
1997 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
2002 return (p1 == p2 || strequal(p1, p2));
2010 /***************************************************************************
2011 Process a new section (service). At this stage all sections are services.
2012 Later we'll have special sections that permit server parameters to be set.
2013 Returns True on success, False on failure.
2014 ***************************************************************************/
2016 static bool do_section(const char *pszSectionName, void *userdata)
2018 struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata;
2020 bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2021 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2024 /* if we've just struck a global section, note the fact. */
2025 lp_ctx->bInGlobalSection = isglobal;
2027 /* check for multiple global sections */
2028 if (lp_ctx->bInGlobalSection) {
2029 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2033 /* if we have a current service, tidy it up before moving on */
2036 if (lp_ctx->currentService != NULL)
2037 bRetval = service_ok(lp_ctx->currentService);
2039 /* if all is still well, move to the next record in the services array */
2041 /* We put this here to avoid an odd message order if messages are */
2042 /* issued by the post-processing of a previous section. */
2043 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2045 if ((lp_ctx->currentService = add_a_service(lp_ctx, &sDefault,
2048 DEBUG(0, ("Failed to add a new service\n"));
2057 /***************************************************************************
2058 Determine if a partcular base parameter is currentl set to the default value.
2059 ***************************************************************************/
2061 static bool is_default(int i)
2063 if (!defaults_saved)
2065 switch (parm_table[i].type) {
2067 return str_list_equal((const char **)parm_table[i].def.lvalue,
2068 (const char **)(*(char ***)parm_table[i].ptr));
2071 return strequal(parm_table[i].def.svalue,
2072 *(char **)parm_table[i].ptr);
2074 return parm_table[i].def.bvalue ==
2075 *(int *)parm_table[i].ptr;
2080 return parm_table[i].def.ivalue ==
2081 *(int *)parm_table[i].ptr;
2088 /***************************************************************************
2089 Display the contents of the global structure.
2090 ***************************************************************************/
2092 static void dump_globals(struct loadparm_context *lp_ctx, FILE *f, bool show_defaults)
2095 struct param_opt *data;
2097 fprintf(f, "# Global parameters\n[global]\n");
2099 for (i = 0; parm_table[i].label; i++)
2100 if (parm_table[i].class == P_GLOBAL &&
2101 parm_table[i].ptr &&
2102 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2103 if (!show_defaults && (parm_table[i].flags & FLAG_DEFAULT))
2105 fprintf(f, "\t%s = ", parm_table[i].label);
2106 print_parameter(&parm_table[i], parm_table[i].ptr, f);
2109 if (lp_ctx->Globals.param_opt != NULL) {
2110 for (data = lp_ctx->Globals.param_opt; data;
2111 data = data->next) {
2112 fprintf(f, "\t%s = %s\n", data->key, data->value);
2118 /***************************************************************************
2119 Display the contents of a single services record.
2120 ***************************************************************************/
2122 static void dump_a_service(struct loadparm_service * pService, FILE * f)
2125 struct param_opt *data;
2127 if (pService != &sDefault)
2128 fprintf(f, "\n[%s]\n", pService->szService);
2130 for (i = 0; parm_table[i].label; i++)
2131 if (parm_table[i].class == P_LOCAL &&
2132 parm_table[i].ptr &&
2133 (*parm_table[i].label != '-') &&
2134 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2135 int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
2137 if (pService == &sDefault) {
2138 if (defaults_saved && is_default(i))
2141 if (equal_parameter(parm_table[i].type,
2142 ((char *)pService) +
2144 ((char *)&sDefault) +
2149 fprintf(f, "\t%s = ", parm_table[i].label);
2150 print_parameter(&parm_table[i],
2151 ((char *)pService) + pdiff, f);
2154 if (pService->param_opt != NULL) {
2155 for (data = pService->param_opt; data; data = data->next) {
2156 fprintf(f, "\t%s = %s\n", data->key, data->value);
2161 bool lp_dump_a_parameter(struct loadparm_context *lp_ctx, int snum, char *parm_name, FILE * f,
2164 struct loadparm_service * pService = lp_ctx->ServicePtrs[snum];
2165 struct parm_struct *parm;
2168 parm = lp_parm_struct(parm_name);
2176 ptr = ((char *)pService) +
2177 PTR_DIFF(parm->ptr, &sDefault);
2179 print_parameter(parm,
2185 /***************************************************************************
2186 Return info about the next service in a service. snum==-1 gives the globals.
2187 Return NULL when out of parameters.
2188 ***************************************************************************/
2190 struct parm_struct *lp_next_parameter(struct loadparm_context *lp_ctx, int snum, int *i,
2194 /* do the globals */
2195 for (; parm_table[*i].label; (*i)++) {
2196 if (parm_table[*i].class == P_SEPARATOR)
2197 return &parm_table[(*i)++];
2199 if (!parm_table[*i].ptr
2200 || (*parm_table[*i].label == '-'))
2204 && (parm_table[*i].ptr ==
2205 parm_table[(*i) - 1].ptr))
2208 return &parm_table[(*i)++];
2211 struct loadparm_service *pService = lp_ctx->ServicePtrs[snum];
2213 for (; parm_table[*i].label; (*i)++) {
2214 if (parm_table[*i].class == P_SEPARATOR)
2215 return &parm_table[(*i)++];
2217 if (parm_table[*i].class == P_LOCAL &&
2218 parm_table[*i].ptr &&
2219 (*parm_table[*i].label != '-') &&
2221 (parm_table[*i].ptr !=
2222 parm_table[(*i) - 1].ptr)))
2225 PTR_DIFF(parm_table[*i].ptr,
2228 if (allparameters ||
2229 !equal_parameter(parm_table[*i].type,
2230 ((char *)pService) +
2232 ((char *)&sDefault) +
2235 return &parm_table[(*i)++];
2245 /***************************************************************************
2246 Auto-load some home services.
2247 ***************************************************************************/
2249 static void lp_add_auto_services(struct loadparm_context *lp_ctx,
2255 /***************************************************************************
2256 Have we loaded a services file yet?
2257 ***************************************************************************/
2259 bool lp_loaded(void)
2264 /***************************************************************************
2265 Unload unused services.
2266 ***************************************************************************/
2268 void lp_killunused(struct loadparm_context *lp_ctx,
2269 struct smbsrv_connection *smb,
2270 bool (*snumused) (struct smbsrv_connection *, int))
2273 for (i = 0; i < lp_ctx->iNumServices; i++) {
2274 if (lp_ctx->ServicePtrs[i] == NULL)
2277 if (!snumused || !snumused(smb, i)) {
2278 talloc_free(lp_ctx->ServicePtrs[i]);
2279 lp_ctx->ServicePtrs[i] = NULL;
2284 /***************************************************************************
2285 Initialise the global parameter structure.
2286 ***************************************************************************/
2287 bool loadparm_init(struct loadparm_context *lp_ctx)
2292 lp_ctx->bInGlobalSection = true;
2294 DEBUG(3, ("Initialising global parameters\n"));
2296 for (i = 0; parm_table[i].label; i++) {
2297 if ((parm_table[i].type == P_STRING ||
2298 parm_table[i].type == P_USTRING) &&
2299 parm_table[i].ptr &&
2300 !(parm_table[i].flags & FLAG_CMDLINE)) {
2301 string_set(talloc_autofree_context(),
2302 (char **)parm_table[i].ptr, "");
2306 lp_do_global_parameter(lp_ctx, "share backend", "classic");
2308 lp_do_global_parameter(lp_ctx, "server role", "standalone");
2310 /* options that can be set on the command line must be initialised via
2311 the slower lp_do_global_parameter() to ensure that FLAG_CMDLINE is obeyed */
2313 lp_do_global_parameter(lp_ctx, "socket options", "TCP_NODELAY");
2315 lp_do_global_parameter(lp_ctx, "workgroup", DEFAULT_WORKGROUP);
2316 myname = get_myname();
2317 lp_do_global_parameter(lp_ctx, "netbios name", myname);
2319 lp_do_global_parameter(lp_ctx, "name resolve order", "lmhosts wins host bcast");
2321 lp_do_global_parameter(lp_ctx, "fstype", FSTYPE_STRING);
2322 lp_do_global_parameter(lp_ctx, "ntvfs handler", "unixuid default");
2323 lp_do_global_parameter(lp_ctx, "max connections", "-1");
2325 lp_do_global_parameter(lp_ctx, "dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup unixinfo");
2326 lp_do_global_parameter(lp_ctx, "server services", "smb rpc nbt wrepl ldap cldap web kdc drepl winbind");
2327 lp_do_global_parameter(lp_ctx, "ntptr providor", "simple_ldb");
2328 lp_do_global_parameter(lp_ctx, "auth methods:domain controller", "anonymous sam_ignoredomain");
2329 lp_do_global_parameter(lp_ctx, "auth methods:member server", "anonymous sam winbind");
2330 lp_do_global_parameter(lp_ctx, "auth methods:standalone", "anonymous sam_ignoredomain");
2331 lp_do_global_parameter(lp_ctx, "private dir", dyn_PRIVATE_DIR);
2332 lp_do_global_parameter(lp_ctx, "sam database", "sam.ldb");
2333 lp_do_global_parameter(lp_ctx, "secrets database", "secrets.ldb");
2334 lp_do_global_parameter(lp_ctx, "spoolss database", "spoolss.ldb");
2335 lp_do_global_parameter(lp_ctx, "wins config database", "wins_config.ldb");
2336 lp_do_global_parameter(lp_ctx, "wins database", "wins.ldb");
2337 lp_do_global_parameter(lp_ctx, "registry:HKEY_LOCAL_MACHINE", "hklm.ldb");
2339 /* This hive should be dynamically generated by Samba using
2340 data from the sam, but for the moment leave it in a tdb to
2341 keep regedt32 from popping up an annoying dialog. */
2342 lp_do_global_parameter(lp_ctx, "registry:HKEY_USERS", "hku.ldb");
2344 /* using UTF8 by default allows us to support all chars */
2345 lp_do_global_parameter(lp_ctx, "unix charset", "UTF8");
2347 /* Use codepage 850 as a default for the dos character set */
2348 lp_do_global_parameter(lp_ctx, "dos charset", "CP850");
2351 * Allow the default PASSWD_CHAT to be overridden in local.h.
2353 lp_do_global_parameter(lp_ctx, "passwd chat", DEFAULT_PASSWD_CHAT);
2355 lp_do_global_parameter(lp_ctx, "pid directory", dyn_PIDDIR);
2356 lp_do_global_parameter(lp_ctx, "lock dir", dyn_LOCKDIR);
2357 lp_do_global_parameter(lp_ctx, "modules dir", dyn_MODULESDIR);
2358 lp_do_global_parameter(lp_ctx, "ncalrpc dir", dyn_NCALRPCDIR);
2360 lp_do_global_parameter(lp_ctx, "socket address", "0.0.0.0");
2361 lp_do_global_parameter_var(lp_ctx, "server string",
2362 "Samba %s", SAMBA_VERSION_STRING);
2364 lp_do_global_parameter_var(lp_ctx, "announce version", "%d.%d",
2365 DEFAULT_MAJOR_VERSION,
2366 DEFAULT_MINOR_VERSION);
2368 lp_do_global_parameter(lp_ctx, "password server", "*");
2370 lp_do_global_parameter(lp_ctx, "max mux", "50");
2371 lp_do_global_parameter(lp_ctx, "max xmit", "12288");
2372 lp_do_global_parameter(lp_ctx, "password level", "0");
2373 lp_do_global_parameter(lp_ctx, "LargeReadwrite", "True");
2374 lp_do_global_parameter(lp_ctx, "server min protocol", "CORE");
2375 lp_do_global_parameter(lp_ctx, "server max protocol", "NT1");
2376 lp_do_global_parameter(lp_ctx, "client min protocol", "CORE");
2377 lp_do_global_parameter(lp_ctx, "client max protocol", "NT1");
2378 lp_do_global_parameter(lp_ctx, "security", "USER");
2379 lp_do_global_parameter(lp_ctx, "paranoid server security", "True");
2380 lp_do_global_parameter(lp_ctx, "EncryptPasswords", "True");
2381 lp_do_global_parameter(lp_ctx, "ReadRaw", "True");
2382 lp_do_global_parameter(lp_ctx, "WriteRaw", "True");
2383 lp_do_global_parameter(lp_ctx, "NullPasswords", "False");
2384 lp_do_global_parameter(lp_ctx, "ObeyPamRestrictions", "False");
2385 lp_do_global_parameter(lp_ctx, "announce as", "NT SERVER");
2387 lp_do_global_parameter(lp_ctx, "TimeServer", "False");
2388 lp_do_global_parameter(lp_ctx, "BindInterfacesOnly", "False");
2389 lp_do_global_parameter(lp_ctx, "Unicode", "True");
2390 lp_do_global_parameter(lp_ctx, "ClientLanManAuth", "True");
2391 lp_do_global_parameter(lp_ctx, "LanmanAuth", "True");
2392 lp_do_global_parameter(lp_ctx, "NTLMAuth", "True");
2393 lp_do_global_parameter(lp_ctx, "client use spnego principal", "False");
2395 lp_do_global_parameter(lp_ctx, "UnixExtensions", "False");
2397 lp_do_global_parameter(lp_ctx, "PreferredMaster", "Auto");
2398 lp_do_global_parameter(lp_ctx, "LocalMaster", "True");
2400 lp_do_global_parameter(lp_ctx, "wins support", "False");
2401 lp_do_global_parameter(lp_ctx, "dns proxy", "True");
2403 lp_do_global_parameter(lp_ctx, "winbind separator", "\\");
2404 lp_do_global_parameter(lp_ctx, "winbind sealed pipes", "True");
2405 lp_do_global_parameter(lp_ctx, "winbindd socket directory", dyn_WINBINDD_SOCKET_DIR);
2406 lp_do_global_parameter(lp_ctx, "template shell", "/bin/false");
2407 lp_do_global_parameter(lp_ctx, "template homedir", "/home/%WORKGROUP%/%ACCOUNTNAME%");
2409 lp_do_global_parameter(lp_ctx, "client signing", "Yes");
2410 lp_do_global_parameter(lp_ctx, "server signing", "auto");
2412 lp_do_global_parameter(lp_ctx, "use spnego", "True");
2414 lp_do_global_parameter(lp_ctx, "smb ports", "445 139");
2415 lp_do_global_parameter(lp_ctx, "nbt port", "137");
2416 lp_do_global_parameter(lp_ctx, "dgram port", "138");
2417 lp_do_global_parameter(lp_ctx, "cldap port", "389");
2418 lp_do_global_parameter(lp_ctx, "krb5 port", "88");
2419 lp_do_global_parameter(lp_ctx, "kpasswd port", "464");
2420 lp_do_global_parameter(lp_ctx, "web port", "901");
2421 lp_do_global_parameter(lp_ctx, "swat directory", dyn_SWATDIR);
2423 lp_do_global_parameter(lp_ctx, "nt status support", "True");
2425 lp_do_global_parameter(lp_ctx, "max wins ttl", "518400"); /* 6 days */
2426 lp_do_global_parameter(lp_ctx, "min wins ttl", "10");
2428 lp_do_global_parameter(lp_ctx, "tls enabled", "True");
2429 lp_do_global_parameter(lp_ctx, "tls keyfile", "tls/key.pem");
2430 lp_do_global_parameter(lp_ctx, "tls certfile", "tls/cert.pem");
2431 lp_do_global_parameter(lp_ctx, "tls cafile", "tls/ca.pem");
2432 lp_do_global_parameter_var(lp_ctx, "js include", "%s", dyn_JSDIR);
2433 lp_do_global_parameter_var(lp_ctx, "setup directory", "%s",
2436 for (i = 0; parm_table[i].label; i++) {
2437 if (!(parm_table[i].flags & FLAG_CMDLINE)) {
2438 parm_table[i].flags |= FLAG_DEFAULT;
2445 /***************************************************************************
2446 Load the services array from the services file. Return True on success,
2448 ***************************************************************************/
2450 bool lp_load(const char *filename)
2454 struct param_opt *data;
2455 struct loadparm_context *lp_ctx = &loadparm;
2457 filename = talloc_strdup(talloc_autofree_context(), filename);
2459 global_loadparm = lp_ctx;
2461 if (lp_ctx->Globals.param_opt != NULL) {
2462 struct param_opt *next;
2463 for (data = lp_ctx->Globals.param_opt; data; data=next) {
2465 if (data->flags & FLAG_CMDLINE) continue;
2466 DLIST_REMOVE(lp_ctx->Globals.param_opt, data);
2471 if (!loadparm_init(lp_ctx))
2474 lp_ctx->Globals.szConfigFile = filename;
2476 lp_ctx->bInGlobalSection = true;
2477 n2 = standard_sub_basic(talloc_autofree_context(), lp_ctx->Globals.szConfigFile);
2478 DEBUG(2, ("lp_load: refreshing parameters from %s\n", n2));
2480 add_to_file_list(lp_ctx, lp_ctx->Globals.szConfigFile, n2);
2482 /* We get sections first, so have to start 'behind' to make up */
2483 lp_ctx->currentService = NULL;
2484 bRetval = pm_process(n2, do_section, do_parameter, lp_ctx);
2486 /* finish up the last section */
2487 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
2489 if (lp_ctx->currentService != NULL)
2490 bRetval = service_ok(lp_ctx->currentService);
2492 lp_add_auto_services(lp_ctx, lp_auto_services(lp_ctx));
2494 lp_add_hidden(lp_ctx, "IPC$", "IPC");
2495 lp_add_hidden(lp_ctx, "ADMIN$", "DISK");
2499 if (!lp_ctx->Globals.szWINSservers && lp_ctx->Globals.bWINSsupport) {
2500 lp_do_global_parameter(lp_ctx, "wins server", "127.0.0.1");
2508 /***************************************************************************
2509 Return the max number of services.
2510 ***************************************************************************/
2512 int lp_numservices(struct loadparm_context *lp_ctx)
2514 return lp_ctx->iNumServices;
2517 /***************************************************************************
2518 Display the contents of the services array in human-readable form.
2519 ***************************************************************************/
2521 void lp_dump(struct loadparm_context *lp_ctx, FILE *f, bool show_defaults,
2527 defaults_saved = false;
2529 dump_globals(lp_ctx, f, show_defaults);
2531 dump_a_service(&sDefault, f);
2533 for (iService = 0; iService < maxtoprint; iService++)
2534 lp_dump_one(f, show_defaults, lp_ctx->ServicePtrs[iService]);
2537 /***************************************************************************
2538 Display the contents of one service in human-readable form.
2539 ***************************************************************************/
2541 void lp_dump_one(FILE *f, bool show_defaults, struct loadparm_service *service)
2543 if (service != NULL) {
2544 if (service->szService[0] == '\0')
2546 dump_a_service(service, f);
2550 struct loadparm_service *lp_servicebynum(struct loadparm_context *lp_ctx,
2553 return lp_ctx->ServicePtrs[snum];
2556 struct loadparm_service *lp_service(struct loadparm_context *lp_ctx,
2557 const char *service_name)
2562 for (iService = lp_ctx->iNumServices - 1; iService >= 0; iService--) {
2563 if (lp_ctx->ServicePtrs[iService] &&
2564 lp_ctx->ServicePtrs[iService]->szService) {
2566 * The substitution here is used to support %U is
2569 serviceName = standard_sub_basic(
2570 lp_ctx->ServicePtrs[iService],
2571 lp_ctx->ServicePtrs[iService]->szService);
2572 if (strequal(serviceName, service_name))
2573 return lp_ctx->ServicePtrs[iService];
2577 DEBUG(7,("lp_servicenumber: couldn't find %s\n", service_name));
2582 /*******************************************************************
2583 A useful volume label function.
2584 ********************************************************************/
2585 const char *volume_label(struct loadparm_service *service)
2587 const char *ret = lp_volume(service);
2589 return lp_servicename(service);
2594 /***********************************************************
2595 If we are PDC then prefer us as DMB
2596 ************************************************************/
2598 bool lp_domain_logons(struct loadparm_context *lp_ctx)
2600 return (lp_server_role(lp_ctx) == ROLE_DOMAIN_CONTROLLER);
2603 const char *lp_printername(struct loadparm_service *service)
2605 const char *ret = _lp_printername(service);
2606 if (ret == NULL || (ret != NULL && *ret == '\0'))
2607 ret = lp_const_servicename(service);
2613 /*******************************************************************
2614 Return the max print jobs per queue.
2615 ********************************************************************/
2617 int lp_maxprintjobs(struct loadparm_service *service)
2619 int maxjobs = (service != NULL) ? service->iMaxPrintJobs : sDefault.iMaxPrintJobs;
2620 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
2621 maxjobs = PRINT_MAX_JOBID - 1;