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/locale.h"
62 #include "system/network.h" /* needed for TCP_NODELAY */
63 #include "librpc/gen_ndr/svcctl.h"
64 #include "librpc/gen_ndr/samr.h"
65 #include "smb_server/smb_server.h"
66 #include "libcli/raw/signing.h"
67 #include "dlinklist.h"
68 #include "param/loadparm.h"
70 static BOOL bLoaded = False;
72 #define standard_sub_basic(str,len)
74 /* some helpful bits */
75 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && ServicePtrs[(i)]->valid)
76 #define VALID(i) ServicePtrs[i]->valid
78 static BOOL do_parameter(const char *, const char *, void *);
79 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...);
81 static BOOL defaults_saved = False;
85 struct param_opt *prev, *next;
92 * This structure describes global (ie., server-wide) parameters.
102 char *display_charset;
107 char *szServerString;
108 char *szAutoServices;
111 char *szShareBackend;
114 char *szWINS_CONFIG_URL;
118 char **szPasswordServers;
119 char *szSocketOptions;
121 char **szWINSservers;
123 char *szSocketAddress;
124 char *szAnnounceVersion; /* This is initialised in init_globals */
127 char **szNetbiosAliases;
128 char *szNetbiosScope;
129 char *szDomainOtherSIDs;
130 char **szNameResolveOrder;
131 char **dcerpc_ep_servers;
132 char **server_services;
133 char *ntptr_providor;
134 char *szWinbindSeparator;
135 char *szWinbinddSocketDirectory;
136 int bWinbindSealedPipes;
137 char *swat_directory;
153 int paranoid_server_security;
156 int announce_as; /* This is initialised in init_globals */
163 char *socket_options;
168 int bPreferredMaster;
169 int bEncryptPasswords;
171 int bObeyPamRestrictions;
176 int bBindInterfacesOnly;
178 int bNTStatusSupport;
184 int bClientPlaintextAuth;
185 int bClientLanManAuth;
186 int bClientNTLMv2Auth;
187 int client_use_spnego_principal;
193 struct param_opt *param_opt;
197 static global Globals;
200 * This structure describes a single service.
215 char **ntvfs_handler;
231 struct param_opt *param_opt;
233 char dummy[3]; /* for alignment */
238 /* This is a default service used to prime a services structure */
239 static service sDefault = {
241 NULL, /* szService */
244 NULL, /* szInclude */
245 NULL, /* szPrintername */
246 NULL, /* szHostsallow */
247 NULL, /* szHostsdeny */
251 NULL, /* ntvfs_handler */
252 1000, /* iMaxPrintJobs */
253 0, /* iMaxConnections */
255 True, /* bAvailable */
256 True, /* bBrowseable */
257 True, /* bRead_only */
258 False, /* bPrint_ok */
259 False, /* bMap_system */
260 False, /* bMap_hidden */
261 True, /* bMap_archive */
262 True, /* bStrictLocking */
264 False, /* bMSDfsRoot */
265 False, /* bStrictSync */
266 False, /* bCIFileSystem */
267 NULL, /* Parametric options */
272 /* local variables */
273 static service **ServicePtrs = NULL;
274 static int iNumServices = 0;
275 static int iServiceIndex = 0;
276 static BOOL bInGlobalSection = True;
277 static int default_server_announce;
279 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
281 /* prototypes for the special type handlers */
282 static BOOL handle_include(const char *pszParmValue, char **ptr);
283 static BOOL handle_copy(const char *pszParmValue, char **ptr);
285 static void set_default_server_announce_type(void);
287 static const struct enum_list enum_protocol[] = {
288 {PROTOCOL_SMB2, "SMB2"},
289 {PROTOCOL_NT1, "NT1"},
290 {PROTOCOL_LANMAN2, "LANMAN2"},
291 {PROTOCOL_LANMAN1, "LANMAN1"},
292 {PROTOCOL_CORE, "CORE"},
293 {PROTOCOL_COREPLUS, "COREPLUS"},
294 {PROTOCOL_COREPLUS, "CORE+"},
298 static const struct enum_list enum_security[] = {
299 {SEC_SHARE, "SHARE"},
304 /* Types of machine we can announce as. */
305 #define ANNOUNCE_AS_NT_SERVER 1
306 #define ANNOUNCE_AS_WIN95 2
307 #define ANNOUNCE_AS_WFW 3
308 #define ANNOUNCE_AS_NT_WORKSTATION 4
310 static const struct enum_list enum_announce_as[] = {
311 {ANNOUNCE_AS_NT_SERVER, "NT"},
312 {ANNOUNCE_AS_NT_SERVER, "NT Server"},
313 {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"},
314 {ANNOUNCE_AS_WIN95, "win95"},
315 {ANNOUNCE_AS_WFW, "WfW"},
319 static const struct enum_list enum_bool_auto[] = {
330 /* Client-side offline caching policy types */
331 #define CSC_POLICY_MANUAL 0
332 #define CSC_POLICY_DOCUMENTS 1
333 #define CSC_POLICY_PROGRAMS 2
334 #define CSC_POLICY_DISABLE 3
336 static const struct enum_list enum_csc_policy[] = {
337 {CSC_POLICY_MANUAL, "manual"},
338 {CSC_POLICY_DOCUMENTS, "documents"},
339 {CSC_POLICY_PROGRAMS, "programs"},
340 {CSC_POLICY_DISABLE, "disable"},
344 /* SMB signing types. */
345 static const struct enum_list enum_smb_signing_vals[] = {
346 {SMB_SIGNING_OFF, "No"},
347 {SMB_SIGNING_OFF, "False"},
348 {SMB_SIGNING_OFF, "0"},
349 {SMB_SIGNING_OFF, "Off"},
350 {SMB_SIGNING_OFF, "disabled"},
351 {SMB_SIGNING_SUPPORTED, "Yes"},
352 {SMB_SIGNING_SUPPORTED, "True"},
353 {SMB_SIGNING_SUPPORTED, "1"},
354 {SMB_SIGNING_SUPPORTED, "On"},
355 {SMB_SIGNING_SUPPORTED, "enabled"},
356 {SMB_SIGNING_REQUIRED, "required"},
357 {SMB_SIGNING_REQUIRED, "mandatory"},
358 {SMB_SIGNING_REQUIRED, "force"},
359 {SMB_SIGNING_REQUIRED, "forced"},
360 {SMB_SIGNING_REQUIRED, "enforced"},
361 {SMB_SIGNING_AUTO, "auto"},
365 static const struct enum_list enum_server_role[] = {
366 {ROLE_STANDALONE, "standalone"},
367 {ROLE_DOMAIN_MEMBER, "member server"},
368 {ROLE_DOMAIN_BDC, "bdc"},
369 {ROLE_DOMAIN_PDC, "pdc"},
374 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
376 * Note: We have a flag called FLAG_DEVELOPER but is not used at this time, it
377 * is implied in current control logic. This may change at some later time. A
378 * flag value of 0 means - show as development option only.
380 * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
381 * screen in SWAT. This is used to exclude parameters as well as to squash all
382 * parameters that have been duplicated by pseudonyms.
384 static struct parm_struct parm_table[] = {
385 {"Base Options", P_SEP, P_SEPARATOR},
387 {"server role", P_ENUM, P_GLOBAL, &Globals.server_role, NULL, enum_server_role, FLAG_BASIC},
389 {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
390 {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
391 {"ncalrpc dir", P_STRING, P_GLOBAL, &Globals.ncalrpc_dir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
392 {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
393 {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
394 {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
395 {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE},
396 {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkgroup, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
397 {"realm", P_STRING, P_GLOBAL, &Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
398 {"netbios name", P_USTRING, P_GLOBAL, &Globals.szNetbiosName, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
399 {"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
400 {"netbios scope", P_USTRING, P_GLOBAL, &Globals.szNetbiosScope, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
401 {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
402 {"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
403 {"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
404 {"ntvfs handler", P_LIST, P_LOCAL, &sDefault.ntvfs_handler, NULL, NULL, FLAG_ADVANCED},
405 {"ntptr providor", P_STRING, P_GLOBAL, &Globals.ntptr_providor, NULL, NULL, FLAG_ADVANCED},
406 {"dcerpc endpoint servers", P_LIST, P_GLOBAL, &Globals.dcerpc_ep_servers, NULL, NULL, FLAG_ADVANCED},
407 {"server services", P_LIST, P_GLOBAL, &Globals.server_services, NULL, NULL, FLAG_ADVANCED},
409 {"Security Options", P_SEP, P_SEPARATOR},
411 {"security", P_ENUM, P_GLOBAL, &Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
412 {"auth methods", P_LIST, P_GLOBAL, &Globals.AuthMethods, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
413 {"encrypt passwords", P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
414 {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
415 {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
416 {"password server", P_LIST, P_GLOBAL, &Globals.szPasswordServers, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
417 {"sam database", P_STRING, P_GLOBAL, &Globals.szSAM_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
418 {"spoolss database", P_STRING, P_GLOBAL, &Globals.szSPOOLSS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
419 {"wins config database", P_STRING, P_GLOBAL, &Globals.szWINS_CONFIG_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
420 {"wins database", P_STRING, P_GLOBAL, &Globals.szWINS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
421 {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
422 {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
423 {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
424 {"lanman auth", P_BOOL, P_GLOBAL, &Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
425 {"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
426 {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
427 {"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
428 {"client plaintext auth", P_BOOL, P_GLOBAL, &Globals.bClientPlaintextAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
429 {"client use spnego principal", P_BOOL, P_GLOBAL, &Globals.client_use_spnego_principal, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
431 {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE},
433 {"hosts allow", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
434 {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
436 {"Logging Options", P_SEP, P_SEPARATOR},
438 {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
439 {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_HIDE},
440 {"log file", P_STRING, P_GLOBAL, &logfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
442 {"Protocol Options", P_SEP, P_SEPARATOR},
444 {"smb ports", P_LIST, P_GLOBAL, &Globals.smb_ports, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
445 {"nbt port", P_INTEGER, P_GLOBAL, &Globals.nbt_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
446 {"dgram port", P_INTEGER, P_GLOBAL, &Globals.dgram_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
447 {"cldap port", P_INTEGER, P_GLOBAL, &Globals.cldap_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
448 {"krb5 port", P_INTEGER, P_GLOBAL, &Globals.krb5_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
449 {"kpasswd port", P_INTEGER, P_GLOBAL, &Globals.kpasswd_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
450 {"web port", P_INTEGER, P_GLOBAL, &Globals.web_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
451 {"tls enabled", P_BOOL, P_GLOBAL, &Globals.tls_enabled, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
452 {"tls keyfile", P_STRING, P_GLOBAL, &Globals.tls_keyfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
453 {"tls certfile", P_STRING, P_GLOBAL, &Globals.tls_certfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
454 {"tls cafile", P_STRING, P_GLOBAL, &Globals.tls_cafile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
455 {"tls crlfile", P_STRING, P_GLOBAL, &Globals.tls_crlfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
456 {"tls dh params file", P_STRING, P_GLOBAL, &Globals.tls_dhpfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
457 {"swat directory", P_STRING, P_GLOBAL, &Globals.swat_directory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
458 {"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, FLAG_DEVELOPER},
459 {"server max protocol", P_ENUM, P_GLOBAL, &Globals.srv_maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
460 {"server min protocol", P_ENUM, P_GLOBAL, &Globals.srv_minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
461 {"client max protocol", P_ENUM, P_GLOBAL, &Globals.cli_maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
462 {"client min protocol", P_ENUM, P_GLOBAL, &Globals.cli_minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
463 {"unicode", P_BOOL, P_GLOBAL, &Globals.bUnicode, NULL, NULL, FLAG_DEVELOPER},
464 {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL, NULL, FLAG_DEVELOPER},
465 {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL, NULL, FLAG_DEVELOPER},
466 {"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
468 {"nt status support", P_BOOL, P_GLOBAL, &Globals.bNTStatusSupport, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
470 {"announce version", P_STRING, P_GLOBAL, &Globals.szAnnounceVersion, NULL, NULL, FLAG_DEVELOPER},
471 {"announce as", P_ENUM, P_GLOBAL, &Globals.announce_as, NULL, enum_announce_as, FLAG_DEVELOPER},
472 {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
473 {"max xmit", P_BYTES, P_GLOBAL, &Globals.max_xmit, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
475 {"name resolve order", P_LIST, P_GLOBAL, &Globals.szNameResolveOrder, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
476 {"max wins ttl", P_INTEGER, P_GLOBAL, &Globals.max_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
477 {"min wins ttl", P_INTEGER, P_GLOBAL, &Globals.min_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
478 {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
479 {"unix extensions", P_BOOL, P_GLOBAL, &Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
480 {"use spnego", P_BOOL, P_GLOBAL, &Globals.bUseSpnego, NULL, NULL, FLAG_DEVELOPER},
481 {"server signing", P_ENUM, P_GLOBAL, &Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
482 {"client signing", P_ENUM, P_GLOBAL, &Globals.client_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
483 {"rpc big endian", P_BOOL, P_GLOBAL, &Globals.bRpcBigEndian, NULL, NULL, FLAG_DEVELOPER},
485 {"Tuning Options", P_SEP, P_SEPARATOR},
487 {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL, NULL, FLAG_SHARE},
488 {"paranoid server security", P_BOOL, P_GLOBAL, &Globals.paranoid_server_security, NULL, NULL, FLAG_DEVELOPER},
489 {"socket options", P_STRING, P_GLOBAL, &Globals.socket_options, NULL, NULL, FLAG_DEVELOPER},
491 {"strict sync", P_BOOL, P_LOCAL, &sDefault.bStrictSync, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
492 {"case insensitive filesystem", P_BOOL, P_LOCAL, &sDefault.bCIFileSystem, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
494 {"Printing Options", P_SEP, P_SEPARATOR},
496 {"max print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxPrintJobs, NULL, NULL, FLAG_PRINT},
497 {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_PRINT},
498 {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_HIDE},
500 {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_PRINT},
501 {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_HIDE},
503 {"Filename Handling", P_SEP, P_SEPARATOR},
505 {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
506 {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
507 {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
509 {"Domain Options", P_SEP, P_SEPARATOR},
511 {"Logon Options", P_SEP, P_SEPARATOR},
514 {"Browse Options", P_SEP, P_SEPARATOR},
516 {"preferred master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
517 {"prefered master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_HIDE},
518 {"local master", P_BOOL, P_GLOBAL, &Globals.bLocalMaster, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
519 {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
520 {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_HIDE},
522 {"WINS Options", P_SEP, P_SEPARATOR},
524 {"wins server", P_LIST, P_GLOBAL, &Globals.szWINSservers, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
525 {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
526 {"dns proxy", P_BOOL, P_GLOBAL, &Globals.bWINSdnsProxy, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
527 {"wins hook", P_STRING, P_GLOBAL, &Globals.szWINSHook, NULL, NULL, FLAG_ADVANCED},
529 {"Locking Options", P_SEP, P_SEPARATOR},
531 {"csc policy", P_ENUM, P_LOCAL, &sDefault.iCSCPolicy, NULL, enum_csc_policy, FLAG_SHARE | FLAG_GLOBAL},
533 {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
535 {"Miscellaneous Options", P_SEP, P_SEPARATOR},
537 {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE},
538 {"share backend", P_STRING, P_GLOBAL, &Globals.szShareBackend, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
539 {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
540 {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
541 {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_HIDE},
542 {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
543 {"modules dir", P_STRING, P_GLOBAL, &Globals.szModulesDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
544 {"pid directory", P_STRING, P_GLOBAL, &Globals.szPidDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
545 {"js include", P_LIST, P_GLOBAL, &Globals.jsInclude, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
546 {"setup directory", P_STRING, P_GLOBAL, &Globals.szSetupDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
548 {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL, NULL, FLAG_DEVELOPER},
549 {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL, NULL, FLAG_HIDE},
551 {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy, NULL, FLAG_HIDE},
552 {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include, NULL, FLAG_HIDE},
554 {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
555 {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_SHARE },
556 {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_SHARE},
558 {"panic action", P_STRING, P_GLOBAL, &panic_action, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
560 {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_SHARE},
561 {"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
562 {"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
563 {"winbindd socket directory", P_STRING, P_GLOBAL, &Globals.szWinbinddSocketDirectory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
564 {"winbind sealed pipes", P_BOOL, P_GLOBAL, &Globals.bWinbindSealedPipes, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
566 {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
571 return the parameter table
573 struct parm_struct *lp_parm_table(void)
578 /***************************************************************************
579 Initialise the global parameter structure.
580 ***************************************************************************/
581 static void init_globals(void)
586 DEBUG(3, ("Initialising global parameters\n"));
588 for (i = 0; parm_table[i].label; i++) {
589 if ((parm_table[i].type == P_STRING ||
590 parm_table[i].type == P_USTRING) &&
592 !(parm_table[i].flags & FLAG_CMDLINE)) {
593 string_set(parm_table[i].ptr, "");
597 do_parameter("config file", dyn_CONFIGFILE, NULL);
599 do_parameter("share backend", "classic", NULL);
601 do_parameter("server role", "standalone", NULL);
603 /* options that can be set on the command line must be initialised via
604 the slower do_parameter() to ensure that FLAG_CMDLINE is obeyed */
606 do_parameter("socket options", "TCP_NODELAY", NULL);
608 do_parameter("workgroup", DEFAULT_WORKGROUP, NULL);
609 myname = get_myname();
610 do_parameter("netbios name", myname, NULL);
612 do_parameter("name resolve order", "lmhosts wins host bcast", NULL);
614 do_parameter("fstype", FSTYPE_STRING, NULL);
615 do_parameter("ntvfs handler", "unixuid default", NULL);
616 do_parameter("max connections", "-1", NULL);
618 do_parameter("dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup", NULL);
619 do_parameter("server services", "smb rpc nbt wrepl ldap cldap web kdc winbind", NULL);
620 do_parameter("ntptr providor", "simple_ldb", NULL);
621 do_parameter("auth methods", "anonymous sam_ignoredomain", NULL);
622 do_parameter("private dir", dyn_PRIVATE_DIR, NULL);
623 do_parameter("sam database", "sam.ldb", NULL);
624 do_parameter("spoolss database", "spoolss.ldb", NULL);
625 do_parameter("wins config database", "wins_config.ldb", NULL);
626 do_parameter("wins database", "wins.ldb", NULL);
627 do_parameter("registry:HKEY_LOCAL_MACHINE", "hklm.ldb", NULL);
629 /* This hive should be dynamically generated by Samba using
630 data from the sam, but for the moment leave it in a tdb to
631 keep regedt32 from popping up an annoying dialog. */
632 do_parameter("registry:HKEY_USERS", "hku.ldb", NULL);
634 /* using UTF8 by default allows us to support all chars */
635 do_parameter("unix charset", "UTF8", NULL);
637 /* Use codepage 850 as a default for the dos character set */
638 do_parameter("dos charset", "CP850", NULL);
641 * Allow the default PASSWD_CHAT to be overridden in local.h.
643 do_parameter("passwd chat", DEFAULT_PASSWD_CHAT, NULL);
645 do_parameter("pid directory", dyn_PIDDIR, NULL);
646 do_parameter("lock dir", dyn_LOCKDIR, NULL);
647 do_parameter("modules dir", dyn_MODULESDIR, NULL);
648 do_parameter("ncalrpc dir", dyn_NCALRPCDIR, NULL);
650 do_parameter("socket address", "0.0.0.0", NULL);
651 do_parameter_var("server string", "Samba %s", SAMBA_VERSION_STRING);
653 do_parameter_var("announce version", "%d.%d",
654 DEFAULT_MAJOR_VERSION,
655 DEFAULT_MINOR_VERSION);
657 do_parameter("password server", "*", NULL);
659 do_parameter("max mux", "50", NULL);
660 do_parameter("max xmit", "12288", NULL);
661 do_parameter("password level", "0", NULL);
662 do_parameter("LargeReadwrite", "True", NULL);
663 do_parameter("server min protocol", "CORE", NULL);
664 do_parameter("server max protocol", "NT1", NULL);
665 do_parameter("client min protocol", "CORE", NULL);
666 do_parameter("client max protocol", "NT1", NULL);
667 do_parameter("security", "USER", NULL);
668 do_parameter("paranoid server security", "True", NULL);
669 do_parameter("EncryptPasswords", "True", NULL);
670 do_parameter("ReadRaw", "True", NULL);
671 do_parameter("WriteRaw", "True", NULL);
672 do_parameter("NullPasswords", "False", NULL);
673 do_parameter("ObeyPamRestrictions", "False", NULL);
674 do_parameter("announce as", "NT SERVER", NULL);
676 do_parameter("TimeServer", "False", NULL);
677 do_parameter("BindInterfacesOnly", "False", NULL);
678 do_parameter("Unicode", "True", NULL);
679 do_parameter("ClientLanManAuth", "True", NULL);
680 do_parameter("LanmanAuth", "True", NULL);
681 do_parameter("NTLMAuth", "True", NULL);
682 do_parameter("client use spnego principal", "False", NULL);
684 do_parameter("UnixExtensions", "False", NULL);
686 do_parameter("PreferredMaster", "Auto", NULL);
687 do_parameter("LocalMaster", "True", NULL);
689 do_parameter("wins support", "False", NULL);
690 do_parameter("dns proxy", "True", NULL);
692 do_parameter("winbind separator", "\\", NULL);
693 do_parameter("winbind sealed pipes", "True", NULL);
694 do_parameter("winbindd socket directory", dyn_WINBINDD_SOCKET_DIR, NULL);
696 do_parameter("client signing", "Yes", NULL);
697 do_parameter("server signing", "auto", NULL);
699 do_parameter("use spnego", "True", NULL);
701 do_parameter("smb ports", SMB_PORTS, NULL);
702 do_parameter("nbt port", "137", NULL);
703 do_parameter("dgram port", "138", NULL);
704 do_parameter("cldap port", "389", NULL);
705 do_parameter("krb5 port", "88", NULL);
706 do_parameter("kpasswd port", "464", NULL);
707 do_parameter("web port", "901", NULL);
708 do_parameter("swat directory", dyn_SWATDIR, NULL);
710 do_parameter("nt status support", "True", NULL);
712 do_parameter("max wins ttl", "518400", NULL); /* 6 days */
713 do_parameter("min wins ttl", "10", NULL);
715 do_parameter("tls enabled", "True", NULL);
716 do_parameter("tls keyfile", "tls/key.pem", NULL);
717 do_parameter("tls certfile", "tls/cert.pem", NULL);
718 do_parameter("tls cafile", "tls/ca.pem", NULL);
719 do_parameter_var("js include", "%s", dyn_JSDIR);
720 do_parameter_var("setup directory", "%s", dyn_SETUPDIR);
722 for (i = 0; parm_table[i].label; i++) {
723 if (!(parm_table[i].flags & FLAG_CMDLINE)) {
724 parm_table[i].flags |= FLAG_DEFAULT;
729 static TALLOC_CTX *lp_talloc;
731 /******************************************************************* a
732 Free up temporary memory - called from the main loop.
733 ********************************************************************/
735 void lp_talloc_free(void)
739 talloc_free(lp_talloc);
743 /*******************************************************************
744 Convenience routine to grab string parameters into temporary memory
745 and run standard_sub_basic on them. The buffers can be written to by
746 callers without affecting the source string.
747 ********************************************************************/
749 static const char *lp_string(const char *s)
751 #if 0 /* until REWRITE done to make thread-safe */
752 size_t len = s ? strlen(s) : 0;
756 /* The follow debug is useful for tracking down memory problems
757 especially if you have an inner loop that is calling a lp_*()
758 function that returns a string. Perhaps this debug should be
759 present all the time? */
762 DEBUG(10, ("lp_string(%s)\n", s));
765 #if 0 /* until REWRITE done to make thread-safe */
767 lp_talloc = talloc_init("lp_talloc");
769 ret = talloc_array(lp_talloc, char, len + 100); /* leave room for substitution */
777 strlcpy(ret, s, len);
779 if (trim_string(ret, "\"", "\"")) {
780 if (strchr(ret,'"') != NULL)
781 strlcpy(ret, s, len);
784 standard_sub_basic(ret,len+100);
791 In this section all the functions that are used to access the
792 parameters from the rest of the program are defined
795 #define FN_GLOBAL_STRING(fn_name,ptr) \
796 const char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
797 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
798 const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");}
799 #define FN_GLOBAL_LIST(fn_name,ptr) \
800 const char **fn_name(void) {return(*(const char ***)(ptr));}
801 #define FN_GLOBAL_BOOL(fn_name,ptr) \
802 BOOL fn_name(void) {return((BOOL)*(int *)(ptr));}
804 #define FN_GLOBAL_CHAR(fn_name,ptr) \
805 char fn_name(void) {return(*(char *)(ptr));}
807 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
808 int fn_name(void) {return(*(int *)(ptr));}
810 #define FN_LOCAL_STRING(fn_name,val) \
811 const char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
812 #define FN_LOCAL_CONST_STRING(fn_name,val) \
813 const char *fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
814 #define FN_LOCAL_LIST(fn_name,val) \
815 const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
816 #define FN_LOCAL_BOOL(fn_name,val) \
817 BOOL fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
819 #define FN_LOCAL_CHAR(fn_name,val) \
820 char fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
822 #define FN_LOCAL_INTEGER(fn_name,val) \
823 int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
825 _PUBLIC_ FN_GLOBAL_INTEGER(lp_server_role, &Globals.server_role)
826 _PUBLIC_ FN_GLOBAL_LIST(lp_smb_ports, &Globals.smb_ports)
827 _PUBLIC_ FN_GLOBAL_INTEGER(lp_nbt_port, &Globals.nbt_port)
828 _PUBLIC_ FN_GLOBAL_INTEGER(lp_dgram_port, &Globals.dgram_port)
829 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cldap_port, &Globals.cldap_port)
830 _PUBLIC_ FN_GLOBAL_INTEGER(lp_krb5_port, &Globals.krb5_port)
831 _PUBLIC_ FN_GLOBAL_INTEGER(lp_kpasswd_port, &Globals.kpasswd_port)
832 _PUBLIC_ FN_GLOBAL_INTEGER(lp_web_port, &Globals.web_port)
833 _PUBLIC_ FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
834 _PUBLIC_ FN_GLOBAL_STRING(lp_swat_directory, &Globals.swat_directory)
835 _PUBLIC_ FN_GLOBAL_BOOL(lp_tls_enabled, &Globals.tls_enabled)
836 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_keyfile, &Globals.tls_keyfile)
837 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_certfile, &Globals.tls_certfile)
838 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_cafile, &Globals.tls_cafile)
839 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_crlfile, &Globals.tls_crlfile)
840 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_dhpfile, &Globals.tls_dhpfile)
841 _PUBLIC_ FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
842 _PUBLIC_ FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset)
843 _PUBLIC_ FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
844 _PUBLIC_ FN_GLOBAL_STRING(lp_share_backend, &Globals.szShareBackend)
845 _PUBLIC_ FN_GLOBAL_STRING(lp_sam_url, &Globals.szSAM_URL)
846 _PUBLIC_ FN_GLOBAL_STRING(lp_spoolss_url, &Globals.szSPOOLSS_URL)
847 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_config_url, &Globals.szWINS_CONFIG_URL)
848 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_url, &Globals.szWINS_URL)
849 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
850 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_winbindd_socket_directory, &Globals.szWinbinddSocketDirectory)
851 _PUBLIC_ FN_GLOBAL_BOOL(lp_winbind_sealed_pipes, &Globals.bWinbindSealedPipes)
852 _PUBLIC_ FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
853 _PUBLIC_ FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
854 _PUBLIC_ FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
855 _PUBLIC_ FN_GLOBAL_STRING(lp_modulesdir, &Globals.szModulesDir)
856 _PUBLIC_ FN_GLOBAL_STRING(lp_setupdir, &Globals.szSetupDir)
857 _PUBLIC_ FN_GLOBAL_STRING(lp_ncalrpc_dir, &Globals.ncalrpc_dir)
858 _PUBLIC_ FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
859 _PUBLIC_ FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, &Globals.dcerpc_ep_servers)
860 _PUBLIC_ FN_GLOBAL_LIST(lp_server_services, &Globals.server_services)
861 _PUBLIC_ FN_GLOBAL_STRING(lp_ntptr_providor, &Globals.ntptr_providor)
862 _PUBLIC_ FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
863 _PUBLIC_ FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
864 _PUBLIC_ FN_GLOBAL_LIST(lp_passwordserver, &Globals.szPasswordServers)
865 _PUBLIC_ FN_GLOBAL_LIST(lp_name_resolve_order, &Globals.szNameResolveOrder)
866 _PUBLIC_ FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
867 _PUBLIC_ FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
868 _PUBLIC_ FN_GLOBAL_STRING(lp_workgroup, &Globals.szWorkgroup)
869 _PUBLIC_ FN_GLOBAL_STRING(lp_netbios_name, &Globals.szNetbiosName)
870 _PUBLIC_ FN_GLOBAL_STRING(lp_netbios_scope, &Globals.szNetbiosScope)
871 _PUBLIC_ FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
872 _PUBLIC_ FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
873 _PUBLIC_ FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
874 _PUBLIC_ FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
876 _PUBLIC_ FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
877 _PUBLIC_ FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
878 _PUBLIC_ FN_GLOBAL_BOOL(lp_wins_dns_proxy, &Globals.bWINSdnsProxy)
879 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
880 _PUBLIC_ FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
881 _PUBLIC_ FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
882 _PUBLIC_ FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
883 _PUBLIC_ FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw)
884 _PUBLIC_ FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords)
885 _PUBLIC_ FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions)
886 _PUBLIC_ FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
887 static FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
888 _PUBLIC_ FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
889 _PUBLIC_ FN_GLOBAL_BOOL(lp_unicode, &Globals.bUnicode)
890 _PUBLIC_ FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
891 _PUBLIC_ FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
892 _PUBLIC_ FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
893 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_plaintext_auth, &Globals.bClientPlaintextAuth)
894 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
895 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
896 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_use_spnego_principal, &Globals.client_use_spnego_principal)
897 _PUBLIC_ FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
898 _PUBLIC_ FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions)
899 _PUBLIC_ FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
900 _PUBLIC_ FN_GLOBAL_BOOL(lp_rpc_big_endian, &Globals.bRpcBigEndian)
901 _PUBLIC_ FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
902 _PUBLIC_ FN_GLOBAL_INTEGER(lp_min_wins_ttl, &Globals.min_wins_ttl)
903 _PUBLIC_ FN_GLOBAL_INTEGER(lp_maxmux, &Globals.max_mux)
904 _PUBLIC_ FN_GLOBAL_INTEGER(lp_max_xmit, &Globals.max_xmit)
905 _PUBLIC_ FN_GLOBAL_INTEGER(lp_passwordlevel, &Globals.pwordlevel)
906 _PUBLIC_ FN_GLOBAL_INTEGER(lp_srv_maxprotocol, &Globals.srv_maxprotocol)
907 _PUBLIC_ FN_GLOBAL_INTEGER(lp_srv_minprotocol, &Globals.srv_minprotocol)
908 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cli_maxprotocol, &Globals.cli_maxprotocol)
909 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cli_minprotocol, &Globals.cli_minprotocol)
910 _PUBLIC_ FN_GLOBAL_INTEGER(lp_security, &Globals.security)
911 _PUBLIC_ FN_GLOBAL_LIST(lp_auth_methods, &Globals.AuthMethods)
912 _PUBLIC_ FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security)
913 static FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as)
914 _PUBLIC_ FN_GLOBAL_LIST(lp_js_include, &Globals.jsInclude)
917 _PUBLIC_ FN_LOCAL_STRING(lp_servicename, szService)
918 _PUBLIC_ FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
919 _PUBLIC_ FN_LOCAL_STRING(lp_pathname, szPath)
920 static FN_LOCAL_STRING(_lp_printername, szPrintername)
921 _PUBLIC_ FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
922 _PUBLIC_ FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
923 _PUBLIC_ FN_LOCAL_STRING(lp_comment, comment)
924 _PUBLIC_ FN_LOCAL_STRING(lp_fstype, fstype)
925 static FN_LOCAL_STRING(lp_volume, volume)
926 _PUBLIC_ FN_LOCAL_LIST(lp_ntvfs_handler, ntvfs_handler)
927 _PUBLIC_ FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
928 _PUBLIC_ FN_LOCAL_BOOL(lp_browseable, bBrowseable)
929 _PUBLIC_ FN_LOCAL_BOOL(lp_readonly, bRead_only)
930 _PUBLIC_ FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
931 _PUBLIC_ FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
932 _PUBLIC_ FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
933 _PUBLIC_ FN_LOCAL_BOOL(lp_strict_locking, bStrictLocking)
934 _PUBLIC_ FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
935 _PUBLIC_ FN_LOCAL_BOOL(lp_ci_filesystem, bCIFileSystem)
936 _PUBLIC_ FN_LOCAL_BOOL(lp_map_system, bMap_system)
937 _PUBLIC_ FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
938 _PUBLIC_ FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
939 _PUBLIC_ FN_GLOBAL_INTEGER(lp_server_signing, &Globals.server_signing)
940 _PUBLIC_ FN_GLOBAL_INTEGER(lp_client_signing, &Globals.client_signing)
942 /* local prototypes */
944 static int map_parameter(const char *pszParmName);
945 static int getservicebyname(const char *pszServiceName,
946 service * pserviceDest);
947 static void copy_service(service * pserviceDest,
948 service * pserviceSource, int *pcopymapDest);
949 static BOOL service_ok(int iService);
950 static BOOL do_section(const char *pszSectionName, void *);
951 static void init_copymap(service * pservice);
953 /* This is a helper function for parametrical options support. */
954 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
955 /* Actual parametrical functions are quite simple */
956 const char *lp_get_parametric(int lookup_service, const char *type, const char *option)
959 struct param_opt *data;
961 if (lookup_service >= iNumServices) return NULL;
963 data = (lookup_service < 0) ?
964 Globals.param_opt : ServicePtrs[lookup_service]->param_opt;
966 asprintf(&vfskey, "%s:%s", type, option);
970 if (strcmp(data->key, vfskey) == 0) {
977 if (lookup_service >= 0) {
978 /* Try to fetch the same option but from globals */
979 /* but only if we are not already working with Globals */
980 data = Globals.param_opt;
982 if (strcmp(data->key, vfskey) == 0) {
996 /*******************************************************************
997 convenience routine to return int parameters.
998 ********************************************************************/
999 static int lp_int(const char *s)
1003 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
1007 return strtol(s, NULL, 0);
1010 /*******************************************************************
1011 convenience routine to return unsigned long parameters.
1012 ********************************************************************/
1013 static int lp_ulong(const char *s)
1017 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
1021 return strtoul(s, NULL, 0);
1024 /*******************************************************************
1025 convenience routine to return boolean parameters.
1026 ********************************************************************/
1027 static BOOL lp_bool(const char *s)
1032 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
1036 if (!set_boolean(s, &ret)) {
1037 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1045 /* Return parametric option from a given service. Type is a part of option before ':' */
1046 /* Parametric option has following syntax: 'Type: option = value' */
1047 /* Returned value is allocated in 'lp_talloc' context */
1049 const char *lp_parm_string(int lookup_service, const char *type, const char *option)
1051 const char *value = lp_get_parametric(lookup_service, type, option);
1054 return lp_string(value);
1059 /* Return parametric option from a given service. Type is a part of option before ':' */
1060 /* Parametric option has following syntax: 'Type: option = value' */
1061 /* Returned value is allocated in 'lp_talloc' context */
1063 const char **lp_parm_string_list(int lookup_service, const char *type, const char *option,
1064 const char *separator)
1066 const char *value = lp_get_parametric(lookup_service, type, option);
1069 return str_list_make(talloc_autofree_context(), value, separator);
1074 /* Return parametric option from a given service. Type is a part of option before ':' */
1075 /* Parametric option has following syntax: 'Type: option = value' */
1077 int lp_parm_int(int lookup_service, const char *type, const char *option, int default_v)
1079 const char *value = lp_get_parametric(lookup_service, type, option);
1082 return lp_int(value);
1087 /* Return parametric option from a given service. Type is a part of
1088 * option before ':'.
1089 * Parametric option has following syntax: 'Type: option = value'.
1092 int lp_parm_bytes(int lookup_service, const char *type, const char *option, int default_v)
1096 const char *value = lp_get_parametric(lookup_service, type, option);
1098 if (value && conv_str_size(value, &bval)) {
1099 if (bval <= INT_MAX) {
1107 /* Return parametric option from a given service. Type is a part of option before ':' */
1108 /* Parametric option has following syntax: 'Type: option = value' */
1110 unsigned long lp_parm_ulong(int lookup_service, const char *type, const char *option, unsigned long default_v)
1112 const char *value = lp_get_parametric(lookup_service, type, option);
1115 return lp_ulong(value);
1120 /* Return parametric option from a given service. Type is a part of option before ':' */
1121 /* Parametric option has following syntax: 'Type: option = value' */
1123 BOOL lp_parm_bool(int lookup_service, const char *type, const char *option, BOOL default_v)
1125 const char *value = lp_get_parametric(lookup_service, type, option);
1128 return lp_bool(value);
1134 /***************************************************************************
1135 Initialise a service to the defaults.
1136 ***************************************************************************/
1138 static void init_service(service * pservice)
1140 memset((char *)pservice, '\0', sizeof(service));
1141 copy_service(pservice, &sDefault, NULL);
1144 /***************************************************************************
1145 Free the dynamically allocated parts of a service struct.
1146 ***************************************************************************/
1148 static void free_service(service *pservice)
1151 struct param_opt *data, *pdata;
1155 if (pservice->szService)
1156 DEBUG(5, ("free_service: Freeing service %s\n",
1157 pservice->szService));
1159 string_free(&pservice->szService);
1160 SAFE_FREE(pservice->copymap);
1162 for (i = 0; parm_table[i].label; i++) {
1163 if ((parm_table[i].type == P_STRING ||
1164 parm_table[i].type == P_USTRING) &&
1165 parm_table[i].class == P_LOCAL) {
1166 string_free((char **)
1167 (((char *)pservice) +
1168 PTR_DIFF(parm_table[i].ptr, &sDefault)));
1169 } else if (parm_table[i].type == P_LIST &&
1170 parm_table[i].class == P_LOCAL) {
1171 char ***listp = (char ***)(((char *)pservice) +
1172 PTR_DIFF(parm_table[i].ptr, &sDefault));
1173 talloc_free(*listp);
1178 DEBUG(5,("Freeing parametrics:\n"));
1179 data = pservice->param_opt;
1181 DEBUG(5,("[%s = %s]\n", data->key, data->value));
1182 string_free(&data->key);
1183 string_free(&data->value);
1189 ZERO_STRUCTP(pservice);
1192 /***************************************************************************
1193 Add a new service to the services array initialising it with the given
1195 ***************************************************************************/
1197 static int add_a_service(const service *pservice, const char *name)
1201 int num_to_alloc = iNumServices + 1;
1202 struct param_opt *data, *pdata;
1204 tservice = *pservice;
1206 /* it might already exist */
1208 i = getservicebyname(name, NULL);
1210 /* Clean all parametric options for service */
1211 /* They will be added during parsing again */
1212 data = ServicePtrs[i]->param_opt;
1214 string_free(&data->key);
1215 string_free(&data->value);
1220 ServicePtrs[i]->param_opt = NULL;
1225 /* find an invalid one */
1226 for (i = 0; i < iNumServices; i++)
1227 if (!ServicePtrs[i]->valid)
1230 /* if not, then create one */
1231 if (i == iNumServices) {
1234 tsp = realloc_p(ServicePtrs, service *, num_to_alloc);
1237 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1242 ServicePtrs[iNumServices] = malloc_p(service);
1244 if (!ServicePtrs[iNumServices]) {
1245 DEBUG(0,("add_a_service: out of memory!\n"));
1251 free_service(ServicePtrs[i]);
1253 ServicePtrs[i]->valid = True;
1255 init_service(ServicePtrs[i]);
1256 copy_service(ServicePtrs[i], &tservice, NULL);
1258 string_set(&ServicePtrs[i]->szService, name);
1262 /***************************************************************************
1263 Add a new home service, with the specified home directory, defaults coming
1265 ***************************************************************************/
1267 BOOL lp_add_home(const char *pszHomename, int iDefaultService,
1268 const char *user, const char *pszHomedir)
1273 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1278 if (!(*(ServicePtrs[iDefaultService]->szPath))
1279 || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(-1))) {
1280 pstrcpy(newHomedir, pszHomedir);
1282 pstrcpy(newHomedir, lp_pathname(iDefaultService));
1283 string_sub(newHomedir,"%H", pszHomedir, sizeof(newHomedir));
1286 string_set(&ServicePtrs[i]->szPath, newHomedir);
1288 if (!(*(ServicePtrs[i]->comment))) {
1290 slprintf(comment, sizeof(comment) - 1,
1291 "Home directory of %s", user);
1292 string_set(&ServicePtrs[i]->comment, comment);
1294 ServicePtrs[i]->bAvailable = sDefault.bAvailable;
1295 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1297 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1303 /***************************************************************************
1304 Add a new service, based on an old one.
1305 ***************************************************************************/
1307 int lp_add_service(const char *pszService, int iDefaultService)
1309 return (add_a_service(ServicePtrs[iDefaultService], pszService));
1312 /***************************************************************************
1313 Add the IPC service.
1314 ***************************************************************************/
1316 static BOOL lp_add_hidden(const char *name, const char *fstype)
1319 int i = add_a_service(&sDefault, name);
1324 slprintf(comment, sizeof(comment) - 1,
1325 "%s Service (%s)", fstype, Globals.szServerString);
1327 string_set(&ServicePtrs[i]->szPath, tmpdir());
1328 string_set(&ServicePtrs[i]->comment, comment);
1329 string_set(&ServicePtrs[i]->fstype, fstype);
1330 ServicePtrs[i]->iMaxConnections = -1;
1331 ServicePtrs[i]->bAvailable = True;
1332 ServicePtrs[i]->bRead_only = True;
1333 ServicePtrs[i]->bPrint_ok = False;
1334 ServicePtrs[i]->bBrowseable = False;
1336 if (strcasecmp(fstype, "IPC") == 0) {
1337 lp_do_parameter(i, "ntvfs handler", "default");
1340 DEBUG(3, ("adding hidden service %s\n", name));
1345 /***************************************************************************
1346 Add a new printer service, with defaults coming from service iFrom.
1347 ***************************************************************************/
1349 BOOL lp_add_printer(const char *pszPrintername, int iDefaultService)
1351 const char *comment = "From Printcap";
1352 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1357 /* note that we do NOT default the availability flag to True - */
1358 /* we take it from the default service passed. This allows all */
1359 /* dynamic printers to be disabled by disabling the [printers] */
1360 /* entry (if/when the 'available' keyword is implemented!). */
1362 /* the printer name is set to the service name. */
1363 string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1364 string_set(&ServicePtrs[i]->comment, comment);
1365 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1366 /* Printers cannot be read_only. */
1367 ServicePtrs[i]->bRead_only = False;
1368 /* Printer services must be printable. */
1369 ServicePtrs[i]->bPrint_ok = True;
1371 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1373 update_server_announce_as_printserver();
1378 /***************************************************************************
1379 Map a parameter's string representation to something we can use.
1380 Returns False if the parameter string is not recognised, else TRUE.
1381 ***************************************************************************/
1383 static int map_parameter(const char *pszParmName)
1387 if (*pszParmName == '-')
1390 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1391 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1394 /* Warn only if it isn't parametric option */
1395 if (strchr(pszParmName, ':') == NULL)
1396 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1397 /* We do return 'fail' for parametric options as well because they are
1398 stored in different storage
1405 return the parameter structure for a parameter
1407 struct parm_struct *lp_parm_struct(const char *name)
1409 int parmnum = map_parameter(name);
1410 if (parmnum == -1) return NULL;
1411 return &parm_table[parmnum];
1415 return the parameter pointer for a parameter
1417 void *lp_parm_ptr(int snum, struct parm_struct *parm)
1422 return ((char *)ServicePtrs[snum]) + PTR_DIFF(parm->ptr, &sDefault);
1425 /***************************************************************************
1426 Find a service by name. Otherwise works like get_service.
1427 ***************************************************************************/
1429 static int getservicebyname(const char *pszServiceName, service * pserviceDest)
1433 for (iService = iNumServices - 1; iService >= 0; iService--)
1434 if (VALID(iService) &&
1435 strwicmp(ServicePtrs[iService]->szService, pszServiceName) == 0) {
1436 if (pserviceDest != NULL)
1437 copy_service(pserviceDest, ServicePtrs[iService], NULL);
1444 /***************************************************************************
1445 Copy a service structure to another.
1446 If pcopymapDest is NULL then copy all fields
1447 ***************************************************************************/
1449 static void copy_service(service * pserviceDest, service * pserviceSource, int *pcopymapDest)
1452 BOOL bcopyall = (pcopymapDest == NULL);
1453 struct param_opt *data, *pdata, *paramo;
1456 for (i = 0; parm_table[i].label; i++)
1457 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1458 (bcopyall || pcopymapDest[i])) {
1459 void *def_ptr = parm_table[i].ptr;
1461 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
1464 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
1467 switch (parm_table[i].type) {
1469 *(int *)dest_ptr = *(int *)src_ptr;
1474 *(int *)dest_ptr = *(int *)src_ptr;
1478 string_set(dest_ptr,
1483 string_set(dest_ptr,
1485 strupper(*(char **)dest_ptr);
1488 *(const char ***)dest_ptr = str_list_copy(talloc_autofree_context(),
1489 *(const char ***)src_ptr);
1497 init_copymap(pserviceDest);
1498 if (pserviceSource->copymap)
1499 memcpy((void *)pserviceDest->copymap,
1500 (void *)pserviceSource->copymap,
1501 sizeof(int) * NUMPARAMETERS);
1504 data = pserviceSource->param_opt;
1507 pdata = pserviceDest->param_opt;
1508 /* Traverse destination */
1510 /* If we already have same option, override it */
1511 if (strcmp(pdata->key, data->key) == 0) {
1512 string_free(&pdata->value);
1513 pdata->value = strdup(data->value);
1517 pdata = pdata->next;
1520 paramo = malloc_p(struct param_opt);
1523 paramo->key = strdup(data->key);
1524 paramo->value = strdup(data->value);
1525 DLIST_ADD(pserviceDest->param_opt, paramo);
1531 /***************************************************************************
1532 Check a service for consistency. Return False if the service is in any way
1533 incomplete or faulty, else True.
1534 ***************************************************************************/
1536 static BOOL service_ok(int iService)
1541 if (ServicePtrs[iService]->szService[0] == '\0') {
1542 DEBUG(0, ("The following message indicates an internal error:\n"));
1543 DEBUG(0, ("No service name in service entry.\n"));
1547 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1548 /* I can't see why you'd want a non-printable printer service... */
1549 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
1550 if (!ServicePtrs[iService]->bPrint_ok) {
1551 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
1552 ServicePtrs[iService]->szService));
1553 ServicePtrs[iService]->bPrint_ok = True;
1554 update_server_announce_as_printserver();
1556 /* [printers] service must also be non-browsable. */
1557 if (ServicePtrs[iService]->bBrowseable)
1558 ServicePtrs[iService]->bBrowseable = False;
1561 /* If a service is flagged unavailable, log the fact at level 0. */
1562 if (!ServicePtrs[iService]->bAvailable)
1563 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
1564 ServicePtrs[iService]->szService));
1569 static struct file_lists {
1570 struct file_lists *next;
1574 } *file_lists = NULL;
1576 /*******************************************************************
1577 Keep a linked list of all config files so we know when one has changed
1578 it's date and needs to be reloaded.
1579 ********************************************************************/
1581 static void add_to_file_list(const char *fname, const char *subfname)
1583 struct file_lists *f = file_lists;
1586 if (f->name && !strcmp(f->name, fname))
1592 f = malloc_p(struct file_lists);
1595 f->next = file_lists;
1596 f->name = strdup(fname);
1601 f->subfname = strdup(subfname);
1607 f->modtime = file_modtime(subfname);
1609 time_t t = file_modtime(subfname);
1615 /*******************************************************************
1616 Check if a config file has changed date.
1617 ********************************************************************/
1619 BOOL lp_file_list_changed(void)
1621 struct file_lists *f = file_lists;
1622 DEBUG(6, ("lp_file_list_changed()\n"));
1628 pstrcpy(n2, f->name);
1629 standard_sub_basic(n2,sizeof(n2));
1631 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
1632 f->name, n2, ctime(&f->modtime)));
1634 mod_time = file_modtime(n2);
1636 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
1638 ("file %s modified: %s\n", n2,
1640 f->modtime = mod_time;
1641 SAFE_FREE(f->subfname);
1642 f->subfname = strdup(n2);
1650 /***************************************************************************
1651 Handle the include operation.
1652 ***************************************************************************/
1654 static BOOL handle_include(const char *pszParmValue, char **ptr)
1657 pstrcpy(fname, pszParmValue);
1659 standard_sub_basic(fname,sizeof(fname));
1661 add_to_file_list(pszParmValue, fname);
1663 string_set(ptr, fname);
1665 if (file_exist(fname))
1666 return (pm_process(fname, do_section, do_parameter, NULL));
1668 DEBUG(2, ("Can't find include file %s\n", fname));
1673 /***************************************************************************
1674 Handle the interpretation of the copy parameter.
1675 ***************************************************************************/
1677 static BOOL handle_copy(const char *pszParmValue, char **ptr)
1681 service serviceTemp;
1683 string_set(ptr, pszParmValue);
1685 init_service(&serviceTemp);
1689 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
1691 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
1692 if (iTemp == iServiceIndex) {
1693 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
1695 copy_service(ServicePtrs[iServiceIndex],
1697 ServicePtrs[iServiceIndex]->copymap);
1701 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
1705 free_service(&serviceTemp);
1709 /***************************************************************************
1710 Initialise a copymap.
1711 ***************************************************************************/
1713 static void init_copymap(service * pservice)
1716 SAFE_FREE(pservice->copymap);
1717 pservice->copymap = malloc_array_p(int, NUMPARAMETERS);
1718 if (!pservice->copymap)
1720 ("Couldn't allocate copymap!! (size %d)\n",
1721 (int)NUMPARAMETERS));
1723 for (i = 0; i < NUMPARAMETERS; i++)
1724 pservice->copymap[i] = True;
1727 #if 0 /* not used anywhere */
1728 /***************************************************************************
1729 Return the local pointer to a parameter given the service number and the
1730 pointer into the default structure.
1731 ***************************************************************************/
1733 void *lp_local_ptr(int snum, void *ptr)
1735 return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
1739 /***************************************************************************
1740 Process a parametric option
1741 ***************************************************************************/
1742 static BOOL lp_do_parameter_parametric(int snum, const char *pszParmName, const char *pszParmValue, int flags)
1744 struct param_opt *paramo, *data;
1747 while (isspace((unsigned char)*pszParmName)) {
1751 name = strdup(pszParmName);
1752 if (!name) return False;
1757 data = Globals.param_opt;
1759 data = ServicePtrs[snum]->param_opt;
1762 /* Traverse destination */
1763 for (paramo=data; paramo; paramo=paramo->next) {
1764 /* If we already have the option set, override it unless
1765 it was a command line option and the new one isn't */
1766 if (strcmp(paramo->key, name) == 0) {
1767 if ((paramo->flags & FLAG_CMDLINE) &&
1768 !(flags & FLAG_CMDLINE)) {
1772 free(paramo->value);
1773 paramo->value = strdup(pszParmValue);
1774 paramo->flags = flags;
1780 paramo = malloc_p(struct param_opt);
1783 paramo->key = strdup(name);
1784 paramo->value = strdup(pszParmValue);
1785 paramo->flags = flags;
1787 DLIST_ADD(Globals.param_opt, paramo);
1789 DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
1797 /***************************************************************************
1798 Process a parameter for a particular service number. If snum < 0
1799 then assume we are in the globals.
1800 ***************************************************************************/
1801 BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
1804 void *parm_ptr = NULL; /* where we are going to store the result */
1805 void *def_ptr = NULL;
1807 parmnum = map_parameter(pszParmName);
1810 if (strchr(pszParmName, ':')) {
1811 return lp_do_parameter_parametric(snum, pszParmName, pszParmValue, 0);
1813 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1817 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1818 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1822 /* if the flag has been set on the command line, then don't allow override,
1823 but don't report an error */
1824 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1828 def_ptr = parm_table[parmnum].ptr;
1830 /* we might point at a service, the default service or a global */
1834 if (parm_table[parmnum].class == P_GLOBAL) {
1836 ("Global parameter %s found in service section!\n",
1841 ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
1846 if (!ServicePtrs[snum]->copymap)
1847 init_copymap(ServicePtrs[snum]);
1849 /* this handles the aliases - set the copymap for other entries with
1850 the same data pointer */
1851 for (i = 0; parm_table[i].label; i++)
1852 if (parm_table[i].ptr == parm_table[parmnum].ptr)
1853 ServicePtrs[snum]->copymap[i] = False;
1856 /* if it is a special case then go ahead */
1857 if (parm_table[parmnum].special) {
1858 parm_table[parmnum].special(pszParmValue, (char **)parm_ptr);
1862 /* now switch on the type of variable it is */
1863 switch (parm_table[parmnum].type)
1866 if (!set_boolean(pszParmValue, parm_ptr)) {
1867 DEBUG(0,("lp_do_parameter(%s): value is not boolean!\n", pszParmValue));
1873 *(int *)parm_ptr = atoi(pszParmValue);
1879 if (conv_str_size(pszParmValue, &val)) {
1880 if (val <= INT_MAX) {
1881 *(int *)parm_ptr = (int)val;
1886 DEBUG(0,("lp_do_parameter(%s): value is not "
1887 "a valid size specifier!\n", pszParmValue));
1892 *(const char ***)parm_ptr = str_list_make(talloc_autofree_context(),
1893 pszParmValue, NULL);
1897 string_set(parm_ptr, pszParmValue);
1901 string_set(parm_ptr, pszParmValue);
1902 strupper(*(char **)parm_ptr);
1906 for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
1909 parm_table[parmnum].enum_list[i].name)) {
1911 parm_table[parmnum].
1916 if (!parm_table[parmnum].enum_list[i].name) {
1917 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n",
1918 pszParmValue, pszParmName));
1926 if (parm_table[parmnum].flags & FLAG_DEFAULT) {
1927 parm_table[parmnum].flags &= ~FLAG_DEFAULT;
1928 /* we have to also unset FLAG_DEFAULT on aliases */
1929 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1930 parm_table[i].flags &= ~FLAG_DEFAULT;
1932 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1933 parm_table[i].flags &= ~FLAG_DEFAULT;
1940 /***************************************************************************
1941 Process a parameter.
1942 ***************************************************************************/
1944 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue, void *userdata)
1946 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
1947 pszParmName, pszParmValue));
1951 variable argument do parameter
1953 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
1955 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...)
1962 s = talloc_vasprintf(NULL, fmt, ap);
1964 ret = do_parameter(pszParmName, s, NULL);
1971 set a parameter from the commandline - this is called from command line parameter
1972 parsing code. It sets the parameter then marks the parameter as unable to be modified
1973 by smb.conf processing
1975 BOOL lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
1977 int parmnum = map_parameter(pszParmName);
1980 while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
1983 if (parmnum < 0 && strchr(pszParmName, ':')) {
1984 /* set a parametric option */
1985 return lp_do_parameter_parametric(-1, pszParmName, pszParmValue, FLAG_CMDLINE);
1989 DEBUG(0,("Unknown option '%s'\n", pszParmName));
1993 /* reset the CMDLINE flag in case this has been called before */
1994 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
1996 if (!lp_do_parameter(-2, pszParmName, pszParmValue)) {
2000 parm_table[parmnum].flags |= FLAG_CMDLINE;
2002 /* we have to also set FLAG_CMDLINE on aliases */
2003 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
2004 parm_table[i].flags |= FLAG_CMDLINE;
2006 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
2007 parm_table[i].flags |= FLAG_CMDLINE;
2014 set a option from the commandline in 'a=b' format. Use to support --option
2016 BOOL lp_set_option(const char *option)
2034 ret = lp_set_cmdline(s, p+1);
2040 #define BOOLSTR(b) ((b) ? "Yes" : "No")
2042 /***************************************************************************
2043 Print a parameter of the specified type.
2044 ***************************************************************************/
2046 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
2052 for (i = 0; p->enum_list[i].name; i++) {
2053 if (*(int *)ptr == p->enum_list[i].value) {
2055 p->enum_list[i].name);
2062 fprintf(f, "%s", BOOLSTR((BOOL)*(int *)ptr));
2067 fprintf(f, "%d", *(int *)ptr);
2071 if ((char ***)ptr && *(char ***)ptr) {
2072 char **list = *(char ***)ptr;
2074 for (; *list; list++)
2075 fprintf(f, "%s%s", *list,
2076 ((*(list+1))?", ":""));
2082 if (*(char **)ptr) {
2083 fprintf(f, "%s", *(char **)ptr);
2091 /***************************************************************************
2092 Check if two parameters are equal.
2093 ***************************************************************************/
2095 static BOOL equal_parameter(parm_type type, void *ptr1, void *ptr2)
2099 return (*((int *)ptr1) == *((int *)ptr2));
2104 return (*((int *)ptr1) == *((int *)ptr2));
2107 return str_list_equal((const char **)(*(char ***)ptr1),
2108 (const char **)(*(char ***)ptr2));
2113 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
2118 return (p1 == p2 || strequal(p1, p2));
2126 /***************************************************************************
2127 Process a new section (service). At this stage all sections are services.
2128 Later we'll have special sections that permit server parameters to be set.
2129 Returns True on success, False on failure.
2130 ***************************************************************************/
2132 static BOOL do_section(const char *pszSectionName, void *userdata)
2135 BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2136 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2139 /* if we've just struck a global section, note the fact. */
2140 bInGlobalSection = isglobal;
2142 /* check for multiple global sections */
2143 if (bInGlobalSection) {
2144 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2148 /* if we have a current service, tidy it up before moving on */
2151 if (iServiceIndex >= 0)
2152 bRetval = service_ok(iServiceIndex);
2154 /* if all is still well, move to the next record in the services array */
2156 /* We put this here to avoid an odd message order if messages are */
2157 /* issued by the post-processing of a previous section. */
2158 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2160 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
2162 DEBUG(0, ("Failed to add a new service\n"));
2171 /***************************************************************************
2172 Determine if a partcular base parameter is currentl set to the default value.
2173 ***************************************************************************/
2175 static BOOL is_default(int i)
2177 if (!defaults_saved)
2179 switch (parm_table[i].type) {
2181 return str_list_equal((const char **)parm_table[i].def.lvalue,
2182 (const char **)(*(char ***)parm_table[i].ptr));
2185 return strequal(parm_table[i].def.svalue,
2186 *(char **)parm_table[i].ptr);
2188 return parm_table[i].def.bvalue ==
2189 *(int *)parm_table[i].ptr;
2193 return parm_table[i].def.ivalue ==
2194 *(int *)parm_table[i].ptr;
2201 /***************************************************************************
2202 Display the contents of the global structure.
2203 ***************************************************************************/
2205 static void dump_globals(FILE *f, BOOL show_defaults)
2208 struct param_opt *data;
2210 fprintf(f, "# Global parameters\n[global]\n");
2212 for (i = 0; parm_table[i].label; i++)
2213 if (parm_table[i].class == P_GLOBAL &&
2214 parm_table[i].ptr &&
2215 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2216 if (!show_defaults && (parm_table[i].flags & FLAG_DEFAULT))
2218 fprintf(f, "\t%s = ", parm_table[i].label);
2219 print_parameter(&parm_table[i], parm_table[i].ptr, f);
2222 if (Globals.param_opt != NULL) {
2223 data = Globals.param_opt;
2225 fprintf(f, "\t%s = %s\n", data->key, data->value);
2232 /***************************************************************************
2233 Display the contents of a single services record.
2234 ***************************************************************************/
2236 static void dump_a_service(service * pService, FILE * f)
2239 struct param_opt *data;
2241 if (pService != &sDefault)
2242 fprintf(f, "\n[%s]\n", pService->szService);
2244 for (i = 0; parm_table[i].label; i++)
2245 if (parm_table[i].class == P_LOCAL &&
2246 parm_table[i].ptr &&
2247 (*parm_table[i].label != '-') &&
2248 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2249 int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
2251 if (pService == &sDefault) {
2252 if (defaults_saved && is_default(i))
2255 if (equal_parameter(parm_table[i].type,
2256 ((char *)pService) +
2258 ((char *)&sDefault) +
2263 fprintf(f, "\t%s = ", parm_table[i].label);
2264 print_parameter(&parm_table[i],
2265 ((char *)pService) + pdiff, f);
2268 if (pService->param_opt != NULL) {
2269 data = pService->param_opt;
2271 fprintf(f, "\t%s = %s\n", data->key, data->value);
2277 BOOL lp_dump_a_parameter(int snum, char *parm_name, FILE * f, BOOL isGlobal)
2279 service * pService = ServicePtrs[snum];
2280 struct parm_struct *parm;
2283 parm = lp_parm_struct(parm_name);
2291 ptr = ((char *)pService) +
2292 PTR_DIFF(parm->ptr, &sDefault);
2294 print_parameter(parm,
2300 /***************************************************************************
2301 Return info about the next service in a service. snum==-1 gives the globals.
2302 Return NULL when out of parameters.
2303 ***************************************************************************/
2305 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
2308 /* do the globals */
2309 for (; parm_table[*i].label; (*i)++) {
2310 if (parm_table[*i].class == P_SEPARATOR)
2311 return &parm_table[(*i)++];
2313 if (!parm_table[*i].ptr
2314 || (*parm_table[*i].label == '-'))
2318 && (parm_table[*i].ptr ==
2319 parm_table[(*i) - 1].ptr))
2322 return &parm_table[(*i)++];
2325 service *pService = ServicePtrs[snum];
2327 for (; parm_table[*i].label; (*i)++) {
2328 if (parm_table[*i].class == P_SEPARATOR)
2329 return &parm_table[(*i)++];
2331 if (parm_table[*i].class == P_LOCAL &&
2332 parm_table[*i].ptr &&
2333 (*parm_table[*i].label != '-') &&
2335 (parm_table[*i].ptr !=
2336 parm_table[(*i) - 1].ptr)))
2339 PTR_DIFF(parm_table[*i].ptr,
2342 if (allparameters ||
2343 !equal_parameter(parm_table[*i].type,
2344 ((char *)pService) +
2346 ((char *)&sDefault) +
2349 return &parm_table[(*i)++];
2359 /***************************************************************************
2360 Return TRUE if the passed service number is within range.
2361 ***************************************************************************/
2363 BOOL lp_snum_ok(int iService)
2365 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
2368 /***************************************************************************
2369 Auto-load some home services.
2370 ***************************************************************************/
2372 static void lp_add_auto_services(const char *str)
2377 /***************************************************************************
2378 Announce ourselves as a print server.
2379 ***************************************************************************/
2381 void update_server_announce_as_printserver(void)
2383 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
2386 /***************************************************************************
2387 Have we loaded a services file yet?
2388 ***************************************************************************/
2390 BOOL lp_loaded(void)
2395 /***************************************************************************
2396 Unload unused services.
2397 ***************************************************************************/
2399 void lp_killunused(struct smbsrv_connection *smb, BOOL (*snumused) (struct smbsrv_connection *, int))
2402 for (i = 0; i < iNumServices; i++) {
2406 if (!snumused || !snumused(smb, i)) {
2407 ServicePtrs[i]->valid = False;
2408 free_service(ServicePtrs[i]);
2413 /***************************************************************************
2415 ***************************************************************************/
2417 void lp_killservice(int iServiceIn)
2419 if (VALID(iServiceIn)) {
2420 ServicePtrs[iServiceIn]->valid = False;
2421 free_service(ServicePtrs[iServiceIn]);
2425 /***************************************************************************
2426 Load the services array from the services file. Return True on success,
2428 ***************************************************************************/
2434 struct param_opt *data;
2438 bInGlobalSection = True;
2440 if (Globals.param_opt != NULL) {
2441 struct param_opt *next;
2442 for (data=Globals.param_opt; data; data=next) {
2444 if (data->flags & FLAG_CMDLINE) continue;
2447 DLIST_REMOVE(Globals.param_opt, data);
2454 pstrcpy(n2, lp_configfile());
2455 standard_sub_basic(n2,sizeof(n2));
2456 DEBUG(2, ("lp_load: refreshing parameters from %s\n", n2));
2458 add_to_file_list(lp_configfile(), n2);
2460 /* We get sections first, so have to start 'behind' to make up */
2462 bRetval = pm_process(n2, do_section, do_parameter, NULL);
2464 /* finish up the last section */
2465 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
2467 if (iServiceIndex >= 0)
2468 bRetval = service_ok(iServiceIndex);
2470 lp_add_auto_services(lp_auto_services());
2472 lp_add_hidden("IPC$", "IPC");
2473 lp_add_hidden("ADMIN$", "DISK");
2475 set_default_server_announce_type();
2479 if (!Globals.szWINSservers && Globals.bWINSsupport) {
2480 lp_do_parameter(-1, "wins server", "127.0.0.1");
2488 /***************************************************************************
2489 Reset the max number of services.
2490 ***************************************************************************/
2492 void lp_resetnumservices(void)
2497 /***************************************************************************
2498 Return the max number of services.
2499 ***************************************************************************/
2501 int lp_numservices(void)
2503 return (iNumServices);
2506 /***************************************************************************
2507 Display the contents of the services array in human-readable form.
2508 ***************************************************************************/
2510 void lp_dump(FILE *f, BOOL show_defaults, int maxtoprint)
2515 defaults_saved = False;
2517 dump_globals(f, show_defaults);
2519 dump_a_service(&sDefault, f);
2521 for (iService = 0; iService < maxtoprint; iService++)
2522 lp_dump_one(f, show_defaults, iService);
2525 /***************************************************************************
2526 Display the contents of one service in human-readable form.
2527 ***************************************************************************/
2529 void lp_dump_one(FILE * f, BOOL show_defaults, int snum)
2532 if (ServicePtrs[snum]->szService[0] == '\0')
2534 dump_a_service(ServicePtrs[snum], f);
2538 /***************************************************************************
2539 Return the number of the service with the given name, or -1 if it doesn't
2540 exist. Note that this is a DIFFERENT ANIMAL from the internal function
2541 getservicebyname()! This works ONLY if all services have been loaded, and
2542 does not copy the found service.
2543 ***************************************************************************/
2545 int lp_servicenumber(const char *pszServiceName)
2548 fstring serviceName;
2551 for (iService = iNumServices - 1; iService >= 0; iService--) {
2552 if (VALID(iService) && ServicePtrs[iService]->szService) {
2554 * The substitution here is used to support %U is
2557 fstrcpy(serviceName, ServicePtrs[iService]->szService);
2558 standard_sub_basic(serviceName,sizeof(serviceName));
2559 if (strequal(serviceName, pszServiceName))
2565 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
2570 int lp_find_valid_service(const char *pszServiceName)
2574 iService = lp_servicenumber(pszServiceName);
2576 if (iService >= 0 && !lp_snum_ok(iService)) {
2577 DEBUG(0,("lp_find_valid_service: Invalid snum %d for '%s'\n",iService, pszServiceName));
2581 if (iService == -1) {
2582 DEBUG(3,("lp_find_valid_service: failed to find service '%s'\n", pszServiceName));
2588 /*******************************************************************
2589 A useful volume label function.
2590 ********************************************************************/
2591 const char *volume_label(int snum)
2593 const char *ret = lp_volume(snum);
2595 return lp_servicename(snum);
2600 /*******************************************************************
2601 Set the server type we will announce as via nmbd.
2602 ********************************************************************/
2604 static void set_default_server_announce_type(void)
2606 default_server_announce = 0;
2607 default_server_announce |= SV_TYPE_WORKSTATION;
2608 default_server_announce |= SV_TYPE_SERVER;
2609 default_server_announce |= SV_TYPE_SERVER_UNIX;
2611 switch (lp_announce_as()) {
2612 case ANNOUNCE_AS_NT_SERVER:
2613 default_server_announce |= SV_TYPE_SERVER_NT;
2614 /* fall through... */
2615 case ANNOUNCE_AS_NT_WORKSTATION:
2616 default_server_announce |= SV_TYPE_NT;
2618 case ANNOUNCE_AS_WIN95:
2619 default_server_announce |= SV_TYPE_WIN95_PLUS;
2621 case ANNOUNCE_AS_WFW:
2622 default_server_announce |= SV_TYPE_WFW;
2628 switch (lp_server_role()) {
2629 case ROLE_DOMAIN_MEMBER:
2630 default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
2632 case ROLE_DOMAIN_PDC:
2633 default_server_announce |= SV_TYPE_DOMAIN_CTRL;
2635 case ROLE_DOMAIN_BDC:
2636 default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
2638 case ROLE_STANDALONE:
2642 if (lp_time_server())
2643 default_server_announce |= SV_TYPE_TIME_SOURCE;
2645 if (lp_host_msdfs())
2646 default_server_announce |= SV_TYPE_DFS_SERVER;
2648 /* TODO: only announce us as print server when we are a print server */
2649 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
2652 /***********************************************************
2653 If we are PDC then prefer us as DMB
2654 ************************************************************/
2656 BOOL lp_domain_master(void)
2658 return (lp_server_role() == ROLE_DOMAIN_PDC);
2661 /***********************************************************
2662 If we are PDC then prefer us as DMB
2663 ************************************************************/
2665 BOOL lp_domain_logons(void)
2667 return (lp_server_role() == ROLE_DOMAIN_PDC) || (lp_server_role() == ROLE_DOMAIN_BDC);
2670 /***********************************************************
2671 If we are DMB then prefer us as LMB
2672 ************************************************************/
2674 BOOL lp_preferred_master(void)
2676 return (lp_local_master() && lp_domain_master());
2679 /*******************************************************************
2681 ********************************************************************/
2683 void lp_remove_service(int snum)
2685 ServicePtrs[snum]->valid = False;
2688 /*******************************************************************
2690 ********************************************************************/
2692 void lp_copy_service(int snum, const char *new_name)
2694 const char *oldname = lp_servicename(snum);
2695 do_section(new_name, NULL);
2697 snum = lp_servicenumber(new_name);
2699 lp_do_parameter(snum, "copy", oldname);
2704 /*******************************************************************
2705 Get the default server type we will announce as via nmbd.
2706 ********************************************************************/
2707 int lp_default_server_announce(void)
2709 return default_server_announce;
2712 const char *lp_printername(int snum)
2714 const char *ret = _lp_printername(snum);
2715 if (ret == NULL || (ret != NULL && *ret == '\0'))
2716 ret = lp_const_servicename(snum);
2722 /*******************************************************************
2723 Return the max print jobs per queue.
2724 ********************************************************************/
2726 int lp_maxprintjobs(int snum)
2728 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
2729 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
2730 maxjobs = PRINT_MAX_JOBID - 1;