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/loadparm.h"
67 static bool bLoaded = false;
69 #define standard_sub_basic talloc_strdup
71 /* some helpful bits */
72 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < loadparm.iNumServices) && VALID(i))
73 #define VALID(i) (loadparm.ServicePtrs[i] != NULL)
75 static bool do_parameter(const char *, const char *, void *);
76 static bool do_parameter_var(const char *pszParmName, const char *fmt, ...);
78 static bool defaults_saved = false;
81 struct param_opt *prev, *next;
88 * This structure describes global (ie., server-wide) parameters.
92 enum server_role server_role;
100 char *szServerString;
101 char *szAutoServices;
104 char *szShareBackend;
108 char *szWINS_CONFIG_URL;
112 char *jsonrpcServicesDir;
113 char **szPasswordServers;
114 char *szSocketOptions;
116 char **szWINSservers;
118 char *szSocketAddress;
119 char *szAnnounceVersion; /* This is initialised in init_globals */
122 char **szNetbiosAliases;
123 char *szNetbiosScope;
124 char *szDomainOtherSIDs;
125 char **szNameResolveOrder;
126 char **dcerpc_ep_servers;
127 char **server_services;
128 char *ntptr_providor;
129 char *szWinbindSeparator;
130 char *szWinbinddSocketDirectory;
131 char *szTemplateShell;
132 char *szTemplateHomedir;
133 int bWinbindSealedPipes;
134 char *webapps_directory;
149 int paranoid_server_security;
152 int announce_as; /* This is initialised in init_globals */
159 char *socket_options;
164 int bPreferredMaster;
165 int bEncryptPasswords;
167 int bObeyPamRestrictions;
172 int bBindInterfacesOnly;
174 int bNTStatusSupport;
180 int bClientPlaintextAuth;
181 int bClientLanManAuth;
182 int bClientNTLMv2Auth;
183 int client_use_spnego_principal;
189 struct param_opt *param_opt;
194 * This structure describes a single service.
208 char **ntvfs_handler;
221 int iCreate_force_mode;
228 struct param_opt *param_opt;
230 char dummy[3]; /* for alignment */
234 /* This is a default service used to prime a services structure */
235 static struct service sDefault = {
236 NULL, /* szService */
239 NULL, /* szInclude */
240 NULL, /* szPrintername */
241 NULL, /* szHostsallow */
242 NULL, /* szHostsdeny */
246 NULL, /* ntvfs_handler */
247 1000, /* iMaxPrintJobs */
248 0, /* iMaxConnections */
250 True, /* bAvailable */
251 True, /* bBrowseable */
252 True, /* bRead_only */
253 False, /* bPrint_ok */
254 False, /* bMap_system */
255 False, /* bMap_hidden */
256 True, /* bMap_archive */
257 True, /* bStrictLocking */
258 0744, /* iCreate_mask */
259 0000, /* iCreate_force_mode */
260 0755, /* iDir_mask */
261 0000, /* iDir_force_mode */
263 False, /* bMSDfsRoot */
264 False, /* bStrictSync */
265 False, /* bCIFileSystem */
266 NULL, /* Parametric options */
271 /* local variables */
272 static struct loadparm_context {
273 struct global Globals;
274 struct service **ServicePtrs;
277 bool bInGlobalSection;
281 .bInGlobalSection = true,
285 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
287 /* prototypes for the special type handlers */
288 static bool handle_include(const char *pszParmValue, char **ptr);
289 static bool handle_copy(const char *pszParmValue, char **ptr);
291 static const struct enum_list enum_protocol[] = {
292 {PROTOCOL_SMB2, "SMB2"},
293 {PROTOCOL_NT1, "NT1"},
294 {PROTOCOL_LANMAN2, "LANMAN2"},
295 {PROTOCOL_LANMAN1, "LANMAN1"},
296 {PROTOCOL_CORE, "CORE"},
297 {PROTOCOL_COREPLUS, "COREPLUS"},
298 {PROTOCOL_COREPLUS, "CORE+"},
302 static const struct enum_list enum_security[] = {
303 {SEC_SHARE, "SHARE"},
308 static const struct enum_list enum_announce_as[] = {
309 {ANNOUNCE_AS_NT_SERVER, "NT"},
310 {ANNOUNCE_AS_NT_SERVER, "NT Server"},
311 {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"},
312 {ANNOUNCE_AS_WIN95, "win95"},
313 {ANNOUNCE_AS_WFW, "WfW"},
317 static const struct enum_list enum_bool_auto[] = {
328 /* Client-side offline caching policy types */
329 #define CSC_POLICY_MANUAL 0
330 #define CSC_POLICY_DOCUMENTS 1
331 #define CSC_POLICY_PROGRAMS 2
332 #define CSC_POLICY_DISABLE 3
334 static const struct enum_list enum_csc_policy[] = {
335 {CSC_POLICY_MANUAL, "manual"},
336 {CSC_POLICY_DOCUMENTS, "documents"},
337 {CSC_POLICY_PROGRAMS, "programs"},
338 {CSC_POLICY_DISABLE, "disable"},
342 /* SMB signing types. */
343 static const struct enum_list enum_smb_signing_vals[] = {
344 {SMB_SIGNING_OFF, "No"},
345 {SMB_SIGNING_OFF, "False"},
346 {SMB_SIGNING_OFF, "0"},
347 {SMB_SIGNING_OFF, "Off"},
348 {SMB_SIGNING_OFF, "disabled"},
349 {SMB_SIGNING_SUPPORTED, "Yes"},
350 {SMB_SIGNING_SUPPORTED, "True"},
351 {SMB_SIGNING_SUPPORTED, "1"},
352 {SMB_SIGNING_SUPPORTED, "On"},
353 {SMB_SIGNING_SUPPORTED, "enabled"},
354 {SMB_SIGNING_REQUIRED, "required"},
355 {SMB_SIGNING_REQUIRED, "mandatory"},
356 {SMB_SIGNING_REQUIRED, "force"},
357 {SMB_SIGNING_REQUIRED, "forced"},
358 {SMB_SIGNING_REQUIRED, "enforced"},
359 {SMB_SIGNING_AUTO, "auto"},
363 static const struct enum_list enum_server_role[] = {
364 {ROLE_STANDALONE, "standalone"},
365 {ROLE_DOMAIN_MEMBER, "member server"},
366 {ROLE_DOMAIN_CONTROLLER, "domain controller"},
371 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
373 * Note: We have a flag called FLAG_DEVELOPER but is not used at this time, it
374 * is implied in current control logic. This may change at some later time. A
375 * flag value of 0 means - show as development option only.
377 * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
378 * screen in SWAT. This is used to exclude parameters as well as to squash all
379 * parameters that have been duplicated by pseudonyms.
381 static struct parm_struct parm_table[] = {
382 {"Base Options", P_SEP, P_SEPARATOR},
384 {"server role", P_ENUM, P_GLOBAL, &loadparm.Globals.server_role, NULL, enum_server_role, FLAG_BASIC},
386 {"dos charset", P_STRING, P_GLOBAL, &dos_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
387 {"unix charset", P_STRING, P_GLOBAL, &unix_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
388 {"ncalrpc dir", P_STRING, P_GLOBAL, &loadparm.Globals.ncalrpc_dir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
389 {"display charset", P_STRING, P_GLOBAL, &display_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
390 {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
391 {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
392 {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE},
393 {"workgroup", P_USTRING, P_GLOBAL, &loadparm.Globals.szWorkgroup, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
394 {"realm", P_STRING, P_GLOBAL, &loadparm.Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
395 {"netbios name", P_USTRING, P_GLOBAL, &loadparm.Globals.szNetbiosName, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
396 {"netbios aliases", P_LIST, P_GLOBAL, &loadparm.Globals.szNetbiosAliases, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
397 {"netbios scope", P_USTRING, P_GLOBAL, &loadparm.Globals.szNetbiosScope, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
398 {"server string", P_STRING, P_GLOBAL, &loadparm.Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
399 {"interfaces", P_LIST, P_GLOBAL, &loadparm.Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
400 {"bind interfaces only", P_BOOL, P_GLOBAL, &loadparm.Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
401 {"ntvfs handler", P_LIST, P_LOCAL, &sDefault.ntvfs_handler, NULL, NULL, FLAG_ADVANCED},
402 {"ntptr providor", P_STRING, P_GLOBAL, &loadparm.Globals.ntptr_providor, NULL, NULL, FLAG_ADVANCED},
403 {"dcerpc endpoint servers", P_LIST, P_GLOBAL, &loadparm.Globals.dcerpc_ep_servers, NULL, NULL, FLAG_ADVANCED},
404 {"server services", P_LIST, P_GLOBAL, &loadparm.Globals.server_services, NULL, NULL, FLAG_ADVANCED},
406 {"Security Options", P_SEP, P_SEPARATOR},
408 {"security", P_ENUM, P_GLOBAL, &loadparm.Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
409 {"encrypt passwords", P_BOOL, P_GLOBAL, &loadparm.Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
410 {"null passwords", P_BOOL, P_GLOBAL, &loadparm.Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
411 {"obey pam restrictions", P_BOOL, P_GLOBAL, &loadparm.Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
412 {"password server", P_LIST, P_GLOBAL, &loadparm.Globals.szPasswordServers, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
413 {"sam database", P_STRING, P_GLOBAL, &loadparm.Globals.szSAM_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
414 {"secrets database", P_STRING, P_GLOBAL, &loadparm.Globals.szSECRETS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
415 {"spoolss database", P_STRING, P_GLOBAL, &loadparm.Globals.szSPOOLSS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
416 {"wins config database", P_STRING, P_GLOBAL, &loadparm.Globals.szWINS_CONFIG_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
417 {"wins database", P_STRING, P_GLOBAL, &loadparm.Globals.szWINS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
418 {"private dir", P_STRING, P_GLOBAL, &loadparm.Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
419 {"passwd chat", P_STRING, P_GLOBAL, &loadparm.Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
420 {"password level", P_INTEGER, P_GLOBAL, &loadparm.Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
421 {"lanman auth", P_BOOL, P_GLOBAL, &loadparm.Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
422 {"ntlm auth", P_BOOL, P_GLOBAL, &loadparm.Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
423 {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &loadparm.Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
424 {"client lanman auth", P_BOOL, P_GLOBAL, &loadparm.Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
425 {"client plaintext auth", P_BOOL, P_GLOBAL, &loadparm.Globals.bClientPlaintextAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
426 {"client use spnego principal", P_BOOL, P_GLOBAL, &loadparm.Globals.client_use_spnego_principal, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
428 {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE},
430 {"create mask", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
431 {"force create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
432 {"directory mask", P_OCTAL, P_LOCAL, &sDefault.iDir_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
433 {"force directory mode", P_OCTAL, P_LOCAL, &sDefault.iDir_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
435 {"hosts allow", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
436 {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
438 {"Logging Options", P_SEP, P_SEPARATOR},
440 {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
441 {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_HIDE},
442 {"log file", P_STRING, P_GLOBAL, &logfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
444 {"Protocol Options", P_SEP, P_SEPARATOR},
446 {"smb ports", P_LIST, P_GLOBAL, &loadparm.Globals.smb_ports, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
447 {"nbt port", P_INTEGER, P_GLOBAL, &loadparm.Globals.nbt_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
448 {"dgram port", P_INTEGER, P_GLOBAL, &loadparm.Globals.dgram_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
449 {"cldap port", P_INTEGER, P_GLOBAL, &loadparm.Globals.cldap_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
450 {"krb5 port", P_INTEGER, P_GLOBAL, &loadparm.Globals.krb5_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
451 {"kpasswd port", P_INTEGER, P_GLOBAL, &loadparm.Globals.kpasswd_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
452 {"web port", P_INTEGER, P_GLOBAL, &loadparm.Globals.web_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
453 {"tls enabled", P_BOOL, P_GLOBAL, &loadparm.Globals.tls_enabled, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
454 {"tls keyfile", P_STRING, P_GLOBAL, &loadparm.Globals.tls_keyfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
455 {"tls certfile", P_STRING, P_GLOBAL, &loadparm.Globals.tls_certfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
456 {"tls cafile", P_STRING, P_GLOBAL, &loadparm.Globals.tls_cafile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
457 {"tls crlfile", P_STRING, P_GLOBAL, &loadparm.Globals.tls_crlfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
458 {"tls dh params file", P_STRING, P_GLOBAL, &loadparm.Globals.tls_dhpfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
459 {"web application directory", P_STRING, P_GLOBAL, &loadparm.Globals.webapps_directory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
460 {"large readwrite", P_BOOL, P_GLOBAL, &loadparm.Globals.bLargeReadwrite, NULL, NULL, FLAG_DEVELOPER},
461 {"server max protocol", P_ENUM, P_GLOBAL, &loadparm.Globals.srv_maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
462 {"server min protocol", P_ENUM, P_GLOBAL, &loadparm.Globals.srv_minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
463 {"client max protocol", P_ENUM, P_GLOBAL, &loadparm.Globals.cli_maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
464 {"client min protocol", P_ENUM, P_GLOBAL, &loadparm.Globals.cli_minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
465 {"unicode", P_BOOL, P_GLOBAL, &loadparm.Globals.bUnicode, NULL, NULL, FLAG_DEVELOPER},
466 {"read raw", P_BOOL, P_GLOBAL, &loadparm.Globals.bReadRaw, NULL, NULL, FLAG_DEVELOPER},
467 {"write raw", P_BOOL, P_GLOBAL, &loadparm.Globals.bWriteRaw, NULL, NULL, FLAG_DEVELOPER},
468 {"disable netbios", P_BOOL, P_GLOBAL, &loadparm.Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
470 {"nt status support", P_BOOL, P_GLOBAL, &loadparm.Globals.bNTStatusSupport, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
472 {"announce version", P_STRING, P_GLOBAL, &loadparm.Globals.szAnnounceVersion, NULL, NULL, FLAG_DEVELOPER},
473 {"announce as", P_ENUM, P_GLOBAL, &loadparm.Globals.announce_as, NULL, enum_announce_as, FLAG_DEVELOPER},
474 {"max mux", P_INTEGER, P_GLOBAL, &loadparm.Globals.max_mux, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
475 {"max xmit", P_BYTES, P_GLOBAL, &loadparm.Globals.max_xmit, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
477 {"name resolve order", P_LIST, P_GLOBAL, &loadparm.Globals.szNameResolveOrder, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
478 {"max wins ttl", P_INTEGER, P_GLOBAL, &loadparm.Globals.max_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
479 {"min wins ttl", P_INTEGER, P_GLOBAL, &loadparm.Globals.min_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
480 {"time server", P_BOOL, P_GLOBAL, &loadparm.Globals.bTimeServer, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
481 {"unix extensions", P_BOOL, P_GLOBAL, &loadparm.Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
482 {"use spnego", P_BOOL, P_GLOBAL, &loadparm.Globals.bUseSpnego, NULL, NULL, FLAG_DEVELOPER},
483 {"server signing", P_ENUM, P_GLOBAL, &loadparm.Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
484 {"client signing", P_ENUM, P_GLOBAL, &loadparm.Globals.client_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
485 {"rpc big endian", P_BOOL, P_GLOBAL, &loadparm.Globals.bRpcBigEndian, NULL, NULL, FLAG_DEVELOPER},
487 {"Tuning Options", P_SEP, P_SEPARATOR},
489 {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL, NULL, FLAG_SHARE},
490 {"paranoid server security", P_BOOL, P_GLOBAL, &loadparm.Globals.paranoid_server_security, NULL, NULL, FLAG_DEVELOPER},
491 {"socket options", P_STRING, P_GLOBAL, &loadparm.Globals.socket_options, NULL, NULL, FLAG_DEVELOPER},
493 {"strict sync", P_BOOL, P_LOCAL, &sDefault.bStrictSync, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
494 {"case insensitive filesystem", P_BOOL, P_LOCAL, &sDefault.bCIFileSystem, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
496 {"Printing Options", P_SEP, P_SEPARATOR},
498 {"max print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxPrintJobs, NULL, NULL, FLAG_PRINT},
499 {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_PRINT},
500 {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_HIDE},
502 {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_PRINT},
503 {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_HIDE},
505 {"Filename Handling", P_SEP, P_SEPARATOR},
507 {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
508 {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
509 {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
511 {"Domain Options", P_SEP, P_SEPARATOR},
513 {"Logon Options", P_SEP, P_SEPARATOR},
516 {"Browse Options", P_SEP, P_SEPARATOR},
518 {"preferred master", P_ENUM, P_GLOBAL, &loadparm.Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
519 {"prefered master", P_ENUM, P_GLOBAL, &loadparm.Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_HIDE},
520 {"local master", P_BOOL, P_GLOBAL, &loadparm.Globals.bLocalMaster, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
521 {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
522 {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_HIDE},
524 {"WINS Options", P_SEP, P_SEPARATOR},
526 {"wins server", P_LIST, P_GLOBAL, &loadparm.Globals.szWINSservers, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
527 {"wins support", P_BOOL, P_GLOBAL, &loadparm.Globals.bWINSsupport, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
528 {"dns proxy", P_BOOL, P_GLOBAL, &loadparm.Globals.bWINSdnsProxy, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
529 {"wins hook", P_STRING, P_GLOBAL, &loadparm.Globals.szWINSHook, NULL, NULL, FLAG_ADVANCED},
531 {"Locking Options", P_SEP, P_SEPARATOR},
533 {"csc policy", P_ENUM, P_LOCAL, &sDefault.iCSCPolicy, NULL, enum_csc_policy, FLAG_SHARE | FLAG_GLOBAL},
535 {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
537 {"Miscellaneous Options", P_SEP, P_SEPARATOR},
539 {"config file", P_STRING, P_GLOBAL, &loadparm.Globals.szConfigFile, NULL, NULL, FLAG_HIDE},
540 {"share backend", P_STRING, P_GLOBAL, &loadparm.Globals.szShareBackend, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
541 {"preload", P_STRING, P_GLOBAL, &loadparm.Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
542 {"auto services", P_STRING, P_GLOBAL, &loadparm.Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
543 {"lock dir", P_STRING, P_GLOBAL, &loadparm.Globals.szLockDir, NULL, NULL, FLAG_HIDE},
544 {"lock directory", P_STRING, P_GLOBAL, &loadparm.Globals.szLockDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
545 {"modules dir", P_STRING, P_GLOBAL, &loadparm.Globals.szModulesDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
546 {"pid directory", P_STRING, P_GLOBAL, &loadparm.Globals.szPidDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
547 {"js include", P_LIST, P_GLOBAL, &loadparm.Globals.jsInclude, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
548 {"jsonrpc services directory", P_STRING, P_GLOBAL, &loadparm.Globals.jsonrpcServicesDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
549 {"setup directory", P_STRING, P_GLOBAL, &loadparm.Globals.szSetupDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
551 {"socket address", P_STRING, P_GLOBAL, &loadparm.Globals.szSocketAddress, NULL, NULL, FLAG_DEVELOPER},
552 {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy, NULL, FLAG_HIDE},
553 {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include, NULL, FLAG_HIDE},
555 {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
556 {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_SHARE },
557 {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_SHARE},
559 {"panic action", P_STRING, P_GLOBAL, &panic_action, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
561 {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_SHARE},
562 {"host msdfs", P_BOOL, P_GLOBAL, &loadparm.Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
563 {"winbind separator", P_STRING, P_GLOBAL, &loadparm.Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
564 {"winbindd socket directory", P_STRING, P_GLOBAL, &loadparm.Globals.szWinbinddSocketDirectory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
565 {"winbind sealed pipes", P_BOOL, P_GLOBAL, &loadparm.Globals.bWinbindSealedPipes, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
566 {"template shell", P_STRING, P_GLOBAL, &loadparm.Globals.szTemplateShell, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
567 {"template homedir", P_STRING, P_GLOBAL, &loadparm.Globals.szTemplateHomedir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
569 {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
574 return the parameter table
576 struct parm_struct *lp_parm_table(void)
581 /***************************************************************************
582 Initialise the global parameter structure.
583 ***************************************************************************/
584 static void init_globals(void)
589 DEBUG(3, ("Initialising global parameters\n"));
591 for (i = 0; parm_table[i].label; i++) {
592 if ((parm_table[i].type == P_STRING ||
593 parm_table[i].type == P_USTRING) &&
595 !(parm_table[i].flags & FLAG_CMDLINE)) {
596 string_set(talloc_autofree_context(),
597 parm_table[i].ptr, "");
601 do_parameter("config file", dyn_CONFIGFILE, NULL);
603 do_parameter("share backend", "classic", NULL);
605 do_parameter("server role", "standalone", NULL);
607 /* options that can be set on the command line must be initialised via
608 the slower do_parameter() to ensure that FLAG_CMDLINE is obeyed */
610 do_parameter("socket options", "TCP_NODELAY", NULL);
612 do_parameter("workgroup", DEFAULT_WORKGROUP, NULL);
613 myname = get_myname();
614 do_parameter("netbios name", myname, NULL);
616 do_parameter("name resolve order", "lmhosts wins host bcast", NULL);
618 do_parameter("fstype", FSTYPE_STRING, NULL);
619 do_parameter("ntvfs handler", "unixuid default", NULL);
620 do_parameter("max connections", "-1", NULL);
622 do_parameter("dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup unixinfo", NULL);
623 do_parameter("server services", "smb rpc nbt wrepl ldap cldap web kdc drepl winbind", NULL);
624 do_parameter("ntptr providor", "simple_ldb", NULL);
625 do_parameter("auth methods:domain controller", "anonymous sam_ignoredomain", NULL);
626 do_parameter("auth methods:member server", "anonymous sam winbind", NULL);
627 do_parameter("auth methods:standalone", "anonymous sam_ignoredomain", NULL);
628 do_parameter("private dir", dyn_PRIVATE_DIR, NULL);
629 do_parameter("sam database", "sam.ldb", NULL);
630 do_parameter("secrets database", "secrets.ldb", NULL);
631 do_parameter("spoolss database", "spoolss.ldb", NULL);
632 do_parameter("wins config database", "wins_config.ldb", NULL);
633 do_parameter("wins database", "wins.ldb", NULL);
634 do_parameter("registry:HKEY_LOCAL_MACHINE", "hklm.ldb", NULL);
636 /* This hive should be dynamically generated by Samba using
637 data from the sam, but for the moment leave it in a tdb to
638 keep regedt32 from popping up an annoying dialog. */
639 do_parameter("registry:HKEY_USERS", "hku.ldb", NULL);
641 /* using UTF8 by default allows us to support all chars */
642 do_parameter("unix charset", "UTF8", NULL);
644 /* Use codepage 850 as a default for the dos character set */
645 do_parameter("dos charset", "CP850", NULL);
648 * Allow the default PASSWD_CHAT to be overridden in local.h.
650 do_parameter("passwd chat", DEFAULT_PASSWD_CHAT, NULL);
652 do_parameter("pid directory", dyn_PIDDIR, NULL);
653 do_parameter("lock dir", dyn_LOCKDIR, NULL);
654 do_parameter("modules dir", dyn_MODULESDIR, NULL);
655 do_parameter("ncalrpc dir", dyn_NCALRPCDIR, NULL);
657 do_parameter("socket address", "0.0.0.0", NULL);
658 do_parameter_var("server string", "Samba %s", SAMBA_VERSION_STRING);
660 do_parameter_var("announce version", "%d.%d",
661 DEFAULT_MAJOR_VERSION,
662 DEFAULT_MINOR_VERSION);
664 do_parameter("password server", "*", NULL);
666 do_parameter("max mux", "50", NULL);
667 do_parameter("max xmit", "12288", NULL);
668 do_parameter("password level", "0", NULL);
669 do_parameter("LargeReadwrite", "True", NULL);
670 do_parameter("server min protocol", "CORE", NULL);
671 do_parameter("server max protocol", "NT1", NULL);
672 do_parameter("client min protocol", "CORE", NULL);
673 do_parameter("client max protocol", "NT1", NULL);
674 do_parameter("security", "USER", NULL);
675 do_parameter("paranoid server security", "True", NULL);
676 do_parameter("EncryptPasswords", "True", NULL);
677 do_parameter("ReadRaw", "True", NULL);
678 do_parameter("WriteRaw", "True", NULL);
679 do_parameter("NullPasswords", "False", NULL);
680 do_parameter("ObeyPamRestrictions", "False", NULL);
681 do_parameter("announce as", "NT SERVER", NULL);
683 do_parameter("TimeServer", "False", NULL);
684 do_parameter("BindInterfacesOnly", "False", NULL);
685 do_parameter("Unicode", "True", NULL);
686 do_parameter("ClientLanManAuth", "True", NULL);
687 do_parameter("LanmanAuth", "True", NULL);
688 do_parameter("NTLMAuth", "True", NULL);
689 do_parameter("client use spnego principal", "False", NULL);
691 do_parameter("UnixExtensions", "False", NULL);
693 do_parameter("PreferredMaster", "Auto", NULL);
694 do_parameter("LocalMaster", "True", NULL);
696 do_parameter("wins support", "False", NULL);
697 do_parameter("dns proxy", "True", NULL);
699 do_parameter("winbind separator", "\\", NULL);
700 do_parameter("winbind sealed pipes", "True", NULL);
701 do_parameter("winbindd socket directory", dyn_WINBINDD_SOCKET_DIR, NULL);
702 do_parameter("template shell", "/bin/false", NULL);
703 do_parameter("template homedir", "/home/%WORKGROUP%/%ACCOUNTNAME%", NULL);
705 do_parameter("client signing", "Yes", NULL);
706 do_parameter("server signing", "auto", NULL);
708 do_parameter("use spnego", "True", NULL);
710 do_parameter("smb ports", "445 139", NULL);
711 do_parameter("nbt port", "137", NULL);
712 do_parameter("dgram port", "138", NULL);
713 do_parameter("cldap port", "389", NULL);
714 do_parameter("krb5 port", "88", NULL);
715 do_parameter("kpasswd port", "464", NULL);
716 do_parameter("web port", "901", NULL);
717 do_parameter("web application directory", dyn_WEBAPPSDIR, NULL);
718 do_parameter("jsonrpc services directory", dyn_SERVICESDIR, NULL);
720 do_parameter("nt status support", "True", NULL);
722 do_parameter("max wins ttl", "518400", NULL); /* 6 days */
723 do_parameter("min wins ttl", "10", NULL);
725 do_parameter("tls enabled", "True", NULL);
726 do_parameter("tls keyfile", "tls/key.pem", NULL);
727 do_parameter("tls certfile", "tls/cert.pem", NULL);
728 do_parameter("tls cafile", "tls/ca.pem", NULL);
729 do_parameter_var("js include", "%s", dyn_JSDIR);
730 do_parameter_var("setup directory", "%s", dyn_SETUPDIR);
732 for (i = 0; parm_table[i].label; i++) {
733 if (!(parm_table[i].flags & FLAG_CMDLINE)) {
734 parm_table[i].flags |= FLAG_DEFAULT;
739 static TALLOC_CTX *lp_talloc;
741 /******************************************************************* a
742 Free up temporary memory - called from the main loop.
743 ********************************************************************/
745 void lp_talloc_free(void)
749 talloc_free(lp_talloc);
753 /*******************************************************************
754 Convenience routine to grab string parameters into temporary memory
755 and run standard_sub_basic on them. The buffers can be written to by
756 callers without affecting the source string.
757 ********************************************************************/
759 static const char *lp_string(const char *s)
761 #if 0 /* until REWRITE done to make thread-safe */
762 size_t len = s ? strlen(s) : 0;
766 /* The follow debug is useful for tracking down memory problems
767 especially if you have an inner loop that is calling a lp_*()
768 function that returns a string. Perhaps this debug should be
769 present all the time? */
772 DEBUG(10, ("lp_string(%s)\n", s));
775 #if 0 /* until REWRITE done to make thread-safe */
777 lp_talloc = talloc_init("lp_talloc");
779 ret = talloc_array(lp_talloc, char, len + 100); /* leave room for substitution */
787 strlcpy(ret, s, len);
789 if (trim_string(ret, "\"", "\"")) {
790 if (strchr(ret,'"') != NULL)
791 strlcpy(ret, s, len);
794 standard_sub_basic(ret,len+100);
801 In this section all the functions that are used to access the
802 parameters from the rest of the program are defined
805 #define FN_GLOBAL_STRING(fn_name,ptr) \
806 const char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
807 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
808 const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");}
809 #define FN_GLOBAL_LIST(fn_name,ptr) \
810 const char **fn_name(void) {return(*(const char ***)(ptr));}
811 #define FN_GLOBAL_BOOL(fn_name,ptr) \
812 bool fn_name(void) {return((bool)*(int *)(ptr));}
814 #define FN_GLOBAL_CHAR(fn_name,ptr) \
815 char fn_name(void) {return(*(char *)(ptr));}
817 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
818 int fn_name(void) {return(*(int *)(ptr));}
820 #define FN_LOCAL_STRING(fn_name,val) \
821 const char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && loadparm.ServicePtrs[(i)]->val) ? loadparm.ServicePtrs[(i)]->val : sDefault.val));}
822 #define FN_LOCAL_CONST_STRING(fn_name,val) \
823 const char *fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && loadparm.ServicePtrs[(i)]->val) ? loadparm.ServicePtrs[(i)]->val : sDefault.val);}
824 #define FN_LOCAL_LIST(fn_name,val) \
825 const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? loadparm.ServicePtrs[(i)]->val : sDefault.val);}
826 #define FN_LOCAL_BOOL(fn_name,val) \
827 bool fn_name(int i) {return(LP_SNUM_OK(i)? loadparm.ServicePtrs[(i)]->val : sDefault.val);}
829 #define FN_LOCAL_CHAR(fn_name,val) \
830 char fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
832 #define FN_LOCAL_INTEGER(fn_name,val) \
833 int fn_name(int i) {return(LP_SNUM_OK(i)? loadparm.ServicePtrs[(i)]->val : sDefault.val);}
835 _PUBLIC_ FN_GLOBAL_INTEGER(lp_server_role, &loadparm.Globals.server_role)
836 _PUBLIC_ FN_GLOBAL_LIST(lp_smb_ports, &loadparm.Globals.smb_ports)
837 _PUBLIC_ FN_GLOBAL_INTEGER(lp_nbt_port, &loadparm.Globals.nbt_port)
838 _PUBLIC_ FN_GLOBAL_INTEGER(lp_dgram_port, &loadparm.Globals.dgram_port)
839 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cldap_port, &loadparm.Globals.cldap_port)
840 _PUBLIC_ FN_GLOBAL_INTEGER(lp_krb5_port, &loadparm.Globals.krb5_port)
841 _PUBLIC_ FN_GLOBAL_INTEGER(lp_kpasswd_port, &loadparm.Globals.kpasswd_port)
842 _PUBLIC_ FN_GLOBAL_INTEGER(lp_web_port, &loadparm.Globals.web_port)
843 _PUBLIC_ FN_GLOBAL_STRING(lp_dos_charset, &dos_charset)
844 _PUBLIC_ FN_GLOBAL_STRING(lp_webapps_directory, &loadparm.Globals.webapps_directory)
845 _PUBLIC_ FN_GLOBAL_BOOL(lp_tls_enabled, &loadparm.Globals.tls_enabled)
846 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_keyfile, &loadparm.Globals.tls_keyfile)
847 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_certfile, &loadparm.Globals.tls_certfile)
848 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_cafile, &loadparm.Globals.tls_cafile)
849 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_crlfile, &loadparm.Globals.tls_crlfile)
850 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_dhpfile, &loadparm.Globals.tls_dhpfile)
851 _PUBLIC_ FN_GLOBAL_STRING(lp_unix_charset, &unix_charset)
852 _PUBLIC_ FN_GLOBAL_STRING(lp_display_charset, &display_charset)
853 _PUBLIC_ FN_GLOBAL_STRING(lp_configfile, &loadparm.Globals.szConfigFile)
854 _PUBLIC_ FN_GLOBAL_STRING(lp_share_backend, &loadparm.Globals.szShareBackend)
855 _PUBLIC_ FN_GLOBAL_STRING(lp_sam_url, &loadparm.Globals.szSAM_URL)
856 _PUBLIC_ FN_GLOBAL_STRING(lp_secrets_url, &loadparm.Globals.szSECRETS_URL)
857 _PUBLIC_ FN_GLOBAL_STRING(lp_spoolss_url, &loadparm.Globals.szSPOOLSS_URL)
858 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_config_url, &loadparm.Globals.szWINS_CONFIG_URL)
859 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_url, &loadparm.Globals.szWINS_URL)
860 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_winbind_separator, &loadparm.Globals.szWinbindSeparator)
861 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_winbindd_socket_directory, &loadparm.Globals.szWinbinddSocketDirectory)
862 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_template_shell, &loadparm.Globals.szTemplateShell)
863 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_template_homedir, &loadparm.Globals.szTemplateHomedir)
864 _PUBLIC_ FN_GLOBAL_BOOL(lp_winbind_sealed_pipes, &loadparm.Globals.bWinbindSealedPipes)
865 _PUBLIC_ FN_GLOBAL_STRING(lp_private_dir, &loadparm.Globals.szPrivateDir)
866 _PUBLIC_ FN_GLOBAL_STRING(lp_serverstring, &loadparm.Globals.szServerString)
867 _PUBLIC_ FN_GLOBAL_STRING(lp_lockdir, &loadparm.Globals.szLockDir)
868 _PUBLIC_ FN_GLOBAL_STRING(lp_modulesdir, &loadparm.Globals.szModulesDir)
869 _PUBLIC_ FN_GLOBAL_STRING(lp_setupdir, &loadparm.Globals.szSetupDir)
870 _PUBLIC_ FN_GLOBAL_STRING(lp_ncalrpc_dir, &loadparm.Globals.ncalrpc_dir)
871 _PUBLIC_ FN_GLOBAL_STRING(lp_piddir, &loadparm.Globals.szPidDir)
872 _PUBLIC_ FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, &loadparm.Globals.dcerpc_ep_servers)
873 _PUBLIC_ FN_GLOBAL_LIST(lp_server_services, &loadparm.Globals.server_services)
874 _PUBLIC_ FN_GLOBAL_STRING(lp_ntptr_providor, &loadparm.Globals.ntptr_providor)
875 _PUBLIC_ FN_GLOBAL_STRING(lp_auto_services, &loadparm.Globals.szAutoServices)
876 _PUBLIC_ FN_GLOBAL_STRING(lp_passwd_chat, &loadparm.Globals.szPasswdChat)
877 _PUBLIC_ FN_GLOBAL_LIST(lp_passwordserver, &loadparm.Globals.szPasswordServers)
878 _PUBLIC_ FN_GLOBAL_LIST(lp_name_resolve_order, &loadparm.Globals.szNameResolveOrder)
879 _PUBLIC_ FN_GLOBAL_STRING(lp_realm, &loadparm.Globals.szRealm)
880 _PUBLIC_ FN_GLOBAL_STRING(lp_socket_options, &loadparm.Globals.socket_options)
881 _PUBLIC_ FN_GLOBAL_STRING(lp_workgroup, &loadparm.Globals.szWorkgroup)
882 _PUBLIC_ FN_GLOBAL_STRING(lp_netbios_name, &loadparm.Globals.szNetbiosName)
883 _PUBLIC_ FN_GLOBAL_STRING(lp_netbios_scope, &loadparm.Globals.szNetbiosScope)
884 _PUBLIC_ FN_GLOBAL_LIST(lp_wins_server_list, &loadparm.Globals.szWINSservers)
885 _PUBLIC_ FN_GLOBAL_LIST(lp_interfaces, &loadparm.Globals.szInterfaces)
886 _PUBLIC_ FN_GLOBAL_STRING(lp_socket_address, &loadparm.Globals.szSocketAddress)
887 _PUBLIC_ FN_GLOBAL_LIST(lp_netbios_aliases, &loadparm.Globals.szNetbiosAliases)
889 _PUBLIC_ FN_GLOBAL_BOOL(lp_disable_netbios, &loadparm.Globals.bDisableNetbios)
890 _PUBLIC_ FN_GLOBAL_BOOL(lp_wins_support, &loadparm.Globals.bWINSsupport)
891 _PUBLIC_ FN_GLOBAL_BOOL(lp_wins_dns_proxy, &loadparm.Globals.bWINSdnsProxy)
892 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_hook, &loadparm.Globals.szWINSHook)
893 _PUBLIC_ FN_GLOBAL_BOOL(lp_local_master, &loadparm.Globals.bLocalMaster)
894 _PUBLIC_ FN_GLOBAL_BOOL(lp_readraw, &loadparm.Globals.bReadRaw)
895 _PUBLIC_ FN_GLOBAL_BOOL(lp_large_readwrite, &loadparm.Globals.bLargeReadwrite)
896 _PUBLIC_ FN_GLOBAL_BOOL(lp_writeraw, &loadparm.Globals.bWriteRaw)
897 _PUBLIC_ FN_GLOBAL_BOOL(lp_null_passwords, &loadparm.Globals.bNullPasswords)
898 _PUBLIC_ FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &loadparm.Globals.bObeyPamRestrictions)
899 _PUBLIC_ FN_GLOBAL_BOOL(lp_encrypted_passwords, &loadparm.Globals.bEncryptPasswords)
900 _PUBLIC_ FN_GLOBAL_BOOL(lp_time_server, &loadparm.Globals.bTimeServer)
901 _PUBLIC_ FN_GLOBAL_BOOL(lp_bind_interfaces_only, &loadparm.Globals.bBindInterfacesOnly)
902 _PUBLIC_ FN_GLOBAL_BOOL(lp_unicode, &loadparm.Globals.bUnicode)
903 _PUBLIC_ FN_GLOBAL_BOOL(lp_nt_status_support, &loadparm.Globals.bNTStatusSupport)
904 _PUBLIC_ FN_GLOBAL_BOOL(lp_lanman_auth, &loadparm.Globals.bLanmanAuth)
905 _PUBLIC_ FN_GLOBAL_BOOL(lp_ntlm_auth, &loadparm.Globals.bNTLMAuth)
906 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_plaintext_auth, &loadparm.Globals.bClientPlaintextAuth)
907 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_lanman_auth, &loadparm.Globals.bClientLanManAuth)
908 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &loadparm.Globals.bClientNTLMv2Auth)
909 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_use_spnego_principal, &loadparm.Globals.client_use_spnego_principal)
910 _PUBLIC_ FN_GLOBAL_BOOL(lp_host_msdfs, &loadparm.Globals.bHostMSDfs)
911 _PUBLIC_ FN_GLOBAL_BOOL(lp_unix_extensions, &loadparm.Globals.bUnixExtensions)
912 _PUBLIC_ FN_GLOBAL_BOOL(lp_use_spnego, &loadparm.Globals.bUseSpnego)
913 _PUBLIC_ FN_GLOBAL_BOOL(lp_rpc_big_endian, &loadparm.Globals.bRpcBigEndian)
914 _PUBLIC_ FN_GLOBAL_INTEGER(lp_max_wins_ttl, &loadparm.Globals.max_wins_ttl)
915 _PUBLIC_ FN_GLOBAL_INTEGER(lp_min_wins_ttl, &loadparm.Globals.min_wins_ttl)
916 _PUBLIC_ FN_GLOBAL_INTEGER(lp_maxmux, &loadparm.Globals.max_mux)
917 _PUBLIC_ FN_GLOBAL_INTEGER(lp_max_xmit, &loadparm.Globals.max_xmit)
918 _PUBLIC_ FN_GLOBAL_INTEGER(lp_passwordlevel, &loadparm.Globals.pwordlevel)
919 _PUBLIC_ FN_GLOBAL_INTEGER(lp_srv_maxprotocol, &loadparm.Globals.srv_maxprotocol)
920 _PUBLIC_ FN_GLOBAL_INTEGER(lp_srv_minprotocol, &loadparm.Globals.srv_minprotocol)
921 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cli_maxprotocol, &loadparm.Globals.cli_maxprotocol)
922 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cli_minprotocol, &loadparm.Globals.cli_minprotocol)
923 _PUBLIC_ FN_GLOBAL_INTEGER(lp_security, &loadparm.Globals.security)
924 _PUBLIC_ FN_GLOBAL_BOOL(lp_paranoid_server_security, &loadparm.Globals.paranoid_server_security)
925 _PUBLIC_ FN_GLOBAL_INTEGER(lp_announce_as, &loadparm.Globals.announce_as)
926 _PUBLIC_ FN_GLOBAL_LIST(lp_js_include, &loadparm.Globals.jsInclude)
927 _PUBLIC_ FN_GLOBAL_STRING(lp_jsonrpc_services_dir, &loadparm.Globals.jsonrpcServicesDir)
928 _PUBLIC_ FN_LOCAL_STRING(lp_servicename, szService)
929 _PUBLIC_ FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
930 _PUBLIC_ FN_LOCAL_STRING(lp_pathname, szPath)
931 static FN_LOCAL_STRING(_lp_printername, szPrintername)
932 _PUBLIC_ FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
933 _PUBLIC_ FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
934 _PUBLIC_ FN_LOCAL_STRING(lp_comment, comment)
935 _PUBLIC_ FN_LOCAL_STRING(lp_fstype, fstype)
936 static FN_LOCAL_STRING(lp_volume, volume)
937 _PUBLIC_ FN_LOCAL_LIST(lp_ntvfs_handler, ntvfs_handler)
938 _PUBLIC_ FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
939 _PUBLIC_ FN_LOCAL_BOOL(lp_browseable, bBrowseable)
940 _PUBLIC_ FN_LOCAL_BOOL(lp_readonly, bRead_only)
941 _PUBLIC_ FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
942 _PUBLIC_ FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
943 _PUBLIC_ FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
944 _PUBLIC_ FN_LOCAL_BOOL(lp_strict_locking, bStrictLocking)
945 _PUBLIC_ FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
946 _PUBLIC_ FN_LOCAL_BOOL(lp_ci_filesystem, bCIFileSystem)
947 _PUBLIC_ FN_LOCAL_BOOL(lp_map_system, bMap_system)
948 _PUBLIC_ FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
949 _PUBLIC_ FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
950 _PUBLIC_ FN_LOCAL_INTEGER(lp_create_mask, iCreate_mask)
951 _PUBLIC_ FN_LOCAL_INTEGER(lp_force_create_mode, iCreate_force_mode)
952 _PUBLIC_ FN_LOCAL_INTEGER(lp_dir_mask, iDir_mask)
953 _PUBLIC_ FN_LOCAL_INTEGER(lp_force_dir_mode, iDir_force_mode)
954 _PUBLIC_ FN_GLOBAL_INTEGER(lp_server_signing, &loadparm.Globals.server_signing)
955 _PUBLIC_ FN_GLOBAL_INTEGER(lp_client_signing, &loadparm.Globals.client_signing)
957 /* local prototypes */
959 static int map_parameter(const char *pszParmName);
960 static int getservicebyname(const char *pszServiceName,
961 struct service * pserviceDest);
962 static void copy_service(struct service * pserviceDest,
963 struct service * pserviceSource, int *pcopymapDest);
964 static bool service_ok(int iService);
965 static bool do_section(const char *pszSectionName, void *);
966 static void init_copymap(struct service * pservice);
968 /* This is a helper function for parametrical options support. */
969 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
970 /* Actual parametrical functions are quite simple */
971 const char *lp_get_parametric(int lookup_service, const char *type, const char *option)
974 struct param_opt *data;
976 if (lookup_service >= 0 && !LP_SNUM_OK(lookup_service))
979 data = (lookup_service < 0) ?
980 loadparm.Globals.param_opt : loadparm.ServicePtrs[lookup_service]->param_opt;
982 asprintf(&vfskey, "%s:%s", type, option);
986 if (strcmp(data->key, vfskey) == 0) {
993 if (lookup_service >= 0) {
994 /* Try to fetch the same option but from globals */
995 /* but only if we are not already working with Globals */
996 for (data = loadparm.Globals.param_opt; data;
998 if (strcmp(data->key, vfskey) == 0) {
1011 /*******************************************************************
1012 convenience routine to return int parameters.
1013 ********************************************************************/
1014 static int lp_int(const char *s)
1018 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
1022 return strtol(s, NULL, 0);
1025 /*******************************************************************
1026 convenience routine to return unsigned long parameters.
1027 ********************************************************************/
1028 static int lp_ulong(const char *s)
1032 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
1036 return strtoul(s, NULL, 0);
1039 /*******************************************************************
1040 convenience routine to return unsigned long parameters.
1041 ********************************************************************/
1042 static double lp_double(const char *s)
1046 DEBUG(0,("lp_double(%s): is called with NULL!\n",s));
1050 return strtod(s, NULL);
1053 /*******************************************************************
1054 convenience routine to return boolean parameters.
1055 ********************************************************************/
1056 static bool lp_bool(const char *s)
1061 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
1065 if (!set_boolean(s, &ret)) {
1066 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1074 /* Return parametric option from a given service. Type is a part of option before ':' */
1075 /* Parametric option has following syntax: 'Type: option = value' */
1076 /* Returned value is allocated in 'lp_talloc' context */
1078 const char *lp_parm_string(int lookup_service, const char *type, const char *option)
1080 const char *value = lp_get_parametric(lookup_service, type, option);
1083 return lp_string(value);
1088 /* Return parametric option from a given service. Type is a part of option before ':' */
1089 /* Parametric option has following syntax: 'Type: option = value' */
1090 /* Returned value is allocated in 'lp_talloc' context */
1092 const char **lp_parm_string_list(int lookup_service, const char *type, const char *option,
1093 const char *separator)
1095 const char *value = lp_get_parametric(lookup_service, type, option);
1098 return str_list_make(talloc_autofree_context(), value, separator);
1103 /* Return parametric option from a given service. Type is a part of option before ':' */
1104 /* Parametric option has following syntax: 'Type: option = value' */
1106 int lp_parm_int(int lookup_service, const char *type, const char *option, int default_v)
1108 const char *value = lp_get_parametric(lookup_service, type, option);
1111 return lp_int(value);
1116 /* Return parametric option from a given service. Type is a part of
1117 * option before ':'.
1118 * Parametric option has following syntax: 'Type: option = value'.
1121 int lp_parm_bytes(int lookup_service, const char *type, const char *option, int default_v)
1125 const char *value = lp_get_parametric(lookup_service, type, option);
1127 if (value && conv_str_size(value, &bval)) {
1128 if (bval <= INT_MAX) {
1136 /* Return parametric option from a given service. Type is a part of option before ':' */
1137 /* Parametric option has following syntax: 'Type: option = value' */
1139 unsigned long lp_parm_ulong(int lookup_service, const char *type, const char *option, unsigned long default_v)
1141 const char *value = lp_get_parametric(lookup_service, type, option);
1144 return lp_ulong(value);
1150 double lp_parm_double(int lookup_service, const char *type, const char *option, double default_v)
1152 const char *value = lp_get_parametric(lookup_service, type, option);
1155 return lp_double(value);
1160 /* Return parametric option from a given service. Type is a part of option before ':' */
1161 /* Parametric option has following syntax: 'Type: option = value' */
1163 bool lp_parm_bool(int lookup_service, const char *type, const char *option,
1166 const char *value = lp_get_parametric(lookup_service, type, option);
1169 return lp_bool(value);
1175 /***************************************************************************
1176 Initialise a service to the defaults.
1177 ***************************************************************************/
1179 static struct service *init_service(TALLOC_CTX *mem_ctx)
1181 struct service *pservice = talloc_zero(mem_ctx, struct service);
1182 copy_service(pservice, &sDefault, NULL);
1186 void string_free(char **str)
1194 /***************************************************************************
1195 Add a new service to the services array initialising it with the given
1197 ***************************************************************************/
1199 static int add_a_service(const struct service *pservice, const char *name)
1202 struct service tservice;
1203 int num_to_alloc = loadparm.iNumServices + 1;
1204 struct param_opt *data, *pdata;
1206 tservice = *pservice;
1208 /* it might already exist */
1210 i = getservicebyname(name, NULL);
1212 /* Clean all parametric options for service */
1213 /* They will be added during parsing again */
1214 data = loadparm.ServicePtrs[i]->param_opt;
1220 loadparm.ServicePtrs[i]->param_opt = NULL;
1225 /* find an invalid one */
1226 for (i = 0; i < loadparm.iNumServices; i++)
1227 if (loadparm.ServicePtrs[i] == NULL)
1230 /* if not, then create one */
1231 if (i == loadparm.iNumServices) {
1232 struct service **tsp;
1234 tsp = realloc_p(loadparm.ServicePtrs, struct service *, num_to_alloc);
1237 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1241 loadparm.ServicePtrs = tsp;
1242 loadparm.ServicePtrs[loadparm.iNumServices] = NULL;
1245 loadparm.iNumServices++;
1248 loadparm.ServicePtrs[i] = init_service(talloc_autofree_context());
1249 if (loadparm.ServicePtrs[i] == NULL) {
1250 DEBUG(0,("add_a_service: out of memory!\n"));
1253 copy_service(loadparm.ServicePtrs[i], &tservice, NULL);
1255 string_set(loadparm.ServicePtrs[i], &loadparm.ServicePtrs[i]->szService, name);
1259 /***************************************************************************
1260 Add a new home service, with the specified home directory, defaults coming
1262 ***************************************************************************/
1264 bool lp_add_home(const char *pszHomename, int iDefaultService,
1265 const char *user, const char *pszHomedir)
1270 i = add_a_service(loadparm.ServicePtrs[iDefaultService], pszHomename);
1275 if (!(*(loadparm.ServicePtrs[iDefaultService]->szPath))
1276 || strequal(loadparm.ServicePtrs[iDefaultService]->szPath, lp_pathname(-1))) {
1277 pstrcpy(newHomedir, pszHomedir);
1279 pstrcpy(newHomedir, lp_pathname(iDefaultService));
1280 string_sub(newHomedir,"%H", pszHomedir, sizeof(newHomedir));
1283 string_set(loadparm.ServicePtrs[i], &loadparm.ServicePtrs[i]->szPath, newHomedir);
1285 if (!(*(loadparm.ServicePtrs[i]->comment))) {
1286 loadparm.ServicePtrs[i]->comment = talloc_asprintf(loadparm.ServicePtrs[i], "Home directory of %s", user);
1288 loadparm.ServicePtrs[i]->bAvailable = sDefault.bAvailable;
1289 loadparm.ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1291 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1297 /***************************************************************************
1298 Add a new service, based on an old one.
1299 ***************************************************************************/
1301 int lp_add_service(const char *pszService, int iDefaultService)
1303 return add_a_service(loadparm.ServicePtrs[iDefaultService], pszService);
1306 /***************************************************************************
1307 Add the IPC service.
1308 ***************************************************************************/
1310 static bool lp_add_hidden(const char *name, const char *fstype)
1312 int i = add_a_service(&sDefault, name);
1313 struct service *service = loadparm.ServicePtrs[i];
1318 string_set(service, &service->szPath, tmpdir());
1320 service->comment = talloc_asprintf(service, "%s Service (%s)",
1321 fstype, loadparm.Globals.szServerString);
1322 string_set(service, &service->fstype, fstype);
1323 service->iMaxConnections = -1;
1324 service->bAvailable = true;
1325 service->bRead_only = true;
1326 service->bPrint_ok = false;
1327 service->bBrowseable = false;
1329 if (strcasecmp(fstype, "IPC") == 0) {
1330 lp_do_parameter(i, "ntvfs handler", "default");
1333 DEBUG(3, ("adding hidden service %s\n", name));
1338 /***************************************************************************
1339 Add a new printer service, with defaults coming from service iFrom.
1340 ***************************************************************************/
1342 bool lp_add_printer(const char *pszPrintername, int iDefaultService)
1344 const char *comment = "From Printcap";
1345 int i = add_a_service(loadparm.ServicePtrs[iDefaultService],
1351 /* note that we do NOT default the availability flag to True - */
1352 /* we take it from the default service passed. This allows all */
1353 /* dynamic printers to be disabled by disabling the [printers] */
1354 /* entry (if/when the 'available' keyword is implemented!). */
1356 /* the printer name is set to the service name. */
1357 string_set(loadparm.ServicePtrs[i], &loadparm.ServicePtrs[i]->szPrintername,
1359 string_set(loadparm.ServicePtrs[i], &loadparm.ServicePtrs[i]->comment, comment);
1360 loadparm.ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1361 /* Printers cannot be read_only. */
1362 loadparm.ServicePtrs[i]->bRead_only = False;
1363 /* Printer services must be printable. */
1364 loadparm.ServicePtrs[i]->bPrint_ok = True;
1366 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1371 /***************************************************************************
1372 Map a parameter's string representation to something we can use.
1373 Returns False if the parameter string is not recognised, else TRUE.
1374 ***************************************************************************/
1376 static int map_parameter(const char *pszParmName)
1380 if (*pszParmName == '-')
1383 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1384 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1387 /* Warn only if it isn't parametric option */
1388 if (strchr(pszParmName, ':') == NULL)
1389 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1390 /* We do return 'fail' for parametric options as well because they are
1391 stored in different storage
1398 return the parameter structure for a parameter
1400 struct parm_struct *lp_parm_struct(const char *name)
1402 int parmnum = map_parameter(name);
1403 if (parmnum == -1) return NULL;
1404 return &parm_table[parmnum];
1408 return the parameter pointer for a parameter
1410 void *lp_parm_ptr(int snum, struct parm_struct *parm)
1415 return ((char *)loadparm.ServicePtrs[snum]) + PTR_DIFF(parm->ptr, &sDefault);
1418 /***************************************************************************
1419 Find a service by name. Otherwise works like get_service.
1420 ***************************************************************************/
1422 static int getservicebyname(const char *pszServiceName,
1423 struct service * pserviceDest)
1427 for (iService = loadparm.iNumServices - 1; iService >= 0; iService--)
1428 if (VALID(iService) &&
1429 strwicmp(loadparm.ServicePtrs[iService]->szService, pszServiceName) == 0) {
1430 if (pserviceDest != NULL)
1431 copy_service(pserviceDest, loadparm.ServicePtrs[iService], NULL);
1438 /***************************************************************************
1439 Copy a service structure to another.
1440 If pcopymapDest is NULL then copy all fields
1441 ***************************************************************************/
1443 static void copy_service(struct service *pserviceDest,
1444 struct service *pserviceSource,
1448 bool bcopyall = (pcopymapDest == NULL);
1449 struct param_opt *data, *pdata, *paramo;
1452 for (i = 0; parm_table[i].label; i++)
1453 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1454 (bcopyall || pcopymapDest[i])) {
1455 void *def_ptr = parm_table[i].ptr;
1457 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
1460 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
1463 switch (parm_table[i].type) {
1465 *(int *)dest_ptr = *(int *)src_ptr;
1471 *(int *)dest_ptr = *(int *)src_ptr;
1475 string_set(pserviceDest, dest_ptr,
1480 string_set(pserviceDest, dest_ptr,
1482 strupper(*(char **)dest_ptr);
1485 *(const char ***)dest_ptr = str_list_copy(talloc_autofree_context(),
1486 *(const char ***)src_ptr);
1494 init_copymap(pserviceDest);
1495 if (pserviceSource->copymap)
1496 memcpy((void *)pserviceDest->copymap,
1497 (void *)pserviceSource->copymap,
1498 sizeof(int) * NUMPARAMETERS);
1501 data = pserviceSource->param_opt;
1504 pdata = pserviceDest->param_opt;
1505 /* Traverse destination */
1507 /* If we already have same option, override it */
1508 if (strcmp(pdata->key, data->key) == 0) {
1509 string_free(&pdata->value);
1510 pdata->value = talloc_reference(pdata,
1515 pdata = pdata->next;
1518 paramo = talloc(pserviceDest, struct param_opt);
1521 paramo->key = talloc_reference(paramo, data->key);
1522 paramo->value = talloc_reference(paramo, data->value);
1523 DLIST_ADD(pserviceDest->param_opt, paramo);
1529 /***************************************************************************
1530 Check a service for consistency. Return False if the service is in any way
1531 incomplete or faulty, else True.
1532 ***************************************************************************/
1534 static bool service_ok(int iService)
1539 if (loadparm.ServicePtrs[iService]->szService[0] == '\0') {
1540 DEBUG(0, ("The following message indicates an internal error:\n"));
1541 DEBUG(0, ("No service name in service entry.\n"));
1545 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1546 /* I can't see why you'd want a non-printable printer service... */
1547 if (strwicmp(loadparm.ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
1548 if (!loadparm.ServicePtrs[iService]->bPrint_ok) {
1549 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
1550 loadparm.ServicePtrs[iService]->szService));
1551 loadparm.ServicePtrs[iService]->bPrint_ok = True;
1553 /* [printers] service must also be non-browsable. */
1554 if (loadparm.ServicePtrs[iService]->bBrowseable)
1555 loadparm.ServicePtrs[iService]->bBrowseable = False;
1558 /* If a service is flagged unavailable, log the fact at level 0. */
1559 if (!loadparm.ServicePtrs[iService]->bAvailable)
1560 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
1561 loadparm.ServicePtrs[iService]->szService));
1566 static struct file_lists {
1567 struct file_lists *next;
1571 } *file_lists = NULL;
1573 /*******************************************************************
1574 Keep a linked list of all config files so we know when one has changed
1575 it's date and needs to be reloaded.
1576 ********************************************************************/
1578 static void add_to_file_list(const char *fname, const char *subfname)
1580 struct file_lists *f = file_lists;
1583 if (f->name && !strcmp(f->name, fname))
1589 f = talloc(talloc_autofree_context(), struct file_lists);
1592 f->next = file_lists;
1593 f->name = talloc_strdup(f, fname);
1598 f->subfname = talloc_strdup(f, subfname);
1604 f->modtime = file_modtime(subfname);
1606 time_t t = file_modtime(subfname);
1612 /*******************************************************************
1613 Check if a config file has changed date.
1614 ********************************************************************/
1616 BOOL lp_file_list_changed(void)
1618 struct file_lists *f = file_lists;
1619 DEBUG(6, ("lp_file_list_changed()\n"));
1625 n2 = standard_sub_basic(talloc_autofree_context(), f->name);
1627 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
1628 f->name, n2, ctime(&f->modtime)));
1630 mod_time = file_modtime(n2);
1632 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
1634 ("file %s modified: %s\n", n2,
1636 f->modtime = mod_time;
1637 talloc_free(f->subfname);
1638 f->subfname = talloc_strdup(f, n2);
1646 /***************************************************************************
1647 Handle the include operation.
1648 ***************************************************************************/
1650 static bool handle_include(const char *pszParmValue, char **ptr)
1652 char *fname = standard_sub_basic(talloc_autofree_context(),
1655 add_to_file_list(pszParmValue, fname);
1657 string_set(talloc_autofree_context(), ptr, fname);
1659 if (file_exist(fname))
1660 return pm_process(fname, do_section, do_parameter, NULL);
1662 DEBUG(2, ("Can't find include file %s\n", fname));
1667 /***************************************************************************
1668 Handle the interpretation of the copy parameter.
1669 ***************************************************************************/
1671 static bool handle_copy(const char *pszParmValue, char **ptr)
1675 struct service *serviceTemp;
1677 string_set(talloc_autofree_context(), ptr, pszParmValue);
1679 serviceTemp = init_service(talloc_autofree_context());
1683 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
1685 if ((iTemp = getservicebyname(pszParmValue, serviceTemp)) >= 0) {
1686 if (iTemp == loadparm.iServiceIndex) {
1687 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
1689 copy_service(loadparm.ServicePtrs[loadparm.iServiceIndex],
1691 loadparm.ServicePtrs[loadparm.iServiceIndex]->copymap);
1695 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
1699 talloc_free(serviceTemp);
1703 /***************************************************************************
1704 Initialise a copymap.
1705 ***************************************************************************/
1707 static void init_copymap(struct service *pservice)
1710 talloc_free(pservice->copymap);
1711 pservice->copymap = talloc_array(pservice, int, NUMPARAMETERS);
1712 if (pservice->copymap == NULL) {
1714 ("Couldn't allocate copymap!! (size %d)\n",
1715 (int)NUMPARAMETERS));
1718 for (i = 0; i < NUMPARAMETERS; i++)
1719 pservice->copymap[i] = true;
1722 #if 0 /* not used anywhere */
1723 /***************************************************************************
1724 Return the local pointer to a parameter given the service number and the
1725 pointer into the default structure.
1726 ***************************************************************************/
1728 void *lp_local_ptr(int snum, void *ptr)
1730 return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
1734 /***************************************************************************
1735 Process a parametric option
1736 ***************************************************************************/
1737 static bool lp_do_parameter_parametric(int snum, const char *pszParmName,
1738 const char *pszParmValue, int flags)
1740 struct param_opt *paramo, *data;
1742 TALLOC_CTX *mem_ctx;
1744 while (isspace((unsigned char)*pszParmName)) {
1748 name = strdup(pszParmName);
1749 if (!name) return False;
1754 data = loadparm.Globals.param_opt;
1755 mem_ctx = talloc_autofree_context();
1757 data = loadparm.ServicePtrs[snum]->param_opt;
1758 mem_ctx = loadparm.ServicePtrs[snum];
1761 /* Traverse destination */
1762 for (paramo=data; paramo; paramo=paramo->next) {
1763 /* If we already have the option set, override it unless
1764 it was a command line option and the new one isn't */
1765 if (strcmp(paramo->key, name) == 0) {
1766 if ((paramo->flags & FLAG_CMDLINE) &&
1767 !(flags & FLAG_CMDLINE)) {
1771 talloc_free(paramo->value);
1772 paramo->value = talloc_strdup(paramo, pszParmValue);
1773 paramo->flags = flags;
1779 paramo = talloc(mem_ctx, struct param_opt);
1782 paramo->key = talloc_strdup(paramo, name);
1783 paramo->value = talloc_strdup(paramo, pszParmValue);
1784 paramo->flags = flags;
1786 DLIST_ADD(loadparm.Globals.param_opt, paramo);
1788 DLIST_ADD(loadparm.ServicePtrs[snum]->param_opt, paramo);
1796 /***************************************************************************
1797 Process a parameter for a particular service number. If snum < 0
1798 then assume we are in the globals.
1799 ***************************************************************************/
1800 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
1803 void *parm_ptr = NULL; /* where we are going to store the result */
1804 void *def_ptr = NULL;
1805 TALLOC_CTX *mem_ctx;
1807 parmnum = map_parameter(pszParmName);
1810 if (strchr(pszParmName, ':')) {
1811 return lp_do_parameter_parametric(snum, pszParmName, pszParmValue, 0);
1813 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1817 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1818 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1822 /* if the flag has been set on the command line, then don't allow override,
1823 but don't report an error */
1824 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1828 def_ptr = parm_table[parmnum].ptr;
1830 /* we might point at a service, the default service or a global */
1833 mem_ctx = talloc_autofree_context();
1835 if (parm_table[parmnum].class == P_GLOBAL) {
1837 ("Global parameter %s found in service section!\n",
1842 ((char *)loadparm.ServicePtrs[snum]) + PTR_DIFF(def_ptr,
1844 mem_ctx = loadparm.ServicePtrs[snum];
1848 if (!loadparm.ServicePtrs[snum]->copymap)
1849 init_copymap(loadparm.ServicePtrs[snum]);
1851 /* this handles the aliases - set the copymap for other entries with
1852 the same data pointer */
1853 for (i = 0; parm_table[i].label; i++)
1854 if (parm_table[i].ptr == parm_table[parmnum].ptr)
1855 loadparm.ServicePtrs[snum]->copymap[i] = false;
1858 /* if it is a special case then go ahead */
1859 if (parm_table[parmnum].special) {
1860 parm_table[parmnum].special(pszParmValue, (char **)parm_ptr);
1864 /* now switch on the type of variable it is */
1865 switch (parm_table[parmnum].type)
1869 if (!set_boolean(pszParmValue, &b)) {
1870 DEBUG(0,("lp_do_parameter(%s): value is not boolean!\n", pszParmValue));
1873 *(int *)parm_ptr = b;
1878 *(int *)parm_ptr = atoi(pszParmValue);
1882 *(int *)parm_ptr = strtol(pszParmValue, NULL, 8);
1888 if (conv_str_size(pszParmValue, &val)) {
1889 if (val <= INT_MAX) {
1890 *(int *)parm_ptr = (int)val;
1895 DEBUG(0,("lp_do_parameter(%s): value is not "
1896 "a valid size specifier!\n", pszParmValue));
1901 *(const char ***)parm_ptr = str_list_make(mem_ctx,
1902 pszParmValue, NULL);
1906 string_set(mem_ctx, parm_ptr, pszParmValue);
1910 string_set(mem_ctx, parm_ptr, pszParmValue);
1911 strupper(*(char **)parm_ptr);
1915 for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
1918 parm_table[parmnum].enum_list[i].name)) {
1920 parm_table[parmnum].
1925 if (!parm_table[parmnum].enum_list[i].name) {
1926 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n",
1927 pszParmValue, pszParmName));
1935 if (parm_table[parmnum].flags & FLAG_DEFAULT) {
1936 parm_table[parmnum].flags &= ~FLAG_DEFAULT;
1937 /* we have to also unset FLAG_DEFAULT on aliases */
1938 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1939 parm_table[i].flags &= ~FLAG_DEFAULT;
1941 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1942 parm_table[i].flags &= ~FLAG_DEFAULT;
1949 /***************************************************************************
1950 Process a parameter.
1951 ***************************************************************************/
1953 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue, void *userdata)
1955 return lp_do_parameter(loadparm.bInGlobalSection ? -2 : loadparm.iServiceIndex,
1956 pszParmName, pszParmValue);
1960 variable argument do parameter
1962 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
1964 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...)
1971 s = talloc_vasprintf(NULL, fmt, ap);
1973 ret = do_parameter(pszParmName, s, NULL);
1980 set a parameter from the commandline - this is called from command line parameter
1981 parsing code. It sets the parameter then marks the parameter as unable to be modified
1982 by smb.conf processing
1984 BOOL lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
1986 int parmnum = map_parameter(pszParmName);
1989 while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
1992 if (parmnum < 0 && strchr(pszParmName, ':')) {
1993 /* set a parametric option */
1994 return lp_do_parameter_parametric(-1, pszParmName, pszParmValue, FLAG_CMDLINE);
1998 DEBUG(0,("Unknown option '%s'\n", pszParmName));
2002 /* reset the CMDLINE flag in case this has been called before */
2003 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
2005 if (!lp_do_parameter(-2, pszParmName, pszParmValue)) {
2009 parm_table[parmnum].flags |= FLAG_CMDLINE;
2011 /* we have to also set FLAG_CMDLINE on aliases */
2012 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
2013 parm_table[i].flags |= FLAG_CMDLINE;
2015 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
2016 parm_table[i].flags |= FLAG_CMDLINE;
2023 set a option from the commandline in 'a=b' format. Use to support --option
2025 BOOL lp_set_option(const char *option)
2043 ret = lp_set_cmdline(s, p+1);
2049 #define BOOLSTR(b) ((b) ? "Yes" : "No")
2051 /***************************************************************************
2052 Print a parameter of the specified type.
2053 ***************************************************************************/
2055 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
2061 for (i = 0; p->enum_list[i].name; i++) {
2062 if (*(int *)ptr == p->enum_list[i].value) {
2064 p->enum_list[i].name);
2071 fprintf(f, "%s", BOOLSTR((BOOL)*(int *)ptr));
2076 fprintf(f, "%d", *(int *)ptr);
2080 fprintf(f, "0%o", *(int *)ptr);
2084 if ((char ***)ptr && *(char ***)ptr) {
2085 char **list = *(char ***)ptr;
2087 for (; *list; list++)
2088 fprintf(f, "%s%s", *list,
2089 ((*(list+1))?", ":""));
2095 if (*(char **)ptr) {
2096 fprintf(f, "%s", *(char **)ptr);
2104 /***************************************************************************
2105 Check if two parameters are equal.
2106 ***************************************************************************/
2108 static BOOL equal_parameter(parm_type type, void *ptr1, void *ptr2)
2112 return (*((int *)ptr1) == *((int *)ptr2));
2118 return (*((int *)ptr1) == *((int *)ptr2));
2121 return str_list_equal((const char **)(*(char ***)ptr1),
2122 (const char **)(*(char ***)ptr2));
2127 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
2132 return (p1 == p2 || strequal(p1, p2));
2140 /***************************************************************************
2141 Process a new section (service). At this stage all sections are services.
2142 Later we'll have special sections that permit server parameters to be set.
2143 Returns True on success, False on failure.
2144 ***************************************************************************/
2146 static BOOL do_section(const char *pszSectionName, void *userdata)
2149 BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2150 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2153 /* if we've just struck a global section, note the fact. */
2154 loadparm.bInGlobalSection = isglobal;
2156 /* check for multiple global sections */
2157 if (loadparm.bInGlobalSection) {
2158 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2162 /* if we have a current service, tidy it up before moving on */
2165 if (loadparm.iServiceIndex >= 0)
2166 bRetval = service_ok(loadparm.iServiceIndex);
2168 /* if all is still well, move to the next record in the services array */
2170 /* We put this here to avoid an odd message order if messages are */
2171 /* issued by the post-processing of a previous section. */
2172 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2174 if ((loadparm.iServiceIndex = add_a_service(&sDefault, pszSectionName))
2176 DEBUG(0, ("Failed to add a new service\n"));
2185 /***************************************************************************
2186 Determine if a partcular base parameter is currentl set to the default value.
2187 ***************************************************************************/
2189 static BOOL is_default(int i)
2191 if (!defaults_saved)
2193 switch (parm_table[i].type) {
2195 return str_list_equal((const char **)parm_table[i].def.lvalue,
2196 (const char **)(*(char ***)parm_table[i].ptr));
2199 return strequal(parm_table[i].def.svalue,
2200 *(char **)parm_table[i].ptr);
2202 return parm_table[i].def.bvalue ==
2203 *(int *)parm_table[i].ptr;
2208 return parm_table[i].def.ivalue ==
2209 *(int *)parm_table[i].ptr;
2216 /***************************************************************************
2217 Display the contents of the global structure.
2218 ***************************************************************************/
2220 static void dump_globals(FILE *f, BOOL show_defaults)
2223 struct param_opt *data;
2225 fprintf(f, "# Global parameters\n[global]\n");
2227 for (i = 0; parm_table[i].label; i++)
2228 if (parm_table[i].class == P_GLOBAL &&
2229 parm_table[i].ptr &&
2230 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2231 if (!show_defaults && (parm_table[i].flags & FLAG_DEFAULT))
2233 fprintf(f, "\t%s = ", parm_table[i].label);
2234 print_parameter(&parm_table[i], parm_table[i].ptr, f);
2237 if (loadparm.Globals.param_opt != NULL) {
2238 for (data = loadparm.Globals.param_opt; data;
2239 data = data->next) {
2240 fprintf(f, "\t%s = %s\n", data->key, data->value);
2246 /***************************************************************************
2247 Display the contents of a single services record.
2248 ***************************************************************************/
2250 static void dump_a_service(struct service * pService, FILE * f)
2253 struct param_opt *data;
2255 if (pService != &sDefault)
2256 fprintf(f, "\n[%s]\n", pService->szService);
2258 for (i = 0; parm_table[i].label; i++)
2259 if (parm_table[i].class == P_LOCAL &&
2260 parm_table[i].ptr &&
2261 (*parm_table[i].label != '-') &&
2262 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2263 int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
2265 if (pService == &sDefault) {
2266 if (defaults_saved && is_default(i))
2269 if (equal_parameter(parm_table[i].type,
2270 ((char *)pService) +
2272 ((char *)&sDefault) +
2277 fprintf(f, "\t%s = ", parm_table[i].label);
2278 print_parameter(&parm_table[i],
2279 ((char *)pService) + pdiff, f);
2282 if (pService->param_opt != NULL) {
2283 for (data = pService->param_opt; data; data = data->next) {
2284 fprintf(f, "\t%s = %s\n", data->key, data->value);
2289 bool lp_dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
2291 struct service * pService = loadparm.ServicePtrs[snum];
2292 struct parm_struct *parm;
2295 parm = lp_parm_struct(parm_name);
2303 ptr = ((char *)pService) +
2304 PTR_DIFF(parm->ptr, &sDefault);
2306 print_parameter(parm,
2312 /***************************************************************************
2313 Return info about the next service in a service. snum==-1 gives the globals.
2314 Return NULL when out of parameters.
2315 ***************************************************************************/
2317 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
2320 /* do the globals */
2321 for (; parm_table[*i].label; (*i)++) {
2322 if (parm_table[*i].class == P_SEPARATOR)
2323 return &parm_table[(*i)++];
2325 if (!parm_table[*i].ptr
2326 || (*parm_table[*i].label == '-'))
2330 && (parm_table[*i].ptr ==
2331 parm_table[(*i) - 1].ptr))
2334 return &parm_table[(*i)++];
2337 struct service *pService = loadparm.ServicePtrs[snum];
2339 for (; parm_table[*i].label; (*i)++) {
2340 if (parm_table[*i].class == P_SEPARATOR)
2341 return &parm_table[(*i)++];
2343 if (parm_table[*i].class == P_LOCAL &&
2344 parm_table[*i].ptr &&
2345 (*parm_table[*i].label != '-') &&
2347 (parm_table[*i].ptr !=
2348 parm_table[(*i) - 1].ptr)))
2351 PTR_DIFF(parm_table[*i].ptr,
2354 if (allparameters ||
2355 !equal_parameter(parm_table[*i].type,
2356 ((char *)pService) +
2358 ((char *)&sDefault) +
2361 return &parm_table[(*i)++];
2371 /***************************************************************************
2372 Return TRUE if the passed service number is within range.
2373 ***************************************************************************/
2375 bool lp_snum_ok(int iService)
2377 return (LP_SNUM_OK(iService) && loadparm.ServicePtrs[iService]->bAvailable);
2380 /***************************************************************************
2381 Auto-load some home services.
2382 ***************************************************************************/
2384 static void lp_add_auto_services(const char *str)
2389 /***************************************************************************
2390 Have we loaded a services file yet?
2391 ***************************************************************************/
2393 BOOL lp_loaded(void)
2398 /***************************************************************************
2399 Unload unused services.
2400 ***************************************************************************/
2402 void lp_killunused(struct smbsrv_connection *smb, BOOL (*snumused) (struct smbsrv_connection *, int))
2405 for (i = 0; i < loadparm.iNumServices; i++) {
2409 if (!snumused || !snumused(smb, i)) {
2410 talloc_free(loadparm.ServicePtrs[i]);
2411 loadparm.ServicePtrs[i] = NULL;
2416 /***************************************************************************
2418 ***************************************************************************/
2420 void lp_killservice(int iServiceIn)
2422 if (VALID(iServiceIn)) {
2423 talloc_free(loadparm.ServicePtrs[iServiceIn]);
2424 loadparm.ServicePtrs[iServiceIn] = NULL;
2428 /***************************************************************************
2429 Load the services array from the services file. Return True on success,
2431 ***************************************************************************/
2437 struct param_opt *data;
2441 loadparm.bInGlobalSection = true;
2443 if (loadparm.Globals.param_opt != NULL) {
2444 struct param_opt *next;
2445 for (data=loadparm.Globals.param_opt; data; data=next) {
2447 if (data->flags & FLAG_CMDLINE) continue;
2448 DLIST_REMOVE(loadparm.Globals.param_opt, data);
2455 n2 = standard_sub_basic(talloc_autofree_context(), lp_configfile());
2456 DEBUG(2, ("lp_load: refreshing parameters from %s\n", n2));
2458 add_to_file_list(lp_configfile(), n2);
2460 /* We get sections first, so have to start 'behind' to make up */
2461 loadparm.iServiceIndex = -1;
2462 bRetval = pm_process(n2, do_section, do_parameter, NULL);
2464 /* finish up the last section */
2465 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
2467 if (loadparm.iServiceIndex >= 0)
2468 bRetval = service_ok(loadparm.iServiceIndex);
2470 lp_add_auto_services(lp_auto_services());
2472 lp_add_hidden("IPC$", "IPC");
2473 lp_add_hidden("ADMIN$", "DISK");
2477 if (!loadparm.Globals.szWINSservers && loadparm.Globals.bWINSsupport) {
2478 lp_do_parameter(-1, "wins server", "127.0.0.1");
2486 /***************************************************************************
2487 Reset the max number of services.
2488 ***************************************************************************/
2490 void lp_resetnumservices(void)
2492 loadparm.iNumServices = 0;
2495 /***************************************************************************
2496 Return the max number of services.
2497 ***************************************************************************/
2499 int lp_numservices(void)
2501 return loadparm.iNumServices;
2504 /***************************************************************************
2505 Display the contents of the services array in human-readable form.
2506 ***************************************************************************/
2508 void lp_dump(FILE *f, BOOL show_defaults, int maxtoprint)
2513 defaults_saved = False;
2515 dump_globals(f, show_defaults);
2517 dump_a_service(&sDefault, f);
2519 for (iService = 0; iService < maxtoprint; iService++)
2520 lp_dump_one(f, show_defaults, iService);
2523 /***************************************************************************
2524 Display the contents of one service in human-readable form.
2525 ***************************************************************************/
2527 void lp_dump_one(FILE *f, bool show_defaults, int snum)
2530 if (loadparm.ServicePtrs[snum]->szService[0] == '\0')
2532 dump_a_service(loadparm.ServicePtrs[snum], f);
2536 /***************************************************************************
2537 Return the number of the service with the given name, or -1 if it doesn't
2538 exist. Note that this is a DIFFERENT ANIMAL from the internal function
2539 getservicebyname()! This works ONLY if all services have been loaded, and
2540 does not copy the found service.
2541 ***************************************************************************/
2543 int lp_servicenumber(const char *pszServiceName)
2549 for (iService = loadparm.iNumServices - 1; iService >= 0; iService--) {
2550 if (VALID(iService) && loadparm.ServicePtrs[iService]->szService) {
2552 * The substitution here is used to support %U is
2555 serviceName = standard_sub_basic(loadparm.ServicePtrs[iService],
2556 loadparm.ServicePtrs[iService]->szService);
2557 if (strequal(serviceName, pszServiceName))
2563 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
2568 int lp_find_valid_service(const char *pszServiceName)
2572 iService = lp_servicenumber(pszServiceName);
2574 if (iService >= 0 && !lp_snum_ok(iService)) {
2575 DEBUG(0,("lp_find_valid_service: Invalid snum %d for '%s'\n",iService, pszServiceName));
2579 if (iService == -1) {
2580 DEBUG(3,("lp_find_valid_service: failed to find service '%s'\n", pszServiceName));
2586 /*******************************************************************
2587 A useful volume label function.
2588 ********************************************************************/
2589 const char *volume_label(int snum)
2591 const char *ret = lp_volume(snum);
2593 return lp_servicename(snum);
2598 /***********************************************************
2599 If we are PDC then prefer us as DMB
2600 ************************************************************/
2602 bool lp_domain_logons(void)
2604 return (lp_server_role() == ROLE_DOMAIN_CONTROLLER);
2607 /*******************************************************************
2609 ********************************************************************/
2611 void lp_remove_service(int snum)
2613 loadparm.ServicePtrs[snum] = NULL;
2616 /*******************************************************************
2618 ********************************************************************/
2620 void lp_copy_service(int snum, const char *new_name)
2622 const char *oldname = lp_servicename(snum);
2623 do_section(new_name, NULL);
2625 snum = lp_servicenumber(new_name);
2627 lp_do_parameter(snum, "copy", oldname);
2631 const char *lp_printername(int snum)
2633 const char *ret = _lp_printername(snum);
2634 if (ret == NULL || (ret != NULL && *ret == '\0'))
2635 ret = lp_const_servicename(snum);
2641 /*******************************************************************
2642 Return the max print jobs per queue.
2643 ********************************************************************/
2645 int lp_maxprintjobs(int snum)
2647 int maxjobs = LP_SNUM_OK(snum) ? loadparm.ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
2648 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
2649 maxjobs = PRINT_MAX_JOBID - 1;