2 Unix SMB/CIFS implementation.
3 Parameter loading functions
4 Copyright (C) Karl Auer 1993-1998
6 Largely re-written by Andrew Tridgell, September 1994
8 Copyright (C) Simo Sorce 2001
9 Copyright (C) Alexander Bokovoy 2002
10 Copyright (C) Stefan (metze) Metzmacher 2002
11 Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003.
12 Copyright (C) James Myers 2003 <myersjj@samba.org>
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32 * This module provides suitable callback functions for the params
33 * module. It builds the internal table of service details which is
34 * then used by the rest of the server.
38 * 1) add it to the global or service structure definition
39 * 2) add it to the parm_table
40 * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
41 * 4) If it's a global then initialise it in init_globals. If a local
42 * (ie. service) parameter then initialise it in the sDefault structure
46 * The configuration file is processed sequentially for speed. It is NOT
47 * accessed randomly as happens in 'real' Windows. For this reason, there
48 * is a fair bit of sequence-dependent code here - ie., code which assumes
49 * that certain things happen before others. In particular, the code which
50 * happens at the boundary between sections is delicately poised, so be
57 #include "dynconfig.h"
59 #include "system/time.h"
60 #include "system/iconv.h"
61 #include "system/network.h"
62 #include "system/printing.h"
63 #include "librpc/gen_ndr/ndr_svcctl.h"
64 #include "librpc/gen_ndr/ndr_samr.h"
65 #include "librpc/gen_ndr/ndr_nbt.h"
66 #include "dlinklist.h"
67 #include "param/loadparm.h"
69 static BOOL bLoaded = False;
72 #define GLOBAL_NAME "global"
76 #define PRINTERS_NAME "printers"
80 #define HOMES_NAME "homes"
83 /* some helpful bits */
84 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && ServicePtrs[(i)]->valid)
85 #define VALID(i) ServicePtrs[i]->valid
87 static BOOL do_parameter(const char *, const char *, void *);
88 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...);
90 static BOOL defaults_saved = False;
94 struct param_opt *prev, *next;
101 * This structure describes global (ie., server-wide) parameters.
111 char *display_charset;
115 char *szServerString;
116 char *szAutoServices;
125 char **szPasswordServers;
126 char *szSocketOptions;
128 char **szWINSservers;
130 char *szSocketAddress;
131 char *szAnnounceVersion; /* This is initialised in init_globals */
134 char **szNetbiosAliases;
135 char *szNetbiosScope;
136 char *szDomainOtherSIDs;
137 char **szNameResolveOrder;
139 char **dcerpc_ep_servers;
140 char **server_services;
141 char *ntptr_providor;
142 char *szWinbindSeparator;
143 BOOL bWinbindSealedPipes;
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"},
304 /* Types of machine we can announce as. */
305 #define ANNOUNCE_AS_NT_SERVER 1
306 #define ANNOUNCE_AS_WIN95 2
307 #define ANNOUNCE_AS_WFW 3
308 #define ANNOUNCE_AS_NT_WORKSTATION 4
310 static const struct enum_list enum_announce_as[] = {
311 {ANNOUNCE_AS_NT_SERVER, "NT"},
312 {ANNOUNCE_AS_NT_SERVER, "NT Server"},
313 {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"},
314 {ANNOUNCE_AS_WIN95, "win95"},
315 {ANNOUNCE_AS_WFW, "WfW"},
319 static const struct enum_list enum_bool_auto[] = {
330 /* Client-side offline caching policy types */
331 #define CSC_POLICY_MANUAL 0
332 #define CSC_POLICY_DOCUMENTS 1
333 #define CSC_POLICY_PROGRAMS 2
334 #define CSC_POLICY_DISABLE 3
336 static const struct enum_list enum_csc_policy[] = {
337 {CSC_POLICY_MANUAL, "manual"},
338 {CSC_POLICY_DOCUMENTS, "documents"},
339 {CSC_POLICY_PROGRAMS, "programs"},
340 {CSC_POLICY_DISABLE, "disable"},
344 /* SMB signing types. */
345 static const struct enum_list enum_smb_signing_vals[] = {
346 {SMB_SIGNING_OFF, "No"},
347 {SMB_SIGNING_OFF, "False"},
348 {SMB_SIGNING_OFF, "0"},
349 {SMB_SIGNING_OFF, "Off"},
350 {SMB_SIGNING_OFF, "disabled"},
351 {SMB_SIGNING_SUPPORTED, "Yes"},
352 {SMB_SIGNING_SUPPORTED, "True"},
353 {SMB_SIGNING_SUPPORTED, "1"},
354 {SMB_SIGNING_SUPPORTED, "On"},
355 {SMB_SIGNING_SUPPORTED, "enabled"},
356 {SMB_SIGNING_REQUIRED, "required"},
357 {SMB_SIGNING_REQUIRED, "mandatory"},
358 {SMB_SIGNING_REQUIRED, "force"},
359 {SMB_SIGNING_REQUIRED, "forced"},
360 {SMB_SIGNING_REQUIRED, "enforced"},
361 {SMB_SIGNING_AUTO, "auto"},
365 static const struct enum_list enum_server_role[] = {
366 {ROLE_STANDALONE, "standalone"},
367 {ROLE_DOMAIN_MEMBER, "member server"},
368 {ROLE_DOMAIN_BDC, "bdc"},
369 {ROLE_DOMAIN_PDC, "pdc"},
374 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
376 * Note: We have a flag called FLAG_DEVELOPER but is not used at this time, it
377 * is implied in current control logic. This may change at some later time. A
378 * flag value of 0 means - show as development option only.
380 * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
381 * screen in SWAT. This is used to exclude parameters as well as to squash all
382 * parameters that have been duplicated by pseudonyms.
384 static struct parm_struct parm_table[] = {
385 {"Base Options", P_SEP, P_SEPARATOR},
387 {"server role", P_ENUM, P_GLOBAL, &Globals.server_role, NULL, enum_server_role, FLAG_BASIC},
389 {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
390 {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
391 {"ncalrpc dir", P_STRING, P_GLOBAL, &Globals.ncalrpc_dir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
392 {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
393 {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
394 {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
395 {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE},
396 {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkgroup, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
397 {"realm", P_STRING, P_GLOBAL, &Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
398 {"netbios name", P_USTRING, P_GLOBAL, &Globals.szNetbiosName, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
399 {"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
400 {"netbios scope", P_USTRING, P_GLOBAL, &Globals.szNetbiosScope, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
401 {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
402 {"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
403 {"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
404 {"ntvfs handler", P_LIST, P_LOCAL, &sDefault.ntvfs_handler, NULL, NULL, FLAG_ADVANCED},
405 {"ntptr providor", P_STRING, P_GLOBAL, &Globals.ntptr_providor, NULL, NULL, FLAG_ADVANCED},
406 {"dcerpc endpoint servers", P_LIST, P_GLOBAL, &Globals.dcerpc_ep_servers, NULL, NULL, FLAG_ADVANCED},
407 {"server services", P_LIST, P_GLOBAL, &Globals.server_services, NULL, NULL, FLAG_ADVANCED},
409 {"Security Options", P_SEP, P_SEPARATOR},
411 {"security", P_ENUM, P_GLOBAL, &Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
412 {"auth methods", P_LIST, P_GLOBAL, &Globals.AuthMethods, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
413 {"encrypt passwords", P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
414 {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
415 {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
416 {"password server", P_LIST, P_GLOBAL, &Globals.szPasswordServers, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
417 {"sam database", P_STRING, P_GLOBAL, &Globals.szSAM_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
418 {"spoolss database", P_STRING, P_GLOBAL, &Globals.szSPOOLSS_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 {"web port", P_INTEGER, P_GLOBAL, &Globals.web_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
449 {"tls enabled", P_BOOL, P_GLOBAL, &Globals.tls_enabled, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
450 {"tls keyfile", P_STRING, P_GLOBAL, &Globals.tls_keyfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
451 {"tls certfile", P_STRING, P_GLOBAL, &Globals.tls_certfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
452 {"tls cafile", P_STRING, P_GLOBAL, &Globals.tls_cafile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
453 {"tls crlfile", P_STRING, P_GLOBAL, &Globals.tls_crlfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
454 {"swat directory", P_STRING, P_GLOBAL, &Globals.swat_directory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
455 {"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, FLAG_DEVELOPER},
456 {"max protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
457 {"min protocol", P_ENUM, P_GLOBAL, &Globals.minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
458 {"unicode", P_BOOL, P_GLOBAL, &Globals.bUnicode, NULL, NULL, FLAG_DEVELOPER},
459 {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL, NULL, FLAG_DEVELOPER},
460 {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL, NULL, FLAG_DEVELOPER},
461 {"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
463 {"nt status support", P_BOOL, P_GLOBAL, &Globals.bNTStatusSupport, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
465 {"announce version", P_STRING, P_GLOBAL, &Globals.szAnnounceVersion, NULL, NULL, FLAG_DEVELOPER},
466 {"announce as", P_ENUM, P_GLOBAL, &Globals.announce_as, NULL, enum_announce_as, FLAG_DEVELOPER},
467 {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
468 {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
470 {"name resolve order", P_LIST, P_GLOBAL, &Globals.szNameResolveOrder, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
471 {"max wins ttl", P_INTEGER, P_GLOBAL, &Globals.max_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
472 {"min wins ttl", P_INTEGER, P_GLOBAL, &Globals.min_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
473 {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
474 {"unix extensions", P_BOOL, P_GLOBAL, &Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
475 {"use spnego", P_BOOL, P_GLOBAL, &Globals.bUseSpnego, NULL, NULL, FLAG_DEVELOPER},
476 {"server signing", P_ENUM, P_GLOBAL, &Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
477 {"client signing", P_ENUM, P_GLOBAL, &Globals.client_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
478 {"rpc big endian", P_BOOL, P_GLOBAL, &Globals.bRpcBigEndian, NULL, NULL, FLAG_DEVELOPER},
480 {"Tuning Options", P_SEP, P_SEPARATOR},
482 {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL, NULL, FLAG_SHARE},
483 {"paranoid server security", P_BOOL, P_GLOBAL, &Globals.paranoid_server_security, NULL, NULL, FLAG_DEVELOPER},
484 {"socket options", P_STRING, P_GLOBAL, &Globals.socket_options, NULL, NULL, FLAG_DEVELOPER},
486 {"strict sync", P_BOOL, P_LOCAL, &sDefault.bStrictSync, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
487 {"case insensitive filesystem", P_BOOL, P_LOCAL, &sDefault.bCIFileSystem, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
489 {"Printing Options", P_SEP, P_SEPARATOR},
491 {"max print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxPrintJobs, NULL, NULL, FLAG_PRINT},
492 {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_PRINT},
493 {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_HIDE},
495 {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_PRINT},
496 {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_HIDE},
498 {"Filename Handling", P_SEP, P_SEPARATOR},
500 {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
501 {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
502 {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
504 {"Domain Options", P_SEP, P_SEPARATOR},
506 {"Logon Options", P_SEP, P_SEPARATOR},
509 {"Browse Options", P_SEP, P_SEPARATOR},
511 {"preferred master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
512 {"prefered master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_HIDE},
513 {"local master", P_BOOL, P_GLOBAL, &Globals.bLocalMaster, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
514 {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
515 {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_HIDE},
517 {"WINS Options", P_SEP, P_SEPARATOR},
519 {"wins server", P_LIST, P_GLOBAL, &Globals.szWINSservers, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
520 {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
522 {"Locking Options", P_SEP, P_SEPARATOR},
524 {"csc policy", P_ENUM, P_LOCAL, &sDefault.iCSCPolicy, NULL, enum_csc_policy, FLAG_SHARE | FLAG_GLOBAL},
526 {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
528 {"Miscellaneous Options", P_SEP, P_SEPARATOR},
530 {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE},
531 {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
532 {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
533 {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_HIDE},
534 {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
535 {"pid directory", P_STRING, P_GLOBAL, &Globals.szPidDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
536 {"js include", P_LIST, P_GLOBAL, &Globals.jsInclude, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
537 {"setup directory", P_STRING, P_GLOBAL, &Globals.szSetupDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
539 {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL, NULL, FLAG_DEVELOPER},
540 {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL, NULL, FLAG_HIDE},
542 {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy, NULL, FLAG_HIDE},
543 {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include, NULL, FLAG_HIDE},
545 {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
546 {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_SHARE },
547 {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_SHARE},
549 {"panic action", P_STRING, P_GLOBAL, &Globals.szPanicAction, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
551 {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_SHARE},
552 {"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
553 {"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
554 {"winbind sealed pipes", P_BOOL, P_GLOBAL, &Globals.bWinbindSealedPipes, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
556 {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
561 return the parameter table
563 struct parm_struct *lp_parm_table(void)
568 /***************************************************************************
569 Initialise the global parameter structure.
570 ***************************************************************************/
571 static void init_globals(void)
576 DEBUG(3, ("Initialising global parameters\n"));
578 for (i = 0; parm_table[i].label; i++) {
579 if ((parm_table[i].type == P_STRING ||
580 parm_table[i].type == P_USTRING) &&
582 !(parm_table[i].flags & FLAG_CMDLINE)) {
583 string_set(parm_table[i].ptr, "");
587 do_parameter("config file", dyn_CONFIGFILE, NULL);
589 do_parameter("server role", "standalone", NULL);
591 /* options that can be set on the command line must be initialised via
592 the slower do_parameter() to ensure that FLAG_CMDLINE is obeyed */
594 do_parameter("socket options", "TCP_NODELAY", NULL);
596 do_parameter("workgroup", DEFAULT_WORKGROUP, NULL);
597 myname = get_myname();
598 do_parameter("netbios name", myname, NULL);
600 do_parameter("max protocol", "NT1", NULL);
601 do_parameter("name resolve order", "lmhosts wins host bcast", NULL);
603 do_parameter("fstype", FSTYPE_STRING, NULL);
604 do_parameter("ntvfs handler", "unixuid default", NULL);
605 do_parameter("max connections", "-1", NULL);
607 do_parameter("dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup", NULL);
608 do_parameter("server services", "smb rpc nbt wrepl ldap cldap web kdc", NULL);
609 do_parameter("ntptr providor", "simple_ldb", NULL);
610 do_parameter("auth methods", "anonymous sam_ignoredomain", NULL);
611 do_parameter("private dir", dyn_PRIVATE_DIR, NULL);
612 do_parameter("sam database", "sam.ldb", NULL);
613 do_parameter("spoolss database", "spoolss.ldb", NULL);
614 do_parameter("wins database", "wins.ldb", NULL);
615 do_parameter("registry:HKEY_LOCAL_MACHINE", "hklm.ldb", NULL);
617 /* This hive should be dynamically generated by Samba using
618 data from the sam, but for the moment leave it in a tdb to
619 keep regedt32 from popping up an annoying dialog. */
620 do_parameter("registry:HKEY_USERS", "hku.ldb", NULL);
622 /* using UTF8 by default allows us to support all chars */
623 do_parameter("unix charset", "UTF8", NULL);
625 /* Use codepage 850 as a default for the dos character set */
626 do_parameter("dos charset", "CP850", NULL);
629 * Allow the default PASSWD_CHAT to be overridden in local.h.
631 do_parameter("passwd chat", DEFAULT_PASSWD_CHAT, NULL);
633 do_parameter("pid directory", dyn_PIDDIR, NULL);
634 do_parameter("lock dir", dyn_LOCKDIR, NULL);
635 do_parameter("ncalrpc dir", dyn_NCALRPCDIR, NULL);
637 do_parameter("socket address", "0.0.0.0", NULL);
638 do_parameter_var("server string", "Samba %s", SAMBA_VERSION_STRING);
640 do_parameter_var("announce version", "%d.%d",
641 DEFAULT_MAJOR_VERSION,
642 DEFAULT_MINOR_VERSION);
644 do_parameter("password server", "*", NULL);
646 do_parameter("max mux", "50", NULL);
647 do_parameter("max xmit", "12288", NULL);
648 do_parameter("password level", "0", NULL);
649 do_parameter("LargeReadwrite", "True", NULL);
650 do_parameter("minprotocol", "CORE", NULL);
651 do_parameter("security", "USER", NULL);
652 do_parameter("paranoid server security", "True", NULL);
653 do_parameter("EncryptPasswords", "True", NULL);
654 do_parameter("ReadRaw", "True", NULL);
655 do_parameter("WriteRaw", "True", NULL);
656 do_parameter("NullPasswords", "False", NULL);
657 do_parameter("ObeyPamRestrictions", "False", NULL);
658 do_parameter("announce as", "NT SERVER", NULL);
660 do_parameter("TimeServer", "False", NULL);
661 do_parameter("BindInterfacesOnly", "False", NULL);
662 do_parameter("Unicode", "True", NULL);
663 do_parameter("ClientLanManAuth", "True", NULL);
664 do_parameter("LanmanAuth", "True", NULL);
665 do_parameter("NTLMAuth", "True", NULL);
666 do_parameter("client use spnego principal", "False", NULL);
668 do_parameter("UnixExtensions", "False", NULL);
670 do_parameter("PreferredMaster", "Auto", NULL);
671 do_parameter("LocalMaster", "True", NULL);
673 do_parameter("WINSsupport", "False", NULL);
675 do_parameter("winbind separator", "\\", NULL);
676 do_parameter("winbind sealed pipes", "True", NULL);
678 do_parameter("client signing", "Yes", NULL);
679 do_parameter("server signing", "auto", NULL);
681 do_parameter("use spnego", "True", NULL);
683 do_parameter("smb ports", SMB_PORTS, NULL);
684 do_parameter("nbt port", "137", NULL);
685 do_parameter("dgram port", "138", NULL);
686 do_parameter("cldap port", "389", NULL);
687 do_parameter("krb5 port", "88", NULL);
688 do_parameter("web port", "901", NULL);
689 do_parameter("swat directory", dyn_SWATDIR, NULL);
691 do_parameter("nt status support", "True", NULL);
693 do_parameter("max wins ttl", "432000", NULL);
694 do_parameter("min wins ttl", "10", NULL);
696 do_parameter("tls enabled", "True", NULL);
697 do_parameter("tls keyfile", "tls/key.pem", NULL);
698 do_parameter("tls certfile", "tls/cert.pem", NULL);
699 do_parameter("tls cafile", "tls/ca.pem", NULL);
700 do_parameter_var("js include", "%s/js", dyn_LIBDIR);
701 do_parameter_var("setup directory", "%s/setup", dyn_LIBDIR);
704 static TALLOC_CTX *lp_talloc;
706 /******************************************************************* a
707 Free up temporary memory - called from the main loop.
708 ********************************************************************/
710 void lp_talloc_free(void)
714 talloc_free(lp_talloc);
718 /*******************************************************************
719 Convenience routine to grab string parameters into temporary memory
720 and run standard_sub_basic on them. The buffers can be written to by
721 callers without affecting the source string.
722 ********************************************************************/
724 static const char *lp_string(const char *s)
726 #if 0 /* until REWRITE done to make thread-safe */
727 size_t len = s ? strlen(s) : 0;
731 /* The follow debug is useful for tracking down memory problems
732 especially if you have an inner loop that is calling a lp_*()
733 function that returns a string. Perhaps this debug should be
734 present all the time? */
737 DEBUG(10, ("lp_string(%s)\n", s));
740 #if 0 /* until REWRITE done to make thread-safe */
742 lp_talloc = talloc_init("lp_talloc");
744 ret = talloc_array(lp_talloc, char, len + 100); /* leave room for substitution */
752 StrnCpy(ret, s, len);
754 if (trim_string(ret, "\"", "\"")) {
755 if (strchr(ret,'"') != NULL)
756 StrnCpy(ret, s, len);
759 standard_sub_basic(ret,len+100);
766 In this section all the functions that are used to access the
767 parameters from the rest of the program are defined
770 #define FN_GLOBAL_STRING(fn_name,ptr) \
771 const char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
772 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
773 const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");}
774 #define FN_GLOBAL_LIST(fn_name,ptr) \
775 const char **fn_name(void) {return(*(const char ***)(ptr));}
776 #define FN_GLOBAL_BOOL(fn_name,ptr) \
777 BOOL fn_name(void) {return(*(BOOL *)(ptr));}
778 #define FN_GLOBAL_CHAR(fn_name,ptr) \
779 char fn_name(void) {return(*(char *)(ptr));}
780 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
781 int fn_name(void) {return(*(int *)(ptr));}
783 #define FN_LOCAL_STRING(fn_name,val) \
784 const char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
785 #define FN_LOCAL_CONST_STRING(fn_name,val) \
786 const char *fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
787 #define FN_LOCAL_LIST(fn_name,val) \
788 const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
789 #define FN_LOCAL_BOOL(fn_name,val) \
790 BOOL fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
791 #define FN_LOCAL_CHAR(fn_name,val) \
792 char fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
793 #define FN_LOCAL_INTEGER(fn_name,val) \
794 int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
796 FN_GLOBAL_INTEGER(lp_server_role, &Globals.server_role)
797 FN_GLOBAL_LIST(lp_smb_ports, &Globals.smb_ports)
798 FN_GLOBAL_INTEGER(lp_nbt_port, &Globals.nbt_port)
799 FN_GLOBAL_INTEGER(lp_dgram_port, &Globals.dgram_port)
800 FN_GLOBAL_INTEGER(lp_cldap_port, &Globals.cldap_port)
801 FN_GLOBAL_INTEGER(lp_krb5_port, &Globals.krb5_port)
802 FN_GLOBAL_INTEGER(lp_web_port, &Globals.web_port)
803 FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
804 FN_GLOBAL_STRING(lp_swat_directory, &Globals.swat_directory)
805 FN_GLOBAL_BOOL(lp_tls_enabled, &Globals.tls_enabled)
806 FN_GLOBAL_STRING(lp_tls_keyfile, &Globals.tls_keyfile)
807 FN_GLOBAL_STRING(lp_tls_certfile, &Globals.tls_certfile)
808 FN_GLOBAL_STRING(lp_tls_cafile, &Globals.tls_cafile)
809 FN_GLOBAL_STRING(lp_tls_crlfile, &Globals.tls_crlfile)
810 FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
811 FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset)
812 FN_GLOBAL_STRING(lp_logfile, &Globals.szLogFile)
813 FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
814 FN_GLOBAL_STRING(lp_sam_url, &Globals.szSAM_URL)
815 FN_GLOBAL_STRING(lp_spoolss_url, &Globals.szSPOOLSS_URL)
816 FN_GLOBAL_STRING(lp_wins_url, &Globals.szWINS_URL)
817 FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
818 FN_GLOBAL_BOOL(lp_winbind_sealed_pipes, &Globals.bWinbindSealedPipes)
819 FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
820 FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
821 FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
822 FN_GLOBAL_STRING(lp_setupdir, &Globals.szSetupDir)
823 FN_GLOBAL_STRING(lp_ncalrpc_dir, &Globals.ncalrpc_dir)
824 FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
825 FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, &Globals.dcerpc_ep_servers)
826 FN_GLOBAL_LIST(lp_server_services, &Globals.server_services)
827 FN_GLOBAL_STRING(lp_ntptr_providor, &Globals.ntptr_providor)
828 FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
829 FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
830 FN_GLOBAL_LIST(lp_passwordserver, &Globals.szPasswordServers)
831 FN_GLOBAL_LIST(lp_name_resolve_order, &Globals.szNameResolveOrder)
832 FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
833 FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
834 FN_GLOBAL_STRING(lp_workgroup, &Globals.szWorkgroup)
835 FN_GLOBAL_STRING(lp_netbios_name, &Globals.szNetbiosName)
836 FN_GLOBAL_STRING(lp_netbios_scope, &Globals.szNetbiosScope)
837 FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
838 FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
839 FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
840 FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
841 FN_GLOBAL_STRING(lp_panic_action, &Globals.szPanicAction)
843 FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
844 FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
845 FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
846 FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
847 FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
848 FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw)
849 FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords)
850 FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions)
851 FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
852 static FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
853 FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
854 FN_GLOBAL_BOOL(lp_unicode, &Globals.bUnicode)
855 FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
856 FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
857 FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
858 FN_GLOBAL_BOOL(lp_client_plaintext_auth, &Globals.bClientPlaintextAuth)
859 FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
860 FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
861 FN_GLOBAL_BOOL(lp_client_use_spnego_principal, &Globals.client_use_spnego_principal)
862 FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
863 FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions)
864 FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
865 FN_GLOBAL_BOOL(lp_rpc_big_endian, &Globals.bRpcBigEndian)
866 FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
867 FN_GLOBAL_INTEGER(lp_min_wins_ttl, &Globals.min_wins_ttl)
868 FN_GLOBAL_INTEGER(lp_maxmux, &Globals.max_mux)
869 FN_GLOBAL_INTEGER(lp_max_xmit, &Globals.max_xmit)
870 FN_GLOBAL_INTEGER(lp_passwordlevel, &Globals.pwordlevel)
871 FN_GLOBAL_INTEGER(lp_maxprotocol, &Globals.maxprotocol)
872 FN_GLOBAL_INTEGER(lp_minprotocol, &Globals.minprotocol)
873 FN_GLOBAL_INTEGER(lp_security, &Globals.security)
874 FN_GLOBAL_LIST(lp_auth_methods, &Globals.AuthMethods)
875 FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security)
876 static FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as)
877 FN_GLOBAL_LIST(lp_js_include, &Globals.jsInclude)
880 FN_LOCAL_STRING(lp_servicename, szService)
881 FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
882 FN_LOCAL_STRING(lp_pathname, szPath)
883 static FN_LOCAL_STRING(_lp_printername, szPrintername)
884 FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
885 FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
886 FN_LOCAL_STRING(lp_comment, comment)
887 FN_LOCAL_STRING(lp_fstype, fstype)
888 static FN_LOCAL_STRING(lp_volume, volume)
889 FN_LOCAL_LIST(lp_ntvfs_handler, ntvfs_handler)
890 FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
891 FN_LOCAL_BOOL(lp_browseable, bBrowseable)
892 FN_LOCAL_BOOL(lp_readonly, bRead_only)
893 FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
894 FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
895 FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
896 FN_LOCAL_BOOL(lp_strict_locking, bStrictLocking)
897 FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
898 FN_LOCAL_BOOL(lp_ci_filesystem, bCIFileSystem)
899 FN_LOCAL_BOOL(lp_map_system, bMap_system)
900 FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
901 FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
902 FN_GLOBAL_INTEGER(lp_server_signing, &Globals.server_signing)
903 FN_GLOBAL_INTEGER(lp_client_signing, &Globals.client_signing)
905 /* local prototypes */
907 static int map_parameter(const char *pszParmName);
908 static BOOL set_boolean(BOOL *pb, const char *pszParmValue);
909 static int getservicebyname(const char *pszServiceName,
910 service * pserviceDest);
911 static void copy_service(service * pserviceDest,
912 service * pserviceSource, BOOL *pcopymapDest);
913 static BOOL service_ok(int iService);
914 static BOOL do_section(const char *pszSectionName, void *);
915 static void init_copymap(service * pservice);
917 /* This is a helper function for parametrical options support. */
918 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
919 /* Actual parametrical functions are quite simple */
920 const char *lp_get_parametric(int lookup_service, const char *type, const char *option)
923 struct param_opt *data;
925 if (lookup_service >= iNumServices) return NULL;
927 data = (lookup_service < 0) ?
928 Globals.param_opt : ServicePtrs[lookup_service]->param_opt;
930 asprintf(&vfskey, "%s:%s", type, option);
934 if (strcmp(data->key, vfskey) == 0) {
941 if (lookup_service >= 0) {
942 /* Try to fetch the same option but from globals */
943 /* but only if we are not already working with Globals */
944 data = Globals.param_opt;
946 if (strcmp(data->key, vfskey) == 0) {
960 /*******************************************************************
961 convenience routine to return int parameters.
962 ********************************************************************/
963 static int lp_int(const char *s)
967 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
971 return strtol(s, NULL, 0);
974 /*******************************************************************
975 convenience routine to return unsigned long parameters.
976 ********************************************************************/
977 static int lp_ulong(const char *s)
981 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
985 return strtoul(s, NULL, 0);
988 /*******************************************************************
989 convenience routine to return boolean parameters.
990 ********************************************************************/
991 static BOOL lp_bool(const char *s)
996 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
1000 if (!set_boolean(&ret,s)) {
1001 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1009 /* Return parametric option from a given service. Type is a part of option before ':' */
1010 /* Parametric option has following syntax: 'Type: option = value' */
1011 /* Returned value is allocated in 'lp_talloc' context */
1013 const char *lp_parm_string(int lookup_service, const char *type, const char *option)
1015 const char *value = lp_get_parametric(lookup_service, type, option);
1018 return lp_string(value);
1023 /* Return parametric option from a given service. Type is a part of option before ':' */
1024 /* Parametric option has following syntax: 'Type: option = value' */
1025 /* Returned value is allocated in 'lp_talloc' context */
1027 const char **lp_parm_string_list(int lookup_service, const char *type, const char *option,
1028 const char *separator)
1030 const char *value = lp_get_parametric(lookup_service, type, option);
1033 return str_list_make(talloc_autofree_context(), value, separator);
1038 /* Return parametric option from a given service. Type is a part of option before ':' */
1039 /* Parametric option has following syntax: 'Type: option = value' */
1041 int lp_parm_int(int lookup_service, const char *type, const char *option, int default_v)
1043 const char *value = lp_get_parametric(lookup_service, type, option);
1046 return lp_int(value);
1051 /* Return parametric option from a given service. Type is a part of option before ':' */
1052 /* Parametric option has following syntax: 'Type: option = value' */
1054 unsigned long lp_parm_ulong(int lookup_service, const char *type, const char *option, unsigned long default_v)
1056 const char *value = lp_get_parametric(lookup_service, type, option);
1059 return lp_ulong(value);
1064 /* Return parametric option from a given service. Type is a part of option before ':' */
1065 /* Parametric option has following syntax: 'Type: option = value' */
1067 BOOL lp_parm_bool(int lookup_service, const char *type, const char *option, BOOL default_v)
1069 const char *value = lp_get_parametric(lookup_service, type, option);
1072 return lp_bool(value);
1078 /***************************************************************************
1079 Initialise a service to the defaults.
1080 ***************************************************************************/
1082 static void init_service(service * pservice)
1084 memset((char *)pservice, '\0', sizeof(service));
1085 copy_service(pservice, &sDefault, NULL);
1088 /***************************************************************************
1089 Free the dynamically allocated parts of a service struct.
1090 ***************************************************************************/
1092 static void free_service(service *pservice)
1095 struct param_opt *data, *pdata;
1099 if (pservice->szService)
1100 DEBUG(5, ("free_service: Freeing service %s\n",
1101 pservice->szService));
1103 string_free(&pservice->szService);
1104 SAFE_FREE(pservice->copymap);
1106 for (i = 0; parm_table[i].label; i++) {
1107 if ((parm_table[i].type == P_STRING ||
1108 parm_table[i].type == P_USTRING) &&
1109 parm_table[i].class == P_LOCAL) {
1110 string_free((char **)
1111 (((char *)pservice) +
1112 PTR_DIFF(parm_table[i].ptr, &sDefault)));
1113 } else if (parm_table[i].type == P_LIST &&
1114 parm_table[i].class == P_LOCAL) {
1115 char ***listp = (char ***)(((char *)pservice) +
1116 PTR_DIFF(parm_table[i].ptr, &sDefault));
1117 talloc_free(*listp);
1122 DEBUG(5,("Freeing parametrics:\n"));
1123 data = pservice->param_opt;
1125 DEBUG(5,("[%s = %s]\n", data->key, data->value));
1126 string_free(&data->key);
1127 string_free(&data->value);
1133 ZERO_STRUCTP(pservice);
1136 /***************************************************************************
1137 Add a new service to the services array initialising it with the given
1139 ***************************************************************************/
1141 static int add_a_service(const service *pservice, const char *name)
1145 int num_to_alloc = iNumServices + 1;
1146 struct param_opt *data, *pdata;
1148 tservice = *pservice;
1150 /* it might already exist */
1152 i = getservicebyname(name, NULL);
1154 /* Clean all parametric options for service */
1155 /* They will be added during parsing again */
1156 data = ServicePtrs[i]->param_opt;
1158 string_free(&data->key);
1159 string_free(&data->value);
1164 ServicePtrs[i]->param_opt = NULL;
1169 /* find an invalid one */
1170 for (i = 0; i < iNumServices; i++)
1171 if (!ServicePtrs[i]->valid)
1174 /* if not, then create one */
1175 if (i == iNumServices) {
1178 tsp = realloc_p(ServicePtrs, service *, num_to_alloc);
1181 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1186 ServicePtrs[iNumServices] = malloc_p(service);
1188 if (!ServicePtrs[iNumServices]) {
1189 DEBUG(0,("add_a_service: out of memory!\n"));
1195 free_service(ServicePtrs[i]);
1197 ServicePtrs[i]->valid = True;
1199 init_service(ServicePtrs[i]);
1200 copy_service(ServicePtrs[i], &tservice, NULL);
1202 string_set(&ServicePtrs[i]->szService, name);
1206 /***************************************************************************
1207 Add a new home service, with the specified home directory, defaults coming
1209 ***************************************************************************/
1211 BOOL lp_add_home(const char *pszHomename, int iDefaultService,
1212 const char *user, const char *pszHomedir)
1217 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1222 if (!(*(ServicePtrs[iDefaultService]->szPath))
1223 || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(-1))) {
1224 pstrcpy(newHomedir, pszHomedir);
1226 pstrcpy(newHomedir, lp_pathname(iDefaultService));
1227 string_sub(newHomedir,"%H", pszHomedir, sizeof(newHomedir));
1230 string_set(&ServicePtrs[i]->szPath, newHomedir);
1232 if (!(*(ServicePtrs[i]->comment))) {
1234 slprintf(comment, sizeof(comment) - 1,
1235 "Home directory of %s", user);
1236 string_set(&ServicePtrs[i]->comment, comment);
1238 ServicePtrs[i]->bAvailable = sDefault.bAvailable;
1239 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1241 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1247 /***************************************************************************
1248 Add a new service, based on an old one.
1249 ***************************************************************************/
1251 int lp_add_service(const char *pszService, int iDefaultService)
1253 return (add_a_service(ServicePtrs[iDefaultService], pszService));
1256 /***************************************************************************
1257 Add the IPC service.
1258 ***************************************************************************/
1260 static BOOL lp_add_hidden(const char *name, const char *fstype)
1263 int i = add_a_service(&sDefault, name);
1268 slprintf(comment, sizeof(comment) - 1,
1269 "%s Service (%s)", fstype, Globals.szServerString);
1271 string_set(&ServicePtrs[i]->szPath, tmpdir());
1272 string_set(&ServicePtrs[i]->comment, comment);
1273 string_set(&ServicePtrs[i]->fstype, fstype);
1274 ServicePtrs[i]->iMaxConnections = -1;
1275 ServicePtrs[i]->bAvailable = True;
1276 ServicePtrs[i]->bRead_only = True;
1277 ServicePtrs[i]->bPrint_ok = False;
1278 ServicePtrs[i]->bBrowseable = False;
1280 if (strcasecmp(fstype, "IPC") == 0) {
1281 lp_do_parameter(i, "ntvfs handler", "default");
1284 DEBUG(3, ("adding hidden service %s\n", name));
1289 /***************************************************************************
1290 Add a new printer service, with defaults coming from service iFrom.
1291 ***************************************************************************/
1293 BOOL lp_add_printer(const char *pszPrintername, int iDefaultService)
1295 const char *comment = "From Printcap";
1296 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1301 /* note that we do NOT default the availability flag to True - */
1302 /* we take it from the default service passed. This allows all */
1303 /* dynamic printers to be disabled by disabling the [printers] */
1304 /* entry (if/when the 'available' keyword is implemented!). */
1306 /* the printer name is set to the service name. */
1307 string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1308 string_set(&ServicePtrs[i]->comment, comment);
1309 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1310 /* Printers cannot be read_only. */
1311 ServicePtrs[i]->bRead_only = False;
1312 /* Printer services must be printable. */
1313 ServicePtrs[i]->bPrint_ok = True;
1315 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1317 update_server_announce_as_printserver();
1322 /***************************************************************************
1323 Map a parameter's string representation to something we can use.
1324 Returns False if the parameter string is not recognised, else TRUE.
1325 ***************************************************************************/
1327 static int map_parameter(const char *pszParmName)
1331 if (*pszParmName == '-')
1334 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1335 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1338 /* Warn only if it isn't parametric option */
1339 if (strchr(pszParmName, ':') == NULL)
1340 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1341 /* We do return 'fail' for parametric options as well because they are
1342 stored in different storage
1349 return the parameter structure for a parameter
1351 struct parm_struct *lp_parm_struct(const char *name)
1353 int parmnum = map_parameter(name);
1354 if (parmnum == -1) return NULL;
1355 return &parm_table[parmnum];
1359 return the parameter pointer for a parameter
1361 void *lp_parm_ptr(int snum, struct parm_struct *parm)
1366 return ((char *)ServicePtrs[snum]) + PTR_DIFF(parm->ptr, &sDefault);
1369 /***************************************************************************
1370 Set a boolean variable from the text value stored in the passed string.
1371 Returns True in success, False if the passed string does not correctly
1372 represent a boolean.
1373 ***************************************************************************/
1375 static BOOL set_boolean(BOOL *pb, const char *pszParmValue)
1380 if (strwicmp(pszParmValue, "yes") == 0 ||
1381 strwicmp(pszParmValue, "true") == 0 ||
1382 strwicmp(pszParmValue, "1") == 0)
1384 else if (strwicmp(pszParmValue, "no") == 0 ||
1385 strwicmp(pszParmValue, "False") == 0 ||
1386 strwicmp(pszParmValue, "0") == 0)
1390 ("ERROR: Badly formed boolean in configuration file: \"%s\".\n",
1397 /***************************************************************************
1398 Find a service by name. Otherwise works like get_service.
1399 ***************************************************************************/
1401 static int getservicebyname(const char *pszServiceName, service * pserviceDest)
1405 for (iService = iNumServices - 1; iService >= 0; iService--)
1406 if (VALID(iService) &&
1407 strwicmp(ServicePtrs[iService]->szService, pszServiceName) == 0) {
1408 if (pserviceDest != NULL)
1409 copy_service(pserviceDest, ServicePtrs[iService], NULL);
1416 /***************************************************************************
1417 Copy a service structure to another.
1418 If pcopymapDest is NULL then copy all fields
1419 ***************************************************************************/
1421 static void copy_service(service * pserviceDest, service * pserviceSource, BOOL *pcopymapDest)
1424 BOOL bcopyall = (pcopymapDest == NULL);
1425 struct param_opt *data, *pdata, *paramo;
1428 for (i = 0; parm_table[i].label; i++)
1429 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1430 (bcopyall || pcopymapDest[i])) {
1431 void *def_ptr = parm_table[i].ptr;
1433 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
1436 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
1439 switch (parm_table[i].type) {
1441 *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
1446 *(int *)dest_ptr = *(int *)src_ptr;
1450 string_set(dest_ptr,
1455 string_set(dest_ptr,
1457 strupper(*(char **)dest_ptr);
1460 *(const char ***)dest_ptr = str_list_copy(talloc_autofree_context(),
1461 *(const char ***)src_ptr);
1469 init_copymap(pserviceDest);
1470 if (pserviceSource->copymap)
1471 memcpy((void *)pserviceDest->copymap,
1472 (void *)pserviceSource->copymap,
1473 sizeof(BOOL) * NUMPARAMETERS);
1476 data = pserviceSource->param_opt;
1479 pdata = pserviceDest->param_opt;
1480 /* Traverse destination */
1482 /* If we already have same option, override it */
1483 if (strcmp(pdata->key, data->key) == 0) {
1484 string_free(&pdata->value);
1485 pdata->value = strdup(data->value);
1489 pdata = pdata->next;
1492 paramo = malloc_p(struct param_opt);
1495 paramo->key = strdup(data->key);
1496 paramo->value = strdup(data->value);
1497 DLIST_ADD(pserviceDest->param_opt, paramo);
1503 /***************************************************************************
1504 Check a service for consistency. Return False if the service is in any way
1505 incomplete or faulty, else True.
1506 ***************************************************************************/
1508 static BOOL service_ok(int iService)
1513 if (ServicePtrs[iService]->szService[0] == '\0') {
1514 DEBUG(0, ("The following message indicates an internal error:\n"));
1515 DEBUG(0, ("No service name in service entry.\n"));
1519 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1520 /* I can't see why you'd want a non-printable printer service... */
1521 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
1522 if (!ServicePtrs[iService]->bPrint_ok) {
1523 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
1524 ServicePtrs[iService]->szService));
1525 ServicePtrs[iService]->bPrint_ok = True;
1526 update_server_announce_as_printserver();
1528 /* [printers] service must also be non-browsable. */
1529 if (ServicePtrs[iService]->bBrowseable)
1530 ServicePtrs[iService]->bBrowseable = False;
1533 /* If a service is flagged unavailable, log the fact at level 0. */
1534 if (!ServicePtrs[iService]->bAvailable)
1535 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
1536 ServicePtrs[iService]->szService));
1541 static struct file_lists {
1542 struct file_lists *next;
1546 } *file_lists = NULL;
1548 /*******************************************************************
1549 Keep a linked list of all config files so we know when one has changed
1550 it's date and needs to be reloaded.
1551 ********************************************************************/
1553 static void add_to_file_list(const char *fname, const char *subfname)
1555 struct file_lists *f = file_lists;
1558 if (f->name && !strcmp(f->name, fname))
1564 f = malloc_p(struct file_lists);
1567 f->next = file_lists;
1568 f->name = strdup(fname);
1573 f->subfname = strdup(subfname);
1579 f->modtime = file_modtime(subfname);
1581 time_t t = file_modtime(subfname);
1587 /*******************************************************************
1588 Check if a config file has changed date.
1589 ********************************************************************/
1591 BOOL lp_file_list_changed(void)
1593 struct file_lists *f = file_lists;
1594 DEBUG(6, ("lp_file_list_changed()\n"));
1600 pstrcpy(n2, f->name);
1601 standard_sub_basic(n2,sizeof(n2));
1603 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
1604 f->name, n2, ctime(&f->modtime)));
1606 mod_time = file_modtime(n2);
1608 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
1610 ("file %s modified: %s\n", n2,
1612 f->modtime = mod_time;
1613 SAFE_FREE(f->subfname);
1614 f->subfname = strdup(n2);
1622 /***************************************************************************
1623 Handle the include operation.
1624 ***************************************************************************/
1626 static BOOL handle_include(const char *pszParmValue, char **ptr)
1629 pstrcpy(fname, pszParmValue);
1631 standard_sub_basic(fname,sizeof(fname));
1633 add_to_file_list(pszParmValue, fname);
1635 string_set(ptr, fname);
1637 if (file_exist(fname))
1638 return (pm_process(fname, do_section, do_parameter, NULL));
1640 DEBUG(2, ("Can't find include file %s\n", fname));
1645 /***************************************************************************
1646 Handle the interpretation of the copy parameter.
1647 ***************************************************************************/
1649 static BOOL handle_copy(const char *pszParmValue, char **ptr)
1653 service serviceTemp;
1655 string_set(ptr, pszParmValue);
1657 init_service(&serviceTemp);
1661 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
1663 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
1664 if (iTemp == iServiceIndex) {
1665 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
1667 copy_service(ServicePtrs[iServiceIndex],
1669 ServicePtrs[iServiceIndex]->copymap);
1673 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
1677 free_service(&serviceTemp);
1681 /***************************************************************************
1682 Initialise a copymap.
1683 ***************************************************************************/
1685 static void init_copymap(service * pservice)
1688 SAFE_FREE(pservice->copymap);
1689 pservice->copymap = malloc_array_p(BOOL, NUMPARAMETERS);
1690 if (!pservice->copymap)
1692 ("Couldn't allocate copymap!! (size %d)\n",
1693 (int)NUMPARAMETERS));
1695 for (i = 0; i < NUMPARAMETERS; i++)
1696 pservice->copymap[i] = True;
1699 /***************************************************************************
1700 Return the local pointer to a parameter given the service number and the
1701 pointer into the default structure.
1702 ***************************************************************************/
1704 void *lp_local_ptr(int snum, void *ptr)
1706 return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
1710 /***************************************************************************
1711 Process a parametric option
1712 ***************************************************************************/
1713 static BOOL lp_do_parameter_parametric(int snum, const char *pszParmName, const char *pszParmValue, int flags)
1715 struct param_opt *paramo, *data;
1718 while (isspace((unsigned char)*pszParmName)) {
1722 name = strdup(pszParmName);
1723 if (!name) return False;
1728 data = Globals.param_opt;
1730 data = ServicePtrs[snum]->param_opt;
1733 /* Traverse destination */
1734 for (paramo=data; paramo; paramo=paramo->next) {
1735 /* If we already have the option set, override it unless
1736 it was a command line option and the new one isn't */
1737 if (strcmp(paramo->key, name) == 0) {
1738 if ((paramo->flags & FLAG_CMDLINE) &&
1739 !(flags & FLAG_CMDLINE)) {
1743 free(paramo->value);
1744 paramo->value = strdup(pszParmValue);
1745 paramo->flags = flags;
1751 paramo = malloc_p(struct param_opt);
1754 paramo->key = strdup(name);
1755 paramo->value = strdup(pszParmValue);
1756 paramo->flags = flags;
1758 DLIST_ADD(Globals.param_opt, paramo);
1760 DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
1768 /***************************************************************************
1769 Process a parameter for a particular service number. If snum < 0
1770 then assume we are in the globals.
1771 ***************************************************************************/
1772 BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
1775 void *parm_ptr = NULL; /* where we are going to store the result */
1776 void *def_ptr = NULL;
1778 parmnum = map_parameter(pszParmName);
1781 if (strchr(pszParmName, ':')) {
1782 return lp_do_parameter_parametric(snum, pszParmName, pszParmValue, 0);
1784 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1788 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1789 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1793 /* if the flag has been set on the command line, then don't allow override,
1794 but don't report an error */
1795 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1799 def_ptr = parm_table[parmnum].ptr;
1801 /* we might point at a service, the default service or a global */
1805 if (parm_table[parmnum].class == P_GLOBAL) {
1807 ("Global parameter %s found in service section!\n",
1812 ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
1817 if (!ServicePtrs[snum]->copymap)
1818 init_copymap(ServicePtrs[snum]);
1820 /* this handles the aliases - set the copymap for other entries with
1821 the same data pointer */
1822 for (i = 0; parm_table[i].label; i++)
1823 if (parm_table[i].ptr == parm_table[parmnum].ptr)
1824 ServicePtrs[snum]->copymap[i] = False;
1827 /* if it is a special case then go ahead */
1828 if (parm_table[parmnum].special) {
1829 parm_table[parmnum].special(pszParmValue, (char **)parm_ptr);
1833 /* now switch on the type of variable it is */
1834 switch (parm_table[parmnum].type)
1837 set_boolean(parm_ptr, pszParmValue);
1841 *(int *)parm_ptr = atoi(pszParmValue);
1845 *(const char ***)parm_ptr = str_list_make(talloc_autofree_context(),
1846 pszParmValue, NULL);
1850 string_set(parm_ptr, pszParmValue);
1854 string_set(parm_ptr, pszParmValue);
1855 strupper(*(char **)parm_ptr);
1859 for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
1862 parm_table[parmnum].enum_list[i].name)) {
1864 parm_table[parmnum].
1869 if (!parm_table[parmnum].enum_list[i].name) {
1870 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n",
1871 pszParmValue, pszParmName));
1882 /***************************************************************************
1883 Process a parameter.
1884 ***************************************************************************/
1886 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue, void *userdata)
1888 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
1889 pszParmName, pszParmValue));
1893 variable argument do parameter
1895 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
1897 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...)
1904 s = talloc_vasprintf(NULL, fmt, ap);
1906 ret = do_parameter(pszParmName, s, NULL);
1913 set a parameter from the commandline - this is called from command line parameter
1914 parsing code. It sets the parameter then marks the parameter as unable to be modified
1915 by smb.conf processing
1917 BOOL lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
1919 int parmnum = map_parameter(pszParmName);
1922 while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
1925 if (parmnum < 0 && strchr(pszParmName, ':')) {
1926 /* set a parametric option */
1927 return lp_do_parameter_parametric(-1, pszParmName, pszParmValue, FLAG_CMDLINE);
1931 DEBUG(0,("Unknown option '%s'\n", pszParmName));
1935 /* reset the CMDLINE flag in case this has been called before */
1936 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
1938 if (!lp_do_parameter(-2, pszParmName, pszParmValue)) {
1942 parm_table[parmnum].flags |= FLAG_CMDLINE;
1944 /* we have to also set FLAG_CMDLINE on aliases */
1945 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1946 parm_table[i].flags |= FLAG_CMDLINE;
1948 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1949 parm_table[i].flags |= FLAG_CMDLINE;
1956 set a option from the commandline in 'a=b' format. Use to support --option
1958 BOOL lp_set_option(const char *option)
1976 ret = lp_set_cmdline(s, p+1);
1982 #define BOOLSTR(b) ((b) ? "Yes" : "No")
1984 /***************************************************************************
1985 Print a parameter of the specified type.
1986 ***************************************************************************/
1988 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
1994 for (i = 0; p->enum_list[i].name; i++) {
1995 if (*(int *)ptr == p->enum_list[i].value) {
1997 p->enum_list[i].name);
2004 fprintf(f, "%s", BOOLSTR(*(BOOL *)ptr));
2008 fprintf(f, "%d", *(int *)ptr);
2012 if ((char ***)ptr && *(char ***)ptr) {
2013 char **list = *(char ***)ptr;
2015 for (; *list; list++)
2016 fprintf(f, "%s%s", *list,
2017 ((*(list+1))?", ":""));
2023 if (*(char **)ptr) {
2024 fprintf(f, "%s", *(char **)ptr);
2032 /***************************************************************************
2033 Check if two parameters are equal.
2034 ***************************************************************************/
2036 static BOOL equal_parameter(parm_type type, void *ptr1, void *ptr2)
2040 return (*((BOOL *)ptr1) == *((BOOL *)ptr2));
2044 return (*((int *)ptr1) == *((int *)ptr2));
2047 return str_list_equal((const char **)(*(char ***)ptr1),
2048 (const char **)(*(char ***)ptr2));
2053 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
2058 return (p1 == p2 || strequal(p1, p2));
2066 /***************************************************************************
2067 Process a new section (service). At this stage all sections are services.
2068 Later we'll have special sections that permit server parameters to be set.
2069 Returns True on success, False on failure.
2070 ***************************************************************************/
2072 static BOOL do_section(const char *pszSectionName, void *userdata)
2075 BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2076 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2079 /* if we've just struck a global section, note the fact. */
2080 bInGlobalSection = isglobal;
2082 /* check for multiple global sections */
2083 if (bInGlobalSection) {
2084 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2088 /* if we have a current service, tidy it up before moving on */
2091 if (iServiceIndex >= 0)
2092 bRetval = service_ok(iServiceIndex);
2094 /* if all is still well, move to the next record in the services array */
2096 /* We put this here to avoid an odd message order if messages are */
2097 /* issued by the post-processing of a previous section. */
2098 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2100 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
2102 DEBUG(0, ("Failed to add a new service\n"));
2111 /***************************************************************************
2112 Determine if a partcular base parameter is currentl set to the default value.
2113 ***************************************************************************/
2115 static BOOL is_default(int i)
2117 if (!defaults_saved)
2119 switch (parm_table[i].type) {
2121 return str_list_equal((const char **)parm_table[i].def.lvalue,
2122 (const char **)(*(char ***)parm_table[i].ptr));
2125 return strequal(parm_table[i].def.svalue,
2126 *(char **)parm_table[i].ptr);
2128 return parm_table[i].def.bvalue ==
2129 *(BOOL *)parm_table[i].ptr;
2132 return parm_table[i].def.ivalue ==
2133 *(int *)parm_table[i].ptr;
2140 /***************************************************************************
2141 Display the contents of the global structure.
2142 ***************************************************************************/
2144 static void dump_globals(FILE *f)
2147 struct param_opt *data;
2149 fprintf(f, "# Global parameters\n[global]\n");
2151 for (i = 0; parm_table[i].label; i++)
2152 if (parm_table[i].class == P_GLOBAL &&
2153 parm_table[i].ptr &&
2154 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2155 if (defaults_saved && is_default(i))
2157 fprintf(f, "\t%s = ", parm_table[i].label);
2158 print_parameter(&parm_table[i], parm_table[i].ptr, f);
2161 if (Globals.param_opt != NULL) {
2162 data = Globals.param_opt;
2164 fprintf(f, "\t%s = %s\n", data->key, data->value);
2171 /***************************************************************************
2172 Display the contents of a single services record.
2173 ***************************************************************************/
2175 static void dump_a_service(service * pService, FILE * f)
2178 struct param_opt *data;
2180 if (pService != &sDefault)
2181 fprintf(f, "\n[%s]\n", pService->szService);
2183 for (i = 0; parm_table[i].label; i++)
2184 if (parm_table[i].class == P_LOCAL &&
2185 parm_table[i].ptr &&
2186 (*parm_table[i].label != '-') &&
2187 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2188 int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
2190 if (pService == &sDefault) {
2191 if (defaults_saved && is_default(i))
2194 if (equal_parameter(parm_table[i].type,
2195 ((char *)pService) +
2197 ((char *)&sDefault) +
2202 fprintf(f, "\t%s = ", parm_table[i].label);
2203 print_parameter(&parm_table[i],
2204 ((char *)pService) + pdiff, f);
2207 if (pService->param_opt != NULL) {
2208 data = pService->param_opt;
2210 fprintf(f, "\t%s = %s\n", data->key, data->value);
2217 /***************************************************************************
2218 Return info about the next service in a service. snum==-1 gives the globals.
2219 Return NULL when out of parameters.
2220 ***************************************************************************/
2222 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
2225 /* do the globals */
2226 for (; parm_table[*i].label; (*i)++) {
2227 if (parm_table[*i].class == P_SEPARATOR)
2228 return &parm_table[(*i)++];
2230 if (!parm_table[*i].ptr
2231 || (*parm_table[*i].label == '-'))
2235 && (parm_table[*i].ptr ==
2236 parm_table[(*i) - 1].ptr))
2239 return &parm_table[(*i)++];
2242 service *pService = ServicePtrs[snum];
2244 for (; parm_table[*i].label; (*i)++) {
2245 if (parm_table[*i].class == P_SEPARATOR)
2246 return &parm_table[(*i)++];
2248 if (parm_table[*i].class == P_LOCAL &&
2249 parm_table[*i].ptr &&
2250 (*parm_table[*i].label != '-') &&
2252 (parm_table[*i].ptr !=
2253 parm_table[(*i) - 1].ptr)))
2256 PTR_DIFF(parm_table[*i].ptr,
2259 if (allparameters ||
2260 !equal_parameter(parm_table[*i].type,
2261 ((char *)pService) +
2263 ((char *)&sDefault) +
2266 return &parm_table[(*i)++];
2276 /***************************************************************************
2277 Return TRUE if the passed service number is within range.
2278 ***************************************************************************/
2280 BOOL lp_snum_ok(int iService)
2282 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
2285 /***************************************************************************
2286 Auto-load some home services.
2287 ***************************************************************************/
2289 static void lp_add_auto_services(const char *str)
2294 /***************************************************************************
2295 Announce ourselves as a print server.
2296 ***************************************************************************/
2298 void update_server_announce_as_printserver(void)
2300 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
2303 /***************************************************************************
2304 Have we loaded a services file yet?
2305 ***************************************************************************/
2307 BOOL lp_loaded(void)
2312 /***************************************************************************
2313 Unload unused services.
2314 ***************************************************************************/
2316 void lp_killunused(struct smbsrv_connection *smb, BOOL (*snumused) (struct smbsrv_connection *, int))
2319 for (i = 0; i < iNumServices; i++) {
2323 if (!snumused || !snumused(smb, i)) {
2324 ServicePtrs[i]->valid = False;
2325 free_service(ServicePtrs[i]);
2330 /***************************************************************************
2332 ***************************************************************************/
2334 void lp_killservice(int iServiceIn)
2336 if (VALID(iServiceIn)) {
2337 ServicePtrs[iServiceIn]->valid = False;
2338 free_service(ServicePtrs[iServiceIn]);
2342 /***************************************************************************
2343 Load the services array from the services file. Return True on success,
2345 ***************************************************************************/
2351 struct param_opt *data;
2355 bInGlobalSection = True;
2357 if (Globals.param_opt != NULL) {
2358 struct param_opt *next;
2359 for (data=Globals.param_opt; data; data=next) {
2361 if (data->flags & FLAG_CMDLINE) continue;
2364 DLIST_REMOVE(Globals.param_opt, data);
2371 pstrcpy(n2, lp_configfile());
2372 standard_sub_basic(n2,sizeof(n2));
2373 DEBUG(2, ("lp_load: refreshing parameters from %s\n", n2));
2375 add_to_file_list(lp_configfile(), n2);
2377 /* We get sections first, so have to start 'behind' to make up */
2379 bRetval = pm_process(n2, do_section, do_parameter, NULL);
2381 /* finish up the last section */
2382 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
2384 if (iServiceIndex >= 0)
2385 bRetval = service_ok(iServiceIndex);
2387 lp_add_auto_services(lp_auto_services());
2389 lp_add_hidden("IPC$", "IPC");
2390 lp_add_hidden("ADMIN$", "DISK");
2392 set_default_server_announce_type();
2396 if (Globals.bWINSsupport) {
2397 lp_do_parameter(-1, "wins server", "127.0.0.1");
2405 /***************************************************************************
2406 Reset the max number of services.
2407 ***************************************************************************/
2409 void lp_resetnumservices(void)
2414 /***************************************************************************
2415 Return the max number of services.
2416 ***************************************************************************/
2418 int lp_numservices(void)
2420 return (iNumServices);
2423 /***************************************************************************
2424 Display the contents of the services array in human-readable form.
2425 ***************************************************************************/
2427 void lp_dump(FILE *f, BOOL show_defaults, int maxtoprint)
2432 defaults_saved = False;
2436 dump_a_service(&sDefault, f);
2438 for (iService = 0; iService < maxtoprint; iService++)
2439 lp_dump_one(f, show_defaults, iService);
2442 /***************************************************************************
2443 Display the contents of one service in human-readable form.
2444 ***************************************************************************/
2446 void lp_dump_one(FILE * f, BOOL show_defaults, int snum)
2449 if (ServicePtrs[snum]->szService[0] == '\0')
2451 dump_a_service(ServicePtrs[snum], f);
2455 /***************************************************************************
2456 Return the number of the service with the given name, or -1 if it doesn't
2457 exist. Note that this is a DIFFERENT ANIMAL from the internal function
2458 getservicebyname()! This works ONLY if all services have been loaded, and
2459 does not copy the found service.
2460 ***************************************************************************/
2462 int lp_servicenumber(const char *pszServiceName)
2465 fstring serviceName;
2468 for (iService = iNumServices - 1; iService >= 0; iService--) {
2469 if (VALID(iService) && ServicePtrs[iService]->szService) {
2471 * The substitution here is used to support %U is
2474 fstrcpy(serviceName, ServicePtrs[iService]->szService);
2475 standard_sub_basic(serviceName,sizeof(serviceName));
2476 if (strequal(serviceName, pszServiceName))
2482 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
2487 /*******************************************************************
2488 A useful volume label function.
2489 ********************************************************************/
2490 const char *volume_label(int snum)
2492 const char *ret = lp_volume(snum);
2494 return lp_servicename(snum);
2499 /*******************************************************************
2500 Set the server type we will announce as via nmbd.
2501 ********************************************************************/
2503 static void set_default_server_announce_type(void)
2505 default_server_announce = 0;
2506 default_server_announce |= SV_TYPE_WORKSTATION;
2507 default_server_announce |= SV_TYPE_SERVER;
2508 default_server_announce |= SV_TYPE_SERVER_UNIX;
2510 switch (lp_announce_as()) {
2511 case ANNOUNCE_AS_NT_SERVER:
2512 default_server_announce |= SV_TYPE_SERVER_NT;
2513 /* fall through... */
2514 case ANNOUNCE_AS_NT_WORKSTATION:
2515 default_server_announce |= SV_TYPE_NT;
2517 case ANNOUNCE_AS_WIN95:
2518 default_server_announce |= SV_TYPE_WIN95_PLUS;
2520 case ANNOUNCE_AS_WFW:
2521 default_server_announce |= SV_TYPE_WFW;
2527 switch (lp_server_role()) {
2528 case ROLE_DOMAIN_MEMBER:
2529 default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
2531 case ROLE_DOMAIN_PDC:
2532 default_server_announce |= SV_TYPE_DOMAIN_CTRL;
2534 case ROLE_DOMAIN_BDC:
2535 default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
2537 case ROLE_STANDALONE:
2541 if (lp_time_server())
2542 default_server_announce |= SV_TYPE_TIME_SOURCE;
2544 if (lp_host_msdfs())
2545 default_server_announce |= SV_TYPE_DFS_SERVER;
2547 /* TODO: only announce us as print server when we are a print server */
2548 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
2551 /***********************************************************
2552 If we are PDC then prefer us as DMB
2553 ************************************************************/
2555 BOOL lp_domain_master(void)
2557 return (lp_server_role() == ROLE_DOMAIN_PDC);
2560 /***********************************************************
2561 If we are PDC then prefer us as DMB
2562 ************************************************************/
2564 BOOL lp_domain_logons(void)
2566 return (lp_server_role() == ROLE_DOMAIN_PDC) || (lp_server_role() == ROLE_DOMAIN_BDC);
2569 /***********************************************************
2570 If we are DMB then prefer us as LMB
2571 ************************************************************/
2573 BOOL lp_preferred_master(void)
2575 return (lp_local_master() && lp_domain_master());
2578 /*******************************************************************
2580 ********************************************************************/
2582 void lp_remove_service(int snum)
2584 ServicePtrs[snum]->valid = False;
2587 /*******************************************************************
2589 ********************************************************************/
2591 void lp_copy_service(int snum, const char *new_name)
2593 const char *oldname = lp_servicename(snum);
2594 do_section(new_name, NULL);
2596 snum = lp_servicenumber(new_name);
2598 lp_do_parameter(snum, "copy", oldname);
2603 /*******************************************************************
2604 Get the default server type we will announce as via nmbd.
2605 ********************************************************************/
2606 int lp_default_server_announce(void)
2608 return default_server_announce;
2611 const char *lp_printername(int snum)
2613 const char *ret = _lp_printername(snum);
2614 if (ret == NULL || (ret != NULL && *ret == '\0'))
2615 ret = lp_const_servicename(snum);
2621 /*******************************************************************
2622 Return the max print jobs per queue.
2623 ********************************************************************/
2625 int lp_maxprintjobs(int snum)
2627 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
2628 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
2629 maxjobs = PRINT_MAX_JOBID - 1;