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>
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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"
59 #include "system/time.h"
60 #include "system/iconv.h"
61 #include "system/network.h"
62 #include "system/printing.h"
63 #include "librpc/gen_ndr/ndr_svcctl.h"
64 #include "librpc/gen_ndr/ndr_samr.h"
65 #include "librpc/gen_ndr/ndr_nbt.h"
66 #include "dlinklist.h"
67 #include "param/loadparm.h"
69 static BOOL bLoaded = False;
72 #define GLOBAL_NAME "global"
76 #define PRINTERS_NAME "printers"
80 #define HOMES_NAME "homes"
83 /* some helpful bits */
84 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && ServicePtrs[(i)]->valid)
85 #define VALID(i) ServicePtrs[i]->valid
87 static BOOL do_parameter(const char *, const char *, void *);
88 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...);
90 static BOOL defaults_saved = False;
94 struct param_opt *prev, *next;
101 * This structure describes global (ie., server-wide) parameters.
111 char *display_charset;
115 char *szServerString;
116 char *szAutoServices;
125 char **szPasswordServers;
126 char *szSocketOptions;
128 char **szWINSservers;
130 char *szSocketAddress;
131 char *szAnnounceVersion; /* This is initialised in init_globals */
134 char **szNetbiosAliases;
135 char *szNetbiosScope;
136 char *szDomainOtherSIDs;
137 char **szNameResolveOrder;
139 char **dcerpc_ep_servers;
140 char **server_services;
141 char *ntptr_providor;
142 char *szWinbindSeparator;
143 char *swat_directory;
156 BOOL paranoid_server_security;
159 int announce_as; /* This is initialised in init_globals */
165 char *socket_options;
168 BOOL bPreferredMaster;
169 BOOL bEncryptPasswords;
171 BOOL bObeyPamRestrictions;
172 BOOL bLargeReadwrite;
176 BOOL bBindInterfacesOnly;
178 BOOL bNTStatusSupport;
184 BOOL bClientPlaintextAuth;
185 BOOL bClientLanManAuth;
186 BOOL bClientNTLMv2Auth;
187 BOOL client_use_spnego_principal;
190 BOOL bUnixExtensions;
191 BOOL bDisableNetbios;
193 struct param_opt *param_opt;
197 static global Globals;
200 * This structure describes a single service.
215 char **ntvfs_handler;
231 struct param_opt *param_opt;
233 char dummy[3]; /* for alignment */
238 /* This is a default service used to prime a services structure */
239 static service sDefault = {
241 NULL, /* szService */
244 NULL, /* szInclude */
245 NULL, /* szPrintername */
246 NULL, /* szHostsallow */
247 NULL, /* szHostsdeny */
251 NULL, /* ntvfs_handler */
252 1000, /* iMaxPrintJobs */
253 0, /* iMaxConnections */
255 True, /* bAvailable */
256 True, /* bBrowseable */
257 True, /* bRead_only */
258 False, /* bPrint_ok */
259 False, /* bMap_system */
260 False, /* bMap_hidden */
261 True, /* bMap_archive */
262 True, /* bStrictLocking */
264 False, /* bMSDfsRoot */
265 False, /* bStrictSync */
266 False, /* bCIFileSystem */
267 NULL, /* Parametric options */
272 /* local variables */
273 static service **ServicePtrs = NULL;
274 static int iNumServices = 0;
275 static int iServiceIndex = 0;
276 static BOOL bInGlobalSection = True;
277 static int default_server_announce;
279 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
281 /* prototypes for the special type handlers */
282 static BOOL handle_include(const char *pszParmValue, char **ptr);
283 static BOOL handle_copy(const char *pszParmValue, char **ptr);
285 static void set_default_server_announce_type(void);
287 static const struct enum_list enum_protocol[] = {
288 {PROTOCOL_NT1, "NT1"},
289 {PROTOCOL_LANMAN2, "LANMAN2"},
290 {PROTOCOL_LANMAN1, "LANMAN1"},
291 {PROTOCOL_CORE, "CORE"},
292 {PROTOCOL_COREPLUS, "COREPLUS"},
293 {PROTOCOL_COREPLUS, "CORE+"},
297 static const struct enum_list enum_security[] = {
298 {SEC_SHARE, "SHARE"},
300 {SEC_SERVER, "SERVER"},
301 {SEC_DOMAIN, "DOMAIN"},
308 /* Types of machine we can announce as. */
309 #define ANNOUNCE_AS_NT_SERVER 1
310 #define ANNOUNCE_AS_WIN95 2
311 #define ANNOUNCE_AS_WFW 3
312 #define ANNOUNCE_AS_NT_WORKSTATION 4
314 static const struct enum_list enum_announce_as[] = {
315 {ANNOUNCE_AS_NT_SERVER, "NT"},
316 {ANNOUNCE_AS_NT_SERVER, "NT Server"},
317 {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"},
318 {ANNOUNCE_AS_WIN95, "win95"},
319 {ANNOUNCE_AS_WFW, "WfW"},
323 static const struct enum_list enum_bool_auto[] = {
334 /* Client-side offline caching policy types */
335 #define CSC_POLICY_MANUAL 0
336 #define CSC_POLICY_DOCUMENTS 1
337 #define CSC_POLICY_PROGRAMS 2
338 #define CSC_POLICY_DISABLE 3
340 static const struct enum_list enum_csc_policy[] = {
341 {CSC_POLICY_MANUAL, "manual"},
342 {CSC_POLICY_DOCUMENTS, "documents"},
343 {CSC_POLICY_PROGRAMS, "programs"},
344 {CSC_POLICY_DISABLE, "disable"},
348 /* SMB signing types. */
349 static const struct enum_list enum_smb_signing_vals[] = {
350 {SMB_SIGNING_OFF, "No"},
351 {SMB_SIGNING_OFF, "False"},
352 {SMB_SIGNING_OFF, "0"},
353 {SMB_SIGNING_OFF, "Off"},
354 {SMB_SIGNING_OFF, "disabled"},
355 {SMB_SIGNING_SUPPORTED, "Yes"},
356 {SMB_SIGNING_SUPPORTED, "True"},
357 {SMB_SIGNING_SUPPORTED, "1"},
358 {SMB_SIGNING_SUPPORTED, "On"},
359 {SMB_SIGNING_SUPPORTED, "enabled"},
360 {SMB_SIGNING_REQUIRED, "required"},
361 {SMB_SIGNING_REQUIRED, "mandatory"},
362 {SMB_SIGNING_REQUIRED, "force"},
363 {SMB_SIGNING_REQUIRED, "forced"},
364 {SMB_SIGNING_REQUIRED, "enforced"},
365 {SMB_SIGNING_AUTO, "auto"},
369 static const struct enum_list enum_server_role[] = {
370 {ROLE_STANDALONE, "standalone"},
371 {ROLE_DOMAIN_MEMBER, "member server"},
372 {ROLE_DOMAIN_BDC, "bdc"},
373 {ROLE_DOMAIN_PDC, "pdc"},
378 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
380 * Note: We have a flag called FLAG_DEVELOPER but is not used at this time, it
381 * is implied in current control logic. This may change at some later time. A
382 * flag value of 0 means - show as development option only.
384 * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
385 * screen in SWAT. This is used to exclude parameters as well as to squash all
386 * parameters that have been duplicated by pseudonyms.
388 static struct parm_struct parm_table[] = {
389 {"Base Options", P_SEP, P_SEPARATOR},
391 {"server role", P_ENUM, P_GLOBAL, &Globals.server_role, NULL, enum_server_role, FLAG_BASIC},
393 {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
394 {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
395 {"ncalrpc dir", P_STRING, P_GLOBAL, &Globals.ncalrpc_dir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
396 {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
397 {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
398 {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
399 {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE},
400 {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkgroup, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
401 {"realm", P_STRING, P_GLOBAL, &Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
402 {"netbios name", P_USTRING, P_GLOBAL, &Globals.szNetbiosName, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
403 {"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
404 {"netbios scope", P_USTRING, P_GLOBAL, &Globals.szNetbiosScope, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
405 {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
406 {"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
407 {"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
408 {"ntvfs handler", P_LIST, P_LOCAL, &sDefault.ntvfs_handler, NULL, NULL, FLAG_ADVANCED},
409 {"ntptr providor", P_STRING, P_GLOBAL, &Globals.ntptr_providor, NULL, NULL, FLAG_ADVANCED},
410 {"dcerpc endpoint servers", P_LIST, P_GLOBAL, &Globals.dcerpc_ep_servers, NULL, NULL, FLAG_ADVANCED},
411 {"server services", P_LIST, P_GLOBAL, &Globals.server_services, NULL, NULL, FLAG_ADVANCED},
413 {"Security Options", P_SEP, P_SEPARATOR},
415 {"security", P_ENUM, P_GLOBAL, &Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
416 {"auth methods", P_LIST, P_GLOBAL, &Globals.AuthMethods, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
417 {"encrypt passwords", P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
418 {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
419 {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
420 {"password server", P_LIST, P_GLOBAL, &Globals.szPasswordServers, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
421 {"sam database", P_STRING, P_GLOBAL, &Globals.szSAM_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
422 {"spoolss database", P_STRING, P_GLOBAL, &Globals.szSPOOLSS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
423 {"wins database", P_STRING, P_GLOBAL, &Globals.szWINS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
424 {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
425 {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
426 {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
427 {"lanman auth", P_BOOL, P_GLOBAL, &Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
428 {"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
429 {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
430 {"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
431 {"client plaintext auth", P_BOOL, P_GLOBAL, &Globals.bClientPlaintextAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
432 {"client use spnego principal", P_BOOL, P_GLOBAL, &Globals.client_use_spnego_principal, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
434 {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE},
436 {"hosts allow", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
437 {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
439 {"Logging Options", P_SEP, P_SEPARATOR},
441 {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
442 {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_HIDE},
443 {"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
445 {"Protocol Options", P_SEP, P_SEPARATOR},
447 {"smb ports", P_LIST, P_GLOBAL, &Globals.smb_ports, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
448 {"nbt port", P_INTEGER, P_GLOBAL, &Globals.nbt_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
449 {"dgram port", P_INTEGER, P_GLOBAL, &Globals.dgram_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
450 {"cldap port", P_INTEGER, P_GLOBAL, &Globals.cldap_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
451 {"krb5 port", P_INTEGER, P_GLOBAL, &Globals.krb5_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
452 {"web port", P_INTEGER, P_GLOBAL, &Globals.web_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
453 {"tls enabled", P_BOOL, P_GLOBAL, &Globals.tls_enabled, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
454 {"tls keyfile", P_STRING, P_GLOBAL, &Globals.tls_keyfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
455 {"tls certfile", P_STRING, P_GLOBAL, &Globals.tls_certfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
456 {"tls cafile", P_STRING, P_GLOBAL, &Globals.tls_cafile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
457 {"tls crlfile", P_STRING, P_GLOBAL, &Globals.tls_crlfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
458 {"swat directory", P_STRING, P_GLOBAL, &Globals.swat_directory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
459 {"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, FLAG_DEVELOPER},
460 {"max protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
461 {"min protocol", P_ENUM, P_GLOBAL, &Globals.minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
462 {"unicode", P_BOOL, P_GLOBAL, &Globals.bUnicode, NULL, NULL, FLAG_DEVELOPER},
463 {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL, NULL, FLAG_DEVELOPER},
464 {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL, NULL, FLAG_DEVELOPER},
465 {"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
467 {"nt status support", P_BOOL, P_GLOBAL, &Globals.bNTStatusSupport, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
469 {"announce version", P_STRING, P_GLOBAL, &Globals.szAnnounceVersion, NULL, NULL, FLAG_DEVELOPER},
470 {"announce as", P_ENUM, P_GLOBAL, &Globals.announce_as, NULL, enum_announce_as, FLAG_DEVELOPER},
471 {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
472 {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
474 {"name resolve order", P_LIST, P_GLOBAL, &Globals.szNameResolveOrder, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
475 {"max wins ttl", P_INTEGER, P_GLOBAL, &Globals.max_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
476 {"min wins ttl", P_INTEGER, P_GLOBAL, &Globals.min_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
477 {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
478 {"unix extensions", P_BOOL, P_GLOBAL, &Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
479 {"use spnego", P_BOOL, P_GLOBAL, &Globals.bUseSpnego, NULL, NULL, FLAG_DEVELOPER},
480 {"server signing", P_ENUM, P_GLOBAL, &Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
481 {"client signing", P_ENUM, P_GLOBAL, &Globals.client_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
482 {"rpc big endian", P_BOOL, P_GLOBAL, &Globals.bRpcBigEndian, NULL, NULL, FLAG_DEVELOPER},
484 {"Tuning Options", P_SEP, P_SEPARATOR},
486 {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL, NULL, FLAG_SHARE},
487 {"paranoid server security", P_BOOL, P_GLOBAL, &Globals.paranoid_server_security, NULL, NULL, FLAG_DEVELOPER},
488 {"socket options", P_STRING, P_GLOBAL, &Globals.socket_options, NULL, NULL, FLAG_DEVELOPER},
490 {"strict sync", P_BOOL, P_LOCAL, &sDefault.bStrictSync, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
491 {"case insensitive filesystem", P_BOOL, P_LOCAL, &sDefault.bCIFileSystem, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
493 {"Printing Options", P_SEP, P_SEPARATOR},
495 {"max print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxPrintJobs, NULL, NULL, FLAG_PRINT},
496 {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_PRINT},
497 {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_HIDE},
499 {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_PRINT},
500 {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_HIDE},
502 {"Filename Handling", P_SEP, P_SEPARATOR},
504 {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
505 {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
506 {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
508 {"Domain Options", P_SEP, P_SEPARATOR},
510 {"Logon Options", P_SEP, P_SEPARATOR},
513 {"Browse Options", P_SEP, P_SEPARATOR},
515 {"preferred master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
516 {"prefered master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_HIDE},
517 {"local master", P_BOOL, P_GLOBAL, &Globals.bLocalMaster, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
518 {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
519 {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_HIDE},
521 {"WINS Options", P_SEP, P_SEPARATOR},
523 {"wins server", P_LIST, P_GLOBAL, &Globals.szWINSservers, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
524 {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
526 {"Locking Options", P_SEP, P_SEPARATOR},
528 {"csc policy", P_ENUM, P_LOCAL, &sDefault.iCSCPolicy, NULL, enum_csc_policy, FLAG_SHARE | FLAG_GLOBAL},
530 {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
532 {"Miscellaneous Options", P_SEP, P_SEPARATOR},
534 {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE},
535 {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
536 {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
537 {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_HIDE},
538 {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
539 {"pid directory", P_STRING, P_GLOBAL, &Globals.szPidDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
540 {"js include", P_LIST, P_GLOBAL, &Globals.jsInclude, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
541 {"setup directory", P_STRING, P_GLOBAL, &Globals.szSetupDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
543 {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL, NULL, FLAG_DEVELOPER},
544 {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL, NULL, FLAG_HIDE},
546 {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy, NULL, FLAG_HIDE},
547 {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include, NULL, FLAG_HIDE},
549 {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
550 {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_SHARE },
551 {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_SHARE},
553 {"panic action", P_STRING, P_GLOBAL, &Globals.szPanicAction, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
555 {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_SHARE},
556 {"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
557 {"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
559 {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
564 return the parameter table
566 struct parm_struct *lp_parm_table(void)
571 /***************************************************************************
572 Initialise the global parameter structure.
573 ***************************************************************************/
574 static void init_globals(void)
579 DEBUG(3, ("Initialising global parameters\n"));
581 for (i = 0; parm_table[i].label; i++) {
582 if ((parm_table[i].type == P_STRING ||
583 parm_table[i].type == P_USTRING) &&
585 !(parm_table[i].flags & FLAG_CMDLINE)) {
586 string_set(parm_table[i].ptr, "");
590 do_parameter("config file", dyn_CONFIGFILE, NULL);
592 do_parameter("server role", "standalone", NULL);
594 /* options that can be set on the command line must be initialised via
595 the slower do_parameter() to ensure that FLAG_CMDLINE is obeyed */
597 do_parameter("socket options", "TCP_NODELAY", NULL);
599 do_parameter("workgroup", DEFAULT_WORKGROUP, NULL);
600 myname = get_myname();
601 do_parameter("netbios name", myname, NULL);
603 do_parameter("max protocol", "NT1", NULL);
604 do_parameter("name resolve order", "lmhosts wins host bcast", NULL);
606 do_parameter("fstype", FSTYPE_STRING, NULL);
607 do_parameter("ntvfs handler", "unixuid default", NULL);
608 do_parameter("max connections", "-1", NULL);
610 do_parameter("dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup", NULL);
611 do_parameter("server services", "smb rpc nbt ldap cldap web kdc", NULL);
612 do_parameter("ntptr providor", "simple_ldb", NULL);
613 do_parameter("auth methods", "anonymous sam_ignoredomain", NULL);
614 do_parameter("private dir", dyn_PRIVATE_DIR, NULL);
615 do_parameter("sam database", "sam.ldb", NULL);
616 do_parameter("spoolss database", "spoolss.ldb", NULL);
617 do_parameter("wins database", "wins.ldb", NULL);
618 do_parameter("registry:HKEY_LOCAL_MACHINE", "hklm.ldb", NULL);
620 /* This hive should be dynamically generated by Samba using
621 data from the sam, but for the moment leave it in a tdb to
622 keep regedt32 from popping up an annoying dialog. */
623 do_parameter("registry:HKEY_USERS", "hku.ldb", NULL);
625 /* using UTF8 by default allows us to support all chars */
626 do_parameter("unix charset", "UTF8", NULL);
628 /* Use codepage 850 as a default for the dos character set */
629 do_parameter("dos charset", "CP850", NULL);
632 * Allow the default PASSWD_CHAT to be overridden in local.h.
634 do_parameter("passwd chat", DEFAULT_PASSWD_CHAT, NULL);
636 do_parameter("pid directory", dyn_PIDDIR, NULL);
637 do_parameter("lock dir", dyn_LOCKDIR, NULL);
638 do_parameter("ncalrpc dir", dyn_NCALRPCDIR, NULL);
640 do_parameter("socket address", "0.0.0.0", NULL);
641 do_parameter_var("server string", "Samba %s", SAMBA_VERSION_STRING);
643 do_parameter_var("announce version", "%d.%d",
644 DEFAULT_MAJOR_VERSION,
645 DEFAULT_MINOR_VERSION);
647 do_parameter("password server", "*", NULL);
649 do_parameter("max mux", "50", NULL);
650 do_parameter("max xmit", "12288", NULL);
651 do_parameter("password level", "0", NULL);
652 do_parameter("LargeReadwrite", "True", NULL);
653 do_parameter("minprotocol", "CORE", NULL);
654 do_parameter("security", "USER", NULL);
655 do_parameter("paranoid server security", "True", NULL);
656 do_parameter("EncryptPasswords", "True", NULL);
657 do_parameter("ReadRaw", "True", NULL);
658 do_parameter("WriteRaw", "True", NULL);
659 do_parameter("NullPasswords", "False", NULL);
660 do_parameter("ObeyPamRestrictions", "False", NULL);
661 do_parameter("announce as", "NT SERVER", NULL);
663 do_parameter("TimeServer", "False", NULL);
664 do_parameter("BindInterfacesOnly", "False", NULL);
665 do_parameter("Unicode", "True", NULL);
666 do_parameter("ClientLanManAuth", "True", NULL);
667 do_parameter("LanmanAuth", "True", NULL);
668 do_parameter("NTLMAuth", "True", NULL);
669 do_parameter("client use spnego principal", "False", NULL);
671 do_parameter("UnixExtensions", "False", NULL);
673 do_parameter("PreferredMaster", "Auto", NULL);
674 do_parameter("LocalMaster", "True", NULL);
676 do_parameter("WINSsupport", "False", NULL);
678 do_parameter("winbind separator", "\\", NULL);
680 do_parameter("client signing", "Yes", NULL);
681 do_parameter("server signing", "auto", NULL);
683 do_parameter("use spnego", "True", NULL);
685 do_parameter("smb ports", SMB_PORTS, NULL);
686 do_parameter("nbt port", "137", NULL);
687 do_parameter("dgram port", "138", NULL);
688 do_parameter("cldap port", "389", NULL);
689 do_parameter("krb5 port", "88", NULL);
690 do_parameter("web port", "901", NULL);
691 do_parameter("swat directory", dyn_SWATDIR, NULL);
693 do_parameter("nt status support", "True", NULL);
695 do_parameter("max wins ttl", "432000", NULL);
696 do_parameter("min wins ttl", "10", NULL);
698 do_parameter("tls enabled", "True", NULL);
699 do_parameter("tls keyfile", "tls/key.pem", NULL);
700 do_parameter("tls certfile", "tls/cert.pem", NULL);
701 do_parameter("tls cafile", "tls/ca.pem", NULL);
702 do_parameter_var("js include", "%s/js", dyn_LIBDIR);
703 do_parameter_var("setup directory", "%s/setup", dyn_LIBDIR);
706 static TALLOC_CTX *lp_talloc;
708 /******************************************************************* a
709 Free up temporary memory - called from the main loop.
710 ********************************************************************/
712 void lp_talloc_free(void)
716 talloc_free(lp_talloc);
720 /*******************************************************************
721 Convenience routine to grab string parameters into temporary memory
722 and run standard_sub_basic on them. The buffers can be written to by
723 callers without affecting the source string.
724 ********************************************************************/
726 static const char *lp_string(const char *s)
728 #if 0 /* until REWRITE done to make thread-safe */
729 size_t len = s ? strlen(s) : 0;
733 /* The follow debug is useful for tracking down memory problems
734 especially if you have an inner loop that is calling a lp_*()
735 function that returns a string. Perhaps this debug should be
736 present all the time? */
739 DEBUG(10, ("lp_string(%s)\n", s));
742 #if 0 /* until REWRITE done to make thread-safe */
744 lp_talloc = talloc_init("lp_talloc");
746 ret = talloc_array(lp_talloc, char, len + 100); /* leave room for substitution */
754 StrnCpy(ret, s, len);
756 if (trim_string(ret, "\"", "\"")) {
757 if (strchr(ret,'"') != NULL)
758 StrnCpy(ret, s, len);
761 standard_sub_basic(ret,len+100);
768 In this section all the functions that are used to access the
769 parameters from the rest of the program are defined
772 #define FN_GLOBAL_STRING(fn_name,ptr) \
773 const char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
774 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
775 const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");}
776 #define FN_GLOBAL_LIST(fn_name,ptr) \
777 const char **fn_name(void) {return(*(const char ***)(ptr));}
778 #define FN_GLOBAL_BOOL(fn_name,ptr) \
779 BOOL fn_name(void) {return(*(BOOL *)(ptr));}
780 #define FN_GLOBAL_CHAR(fn_name,ptr) \
781 char fn_name(void) {return(*(char *)(ptr));}
782 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
783 int fn_name(void) {return(*(int *)(ptr));}
785 #define FN_LOCAL_STRING(fn_name,val) \
786 const char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
787 #define FN_LOCAL_CONST_STRING(fn_name,val) \
788 const char *fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
789 #define FN_LOCAL_LIST(fn_name,val) \
790 const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
791 #define FN_LOCAL_BOOL(fn_name,val) \
792 BOOL fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
793 #define FN_LOCAL_CHAR(fn_name,val) \
794 char fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
795 #define FN_LOCAL_INTEGER(fn_name,val) \
796 int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
798 FN_GLOBAL_INTEGER(lp_server_role, &Globals.server_role)
799 FN_GLOBAL_LIST(lp_smb_ports, &Globals.smb_ports)
800 FN_GLOBAL_INTEGER(lp_nbt_port, &Globals.nbt_port)
801 FN_GLOBAL_INTEGER(lp_dgram_port, &Globals.dgram_port)
802 FN_GLOBAL_INTEGER(lp_cldap_port, &Globals.cldap_port)
803 FN_GLOBAL_INTEGER(lp_krb5_port, &Globals.krb5_port)
804 FN_GLOBAL_INTEGER(lp_web_port, &Globals.web_port)
805 FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
806 FN_GLOBAL_STRING(lp_swat_directory, &Globals.swat_directory)
807 FN_GLOBAL_BOOL(lp_tls_enabled, &Globals.tls_enabled)
808 FN_GLOBAL_STRING(lp_tls_keyfile, &Globals.tls_keyfile)
809 FN_GLOBAL_STRING(lp_tls_certfile, &Globals.tls_certfile)
810 FN_GLOBAL_STRING(lp_tls_cafile, &Globals.tls_cafile)
811 FN_GLOBAL_STRING(lp_tls_crlfile, &Globals.tls_crlfile)
812 FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
813 FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset)
814 FN_GLOBAL_STRING(lp_logfile, &Globals.szLogFile)
815 FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
816 FN_GLOBAL_STRING(lp_sam_url, &Globals.szSAM_URL)
817 FN_GLOBAL_STRING(lp_spoolss_url, &Globals.szSPOOLSS_URL)
818 FN_GLOBAL_STRING(lp_wins_url, &Globals.szWINS_URL)
819 FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
820 FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
821 FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
822 FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
823 FN_GLOBAL_STRING(lp_setupdir, &Globals.szSetupDir)
824 FN_GLOBAL_STRING(lp_ncalrpc_dir, &Globals.ncalrpc_dir)
825 FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
826 FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, &Globals.dcerpc_ep_servers)
827 FN_GLOBAL_LIST(lp_server_services, &Globals.server_services)
828 FN_GLOBAL_STRING(lp_ntptr_providor, &Globals.ntptr_providor)
829 FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
830 FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
831 FN_GLOBAL_LIST(lp_passwordserver, &Globals.szPasswordServers)
832 FN_GLOBAL_LIST(lp_name_resolve_order, &Globals.szNameResolveOrder)
833 FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
834 FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
835 FN_GLOBAL_STRING(lp_workgroup, &Globals.szWorkgroup)
836 FN_GLOBAL_STRING(lp_netbios_name, &Globals.szNetbiosName)
837 FN_GLOBAL_STRING(lp_netbios_scope, &Globals.szNetbiosScope)
838 FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
839 FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
840 FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
841 FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
842 FN_GLOBAL_STRING(lp_panic_action, &Globals.szPanicAction)
844 FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
845 FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
846 FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
847 FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
848 FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
849 FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw)
850 FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords)
851 FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions)
852 FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
853 static FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
854 FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
855 FN_GLOBAL_BOOL(lp_unicode, &Globals.bUnicode)
856 FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
857 FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
858 FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
859 FN_GLOBAL_BOOL(lp_client_plaintext_auth, &Globals.bClientPlaintextAuth)
860 FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
861 FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
862 FN_GLOBAL_BOOL(lp_client_use_spnego_principal, &Globals.client_use_spnego_principal)
863 FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
864 FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions)
865 FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
866 FN_GLOBAL_BOOL(lp_rpc_big_endian, &Globals.bRpcBigEndian)
867 FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
868 FN_GLOBAL_INTEGER(lp_min_wins_ttl, &Globals.min_wins_ttl)
869 FN_GLOBAL_INTEGER(lp_maxmux, &Globals.max_mux)
870 FN_GLOBAL_INTEGER(lp_max_xmit, &Globals.max_xmit)
871 FN_GLOBAL_INTEGER(lp_passwordlevel, &Globals.pwordlevel)
872 FN_GLOBAL_INTEGER(lp_maxprotocol, &Globals.maxprotocol)
873 FN_GLOBAL_INTEGER(lp_minprotocol, &Globals.minprotocol)
874 FN_GLOBAL_INTEGER(lp_security, &Globals.security)
875 FN_GLOBAL_LIST(lp_auth_methods, &Globals.AuthMethods)
876 FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security)
877 static FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as)
878 FN_GLOBAL_LIST(lp_js_include, &Globals.jsInclude)
881 FN_LOCAL_STRING(lp_servicename, szService)
882 FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
883 FN_LOCAL_STRING(lp_pathname, szPath)
884 static FN_LOCAL_STRING(_lp_printername, szPrintername)
885 FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
886 FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
887 FN_LOCAL_STRING(lp_comment, comment)
888 FN_LOCAL_STRING(lp_fstype, fstype)
889 static FN_LOCAL_STRING(lp_volume, volume)
890 FN_LOCAL_LIST(lp_ntvfs_handler, ntvfs_handler)
891 FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
892 FN_LOCAL_BOOL(lp_browseable, bBrowseable)
893 FN_LOCAL_BOOL(lp_readonly, bRead_only)
894 FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
895 FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
896 FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
897 FN_LOCAL_BOOL(lp_strict_locking, bStrictLocking)
898 FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
899 FN_LOCAL_BOOL(lp_ci_filesystem, bCIFileSystem)
900 FN_LOCAL_BOOL(lp_map_system, bMap_system)
901 FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
902 FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
903 FN_GLOBAL_INTEGER(lp_server_signing, &Globals.server_signing)
904 FN_GLOBAL_INTEGER(lp_client_signing, &Globals.client_signing)
906 /* local prototypes */
908 static int map_parameter(const char *pszParmName);
909 static BOOL set_boolean(BOOL *pb, const char *pszParmValue);
910 static int getservicebyname(const char *pszServiceName,
911 service * pserviceDest);
912 static void copy_service(service * pserviceDest,
913 service * pserviceSource, BOOL *pcopymapDest);
914 static BOOL service_ok(int iService);
915 static BOOL do_section(const char *pszSectionName, void *);
916 static void init_copymap(service * pservice);
918 /* This is a helper function for parametrical options support. */
919 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
920 /* Actual parametrical functions are quite simple */
921 const char *lp_get_parametric(int lookup_service, const char *type, const char *option)
924 struct param_opt *data;
926 if (lookup_service >= iNumServices) return NULL;
928 data = (lookup_service < 0) ?
929 Globals.param_opt : ServicePtrs[lookup_service]->param_opt;
931 asprintf(&vfskey, "%s:%s", type, option);
935 if (strcmp(data->key, vfskey) == 0) {
942 if (lookup_service >= 0) {
943 /* Try to fetch the same option but from globals */
944 /* but only if we are not already working with Globals */
945 data = Globals.param_opt;
947 if (strcmp(data->key, vfskey) == 0) {
961 /*******************************************************************
962 convenience routine to return int parameters.
963 ********************************************************************/
964 static int lp_int(const char *s)
968 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
972 return strtol(s, NULL, 0);
975 /*******************************************************************
976 convenience routine to return unsigned long parameters.
977 ********************************************************************/
978 static int lp_ulong(const char *s)
982 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
986 return strtoul(s, NULL, 0);
989 /*******************************************************************
990 convenience routine to return boolean parameters.
991 ********************************************************************/
992 static BOOL lp_bool(const char *s)
997 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
1001 if (!set_boolean(&ret,s)) {
1002 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1010 /* Return parametric option from a given service. Type is a part of option before ':' */
1011 /* Parametric option has following syntax: 'Type: option = value' */
1012 /* Returned value is allocated in 'lp_talloc' context */
1014 const char *lp_parm_string(int lookup_service, const char *type, const char *option)
1016 const char *value = lp_get_parametric(lookup_service, type, option);
1019 return lp_string(value);
1024 /* Return parametric option from a given service. Type is a part of option before ':' */
1025 /* Parametric option has following syntax: 'Type: option = value' */
1026 /* Returned value is allocated in 'lp_talloc' context */
1028 const char **lp_parm_string_list(int lookup_service, const char *type, const char *option,
1029 const char *separator)
1031 const char *value = lp_get_parametric(lookup_service, type, option);
1034 return str_list_make(talloc_autofree_context(), value, separator);
1039 /* Return parametric option from a given service. Type is a part of option before ':' */
1040 /* Parametric option has following syntax: 'Type: option = value' */
1042 int lp_parm_int(int lookup_service, const char *type, const char *option, int default_v)
1044 const char *value = lp_get_parametric(lookup_service, type, option);
1047 return lp_int(value);
1052 /* Return parametric option from a given service. Type is a part of option before ':' */
1053 /* Parametric option has following syntax: 'Type: option = value' */
1055 unsigned long lp_parm_ulong(int lookup_service, const char *type, const char *option, unsigned long default_v)
1057 const char *value = lp_get_parametric(lookup_service, type, option);
1060 return lp_ulong(value);
1065 /* Return parametric option from a given service. Type is a part of option before ':' */
1066 /* Parametric option has following syntax: 'Type: option = value' */
1068 BOOL lp_parm_bool(int lookup_service, const char *type, const char *option, BOOL default_v)
1070 const char *value = lp_get_parametric(lookup_service, type, option);
1073 return lp_bool(value);
1079 /***************************************************************************
1080 Initialise a service to the defaults.
1081 ***************************************************************************/
1083 static void init_service(service * pservice)
1085 memset((char *)pservice, '\0', sizeof(service));
1086 copy_service(pservice, &sDefault, NULL);
1089 /***************************************************************************
1090 Free the dynamically allocated parts of a service struct.
1091 ***************************************************************************/
1093 static void free_service(service *pservice)
1096 struct param_opt *data, *pdata;
1100 if (pservice->szService)
1101 DEBUG(5, ("free_service: Freeing service %s\n",
1102 pservice->szService));
1104 string_free(&pservice->szService);
1105 SAFE_FREE(pservice->copymap);
1107 for (i = 0; parm_table[i].label; i++) {
1108 if ((parm_table[i].type == P_STRING ||
1109 parm_table[i].type == P_USTRING) &&
1110 parm_table[i].class == P_LOCAL) {
1111 string_free((char **)
1112 (((char *)pservice) +
1113 PTR_DIFF(parm_table[i].ptr, &sDefault)));
1114 } else if (parm_table[i].type == P_LIST &&
1115 parm_table[i].class == P_LOCAL) {
1116 char ***listp = (char ***)(((char *)pservice) +
1117 PTR_DIFF(parm_table[i].ptr, &sDefault));
1118 talloc_free(*listp);
1123 DEBUG(5,("Freeing parametrics:\n"));
1124 data = pservice->param_opt;
1126 DEBUG(5,("[%s = %s]\n", data->key, data->value));
1127 string_free(&data->key);
1128 string_free(&data->value);
1134 ZERO_STRUCTP(pservice);
1137 /***************************************************************************
1138 Add a new service to the services array initialising it with the given
1140 ***************************************************************************/
1142 static int add_a_service(const service *pservice, const char *name)
1146 int num_to_alloc = iNumServices + 1;
1147 struct param_opt *data, *pdata;
1149 tservice = *pservice;
1151 /* it might already exist */
1153 i = getservicebyname(name, NULL);
1155 /* Clean all parametric options for service */
1156 /* They will be added during parsing again */
1157 data = ServicePtrs[i]->param_opt;
1159 string_free(&data->key);
1160 string_free(&data->value);
1165 ServicePtrs[i]->param_opt = NULL;
1170 /* find an invalid one */
1171 for (i = 0; i < iNumServices; i++)
1172 if (!ServicePtrs[i]->valid)
1175 /* if not, then create one */
1176 if (i == iNumServices) {
1179 tsp = realloc_p(ServicePtrs, service *, num_to_alloc);
1182 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1187 ServicePtrs[iNumServices] = malloc_p(service);
1189 if (!ServicePtrs[iNumServices]) {
1190 DEBUG(0,("add_a_service: out of memory!\n"));
1196 free_service(ServicePtrs[i]);
1198 ServicePtrs[i]->valid = True;
1200 init_service(ServicePtrs[i]);
1201 copy_service(ServicePtrs[i], &tservice, NULL);
1203 string_set(&ServicePtrs[i]->szService, name);
1207 /***************************************************************************
1208 Add a new home service, with the specified home directory, defaults coming
1210 ***************************************************************************/
1212 BOOL lp_add_home(const char *pszHomename, int iDefaultService,
1213 const char *user, const char *pszHomedir)
1218 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1223 if (!(*(ServicePtrs[iDefaultService]->szPath))
1224 || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(-1))) {
1225 pstrcpy(newHomedir, pszHomedir);
1227 pstrcpy(newHomedir, lp_pathname(iDefaultService));
1228 string_sub(newHomedir,"%H", pszHomedir, sizeof(newHomedir));
1231 string_set(&ServicePtrs[i]->szPath, newHomedir);
1233 if (!(*(ServicePtrs[i]->comment))) {
1235 slprintf(comment, sizeof(comment) - 1,
1236 "Home directory of %s", user);
1237 string_set(&ServicePtrs[i]->comment, comment);
1239 ServicePtrs[i]->bAvailable = sDefault.bAvailable;
1240 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1242 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1248 /***************************************************************************
1249 Add a new service, based on an old one.
1250 ***************************************************************************/
1252 int lp_add_service(const char *pszService, int iDefaultService)
1254 return (add_a_service(ServicePtrs[iDefaultService], pszService));
1257 /***************************************************************************
1258 Add the IPC service.
1259 ***************************************************************************/
1261 static BOOL lp_add_hidden(const char *name, const char *fstype)
1264 int i = add_a_service(&sDefault, name);
1269 slprintf(comment, sizeof(comment) - 1,
1270 "%s Service (%s)", fstype, Globals.szServerString);
1272 string_set(&ServicePtrs[i]->szPath, tmpdir());
1273 string_set(&ServicePtrs[i]->comment, comment);
1274 string_set(&ServicePtrs[i]->fstype, fstype);
1275 ServicePtrs[i]->iMaxConnections = -1;
1276 ServicePtrs[i]->bAvailable = True;
1277 ServicePtrs[i]->bRead_only = True;
1278 ServicePtrs[i]->bPrint_ok = False;
1279 ServicePtrs[i]->bBrowseable = False;
1281 if (strcasecmp(fstype, "IPC") == 0) {
1282 lp_do_parameter(i, "ntvfs handler", "default");
1285 DEBUG(3, ("adding hidden service %s\n", name));
1290 /***************************************************************************
1291 Add a new printer service, with defaults coming from service iFrom.
1292 ***************************************************************************/
1294 BOOL lp_add_printer(const char *pszPrintername, int iDefaultService)
1296 const char *comment = "From Printcap";
1297 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1302 /* note that we do NOT default the availability flag to True - */
1303 /* we take it from the default service passed. This allows all */
1304 /* dynamic printers to be disabled by disabling the [printers] */
1305 /* entry (if/when the 'available' keyword is implemented!). */
1307 /* the printer name is set to the service name. */
1308 string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1309 string_set(&ServicePtrs[i]->comment, comment);
1310 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1311 /* Printers cannot be read_only. */
1312 ServicePtrs[i]->bRead_only = False;
1313 /* Printer services must be printable. */
1314 ServicePtrs[i]->bPrint_ok = True;
1316 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1318 update_server_announce_as_printserver();
1323 /***************************************************************************
1324 Map a parameter's string representation to something we can use.
1325 Returns False if the parameter string is not recognised, else TRUE.
1326 ***************************************************************************/
1328 static int map_parameter(const char *pszParmName)
1332 if (*pszParmName == '-')
1335 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1336 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1339 /* Warn only if it isn't parametric option */
1340 if (strchr(pszParmName, ':') == NULL)
1341 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1342 /* We do return 'fail' for parametric options as well because they are
1343 stored in different storage
1350 return the parameter structure for a parameter
1352 struct parm_struct *lp_parm_struct(const char *name)
1354 int parmnum = map_parameter(name);
1355 if (parmnum == -1) return NULL;
1356 return &parm_table[parmnum];
1360 return the parameter pointer for a parameter
1362 void *lp_parm_ptr(int snum, struct parm_struct *parm)
1367 return ((char *)ServicePtrs[snum]) + PTR_DIFF(parm->ptr, &sDefault);
1370 /***************************************************************************
1371 Set a boolean variable from the text value stored in the passed string.
1372 Returns True in success, False if the passed string does not correctly
1373 represent a boolean.
1374 ***************************************************************************/
1376 static BOOL set_boolean(BOOL *pb, const char *pszParmValue)
1381 if (strwicmp(pszParmValue, "yes") == 0 ||
1382 strwicmp(pszParmValue, "true") == 0 ||
1383 strwicmp(pszParmValue, "1") == 0)
1385 else if (strwicmp(pszParmValue, "no") == 0 ||
1386 strwicmp(pszParmValue, "False") == 0 ||
1387 strwicmp(pszParmValue, "0") == 0)
1391 ("ERROR: Badly formed boolean in configuration file: \"%s\".\n",
1398 /***************************************************************************
1399 Find a service by name. Otherwise works like get_service.
1400 ***************************************************************************/
1402 static int getservicebyname(const char *pszServiceName, service * pserviceDest)
1406 for (iService = iNumServices - 1; iService >= 0; iService--)
1407 if (VALID(iService) &&
1408 strwicmp(ServicePtrs[iService]->szService, pszServiceName) == 0) {
1409 if (pserviceDest != NULL)
1410 copy_service(pserviceDest, ServicePtrs[iService], NULL);
1417 /***************************************************************************
1418 Copy a service structure to another.
1419 If pcopymapDest is NULL then copy all fields
1420 ***************************************************************************/
1422 static void copy_service(service * pserviceDest, service * pserviceSource, BOOL *pcopymapDest)
1425 BOOL bcopyall = (pcopymapDest == NULL);
1426 struct param_opt *data, *pdata, *paramo;
1429 for (i = 0; parm_table[i].label; i++)
1430 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1431 (bcopyall || pcopymapDest[i])) {
1432 void *def_ptr = parm_table[i].ptr;
1434 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
1437 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
1440 switch (parm_table[i].type) {
1442 *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
1447 *(int *)dest_ptr = *(int *)src_ptr;
1451 string_set(dest_ptr,
1456 string_set(dest_ptr,
1458 strupper(*(char **)dest_ptr);
1461 *(const char ***)dest_ptr = str_list_copy(talloc_autofree_context(),
1462 *(const char ***)src_ptr);
1470 init_copymap(pserviceDest);
1471 if (pserviceSource->copymap)
1472 memcpy((void *)pserviceDest->copymap,
1473 (void *)pserviceSource->copymap,
1474 sizeof(BOOL) * NUMPARAMETERS);
1477 data = pserviceSource->param_opt;
1480 pdata = pserviceDest->param_opt;
1481 /* Traverse destination */
1483 /* If we already have same option, override it */
1484 if (strcmp(pdata->key, data->key) == 0) {
1485 string_free(&pdata->value);
1486 pdata->value = strdup(data->value);
1490 pdata = pdata->next;
1493 paramo = smb_xmalloc_p(struct param_opt);
1494 paramo->key = strdup(data->key);
1495 paramo->value = strdup(data->value);
1496 DLIST_ADD(pserviceDest->param_opt, paramo);
1502 /***************************************************************************
1503 Check a service for consistency. Return False if the service is in any way
1504 incomplete or faulty, else True.
1505 ***************************************************************************/
1507 static BOOL service_ok(int iService)
1512 if (ServicePtrs[iService]->szService[0] == '\0') {
1513 DEBUG(0, ("The following message indicates an internal error:\n"));
1514 DEBUG(0, ("No service name in service entry.\n"));
1518 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1519 /* I can't see why you'd want a non-printable printer service... */
1520 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
1521 if (!ServicePtrs[iService]->bPrint_ok) {
1522 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
1523 ServicePtrs[iService]->szService));
1524 ServicePtrs[iService]->bPrint_ok = True;
1525 update_server_announce_as_printserver();
1527 /* [printers] service must also be non-browsable. */
1528 if (ServicePtrs[iService]->bBrowseable)
1529 ServicePtrs[iService]->bBrowseable = False;
1532 /* If a service is flagged unavailable, log the fact at level 0. */
1533 if (!ServicePtrs[iService]->bAvailable)
1534 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
1535 ServicePtrs[iService]->szService));
1540 static struct file_lists {
1541 struct file_lists *next;
1545 } *file_lists = NULL;
1547 /*******************************************************************
1548 Keep a linked list of all config files so we know when one has changed
1549 it's date and needs to be reloaded.
1550 ********************************************************************/
1552 static void add_to_file_list(const char *fname, const char *subfname)
1554 struct file_lists *f = file_lists;
1557 if (f->name && !strcmp(f->name, fname))
1563 f = malloc_p(struct file_lists);
1566 f->next = file_lists;
1567 f->name = strdup(fname);
1572 f->subfname = strdup(subfname);
1578 f->modtime = file_modtime(subfname);
1580 time_t t = file_modtime(subfname);
1586 /*******************************************************************
1587 Check if a config file has changed date.
1588 ********************************************************************/
1590 BOOL lp_file_list_changed(void)
1592 struct file_lists *f = file_lists;
1593 DEBUG(6, ("lp_file_list_changed()\n"));
1599 pstrcpy(n2, f->name);
1600 standard_sub_basic(n2,sizeof(n2));
1602 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
1603 f->name, n2, ctime(&f->modtime)));
1605 mod_time = file_modtime(n2);
1607 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
1609 ("file %s modified: %s\n", n2,
1611 f->modtime = mod_time;
1612 SAFE_FREE(f->subfname);
1613 f->subfname = strdup(n2);
1621 /***************************************************************************
1622 Handle the include operation.
1623 ***************************************************************************/
1625 static BOOL handle_include(const char *pszParmValue, char **ptr)
1628 pstrcpy(fname, pszParmValue);
1630 standard_sub_basic(fname,sizeof(fname));
1632 add_to_file_list(pszParmValue, fname);
1634 string_set(ptr, fname);
1636 if (file_exist(fname))
1637 return (pm_process(fname, do_section, do_parameter, NULL));
1639 DEBUG(2, ("Can't find include file %s\n", fname));
1644 /***************************************************************************
1645 Handle the interpretation of the copy parameter.
1646 ***************************************************************************/
1648 static BOOL handle_copy(const char *pszParmValue, char **ptr)
1652 service serviceTemp;
1654 string_set(ptr, pszParmValue);
1656 init_service(&serviceTemp);
1660 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
1662 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
1663 if (iTemp == iServiceIndex) {
1664 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
1666 copy_service(ServicePtrs[iServiceIndex],
1668 ServicePtrs[iServiceIndex]->copymap);
1672 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
1676 free_service(&serviceTemp);
1680 /***************************************************************************
1681 Initialise a copymap.
1682 ***************************************************************************/
1684 static void init_copymap(service * pservice)
1687 SAFE_FREE(pservice->copymap);
1688 pservice->copymap = malloc_array_p(BOOL, NUMPARAMETERS);
1689 if (!pservice->copymap)
1691 ("Couldn't allocate copymap!! (size %d)\n",
1692 (int)NUMPARAMETERS));
1694 for (i = 0; i < NUMPARAMETERS; i++)
1695 pservice->copymap[i] = True;
1698 /***************************************************************************
1699 Return the local pointer to a parameter given the service number and the
1700 pointer into the default structure.
1701 ***************************************************************************/
1703 void *lp_local_ptr(int snum, void *ptr)
1705 return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
1709 /***************************************************************************
1710 Process a parametric option
1711 ***************************************************************************/
1712 static BOOL lp_do_parameter_parametric(int snum, const char *pszParmName, const char *pszParmValue, int flags)
1714 struct param_opt *paramo, *data;
1717 while (isspace((unsigned char)*pszParmName)) {
1721 name = strdup(pszParmName);
1722 if (!name) return False;
1727 data = Globals.param_opt;
1729 data = ServicePtrs[snum]->param_opt;
1732 /* Traverse destination */
1733 for (paramo=data; paramo; paramo=paramo->next) {
1734 /* If we already have the option set, override it unless
1735 it was a command line option and the new one isn't */
1736 if (strcmp(paramo->key, name) == 0) {
1737 if ((paramo->flags & FLAG_CMDLINE) &&
1738 !(flags & FLAG_CMDLINE)) {
1742 free(paramo->value);
1743 paramo->value = strdup(pszParmValue);
1744 paramo->flags = flags;
1750 paramo = smb_xmalloc_p(struct param_opt);
1751 paramo->key = strdup(name);
1752 paramo->value = strdup(pszParmValue);
1753 paramo->flags = flags;
1755 DLIST_ADD(Globals.param_opt, paramo);
1757 DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
1765 /***************************************************************************
1766 Process a parameter for a particular service number. If snum < 0
1767 then assume we are in the globals.
1768 ***************************************************************************/
1769 BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
1772 void *parm_ptr = NULL; /* where we are going to store the result */
1773 void *def_ptr = NULL;
1775 parmnum = map_parameter(pszParmName);
1778 if (strchr(pszParmName, ':')) {
1779 return lp_do_parameter_parametric(snum, pszParmName, pszParmValue, 0);
1781 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1785 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1786 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1790 /* if the flag has been set on the command line, then don't allow override,
1791 but don't report an error */
1792 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1796 def_ptr = parm_table[parmnum].ptr;
1798 /* we might point at a service, the default service or a global */
1802 if (parm_table[parmnum].class == P_GLOBAL) {
1804 ("Global parameter %s found in service section!\n",
1809 ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
1814 if (!ServicePtrs[snum]->copymap)
1815 init_copymap(ServicePtrs[snum]);
1817 /* this handles the aliases - set the copymap for other entries with
1818 the same data pointer */
1819 for (i = 0; parm_table[i].label; i++)
1820 if (parm_table[i].ptr == parm_table[parmnum].ptr)
1821 ServicePtrs[snum]->copymap[i] = False;
1824 /* if it is a special case then go ahead */
1825 if (parm_table[parmnum].special) {
1826 parm_table[parmnum].special(pszParmValue, (char **)parm_ptr);
1830 /* now switch on the type of variable it is */
1831 switch (parm_table[parmnum].type)
1834 set_boolean(parm_ptr, pszParmValue);
1838 *(int *)parm_ptr = atoi(pszParmValue);
1842 *(const char ***)parm_ptr = str_list_make(talloc_autofree_context(),
1843 pszParmValue, NULL);
1847 string_set(parm_ptr, pszParmValue);
1851 string_set(parm_ptr, pszParmValue);
1852 strupper(*(char **)parm_ptr);
1856 for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
1859 parm_table[parmnum].enum_list[i].name)) {
1861 parm_table[parmnum].
1866 if (!parm_table[parmnum].enum_list[i].name) {
1867 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n",
1868 pszParmValue, pszParmName));
1879 /***************************************************************************
1880 Process a parameter.
1881 ***************************************************************************/
1883 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue, void *userdata)
1885 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
1886 pszParmName, pszParmValue));
1890 variable argument do parameter
1892 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
1894 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...)
1901 s = talloc_vasprintf(NULL, fmt, ap);
1903 ret = do_parameter(pszParmName, s, NULL);
1910 set a parameter from the commandline - this is called from command line parameter
1911 parsing code. It sets the parameter then marks the parameter as unable to be modified
1912 by smb.conf processing
1914 BOOL lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
1916 int parmnum = map_parameter(pszParmName);
1919 while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
1922 if (parmnum < 0 && strchr(pszParmName, ':')) {
1923 /* set a parametric option */
1924 return lp_do_parameter_parametric(-1, pszParmName, pszParmValue, FLAG_CMDLINE);
1928 DEBUG(0,("Unknown option '%s'\n", pszParmName));
1932 /* reset the CMDLINE flag in case this has been called before */
1933 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
1935 if (!lp_do_parameter(-2, pszParmName, pszParmValue)) {
1939 parm_table[parmnum].flags |= FLAG_CMDLINE;
1941 /* we have to also set FLAG_CMDLINE on aliases */
1942 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1943 parm_table[i].flags |= FLAG_CMDLINE;
1945 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1946 parm_table[i].flags |= FLAG_CMDLINE;
1953 set a option from the commandline in 'a=b' format. Use to support --option
1955 BOOL lp_set_option(const char *option)
1973 ret = lp_set_cmdline(s, p+1);
1979 #define BOOLSTR(b) ((b) ? "Yes" : "No")
1981 /***************************************************************************
1982 Print a parameter of the specified type.
1983 ***************************************************************************/
1985 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
1991 for (i = 0; p->enum_list[i].name; i++) {
1992 if (*(int *)ptr == p->enum_list[i].value) {
1994 p->enum_list[i].name);
2001 fprintf(f, "%s", BOOLSTR(*(BOOL *)ptr));
2005 fprintf(f, "%d", *(int *)ptr);
2009 if ((char ***)ptr && *(char ***)ptr) {
2010 char **list = *(char ***)ptr;
2012 for (; *list; list++)
2013 fprintf(f, "%s%s", *list,
2014 ((*(list+1))?", ":""));
2020 if (*(char **)ptr) {
2021 fprintf(f, "%s", *(char **)ptr);
2029 /***************************************************************************
2030 Check if two parameters are equal.
2031 ***************************************************************************/
2033 static BOOL equal_parameter(parm_type type, void *ptr1, void *ptr2)
2037 return (*((BOOL *)ptr1) == *((BOOL *)ptr2));
2041 return (*((int *)ptr1) == *((int *)ptr2));
2044 return str_list_equal((const char **)(*(char ***)ptr1),
2045 (const char **)(*(char ***)ptr2));
2050 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
2055 return (p1 == p2 || strequal(p1, p2));
2063 /***************************************************************************
2064 Process a new section (service). At this stage all sections are services.
2065 Later we'll have special sections that permit server parameters to be set.
2066 Returns True on success, False on failure.
2067 ***************************************************************************/
2069 static BOOL do_section(const char *pszSectionName, void *userdata)
2072 BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2073 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2076 /* if we've just struck a global section, note the fact. */
2077 bInGlobalSection = isglobal;
2079 /* check for multiple global sections */
2080 if (bInGlobalSection) {
2081 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2085 /* if we have a current service, tidy it up before moving on */
2088 if (iServiceIndex >= 0)
2089 bRetval = service_ok(iServiceIndex);
2091 /* if all is still well, move to the next record in the services array */
2093 /* We put this here to avoid an odd message order if messages are */
2094 /* issued by the post-processing of a previous section. */
2095 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2097 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
2099 DEBUG(0, ("Failed to add a new service\n"));
2108 /***************************************************************************
2109 Determine if a partcular base parameter is currentl set to the default value.
2110 ***************************************************************************/
2112 static BOOL is_default(int i)
2114 if (!defaults_saved)
2116 switch (parm_table[i].type) {
2118 return str_list_equal((const char **)parm_table[i].def.lvalue,
2119 (const char **)(*(char ***)parm_table[i].ptr));
2122 return strequal(parm_table[i].def.svalue,
2123 *(char **)parm_table[i].ptr);
2125 return parm_table[i].def.bvalue ==
2126 *(BOOL *)parm_table[i].ptr;
2129 return parm_table[i].def.ivalue ==
2130 *(int *)parm_table[i].ptr;
2137 /***************************************************************************
2138 Display the contents of the global structure.
2139 ***************************************************************************/
2141 static void dump_globals(FILE *f)
2144 struct param_opt *data;
2146 fprintf(f, "# Global parameters\n[global]\n");
2148 for (i = 0; parm_table[i].label; i++)
2149 if (parm_table[i].class == P_GLOBAL &&
2150 parm_table[i].ptr &&
2151 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2152 if (defaults_saved && is_default(i))
2154 fprintf(f, "\t%s = ", parm_table[i].label);
2155 print_parameter(&parm_table[i], parm_table[i].ptr, f);
2158 if (Globals.param_opt != NULL) {
2159 data = Globals.param_opt;
2161 fprintf(f, "\t%s = %s\n", data->key, data->value);
2168 /***************************************************************************
2169 Display the contents of a single services record.
2170 ***************************************************************************/
2172 static void dump_a_service(service * pService, FILE * f)
2175 struct param_opt *data;
2177 if (pService != &sDefault)
2178 fprintf(f, "\n[%s]\n", pService->szService);
2180 for (i = 0; parm_table[i].label; i++)
2181 if (parm_table[i].class == P_LOCAL &&
2182 parm_table[i].ptr &&
2183 (*parm_table[i].label != '-') &&
2184 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2185 int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
2187 if (pService == &sDefault) {
2188 if (defaults_saved && is_default(i))
2191 if (equal_parameter(parm_table[i].type,
2192 ((char *)pService) +
2194 ((char *)&sDefault) +
2199 fprintf(f, "\t%s = ", parm_table[i].label);
2200 print_parameter(&parm_table[i],
2201 ((char *)pService) + pdiff, f);
2204 if (pService->param_opt != NULL) {
2205 data = pService->param_opt;
2207 fprintf(f, "\t%s = %s\n", data->key, data->value);
2214 /***************************************************************************
2215 Return info about the next service in a service. snum==-1 gives the globals.
2216 Return NULL when out of parameters.
2217 ***************************************************************************/
2219 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
2222 /* do the globals */
2223 for (; parm_table[*i].label; (*i)++) {
2224 if (parm_table[*i].class == P_SEPARATOR)
2225 return &parm_table[(*i)++];
2227 if (!parm_table[*i].ptr
2228 || (*parm_table[*i].label == '-'))
2232 && (parm_table[*i].ptr ==
2233 parm_table[(*i) - 1].ptr))
2236 return &parm_table[(*i)++];
2239 service *pService = ServicePtrs[snum];
2241 for (; parm_table[*i].label; (*i)++) {
2242 if (parm_table[*i].class == P_SEPARATOR)
2243 return &parm_table[(*i)++];
2245 if (parm_table[*i].class == P_LOCAL &&
2246 parm_table[*i].ptr &&
2247 (*parm_table[*i].label != '-') &&
2249 (parm_table[*i].ptr !=
2250 parm_table[(*i) - 1].ptr)))
2253 PTR_DIFF(parm_table[*i].ptr,
2256 if (allparameters ||
2257 !equal_parameter(parm_table[*i].type,
2258 ((char *)pService) +
2260 ((char *)&sDefault) +
2263 return &parm_table[(*i)++];
2273 /***************************************************************************
2274 Return TRUE if the passed service number is within range.
2275 ***************************************************************************/
2277 BOOL lp_snum_ok(int iService)
2279 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
2282 /***************************************************************************
2283 Auto-load some home services.
2284 ***************************************************************************/
2286 static void lp_add_auto_services(const char *str)
2291 /***************************************************************************
2292 Announce ourselves as a print server.
2293 ***************************************************************************/
2295 void update_server_announce_as_printserver(void)
2297 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
2300 /***************************************************************************
2301 Have we loaded a services file yet?
2302 ***************************************************************************/
2304 BOOL lp_loaded(void)
2309 /***************************************************************************
2310 Unload unused services.
2311 ***************************************************************************/
2313 void lp_killunused(struct smbsrv_connection *smb, BOOL (*snumused) (struct smbsrv_connection *, int))
2316 for (i = 0; i < iNumServices; i++) {
2320 if (!snumused || !snumused(smb, i)) {
2321 ServicePtrs[i]->valid = False;
2322 free_service(ServicePtrs[i]);
2327 /***************************************************************************
2329 ***************************************************************************/
2331 void lp_killservice(int iServiceIn)
2333 if (VALID(iServiceIn)) {
2334 ServicePtrs[iServiceIn]->valid = False;
2335 free_service(ServicePtrs[iServiceIn]);
2339 /***************************************************************************
2340 Load the services array from the services file. Return True on success,
2342 ***************************************************************************/
2348 struct param_opt *data;
2352 bInGlobalSection = True;
2354 if (Globals.param_opt != NULL) {
2355 struct param_opt *next;
2356 for (data=Globals.param_opt; data; data=next) {
2358 if (data->flags & FLAG_CMDLINE) continue;
2361 DLIST_REMOVE(Globals.param_opt, data);
2368 pstrcpy(n2, lp_configfile());
2369 standard_sub_basic(n2,sizeof(n2));
2370 DEBUG(2, ("lp_load: refreshing parameters from %s\n", n2));
2372 add_to_file_list(lp_configfile(), n2);
2374 /* We get sections first, so have to start 'behind' to make up */
2376 bRetval = pm_process(n2, do_section, do_parameter, NULL);
2378 /* finish up the last section */
2379 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
2381 if (iServiceIndex >= 0)
2382 bRetval = service_ok(iServiceIndex);
2384 lp_add_auto_services(lp_auto_services());
2386 lp_add_hidden("IPC$", "IPC");
2387 lp_add_hidden("ADMIN$", "DISK");
2389 set_default_server_announce_type();
2393 if (Globals.bWINSsupport) {
2394 lp_do_parameter(-1, "wins server", "127.0.0.1");
2402 /***************************************************************************
2403 Reset the max number of services.
2404 ***************************************************************************/
2406 void lp_resetnumservices(void)
2411 /***************************************************************************
2412 Return the max number of services.
2413 ***************************************************************************/
2415 int lp_numservices(void)
2417 return (iNumServices);
2420 /***************************************************************************
2421 Display the contents of the services array in human-readable form.
2422 ***************************************************************************/
2424 void lp_dump(FILE *f, BOOL show_defaults, int maxtoprint)
2429 defaults_saved = False;
2433 dump_a_service(&sDefault, f);
2435 for (iService = 0; iService < maxtoprint; iService++)
2436 lp_dump_one(f, show_defaults, iService);
2439 /***************************************************************************
2440 Display the contents of one service in human-readable form.
2441 ***************************************************************************/
2443 void lp_dump_one(FILE * f, BOOL show_defaults, int snum)
2446 if (ServicePtrs[snum]->szService[0] == '\0')
2448 dump_a_service(ServicePtrs[snum], f);
2452 /***************************************************************************
2453 Return the number of the service with the given name, or -1 if it doesn't
2454 exist. Note that this is a DIFFERENT ANIMAL from the internal function
2455 getservicebyname()! This works ONLY if all services have been loaded, and
2456 does not copy the found service.
2457 ***************************************************************************/
2459 int lp_servicenumber(const char *pszServiceName)
2462 fstring serviceName;
2465 for (iService = iNumServices - 1; iService >= 0; iService--) {
2466 if (VALID(iService) && ServicePtrs[iService]->szService) {
2468 * The substitution here is used to support %U is
2471 fstrcpy(serviceName, ServicePtrs[iService]->szService);
2472 standard_sub_basic(serviceName,sizeof(serviceName));
2473 if (strequal(serviceName, pszServiceName))
2479 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
2484 /*******************************************************************
2485 A useful volume label function.
2486 ********************************************************************/
2487 const char *volume_label(int snum)
2489 const char *ret = lp_volume(snum);
2491 return lp_servicename(snum);
2496 /*******************************************************************
2497 Set the server type we will announce as via nmbd.
2498 ********************************************************************/
2500 static void set_default_server_announce_type(void)
2502 default_server_announce = 0;
2503 default_server_announce |= SV_TYPE_WORKSTATION;
2504 default_server_announce |= SV_TYPE_SERVER;
2505 default_server_announce |= SV_TYPE_SERVER_UNIX;
2507 switch (lp_announce_as()) {
2508 case ANNOUNCE_AS_NT_SERVER:
2509 default_server_announce |= SV_TYPE_SERVER_NT;
2510 /* fall through... */
2511 case ANNOUNCE_AS_NT_WORKSTATION:
2512 default_server_announce |= SV_TYPE_NT;
2514 case ANNOUNCE_AS_WIN95:
2515 default_server_announce |= SV_TYPE_WIN95_PLUS;
2517 case ANNOUNCE_AS_WFW:
2518 default_server_announce |= SV_TYPE_WFW;
2524 switch (lp_server_role()) {
2525 case ROLE_DOMAIN_MEMBER:
2526 default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
2528 case ROLE_DOMAIN_PDC:
2529 default_server_announce |= SV_TYPE_DOMAIN_CTRL;
2531 case ROLE_DOMAIN_BDC:
2532 default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
2534 case ROLE_STANDALONE:
2538 if (lp_time_server())
2539 default_server_announce |= SV_TYPE_TIME_SOURCE;
2541 if (lp_host_msdfs())
2542 default_server_announce |= SV_TYPE_DFS_SERVER;
2544 /* TODO: only announce us as print server when we are a print server */
2545 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
2548 /***********************************************************
2549 If we are PDC then prefer us as DMB
2550 ************************************************************/
2552 BOOL lp_domain_master(void)
2554 return (lp_server_role() == ROLE_DOMAIN_PDC);
2557 /***********************************************************
2558 If we are PDC then prefer us as DMB
2559 ************************************************************/
2561 BOOL lp_domain_logons(void)
2563 return (lp_server_role() == ROLE_DOMAIN_PDC) || (lp_server_role() == ROLE_DOMAIN_BDC);
2566 /***********************************************************
2567 If we are DMB then prefer us as LMB
2568 ************************************************************/
2570 BOOL lp_preferred_master(void)
2572 return (lp_local_master() && lp_domain_master());
2575 /*******************************************************************
2577 ********************************************************************/
2579 void lp_remove_service(int snum)
2581 ServicePtrs[snum]->valid = False;
2584 /*******************************************************************
2586 ********************************************************************/
2588 void lp_copy_service(int snum, const char *new_name)
2590 const char *oldname = lp_servicename(snum);
2591 do_section(new_name, NULL);
2593 snum = lp_servicenumber(new_name);
2595 lp_do_parameter(snum, "copy", oldname);
2600 /*******************************************************************
2601 Get the default server type we will announce as via nmbd.
2602 ********************************************************************/
2603 int lp_default_server_announce(void)
2605 return default_server_announce;
2608 const char *lp_printername(int snum)
2610 const char *ret = _lp_printername(snum);
2611 if (ret == NULL || (ret != NULL && *ret == '\0'))
2612 ret = lp_const_servicename(snum);
2618 /*******************************************************************
2619 Return the max print jobs per queue.
2620 ********************************************************************/
2622 int lp_maxprintjobs(int snum)
2624 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
2625 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
2626 maxjobs = PRINT_MAX_JOBID - 1;