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
58 #include "dynconfig.h"
60 #include "system/time.h"
61 #include "system/iconv.h"
62 #include "librpc/gen_ndr/ndr_svcctl.h"
63 #include "librpc/gen_ndr/ndr_samr.h"
64 #include "dlinklist.h"
65 #include "param/loadparm.h"
67 static BOOL bLoaded = False;
69 /* some helpful bits */
70 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && ServicePtrs[(i)]->valid)
71 #define VALID(i) ServicePtrs[i]->valid
73 static BOOL do_parameter(const char *, const char *, void *);
74 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...);
76 static BOOL defaults_saved = False;
80 struct param_opt *prev, *next;
87 * This structure describes global (ie., server-wide) parameters.
97 char *display_charset;
101 char *szServerString;
102 char *szAutoServices;
108 char *szWINS_CONFIG_URL;
112 char **szPasswordServers;
113 char *szSocketOptions;
115 char **szWINSservers;
117 char *szSocketAddress;
118 char *szAnnounceVersion; /* This is initialised in init_globals */
121 char **szNetbiosAliases;
122 char *szNetbiosScope;
123 char *szDomainOtherSIDs;
124 char **szNameResolveOrder;
126 char **dcerpc_ep_servers;
127 char **server_services;
128 char *ntptr_providor;
129 char *szWinbindSeparator;
130 BOOL bWinbindSealedPipes;
131 char *swat_directory;
144 BOOL paranoid_server_security;
147 int announce_as; /* This is initialised in init_globals */
154 char *socket_options;
158 BOOL bPreferredMaster;
159 BOOL bEncryptPasswords;
161 BOOL bObeyPamRestrictions;
162 BOOL bLargeReadwrite;
166 BOOL bBindInterfacesOnly;
168 BOOL bNTStatusSupport;
174 BOOL bClientPlaintextAuth;
175 BOOL bClientLanManAuth;
176 BOOL bClientNTLMv2Auth;
177 BOOL client_use_spnego_principal;
180 BOOL bUnixExtensions;
181 BOOL bDisableNetbios;
183 struct param_opt *param_opt;
187 static global Globals;
190 * This structure describes a single service.
205 char **ntvfs_handler;
221 struct param_opt *param_opt;
223 char dummy[3]; /* for alignment */
228 /* This is a default service used to prime a services structure */
229 static service sDefault = {
231 NULL, /* szService */
234 NULL, /* szInclude */
235 NULL, /* szPrintername */
236 NULL, /* szHostsallow */
237 NULL, /* szHostsdeny */
241 NULL, /* ntvfs_handler */
242 1000, /* iMaxPrintJobs */
243 0, /* iMaxConnections */
245 True, /* bAvailable */
246 True, /* bBrowseable */
247 True, /* bRead_only */
248 False, /* bPrint_ok */
249 False, /* bMap_system */
250 False, /* bMap_hidden */
251 True, /* bMap_archive */
252 True, /* bStrictLocking */
254 False, /* bMSDfsRoot */
255 False, /* bStrictSync */
256 False, /* bCIFileSystem */
257 NULL, /* Parametric options */
262 /* local variables */
263 static service **ServicePtrs = NULL;
264 static int iNumServices = 0;
265 static int iServiceIndex = 0;
266 static BOOL bInGlobalSection = True;
267 static int default_server_announce;
269 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
271 /* prototypes for the special type handlers */
272 static BOOL handle_include(const char *pszParmValue, char **ptr);
273 static BOOL handle_copy(const char *pszParmValue, char **ptr);
275 static void set_default_server_announce_type(void);
277 static const struct enum_list enum_protocol[] = {
278 {PROTOCOL_NT1, "NT1"},
279 {PROTOCOL_LANMAN2, "LANMAN2"},
280 {PROTOCOL_LANMAN1, "LANMAN1"},
281 {PROTOCOL_CORE, "CORE"},
282 {PROTOCOL_COREPLUS, "COREPLUS"},
283 {PROTOCOL_COREPLUS, "CORE+"},
287 static const struct enum_list enum_security[] = {
288 {SEC_SHARE, "SHARE"},
293 /* Types of machine we can announce as. */
294 #define ANNOUNCE_AS_NT_SERVER 1
295 #define ANNOUNCE_AS_WIN95 2
296 #define ANNOUNCE_AS_WFW 3
297 #define ANNOUNCE_AS_NT_WORKSTATION 4
299 static const struct enum_list enum_announce_as[] = {
300 {ANNOUNCE_AS_NT_SERVER, "NT"},
301 {ANNOUNCE_AS_NT_SERVER, "NT Server"},
302 {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"},
303 {ANNOUNCE_AS_WIN95, "win95"},
304 {ANNOUNCE_AS_WFW, "WfW"},
308 static const struct enum_list enum_bool_auto[] = {
319 /* Client-side offline caching policy types */
320 #define CSC_POLICY_MANUAL 0
321 #define CSC_POLICY_DOCUMENTS 1
322 #define CSC_POLICY_PROGRAMS 2
323 #define CSC_POLICY_DISABLE 3
325 static const struct enum_list enum_csc_policy[] = {
326 {CSC_POLICY_MANUAL, "manual"},
327 {CSC_POLICY_DOCUMENTS, "documents"},
328 {CSC_POLICY_PROGRAMS, "programs"},
329 {CSC_POLICY_DISABLE, "disable"},
333 /* SMB signing types. */
334 static const struct enum_list enum_smb_signing_vals[] = {
335 {SMB_SIGNING_OFF, "No"},
336 {SMB_SIGNING_OFF, "False"},
337 {SMB_SIGNING_OFF, "0"},
338 {SMB_SIGNING_OFF, "Off"},
339 {SMB_SIGNING_OFF, "disabled"},
340 {SMB_SIGNING_SUPPORTED, "Yes"},
341 {SMB_SIGNING_SUPPORTED, "True"},
342 {SMB_SIGNING_SUPPORTED, "1"},
343 {SMB_SIGNING_SUPPORTED, "On"},
344 {SMB_SIGNING_SUPPORTED, "enabled"},
345 {SMB_SIGNING_REQUIRED, "required"},
346 {SMB_SIGNING_REQUIRED, "mandatory"},
347 {SMB_SIGNING_REQUIRED, "force"},
348 {SMB_SIGNING_REQUIRED, "forced"},
349 {SMB_SIGNING_REQUIRED, "enforced"},
350 {SMB_SIGNING_AUTO, "auto"},
354 static const struct enum_list enum_server_role[] = {
355 {ROLE_STANDALONE, "standalone"},
356 {ROLE_DOMAIN_MEMBER, "member server"},
357 {ROLE_DOMAIN_BDC, "bdc"},
358 {ROLE_DOMAIN_PDC, "pdc"},
363 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
365 * Note: We have a flag called FLAG_DEVELOPER but is not used at this time, it
366 * is implied in current control logic. This may change at some later time. A
367 * flag value of 0 means - show as development option only.
369 * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
370 * screen in SWAT. This is used to exclude parameters as well as to squash all
371 * parameters that have been duplicated by pseudonyms.
373 static struct parm_struct parm_table[] = {
374 {"Base Options", P_SEP, P_SEPARATOR},
376 {"server role", P_ENUM, P_GLOBAL, &Globals.server_role, NULL, enum_server_role, FLAG_BASIC},
378 {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
379 {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
380 {"ncalrpc dir", P_STRING, P_GLOBAL, &Globals.ncalrpc_dir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
381 {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
382 {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
383 {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
384 {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE},
385 {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkgroup, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
386 {"realm", P_STRING, P_GLOBAL, &Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
387 {"netbios name", P_USTRING, P_GLOBAL, &Globals.szNetbiosName, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
388 {"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
389 {"netbios scope", P_USTRING, P_GLOBAL, &Globals.szNetbiosScope, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
390 {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
391 {"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
392 {"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
393 {"ntvfs handler", P_LIST, P_LOCAL, &sDefault.ntvfs_handler, NULL, NULL, FLAG_ADVANCED},
394 {"ntptr providor", P_STRING, P_GLOBAL, &Globals.ntptr_providor, NULL, NULL, FLAG_ADVANCED},
395 {"dcerpc endpoint servers", P_LIST, P_GLOBAL, &Globals.dcerpc_ep_servers, NULL, NULL, FLAG_ADVANCED},
396 {"server services", P_LIST, P_GLOBAL, &Globals.server_services, NULL, NULL, FLAG_ADVANCED},
398 {"Security Options", P_SEP, P_SEPARATOR},
400 {"security", P_ENUM, P_GLOBAL, &Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
401 {"auth methods", P_LIST, P_GLOBAL, &Globals.AuthMethods, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
402 {"encrypt passwords", P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
403 {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
404 {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
405 {"password server", P_LIST, P_GLOBAL, &Globals.szPasswordServers, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
406 {"sam database", P_STRING, P_GLOBAL, &Globals.szSAM_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
407 {"spoolss database", P_STRING, P_GLOBAL, &Globals.szSPOOLSS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
408 {"wins config database", P_STRING, P_GLOBAL, &Globals.szWINS_CONFIG_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
409 {"wins database", P_STRING, P_GLOBAL, &Globals.szWINS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
410 {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
411 {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
412 {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
413 {"lanman auth", P_BOOL, P_GLOBAL, &Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
414 {"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
415 {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
416 {"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
417 {"client plaintext auth", P_BOOL, P_GLOBAL, &Globals.bClientPlaintextAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
418 {"client use spnego principal", P_BOOL, P_GLOBAL, &Globals.client_use_spnego_principal, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
420 {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE},
422 {"hosts allow", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
423 {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
425 {"Logging Options", P_SEP, P_SEPARATOR},
427 {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
428 {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_HIDE},
429 {"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
431 {"Protocol Options", P_SEP, P_SEPARATOR},
433 {"smb ports", P_LIST, P_GLOBAL, &Globals.smb_ports, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
434 {"nbt port", P_INTEGER, P_GLOBAL, &Globals.nbt_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
435 {"dgram port", P_INTEGER, P_GLOBAL, &Globals.dgram_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
436 {"cldap port", P_INTEGER, P_GLOBAL, &Globals.cldap_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
437 {"krb5 port", P_INTEGER, P_GLOBAL, &Globals.krb5_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
438 {"kpasswd port", P_INTEGER, P_GLOBAL, &Globals.kpasswd_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
439 {"web port", P_INTEGER, P_GLOBAL, &Globals.web_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
440 {"tls enabled", P_BOOL, P_GLOBAL, &Globals.tls_enabled, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
441 {"tls keyfile", P_STRING, P_GLOBAL, &Globals.tls_keyfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
442 {"tls certfile", P_STRING, P_GLOBAL, &Globals.tls_certfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
443 {"tls cafile", P_STRING, P_GLOBAL, &Globals.tls_cafile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
444 {"tls crlfile", P_STRING, P_GLOBAL, &Globals.tls_crlfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
445 {"swat directory", P_STRING, P_GLOBAL, &Globals.swat_directory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
446 {"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, FLAG_DEVELOPER},
447 {"max protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
448 {"min protocol", P_ENUM, P_GLOBAL, &Globals.minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
449 {"unicode", P_BOOL, P_GLOBAL, &Globals.bUnicode, NULL, NULL, FLAG_DEVELOPER},
450 {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL, NULL, FLAG_DEVELOPER},
451 {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL, NULL, FLAG_DEVELOPER},
452 {"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
454 {"nt status support", P_BOOL, P_GLOBAL, &Globals.bNTStatusSupport, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
456 {"announce version", P_STRING, P_GLOBAL, &Globals.szAnnounceVersion, NULL, NULL, FLAG_DEVELOPER},
457 {"announce as", P_ENUM, P_GLOBAL, &Globals.announce_as, NULL, enum_announce_as, FLAG_DEVELOPER},
458 {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
459 {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
461 {"name resolve order", P_LIST, P_GLOBAL, &Globals.szNameResolveOrder, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
462 {"max wins ttl", P_INTEGER, P_GLOBAL, &Globals.max_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
463 {"min wins ttl", P_INTEGER, P_GLOBAL, &Globals.min_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
464 {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
465 {"unix extensions", P_BOOL, P_GLOBAL, &Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
466 {"use spnego", P_BOOL, P_GLOBAL, &Globals.bUseSpnego, NULL, NULL, FLAG_DEVELOPER},
467 {"server signing", P_ENUM, P_GLOBAL, &Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
468 {"client signing", P_ENUM, P_GLOBAL, &Globals.client_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
469 {"rpc big endian", P_BOOL, P_GLOBAL, &Globals.bRpcBigEndian, NULL, NULL, FLAG_DEVELOPER},
471 {"Tuning Options", P_SEP, P_SEPARATOR},
473 {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL, NULL, FLAG_SHARE},
474 {"paranoid server security", P_BOOL, P_GLOBAL, &Globals.paranoid_server_security, NULL, NULL, FLAG_DEVELOPER},
475 {"socket options", P_STRING, P_GLOBAL, &Globals.socket_options, NULL, NULL, FLAG_DEVELOPER},
477 {"strict sync", P_BOOL, P_LOCAL, &sDefault.bStrictSync, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
478 {"case insensitive filesystem", P_BOOL, P_LOCAL, &sDefault.bCIFileSystem, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
480 {"Printing Options", P_SEP, P_SEPARATOR},
482 {"max print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxPrintJobs, NULL, NULL, FLAG_PRINT},
483 {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_PRINT},
484 {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_HIDE},
486 {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_PRINT},
487 {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_HIDE},
489 {"Filename Handling", P_SEP, P_SEPARATOR},
491 {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
492 {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
493 {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
495 {"Domain Options", P_SEP, P_SEPARATOR},
497 {"Logon Options", P_SEP, P_SEPARATOR},
500 {"Browse Options", P_SEP, P_SEPARATOR},
502 {"preferred master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
503 {"prefered master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_HIDE},
504 {"local master", P_BOOL, P_GLOBAL, &Globals.bLocalMaster, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
505 {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
506 {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_HIDE},
508 {"WINS Options", P_SEP, P_SEPARATOR},
510 {"wins server", P_LIST, P_GLOBAL, &Globals.szWINSservers, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
511 {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
512 {"dns proxy", P_BOOL, P_GLOBAL, &Globals.bWINSdnsProxy, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
514 {"Locking Options", P_SEP, P_SEPARATOR},
516 {"csc policy", P_ENUM, P_LOCAL, &sDefault.iCSCPolicy, NULL, enum_csc_policy, FLAG_SHARE | FLAG_GLOBAL},
518 {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
520 {"Miscellaneous Options", P_SEP, P_SEPARATOR},
522 {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE},
523 {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
524 {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
525 {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_HIDE},
526 {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
527 {"pid directory", P_STRING, P_GLOBAL, &Globals.szPidDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
528 {"js include", P_LIST, P_GLOBAL, &Globals.jsInclude, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
529 {"setup directory", P_STRING, P_GLOBAL, &Globals.szSetupDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
531 {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL, NULL, FLAG_DEVELOPER},
532 {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL, NULL, FLAG_HIDE},
534 {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy, NULL, FLAG_HIDE},
535 {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include, NULL, FLAG_HIDE},
537 {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
538 {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_SHARE },
539 {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_SHARE},
541 {"panic action", P_STRING, P_GLOBAL, &Globals.szPanicAction, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
543 {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_SHARE},
544 {"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
545 {"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
546 {"winbind sealed pipes", P_BOOL, P_GLOBAL, &Globals.bWinbindSealedPipes, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
548 {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
553 return the parameter table
555 struct parm_struct *lp_parm_table(void)
560 /***************************************************************************
561 Initialise the global parameter structure.
562 ***************************************************************************/
563 static void init_globals(void)
568 DEBUG(3, ("Initialising global parameters\n"));
570 for (i = 0; parm_table[i].label; i++) {
571 if ((parm_table[i].type == P_STRING ||
572 parm_table[i].type == P_USTRING) &&
574 !(parm_table[i].flags & FLAG_CMDLINE)) {
575 string_set(parm_table[i].ptr, "");
579 do_parameter("config file", dyn_CONFIGFILE, NULL);
581 do_parameter("server role", "standalone", NULL);
583 /* options that can be set on the command line must be initialised via
584 the slower do_parameter() to ensure that FLAG_CMDLINE is obeyed */
586 do_parameter("socket options", "TCP_NODELAY", NULL);
588 do_parameter("workgroup", DEFAULT_WORKGROUP, NULL);
589 myname = get_myname();
590 do_parameter("netbios name", myname, NULL);
592 do_parameter("max protocol", "NT1", NULL);
593 do_parameter("name resolve order", "lmhosts wins host bcast", NULL);
595 do_parameter("fstype", FSTYPE_STRING, NULL);
596 do_parameter("ntvfs handler", "unixuid default", NULL);
597 do_parameter("max connections", "-1", NULL);
599 do_parameter("dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup", NULL);
600 do_parameter("server services", "smb rpc nbt wrepl ldap cldap web kdc", NULL);
601 do_parameter("ntptr providor", "simple_ldb", NULL);
602 do_parameter("auth methods", "anonymous sam_ignoredomain", NULL);
603 do_parameter("private dir", dyn_PRIVATE_DIR, NULL);
604 do_parameter("sam database", "sam.ldb", NULL);
605 do_parameter("spoolss database", "spoolss.ldb", NULL);
606 do_parameter("wins config database", "wins_config.ldb", NULL);
607 do_parameter("wins database", "wins.ldb", NULL);
608 do_parameter("registry:HKEY_LOCAL_MACHINE", "hklm.ldb", NULL);
610 /* This hive should be dynamically generated by Samba using
611 data from the sam, but for the moment leave it in a tdb to
612 keep regedt32 from popping up an annoying dialog. */
613 do_parameter("registry:HKEY_USERS", "hku.ldb", NULL);
615 /* using UTF8 by default allows us to support all chars */
616 do_parameter("unix charset", "UTF8", NULL);
618 /* Use codepage 850 as a default for the dos character set */
619 do_parameter("dos charset", "CP850", NULL);
622 * Allow the default PASSWD_CHAT to be overridden in local.h.
624 do_parameter("passwd chat", DEFAULT_PASSWD_CHAT, NULL);
626 do_parameter("pid directory", dyn_PIDDIR, NULL);
627 do_parameter("lock dir", dyn_LOCKDIR, NULL);
628 do_parameter("ncalrpc dir", dyn_NCALRPCDIR, NULL);
630 do_parameter("socket address", "0.0.0.0", NULL);
631 do_parameter_var("server string", "Samba %s", SAMBA_VERSION_STRING);
633 do_parameter_var("announce version", "%d.%d",
634 DEFAULT_MAJOR_VERSION,
635 DEFAULT_MINOR_VERSION);
637 do_parameter("password server", "*", NULL);
639 do_parameter("max mux", "50", NULL);
640 do_parameter("max xmit", "12288", NULL);
641 do_parameter("password level", "0", NULL);
642 do_parameter("LargeReadwrite", "True", NULL);
643 do_parameter("minprotocol", "CORE", NULL);
644 do_parameter("security", "USER", NULL);
645 do_parameter("paranoid server security", "True", NULL);
646 do_parameter("EncryptPasswords", "True", NULL);
647 do_parameter("ReadRaw", "True", NULL);
648 do_parameter("WriteRaw", "True", NULL);
649 do_parameter("NullPasswords", "False", NULL);
650 do_parameter("ObeyPamRestrictions", "False", NULL);
651 do_parameter("announce as", "NT SERVER", NULL);
653 do_parameter("TimeServer", "False", NULL);
654 do_parameter("BindInterfacesOnly", "False", NULL);
655 do_parameter("Unicode", "True", NULL);
656 do_parameter("ClientLanManAuth", "True", NULL);
657 do_parameter("LanmanAuth", "True", NULL);
658 do_parameter("NTLMAuth", "True", NULL);
659 do_parameter("client use spnego principal", "False", NULL);
661 do_parameter("UnixExtensions", "False", NULL);
663 do_parameter("PreferredMaster", "Auto", NULL);
664 do_parameter("LocalMaster", "True", NULL);
666 do_parameter("wins support", "False", NULL);
667 do_parameter("dns proxy", "True", NULL);
669 do_parameter("winbind separator", "\\", NULL);
670 do_parameter("winbind sealed pipes", "True", NULL);
672 do_parameter("client signing", "Yes", NULL);
673 do_parameter("server signing", "auto", NULL);
675 do_parameter("use spnego", "True", NULL);
677 do_parameter("smb ports", SMB_PORTS, NULL);
678 do_parameter("nbt port", "137", NULL);
679 do_parameter("dgram port", "138", NULL);
680 do_parameter("cldap port", "389", NULL);
681 do_parameter("krb5 port", "88", NULL);
682 do_parameter("kpasswd port", "464", NULL);
683 do_parameter("web port", "901", NULL);
684 do_parameter("swat directory", dyn_SWATDIR, NULL);
686 do_parameter("nt status support", "True", NULL);
688 do_parameter("max wins ttl", "518400", NULL); /* 6 days */
689 do_parameter("min wins ttl", "10", NULL);
691 do_parameter("tls enabled", "True", NULL);
692 do_parameter("tls keyfile", "tls/key.pem", NULL);
693 do_parameter("tls certfile", "tls/cert.pem", NULL);
694 do_parameter("tls cafile", "tls/ca.pem", NULL);
695 do_parameter_var("js include", "%s/js", dyn_LIBDIR);
696 do_parameter_var("setup directory", "%s/setup", dyn_LIBDIR);
698 for (i = 0; parm_table[i].label; i++) {
699 if (!(parm_table[i].flags & FLAG_CMDLINE)) {
700 parm_table[i].flags |= FLAG_DEFAULT;
705 static TALLOC_CTX *lp_talloc;
707 /******************************************************************* a
708 Free up temporary memory - called from the main loop.
709 ********************************************************************/
711 void lp_talloc_free(void)
715 talloc_free(lp_talloc);
719 /*******************************************************************
720 Convenience routine to grab string parameters into temporary memory
721 and run standard_sub_basic on them. The buffers can be written to by
722 callers without affecting the source string.
723 ********************************************************************/
725 static const char *lp_string(const char *s)
727 #if 0 /* until REWRITE done to make thread-safe */
728 size_t len = s ? strlen(s) : 0;
732 /* The follow debug is useful for tracking down memory problems
733 especially if you have an inner loop that is calling a lp_*()
734 function that returns a string. Perhaps this debug should be
735 present all the time? */
738 DEBUG(10, ("lp_string(%s)\n", s));
741 #if 0 /* until REWRITE done to make thread-safe */
743 lp_talloc = talloc_init("lp_talloc");
745 ret = talloc_array(lp_talloc, char, len + 100); /* leave room for substitution */
753 StrnCpy(ret, s, len);
755 if (trim_string(ret, "\"", "\"")) {
756 if (strchr(ret,'"') != NULL)
757 StrnCpy(ret, s, len);
760 standard_sub_basic(ret,len+100);
767 In this section all the functions that are used to access the
768 parameters from the rest of the program are defined
771 #define FN_GLOBAL_STRING(fn_name,ptr) \
772 const char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
773 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
774 const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");}
775 #define FN_GLOBAL_LIST(fn_name,ptr) \
776 const char **fn_name(void) {return(*(const char ***)(ptr));}
777 #define FN_GLOBAL_BOOL(fn_name,ptr) \
778 BOOL fn_name(void) {return(*(BOOL *)(ptr));}
779 #define FN_GLOBAL_CHAR(fn_name,ptr) \
780 char fn_name(void) {return(*(char *)(ptr));}
781 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
782 int fn_name(void) {return(*(int *)(ptr));}
784 #define FN_LOCAL_STRING(fn_name,val) \
785 const char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
786 #define FN_LOCAL_CONST_STRING(fn_name,val) \
787 const char *fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
788 #define FN_LOCAL_LIST(fn_name,val) \
789 const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
790 #define FN_LOCAL_BOOL(fn_name,val) \
791 BOOL fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
792 #define FN_LOCAL_CHAR(fn_name,val) \
793 char fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
794 #define FN_LOCAL_INTEGER(fn_name,val) \
795 int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
797 FN_GLOBAL_INTEGER(lp_server_role, &Globals.server_role)
798 FN_GLOBAL_LIST(lp_smb_ports, &Globals.smb_ports)
799 FN_GLOBAL_INTEGER(lp_nbt_port, &Globals.nbt_port)
800 FN_GLOBAL_INTEGER(lp_dgram_port, &Globals.dgram_port)
801 FN_GLOBAL_INTEGER(lp_cldap_port, &Globals.cldap_port)
802 FN_GLOBAL_INTEGER(lp_krb5_port, &Globals.krb5_port)
803 FN_GLOBAL_INTEGER(lp_kpasswd_port, &Globals.kpasswd_port)
804 FN_GLOBAL_INTEGER(lp_web_port, &Globals.web_port)
805 FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
806 FN_GLOBAL_STRING(lp_swat_directory, &Globals.swat_directory)
807 FN_GLOBAL_BOOL(lp_tls_enabled, &Globals.tls_enabled)
808 FN_GLOBAL_STRING(lp_tls_keyfile, &Globals.tls_keyfile)
809 FN_GLOBAL_STRING(lp_tls_certfile, &Globals.tls_certfile)
810 FN_GLOBAL_STRING(lp_tls_cafile, &Globals.tls_cafile)
811 FN_GLOBAL_STRING(lp_tls_crlfile, &Globals.tls_crlfile)
812 FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
813 FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset)
814 FN_GLOBAL_STRING(lp_logfile, &Globals.szLogFile)
815 FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
816 FN_GLOBAL_STRING(lp_sam_url, &Globals.szSAM_URL)
817 FN_GLOBAL_STRING(lp_spoolss_url, &Globals.szSPOOLSS_URL)
818 FN_GLOBAL_STRING(lp_wins_config_url, &Globals.szWINS_CONFIG_URL)
819 FN_GLOBAL_STRING(lp_wins_url, &Globals.szWINS_URL)
820 FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
821 FN_GLOBAL_BOOL(lp_winbind_sealed_pipes, &Globals.bWinbindSealedPipes)
822 FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
823 FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
824 FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
825 FN_GLOBAL_STRING(lp_setupdir, &Globals.szSetupDir)
826 FN_GLOBAL_STRING(lp_ncalrpc_dir, &Globals.ncalrpc_dir)
827 FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
828 FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, &Globals.dcerpc_ep_servers)
829 FN_GLOBAL_LIST(lp_server_services, &Globals.server_services)
830 FN_GLOBAL_STRING(lp_ntptr_providor, &Globals.ntptr_providor)
831 FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
832 FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
833 FN_GLOBAL_LIST(lp_passwordserver, &Globals.szPasswordServers)
834 FN_GLOBAL_LIST(lp_name_resolve_order, &Globals.szNameResolveOrder)
835 FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
836 FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
837 FN_GLOBAL_STRING(lp_workgroup, &Globals.szWorkgroup)
838 FN_GLOBAL_STRING(lp_netbios_name, &Globals.szNetbiosName)
839 FN_GLOBAL_STRING(lp_netbios_scope, &Globals.szNetbiosScope)
840 FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
841 FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
842 FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
843 FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
844 FN_GLOBAL_STRING(lp_panic_action, &Globals.szPanicAction)
846 FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
847 FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
848 FN_GLOBAL_BOOL(lp_wins_dns_proxy, &Globals.bWINSdnsProxy)
849 FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
850 FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
851 FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
852 FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw)
853 FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords)
854 FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions)
855 FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
856 static FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
857 FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
858 FN_GLOBAL_BOOL(lp_unicode, &Globals.bUnicode)
859 FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
860 FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
861 FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
862 FN_GLOBAL_BOOL(lp_client_plaintext_auth, &Globals.bClientPlaintextAuth)
863 FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
864 FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
865 FN_GLOBAL_BOOL(lp_client_use_spnego_principal, &Globals.client_use_spnego_principal)
866 FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
867 FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions)
868 FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
869 FN_GLOBAL_BOOL(lp_rpc_big_endian, &Globals.bRpcBigEndian)
870 FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
871 FN_GLOBAL_INTEGER(lp_min_wins_ttl, &Globals.min_wins_ttl)
872 FN_GLOBAL_INTEGER(lp_maxmux, &Globals.max_mux)
873 FN_GLOBAL_INTEGER(lp_max_xmit, &Globals.max_xmit)
874 FN_GLOBAL_INTEGER(lp_passwordlevel, &Globals.pwordlevel)
875 FN_GLOBAL_INTEGER(lp_maxprotocol, &Globals.maxprotocol)
876 FN_GLOBAL_INTEGER(lp_minprotocol, &Globals.minprotocol)
877 FN_GLOBAL_INTEGER(lp_security, &Globals.security)
878 FN_GLOBAL_LIST(lp_auth_methods, &Globals.AuthMethods)
879 FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security)
880 static FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as)
881 FN_GLOBAL_LIST(lp_js_include, &Globals.jsInclude)
884 FN_LOCAL_STRING(lp_servicename, szService)
885 FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
886 FN_LOCAL_STRING(lp_pathname, szPath)
887 static FN_LOCAL_STRING(_lp_printername, szPrintername)
888 FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
889 FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
890 FN_LOCAL_STRING(lp_comment, comment)
891 FN_LOCAL_STRING(lp_fstype, fstype)
892 static FN_LOCAL_STRING(lp_volume, volume)
893 FN_LOCAL_LIST(lp_ntvfs_handler, ntvfs_handler)
894 FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
895 FN_LOCAL_BOOL(lp_browseable, bBrowseable)
896 FN_LOCAL_BOOL(lp_readonly, bRead_only)
897 FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
898 FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
899 FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
900 FN_LOCAL_BOOL(lp_strict_locking, bStrictLocking)
901 FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
902 FN_LOCAL_BOOL(lp_ci_filesystem, bCIFileSystem)
903 FN_LOCAL_BOOL(lp_map_system, bMap_system)
904 FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
905 FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
906 FN_GLOBAL_INTEGER(lp_server_signing, &Globals.server_signing)
907 FN_GLOBAL_INTEGER(lp_client_signing, &Globals.client_signing)
909 /* local prototypes */
911 static int map_parameter(const char *pszParmName);
912 static BOOL set_boolean(BOOL *pb, const char *pszParmValue);
913 static int getservicebyname(const char *pszServiceName,
914 service * pserviceDest);
915 static void copy_service(service * pserviceDest,
916 service * pserviceSource, BOOL *pcopymapDest);
917 static BOOL service_ok(int iService);
918 static BOOL do_section(const char *pszSectionName, void *);
919 static void init_copymap(service * pservice);
921 /* This is a helper function for parametrical options support. */
922 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
923 /* Actual parametrical functions are quite simple */
924 const char *lp_get_parametric(int lookup_service, const char *type, const char *option)
927 struct param_opt *data;
929 if (lookup_service >= iNumServices) return NULL;
931 data = (lookup_service < 0) ?
932 Globals.param_opt : ServicePtrs[lookup_service]->param_opt;
934 asprintf(&vfskey, "%s:%s", type, option);
938 if (strcmp(data->key, vfskey) == 0) {
945 if (lookup_service >= 0) {
946 /* Try to fetch the same option but from globals */
947 /* but only if we are not already working with Globals */
948 data = Globals.param_opt;
950 if (strcmp(data->key, vfskey) == 0) {
964 /*******************************************************************
965 convenience routine to return int parameters.
966 ********************************************************************/
967 static int lp_int(const char *s)
971 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
975 return strtol(s, NULL, 0);
978 /*******************************************************************
979 convenience routine to return unsigned long parameters.
980 ********************************************************************/
981 static int lp_ulong(const char *s)
985 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
989 return strtoul(s, NULL, 0);
992 /*******************************************************************
993 convenience routine to return boolean parameters.
994 ********************************************************************/
995 static BOOL lp_bool(const char *s)
1000 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
1004 if (!set_boolean(&ret,s)) {
1005 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1013 /* Return parametric option from a given service. Type is a part of option before ':' */
1014 /* Parametric option has following syntax: 'Type: option = value' */
1015 /* Returned value is allocated in 'lp_talloc' context */
1017 const char *lp_parm_string(int lookup_service, const char *type, const char *option)
1019 const char *value = lp_get_parametric(lookup_service, type, option);
1022 return lp_string(value);
1027 /* Return parametric option from a given service. Type is a part of option before ':' */
1028 /* Parametric option has following syntax: 'Type: option = value' */
1029 /* Returned value is allocated in 'lp_talloc' context */
1031 const char **lp_parm_string_list(int lookup_service, const char *type, const char *option,
1032 const char *separator)
1034 const char *value = lp_get_parametric(lookup_service, type, option);
1037 return str_list_make(talloc_autofree_context(), value, separator);
1042 /* Return parametric option from a given service. Type is a part of option before ':' */
1043 /* Parametric option has following syntax: 'Type: option = value' */
1045 int lp_parm_int(int lookup_service, const char *type, const char *option, int default_v)
1047 const char *value = lp_get_parametric(lookup_service, type, option);
1050 return lp_int(value);
1055 /* Return parametric option from a given service. Type is a part of option before ':' */
1056 /* Parametric option has following syntax: 'Type: option = value' */
1058 unsigned long lp_parm_ulong(int lookup_service, const char *type, const char *option, unsigned long default_v)
1060 const char *value = lp_get_parametric(lookup_service, type, option);
1063 return lp_ulong(value);
1068 /* Return parametric option from a given service. Type is a part of option before ':' */
1069 /* Parametric option has following syntax: 'Type: option = value' */
1071 BOOL lp_parm_bool(int lookup_service, const char *type, const char *option, BOOL default_v)
1073 const char *value = lp_get_parametric(lookup_service, type, option);
1076 return lp_bool(value);
1082 /***************************************************************************
1083 Initialise a service to the defaults.
1084 ***************************************************************************/
1086 static void init_service(service * pservice)
1088 memset((char *)pservice, '\0', sizeof(service));
1089 copy_service(pservice, &sDefault, NULL);
1092 /***************************************************************************
1093 Free the dynamically allocated parts of a service struct.
1094 ***************************************************************************/
1096 static void free_service(service *pservice)
1099 struct param_opt *data, *pdata;
1103 if (pservice->szService)
1104 DEBUG(5, ("free_service: Freeing service %s\n",
1105 pservice->szService));
1107 string_free(&pservice->szService);
1108 SAFE_FREE(pservice->copymap);
1110 for (i = 0; parm_table[i].label; i++) {
1111 if ((parm_table[i].type == P_STRING ||
1112 parm_table[i].type == P_USTRING) &&
1113 parm_table[i].class == P_LOCAL) {
1114 string_free((char **)
1115 (((char *)pservice) +
1116 PTR_DIFF(parm_table[i].ptr, &sDefault)));
1117 } else if (parm_table[i].type == P_LIST &&
1118 parm_table[i].class == P_LOCAL) {
1119 char ***listp = (char ***)(((char *)pservice) +
1120 PTR_DIFF(parm_table[i].ptr, &sDefault));
1121 talloc_free(*listp);
1126 DEBUG(5,("Freeing parametrics:\n"));
1127 data = pservice->param_opt;
1129 DEBUG(5,("[%s = %s]\n", data->key, data->value));
1130 string_free(&data->key);
1131 string_free(&data->value);
1137 ZERO_STRUCTP(pservice);
1140 /***************************************************************************
1141 Add a new service to the services array initialising it with the given
1143 ***************************************************************************/
1145 static int add_a_service(const service *pservice, const char *name)
1149 int num_to_alloc = iNumServices + 1;
1150 struct param_opt *data, *pdata;
1152 tservice = *pservice;
1154 /* it might already exist */
1156 i = getservicebyname(name, NULL);
1158 /* Clean all parametric options for service */
1159 /* They will be added during parsing again */
1160 data = ServicePtrs[i]->param_opt;
1162 string_free(&data->key);
1163 string_free(&data->value);
1168 ServicePtrs[i]->param_opt = NULL;
1173 /* find an invalid one */
1174 for (i = 0; i < iNumServices; i++)
1175 if (!ServicePtrs[i]->valid)
1178 /* if not, then create one */
1179 if (i == iNumServices) {
1182 tsp = realloc_p(ServicePtrs, service *, num_to_alloc);
1185 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1190 ServicePtrs[iNumServices] = malloc_p(service);
1192 if (!ServicePtrs[iNumServices]) {
1193 DEBUG(0,("add_a_service: out of memory!\n"));
1199 free_service(ServicePtrs[i]);
1201 ServicePtrs[i]->valid = True;
1203 init_service(ServicePtrs[i]);
1204 copy_service(ServicePtrs[i], &tservice, NULL);
1206 string_set(&ServicePtrs[i]->szService, name);
1210 /***************************************************************************
1211 Add a new home service, with the specified home directory, defaults coming
1213 ***************************************************************************/
1215 BOOL lp_add_home(const char *pszHomename, int iDefaultService,
1216 const char *user, const char *pszHomedir)
1221 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1226 if (!(*(ServicePtrs[iDefaultService]->szPath))
1227 || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(-1))) {
1228 pstrcpy(newHomedir, pszHomedir);
1230 pstrcpy(newHomedir, lp_pathname(iDefaultService));
1231 string_sub(newHomedir,"%H", pszHomedir, sizeof(newHomedir));
1234 string_set(&ServicePtrs[i]->szPath, newHomedir);
1236 if (!(*(ServicePtrs[i]->comment))) {
1238 slprintf(comment, sizeof(comment) - 1,
1239 "Home directory of %s", user);
1240 string_set(&ServicePtrs[i]->comment, comment);
1242 ServicePtrs[i]->bAvailable = sDefault.bAvailable;
1243 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1245 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1251 /***************************************************************************
1252 Add a new service, based on an old one.
1253 ***************************************************************************/
1255 int lp_add_service(const char *pszService, int iDefaultService)
1257 return (add_a_service(ServicePtrs[iDefaultService], pszService));
1260 /***************************************************************************
1261 Add the IPC service.
1262 ***************************************************************************/
1264 static BOOL lp_add_hidden(const char *name, const char *fstype)
1267 int i = add_a_service(&sDefault, name);
1272 slprintf(comment, sizeof(comment) - 1,
1273 "%s Service (%s)", fstype, Globals.szServerString);
1275 string_set(&ServicePtrs[i]->szPath, tmpdir());
1276 string_set(&ServicePtrs[i]->comment, comment);
1277 string_set(&ServicePtrs[i]->fstype, fstype);
1278 ServicePtrs[i]->iMaxConnections = -1;
1279 ServicePtrs[i]->bAvailable = True;
1280 ServicePtrs[i]->bRead_only = True;
1281 ServicePtrs[i]->bPrint_ok = False;
1282 ServicePtrs[i]->bBrowseable = False;
1284 if (strcasecmp(fstype, "IPC") == 0) {
1285 lp_do_parameter(i, "ntvfs handler", "default");
1288 DEBUG(3, ("adding hidden service %s\n", name));
1293 /***************************************************************************
1294 Add a new printer service, with defaults coming from service iFrom.
1295 ***************************************************************************/
1297 BOOL lp_add_printer(const char *pszPrintername, int iDefaultService)
1299 const char *comment = "From Printcap";
1300 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1305 /* note that we do NOT default the availability flag to True - */
1306 /* we take it from the default service passed. This allows all */
1307 /* dynamic printers to be disabled by disabling the [printers] */
1308 /* entry (if/when the 'available' keyword is implemented!). */
1310 /* the printer name is set to the service name. */
1311 string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1312 string_set(&ServicePtrs[i]->comment, comment);
1313 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1314 /* Printers cannot be read_only. */
1315 ServicePtrs[i]->bRead_only = False;
1316 /* Printer services must be printable. */
1317 ServicePtrs[i]->bPrint_ok = True;
1319 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1321 update_server_announce_as_printserver();
1326 /***************************************************************************
1327 Map a parameter's string representation to something we can use.
1328 Returns False if the parameter string is not recognised, else TRUE.
1329 ***************************************************************************/
1331 static int map_parameter(const char *pszParmName)
1335 if (*pszParmName == '-')
1338 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1339 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1342 /* Warn only if it isn't parametric option */
1343 if (strchr(pszParmName, ':') == NULL)
1344 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1345 /* We do return 'fail' for parametric options as well because they are
1346 stored in different storage
1353 return the parameter structure for a parameter
1355 struct parm_struct *lp_parm_struct(const char *name)
1357 int parmnum = map_parameter(name);
1358 if (parmnum == -1) return NULL;
1359 return &parm_table[parmnum];
1363 return the parameter pointer for a parameter
1365 void *lp_parm_ptr(int snum, struct parm_struct *parm)
1370 return ((char *)ServicePtrs[snum]) + PTR_DIFF(parm->ptr, &sDefault);
1373 /***************************************************************************
1374 Set a boolean variable from the text value stored in the passed string.
1375 Returns True in success, False if the passed string does not correctly
1376 represent a boolean.
1377 ***************************************************************************/
1379 static BOOL set_boolean(BOOL *pb, const char *pszParmValue)
1384 if (strwicmp(pszParmValue, "yes") == 0 ||
1385 strwicmp(pszParmValue, "true") == 0 ||
1386 strwicmp(pszParmValue, "1") == 0)
1388 else if (strwicmp(pszParmValue, "no") == 0 ||
1389 strwicmp(pszParmValue, "False") == 0 ||
1390 strwicmp(pszParmValue, "0") == 0)
1394 ("ERROR: Badly formed boolean in configuration file: \"%s\".\n",
1401 /***************************************************************************
1402 Find a service by name. Otherwise works like get_service.
1403 ***************************************************************************/
1405 static int getservicebyname(const char *pszServiceName, service * pserviceDest)
1409 for (iService = iNumServices - 1; iService >= 0; iService--)
1410 if (VALID(iService) &&
1411 strwicmp(ServicePtrs[iService]->szService, pszServiceName) == 0) {
1412 if (pserviceDest != NULL)
1413 copy_service(pserviceDest, ServicePtrs[iService], NULL);
1420 /***************************************************************************
1421 Copy a service structure to another.
1422 If pcopymapDest is NULL then copy all fields
1423 ***************************************************************************/
1425 static void copy_service(service * pserviceDest, service * pserviceSource, BOOL *pcopymapDest)
1428 BOOL bcopyall = (pcopymapDest == NULL);
1429 struct param_opt *data, *pdata, *paramo;
1432 for (i = 0; parm_table[i].label; i++)
1433 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1434 (bcopyall || pcopymapDest[i])) {
1435 void *def_ptr = parm_table[i].ptr;
1437 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
1440 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
1443 switch (parm_table[i].type) {
1445 *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
1450 *(int *)dest_ptr = *(int *)src_ptr;
1454 string_set(dest_ptr,
1459 string_set(dest_ptr,
1461 strupper(*(char **)dest_ptr);
1464 *(const char ***)dest_ptr = str_list_copy(talloc_autofree_context(),
1465 *(const char ***)src_ptr);
1473 init_copymap(pserviceDest);
1474 if (pserviceSource->copymap)
1475 memcpy((void *)pserviceDest->copymap,
1476 (void *)pserviceSource->copymap,
1477 sizeof(BOOL) * NUMPARAMETERS);
1480 data = pserviceSource->param_opt;
1483 pdata = pserviceDest->param_opt;
1484 /* Traverse destination */
1486 /* If we already have same option, override it */
1487 if (strcmp(pdata->key, data->key) == 0) {
1488 string_free(&pdata->value);
1489 pdata->value = strdup(data->value);
1493 pdata = pdata->next;
1496 paramo = malloc_p(struct param_opt);
1499 paramo->key = strdup(data->key);
1500 paramo->value = strdup(data->value);
1501 DLIST_ADD(pserviceDest->param_opt, paramo);
1507 /***************************************************************************
1508 Check a service for consistency. Return False if the service is in any way
1509 incomplete or faulty, else True.
1510 ***************************************************************************/
1512 static BOOL service_ok(int iService)
1517 if (ServicePtrs[iService]->szService[0] == '\0') {
1518 DEBUG(0, ("The following message indicates an internal error:\n"));
1519 DEBUG(0, ("No service name in service entry.\n"));
1523 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1524 /* I can't see why you'd want a non-printable printer service... */
1525 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
1526 if (!ServicePtrs[iService]->bPrint_ok) {
1527 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
1528 ServicePtrs[iService]->szService));
1529 ServicePtrs[iService]->bPrint_ok = True;
1530 update_server_announce_as_printserver();
1532 /* [printers] service must also be non-browsable. */
1533 if (ServicePtrs[iService]->bBrowseable)
1534 ServicePtrs[iService]->bBrowseable = False;
1537 /* If a service is flagged unavailable, log the fact at level 0. */
1538 if (!ServicePtrs[iService]->bAvailable)
1539 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
1540 ServicePtrs[iService]->szService));
1545 static struct file_lists {
1546 struct file_lists *next;
1550 } *file_lists = NULL;
1552 /*******************************************************************
1553 Keep a linked list of all config files so we know when one has changed
1554 it's date and needs to be reloaded.
1555 ********************************************************************/
1557 static void add_to_file_list(const char *fname, const char *subfname)
1559 struct file_lists *f = file_lists;
1562 if (f->name && !strcmp(f->name, fname))
1568 f = malloc_p(struct file_lists);
1571 f->next = file_lists;
1572 f->name = strdup(fname);
1577 f->subfname = strdup(subfname);
1583 f->modtime = file_modtime(subfname);
1585 time_t t = file_modtime(subfname);
1591 /*******************************************************************
1592 Check if a config file has changed date.
1593 ********************************************************************/
1595 BOOL lp_file_list_changed(void)
1597 struct file_lists *f = file_lists;
1598 DEBUG(6, ("lp_file_list_changed()\n"));
1604 pstrcpy(n2, f->name);
1605 standard_sub_basic(n2,sizeof(n2));
1607 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
1608 f->name, n2, ctime(&f->modtime)));
1610 mod_time = file_modtime(n2);
1612 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
1614 ("file %s modified: %s\n", n2,
1616 f->modtime = mod_time;
1617 SAFE_FREE(f->subfname);
1618 f->subfname = strdup(n2);
1626 /***************************************************************************
1627 Handle the include operation.
1628 ***************************************************************************/
1630 static BOOL handle_include(const char *pszParmValue, char **ptr)
1633 pstrcpy(fname, pszParmValue);
1635 standard_sub_basic(fname,sizeof(fname));
1637 add_to_file_list(pszParmValue, fname);
1639 string_set(ptr, fname);
1641 if (file_exist(fname))
1642 return (pm_process(fname, do_section, do_parameter, NULL));
1644 DEBUG(2, ("Can't find include file %s\n", fname));
1649 /***************************************************************************
1650 Handle the interpretation of the copy parameter.
1651 ***************************************************************************/
1653 static BOOL handle_copy(const char *pszParmValue, char **ptr)
1657 service serviceTemp;
1659 string_set(ptr, pszParmValue);
1661 init_service(&serviceTemp);
1665 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
1667 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
1668 if (iTemp == iServiceIndex) {
1669 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
1671 copy_service(ServicePtrs[iServiceIndex],
1673 ServicePtrs[iServiceIndex]->copymap);
1677 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
1681 free_service(&serviceTemp);
1685 /***************************************************************************
1686 Initialise a copymap.
1687 ***************************************************************************/
1689 static void init_copymap(service * pservice)
1692 SAFE_FREE(pservice->copymap);
1693 pservice->copymap = malloc_array_p(BOOL, NUMPARAMETERS);
1694 if (!pservice->copymap)
1696 ("Couldn't allocate copymap!! (size %d)\n",
1697 (int)NUMPARAMETERS));
1699 for (i = 0; i < NUMPARAMETERS; i++)
1700 pservice->copymap[i] = True;
1703 /***************************************************************************
1704 Return the local pointer to a parameter given the service number and the
1705 pointer into the default structure.
1706 ***************************************************************************/
1708 void *lp_local_ptr(int snum, void *ptr)
1710 return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
1714 /***************************************************************************
1715 Process a parametric option
1716 ***************************************************************************/
1717 static BOOL lp_do_parameter_parametric(int snum, const char *pszParmName, const char *pszParmValue, int flags)
1719 struct param_opt *paramo, *data;
1722 while (isspace((unsigned char)*pszParmName)) {
1726 name = strdup(pszParmName);
1727 if (!name) return False;
1732 data = Globals.param_opt;
1734 data = ServicePtrs[snum]->param_opt;
1737 /* Traverse destination */
1738 for (paramo=data; paramo; paramo=paramo->next) {
1739 /* If we already have the option set, override it unless
1740 it was a command line option and the new one isn't */
1741 if (strcmp(paramo->key, name) == 0) {
1742 if ((paramo->flags & FLAG_CMDLINE) &&
1743 !(flags & FLAG_CMDLINE)) {
1747 free(paramo->value);
1748 paramo->value = strdup(pszParmValue);
1749 paramo->flags = flags;
1755 paramo = malloc_p(struct param_opt);
1758 paramo->key = strdup(name);
1759 paramo->value = strdup(pszParmValue);
1760 paramo->flags = flags;
1762 DLIST_ADD(Globals.param_opt, paramo);
1764 DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
1772 /***************************************************************************
1773 Process a parameter for a particular service number. If snum < 0
1774 then assume we are in the globals.
1775 ***************************************************************************/
1776 BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
1779 void *parm_ptr = NULL; /* where we are going to store the result */
1780 void *def_ptr = NULL;
1782 parmnum = map_parameter(pszParmName);
1785 if (strchr(pszParmName, ':')) {
1786 return lp_do_parameter_parametric(snum, pszParmName, pszParmValue, 0);
1788 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1792 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1793 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1797 /* if the flag has been set on the command line, then don't allow override,
1798 but don't report an error */
1799 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1803 def_ptr = parm_table[parmnum].ptr;
1805 /* we might point at a service, the default service or a global */
1809 if (parm_table[parmnum].class == P_GLOBAL) {
1811 ("Global parameter %s found in service section!\n",
1816 ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
1821 if (!ServicePtrs[snum]->copymap)
1822 init_copymap(ServicePtrs[snum]);
1824 /* this handles the aliases - set the copymap for other entries with
1825 the same data pointer */
1826 for (i = 0; parm_table[i].label; i++)
1827 if (parm_table[i].ptr == parm_table[parmnum].ptr)
1828 ServicePtrs[snum]->copymap[i] = False;
1831 /* if it is a special case then go ahead */
1832 if (parm_table[parmnum].special) {
1833 parm_table[parmnum].special(pszParmValue, (char **)parm_ptr);
1837 /* now switch on the type of variable it is */
1838 switch (parm_table[parmnum].type)
1841 set_boolean(parm_ptr, pszParmValue);
1845 *(int *)parm_ptr = atoi(pszParmValue);
1849 *(const char ***)parm_ptr = str_list_make(talloc_autofree_context(),
1850 pszParmValue, NULL);
1854 string_set(parm_ptr, pszParmValue);
1858 string_set(parm_ptr, pszParmValue);
1859 strupper(*(char **)parm_ptr);
1863 for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
1866 parm_table[parmnum].enum_list[i].name)) {
1868 parm_table[parmnum].
1873 if (!parm_table[parmnum].enum_list[i].name) {
1874 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n",
1875 pszParmValue, pszParmName));
1883 if (parm_table[parmnum].flags & FLAG_DEFAULT) {
1884 parm_table[parmnum].flags &= ~FLAG_DEFAULT;
1885 /* we have to also unset FLAG_DEFAULT on aliases */
1886 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1887 parm_table[i].flags &= ~FLAG_DEFAULT;
1889 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1890 parm_table[i].flags &= ~FLAG_DEFAULT;
1897 /***************************************************************************
1898 Process a parameter.
1899 ***************************************************************************/
1901 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue, void *userdata)
1903 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
1904 pszParmName, pszParmValue));
1908 variable argument do parameter
1910 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
1912 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...)
1919 s = talloc_vasprintf(NULL, fmt, ap);
1921 ret = do_parameter(pszParmName, s, NULL);
1928 set a parameter from the commandline - this is called from command line parameter
1929 parsing code. It sets the parameter then marks the parameter as unable to be modified
1930 by smb.conf processing
1932 BOOL lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
1934 int parmnum = map_parameter(pszParmName);
1937 while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
1940 if (parmnum < 0 && strchr(pszParmName, ':')) {
1941 /* set a parametric option */
1942 return lp_do_parameter_parametric(-1, pszParmName, pszParmValue, FLAG_CMDLINE);
1946 DEBUG(0,("Unknown option '%s'\n", pszParmName));
1950 /* reset the CMDLINE flag in case this has been called before */
1951 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
1953 if (!lp_do_parameter(-2, pszParmName, pszParmValue)) {
1957 parm_table[parmnum].flags |= FLAG_CMDLINE;
1959 /* we have to also set FLAG_CMDLINE on aliases */
1960 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1961 parm_table[i].flags |= FLAG_CMDLINE;
1963 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1964 parm_table[i].flags |= FLAG_CMDLINE;
1971 set a option from the commandline in 'a=b' format. Use to support --option
1973 BOOL lp_set_option(const char *option)
1991 ret = lp_set_cmdline(s, p+1);
1997 #define BOOLSTR(b) ((b) ? "Yes" : "No")
1999 /***************************************************************************
2000 Print a parameter of the specified type.
2001 ***************************************************************************/
2003 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
2009 for (i = 0; p->enum_list[i].name; i++) {
2010 if (*(int *)ptr == p->enum_list[i].value) {
2012 p->enum_list[i].name);
2019 fprintf(f, "%s", BOOLSTR(*(BOOL *)ptr));
2023 fprintf(f, "%d", *(int *)ptr);
2027 if ((char ***)ptr && *(char ***)ptr) {
2028 char **list = *(char ***)ptr;
2030 for (; *list; list++)
2031 fprintf(f, "%s%s", *list,
2032 ((*(list+1))?", ":""));
2038 if (*(char **)ptr) {
2039 fprintf(f, "%s", *(char **)ptr);
2047 /***************************************************************************
2048 Check if two parameters are equal.
2049 ***************************************************************************/
2051 static BOOL equal_parameter(parm_type type, void *ptr1, void *ptr2)
2055 return (*((BOOL *)ptr1) == *((BOOL *)ptr2));
2059 return (*((int *)ptr1) == *((int *)ptr2));
2062 return str_list_equal((const char **)(*(char ***)ptr1),
2063 (const char **)(*(char ***)ptr2));
2068 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
2073 return (p1 == p2 || strequal(p1, p2));
2081 /***************************************************************************
2082 Process a new section (service). At this stage all sections are services.
2083 Later we'll have special sections that permit server parameters to be set.
2084 Returns True on success, False on failure.
2085 ***************************************************************************/
2087 static BOOL do_section(const char *pszSectionName, void *userdata)
2090 BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2091 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2094 /* if we've just struck a global section, note the fact. */
2095 bInGlobalSection = isglobal;
2097 /* check for multiple global sections */
2098 if (bInGlobalSection) {
2099 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2103 /* if we have a current service, tidy it up before moving on */
2106 if (iServiceIndex >= 0)
2107 bRetval = service_ok(iServiceIndex);
2109 /* if all is still well, move to the next record in the services array */
2111 /* We put this here to avoid an odd message order if messages are */
2112 /* issued by the post-processing of a previous section. */
2113 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2115 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
2117 DEBUG(0, ("Failed to add a new service\n"));
2126 /***************************************************************************
2127 Determine if a partcular base parameter is currentl set to the default value.
2128 ***************************************************************************/
2130 static BOOL is_default(int i)
2132 if (!defaults_saved)
2134 switch (parm_table[i].type) {
2136 return str_list_equal((const char **)parm_table[i].def.lvalue,
2137 (const char **)(*(char ***)parm_table[i].ptr));
2140 return strequal(parm_table[i].def.svalue,
2141 *(char **)parm_table[i].ptr);
2143 return parm_table[i].def.bvalue ==
2144 *(BOOL *)parm_table[i].ptr;
2147 return parm_table[i].def.ivalue ==
2148 *(int *)parm_table[i].ptr;
2155 /***************************************************************************
2156 Display the contents of the global structure.
2157 ***************************************************************************/
2159 static void dump_globals(FILE *f, BOOL show_defaults)
2162 struct param_opt *data;
2164 fprintf(f, "# Global parameters\n[global]\n");
2166 for (i = 0; parm_table[i].label; i++)
2167 if (parm_table[i].class == P_GLOBAL &&
2168 parm_table[i].ptr &&
2169 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2170 if (!show_defaults && (parm_table[i].flags & FLAG_DEFAULT))
2172 fprintf(f, "\t%s = ", parm_table[i].label);
2173 print_parameter(&parm_table[i], parm_table[i].ptr, f);
2176 if (Globals.param_opt != NULL) {
2177 data = Globals.param_opt;
2179 fprintf(f, "\t%s = %s\n", data->key, data->value);
2186 /***************************************************************************
2187 Display the contents of a single services record.
2188 ***************************************************************************/
2190 static void dump_a_service(service * pService, FILE * f)
2193 struct param_opt *data;
2195 if (pService != &sDefault)
2196 fprintf(f, "\n[%s]\n", pService->szService);
2198 for (i = 0; parm_table[i].label; i++)
2199 if (parm_table[i].class == P_LOCAL &&
2200 parm_table[i].ptr &&
2201 (*parm_table[i].label != '-') &&
2202 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2203 int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
2205 if (pService == &sDefault) {
2206 if (defaults_saved && is_default(i))
2209 if (equal_parameter(parm_table[i].type,
2210 ((char *)pService) +
2212 ((char *)&sDefault) +
2217 fprintf(f, "\t%s = ", parm_table[i].label);
2218 print_parameter(&parm_table[i],
2219 ((char *)pService) + pdiff, f);
2222 if (pService->param_opt != NULL) {
2223 data = pService->param_opt;
2225 fprintf(f, "\t%s = %s\n", data->key, data->value);
2231 BOOL lp_dump_a_parameter(int snum, char *parm_name, FILE * f, BOOL isGlobal)
2233 service * pService = ServicePtrs[snum];
2236 struct parm_struct *parm;
2244 parm = lp_parm_struct(parm_name);
2252 ptr = ((char *)pService) +
2253 PTR_DIFF(parm->ptr, &sDefault);
2255 print_parameter(parm,
2261 /***************************************************************************
2262 Return info about the next service in a service. snum==-1 gives the globals.
2263 Return NULL when out of parameters.
2264 ***************************************************************************/
2266 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
2269 /* do the globals */
2270 for (; parm_table[*i].label; (*i)++) {
2271 if (parm_table[*i].class == P_SEPARATOR)
2272 return &parm_table[(*i)++];
2274 if (!parm_table[*i].ptr
2275 || (*parm_table[*i].label == '-'))
2279 && (parm_table[*i].ptr ==
2280 parm_table[(*i) - 1].ptr))
2283 return &parm_table[(*i)++];
2286 service *pService = ServicePtrs[snum];
2288 for (; parm_table[*i].label; (*i)++) {
2289 if (parm_table[*i].class == P_SEPARATOR)
2290 return &parm_table[(*i)++];
2292 if (parm_table[*i].class == P_LOCAL &&
2293 parm_table[*i].ptr &&
2294 (*parm_table[*i].label != '-') &&
2296 (parm_table[*i].ptr !=
2297 parm_table[(*i) - 1].ptr)))
2300 PTR_DIFF(parm_table[*i].ptr,
2303 if (allparameters ||
2304 !equal_parameter(parm_table[*i].type,
2305 ((char *)pService) +
2307 ((char *)&sDefault) +
2310 return &parm_table[(*i)++];
2320 /***************************************************************************
2321 Return TRUE if the passed service number is within range.
2322 ***************************************************************************/
2324 BOOL lp_snum_ok(int iService)
2326 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
2329 /***************************************************************************
2330 Auto-load some home services.
2331 ***************************************************************************/
2333 static void lp_add_auto_services(const char *str)
2338 /***************************************************************************
2339 Announce ourselves as a print server.
2340 ***************************************************************************/
2342 void update_server_announce_as_printserver(void)
2344 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
2347 /***************************************************************************
2348 Have we loaded a services file yet?
2349 ***************************************************************************/
2351 BOOL lp_loaded(void)
2356 /***************************************************************************
2357 Unload unused services.
2358 ***************************************************************************/
2360 void lp_killunused(struct smbsrv_connection *smb, BOOL (*snumused) (struct smbsrv_connection *, int))
2363 for (i = 0; i < iNumServices; i++) {
2367 if (!snumused || !snumused(smb, i)) {
2368 ServicePtrs[i]->valid = False;
2369 free_service(ServicePtrs[i]);
2374 /***************************************************************************
2376 ***************************************************************************/
2378 void lp_killservice(int iServiceIn)
2380 if (VALID(iServiceIn)) {
2381 ServicePtrs[iServiceIn]->valid = False;
2382 free_service(ServicePtrs[iServiceIn]);
2386 /***************************************************************************
2387 Load the services array from the services file. Return True on success,
2389 ***************************************************************************/
2395 struct param_opt *data;
2399 bInGlobalSection = True;
2401 if (Globals.param_opt != NULL) {
2402 struct param_opt *next;
2403 for (data=Globals.param_opt; data; data=next) {
2405 if (data->flags & FLAG_CMDLINE) continue;
2408 DLIST_REMOVE(Globals.param_opt, data);
2415 pstrcpy(n2, lp_configfile());
2416 standard_sub_basic(n2,sizeof(n2));
2417 DEBUG(2, ("lp_load: refreshing parameters from %s\n", n2));
2419 add_to_file_list(lp_configfile(), n2);
2421 /* We get sections first, so have to start 'behind' to make up */
2423 bRetval = pm_process(n2, do_section, do_parameter, NULL);
2425 /* finish up the last section */
2426 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
2428 if (iServiceIndex >= 0)
2429 bRetval = service_ok(iServiceIndex);
2431 lp_add_auto_services(lp_auto_services());
2433 lp_add_hidden("IPC$", "IPC");
2434 lp_add_hidden("ADMIN$", "DISK");
2436 set_default_server_announce_type();
2440 if (!Globals.szWINSservers && Globals.bWINSsupport) {
2441 lp_do_parameter(-1, "wins server", "127.0.0.1");
2449 /***************************************************************************
2450 Reset the max number of services.
2451 ***************************************************************************/
2453 void lp_resetnumservices(void)
2458 /***************************************************************************
2459 Return the max number of services.
2460 ***************************************************************************/
2462 int lp_numservices(void)
2464 return (iNumServices);
2467 /***************************************************************************
2468 Display the contents of the services array in human-readable form.
2469 ***************************************************************************/
2471 void lp_dump(FILE *f, BOOL show_defaults, int maxtoprint)
2476 defaults_saved = False;
2478 dump_globals(f, show_defaults);
2480 dump_a_service(&sDefault, f);
2482 for (iService = 0; iService < maxtoprint; iService++)
2483 lp_dump_one(f, show_defaults, iService);
2486 /***************************************************************************
2487 Display the contents of one service in human-readable form.
2488 ***************************************************************************/
2490 void lp_dump_one(FILE * f, BOOL show_defaults, int snum)
2493 if (ServicePtrs[snum]->szService[0] == '\0')
2495 dump_a_service(ServicePtrs[snum], f);
2499 /***************************************************************************
2500 Return the number of the service with the given name, or -1 if it doesn't
2501 exist. Note that this is a DIFFERENT ANIMAL from the internal function
2502 getservicebyname()! This works ONLY if all services have been loaded, and
2503 does not copy the found service.
2504 ***************************************************************************/
2506 int lp_servicenumber(const char *pszServiceName)
2509 fstring serviceName;
2512 for (iService = iNumServices - 1; iService >= 0; iService--) {
2513 if (VALID(iService) && ServicePtrs[iService]->szService) {
2515 * The substitution here is used to support %U is
2518 fstrcpy(serviceName, ServicePtrs[iService]->szService);
2519 standard_sub_basic(serviceName,sizeof(serviceName));
2520 if (strequal(serviceName, pszServiceName))
2526 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
2531 /*******************************************************************
2532 A useful volume label function.
2533 ********************************************************************/
2534 const char *volume_label(int snum)
2536 const char *ret = lp_volume(snum);
2538 return lp_servicename(snum);
2543 /*******************************************************************
2544 Set the server type we will announce as via nmbd.
2545 ********************************************************************/
2547 static void set_default_server_announce_type(void)
2549 default_server_announce = 0;
2550 default_server_announce |= SV_TYPE_WORKSTATION;
2551 default_server_announce |= SV_TYPE_SERVER;
2552 default_server_announce |= SV_TYPE_SERVER_UNIX;
2554 switch (lp_announce_as()) {
2555 case ANNOUNCE_AS_NT_SERVER:
2556 default_server_announce |= SV_TYPE_SERVER_NT;
2557 /* fall through... */
2558 case ANNOUNCE_AS_NT_WORKSTATION:
2559 default_server_announce |= SV_TYPE_NT;
2561 case ANNOUNCE_AS_WIN95:
2562 default_server_announce |= SV_TYPE_WIN95_PLUS;
2564 case ANNOUNCE_AS_WFW:
2565 default_server_announce |= SV_TYPE_WFW;
2571 switch (lp_server_role()) {
2572 case ROLE_DOMAIN_MEMBER:
2573 default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
2575 case ROLE_DOMAIN_PDC:
2576 default_server_announce |= SV_TYPE_DOMAIN_CTRL;
2578 case ROLE_DOMAIN_BDC:
2579 default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
2581 case ROLE_STANDALONE:
2585 if (lp_time_server())
2586 default_server_announce |= SV_TYPE_TIME_SOURCE;
2588 if (lp_host_msdfs())
2589 default_server_announce |= SV_TYPE_DFS_SERVER;
2591 /* TODO: only announce us as print server when we are a print server */
2592 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
2595 /***********************************************************
2596 If we are PDC then prefer us as DMB
2597 ************************************************************/
2599 BOOL lp_domain_master(void)
2601 return (lp_server_role() == ROLE_DOMAIN_PDC);
2604 /***********************************************************
2605 If we are PDC then prefer us as DMB
2606 ************************************************************/
2608 BOOL lp_domain_logons(void)
2610 return (lp_server_role() == ROLE_DOMAIN_PDC) || (lp_server_role() == ROLE_DOMAIN_BDC);
2613 /***********************************************************
2614 If we are DMB then prefer us as LMB
2615 ************************************************************/
2617 BOOL lp_preferred_master(void)
2619 return (lp_local_master() && lp_domain_master());
2622 /*******************************************************************
2624 ********************************************************************/
2626 void lp_remove_service(int snum)
2628 ServicePtrs[snum]->valid = False;
2631 /*******************************************************************
2633 ********************************************************************/
2635 void lp_copy_service(int snum, const char *new_name)
2637 const char *oldname = lp_servicename(snum);
2638 do_section(new_name, NULL);
2640 snum = lp_servicenumber(new_name);
2642 lp_do_parameter(snum, "copy", oldname);
2647 /*******************************************************************
2648 Get the default server type we will announce as via nmbd.
2649 ********************************************************************/
2650 int lp_default_server_announce(void)
2652 return default_server_announce;
2655 const char *lp_printername(int snum)
2657 const char *ret = _lp_printername(snum);
2658 if (ret == NULL || (ret != NULL && *ret == '\0'))
2659 ret = lp_const_servicename(snum);
2665 /*******************************************************************
2666 Return the max print jobs per queue.
2667 ********************************************************************/
2669 int lp_maxprintjobs(int snum)
2671 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
2672 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
2673 maxjobs = PRINT_MAX_JOBID - 1;