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;
159 BOOL bPreferredMaster;
160 BOOL bEncryptPasswords;
162 BOOL bObeyPamRestrictions;
163 BOOL bLargeReadwrite;
167 BOOL bBindInterfacesOnly;
169 BOOL bNTStatusSupport;
175 BOOL bClientPlaintextAuth;
176 BOOL bClientLanManAuth;
177 BOOL bClientNTLMv2Auth;
178 BOOL client_use_spnego_principal;
181 BOOL bUnixExtensions;
182 BOOL bDisableNetbios;
184 struct param_opt *param_opt;
188 static global Globals;
191 * This structure describes a single service.
206 char **ntvfs_handler;
222 struct param_opt *param_opt;
224 char dummy[3]; /* for alignment */
229 /* This is a default service used to prime a services structure */
230 static service sDefault = {
232 NULL, /* szService */
235 NULL, /* szInclude */
236 NULL, /* szPrintername */
237 NULL, /* szHostsallow */
238 NULL, /* szHostsdeny */
242 NULL, /* ntvfs_handler */
243 1000, /* iMaxPrintJobs */
244 0, /* iMaxConnections */
246 True, /* bAvailable */
247 True, /* bBrowseable */
248 True, /* bRead_only */
249 False, /* bPrint_ok */
250 False, /* bMap_system */
251 False, /* bMap_hidden */
252 True, /* bMap_archive */
253 True, /* bStrictLocking */
255 False, /* bMSDfsRoot */
256 False, /* bStrictSync */
257 False, /* bCIFileSystem */
258 NULL, /* Parametric options */
263 /* local variables */
264 static service **ServicePtrs = NULL;
265 static int iNumServices = 0;
266 static int iServiceIndex = 0;
267 static BOOL bInGlobalSection = True;
268 static int default_server_announce;
270 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
272 /* prototypes for the special type handlers */
273 static BOOL handle_include(const char *pszParmValue, char **ptr);
274 static BOOL handle_copy(const char *pszParmValue, char **ptr);
276 static void set_default_server_announce_type(void);
278 static const struct enum_list enum_protocol[] = {
279 {PROTOCOL_NT1, "NT1"},
280 {PROTOCOL_LANMAN2, "LANMAN2"},
281 {PROTOCOL_LANMAN1, "LANMAN1"},
282 {PROTOCOL_CORE, "CORE"},
283 {PROTOCOL_COREPLUS, "COREPLUS"},
284 {PROTOCOL_COREPLUS, "CORE+"},
288 static const struct enum_list enum_security[] = {
289 {SEC_SHARE, "SHARE"},
294 /* Types of machine we can announce as. */
295 #define ANNOUNCE_AS_NT_SERVER 1
296 #define ANNOUNCE_AS_WIN95 2
297 #define ANNOUNCE_AS_WFW 3
298 #define ANNOUNCE_AS_NT_WORKSTATION 4
300 static const struct enum_list enum_announce_as[] = {
301 {ANNOUNCE_AS_NT_SERVER, "NT"},
302 {ANNOUNCE_AS_NT_SERVER, "NT Server"},
303 {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"},
304 {ANNOUNCE_AS_WIN95, "win95"},
305 {ANNOUNCE_AS_WFW, "WfW"},
309 static const struct enum_list enum_bool_auto[] = {
320 /* Client-side offline caching policy types */
321 #define CSC_POLICY_MANUAL 0
322 #define CSC_POLICY_DOCUMENTS 1
323 #define CSC_POLICY_PROGRAMS 2
324 #define CSC_POLICY_DISABLE 3
326 static const struct enum_list enum_csc_policy[] = {
327 {CSC_POLICY_MANUAL, "manual"},
328 {CSC_POLICY_DOCUMENTS, "documents"},
329 {CSC_POLICY_PROGRAMS, "programs"},
330 {CSC_POLICY_DISABLE, "disable"},
334 /* SMB signing types. */
335 static const struct enum_list enum_smb_signing_vals[] = {
336 {SMB_SIGNING_OFF, "No"},
337 {SMB_SIGNING_OFF, "False"},
338 {SMB_SIGNING_OFF, "0"},
339 {SMB_SIGNING_OFF, "Off"},
340 {SMB_SIGNING_OFF, "disabled"},
341 {SMB_SIGNING_SUPPORTED, "Yes"},
342 {SMB_SIGNING_SUPPORTED, "True"},
343 {SMB_SIGNING_SUPPORTED, "1"},
344 {SMB_SIGNING_SUPPORTED, "On"},
345 {SMB_SIGNING_SUPPORTED, "enabled"},
346 {SMB_SIGNING_REQUIRED, "required"},
347 {SMB_SIGNING_REQUIRED, "mandatory"},
348 {SMB_SIGNING_REQUIRED, "force"},
349 {SMB_SIGNING_REQUIRED, "forced"},
350 {SMB_SIGNING_REQUIRED, "enforced"},
351 {SMB_SIGNING_AUTO, "auto"},
355 static const struct enum_list enum_server_role[] = {
356 {ROLE_STANDALONE, "standalone"},
357 {ROLE_DOMAIN_MEMBER, "member server"},
358 {ROLE_DOMAIN_BDC, "bdc"},
359 {ROLE_DOMAIN_PDC, "pdc"},
364 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
366 * Note: We have a flag called FLAG_DEVELOPER but is not used at this time, it
367 * is implied in current control logic. This may change at some later time. A
368 * flag value of 0 means - show as development option only.
370 * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
371 * screen in SWAT. This is used to exclude parameters as well as to squash all
372 * parameters that have been duplicated by pseudonyms.
374 static struct parm_struct parm_table[] = {
375 {"Base Options", P_SEP, P_SEPARATOR},
377 {"server role", P_ENUM, P_GLOBAL, &Globals.server_role, NULL, enum_server_role, FLAG_BASIC},
379 {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
380 {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
381 {"ncalrpc dir", P_STRING, P_GLOBAL, &Globals.ncalrpc_dir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
382 {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
383 {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
384 {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
385 {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE},
386 {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkgroup, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
387 {"realm", P_STRING, P_GLOBAL, &Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
388 {"netbios name", P_USTRING, P_GLOBAL, &Globals.szNetbiosName, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
389 {"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
390 {"netbios scope", P_USTRING, P_GLOBAL, &Globals.szNetbiosScope, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
391 {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
392 {"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
393 {"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
394 {"ntvfs handler", P_LIST, P_LOCAL, &sDefault.ntvfs_handler, NULL, NULL, FLAG_ADVANCED},
395 {"ntptr providor", P_STRING, P_GLOBAL, &Globals.ntptr_providor, NULL, NULL, FLAG_ADVANCED},
396 {"dcerpc endpoint servers", P_LIST, P_GLOBAL, &Globals.dcerpc_ep_servers, NULL, NULL, FLAG_ADVANCED},
397 {"server services", P_LIST, P_GLOBAL, &Globals.server_services, NULL, NULL, FLAG_ADVANCED},
399 {"Security Options", P_SEP, P_SEPARATOR},
401 {"security", P_ENUM, P_GLOBAL, &Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
402 {"auth methods", P_LIST, P_GLOBAL, &Globals.AuthMethods, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
403 {"encrypt passwords", P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
404 {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
405 {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
406 {"password server", P_LIST, P_GLOBAL, &Globals.szPasswordServers, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
407 {"sam database", P_STRING, P_GLOBAL, &Globals.szSAM_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
408 {"spoolss database", P_STRING, P_GLOBAL, &Globals.szSPOOLSS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
409 {"wins config database", P_STRING, P_GLOBAL, &Globals.szWINS_CONFIG_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
410 {"wins database", P_STRING, P_GLOBAL, &Globals.szWINS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
411 {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
412 {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
413 {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
414 {"lanman auth", P_BOOL, P_GLOBAL, &Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
415 {"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
416 {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
417 {"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
418 {"client plaintext auth", P_BOOL, P_GLOBAL, &Globals.bClientPlaintextAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
419 {"client use spnego principal", P_BOOL, P_GLOBAL, &Globals.client_use_spnego_principal, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
421 {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE},
423 {"hosts allow", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
424 {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
426 {"Logging Options", P_SEP, P_SEPARATOR},
428 {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
429 {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_HIDE},
430 {"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
432 {"Protocol Options", P_SEP, P_SEPARATOR},
434 {"smb ports", P_LIST, P_GLOBAL, &Globals.smb_ports, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
435 {"nbt port", P_INTEGER, P_GLOBAL, &Globals.nbt_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
436 {"dgram port", P_INTEGER, P_GLOBAL, &Globals.dgram_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
437 {"cldap port", P_INTEGER, P_GLOBAL, &Globals.cldap_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
438 {"krb5 port", P_INTEGER, P_GLOBAL, &Globals.krb5_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
439 {"kpasswd port", P_INTEGER, P_GLOBAL, &Globals.kpasswd_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
440 {"web port", P_INTEGER, P_GLOBAL, &Globals.web_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
441 {"tls enabled", P_BOOL, P_GLOBAL, &Globals.tls_enabled, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
442 {"tls keyfile", P_STRING, P_GLOBAL, &Globals.tls_keyfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
443 {"tls certfile", P_STRING, P_GLOBAL, &Globals.tls_certfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
444 {"tls cafile", P_STRING, P_GLOBAL, &Globals.tls_cafile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
445 {"tls crlfile", P_STRING, P_GLOBAL, &Globals.tls_crlfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
446 {"swat directory", P_STRING, P_GLOBAL, &Globals.swat_directory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
447 {"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, FLAG_DEVELOPER},
448 {"max protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
449 {"min protocol", P_ENUM, P_GLOBAL, &Globals.minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
450 {"unicode", P_BOOL, P_GLOBAL, &Globals.bUnicode, NULL, NULL, FLAG_DEVELOPER},
451 {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL, NULL, FLAG_DEVELOPER},
452 {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL, NULL, FLAG_DEVELOPER},
453 {"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
455 {"nt status support", P_BOOL, P_GLOBAL, &Globals.bNTStatusSupport, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
457 {"announce version", P_STRING, P_GLOBAL, &Globals.szAnnounceVersion, NULL, NULL, FLAG_DEVELOPER},
458 {"announce as", P_ENUM, P_GLOBAL, &Globals.announce_as, NULL, enum_announce_as, FLAG_DEVELOPER},
459 {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
460 {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
462 {"name resolve order", P_LIST, P_GLOBAL, &Globals.szNameResolveOrder, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
463 {"max wins ttl", P_INTEGER, P_GLOBAL, &Globals.max_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
464 {"min wins ttl", P_INTEGER, P_GLOBAL, &Globals.min_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
465 {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
466 {"unix extensions", P_BOOL, P_GLOBAL, &Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
467 {"use spnego", P_BOOL, P_GLOBAL, &Globals.bUseSpnego, NULL, NULL, FLAG_DEVELOPER},
468 {"server signing", P_ENUM, P_GLOBAL, &Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
469 {"client signing", P_ENUM, P_GLOBAL, &Globals.client_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
470 {"rpc big endian", P_BOOL, P_GLOBAL, &Globals.bRpcBigEndian, NULL, NULL, FLAG_DEVELOPER},
472 {"Tuning Options", P_SEP, P_SEPARATOR},
474 {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL, NULL, FLAG_SHARE},
475 {"paranoid server security", P_BOOL, P_GLOBAL, &Globals.paranoid_server_security, NULL, NULL, FLAG_DEVELOPER},
476 {"socket options", P_STRING, P_GLOBAL, &Globals.socket_options, NULL, NULL, FLAG_DEVELOPER},
478 {"strict sync", P_BOOL, P_LOCAL, &sDefault.bStrictSync, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
479 {"case insensitive filesystem", P_BOOL, P_LOCAL, &sDefault.bCIFileSystem, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
481 {"Printing Options", P_SEP, P_SEPARATOR},
483 {"max print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxPrintJobs, NULL, NULL, FLAG_PRINT},
484 {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_PRINT},
485 {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_HIDE},
487 {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_PRINT},
488 {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_HIDE},
490 {"Filename Handling", P_SEP, P_SEPARATOR},
492 {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
493 {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
494 {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
496 {"Domain Options", P_SEP, P_SEPARATOR},
498 {"Logon Options", P_SEP, P_SEPARATOR},
501 {"Browse Options", P_SEP, P_SEPARATOR},
503 {"preferred master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
504 {"prefered master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_HIDE},
505 {"local master", P_BOOL, P_GLOBAL, &Globals.bLocalMaster, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
506 {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
507 {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_HIDE},
509 {"WINS Options", P_SEP, P_SEPARATOR},
511 {"wins server", P_LIST, P_GLOBAL, &Globals.szWINSservers, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
512 {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
513 {"dns proxy", P_BOOL, P_GLOBAL, &Globals.bWINSdnsProxy, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
514 {"wins hook", P_STRING, P_GLOBAL, &Globals.szWINSHook, NULL, NULL, FLAG_ADVANCED},
516 {"Locking Options", P_SEP, P_SEPARATOR},
518 {"csc policy", P_ENUM, P_LOCAL, &sDefault.iCSCPolicy, NULL, enum_csc_policy, FLAG_SHARE | FLAG_GLOBAL},
520 {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
522 {"Miscellaneous Options", P_SEP, P_SEPARATOR},
524 {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE},
525 {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
526 {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
527 {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_HIDE},
528 {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
529 {"pid directory", P_STRING, P_GLOBAL, &Globals.szPidDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
530 {"js include", P_LIST, P_GLOBAL, &Globals.jsInclude, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
531 {"setup directory", P_STRING, P_GLOBAL, &Globals.szSetupDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
533 {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL, NULL, FLAG_DEVELOPER},
534 {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL, NULL, FLAG_HIDE},
536 {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy, NULL, FLAG_HIDE},
537 {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include, NULL, FLAG_HIDE},
539 {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
540 {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_SHARE },
541 {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_SHARE},
543 {"panic action", P_STRING, P_GLOBAL, &Globals.szPanicAction, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
545 {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_SHARE},
546 {"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
547 {"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
548 {"winbind sealed pipes", P_BOOL, P_GLOBAL, &Globals.bWinbindSealedPipes, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
550 {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
555 return the parameter table
557 struct parm_struct *lp_parm_table(void)
562 /***************************************************************************
563 Initialise the global parameter structure.
564 ***************************************************************************/
565 static void init_globals(void)
570 DEBUG(3, ("Initialising global parameters\n"));
572 for (i = 0; parm_table[i].label; i++) {
573 if ((parm_table[i].type == P_STRING ||
574 parm_table[i].type == P_USTRING) &&
576 !(parm_table[i].flags & FLAG_CMDLINE)) {
577 string_set(parm_table[i].ptr, "");
581 do_parameter("config file", dyn_CONFIGFILE, NULL);
583 do_parameter("server role", "standalone", NULL);
585 /* options that can be set on the command line must be initialised via
586 the slower do_parameter() to ensure that FLAG_CMDLINE is obeyed */
588 do_parameter("socket options", "TCP_NODELAY", NULL);
590 do_parameter("workgroup", DEFAULT_WORKGROUP, NULL);
591 myname = get_myname();
592 do_parameter("netbios name", myname, NULL);
594 do_parameter("max protocol", "NT1", NULL);
595 do_parameter("name resolve order", "lmhosts wins host bcast", NULL);
597 do_parameter("fstype", FSTYPE_STRING, NULL);
598 do_parameter("ntvfs handler", "unixuid default", NULL);
599 do_parameter("max connections", "-1", NULL);
601 do_parameter("dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup", NULL);
602 do_parameter("server services", "smb rpc nbt wrepl ldap cldap web kdc", NULL);
603 do_parameter("ntptr providor", "simple_ldb", NULL);
604 do_parameter("auth methods", "anonymous sam_ignoredomain", NULL);
605 do_parameter("private dir", dyn_PRIVATE_DIR, NULL);
606 do_parameter("sam database", "sam.ldb", NULL);
607 do_parameter("spoolss database", "spoolss.ldb", NULL);
608 do_parameter("wins config database", "wins_config.ldb", NULL);
609 do_parameter("wins database", "wins.ldb", NULL);
610 do_parameter("registry:HKEY_LOCAL_MACHINE", "hklm.ldb", NULL);
612 /* This hive should be dynamically generated by Samba using
613 data from the sam, but for the moment leave it in a tdb to
614 keep regedt32 from popping up an annoying dialog. */
615 do_parameter("registry:HKEY_USERS", "hku.ldb", NULL);
617 /* using UTF8 by default allows us to support all chars */
618 do_parameter("unix charset", "UTF8", NULL);
620 /* Use codepage 850 as a default for the dos character set */
621 do_parameter("dos charset", "CP850", NULL);
624 * Allow the default PASSWD_CHAT to be overridden in local.h.
626 do_parameter("passwd chat", DEFAULT_PASSWD_CHAT, NULL);
628 do_parameter("pid directory", dyn_PIDDIR, NULL);
629 do_parameter("lock dir", dyn_LOCKDIR, NULL);
630 do_parameter("ncalrpc dir", dyn_NCALRPCDIR, NULL);
632 do_parameter("socket address", "0.0.0.0", NULL);
633 do_parameter_var("server string", "Samba %s", SAMBA_VERSION_STRING);
635 do_parameter_var("announce version", "%d.%d",
636 DEFAULT_MAJOR_VERSION,
637 DEFAULT_MINOR_VERSION);
639 do_parameter("password server", "*", NULL);
641 do_parameter("max mux", "50", NULL);
642 do_parameter("max xmit", "12288", NULL);
643 do_parameter("password level", "0", NULL);
644 do_parameter("LargeReadwrite", "True", NULL);
645 do_parameter("minprotocol", "CORE", NULL);
646 do_parameter("security", "USER", NULL);
647 do_parameter("paranoid server security", "True", NULL);
648 do_parameter("EncryptPasswords", "True", NULL);
649 do_parameter("ReadRaw", "True", NULL);
650 do_parameter("WriteRaw", "True", NULL);
651 do_parameter("NullPasswords", "False", NULL);
652 do_parameter("ObeyPamRestrictions", "False", NULL);
653 do_parameter("announce as", "NT SERVER", NULL);
655 do_parameter("TimeServer", "False", NULL);
656 do_parameter("BindInterfacesOnly", "False", NULL);
657 do_parameter("Unicode", "True", NULL);
658 do_parameter("ClientLanManAuth", "True", NULL);
659 do_parameter("LanmanAuth", "True", NULL);
660 do_parameter("NTLMAuth", "True", NULL);
661 do_parameter("client use spnego principal", "False", NULL);
663 do_parameter("UnixExtensions", "False", NULL);
665 do_parameter("PreferredMaster", "Auto", NULL);
666 do_parameter("LocalMaster", "True", NULL);
668 do_parameter("wins support", "False", NULL);
669 do_parameter("dns proxy", "True", NULL);
671 do_parameter("winbind separator", "\\", NULL);
672 do_parameter("winbind sealed pipes", "True", NULL);
674 do_parameter("client signing", "Yes", NULL);
675 do_parameter("server signing", "auto", NULL);
677 do_parameter("use spnego", "True", NULL);
679 do_parameter("smb ports", SMB_PORTS, NULL);
680 do_parameter("nbt port", "137", NULL);
681 do_parameter("dgram port", "138", NULL);
682 do_parameter("cldap port", "389", NULL);
683 do_parameter("krb5 port", "88", NULL);
684 do_parameter("kpasswd port", "464", NULL);
685 do_parameter("web port", "901", NULL);
686 do_parameter("swat directory", dyn_SWATDIR, NULL);
688 do_parameter("nt status support", "True", NULL);
690 do_parameter("max wins ttl", "518400", NULL); /* 6 days */
691 do_parameter("min wins ttl", "10", NULL);
693 do_parameter("tls enabled", "True", NULL);
694 do_parameter("tls keyfile", "tls/key.pem", NULL);
695 do_parameter("tls certfile", "tls/cert.pem", NULL);
696 do_parameter("tls cafile", "tls/ca.pem", NULL);
697 do_parameter_var("js include", "%s", dyn_JSDIR);
698 do_parameter_var("setup directory", "%s", dyn_SETUPDIR);
700 for (i = 0; parm_table[i].label; i++) {
701 if (!(parm_table[i].flags & FLAG_CMDLINE)) {
702 parm_table[i].flags |= FLAG_DEFAULT;
707 static TALLOC_CTX *lp_talloc;
709 /******************************************************************* a
710 Free up temporary memory - called from the main loop.
711 ********************************************************************/
713 void lp_talloc_free(void)
717 talloc_free(lp_talloc);
721 /*******************************************************************
722 Convenience routine to grab string parameters into temporary memory
723 and run standard_sub_basic on them. The buffers can be written to by
724 callers without affecting the source string.
725 ********************************************************************/
727 static const char *lp_string(const char *s)
729 #if 0 /* until REWRITE done to make thread-safe */
730 size_t len = s ? strlen(s) : 0;
734 /* The follow debug is useful for tracking down memory problems
735 especially if you have an inner loop that is calling a lp_*()
736 function that returns a string. Perhaps this debug should be
737 present all the time? */
740 DEBUG(10, ("lp_string(%s)\n", s));
743 #if 0 /* until REWRITE done to make thread-safe */
745 lp_talloc = talloc_init("lp_talloc");
747 ret = talloc_array(lp_talloc, char, len + 100); /* leave room for substitution */
755 StrnCpy(ret, s, len);
757 if (trim_string(ret, "\"", "\"")) {
758 if (strchr(ret,'"') != NULL)
759 StrnCpy(ret, s, len);
762 standard_sub_basic(ret,len+100);
769 In this section all the functions that are used to access the
770 parameters from the rest of the program are defined
773 #define FN_GLOBAL_STRING(fn_name,ptr) \
774 const char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
775 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
776 const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");}
777 #define FN_GLOBAL_LIST(fn_name,ptr) \
778 const char **fn_name(void) {return(*(const char ***)(ptr));}
779 #define FN_GLOBAL_BOOL(fn_name,ptr) \
780 BOOL fn_name(void) {return(*(BOOL *)(ptr));}
781 #define FN_GLOBAL_CHAR(fn_name,ptr) \
782 char fn_name(void) {return(*(char *)(ptr));}
783 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
784 int fn_name(void) {return(*(int *)(ptr));}
786 #define FN_LOCAL_STRING(fn_name,val) \
787 const char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
788 #define FN_LOCAL_CONST_STRING(fn_name,val) \
789 const char *fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
790 #define FN_LOCAL_LIST(fn_name,val) \
791 const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
792 #define FN_LOCAL_BOOL(fn_name,val) \
793 BOOL fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
794 #define FN_LOCAL_CHAR(fn_name,val) \
795 char fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
796 #define FN_LOCAL_INTEGER(fn_name,val) \
797 int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
799 FN_GLOBAL_INTEGER(lp_server_role, &Globals.server_role)
800 FN_GLOBAL_LIST(lp_smb_ports, &Globals.smb_ports)
801 FN_GLOBAL_INTEGER(lp_nbt_port, &Globals.nbt_port)
802 FN_GLOBAL_INTEGER(lp_dgram_port, &Globals.dgram_port)
803 FN_GLOBAL_INTEGER(lp_cldap_port, &Globals.cldap_port)
804 FN_GLOBAL_INTEGER(lp_krb5_port, &Globals.krb5_port)
805 FN_GLOBAL_INTEGER(lp_kpasswd_port, &Globals.kpasswd_port)
806 FN_GLOBAL_INTEGER(lp_web_port, &Globals.web_port)
807 FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
808 FN_GLOBAL_STRING(lp_swat_directory, &Globals.swat_directory)
809 FN_GLOBAL_BOOL(lp_tls_enabled, &Globals.tls_enabled)
810 FN_GLOBAL_STRING(lp_tls_keyfile, &Globals.tls_keyfile)
811 FN_GLOBAL_STRING(lp_tls_certfile, &Globals.tls_certfile)
812 FN_GLOBAL_STRING(lp_tls_cafile, &Globals.tls_cafile)
813 FN_GLOBAL_STRING(lp_tls_crlfile, &Globals.tls_crlfile)
814 FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
815 FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset)
816 FN_GLOBAL_STRING(lp_logfile, &Globals.szLogFile)
817 FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
818 FN_GLOBAL_STRING(lp_sam_url, &Globals.szSAM_URL)
819 FN_GLOBAL_STRING(lp_spoolss_url, &Globals.szSPOOLSS_URL)
820 FN_GLOBAL_STRING(lp_wins_config_url, &Globals.szWINS_CONFIG_URL)
821 FN_GLOBAL_STRING(lp_wins_url, &Globals.szWINS_URL)
822 FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
823 FN_GLOBAL_BOOL(lp_winbind_sealed_pipes, &Globals.bWinbindSealedPipes)
824 FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
825 FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
826 FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
827 FN_GLOBAL_STRING(lp_setupdir, &Globals.szSetupDir)
828 FN_GLOBAL_STRING(lp_ncalrpc_dir, &Globals.ncalrpc_dir)
829 FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
830 FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, &Globals.dcerpc_ep_servers)
831 FN_GLOBAL_LIST(lp_server_services, &Globals.server_services)
832 FN_GLOBAL_STRING(lp_ntptr_providor, &Globals.ntptr_providor)
833 FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
834 FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
835 FN_GLOBAL_LIST(lp_passwordserver, &Globals.szPasswordServers)
836 FN_GLOBAL_LIST(lp_name_resolve_order, &Globals.szNameResolveOrder)
837 FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
838 FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
839 FN_GLOBAL_STRING(lp_workgroup, &Globals.szWorkgroup)
840 FN_GLOBAL_STRING(lp_netbios_name, &Globals.szNetbiosName)
841 FN_GLOBAL_STRING(lp_netbios_scope, &Globals.szNetbiosScope)
842 FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
843 FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
844 FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
845 FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
846 FN_GLOBAL_STRING(lp_panic_action, &Globals.szPanicAction)
848 FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
849 FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
850 FN_GLOBAL_BOOL(lp_wins_dns_proxy, &Globals.bWINSdnsProxy)
851 FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
852 FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
853 FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
854 FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
855 FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw)
856 FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords)
857 FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions)
858 FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
859 static FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
860 FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
861 FN_GLOBAL_BOOL(lp_unicode, &Globals.bUnicode)
862 FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
863 FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
864 FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
865 FN_GLOBAL_BOOL(lp_client_plaintext_auth, &Globals.bClientPlaintextAuth)
866 FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
867 FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
868 FN_GLOBAL_BOOL(lp_client_use_spnego_principal, &Globals.client_use_spnego_principal)
869 FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
870 FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions)
871 FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
872 FN_GLOBAL_BOOL(lp_rpc_big_endian, &Globals.bRpcBigEndian)
873 FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
874 FN_GLOBAL_INTEGER(lp_min_wins_ttl, &Globals.min_wins_ttl)
875 FN_GLOBAL_INTEGER(lp_maxmux, &Globals.max_mux)
876 FN_GLOBAL_INTEGER(lp_max_xmit, &Globals.max_xmit)
877 FN_GLOBAL_INTEGER(lp_passwordlevel, &Globals.pwordlevel)
878 FN_GLOBAL_INTEGER(lp_maxprotocol, &Globals.maxprotocol)
879 FN_GLOBAL_INTEGER(lp_minprotocol, &Globals.minprotocol)
880 FN_GLOBAL_INTEGER(lp_security, &Globals.security)
881 FN_GLOBAL_LIST(lp_auth_methods, &Globals.AuthMethods)
882 FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security)
883 static FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as)
884 FN_GLOBAL_LIST(lp_js_include, &Globals.jsInclude)
887 FN_LOCAL_STRING(lp_servicename, szService)
888 FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
889 FN_LOCAL_STRING(lp_pathname, szPath)
890 static FN_LOCAL_STRING(_lp_printername, szPrintername)
891 FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
892 FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
893 FN_LOCAL_STRING(lp_comment, comment)
894 FN_LOCAL_STRING(lp_fstype, fstype)
895 static FN_LOCAL_STRING(lp_volume, volume)
896 FN_LOCAL_LIST(lp_ntvfs_handler, ntvfs_handler)
897 FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
898 FN_LOCAL_BOOL(lp_browseable, bBrowseable)
899 FN_LOCAL_BOOL(lp_readonly, bRead_only)
900 FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
901 FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
902 FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
903 FN_LOCAL_BOOL(lp_strict_locking, bStrictLocking)
904 FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
905 FN_LOCAL_BOOL(lp_ci_filesystem, bCIFileSystem)
906 FN_LOCAL_BOOL(lp_map_system, bMap_system)
907 FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
908 FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
909 FN_GLOBAL_INTEGER(lp_server_signing, &Globals.server_signing)
910 FN_GLOBAL_INTEGER(lp_client_signing, &Globals.client_signing)
912 /* local prototypes */
914 static int map_parameter(const char *pszParmName);
915 static int getservicebyname(const char *pszServiceName,
916 service * pserviceDest);
917 static void copy_service(service * pserviceDest,
918 service * pserviceSource, BOOL *pcopymapDest);
919 static BOOL service_ok(int iService);
920 static BOOL do_section(const char *pszSectionName, void *);
921 static void init_copymap(service * pservice);
923 /* This is a helper function for parametrical options support. */
924 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
925 /* Actual parametrical functions are quite simple */
926 const char *lp_get_parametric(int lookup_service, const char *type, const char *option)
929 struct param_opt *data;
931 if (lookup_service >= iNumServices) return NULL;
933 data = (lookup_service < 0) ?
934 Globals.param_opt : ServicePtrs[lookup_service]->param_opt;
936 asprintf(&vfskey, "%s:%s", type, option);
940 if (strcmp(data->key, vfskey) == 0) {
947 if (lookup_service >= 0) {
948 /* Try to fetch the same option but from globals */
949 /* but only if we are not already working with Globals */
950 data = Globals.param_opt;
952 if (strcmp(data->key, vfskey) == 0) {
966 /*******************************************************************
967 convenience routine to return int parameters.
968 ********************************************************************/
969 static int lp_int(const char *s)
973 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
977 return strtol(s, NULL, 0);
980 /*******************************************************************
981 convenience routine to return unsigned long parameters.
982 ********************************************************************/
983 static int lp_ulong(const char *s)
987 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
991 return strtoul(s, NULL, 0);
994 /*******************************************************************
995 convenience routine to return boolean parameters.
996 ********************************************************************/
997 static BOOL lp_bool(const char *s)
1002 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
1006 if (!set_boolean(s, &ret)) {
1007 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1015 /* Return parametric option from a given service. Type is a part of option before ':' */
1016 /* Parametric option has following syntax: 'Type: option = value' */
1017 /* Returned value is allocated in 'lp_talloc' context */
1019 const char *lp_parm_string(int lookup_service, const char *type, const char *option)
1021 const char *value = lp_get_parametric(lookup_service, type, option);
1024 return lp_string(value);
1029 /* Return parametric option from a given service. Type is a part of option before ':' */
1030 /* Parametric option has following syntax: 'Type: option = value' */
1031 /* Returned value is allocated in 'lp_talloc' context */
1033 const char **lp_parm_string_list(int lookup_service, const char *type, const char *option,
1034 const char *separator)
1036 const char *value = lp_get_parametric(lookup_service, type, option);
1039 return str_list_make(talloc_autofree_context(), value, separator);
1044 /* Return parametric option from a given service. Type is a part of option before ':' */
1045 /* Parametric option has following syntax: 'Type: option = value' */
1047 int lp_parm_int(int lookup_service, const char *type, const char *option, int default_v)
1049 const char *value = lp_get_parametric(lookup_service, type, option);
1052 return lp_int(value);
1057 /* Return parametric option from a given service. Type is a part of option before ':' */
1058 /* Parametric option has following syntax: 'Type: option = value' */
1060 unsigned long lp_parm_ulong(int lookup_service, const char *type, const char *option, unsigned long default_v)
1062 const char *value = lp_get_parametric(lookup_service, type, option);
1065 return lp_ulong(value);
1070 /* Return parametric option from a given service. Type is a part of option before ':' */
1071 /* Parametric option has following syntax: 'Type: option = value' */
1073 BOOL lp_parm_bool(int lookup_service, const char *type, const char *option, BOOL default_v)
1075 const char *value = lp_get_parametric(lookup_service, type, option);
1078 return lp_bool(value);
1084 /***************************************************************************
1085 Initialise a service to the defaults.
1086 ***************************************************************************/
1088 static void init_service(service * pservice)
1090 memset((char *)pservice, '\0', sizeof(service));
1091 copy_service(pservice, &sDefault, NULL);
1094 /***************************************************************************
1095 Free the dynamically allocated parts of a service struct.
1096 ***************************************************************************/
1098 static void free_service(service *pservice)
1101 struct param_opt *data, *pdata;
1105 if (pservice->szService)
1106 DEBUG(5, ("free_service: Freeing service %s\n",
1107 pservice->szService));
1109 string_free(&pservice->szService);
1110 SAFE_FREE(pservice->copymap);
1112 for (i = 0; parm_table[i].label; i++) {
1113 if ((parm_table[i].type == P_STRING ||
1114 parm_table[i].type == P_USTRING) &&
1115 parm_table[i].class == P_LOCAL) {
1116 string_free((char **)
1117 (((char *)pservice) +
1118 PTR_DIFF(parm_table[i].ptr, &sDefault)));
1119 } else if (parm_table[i].type == P_LIST &&
1120 parm_table[i].class == P_LOCAL) {
1121 char ***listp = (char ***)(((char *)pservice) +
1122 PTR_DIFF(parm_table[i].ptr, &sDefault));
1123 talloc_free(*listp);
1128 DEBUG(5,("Freeing parametrics:\n"));
1129 data = pservice->param_opt;
1131 DEBUG(5,("[%s = %s]\n", data->key, data->value));
1132 string_free(&data->key);
1133 string_free(&data->value);
1139 ZERO_STRUCTP(pservice);
1142 /***************************************************************************
1143 Add a new service to the services array initialising it with the given
1145 ***************************************************************************/
1147 static int add_a_service(const service *pservice, const char *name)
1151 int num_to_alloc = iNumServices + 1;
1152 struct param_opt *data, *pdata;
1154 tservice = *pservice;
1156 /* it might already exist */
1158 i = getservicebyname(name, NULL);
1160 /* Clean all parametric options for service */
1161 /* They will be added during parsing again */
1162 data = ServicePtrs[i]->param_opt;
1164 string_free(&data->key);
1165 string_free(&data->value);
1170 ServicePtrs[i]->param_opt = NULL;
1175 /* find an invalid one */
1176 for (i = 0; i < iNumServices; i++)
1177 if (!ServicePtrs[i]->valid)
1180 /* if not, then create one */
1181 if (i == iNumServices) {
1184 tsp = realloc_p(ServicePtrs, service *, num_to_alloc);
1187 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1192 ServicePtrs[iNumServices] = malloc_p(service);
1194 if (!ServicePtrs[iNumServices]) {
1195 DEBUG(0,("add_a_service: out of memory!\n"));
1201 free_service(ServicePtrs[i]);
1203 ServicePtrs[i]->valid = True;
1205 init_service(ServicePtrs[i]);
1206 copy_service(ServicePtrs[i], &tservice, NULL);
1208 string_set(&ServicePtrs[i]->szService, name);
1212 /***************************************************************************
1213 Add a new home service, with the specified home directory, defaults coming
1215 ***************************************************************************/
1217 BOOL lp_add_home(const char *pszHomename, int iDefaultService,
1218 const char *user, const char *pszHomedir)
1223 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1228 if (!(*(ServicePtrs[iDefaultService]->szPath))
1229 || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(-1))) {
1230 pstrcpy(newHomedir, pszHomedir);
1232 pstrcpy(newHomedir, lp_pathname(iDefaultService));
1233 string_sub(newHomedir,"%H", pszHomedir, sizeof(newHomedir));
1236 string_set(&ServicePtrs[i]->szPath, newHomedir);
1238 if (!(*(ServicePtrs[i]->comment))) {
1240 slprintf(comment, sizeof(comment) - 1,
1241 "Home directory of %s", user);
1242 string_set(&ServicePtrs[i]->comment, comment);
1244 ServicePtrs[i]->bAvailable = sDefault.bAvailable;
1245 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1247 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1253 /***************************************************************************
1254 Add a new service, based on an old one.
1255 ***************************************************************************/
1257 int lp_add_service(const char *pszService, int iDefaultService)
1259 return (add_a_service(ServicePtrs[iDefaultService], pszService));
1262 /***************************************************************************
1263 Add the IPC service.
1264 ***************************************************************************/
1266 static BOOL lp_add_hidden(const char *name, const char *fstype)
1269 int i = add_a_service(&sDefault, name);
1274 slprintf(comment, sizeof(comment) - 1,
1275 "%s Service (%s)", fstype, Globals.szServerString);
1277 string_set(&ServicePtrs[i]->szPath, tmpdir());
1278 string_set(&ServicePtrs[i]->comment, comment);
1279 string_set(&ServicePtrs[i]->fstype, fstype);
1280 ServicePtrs[i]->iMaxConnections = -1;
1281 ServicePtrs[i]->bAvailable = True;
1282 ServicePtrs[i]->bRead_only = True;
1283 ServicePtrs[i]->bPrint_ok = False;
1284 ServicePtrs[i]->bBrowseable = False;
1286 if (strcasecmp(fstype, "IPC") == 0) {
1287 lp_do_parameter(i, "ntvfs handler", "default");
1290 DEBUG(3, ("adding hidden service %s\n", name));
1295 /***************************************************************************
1296 Add a new printer service, with defaults coming from service iFrom.
1297 ***************************************************************************/
1299 BOOL lp_add_printer(const char *pszPrintername, int iDefaultService)
1301 const char *comment = "From Printcap";
1302 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1307 /* note that we do NOT default the availability flag to True - */
1308 /* we take it from the default service passed. This allows all */
1309 /* dynamic printers to be disabled by disabling the [printers] */
1310 /* entry (if/when the 'available' keyword is implemented!). */
1312 /* the printer name is set to the service name. */
1313 string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1314 string_set(&ServicePtrs[i]->comment, comment);
1315 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1316 /* Printers cannot be read_only. */
1317 ServicePtrs[i]->bRead_only = False;
1318 /* Printer services must be printable. */
1319 ServicePtrs[i]->bPrint_ok = True;
1321 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1323 update_server_announce_as_printserver();
1328 /***************************************************************************
1329 Map a parameter's string representation to something we can use.
1330 Returns False if the parameter string is not recognised, else TRUE.
1331 ***************************************************************************/
1333 static int map_parameter(const char *pszParmName)
1337 if (*pszParmName == '-')
1340 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1341 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1344 /* Warn only if it isn't parametric option */
1345 if (strchr(pszParmName, ':') == NULL)
1346 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1347 /* We do return 'fail' for parametric options as well because they are
1348 stored in different storage
1355 return the parameter structure for a parameter
1357 struct parm_struct *lp_parm_struct(const char *name)
1359 int parmnum = map_parameter(name);
1360 if (parmnum == -1) return NULL;
1361 return &parm_table[parmnum];
1365 return the parameter pointer for a parameter
1367 void *lp_parm_ptr(int snum, struct parm_struct *parm)
1372 return ((char *)ServicePtrs[snum]) + PTR_DIFF(parm->ptr, &sDefault);
1375 /***************************************************************************
1376 Find a service by name. Otherwise works like get_service.
1377 ***************************************************************************/
1379 static int getservicebyname(const char *pszServiceName, service * pserviceDest)
1383 for (iService = iNumServices - 1; iService >= 0; iService--)
1384 if (VALID(iService) &&
1385 strwicmp(ServicePtrs[iService]->szService, pszServiceName) == 0) {
1386 if (pserviceDest != NULL)
1387 copy_service(pserviceDest, ServicePtrs[iService], NULL);
1394 /***************************************************************************
1395 Copy a service structure to another.
1396 If pcopymapDest is NULL then copy all fields
1397 ***************************************************************************/
1399 static void copy_service(service * pserviceDest, service * pserviceSource, BOOL *pcopymapDest)
1402 BOOL bcopyall = (pcopymapDest == NULL);
1403 struct param_opt *data, *pdata, *paramo;
1406 for (i = 0; parm_table[i].label; i++)
1407 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1408 (bcopyall || pcopymapDest[i])) {
1409 void *def_ptr = parm_table[i].ptr;
1411 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
1414 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
1417 switch (parm_table[i].type) {
1419 *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
1424 *(int *)dest_ptr = *(int *)src_ptr;
1428 string_set(dest_ptr,
1433 string_set(dest_ptr,
1435 strupper(*(char **)dest_ptr);
1438 *(const char ***)dest_ptr = str_list_copy(talloc_autofree_context(),
1439 *(const char ***)src_ptr);
1447 init_copymap(pserviceDest);
1448 if (pserviceSource->copymap)
1449 memcpy((void *)pserviceDest->copymap,
1450 (void *)pserviceSource->copymap,
1451 sizeof(BOOL) * NUMPARAMETERS);
1454 data = pserviceSource->param_opt;
1457 pdata = pserviceDest->param_opt;
1458 /* Traverse destination */
1460 /* If we already have same option, override it */
1461 if (strcmp(pdata->key, data->key) == 0) {
1462 string_free(&pdata->value);
1463 pdata->value = strdup(data->value);
1467 pdata = pdata->next;
1470 paramo = malloc_p(struct param_opt);
1473 paramo->key = strdup(data->key);
1474 paramo->value = strdup(data->value);
1475 DLIST_ADD(pserviceDest->param_opt, paramo);
1481 /***************************************************************************
1482 Check a service for consistency. Return False if the service is in any way
1483 incomplete or faulty, else True.
1484 ***************************************************************************/
1486 static BOOL service_ok(int iService)
1491 if (ServicePtrs[iService]->szService[0] == '\0') {
1492 DEBUG(0, ("The following message indicates an internal error:\n"));
1493 DEBUG(0, ("No service name in service entry.\n"));
1497 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1498 /* I can't see why you'd want a non-printable printer service... */
1499 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
1500 if (!ServicePtrs[iService]->bPrint_ok) {
1501 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
1502 ServicePtrs[iService]->szService));
1503 ServicePtrs[iService]->bPrint_ok = True;
1504 update_server_announce_as_printserver();
1506 /* [printers] service must also be non-browsable. */
1507 if (ServicePtrs[iService]->bBrowseable)
1508 ServicePtrs[iService]->bBrowseable = False;
1511 /* If a service is flagged unavailable, log the fact at level 0. */
1512 if (!ServicePtrs[iService]->bAvailable)
1513 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
1514 ServicePtrs[iService]->szService));
1519 static struct file_lists {
1520 struct file_lists *next;
1524 } *file_lists = NULL;
1526 /*******************************************************************
1527 Keep a linked list of all config files so we know when one has changed
1528 it's date and needs to be reloaded.
1529 ********************************************************************/
1531 static void add_to_file_list(const char *fname, const char *subfname)
1533 struct file_lists *f = file_lists;
1536 if (f->name && !strcmp(f->name, fname))
1542 f = malloc_p(struct file_lists);
1545 f->next = file_lists;
1546 f->name = strdup(fname);
1551 f->subfname = strdup(subfname);
1557 f->modtime = file_modtime(subfname);
1559 time_t t = file_modtime(subfname);
1565 /*******************************************************************
1566 Check if a config file has changed date.
1567 ********************************************************************/
1569 BOOL lp_file_list_changed(void)
1571 struct file_lists *f = file_lists;
1572 DEBUG(6, ("lp_file_list_changed()\n"));
1578 pstrcpy(n2, f->name);
1579 standard_sub_basic(n2,sizeof(n2));
1581 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
1582 f->name, n2, ctime(&f->modtime)));
1584 mod_time = file_modtime(n2);
1586 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
1588 ("file %s modified: %s\n", n2,
1590 f->modtime = mod_time;
1591 SAFE_FREE(f->subfname);
1592 f->subfname = strdup(n2);
1600 /***************************************************************************
1601 Handle the include operation.
1602 ***************************************************************************/
1604 static BOOL handle_include(const char *pszParmValue, char **ptr)
1607 pstrcpy(fname, pszParmValue);
1609 standard_sub_basic(fname,sizeof(fname));
1611 add_to_file_list(pszParmValue, fname);
1613 string_set(ptr, fname);
1615 if (file_exist(fname))
1616 return (pm_process(fname, do_section, do_parameter, NULL));
1618 DEBUG(2, ("Can't find include file %s\n", fname));
1623 /***************************************************************************
1624 Handle the interpretation of the copy parameter.
1625 ***************************************************************************/
1627 static BOOL handle_copy(const char *pszParmValue, char **ptr)
1631 service serviceTemp;
1633 string_set(ptr, pszParmValue);
1635 init_service(&serviceTemp);
1639 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
1641 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
1642 if (iTemp == iServiceIndex) {
1643 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
1645 copy_service(ServicePtrs[iServiceIndex],
1647 ServicePtrs[iServiceIndex]->copymap);
1651 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
1655 free_service(&serviceTemp);
1659 /***************************************************************************
1660 Initialise a copymap.
1661 ***************************************************************************/
1663 static void init_copymap(service * pservice)
1666 SAFE_FREE(pservice->copymap);
1667 pservice->copymap = malloc_array_p(BOOL, NUMPARAMETERS);
1668 if (!pservice->copymap)
1670 ("Couldn't allocate copymap!! (size %d)\n",
1671 (int)NUMPARAMETERS));
1673 for (i = 0; i < NUMPARAMETERS; i++)
1674 pservice->copymap[i] = True;
1677 /***************************************************************************
1678 Return the local pointer to a parameter given the service number and the
1679 pointer into the default structure.
1680 ***************************************************************************/
1682 void *lp_local_ptr(int snum, void *ptr)
1684 return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
1688 /***************************************************************************
1689 Process a parametric option
1690 ***************************************************************************/
1691 static BOOL lp_do_parameter_parametric(int snum, const char *pszParmName, const char *pszParmValue, int flags)
1693 struct param_opt *paramo, *data;
1696 while (isspace((unsigned char)*pszParmName)) {
1700 name = strdup(pszParmName);
1701 if (!name) return False;
1706 data = Globals.param_opt;
1708 data = ServicePtrs[snum]->param_opt;
1711 /* Traverse destination */
1712 for (paramo=data; paramo; paramo=paramo->next) {
1713 /* If we already have the option set, override it unless
1714 it was a command line option and the new one isn't */
1715 if (strcmp(paramo->key, name) == 0) {
1716 if ((paramo->flags & FLAG_CMDLINE) &&
1717 !(flags & FLAG_CMDLINE)) {
1721 free(paramo->value);
1722 paramo->value = strdup(pszParmValue);
1723 paramo->flags = flags;
1729 paramo = malloc_p(struct param_opt);
1732 paramo->key = strdup(name);
1733 paramo->value = strdup(pszParmValue);
1734 paramo->flags = flags;
1736 DLIST_ADD(Globals.param_opt, paramo);
1738 DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
1746 /***************************************************************************
1747 Process a parameter for a particular service number. If snum < 0
1748 then assume we are in the globals.
1749 ***************************************************************************/
1750 BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
1753 void *parm_ptr = NULL; /* where we are going to store the result */
1754 void *def_ptr = NULL;
1756 parmnum = map_parameter(pszParmName);
1759 if (strchr(pszParmName, ':')) {
1760 return lp_do_parameter_parametric(snum, pszParmName, pszParmValue, 0);
1762 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1766 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1767 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1771 /* if the flag has been set on the command line, then don't allow override,
1772 but don't report an error */
1773 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1777 def_ptr = parm_table[parmnum].ptr;
1779 /* we might point at a service, the default service or a global */
1783 if (parm_table[parmnum].class == P_GLOBAL) {
1785 ("Global parameter %s found in service section!\n",
1790 ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
1795 if (!ServicePtrs[snum]->copymap)
1796 init_copymap(ServicePtrs[snum]);
1798 /* this handles the aliases - set the copymap for other entries with
1799 the same data pointer */
1800 for (i = 0; parm_table[i].label; i++)
1801 if (parm_table[i].ptr == parm_table[parmnum].ptr)
1802 ServicePtrs[snum]->copymap[i] = False;
1805 /* if it is a special case then go ahead */
1806 if (parm_table[parmnum].special) {
1807 parm_table[parmnum].special(pszParmValue, (char **)parm_ptr);
1811 /* now switch on the type of variable it is */
1812 switch (parm_table[parmnum].type)
1815 if (!set_boolean(pszParmValue, parm_ptr)) {
1816 DEBUG(0,("lp_do_parameter(%s): value is not boolean!\n", pszParmValue));
1822 *(int *)parm_ptr = atoi(pszParmValue);
1826 *(const char ***)parm_ptr = str_list_make(talloc_autofree_context(),
1827 pszParmValue, NULL);
1831 string_set(parm_ptr, pszParmValue);
1835 string_set(parm_ptr, pszParmValue);
1836 strupper(*(char **)parm_ptr);
1840 for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
1843 parm_table[parmnum].enum_list[i].name)) {
1845 parm_table[parmnum].
1850 if (!parm_table[parmnum].enum_list[i].name) {
1851 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n",
1852 pszParmValue, pszParmName));
1860 if (parm_table[parmnum].flags & FLAG_DEFAULT) {
1861 parm_table[parmnum].flags &= ~FLAG_DEFAULT;
1862 /* we have to also unset FLAG_DEFAULT on aliases */
1863 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1864 parm_table[i].flags &= ~FLAG_DEFAULT;
1866 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1867 parm_table[i].flags &= ~FLAG_DEFAULT;
1874 /***************************************************************************
1875 Process a parameter.
1876 ***************************************************************************/
1878 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue, void *userdata)
1880 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
1881 pszParmName, pszParmValue));
1885 variable argument do parameter
1887 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
1889 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...)
1896 s = talloc_vasprintf(NULL, fmt, ap);
1898 ret = do_parameter(pszParmName, s, NULL);
1905 set a parameter from the commandline - this is called from command line parameter
1906 parsing code. It sets the parameter then marks the parameter as unable to be modified
1907 by smb.conf processing
1909 BOOL lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
1911 int parmnum = map_parameter(pszParmName);
1914 while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
1917 if (parmnum < 0 && strchr(pszParmName, ':')) {
1918 /* set a parametric option */
1919 return lp_do_parameter_parametric(-1, pszParmName, pszParmValue, FLAG_CMDLINE);
1923 DEBUG(0,("Unknown option '%s'\n", pszParmName));
1927 /* reset the CMDLINE flag in case this has been called before */
1928 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
1930 if (!lp_do_parameter(-2, pszParmName, pszParmValue)) {
1934 parm_table[parmnum].flags |= FLAG_CMDLINE;
1936 /* we have to also set FLAG_CMDLINE on aliases */
1937 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1938 parm_table[i].flags |= FLAG_CMDLINE;
1940 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1941 parm_table[i].flags |= FLAG_CMDLINE;
1948 set a option from the commandline in 'a=b' format. Use to support --option
1950 BOOL lp_set_option(const char *option)
1968 ret = lp_set_cmdline(s, p+1);
1974 #define BOOLSTR(b) ((b) ? "Yes" : "No")
1976 /***************************************************************************
1977 Print a parameter of the specified type.
1978 ***************************************************************************/
1980 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
1986 for (i = 0; p->enum_list[i].name; i++) {
1987 if (*(int *)ptr == p->enum_list[i].value) {
1989 p->enum_list[i].name);
1996 fprintf(f, "%s", BOOLSTR(*(BOOL *)ptr));
2000 fprintf(f, "%d", *(int *)ptr);
2004 if ((char ***)ptr && *(char ***)ptr) {
2005 char **list = *(char ***)ptr;
2007 for (; *list; list++)
2008 fprintf(f, "%s%s", *list,
2009 ((*(list+1))?", ":""));
2015 if (*(char **)ptr) {
2016 fprintf(f, "%s", *(char **)ptr);
2024 /***************************************************************************
2025 Check if two parameters are equal.
2026 ***************************************************************************/
2028 static BOOL equal_parameter(parm_type type, void *ptr1, void *ptr2)
2032 return (*((BOOL *)ptr1) == *((BOOL *)ptr2));
2036 return (*((int *)ptr1) == *((int *)ptr2));
2039 return str_list_equal((const char **)(*(char ***)ptr1),
2040 (const char **)(*(char ***)ptr2));
2045 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
2050 return (p1 == p2 || strequal(p1, p2));
2058 /***************************************************************************
2059 Process a new section (service). At this stage all sections are services.
2060 Later we'll have special sections that permit server parameters to be set.
2061 Returns True on success, False on failure.
2062 ***************************************************************************/
2064 static BOOL do_section(const char *pszSectionName, void *userdata)
2067 BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2068 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2071 /* if we've just struck a global section, note the fact. */
2072 bInGlobalSection = isglobal;
2074 /* check for multiple global sections */
2075 if (bInGlobalSection) {
2076 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2080 /* if we have a current service, tidy it up before moving on */
2083 if (iServiceIndex >= 0)
2084 bRetval = service_ok(iServiceIndex);
2086 /* if all is still well, move to the next record in the services array */
2088 /* We put this here to avoid an odd message order if messages are */
2089 /* issued by the post-processing of a previous section. */
2090 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2092 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
2094 DEBUG(0, ("Failed to add a new service\n"));
2103 /***************************************************************************
2104 Determine if a partcular base parameter is currentl set to the default value.
2105 ***************************************************************************/
2107 static BOOL is_default(int i)
2109 if (!defaults_saved)
2111 switch (parm_table[i].type) {
2113 return str_list_equal((const char **)parm_table[i].def.lvalue,
2114 (const char **)(*(char ***)parm_table[i].ptr));
2117 return strequal(parm_table[i].def.svalue,
2118 *(char **)parm_table[i].ptr);
2120 return parm_table[i].def.bvalue ==
2121 *(BOOL *)parm_table[i].ptr;
2124 return parm_table[i].def.ivalue ==
2125 *(int *)parm_table[i].ptr;
2132 /***************************************************************************
2133 Display the contents of the global structure.
2134 ***************************************************************************/
2136 static void dump_globals(FILE *f, BOOL show_defaults)
2139 struct param_opt *data;
2141 fprintf(f, "# Global parameters\n[global]\n");
2143 for (i = 0; parm_table[i].label; i++)
2144 if (parm_table[i].class == P_GLOBAL &&
2145 parm_table[i].ptr &&
2146 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2147 if (!show_defaults && (parm_table[i].flags & FLAG_DEFAULT))
2149 fprintf(f, "\t%s = ", parm_table[i].label);
2150 print_parameter(&parm_table[i], parm_table[i].ptr, f);
2153 if (Globals.param_opt != NULL) {
2154 data = Globals.param_opt;
2156 fprintf(f, "\t%s = %s\n", data->key, data->value);
2163 /***************************************************************************
2164 Display the contents of a single services record.
2165 ***************************************************************************/
2167 static void dump_a_service(service * pService, FILE * f)
2170 struct param_opt *data;
2172 if (pService != &sDefault)
2173 fprintf(f, "\n[%s]\n", pService->szService);
2175 for (i = 0; parm_table[i].label; i++)
2176 if (parm_table[i].class == P_LOCAL &&
2177 parm_table[i].ptr &&
2178 (*parm_table[i].label != '-') &&
2179 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2180 int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
2182 if (pService == &sDefault) {
2183 if (defaults_saved && is_default(i))
2186 if (equal_parameter(parm_table[i].type,
2187 ((char *)pService) +
2189 ((char *)&sDefault) +
2194 fprintf(f, "\t%s = ", parm_table[i].label);
2195 print_parameter(&parm_table[i],
2196 ((char *)pService) + pdiff, f);
2199 if (pService->param_opt != NULL) {
2200 data = pService->param_opt;
2202 fprintf(f, "\t%s = %s\n", data->key, data->value);
2208 BOOL lp_dump_a_parameter(int snum, char *parm_name, FILE * f, BOOL isGlobal)
2210 service * pService = ServicePtrs[snum];
2213 struct parm_struct *parm;
2221 parm = lp_parm_struct(parm_name);
2229 ptr = ((char *)pService) +
2230 PTR_DIFF(parm->ptr, &sDefault);
2232 print_parameter(parm,
2238 /***************************************************************************
2239 Return info about the next service in a service. snum==-1 gives the globals.
2240 Return NULL when out of parameters.
2241 ***************************************************************************/
2243 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
2246 /* do the globals */
2247 for (; parm_table[*i].label; (*i)++) {
2248 if (parm_table[*i].class == P_SEPARATOR)
2249 return &parm_table[(*i)++];
2251 if (!parm_table[*i].ptr
2252 || (*parm_table[*i].label == '-'))
2256 && (parm_table[*i].ptr ==
2257 parm_table[(*i) - 1].ptr))
2260 return &parm_table[(*i)++];
2263 service *pService = ServicePtrs[snum];
2265 for (; parm_table[*i].label; (*i)++) {
2266 if (parm_table[*i].class == P_SEPARATOR)
2267 return &parm_table[(*i)++];
2269 if (parm_table[*i].class == P_LOCAL &&
2270 parm_table[*i].ptr &&
2271 (*parm_table[*i].label != '-') &&
2273 (parm_table[*i].ptr !=
2274 parm_table[(*i) - 1].ptr)))
2277 PTR_DIFF(parm_table[*i].ptr,
2280 if (allparameters ||
2281 !equal_parameter(parm_table[*i].type,
2282 ((char *)pService) +
2284 ((char *)&sDefault) +
2287 return &parm_table[(*i)++];
2297 /***************************************************************************
2298 Return TRUE if the passed service number is within range.
2299 ***************************************************************************/
2301 BOOL lp_snum_ok(int iService)
2303 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
2306 /***************************************************************************
2307 Auto-load some home services.
2308 ***************************************************************************/
2310 static void lp_add_auto_services(const char *str)
2315 /***************************************************************************
2316 Announce ourselves as a print server.
2317 ***************************************************************************/
2319 void update_server_announce_as_printserver(void)
2321 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
2324 /***************************************************************************
2325 Have we loaded a services file yet?
2326 ***************************************************************************/
2328 BOOL lp_loaded(void)
2333 /***************************************************************************
2334 Unload unused services.
2335 ***************************************************************************/
2337 void lp_killunused(struct smbsrv_connection *smb, BOOL (*snumused) (struct smbsrv_connection *, int))
2340 for (i = 0; i < iNumServices; i++) {
2344 if (!snumused || !snumused(smb, i)) {
2345 ServicePtrs[i]->valid = False;
2346 free_service(ServicePtrs[i]);
2351 /***************************************************************************
2353 ***************************************************************************/
2355 void lp_killservice(int iServiceIn)
2357 if (VALID(iServiceIn)) {
2358 ServicePtrs[iServiceIn]->valid = False;
2359 free_service(ServicePtrs[iServiceIn]);
2363 /***************************************************************************
2364 Load the services array from the services file. Return True on success,
2366 ***************************************************************************/
2372 struct param_opt *data;
2376 bInGlobalSection = True;
2378 if (Globals.param_opt != NULL) {
2379 struct param_opt *next;
2380 for (data=Globals.param_opt; data; data=next) {
2382 if (data->flags & FLAG_CMDLINE) continue;
2385 DLIST_REMOVE(Globals.param_opt, data);
2392 pstrcpy(n2, lp_configfile());
2393 standard_sub_basic(n2,sizeof(n2));
2394 DEBUG(2, ("lp_load: refreshing parameters from %s\n", n2));
2396 add_to_file_list(lp_configfile(), n2);
2398 /* We get sections first, so have to start 'behind' to make up */
2400 bRetval = pm_process(n2, do_section, do_parameter, NULL);
2402 /* finish up the last section */
2403 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
2405 if (iServiceIndex >= 0)
2406 bRetval = service_ok(iServiceIndex);
2408 lp_add_auto_services(lp_auto_services());
2410 lp_add_hidden("IPC$", "IPC");
2411 lp_add_hidden("ADMIN$", "DISK");
2413 set_default_server_announce_type();
2417 if (!Globals.szWINSservers && Globals.bWINSsupport) {
2418 lp_do_parameter(-1, "wins server", "127.0.0.1");
2426 /***************************************************************************
2427 Reset the max number of services.
2428 ***************************************************************************/
2430 void lp_resetnumservices(void)
2435 /***************************************************************************
2436 Return the max number of services.
2437 ***************************************************************************/
2439 int lp_numservices(void)
2441 return (iNumServices);
2444 /***************************************************************************
2445 Display the contents of the services array in human-readable form.
2446 ***************************************************************************/
2448 void lp_dump(FILE *f, BOOL show_defaults, int maxtoprint)
2453 defaults_saved = False;
2455 dump_globals(f, show_defaults);
2457 dump_a_service(&sDefault, f);
2459 for (iService = 0; iService < maxtoprint; iService++)
2460 lp_dump_one(f, show_defaults, iService);
2463 /***************************************************************************
2464 Display the contents of one service in human-readable form.
2465 ***************************************************************************/
2467 void lp_dump_one(FILE * f, BOOL show_defaults, int snum)
2470 if (ServicePtrs[snum]->szService[0] == '\0')
2472 dump_a_service(ServicePtrs[snum], f);
2476 /***************************************************************************
2477 Return the number of the service with the given name, or -1 if it doesn't
2478 exist. Note that this is a DIFFERENT ANIMAL from the internal function
2479 getservicebyname()! This works ONLY if all services have been loaded, and
2480 does not copy the found service.
2481 ***************************************************************************/
2483 int lp_servicenumber(const char *pszServiceName)
2486 fstring serviceName;
2489 for (iService = iNumServices - 1; iService >= 0; iService--) {
2490 if (VALID(iService) && ServicePtrs[iService]->szService) {
2492 * The substitution here is used to support %U is
2495 fstrcpy(serviceName, ServicePtrs[iService]->szService);
2496 standard_sub_basic(serviceName,sizeof(serviceName));
2497 if (strequal(serviceName, pszServiceName))
2503 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
2508 /*******************************************************************
2509 A useful volume label function.
2510 ********************************************************************/
2511 const char *volume_label(int snum)
2513 const char *ret = lp_volume(snum);
2515 return lp_servicename(snum);
2520 /*******************************************************************
2521 Set the server type we will announce as via nmbd.
2522 ********************************************************************/
2524 static void set_default_server_announce_type(void)
2526 default_server_announce = 0;
2527 default_server_announce |= SV_TYPE_WORKSTATION;
2528 default_server_announce |= SV_TYPE_SERVER;
2529 default_server_announce |= SV_TYPE_SERVER_UNIX;
2531 switch (lp_announce_as()) {
2532 case ANNOUNCE_AS_NT_SERVER:
2533 default_server_announce |= SV_TYPE_SERVER_NT;
2534 /* fall through... */
2535 case ANNOUNCE_AS_NT_WORKSTATION:
2536 default_server_announce |= SV_TYPE_NT;
2538 case ANNOUNCE_AS_WIN95:
2539 default_server_announce |= SV_TYPE_WIN95_PLUS;
2541 case ANNOUNCE_AS_WFW:
2542 default_server_announce |= SV_TYPE_WFW;
2548 switch (lp_server_role()) {
2549 case ROLE_DOMAIN_MEMBER:
2550 default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
2552 case ROLE_DOMAIN_PDC:
2553 default_server_announce |= SV_TYPE_DOMAIN_CTRL;
2555 case ROLE_DOMAIN_BDC:
2556 default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
2558 case ROLE_STANDALONE:
2562 if (lp_time_server())
2563 default_server_announce |= SV_TYPE_TIME_SOURCE;
2565 if (lp_host_msdfs())
2566 default_server_announce |= SV_TYPE_DFS_SERVER;
2568 /* TODO: only announce us as print server when we are a print server */
2569 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
2572 /***********************************************************
2573 If we are PDC then prefer us as DMB
2574 ************************************************************/
2576 BOOL lp_domain_master(void)
2578 return (lp_server_role() == ROLE_DOMAIN_PDC);
2581 /***********************************************************
2582 If we are PDC then prefer us as DMB
2583 ************************************************************/
2585 BOOL lp_domain_logons(void)
2587 return (lp_server_role() == ROLE_DOMAIN_PDC) || (lp_server_role() == ROLE_DOMAIN_BDC);
2590 /***********************************************************
2591 If we are DMB then prefer us as LMB
2592 ************************************************************/
2594 BOOL lp_preferred_master(void)
2596 return (lp_local_master() && lp_domain_master());
2599 /*******************************************************************
2601 ********************************************************************/
2603 void lp_remove_service(int snum)
2605 ServicePtrs[snum]->valid = False;
2608 /*******************************************************************
2610 ********************************************************************/
2612 void lp_copy_service(int snum, const char *new_name)
2614 const char *oldname = lp_servicename(snum);
2615 do_section(new_name, NULL);
2617 snum = lp_servicenumber(new_name);
2619 lp_do_parameter(snum, "copy", oldname);
2624 /*******************************************************************
2625 Get the default server type we will announce as via nmbd.
2626 ********************************************************************/
2627 int lp_default_server_announce(void)
2629 return default_server_announce;
2632 const char *lp_printername(int snum)
2634 const char *ret = _lp_printername(snum);
2635 if (ret == NULL || (ret != NULL && *ret == '\0'))
2636 ret = lp_const_servicename(snum);
2642 /*******************************************************************
2643 Return the max print jobs per queue.
2644 ********************************************************************/
2646 int lp_maxprintjobs(int snum)
2648 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
2649 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
2650 maxjobs = PRINT_MAX_JOBID - 1;