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;
120 char *szSMBPasswdFile;
126 char **szPasswordServers;
127 char *szSocketOptions;
129 char **szWINSservers;
131 char *szSocketAddress;
132 char *szAnnounceVersion; /* This is initialised in init_globals */
135 char **szNetbiosAliases;
136 char *szNetbiosScope;
137 char *szDomainOtherSIDs;
138 char **szNameResolveOrder;
140 char **dcerpc_ep_servers;
141 char **server_services;
142 char *ntptr_providor;
143 char *szWinbindSeparator;
144 char *swat_directory;
157 BOOL paranoid_server_security;
160 int announce_as; /* This is initialised in init_globals */
166 char *socket_options;
169 BOOL bPreferredMaster;
170 BOOL bEncryptPasswords;
172 BOOL bObeyPamRestrictions;
173 BOOL bLargeReadwrite;
177 BOOL bBindInterfacesOnly;
179 BOOL bNTStatusSupport;
185 BOOL bClientPlaintextAuth;
186 BOOL bClientLanManAuth;
187 BOOL bClientNTLMv2Auth;
188 BOOL client_use_spnego_principal;
191 BOOL bUnixExtensions;
192 BOOL bDisableNetbios;
194 struct param_opt *param_opt;
198 static global Globals;
201 * This structure describes a single service.
216 char **ntvfs_handler;
232 struct param_opt *param_opt;
234 char dummy[3]; /* for alignment */
239 /* This is a default service used to prime a services structure */
240 static service sDefault = {
242 NULL, /* szService */
245 NULL, /* szInclude */
246 NULL, /* szPrintername */
247 NULL, /* szHostsallow */
248 NULL, /* szHostsdeny */
252 NULL, /* ntvfs_handler */
253 1000, /* iMaxPrintJobs */
254 0, /* iMaxConnections */
256 True, /* bAvailable */
257 True, /* bBrowseable */
258 True, /* bRead_only */
259 False, /* bPrint_ok */
260 False, /* bMap_system */
261 False, /* bMap_hidden */
262 True, /* bMap_archive */
263 True, /* bStrictLocking */
265 False, /* bMSDfsRoot */
266 False, /* bStrictSync */
267 False, /* bCIFileSystem */
268 NULL, /* Parametric options */
273 /* local variables */
274 static service **ServicePtrs = NULL;
275 static int iNumServices = 0;
276 static int iServiceIndex = 0;
277 static BOOL bInGlobalSection = True;
278 static int default_server_announce;
280 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
282 /* prototypes for the special type handlers */
283 static BOOL handle_include(const char *pszParmValue, char **ptr);
284 static BOOL handle_copy(const char *pszParmValue, char **ptr);
286 static void set_default_server_announce_type(void);
288 static const struct enum_list enum_protocol[] = {
289 {PROTOCOL_NT1, "NT1"},
290 {PROTOCOL_LANMAN2, "LANMAN2"},
291 {PROTOCOL_LANMAN1, "LANMAN1"},
292 {PROTOCOL_CORE, "CORE"},
293 {PROTOCOL_COREPLUS, "COREPLUS"},
294 {PROTOCOL_COREPLUS, "CORE+"},
298 static const struct enum_list enum_security[] = {
299 {SEC_SHARE, "SHARE"},
301 {SEC_SERVER, "SERVER"},
302 {SEC_DOMAIN, "DOMAIN"},
309 /* Types of machine we can announce as. */
310 #define ANNOUNCE_AS_NT_SERVER 1
311 #define ANNOUNCE_AS_WIN95 2
312 #define ANNOUNCE_AS_WFW 3
313 #define ANNOUNCE_AS_NT_WORKSTATION 4
315 static const struct enum_list enum_announce_as[] = {
316 {ANNOUNCE_AS_NT_SERVER, "NT"},
317 {ANNOUNCE_AS_NT_SERVER, "NT Server"},
318 {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"},
319 {ANNOUNCE_AS_WIN95, "win95"},
320 {ANNOUNCE_AS_WFW, "WfW"},
324 static const struct enum_list enum_bool_auto[] = {
335 /* Client-side offline caching policy types */
336 #define CSC_POLICY_MANUAL 0
337 #define CSC_POLICY_DOCUMENTS 1
338 #define CSC_POLICY_PROGRAMS 2
339 #define CSC_POLICY_DISABLE 3
341 static const struct enum_list enum_csc_policy[] = {
342 {CSC_POLICY_MANUAL, "manual"},
343 {CSC_POLICY_DOCUMENTS, "documents"},
344 {CSC_POLICY_PROGRAMS, "programs"},
345 {CSC_POLICY_DISABLE, "disable"},
349 /* SMB signing types. */
350 static const struct enum_list enum_smb_signing_vals[] = {
351 {SMB_SIGNING_OFF, "No"},
352 {SMB_SIGNING_OFF, "False"},
353 {SMB_SIGNING_OFF, "0"},
354 {SMB_SIGNING_OFF, "Off"},
355 {SMB_SIGNING_OFF, "disabled"},
356 {SMB_SIGNING_SUPPORTED, "Yes"},
357 {SMB_SIGNING_SUPPORTED, "True"},
358 {SMB_SIGNING_SUPPORTED, "1"},
359 {SMB_SIGNING_SUPPORTED, "On"},
360 {SMB_SIGNING_SUPPORTED, "enabled"},
361 {SMB_SIGNING_REQUIRED, "required"},
362 {SMB_SIGNING_REQUIRED, "mandatory"},
363 {SMB_SIGNING_REQUIRED, "force"},
364 {SMB_SIGNING_REQUIRED, "forced"},
365 {SMB_SIGNING_REQUIRED, "enforced"},
366 {SMB_SIGNING_AUTO, "auto"},
370 static const struct enum_list enum_server_role[] = {
371 {ROLE_STANDALONE, "standalone"},
372 {ROLE_DOMAIN_MEMBER, "member server"},
373 {ROLE_DOMAIN_BDC, "bdc"},
374 {ROLE_DOMAIN_PDC, "pdc"},
379 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
381 * Note: We have a flag called FLAG_DEVELOPER but is not used at this time, it
382 * is implied in current control logic. This may change at some later time. A
383 * flag value of 0 means - show as development option only.
385 * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
386 * screen in SWAT. This is used to exclude parameters as well as to squash all
387 * parameters that have been duplicated by pseudonyms.
389 static struct parm_struct parm_table[] = {
390 {"Base Options", P_SEP, P_SEPARATOR},
392 {"server role", P_ENUM, P_GLOBAL, &Globals.server_role, NULL, enum_server_role, FLAG_BASIC},
394 {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
395 {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
396 {"ncalrpc dir", P_STRING, P_GLOBAL, &Globals.ncalrpc_dir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
397 {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
398 {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
399 {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
400 {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE},
401 {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkgroup, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
402 {"realm", P_STRING, P_GLOBAL, &Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
403 {"netbios name", P_USTRING, P_GLOBAL, &Globals.szNetbiosName, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
404 {"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
405 {"netbios scope", P_USTRING, P_GLOBAL, &Globals.szNetbiosScope, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
406 {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
407 {"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
408 {"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
409 {"ntvfs handler", P_LIST, P_LOCAL, &sDefault.ntvfs_handler, NULL, NULL, FLAG_ADVANCED},
410 {"ntptr providor", P_STRING, P_GLOBAL, &Globals.ntptr_providor, NULL, NULL, FLAG_ADVANCED},
411 {"dcerpc endpoint servers", P_LIST, P_GLOBAL, &Globals.dcerpc_ep_servers, NULL, NULL, FLAG_ADVANCED},
412 {"server services", P_LIST, P_GLOBAL, &Globals.server_services, NULL, NULL, FLAG_ADVANCED},
414 {"Security Options", P_SEP, P_SEPARATOR},
416 {"security", P_ENUM, P_GLOBAL, &Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
417 {"auth methods", P_LIST, P_GLOBAL, &Globals.AuthMethods, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
418 {"encrypt passwords", P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
419 {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
420 {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
421 {"password server", P_LIST, P_GLOBAL, &Globals.szPasswordServers, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
422 {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
423 {"sam database", P_STRING, P_GLOBAL, &Globals.szSAM_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
424 {"spoolss database", P_STRING, P_GLOBAL, &Globals.szSPOOLSS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
425 {"wins database", P_STRING, P_GLOBAL, &Globals.szWINS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
426 {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
428 {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
429 {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
430 {"lanman auth", P_BOOL, P_GLOBAL, &Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
431 {"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
432 {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
433 {"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
434 {"client plaintext auth", P_BOOL, P_GLOBAL, &Globals.bClientPlaintextAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
435 {"client use spnego principal", P_BOOL, P_GLOBAL, &Globals.client_use_spnego_principal, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
437 {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE},
439 {"hosts allow", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
440 {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
442 {"Logging Options", P_SEP, P_SEPARATOR},
444 {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
445 {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_HIDE},
446 {"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
448 {"Protocol Options", P_SEP, P_SEPARATOR},
450 {"smb ports", P_LIST, P_GLOBAL, &Globals.smb_ports, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
451 {"nbt port", P_INTEGER, P_GLOBAL, &Globals.nbt_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
452 {"dgram port", P_INTEGER, P_GLOBAL, &Globals.dgram_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
453 {"cldap port", P_INTEGER, P_GLOBAL, &Globals.cldap_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
454 {"krb5 port", P_INTEGER, P_GLOBAL, &Globals.krb5_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
455 {"web port", P_INTEGER, P_GLOBAL, &Globals.web_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
456 {"tls enabled", P_BOOL, P_GLOBAL, &Globals.tls_enabled, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
457 {"tls keyfile", P_STRING, P_GLOBAL, &Globals.tls_keyfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
458 {"tls certfile", P_STRING, P_GLOBAL, &Globals.tls_certfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
459 {"tls cafile", P_STRING, P_GLOBAL, &Globals.tls_cafile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
460 {"tls crlfile", P_STRING, P_GLOBAL, &Globals.tls_crlfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
461 {"swat directory", P_STRING, P_GLOBAL, &Globals.swat_directory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
462 {"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, FLAG_DEVELOPER},
463 {"max protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
464 {"min protocol", P_ENUM, P_GLOBAL, &Globals.minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
465 {"unicode", P_BOOL, P_GLOBAL, &Globals.bUnicode, NULL, NULL, FLAG_DEVELOPER},
466 {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL, NULL, FLAG_DEVELOPER},
467 {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL, NULL, FLAG_DEVELOPER},
468 {"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
470 {"nt status support", P_BOOL, P_GLOBAL, &Globals.bNTStatusSupport, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
472 {"announce version", P_STRING, P_GLOBAL, &Globals.szAnnounceVersion, NULL, NULL, FLAG_DEVELOPER},
473 {"announce as", P_ENUM, P_GLOBAL, &Globals.announce_as, NULL, enum_announce_as, FLAG_DEVELOPER},
474 {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
475 {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
477 {"name resolve order", P_LIST, P_GLOBAL, &Globals.szNameResolveOrder, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
478 {"max wins ttl", P_INTEGER, P_GLOBAL, &Globals.max_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
479 {"min wins ttl", P_INTEGER, P_GLOBAL, &Globals.min_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
480 {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
481 {"unix extensions", P_BOOL, P_GLOBAL, &Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
482 {"use spnego", P_BOOL, P_GLOBAL, &Globals.bUseSpnego, NULL, NULL, FLAG_DEVELOPER},
483 {"server signing", P_ENUM, P_GLOBAL, &Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
484 {"client signing", P_ENUM, P_GLOBAL, &Globals.client_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
485 {"rpc big endian", P_BOOL, P_GLOBAL, &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, &Globals.paranoid_server_security, NULL, NULL, FLAG_DEVELOPER},
491 {"socket options", P_STRING, P_GLOBAL, &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, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
519 {"prefered master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_HIDE},
520 {"local master", P_BOOL, P_GLOBAL, &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, &Globals.szWINSservers, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
527 {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
529 {"Locking Options", P_SEP, P_SEPARATOR},
531 {"csc policy", P_ENUM, P_LOCAL, &sDefault.iCSCPolicy, NULL, enum_csc_policy, FLAG_SHARE | FLAG_GLOBAL},
533 {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
535 {"Miscellaneous Options", P_SEP, P_SEPARATOR},
537 {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE},
538 {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
539 {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
540 {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_HIDE},
541 {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
542 {"pid directory", P_STRING, P_GLOBAL, &Globals.szPidDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
543 {"js include", P_LIST, P_GLOBAL, &Globals.jsInclude, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
544 {"setup directory", P_STRING, P_GLOBAL, &Globals.szSetupDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
546 {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL, NULL, FLAG_DEVELOPER},
547 {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL, NULL, FLAG_HIDE},
549 {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy, NULL, FLAG_HIDE},
550 {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include, NULL, FLAG_HIDE},
552 {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
553 {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_SHARE },
554 {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_SHARE},
556 {"panic action", P_STRING, P_GLOBAL, &Globals.szPanicAction, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
558 {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_SHARE},
559 {"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
560 {"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
562 {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
567 return the parameter table
569 struct parm_struct *lp_parm_table(void)
574 /***************************************************************************
575 Initialise the global parameter structure.
576 ***************************************************************************/
577 static void init_globals(void)
582 DEBUG(3, ("Initialising global parameters\n"));
584 for (i = 0; parm_table[i].label; i++) {
585 if ((parm_table[i].type == P_STRING ||
586 parm_table[i].type == P_USTRING) &&
588 !(parm_table[i].flags & FLAG_CMDLINE)) {
589 string_set(parm_table[i].ptr, "");
593 do_parameter("config file", dyn_CONFIGFILE, NULL);
595 do_parameter("server role", "standalone", NULL);
597 /* options that can be set on the command line must be initialised via
598 the slower do_parameter() to ensure that FLAG_CMDLINE is obeyed */
600 do_parameter("socket options", "TCP_NODELAY", NULL);
602 do_parameter("workgroup", DEFAULT_WORKGROUP, NULL);
603 myname = get_myname();
604 do_parameter("netbios name", myname, NULL);
606 do_parameter("max protocol", "NT1", NULL);
607 do_parameter("name resolve order", "lmhosts wins host bcast", NULL);
609 do_parameter("fstype", FSTYPE_STRING, NULL);
610 do_parameter("ntvfs handler", "unixuid default", NULL);
611 do_parameter("max connections", "-1", NULL);
613 do_parameter("dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup", NULL);
614 do_parameter("server services", "smb rpc nbt ldap cldap web kdc", NULL);
615 do_parameter("ntptr providor", "simple_ldb", NULL);
616 do_parameter("auth methods", "anonymous sam_ignoredomain", NULL);
617 do_parameter("smb passwd file", dyn_SMB_PASSWD_FILE, NULL);
618 do_parameter("private dir", dyn_PRIVATE_DIR, NULL);
619 do_parameter("sam database", "sam.ldb", NULL);
620 do_parameter("spoolss database", "spoolss.ldb", NULL);
621 do_parameter("wins database", "wins.ldb", NULL);
622 do_parameter("registry:HKEY_LOCAL_MACHINE", "hklm.ldb", NULL);
624 /* This hive should be dynamically generated by Samba using
625 data from the sam, but for the moment leave it in a tdb to
626 keep regedt32 from popping up an annoying dialog. */
627 do_parameter("registry:HKEY_USERS", "hku.ldb", NULL);
629 /* using UTF8 by default allows us to support all chars */
630 do_parameter("unix charset", "UTF8", NULL);
632 /* Use codepage 850 as a default for the dos character set */
633 do_parameter("dos charset", "CP850", NULL);
636 * Allow the default PASSWD_CHAT to be overridden in local.h.
638 do_parameter("passwd chat", DEFAULT_PASSWD_CHAT, NULL);
640 do_parameter("pid directory", dyn_PIDDIR, NULL);
641 do_parameter("lock dir", dyn_LOCKDIR, NULL);
642 do_parameter("ncalrpc dir", dyn_NCALRPCDIR, NULL);
644 do_parameter("socket address", "0.0.0.0", NULL);
645 do_parameter_var("server string", "Samba %s", SAMBA_VERSION_STRING);
647 do_parameter_var("announce version", "%d.%d",
648 DEFAULT_MAJOR_VERSION,
649 DEFAULT_MINOR_VERSION);
651 do_parameter("password server", "*", NULL);
653 do_parameter("max mux", "50", NULL);
654 do_parameter("max xmit", "12288", NULL);
655 do_parameter("password level", "0", NULL);
656 do_parameter("LargeReadwrite", "True", NULL);
657 do_parameter("minprotocol", "CORE", NULL);
658 do_parameter("security", "USER", NULL);
659 do_parameter("paranoid server security", "True", NULL);
660 do_parameter("EncryptPasswords", "True", NULL);
661 do_parameter("ReadRaw", "True", NULL);
662 do_parameter("WriteRaw", "True", NULL);
663 do_parameter("NullPasswords", "False", NULL);
664 do_parameter("ObeyPamRestrictions", "False", NULL);
665 do_parameter("announce as", "NT SERVER", NULL);
667 do_parameter("TimeServer", "False", NULL);
668 do_parameter("BindInterfacesOnly", "False", NULL);
669 do_parameter("Unicode", "True", NULL);
670 do_parameter("ClientLanManAuth", "True", NULL);
671 do_parameter("LanmanAuth", "True", NULL);
672 do_parameter("NTLMAuth", "True", NULL);
673 do_parameter("client use spnego principal", "False", NULL);
675 do_parameter("UnixExtensions", "False", NULL);
677 do_parameter("PreferredMaster", "Auto", NULL);
678 do_parameter("LocalMaster", "True", NULL);
680 do_parameter("WINSsupport", "False", NULL);
682 do_parameter("winbind separator", "\\", NULL);
684 do_parameter("client signing", "Yes", NULL);
685 do_parameter("server signing", "auto", NULL);
687 do_parameter("use spnego", "True", NULL);
689 do_parameter("smb ports", SMB_PORTS, NULL);
690 do_parameter("nbt port", "137", NULL);
691 do_parameter("dgram port", "138", NULL);
692 do_parameter("cldap port", "389", NULL);
693 do_parameter("krb5 port", "88", NULL);
694 do_parameter("web port", "901", NULL);
695 do_parameter("swat directory", dyn_SWATDIR, NULL);
697 do_parameter("nt status support", "True", NULL);
699 do_parameter("max wins ttl", "432000", NULL);
700 do_parameter("min wins ttl", "10", NULL);
702 do_parameter("tls enabled", "True", NULL);
703 do_parameter("tls keyfile", "tls/key.pem", NULL);
704 do_parameter("tls certfile", "tls/cert.pem", NULL);
705 do_parameter("tls cafile", "tls/ca.pem", NULL);
706 do_parameter_var("js include", "%s/js", dyn_LIBDIR);
707 do_parameter_var("setup directory", "%s/setup", dyn_LIBDIR);
710 static TALLOC_CTX *lp_talloc;
712 /******************************************************************* a
713 Free up temporary memory - called from the main loop.
714 ********************************************************************/
716 void lp_talloc_free(void)
720 talloc_free(lp_talloc);
724 /*******************************************************************
725 Convenience routine to grab string parameters into temporary memory
726 and run standard_sub_basic on them. The buffers can be written to by
727 callers without affecting the source string.
728 ********************************************************************/
730 static const char *lp_string(const char *s)
732 #if 0 /* until REWRITE done to make thread-safe */
733 size_t len = s ? strlen(s) : 0;
737 /* The follow debug is useful for tracking down memory problems
738 especially if you have an inner loop that is calling a lp_*()
739 function that returns a string. Perhaps this debug should be
740 present all the time? */
743 DEBUG(10, ("lp_string(%s)\n", s));
746 #if 0 /* until REWRITE done to make thread-safe */
748 lp_talloc = talloc_init("lp_talloc");
750 ret = talloc_array(lp_talloc, char, len + 100); /* leave room for substitution */
758 StrnCpy(ret, s, len);
760 if (trim_string(ret, "\"", "\"")) {
761 if (strchr(ret,'"') != NULL)
762 StrnCpy(ret, s, len);
765 standard_sub_basic(ret,len+100);
772 In this section all the functions that are used to access the
773 parameters from the rest of the program are defined
776 #define FN_GLOBAL_STRING(fn_name,ptr) \
777 const char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
778 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
779 const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");}
780 #define FN_GLOBAL_LIST(fn_name,ptr) \
781 const char **fn_name(void) {return(*(const char ***)(ptr));}
782 #define FN_GLOBAL_BOOL(fn_name,ptr) \
783 BOOL fn_name(void) {return(*(BOOL *)(ptr));}
784 #define FN_GLOBAL_CHAR(fn_name,ptr) \
785 char fn_name(void) {return(*(char *)(ptr));}
786 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
787 int fn_name(void) {return(*(int *)(ptr));}
789 #define FN_LOCAL_STRING(fn_name,val) \
790 const char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
791 #define FN_LOCAL_CONST_STRING(fn_name,val) \
792 const char *fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
793 #define FN_LOCAL_LIST(fn_name,val) \
794 const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
795 #define FN_LOCAL_BOOL(fn_name,val) \
796 BOOL fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
797 #define FN_LOCAL_CHAR(fn_name,val) \
798 char fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
799 #define FN_LOCAL_INTEGER(fn_name,val) \
800 int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
802 FN_GLOBAL_INTEGER(lp_server_role, &Globals.server_role)
803 FN_GLOBAL_LIST(lp_smb_ports, &Globals.smb_ports)
804 FN_GLOBAL_INTEGER(lp_nbt_port, &Globals.nbt_port)
805 FN_GLOBAL_INTEGER(lp_dgram_port, &Globals.dgram_port)
806 FN_GLOBAL_INTEGER(lp_cldap_port, &Globals.cldap_port)
807 FN_GLOBAL_INTEGER(lp_krb5_port, &Globals.krb5_port)
808 FN_GLOBAL_INTEGER(lp_web_port, &Globals.web_port)
809 FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
810 FN_GLOBAL_STRING(lp_swat_directory, &Globals.swat_directory)
811 FN_GLOBAL_BOOL(lp_tls_enabled, &Globals.tls_enabled)
812 FN_GLOBAL_STRING(lp_tls_keyfile, &Globals.tls_keyfile)
813 FN_GLOBAL_STRING(lp_tls_certfile, &Globals.tls_certfile)
814 FN_GLOBAL_STRING(lp_tls_cafile, &Globals.tls_cafile)
815 FN_GLOBAL_STRING(lp_tls_crlfile, &Globals.tls_crlfile)
816 FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
817 FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset)
818 FN_GLOBAL_STRING(lp_logfile, &Globals.szLogFile)
819 FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
820 FN_GLOBAL_STRING(lp_smb_passwd_file, &Globals.szSMBPasswdFile)
821 FN_GLOBAL_STRING(lp_sam_url, &Globals.szSAM_URL)
822 FN_GLOBAL_STRING(lp_spoolss_url, &Globals.szSPOOLSS_URL)
823 FN_GLOBAL_STRING(lp_wins_url, &Globals.szWINS_URL)
824 FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
825 FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
826 FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
827 FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
828 FN_GLOBAL_STRING(lp_setupdir, &Globals.szSetupDir)
829 FN_GLOBAL_STRING(lp_ncalrpc_dir, &Globals.ncalrpc_dir)
830 FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
831 FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, &Globals.dcerpc_ep_servers)
832 FN_GLOBAL_LIST(lp_server_services, &Globals.server_services)
833 FN_GLOBAL_STRING(lp_ntptr_providor, &Globals.ntptr_providor)
834 FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
835 FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
836 FN_GLOBAL_LIST(lp_passwordserver, &Globals.szPasswordServers)
837 FN_GLOBAL_LIST(lp_name_resolve_order, &Globals.szNameResolveOrder)
838 FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
839 FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
840 FN_GLOBAL_STRING(lp_workgroup, &Globals.szWorkgroup)
841 FN_GLOBAL_STRING(lp_netbios_name, &Globals.szNetbiosName)
842 FN_GLOBAL_STRING(lp_netbios_scope, &Globals.szNetbiosScope)
843 FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
844 FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
845 FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
846 FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
847 FN_GLOBAL_STRING(lp_panic_action, &Globals.szPanicAction)
849 FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
850 FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
851 FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
852 FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
853 FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
854 FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw)
855 FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords)
856 FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions)
857 FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
858 static FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
859 FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
860 FN_GLOBAL_BOOL(lp_unicode, &Globals.bUnicode)
861 FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
862 FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
863 FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
864 FN_GLOBAL_BOOL(lp_client_plaintext_auth, &Globals.bClientPlaintextAuth)
865 FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
866 FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
867 FN_GLOBAL_BOOL(lp_client_use_spnego_principal, &Globals.client_use_spnego_principal)
868 FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
869 FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions)
870 FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
871 FN_GLOBAL_BOOL(lp_rpc_big_endian, &Globals.bRpcBigEndian)
872 FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
873 FN_GLOBAL_INTEGER(lp_min_wins_ttl, &Globals.min_wins_ttl)
874 FN_GLOBAL_INTEGER(lp_maxmux, &Globals.max_mux)
875 FN_GLOBAL_INTEGER(lp_max_xmit, &Globals.max_xmit)
876 FN_GLOBAL_INTEGER(lp_passwordlevel, &Globals.pwordlevel)
877 FN_GLOBAL_INTEGER(lp_maxprotocol, &Globals.maxprotocol)
878 FN_GLOBAL_INTEGER(lp_minprotocol, &Globals.minprotocol)
879 FN_GLOBAL_INTEGER(lp_security, &Globals.security)
880 FN_GLOBAL_LIST(lp_auth_methods, &Globals.AuthMethods)
881 FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security)
882 static FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as)
883 FN_GLOBAL_LIST(lp_js_include, &Globals.jsInclude)
886 FN_LOCAL_STRING(lp_servicename, szService)
887 FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
888 FN_LOCAL_STRING(lp_pathname, szPath)
889 static FN_LOCAL_STRING(_lp_printername, szPrintername)
890 FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
891 FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
892 FN_LOCAL_STRING(lp_comment, comment)
893 FN_LOCAL_STRING(lp_fstype, fstype)
894 static FN_LOCAL_STRING(lp_volume, volume)
895 FN_LOCAL_LIST(lp_ntvfs_handler, ntvfs_handler)
896 FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
897 FN_LOCAL_BOOL(lp_browseable, bBrowseable)
898 FN_LOCAL_BOOL(lp_readonly, bRead_only)
899 FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
900 FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
901 FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
902 FN_LOCAL_BOOL(lp_strict_locking, bStrictLocking)
903 FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
904 FN_LOCAL_BOOL(lp_ci_filesystem, bCIFileSystem)
905 FN_LOCAL_BOOL(lp_map_system, bMap_system)
906 FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
907 FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
908 FN_GLOBAL_INTEGER(lp_server_signing, &Globals.server_signing)
909 FN_GLOBAL_INTEGER(lp_client_signing, &Globals.client_signing)
911 /* local prototypes */
913 static int map_parameter(const char *pszParmName);
914 static BOOL set_boolean(BOOL *pb, const char *pszParmValue);
915 static int getservicebyname(const char *pszServiceName,
916 service * pserviceDest);
917 static void copy_service(service * pserviceDest,
918 service * pserviceSource, BOOL *pcopymapDest);
919 static BOOL service_ok(int iService);
920 static BOOL do_section(const char *pszSectionName, void *);
921 static void init_copymap(service * pservice);
923 /* This is a helper function for parametrical options support. */
924 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
925 /* Actual parametrical functions are quite simple */
926 const char *lp_get_parametric(int lookup_service, const char *type, const char *option)
929 struct param_opt *data;
931 if (lookup_service >= iNumServices) return NULL;
933 data = (lookup_service < 0) ?
934 Globals.param_opt : ServicePtrs[lookup_service]->param_opt;
936 asprintf(&vfskey, "%s:%s", type, option);
940 if (strcmp(data->key, vfskey) == 0) {
947 if (lookup_service >= 0) {
948 /* Try to fetch the same option but from globals */
949 /* but only if we are not already working with Globals */
950 data = Globals.param_opt;
952 if (strcmp(data->key, vfskey) == 0) {
966 /*******************************************************************
967 convenience routine to return int parameters.
968 ********************************************************************/
969 static int lp_int(const char *s)
973 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
977 return strtol(s, NULL, 0);
980 /*******************************************************************
981 convenience routine to return unsigned long parameters.
982 ********************************************************************/
983 static int lp_ulong(const char *s)
987 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
991 return strtoul(s, NULL, 0);
994 /*******************************************************************
995 convenience routine to return boolean parameters.
996 ********************************************************************/
997 static BOOL lp_bool(const char *s)
1002 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
1006 if (!set_boolean(&ret,s)) {
1007 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1015 /* Return parametric option from a given service. Type is a part of option before ':' */
1016 /* Parametric option has following syntax: 'Type: option = value' */
1017 /* Returned value is allocated in 'lp_talloc' context */
1019 const char *lp_parm_string(int lookup_service, const char *type, const char *option)
1021 const char *value = lp_get_parametric(lookup_service, type, option);
1024 return lp_string(value);
1029 /* Return parametric option from a given service. Type is a part of option before ':' */
1030 /* Parametric option has following syntax: 'Type: option = value' */
1031 /* Returned value is allocated in 'lp_talloc' context */
1033 const char **lp_parm_string_list(int lookup_service, const char *type, const char *option,
1034 const char *separator)
1036 const char *value = lp_get_parametric(lookup_service, type, option);
1039 return str_list_make(talloc_autofree_context(), value, separator);
1044 /* Return parametric option from a given service. Type is a part of option before ':' */
1045 /* Parametric option has following syntax: 'Type: option = value' */
1047 int lp_parm_int(int lookup_service, const char *type, const char *option, int default_v)
1049 const char *value = lp_get_parametric(lookup_service, type, option);
1052 return lp_int(value);
1057 /* Return parametric option from a given service. Type is a part of option before ':' */
1058 /* Parametric option has following syntax: 'Type: option = value' */
1060 unsigned long lp_parm_ulong(int lookup_service, const char *type, const char *option, unsigned long default_v)
1062 const char *value = lp_get_parametric(lookup_service, type, option);
1065 return lp_ulong(value);
1070 /* Return parametric option from a given service. Type is a part of option before ':' */
1071 /* Parametric option has following syntax: 'Type: option = value' */
1073 BOOL lp_parm_bool(int lookup_service, const char *type, const char *option, BOOL default_v)
1075 const char *value = lp_get_parametric(lookup_service, type, option);
1078 return lp_bool(value);
1084 /***************************************************************************
1085 Initialise a service to the defaults.
1086 ***************************************************************************/
1088 static void init_service(service * pservice)
1090 memset((char *)pservice, '\0', sizeof(service));
1091 copy_service(pservice, &sDefault, NULL);
1094 /***************************************************************************
1095 Free the dynamically allocated parts of a service struct.
1096 ***************************************************************************/
1098 static void free_service(service *pservice)
1101 struct param_opt *data, *pdata;
1105 if (pservice->szService)
1106 DEBUG(5, ("free_service: Freeing service %s\n",
1107 pservice->szService));
1109 string_free(&pservice->szService);
1110 SAFE_FREE(pservice->copymap);
1112 for (i = 0; parm_table[i].label; i++) {
1113 if ((parm_table[i].type == P_STRING ||
1114 parm_table[i].type == P_USTRING) &&
1115 parm_table[i].class == P_LOCAL) {
1116 string_free((char **)
1117 (((char *)pservice) +
1118 PTR_DIFF(parm_table[i].ptr, &sDefault)));
1119 } else if (parm_table[i].type == P_LIST &&
1120 parm_table[i].class == P_LOCAL) {
1121 char ***listp = (char ***)(((char *)pservice) +
1122 PTR_DIFF(parm_table[i].ptr, &sDefault));
1123 talloc_free(*listp);
1128 DEBUG(5,("Freeing parametrics:\n"));
1129 data = pservice->param_opt;
1131 DEBUG(5,("[%s = %s]\n", data->key, data->value));
1132 string_free(&data->key);
1133 string_free(&data->value);
1139 ZERO_STRUCTP(pservice);
1142 /***************************************************************************
1143 Add a new service to the services array initialising it with the given
1145 ***************************************************************************/
1147 static int add_a_service(const service *pservice, const char *name)
1151 int num_to_alloc = iNumServices + 1;
1152 struct param_opt *data, *pdata;
1154 tservice = *pservice;
1156 /* it might already exist */
1158 i = getservicebyname(name, NULL);
1160 /* Clean all parametric options for service */
1161 /* They will be added during parsing again */
1162 data = ServicePtrs[i]->param_opt;
1164 string_free(&data->key);
1165 string_free(&data->value);
1170 ServicePtrs[i]->param_opt = NULL;
1175 /* find an invalid one */
1176 for (i = 0; i < iNumServices; i++)
1177 if (!ServicePtrs[i]->valid)
1180 /* if not, then create one */
1181 if (i == iNumServices) {
1184 tsp = realloc_p(ServicePtrs, service *, num_to_alloc);
1187 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1192 ServicePtrs[iNumServices] = malloc_p(service);
1194 if (!ServicePtrs[iNumServices]) {
1195 DEBUG(0,("add_a_service: out of memory!\n"));
1201 free_service(ServicePtrs[i]);
1203 ServicePtrs[i]->valid = True;
1205 init_service(ServicePtrs[i]);
1206 copy_service(ServicePtrs[i], &tservice, NULL);
1208 string_set(&ServicePtrs[i]->szService, name);
1212 /***************************************************************************
1213 Add a new home service, with the specified home directory, defaults coming
1215 ***************************************************************************/
1217 BOOL lp_add_home(const char *pszHomename, int iDefaultService,
1218 const char *user, const char *pszHomedir)
1223 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1228 if (!(*(ServicePtrs[iDefaultService]->szPath))
1229 || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(-1))) {
1230 pstrcpy(newHomedir, pszHomedir);
1232 pstrcpy(newHomedir, lp_pathname(iDefaultService));
1233 string_sub(newHomedir,"%H", pszHomedir, sizeof(newHomedir));
1236 string_set(&ServicePtrs[i]->szPath, newHomedir);
1238 if (!(*(ServicePtrs[i]->comment))) {
1240 slprintf(comment, sizeof(comment) - 1,
1241 "Home directory of %s", user);
1242 string_set(&ServicePtrs[i]->comment, comment);
1244 ServicePtrs[i]->bAvailable = sDefault.bAvailable;
1245 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1247 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1253 /***************************************************************************
1254 Add a new service, based on an old one.
1255 ***************************************************************************/
1257 int lp_add_service(const char *pszService, int iDefaultService)
1259 return (add_a_service(ServicePtrs[iDefaultService], pszService));
1262 /***************************************************************************
1263 Add the IPC service.
1264 ***************************************************************************/
1266 static BOOL lp_add_hidden(const char *name, const char *fstype)
1269 int i = add_a_service(&sDefault, name);
1274 slprintf(comment, sizeof(comment) - 1,
1275 "%s Service (%s)", fstype, Globals.szServerString);
1277 string_set(&ServicePtrs[i]->szPath, tmpdir());
1278 string_set(&ServicePtrs[i]->comment, comment);
1279 string_set(&ServicePtrs[i]->fstype, fstype);
1280 ServicePtrs[i]->iMaxConnections = -1;
1281 ServicePtrs[i]->bAvailable = True;
1282 ServicePtrs[i]->bRead_only = True;
1283 ServicePtrs[i]->bPrint_ok = False;
1284 ServicePtrs[i]->bBrowseable = False;
1286 if (strcasecmp(fstype, "IPC") == 0) {
1287 lp_do_parameter(i, "ntvfs handler", "default");
1290 DEBUG(3, ("adding hidden service %s\n", name));
1295 /***************************************************************************
1296 Add a new printer service, with defaults coming from service iFrom.
1297 ***************************************************************************/
1299 BOOL lp_add_printer(const char *pszPrintername, int iDefaultService)
1301 const char *comment = "From Printcap";
1302 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1307 /* note that we do NOT default the availability flag to True - */
1308 /* we take it from the default service passed. This allows all */
1309 /* dynamic printers to be disabled by disabling the [printers] */
1310 /* entry (if/when the 'available' keyword is implemented!). */
1312 /* the printer name is set to the service name. */
1313 string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1314 string_set(&ServicePtrs[i]->comment, comment);
1315 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1316 /* Printers cannot be read_only. */
1317 ServicePtrs[i]->bRead_only = False;
1318 /* Printer services must be printable. */
1319 ServicePtrs[i]->bPrint_ok = True;
1321 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1323 update_server_announce_as_printserver();
1328 /***************************************************************************
1329 Map a parameter's string representation to something we can use.
1330 Returns False if the parameter string is not recognised, else TRUE.
1331 ***************************************************************************/
1333 static int map_parameter(const char *pszParmName)
1337 if (*pszParmName == '-')
1340 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1341 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1344 /* Warn only if it isn't parametric option */
1345 if (strchr(pszParmName, ':') == NULL)
1346 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1347 /* We do return 'fail' for parametric options as well because they are
1348 stored in different storage
1355 return the parameter structure for a parameter
1357 struct parm_struct *lp_parm_struct(const char *name)
1359 int parmnum = map_parameter(name);
1360 if (parmnum == -1) return NULL;
1361 return &parm_table[parmnum];
1365 return the parameter pointer for a parameter
1367 void *lp_parm_ptr(int snum, struct parm_struct *parm)
1372 return ((char *)ServicePtrs[snum]) + PTR_DIFF(parm->ptr, &sDefault);
1375 /***************************************************************************
1376 Set a boolean variable from the text value stored in the passed string.
1377 Returns True in success, False if the passed string does not correctly
1378 represent a boolean.
1379 ***************************************************************************/
1381 static BOOL set_boolean(BOOL *pb, const char *pszParmValue)
1386 if (strwicmp(pszParmValue, "yes") == 0 ||
1387 strwicmp(pszParmValue, "true") == 0 ||
1388 strwicmp(pszParmValue, "1") == 0)
1390 else if (strwicmp(pszParmValue, "no") == 0 ||
1391 strwicmp(pszParmValue, "False") == 0 ||
1392 strwicmp(pszParmValue, "0") == 0)
1396 ("ERROR: Badly formed boolean in configuration file: \"%s\".\n",
1403 /***************************************************************************
1404 Find a service by name. Otherwise works like get_service.
1405 ***************************************************************************/
1407 static int getservicebyname(const char *pszServiceName, service * pserviceDest)
1411 for (iService = iNumServices - 1; iService >= 0; iService--)
1412 if (VALID(iService) &&
1413 strwicmp(ServicePtrs[iService]->szService, pszServiceName) == 0) {
1414 if (pserviceDest != NULL)
1415 copy_service(pserviceDest, ServicePtrs[iService], NULL);
1422 /***************************************************************************
1423 Copy a service structure to another.
1424 If pcopymapDest is NULL then copy all fields
1425 ***************************************************************************/
1427 static void copy_service(service * pserviceDest, service * pserviceSource, BOOL *pcopymapDest)
1430 BOOL bcopyall = (pcopymapDest == NULL);
1431 struct param_opt *data, *pdata, *paramo;
1434 for (i = 0; parm_table[i].label; i++)
1435 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1436 (bcopyall || pcopymapDest[i])) {
1437 void *def_ptr = parm_table[i].ptr;
1439 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
1442 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
1445 switch (parm_table[i].type) {
1447 *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
1452 *(int *)dest_ptr = *(int *)src_ptr;
1456 string_set(dest_ptr,
1461 string_set(dest_ptr,
1463 strupper(*(char **)dest_ptr);
1466 *(const char ***)dest_ptr = str_list_copy(talloc_autofree_context(),
1467 *(const char ***)src_ptr);
1475 init_copymap(pserviceDest);
1476 if (pserviceSource->copymap)
1477 memcpy((void *)pserviceDest->copymap,
1478 (void *)pserviceSource->copymap,
1479 sizeof(BOOL) * NUMPARAMETERS);
1482 data = pserviceSource->param_opt;
1485 pdata = pserviceDest->param_opt;
1486 /* Traverse destination */
1488 /* If we already have same option, override it */
1489 if (strcmp(pdata->key, data->key) == 0) {
1490 string_free(&pdata->value);
1491 pdata->value = strdup(data->value);
1495 pdata = pdata->next;
1498 paramo = smb_xmalloc_p(struct param_opt);
1499 paramo->key = strdup(data->key);
1500 paramo->value = strdup(data->value);
1501 DLIST_ADD(pserviceDest->param_opt, paramo);
1507 /***************************************************************************
1508 Check a service for consistency. Return False if the service is in any way
1509 incomplete or faulty, else True.
1510 ***************************************************************************/
1512 static BOOL service_ok(int iService)
1517 if (ServicePtrs[iService]->szService[0] == '\0') {
1518 DEBUG(0, ("The following message indicates an internal error:\n"));
1519 DEBUG(0, ("No service name in service entry.\n"));
1523 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1524 /* I can't see why you'd want a non-printable printer service... */
1525 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
1526 if (!ServicePtrs[iService]->bPrint_ok) {
1527 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
1528 ServicePtrs[iService]->szService));
1529 ServicePtrs[iService]->bPrint_ok = True;
1530 update_server_announce_as_printserver();
1532 /* [printers] service must also be non-browsable. */
1533 if (ServicePtrs[iService]->bBrowseable)
1534 ServicePtrs[iService]->bBrowseable = False;
1537 /* If a service is flagged unavailable, log the fact at level 0. */
1538 if (!ServicePtrs[iService]->bAvailable)
1539 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
1540 ServicePtrs[iService]->szService));
1545 static struct file_lists {
1546 struct file_lists *next;
1550 } *file_lists = NULL;
1552 /*******************************************************************
1553 Keep a linked list of all config files so we know when one has changed
1554 it's date and needs to be reloaded.
1555 ********************************************************************/
1557 static void add_to_file_list(const char *fname, const char *subfname)
1559 struct file_lists *f = file_lists;
1562 if (f->name && !strcmp(f->name, fname))
1568 f = malloc_p(struct file_lists);
1571 f->next = file_lists;
1572 f->name = strdup(fname);
1577 f->subfname = strdup(subfname);
1583 f->modtime = file_modtime(subfname);
1585 time_t t = file_modtime(subfname);
1591 /*******************************************************************
1592 Check if a config file has changed date.
1593 ********************************************************************/
1595 BOOL lp_file_list_changed(void)
1597 struct file_lists *f = file_lists;
1598 DEBUG(6, ("lp_file_list_changed()\n"));
1604 pstrcpy(n2, f->name);
1605 standard_sub_basic(n2,sizeof(n2));
1607 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
1608 f->name, n2, ctime(&f->modtime)));
1610 mod_time = file_modtime(n2);
1612 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
1614 ("file %s modified: %s\n", n2,
1616 f->modtime = mod_time;
1617 SAFE_FREE(f->subfname);
1618 f->subfname = strdup(n2);
1626 /***************************************************************************
1627 Handle the include operation.
1628 ***************************************************************************/
1630 static BOOL handle_include(const char *pszParmValue, char **ptr)
1633 pstrcpy(fname, pszParmValue);
1635 standard_sub_basic(fname,sizeof(fname));
1637 add_to_file_list(pszParmValue, fname);
1639 string_set(ptr, fname);
1641 if (file_exist(fname))
1642 return (pm_process(fname, do_section, do_parameter, NULL));
1644 DEBUG(2, ("Can't find include file %s\n", fname));
1649 /***************************************************************************
1650 Handle the interpretation of the copy parameter.
1651 ***************************************************************************/
1653 static BOOL handle_copy(const char *pszParmValue, char **ptr)
1657 service serviceTemp;
1659 string_set(ptr, pszParmValue);
1661 init_service(&serviceTemp);
1665 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
1667 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
1668 if (iTemp == iServiceIndex) {
1669 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
1671 copy_service(ServicePtrs[iServiceIndex],
1673 ServicePtrs[iServiceIndex]->copymap);
1677 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
1681 free_service(&serviceTemp);
1685 /***************************************************************************
1686 Initialise a copymap.
1687 ***************************************************************************/
1689 static void init_copymap(service * pservice)
1692 SAFE_FREE(pservice->copymap);
1693 pservice->copymap = malloc_array_p(BOOL, NUMPARAMETERS);
1694 if (!pservice->copymap)
1696 ("Couldn't allocate copymap!! (size %d)\n",
1697 (int)NUMPARAMETERS));
1699 for (i = 0; i < NUMPARAMETERS; i++)
1700 pservice->copymap[i] = True;
1703 /***************************************************************************
1704 Return the local pointer to a parameter given the service number and the
1705 pointer into the default structure.
1706 ***************************************************************************/
1708 void *lp_local_ptr(int snum, void *ptr)
1710 return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
1714 /***************************************************************************
1715 Process a parametric option
1716 ***************************************************************************/
1717 static BOOL lp_do_parameter_parametric(int snum, const char *pszParmName, const char *pszParmValue, int flags)
1719 struct param_opt *paramo, *data;
1722 while (isspace((unsigned char)*pszParmName)) {
1726 name = strdup(pszParmName);
1727 if (!name) return False;
1732 data = Globals.param_opt;
1734 data = ServicePtrs[snum]->param_opt;
1737 /* Traverse destination */
1738 for (paramo=data; paramo; paramo=paramo->next) {
1739 /* If we already have the option set, override it unless
1740 it was a command line option and the new one isn't */
1741 if (strcmp(paramo->key, name) == 0) {
1742 if ((paramo->flags & FLAG_CMDLINE) &&
1743 !(flags & FLAG_CMDLINE)) {
1747 free(paramo->value);
1748 paramo->value = strdup(pszParmValue);
1749 paramo->flags = flags;
1755 paramo = smb_xmalloc_p(struct param_opt);
1756 paramo->key = strdup(name);
1757 paramo->value = strdup(pszParmValue);
1758 paramo->flags = flags;
1760 DLIST_ADD(Globals.param_opt, paramo);
1762 DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
1770 /***************************************************************************
1771 Process a parameter for a particular service number. If snum < 0
1772 then assume we are in the globals.
1773 ***************************************************************************/
1774 BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
1777 void *parm_ptr = NULL; /* where we are going to store the result */
1778 void *def_ptr = NULL;
1780 parmnum = map_parameter(pszParmName);
1783 if (strchr(pszParmName, ':')) {
1784 return lp_do_parameter_parametric(snum, pszParmName, pszParmValue, 0);
1786 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1790 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1791 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1795 /* if the flag has been set on the command line, then don't allow override,
1796 but don't report an error */
1797 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1801 def_ptr = parm_table[parmnum].ptr;
1803 /* we might point at a service, the default service or a global */
1807 if (parm_table[parmnum].class == P_GLOBAL) {
1809 ("Global parameter %s found in service section!\n",
1814 ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
1819 if (!ServicePtrs[snum]->copymap)
1820 init_copymap(ServicePtrs[snum]);
1822 /* this handles the aliases - set the copymap for other entries with
1823 the same data pointer */
1824 for (i = 0; parm_table[i].label; i++)
1825 if (parm_table[i].ptr == parm_table[parmnum].ptr)
1826 ServicePtrs[snum]->copymap[i] = False;
1829 /* if it is a special case then go ahead */
1830 if (parm_table[parmnum].special) {
1831 parm_table[parmnum].special(pszParmValue, (char **)parm_ptr);
1835 /* now switch on the type of variable it is */
1836 switch (parm_table[parmnum].type)
1839 set_boolean(parm_ptr, pszParmValue);
1843 *(int *)parm_ptr = atoi(pszParmValue);
1847 *(const char ***)parm_ptr = str_list_make(talloc_autofree_context(),
1848 pszParmValue, NULL);
1852 string_set(parm_ptr, pszParmValue);
1856 string_set(parm_ptr, pszParmValue);
1857 strupper(*(char **)parm_ptr);
1861 for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
1864 parm_table[parmnum].enum_list[i].name)) {
1866 parm_table[parmnum].
1871 if (!parm_table[parmnum].enum_list[i].name) {
1872 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n",
1873 pszParmValue, pszParmName));
1884 /***************************************************************************
1885 Process a parameter.
1886 ***************************************************************************/
1888 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue, void *userdata)
1890 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
1891 pszParmName, pszParmValue));
1895 variable argument do parameter
1897 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
1899 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...)
1906 s = talloc_vasprintf(NULL, fmt, ap);
1908 ret = do_parameter(pszParmName, s, NULL);
1915 set a parameter from the commandline - this is called from command line parameter
1916 parsing code. It sets the parameter then marks the parameter as unable to be modified
1917 by smb.conf processing
1919 BOOL lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
1921 int parmnum = map_parameter(pszParmName);
1924 while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
1927 if (parmnum < 0 && strchr(pszParmName, ':')) {
1928 /* set a parametric option */
1929 return lp_do_parameter_parametric(-1, pszParmName, pszParmValue, FLAG_CMDLINE);
1933 DEBUG(0,("Unknown option '%s'\n", pszParmName));
1937 /* reset the CMDLINE flag in case this has been called before */
1938 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
1940 if (!lp_do_parameter(-2, pszParmName, pszParmValue)) {
1944 parm_table[parmnum].flags |= FLAG_CMDLINE;
1946 /* we have to also set FLAG_CMDLINE on aliases */
1947 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1948 parm_table[i].flags |= FLAG_CMDLINE;
1950 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1951 parm_table[i].flags |= FLAG_CMDLINE;
1958 set a option from the commandline in 'a=b' format. Use to support --option
1960 BOOL lp_set_option(const char *option)
1978 ret = lp_set_cmdline(s, p+1);
1984 #define BOOLSTR(b) ((b) ? "Yes" : "No")
1986 /***************************************************************************
1987 Print a parameter of the specified type.
1988 ***************************************************************************/
1990 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
1996 for (i = 0; p->enum_list[i].name; i++) {
1997 if (*(int *)ptr == p->enum_list[i].value) {
1999 p->enum_list[i].name);
2006 fprintf(f, "%s", BOOLSTR(*(BOOL *)ptr));
2010 fprintf(f, "%d", *(int *)ptr);
2014 if ((char ***)ptr && *(char ***)ptr) {
2015 char **list = *(char ***)ptr;
2017 for (; *list; list++)
2018 fprintf(f, "%s%s", *list,
2019 ((*(list+1))?", ":""));
2025 if (*(char **)ptr) {
2026 fprintf(f, "%s", *(char **)ptr);
2034 /***************************************************************************
2035 Check if two parameters are equal.
2036 ***************************************************************************/
2038 static BOOL equal_parameter(parm_type type, void *ptr1, void *ptr2)
2042 return (*((BOOL *)ptr1) == *((BOOL *)ptr2));
2046 return (*((int *)ptr1) == *((int *)ptr2));
2049 return str_list_equal((const char **)(*(char ***)ptr1),
2050 (const char **)(*(char ***)ptr2));
2055 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
2060 return (p1 == p2 || strequal(p1, p2));
2068 /***************************************************************************
2069 Process a new section (service). At this stage all sections are services.
2070 Later we'll have special sections that permit server parameters to be set.
2071 Returns True on success, False on failure.
2072 ***************************************************************************/
2074 static BOOL do_section(const char *pszSectionName, void *userdata)
2077 BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2078 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2081 /* if we've just struck a global section, note the fact. */
2082 bInGlobalSection = isglobal;
2084 /* check for multiple global sections */
2085 if (bInGlobalSection) {
2086 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2090 /* if we have a current service, tidy it up before moving on */
2093 if (iServiceIndex >= 0)
2094 bRetval = service_ok(iServiceIndex);
2096 /* if all is still well, move to the next record in the services array */
2098 /* We put this here to avoid an odd message order if messages are */
2099 /* issued by the post-processing of a previous section. */
2100 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2102 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
2104 DEBUG(0, ("Failed to add a new service\n"));
2113 /***************************************************************************
2114 Determine if a partcular base parameter is currentl set to the default value.
2115 ***************************************************************************/
2117 static BOOL is_default(int i)
2119 if (!defaults_saved)
2121 switch (parm_table[i].type) {
2123 return str_list_equal((const char **)parm_table[i].def.lvalue,
2124 (const char **)(*(char ***)parm_table[i].ptr));
2127 return strequal(parm_table[i].def.svalue,
2128 *(char **)parm_table[i].ptr);
2130 return parm_table[i].def.bvalue ==
2131 *(BOOL *)parm_table[i].ptr;
2134 return parm_table[i].def.ivalue ==
2135 *(int *)parm_table[i].ptr;
2142 /***************************************************************************
2143 Display the contents of the global structure.
2144 ***************************************************************************/
2146 static void dump_globals(FILE *f)
2149 struct param_opt *data;
2151 fprintf(f, "# Global parameters\n[global]\n");
2153 for (i = 0; parm_table[i].label; i++)
2154 if (parm_table[i].class == P_GLOBAL &&
2155 parm_table[i].ptr &&
2156 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2157 if (defaults_saved && is_default(i))
2159 fprintf(f, "\t%s = ", parm_table[i].label);
2160 print_parameter(&parm_table[i], parm_table[i].ptr, f);
2163 if (Globals.param_opt != NULL) {
2164 data = Globals.param_opt;
2166 fprintf(f, "\t%s = %s\n", data->key, data->value);
2173 /***************************************************************************
2174 Display the contents of a single services record.
2175 ***************************************************************************/
2177 static void dump_a_service(service * pService, FILE * f)
2180 struct param_opt *data;
2182 if (pService != &sDefault)
2183 fprintf(f, "\n[%s]\n", pService->szService);
2185 for (i = 0; parm_table[i].label; i++)
2186 if (parm_table[i].class == P_LOCAL &&
2187 parm_table[i].ptr &&
2188 (*parm_table[i].label != '-') &&
2189 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2190 int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
2192 if (pService == &sDefault) {
2193 if (defaults_saved && is_default(i))
2196 if (equal_parameter(parm_table[i].type,
2197 ((char *)pService) +
2199 ((char *)&sDefault) +
2204 fprintf(f, "\t%s = ", parm_table[i].label);
2205 print_parameter(&parm_table[i],
2206 ((char *)pService) + pdiff, f);
2209 if (pService->param_opt != NULL) {
2210 data = pService->param_opt;
2212 fprintf(f, "\t%s = %s\n", data->key, data->value);
2219 /***************************************************************************
2220 Return info about the next service in a service. snum==-1 gives the globals.
2221 Return NULL when out of parameters.
2222 ***************************************************************************/
2224 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
2227 /* do the globals */
2228 for (; parm_table[*i].label; (*i)++) {
2229 if (parm_table[*i].class == P_SEPARATOR)
2230 return &parm_table[(*i)++];
2232 if (!parm_table[*i].ptr
2233 || (*parm_table[*i].label == '-'))
2237 && (parm_table[*i].ptr ==
2238 parm_table[(*i) - 1].ptr))
2241 return &parm_table[(*i)++];
2244 service *pService = ServicePtrs[snum];
2246 for (; parm_table[*i].label; (*i)++) {
2247 if (parm_table[*i].class == P_SEPARATOR)
2248 return &parm_table[(*i)++];
2250 if (parm_table[*i].class == P_LOCAL &&
2251 parm_table[*i].ptr &&
2252 (*parm_table[*i].label != '-') &&
2254 (parm_table[*i].ptr !=
2255 parm_table[(*i) - 1].ptr)))
2258 PTR_DIFF(parm_table[*i].ptr,
2261 if (allparameters ||
2262 !equal_parameter(parm_table[*i].type,
2263 ((char *)pService) +
2265 ((char *)&sDefault) +
2268 return &parm_table[(*i)++];
2278 /***************************************************************************
2279 Return TRUE if the passed service number is within range.
2280 ***************************************************************************/
2282 BOOL lp_snum_ok(int iService)
2284 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
2287 /***************************************************************************
2288 Auto-load some home services.
2289 ***************************************************************************/
2291 static void lp_add_auto_services(const char *str)
2296 /***************************************************************************
2297 Announce ourselves as a print server.
2298 ***************************************************************************/
2300 void update_server_announce_as_printserver(void)
2302 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
2305 /***************************************************************************
2306 Have we loaded a services file yet?
2307 ***************************************************************************/
2309 BOOL lp_loaded(void)
2314 /***************************************************************************
2315 Unload unused services.
2316 ***************************************************************************/
2318 void lp_killunused(struct smbsrv_connection *smb, BOOL (*snumused) (struct smbsrv_connection *, int))
2321 for (i = 0; i < iNumServices; i++) {
2325 if (!snumused || !snumused(smb, i)) {
2326 ServicePtrs[i]->valid = False;
2327 free_service(ServicePtrs[i]);
2332 /***************************************************************************
2334 ***************************************************************************/
2336 void lp_killservice(int iServiceIn)
2338 if (VALID(iServiceIn)) {
2339 ServicePtrs[iServiceIn]->valid = False;
2340 free_service(ServicePtrs[iServiceIn]);
2344 /***************************************************************************
2345 Load the services array from the services file. Return True on success,
2347 ***************************************************************************/
2353 struct param_opt *data;
2357 bInGlobalSection = True;
2359 if (Globals.param_opt != NULL) {
2360 struct param_opt *next;
2361 for (data=Globals.param_opt; data; data=next) {
2363 if (data->flags & FLAG_CMDLINE) continue;
2366 DLIST_REMOVE(Globals.param_opt, data);
2373 pstrcpy(n2, lp_configfile());
2374 standard_sub_basic(n2,sizeof(n2));
2375 DEBUG(2, ("lp_load: refreshing parameters from %s\n", n2));
2377 add_to_file_list(lp_configfile(), n2);
2379 /* We get sections first, so have to start 'behind' to make up */
2381 bRetval = pm_process(n2, do_section, do_parameter, NULL);
2383 /* finish up the last section */
2384 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
2386 if (iServiceIndex >= 0)
2387 bRetval = service_ok(iServiceIndex);
2389 lp_add_auto_services(lp_auto_services());
2391 lp_add_hidden("IPC$", "IPC");
2392 lp_add_hidden("ADMIN$", "DISK");
2394 set_default_server_announce_type();
2398 if (Globals.bWINSsupport) {
2399 lp_do_parameter(-1, "wins server", "127.0.0.1");
2407 /***************************************************************************
2408 Reset the max number of services.
2409 ***************************************************************************/
2411 void lp_resetnumservices(void)
2416 /***************************************************************************
2417 Return the max number of services.
2418 ***************************************************************************/
2420 int lp_numservices(void)
2422 return (iNumServices);
2425 /***************************************************************************
2426 Display the contents of the services array in human-readable form.
2427 ***************************************************************************/
2429 void lp_dump(FILE *f, BOOL show_defaults, int maxtoprint)
2434 defaults_saved = False;
2438 dump_a_service(&sDefault, f);
2440 for (iService = 0; iService < maxtoprint; iService++)
2441 lp_dump_one(f, show_defaults, iService);
2444 /***************************************************************************
2445 Display the contents of one service in human-readable form.
2446 ***************************************************************************/
2448 void lp_dump_one(FILE * f, BOOL show_defaults, int snum)
2451 if (ServicePtrs[snum]->szService[0] == '\0')
2453 dump_a_service(ServicePtrs[snum], f);
2457 /***************************************************************************
2458 Return the number of the service with the given name, or -1 if it doesn't
2459 exist. Note that this is a DIFFERENT ANIMAL from the internal function
2460 getservicebyname()! This works ONLY if all services have been loaded, and
2461 does not copy the found service.
2462 ***************************************************************************/
2464 int lp_servicenumber(const char *pszServiceName)
2467 fstring serviceName;
2470 for (iService = iNumServices - 1; iService >= 0; iService--) {
2471 if (VALID(iService) && ServicePtrs[iService]->szService) {
2473 * The substitution here is used to support %U is
2476 fstrcpy(serviceName, ServicePtrs[iService]->szService);
2477 standard_sub_basic(serviceName,sizeof(serviceName));
2478 if (strequal(serviceName, pszServiceName))
2484 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
2489 /*******************************************************************
2490 A useful volume label function.
2491 ********************************************************************/
2492 const char *volume_label(int snum)
2494 const char *ret = lp_volume(snum);
2496 return lp_servicename(snum);
2501 /*******************************************************************
2502 Set the server type we will announce as via nmbd.
2503 ********************************************************************/
2505 static void set_default_server_announce_type(void)
2507 default_server_announce = 0;
2508 default_server_announce |= SV_TYPE_WORKSTATION;
2509 default_server_announce |= SV_TYPE_SERVER;
2510 default_server_announce |= SV_TYPE_SERVER_UNIX;
2512 switch (lp_announce_as()) {
2513 case ANNOUNCE_AS_NT_SERVER:
2514 default_server_announce |= SV_TYPE_SERVER_NT;
2515 /* fall through... */
2516 case ANNOUNCE_AS_NT_WORKSTATION:
2517 default_server_announce |= SV_TYPE_NT;
2519 case ANNOUNCE_AS_WIN95:
2520 default_server_announce |= SV_TYPE_WIN95_PLUS;
2522 case ANNOUNCE_AS_WFW:
2523 default_server_announce |= SV_TYPE_WFW;
2529 switch (lp_server_role()) {
2530 case ROLE_DOMAIN_MEMBER:
2531 default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
2533 case ROLE_DOMAIN_PDC:
2534 default_server_announce |= SV_TYPE_DOMAIN_CTRL;
2536 case ROLE_DOMAIN_BDC:
2537 default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
2539 case ROLE_STANDALONE:
2543 if (lp_time_server())
2544 default_server_announce |= SV_TYPE_TIME_SOURCE;
2546 if (lp_host_msdfs())
2547 default_server_announce |= SV_TYPE_DFS_SERVER;
2549 /* TODO: only announce us as print server when we are a print server */
2550 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
2553 /***********************************************************
2554 If we are PDC then prefer us as DMB
2555 ************************************************************/
2557 BOOL lp_domain_master(void)
2559 return (lp_server_role() == ROLE_DOMAIN_PDC);
2562 /***********************************************************
2563 If we are PDC then prefer us as DMB
2564 ************************************************************/
2566 BOOL lp_domain_logons(void)
2568 return (lp_server_role() == ROLE_DOMAIN_PDC) || (lp_server_role() == ROLE_DOMAIN_BDC);
2571 /***********************************************************
2572 If we are DMB then prefer us as LMB
2573 ************************************************************/
2575 BOOL lp_preferred_master(void)
2577 return (lp_local_master() && lp_domain_master());
2580 /*******************************************************************
2582 ********************************************************************/
2584 void lp_remove_service(int snum)
2586 ServicePtrs[snum]->valid = False;
2589 /*******************************************************************
2591 ********************************************************************/
2593 void lp_copy_service(int snum, const char *new_name)
2595 const char *oldname = lp_servicename(snum);
2596 do_section(new_name, NULL);
2598 snum = lp_servicenumber(new_name);
2600 lp_do_parameter(snum, "copy", oldname);
2605 /*******************************************************************
2606 Get the default server type we will announce as via nmbd.
2607 ********************************************************************/
2608 int lp_default_server_announce(void)
2610 return default_server_announce;
2613 const char *lp_printername(int snum)
2615 const char *ret = _lp_printername(snum);
2616 if (ret == NULL || (ret != NULL && *ret == '\0'))
2617 ret = lp_const_servicename(snum);
2623 /*******************************************************************
2624 Return the max print jobs per queue.
2625 ********************************************************************/
2627 int lp_maxprintjobs(int snum)
2629 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
2630 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
2631 maxjobs = PRINT_MAX_JOBID - 1;