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 * This structure describes global (ie., server-wide) parameters.
77 struct loadparm_global
79 enum server_role server_role;
81 const char **smb_ports;
85 char *display_charset;
93 const char *szConfigFile;
98 char *szWINS_CONFIG_URL;
101 const char **jsInclude;
102 char *jsonrpcServicesDir;
103 const char **szPasswordServers;
104 char *szSocketOptions;
106 const char **szWINSservers;
107 const char **szInterfaces;
108 char *szSocketAddress;
109 char *szAnnounceVersion; /* This is initialised in init_globals */
112 const char **szNetbiosAliases;
113 char *szNetbiosScope;
114 char *szDomainOtherSIDs;
115 const char **szNameResolveOrder;
116 const char **dcerpc_ep_servers;
117 const char **server_services;
118 char *ntptr_providor;
119 char *szWinbindSeparator;
120 char *szWinbinddSocketDirectory;
121 char *szTemplateShell;
122 char *szTemplateHomedir;
123 int bWinbindSealedPipes;
124 char *swat_directory;
139 int paranoid_server_security;
142 int announce_as; /* This is initialised in init_globals */
149 char *socket_options;
154 int bPreferredMaster;
155 int bEncryptPasswords;
157 int bObeyPamRestrictions;
162 int bBindInterfacesOnly;
164 int bNTStatusSupport;
170 int bClientPlaintextAuth;
171 int bClientLanManAuth;
172 int bClientNTLMv2Auth;
173 int client_use_spnego_principal;
179 struct param_opt *param_opt;
184 * This structure describes a single service.
186 struct loadparm_service
198 char **ntvfs_handler;
211 int iCreate_force_mode;
218 struct param_opt *param_opt;
220 char dummy[3]; /* for alignment */
224 /* This is a default service used to prime a services structure */
225 static struct loadparm_service sDefault = {
230 .szPrintername = NULL,
231 .szHostsallow = NULL,
236 .ntvfs_handler = NULL,
237 .iMaxPrintJobs = 1000,
238 .iMaxConnections = 0,
244 .bMap_system = false,
245 .bMap_hidden = false,
246 .bMap_archive = true,
247 .bStrictLocking = true,
248 .iCreate_mask = 0744,
249 .iCreate_force_mode = 0000,
251 .iDir_force_mode = 0000,
254 .bStrictSync = false,
255 .bCIFileSystem = false,
258 /* local variables */
259 static struct loadparm_context {
260 struct loadparm_global Globals;
261 struct loadparm_service **ServicePtrs;
263 struct loadparm_service *currentService;
264 bool bInGlobalSection;
266 struct file_lists *next;
273 struct loadparm_context *global_loadparm = &loadparm;
275 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
277 /* prototypes for the special type handlers */
278 static bool handle_include(struct loadparm_context *lp_ctx,
279 const char *pszParmValue, char **ptr);
280 static bool handle_copy(struct loadparm_context *lp_ctx,
281 const char *pszParmValue, char **ptr);
283 static const struct enum_list enum_protocol[] = {
284 {PROTOCOL_SMB2, "SMB2"},
285 {PROTOCOL_NT1, "NT1"},
286 {PROTOCOL_LANMAN2, "LANMAN2"},
287 {PROTOCOL_LANMAN1, "LANMAN1"},
288 {PROTOCOL_CORE, "CORE"},
289 {PROTOCOL_COREPLUS, "COREPLUS"},
290 {PROTOCOL_COREPLUS, "CORE+"},
294 static const struct enum_list enum_security[] = {
295 {SEC_SHARE, "SHARE"},
300 static const struct enum_list enum_announce_as[] = {
301 {ANNOUNCE_AS_NT_SERVER, "NT"},
302 {ANNOUNCE_AS_NT_SERVER, "NT Server"},
303 {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"},
304 {ANNOUNCE_AS_WIN95, "win95"},
305 {ANNOUNCE_AS_WFW, "WfW"},
309 static const struct enum_list enum_bool_auto[] = {
320 /* Client-side offline caching policy types */
323 CSC_POLICY_DOCUMENTS=1,
324 CSC_POLICY_PROGRAMS=2,
328 static const struct enum_list enum_csc_policy[] = {
329 {CSC_POLICY_MANUAL, "manual"},
330 {CSC_POLICY_DOCUMENTS, "documents"},
331 {CSC_POLICY_PROGRAMS, "programs"},
332 {CSC_POLICY_DISABLE, "disable"},
336 /* SMB signing types. */
337 static const struct enum_list enum_smb_signing_vals[] = {
338 {SMB_SIGNING_OFF, "No"},
339 {SMB_SIGNING_OFF, "False"},
340 {SMB_SIGNING_OFF, "0"},
341 {SMB_SIGNING_OFF, "Off"},
342 {SMB_SIGNING_OFF, "disabled"},
343 {SMB_SIGNING_SUPPORTED, "Yes"},
344 {SMB_SIGNING_SUPPORTED, "True"},
345 {SMB_SIGNING_SUPPORTED, "1"},
346 {SMB_SIGNING_SUPPORTED, "On"},
347 {SMB_SIGNING_SUPPORTED, "enabled"},
348 {SMB_SIGNING_REQUIRED, "required"},
349 {SMB_SIGNING_REQUIRED, "mandatory"},
350 {SMB_SIGNING_REQUIRED, "force"},
351 {SMB_SIGNING_REQUIRED, "forced"},
352 {SMB_SIGNING_REQUIRED, "enforced"},
353 {SMB_SIGNING_AUTO, "auto"},
357 static const struct enum_list enum_server_role[] = {
358 {ROLE_STANDALONE, "standalone"},
359 {ROLE_DOMAIN_MEMBER, "member server"},
360 {ROLE_DOMAIN_CONTROLLER, "domain controller"},
365 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
367 * Note: We have a flag called FLAG_DEVELOPER but is not used at this time, it
368 * is implied in current control logic. This may change at some later time. A
369 * flag value of 0 means - show as development option only.
371 * The FLAG_HIDE is explicit. Parameters set this way do NOT appear in any edit
372 * screen in SWAT. This is used to exclude parameters as well as to squash all
373 * parameters that have been duplicated by pseudonyms.
375 static struct parm_struct parm_table[] = {
376 {"config file", P_STRING, P_GLOBAL, &loadparm.Globals.szConfigFile, NULL, NULL, FLAG_HIDE},
378 {"server role", P_ENUM, P_GLOBAL, &loadparm.Globals.server_role, NULL, enum_server_role, FLAG_BASIC},
380 {"dos charset", P_STRING, P_GLOBAL, &loadparm.Globals.dos_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
381 {"unix charset", P_STRING, P_GLOBAL, &loadparm.Globals.unix_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
382 {"ncalrpc dir", P_STRING, P_GLOBAL, &loadparm.Globals.ncalrpc_dir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
383 {"display charset", P_STRING, P_GLOBAL, &loadparm.Globals.display_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
384 {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
385 {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
386 {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE},
387 {"workgroup", P_USTRING, P_GLOBAL, &loadparm.Globals.szWorkgroup, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
388 {"realm", P_STRING, P_GLOBAL, &loadparm.Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
389 {"netbios name", P_USTRING, P_GLOBAL, &loadparm.Globals.szNetbiosName, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
390 {"netbios aliases", P_LIST, P_GLOBAL, &loadparm.Globals.szNetbiosAliases, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
391 {"netbios scope", P_USTRING, P_GLOBAL, &loadparm.Globals.szNetbiosScope, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
392 {"server string", P_STRING, P_GLOBAL, &loadparm.Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
393 {"interfaces", P_LIST, P_GLOBAL, &loadparm.Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
394 {"bind interfaces only", P_BOOL, P_GLOBAL, &loadparm.Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
395 {"ntvfs handler", P_LIST, P_LOCAL, &sDefault.ntvfs_handler, NULL, NULL, FLAG_ADVANCED},
396 {"ntptr providor", P_STRING, P_GLOBAL, &loadparm.Globals.ntptr_providor, NULL, NULL, FLAG_ADVANCED},
397 {"dcerpc endpoint servers", P_LIST, P_GLOBAL, &loadparm.Globals.dcerpc_ep_servers, NULL, NULL, FLAG_ADVANCED},
398 {"server services", P_LIST, P_GLOBAL, &loadparm.Globals.server_services, NULL, NULL, FLAG_ADVANCED},
400 {"security", P_ENUM, P_GLOBAL, &loadparm.Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
401 {"encrypt passwords", P_BOOL, P_GLOBAL, &loadparm.Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
402 {"null passwords", P_BOOL, P_GLOBAL, &loadparm.Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
403 {"obey pam restrictions", P_BOOL, P_GLOBAL, &loadparm.Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
404 {"password server", P_LIST, P_GLOBAL, &loadparm.Globals.szPasswordServers, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
405 {"sam database", P_STRING, P_GLOBAL, &loadparm.Globals.szSAM_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
406 {"secrets database", P_STRING, P_GLOBAL, &loadparm.Globals.szSECRETS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
407 {"spoolss database", P_STRING, P_GLOBAL, &loadparm.Globals.szSPOOLSS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
408 {"wins config database", P_STRING, P_GLOBAL, &loadparm.Globals.szWINS_CONFIG_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
409 {"wins database", P_STRING, P_GLOBAL, &loadparm.Globals.szWINS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
410 {"private dir", P_STRING, P_GLOBAL, &loadparm.Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
411 {"passwd chat", P_STRING, P_GLOBAL, &loadparm.Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
412 {"password level", P_INTEGER, P_GLOBAL, &loadparm.Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
413 {"lanman auth", P_BOOL, P_GLOBAL, &loadparm.Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
414 {"ntlm auth", P_BOOL, P_GLOBAL, &loadparm.Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
415 {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &loadparm.Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
416 {"client lanman auth", P_BOOL, P_GLOBAL, &loadparm.Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
417 {"client plaintext auth", P_BOOL, P_GLOBAL, &loadparm.Globals.bClientPlaintextAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
418 {"client use spnego principal", P_BOOL, P_GLOBAL, &loadparm.Globals.client_use_spnego_principal, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
420 {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE},
422 {"create mask", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
423 {"force create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
424 {"directory mask", P_OCTAL, P_LOCAL, &sDefault.iDir_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
425 {"force directory mode", P_OCTAL, P_LOCAL, &sDefault.iDir_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
427 {"hosts allow", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
428 {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
430 {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
431 {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_HIDE},
432 {"log file", P_STRING, P_GLOBAL, &logfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
434 {"smb ports", P_LIST, P_GLOBAL, &loadparm.Globals.smb_ports, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
435 {"nbt port", P_INTEGER, P_GLOBAL, &loadparm.Globals.nbt_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
436 {"dgram port", P_INTEGER, P_GLOBAL, &loadparm.Globals.dgram_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
437 {"cldap port", P_INTEGER, P_GLOBAL, &loadparm.Globals.cldap_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
438 {"krb5 port", P_INTEGER, P_GLOBAL, &loadparm.Globals.krb5_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
439 {"kpasswd port", P_INTEGER, P_GLOBAL, &loadparm.Globals.kpasswd_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
440 {"web port", P_INTEGER, P_GLOBAL, &loadparm.Globals.web_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
441 {"tls enabled", P_BOOL, P_GLOBAL, &loadparm.Globals.tls_enabled, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
442 {"tls keyfile", P_STRING, P_GLOBAL, &loadparm.Globals.tls_keyfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
443 {"tls certfile", P_STRING, P_GLOBAL, &loadparm.Globals.tls_certfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
444 {"tls cafile", P_STRING, P_GLOBAL, &loadparm.Globals.tls_cafile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
445 {"tls crlfile", P_STRING, P_GLOBAL, &loadparm.Globals.tls_crlfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
446 {"tls dh params file", P_STRING, P_GLOBAL, &loadparm.Globals.tls_dhpfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
447 {"swat directory", P_STRING, P_GLOBAL, &loadparm.Globals.swat_directory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
448 {"large readwrite", P_BOOL, P_GLOBAL, &loadparm.Globals.bLargeReadwrite, NULL, NULL, FLAG_DEVELOPER},
449 {"server max protocol", P_ENUM, P_GLOBAL, &loadparm.Globals.srv_maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
450 {"server min protocol", P_ENUM, P_GLOBAL, &loadparm.Globals.srv_minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
451 {"client max protocol", P_ENUM, P_GLOBAL, &loadparm.Globals.cli_maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
452 {"client min protocol", P_ENUM, P_GLOBAL, &loadparm.Globals.cli_minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
453 {"unicode", P_BOOL, P_GLOBAL, &loadparm.Globals.bUnicode, NULL, NULL, FLAG_DEVELOPER},
454 {"read raw", P_BOOL, P_GLOBAL, &loadparm.Globals.bReadRaw, NULL, NULL, FLAG_DEVELOPER},
455 {"write raw", P_BOOL, P_GLOBAL, &loadparm.Globals.bWriteRaw, NULL, NULL, FLAG_DEVELOPER},
456 {"disable netbios", P_BOOL, P_GLOBAL, &loadparm.Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
458 {"nt status support", P_BOOL, P_GLOBAL, &loadparm.Globals.bNTStatusSupport, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
460 {"announce version", P_STRING, P_GLOBAL, &loadparm.Globals.szAnnounceVersion, NULL, NULL, FLAG_DEVELOPER},
461 {"announce as", P_ENUM, P_GLOBAL, &loadparm.Globals.announce_as, NULL, enum_announce_as, FLAG_DEVELOPER},
462 {"max mux", P_INTEGER, P_GLOBAL, &loadparm.Globals.max_mux, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
463 {"max xmit", P_BYTES, P_GLOBAL, &loadparm.Globals.max_xmit, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
465 {"name resolve order", P_LIST, P_GLOBAL, &loadparm.Globals.szNameResolveOrder, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
466 {"max wins ttl", P_INTEGER, P_GLOBAL, &loadparm.Globals.max_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
467 {"min wins ttl", P_INTEGER, P_GLOBAL, &loadparm.Globals.min_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
468 {"time server", P_BOOL, P_GLOBAL, &loadparm.Globals.bTimeServer, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
469 {"unix extensions", P_BOOL, P_GLOBAL, &loadparm.Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
470 {"use spnego", P_BOOL, P_GLOBAL, &loadparm.Globals.bUseSpnego, NULL, NULL, FLAG_DEVELOPER},
471 {"server signing", P_ENUM, P_GLOBAL, &loadparm.Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
472 {"client signing", P_ENUM, P_GLOBAL, &loadparm.Globals.client_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
473 {"rpc big endian", P_BOOL, P_GLOBAL, &loadparm.Globals.bRpcBigEndian, NULL, NULL, FLAG_DEVELOPER},
475 {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL, NULL, FLAG_SHARE},
476 {"paranoid server security", P_BOOL, P_GLOBAL, &loadparm.Globals.paranoid_server_security, NULL, NULL, FLAG_DEVELOPER},
477 {"socket options", P_STRING, P_GLOBAL, &loadparm.Globals.socket_options, NULL, NULL, FLAG_DEVELOPER},
479 {"strict sync", P_BOOL, P_LOCAL, &sDefault.bStrictSync, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
480 {"case insensitive filesystem", P_BOOL, P_LOCAL, &sDefault.bCIFileSystem, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
482 {"max print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxPrintJobs, NULL, NULL, FLAG_PRINT},
483 {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_PRINT},
484 {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_HIDE},
486 {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_PRINT},
487 {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_HIDE},
489 {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
490 {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
491 {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
493 {"preferred master", P_ENUM, P_GLOBAL, &loadparm.Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
494 {"prefered master", P_ENUM, P_GLOBAL, &loadparm.Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_HIDE},
495 {"local master", P_BOOL, P_GLOBAL, &loadparm.Globals.bLocalMaster, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
496 {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
497 {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_HIDE},
499 {"wins server", P_LIST, P_GLOBAL, &loadparm.Globals.szWINSservers, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
500 {"wins support", P_BOOL, P_GLOBAL, &loadparm.Globals.bWINSsupport, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
501 {"dns proxy", P_BOOL, P_GLOBAL, &loadparm.Globals.bWINSdnsProxy, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
502 {"wins hook", P_STRING, P_GLOBAL, &loadparm.Globals.szWINSHook, NULL, NULL, FLAG_ADVANCED},
504 {"csc policy", P_ENUM, P_LOCAL, &sDefault.iCSCPolicy, NULL, enum_csc_policy, FLAG_SHARE | FLAG_GLOBAL},
506 {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
508 {"share backend", P_STRING, P_GLOBAL, &loadparm.Globals.szShareBackend, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
509 {"preload", P_STRING, P_GLOBAL, &loadparm.Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
510 {"auto services", P_STRING, P_GLOBAL, &loadparm.Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
511 {"lock dir", P_STRING, P_GLOBAL, &loadparm.Globals.szLockDir, NULL, NULL, FLAG_HIDE},
512 {"lock directory", P_STRING, P_GLOBAL, &loadparm.Globals.szLockDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
513 {"modules dir", P_STRING, P_GLOBAL, &loadparm.Globals.szModulesDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
514 {"pid directory", P_STRING, P_GLOBAL, &loadparm.Globals.szPidDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
515 {"js include", P_LIST, P_GLOBAL, &loadparm.Globals.jsInclude, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
516 {"setup directory", P_STRING, P_GLOBAL, &loadparm.Globals.szSetupDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
518 {"socket address", P_STRING, P_GLOBAL, &loadparm.Globals.szSocketAddress, NULL, NULL, FLAG_DEVELOPER},
519 {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy, NULL, FLAG_HIDE},
520 {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include, NULL, FLAG_HIDE},
522 {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
523 {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_SHARE },
524 {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_SHARE},
526 {"panic action", P_STRING, P_GLOBAL, &panic_action, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
528 {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_SHARE},
529 {"host msdfs", P_BOOL, P_GLOBAL, &loadparm.Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
530 {"winbind separator", P_STRING, P_GLOBAL, &loadparm.Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
531 {"winbindd socket directory", P_STRING, P_GLOBAL, &loadparm.Globals.szWinbinddSocketDirectory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
532 {"winbind sealed pipes", P_BOOL, P_GLOBAL, &loadparm.Globals.bWinbindSealedPipes, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
533 {"template shell", P_STRING, P_GLOBAL, &loadparm.Globals.szTemplateShell, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
534 {"template homedir", P_STRING, P_GLOBAL, &loadparm.Globals.szTemplateHomedir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
536 {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
541 return the parameter table
543 struct parm_struct *lp_parm_table(void)
548 static TALLOC_CTX *lp_talloc;
550 /******************************************************************* a
551 Free up temporary memory - called from the main loop.
552 ********************************************************************/
554 void lp_talloc_free(void)
558 talloc_free(lp_talloc);
562 /*******************************************************************
563 Convenience routine to grab string parameters into temporary memory
564 and run standard_sub_basic on them. The buffers can be written to by
565 callers without affecting the source string.
566 ********************************************************************/
568 static const char *lp_string(const char *s)
570 #if 0 /* until REWRITE done to make thread-safe */
571 size_t len = s ? strlen(s) : 0;
575 /* The follow debug is useful for tracking down memory problems
576 especially if you have an inner loop that is calling a lp_*()
577 function that returns a string. Perhaps this debug should be
578 present all the time? */
581 DEBUG(10, ("lp_string(%s)\n", s));
584 #if 0 /* until REWRITE done to make thread-safe */
586 lp_talloc = talloc_init("lp_talloc");
588 ret = talloc_array(lp_talloc, char, len + 100); /* leave room for substitution */
596 strlcpy(ret, s, len);
598 if (trim_string(ret, "\"", "\"")) {
599 if (strchr(ret,'"') != NULL)
600 strlcpy(ret, s, len);
603 standard_sub_basic(ret,len+100);
610 In this section all the functions that are used to access the
611 parameters from the rest of the program are defined
614 #define FN_GLOBAL_STRING(fn_name,var_name) \
615 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) : "";}
616 #define FN_GLOBAL_CONST_STRING(fn_name,var_name) \
617 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 : "";}
618 #define FN_GLOBAL_LIST(fn_name,var_name) \
619 const char **fn_name(struct loadparm_context *lp_ctx) {if (lp_ctx == NULL) return NULL; return lp_ctx->Globals.var_name;}
620 #define FN_GLOBAL_BOOL(fn_name,var_name) \
621 bool fn_name(struct loadparm_context *lp_ctx) {if (lp_ctx == NULL) return false; return lp_ctx->Globals.var_name;}
623 #define FN_GLOBAL_CHAR(fn_name,ptr) \
624 char fn_name(void) {return(*(char *)(ptr));}
626 #define FN_GLOBAL_INTEGER(fn_name,var_name) \
627 int fn_name(struct loadparm_context *lp_ctx) {if (lp_ctx == NULL) return 0; return lp_ctx->Globals.var_name;}
629 #define FN_LOCAL_STRING(fn_name,val) \
630 const char *fn_name(struct loadparm_service *service) {return(lp_string((const char *)((service != NULL && service->val != NULL) ? service->val : sDefault.val)));}
631 #define FN_LOCAL_CONST_STRING(fn_name,val) \
632 const char *fn_name(struct loadparm_service *service) {return (const char *)(service != NULL && service->val != NULL) ? service->val : sDefault.val;}
633 #define FN_LOCAL_LIST(fn_name,val) \
634 const char **fn_name(struct loadparm_service *service) {return(const char **)(service != NULL && service->val != NULL? service->val : sDefault.val);}
635 #define FN_LOCAL_BOOL(fn_name,val) \
636 bool fn_name(struct loadparm_service *service) {return((service != NULL)? service->val : sDefault.val);}
637 #define FN_LOCAL_INTEGER(fn_name,val) \
638 int fn_name(struct loadparm_service *service) {return((service != NULL)? service->val : sDefault.val);}
640 _PUBLIC_ FN_GLOBAL_INTEGER(lp_server_role, server_role)
641 _PUBLIC_ FN_GLOBAL_LIST(lp_smb_ports, smb_ports)
642 _PUBLIC_ FN_GLOBAL_INTEGER(lp_nbt_port, nbt_port)
643 _PUBLIC_ FN_GLOBAL_INTEGER(lp_dgram_port, dgram_port)
644 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cldap_port, cldap_port)
645 _PUBLIC_ FN_GLOBAL_INTEGER(lp_krb5_port, krb5_port)
646 _PUBLIC_ FN_GLOBAL_INTEGER(lp_kpasswd_port, kpasswd_port)
647 _PUBLIC_ FN_GLOBAL_INTEGER(lp_web_port, web_port)
648 _PUBLIC_ FN_GLOBAL_STRING(lp_swat_directory, swat_directory)
649 _PUBLIC_ FN_GLOBAL_BOOL(lp_tls_enabled, tls_enabled)
650 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_keyfile, tls_keyfile)
651 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_certfile, tls_certfile)
652 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_cafile, tls_cafile)
653 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_crlfile, tls_crlfile)
654 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_dhpfile, tls_dhpfile)
655 _PUBLIC_ FN_GLOBAL_STRING(lp_share_backend, szShareBackend)
656 _PUBLIC_ FN_GLOBAL_STRING(lp_sam_url, szSAM_URL)
657 _PUBLIC_ FN_GLOBAL_STRING(lp_secrets_url, szSECRETS_URL)
658 _PUBLIC_ FN_GLOBAL_STRING(lp_spoolss_url, szSPOOLSS_URL)
659 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_config_url, szWINS_CONFIG_URL)
660 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_url, szWINS_URL)
661 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_winbind_separator, szWinbindSeparator)
662 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_winbindd_socket_directory, szWinbinddSocketDirectory)
663 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_template_shell, szTemplateShell)
664 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_template_homedir, szTemplateHomedir)
665 _PUBLIC_ FN_GLOBAL_BOOL(lp_winbind_sealed_pipes, bWinbindSealedPipes)
666 _PUBLIC_ FN_GLOBAL_STRING(lp_private_dir, szPrivateDir)
667 _PUBLIC_ FN_GLOBAL_STRING(lp_serverstring, szServerString)
668 _PUBLIC_ FN_GLOBAL_STRING(lp_lockdir, szLockDir)
669 _PUBLIC_ FN_GLOBAL_STRING(lp_modulesdir, szModulesDir)
670 _PUBLIC_ FN_GLOBAL_STRING(lp_setupdir, szSetupDir)
671 _PUBLIC_ FN_GLOBAL_STRING(lp_ncalrpc_dir, ncalrpc_dir)
672 _PUBLIC_ FN_GLOBAL_STRING(lp_dos_charset, dos_charset)
673 _PUBLIC_ FN_GLOBAL_STRING(lp_unix_charset, unix_charset)
674 _PUBLIC_ FN_GLOBAL_STRING(lp_display_charset, display_charset)
675 _PUBLIC_ FN_GLOBAL_STRING(lp_piddir, szPidDir)
676 _PUBLIC_ FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, dcerpc_ep_servers)
677 _PUBLIC_ FN_GLOBAL_LIST(lp_server_services, server_services)
678 _PUBLIC_ FN_GLOBAL_STRING(lp_ntptr_providor, ntptr_providor)
679 _PUBLIC_ FN_GLOBAL_STRING(lp_auto_services, szAutoServices)
680 _PUBLIC_ FN_GLOBAL_STRING(lp_passwd_chat, szPasswdChat)
681 _PUBLIC_ FN_GLOBAL_LIST(lp_passwordserver, szPasswordServers)
682 _PUBLIC_ FN_GLOBAL_LIST(lp_name_resolve_order, szNameResolveOrder)
683 _PUBLIC_ FN_GLOBAL_STRING(lp_realm, szRealm)
684 _PUBLIC_ FN_GLOBAL_STRING(lp_socket_options, socket_options)
685 _PUBLIC_ FN_GLOBAL_STRING(lp_workgroup, szWorkgroup)
686 _PUBLIC_ FN_GLOBAL_STRING(lp_netbios_name, szNetbiosName)
687 _PUBLIC_ FN_GLOBAL_STRING(lp_netbios_scope, szNetbiosScope)
688 _PUBLIC_ FN_GLOBAL_LIST(lp_wins_server_list, szWINSservers)
689 _PUBLIC_ FN_GLOBAL_LIST(lp_interfaces, szInterfaces)
690 _PUBLIC_ FN_GLOBAL_STRING(lp_socket_address, szSocketAddress)
691 _PUBLIC_ FN_GLOBAL_LIST(lp_netbios_aliases, szNetbiosAliases)
693 _PUBLIC_ FN_GLOBAL_BOOL(lp_disable_netbios, bDisableNetbios)
694 _PUBLIC_ FN_GLOBAL_BOOL(lp_wins_support, bWINSsupport)
695 _PUBLIC_ FN_GLOBAL_BOOL(lp_wins_dns_proxy, bWINSdnsProxy)
696 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_hook, szWINSHook)
697 _PUBLIC_ FN_GLOBAL_STRING(lp_configfile, szConfigFile)
698 _PUBLIC_ FN_GLOBAL_BOOL(lp_local_master, bLocalMaster)
699 _PUBLIC_ FN_GLOBAL_BOOL(lp_readraw, bReadRaw)
700 _PUBLIC_ FN_GLOBAL_BOOL(lp_large_readwrite, bLargeReadwrite)
701 _PUBLIC_ FN_GLOBAL_BOOL(lp_writeraw, bWriteRaw)
702 _PUBLIC_ FN_GLOBAL_BOOL(lp_null_passwords, bNullPasswords)
703 _PUBLIC_ FN_GLOBAL_BOOL(lp_obey_pam_restrictions, bObeyPamRestrictions)
704 _PUBLIC_ FN_GLOBAL_BOOL(lp_encrypted_passwords, bEncryptPasswords)
705 _PUBLIC_ FN_GLOBAL_BOOL(lp_time_server, bTimeServer)
706 _PUBLIC_ FN_GLOBAL_BOOL(lp_bind_interfaces_only, bBindInterfacesOnly)
707 _PUBLIC_ FN_GLOBAL_BOOL(lp_unicode, bUnicode)
708 _PUBLIC_ FN_GLOBAL_BOOL(lp_nt_status_support, bNTStatusSupport)
709 _PUBLIC_ FN_GLOBAL_BOOL(lp_lanman_auth, bLanmanAuth)
710 _PUBLIC_ FN_GLOBAL_BOOL(lp_ntlm_auth, bNTLMAuth)
711 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_plaintext_auth, bClientPlaintextAuth)
712 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_lanman_auth, bClientLanManAuth)
713 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, bClientNTLMv2Auth)
714 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_use_spnego_principal, client_use_spnego_principal)
715 _PUBLIC_ FN_GLOBAL_BOOL(lp_host_msdfs, bHostMSDfs)
716 _PUBLIC_ FN_GLOBAL_BOOL(lp_unix_extensions, bUnixExtensions)
717 _PUBLIC_ FN_GLOBAL_BOOL(lp_use_spnego, bUseSpnego)
718 _PUBLIC_ FN_GLOBAL_BOOL(lp_rpc_big_endian, bRpcBigEndian)
719 _PUBLIC_ FN_GLOBAL_INTEGER(lp_max_wins_ttl, max_wins_ttl)
720 _PUBLIC_ FN_GLOBAL_INTEGER(lp_min_wins_ttl, min_wins_ttl)
721 _PUBLIC_ FN_GLOBAL_INTEGER(lp_maxmux, max_mux)
722 _PUBLIC_ FN_GLOBAL_INTEGER(lp_max_xmit, max_xmit)
723 _PUBLIC_ FN_GLOBAL_INTEGER(lp_passwordlevel, pwordlevel)
724 _PUBLIC_ FN_GLOBAL_INTEGER(lp_srv_maxprotocol, srv_maxprotocol)
725 _PUBLIC_ FN_GLOBAL_INTEGER(lp_srv_minprotocol, srv_minprotocol)
726 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cli_maxprotocol, cli_maxprotocol)
727 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cli_minprotocol, cli_minprotocol)
728 _PUBLIC_ FN_GLOBAL_INTEGER(lp_security, security)
729 _PUBLIC_ FN_GLOBAL_BOOL(lp_paranoid_server_security, paranoid_server_security)
730 _PUBLIC_ FN_GLOBAL_INTEGER(lp_announce_as, announce_as)
731 _PUBLIC_ FN_GLOBAL_LIST(lp_js_include, jsInclude)
732 _PUBLIC_ FN_LOCAL_STRING(lp_servicename, szService)
733 _PUBLIC_ FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
734 _PUBLIC_ FN_LOCAL_STRING(lp_pathname, szPath)
735 static FN_LOCAL_STRING(_lp_printername, szPrintername)
736 _PUBLIC_ FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
737 _PUBLIC_ FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
738 _PUBLIC_ FN_LOCAL_STRING(lp_comment, comment)
739 _PUBLIC_ FN_LOCAL_STRING(lp_fstype, fstype)
740 static FN_LOCAL_STRING(lp_volume, volume)
741 _PUBLIC_ FN_LOCAL_LIST(lp_ntvfs_handler, ntvfs_handler)
742 _PUBLIC_ FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
743 _PUBLIC_ FN_LOCAL_BOOL(lp_browseable, bBrowseable)
744 _PUBLIC_ FN_LOCAL_BOOL(lp_readonly, bRead_only)
745 _PUBLIC_ FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
746 _PUBLIC_ FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
747 _PUBLIC_ FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
748 _PUBLIC_ FN_LOCAL_BOOL(lp_strict_locking, bStrictLocking)
749 _PUBLIC_ FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
750 _PUBLIC_ FN_LOCAL_BOOL(lp_ci_filesystem, bCIFileSystem)
751 _PUBLIC_ FN_LOCAL_BOOL(lp_map_system, bMap_system)
752 _PUBLIC_ FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
753 _PUBLIC_ FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
754 _PUBLIC_ FN_LOCAL_INTEGER(lp_create_mask, iCreate_mask)
755 _PUBLIC_ FN_LOCAL_INTEGER(lp_force_create_mode, iCreate_force_mode)
756 _PUBLIC_ FN_LOCAL_INTEGER(lp_dir_mask, iDir_mask)
757 _PUBLIC_ FN_LOCAL_INTEGER(lp_force_dir_mode, iDir_force_mode)
758 _PUBLIC_ FN_GLOBAL_INTEGER(lp_server_signing, server_signing)
759 _PUBLIC_ FN_GLOBAL_INTEGER(lp_client_signing, client_signing)
761 /* local prototypes */
762 static int map_parameter(const char *pszParmName);
763 static struct loadparm_service *getservicebyname(struct loadparm_context *lp_ctx,
764 const char *pszServiceName);
765 static void copy_service(struct loadparm_service *pserviceDest,
766 struct loadparm_service *pserviceSource,
768 static bool service_ok(struct loadparm_service *service);
769 static bool do_section(const char *pszSectionName, void *);
770 static void init_copymap(struct loadparm_service *pservice);
772 /* This is a helper function for parametrical options support. */
773 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
774 /* Actual parametrical functions are quite simple */
775 const char *lp_get_parametric(struct loadparm_context *lp_ctx,
776 struct loadparm_service *service,
777 const char *type, const char *option)
780 struct param_opt *data;
782 data = (service == NULL ? lp_ctx->Globals.param_opt : service->param_opt);
784 asprintf(&vfskey, "%s:%s", type, option);
788 if (strcmp(data->key, vfskey) == 0) {
795 if (service != NULL) {
796 /* Try to fetch the same option but from globals */
797 /* but only if we are not already working with Globals */
798 for (data = lp_ctx->Globals.param_opt; data;
800 if (strcmp(data->key, vfskey) == 0) {
813 /*******************************************************************
814 convenience routine to return int parameters.
815 ********************************************************************/
816 static int lp_int(const char *s)
820 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
824 return strtol(s, NULL, 0);
827 /*******************************************************************
828 convenience routine to return unsigned long parameters.
829 ********************************************************************/
830 static int lp_ulong(const char *s)
834 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
838 return strtoul(s, NULL, 0);
841 /*******************************************************************
842 convenience routine to return unsigned long parameters.
843 ********************************************************************/
844 static double lp_double(const char *s)
848 DEBUG(0,("lp_double(%s): is called with NULL!\n",s));
852 return strtod(s, NULL);
855 /*******************************************************************
856 convenience routine to return boolean parameters.
857 ********************************************************************/
858 static bool lp_bool(const char *s)
863 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
867 if (!set_boolean(s, &ret)) {
868 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
876 /* Return parametric option from a given service. Type is a part of option before ':' */
877 /* Parametric option has following syntax: 'Type: option = value' */
878 /* Returned value is allocated in 'lp_talloc' context */
880 const char *lp_parm_string(struct loadparm_context *lp_ctx,
881 struct loadparm_service *service, const char *type,
884 const char *value = lp_get_parametric(lp_ctx, service, type, option);
887 return lp_string(value);
892 /* Return parametric option from a given service. Type is a part of option before ':' */
893 /* Parametric option has following syntax: 'Type: option = value' */
894 /* Returned value is allocated in 'lp_talloc' context */
896 const char **lp_parm_string_list(struct loadparm_context *lp_ctx,
897 struct loadparm_service *service,
899 const char *option, const char *separator)
901 const char *value = lp_get_parametric(lp_ctx, service, type, option);
904 return str_list_make(talloc_autofree_context(), value,
910 /* Return parametric option from a given service. Type is a part of option before ':' */
911 /* Parametric option has following syntax: 'Type: option = value' */
913 int lp_parm_int(struct loadparm_context *lp_ctx,
914 struct loadparm_service *service, const char *type,
915 const char *option, int default_v)
917 const char *value = lp_get_parametric(lp_ctx, service, type, option);
920 return lp_int(value);
925 /* Return parametric option from a given service. Type is a part of
927 * Parametric option has following syntax: 'Type: option = value'.
930 int lp_parm_bytes(struct loadparm_context *lp_ctx,
931 struct loadparm_service *service, const char *type,
932 const char *option, int default_v)
936 const char *value = lp_get_parametric(lp_ctx, service, type, option);
938 if (value && conv_str_size(value, &bval)) {
939 if (bval <= INT_MAX) {
947 /* Return parametric option from a given service. Type is a part of option before ':' */
948 /* Parametric option has following syntax: 'Type: option = value' */
950 unsigned long lp_parm_ulong(struct loadparm_context *lp_ctx,
951 struct loadparm_service *service, const char *type,
952 const char *option, unsigned long default_v)
954 const char *value = lp_get_parametric(lp_ctx, service, type, option);
957 return lp_ulong(value);
963 double lp_parm_double(struct loadparm_context *lp_ctx,
964 struct loadparm_service *service, const char *type,
965 const char *option, double default_v)
967 const char *value = lp_get_parametric(lp_ctx, service, type, option);
970 return lp_double(value);
975 /* Return parametric option from a given service. Type is a part of option before ':' */
976 /* Parametric option has following syntax: 'Type: option = value' */
978 bool lp_parm_bool(struct loadparm_context *lp_ctx,
979 struct loadparm_service *service, const char *type,
980 const char *option, bool default_v)
982 const char *value = lp_get_parametric(lp_ctx, service, type, option);
985 return lp_bool(value);
991 /***************************************************************************
992 Initialise a service to the defaults.
993 ***************************************************************************/
995 static struct loadparm_service *init_service(TALLOC_CTX *mem_ctx)
997 struct loadparm_service *pservice =
998 talloc_zero(mem_ctx, struct loadparm_service);
999 copy_service(pservice, &sDefault, NULL);
1004 Set a string value, deallocating any existing space, and allocing the space
1007 static bool string_set(TALLOC_CTX *mem_ctx, char **dest, const char *src)
1014 *dest = talloc_strdup(mem_ctx, src);
1015 if ((*dest) == NULL) {
1016 DEBUG(0,("Out of memory in string_init\n"));
1025 /***************************************************************************
1026 Add a new service to the services array initialising it with the given
1028 ***************************************************************************/
1030 static struct loadparm_service *add_a_service(struct loadparm_context *lp_ctx,
1031 const struct loadparm_service *pservice,
1035 struct loadparm_service tservice;
1036 int num_to_alloc = lp_ctx->iNumServices + 1;
1037 struct param_opt *data, *pdata;
1039 tservice = *pservice;
1041 /* it might already exist */
1043 struct loadparm_service *service = getservicebyname(lp_ctx,
1045 if (service != NULL) {
1046 /* Clean all parametric options for service */
1047 /* They will be added during parsing again */
1048 data = service->param_opt;
1054 service->param_opt = NULL;
1059 /* find an invalid one */
1060 for (i = 0; i < lp_ctx->iNumServices; i++)
1061 if (lp_ctx->ServicePtrs[i] == NULL)
1064 /* if not, then create one */
1065 if (i == lp_ctx->iNumServices) {
1066 struct loadparm_service **tsp;
1068 tsp = realloc_p(lp_ctx->ServicePtrs, struct loadparm_service *,
1072 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1076 lp_ctx->ServicePtrs = tsp;
1077 lp_ctx->ServicePtrs[lp_ctx->iNumServices] = NULL;
1080 lp_ctx->iNumServices++;
1083 lp_ctx->ServicePtrs[i] = init_service(talloc_autofree_context());
1084 if (lp_ctx->ServicePtrs[i] == NULL) {
1085 DEBUG(0,("add_a_service: out of memory!\n"));
1088 copy_service(lp_ctx->ServicePtrs[i], &tservice, NULL);
1090 string_set(lp_ctx->ServicePtrs[i], &lp_ctx->ServicePtrs[i]->szService, name);
1091 return lp_ctx->ServicePtrs[i];
1094 /***************************************************************************
1095 Add a new home service, with the specified home directory, defaults coming
1097 ***************************************************************************/
1099 bool lp_add_home(struct loadparm_context *lp_ctx,
1100 const char *pszHomename,
1101 struct loadparm_service *default_service,
1102 const char *user, const char *pszHomedir)
1104 struct loadparm_service *service;
1106 service = add_a_service(lp_ctx, default_service, pszHomename);
1108 if (service == NULL)
1111 if (!(*(default_service->szPath))
1112 || strequal(default_service->szPath, sDefault.szPath)) {
1113 service->szPath = talloc_strdup(service, pszHomedir);
1115 service->szPath = string_sub_talloc(service, lp_pathname(default_service),"%H", pszHomedir);
1118 if (!(*(service->comment))) {
1119 service->comment = talloc_asprintf(service, "Home directory of %s", user);
1121 service->bAvailable = default_service->bAvailable;
1122 service->bBrowseable = default_service->bBrowseable;
1124 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n",
1125 pszHomename, user, service->szPath));
1130 /***************************************************************************
1131 Add a new service, based on an old one.
1132 ***************************************************************************/
1134 struct loadparm_service *lp_add_service(struct loadparm_context *lp_ctx,
1135 const char *pszService,
1136 struct loadparm_service *default_service)
1138 return add_a_service(lp_ctx, default_service, pszService);
1141 /***************************************************************************
1142 Add the IPC service.
1143 ***************************************************************************/
1145 static bool lp_add_hidden(struct loadparm_context *lp_ctx, const char *name,
1148 struct loadparm_service *service = add_a_service(lp_ctx, &sDefault, name);
1150 if (service == NULL)
1153 string_set(service, &service->szPath, tmpdir());
1155 service->comment = talloc_asprintf(service, "%s Service (%s)",
1156 fstype, lp_ctx->Globals.szServerString);
1157 string_set(service, &service->fstype, fstype);
1158 service->iMaxConnections = -1;
1159 service->bAvailable = true;
1160 service->bRead_only = true;
1161 service->bPrint_ok = false;
1162 service->bBrowseable = false;
1164 if (strcasecmp(fstype, "IPC") == 0) {
1165 lp_do_service_parameter(lp_ctx, service, "ntvfs handler",
1169 DEBUG(3, ("adding hidden service %s\n", name));
1174 /***************************************************************************
1175 Add a new printer service, with defaults coming from service iFrom.
1176 ***************************************************************************/
1178 bool lp_add_printer(struct loadparm_context *lp_ctx,
1179 const char *pszPrintername,
1180 struct loadparm_service *default_service)
1182 const char *comment = "From Printcap";
1183 struct loadparm_service *service;
1184 service = add_a_service(lp_ctx, default_service, pszPrintername);
1186 if (service == NULL)
1189 /* note that we do NOT default the availability flag to True - */
1190 /* we take it from the default service passed. This allows all */
1191 /* dynamic printers to be disabled by disabling the [printers] */
1192 /* entry (if/when the 'available' keyword is implemented!). */
1194 /* the printer name is set to the service name. */
1195 string_set(service, &service->szPrintername, pszPrintername);
1196 string_set(service, &service->comment, comment);
1197 service->bBrowseable = sDefault.bBrowseable;
1198 /* Printers cannot be read_only. */
1199 service->bRead_only = false;
1200 /* Printer services must be printable. */
1201 service->bPrint_ok = true;
1203 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1208 /***************************************************************************
1209 Map a parameter's string representation to something we can use.
1210 Returns False if the parameter string is not recognised, else TRUE.
1211 ***************************************************************************/
1213 static int map_parameter(const char *pszParmName)
1217 if (*pszParmName == '-')
1220 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1221 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1224 /* Warn only if it isn't parametric option */
1225 if (strchr(pszParmName, ':') == NULL)
1226 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1227 /* We do return 'fail' for parametric options as well because they are
1228 stored in different storage
1235 return the parameter structure for a parameter
1237 struct parm_struct *lp_parm_struct(const char *name)
1239 int parmnum = map_parameter(name);
1240 if (parmnum == -1) return NULL;
1241 return &parm_table[parmnum];
1245 return the parameter pointer for a parameter
1247 void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
1249 if (service == NULL)
1252 return ((char *)service) + PTR_DIFF(parm->ptr, &sDefault);
1255 /***************************************************************************
1256 Find a service by name. Otherwise works like get_service.
1257 ***************************************************************************/
1259 static struct loadparm_service *getservicebyname(struct loadparm_context *lp_ctx,
1260 const char *pszServiceName)
1264 for (iService = lp_ctx->iNumServices - 1; iService >= 0; iService--)
1265 if (lp_ctx->ServicePtrs[iService] != NULL &&
1266 strwicmp(lp_ctx->ServicePtrs[iService]->szService, pszServiceName) == 0) {
1267 return lp_ctx->ServicePtrs[iService];
1273 /***************************************************************************
1274 Copy a service structure to another.
1275 If pcopymapDest is NULL then copy all fields
1276 ***************************************************************************/
1278 static void copy_service(struct loadparm_service *pserviceDest,
1279 struct loadparm_service *pserviceSource,
1283 bool bcopyall = (pcopymapDest == NULL);
1284 struct param_opt *data, *pdata, *paramo;
1287 for (i = 0; parm_table[i].label; i++)
1288 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1289 (bcopyall || pcopymapDest[i])) {
1290 void *def_ptr = parm_table[i].ptr;
1292 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
1295 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
1298 switch (parm_table[i].type) {
1300 *(int *)dest_ptr = *(int *)src_ptr;
1306 *(int *)dest_ptr = *(int *)src_ptr;
1310 string_set(pserviceDest,
1316 string_set(pserviceDest,
1319 strupper(*(char **)dest_ptr);
1322 *(const char ***)dest_ptr = str_list_copy(talloc_autofree_context(),
1323 *(const char ***)src_ptr);
1331 init_copymap(pserviceDest);
1332 if (pserviceSource->copymap)
1333 memcpy((void *)pserviceDest->copymap,
1334 (void *)pserviceSource->copymap,
1335 sizeof(int) * NUMPARAMETERS);
1338 data = pserviceSource->param_opt;
1341 pdata = pserviceDest->param_opt;
1342 /* Traverse destination */
1344 /* If we already have same option, override it */
1345 if (strcmp(pdata->key, data->key) == 0) {
1346 talloc_free(pdata->value);
1347 pdata->value = talloc_reference(pdata,
1352 pdata = pdata->next;
1355 paramo = talloc(pserviceDest, struct param_opt);
1358 paramo->key = talloc_reference(paramo, data->key);
1359 paramo->value = talloc_reference(paramo, data->value);
1360 DLIST_ADD(pserviceDest->param_opt, paramo);
1366 /***************************************************************************
1367 Check a service for consistency. Return False if the service is in any way
1368 incomplete or faulty, else True.
1369 ***************************************************************************/
1371 static bool service_ok(struct loadparm_service *service)
1376 if (service->szService[0] == '\0') {
1377 DEBUG(0, ("The following message indicates an internal error:\n"));
1378 DEBUG(0, ("No service name in service entry.\n"));
1382 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1383 /* I can't see why you'd want a non-printable printer service... */
1384 if (strwicmp(service->szService, PRINTERS_NAME) == 0) {
1385 if (!service->bPrint_ok) {
1386 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
1387 service->szService));
1388 service->bPrint_ok = true;
1390 /* [printers] service must also be non-browsable. */
1391 if (service->bBrowseable)
1392 service->bBrowseable = false;
1395 /* If a service is flagged unavailable, log the fact at level 0. */
1396 if (!service->bAvailable)
1397 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
1398 service->szService));
1404 /*******************************************************************
1405 Keep a linked list of all config files so we know when one has changed
1406 it's date and needs to be reloaded.
1407 ********************************************************************/
1409 static void add_to_file_list(struct loadparm_context *lp_ctx,
1410 const char *fname, const char *subfname)
1412 struct file_lists *f = lp_ctx->file_lists;
1415 if (f->name && !strcmp(f->name, fname))
1421 f = talloc(talloc_autofree_context(), struct file_lists);
1424 f->next = lp_ctx->file_lists;
1425 f->name = talloc_strdup(f, fname);
1430 f->subfname = talloc_strdup(f, subfname);
1435 lp_ctx->file_lists = f;
1436 f->modtime = file_modtime(subfname);
1438 time_t t = file_modtime(subfname);
1444 /*******************************************************************
1445 Check if a config file has changed date.
1446 ********************************************************************/
1448 bool lp_file_list_changed(struct loadparm_context *lp_ctx)
1450 struct file_lists *f;
1451 DEBUG(6, ("lp_file_list_changed()\n"));
1453 for (f = lp_ctx->file_lists; f != NULL; f = f->next) {
1457 n2 = standard_sub_basic(talloc_autofree_context(), f->name);
1459 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
1460 f->name, n2, ctime(&f->modtime)));
1462 mod_time = file_modtime(n2);
1464 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
1465 DEBUGADD(6, ("file %s modified: %s\n", n2,
1467 f->modtime = mod_time;
1468 talloc_free(f->subfname);
1469 f->subfname = talloc_strdup(f, n2);
1476 /***************************************************************************
1477 Handle the include operation.
1478 ***************************************************************************/
1480 static bool handle_include(struct loadparm_context *lp_ctx,
1481 const char *pszParmValue, char **ptr)
1483 char *fname = standard_sub_basic(talloc_autofree_context(),
1486 add_to_file_list(lp_ctx, pszParmValue, fname);
1488 string_set(talloc_autofree_context(), ptr, fname);
1490 if (file_exist(fname))
1491 return pm_process(fname, do_section, do_parameter, lp_ctx);
1493 DEBUG(2, ("Can't find include file %s\n", fname));
1498 /***************************************************************************
1499 Handle the interpretation of the copy parameter.
1500 ***************************************************************************/
1502 static bool handle_copy(struct loadparm_context *lp_ctx,
1503 const char *pszParmValue, char **ptr)
1506 struct loadparm_service *serviceTemp;
1508 string_set(talloc_autofree_context(), ptr, pszParmValue);
1512 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
1514 if ((serviceTemp = getservicebyname(lp_ctx, pszParmValue)) != NULL) {
1515 if (serviceTemp == lp_ctx->currentService) {
1516 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
1518 copy_service(lp_ctx->currentService,
1520 lp_ctx->currentService->copymap);
1524 DEBUG(0, ("Unable to copy service - source not found: %s\n",
1532 /***************************************************************************
1533 Initialise a copymap.
1534 ***************************************************************************/
1536 static void init_copymap(struct loadparm_service *pservice)
1539 talloc_free(pservice->copymap);
1540 pservice->copymap = talloc_array(pservice, int, NUMPARAMETERS);
1541 if (pservice->copymap == NULL) {
1543 ("Couldn't allocate copymap!! (size %d)\n",
1544 (int)NUMPARAMETERS));
1547 for (i = 0; i < NUMPARAMETERS; i++)
1548 pservice->copymap[i] = true;
1551 /***************************************************************************
1552 Process a parametric option
1553 ***************************************************************************/
1554 static bool lp_do_parameter_parametric(struct loadparm_context *lp_ctx,
1555 struct loadparm_service *service,
1556 const char *pszParmName,
1557 const char *pszParmValue, int flags)
1559 struct param_opt *paramo, *data;
1561 TALLOC_CTX *mem_ctx;
1563 while (isspace((unsigned char)*pszParmName)) {
1567 name = strdup(pszParmName);
1568 if (!name) return false;
1572 if (service == NULL) {
1573 data = lp_ctx->Globals.param_opt;
1574 mem_ctx = talloc_autofree_context();
1576 data = service->param_opt;
1580 /* Traverse destination */
1581 for (paramo=data; paramo; paramo=paramo->next) {
1582 /* If we already have the option set, override it unless
1583 it was a command line option and the new one isn't */
1584 if (strcmp(paramo->key, name) == 0) {
1585 if ((paramo->flags & FLAG_CMDLINE) &&
1586 !(flags & FLAG_CMDLINE)) {
1590 talloc_free(paramo->value);
1591 paramo->value = talloc_strdup(paramo, pszParmValue);
1592 paramo->flags = flags;
1598 paramo = talloc(mem_ctx, struct param_opt);
1601 paramo->key = talloc_strdup(paramo, name);
1602 paramo->value = talloc_strdup(paramo, pszParmValue);
1603 paramo->flags = flags;
1604 if (service == NULL) {
1605 DLIST_ADD(lp_ctx->Globals.param_opt, paramo);
1607 DLIST_ADD(service->param_opt, paramo);
1615 static bool set_variable(TALLOC_CTX *mem_ctx, int parmnum, void *parm_ptr,
1616 const char *pszParmName, const char *pszParmValue,
1617 struct loadparm_context *lp_ctx)
1620 /* if it is a special case then go ahead */
1621 if (parm_table[parmnum].special) {
1622 parm_table[parmnum].special(lp_ctx, pszParmValue,
1627 /* now switch on the type of variable it is */
1628 switch (parm_table[parmnum].type)
1632 if (!set_boolean(pszParmValue, &b)) {
1633 DEBUG(0,("lp_do_parameter(%s): value is not boolean!\n", pszParmValue));
1636 *(int *)parm_ptr = b;
1641 *(int *)parm_ptr = atoi(pszParmValue);
1645 *(int *)parm_ptr = strtol(pszParmValue, NULL, 8);
1651 if (conv_str_size(pszParmValue, &val)) {
1652 if (val <= INT_MAX) {
1653 *(int *)parm_ptr = (int)val;
1658 DEBUG(0,("lp_do_parameter(%s): value is not "
1659 "a valid size specifier!\n", pszParmValue));
1664 *(const char ***)parm_ptr = str_list_make(mem_ctx,
1665 pszParmValue, NULL);
1669 string_set(mem_ctx, (char **)parm_ptr, pszParmValue);
1673 string_set(mem_ctx, (char **)parm_ptr, pszParmValue);
1674 strupper(*(char **)parm_ptr);
1678 for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
1681 parm_table[parmnum].enum_list[i].name)) {
1683 parm_table[parmnum].
1688 if (!parm_table[parmnum].enum_list[i].name) {
1689 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n",
1690 pszParmValue, pszParmName));
1696 if (parm_table[parmnum].flags & FLAG_DEFAULT) {
1697 parm_table[parmnum].flags &= ~FLAG_DEFAULT;
1698 /* we have to also unset FLAG_DEFAULT on aliases */
1699 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1700 parm_table[i].flags &= ~FLAG_DEFAULT;
1702 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1703 parm_table[i].flags &= ~FLAG_DEFAULT;
1710 bool lp_do_global_parameter(struct loadparm_context *lp_ctx,
1711 const char *pszParmName, const char *pszParmValue)
1713 int parmnum = map_parameter(pszParmName);
1717 if (strchr(pszParmName, ':')) {
1718 return lp_do_parameter_parametric(lp_ctx, NULL, pszParmName, pszParmValue, 0);
1720 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1724 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1725 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1729 /* if the flag has been set on the command line, then don't allow override,
1730 but don't report an error */
1731 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1735 parm_ptr = parm_table[parmnum].ptr;
1737 return set_variable(talloc_autofree_context(), parmnum, parm_ptr,
1738 pszParmName, pszParmValue, lp_ctx);
1741 bool lp_do_service_parameter(struct loadparm_context *lp_ctx,
1742 struct loadparm_service *service,
1743 const char *pszParmName, const char *pszParmValue)
1745 void *def_ptr = NULL;
1748 int parmnum = map_parameter(pszParmName);
1751 if (strchr(pszParmName, ':')) {
1752 return lp_do_parameter_parametric(lp_ctx, service, pszParmName, pszParmValue, 0);
1754 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1758 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1759 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1763 /* if the flag has been set on the command line, then don't allow override,
1764 but don't report an error */
1765 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1769 def_ptr = parm_table[parmnum].ptr;
1771 if (parm_table[parmnum].class == P_GLOBAL) {
1773 ("Global parameter %s found in service section!\n",
1777 parm_ptr = ((char *)service) + PTR_DIFF(def_ptr, &sDefault);
1779 if (!service->copymap)
1780 init_copymap(service);
1782 /* this handles the aliases - set the copymap for other
1783 * entries with the same data pointer */
1784 for (i = 0; parm_table[i].label; i++)
1785 if (parm_table[i].ptr == parm_table[parmnum].ptr)
1786 service->copymap[i] = false;
1788 return set_variable(service, parmnum, parm_ptr, pszParmName,
1789 pszParmValue, lp_ctx);
1792 /***************************************************************************
1793 Process a parameter.
1794 ***************************************************************************/
1796 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
1799 struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata;
1801 if (lp_ctx->bInGlobalSection)
1802 return lp_do_global_parameter(lp_ctx, pszParmName,
1805 return lp_do_service_parameter(lp_ctx, lp_ctx->currentService,
1806 pszParmName, pszParmValue);
1810 variable argument do parameter
1812 bool lp_do_global_parameter_var(struct loadparm_context *lp_ctx, const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4);
1813 bool lp_do_global_parameter_var(struct loadparm_context *lp_ctx,
1814 const char *pszParmName, const char *fmt, ...)
1821 s = talloc_vasprintf(NULL, fmt, ap);
1823 ret = lp_do_global_parameter(lp_ctx, pszParmName, s);
1830 set a parameter from the commandline - this is called from command line parameter
1831 parsing code. It sets the parameter then marks the parameter as unable to be modified
1832 by smb.conf processing
1834 bool lp_set_cmdline(struct loadparm_context *lp_ctx, const char *pszParmName,
1835 const char *pszParmValue)
1837 int parmnum = map_parameter(pszParmName);
1840 while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
1843 if (parmnum < 0 && strchr(pszParmName, ':')) {
1844 /* set a parametric option */
1845 return lp_do_parameter_parametric(lp_ctx, NULL, pszParmName,
1846 pszParmValue, FLAG_CMDLINE);
1850 DEBUG(0,("Unknown option '%s'\n", pszParmName));
1854 /* reset the CMDLINE flag in case this has been called before */
1855 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
1857 if (!lp_do_global_parameter(lp_ctx, pszParmName, pszParmValue)) {
1861 parm_table[parmnum].flags |= FLAG_CMDLINE;
1863 /* we have to also set FLAG_CMDLINE on aliases */
1864 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1865 parm_table[i].flags |= FLAG_CMDLINE;
1867 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1868 parm_table[i].flags |= FLAG_CMDLINE;
1875 set a option from the commandline in 'a=b' format. Use to support --option
1877 bool lp_set_option(struct loadparm_context *lp_ctx, const char *option)
1895 ret = lp_set_cmdline(lp_ctx, s, p+1);
1901 #define BOOLSTR(b) ((b) ? "Yes" : "No")
1903 /***************************************************************************
1904 Print a parameter of the specified type.
1905 ***************************************************************************/
1907 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
1913 for (i = 0; p->enum_list[i].name; i++) {
1914 if (*(int *)ptr == p->enum_list[i].value) {
1916 p->enum_list[i].name);
1923 fprintf(f, "%s", BOOLSTR((bool)*(int *)ptr));
1928 fprintf(f, "%d", *(int *)ptr);
1932 fprintf(f, "0%o", *(int *)ptr);
1936 if ((char ***)ptr && *(char ***)ptr) {
1937 char **list = *(char ***)ptr;
1939 for (; *list; list++)
1940 fprintf(f, "%s%s", *list,
1941 ((*(list+1))?", ":""));
1947 if (*(char **)ptr) {
1948 fprintf(f, "%s", *(char **)ptr);
1954 /***************************************************************************
1955 Check if two parameters are equal.
1956 ***************************************************************************/
1958 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
1962 return (*((int *)ptr1) == *((int *)ptr2));
1968 return (*((int *)ptr1) == *((int *)ptr2));
1971 return str_list_equal((const char **)(*(char ***)ptr1),
1972 (const char **)(*(char ***)ptr2));
1977 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
1982 return (p1 == p2 || strequal(p1, p2));
1988 /***************************************************************************
1989 Process a new section (service). At this stage all sections are services.
1990 Later we'll have special sections that permit server parameters to be set.
1991 Returns True on success, False on failure.
1992 ***************************************************************************/
1994 static bool do_section(const char *pszSectionName, void *userdata)
1996 struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata;
1998 bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
1999 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2002 /* if we've just struck a global section, note the fact. */
2003 lp_ctx->bInGlobalSection = isglobal;
2005 /* check for multiple global sections */
2006 if (lp_ctx->bInGlobalSection) {
2007 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2011 /* if we have a current service, tidy it up before moving on */
2014 if (lp_ctx->currentService != NULL)
2015 bRetval = service_ok(lp_ctx->currentService);
2017 /* if all is still well, move to the next record in the services array */
2019 /* We put this here to avoid an odd message order if messages are */
2020 /* issued by the post-processing of a previous section. */
2021 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2023 if ((lp_ctx->currentService = add_a_service(lp_ctx, &sDefault,
2026 DEBUG(0, ("Failed to add a new service\n"));
2035 /***************************************************************************
2036 Determine if a partcular base parameter is currentl set to the default value.
2037 ***************************************************************************/
2039 static bool is_default(int i)
2041 if (!defaults_saved)
2043 switch (parm_table[i].type) {
2045 return str_list_equal((const char **)parm_table[i].def.lvalue,
2046 (const char **)(*(char ***)parm_table[i].ptr));
2049 return strequal(parm_table[i].def.svalue,
2050 *(char **)parm_table[i].ptr);
2052 return parm_table[i].def.bvalue ==
2053 *(int *)parm_table[i].ptr;
2058 return parm_table[i].def.ivalue ==
2059 *(int *)parm_table[i].ptr;
2064 /***************************************************************************
2065 Display the contents of the global structure.
2066 ***************************************************************************/
2068 static void dump_globals(struct loadparm_context *lp_ctx, FILE *f, bool show_defaults)
2071 struct param_opt *data;
2073 fprintf(f, "# Global parameters\n[global]\n");
2075 for (i = 0; parm_table[i].label; i++)
2076 if (parm_table[i].class == P_GLOBAL &&
2077 parm_table[i].ptr &&
2078 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2079 if (!show_defaults && (parm_table[i].flags & FLAG_DEFAULT))
2081 fprintf(f, "\t%s = ", parm_table[i].label);
2082 print_parameter(&parm_table[i], parm_table[i].ptr, f);
2085 if (lp_ctx->Globals.param_opt != NULL) {
2086 for (data = lp_ctx->Globals.param_opt; data;
2087 data = data->next) {
2088 fprintf(f, "\t%s = %s\n", data->key, data->value);
2094 /***************************************************************************
2095 Display the contents of a single services record.
2096 ***************************************************************************/
2098 static void dump_a_service(struct loadparm_service * pService, FILE * f)
2101 struct param_opt *data;
2103 if (pService != &sDefault)
2104 fprintf(f, "\n[%s]\n", pService->szService);
2106 for (i = 0; parm_table[i].label; i++)
2107 if (parm_table[i].class == P_LOCAL &&
2108 parm_table[i].ptr &&
2109 (*parm_table[i].label != '-') &&
2110 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2111 int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
2113 if (pService == &sDefault) {
2114 if (defaults_saved && is_default(i))
2117 if (equal_parameter(parm_table[i].type,
2118 ((char *)pService) +
2120 ((char *)&sDefault) +
2125 fprintf(f, "\t%s = ", parm_table[i].label);
2126 print_parameter(&parm_table[i],
2127 ((char *)pService) + pdiff, f);
2130 if (pService->param_opt != NULL) {
2131 for (data = pService->param_opt; data; data = data->next) {
2132 fprintf(f, "\t%s = %s\n", data->key, data->value);
2137 bool lp_dump_a_parameter(struct loadparm_context *lp_ctx, int snum, char *parm_name, FILE * f,
2140 struct loadparm_service * pService = lp_ctx->ServicePtrs[snum];
2141 struct parm_struct *parm;
2144 parm = lp_parm_struct(parm_name);
2152 ptr = ((char *)pService) +
2153 PTR_DIFF(parm->ptr, &sDefault);
2155 print_parameter(parm,
2161 /***************************************************************************
2162 Return info about the next service in a service. snum==-1 gives the globals.
2163 Return NULL when out of parameters.
2164 ***************************************************************************/
2166 struct parm_struct *lp_next_parameter(struct loadparm_context *lp_ctx, int snum, int *i,
2170 /* do the globals */
2171 for (; parm_table[*i].label; (*i)++) {
2172 if (!parm_table[*i].ptr
2173 || (*parm_table[*i].label == '-'))
2177 && (parm_table[*i].ptr ==
2178 parm_table[(*i) - 1].ptr))
2181 return &parm_table[(*i)++];
2184 struct loadparm_service *pService = lp_ctx->ServicePtrs[snum];
2186 for (; parm_table[*i].label; (*i)++) {
2187 if (parm_table[*i].class == P_LOCAL &&
2188 parm_table[*i].ptr &&
2189 (*parm_table[*i].label != '-') &&
2191 (parm_table[*i].ptr !=
2192 parm_table[(*i) - 1].ptr)))
2195 PTR_DIFF(parm_table[*i].ptr,
2198 if (allparameters ||
2199 !equal_parameter(parm_table[*i].type,
2200 ((char *)pService) +
2202 ((char *)&sDefault) +
2205 return &parm_table[(*i)++];
2215 /***************************************************************************
2216 Auto-load some home services.
2217 ***************************************************************************/
2219 static void lp_add_auto_services(struct loadparm_context *lp_ctx,
2225 /***************************************************************************
2226 Have we loaded a services file yet?
2227 ***************************************************************************/
2229 bool lp_loaded(void)
2234 /***************************************************************************
2235 Unload unused services.
2236 ***************************************************************************/
2238 void lp_killunused(struct loadparm_context *lp_ctx,
2239 struct smbsrv_connection *smb,
2240 bool (*snumused) (struct smbsrv_connection *, int))
2243 for (i = 0; i < lp_ctx->iNumServices; i++) {
2244 if (lp_ctx->ServicePtrs[i] == NULL)
2247 if (!snumused || !snumused(smb, i)) {
2248 talloc_free(lp_ctx->ServicePtrs[i]);
2249 lp_ctx->ServicePtrs[i] = NULL;
2254 /***************************************************************************
2255 Initialise the global parameter structure.
2256 ***************************************************************************/
2257 bool loadparm_init(struct loadparm_context *lp_ctx)
2262 lp_ctx->bInGlobalSection = true;
2264 DEBUG(3, ("Initialising global parameters\n"));
2266 for (i = 0; parm_table[i].label; i++) {
2267 if ((parm_table[i].type == P_STRING ||
2268 parm_table[i].type == P_USTRING) &&
2269 parm_table[i].ptr &&
2270 !(parm_table[i].flags & FLAG_CMDLINE)) {
2271 string_set(talloc_autofree_context(),
2272 (char **)parm_table[i].ptr, "");
2276 lp_do_global_parameter(lp_ctx, "share backend", "classic");
2278 lp_do_global_parameter(lp_ctx, "server role", "standalone");
2280 /* options that can be set on the command line must be initialised via
2281 the slower lp_do_global_parameter() to ensure that FLAG_CMDLINE is obeyed */
2283 lp_do_global_parameter(lp_ctx, "socket options", "TCP_NODELAY");
2285 lp_do_global_parameter(lp_ctx, "workgroup", DEFAULT_WORKGROUP);
2286 myname = get_myname();
2287 lp_do_global_parameter(lp_ctx, "netbios name", myname);
2289 lp_do_global_parameter(lp_ctx, "name resolve order", "lmhosts wins host bcast");
2291 lp_do_global_parameter(lp_ctx, "fstype", FSTYPE_STRING);
2292 lp_do_global_parameter(lp_ctx, "ntvfs handler", "unixuid default");
2293 lp_do_global_parameter(lp_ctx, "max connections", "-1");
2295 lp_do_global_parameter(lp_ctx, "dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup unixinfo");
2296 lp_do_global_parameter(lp_ctx, "server services", "smb rpc nbt wrepl ldap cldap web kdc drepl winbind");
2297 lp_do_global_parameter(lp_ctx, "ntptr providor", "simple_ldb");
2298 lp_do_global_parameter(lp_ctx, "auth methods:domain controller", "anonymous sam_ignoredomain");
2299 lp_do_global_parameter(lp_ctx, "auth methods:member server", "anonymous sam winbind");
2300 lp_do_global_parameter(lp_ctx, "auth methods:standalone", "anonymous sam_ignoredomain");
2301 lp_do_global_parameter(lp_ctx, "private dir", dyn_PRIVATE_DIR);
2302 lp_do_global_parameter(lp_ctx, "sam database", "sam.ldb");
2303 lp_do_global_parameter(lp_ctx, "secrets database", "secrets.ldb");
2304 lp_do_global_parameter(lp_ctx, "spoolss database", "spoolss.ldb");
2305 lp_do_global_parameter(lp_ctx, "wins config database", "wins_config.ldb");
2306 lp_do_global_parameter(lp_ctx, "wins database", "wins.ldb");
2307 lp_do_global_parameter(lp_ctx, "registry:HKEY_LOCAL_MACHINE", "hklm.ldb");
2309 /* This hive should be dynamically generated by Samba using
2310 data from the sam, but for the moment leave it in a tdb to
2311 keep regedt32 from popping up an annoying dialog. */
2312 lp_do_global_parameter(lp_ctx, "registry:HKEY_USERS", "hku.ldb");
2314 /* using UTF8 by default allows us to support all chars */
2315 lp_do_global_parameter(lp_ctx, "unix charset", "UTF8");
2317 /* Use codepage 850 as a default for the dos character set */
2318 lp_do_global_parameter(lp_ctx, "dos charset", "CP850");
2321 * Allow the default PASSWD_CHAT to be overridden in local.h.
2323 lp_do_global_parameter(lp_ctx, "passwd chat", DEFAULT_PASSWD_CHAT);
2325 lp_do_global_parameter(lp_ctx, "pid directory", dyn_PIDDIR);
2326 lp_do_global_parameter(lp_ctx, "lock dir", dyn_LOCKDIR);
2327 lp_do_global_parameter(lp_ctx, "modules dir", dyn_MODULESDIR);
2328 lp_do_global_parameter(lp_ctx, "ncalrpc dir", dyn_NCALRPCDIR);
2330 lp_do_global_parameter(lp_ctx, "socket address", "0.0.0.0");
2331 lp_do_global_parameter_var(lp_ctx, "server string",
2332 "Samba %s", SAMBA_VERSION_STRING);
2334 lp_do_global_parameter_var(lp_ctx, "announce version", "%d.%d",
2335 DEFAULT_MAJOR_VERSION,
2336 DEFAULT_MINOR_VERSION);
2338 lp_do_global_parameter(lp_ctx, "password server", "*");
2340 lp_do_global_parameter(lp_ctx, "max mux", "50");
2341 lp_do_global_parameter(lp_ctx, "max xmit", "12288");
2342 lp_do_global_parameter(lp_ctx, "password level", "0");
2343 lp_do_global_parameter(lp_ctx, "LargeReadwrite", "True");
2344 lp_do_global_parameter(lp_ctx, "server min protocol", "CORE");
2345 lp_do_global_parameter(lp_ctx, "server max protocol", "NT1");
2346 lp_do_global_parameter(lp_ctx, "client min protocol", "CORE");
2347 lp_do_global_parameter(lp_ctx, "client max protocol", "NT1");
2348 lp_do_global_parameter(lp_ctx, "security", "USER");
2349 lp_do_global_parameter(lp_ctx, "paranoid server security", "True");
2350 lp_do_global_parameter(lp_ctx, "EncryptPasswords", "True");
2351 lp_do_global_parameter(lp_ctx, "ReadRaw", "True");
2352 lp_do_global_parameter(lp_ctx, "WriteRaw", "True");
2353 lp_do_global_parameter(lp_ctx, "NullPasswords", "False");
2354 lp_do_global_parameter(lp_ctx, "ObeyPamRestrictions", "False");
2355 lp_do_global_parameter(lp_ctx, "announce as", "NT SERVER");
2357 lp_do_global_parameter(lp_ctx, "TimeServer", "False");
2358 lp_do_global_parameter(lp_ctx, "BindInterfacesOnly", "False");
2359 lp_do_global_parameter(lp_ctx, "Unicode", "True");
2360 lp_do_global_parameter(lp_ctx, "ClientLanManAuth", "True");
2361 lp_do_global_parameter(lp_ctx, "LanmanAuth", "True");
2362 lp_do_global_parameter(lp_ctx, "NTLMAuth", "True");
2363 lp_do_global_parameter(lp_ctx, "client use spnego principal", "False");
2365 lp_do_global_parameter(lp_ctx, "UnixExtensions", "False");
2367 lp_do_global_parameter(lp_ctx, "PreferredMaster", "Auto");
2368 lp_do_global_parameter(lp_ctx, "LocalMaster", "True");
2370 lp_do_global_parameter(lp_ctx, "wins support", "False");
2371 lp_do_global_parameter(lp_ctx, "dns proxy", "True");
2373 lp_do_global_parameter(lp_ctx, "winbind separator", "\\");
2374 lp_do_global_parameter(lp_ctx, "winbind sealed pipes", "True");
2375 lp_do_global_parameter(lp_ctx, "winbindd socket directory", dyn_WINBINDD_SOCKET_DIR);
2376 lp_do_global_parameter(lp_ctx, "template shell", "/bin/false");
2377 lp_do_global_parameter(lp_ctx, "template homedir", "/home/%WORKGROUP%/%ACCOUNTNAME%");
2379 lp_do_global_parameter(lp_ctx, "client signing", "Yes");
2380 lp_do_global_parameter(lp_ctx, "server signing", "auto");
2382 lp_do_global_parameter(lp_ctx, "use spnego", "True");
2384 lp_do_global_parameter(lp_ctx, "smb ports", "445 139");
2385 lp_do_global_parameter(lp_ctx, "nbt port", "137");
2386 lp_do_global_parameter(lp_ctx, "dgram port", "138");
2387 lp_do_global_parameter(lp_ctx, "cldap port", "389");
2388 lp_do_global_parameter(lp_ctx, "krb5 port", "88");
2389 lp_do_global_parameter(lp_ctx, "kpasswd port", "464");
2390 lp_do_global_parameter(lp_ctx, "web port", "901");
2391 lp_do_global_parameter(lp_ctx, "swat directory", dyn_SWATDIR);
2393 lp_do_global_parameter(lp_ctx, "nt status support", "True");
2395 lp_do_global_parameter(lp_ctx, "max wins ttl", "518400"); /* 6 days */
2396 lp_do_global_parameter(lp_ctx, "min wins ttl", "10");
2398 lp_do_global_parameter(lp_ctx, "tls enabled", "True");
2399 lp_do_global_parameter(lp_ctx, "tls keyfile", "tls/key.pem");
2400 lp_do_global_parameter(lp_ctx, "tls certfile", "tls/cert.pem");
2401 lp_do_global_parameter(lp_ctx, "tls cafile", "tls/ca.pem");
2402 lp_do_global_parameter_var(lp_ctx, "js include", "%s", dyn_JSDIR);
2403 lp_do_global_parameter_var(lp_ctx, "setup directory", "%s",
2406 for (i = 0; parm_table[i].label; i++) {
2407 if (!(parm_table[i].flags & FLAG_CMDLINE)) {
2408 parm_table[i].flags |= FLAG_DEFAULT;
2415 _PUBLIC_ _DEPRECATED_ bool lp_load_default(void)
2417 return lp_load(dyn_CONFIGFILE);
2420 /***************************************************************************
2421 Load the services array from the services file. Return True on success,
2423 ***************************************************************************/
2425 bool lp_load(const char *filename)
2429 struct param_opt *data;
2430 struct loadparm_context *lp_ctx = &loadparm;
2432 filename = talloc_strdup(talloc_autofree_context(), filename);
2434 global_loadparm = lp_ctx;
2436 if (lp_ctx->Globals.param_opt != NULL) {
2437 struct param_opt *next;
2438 for (data = lp_ctx->Globals.param_opt; data; data=next) {
2440 if (data->flags & FLAG_CMDLINE) continue;
2441 DLIST_REMOVE(lp_ctx->Globals.param_opt, data);
2446 if (!loadparm_init(lp_ctx))
2449 lp_ctx->Globals.szConfigFile = filename;
2451 lp_ctx->bInGlobalSection = true;
2452 n2 = standard_sub_basic(talloc_autofree_context(), lp_ctx->Globals.szConfigFile);
2453 DEBUG(2, ("lp_load: refreshing parameters from %s\n", n2));
2455 add_to_file_list(lp_ctx, lp_ctx->Globals.szConfigFile, n2);
2457 /* We get sections first, so have to start 'behind' to make up */
2458 lp_ctx->currentService = NULL;
2459 bRetval = pm_process(n2, do_section, do_parameter, lp_ctx);
2461 /* finish up the last section */
2462 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
2464 if (lp_ctx->currentService != NULL)
2465 bRetval = service_ok(lp_ctx->currentService);
2467 lp_add_auto_services(lp_ctx, lp_auto_services(lp_ctx));
2469 lp_add_hidden(lp_ctx, "IPC$", "IPC");
2470 lp_add_hidden(lp_ctx, "ADMIN$", "DISK");
2474 if (!lp_ctx->Globals.szWINSservers && lp_ctx->Globals.bWINSsupport) {
2475 lp_do_global_parameter(lp_ctx, "wins server", "127.0.0.1");
2483 /***************************************************************************
2484 Return the max number of services.
2485 ***************************************************************************/
2487 int lp_numservices(struct loadparm_context *lp_ctx)
2489 return lp_ctx->iNumServices;
2492 /***************************************************************************
2493 Display the contents of the services array in human-readable form.
2494 ***************************************************************************/
2496 void lp_dump(struct loadparm_context *lp_ctx, FILE *f, bool show_defaults,
2502 defaults_saved = false;
2504 dump_globals(lp_ctx, f, show_defaults);
2506 dump_a_service(&sDefault, f);
2508 for (iService = 0; iService < maxtoprint; iService++)
2509 lp_dump_one(f, show_defaults, lp_ctx->ServicePtrs[iService]);
2512 /***************************************************************************
2513 Display the contents of one service in human-readable form.
2514 ***************************************************************************/
2516 void lp_dump_one(FILE *f, bool show_defaults, struct loadparm_service *service)
2518 if (service != NULL) {
2519 if (service->szService[0] == '\0')
2521 dump_a_service(service, f);
2525 struct loadparm_service *lp_servicebynum(struct loadparm_context *lp_ctx,
2528 return lp_ctx->ServicePtrs[snum];
2531 struct loadparm_service *lp_service(struct loadparm_context *lp_ctx,
2532 const char *service_name)
2537 for (iService = lp_ctx->iNumServices - 1; iService >= 0; iService--) {
2538 if (lp_ctx->ServicePtrs[iService] &&
2539 lp_ctx->ServicePtrs[iService]->szService) {
2541 * The substitution here is used to support %U is
2544 serviceName = standard_sub_basic(
2545 lp_ctx->ServicePtrs[iService],
2546 lp_ctx->ServicePtrs[iService]->szService);
2547 if (strequal(serviceName, service_name))
2548 return lp_ctx->ServicePtrs[iService];
2552 DEBUG(7,("lp_servicenumber: couldn't find %s\n", service_name));
2557 /*******************************************************************
2558 A useful volume label function.
2559 ********************************************************************/
2560 const char *volume_label(struct loadparm_service *service)
2562 const char *ret = lp_volume(service);
2564 return lp_servicename(service);
2569 /***********************************************************
2570 If we are PDC then prefer us as DMB
2571 ************************************************************/
2573 bool lp_domain_logons(struct loadparm_context *lp_ctx)
2575 return (lp_server_role(lp_ctx) == ROLE_DOMAIN_CONTROLLER);
2578 const char *lp_printername(struct loadparm_service *service)
2580 const char *ret = _lp_printername(service);
2581 if (ret == NULL || (ret != NULL && *ret == '\0'))
2582 ret = lp_const_servicename(service);
2588 /*******************************************************************
2589 Return the max print jobs per queue.
2590 ********************************************************************/
2592 int lp_maxprintjobs(struct loadparm_service *service)
2594 int maxjobs = (service != NULL) ? service->iMaxPrintJobs : sDefault.iMaxPrintJobs;
2595 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
2596 maxjobs = PRINT_MAX_JOBID - 1;