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 "librpc/gen_ndr/ndr_svcctl.h"
62 #include "librpc/gen_ndr/ndr_samr.h"
63 #include "dlinklist.h"
64 #include "param/loadparm.h"
66 static BOOL bLoaded = False;
69 #define GLOBAL_NAME "global"
73 #define PRINTERS_NAME "printers"
77 #define HOMES_NAME "homes"
80 /* some helpful bits */
81 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && ServicePtrs[(i)]->valid)
82 #define VALID(i) ServicePtrs[i]->valid
84 static BOOL do_parameter(const char *, const char *, void *);
85 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...);
87 static BOOL defaults_saved = False;
91 struct param_opt *prev, *next;
98 * This structure describes global (ie., server-wide) parameters.
108 char *display_charset;
112 char *szServerString;
113 char *szAutoServices;
119 char *szWINS_CONFIG_URL;
123 char **szPasswordServers;
124 char *szSocketOptions;
126 char **szWINSservers;
128 char *szSocketAddress;
129 char *szAnnounceVersion; /* This is initialised in init_globals */
132 char **szNetbiosAliases;
133 char *szNetbiosScope;
134 char *szDomainOtherSIDs;
135 char **szNameResolveOrder;
137 char **dcerpc_ep_servers;
138 char **server_services;
139 char *ntptr_providor;
140 char *szWinbindSeparator;
141 BOOL bWinbindSealedPipes;
142 char *swat_directory;
155 BOOL paranoid_server_security;
158 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"},
303 /* Types of machine we can announce as. */
304 #define ANNOUNCE_AS_NT_SERVER 1
305 #define ANNOUNCE_AS_WIN95 2
306 #define ANNOUNCE_AS_WFW 3
307 #define ANNOUNCE_AS_NT_WORKSTATION 4
309 static const struct enum_list enum_announce_as[] = {
310 {ANNOUNCE_AS_NT_SERVER, "NT"},
311 {ANNOUNCE_AS_NT_SERVER, "NT Server"},
312 {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"},
313 {ANNOUNCE_AS_WIN95, "win95"},
314 {ANNOUNCE_AS_WFW, "WfW"},
318 static const struct enum_list enum_bool_auto[] = {
329 /* Client-side offline caching policy types */
330 #define CSC_POLICY_MANUAL 0
331 #define CSC_POLICY_DOCUMENTS 1
332 #define CSC_POLICY_PROGRAMS 2
333 #define CSC_POLICY_DISABLE 3
335 static const struct enum_list enum_csc_policy[] = {
336 {CSC_POLICY_MANUAL, "manual"},
337 {CSC_POLICY_DOCUMENTS, "documents"},
338 {CSC_POLICY_PROGRAMS, "programs"},
339 {CSC_POLICY_DISABLE, "disable"},
343 /* SMB signing types. */
344 static const struct enum_list enum_smb_signing_vals[] = {
345 {SMB_SIGNING_OFF, "No"},
346 {SMB_SIGNING_OFF, "False"},
347 {SMB_SIGNING_OFF, "0"},
348 {SMB_SIGNING_OFF, "Off"},
349 {SMB_SIGNING_OFF, "disabled"},
350 {SMB_SIGNING_SUPPORTED, "Yes"},
351 {SMB_SIGNING_SUPPORTED, "True"},
352 {SMB_SIGNING_SUPPORTED, "1"},
353 {SMB_SIGNING_SUPPORTED, "On"},
354 {SMB_SIGNING_SUPPORTED, "enabled"},
355 {SMB_SIGNING_REQUIRED, "required"},
356 {SMB_SIGNING_REQUIRED, "mandatory"},
357 {SMB_SIGNING_REQUIRED, "force"},
358 {SMB_SIGNING_REQUIRED, "forced"},
359 {SMB_SIGNING_REQUIRED, "enforced"},
360 {SMB_SIGNING_AUTO, "auto"},
364 static const struct enum_list enum_server_role[] = {
365 {ROLE_STANDALONE, "standalone"},
366 {ROLE_DOMAIN_MEMBER, "member server"},
367 {ROLE_DOMAIN_BDC, "bdc"},
368 {ROLE_DOMAIN_PDC, "pdc"},
373 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
375 * Note: We have a flag called FLAG_DEVELOPER but is not used at this time, it
376 * is implied in current control logic. This may change at some later time. A
377 * flag value of 0 means - show as development option only.
379 * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
380 * screen in SWAT. This is used to exclude parameters as well as to squash all
381 * parameters that have been duplicated by pseudonyms.
383 static struct parm_struct parm_table[] = {
384 {"Base Options", P_SEP, P_SEPARATOR},
386 {"server role", P_ENUM, P_GLOBAL, &Globals.server_role, NULL, enum_server_role, FLAG_BASIC},
388 {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
389 {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
390 {"ncalrpc dir", P_STRING, P_GLOBAL, &Globals.ncalrpc_dir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
391 {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
392 {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
393 {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
394 {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE},
395 {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkgroup, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
396 {"realm", P_STRING, P_GLOBAL, &Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
397 {"netbios name", P_USTRING, P_GLOBAL, &Globals.szNetbiosName, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
398 {"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
399 {"netbios scope", P_USTRING, P_GLOBAL, &Globals.szNetbiosScope, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
400 {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
401 {"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
402 {"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
403 {"ntvfs handler", P_LIST, P_LOCAL, &sDefault.ntvfs_handler, NULL, NULL, FLAG_ADVANCED},
404 {"ntptr providor", P_STRING, P_GLOBAL, &Globals.ntptr_providor, NULL, NULL, FLAG_ADVANCED},
405 {"dcerpc endpoint servers", P_LIST, P_GLOBAL, &Globals.dcerpc_ep_servers, NULL, NULL, FLAG_ADVANCED},
406 {"server services", P_LIST, P_GLOBAL, &Globals.server_services, NULL, NULL, FLAG_ADVANCED},
408 {"Security Options", P_SEP, P_SEPARATOR},
410 {"security", P_ENUM, P_GLOBAL, &Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
411 {"auth methods", P_LIST, P_GLOBAL, &Globals.AuthMethods, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
412 {"encrypt passwords", P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
413 {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
414 {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
415 {"password server", P_LIST, P_GLOBAL, &Globals.szPasswordServers, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
416 {"sam database", P_STRING, P_GLOBAL, &Globals.szSAM_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
417 {"spoolss database", P_STRING, P_GLOBAL, &Globals.szSPOOLSS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
418 {"wins config database", P_STRING, P_GLOBAL, &Globals.szWINS_CONFIG_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
419 {"wins database", P_STRING, P_GLOBAL, &Globals.szWINS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
420 {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
421 {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
422 {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
423 {"lanman auth", P_BOOL, P_GLOBAL, &Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
424 {"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
425 {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
426 {"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
427 {"client plaintext auth", P_BOOL, P_GLOBAL, &Globals.bClientPlaintextAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
428 {"client use spnego principal", P_BOOL, P_GLOBAL, &Globals.client_use_spnego_principal, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
430 {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE},
432 {"hosts allow", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
433 {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
435 {"Logging Options", P_SEP, P_SEPARATOR},
437 {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
438 {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_HIDE},
439 {"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
441 {"Protocol Options", P_SEP, P_SEPARATOR},
443 {"smb ports", P_LIST, P_GLOBAL, &Globals.smb_ports, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
444 {"nbt port", P_INTEGER, P_GLOBAL, &Globals.nbt_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
445 {"dgram port", P_INTEGER, P_GLOBAL, &Globals.dgram_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
446 {"cldap port", P_INTEGER, P_GLOBAL, &Globals.cldap_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
447 {"krb5 port", P_INTEGER, P_GLOBAL, &Globals.krb5_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
448 {"kpasswd port", P_INTEGER, P_GLOBAL, &Globals.kpasswd_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
449 {"web port", P_INTEGER, P_GLOBAL, &Globals.web_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
450 {"tls enabled", P_BOOL, P_GLOBAL, &Globals.tls_enabled, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
451 {"tls keyfile", P_STRING, P_GLOBAL, &Globals.tls_keyfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
452 {"tls certfile", P_STRING, P_GLOBAL, &Globals.tls_certfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
453 {"tls cafile", P_STRING, P_GLOBAL, &Globals.tls_cafile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
454 {"tls crlfile", P_STRING, P_GLOBAL, &Globals.tls_crlfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
455 {"swat directory", P_STRING, P_GLOBAL, &Globals.swat_directory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
456 {"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, FLAG_DEVELOPER},
457 {"max protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
458 {"min protocol", P_ENUM, P_GLOBAL, &Globals.minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
459 {"unicode", P_BOOL, P_GLOBAL, &Globals.bUnicode, NULL, NULL, FLAG_DEVELOPER},
460 {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL, NULL, FLAG_DEVELOPER},
461 {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL, NULL, FLAG_DEVELOPER},
462 {"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
464 {"nt status support", P_BOOL, P_GLOBAL, &Globals.bNTStatusSupport, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
466 {"announce version", P_STRING, P_GLOBAL, &Globals.szAnnounceVersion, NULL, NULL, FLAG_DEVELOPER},
467 {"announce as", P_ENUM, P_GLOBAL, &Globals.announce_as, NULL, enum_announce_as, FLAG_DEVELOPER},
468 {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
469 {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
471 {"name resolve order", P_LIST, P_GLOBAL, &Globals.szNameResolveOrder, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
472 {"max wins ttl", P_INTEGER, P_GLOBAL, &Globals.max_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
473 {"min wins ttl", P_INTEGER, P_GLOBAL, &Globals.min_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
474 {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
475 {"unix extensions", P_BOOL, P_GLOBAL, &Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
476 {"use spnego", P_BOOL, P_GLOBAL, &Globals.bUseSpnego, NULL, NULL, FLAG_DEVELOPER},
477 {"server signing", P_ENUM, P_GLOBAL, &Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
478 {"client signing", P_ENUM, P_GLOBAL, &Globals.client_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
479 {"rpc big endian", P_BOOL, P_GLOBAL, &Globals.bRpcBigEndian, NULL, NULL, FLAG_DEVELOPER},
481 {"Tuning Options", P_SEP, P_SEPARATOR},
483 {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL, NULL, FLAG_SHARE},
484 {"paranoid server security", P_BOOL, P_GLOBAL, &Globals.paranoid_server_security, NULL, NULL, FLAG_DEVELOPER},
485 {"socket options", P_STRING, P_GLOBAL, &Globals.socket_options, NULL, NULL, FLAG_DEVELOPER},
487 {"strict sync", P_BOOL, P_LOCAL, &sDefault.bStrictSync, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
488 {"case insensitive filesystem", P_BOOL, P_LOCAL, &sDefault.bCIFileSystem, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
490 {"Printing Options", P_SEP, P_SEPARATOR},
492 {"max print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxPrintJobs, NULL, NULL, FLAG_PRINT},
493 {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_PRINT},
494 {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_HIDE},
496 {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_PRINT},
497 {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_HIDE},
499 {"Filename Handling", P_SEP, P_SEPARATOR},
501 {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
502 {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
503 {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
505 {"Domain Options", P_SEP, P_SEPARATOR},
507 {"Logon Options", P_SEP, P_SEPARATOR},
510 {"Browse Options", P_SEP, P_SEPARATOR},
512 {"preferred master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
513 {"prefered master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_HIDE},
514 {"local master", P_BOOL, P_GLOBAL, &Globals.bLocalMaster, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
515 {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
516 {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_HIDE},
518 {"WINS Options", P_SEP, P_SEPARATOR},
520 {"wins server", P_LIST, P_GLOBAL, &Globals.szWINSservers, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
521 {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
523 {"Locking Options", P_SEP, P_SEPARATOR},
525 {"csc policy", P_ENUM, P_LOCAL, &sDefault.iCSCPolicy, NULL, enum_csc_policy, FLAG_SHARE | FLAG_GLOBAL},
527 {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
529 {"Miscellaneous Options", P_SEP, P_SEPARATOR},
531 {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE},
532 {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
533 {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
534 {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_HIDE},
535 {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
536 {"pid directory", P_STRING, P_GLOBAL, &Globals.szPidDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
537 {"js include", P_LIST, P_GLOBAL, &Globals.jsInclude, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
538 {"setup directory", P_STRING, P_GLOBAL, &Globals.szSetupDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
540 {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL, NULL, FLAG_DEVELOPER},
541 {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL, NULL, FLAG_HIDE},
543 {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy, NULL, FLAG_HIDE},
544 {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include, NULL, FLAG_HIDE},
546 {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
547 {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_SHARE },
548 {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_SHARE},
550 {"panic action", P_STRING, P_GLOBAL, &Globals.szPanicAction, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
552 {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_SHARE},
553 {"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
554 {"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
555 {"winbind sealed pipes", P_BOOL, P_GLOBAL, &Globals.bWinbindSealedPipes, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
557 {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
562 return the parameter table
564 struct parm_struct *lp_parm_table(void)
569 /***************************************************************************
570 Initialise the global parameter structure.
571 ***************************************************************************/
572 static void init_globals(void)
577 DEBUG(3, ("Initialising global parameters\n"));
579 for (i = 0; parm_table[i].label; i++) {
580 if ((parm_table[i].type == P_STRING ||
581 parm_table[i].type == P_USTRING) &&
583 !(parm_table[i].flags & FLAG_CMDLINE)) {
584 string_set(parm_table[i].ptr, "");
588 do_parameter("config file", dyn_CONFIGFILE, NULL);
590 do_parameter("server role", "standalone", NULL);
592 /* options that can be set on the command line must be initialised via
593 the slower do_parameter() to ensure that FLAG_CMDLINE is obeyed */
595 do_parameter("socket options", "TCP_NODELAY", NULL);
597 do_parameter("workgroup", DEFAULT_WORKGROUP, NULL);
598 myname = get_myname();
599 do_parameter("netbios name", myname, NULL);
601 do_parameter("max protocol", "NT1", NULL);
602 do_parameter("name resolve order", "lmhosts wins host bcast", NULL);
604 do_parameter("fstype", FSTYPE_STRING, NULL);
605 do_parameter("ntvfs handler", "unixuid default", NULL);
606 do_parameter("max connections", "-1", NULL);
608 do_parameter("dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup", NULL);
609 do_parameter("server services", "smb rpc nbt wrepl ldap cldap web kdc", NULL);
610 do_parameter("ntptr providor", "simple_ldb", NULL);
611 do_parameter("auth methods", "anonymous sam_ignoredomain", NULL);
612 do_parameter("private dir", dyn_PRIVATE_DIR, NULL);
613 do_parameter("sam database", "sam.ldb", NULL);
614 do_parameter("spoolss database", "spoolss.ldb", NULL);
615 do_parameter("wins config database", "wins_config.ldb", NULL);
616 do_parameter("wins database", "wins.ldb", NULL);
617 do_parameter("registry:HKEY_LOCAL_MACHINE", "hklm.ldb", NULL);
619 /* This hive should be dynamically generated by Samba using
620 data from the sam, but for the moment leave it in a tdb to
621 keep regedt32 from popping up an annoying dialog. */
622 do_parameter("registry:HKEY_USERS", "hku.ldb", NULL);
624 /* using UTF8 by default allows us to support all chars */
625 do_parameter("unix charset", "UTF8", NULL);
627 /* Use codepage 850 as a default for the dos character set */
628 do_parameter("dos charset", "CP850", NULL);
631 * Allow the default PASSWD_CHAT to be overridden in local.h.
633 do_parameter("passwd chat", DEFAULT_PASSWD_CHAT, NULL);
635 do_parameter("pid directory", dyn_PIDDIR, NULL);
636 do_parameter("lock dir", dyn_LOCKDIR, NULL);
637 do_parameter("ncalrpc dir", dyn_NCALRPCDIR, NULL);
639 do_parameter("socket address", "0.0.0.0", NULL);
640 do_parameter_var("server string", "Samba %s", SAMBA_VERSION_STRING);
642 do_parameter_var("announce version", "%d.%d",
643 DEFAULT_MAJOR_VERSION,
644 DEFAULT_MINOR_VERSION);
646 do_parameter("password server", "*", NULL);
648 do_parameter("max mux", "50", NULL);
649 do_parameter("max xmit", "12288", NULL);
650 do_parameter("password level", "0", NULL);
651 do_parameter("LargeReadwrite", "True", NULL);
652 do_parameter("minprotocol", "CORE", NULL);
653 do_parameter("security", "USER", NULL);
654 do_parameter("paranoid server security", "True", NULL);
655 do_parameter("EncryptPasswords", "True", NULL);
656 do_parameter("ReadRaw", "True", NULL);
657 do_parameter("WriteRaw", "True", NULL);
658 do_parameter("NullPasswords", "False", NULL);
659 do_parameter("ObeyPamRestrictions", "False", NULL);
660 do_parameter("announce as", "NT SERVER", NULL);
662 do_parameter("TimeServer", "False", NULL);
663 do_parameter("BindInterfacesOnly", "False", NULL);
664 do_parameter("Unicode", "True", NULL);
665 do_parameter("ClientLanManAuth", "True", NULL);
666 do_parameter("LanmanAuth", "True", NULL);
667 do_parameter("NTLMAuth", "True", NULL);
668 do_parameter("client use spnego principal", "False", NULL);
670 do_parameter("UnixExtensions", "False", NULL);
672 do_parameter("PreferredMaster", "Auto", NULL);
673 do_parameter("LocalMaster", "True", NULL);
675 do_parameter("WINSsupport", "False", NULL);
677 do_parameter("winbind separator", "\\", NULL);
678 do_parameter("winbind sealed pipes", "True", 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("kpasswd port", "464", NULL);
691 do_parameter("web port", "901", NULL);
692 do_parameter("swat directory", dyn_SWATDIR, NULL);
694 do_parameter("nt status support", "True", NULL);
696 do_parameter("max wins ttl", "518400", NULL); /* 6 days */
697 do_parameter("min wins ttl", "10", NULL);
699 do_parameter("tls enabled", "True", NULL);
700 do_parameter("tls keyfile", "tls/key.pem", NULL);
701 do_parameter("tls certfile", "tls/cert.pem", NULL);
702 do_parameter("tls cafile", "tls/ca.pem", NULL);
703 do_parameter_var("js include", "%s/js", dyn_LIBDIR);
704 do_parameter_var("setup directory", "%s/setup", dyn_LIBDIR);
707 static TALLOC_CTX *lp_talloc;
709 /******************************************************************* a
710 Free up temporary memory - called from the main loop.
711 ********************************************************************/
713 void lp_talloc_free(void)
717 talloc_free(lp_talloc);
721 /*******************************************************************
722 Convenience routine to grab string parameters into temporary memory
723 and run standard_sub_basic on them. The buffers can be written to by
724 callers without affecting the source string.
725 ********************************************************************/
727 static const char *lp_string(const char *s)
729 #if 0 /* until REWRITE done to make thread-safe */
730 size_t len = s ? strlen(s) : 0;
734 /* The follow debug is useful for tracking down memory problems
735 especially if you have an inner loop that is calling a lp_*()
736 function that returns a string. Perhaps this debug should be
737 present all the time? */
740 DEBUG(10, ("lp_string(%s)\n", s));
743 #if 0 /* until REWRITE done to make thread-safe */
745 lp_talloc = talloc_init("lp_talloc");
747 ret = talloc_array(lp_talloc, char, len + 100); /* leave room for substitution */
755 StrnCpy(ret, s, len);
757 if (trim_string(ret, "\"", "\"")) {
758 if (strchr(ret,'"') != NULL)
759 StrnCpy(ret, s, len);
762 standard_sub_basic(ret,len+100);
769 In this section all the functions that are used to access the
770 parameters from the rest of the program are defined
773 #define FN_GLOBAL_STRING(fn_name,ptr) \
774 const char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
775 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
776 const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");}
777 #define FN_GLOBAL_LIST(fn_name,ptr) \
778 const char **fn_name(void) {return(*(const char ***)(ptr));}
779 #define FN_GLOBAL_BOOL(fn_name,ptr) \
780 BOOL fn_name(void) {return(*(BOOL *)(ptr));}
781 #define FN_GLOBAL_CHAR(fn_name,ptr) \
782 char fn_name(void) {return(*(char *)(ptr));}
783 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
784 int fn_name(void) {return(*(int *)(ptr));}
786 #define FN_LOCAL_STRING(fn_name,val) \
787 const char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
788 #define FN_LOCAL_CONST_STRING(fn_name,val) \
789 const char *fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
790 #define FN_LOCAL_LIST(fn_name,val) \
791 const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
792 #define FN_LOCAL_BOOL(fn_name,val) \
793 BOOL fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
794 #define FN_LOCAL_CHAR(fn_name,val) \
795 char fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
796 #define FN_LOCAL_INTEGER(fn_name,val) \
797 int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
799 FN_GLOBAL_INTEGER(lp_server_role, &Globals.server_role)
800 FN_GLOBAL_LIST(lp_smb_ports, &Globals.smb_ports)
801 FN_GLOBAL_INTEGER(lp_nbt_port, &Globals.nbt_port)
802 FN_GLOBAL_INTEGER(lp_dgram_port, &Globals.dgram_port)
803 FN_GLOBAL_INTEGER(lp_cldap_port, &Globals.cldap_port)
804 FN_GLOBAL_INTEGER(lp_krb5_port, &Globals.krb5_port)
805 FN_GLOBAL_INTEGER(lp_kpasswd_port, &Globals.kpasswd_port)
806 FN_GLOBAL_INTEGER(lp_web_port, &Globals.web_port)
807 FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
808 FN_GLOBAL_STRING(lp_swat_directory, &Globals.swat_directory)
809 FN_GLOBAL_BOOL(lp_tls_enabled, &Globals.tls_enabled)
810 FN_GLOBAL_STRING(lp_tls_keyfile, &Globals.tls_keyfile)
811 FN_GLOBAL_STRING(lp_tls_certfile, &Globals.tls_certfile)
812 FN_GLOBAL_STRING(lp_tls_cafile, &Globals.tls_cafile)
813 FN_GLOBAL_STRING(lp_tls_crlfile, &Globals.tls_crlfile)
814 FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
815 FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset)
816 FN_GLOBAL_STRING(lp_logfile, &Globals.szLogFile)
817 FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
818 FN_GLOBAL_STRING(lp_sam_url, &Globals.szSAM_URL)
819 FN_GLOBAL_STRING(lp_spoolss_url, &Globals.szSPOOLSS_URL)
820 FN_GLOBAL_STRING(lp_wins_config_url, &Globals.szWINS_CONFIG_URL)
821 FN_GLOBAL_STRING(lp_wins_url, &Globals.szWINS_URL)
822 FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
823 FN_GLOBAL_BOOL(lp_winbind_sealed_pipes, &Globals.bWinbindSealedPipes)
824 FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
825 FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
826 FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
827 FN_GLOBAL_STRING(lp_setupdir, &Globals.szSetupDir)
828 FN_GLOBAL_STRING(lp_ncalrpc_dir, &Globals.ncalrpc_dir)
829 FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
830 FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, &Globals.dcerpc_ep_servers)
831 FN_GLOBAL_LIST(lp_server_services, &Globals.server_services)
832 FN_GLOBAL_STRING(lp_ntptr_providor, &Globals.ntptr_providor)
833 FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
834 FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
835 FN_GLOBAL_LIST(lp_passwordserver, &Globals.szPasswordServers)
836 FN_GLOBAL_LIST(lp_name_resolve_order, &Globals.szNameResolveOrder)
837 FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
838 FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
839 FN_GLOBAL_STRING(lp_workgroup, &Globals.szWorkgroup)
840 FN_GLOBAL_STRING(lp_netbios_name, &Globals.szNetbiosName)
841 FN_GLOBAL_STRING(lp_netbios_scope, &Globals.szNetbiosScope)
842 FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
843 FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
844 FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
845 FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
846 FN_GLOBAL_STRING(lp_panic_action, &Globals.szPanicAction)
848 FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
849 FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
850 FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
851 FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
852 FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
853 FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw)
854 FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords)
855 FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions)
856 FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
857 static FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
858 FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
859 FN_GLOBAL_BOOL(lp_unicode, &Globals.bUnicode)
860 FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
861 FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
862 FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
863 FN_GLOBAL_BOOL(lp_client_plaintext_auth, &Globals.bClientPlaintextAuth)
864 FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
865 FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
866 FN_GLOBAL_BOOL(lp_client_use_spnego_principal, &Globals.client_use_spnego_principal)
867 FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
868 FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions)
869 FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
870 FN_GLOBAL_BOOL(lp_rpc_big_endian, &Globals.bRpcBigEndian)
871 FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
872 FN_GLOBAL_INTEGER(lp_min_wins_ttl, &Globals.min_wins_ttl)
873 FN_GLOBAL_INTEGER(lp_maxmux, &Globals.max_mux)
874 FN_GLOBAL_INTEGER(lp_max_xmit, &Globals.max_xmit)
875 FN_GLOBAL_INTEGER(lp_passwordlevel, &Globals.pwordlevel)
876 FN_GLOBAL_INTEGER(lp_maxprotocol, &Globals.maxprotocol)
877 FN_GLOBAL_INTEGER(lp_minprotocol, &Globals.minprotocol)
878 FN_GLOBAL_INTEGER(lp_security, &Globals.security)
879 FN_GLOBAL_LIST(lp_auth_methods, &Globals.AuthMethods)
880 FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security)
881 static FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as)
882 FN_GLOBAL_LIST(lp_js_include, &Globals.jsInclude)
885 FN_LOCAL_STRING(lp_servicename, szService)
886 FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
887 FN_LOCAL_STRING(lp_pathname, szPath)
888 static FN_LOCAL_STRING(_lp_printername, szPrintername)
889 FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
890 FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
891 FN_LOCAL_STRING(lp_comment, comment)
892 FN_LOCAL_STRING(lp_fstype, fstype)
893 static FN_LOCAL_STRING(lp_volume, volume)
894 FN_LOCAL_LIST(lp_ntvfs_handler, ntvfs_handler)
895 FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
896 FN_LOCAL_BOOL(lp_browseable, bBrowseable)
897 FN_LOCAL_BOOL(lp_readonly, bRead_only)
898 FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
899 FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
900 FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
901 FN_LOCAL_BOOL(lp_strict_locking, bStrictLocking)
902 FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
903 FN_LOCAL_BOOL(lp_ci_filesystem, bCIFileSystem)
904 FN_LOCAL_BOOL(lp_map_system, bMap_system)
905 FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
906 FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
907 FN_GLOBAL_INTEGER(lp_server_signing, &Globals.server_signing)
908 FN_GLOBAL_INTEGER(lp_client_signing, &Globals.client_signing)
910 /* local prototypes */
912 static int map_parameter(const char *pszParmName);
913 static BOOL set_boolean(BOOL *pb, const char *pszParmValue);
914 static int getservicebyname(const char *pszServiceName,
915 service * pserviceDest);
916 static void copy_service(service * pserviceDest,
917 service * pserviceSource, BOOL *pcopymapDest);
918 static BOOL service_ok(int iService);
919 static BOOL do_section(const char *pszSectionName, void *);
920 static void init_copymap(service * pservice);
922 /* This is a helper function for parametrical options support. */
923 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
924 /* Actual parametrical functions are quite simple */
925 const char *lp_get_parametric(int lookup_service, const char *type, const char *option)
928 struct param_opt *data;
930 if (lookup_service >= iNumServices) return NULL;
932 data = (lookup_service < 0) ?
933 Globals.param_opt : ServicePtrs[lookup_service]->param_opt;
935 asprintf(&vfskey, "%s:%s", type, option);
939 if (strcmp(data->key, vfskey) == 0) {
946 if (lookup_service >= 0) {
947 /* Try to fetch the same option but from globals */
948 /* but only if we are not already working with Globals */
949 data = Globals.param_opt;
951 if (strcmp(data->key, vfskey) == 0) {
965 /*******************************************************************
966 convenience routine to return int parameters.
967 ********************************************************************/
968 static int lp_int(const char *s)
972 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
976 return strtol(s, NULL, 0);
979 /*******************************************************************
980 convenience routine to return unsigned long parameters.
981 ********************************************************************/
982 static int lp_ulong(const char *s)
986 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
990 return strtoul(s, NULL, 0);
993 /*******************************************************************
994 convenience routine to return boolean parameters.
995 ********************************************************************/
996 static BOOL lp_bool(const char *s)
1001 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
1005 if (!set_boolean(&ret,s)) {
1006 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1014 /* Return parametric option from a given service. Type is a part of option before ':' */
1015 /* Parametric option has following syntax: 'Type: option = value' */
1016 /* Returned value is allocated in 'lp_talloc' context */
1018 const char *lp_parm_string(int lookup_service, const char *type, const char *option)
1020 const char *value = lp_get_parametric(lookup_service, type, option);
1023 return lp_string(value);
1028 /* Return parametric option from a given service. Type is a part of option before ':' */
1029 /* Parametric option has following syntax: 'Type: option = value' */
1030 /* Returned value is allocated in 'lp_talloc' context */
1032 const char **lp_parm_string_list(int lookup_service, const char *type, const char *option,
1033 const char *separator)
1035 const char *value = lp_get_parametric(lookup_service, type, option);
1038 return str_list_make(talloc_autofree_context(), value, separator);
1043 /* Return parametric option from a given service. Type is a part of option before ':' */
1044 /* Parametric option has following syntax: 'Type: option = value' */
1046 int lp_parm_int(int lookup_service, const char *type, const char *option, int default_v)
1048 const char *value = lp_get_parametric(lookup_service, type, option);
1051 return lp_int(value);
1056 /* Return parametric option from a given service. Type is a part of option before ':' */
1057 /* Parametric option has following syntax: 'Type: option = value' */
1059 unsigned long lp_parm_ulong(int lookup_service, const char *type, const char *option, unsigned long default_v)
1061 const char *value = lp_get_parametric(lookup_service, type, option);
1064 return lp_ulong(value);
1069 /* Return parametric option from a given service. Type is a part of option before ':' */
1070 /* Parametric option has following syntax: 'Type: option = value' */
1072 BOOL lp_parm_bool(int lookup_service, const char *type, const char *option, BOOL default_v)
1074 const char *value = lp_get_parametric(lookup_service, type, option);
1077 return lp_bool(value);
1083 /***************************************************************************
1084 Initialise a service to the defaults.
1085 ***************************************************************************/
1087 static void init_service(service * pservice)
1089 memset((char *)pservice, '\0', sizeof(service));
1090 copy_service(pservice, &sDefault, NULL);
1093 /***************************************************************************
1094 Free the dynamically allocated parts of a service struct.
1095 ***************************************************************************/
1097 static void free_service(service *pservice)
1100 struct param_opt *data, *pdata;
1104 if (pservice->szService)
1105 DEBUG(5, ("free_service: Freeing service %s\n",
1106 pservice->szService));
1108 string_free(&pservice->szService);
1109 SAFE_FREE(pservice->copymap);
1111 for (i = 0; parm_table[i].label; i++) {
1112 if ((parm_table[i].type == P_STRING ||
1113 parm_table[i].type == P_USTRING) &&
1114 parm_table[i].class == P_LOCAL) {
1115 string_free((char **)
1116 (((char *)pservice) +
1117 PTR_DIFF(parm_table[i].ptr, &sDefault)));
1118 } else if (parm_table[i].type == P_LIST &&
1119 parm_table[i].class == P_LOCAL) {
1120 char ***listp = (char ***)(((char *)pservice) +
1121 PTR_DIFF(parm_table[i].ptr, &sDefault));
1122 talloc_free(*listp);
1127 DEBUG(5,("Freeing parametrics:\n"));
1128 data = pservice->param_opt;
1130 DEBUG(5,("[%s = %s]\n", data->key, data->value));
1131 string_free(&data->key);
1132 string_free(&data->value);
1138 ZERO_STRUCTP(pservice);
1141 /***************************************************************************
1142 Add a new service to the services array initialising it with the given
1144 ***************************************************************************/
1146 static int add_a_service(const service *pservice, const char *name)
1150 int num_to_alloc = iNumServices + 1;
1151 struct param_opt *data, *pdata;
1153 tservice = *pservice;
1155 /* it might already exist */
1157 i = getservicebyname(name, NULL);
1159 /* Clean all parametric options for service */
1160 /* They will be added during parsing again */
1161 data = ServicePtrs[i]->param_opt;
1163 string_free(&data->key);
1164 string_free(&data->value);
1169 ServicePtrs[i]->param_opt = NULL;
1174 /* find an invalid one */
1175 for (i = 0; i < iNumServices; i++)
1176 if (!ServicePtrs[i]->valid)
1179 /* if not, then create one */
1180 if (i == iNumServices) {
1183 tsp = realloc_p(ServicePtrs, service *, num_to_alloc);
1186 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1191 ServicePtrs[iNumServices] = malloc_p(service);
1193 if (!ServicePtrs[iNumServices]) {
1194 DEBUG(0,("add_a_service: out of memory!\n"));
1200 free_service(ServicePtrs[i]);
1202 ServicePtrs[i]->valid = True;
1204 init_service(ServicePtrs[i]);
1205 copy_service(ServicePtrs[i], &tservice, NULL);
1207 string_set(&ServicePtrs[i]->szService, name);
1211 /***************************************************************************
1212 Add a new home service, with the specified home directory, defaults coming
1214 ***************************************************************************/
1216 BOOL lp_add_home(const char *pszHomename, int iDefaultService,
1217 const char *user, const char *pszHomedir)
1222 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1227 if (!(*(ServicePtrs[iDefaultService]->szPath))
1228 || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(-1))) {
1229 pstrcpy(newHomedir, pszHomedir);
1231 pstrcpy(newHomedir, lp_pathname(iDefaultService));
1232 string_sub(newHomedir,"%H", pszHomedir, sizeof(newHomedir));
1235 string_set(&ServicePtrs[i]->szPath, newHomedir);
1237 if (!(*(ServicePtrs[i]->comment))) {
1239 slprintf(comment, sizeof(comment) - 1,
1240 "Home directory of %s", user);
1241 string_set(&ServicePtrs[i]->comment, comment);
1243 ServicePtrs[i]->bAvailable = sDefault.bAvailable;
1244 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1246 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1252 /***************************************************************************
1253 Add a new service, based on an old one.
1254 ***************************************************************************/
1256 int lp_add_service(const char *pszService, int iDefaultService)
1258 return (add_a_service(ServicePtrs[iDefaultService], pszService));
1261 /***************************************************************************
1262 Add the IPC service.
1263 ***************************************************************************/
1265 static BOOL lp_add_hidden(const char *name, const char *fstype)
1268 int i = add_a_service(&sDefault, name);
1273 slprintf(comment, sizeof(comment) - 1,
1274 "%s Service (%s)", fstype, Globals.szServerString);
1276 string_set(&ServicePtrs[i]->szPath, tmpdir());
1277 string_set(&ServicePtrs[i]->comment, comment);
1278 string_set(&ServicePtrs[i]->fstype, fstype);
1279 ServicePtrs[i]->iMaxConnections = -1;
1280 ServicePtrs[i]->bAvailable = True;
1281 ServicePtrs[i]->bRead_only = True;
1282 ServicePtrs[i]->bPrint_ok = False;
1283 ServicePtrs[i]->bBrowseable = False;
1285 if (strcasecmp(fstype, "IPC") == 0) {
1286 lp_do_parameter(i, "ntvfs handler", "default");
1289 DEBUG(3, ("adding hidden service %s\n", name));
1294 /***************************************************************************
1295 Add a new printer service, with defaults coming from service iFrom.
1296 ***************************************************************************/
1298 BOOL lp_add_printer(const char *pszPrintername, int iDefaultService)
1300 const char *comment = "From Printcap";
1301 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1306 /* note that we do NOT default the availability flag to True - */
1307 /* we take it from the default service passed. This allows all */
1308 /* dynamic printers to be disabled by disabling the [printers] */
1309 /* entry (if/when the 'available' keyword is implemented!). */
1311 /* the printer name is set to the service name. */
1312 string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1313 string_set(&ServicePtrs[i]->comment, comment);
1314 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1315 /* Printers cannot be read_only. */
1316 ServicePtrs[i]->bRead_only = False;
1317 /* Printer services must be printable. */
1318 ServicePtrs[i]->bPrint_ok = True;
1320 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1322 update_server_announce_as_printserver();
1327 /***************************************************************************
1328 Map a parameter's string representation to something we can use.
1329 Returns False if the parameter string is not recognised, else TRUE.
1330 ***************************************************************************/
1332 static int map_parameter(const char *pszParmName)
1336 if (*pszParmName == '-')
1339 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1340 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1343 /* Warn only if it isn't parametric option */
1344 if (strchr(pszParmName, ':') == NULL)
1345 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1346 /* We do return 'fail' for parametric options as well because they are
1347 stored in different storage
1354 return the parameter structure for a parameter
1356 struct parm_struct *lp_parm_struct(const char *name)
1358 int parmnum = map_parameter(name);
1359 if (parmnum == -1) return NULL;
1360 return &parm_table[parmnum];
1364 return the parameter pointer for a parameter
1366 void *lp_parm_ptr(int snum, struct parm_struct *parm)
1371 return ((char *)ServicePtrs[snum]) + PTR_DIFF(parm->ptr, &sDefault);
1374 /***************************************************************************
1375 Set a boolean variable from the text value stored in the passed string.
1376 Returns True in success, False if the passed string does not correctly
1377 represent a boolean.
1378 ***************************************************************************/
1380 static BOOL set_boolean(BOOL *pb, const char *pszParmValue)
1385 if (strwicmp(pszParmValue, "yes") == 0 ||
1386 strwicmp(pszParmValue, "true") == 0 ||
1387 strwicmp(pszParmValue, "1") == 0)
1389 else if (strwicmp(pszParmValue, "no") == 0 ||
1390 strwicmp(pszParmValue, "False") == 0 ||
1391 strwicmp(pszParmValue, "0") == 0)
1395 ("ERROR: Badly formed boolean in configuration file: \"%s\".\n",
1402 /***************************************************************************
1403 Find a service by name. Otherwise works like get_service.
1404 ***************************************************************************/
1406 static int getservicebyname(const char *pszServiceName, service * pserviceDest)
1410 for (iService = iNumServices - 1; iService >= 0; iService--)
1411 if (VALID(iService) &&
1412 strwicmp(ServicePtrs[iService]->szService, pszServiceName) == 0) {
1413 if (pserviceDest != NULL)
1414 copy_service(pserviceDest, ServicePtrs[iService], NULL);
1421 /***************************************************************************
1422 Copy a service structure to another.
1423 If pcopymapDest is NULL then copy all fields
1424 ***************************************************************************/
1426 static void copy_service(service * pserviceDest, service * pserviceSource, BOOL *pcopymapDest)
1429 BOOL bcopyall = (pcopymapDest == NULL);
1430 struct param_opt *data, *pdata, *paramo;
1433 for (i = 0; parm_table[i].label; i++)
1434 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1435 (bcopyall || pcopymapDest[i])) {
1436 void *def_ptr = parm_table[i].ptr;
1438 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
1441 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
1444 switch (parm_table[i].type) {
1446 *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
1451 *(int *)dest_ptr = *(int *)src_ptr;
1455 string_set(dest_ptr,
1460 string_set(dest_ptr,
1462 strupper(*(char **)dest_ptr);
1465 *(const char ***)dest_ptr = str_list_copy(talloc_autofree_context(),
1466 *(const char ***)src_ptr);
1474 init_copymap(pserviceDest);
1475 if (pserviceSource->copymap)
1476 memcpy((void *)pserviceDest->copymap,
1477 (void *)pserviceSource->copymap,
1478 sizeof(BOOL) * NUMPARAMETERS);
1481 data = pserviceSource->param_opt;
1484 pdata = pserviceDest->param_opt;
1485 /* Traverse destination */
1487 /* If we already have same option, override it */
1488 if (strcmp(pdata->key, data->key) == 0) {
1489 string_free(&pdata->value);
1490 pdata->value = strdup(data->value);
1494 pdata = pdata->next;
1497 paramo = malloc_p(struct param_opt);
1500 paramo->key = strdup(data->key);
1501 paramo->value = strdup(data->value);
1502 DLIST_ADD(pserviceDest->param_opt, paramo);
1508 /***************************************************************************
1509 Check a service for consistency. Return False if the service is in any way
1510 incomplete or faulty, else True.
1511 ***************************************************************************/
1513 static BOOL service_ok(int iService)
1518 if (ServicePtrs[iService]->szService[0] == '\0') {
1519 DEBUG(0, ("The following message indicates an internal error:\n"));
1520 DEBUG(0, ("No service name in service entry.\n"));
1524 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1525 /* I can't see why you'd want a non-printable printer service... */
1526 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
1527 if (!ServicePtrs[iService]->bPrint_ok) {
1528 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
1529 ServicePtrs[iService]->szService));
1530 ServicePtrs[iService]->bPrint_ok = True;
1531 update_server_announce_as_printserver();
1533 /* [printers] service must also be non-browsable. */
1534 if (ServicePtrs[iService]->bBrowseable)
1535 ServicePtrs[iService]->bBrowseable = False;
1538 /* If a service is flagged unavailable, log the fact at level 0. */
1539 if (!ServicePtrs[iService]->bAvailable)
1540 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
1541 ServicePtrs[iService]->szService));
1546 static struct file_lists {
1547 struct file_lists *next;
1551 } *file_lists = NULL;
1553 /*******************************************************************
1554 Keep a linked list of all config files so we know when one has changed
1555 it's date and needs to be reloaded.
1556 ********************************************************************/
1558 static void add_to_file_list(const char *fname, const char *subfname)
1560 struct file_lists *f = file_lists;
1563 if (f->name && !strcmp(f->name, fname))
1569 f = malloc_p(struct file_lists);
1572 f->next = file_lists;
1573 f->name = strdup(fname);
1578 f->subfname = strdup(subfname);
1584 f->modtime = file_modtime(subfname);
1586 time_t t = file_modtime(subfname);
1592 /*******************************************************************
1593 Check if a config file has changed date.
1594 ********************************************************************/
1596 BOOL lp_file_list_changed(void)
1598 struct file_lists *f = file_lists;
1599 DEBUG(6, ("lp_file_list_changed()\n"));
1605 pstrcpy(n2, f->name);
1606 standard_sub_basic(n2,sizeof(n2));
1608 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
1609 f->name, n2, ctime(&f->modtime)));
1611 mod_time = file_modtime(n2);
1613 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
1615 ("file %s modified: %s\n", n2,
1617 f->modtime = mod_time;
1618 SAFE_FREE(f->subfname);
1619 f->subfname = strdup(n2);
1627 /***************************************************************************
1628 Handle the include operation.
1629 ***************************************************************************/
1631 static BOOL handle_include(const char *pszParmValue, char **ptr)
1634 pstrcpy(fname, pszParmValue);
1636 standard_sub_basic(fname,sizeof(fname));
1638 add_to_file_list(pszParmValue, fname);
1640 string_set(ptr, fname);
1642 if (file_exist(fname))
1643 return (pm_process(fname, do_section, do_parameter, NULL));
1645 DEBUG(2, ("Can't find include file %s\n", fname));
1650 /***************************************************************************
1651 Handle the interpretation of the copy parameter.
1652 ***************************************************************************/
1654 static BOOL handle_copy(const char *pszParmValue, char **ptr)
1658 service serviceTemp;
1660 string_set(ptr, pszParmValue);
1662 init_service(&serviceTemp);
1666 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
1668 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
1669 if (iTemp == iServiceIndex) {
1670 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
1672 copy_service(ServicePtrs[iServiceIndex],
1674 ServicePtrs[iServiceIndex]->copymap);
1678 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
1682 free_service(&serviceTemp);
1686 /***************************************************************************
1687 Initialise a copymap.
1688 ***************************************************************************/
1690 static void init_copymap(service * pservice)
1693 SAFE_FREE(pservice->copymap);
1694 pservice->copymap = malloc_array_p(BOOL, NUMPARAMETERS);
1695 if (!pservice->copymap)
1697 ("Couldn't allocate copymap!! (size %d)\n",
1698 (int)NUMPARAMETERS));
1700 for (i = 0; i < NUMPARAMETERS; i++)
1701 pservice->copymap[i] = True;
1704 /***************************************************************************
1705 Return the local pointer to a parameter given the service number and the
1706 pointer into the default structure.
1707 ***************************************************************************/
1709 void *lp_local_ptr(int snum, void *ptr)
1711 return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
1715 /***************************************************************************
1716 Process a parametric option
1717 ***************************************************************************/
1718 static BOOL lp_do_parameter_parametric(int snum, const char *pszParmName, const char *pszParmValue, int flags)
1720 struct param_opt *paramo, *data;
1723 while (isspace((unsigned char)*pszParmName)) {
1727 name = strdup(pszParmName);
1728 if (!name) return False;
1733 data = Globals.param_opt;
1735 data = ServicePtrs[snum]->param_opt;
1738 /* Traverse destination */
1739 for (paramo=data; paramo; paramo=paramo->next) {
1740 /* If we already have the option set, override it unless
1741 it was a command line option and the new one isn't */
1742 if (strcmp(paramo->key, name) == 0) {
1743 if ((paramo->flags & FLAG_CMDLINE) &&
1744 !(flags & FLAG_CMDLINE)) {
1748 free(paramo->value);
1749 paramo->value = strdup(pszParmValue);
1750 paramo->flags = flags;
1756 paramo = malloc_p(struct param_opt);
1759 paramo->key = strdup(name);
1760 paramo->value = strdup(pszParmValue);
1761 paramo->flags = flags;
1763 DLIST_ADD(Globals.param_opt, paramo);
1765 DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
1773 /***************************************************************************
1774 Process a parameter for a particular service number. If snum < 0
1775 then assume we are in the globals.
1776 ***************************************************************************/
1777 BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
1780 void *parm_ptr = NULL; /* where we are going to store the result */
1781 void *def_ptr = NULL;
1783 parmnum = map_parameter(pszParmName);
1786 if (strchr(pszParmName, ':')) {
1787 return lp_do_parameter_parametric(snum, pszParmName, pszParmValue, 0);
1789 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1793 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1794 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1798 /* if the flag has been set on the command line, then don't allow override,
1799 but don't report an error */
1800 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1804 def_ptr = parm_table[parmnum].ptr;
1806 /* we might point at a service, the default service or a global */
1810 if (parm_table[parmnum].class == P_GLOBAL) {
1812 ("Global parameter %s found in service section!\n",
1817 ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
1822 if (!ServicePtrs[snum]->copymap)
1823 init_copymap(ServicePtrs[snum]);
1825 /* this handles the aliases - set the copymap for other entries with
1826 the same data pointer */
1827 for (i = 0; parm_table[i].label; i++)
1828 if (parm_table[i].ptr == parm_table[parmnum].ptr)
1829 ServicePtrs[snum]->copymap[i] = False;
1832 /* if it is a special case then go ahead */
1833 if (parm_table[parmnum].special) {
1834 parm_table[parmnum].special(pszParmValue, (char **)parm_ptr);
1838 /* now switch on the type of variable it is */
1839 switch (parm_table[parmnum].type)
1842 set_boolean(parm_ptr, pszParmValue);
1846 *(int *)parm_ptr = atoi(pszParmValue);
1850 *(const char ***)parm_ptr = str_list_make(talloc_autofree_context(),
1851 pszParmValue, NULL);
1855 string_set(parm_ptr, pszParmValue);
1859 string_set(parm_ptr, pszParmValue);
1860 strupper(*(char **)parm_ptr);
1864 for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
1867 parm_table[parmnum].enum_list[i].name)) {
1869 parm_table[parmnum].
1874 if (!parm_table[parmnum].enum_list[i].name) {
1875 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n",
1876 pszParmValue, pszParmName));
1887 /***************************************************************************
1888 Process a parameter.
1889 ***************************************************************************/
1891 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue, void *userdata)
1893 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
1894 pszParmName, pszParmValue));
1898 variable argument do parameter
1900 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
1902 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...)
1909 s = talloc_vasprintf(NULL, fmt, ap);
1911 ret = do_parameter(pszParmName, s, NULL);
1918 set a parameter from the commandline - this is called from command line parameter
1919 parsing code. It sets the parameter then marks the parameter as unable to be modified
1920 by smb.conf processing
1922 BOOL lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
1924 int parmnum = map_parameter(pszParmName);
1927 while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
1930 if (parmnum < 0 && strchr(pszParmName, ':')) {
1931 /* set a parametric option */
1932 return lp_do_parameter_parametric(-1, pszParmName, pszParmValue, FLAG_CMDLINE);
1936 DEBUG(0,("Unknown option '%s'\n", pszParmName));
1940 /* reset the CMDLINE flag in case this has been called before */
1941 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
1943 if (!lp_do_parameter(-2, pszParmName, pszParmValue)) {
1947 parm_table[parmnum].flags |= FLAG_CMDLINE;
1949 /* we have to also set FLAG_CMDLINE on aliases */
1950 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1951 parm_table[i].flags |= FLAG_CMDLINE;
1953 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1954 parm_table[i].flags |= FLAG_CMDLINE;
1961 set a option from the commandline in 'a=b' format. Use to support --option
1963 BOOL lp_set_option(const char *option)
1981 ret = lp_set_cmdline(s, p+1);
1987 #define BOOLSTR(b) ((b) ? "Yes" : "No")
1989 /***************************************************************************
1990 Print a parameter of the specified type.
1991 ***************************************************************************/
1993 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
1999 for (i = 0; p->enum_list[i].name; i++) {
2000 if (*(int *)ptr == p->enum_list[i].value) {
2002 p->enum_list[i].name);
2009 fprintf(f, "%s", BOOLSTR(*(BOOL *)ptr));
2013 fprintf(f, "%d", *(int *)ptr);
2017 if ((char ***)ptr && *(char ***)ptr) {
2018 char **list = *(char ***)ptr;
2020 for (; *list; list++)
2021 fprintf(f, "%s%s", *list,
2022 ((*(list+1))?", ":""));
2028 if (*(char **)ptr) {
2029 fprintf(f, "%s", *(char **)ptr);
2037 /***************************************************************************
2038 Check if two parameters are equal.
2039 ***************************************************************************/
2041 static BOOL equal_parameter(parm_type type, void *ptr1, void *ptr2)
2045 return (*((BOOL *)ptr1) == *((BOOL *)ptr2));
2049 return (*((int *)ptr1) == *((int *)ptr2));
2052 return str_list_equal((const char **)(*(char ***)ptr1),
2053 (const char **)(*(char ***)ptr2));
2058 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
2063 return (p1 == p2 || strequal(p1, p2));
2071 /***************************************************************************
2072 Process a new section (service). At this stage all sections are services.
2073 Later we'll have special sections that permit server parameters to be set.
2074 Returns True on success, False on failure.
2075 ***************************************************************************/
2077 static BOOL do_section(const char *pszSectionName, void *userdata)
2080 BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2081 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2084 /* if we've just struck a global section, note the fact. */
2085 bInGlobalSection = isglobal;
2087 /* check for multiple global sections */
2088 if (bInGlobalSection) {
2089 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2093 /* if we have a current service, tidy it up before moving on */
2096 if (iServiceIndex >= 0)
2097 bRetval = service_ok(iServiceIndex);
2099 /* if all is still well, move to the next record in the services array */
2101 /* We put this here to avoid an odd message order if messages are */
2102 /* issued by the post-processing of a previous section. */
2103 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2105 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
2107 DEBUG(0, ("Failed to add a new service\n"));
2116 /***************************************************************************
2117 Determine if a partcular base parameter is currentl set to the default value.
2118 ***************************************************************************/
2120 static BOOL is_default(int i)
2122 if (!defaults_saved)
2124 switch (parm_table[i].type) {
2126 return str_list_equal((const char **)parm_table[i].def.lvalue,
2127 (const char **)(*(char ***)parm_table[i].ptr));
2130 return strequal(parm_table[i].def.svalue,
2131 *(char **)parm_table[i].ptr);
2133 return parm_table[i].def.bvalue ==
2134 *(BOOL *)parm_table[i].ptr;
2137 return parm_table[i].def.ivalue ==
2138 *(int *)parm_table[i].ptr;
2145 /***************************************************************************
2146 Display the contents of the global structure.
2147 ***************************************************************************/
2149 static void dump_globals(FILE *f)
2152 struct param_opt *data;
2154 fprintf(f, "# Global parameters\n[global]\n");
2156 for (i = 0; parm_table[i].label; i++)
2157 if (parm_table[i].class == P_GLOBAL &&
2158 parm_table[i].ptr &&
2159 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2160 if (defaults_saved && is_default(i))
2162 fprintf(f, "\t%s = ", parm_table[i].label);
2163 print_parameter(&parm_table[i], parm_table[i].ptr, f);
2166 if (Globals.param_opt != NULL) {
2167 data = Globals.param_opt;
2169 fprintf(f, "\t%s = %s\n", data->key, data->value);
2176 /***************************************************************************
2177 Display the contents of a single services record.
2178 ***************************************************************************/
2180 static void dump_a_service(service * pService, FILE * f)
2183 struct param_opt *data;
2185 if (pService != &sDefault)
2186 fprintf(f, "\n[%s]\n", pService->szService);
2188 for (i = 0; parm_table[i].label; i++)
2189 if (parm_table[i].class == P_LOCAL &&
2190 parm_table[i].ptr &&
2191 (*parm_table[i].label != '-') &&
2192 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2193 int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
2195 if (pService == &sDefault) {
2196 if (defaults_saved && is_default(i))
2199 if (equal_parameter(parm_table[i].type,
2200 ((char *)pService) +
2202 ((char *)&sDefault) +
2207 fprintf(f, "\t%s = ", parm_table[i].label);
2208 print_parameter(&parm_table[i],
2209 ((char *)pService) + pdiff, f);
2212 if (pService->param_opt != NULL) {
2213 data = pService->param_opt;
2215 fprintf(f, "\t%s = %s\n", data->key, data->value);
2222 /***************************************************************************
2223 Return info about the next service in a service. snum==-1 gives the globals.
2224 Return NULL when out of parameters.
2225 ***************************************************************************/
2227 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
2230 /* do the globals */
2231 for (; parm_table[*i].label; (*i)++) {
2232 if (parm_table[*i].class == P_SEPARATOR)
2233 return &parm_table[(*i)++];
2235 if (!parm_table[*i].ptr
2236 || (*parm_table[*i].label == '-'))
2240 && (parm_table[*i].ptr ==
2241 parm_table[(*i) - 1].ptr))
2244 return &parm_table[(*i)++];
2247 service *pService = ServicePtrs[snum];
2249 for (; parm_table[*i].label; (*i)++) {
2250 if (parm_table[*i].class == P_SEPARATOR)
2251 return &parm_table[(*i)++];
2253 if (parm_table[*i].class == P_LOCAL &&
2254 parm_table[*i].ptr &&
2255 (*parm_table[*i].label != '-') &&
2257 (parm_table[*i].ptr !=
2258 parm_table[(*i) - 1].ptr)))
2261 PTR_DIFF(parm_table[*i].ptr,
2264 if (allparameters ||
2265 !equal_parameter(parm_table[*i].type,
2266 ((char *)pService) +
2268 ((char *)&sDefault) +
2271 return &parm_table[(*i)++];
2281 /***************************************************************************
2282 Return TRUE if the passed service number is within range.
2283 ***************************************************************************/
2285 BOOL lp_snum_ok(int iService)
2287 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
2290 /***************************************************************************
2291 Auto-load some home services.
2292 ***************************************************************************/
2294 static void lp_add_auto_services(const char *str)
2299 /***************************************************************************
2300 Announce ourselves as a print server.
2301 ***************************************************************************/
2303 void update_server_announce_as_printserver(void)
2305 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
2308 /***************************************************************************
2309 Have we loaded a services file yet?
2310 ***************************************************************************/
2312 BOOL lp_loaded(void)
2317 /***************************************************************************
2318 Unload unused services.
2319 ***************************************************************************/
2321 void lp_killunused(struct smbsrv_connection *smb, BOOL (*snumused) (struct smbsrv_connection *, int))
2324 for (i = 0; i < iNumServices; i++) {
2328 if (!snumused || !snumused(smb, i)) {
2329 ServicePtrs[i]->valid = False;
2330 free_service(ServicePtrs[i]);
2335 /***************************************************************************
2337 ***************************************************************************/
2339 void lp_killservice(int iServiceIn)
2341 if (VALID(iServiceIn)) {
2342 ServicePtrs[iServiceIn]->valid = False;
2343 free_service(ServicePtrs[iServiceIn]);
2347 /***************************************************************************
2348 Load the services array from the services file. Return True on success,
2350 ***************************************************************************/
2356 struct param_opt *data;
2360 bInGlobalSection = True;
2362 if (Globals.param_opt != NULL) {
2363 struct param_opt *next;
2364 for (data=Globals.param_opt; data; data=next) {
2366 if (data->flags & FLAG_CMDLINE) continue;
2369 DLIST_REMOVE(Globals.param_opt, data);
2376 pstrcpy(n2, lp_configfile());
2377 standard_sub_basic(n2,sizeof(n2));
2378 DEBUG(2, ("lp_load: refreshing parameters from %s\n", n2));
2380 add_to_file_list(lp_configfile(), n2);
2382 /* We get sections first, so have to start 'behind' to make up */
2384 bRetval = pm_process(n2, do_section, do_parameter, NULL);
2386 /* finish up the last section */
2387 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
2389 if (iServiceIndex >= 0)
2390 bRetval = service_ok(iServiceIndex);
2392 lp_add_auto_services(lp_auto_services());
2394 lp_add_hidden("IPC$", "IPC");
2395 lp_add_hidden("ADMIN$", "DISK");
2397 set_default_server_announce_type();
2401 if (!Globals.szWINSservers && Globals.bWINSsupport) {
2402 lp_do_parameter(-1, "wins server", "127.0.0.1");
2410 /***************************************************************************
2411 Reset the max number of services.
2412 ***************************************************************************/
2414 void lp_resetnumservices(void)
2419 /***************************************************************************
2420 Return the max number of services.
2421 ***************************************************************************/
2423 int lp_numservices(void)
2425 return (iNumServices);
2428 /***************************************************************************
2429 Display the contents of the services array in human-readable form.
2430 ***************************************************************************/
2432 void lp_dump(FILE *f, BOOL show_defaults, int maxtoprint)
2437 defaults_saved = False;
2441 dump_a_service(&sDefault, f);
2443 for (iService = 0; iService < maxtoprint; iService++)
2444 lp_dump_one(f, show_defaults, iService);
2447 /***************************************************************************
2448 Display the contents of one service in human-readable form.
2449 ***************************************************************************/
2451 void lp_dump_one(FILE * f, BOOL show_defaults, int snum)
2454 if (ServicePtrs[snum]->szService[0] == '\0')
2456 dump_a_service(ServicePtrs[snum], f);
2460 /***************************************************************************
2461 Return the number of the service with the given name, or -1 if it doesn't
2462 exist. Note that this is a DIFFERENT ANIMAL from the internal function
2463 getservicebyname()! This works ONLY if all services have been loaded, and
2464 does not copy the found service.
2465 ***************************************************************************/
2467 int lp_servicenumber(const char *pszServiceName)
2470 fstring serviceName;
2473 for (iService = iNumServices - 1; iService >= 0; iService--) {
2474 if (VALID(iService) && ServicePtrs[iService]->szService) {
2476 * The substitution here is used to support %U is
2479 fstrcpy(serviceName, ServicePtrs[iService]->szService);
2480 standard_sub_basic(serviceName,sizeof(serviceName));
2481 if (strequal(serviceName, pszServiceName))
2487 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
2492 /*******************************************************************
2493 A useful volume label function.
2494 ********************************************************************/
2495 const char *volume_label(int snum)
2497 const char *ret = lp_volume(snum);
2499 return lp_servicename(snum);
2504 /*******************************************************************
2505 Set the server type we will announce as via nmbd.
2506 ********************************************************************/
2508 static void set_default_server_announce_type(void)
2510 default_server_announce = 0;
2511 default_server_announce |= SV_TYPE_WORKSTATION;
2512 default_server_announce |= SV_TYPE_SERVER;
2513 default_server_announce |= SV_TYPE_SERVER_UNIX;
2515 switch (lp_announce_as()) {
2516 case ANNOUNCE_AS_NT_SERVER:
2517 default_server_announce |= SV_TYPE_SERVER_NT;
2518 /* fall through... */
2519 case ANNOUNCE_AS_NT_WORKSTATION:
2520 default_server_announce |= SV_TYPE_NT;
2522 case ANNOUNCE_AS_WIN95:
2523 default_server_announce |= SV_TYPE_WIN95_PLUS;
2525 case ANNOUNCE_AS_WFW:
2526 default_server_announce |= SV_TYPE_WFW;
2532 switch (lp_server_role()) {
2533 case ROLE_DOMAIN_MEMBER:
2534 default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
2536 case ROLE_DOMAIN_PDC:
2537 default_server_announce |= SV_TYPE_DOMAIN_CTRL;
2539 case ROLE_DOMAIN_BDC:
2540 default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
2542 case ROLE_STANDALONE:
2546 if (lp_time_server())
2547 default_server_announce |= SV_TYPE_TIME_SOURCE;
2549 if (lp_host_msdfs())
2550 default_server_announce |= SV_TYPE_DFS_SERVER;
2552 /* TODO: only announce us as print server when we are a print server */
2553 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
2556 /***********************************************************
2557 If we are PDC then prefer us as DMB
2558 ************************************************************/
2560 BOOL lp_domain_master(void)
2562 return (lp_server_role() == ROLE_DOMAIN_PDC);
2565 /***********************************************************
2566 If we are PDC then prefer us as DMB
2567 ************************************************************/
2569 BOOL lp_domain_logons(void)
2571 return (lp_server_role() == ROLE_DOMAIN_PDC) || (lp_server_role() == ROLE_DOMAIN_BDC);
2574 /***********************************************************
2575 If we are DMB then prefer us as LMB
2576 ************************************************************/
2578 BOOL lp_preferred_master(void)
2580 return (lp_local_master() && lp_domain_master());
2583 /*******************************************************************
2585 ********************************************************************/
2587 void lp_remove_service(int snum)
2589 ServicePtrs[snum]->valid = False;
2592 /*******************************************************************
2594 ********************************************************************/
2596 void lp_copy_service(int snum, const char *new_name)
2598 const char *oldname = lp_servicename(snum);
2599 do_section(new_name, NULL);
2601 snum = lp_servicenumber(new_name);
2603 lp_do_parameter(snum, "copy", oldname);
2608 /*******************************************************************
2609 Get the default server type we will announce as via nmbd.
2610 ********************************************************************/
2611 int lp_default_server_announce(void)
2613 return default_server_announce;
2616 const char *lp_printername(int snum)
2618 const char *ret = _lp_printername(snum);
2619 if (ret == NULL || (ret != NULL && *ret == '\0'))
2620 ret = lp_const_servicename(snum);
2626 /*******************************************************************
2627 Return the max print jobs per queue.
2628 ********************************************************************/
2630 int lp_maxprintjobs(int snum)
2632 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
2633 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
2634 maxjobs = PRINT_MAX_JOBID - 1;