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 #define standard_sub_basic talloc_strdup
69 static bool do_parameter(const char *, const char *, void *);
70 static bool defaults_saved = false;
73 * This structure describes global (ie., server-wide) parameters.
75 struct loadparm_global
77 enum server_role server_role;
79 const char **smb_ports;
83 char *display_charset;
91 const char *szConfigFile;
96 char *szWINS_CONFIG_URL;
99 const char **jsInclude;
100 char *jsonrpcServicesDir;
101 const char **szPasswordServers;
102 char *szSocketOptions;
104 const char **szWINSservers;
105 const char **szInterfaces;
106 char *szSocketAddress;
107 char *szAnnounceVersion; /* This is initialised in init_globals */
110 const char **szNetbiosAliases;
111 char *szNetbiosScope;
112 char *szDomainOtherSIDs;
113 const char **szNameResolveOrder;
114 const char **dcerpc_ep_servers;
115 const char **server_services;
116 char *ntptr_providor;
117 char *szWinbindSeparator;
118 char *szWinbinddSocketDirectory;
119 char *szTemplateShell;
120 char *szTemplateHomedir;
121 int bWinbindSealedPipes;
122 char *swat_directory;
140 int paranoid_server_security;
143 int announce_as; /* This is initialised in init_globals */
150 char *socket_options;
155 int bPreferredMaster;
156 int bEncryptPasswords;
158 int bObeyPamRestrictions;
163 int bBindInterfacesOnly;
165 int bNTStatusSupport;
171 int bClientPlaintextAuth;
172 int bClientLanManAuth;
173 int bClientNTLMv2Auth;
174 int client_use_spnego_principal;
180 struct param_opt *param_opt;
185 * This structure describes a single service.
187 struct loadparm_service
199 char **ntvfs_handler;
212 int iCreate_force_mode;
219 struct param_opt *param_opt;
221 char dummy[3]; /* for alignment */
225 /* This is a default service used to prime a services structure */
226 struct loadparm_service sDefault = {
231 .szPrintername = NULL,
232 .szHostsallow = NULL,
237 .ntvfs_handler = NULL,
238 .iMaxPrintJobs = 1000,
239 .iMaxConnections = 0,
245 .bMap_system = false,
246 .bMap_hidden = false,
247 .bMap_archive = true,
248 .bStrictLocking = true,
249 .iCreate_mask = 0744,
250 .iCreate_force_mode = 0000,
252 .iDir_force_mode = 0000,
255 .bStrictSync = false,
256 .bCIFileSystem = false,
259 /* local variables */
260 struct loadparm_context {
261 struct loadparm_global *globals;
262 struct loadparm_service **services;
264 struct loadparm_service *currentService;
265 bool bInGlobalSection;
267 struct file_lists *next;
274 struct loadparm_context *global_loadparm = NULL;
276 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
278 /* prototypes for the special type handlers */
279 static bool handle_include(struct loadparm_context *lp_ctx,
280 const char *pszParmValue, char **ptr);
281 static bool handle_copy(struct loadparm_context *lp_ctx,
282 const char *pszParmValue, char **ptr);
283 static bool handle_debuglevel(struct loadparm_context *lp_ctx,
284 const char *pszParmValue, char **ptr);
285 static bool handle_logfile(struct loadparm_context *lp_ctx,
286 const char *pszParmValue, char **ptr);
288 static const struct enum_list enum_protocol[] = {
289 {PROTOCOL_SMB2, "SMB2"},
290 {PROTOCOL_NT1, "NT1"},
291 {PROTOCOL_LANMAN2, "LANMAN2"},
292 {PROTOCOL_LANMAN1, "LANMAN1"},
293 {PROTOCOL_CORE, "CORE"},
294 {PROTOCOL_COREPLUS, "COREPLUS"},
295 {PROTOCOL_COREPLUS, "CORE+"},
299 static const struct enum_list enum_security[] = {
300 {SEC_SHARE, "SHARE"},
305 static const struct enum_list enum_announce_as[] = {
306 {ANNOUNCE_AS_NT_SERVER, "NT"},
307 {ANNOUNCE_AS_NT_SERVER, "NT Server"},
308 {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"},
309 {ANNOUNCE_AS_WIN95, "win95"},
310 {ANNOUNCE_AS_WFW, "WfW"},
314 static const struct enum_list enum_bool_auto[] = {
325 /* Client-side offline caching policy types */
328 CSC_POLICY_DOCUMENTS=1,
329 CSC_POLICY_PROGRAMS=2,
333 static const struct enum_list enum_csc_policy[] = {
334 {CSC_POLICY_MANUAL, "manual"},
335 {CSC_POLICY_DOCUMENTS, "documents"},
336 {CSC_POLICY_PROGRAMS, "programs"},
337 {CSC_POLICY_DISABLE, "disable"},
341 /* SMB signing types. */
342 static const struct enum_list enum_smb_signing_vals[] = {
343 {SMB_SIGNING_OFF, "No"},
344 {SMB_SIGNING_OFF, "False"},
345 {SMB_SIGNING_OFF, "0"},
346 {SMB_SIGNING_OFF, "Off"},
347 {SMB_SIGNING_OFF, "disabled"},
348 {SMB_SIGNING_SUPPORTED, "Yes"},
349 {SMB_SIGNING_SUPPORTED, "True"},
350 {SMB_SIGNING_SUPPORTED, "1"},
351 {SMB_SIGNING_SUPPORTED, "On"},
352 {SMB_SIGNING_SUPPORTED, "enabled"},
353 {SMB_SIGNING_REQUIRED, "required"},
354 {SMB_SIGNING_REQUIRED, "mandatory"},
355 {SMB_SIGNING_REQUIRED, "force"},
356 {SMB_SIGNING_REQUIRED, "forced"},
357 {SMB_SIGNING_REQUIRED, "enforced"},
358 {SMB_SIGNING_AUTO, "auto"},
362 static const struct enum_list enum_server_role[] = {
363 {ROLE_STANDALONE, "standalone"},
364 {ROLE_DOMAIN_MEMBER, "member server"},
365 {ROLE_DOMAIN_CONTROLLER, "domain controller"},
370 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
372 * Note: We have a flag called FLAG_DEVELOPER but is not used at this time, it
373 * is implied in current control logic. This may change at some later time. A
374 * flag value of 0 means - show as development option only.
376 * The FLAG_HIDE is explicit. Parameters set this way do NOT appear in any edit
377 * screen in SWAT. This is used to exclude parameters as well as to squash all
378 * parameters that have been duplicated by pseudonyms.
381 #define GLOBAL_VAR(name) offsetof(struct loadparm_global, name)
382 #define LOCAL_VAR(name) offsetof(struct loadparm_service, name)
384 static struct parm_struct parm_table[] = {
385 {"config file", P_STRING, P_GLOBAL, GLOBAL_VAR(szConfigFile), NULL, NULL, FLAG_HIDE},
387 {"server role", P_ENUM, P_GLOBAL, GLOBAL_VAR(server_role), NULL, enum_server_role, FLAG_BASIC},
389 {"dos charset", P_STRING, P_GLOBAL, GLOBAL_VAR(dos_charset), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
390 {"unix charset", P_STRING, P_GLOBAL, GLOBAL_VAR(unix_charset), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
391 {"ncalrpc dir", P_STRING, P_GLOBAL, GLOBAL_VAR(ncalrpc_dir), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
392 {"display charset", P_STRING, P_GLOBAL, GLOBAL_VAR(display_charset), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
393 {"comment", P_STRING, P_LOCAL, LOCAL_VAR(comment), NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
394 {"path", P_STRING, P_LOCAL, LOCAL_VAR(szPath), NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
395 {"directory", P_STRING, P_LOCAL, LOCAL_VAR(szPath), NULL, NULL, FLAG_HIDE},
396 {"workgroup", P_USTRING, P_GLOBAL, GLOBAL_VAR(szWorkgroup), NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
397 {"realm", P_STRING, P_GLOBAL, GLOBAL_VAR(szRealm), NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
398 {"netbios name", P_USTRING, P_GLOBAL, GLOBAL_VAR(szNetbiosName), NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
399 {"netbios aliases", P_LIST, P_GLOBAL, GLOBAL_VAR(szNetbiosAliases), NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
400 {"netbios scope", P_USTRING, P_GLOBAL, GLOBAL_VAR(szNetbiosScope), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
401 {"server string", P_STRING, P_GLOBAL, GLOBAL_VAR(szServerString), NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
402 {"interfaces", P_LIST, P_GLOBAL, GLOBAL_VAR(szInterfaces), NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
403 {"bind interfaces only", P_BOOL, P_GLOBAL, GLOBAL_VAR(bBindInterfacesOnly), NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
404 {"ntvfs handler", P_LIST, P_LOCAL, LOCAL_VAR(ntvfs_handler), NULL, NULL, FLAG_ADVANCED},
405 {"ntptr providor", P_STRING, P_GLOBAL, GLOBAL_VAR(ntptr_providor), NULL, NULL, FLAG_ADVANCED},
406 {"dcerpc endpoint servers", P_LIST, P_GLOBAL, GLOBAL_VAR(dcerpc_ep_servers), NULL, NULL, FLAG_ADVANCED},
407 {"server services", P_LIST, P_GLOBAL, GLOBAL_VAR(server_services), NULL, NULL, FLAG_ADVANCED},
409 {"security", P_ENUM, P_GLOBAL, GLOBAL_VAR(security), NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
410 {"encrypt passwords", P_BOOL, P_GLOBAL, GLOBAL_VAR(bEncryptPasswords), NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
411 {"null passwords", P_BOOL, P_GLOBAL, GLOBAL_VAR(bNullPasswords), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
412 {"obey pam restrictions", P_BOOL, P_GLOBAL, GLOBAL_VAR(bObeyPamRestrictions), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
413 {"password server", P_LIST, P_GLOBAL, GLOBAL_VAR(szPasswordServers), NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
414 {"sam database", P_STRING, P_GLOBAL, GLOBAL_VAR(szSAM_URL), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
415 {"secrets database", P_STRING, P_GLOBAL, GLOBAL_VAR(szSECRETS_URL), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
416 {"spoolss database", P_STRING, P_GLOBAL, GLOBAL_VAR(szSPOOLSS_URL), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
417 {"wins config database", P_STRING, P_GLOBAL, GLOBAL_VAR(szWINS_CONFIG_URL), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
418 {"wins database", P_STRING, P_GLOBAL, GLOBAL_VAR(szWINS_URL), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
419 {"private dir", P_STRING, P_GLOBAL, GLOBAL_VAR(szPrivateDir), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
420 {"passwd chat", P_STRING, P_GLOBAL, GLOBAL_VAR(szPasswdChat), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
421 {"password level", P_INTEGER, P_GLOBAL, GLOBAL_VAR(pwordlevel), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
422 {"lanman auth", P_BOOL, P_GLOBAL, GLOBAL_VAR(bLanmanAuth), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
423 {"ntlm auth", P_BOOL, P_GLOBAL, GLOBAL_VAR(bNTLMAuth), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
424 {"client NTLMv2 auth", P_BOOL, P_GLOBAL, GLOBAL_VAR(bClientNTLMv2Auth), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
425 {"client lanman auth", P_BOOL, P_GLOBAL, GLOBAL_VAR(bClientLanManAuth), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
426 {"client plaintext auth", P_BOOL, P_GLOBAL, GLOBAL_VAR(bClientPlaintextAuth), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
427 {"client use spnego principal", P_BOOL, P_GLOBAL, GLOBAL_VAR(client_use_spnego_principal), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
429 {"read only", P_BOOL, P_LOCAL, LOCAL_VAR(bRead_only), NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE},
431 {"create mask", P_OCTAL, P_LOCAL, LOCAL_VAR(iCreate_mask), NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
432 {"force create mode", P_OCTAL, P_LOCAL, LOCAL_VAR(iCreate_force_mode), NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
433 {"directory mask", P_OCTAL, P_LOCAL, LOCAL_VAR(iDir_mask), NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
434 {"force directory mode", P_OCTAL, P_LOCAL, LOCAL_VAR(iDir_force_mode), NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
436 {"hosts allow", P_LIST, P_LOCAL, LOCAL_VAR(szHostsallow), NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
437 {"hosts deny", P_LIST, P_LOCAL, LOCAL_VAR(szHostsdeny), NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
439 {"log level", P_INTEGER, P_GLOBAL, GLOBAL_VAR(debuglevel), handle_debuglevel, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
440 {"debuglevel", P_INTEGER, P_GLOBAL, GLOBAL_VAR(debuglevel), handle_debuglevel, NULL, FLAG_HIDE},
441 {"log file", P_STRING, P_GLOBAL, GLOBAL_VAR(logfile), handle_logfile, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
443 {"smb ports", P_LIST, P_GLOBAL, GLOBAL_VAR(smb_ports), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
444 {"nbt port", P_INTEGER, P_GLOBAL, GLOBAL_VAR(nbt_port), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
445 {"dgram port", P_INTEGER, P_GLOBAL, GLOBAL_VAR(dgram_port), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
446 {"cldap port", P_INTEGER, P_GLOBAL, GLOBAL_VAR(cldap_port), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
447 {"krb5 port", P_INTEGER, P_GLOBAL, GLOBAL_VAR(krb5_port), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
448 {"kpasswd port", P_INTEGER, P_GLOBAL, GLOBAL_VAR(kpasswd_port), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
449 {"web port", P_INTEGER, P_GLOBAL, GLOBAL_VAR(web_port), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
450 {"tls enabled", P_BOOL, P_GLOBAL, GLOBAL_VAR(tls_enabled), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
451 {"tls keyfile", P_STRING, P_GLOBAL, GLOBAL_VAR(tls_keyfile), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
452 {"tls certfile", P_STRING, P_GLOBAL, GLOBAL_VAR(tls_certfile), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
453 {"tls cafile", P_STRING, P_GLOBAL, GLOBAL_VAR(tls_cafile), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
454 {"tls crlfile", P_STRING, P_GLOBAL, GLOBAL_VAR(tls_crlfile), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
455 {"tls dh params file", P_STRING, P_GLOBAL, GLOBAL_VAR(tls_dhpfile), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
456 {"swat directory", P_STRING, P_GLOBAL, GLOBAL_VAR(swat_directory), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
457 {"large readwrite", P_BOOL, P_GLOBAL, GLOBAL_VAR(bLargeReadwrite), NULL, NULL, FLAG_DEVELOPER},
458 {"server max protocol", P_ENUM, P_GLOBAL, GLOBAL_VAR(srv_maxprotocol), NULL, enum_protocol, FLAG_DEVELOPER},
459 {"server min protocol", P_ENUM, P_GLOBAL, GLOBAL_VAR(srv_minprotocol), NULL, enum_protocol, FLAG_DEVELOPER},
460 {"client max protocol", P_ENUM, P_GLOBAL, GLOBAL_VAR(cli_maxprotocol), NULL, enum_protocol, FLAG_DEVELOPER},
461 {"client min protocol", P_ENUM, P_GLOBAL, GLOBAL_VAR(cli_minprotocol), NULL, enum_protocol, FLAG_DEVELOPER},
462 {"unicode", P_BOOL, P_GLOBAL, GLOBAL_VAR(bUnicode), NULL, NULL, FLAG_DEVELOPER},
463 {"read raw", P_BOOL, P_GLOBAL, GLOBAL_VAR(bReadRaw), NULL, NULL, FLAG_DEVELOPER},
464 {"write raw", P_BOOL, P_GLOBAL, GLOBAL_VAR(bWriteRaw), NULL, NULL, FLAG_DEVELOPER},
465 {"disable netbios", P_BOOL, P_GLOBAL, GLOBAL_VAR(bDisableNetbios), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
467 {"nt status support", P_BOOL, P_GLOBAL, GLOBAL_VAR(bNTStatusSupport), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
469 {"announce version", P_STRING, P_GLOBAL, GLOBAL_VAR(szAnnounceVersion), NULL, NULL, FLAG_DEVELOPER},
470 {"announce as", P_ENUM, P_GLOBAL, GLOBAL_VAR(announce_as), NULL, enum_announce_as, FLAG_DEVELOPER},
471 {"max mux", P_INTEGER, P_GLOBAL, GLOBAL_VAR(max_mux), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
472 {"max xmit", P_BYTES, P_GLOBAL, GLOBAL_VAR(max_xmit), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
474 {"name resolve order", P_LIST, P_GLOBAL, GLOBAL_VAR(szNameResolveOrder), NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
475 {"max wins ttl", P_INTEGER, P_GLOBAL, GLOBAL_VAR(max_wins_ttl), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
476 {"min wins ttl", P_INTEGER, P_GLOBAL, GLOBAL_VAR(min_wins_ttl), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
477 {"time server", P_BOOL, P_GLOBAL, GLOBAL_VAR(bTimeServer), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
478 {"unix extensions", P_BOOL, P_GLOBAL, GLOBAL_VAR(bUnixExtensions), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
479 {"use spnego", P_BOOL, P_GLOBAL, GLOBAL_VAR(bUseSpnego), NULL, NULL, FLAG_DEVELOPER},
480 {"server signing", P_ENUM, P_GLOBAL, GLOBAL_VAR(server_signing), NULL, enum_smb_signing_vals, FLAG_ADVANCED},
481 {"client signing", P_ENUM, P_GLOBAL, GLOBAL_VAR(client_signing), NULL, enum_smb_signing_vals, FLAG_ADVANCED},
482 {"rpc big endian", P_BOOL, P_GLOBAL, GLOBAL_VAR(bRpcBigEndian), NULL, NULL, FLAG_DEVELOPER},
484 {"max connections", P_INTEGER, P_LOCAL, LOCAL_VAR(iMaxConnections), NULL, NULL, FLAG_SHARE},
485 {"paranoid server security", P_BOOL, P_GLOBAL, GLOBAL_VAR(paranoid_server_security), NULL, NULL, FLAG_DEVELOPER},
486 {"socket options", P_STRING, P_GLOBAL, GLOBAL_VAR(socket_options), NULL, NULL, FLAG_DEVELOPER},
488 {"strict sync", P_BOOL, P_LOCAL, LOCAL_VAR(bStrictSync), NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
489 {"case insensitive filesystem", P_BOOL, P_LOCAL, LOCAL_VAR(bCIFileSystem), NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
491 {"max print jobs", P_INTEGER, P_LOCAL, LOCAL_VAR(iMaxPrintJobs), NULL, NULL, FLAG_PRINT},
492 {"printable", P_BOOL, P_LOCAL, LOCAL_VAR(bPrint_ok), NULL, NULL, FLAG_PRINT},
493 {"print ok", P_BOOL, P_LOCAL, LOCAL_VAR(bPrint_ok), NULL, NULL, FLAG_HIDE},
495 {"printer name", P_STRING, P_LOCAL, LOCAL_VAR(szPrintername), NULL, NULL, FLAG_PRINT},
496 {"printer", P_STRING, P_LOCAL, LOCAL_VAR(szPrintername), NULL, NULL, FLAG_HIDE},
498 {"map system", P_BOOL, P_LOCAL, LOCAL_VAR(bMap_system), NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
499 {"map hidden", P_BOOL, P_LOCAL, LOCAL_VAR(bMap_hidden), NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
500 {"map archive", P_BOOL, P_LOCAL, LOCAL_VAR(bMap_archive), NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
502 {"preferred master", P_ENUM, P_GLOBAL, GLOBAL_VAR(bPreferredMaster), NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
503 {"prefered master", P_ENUM, P_GLOBAL, GLOBAL_VAR(bPreferredMaster), NULL, enum_bool_auto, FLAG_HIDE},
504 {"local master", P_BOOL, P_GLOBAL, GLOBAL_VAR(bLocalMaster), NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
505 {"browseable", P_BOOL, P_LOCAL, LOCAL_VAR(bBrowseable), NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
506 {"browsable", P_BOOL, P_LOCAL, LOCAL_VAR(bBrowseable), NULL, NULL, FLAG_HIDE},
508 {"wins server", P_LIST, P_GLOBAL, GLOBAL_VAR(szWINSservers), NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
509 {"wins support", P_BOOL, P_GLOBAL, GLOBAL_VAR(bWINSsupport), NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
510 {"dns proxy", P_BOOL, P_GLOBAL, GLOBAL_VAR(bWINSdnsProxy), NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
511 {"wins hook", P_STRING, P_GLOBAL, GLOBAL_VAR(szWINSHook), NULL, NULL, FLAG_ADVANCED},
513 {"csc policy", P_ENUM, P_LOCAL, LOCAL_VAR(iCSCPolicy), NULL, enum_csc_policy, FLAG_SHARE | FLAG_GLOBAL},
515 {"strict locking", P_BOOL, P_LOCAL, LOCAL_VAR(bStrictLocking), NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
517 {"share backend", P_STRING, P_GLOBAL, GLOBAL_VAR(szShareBackend), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
518 {"preload", P_STRING, P_GLOBAL, GLOBAL_VAR(szAutoServices), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
519 {"auto services", P_STRING, P_GLOBAL, GLOBAL_VAR(szAutoServices), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
520 {"lock dir", P_STRING, P_GLOBAL, GLOBAL_VAR(szLockDir), NULL, NULL, FLAG_HIDE},
521 {"lock directory", P_STRING, P_GLOBAL, GLOBAL_VAR(szLockDir), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
522 {"modules dir", P_STRING, P_GLOBAL, GLOBAL_VAR(szModulesDir), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
523 {"pid directory", P_STRING, P_GLOBAL, GLOBAL_VAR(szPidDir), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
524 {"js include", P_LIST, P_GLOBAL, GLOBAL_VAR(jsInclude), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
525 {"setup directory", P_STRING, P_GLOBAL, GLOBAL_VAR(szSetupDir), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
527 {"socket address", P_STRING, P_GLOBAL, GLOBAL_VAR(szSocketAddress), NULL, NULL, FLAG_DEVELOPER},
528 {"copy", P_STRING, P_LOCAL, LOCAL_VAR(szCopy), handle_copy, NULL, FLAG_HIDE},
529 {"include", P_STRING, P_LOCAL, LOCAL_VAR(szInclude), handle_include, NULL, FLAG_HIDE},
531 {"available", P_BOOL, P_LOCAL, LOCAL_VAR(bAvailable), NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
532 {"volume", P_STRING, P_LOCAL, LOCAL_VAR(volume), NULL, NULL, FLAG_SHARE },
533 {"fstype", P_STRING, P_LOCAL, LOCAL_VAR(fstype), NULL, NULL, FLAG_SHARE},
535 {"panic action", P_STRING, P_GLOBAL, GLOBAL_VAR(panic_action), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
537 {"msdfs root", P_BOOL, P_LOCAL, LOCAL_VAR(bMSDfsRoot), NULL, NULL, FLAG_SHARE},
538 {"host msdfs", P_BOOL, P_GLOBAL, GLOBAL_VAR(bHostMSDfs), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
539 {"winbind separator", P_STRING, P_GLOBAL, GLOBAL_VAR(szWinbindSeparator), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
540 {"winbindd socket directory", P_STRING, P_GLOBAL, GLOBAL_VAR(szWinbinddSocketDirectory), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
541 {"winbind sealed pipes", P_BOOL, P_GLOBAL, GLOBAL_VAR(bWinbindSealedPipes), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
542 {"template shell", P_STRING, P_GLOBAL, GLOBAL_VAR(szTemplateShell), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
543 {"template homedir", P_STRING, P_GLOBAL, GLOBAL_VAR(szTemplateHomedir), NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
545 {NULL, P_BOOL, P_NONE, 0, NULL, NULL, 0}
550 return the parameter table
552 struct parm_struct *lp_parm_table(void)
557 /*******************************************************************
558 Convenience routine to grab string parameters into temporary memory
559 and run standard_sub_basic on them. The buffers can be written to by
560 callers without affecting the source string.
561 ********************************************************************/
563 static const char *lp_string(const char *s)
565 #if 0 /* until REWRITE done to make thread-safe */
566 size_t len = s ? strlen(s) : 0;
570 /* The follow debug is useful for tracking down memory problems
571 especially if you have an inner loop that is calling a lp_*()
572 function that returns a string. Perhaps this debug should be
573 present all the time? */
576 DEBUG(10, ("lp_string(%s)\n", s));
579 #if 0 /* until REWRITE done to make thread-safe */
581 lp_talloc = talloc_init("lp_talloc");
583 ret = talloc_array(lp_talloc, char, len + 100); /* leave room for substitution */
591 strlcpy(ret, s, len);
593 if (trim_string(ret, "\"", "\"")) {
594 if (strchr(ret,'"') != NULL)
595 strlcpy(ret, s, len);
598 standard_sub_basic(ret,len+100);
605 In this section all the functions that are used to access the
606 parameters from the rest of the program are defined
609 #define FN_GLOBAL_STRING(fn_name,var_name) \
610 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) : "";}
611 #define FN_GLOBAL_CONST_STRING(fn_name,var_name) \
612 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 : "";}
613 #define FN_GLOBAL_LIST(fn_name,var_name) \
614 const char **fn_name(struct loadparm_context *lp_ctx) {if (lp_ctx == NULL) return NULL; return lp_ctx->globals->var_name;}
615 #define FN_GLOBAL_BOOL(fn_name,var_name) \
616 bool fn_name(struct loadparm_context *lp_ctx) {if (lp_ctx == NULL) return false; return lp_ctx->globals->var_name;}
618 #define FN_GLOBAL_CHAR(fn_name,ptr) \
619 char fn_name(void) {return(*(char *)(ptr));}
621 #define FN_GLOBAL_INTEGER(fn_name,var_name) \
622 int fn_name(struct loadparm_context *lp_ctx) {if (lp_ctx == NULL) return 0; return lp_ctx->globals->var_name;}
624 #define FN_LOCAL_STRING(fn_name,val) \
625 const char *fn_name(struct loadparm_service *service) {return(lp_string((const char *)((service != NULL && service->val != NULL) ? service->val : sDefault.val)));}
626 #define FN_LOCAL_CONST_STRING(fn_name,val) \
627 const char *fn_name(struct loadparm_service *service) {return (const char *)(service != NULL && service->val != NULL) ? service->val : sDefault.val;}
628 #define FN_LOCAL_LIST(fn_name,val) \
629 const char **fn_name(struct loadparm_service *service) {return(const char **)(service != NULL && service->val != NULL? service->val : sDefault.val);}
630 #define FN_LOCAL_BOOL(fn_name,val) \
631 bool fn_name(struct loadparm_service *service) {return((service != NULL)? service->val : sDefault.val);}
632 #define FN_LOCAL_INTEGER(fn_name,val) \
633 int fn_name(struct loadparm_service *service) {return((service != NULL)? service->val : sDefault.val);}
635 _PUBLIC_ FN_GLOBAL_INTEGER(lp_server_role, server_role)
636 _PUBLIC_ FN_GLOBAL_LIST(lp_smb_ports, smb_ports)
637 _PUBLIC_ FN_GLOBAL_INTEGER(lp_nbt_port, nbt_port)
638 _PUBLIC_ FN_GLOBAL_INTEGER(lp_dgram_port, dgram_port)
639 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cldap_port, cldap_port)
640 _PUBLIC_ FN_GLOBAL_INTEGER(lp_krb5_port, krb5_port)
641 _PUBLIC_ FN_GLOBAL_INTEGER(lp_kpasswd_port, kpasswd_port)
642 _PUBLIC_ FN_GLOBAL_INTEGER(lp_web_port, web_port)
643 _PUBLIC_ FN_GLOBAL_STRING(lp_swat_directory, swat_directory)
644 _PUBLIC_ FN_GLOBAL_BOOL(lp_tls_enabled, tls_enabled)
645 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_keyfile, tls_keyfile)
646 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_certfile, tls_certfile)
647 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_cafile, tls_cafile)
648 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_crlfile, tls_crlfile)
649 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_dhpfile, tls_dhpfile)
650 _PUBLIC_ FN_GLOBAL_STRING(lp_share_backend, szShareBackend)
651 _PUBLIC_ FN_GLOBAL_STRING(lp_sam_url, szSAM_URL)
652 _PUBLIC_ FN_GLOBAL_STRING(lp_secrets_url, szSECRETS_URL)
653 _PUBLIC_ FN_GLOBAL_STRING(lp_spoolss_url, szSPOOLSS_URL)
654 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_config_url, szWINS_CONFIG_URL)
655 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_url, szWINS_URL)
656 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_winbind_separator, szWinbindSeparator)
657 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_winbindd_socket_directory, szWinbinddSocketDirectory)
658 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_template_shell, szTemplateShell)
659 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_template_homedir, szTemplateHomedir)
660 _PUBLIC_ FN_GLOBAL_BOOL(lp_winbind_sealed_pipes, bWinbindSealedPipes)
661 _PUBLIC_ FN_GLOBAL_STRING(lp_private_dir, szPrivateDir)
662 _PUBLIC_ FN_GLOBAL_STRING(lp_serverstring, szServerString)
663 _PUBLIC_ FN_GLOBAL_STRING(lp_lockdir, szLockDir)
664 _PUBLIC_ FN_GLOBAL_STRING(lp_modulesdir, szModulesDir)
665 _PUBLIC_ FN_GLOBAL_STRING(lp_setupdir, szSetupDir)
666 _PUBLIC_ FN_GLOBAL_STRING(lp_ncalrpc_dir, ncalrpc_dir)
667 _PUBLIC_ FN_GLOBAL_STRING(lp_dos_charset, dos_charset)
668 _PUBLIC_ FN_GLOBAL_STRING(lp_unix_charset, unix_charset)
669 _PUBLIC_ FN_GLOBAL_STRING(lp_display_charset, display_charset)
670 _PUBLIC_ FN_GLOBAL_STRING(lp_piddir, szPidDir)
671 _PUBLIC_ FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, dcerpc_ep_servers)
672 _PUBLIC_ FN_GLOBAL_LIST(lp_server_services, server_services)
673 _PUBLIC_ FN_GLOBAL_STRING(lp_ntptr_providor, ntptr_providor)
674 _PUBLIC_ FN_GLOBAL_STRING(lp_auto_services, szAutoServices)
675 _PUBLIC_ FN_GLOBAL_STRING(lp_passwd_chat, szPasswdChat)
676 _PUBLIC_ FN_GLOBAL_LIST(lp_passwordserver, szPasswordServers)
677 _PUBLIC_ FN_GLOBAL_LIST(lp_name_resolve_order, szNameResolveOrder)
678 _PUBLIC_ FN_GLOBAL_STRING(lp_realm, szRealm)
679 _PUBLIC_ FN_GLOBAL_STRING(lp_socket_options, socket_options)
680 _PUBLIC_ FN_GLOBAL_STRING(lp_workgroup, szWorkgroup)
681 _PUBLIC_ FN_GLOBAL_STRING(lp_netbios_name, szNetbiosName)
682 _PUBLIC_ FN_GLOBAL_STRING(lp_netbios_scope, szNetbiosScope)
683 _PUBLIC_ FN_GLOBAL_LIST(lp_wins_server_list, szWINSservers)
684 _PUBLIC_ FN_GLOBAL_LIST(lp_interfaces, szInterfaces)
685 _PUBLIC_ FN_GLOBAL_STRING(lp_socket_address, szSocketAddress)
686 _PUBLIC_ FN_GLOBAL_LIST(lp_netbios_aliases, szNetbiosAliases)
688 _PUBLIC_ FN_GLOBAL_BOOL(lp_disable_netbios, bDisableNetbios)
689 _PUBLIC_ FN_GLOBAL_BOOL(lp_wins_support, bWINSsupport)
690 _PUBLIC_ FN_GLOBAL_BOOL(lp_wins_dns_proxy, bWINSdnsProxy)
691 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_hook, szWINSHook)
692 _PUBLIC_ FN_GLOBAL_STRING(lp_configfile, szConfigFile)
693 _PUBLIC_ FN_GLOBAL_BOOL(lp_local_master, bLocalMaster)
694 _PUBLIC_ FN_GLOBAL_BOOL(lp_readraw, bReadRaw)
695 _PUBLIC_ FN_GLOBAL_BOOL(lp_large_readwrite, bLargeReadwrite)
696 _PUBLIC_ FN_GLOBAL_BOOL(lp_writeraw, bWriteRaw)
697 _PUBLIC_ FN_GLOBAL_BOOL(lp_null_passwords, bNullPasswords)
698 _PUBLIC_ FN_GLOBAL_BOOL(lp_obey_pam_restrictions, bObeyPamRestrictions)
699 _PUBLIC_ FN_GLOBAL_BOOL(lp_encrypted_passwords, bEncryptPasswords)
700 _PUBLIC_ FN_GLOBAL_BOOL(lp_time_server, bTimeServer)
701 _PUBLIC_ FN_GLOBAL_BOOL(lp_bind_interfaces_only, bBindInterfacesOnly)
702 _PUBLIC_ FN_GLOBAL_BOOL(lp_unicode, bUnicode)
703 _PUBLIC_ FN_GLOBAL_BOOL(lp_nt_status_support, bNTStatusSupport)
704 _PUBLIC_ FN_GLOBAL_BOOL(lp_lanman_auth, bLanmanAuth)
705 _PUBLIC_ FN_GLOBAL_BOOL(lp_ntlm_auth, bNTLMAuth)
706 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_plaintext_auth, bClientPlaintextAuth)
707 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_lanman_auth, bClientLanManAuth)
708 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, bClientNTLMv2Auth)
709 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_use_spnego_principal, client_use_spnego_principal)
710 _PUBLIC_ FN_GLOBAL_BOOL(lp_host_msdfs, bHostMSDfs)
711 _PUBLIC_ FN_GLOBAL_BOOL(lp_unix_extensions, bUnixExtensions)
712 _PUBLIC_ FN_GLOBAL_BOOL(lp_use_spnego, bUseSpnego)
713 _PUBLIC_ FN_GLOBAL_BOOL(lp_rpc_big_endian, bRpcBigEndian)
714 _PUBLIC_ FN_GLOBAL_INTEGER(lp_max_wins_ttl, max_wins_ttl)
715 _PUBLIC_ FN_GLOBAL_INTEGER(lp_min_wins_ttl, min_wins_ttl)
716 _PUBLIC_ FN_GLOBAL_INTEGER(lp_maxmux, max_mux)
717 _PUBLIC_ FN_GLOBAL_INTEGER(lp_max_xmit, max_xmit)
718 _PUBLIC_ FN_GLOBAL_INTEGER(lp_passwordlevel, pwordlevel)
719 _PUBLIC_ FN_GLOBAL_INTEGER(lp_srv_maxprotocol, srv_maxprotocol)
720 _PUBLIC_ FN_GLOBAL_INTEGER(lp_srv_minprotocol, srv_minprotocol)
721 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cli_maxprotocol, cli_maxprotocol)
722 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cli_minprotocol, cli_minprotocol)
723 _PUBLIC_ FN_GLOBAL_INTEGER(lp_security, security)
724 _PUBLIC_ FN_GLOBAL_BOOL(lp_paranoid_server_security, paranoid_server_security)
725 _PUBLIC_ FN_GLOBAL_INTEGER(lp_announce_as, announce_as)
726 _PUBLIC_ FN_GLOBAL_LIST(lp_js_include, jsInclude)
727 _PUBLIC_ FN_LOCAL_STRING(lp_servicename, szService)
728 _PUBLIC_ FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
729 _PUBLIC_ FN_LOCAL_STRING(lp_pathname, szPath)
730 static FN_LOCAL_STRING(_lp_printername, szPrintername)
731 _PUBLIC_ FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
732 _PUBLIC_ FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
733 _PUBLIC_ FN_LOCAL_STRING(lp_comment, comment)
734 _PUBLIC_ FN_LOCAL_STRING(lp_fstype, fstype)
735 static FN_LOCAL_STRING(lp_volume, volume)
736 _PUBLIC_ FN_LOCAL_LIST(lp_ntvfs_handler, ntvfs_handler)
737 _PUBLIC_ FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
738 _PUBLIC_ FN_LOCAL_BOOL(lp_browseable, bBrowseable)
739 _PUBLIC_ FN_LOCAL_BOOL(lp_readonly, bRead_only)
740 _PUBLIC_ FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
741 _PUBLIC_ FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
742 _PUBLIC_ FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
743 _PUBLIC_ FN_LOCAL_BOOL(lp_strict_locking, bStrictLocking)
744 _PUBLIC_ FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
745 _PUBLIC_ FN_LOCAL_BOOL(lp_ci_filesystem, bCIFileSystem)
746 _PUBLIC_ FN_LOCAL_BOOL(lp_map_system, bMap_system)
747 _PUBLIC_ FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
748 _PUBLIC_ FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
749 _PUBLIC_ FN_LOCAL_INTEGER(lp_create_mask, iCreate_mask)
750 _PUBLIC_ FN_LOCAL_INTEGER(lp_force_create_mode, iCreate_force_mode)
751 _PUBLIC_ FN_LOCAL_INTEGER(lp_dir_mask, iDir_mask)
752 _PUBLIC_ FN_LOCAL_INTEGER(lp_force_dir_mode, iDir_force_mode)
753 _PUBLIC_ FN_GLOBAL_INTEGER(lp_server_signing, server_signing)
754 _PUBLIC_ FN_GLOBAL_INTEGER(lp_client_signing, client_signing)
756 /* local prototypes */
757 static int map_parameter(const char *pszParmName);
758 static struct loadparm_service *getservicebyname(struct loadparm_context *lp_ctx,
759 const char *pszServiceName);
760 static void copy_service(struct loadparm_service *pserviceDest,
761 struct loadparm_service *pserviceSource,
763 static bool service_ok(struct loadparm_service *service);
764 static bool do_section(const char *pszSectionName, void *);
765 static void init_copymap(struct loadparm_service *pservice);
767 /* This is a helper function for parametrical options support. */
768 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
769 /* Actual parametrical functions are quite simple */
770 const char *lp_get_parametric(struct loadparm_context *lp_ctx,
771 struct loadparm_service *service,
772 const char *type, const char *option)
775 struct param_opt *data;
777 data = (service == NULL ? lp_ctx->globals->param_opt : service->param_opt);
779 asprintf(&vfskey, "%s:%s", type, option);
783 if (strcmp(data->key, vfskey) == 0) {
790 if (service != NULL) {
791 /* Try to fetch the same option but from globals */
792 /* but only if we are not already working with globals */
793 for (data = lp_ctx->globals->param_opt; data;
795 if (strcmp(data->key, vfskey) == 0) {
808 /*******************************************************************
809 convenience routine to return int parameters.
810 ********************************************************************/
811 static int lp_int(const char *s)
815 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
819 return strtol(s, NULL, 0);
822 /*******************************************************************
823 convenience routine to return unsigned long parameters.
824 ********************************************************************/
825 static int lp_ulong(const char *s)
829 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
833 return strtoul(s, NULL, 0);
836 /*******************************************************************
837 convenience routine to return unsigned long parameters.
838 ********************************************************************/
839 static double lp_double(const char *s)
843 DEBUG(0,("lp_double(%s): is called with NULL!\n",s));
847 return strtod(s, NULL);
850 /*******************************************************************
851 convenience routine to return boolean parameters.
852 ********************************************************************/
853 static bool lp_bool(const char *s)
858 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
862 if (!set_boolean(s, &ret)) {
863 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
871 /* Return parametric option from a given service. Type is a part of option before ':' */
872 /* Parametric option has following syntax: 'Type: option = value' */
873 /* Returned value is allocated in 'lp_talloc' context */
875 const char *lp_parm_string(struct loadparm_context *lp_ctx,
876 struct loadparm_service *service, const char *type,
879 const char *value = lp_get_parametric(lp_ctx, service, type, option);
882 return lp_string(value);
887 /* Return parametric option from a given service. Type is a part of option before ':' */
888 /* Parametric option has following syntax: 'Type: option = value' */
889 /* Returned value is allocated in 'lp_talloc' context */
891 const char **lp_parm_string_list(TALLOC_CTX *mem_ctx,
892 struct loadparm_context *lp_ctx,
893 struct loadparm_service *service,
895 const char *option, const char *separator)
897 const char *value = lp_get_parametric(lp_ctx, service, type, option);
900 return str_list_make(mem_ctx, value, separator);
905 /* Return parametric option from a given service. Type is a part of option before ':' */
906 /* Parametric option has following syntax: 'Type: option = value' */
908 int lp_parm_int(struct loadparm_context *lp_ctx,
909 struct loadparm_service *service, const char *type,
910 const char *option, int default_v)
912 const char *value = lp_get_parametric(lp_ctx, service, type, option);
915 return lp_int(value);
920 /* Return parametric option from a given service. Type is a part of
922 * Parametric option has following syntax: 'Type: option = value'.
925 int lp_parm_bytes(struct loadparm_context *lp_ctx,
926 struct loadparm_service *service, const char *type,
927 const char *option, int default_v)
931 const char *value = lp_get_parametric(lp_ctx, service, type, option);
933 if (value && conv_str_size(value, &bval)) {
934 if (bval <= INT_MAX) {
942 /* Return parametric option from a given service. Type is a part of option before ':' */
943 /* Parametric option has following syntax: 'Type: option = value' */
945 unsigned long lp_parm_ulong(struct loadparm_context *lp_ctx,
946 struct loadparm_service *service, const char *type,
947 const char *option, unsigned long default_v)
949 const char *value = lp_get_parametric(lp_ctx, service, type, option);
952 return lp_ulong(value);
958 double lp_parm_double(struct loadparm_context *lp_ctx,
959 struct loadparm_service *service, const char *type,
960 const char *option, double default_v)
962 const char *value = lp_get_parametric(lp_ctx, service, type, option);
965 return lp_double(value);
970 /* Return parametric option from a given service. Type is a part of option before ':' */
971 /* Parametric option has following syntax: 'Type: option = value' */
973 bool lp_parm_bool(struct loadparm_context *lp_ctx,
974 struct loadparm_service *service, const char *type,
975 const char *option, bool default_v)
977 const char *value = lp_get_parametric(lp_ctx, service, type, option);
980 return lp_bool(value);
986 /***************************************************************************
987 Initialise a service to the defaults.
988 ***************************************************************************/
990 static struct loadparm_service *init_service(TALLOC_CTX *mem_ctx)
992 struct loadparm_service *pservice =
993 talloc_zero(mem_ctx, struct loadparm_service);
994 copy_service(pservice, &sDefault, NULL);
999 Set a string value, deallocating any existing space, and allocing the space
1002 static bool string_set(TALLOC_CTX *mem_ctx, char **dest, const char *src)
1009 *dest = talloc_strdup(mem_ctx, src);
1010 if ((*dest) == NULL) {
1011 DEBUG(0,("Out of memory in string_init\n"));
1020 /***************************************************************************
1021 Add a new service to the services array initialising it with the given
1023 ***************************************************************************/
1025 struct loadparm_service *lp_add_service(struct loadparm_context *lp_ctx,
1026 const struct loadparm_service *pservice,
1030 struct loadparm_service tservice;
1031 int num_to_alloc = lp_ctx->iNumServices + 1;
1032 struct param_opt *data, *pdata;
1034 tservice = *pservice;
1036 /* it might already exist */
1038 struct loadparm_service *service = getservicebyname(lp_ctx,
1040 if (service != NULL) {
1041 /* Clean all parametric options for service */
1042 /* They will be added during parsing again */
1043 data = service->param_opt;
1049 service->param_opt = NULL;
1054 /* find an invalid one */
1055 for (i = 0; i < lp_ctx->iNumServices; i++)
1056 if (lp_ctx->services[i] == NULL)
1059 /* if not, then create one */
1060 if (i == lp_ctx->iNumServices) {
1061 struct loadparm_service **tsp;
1063 tsp = talloc_realloc(lp_ctx, lp_ctx->services, struct loadparm_service *, num_to_alloc);
1066 DEBUG(0,("lp_add_service: failed to enlarge services!\n"));
1069 lp_ctx->services = tsp;
1070 lp_ctx->services[lp_ctx->iNumServices] = NULL;
1073 lp_ctx->iNumServices++;
1076 lp_ctx->services[i] = init_service(lp_ctx->services);
1077 if (lp_ctx->services[i] == NULL) {
1078 DEBUG(0,("lp_add_service: out of memory!\n"));
1081 copy_service(lp_ctx->services[i], &tservice, NULL);
1083 string_set(lp_ctx->services[i], &lp_ctx->services[i]->szService, name);
1084 return lp_ctx->services[i];
1087 /***************************************************************************
1088 Add a new home service, with the specified home directory, defaults coming
1090 ***************************************************************************/
1092 bool lp_add_home(struct loadparm_context *lp_ctx,
1093 const char *pszHomename,
1094 struct loadparm_service *default_service,
1095 const char *user, const char *pszHomedir)
1097 struct loadparm_service *service;
1099 service = lp_add_service(lp_ctx, default_service, pszHomename);
1101 if (service == NULL)
1104 if (!(*(default_service->szPath))
1105 || strequal(default_service->szPath, sDefault.szPath)) {
1106 service->szPath = talloc_strdup(service, pszHomedir);
1108 service->szPath = string_sub_talloc(service, lp_pathname(default_service),"%H", pszHomedir);
1111 if (!(*(service->comment))) {
1112 service->comment = talloc_asprintf(service, "Home directory of %s", user);
1114 service->bAvailable = default_service->bAvailable;
1115 service->bBrowseable = default_service->bBrowseable;
1117 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n",
1118 pszHomename, user, service->szPath));
1123 /***************************************************************************
1124 Add the IPC service.
1125 ***************************************************************************/
1127 static bool lp_add_hidden(struct loadparm_context *lp_ctx, const char *name,
1130 struct loadparm_service *service = lp_add_service(lp_ctx, &sDefault, name);
1132 if (service == NULL)
1135 string_set(service, &service->szPath, tmpdir());
1137 service->comment = talloc_asprintf(service, "%s Service (%s)",
1138 fstype, lp_ctx->globals->szServerString);
1139 string_set(service, &service->fstype, fstype);
1140 service->iMaxConnections = -1;
1141 service->bAvailable = true;
1142 service->bRead_only = true;
1143 service->bPrint_ok = false;
1144 service->bBrowseable = false;
1146 if (strcasecmp(fstype, "IPC") == 0) {
1147 lp_do_service_parameter(lp_ctx, service, "ntvfs handler",
1151 DEBUG(3, ("adding hidden service %s\n", name));
1156 /***************************************************************************
1157 Add a new printer service, with defaults coming from service iFrom.
1158 ***************************************************************************/
1160 bool lp_add_printer(struct loadparm_context *lp_ctx,
1161 const char *pszPrintername,
1162 struct loadparm_service *default_service)
1164 const char *comment = "From Printcap";
1165 struct loadparm_service *service;
1166 service = lp_add_service(lp_ctx, default_service, pszPrintername);
1168 if (service == NULL)
1171 /* note that we do NOT default the availability flag to True - */
1172 /* we take it from the default service passed. This allows all */
1173 /* dynamic printers to be disabled by disabling the [printers] */
1174 /* entry (if/when the 'available' keyword is implemented!). */
1176 /* the printer name is set to the service name. */
1177 string_set(service, &service->szPrintername, pszPrintername);
1178 string_set(service, &service->comment, comment);
1179 service->bBrowseable = default_service->bBrowseable;
1180 /* Printers cannot be read_only. */
1181 service->bRead_only = false;
1182 /* Printer services must be printable. */
1183 service->bPrint_ok = true;
1185 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1191 * Map a parameter's string representation to something we can use.
1192 * Returns False if the parameter string is not recognised, else TRUE.
1195 static int map_parameter(const char *pszParmName)
1199 if (*pszParmName == '-')
1202 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1203 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1206 /* Warn only if it isn't parametric option */
1207 if (strchr(pszParmName, ':') == NULL)
1208 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1209 /* We do return 'fail' for parametric options as well because they are
1210 stored in different storage
1217 return the parameter structure for a parameter
1219 struct parm_struct *lp_parm_struct(const char *name)
1221 int parmnum = map_parameter(name);
1222 if (parmnum == -1) return NULL;
1223 return &parm_table[parmnum];
1227 return the parameter pointer for a parameter
1229 void *lp_parm_ptr(struct loadparm_context *lp_ctx,
1230 struct loadparm_service *service, struct parm_struct *parm)
1232 if (service == NULL) {
1233 if (parm->class == P_LOCAL)
1234 return ((char *)&sDefault)+parm->offset;
1235 else if (parm->class == P_GLOBAL)
1236 return ((char *)lp_ctx->globals)+parm->offset;
1239 return ((char *)service) + parm->offset;
1243 /***************************************************************************
1244 Find a service by name. Otherwise works like get_service.
1245 ***************************************************************************/
1247 static struct loadparm_service *getservicebyname(struct loadparm_context *lp_ctx,
1248 const char *pszServiceName)
1252 for (iService = lp_ctx->iNumServices - 1; iService >= 0; iService--)
1253 if (lp_ctx->services[iService] != NULL &&
1254 strwicmp(lp_ctx->services[iService]->szService, pszServiceName) == 0) {
1255 return lp_ctx->services[iService];
1261 /***************************************************************************
1262 Copy a service structure to another.
1263 If pcopymapDest is NULL then copy all fields
1264 ***************************************************************************/
1266 static void copy_service(struct loadparm_service *pserviceDest,
1267 struct loadparm_service *pserviceSource,
1271 bool bcopyall = (pcopymapDest == NULL);
1272 struct param_opt *data, *pdata, *paramo;
1275 for (i = 0; parm_table[i].label; i++)
1276 if (parm_table[i].offset != -1 && parm_table[i].class == P_LOCAL &&
1277 (bcopyall || pcopymapDest[i])) {
1279 ((char *)pserviceSource) + parm_table[i].offset;
1281 ((char *)pserviceDest) + parm_table[i].offset;
1283 switch (parm_table[i].type) {
1285 *(int *)dest_ptr = *(int *)src_ptr;
1291 *(int *)dest_ptr = *(int *)src_ptr;
1295 string_set(pserviceDest,
1301 string_set(pserviceDest,
1304 strupper(*(char **)dest_ptr);
1307 *(const char ***)dest_ptr = str_list_copy(pserviceDest,
1308 *(const char ***)src_ptr);
1316 init_copymap(pserviceDest);
1317 if (pserviceSource->copymap)
1318 memcpy((void *)pserviceDest->copymap,
1319 (void *)pserviceSource->copymap,
1320 sizeof(int) * NUMPARAMETERS);
1323 data = pserviceSource->param_opt;
1326 pdata = pserviceDest->param_opt;
1327 /* Traverse destination */
1329 /* If we already have same option, override it */
1330 if (strcmp(pdata->key, data->key) == 0) {
1331 talloc_free(pdata->value);
1332 pdata->value = talloc_reference(pdata,
1337 pdata = pdata->next;
1340 paramo = talloc(pserviceDest, struct param_opt);
1343 paramo->key = talloc_reference(paramo, data->key);
1344 paramo->value = talloc_reference(paramo, data->value);
1345 DLIST_ADD(pserviceDest->param_opt, paramo);
1352 * Check a service for consistency. Return False if the service is in any way
1353 * incomplete or faulty, else True.
1355 static bool service_ok(struct loadparm_service *service)
1360 if (service->szService[0] == '\0') {
1361 DEBUG(0, ("The following message indicates an internal error:\n"));
1362 DEBUG(0, ("No service name in service entry.\n"));
1366 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1367 /* I can't see why you'd want a non-printable printer service... */
1368 if (strwicmp(service->szService, PRINTERS_NAME) == 0) {
1369 if (!service->bPrint_ok) {
1370 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
1371 service->szService));
1372 service->bPrint_ok = true;
1374 /* [printers] service must also be non-browsable. */
1375 if (service->bBrowseable)
1376 service->bBrowseable = false;
1379 /* If a service is flagged unavailable, log the fact at level 0. */
1380 if (!service->bAvailable)
1381 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
1382 service->szService));
1388 /*******************************************************************
1389 Keep a linked list of all config files so we know when one has changed
1390 it's date and needs to be reloaded.
1391 ********************************************************************/
1393 static void add_to_file_list(struct loadparm_context *lp_ctx,
1394 const char *fname, const char *subfname)
1396 struct file_lists *f = lp_ctx->file_lists;
1399 if (f->name && !strcmp(f->name, fname))
1405 f = talloc(lp_ctx, struct file_lists);
1408 f->next = lp_ctx->file_lists;
1409 f->name = talloc_strdup(f, fname);
1414 f->subfname = talloc_strdup(f, subfname);
1419 lp_ctx->file_lists = f;
1420 f->modtime = file_modtime(subfname);
1422 time_t t = file_modtime(subfname);
1428 /*******************************************************************
1429 Check if a config file has changed date.
1430 ********************************************************************/
1431 bool lp_file_list_changed(struct loadparm_context *lp_ctx)
1433 struct file_lists *f;
1434 DEBUG(6, ("lp_file_list_changed()\n"));
1436 for (f = lp_ctx->file_lists; f != NULL; f = f->next) {
1440 n2 = standard_sub_basic(lp_ctx, f->name);
1442 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
1443 f->name, n2, ctime(&f->modtime)));
1445 mod_time = file_modtime(n2);
1447 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
1448 DEBUGADD(6, ("file %s modified: %s\n", n2,
1450 f->modtime = mod_time;
1451 talloc_free(f->subfname);
1452 f->subfname = talloc_strdup(f, n2);
1459 /***************************************************************************
1460 Handle the include operation.
1461 ***************************************************************************/
1463 static bool handle_include(struct loadparm_context *lp_ctx,
1464 const char *pszParmValue, char **ptr)
1466 char *fname = standard_sub_basic(lp_ctx, pszParmValue);
1468 add_to_file_list(lp_ctx, pszParmValue, fname);
1470 string_set(lp_ctx, ptr, fname);
1472 if (file_exist(fname))
1473 return pm_process(fname, do_section, do_parameter, lp_ctx);
1475 DEBUG(2, ("Can't find include file %s\n", fname));
1480 /***************************************************************************
1481 Handle the interpretation of the copy parameter.
1482 ***************************************************************************/
1484 static bool handle_copy(struct loadparm_context *lp_ctx,
1485 const char *pszParmValue, char **ptr)
1488 struct loadparm_service *serviceTemp;
1490 string_set(lp_ctx, ptr, pszParmValue);
1494 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
1496 if ((serviceTemp = getservicebyname(lp_ctx, pszParmValue)) != NULL) {
1497 if (serviceTemp == lp_ctx->currentService) {
1498 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
1500 copy_service(lp_ctx->currentService,
1502 lp_ctx->currentService->copymap);
1506 DEBUG(0, ("Unable to copy service - source not found: %s\n",
1514 static bool handle_debuglevel(struct loadparm_context *lp_ctx,
1515 const char *pszParmValue, char **ptr)
1517 DEBUGLEVEL = atoi(pszParmValue);
1522 static bool handle_logfile(struct loadparm_context *lp_ctx,
1523 const char *pszParmValue, char **ptr)
1525 logfile = pszParmValue;
1529 /***************************************************************************
1530 Initialise a copymap.
1531 ***************************************************************************/
1533 static void init_copymap(struct loadparm_service *pservice)
1536 talloc_free(pservice->copymap);
1537 pservice->copymap = talloc_array(pservice, int, NUMPARAMETERS);
1538 if (pservice->copymap == NULL) {
1540 ("Couldn't allocate copymap!! (size %d)\n",
1541 (int)NUMPARAMETERS));
1544 for (i = 0; i < NUMPARAMETERS; i++)
1545 pservice->copymap[i] = true;
1548 /***************************************************************************
1549 Process a parametric option
1550 ***************************************************************************/
1551 static bool lp_do_parameter_parametric(struct loadparm_context *lp_ctx,
1552 struct loadparm_service *service,
1553 const char *pszParmName,
1554 const char *pszParmValue, int flags)
1556 struct param_opt *paramo, *data;
1558 TALLOC_CTX *mem_ctx;
1560 while (isspace((unsigned char)*pszParmName)) {
1564 name = strdup(pszParmName);
1565 if (!name) return false;
1569 if (service == NULL) {
1570 data = lp_ctx->globals->param_opt;
1571 mem_ctx = lp_ctx->globals;
1573 data = service->param_opt;
1577 /* Traverse destination */
1578 for (paramo=data; paramo; paramo=paramo->next) {
1579 /* If we already have the option set, override it unless
1580 it was a command line option and the new one isn't */
1581 if (strcmp(paramo->key, name) == 0) {
1582 if ((paramo->flags & FLAG_CMDLINE) &&
1583 !(flags & FLAG_CMDLINE)) {
1587 talloc_free(paramo->value);
1588 paramo->value = talloc_strdup(paramo, pszParmValue);
1589 paramo->flags = flags;
1595 paramo = talloc(mem_ctx, struct param_opt);
1598 paramo->key = talloc_strdup(paramo, name);
1599 paramo->value = talloc_strdup(paramo, pszParmValue);
1600 paramo->flags = flags;
1601 if (service == NULL) {
1602 DLIST_ADD(lp_ctx->globals->param_opt, paramo);
1604 DLIST_ADD(service->param_opt, paramo);
1612 static bool set_variable(TALLOC_CTX *mem_ctx, int parmnum, void *parm_ptr,
1613 const char *pszParmName, const char *pszParmValue,
1614 struct loadparm_context *lp_ctx)
1617 /* if it is a special case then go ahead */
1618 if (parm_table[parmnum].special) {
1619 parm_table[parmnum].special(lp_ctx, pszParmValue,
1624 /* now switch on the type of variable it is */
1625 switch (parm_table[parmnum].type)
1629 if (!set_boolean(pszParmValue, &b)) {
1630 DEBUG(0,("lp_do_parameter(%s): value is not boolean!\n", pszParmValue));
1633 *(int *)parm_ptr = b;
1638 *(int *)parm_ptr = atoi(pszParmValue);
1642 *(int *)parm_ptr = strtol(pszParmValue, NULL, 8);
1648 if (conv_str_size(pszParmValue, &val)) {
1649 if (val <= INT_MAX) {
1650 *(int *)parm_ptr = (int)val;
1655 DEBUG(0,("lp_do_parameter(%s): value is not "
1656 "a valid size specifier!\n", pszParmValue));
1661 *(const char ***)parm_ptr = str_list_make(mem_ctx,
1662 pszParmValue, NULL);
1666 string_set(mem_ctx, (char **)parm_ptr, pszParmValue);
1670 string_set(mem_ctx, (char **)parm_ptr, pszParmValue);
1671 strupper(*(char **)parm_ptr);
1675 for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
1678 parm_table[parmnum].enum_list[i].name)) {
1680 parm_table[parmnum].
1685 if (!parm_table[parmnum].enum_list[i].name) {
1686 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n",
1687 pszParmValue, pszParmName));
1693 if (parm_table[parmnum].flags & FLAG_DEFAULT) {
1694 parm_table[parmnum].flags &= ~FLAG_DEFAULT;
1695 /* we have to also unset FLAG_DEFAULT on aliases */
1696 for (i=parmnum-1;i>=0 && parm_table[i].offset == parm_table[parmnum].offset;i--) {
1697 parm_table[i].flags &= ~FLAG_DEFAULT;
1699 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset;i++) {
1700 parm_table[i].flags &= ~FLAG_DEFAULT;
1707 bool lp_do_global_parameter(struct loadparm_context *lp_ctx,
1708 const char *pszParmName, const char *pszParmValue)
1710 int parmnum = map_parameter(pszParmName);
1714 if (strchr(pszParmName, ':')) {
1715 return lp_do_parameter_parametric(lp_ctx, NULL, pszParmName, pszParmValue, 0);
1717 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1721 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1722 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1726 /* if the flag has been set on the command line, then don't allow override,
1727 but don't report an error */
1728 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1732 parm_ptr = lp_parm_ptr(lp_ctx, NULL, &parm_table[parmnum]);
1734 return set_variable(lp_ctx, parmnum, parm_ptr,
1735 pszParmName, pszParmValue, lp_ctx);
1738 bool lp_do_service_parameter(struct loadparm_context *lp_ctx,
1739 struct loadparm_service *service,
1740 const char *pszParmName, const char *pszParmValue)
1744 int parmnum = map_parameter(pszParmName);
1747 if (strchr(pszParmName, ':')) {
1748 return lp_do_parameter_parametric(lp_ctx, service, pszParmName, pszParmValue, 0);
1750 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1754 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1755 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1759 /* if the flag has been set on the command line, then don't allow override,
1760 but don't report an error */
1761 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1765 if (parm_table[parmnum].class == P_GLOBAL) {
1767 ("Global parameter %s found in service section!\n",
1771 parm_ptr = ((char *)service) + parm_table[parmnum].offset;
1773 if (!service->copymap)
1774 init_copymap(service);
1776 /* this handles the aliases - set the copymap for other
1777 * entries with the same data pointer */
1778 for (i = 0; parm_table[i].label; i++)
1779 if (parm_table[i].offset == parm_table[parmnum].offset &&
1780 parm_table[i].class == parm_table[parmnum].class)
1781 service->copymap[i] = false;
1783 return set_variable(service, parmnum, parm_ptr, pszParmName,
1784 pszParmValue, lp_ctx);
1787 /***************************************************************************
1788 Process a parameter.
1789 ***************************************************************************/
1791 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
1794 struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata;
1796 if (lp_ctx->bInGlobalSection)
1797 return lp_do_global_parameter(lp_ctx, pszParmName,
1800 return lp_do_service_parameter(lp_ctx, lp_ctx->currentService,
1801 pszParmName, pszParmValue);
1805 variable argument do parameter
1807 bool lp_do_global_parameter_var(struct loadparm_context *lp_ctx, const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4);
1808 bool lp_do_global_parameter_var(struct loadparm_context *lp_ctx,
1809 const char *pszParmName, const char *fmt, ...)
1816 s = talloc_vasprintf(NULL, fmt, ap);
1818 ret = lp_do_global_parameter(lp_ctx, pszParmName, s);
1825 set a parameter from the commandline - this is called from command line parameter
1826 parsing code. It sets the parameter then marks the parameter as unable to be modified
1827 by smb.conf processing
1829 bool lp_set_cmdline(struct loadparm_context *lp_ctx, const char *pszParmName,
1830 const char *pszParmValue)
1832 int parmnum = map_parameter(pszParmName);
1835 while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
1838 if (parmnum < 0 && strchr(pszParmName, ':')) {
1839 /* set a parametric option */
1840 return lp_do_parameter_parametric(lp_ctx, NULL, pszParmName,
1841 pszParmValue, FLAG_CMDLINE);
1845 DEBUG(0,("Unknown option '%s'\n", pszParmName));
1849 /* reset the CMDLINE flag in case this has been called before */
1850 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
1852 if (!lp_do_global_parameter(lp_ctx, pszParmName, pszParmValue)) {
1856 parm_table[parmnum].flags |= FLAG_CMDLINE;
1858 /* we have to also set FLAG_CMDLINE on aliases */
1859 for (i=parmnum-1;i>=0 && parm_table[i].offset == parm_table[parmnum].offset;i--) {
1860 parm_table[i].flags |= FLAG_CMDLINE;
1862 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset;i++) {
1863 parm_table[i].flags |= FLAG_CMDLINE;
1870 set a option from the commandline in 'a=b' format. Use to support --option
1872 bool lp_set_option(struct loadparm_context *lp_ctx, const char *option)
1890 ret = lp_set_cmdline(lp_ctx, s, p+1);
1896 #define BOOLSTR(b) ((b) ? "Yes" : "No")
1898 /***************************************************************************
1899 Print a parameter of the specified type.
1900 ***************************************************************************/
1902 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
1908 for (i = 0; p->enum_list[i].name; i++) {
1909 if (*(int *)ptr == p->enum_list[i].value) {
1911 p->enum_list[i].name);
1918 fprintf(f, "%s", BOOLSTR((bool)*(int *)ptr));
1923 fprintf(f, "%d", *(int *)ptr);
1927 fprintf(f, "0%o", *(int *)ptr);
1931 if ((char ***)ptr && *(char ***)ptr) {
1932 char **list = *(char ***)ptr;
1934 for (; *list; list++)
1935 fprintf(f, "%s%s", *list,
1936 ((*(list+1))?", ":""));
1942 if (*(char **)ptr) {
1943 fprintf(f, "%s", *(char **)ptr);
1949 /***************************************************************************
1950 Check if two parameters are equal.
1951 ***************************************************************************/
1953 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
1957 return (*((int *)ptr1) == *((int *)ptr2));
1963 return (*((int *)ptr1) == *((int *)ptr2));
1966 return str_list_equal((const char **)(*(char ***)ptr1),
1967 (const char **)(*(char ***)ptr2));
1972 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
1977 return (p1 == p2 || strequal(p1, p2));
1983 /***************************************************************************
1984 Process a new section (service). At this stage all sections are services.
1985 Later we'll have special sections that permit server parameters to be set.
1986 Returns True on success, False on failure.
1987 ***************************************************************************/
1989 static bool do_section(const char *pszSectionName, void *userdata)
1991 struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata;
1993 bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
1994 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
1997 /* if we've just struck a global section, note the fact. */
1998 lp_ctx->bInGlobalSection = isglobal;
2000 /* check for multiple global sections */
2001 if (lp_ctx->bInGlobalSection) {
2002 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2006 /* if we have a current service, tidy it up before moving on */
2009 if (lp_ctx->currentService != NULL)
2010 bRetval = service_ok(lp_ctx->currentService);
2012 /* if all is still well, move to the next record in the services array */
2014 /* We put this here to avoid an odd message order if messages are */
2015 /* issued by the post-processing of a previous section. */
2016 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2018 if ((lp_ctx->currentService = lp_add_service(lp_ctx, &sDefault,
2021 DEBUG(0, ("Failed to add a new service\n"));
2030 /***************************************************************************
2031 Determine if a partcular base parameter is currentl set to the default value.
2032 ***************************************************************************/
2034 static bool is_default(int i)
2036 void *def_ptr = ((char *)&sDefault) + parm_table[i].offset;
2037 if (!defaults_saved)
2039 switch (parm_table[i].type) {
2041 return str_list_equal((const char **)parm_table[i].def.lvalue,
2042 (const char **)def_ptr);
2045 return strequal(parm_table[i].def.svalue,
2048 return parm_table[i].def.bvalue ==
2054 return parm_table[i].def.ivalue ==
2060 /***************************************************************************
2061 Display the contents of the global structure.
2062 ***************************************************************************/
2064 static void dump_globals(struct loadparm_context *lp_ctx, FILE *f,
2068 struct param_opt *data;
2070 fprintf(f, "# Global parameters\n[global]\n");
2072 for (i = 0; parm_table[i].label; i++)
2073 if (parm_table[i].class == P_GLOBAL &&
2074 parm_table[i].offset != -1 &&
2075 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
2076 if (!show_defaults && (parm_table[i].flags & FLAG_DEFAULT))
2078 fprintf(f, "\t%s = ", parm_table[i].label);
2079 print_parameter(&parm_table[i], lp_parm_ptr(lp_ctx, NULL, &parm_table[i]), f);
2082 if (lp_ctx->globals->param_opt != NULL) {
2083 for (data = lp_ctx->globals->param_opt; data;
2084 data = data->next) {
2085 fprintf(f, "\t%s = %s\n", data->key, data->value);
2091 /***************************************************************************
2092 Display the contents of a single services record.
2093 ***************************************************************************/
2095 static void dump_a_service(struct loadparm_service * pService, FILE * f)
2098 struct param_opt *data;
2100 if (pService != &sDefault)
2101 fprintf(f, "\n[%s]\n", pService->szService);
2103 for (i = 0; parm_table[i].label; i++)
2104 if (parm_table[i].class == P_LOCAL &&
2105 parm_table[i].offset != -1 &&
2106 (*parm_table[i].label != '-') &&
2107 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
2108 if (pService == &sDefault) {
2109 if (defaults_saved && is_default(i))
2112 if (equal_parameter(parm_table[i].type,
2113 ((char *)pService) +
2114 parm_table[i].offset,
2115 ((char *)&sDefault) +
2116 parm_table[i].offset))
2120 fprintf(f, "\t%s = ", parm_table[i].label);
2121 print_parameter(&parm_table[i],
2122 ((char *)pService) + parm_table[i].offset, f);
2125 if (pService->param_opt != NULL) {
2126 for (data = pService->param_opt; data; data = data->next) {
2127 fprintf(f, "\t%s = %s\n", data->key, data->value);
2132 bool lp_dump_a_parameter(struct loadparm_context *lp_ctx,
2133 struct loadparm_service *service,
2134 const char *parm_name, FILE * f)
2136 struct parm_struct *parm;
2139 parm = lp_parm_struct(parm_name);
2144 ptr = lp_parm_ptr(lp_ctx, service,parm);
2146 print_parameter(parm, ptr, f);
2151 /***************************************************************************
2152 Return info about the next service in a service. snum==-1 gives the globals.
2153 Return NULL when out of parameters.
2154 ***************************************************************************/
2156 struct parm_struct *lp_next_parameter(struct loadparm_context *lp_ctx, int snum, int *i,
2160 /* do the globals */
2161 for (; parm_table[*i].label; (*i)++) {
2162 if (parm_table[*i].offset == -1
2163 || (*parm_table[*i].label == '-'))
2167 && (parm_table[*i].offset ==
2168 parm_table[(*i) - 1].offset))
2171 return &parm_table[(*i)++];
2174 struct loadparm_service *pService = lp_ctx->services[snum];
2176 for (; parm_table[*i].label; (*i)++) {
2177 if (parm_table[*i].class == P_LOCAL &&
2178 parm_table[*i].offset != -1 &&
2179 (*parm_table[*i].label != '-') &&
2181 (parm_table[*i].offset !=
2182 parm_table[(*i) - 1].offset)))
2184 if (allparameters ||
2185 !equal_parameter(parm_table[*i].type,
2186 ((char *)pService) +
2187 parm_table[*i].offset,
2188 ((char *)&sDefault) +
2189 parm_table[*i].offset))
2191 return &parm_table[(*i)++];
2202 * Auto-load some home services.
2204 static void lp_add_auto_services(struct loadparm_context *lp_ctx,
2211 /***************************************************************************
2212 Unload unused services.
2213 ***************************************************************************/
2215 void lp_killunused(struct loadparm_context *lp_ctx,
2216 struct smbsrv_connection *smb,
2217 bool (*snumused) (struct smbsrv_connection *, int))
2220 for (i = 0; i < lp_ctx->iNumServices; i++) {
2221 if (lp_ctx->services[i] == NULL)
2224 if (!snumused || !snumused(smb, i)) {
2225 talloc_free(lp_ctx->services[i]);
2226 lp_ctx->services[i] = NULL;
2232 static int lp_destructor(struct loadparm_context *lp_ctx)
2234 struct param_opt *data;
2236 if (lp_ctx->globals->param_opt != NULL) {
2237 struct param_opt *next;
2238 for (data = lp_ctx->globals->param_opt; data; data=next) {
2240 if (data->flags & FLAG_CMDLINE) continue;
2241 DLIST_REMOVE(lp_ctx->globals->param_opt, data);
2250 * Initialise the global parameter structure.
2252 struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
2256 struct loadparm_context *lp_ctx;
2258 lp_ctx = talloc_zero(mem_ctx, struct loadparm_context);
2262 talloc_set_destructor(lp_ctx, lp_destructor);
2263 lp_ctx->bInGlobalSection = true;
2264 lp_ctx->globals = talloc_zero(lp_ctx, struct loadparm_global);
2266 DEBUG(3, ("Initialising global parameters\n"));
2268 for (i = 0; parm_table[i].label; i++) {
2269 if ((parm_table[i].type == P_STRING ||
2270 parm_table[i].type == P_USTRING) &&
2271 parm_table[i].offset != -1 &&
2272 !(parm_table[i].flags & FLAG_CMDLINE)) {
2273 char **r = ((char *)(parm_table[i].class == P_LOCAL)?&sDefault:lp_ctx->globals) + parm_table[i].offset;
2274 *r = talloc_strdup(lp_ctx, "");
2278 lp_do_global_parameter(lp_ctx, "share backend", "classic");
2280 lp_do_global_parameter(lp_ctx, "server role", "standalone");
2282 /* options that can be set on the command line must be initialised via
2283 the slower lp_do_global_parameter() to ensure that FLAG_CMDLINE is obeyed */
2285 lp_do_global_parameter(lp_ctx, "socket options", "TCP_NODELAY");
2287 lp_do_global_parameter(lp_ctx, "workgroup", DEFAULT_WORKGROUP);
2288 myname = get_myname();
2289 lp_do_global_parameter(lp_ctx, "netbios name", myname);
2291 lp_do_global_parameter(lp_ctx, "name resolve order", "lmhosts wins host bcast");
2293 lp_do_global_parameter(lp_ctx, "fstype", FSTYPE_STRING);
2294 lp_do_global_parameter(lp_ctx, "ntvfs handler", "unixuid default");
2295 lp_do_global_parameter(lp_ctx, "max connections", "-1");
2297 lp_do_global_parameter(lp_ctx, "dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup unixinfo");
2298 lp_do_global_parameter(lp_ctx, "server services", "smb rpc nbt wrepl ldap cldap web kdc drepl winbind");
2299 lp_do_global_parameter(lp_ctx, "ntptr providor", "simple_ldb");
2300 lp_do_global_parameter(lp_ctx, "auth methods:domain controller", "anonymous sam_ignoredomain");
2301 lp_do_global_parameter(lp_ctx, "auth methods:member server", "anonymous sam winbind");
2302 lp_do_global_parameter(lp_ctx, "auth methods:standalone", "anonymous sam_ignoredomain");
2303 lp_do_global_parameter(lp_ctx, "private dir", dyn_PRIVATE_DIR);
2304 lp_do_global_parameter(lp_ctx, "sam database", "sam.ldb");
2305 lp_do_global_parameter(lp_ctx, "secrets database", "secrets.ldb");
2306 lp_do_global_parameter(lp_ctx, "spoolss database", "spoolss.ldb");
2307 lp_do_global_parameter(lp_ctx, "wins config database", "wins_config.ldb");
2308 lp_do_global_parameter(lp_ctx, "wins database", "wins.ldb");
2309 lp_do_global_parameter(lp_ctx, "registry:HKEY_LOCAL_MACHINE", "hklm.ldb");
2311 /* This hive should be dynamically generated by Samba using
2312 data from the sam, but for the moment leave it in a tdb to
2313 keep regedt32 from popping up an annoying dialog. */
2314 lp_do_global_parameter(lp_ctx, "registry:HKEY_USERS", "hku.ldb");
2316 /* using UTF8 by default allows us to support all chars */
2317 lp_do_global_parameter(lp_ctx, "unix charset", "UTF8");
2319 /* Use codepage 850 as a default for the dos character set */
2320 lp_do_global_parameter(lp_ctx, "dos charset", "CP850");
2323 * Allow the default PASSWD_CHAT to be overridden in local.h.
2325 lp_do_global_parameter(lp_ctx, "passwd chat", DEFAULT_PASSWD_CHAT);
2327 lp_do_global_parameter(lp_ctx, "pid directory", dyn_PIDDIR);
2328 lp_do_global_parameter(lp_ctx, "lock dir", dyn_LOCKDIR);
2329 lp_do_global_parameter(lp_ctx, "modules dir", dyn_MODULESDIR);
2330 lp_do_global_parameter(lp_ctx, "ncalrpc dir", dyn_NCALRPCDIR);
2332 lp_do_global_parameter(lp_ctx, "socket address", "0.0.0.0");
2333 lp_do_global_parameter_var(lp_ctx, "server string",
2334 "Samba %s", SAMBA_VERSION_STRING);
2336 lp_do_global_parameter_var(lp_ctx, "announce version", "%d.%d",
2337 DEFAULT_MAJOR_VERSION,
2338 DEFAULT_MINOR_VERSION);
2340 lp_do_global_parameter(lp_ctx, "password server", "*");
2342 lp_do_global_parameter(lp_ctx, "max mux", "50");
2343 lp_do_global_parameter(lp_ctx, "max xmit", "12288");
2344 lp_do_global_parameter(lp_ctx, "password level", "0");
2345 lp_do_global_parameter(lp_ctx, "LargeReadwrite", "True");
2346 lp_do_global_parameter(lp_ctx, "server min protocol", "CORE");
2347 lp_do_global_parameter(lp_ctx, "server max protocol", "NT1");
2348 lp_do_global_parameter(lp_ctx, "client min protocol", "CORE");
2349 lp_do_global_parameter(lp_ctx, "client max protocol", "NT1");
2350 lp_do_global_parameter(lp_ctx, "security", "USER");
2351 lp_do_global_parameter(lp_ctx, "paranoid server security", "True");
2352 lp_do_global_parameter(lp_ctx, "EncryptPasswords", "True");
2353 lp_do_global_parameter(lp_ctx, "ReadRaw", "True");
2354 lp_do_global_parameter(lp_ctx, "WriteRaw", "True");
2355 lp_do_global_parameter(lp_ctx, "NullPasswords", "False");
2356 lp_do_global_parameter(lp_ctx, "ObeyPamRestrictions", "False");
2357 lp_do_global_parameter(lp_ctx, "announce as", "NT SERVER");
2359 lp_do_global_parameter(lp_ctx, "TimeServer", "False");
2360 lp_do_global_parameter(lp_ctx, "BindInterfacesOnly", "False");
2361 lp_do_global_parameter(lp_ctx, "Unicode", "True");
2362 lp_do_global_parameter(lp_ctx, "ClientLanManAuth", "True");
2363 lp_do_global_parameter(lp_ctx, "LanmanAuth", "True");
2364 lp_do_global_parameter(lp_ctx, "NTLMAuth", "True");
2365 lp_do_global_parameter(lp_ctx, "client use spnego principal", "False");
2367 lp_do_global_parameter(lp_ctx, "UnixExtensions", "False");
2369 lp_do_global_parameter(lp_ctx, "PreferredMaster", "Auto");
2370 lp_do_global_parameter(lp_ctx, "LocalMaster", "True");
2372 lp_do_global_parameter(lp_ctx, "wins support", "False");
2373 lp_do_global_parameter(lp_ctx, "dns proxy", "True");
2375 lp_do_global_parameter(lp_ctx, "winbind separator", "\\");
2376 lp_do_global_parameter(lp_ctx, "winbind sealed pipes", "True");
2377 lp_do_global_parameter(lp_ctx, "winbindd socket directory", dyn_WINBINDD_SOCKET_DIR);
2378 lp_do_global_parameter(lp_ctx, "template shell", "/bin/false");
2379 lp_do_global_parameter(lp_ctx, "template homedir", "/home/%WORKGROUP%/%ACCOUNTNAME%");
2381 lp_do_global_parameter(lp_ctx, "client signing", "Yes");
2382 lp_do_global_parameter(lp_ctx, "server signing", "auto");
2384 lp_do_global_parameter(lp_ctx, "use spnego", "True");
2386 lp_do_global_parameter(lp_ctx, "smb ports", "445 139");
2387 lp_do_global_parameter(lp_ctx, "nbt port", "137");
2388 lp_do_global_parameter(lp_ctx, "dgram port", "138");
2389 lp_do_global_parameter(lp_ctx, "cldap port", "389");
2390 lp_do_global_parameter(lp_ctx, "krb5 port", "88");
2391 lp_do_global_parameter(lp_ctx, "kpasswd port", "464");
2392 lp_do_global_parameter(lp_ctx, "web port", "901");
2393 lp_do_global_parameter(lp_ctx, "swat directory", dyn_SWATDIR);
2395 lp_do_global_parameter(lp_ctx, "nt status support", "True");
2397 lp_do_global_parameter(lp_ctx, "max wins ttl", "518400"); /* 6 days */
2398 lp_do_global_parameter(lp_ctx, "min wins ttl", "10");
2400 lp_do_global_parameter(lp_ctx, "tls enabled", "True");
2401 lp_do_global_parameter(lp_ctx, "tls keyfile", "tls/key.pem");
2402 lp_do_global_parameter(lp_ctx, "tls certfile", "tls/cert.pem");
2403 lp_do_global_parameter(lp_ctx, "tls cafile", "tls/ca.pem");
2404 lp_do_global_parameter_var(lp_ctx, "js include", "%s", dyn_JSDIR);
2405 lp_do_global_parameter_var(lp_ctx, "setup directory", "%s",
2408 for (i = 0; parm_table[i].label; i++) {
2409 if (!(parm_table[i].flags & FLAG_CMDLINE)) {
2410 parm_table[i].flags |= FLAG_DEFAULT;
2418 * Load the services array from the services file.
2420 * Return True on success, False on failure.
2422 bool lp_load(TALLOC_CTX *mem_ctx, const char *filename, struct loadparm_context **ret_lp)
2426 struct loadparm_context *lp_ctx;
2431 lp_ctx = loadparm_init(mem_ctx);
2435 global_loadparm = lp_ctx;
2437 filename = talloc_strdup(lp_ctx, filename);
2439 lp_ctx->globals->szConfigFile = filename;
2441 lp_ctx->bInGlobalSection = true;
2442 n2 = standard_sub_basic(lp_ctx, lp_ctx->globals->szConfigFile);
2443 DEBUG(2, ("lp_load: refreshing parameters from %s\n", n2));
2445 add_to_file_list(lp_ctx, lp_ctx->globals->szConfigFile, n2);
2447 /* We get sections first, so have to start 'behind' to make up */
2448 lp_ctx->currentService = NULL;
2449 bRetval = pm_process(n2, do_section, do_parameter, lp_ctx);
2451 /* finish up the last section */
2452 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
2454 if (lp_ctx->currentService != NULL)
2455 bRetval = service_ok(lp_ctx->currentService);
2457 lp_add_auto_services(lp_ctx, lp_auto_services(lp_ctx));
2459 lp_add_hidden(lp_ctx, "IPC$", "IPC");
2460 lp_add_hidden(lp_ctx, "ADMIN$", "DISK");
2462 if (!lp_ctx->globals->szWINSservers && lp_ctx->globals->bWINSsupport) {
2463 lp_do_global_parameter(lp_ctx, "wins server", "127.0.0.1");
2466 panic_action = lp_ctx->globals->panic_action;
2477 * Return the max number of services.
2480 int lp_numservices(struct loadparm_context *lp_ctx)
2482 return lp_ctx->iNumServices;
2486 * Display the contents of the services array in human-readable form.
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->services[iService]);
2506 * Display the contents of one service in human-readable form.
2508 void lp_dump_one(FILE *f, bool show_defaults, struct loadparm_service *service)
2510 if (service != NULL) {
2511 if (service->szService[0] == '\0')
2513 dump_a_service(service, f);
2517 struct loadparm_service *lp_servicebynum(struct loadparm_context *lp_ctx,
2520 return lp_ctx->services[snum];
2523 struct loadparm_service *lp_service(struct loadparm_context *lp_ctx,
2524 const char *service_name)
2529 for (iService = lp_ctx->iNumServices - 1; iService >= 0; iService--) {
2530 if (lp_ctx->services[iService] &&
2531 lp_ctx->services[iService]->szService) {
2533 * The substitution here is used to support %U is
2536 serviceName = standard_sub_basic(
2537 lp_ctx->services[iService],
2538 lp_ctx->services[iService]->szService);
2539 if (strequal(serviceName, service_name))
2540 return lp_ctx->services[iService];
2544 DEBUG(7,("lp_servicenumber: couldn't find %s\n", service_name));
2550 * A useful volume label function.
2552 const char *volume_label(struct loadparm_service *service)
2554 const char *ret = lp_volume(service);
2556 return lp_servicename(service);
2562 * If we are PDC then prefer us as DMB
2564 const char *lp_printername(struct loadparm_service *service)
2566 const char *ret = _lp_printername(service);
2567 if (ret == NULL || (ret != NULL && *ret == '\0'))
2568 ret = lp_const_servicename(service);
2575 * Return the max print jobs per queue.
2577 int lp_maxprintjobs(struct loadparm_service *service)
2579 int maxjobs = (service != NULL) ? service->iMaxPrintJobs : sDefault.iMaxPrintJobs;
2580 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
2581 maxjobs = PRINT_MAX_JOBID - 1;