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 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.
376 #define GLOBAL_VAR(name) &loadparm.Globals.name
377 #define LOCAL_VAR(name) &sDefault.name
379 static struct parm_struct parm_table[] = {
380 {"config file", P_STRING, P_GLOBAL, GLOBAL_VAR(szConfigFile), NULL, NULL, FLAG_HIDE},
382 {"server role", P_ENUM, P_GLOBAL, GLOBAL_VAR(server_role), NULL, enum_server_role, FLAG_BASIC},
384 {"dos charset", P_STRING, P_GLOBAL, GLOBAL_VAR(dos_charset), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
385 {"unix charset", P_STRING, P_GLOBAL, GLOBAL_VAR(unix_charset), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
386 {"ncalrpc dir", P_STRING, P_GLOBAL, GLOBAL_VAR(ncalrpc_dir), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
387 {"display charset", P_STRING, P_GLOBAL, GLOBAL_VAR(display_charset), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
388 {"comment", P_STRING, P_LOCAL, LOCAL_VAR(comment), NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
389 {"path", P_STRING, P_LOCAL, LOCAL_VAR(szPath), NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
390 {"directory", P_STRING, P_LOCAL, LOCAL_VAR(szPath), NULL, NULL, FLAG_HIDE},
391 {"workgroup", P_USTRING, P_GLOBAL, GLOBAL_VAR(szWorkgroup), NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
392 {"realm", P_STRING, P_GLOBAL, GLOBAL_VAR(szRealm), NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
393 {"netbios name", P_USTRING, P_GLOBAL, GLOBAL_VAR(szNetbiosName), NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
394 {"netbios aliases", P_LIST, P_GLOBAL, GLOBAL_VAR(szNetbiosAliases), NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
395 {"netbios scope", P_USTRING, P_GLOBAL, GLOBAL_VAR(szNetbiosScope), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
396 {"server string", P_STRING, P_GLOBAL, GLOBAL_VAR(szServerString), NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
397 {"interfaces", P_LIST, P_GLOBAL, GLOBAL_VAR(szInterfaces), NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
398 {"bind interfaces only", P_BOOL, P_GLOBAL, GLOBAL_VAR(bBindInterfacesOnly), NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
399 {"ntvfs handler", P_LIST, P_LOCAL, LOCAL_VAR(ntvfs_handler), NULL, NULL, FLAG_ADVANCED},
400 {"ntptr providor", P_STRING, P_GLOBAL, GLOBAL_VAR(ntptr_providor), NULL, NULL, FLAG_ADVANCED},
401 {"dcerpc endpoint servers", P_LIST, P_GLOBAL, GLOBAL_VAR()dcerpc_ep_servers, NULL, NULL, FLAG_ADVANCED},
402 {"server services", P_LIST, P_GLOBAL, GLOBAL_VAR(server_services), NULL, NULL, FLAG_ADVANCED},
404 {"security", P_ENUM, P_GLOBAL, GLOBAL_VAR(security), NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
405 {"encrypt passwords", P_BOOL, P_GLOBAL, GLOBAL_VAR(bEncryptPasswords), NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
406 {"null passwords", P_BOOL, P_GLOBAL, GLOBAL_VAR(bNullPasswords), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
407 {"obey pam restrictions", P_BOOL, P_GLOBAL, GLOBAL_VAR(bObeyPamRestrictions), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
408 {"password server", P_LIST, P_GLOBAL, GLOBAL_VAR(szPasswordServers), NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
409 {"sam database", P_STRING, P_GLOBAL, GLOBAL_VAR(szSAM_URL), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
410 {"secrets database", P_STRING, P_GLOBAL, GLOBAL_VAR(szSECRETS_URL), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
411 {"spoolss database", P_STRING, P_GLOBAL, GLOBAL_VAR(szSPOOLSS_URL), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
412 {"wins config database", P_STRING, P_GLOBAL, GLOBAL_VAR(szWINS_CONFIG_URL), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
413 {"wins database", P_STRING, P_GLOBAL, GLOBAL_VAR(szWINS_URL), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
414 {"private dir", P_STRING, P_GLOBAL, GLOBAL_VAR(szPrivateDir), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
415 {"passwd chat", P_STRING, P_GLOBAL, GLOBAL_VAR(szPasswdChat), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
416 {"password level", P_INTEGER, P_GLOBAL, GLOBAL_VAR(pwordlevel), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
417 {"lanman auth", P_BOOL, P_GLOBAL, GLOBAL_VAR(bLanmanAuth), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
418 {"ntlm auth", P_BOOL, P_GLOBAL, GLOBAL_VAR(bNTLMAuth), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
419 {"client NTLMv2 auth", P_BOOL, P_GLOBAL, GLOBAL_VAR(bClientNTLMv2Auth), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
420 {"client lanman auth", P_BOOL, P_GLOBAL, GLOBAL_VAR(bClientLanManAuth), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
421 {"client plaintext auth", P_BOOL, P_GLOBAL, GLOBAL_VAR(bClientPlaintextAuth), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
422 {"client use spnego principal", P_BOOL, P_GLOBAL, GLOBAL_VAR(client_use_spnego_principal), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
424 {"read only", P_BOOL, P_LOCAL, LOCAL_VAR(bRead_only), NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE},
426 {"create mask", P_OCTAL, P_LOCAL, LOCAL_VAR(iCreate_mask), NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
427 {"force create mode", P_OCTAL, P_LOCAL, LOCAL_VAR(iCreate_force_mode), NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
428 {"directory mask", P_OCTAL, P_LOCAL, LOCAL_VAR(iDir_mask), NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
429 {"force directory mode", P_OCTAL, P_LOCAL, LOCAL_VAR(iDir_force_mode), NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
431 {"hosts allow", P_LIST, P_LOCAL, LOCAL_VAR(szHostsallow), NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
432 {"hosts deny", P_LIST, P_LOCAL, LOCAL_VAR(szHostsdeny), NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
434 {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
435 {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_HIDE},
436 {"log file", P_STRING, P_GLOBAL, &logfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
438 {"smb ports", P_LIST, P_GLOBAL, GLOBAL_VAR(smb_ports), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
439 {"nbt port", P_INTEGER, P_GLOBAL, GLOBAL_VAR(nbt_port), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
440 {"dgram port", P_INTEGER, P_GLOBAL, GLOBAL_VAR(dgram_port), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
441 {"cldap port", P_INTEGER, P_GLOBAL, GLOBAL_VAR(cldap_port), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
442 {"krb5 port", P_INTEGER, P_GLOBAL, GLOBAL_VAR(krb5_port), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
443 {"kpasswd port", P_INTEGER, P_GLOBAL, GLOBAL_VAR(kpasswd_port), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
444 {"web port", P_INTEGER, P_GLOBAL, GLOBAL_VAR(web_port), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
445 {"tls enabled", P_BOOL, P_GLOBAL, GLOBAL_VAR(tls_enabled), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
446 {"tls keyfile", P_STRING, P_GLOBAL, GLOBAL_VAR(tls_keyfile), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
447 {"tls certfile", P_STRING, P_GLOBAL, GLOBAL_VAR(tls_certfile), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
448 {"tls cafile", P_STRING, P_GLOBAL, GLOBAL_VAR(tls_cafile), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
449 {"tls crlfile", P_STRING, P_GLOBAL, GLOBAL_VAR(tls_crlfile), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
450 {"tls dh params file", P_STRING, P_GLOBAL, GLOBAL_VAR(tls_dhpfile), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
451 {"swat directory", P_STRING, P_GLOBAL, GLOBAL_VAR(swat_directory), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
452 {"large readwrite", P_BOOL, P_GLOBAL, GLOBAL_VAR(bLargeReadwrite), NULL, NULL, FLAG_DEVELOPER},
453 {"server max protocol", P_ENUM, P_GLOBAL, GLOBAL_VAR(srv_maxprotocol), NULL, enum_protocol, FLAG_DEVELOPER},
454 {"server min protocol", P_ENUM, P_GLOBAL, GLOBAL_VAR(srv_minprotocol), NULL, enum_protocol, FLAG_DEVELOPER},
455 {"client max protocol", P_ENUM, P_GLOBAL, GLOBAL_VAR(cli_maxprotocol), NULL, enum_protocol, FLAG_DEVELOPER},
456 {"client min protocol", P_ENUM, P_GLOBAL, GLOBAL_VAR(cli_minprotocol), NULL, enum_protocol, FLAG_DEVELOPER},
457 {"unicode", P_BOOL, P_GLOBAL, GLOBAL_VAR(bUnicode), NULL, NULL, FLAG_DEVELOPER},
458 {"read raw", P_BOOL, P_GLOBAL, GLOBAL_VAR(bReadRaw), NULL, NULL, FLAG_DEVELOPER},
459 {"write raw", P_BOOL, P_GLOBAL, GLOBAL_VAR(bWriteRaw), NULL, NULL, FLAG_DEVELOPER},
460 {"disable netbios", P_BOOL, P_GLOBAL, GLOBAL_VAR(bDisableNetbios), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
462 {"nt status support", P_BOOL, P_GLOBAL, GLOBAL_VAR(bNTStatusSupport), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
464 {"announce version", P_STRING, P_GLOBAL, GLOBAL_VAR(szAnnounceVersion), NULL, NULL, FLAG_DEVELOPER},
465 {"announce as", P_ENUM, P_GLOBAL, GLOBAL_VAR(announce_as), NULL, enum_announce_as, FLAG_DEVELOPER},
466 {"max mux", P_INTEGER, P_GLOBAL, GLOBAL_VAR(max_mux), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
467 {"max xmit", P_BYTES, P_GLOBAL, GLOBAL_VAR(max_xmit), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
469 {"name resolve order", P_LIST, P_GLOBAL, GLOBAL_VAR(szNameResolveOrder), NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
470 {"max wins ttl", P_INTEGER, P_GLOBAL, GLOBAL_VAR(max_wins_ttl), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
471 {"min wins ttl", P_INTEGER, P_GLOBAL, GLOBAL_VAR(min_wins_ttl), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
472 {"time server", P_BOOL, P_GLOBAL, GLOBAL_VAR(bTimeServer), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
473 {"unix extensions", P_BOOL, P_GLOBAL, GLOBAL_VAR(bUnixExtensions), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
474 {"use spnego", P_BOOL, P_GLOBAL, GLOBAL_VAR(bUseSpnego), NULL, NULL, FLAG_DEVELOPER},
475 {"server signing", P_ENUM, P_GLOBAL, GLOBAL_VAR(server_signing), NULL, enum_smb_signing_vals, FLAG_ADVANCED},
476 {"client signing", P_ENUM, P_GLOBAL, GLOBAL_VAR(client_signing), NULL, enum_smb_signing_vals, FLAG_ADVANCED},
477 {"rpc big endian", P_BOOL, P_GLOBAL, GLOBAL_VAR(bRpcBigEndian), NULL, NULL, FLAG_DEVELOPER},
479 {"max connections", P_INTEGER, P_LOCAL, LOCAL_VAR(iMaxConnections), NULL, NULL, FLAG_SHARE},
480 {"paranoid server security", P_BOOL, P_GLOBAL, GLOBAL_VAR(paranoid_server_security), NULL, NULL, FLAG_DEVELOPER},
481 {"socket options", P_STRING, P_GLOBAL, GLOBAL_VAR(socket_options), NULL, NULL, FLAG_DEVELOPER},
483 {"strict sync", P_BOOL, P_LOCAL, LOCAL_VAR(bStrictSync), NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
484 {"case insensitive filesystem", P_BOOL, P_LOCAL, LOCAL_VAR(bCIFileSystem), NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
486 {"max print jobs", P_INTEGER, P_LOCAL, LOCAL_VAR(iMaxPrintJobs), NULL, NULL, FLAG_PRINT},
487 {"printable", P_BOOL, P_LOCAL, LOCAL_VAR(bPrint_ok), NULL, NULL, FLAG_PRINT},
488 {"print ok", P_BOOL, P_LOCAL, LOCAL_VAR(bPrint_ok), NULL, NULL, FLAG_HIDE},
490 {"printer name", P_STRING, P_LOCAL, LOCAL_VAR(szPrintername), NULL, NULL, FLAG_PRINT},
491 {"printer", P_STRING, P_LOCAL, LOCAL_VAR(szPrintername), NULL, NULL, FLAG_HIDE},
493 {"map system", P_BOOL, P_LOCAL, LOCAL_VAR(bMap_system), NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
494 {"map hidden", P_BOOL, P_LOCAL, LOCAL_VAR(bMap_hidden), NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
495 {"map archive", P_BOOL, P_LOCAL, LOCAL_VAR(bMap_archive), NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
497 {"preferred master", P_ENUM, P_GLOBAL, GLOBAL_VAR(bPreferredMaster), NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
498 {"prefered master", P_ENUM, P_GLOBAL, GLOBAL_VAR(bPreferredMaster), NULL, enum_bool_auto, FLAG_HIDE},
499 {"local master", P_BOOL, P_GLOBAL, GLOBAL_VAR(bLocalMaster), NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
500 {"browseable", P_BOOL, P_LOCAL, LOCAL_VAR(bBrowseable), NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
501 {"browsable", P_BOOL, P_LOCAL, LOCAL_VAR(bBrowseable), NULL, NULL, FLAG_HIDE},
503 {"wins server", P_LIST, P_GLOBAL, GLOBAL_VAR(szWINSservers), NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
504 {"wins support", P_BOOL, P_GLOBAL, GLOBAL_VAR(bWINSsupport), NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
505 {"dns proxy", P_BOOL, P_GLOBAL, GLOBAL_VAR(bWINSdnsProxy), NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
506 {"wins hook", P_STRING, P_GLOBAL, GLOBAL_VAR(szWINSHook), NULL, NULL, FLAG_ADVANCED},
508 {"csc policy", P_ENUM, P_LOCAL, LOCAL_VAR(iCSCPolicy), NULL, enum_csc_policy, FLAG_SHARE | FLAG_GLOBAL},
510 {"strict locking", P_BOOL, P_LOCAL, LOCAL_VAR(bStrictLocking), NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
512 {"share backend", P_STRING, P_GLOBAL, GLOBAL_VAR(szShareBackend), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
513 {"preload", P_STRING, P_GLOBAL, GLOBAL_VAR(szAutoServices), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
514 {"auto services", P_STRING, P_GLOBAL, GLOBAL_VAR(szAutoServices), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
515 {"lock dir", P_STRING, P_GLOBAL, GLOBAL_VAR(szLockDir), NULL, NULL, FLAG_HIDE},
516 {"lock directory", P_STRING, P_GLOBAL, GLOBAL_VAR(szLockDir), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
517 {"modules dir", P_STRING, P_GLOBAL, GLOBAL_VAR(szModulesDir), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
518 {"pid directory", P_STRING, P_GLOBAL, GLOBAL_VAR(szPidDir), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
519 {"js include", P_LIST, P_GLOBAL, GLOBAL_VAR(jsInclude), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
520 {"setup directory", P_STRING, P_GLOBAL, GLOBAL_VAR(szSetupDir), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
522 {"socket address", P_STRING, P_GLOBAL, GLOBAL_VAR(szSocketAddress), NULL, NULL, FLAG_DEVELOPER},
523 {"copy", P_STRING, P_LOCAL, LOCAL_VAR(szCopy), handle_copy, NULL, FLAG_HIDE},
524 {"include", P_STRING, P_LOCAL, LOCAL_VAR(szInclude), handle_include, NULL, FLAG_HIDE},
526 {"available", P_BOOL, P_LOCAL, LOCAL_VAR(bAvailable), NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
527 {"volume", P_STRING, P_LOCAL, LOCAL_VAR(volume), NULL, NULL, FLAG_SHARE },
528 {"fstype", P_STRING, P_LOCAL, LOCAL_VAR(fstype), NULL, NULL, FLAG_SHARE},
530 {"panic action", P_STRING, P_GLOBAL, &panic_action, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
532 {"msdfs root", P_BOOL, P_LOCAL, LOCAL_VAR(bMSDfsRoot), NULL, NULL, FLAG_SHARE},
533 {"host msdfs", P_BOOL, P_GLOBAL, GLOBAL_VAR(bHostMSDfs), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
534 {"winbind separator", P_STRING, P_GLOBAL, GLOBAL_VAR(szWinbindSeparator), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
535 {"winbindd socket directory", P_STRING, P_GLOBAL, GLOBAL_VAR(szWinbinddSocketDirectory), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
536 {"winbind sealed pipes", P_BOOL, P_GLOBAL, GLOBAL_VAR(bWinbindSealedPipes), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
537 {"template shell", P_STRING, P_GLOBAL, GLOBAL_VAR(szTemplateShell), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
538 {"template homedir", P_STRING, P_GLOBAL, GLOBAL_VAR(szTemplateHomedir), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
540 {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
545 return the parameter table
547 struct parm_struct *lp_parm_table(void)
552 static TALLOC_CTX *lp_talloc;
554 /******************************************************************* a
555 Free up temporary memory - called from the main loop.
556 ********************************************************************/
558 void lp_talloc_free(void)
562 talloc_free(lp_talloc);
566 /*******************************************************************
567 Convenience routine to grab string parameters into temporary memory
568 and run standard_sub_basic on them. The buffers can be written to by
569 callers without affecting the source string.
570 ********************************************************************/
572 static const char *lp_string(const char *s)
574 #if 0 /* until REWRITE done to make thread-safe */
575 size_t len = s ? strlen(s) : 0;
579 /* The follow debug is useful for tracking down memory problems
580 especially if you have an inner loop that is calling a lp_*()
581 function that returns a string. Perhaps this debug should be
582 present all the time? */
585 DEBUG(10, ("lp_string(%s)\n", s));
588 #if 0 /* until REWRITE done to make thread-safe */
590 lp_talloc = talloc_init("lp_talloc");
592 ret = talloc_array(lp_talloc, char, len + 100); /* leave room for substitution */
600 strlcpy(ret, s, len);
602 if (trim_string(ret, "\"", "\"")) {
603 if (strchr(ret,'"') != NULL)
604 strlcpy(ret, s, len);
607 standard_sub_basic(ret,len+100);
614 In this section all the functions that are used to access the
615 parameters from the rest of the program are defined
618 #define FN_GLOBAL_STRING(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 ? lp_string(lp_ctx->Globals.var_name) : "";}
620 #define FN_GLOBAL_CONST_STRING(fn_name,var_name) \
621 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 : "";}
622 #define FN_GLOBAL_LIST(fn_name,var_name) \
623 const char **fn_name(struct loadparm_context *lp_ctx) {if (lp_ctx == NULL) return NULL; return lp_ctx->Globals.var_name;}
624 #define FN_GLOBAL_BOOL(fn_name,var_name) \
625 bool fn_name(struct loadparm_context *lp_ctx) {if (lp_ctx == NULL) return false; return lp_ctx->Globals.var_name;}
627 #define FN_GLOBAL_CHAR(fn_name,ptr) \
628 char fn_name(void) {return(*(char *)(ptr));}
630 #define FN_GLOBAL_INTEGER(fn_name,var_name) \
631 int fn_name(struct loadparm_context *lp_ctx) {if (lp_ctx == NULL) return 0; return lp_ctx->Globals.var_name;}
633 #define FN_LOCAL_STRING(fn_name,val) \
634 const char *fn_name(struct loadparm_service *service) {return(lp_string((const char *)((service != NULL && service->val != NULL) ? service->val : sDefault.val)));}
635 #define FN_LOCAL_CONST_STRING(fn_name,val) \
636 const char *fn_name(struct loadparm_service *service) {return (const char *)(service != NULL && service->val != NULL) ? service->val : sDefault.val;}
637 #define FN_LOCAL_LIST(fn_name,val) \
638 const char **fn_name(struct loadparm_service *service) {return(const char **)(service != NULL && service->val != NULL? service->val : sDefault.val);}
639 #define FN_LOCAL_BOOL(fn_name,val) \
640 bool fn_name(struct loadparm_service *service) {return((service != NULL)? service->val : sDefault.val);}
641 #define FN_LOCAL_INTEGER(fn_name,val) \
642 int fn_name(struct loadparm_service *service) {return((service != NULL)? service->val : sDefault.val);}
644 _PUBLIC_ FN_GLOBAL_INTEGER(lp_server_role, server_role)
645 _PUBLIC_ FN_GLOBAL_LIST(lp_smb_ports, smb_ports)
646 _PUBLIC_ FN_GLOBAL_INTEGER(lp_nbt_port, nbt_port)
647 _PUBLIC_ FN_GLOBAL_INTEGER(lp_dgram_port, dgram_port)
648 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cldap_port, cldap_port)
649 _PUBLIC_ FN_GLOBAL_INTEGER(lp_krb5_port, krb5_port)
650 _PUBLIC_ FN_GLOBAL_INTEGER(lp_kpasswd_port, kpasswd_port)
651 _PUBLIC_ FN_GLOBAL_INTEGER(lp_web_port, web_port)
652 _PUBLIC_ FN_GLOBAL_STRING(lp_swat_directory, swat_directory)
653 _PUBLIC_ FN_GLOBAL_BOOL(lp_tls_enabled, tls_enabled)
654 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_keyfile, tls_keyfile)
655 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_certfile, tls_certfile)
656 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_cafile, tls_cafile)
657 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_crlfile, tls_crlfile)
658 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_dhpfile, tls_dhpfile)
659 _PUBLIC_ FN_GLOBAL_STRING(lp_share_backend, szShareBackend)
660 _PUBLIC_ FN_GLOBAL_STRING(lp_sam_url, szSAM_URL)
661 _PUBLIC_ FN_GLOBAL_STRING(lp_secrets_url, szSECRETS_URL)
662 _PUBLIC_ FN_GLOBAL_STRING(lp_spoolss_url, szSPOOLSS_URL)
663 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_config_url, szWINS_CONFIG_URL)
664 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_url, szWINS_URL)
665 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_winbind_separator, szWinbindSeparator)
666 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_winbindd_socket_directory, szWinbinddSocketDirectory)
667 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_template_shell, szTemplateShell)
668 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_template_homedir, szTemplateHomedir)
669 _PUBLIC_ FN_GLOBAL_BOOL(lp_winbind_sealed_pipes, bWinbindSealedPipes)
670 _PUBLIC_ FN_GLOBAL_STRING(lp_private_dir, szPrivateDir)
671 _PUBLIC_ FN_GLOBAL_STRING(lp_serverstring, szServerString)
672 _PUBLIC_ FN_GLOBAL_STRING(lp_lockdir, szLockDir)
673 _PUBLIC_ FN_GLOBAL_STRING(lp_modulesdir, szModulesDir)
674 _PUBLIC_ FN_GLOBAL_STRING(lp_setupdir, szSetupDir)
675 _PUBLIC_ FN_GLOBAL_STRING(lp_ncalrpc_dir, ncalrpc_dir)
676 _PUBLIC_ FN_GLOBAL_STRING(lp_dos_charset, dos_charset)
677 _PUBLIC_ FN_GLOBAL_STRING(lp_unix_charset, unix_charset)
678 _PUBLIC_ FN_GLOBAL_STRING(lp_display_charset, display_charset)
679 _PUBLIC_ FN_GLOBAL_STRING(lp_piddir, szPidDir)
680 _PUBLIC_ FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, dcerpc_ep_servers)
681 _PUBLIC_ FN_GLOBAL_LIST(lp_server_services, server_services)
682 _PUBLIC_ FN_GLOBAL_STRING(lp_ntptr_providor, ntptr_providor)
683 _PUBLIC_ FN_GLOBAL_STRING(lp_auto_services, szAutoServices)
684 _PUBLIC_ FN_GLOBAL_STRING(lp_passwd_chat, szPasswdChat)
685 _PUBLIC_ FN_GLOBAL_LIST(lp_passwordserver, szPasswordServers)
686 _PUBLIC_ FN_GLOBAL_LIST(lp_name_resolve_order, szNameResolveOrder)
687 _PUBLIC_ FN_GLOBAL_STRING(lp_realm, szRealm)
688 _PUBLIC_ FN_GLOBAL_STRING(lp_socket_options, socket_options)
689 _PUBLIC_ FN_GLOBAL_STRING(lp_workgroup, szWorkgroup)
690 _PUBLIC_ FN_GLOBAL_STRING(lp_netbios_name, szNetbiosName)
691 _PUBLIC_ FN_GLOBAL_STRING(lp_netbios_scope, szNetbiosScope)
692 _PUBLIC_ FN_GLOBAL_LIST(lp_wins_server_list, szWINSservers)
693 _PUBLIC_ FN_GLOBAL_LIST(lp_interfaces, szInterfaces)
694 _PUBLIC_ FN_GLOBAL_STRING(lp_socket_address, szSocketAddress)
695 _PUBLIC_ FN_GLOBAL_LIST(lp_netbios_aliases, szNetbiosAliases)
697 _PUBLIC_ FN_GLOBAL_BOOL(lp_disable_netbios, bDisableNetbios)
698 _PUBLIC_ FN_GLOBAL_BOOL(lp_wins_support, bWINSsupport)
699 _PUBLIC_ FN_GLOBAL_BOOL(lp_wins_dns_proxy, bWINSdnsProxy)
700 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_hook, szWINSHook)
701 _PUBLIC_ FN_GLOBAL_STRING(lp_configfile, szConfigFile)
702 _PUBLIC_ FN_GLOBAL_BOOL(lp_local_master, bLocalMaster)
703 _PUBLIC_ FN_GLOBAL_BOOL(lp_readraw, bReadRaw)
704 _PUBLIC_ FN_GLOBAL_BOOL(lp_large_readwrite, bLargeReadwrite)
705 _PUBLIC_ FN_GLOBAL_BOOL(lp_writeraw, bWriteRaw)
706 _PUBLIC_ FN_GLOBAL_BOOL(lp_null_passwords, bNullPasswords)
707 _PUBLIC_ FN_GLOBAL_BOOL(lp_obey_pam_restrictions, bObeyPamRestrictions)
708 _PUBLIC_ FN_GLOBAL_BOOL(lp_encrypted_passwords, bEncryptPasswords)
709 _PUBLIC_ FN_GLOBAL_BOOL(lp_time_server, bTimeServer)
710 _PUBLIC_ FN_GLOBAL_BOOL(lp_bind_interfaces_only, bBindInterfacesOnly)
711 _PUBLIC_ FN_GLOBAL_BOOL(lp_unicode, bUnicode)
712 _PUBLIC_ FN_GLOBAL_BOOL(lp_nt_status_support, bNTStatusSupport)
713 _PUBLIC_ FN_GLOBAL_BOOL(lp_lanman_auth, bLanmanAuth)
714 _PUBLIC_ FN_GLOBAL_BOOL(lp_ntlm_auth, bNTLMAuth)
715 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_plaintext_auth, bClientPlaintextAuth)
716 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_lanman_auth, bClientLanManAuth)
717 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, bClientNTLMv2Auth)
718 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_use_spnego_principal, client_use_spnego_principal)
719 _PUBLIC_ FN_GLOBAL_BOOL(lp_host_msdfs, bHostMSDfs)
720 _PUBLIC_ FN_GLOBAL_BOOL(lp_unix_extensions, bUnixExtensions)
721 _PUBLIC_ FN_GLOBAL_BOOL(lp_use_spnego, bUseSpnego)
722 _PUBLIC_ FN_GLOBAL_BOOL(lp_rpc_big_endian, bRpcBigEndian)
723 _PUBLIC_ FN_GLOBAL_INTEGER(lp_max_wins_ttl, max_wins_ttl)
724 _PUBLIC_ FN_GLOBAL_INTEGER(lp_min_wins_ttl, min_wins_ttl)
725 _PUBLIC_ FN_GLOBAL_INTEGER(lp_maxmux, max_mux)
726 _PUBLIC_ FN_GLOBAL_INTEGER(lp_max_xmit, max_xmit)
727 _PUBLIC_ FN_GLOBAL_INTEGER(lp_passwordlevel, pwordlevel)
728 _PUBLIC_ FN_GLOBAL_INTEGER(lp_srv_maxprotocol, srv_maxprotocol)
729 _PUBLIC_ FN_GLOBAL_INTEGER(lp_srv_minprotocol, srv_minprotocol)
730 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cli_maxprotocol, cli_maxprotocol)
731 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cli_minprotocol, cli_minprotocol)
732 _PUBLIC_ FN_GLOBAL_INTEGER(lp_security, security)
733 _PUBLIC_ FN_GLOBAL_BOOL(lp_paranoid_server_security, paranoid_server_security)
734 _PUBLIC_ FN_GLOBAL_INTEGER(lp_announce_as, announce_as)
735 _PUBLIC_ FN_GLOBAL_LIST(lp_js_include, jsInclude)
736 _PUBLIC_ FN_LOCAL_STRING(lp_servicename, szService)
737 _PUBLIC_ FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
738 _PUBLIC_ FN_LOCAL_STRING(lp_pathname, szPath)
739 static FN_LOCAL_STRING(_lp_printername, szPrintername)
740 _PUBLIC_ FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
741 _PUBLIC_ FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
742 _PUBLIC_ FN_LOCAL_STRING(lp_comment, comment)
743 _PUBLIC_ FN_LOCAL_STRING(lp_fstype, fstype)
744 static FN_LOCAL_STRING(lp_volume, volume)
745 _PUBLIC_ FN_LOCAL_LIST(lp_ntvfs_handler, ntvfs_handler)
746 _PUBLIC_ FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
747 _PUBLIC_ FN_LOCAL_BOOL(lp_browseable, bBrowseable)
748 _PUBLIC_ FN_LOCAL_BOOL(lp_readonly, bRead_only)
749 _PUBLIC_ FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
750 _PUBLIC_ FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
751 _PUBLIC_ FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
752 _PUBLIC_ FN_LOCAL_BOOL(lp_strict_locking, bStrictLocking)
753 _PUBLIC_ FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
754 _PUBLIC_ FN_LOCAL_BOOL(lp_ci_filesystem, bCIFileSystem)
755 _PUBLIC_ FN_LOCAL_BOOL(lp_map_system, bMap_system)
756 _PUBLIC_ FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
757 _PUBLIC_ FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
758 _PUBLIC_ FN_LOCAL_INTEGER(lp_create_mask, iCreate_mask)
759 _PUBLIC_ FN_LOCAL_INTEGER(lp_force_create_mode, iCreate_force_mode)
760 _PUBLIC_ FN_LOCAL_INTEGER(lp_dir_mask, iDir_mask)
761 _PUBLIC_ FN_LOCAL_INTEGER(lp_force_dir_mode, iDir_force_mode)
762 _PUBLIC_ FN_GLOBAL_INTEGER(lp_server_signing, server_signing)
763 _PUBLIC_ FN_GLOBAL_INTEGER(lp_client_signing, client_signing)
765 /* local prototypes */
766 static int map_parameter(const char *pszParmName);
767 static struct loadparm_service *getservicebyname(struct loadparm_context *lp_ctx,
768 const char *pszServiceName);
769 static void copy_service(struct loadparm_service *pserviceDest,
770 struct loadparm_service *pserviceSource,
772 static bool service_ok(struct loadparm_service *service);
773 static bool do_section(const char *pszSectionName, void *);
774 static void init_copymap(struct loadparm_service *pservice);
776 /* This is a helper function for parametrical options support. */
777 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
778 /* Actual parametrical functions are quite simple */
779 const char *lp_get_parametric(struct loadparm_context *lp_ctx,
780 struct loadparm_service *service,
781 const char *type, const char *option)
784 struct param_opt *data;
786 data = (service == NULL ? lp_ctx->Globals.param_opt : service->param_opt);
788 asprintf(&vfskey, "%s:%s", type, option);
792 if (strcmp(data->key, vfskey) == 0) {
799 if (service != NULL) {
800 /* Try to fetch the same option but from globals */
801 /* but only if we are not already working with Globals */
802 for (data = lp_ctx->Globals.param_opt; data;
804 if (strcmp(data->key, vfskey) == 0) {
817 /*******************************************************************
818 convenience routine to return int parameters.
819 ********************************************************************/
820 static int lp_int(const char *s)
824 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
828 return strtol(s, NULL, 0);
831 /*******************************************************************
832 convenience routine to return unsigned long parameters.
833 ********************************************************************/
834 static int lp_ulong(const char *s)
838 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
842 return strtoul(s, NULL, 0);
845 /*******************************************************************
846 convenience routine to return unsigned long parameters.
847 ********************************************************************/
848 static double lp_double(const char *s)
852 DEBUG(0,("lp_double(%s): is called with NULL!\n",s));
856 return strtod(s, NULL);
859 /*******************************************************************
860 convenience routine to return boolean parameters.
861 ********************************************************************/
862 static bool lp_bool(const char *s)
867 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
871 if (!set_boolean(s, &ret)) {
872 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
880 /* Return parametric option from a given service. Type is a part of option before ':' */
881 /* Parametric option has following syntax: 'Type: option = value' */
882 /* Returned value is allocated in 'lp_talloc' context */
884 const char *lp_parm_string(struct loadparm_context *lp_ctx,
885 struct loadparm_service *service, const char *type,
888 const char *value = lp_get_parametric(lp_ctx, service, type, option);
891 return lp_string(value);
896 /* Return parametric option from a given service. Type is a part of option before ':' */
897 /* Parametric option has following syntax: 'Type: option = value' */
898 /* Returned value is allocated in 'lp_talloc' context */
900 const char **lp_parm_string_list(struct loadparm_context *lp_ctx,
901 struct loadparm_service *service,
903 const char *option, const char *separator)
905 const char *value = lp_get_parametric(lp_ctx, service, type, option);
908 return str_list_make(talloc_autofree_context(), value,
914 /* Return parametric option from a given service. Type is a part of option before ':' */
915 /* Parametric option has following syntax: 'Type: option = value' */
917 int lp_parm_int(struct loadparm_context *lp_ctx,
918 struct loadparm_service *service, const char *type,
919 const char *option, int default_v)
921 const char *value = lp_get_parametric(lp_ctx, service, type, option);
924 return lp_int(value);
929 /* Return parametric option from a given service. Type is a part of
931 * Parametric option has following syntax: 'Type: option = value'.
934 int lp_parm_bytes(struct loadparm_context *lp_ctx,
935 struct loadparm_service *service, const char *type,
936 const char *option, int default_v)
940 const char *value = lp_get_parametric(lp_ctx, service, type, option);
942 if (value && conv_str_size(value, &bval)) {
943 if (bval <= INT_MAX) {
951 /* Return parametric option from a given service. Type is a part of option before ':' */
952 /* Parametric option has following syntax: 'Type: option = value' */
954 unsigned long lp_parm_ulong(struct loadparm_context *lp_ctx,
955 struct loadparm_service *service, const char *type,
956 const char *option, unsigned long default_v)
958 const char *value = lp_get_parametric(lp_ctx, service, type, option);
961 return lp_ulong(value);
967 double lp_parm_double(struct loadparm_context *lp_ctx,
968 struct loadparm_service *service, const char *type,
969 const char *option, double default_v)
971 const char *value = lp_get_parametric(lp_ctx, service, type, option);
974 return lp_double(value);
979 /* Return parametric option from a given service. Type is a part of option before ':' */
980 /* Parametric option has following syntax: 'Type: option = value' */
982 bool lp_parm_bool(struct loadparm_context *lp_ctx,
983 struct loadparm_service *service, const char *type,
984 const char *option, bool default_v)
986 const char *value = lp_get_parametric(lp_ctx, service, type, option);
989 return lp_bool(value);
995 /***************************************************************************
996 Initialise a service to the defaults.
997 ***************************************************************************/
999 static struct loadparm_service *init_service(TALLOC_CTX *mem_ctx)
1001 struct loadparm_service *pservice =
1002 talloc_zero(mem_ctx, struct loadparm_service);
1003 copy_service(pservice, &sDefault, NULL);
1008 Set a string value, deallocating any existing space, and allocing the space
1011 static bool string_set(TALLOC_CTX *mem_ctx, char **dest, const char *src)
1018 *dest = talloc_strdup(mem_ctx, src);
1019 if ((*dest) == NULL) {
1020 DEBUG(0,("Out of memory in string_init\n"));
1029 /***************************************************************************
1030 Add a new service to the services array initialising it with the given
1032 ***************************************************************************/
1034 struct loadparm_service *lp_add_service(struct loadparm_context *lp_ctx,
1035 const struct loadparm_service *pservice,
1039 struct loadparm_service tservice;
1040 int num_to_alloc = lp_ctx->iNumServices + 1;
1041 struct param_opt *data, *pdata;
1043 tservice = *pservice;
1045 /* it might already exist */
1047 struct loadparm_service *service = getservicebyname(lp_ctx,
1049 if (service != NULL) {
1050 /* Clean all parametric options for service */
1051 /* They will be added during parsing again */
1052 data = service->param_opt;
1058 service->param_opt = NULL;
1063 /* find an invalid one */
1064 for (i = 0; i < lp_ctx->iNumServices; i++)
1065 if (lp_ctx->ServicePtrs[i] == NULL)
1068 /* if not, then create one */
1069 if (i == lp_ctx->iNumServices) {
1070 struct loadparm_service **tsp;
1072 tsp = realloc_p(lp_ctx->ServicePtrs, struct loadparm_service *,
1076 DEBUG(0,("lp_add_service: failed to enlarge ServicePtrs!\n"));
1080 lp_ctx->ServicePtrs = tsp;
1081 lp_ctx->ServicePtrs[lp_ctx->iNumServices] = NULL;
1084 lp_ctx->iNumServices++;
1087 lp_ctx->ServicePtrs[i] = init_service(talloc_autofree_context());
1088 if (lp_ctx->ServicePtrs[i] == NULL) {
1089 DEBUG(0,("lp_add_service: out of memory!\n"));
1092 copy_service(lp_ctx->ServicePtrs[i], &tservice, NULL);
1094 string_set(lp_ctx->ServicePtrs[i], &lp_ctx->ServicePtrs[i]->szService, name);
1095 return lp_ctx->ServicePtrs[i];
1098 /***************************************************************************
1099 Add a new home service, with the specified home directory, defaults coming
1101 ***************************************************************************/
1103 bool lp_add_home(struct loadparm_context *lp_ctx,
1104 const char *pszHomename,
1105 struct loadparm_service *default_service,
1106 const char *user, const char *pszHomedir)
1108 struct loadparm_service *service;
1110 service = lp_add_service(lp_ctx, default_service, pszHomename);
1112 if (service == NULL)
1115 if (!(*(default_service->szPath))
1116 || strequal(default_service->szPath, sDefault.szPath)) {
1117 service->szPath = talloc_strdup(service, pszHomedir);
1119 service->szPath = string_sub_talloc(service, lp_pathname(default_service),"%H", pszHomedir);
1122 if (!(*(service->comment))) {
1123 service->comment = talloc_asprintf(service, "Home directory of %s", user);
1125 service->bAvailable = default_service->bAvailable;
1126 service->bBrowseable = default_service->bBrowseable;
1128 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n",
1129 pszHomename, user, service->szPath));
1134 /***************************************************************************
1135 Add the IPC service.
1136 ***************************************************************************/
1138 static bool lp_add_hidden(struct loadparm_context *lp_ctx, const char *name,
1141 struct loadparm_service *service = lp_add_service(lp_ctx, &sDefault, name);
1143 if (service == NULL)
1146 string_set(service, &service->szPath, tmpdir());
1148 service->comment = talloc_asprintf(service, "%s Service (%s)",
1149 fstype, lp_ctx->Globals.szServerString);
1150 string_set(service, &service->fstype, fstype);
1151 service->iMaxConnections = -1;
1152 service->bAvailable = true;
1153 service->bRead_only = true;
1154 service->bPrint_ok = false;
1155 service->bBrowseable = false;
1157 if (strcasecmp(fstype, "IPC") == 0) {
1158 lp_do_service_parameter(lp_ctx, service, "ntvfs handler",
1162 DEBUG(3, ("adding hidden service %s\n", name));
1167 /***************************************************************************
1168 Add a new printer service, with defaults coming from service iFrom.
1169 ***************************************************************************/
1171 bool lp_add_printer(struct loadparm_context *lp_ctx,
1172 const char *pszPrintername,
1173 struct loadparm_service *default_service)
1175 const char *comment = "From Printcap";
1176 struct loadparm_service *service;
1177 service = lp_add_service(lp_ctx, default_service, pszPrintername);
1179 if (service == NULL)
1182 /* note that we do NOT default the availability flag to True - */
1183 /* we take it from the default service passed. This allows all */
1184 /* dynamic printers to be disabled by disabling the [printers] */
1185 /* entry (if/when the 'available' keyword is implemented!). */
1187 /* the printer name is set to the service name. */
1188 string_set(service, &service->szPrintername, pszPrintername);
1189 string_set(service, &service->comment, comment);
1190 service->bBrowseable = sDefault.bBrowseable;
1191 /* Printers cannot be read_only. */
1192 service->bRead_only = false;
1193 /* Printer services must be printable. */
1194 service->bPrint_ok = true;
1196 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1201 /***************************************************************************
1202 Map a parameter's string representation to something we can use.
1203 Returns False if the parameter string is not recognised, else TRUE.
1204 ***************************************************************************/
1206 static int map_parameter(const char *pszParmName)
1210 if (*pszParmName == '-')
1213 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1214 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1217 /* Warn only if it isn't parametric option */
1218 if (strchr(pszParmName, ':') == NULL)
1219 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1220 /* We do return 'fail' for parametric options as well because they are
1221 stored in different storage
1228 return the parameter structure for a parameter
1230 struct parm_struct *lp_parm_struct(const char *name)
1232 int parmnum = map_parameter(name);
1233 if (parmnum == -1) return NULL;
1234 return &parm_table[parmnum];
1238 return the parameter pointer for a parameter
1240 void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
1242 if (service == NULL)
1245 return ((char *)service) + PTR_DIFF(parm->ptr, &sDefault);
1248 /***************************************************************************
1249 Find a service by name. Otherwise works like get_service.
1250 ***************************************************************************/
1252 static struct loadparm_service *getservicebyname(struct loadparm_context *lp_ctx,
1253 const char *pszServiceName)
1257 for (iService = lp_ctx->iNumServices - 1; iService >= 0; iService--)
1258 if (lp_ctx->ServicePtrs[iService] != NULL &&
1259 strwicmp(lp_ctx->ServicePtrs[iService]->szService, pszServiceName) == 0) {
1260 return lp_ctx->ServicePtrs[iService];
1266 /***************************************************************************
1267 Copy a service structure to another.
1268 If pcopymapDest is NULL then copy all fields
1269 ***************************************************************************/
1271 static void copy_service(struct loadparm_service *pserviceDest,
1272 struct loadparm_service *pserviceSource,
1276 bool bcopyall = (pcopymapDest == NULL);
1277 struct param_opt *data, *pdata, *paramo;
1280 for (i = 0; parm_table[i].label; i++)
1281 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1282 (bcopyall || pcopymapDest[i])) {
1283 void *def_ptr = parm_table[i].ptr;
1285 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
1288 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
1291 switch (parm_table[i].type) {
1293 *(int *)dest_ptr = *(int *)src_ptr;
1299 *(int *)dest_ptr = *(int *)src_ptr;
1303 string_set(pserviceDest,
1309 string_set(pserviceDest,
1312 strupper(*(char **)dest_ptr);
1315 *(const char ***)dest_ptr = str_list_copy(talloc_autofree_context(),
1316 *(const char ***)src_ptr);
1324 init_copymap(pserviceDest);
1325 if (pserviceSource->copymap)
1326 memcpy((void *)pserviceDest->copymap,
1327 (void *)pserviceSource->copymap,
1328 sizeof(int) * NUMPARAMETERS);
1331 data = pserviceSource->param_opt;
1334 pdata = pserviceDest->param_opt;
1335 /* Traverse destination */
1337 /* If we already have same option, override it */
1338 if (strcmp(pdata->key, data->key) == 0) {
1339 talloc_free(pdata->value);
1340 pdata->value = talloc_reference(pdata,
1345 pdata = pdata->next;
1348 paramo = talloc(pserviceDest, struct param_opt);
1351 paramo->key = talloc_reference(paramo, data->key);
1352 paramo->value = talloc_reference(paramo, data->value);
1353 DLIST_ADD(pserviceDest->param_opt, paramo);
1359 /***************************************************************************
1360 Check a service for consistency. Return False if the service is in any way
1361 incomplete or faulty, else True.
1362 ***************************************************************************/
1364 static bool service_ok(struct loadparm_service *service)
1369 if (service->szService[0] == '\0') {
1370 DEBUG(0, ("The following message indicates an internal error:\n"));
1371 DEBUG(0, ("No service name in service entry.\n"));
1375 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1376 /* I can't see why you'd want a non-printable printer service... */
1377 if (strwicmp(service->szService, PRINTERS_NAME) == 0) {
1378 if (!service->bPrint_ok) {
1379 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
1380 service->szService));
1381 service->bPrint_ok = true;
1383 /* [printers] service must also be non-browsable. */
1384 if (service->bBrowseable)
1385 service->bBrowseable = false;
1388 /* If a service is flagged unavailable, log the fact at level 0. */
1389 if (!service->bAvailable)
1390 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
1391 service->szService));
1397 /*******************************************************************
1398 Keep a linked list of all config files so we know when one has changed
1399 it's date and needs to be reloaded.
1400 ********************************************************************/
1402 static void add_to_file_list(struct loadparm_context *lp_ctx,
1403 const char *fname, const char *subfname)
1405 struct file_lists *f = lp_ctx->file_lists;
1408 if (f->name && !strcmp(f->name, fname))
1414 f = talloc(talloc_autofree_context(), struct file_lists);
1417 f->next = lp_ctx->file_lists;
1418 f->name = talloc_strdup(f, fname);
1423 f->subfname = talloc_strdup(f, subfname);
1428 lp_ctx->file_lists = f;
1429 f->modtime = file_modtime(subfname);
1431 time_t t = file_modtime(subfname);
1437 /*******************************************************************
1438 Check if a config file has changed date.
1439 ********************************************************************/
1441 bool lp_file_list_changed(struct loadparm_context *lp_ctx)
1443 struct file_lists *f;
1444 DEBUG(6, ("lp_file_list_changed()\n"));
1446 for (f = lp_ctx->file_lists; f != NULL; f = f->next) {
1450 n2 = standard_sub_basic(talloc_autofree_context(), f->name);
1452 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
1453 f->name, n2, ctime(&f->modtime)));
1455 mod_time = file_modtime(n2);
1457 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
1458 DEBUGADD(6, ("file %s modified: %s\n", n2,
1460 f->modtime = mod_time;
1461 talloc_free(f->subfname);
1462 f->subfname = talloc_strdup(f, n2);
1469 /***************************************************************************
1470 Handle the include operation.
1471 ***************************************************************************/
1473 static bool handle_include(struct loadparm_context *lp_ctx,
1474 const char *pszParmValue, char **ptr)
1476 char *fname = standard_sub_basic(talloc_autofree_context(),
1479 add_to_file_list(lp_ctx, pszParmValue, fname);
1481 string_set(talloc_autofree_context(), ptr, fname);
1483 if (file_exist(fname))
1484 return pm_process(fname, do_section, do_parameter, lp_ctx);
1486 DEBUG(2, ("Can't find include file %s\n", fname));
1491 /***************************************************************************
1492 Handle the interpretation of the copy parameter.
1493 ***************************************************************************/
1495 static bool handle_copy(struct loadparm_context *lp_ctx,
1496 const char *pszParmValue, char **ptr)
1499 struct loadparm_service *serviceTemp;
1501 string_set(talloc_autofree_context(), ptr, pszParmValue);
1505 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
1507 if ((serviceTemp = getservicebyname(lp_ctx, pszParmValue)) != NULL) {
1508 if (serviceTemp == lp_ctx->currentService) {
1509 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
1511 copy_service(lp_ctx->currentService,
1513 lp_ctx->currentService->copymap);
1517 DEBUG(0, ("Unable to copy service - source not found: %s\n",
1525 /***************************************************************************
1526 Initialise a copymap.
1527 ***************************************************************************/
1529 static void init_copymap(struct loadparm_service *pservice)
1532 talloc_free(pservice->copymap);
1533 pservice->copymap = talloc_array(pservice, int, NUMPARAMETERS);
1534 if (pservice->copymap == NULL) {
1536 ("Couldn't allocate copymap!! (size %d)\n",
1537 (int)NUMPARAMETERS));
1540 for (i = 0; i < NUMPARAMETERS; i++)
1541 pservice->copymap[i] = true;
1544 /***************************************************************************
1545 Process a parametric option
1546 ***************************************************************************/
1547 static bool lp_do_parameter_parametric(struct loadparm_context *lp_ctx,
1548 struct loadparm_service *service,
1549 const char *pszParmName,
1550 const char *pszParmValue, int flags)
1552 struct param_opt *paramo, *data;
1554 TALLOC_CTX *mem_ctx;
1556 while (isspace((unsigned char)*pszParmName)) {
1560 name = strdup(pszParmName);
1561 if (!name) return false;
1565 if (service == NULL) {
1566 data = lp_ctx->Globals.param_opt;
1567 mem_ctx = talloc_autofree_context();
1569 data = service->param_opt;
1573 /* Traverse destination */
1574 for (paramo=data; paramo; paramo=paramo->next) {
1575 /* If we already have the option set, override it unless
1576 it was a command line option and the new one isn't */
1577 if (strcmp(paramo->key, name) == 0) {
1578 if ((paramo->flags & FLAG_CMDLINE) &&
1579 !(flags & FLAG_CMDLINE)) {
1583 talloc_free(paramo->value);
1584 paramo->value = talloc_strdup(paramo, pszParmValue);
1585 paramo->flags = flags;
1591 paramo = talloc(mem_ctx, struct param_opt);
1594 paramo->key = talloc_strdup(paramo, name);
1595 paramo->value = talloc_strdup(paramo, pszParmValue);
1596 paramo->flags = flags;
1597 if (service == NULL) {
1598 DLIST_ADD(lp_ctx->Globals.param_opt, paramo);
1600 DLIST_ADD(service->param_opt, paramo);
1608 static bool set_variable(TALLOC_CTX *mem_ctx, int parmnum, void *parm_ptr,
1609 const char *pszParmName, const char *pszParmValue,
1610 struct loadparm_context *lp_ctx)
1613 /* if it is a special case then go ahead */
1614 if (parm_table[parmnum].special) {
1615 parm_table[parmnum].special(lp_ctx, pszParmValue,
1620 /* now switch on the type of variable it is */
1621 switch (parm_table[parmnum].type)
1625 if (!set_boolean(pszParmValue, &b)) {
1626 DEBUG(0,("lp_do_parameter(%s): value is not boolean!\n", pszParmValue));
1629 *(int *)parm_ptr = b;
1634 *(int *)parm_ptr = atoi(pszParmValue);
1638 *(int *)parm_ptr = strtol(pszParmValue, NULL, 8);
1644 if (conv_str_size(pszParmValue, &val)) {
1645 if (val <= INT_MAX) {
1646 *(int *)parm_ptr = (int)val;
1651 DEBUG(0,("lp_do_parameter(%s): value is not "
1652 "a valid size specifier!\n", pszParmValue));
1657 *(const char ***)parm_ptr = str_list_make(mem_ctx,
1658 pszParmValue, NULL);
1662 string_set(mem_ctx, (char **)parm_ptr, pszParmValue);
1666 string_set(mem_ctx, (char **)parm_ptr, pszParmValue);
1667 strupper(*(char **)parm_ptr);
1671 for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
1674 parm_table[parmnum].enum_list[i].name)) {
1676 parm_table[parmnum].
1681 if (!parm_table[parmnum].enum_list[i].name) {
1682 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n",
1683 pszParmValue, pszParmName));
1689 if (parm_table[parmnum].flags & FLAG_DEFAULT) {
1690 parm_table[parmnum].flags &= ~FLAG_DEFAULT;
1691 /* we have to also unset FLAG_DEFAULT on aliases */
1692 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1693 parm_table[i].flags &= ~FLAG_DEFAULT;
1695 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1696 parm_table[i].flags &= ~FLAG_DEFAULT;
1703 bool lp_do_global_parameter(struct loadparm_context *lp_ctx,
1704 const char *pszParmName, const char *pszParmValue)
1706 int parmnum = map_parameter(pszParmName);
1710 if (strchr(pszParmName, ':')) {
1711 return lp_do_parameter_parametric(lp_ctx, NULL, pszParmName, pszParmValue, 0);
1713 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1717 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1718 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1722 /* if the flag has been set on the command line, then don't allow override,
1723 but don't report an error */
1724 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1728 parm_ptr = parm_table[parmnum].ptr;
1730 return set_variable(talloc_autofree_context(), parmnum, parm_ptr,
1731 pszParmName, pszParmValue, lp_ctx);
1734 bool lp_do_service_parameter(struct loadparm_context *lp_ctx,
1735 struct loadparm_service *service,
1736 const char *pszParmName, const char *pszParmValue)
1738 void *def_ptr = NULL;
1741 int parmnum = map_parameter(pszParmName);
1744 if (strchr(pszParmName, ':')) {
1745 return lp_do_parameter_parametric(lp_ctx, service, pszParmName, pszParmValue, 0);
1747 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1751 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1752 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1756 /* if the flag has been set on the command line, then don't allow override,
1757 but don't report an error */
1758 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1762 def_ptr = parm_table[parmnum].ptr;
1764 if (parm_table[parmnum].class == P_GLOBAL) {
1766 ("Global parameter %s found in service section!\n",
1770 parm_ptr = ((char *)service) + PTR_DIFF(def_ptr, &sDefault);
1772 if (!service->copymap)
1773 init_copymap(service);
1775 /* this handles the aliases - set the copymap for other
1776 * entries with the same data pointer */
1777 for (i = 0; parm_table[i].label; i++)
1778 if (parm_table[i].ptr == parm_table[parmnum].ptr)
1779 service->copymap[i] = false;
1781 return set_variable(service, parmnum, parm_ptr, pszParmName,
1782 pszParmValue, lp_ctx);
1785 /***************************************************************************
1786 Process a parameter.
1787 ***************************************************************************/
1789 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
1792 struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata;
1794 if (lp_ctx->bInGlobalSection)
1795 return lp_do_global_parameter(lp_ctx, pszParmName,
1798 return lp_do_service_parameter(lp_ctx, lp_ctx->currentService,
1799 pszParmName, pszParmValue);
1803 variable argument do parameter
1805 bool lp_do_global_parameter_var(struct loadparm_context *lp_ctx, const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4);
1806 bool lp_do_global_parameter_var(struct loadparm_context *lp_ctx,
1807 const char *pszParmName, const char *fmt, ...)
1814 s = talloc_vasprintf(NULL, fmt, ap);
1816 ret = lp_do_global_parameter(lp_ctx, pszParmName, s);
1823 set a parameter from the commandline - this is called from command line parameter
1824 parsing code. It sets the parameter then marks the parameter as unable to be modified
1825 by smb.conf processing
1827 bool lp_set_cmdline(struct loadparm_context *lp_ctx, const char *pszParmName,
1828 const char *pszParmValue)
1830 int parmnum = map_parameter(pszParmName);
1833 while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
1836 if (parmnum < 0 && strchr(pszParmName, ':')) {
1837 /* set a parametric option */
1838 return lp_do_parameter_parametric(lp_ctx, NULL, pszParmName,
1839 pszParmValue, FLAG_CMDLINE);
1843 DEBUG(0,("Unknown option '%s'\n", pszParmName));
1847 /* reset the CMDLINE flag in case this has been called before */
1848 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
1850 if (!lp_do_global_parameter(lp_ctx, pszParmName, pszParmValue)) {
1854 parm_table[parmnum].flags |= FLAG_CMDLINE;
1856 /* we have to also set FLAG_CMDLINE on aliases */
1857 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1858 parm_table[i].flags |= FLAG_CMDLINE;
1860 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1861 parm_table[i].flags |= FLAG_CMDLINE;
1868 set a option from the commandline in 'a=b' format. Use to support --option
1870 bool lp_set_option(struct loadparm_context *lp_ctx, const char *option)
1888 ret = lp_set_cmdline(lp_ctx, s, p+1);
1894 #define BOOLSTR(b) ((b) ? "Yes" : "No")
1896 /***************************************************************************
1897 Print a parameter of the specified type.
1898 ***************************************************************************/
1900 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
1906 for (i = 0; p->enum_list[i].name; i++) {
1907 if (*(int *)ptr == p->enum_list[i].value) {
1909 p->enum_list[i].name);
1916 fprintf(f, "%s", BOOLSTR((bool)*(int *)ptr));
1921 fprintf(f, "%d", *(int *)ptr);
1925 fprintf(f, "0%o", *(int *)ptr);
1929 if ((char ***)ptr && *(char ***)ptr) {
1930 char **list = *(char ***)ptr;
1932 for (; *list; list++)
1933 fprintf(f, "%s%s", *list,
1934 ((*(list+1))?", ":""));
1940 if (*(char **)ptr) {
1941 fprintf(f, "%s", *(char **)ptr);
1947 /***************************************************************************
1948 Check if two parameters are equal.
1949 ***************************************************************************/
1951 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
1955 return (*((int *)ptr1) == *((int *)ptr2));
1961 return (*((int *)ptr1) == *((int *)ptr2));
1964 return str_list_equal((const char **)(*(char ***)ptr1),
1965 (const char **)(*(char ***)ptr2));
1970 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
1975 return (p1 == p2 || strequal(p1, p2));
1981 /***************************************************************************
1982 Process a new section (service). At this stage all sections are services.
1983 Later we'll have special sections that permit server parameters to be set.
1984 Returns True on success, False on failure.
1985 ***************************************************************************/
1987 static bool do_section(const char *pszSectionName, void *userdata)
1989 struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata;
1991 bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
1992 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
1995 /* if we've just struck a global section, note the fact. */
1996 lp_ctx->bInGlobalSection = isglobal;
1998 /* check for multiple global sections */
1999 if (lp_ctx->bInGlobalSection) {
2000 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2004 /* if we have a current service, tidy it up before moving on */
2007 if (lp_ctx->currentService != NULL)
2008 bRetval = service_ok(lp_ctx->currentService);
2010 /* if all is still well, move to the next record in the services array */
2012 /* We put this here to avoid an odd message order if messages are */
2013 /* issued by the post-processing of a previous section. */
2014 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2016 if ((lp_ctx->currentService = lp_add_service(lp_ctx, &sDefault,
2019 DEBUG(0, ("Failed to add a new service\n"));
2028 /***************************************************************************
2029 Determine if a partcular base parameter is currentl set to the default value.
2030 ***************************************************************************/
2032 static bool is_default(int i)
2034 if (!defaults_saved)
2036 switch (parm_table[i].type) {
2038 return str_list_equal((const char **)parm_table[i].def.lvalue,
2039 (const char **)(*(char ***)parm_table[i].ptr));
2042 return strequal(parm_table[i].def.svalue,
2043 *(char **)parm_table[i].ptr);
2045 return parm_table[i].def.bvalue ==
2046 *(int *)parm_table[i].ptr;
2051 return parm_table[i].def.ivalue ==
2052 *(int *)parm_table[i].ptr;
2057 /***************************************************************************
2058 Display the contents of the global structure.
2059 ***************************************************************************/
2061 static void dump_globals(struct loadparm_context *lp_ctx, FILE *f, bool show_defaults)
2064 struct param_opt *data;
2066 fprintf(f, "# Global parameters\n[global]\n");
2068 for (i = 0; parm_table[i].label; i++)
2069 if (parm_table[i].class == P_GLOBAL &&
2070 parm_table[i].ptr &&
2071 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2072 if (!show_defaults && (parm_table[i].flags & FLAG_DEFAULT))
2074 fprintf(f, "\t%s = ", parm_table[i].label);
2075 print_parameter(&parm_table[i], parm_table[i].ptr, f);
2078 if (lp_ctx->Globals.param_opt != NULL) {
2079 for (data = lp_ctx->Globals.param_opt; data;
2080 data = data->next) {
2081 fprintf(f, "\t%s = %s\n", data->key, data->value);
2087 /***************************************************************************
2088 Display the contents of a single services record.
2089 ***************************************************************************/
2091 static void dump_a_service(struct loadparm_service * pService, FILE * f)
2094 struct param_opt *data;
2096 if (pService != &sDefault)
2097 fprintf(f, "\n[%s]\n", pService->szService);
2099 for (i = 0; parm_table[i].label; i++)
2100 if (parm_table[i].class == P_LOCAL &&
2101 parm_table[i].ptr &&
2102 (*parm_table[i].label != '-') &&
2103 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2104 int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
2106 if (pService == &sDefault) {
2107 if (defaults_saved && is_default(i))
2110 if (equal_parameter(parm_table[i].type,
2111 ((char *)pService) +
2113 ((char *)&sDefault) +
2118 fprintf(f, "\t%s = ", parm_table[i].label);
2119 print_parameter(&parm_table[i],
2120 ((char *)pService) + pdiff, f);
2123 if (pService->param_opt != NULL) {
2124 for (data = pService->param_opt; data; data = data->next) {
2125 fprintf(f, "\t%s = %s\n", data->key, data->value);
2130 bool lp_dump_a_parameter(struct loadparm_context *lp_ctx, int snum, char *parm_name, FILE * f,
2133 struct loadparm_service * pService = lp_ctx->ServicePtrs[snum];
2134 struct parm_struct *parm;
2137 parm = lp_parm_struct(parm_name);
2145 ptr = ((char *)pService) +
2146 PTR_DIFF(parm->ptr, &sDefault);
2148 print_parameter(parm,
2154 /***************************************************************************
2155 Return info about the next service in a service. snum==-1 gives the globals.
2156 Return NULL when out of parameters.
2157 ***************************************************************************/
2159 struct parm_struct *lp_next_parameter(struct loadparm_context *lp_ctx, int snum, int *i,
2163 /* do the globals */
2164 for (; parm_table[*i].label; (*i)++) {
2165 if (!parm_table[*i].ptr
2166 || (*parm_table[*i].label == '-'))
2170 && (parm_table[*i].ptr ==
2171 parm_table[(*i) - 1].ptr))
2174 return &parm_table[(*i)++];
2177 struct loadparm_service *pService = lp_ctx->ServicePtrs[snum];
2179 for (; parm_table[*i].label; (*i)++) {
2180 if (parm_table[*i].class == P_LOCAL &&
2181 parm_table[*i].ptr &&
2182 (*parm_table[*i].label != '-') &&
2184 (parm_table[*i].ptr !=
2185 parm_table[(*i) - 1].ptr)))
2188 PTR_DIFF(parm_table[*i].ptr,
2191 if (allparameters ||
2192 !equal_parameter(parm_table[*i].type,
2193 ((char *)pService) +
2195 ((char *)&sDefault) +
2198 return &parm_table[(*i)++];
2208 /***************************************************************************
2209 Auto-load some home services.
2210 ***************************************************************************/
2212 static void lp_add_auto_services(struct loadparm_context *lp_ctx,
2218 /***************************************************************************
2219 Have we loaded a services file yet?
2220 ***************************************************************************/
2222 bool lp_loaded(void)
2227 /***************************************************************************
2228 Unload unused services.
2229 ***************************************************************************/
2231 void lp_killunused(struct loadparm_context *lp_ctx,
2232 struct smbsrv_connection *smb,
2233 bool (*snumused) (struct smbsrv_connection *, int))
2236 for (i = 0; i < lp_ctx->iNumServices; i++) {
2237 if (lp_ctx->ServicePtrs[i] == NULL)
2240 if (!snumused || !snumused(smb, i)) {
2241 talloc_free(lp_ctx->ServicePtrs[i]);
2242 lp_ctx->ServicePtrs[i] = NULL;
2247 /***************************************************************************
2248 Initialise the global parameter structure.
2249 ***************************************************************************/
2250 bool loadparm_init(struct loadparm_context *lp_ctx)
2255 lp_ctx->bInGlobalSection = true;
2257 DEBUG(3, ("Initialising global parameters\n"));
2259 for (i = 0; parm_table[i].label; i++) {
2260 if ((parm_table[i].type == P_STRING ||
2261 parm_table[i].type == P_USTRING) &&
2262 parm_table[i].ptr &&
2263 !(parm_table[i].flags & FLAG_CMDLINE)) {
2264 string_set(talloc_autofree_context(),
2265 (char **)parm_table[i].ptr, "");
2269 lp_do_global_parameter(lp_ctx, "share backend", "classic");
2271 lp_do_global_parameter(lp_ctx, "server role", "standalone");
2273 /* options that can be set on the command line must be initialised via
2274 the slower lp_do_global_parameter() to ensure that FLAG_CMDLINE is obeyed */
2276 lp_do_global_parameter(lp_ctx, "socket options", "TCP_NODELAY");
2278 lp_do_global_parameter(lp_ctx, "workgroup", DEFAULT_WORKGROUP);
2279 myname = get_myname();
2280 lp_do_global_parameter(lp_ctx, "netbios name", myname);
2282 lp_do_global_parameter(lp_ctx, "name resolve order", "lmhosts wins host bcast");
2284 lp_do_global_parameter(lp_ctx, "fstype", FSTYPE_STRING);
2285 lp_do_global_parameter(lp_ctx, "ntvfs handler", "unixuid default");
2286 lp_do_global_parameter(lp_ctx, "max connections", "-1");
2288 lp_do_global_parameter(lp_ctx, "dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup unixinfo");
2289 lp_do_global_parameter(lp_ctx, "server services", "smb rpc nbt wrepl ldap cldap web kdc drepl winbind");
2290 lp_do_global_parameter(lp_ctx, "ntptr providor", "simple_ldb");
2291 lp_do_global_parameter(lp_ctx, "auth methods:domain controller", "anonymous sam_ignoredomain");
2292 lp_do_global_parameter(lp_ctx, "auth methods:member server", "anonymous sam winbind");
2293 lp_do_global_parameter(lp_ctx, "auth methods:standalone", "anonymous sam_ignoredomain");
2294 lp_do_global_parameter(lp_ctx, "private dir", dyn_PRIVATE_DIR);
2295 lp_do_global_parameter(lp_ctx, "sam database", "sam.ldb");
2296 lp_do_global_parameter(lp_ctx, "secrets database", "secrets.ldb");
2297 lp_do_global_parameter(lp_ctx, "spoolss database", "spoolss.ldb");
2298 lp_do_global_parameter(lp_ctx, "wins config database", "wins_config.ldb");
2299 lp_do_global_parameter(lp_ctx, "wins database", "wins.ldb");
2300 lp_do_global_parameter(lp_ctx, "registry:HKEY_LOCAL_MACHINE", "hklm.ldb");
2302 /* This hive should be dynamically generated by Samba using
2303 data from the sam, but for the moment leave it in a tdb to
2304 keep regedt32 from popping up an annoying dialog. */
2305 lp_do_global_parameter(lp_ctx, "registry:HKEY_USERS", "hku.ldb");
2307 /* using UTF8 by default allows us to support all chars */
2308 lp_do_global_parameter(lp_ctx, "unix charset", "UTF8");
2310 /* Use codepage 850 as a default for the dos character set */
2311 lp_do_global_parameter(lp_ctx, "dos charset", "CP850");
2314 * Allow the default PASSWD_CHAT to be overridden in local.h.
2316 lp_do_global_parameter(lp_ctx, "passwd chat", DEFAULT_PASSWD_CHAT);
2318 lp_do_global_parameter(lp_ctx, "pid directory", dyn_PIDDIR);
2319 lp_do_global_parameter(lp_ctx, "lock dir", dyn_LOCKDIR);
2320 lp_do_global_parameter(lp_ctx, "modules dir", dyn_MODULESDIR);
2321 lp_do_global_parameter(lp_ctx, "ncalrpc dir", dyn_NCALRPCDIR);
2323 lp_do_global_parameter(lp_ctx, "socket address", "0.0.0.0");
2324 lp_do_global_parameter_var(lp_ctx, "server string",
2325 "Samba %s", SAMBA_VERSION_STRING);
2327 lp_do_global_parameter_var(lp_ctx, "announce version", "%d.%d",
2328 DEFAULT_MAJOR_VERSION,
2329 DEFAULT_MINOR_VERSION);
2331 lp_do_global_parameter(lp_ctx, "password server", "*");
2333 lp_do_global_parameter(lp_ctx, "max mux", "50");
2334 lp_do_global_parameter(lp_ctx, "max xmit", "12288");
2335 lp_do_global_parameter(lp_ctx, "password level", "0");
2336 lp_do_global_parameter(lp_ctx, "LargeReadwrite", "True");
2337 lp_do_global_parameter(lp_ctx, "server min protocol", "CORE");
2338 lp_do_global_parameter(lp_ctx, "server max protocol", "NT1");
2339 lp_do_global_parameter(lp_ctx, "client min protocol", "CORE");
2340 lp_do_global_parameter(lp_ctx, "client max protocol", "NT1");
2341 lp_do_global_parameter(lp_ctx, "security", "USER");
2342 lp_do_global_parameter(lp_ctx, "paranoid server security", "True");
2343 lp_do_global_parameter(lp_ctx, "EncryptPasswords", "True");
2344 lp_do_global_parameter(lp_ctx, "ReadRaw", "True");
2345 lp_do_global_parameter(lp_ctx, "WriteRaw", "True");
2346 lp_do_global_parameter(lp_ctx, "NullPasswords", "False");
2347 lp_do_global_parameter(lp_ctx, "ObeyPamRestrictions", "False");
2348 lp_do_global_parameter(lp_ctx, "announce as", "NT SERVER");
2350 lp_do_global_parameter(lp_ctx, "TimeServer", "False");
2351 lp_do_global_parameter(lp_ctx, "BindInterfacesOnly", "False");
2352 lp_do_global_parameter(lp_ctx, "Unicode", "True");
2353 lp_do_global_parameter(lp_ctx, "ClientLanManAuth", "True");
2354 lp_do_global_parameter(lp_ctx, "LanmanAuth", "True");
2355 lp_do_global_parameter(lp_ctx, "NTLMAuth", "True");
2356 lp_do_global_parameter(lp_ctx, "client use spnego principal", "False");
2358 lp_do_global_parameter(lp_ctx, "UnixExtensions", "False");
2360 lp_do_global_parameter(lp_ctx, "PreferredMaster", "Auto");
2361 lp_do_global_parameter(lp_ctx, "LocalMaster", "True");
2363 lp_do_global_parameter(lp_ctx, "wins support", "False");
2364 lp_do_global_parameter(lp_ctx, "dns proxy", "True");
2366 lp_do_global_parameter(lp_ctx, "winbind separator", "\\");
2367 lp_do_global_parameter(lp_ctx, "winbind sealed pipes", "True");
2368 lp_do_global_parameter(lp_ctx, "winbindd socket directory", dyn_WINBINDD_SOCKET_DIR);
2369 lp_do_global_parameter(lp_ctx, "template shell", "/bin/false");
2370 lp_do_global_parameter(lp_ctx, "template homedir", "/home/%WORKGROUP%/%ACCOUNTNAME%");
2372 lp_do_global_parameter(lp_ctx, "client signing", "Yes");
2373 lp_do_global_parameter(lp_ctx, "server signing", "auto");
2375 lp_do_global_parameter(lp_ctx, "use spnego", "True");
2377 lp_do_global_parameter(lp_ctx, "smb ports", "445 139");
2378 lp_do_global_parameter(lp_ctx, "nbt port", "137");
2379 lp_do_global_parameter(lp_ctx, "dgram port", "138");
2380 lp_do_global_parameter(lp_ctx, "cldap port", "389");
2381 lp_do_global_parameter(lp_ctx, "krb5 port", "88");
2382 lp_do_global_parameter(lp_ctx, "kpasswd port", "464");
2383 lp_do_global_parameter(lp_ctx, "web port", "901");
2384 lp_do_global_parameter(lp_ctx, "swat directory", dyn_SWATDIR);
2386 lp_do_global_parameter(lp_ctx, "nt status support", "True");
2388 lp_do_global_parameter(lp_ctx, "max wins ttl", "518400"); /* 6 days */
2389 lp_do_global_parameter(lp_ctx, "min wins ttl", "10");
2391 lp_do_global_parameter(lp_ctx, "tls enabled", "True");
2392 lp_do_global_parameter(lp_ctx, "tls keyfile", "tls/key.pem");
2393 lp_do_global_parameter(lp_ctx, "tls certfile", "tls/cert.pem");
2394 lp_do_global_parameter(lp_ctx, "tls cafile", "tls/ca.pem");
2395 lp_do_global_parameter_var(lp_ctx, "js include", "%s", dyn_JSDIR);
2396 lp_do_global_parameter_var(lp_ctx, "setup directory", "%s",
2399 for (i = 0; parm_table[i].label; i++) {
2400 if (!(parm_table[i].flags & FLAG_CMDLINE)) {
2401 parm_table[i].flags |= FLAG_DEFAULT;
2408 _PUBLIC_ _DEPRECATED_ bool lp_load_default(void)
2410 return lp_load(dyn_CONFIGFILE);
2413 /***************************************************************************
2414 Load the services array from the services file. Return True on success,
2416 ***************************************************************************/
2418 bool lp_load(const char *filename)
2422 struct param_opt *data;
2423 struct loadparm_context *lp_ctx = &loadparm;
2425 filename = talloc_strdup(talloc_autofree_context(), filename);
2427 global_loadparm = lp_ctx;
2429 if (lp_ctx->Globals.param_opt != NULL) {
2430 struct param_opt *next;
2431 for (data = lp_ctx->Globals.param_opt; data; data=next) {
2433 if (data->flags & FLAG_CMDLINE) continue;
2434 DLIST_REMOVE(lp_ctx->Globals.param_opt, data);
2439 if (!loadparm_init(lp_ctx))
2442 lp_ctx->Globals.szConfigFile = filename;
2444 lp_ctx->bInGlobalSection = true;
2445 n2 = standard_sub_basic(talloc_autofree_context(), lp_ctx->Globals.szConfigFile);
2446 DEBUG(2, ("lp_load: refreshing parameters from %s\n", n2));
2448 add_to_file_list(lp_ctx, lp_ctx->Globals.szConfigFile, n2);
2450 /* We get sections first, so have to start 'behind' to make up */
2451 lp_ctx->currentService = NULL;
2452 bRetval = pm_process(n2, do_section, do_parameter, lp_ctx);
2454 /* finish up the last section */
2455 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
2457 if (lp_ctx->currentService != NULL)
2458 bRetval = service_ok(lp_ctx->currentService);
2460 lp_add_auto_services(lp_ctx, lp_auto_services(lp_ctx));
2462 lp_add_hidden(lp_ctx, "IPC$", "IPC");
2463 lp_add_hidden(lp_ctx, "ADMIN$", "DISK");
2467 if (!lp_ctx->Globals.szWINSservers && lp_ctx->Globals.bWINSsupport) {
2468 lp_do_global_parameter(lp_ctx, "wins server", "127.0.0.1");
2476 /***************************************************************************
2477 Return the max number of services.
2478 ***************************************************************************/
2480 int lp_numservices(struct loadparm_context *lp_ctx)
2482 return lp_ctx->iNumServices;
2485 /***************************************************************************
2486 Display the contents of the services array in human-readable form.
2487 ***************************************************************************/
2489 void lp_dump(struct loadparm_context *lp_ctx, FILE *f, bool show_defaults,
2495 defaults_saved = false;
2497 dump_globals(lp_ctx, f, show_defaults);
2499 dump_a_service(&sDefault, f);
2501 for (iService = 0; iService < maxtoprint; iService++)
2502 lp_dump_one(f, show_defaults, lp_ctx->ServicePtrs[iService]);
2505 /***************************************************************************
2506 Display the contents of one service in human-readable form.
2507 ***************************************************************************/
2509 void lp_dump_one(FILE *f, bool show_defaults, struct loadparm_service *service)
2511 if (service != NULL) {
2512 if (service->szService[0] == '\0')
2514 dump_a_service(service, f);
2518 struct loadparm_service *lp_servicebynum(struct loadparm_context *lp_ctx,
2521 return lp_ctx->ServicePtrs[snum];
2524 struct loadparm_service *lp_service(struct loadparm_context *lp_ctx,
2525 const char *service_name)
2530 for (iService = lp_ctx->iNumServices - 1; iService >= 0; iService--) {
2531 if (lp_ctx->ServicePtrs[iService] &&
2532 lp_ctx->ServicePtrs[iService]->szService) {
2534 * The substitution here is used to support %U is
2537 serviceName = standard_sub_basic(
2538 lp_ctx->ServicePtrs[iService],
2539 lp_ctx->ServicePtrs[iService]->szService);
2540 if (strequal(serviceName, service_name))
2541 return lp_ctx->ServicePtrs[iService];
2545 DEBUG(7,("lp_servicenumber: couldn't find %s\n", service_name));
2550 /*******************************************************************
2551 A useful volume label function.
2552 ********************************************************************/
2553 const char *volume_label(struct loadparm_service *service)
2555 const char *ret = lp_volume(service);
2557 return lp_servicename(service);
2562 /***********************************************************
2563 If we are PDC then prefer us as DMB
2564 ************************************************************/
2566 bool lp_domain_logons(struct loadparm_context *lp_ctx)
2568 return (lp_server_role(lp_ctx) == ROLE_DOMAIN_CONTROLLER);
2571 const char *lp_printername(struct loadparm_service *service)
2573 const char *ret = _lp_printername(service);
2574 if (ret == NULL || (ret != NULL && *ret == '\0'))
2575 ret = lp_const_servicename(service);
2581 /*******************************************************************
2582 Return the max print jobs per queue.
2583 ********************************************************************/
2585 int lp_maxprintjobs(struct loadparm_service *service)
2587 int maxjobs = (service != NULL) ? service->iMaxPrintJobs : sDefault.iMaxPrintJobs;
2588 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
2589 maxjobs = PRINT_MAX_JOBID - 1;