r16464: split client and server min/max protocol settings
[Samba/aatanasov.git] / source / param / loadparm.c
blobe76d955b5eb6f6fb81477f1107d936ce155312ba
1 /*
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.
30 * Load parameters.
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.
36 * To add a parameter:
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
45 * Notes:
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
51 * careful!
55 #include "includes.h"
56 #include "smb.h"
57 #include "version.h"
58 #include "dynconfig.h"
59 #include "pstring.h"
60 #include "system/time.h"
61 #include "system/locale.h"
62 #include "librpc/gen_ndr/svcctl.h"
63 #include "librpc/gen_ndr/samr.h"
64 #include "smb_server/smb_server.h"
65 #include "libcli/raw/signing.h"
66 #include "dlinklist.h"
67 #include "param/loadparm.h"
69 static BOOL bLoaded = False;
71 /* some helpful bits */
72 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && ServicePtrs[(i)]->valid)
73 #define VALID(i) ServicePtrs[i]->valid
75 static BOOL do_parameter(const char *, const char *, void *);
76 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...);
78 static BOOL defaults_saved = False;
81 struct param_opt {
82 struct param_opt *prev, *next;
83 char *key;
84 char *value;
85 int flags;
88 /*
89 * This structure describes global (ie., server-wide) parameters.
91 typedef struct
93 int server_role;
95 char **smb_ports;
96 char *dos_charset;
97 char *unix_charset;
98 char *ncalrpc_dir;
99 char *display_charset;
100 char *szLockDir;
101 char *szModulesDir;
102 char *szPidDir;
103 char *szSetupDir;
104 char *szServerString;
105 char *szAutoServices;
106 char *szPasswdChat;
107 char *szConfigFile;
108 char *szSAM_URL;
109 char *szSPOOLSS_URL;
110 char *szWINS_CONFIG_URL;
111 char *szWINS_URL;
112 char *szPrivateDir;
113 char **jsInclude;
114 char **szPasswordServers;
115 char *szSocketOptions;
116 char *szRealm;
117 char **szWINSservers;
118 char **szInterfaces;
119 char *szSocketAddress;
120 char *szAnnounceVersion; /* This is initialised in init_globals */
121 char *szWorkgroup;
122 char *szNetbiosName;
123 char **szNetbiosAliases;
124 char *szNetbiosScope;
125 char *szDomainOtherSIDs;
126 char **szNameResolveOrder;
127 char **dcerpc_ep_servers;
128 char **server_services;
129 char *ntptr_providor;
130 char *szWinbindSeparator;
131 char *szWinbinddSocketDirectory;
132 int bWinbindSealedPipes;
133 char *swat_directory;
134 int tls_enabled;
135 char *tls_keyfile;
136 char *tls_certfile;
137 char *tls_cafile;
138 char *tls_crlfile;
139 int max_mux;
140 int max_xmit;
141 int pwordlevel;
142 int srv_maxprotocol;
143 int srv_minprotocol;
144 int cli_maxprotocol;
145 int cli_minprotocol;
146 int security;
147 char **AuthMethods;
148 int paranoid_server_security;
149 int max_wins_ttl;
150 int min_wins_ttl;
151 int announce_as; /* This is initialised in init_globals */
152 int nbt_port;
153 int dgram_port;
154 int cldap_port;
155 int krb5_port;
156 int kpasswd_port;
157 int web_port;
158 char *socket_options;
159 int bWINSsupport;
160 int bWINSdnsProxy;
161 char *szWINSHook;
162 int bLocalMaster;
163 int bPreferredMaster;
164 int bEncryptPasswords;
165 int bNullPasswords;
166 int bObeyPamRestrictions;
167 int bLargeReadwrite;
168 int bReadRaw;
169 int bWriteRaw;
170 int bTimeServer;
171 int bBindInterfacesOnly;
172 int bNTSmbSupport;
173 int bNTStatusSupport;
174 int bLanmanAuth;
175 int bNTLMAuth;
176 int bUseSpnego;
177 int server_signing;
178 int client_signing;
179 int bClientPlaintextAuth;
180 int bClientLanManAuth;
181 int bClientNTLMv2Auth;
182 int client_use_spnego_principal;
183 int bHostMSDfs;
184 int bUnicode;
185 int bUnixExtensions;
186 int bDisableNetbios;
187 int bRpcBigEndian;
188 struct param_opt *param_opt;
190 global;
192 static global Globals;
195 * This structure describes a single service.
197 typedef struct
199 int valid;
200 char *szService;
201 char *szPath;
202 char *szCopy;
203 char *szInclude;
204 char *szPrintername;
205 char **szHostsallow;
206 char **szHostsdeny;
207 char *comment;
208 char *volume;
209 char *fstype;
210 char **ntvfs_handler;
211 int iMaxPrintJobs;
212 int iMaxConnections;
213 int iCSCPolicy;
214 int bAvailable;
215 int bBrowseable;
216 int bRead_only;
217 int bPrint_ok;
218 int bMap_system;
219 int bMap_hidden;
220 int bMap_archive;
221 int bStrictLocking;
222 int *copymap;
223 int bMSDfsRoot;
224 int bStrictSync;
225 int bCIFileSystem;
226 struct param_opt *param_opt;
228 char dummy[3]; /* for alignment */
230 service;
233 /* This is a default service used to prime a services structure */
234 static service sDefault = {
235 True, /* valid */
236 NULL, /* szService */
237 NULL, /* szPath */
238 NULL, /* szCopy */
239 NULL, /* szInclude */
240 NULL, /* szPrintername */
241 NULL, /* szHostsallow */
242 NULL, /* szHostsdeny */
243 NULL, /* comment */
244 NULL, /* volume */
245 NULL, /* fstype */
246 NULL, /* ntvfs_handler */
247 1000, /* iMaxPrintJobs */
248 0, /* iMaxConnections */
249 0, /* iCSCPolicy */
250 True, /* bAvailable */
251 True, /* bBrowseable */
252 True, /* bRead_only */
253 False, /* bPrint_ok */
254 False, /* bMap_system */
255 False, /* bMap_hidden */
256 True, /* bMap_archive */
257 True, /* bStrictLocking */
258 NULL, /* copymap */
259 False, /* bMSDfsRoot */
260 False, /* bStrictSync */
261 False, /* bCIFileSystem */
262 NULL, /* Parametric options */
264 "" /* dummy */
267 /* local variables */
268 static service **ServicePtrs = NULL;
269 static int iNumServices = 0;
270 static int iServiceIndex = 0;
271 static BOOL bInGlobalSection = True;
272 static int default_server_announce;
274 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
276 /* prototypes for the special type handlers */
277 static BOOL handle_include(const char *pszParmValue, char **ptr);
278 static BOOL handle_copy(const char *pszParmValue, char **ptr);
280 static void set_default_server_announce_type(void);
282 static const struct enum_list enum_protocol[] = {
283 {PROTOCOL_SMB2, "SMB2"},
284 {PROTOCOL_NT1, "NT1"},
285 {PROTOCOL_LANMAN2, "LANMAN2"},
286 {PROTOCOL_LANMAN1, "LANMAN1"},
287 {PROTOCOL_CORE, "CORE"},
288 {PROTOCOL_COREPLUS, "COREPLUS"},
289 {PROTOCOL_COREPLUS, "CORE+"},
290 {-1, NULL}
293 static const struct enum_list enum_security[] = {
294 {SEC_SHARE, "SHARE"},
295 {SEC_USER, "USER"},
296 {-1, NULL}
299 /* Types of machine we can announce as. */
300 #define ANNOUNCE_AS_NT_SERVER 1
301 #define ANNOUNCE_AS_WIN95 2
302 #define ANNOUNCE_AS_WFW 3
303 #define ANNOUNCE_AS_NT_WORKSTATION 4
305 static const struct enum_list enum_announce_as[] = {
306 {ANNOUNCE_AS_NT_SERVER, "NT"},
307 {ANNOUNCE_AS_NT_SERVER, "NT Server"},
308 {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"},
309 {ANNOUNCE_AS_WIN95, "win95"},
310 {ANNOUNCE_AS_WFW, "WfW"},
311 {-1, NULL}
314 static const struct enum_list enum_bool_auto[] = {
315 {False, "No"},
316 {False, "False"},
317 {False, "0"},
318 {True, "Yes"},
319 {True, "True"},
320 {True, "1"},
321 {Auto, "Auto"},
322 {-1, NULL}
325 /* Client-side offline caching policy types */
326 #define CSC_POLICY_MANUAL 0
327 #define CSC_POLICY_DOCUMENTS 1
328 #define CSC_POLICY_PROGRAMS 2
329 #define CSC_POLICY_DISABLE 3
331 static const struct enum_list enum_csc_policy[] = {
332 {CSC_POLICY_MANUAL, "manual"},
333 {CSC_POLICY_DOCUMENTS, "documents"},
334 {CSC_POLICY_PROGRAMS, "programs"},
335 {CSC_POLICY_DISABLE, "disable"},
336 {-1, NULL}
339 /* SMB signing types. */
340 static const struct enum_list enum_smb_signing_vals[] = {
341 {SMB_SIGNING_OFF, "No"},
342 {SMB_SIGNING_OFF, "False"},
343 {SMB_SIGNING_OFF, "0"},
344 {SMB_SIGNING_OFF, "Off"},
345 {SMB_SIGNING_OFF, "disabled"},
346 {SMB_SIGNING_SUPPORTED, "Yes"},
347 {SMB_SIGNING_SUPPORTED, "True"},
348 {SMB_SIGNING_SUPPORTED, "1"},
349 {SMB_SIGNING_SUPPORTED, "On"},
350 {SMB_SIGNING_SUPPORTED, "enabled"},
351 {SMB_SIGNING_REQUIRED, "required"},
352 {SMB_SIGNING_REQUIRED, "mandatory"},
353 {SMB_SIGNING_REQUIRED, "force"},
354 {SMB_SIGNING_REQUIRED, "forced"},
355 {SMB_SIGNING_REQUIRED, "enforced"},
356 {SMB_SIGNING_AUTO, "auto"},
357 {-1, NULL}
360 static const struct enum_list enum_server_role[] = {
361 {ROLE_STANDALONE, "standalone"},
362 {ROLE_DOMAIN_MEMBER, "member server"},
363 {ROLE_DOMAIN_BDC, "bdc"},
364 {ROLE_DOMAIN_PDC, "pdc"},
365 {-1, NULL}
369 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
371 * Note: We have a flag called FLAG_DEVELOPER but is not used at this time, it
372 * is implied in current control logic. This may change at some later time. A
373 * flag value of 0 means - show as development option only.
375 * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
376 * screen in SWAT. This is used to exclude parameters as well as to squash all
377 * parameters that have been duplicated by pseudonyms.
379 static struct parm_struct parm_table[] = {
380 {"Base Options", P_SEP, P_SEPARATOR},
382 {"server role", P_ENUM, P_GLOBAL, &Globals.server_role, NULL, enum_server_role, FLAG_BASIC},
384 {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
385 {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
386 {"ncalrpc dir", P_STRING, P_GLOBAL, &Globals.ncalrpc_dir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
387 {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
388 {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
389 {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
390 {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE},
391 {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkgroup, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
392 {"realm", P_STRING, P_GLOBAL, &Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
393 {"netbios name", P_USTRING, P_GLOBAL, &Globals.szNetbiosName, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
394 {"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
395 {"netbios scope", P_USTRING, P_GLOBAL, &Globals.szNetbiosScope, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
396 {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
397 {"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
398 {"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
399 {"ntvfs handler", P_LIST, P_LOCAL, &sDefault.ntvfs_handler, NULL, NULL, FLAG_ADVANCED},
400 {"ntptr providor", P_STRING, P_GLOBAL, &Globals.ntptr_providor, NULL, NULL, FLAG_ADVANCED},
401 {"dcerpc endpoint servers", P_LIST, P_GLOBAL, &Globals.dcerpc_ep_servers, NULL, NULL, FLAG_ADVANCED},
402 {"server services", P_LIST, P_GLOBAL, &Globals.server_services, NULL, NULL, FLAG_ADVANCED},
404 {"Security Options", P_SEP, P_SEPARATOR},
406 {"security", P_ENUM, P_GLOBAL, &Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
407 {"auth methods", P_LIST, P_GLOBAL, &Globals.AuthMethods, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
408 {"encrypt passwords", P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
409 {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
410 {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
411 {"password server", P_LIST, P_GLOBAL, &Globals.szPasswordServers, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
412 {"sam database", P_STRING, P_GLOBAL, &Globals.szSAM_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
413 {"spoolss database", P_STRING, P_GLOBAL, &Globals.szSPOOLSS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
414 {"wins config database", P_STRING, P_GLOBAL, &Globals.szWINS_CONFIG_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
415 {"wins database", P_STRING, P_GLOBAL, &Globals.szWINS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
416 {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
417 {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
418 {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
419 {"lanman auth", P_BOOL, P_GLOBAL, &Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
420 {"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
421 {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
422 {"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
423 {"client plaintext auth", P_BOOL, P_GLOBAL, &Globals.bClientPlaintextAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
424 {"client use spnego principal", P_BOOL, P_GLOBAL, &Globals.client_use_spnego_principal, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
426 {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE},
428 {"hosts allow", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
429 {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
431 {"Logging Options", P_SEP, P_SEPARATOR},
433 {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
434 {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_HIDE},
435 {"log file", P_STRING, P_GLOBAL, &logfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
437 {"Protocol Options", P_SEP, P_SEPARATOR},
439 {"smb ports", P_LIST, P_GLOBAL, &Globals.smb_ports, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
440 {"nbt port", P_INTEGER, P_GLOBAL, &Globals.nbt_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
441 {"dgram port", P_INTEGER, P_GLOBAL, &Globals.dgram_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
442 {"cldap port", P_INTEGER, P_GLOBAL, &Globals.cldap_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
443 {"krb5 port", P_INTEGER, P_GLOBAL, &Globals.krb5_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
444 {"kpasswd port", P_INTEGER, P_GLOBAL, &Globals.kpasswd_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
445 {"web port", P_INTEGER, P_GLOBAL, &Globals.web_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
446 {"tls enabled", P_BOOL, P_GLOBAL, &Globals.tls_enabled, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
447 {"tls keyfile", P_STRING, P_GLOBAL, &Globals.tls_keyfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
448 {"tls certfile", P_STRING, P_GLOBAL, &Globals.tls_certfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
449 {"tls cafile", P_STRING, P_GLOBAL, &Globals.tls_cafile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
450 {"tls crlfile", P_STRING, P_GLOBAL, &Globals.tls_crlfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
451 {"swat directory", P_STRING, P_GLOBAL, &Globals.swat_directory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
452 {"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, FLAG_DEVELOPER},
453 {"server max protocol", P_ENUM, P_GLOBAL, &Globals.srv_maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
454 {"server min protocol", P_ENUM, P_GLOBAL, &Globals.srv_minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
455 {"client max protocol", P_ENUM, P_GLOBAL, &Globals.cli_maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
456 {"client min protocol", P_ENUM, P_GLOBAL, &Globals.cli_minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
457 {"unicode", P_BOOL, P_GLOBAL, &Globals.bUnicode, NULL, NULL, FLAG_DEVELOPER},
458 {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL, NULL, FLAG_DEVELOPER},
459 {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL, NULL, FLAG_DEVELOPER},
460 {"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
462 {"nt status support", P_BOOL, P_GLOBAL, &Globals.bNTStatusSupport, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
464 {"announce version", P_STRING, P_GLOBAL, &Globals.szAnnounceVersion, NULL, NULL, FLAG_DEVELOPER},
465 {"announce as", P_ENUM, P_GLOBAL, &Globals.announce_as, NULL, enum_announce_as, FLAG_DEVELOPER},
466 {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
467 {"max xmit", P_BYTES, P_GLOBAL, &Globals.max_xmit, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
469 {"name resolve order", P_LIST, P_GLOBAL, &Globals.szNameResolveOrder, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
470 {"max wins ttl", P_INTEGER, P_GLOBAL, &Globals.max_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
471 {"min wins ttl", P_INTEGER, P_GLOBAL, &Globals.min_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
472 {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
473 {"unix extensions", P_BOOL, P_GLOBAL, &Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
474 {"use spnego", P_BOOL, P_GLOBAL, &Globals.bUseSpnego, NULL, NULL, FLAG_DEVELOPER},
475 {"server signing", P_ENUM, P_GLOBAL, &Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
476 {"client signing", P_ENUM, P_GLOBAL, &Globals.client_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
477 {"rpc big endian", P_BOOL, P_GLOBAL, &Globals.bRpcBigEndian, NULL, NULL, FLAG_DEVELOPER},
479 {"Tuning Options", P_SEP, P_SEPARATOR},
481 {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL, NULL, FLAG_SHARE},
482 {"paranoid server security", P_BOOL, P_GLOBAL, &Globals.paranoid_server_security, NULL, NULL, FLAG_DEVELOPER},
483 {"socket options", P_STRING, P_GLOBAL, &Globals.socket_options, NULL, NULL, FLAG_DEVELOPER},
485 {"strict sync", P_BOOL, P_LOCAL, &sDefault.bStrictSync, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
486 {"case insensitive filesystem", P_BOOL, P_LOCAL, &sDefault.bCIFileSystem, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
488 {"Printing Options", P_SEP, P_SEPARATOR},
490 {"max print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxPrintJobs, NULL, NULL, FLAG_PRINT},
491 {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_PRINT},
492 {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_HIDE},
494 {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_PRINT},
495 {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_HIDE},
497 {"Filename Handling", P_SEP, P_SEPARATOR},
499 {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
500 {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
501 {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
503 {"Domain Options", P_SEP, P_SEPARATOR},
505 {"Logon Options", P_SEP, P_SEPARATOR},
508 {"Browse Options", P_SEP, P_SEPARATOR},
510 {"preferred master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
511 {"prefered master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_HIDE},
512 {"local master", P_BOOL, P_GLOBAL, &Globals.bLocalMaster, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
513 {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
514 {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_HIDE},
516 {"WINS Options", P_SEP, P_SEPARATOR},
518 {"wins server", P_LIST, P_GLOBAL, &Globals.szWINSservers, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
519 {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
520 {"dns proxy", P_BOOL, P_GLOBAL, &Globals.bWINSdnsProxy, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
521 {"wins hook", P_STRING, P_GLOBAL, &Globals.szWINSHook, NULL, NULL, FLAG_ADVANCED},
523 {"Locking Options", P_SEP, P_SEPARATOR},
525 {"csc policy", P_ENUM, P_LOCAL, &sDefault.iCSCPolicy, NULL, enum_csc_policy, FLAG_SHARE | FLAG_GLOBAL},
527 {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
529 {"Miscellaneous Options", P_SEP, P_SEPARATOR},
531 {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE},
532 {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
533 {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
534 {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_HIDE},
535 {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
536 {"modules dir", P_STRING, P_GLOBAL, &Globals.szModulesDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
537 {"pid directory", P_STRING, P_GLOBAL, &Globals.szPidDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
538 {"js include", P_LIST, P_GLOBAL, &Globals.jsInclude, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
539 {"setup directory", P_STRING, P_GLOBAL, &Globals.szSetupDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
541 {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL, NULL, FLAG_DEVELOPER},
542 {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL, NULL, FLAG_HIDE},
544 {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy, NULL, FLAG_HIDE},
545 {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include, NULL, FLAG_HIDE},
547 {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
548 {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_SHARE },
549 {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_SHARE},
551 {"panic action", P_STRING, P_GLOBAL, &panic_action, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
553 {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_SHARE},
554 {"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
555 {"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
556 {"winbindd socket directory", P_STRING, P_GLOBAL, &Globals.szWinbinddSocketDirectory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
557 {"winbind sealed pipes", P_BOOL, P_GLOBAL, &Globals.bWinbindSealedPipes, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
559 {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
564 return the parameter table
566 struct parm_struct *lp_parm_table(void)
568 return parm_table;
571 /***************************************************************************
572 Initialise the global parameter structure.
573 ***************************************************************************/
574 static void init_globals(void)
576 int i;
577 char *myname;
579 DEBUG(3, ("Initialising global parameters\n"));
581 for (i = 0; parm_table[i].label; i++) {
582 if ((parm_table[i].type == P_STRING ||
583 parm_table[i].type == P_USTRING) &&
584 parm_table[i].ptr &&
585 !(parm_table[i].flags & FLAG_CMDLINE)) {
586 string_set(parm_table[i].ptr, "");
590 do_parameter("config file", dyn_CONFIGFILE, NULL);
592 do_parameter("server role", "standalone", NULL);
594 /* options that can be set on the command line must be initialised via
595 the slower do_parameter() to ensure that FLAG_CMDLINE is obeyed */
596 #ifdef TCP_NODELAY
597 do_parameter("socket options", "TCP_NODELAY", NULL);
598 #endif
599 do_parameter("workgroup", DEFAULT_WORKGROUP, NULL);
600 myname = get_myname();
601 do_parameter("netbios name", myname, NULL);
602 SAFE_FREE(myname);
603 do_parameter("name resolve order", "lmhosts wins host bcast", NULL);
605 do_parameter("fstype", FSTYPE_STRING, NULL);
606 do_parameter("ntvfs handler", "unixuid default", NULL);
607 do_parameter("max connections", "-1", NULL);
609 do_parameter("dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup", NULL);
610 do_parameter("server services", "smb rpc nbt wrepl ldap cldap web kdc winbind", NULL);
611 do_parameter("ntptr providor", "simple_ldb", NULL);
612 do_parameter("auth methods", "anonymous sam_ignoredomain", NULL);
613 do_parameter("private dir", dyn_PRIVATE_DIR, NULL);
614 do_parameter("sam database", "sam.ldb", NULL);
615 do_parameter("spoolss database", "spoolss.ldb", NULL);
616 do_parameter("wins config database", "wins_config.ldb", NULL);
617 do_parameter("wins database", "wins.ldb", NULL);
618 do_parameter("registry:HKEY_LOCAL_MACHINE", "hklm.ldb", NULL);
620 /* This hive should be dynamically generated by Samba using
621 data from the sam, but for the moment leave it in a tdb to
622 keep regedt32 from popping up an annoying dialog. */
623 do_parameter("registry:HKEY_USERS", "hku.ldb", NULL);
625 /* using UTF8 by default allows us to support all chars */
626 do_parameter("unix charset", "UTF8", NULL);
628 /* Use codepage 850 as a default for the dos character set */
629 do_parameter("dos charset", "CP850", NULL);
632 * Allow the default PASSWD_CHAT to be overridden in local.h.
634 do_parameter("passwd chat", DEFAULT_PASSWD_CHAT, NULL);
636 do_parameter("pid directory", dyn_PIDDIR, NULL);
637 do_parameter("lock dir", dyn_LOCKDIR, NULL);
638 do_parameter("modules dir", dyn_MODULESDIR, NULL);
639 do_parameter("ncalrpc dir", dyn_NCALRPCDIR, NULL);
641 do_parameter("socket address", "0.0.0.0", NULL);
642 do_parameter_var("server string", "Samba %s", SAMBA_VERSION_STRING);
644 do_parameter_var("announce version", "%d.%d",
645 DEFAULT_MAJOR_VERSION,
646 DEFAULT_MINOR_VERSION);
648 do_parameter("password server", "*", NULL);
650 do_parameter("max mux", "50", NULL);
651 do_parameter("max xmit", "12288", NULL);
652 do_parameter("password level", "0", NULL);
653 do_parameter("LargeReadwrite", "True", NULL);
654 do_parameter("server min protocol", "CORE", NULL);
655 do_parameter("server max protocol", "NT1", NULL);
656 do_parameter("client min protocol", "CORE", NULL);
657 do_parameter("client max protocol", "NT1", NULL);
658 do_parameter("security", "USER", NULL);
659 do_parameter("paranoid server security", "True", NULL);
660 do_parameter("EncryptPasswords", "True", NULL);
661 do_parameter("ReadRaw", "True", NULL);
662 do_parameter("WriteRaw", "True", NULL);
663 do_parameter("NullPasswords", "False", NULL);
664 do_parameter("ObeyPamRestrictions", "False", NULL);
665 do_parameter("announce as", "NT SERVER", NULL);
667 do_parameter("TimeServer", "False", NULL);
668 do_parameter("BindInterfacesOnly", "False", NULL);
669 do_parameter("Unicode", "True", NULL);
670 do_parameter("ClientLanManAuth", "True", NULL);
671 do_parameter("LanmanAuth", "True", NULL);
672 do_parameter("NTLMAuth", "True", NULL);
673 do_parameter("client use spnego principal", "False", NULL);
675 do_parameter("UnixExtensions", "False", NULL);
677 do_parameter("PreferredMaster", "Auto", NULL);
678 do_parameter("LocalMaster", "True", NULL);
680 do_parameter("wins support", "False", NULL);
681 do_parameter("dns proxy", "True", NULL);
683 do_parameter("winbind separator", "\\", NULL);
684 do_parameter("winbind sealed pipes", "True", NULL);
685 do_parameter("winbindd socket directory", dyn_WINBINDD_SOCKET_DIR, NULL);
687 do_parameter("client signing", "Yes", NULL);
688 do_parameter("server signing", "auto", NULL);
690 do_parameter("use spnego", "True", NULL);
692 do_parameter("smb ports", SMB_PORTS, NULL);
693 do_parameter("nbt port", "137", NULL);
694 do_parameter("dgram port", "138", NULL);
695 do_parameter("cldap port", "389", NULL);
696 do_parameter("krb5 port", "88", NULL);
697 do_parameter("kpasswd port", "464", NULL);
698 do_parameter("web port", "901", NULL);
699 do_parameter("swat directory", dyn_SWATDIR, NULL);
701 do_parameter("nt status support", "True", NULL);
703 do_parameter("max wins ttl", "518400", NULL); /* 6 days */
704 do_parameter("min wins ttl", "10", NULL);
706 do_parameter("tls enabled", "True", NULL);
707 do_parameter("tls keyfile", "tls/key.pem", NULL);
708 do_parameter("tls certfile", "tls/cert.pem", NULL);
709 do_parameter("tls cafile", "tls/ca.pem", NULL);
710 do_parameter_var("js include", "%s", dyn_JSDIR);
711 do_parameter_var("setup directory", "%s", dyn_SETUPDIR);
713 for (i = 0; parm_table[i].label; i++) {
714 if (!(parm_table[i].flags & FLAG_CMDLINE)) {
715 parm_table[i].flags |= FLAG_DEFAULT;
720 static TALLOC_CTX *lp_talloc;
722 /******************************************************************* a
723 Free up temporary memory - called from the main loop.
724 ********************************************************************/
726 void lp_talloc_free(void)
728 if (!lp_talloc)
729 return;
730 talloc_free(lp_talloc);
731 lp_talloc = NULL;
734 /*******************************************************************
735 Convenience routine to grab string parameters into temporary memory
736 and run standard_sub_basic on them. The buffers can be written to by
737 callers without affecting the source string.
738 ********************************************************************/
740 static const char *lp_string(const char *s)
742 #if 0 /* until REWRITE done to make thread-safe */
743 size_t len = s ? strlen(s) : 0;
744 char *ret;
745 #endif
747 /* The follow debug is useful for tracking down memory problems
748 especially if you have an inner loop that is calling a lp_*()
749 function that returns a string. Perhaps this debug should be
750 present all the time? */
752 #if 0
753 DEBUG(10, ("lp_string(%s)\n", s));
754 #endif
756 #if 0 /* until REWRITE done to make thread-safe */
757 if (!lp_talloc)
758 lp_talloc = talloc_init("lp_talloc");
760 ret = talloc_array(lp_talloc, char, len + 100); /* leave room for substitution */
762 if (!ret)
763 return NULL;
765 if (!s)
766 *ret = 0;
767 else
768 strlcpy(ret, s, len);
770 if (trim_string(ret, "\"", "\"")) {
771 if (strchr(ret,'"') != NULL)
772 strlcpy(ret, s, len);
775 standard_sub_basic(ret,len+100);
776 return (ret);
777 #endif
778 return s;
782 In this section all the functions that are used to access the
783 parameters from the rest of the program are defined
786 #define FN_GLOBAL_STRING(fn_name,ptr) \
787 const char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
788 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
789 const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");}
790 #define FN_GLOBAL_LIST(fn_name,ptr) \
791 const char **fn_name(void) {return(*(const char ***)(ptr));}
792 #define FN_GLOBAL_BOOL(fn_name,ptr) \
793 BOOL fn_name(void) {return((BOOL)*(int *)(ptr));}
794 #define FN_GLOBAL_CHAR(fn_name,ptr) \
795 char fn_name(void) {return(*(char *)(ptr));}
796 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
797 int fn_name(void) {return(*(int *)(ptr));}
799 #define FN_LOCAL_STRING(fn_name,val) \
800 const char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
801 #define FN_LOCAL_CONST_STRING(fn_name,val) \
802 const char *fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
803 #define FN_LOCAL_LIST(fn_name,val) \
804 const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
805 #define FN_LOCAL_BOOL(fn_name,val) \
806 BOOL fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
807 #define FN_LOCAL_CHAR(fn_name,val) \
808 char fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
809 #define FN_LOCAL_INTEGER(fn_name,val) \
810 int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
812 _PUBLIC_ FN_GLOBAL_INTEGER(lp_server_role, &Globals.server_role)
813 _PUBLIC_ FN_GLOBAL_LIST(lp_smb_ports, &Globals.smb_ports)
814 _PUBLIC_ FN_GLOBAL_INTEGER(lp_nbt_port, &Globals.nbt_port)
815 _PUBLIC_ FN_GLOBAL_INTEGER(lp_dgram_port, &Globals.dgram_port)
816 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cldap_port, &Globals.cldap_port)
817 _PUBLIC_ FN_GLOBAL_INTEGER(lp_krb5_port, &Globals.krb5_port)
818 _PUBLIC_ FN_GLOBAL_INTEGER(lp_kpasswd_port, &Globals.kpasswd_port)
819 _PUBLIC_ FN_GLOBAL_INTEGER(lp_web_port, &Globals.web_port)
820 _PUBLIC_ FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
821 _PUBLIC_ FN_GLOBAL_STRING(lp_swat_directory, &Globals.swat_directory)
822 _PUBLIC_ FN_GLOBAL_BOOL(lp_tls_enabled, &Globals.tls_enabled)
823 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_keyfile, &Globals.tls_keyfile)
824 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_certfile, &Globals.tls_certfile)
825 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_cafile, &Globals.tls_cafile)
826 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_crlfile, &Globals.tls_crlfile)
827 _PUBLIC_ FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
828 _PUBLIC_ FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset)
829 _PUBLIC_ FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
830 _PUBLIC_ FN_GLOBAL_STRING(lp_sam_url, &Globals.szSAM_URL)
831 _PUBLIC_ FN_GLOBAL_STRING(lp_spoolss_url, &Globals.szSPOOLSS_URL)
832 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_config_url, &Globals.szWINS_CONFIG_URL)
833 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_url, &Globals.szWINS_URL)
834 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
835 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_winbindd_socket_directory, &Globals.szWinbinddSocketDirectory)
836 _PUBLIC_ FN_GLOBAL_BOOL(lp_winbind_sealed_pipes, &Globals.bWinbindSealedPipes)
837 _PUBLIC_ FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
838 _PUBLIC_ FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
839 _PUBLIC_ FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
840 _PUBLIC_ FN_GLOBAL_STRING(lp_modulesdir, &Globals.szModulesDir)
841 _PUBLIC_ FN_GLOBAL_STRING(lp_setupdir, &Globals.szSetupDir)
842 _PUBLIC_ FN_GLOBAL_STRING(lp_ncalrpc_dir, &Globals.ncalrpc_dir)
843 _PUBLIC_ FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
844 _PUBLIC_ FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, &Globals.dcerpc_ep_servers)
845 _PUBLIC_ FN_GLOBAL_LIST(lp_server_services, &Globals.server_services)
846 _PUBLIC_ FN_GLOBAL_STRING(lp_ntptr_providor, &Globals.ntptr_providor)
847 _PUBLIC_ FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
848 _PUBLIC_ FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
849 _PUBLIC_ FN_GLOBAL_LIST(lp_passwordserver, &Globals.szPasswordServers)
850 _PUBLIC_ FN_GLOBAL_LIST(lp_name_resolve_order, &Globals.szNameResolveOrder)
851 _PUBLIC_ FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
852 _PUBLIC_ FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
853 _PUBLIC_ FN_GLOBAL_STRING(lp_workgroup, &Globals.szWorkgroup)
854 _PUBLIC_ FN_GLOBAL_STRING(lp_netbios_name, &Globals.szNetbiosName)
855 _PUBLIC_ FN_GLOBAL_STRING(lp_netbios_scope, &Globals.szNetbiosScope)
856 _PUBLIC_ FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
857 _PUBLIC_ FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
858 _PUBLIC_ FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
859 _PUBLIC_ FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
861 _PUBLIC_ FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
862 _PUBLIC_ FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
863 _PUBLIC_ FN_GLOBAL_BOOL(lp_wins_dns_proxy, &Globals.bWINSdnsProxy)
864 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
865 _PUBLIC_ FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
866 _PUBLIC_ FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
867 _PUBLIC_ FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
868 _PUBLIC_ FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw)
869 _PUBLIC_ FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords)
870 _PUBLIC_ FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions)
871 _PUBLIC_ FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
872 static FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
873 _PUBLIC_ FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
874 _PUBLIC_ FN_GLOBAL_BOOL(lp_unicode, &Globals.bUnicode)
875 _PUBLIC_ FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
876 _PUBLIC_ FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
877 _PUBLIC_ FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
878 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_plaintext_auth, &Globals.bClientPlaintextAuth)
879 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
880 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
881 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_use_spnego_principal, &Globals.client_use_spnego_principal)
882 _PUBLIC_ FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
883 _PUBLIC_ FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions)
884 _PUBLIC_ FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
885 _PUBLIC_ FN_GLOBAL_BOOL(lp_rpc_big_endian, &Globals.bRpcBigEndian)
886 _PUBLIC_ FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
887 _PUBLIC_ FN_GLOBAL_INTEGER(lp_min_wins_ttl, &Globals.min_wins_ttl)
888 _PUBLIC_ FN_GLOBAL_INTEGER(lp_maxmux, &Globals.max_mux)
889 _PUBLIC_ FN_GLOBAL_INTEGER(lp_max_xmit, &Globals.max_xmit)
890 _PUBLIC_ FN_GLOBAL_INTEGER(lp_passwordlevel, &Globals.pwordlevel)
891 _PUBLIC_ FN_GLOBAL_INTEGER(lp_srv_maxprotocol, &Globals.srv_maxprotocol)
892 _PUBLIC_ FN_GLOBAL_INTEGER(lp_srv_minprotocol, &Globals.srv_minprotocol)
893 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cli_maxprotocol, &Globals.cli_maxprotocol)
894 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cli_minprotocol, &Globals.cli_minprotocol)
895 _PUBLIC_ FN_GLOBAL_INTEGER(lp_security, &Globals.security)
896 _PUBLIC_ FN_GLOBAL_LIST(lp_auth_methods, &Globals.AuthMethods)
897 _PUBLIC_ FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security)
898 static FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as)
899 _PUBLIC_ FN_GLOBAL_LIST(lp_js_include, &Globals.jsInclude)
900 _PUBLIC_
901 _PUBLIC_
902 _PUBLIC_ FN_LOCAL_STRING(lp_servicename, szService)
903 _PUBLIC_ FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
904 _PUBLIC_ FN_LOCAL_STRING(lp_pathname, szPath)
905 static FN_LOCAL_STRING(_lp_printername, szPrintername)
906 _PUBLIC_ FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
907 _PUBLIC_ FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
908 _PUBLIC_ FN_LOCAL_STRING(lp_comment, comment)
909 _PUBLIC_ FN_LOCAL_STRING(lp_fstype, fstype)
910 static FN_LOCAL_STRING(lp_volume, volume)
911 _PUBLIC_ FN_LOCAL_LIST(lp_ntvfs_handler, ntvfs_handler)
912 _PUBLIC_ FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
913 _PUBLIC_ FN_LOCAL_BOOL(lp_browseable, bBrowseable)
914 _PUBLIC_ FN_LOCAL_BOOL(lp_readonly, bRead_only)
915 _PUBLIC_ FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
916 _PUBLIC_ FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
917 _PUBLIC_ FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
918 _PUBLIC_ FN_LOCAL_BOOL(lp_strict_locking, bStrictLocking)
919 _PUBLIC_ FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
920 _PUBLIC_ FN_LOCAL_BOOL(lp_ci_filesystem, bCIFileSystem)
921 _PUBLIC_ FN_LOCAL_BOOL(lp_map_system, bMap_system)
922 _PUBLIC_ FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
923 _PUBLIC_ FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
924 _PUBLIC_ FN_GLOBAL_INTEGER(lp_server_signing, &Globals.server_signing)
925 _PUBLIC_ FN_GLOBAL_INTEGER(lp_client_signing, &Globals.client_signing)
927 /* local prototypes */
929 static int map_parameter(const char *pszParmName);
930 static int getservicebyname(const char *pszServiceName,
931 service * pserviceDest);
932 static void copy_service(service * pserviceDest,
933 service * pserviceSource, int *pcopymapDest);
934 static BOOL service_ok(int iService);
935 static BOOL do_section(const char *pszSectionName, void *);
936 static void init_copymap(service * pservice);
938 /* This is a helper function for parametrical options support. */
939 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
940 /* Actual parametrical functions are quite simple */
941 const char *lp_get_parametric(int lookup_service, const char *type, const char *option)
943 char *vfskey;
944 struct param_opt *data;
946 if (lookup_service >= iNumServices) return NULL;
948 data = (lookup_service < 0) ?
949 Globals.param_opt : ServicePtrs[lookup_service]->param_opt;
951 asprintf(&vfskey, "%s:%s", type, option);
952 strlower(vfskey);
954 while (data) {
955 if (strcmp(data->key, vfskey) == 0) {
956 free(vfskey);
957 return data->value;
959 data = data->next;
962 if (lookup_service >= 0) {
963 /* Try to fetch the same option but from globals */
964 /* but only if we are not already working with Globals */
965 data = Globals.param_opt;
966 while (data) {
967 if (strcmp(data->key, vfskey) == 0) {
968 free(vfskey);
969 return data->value;
971 data = data->next;
975 free(vfskey);
977 return NULL;
981 /*******************************************************************
982 convenience routine to return int parameters.
983 ********************************************************************/
984 static int lp_int(const char *s)
987 if (!s) {
988 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
989 return (-1);
992 return strtol(s, NULL, 0);
995 /*******************************************************************
996 convenience routine to return unsigned long parameters.
997 ********************************************************************/
998 static int lp_ulong(const char *s)
1001 if (!s) {
1002 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
1003 return (-1);
1006 return strtoul(s, NULL, 0);
1009 /*******************************************************************
1010 convenience routine to return boolean parameters.
1011 ********************************************************************/
1012 static BOOL lp_bool(const char *s)
1014 BOOL ret = False;
1016 if (!s) {
1017 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
1018 return False;
1021 if (!set_boolean(s, &ret)) {
1022 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1023 return False;
1026 return ret;
1030 /* Return parametric option from a given service. Type is a part of option before ':' */
1031 /* Parametric option has following syntax: 'Type: option = value' */
1032 /* Returned value is allocated in 'lp_talloc' context */
1034 const char *lp_parm_string(int lookup_service, const char *type, const char *option)
1036 const char *value = lp_get_parametric(lookup_service, type, option);
1038 if (value)
1039 return lp_string(value);
1041 return NULL;
1044 /* Return parametric option from a given service. Type is a part of option before ':' */
1045 /* Parametric option has following syntax: 'Type: option = value' */
1046 /* Returned value is allocated in 'lp_talloc' context */
1048 const char **lp_parm_string_list(int lookup_service, const char *type, const char *option,
1049 const char *separator)
1051 const char *value = lp_get_parametric(lookup_service, type, option);
1053 if (value)
1054 return str_list_make(talloc_autofree_context(), value, separator);
1056 return NULL;
1059 /* Return parametric option from a given service. Type is a part of option before ':' */
1060 /* Parametric option has following syntax: 'Type: option = value' */
1062 int lp_parm_int(int lookup_service, const char *type, const char *option, int default_v)
1064 const char *value = lp_get_parametric(lookup_service, type, option);
1066 if (value)
1067 return lp_int(value);
1069 return default_v;
1072 /* Return parametric option from a given service. Type is a part of
1073 * option before ':'.
1074 * Parametric option has following syntax: 'Type: option = value'.
1077 int lp_parm_bytes(int lookup_service, const char *type, const char *option, int default_v)
1079 uint64_t bval;
1081 const char *value = lp_get_parametric(lookup_service, type, option);
1083 if (value && conv_str_size(value, &bval)) {
1084 if (bval <= INT_MAX) {
1085 return (int)bval;
1089 return default_v;
1092 /* Return parametric option from a given service. Type is a part of option before ':' */
1093 /* Parametric option has following syntax: 'Type: option = value' */
1095 unsigned long lp_parm_ulong(int lookup_service, const char *type, const char *option, unsigned long default_v)
1097 const char *value = lp_get_parametric(lookup_service, type, option);
1099 if (value)
1100 return lp_ulong(value);
1102 return default_v;
1105 /* Return parametric option from a given service. Type is a part of option before ':' */
1106 /* Parametric option has following syntax: 'Type: option = value' */
1108 BOOL lp_parm_bool(int lookup_service, const char *type, const char *option, BOOL default_v)
1110 const char *value = lp_get_parametric(lookup_service, type, option);
1112 if (value)
1113 return lp_bool(value);
1115 return default_v;
1119 /***************************************************************************
1120 Initialise a service to the defaults.
1121 ***************************************************************************/
1123 static void init_service(service * pservice)
1125 memset((char *)pservice, '\0', sizeof(service));
1126 copy_service(pservice, &sDefault, NULL);
1129 /***************************************************************************
1130 Free the dynamically allocated parts of a service struct.
1131 ***************************************************************************/
1133 static void free_service(service *pservice)
1135 int i;
1136 struct param_opt *data, *pdata;
1137 if (!pservice)
1138 return;
1140 if (pservice->szService)
1141 DEBUG(5, ("free_service: Freeing service %s\n",
1142 pservice->szService));
1144 string_free(&pservice->szService);
1145 SAFE_FREE(pservice->copymap);
1147 for (i = 0; parm_table[i].label; i++) {
1148 if ((parm_table[i].type == P_STRING ||
1149 parm_table[i].type == P_USTRING) &&
1150 parm_table[i].class == P_LOCAL) {
1151 string_free((char **)
1152 (((char *)pservice) +
1153 PTR_DIFF(parm_table[i].ptr, &sDefault)));
1154 } else if (parm_table[i].type == P_LIST &&
1155 parm_table[i].class == P_LOCAL) {
1156 char ***listp = (char ***)(((char *)pservice) +
1157 PTR_DIFF(parm_table[i].ptr, &sDefault));
1158 talloc_free(*listp);
1159 *listp = NULL;
1163 DEBUG(5,("Freeing parametrics:\n"));
1164 data = pservice->param_opt;
1165 while (data) {
1166 DEBUG(5,("[%s = %s]\n", data->key, data->value));
1167 string_free(&data->key);
1168 string_free(&data->value);
1169 pdata = data->next;
1170 SAFE_FREE(data);
1171 data = pdata;
1174 ZERO_STRUCTP(pservice);
1177 /***************************************************************************
1178 Add a new service to the services array initialising it with the given
1179 service.
1180 ***************************************************************************/
1182 static int add_a_service(const service *pservice, const char *name)
1184 int i;
1185 service tservice;
1186 int num_to_alloc = iNumServices + 1;
1187 struct param_opt *data, *pdata;
1189 tservice = *pservice;
1191 /* it might already exist */
1192 if (name) {
1193 i = getservicebyname(name, NULL);
1194 if (i >= 0) {
1195 /* Clean all parametric options for service */
1196 /* They will be added during parsing again */
1197 data = ServicePtrs[i]->param_opt;
1198 while (data) {
1199 string_free(&data->key);
1200 string_free(&data->value);
1201 pdata = data->next;
1202 SAFE_FREE(data);
1203 data = pdata;
1205 ServicePtrs[i]->param_opt = NULL;
1206 return (i);
1210 /* find an invalid one */
1211 for (i = 0; i < iNumServices; i++)
1212 if (!ServicePtrs[i]->valid)
1213 break;
1215 /* if not, then create one */
1216 if (i == iNumServices) {
1217 service **tsp;
1219 tsp = realloc_p(ServicePtrs, service *, num_to_alloc);
1221 if (!tsp) {
1222 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1223 return (-1);
1225 else {
1226 ServicePtrs = tsp;
1227 ServicePtrs[iNumServices] = malloc_p(service);
1229 if (!ServicePtrs[iNumServices]) {
1230 DEBUG(0,("add_a_service: out of memory!\n"));
1231 return (-1);
1234 iNumServices++;
1235 } else
1236 free_service(ServicePtrs[i]);
1238 ServicePtrs[i]->valid = True;
1240 init_service(ServicePtrs[i]);
1241 copy_service(ServicePtrs[i], &tservice, NULL);
1242 if (name)
1243 string_set(&ServicePtrs[i]->szService, name);
1244 return (i);
1247 /***************************************************************************
1248 Add a new home service, with the specified home directory, defaults coming
1249 from service ifrom.
1250 ***************************************************************************/
1252 BOOL lp_add_home(const char *pszHomename, int iDefaultService,
1253 const char *user, const char *pszHomedir)
1255 int i;
1256 pstring newHomedir;
1258 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1260 if (i < 0)
1261 return (False);
1263 if (!(*(ServicePtrs[iDefaultService]->szPath))
1264 || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(-1))) {
1265 pstrcpy(newHomedir, pszHomedir);
1266 } else {
1267 pstrcpy(newHomedir, lp_pathname(iDefaultService));
1268 string_sub(newHomedir,"%H", pszHomedir, sizeof(newHomedir));
1271 string_set(&ServicePtrs[i]->szPath, newHomedir);
1273 if (!(*(ServicePtrs[i]->comment))) {
1274 pstring comment;
1275 slprintf(comment, sizeof(comment) - 1,
1276 "Home directory of %s", user);
1277 string_set(&ServicePtrs[i]->comment, comment);
1279 ServicePtrs[i]->bAvailable = sDefault.bAvailable;
1280 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1282 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1283 user, newHomedir));
1285 return (True);
1288 /***************************************************************************
1289 Add a new service, based on an old one.
1290 ***************************************************************************/
1292 int lp_add_service(const char *pszService, int iDefaultService)
1294 return (add_a_service(ServicePtrs[iDefaultService], pszService));
1297 /***************************************************************************
1298 Add the IPC service.
1299 ***************************************************************************/
1301 static BOOL lp_add_hidden(const char *name, const char *fstype)
1303 pstring comment;
1304 int i = add_a_service(&sDefault, name);
1306 if (i < 0)
1307 return (False);
1309 slprintf(comment, sizeof(comment) - 1,
1310 "%s Service (%s)", fstype, Globals.szServerString);
1312 string_set(&ServicePtrs[i]->szPath, tmpdir());
1313 string_set(&ServicePtrs[i]->comment, comment);
1314 string_set(&ServicePtrs[i]->fstype, fstype);
1315 ServicePtrs[i]->iMaxConnections = -1;
1316 ServicePtrs[i]->bAvailable = True;
1317 ServicePtrs[i]->bRead_only = True;
1318 ServicePtrs[i]->bPrint_ok = False;
1319 ServicePtrs[i]->bBrowseable = False;
1321 if (strcasecmp(fstype, "IPC") == 0) {
1322 lp_do_parameter(i, "ntvfs handler", "default");
1325 DEBUG(3, ("adding hidden service %s\n", name));
1327 return (True);
1330 /***************************************************************************
1331 Add a new printer service, with defaults coming from service iFrom.
1332 ***************************************************************************/
1334 BOOL lp_add_printer(const char *pszPrintername, int iDefaultService)
1336 const char *comment = "From Printcap";
1337 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1339 if (i < 0)
1340 return (False);
1342 /* note that we do NOT default the availability flag to True - */
1343 /* we take it from the default service passed. This allows all */
1344 /* dynamic printers to be disabled by disabling the [printers] */
1345 /* entry (if/when the 'available' keyword is implemented!). */
1347 /* the printer name is set to the service name. */
1348 string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1349 string_set(&ServicePtrs[i]->comment, comment);
1350 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1351 /* Printers cannot be read_only. */
1352 ServicePtrs[i]->bRead_only = False;
1353 /* Printer services must be printable. */
1354 ServicePtrs[i]->bPrint_ok = True;
1356 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1358 update_server_announce_as_printserver();
1360 return (True);
1363 /***************************************************************************
1364 Map a parameter's string representation to something we can use.
1365 Returns False if the parameter string is not recognised, else TRUE.
1366 ***************************************************************************/
1368 static int map_parameter(const char *pszParmName)
1370 int iIndex;
1372 if (*pszParmName == '-')
1373 return (-1);
1375 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1376 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1377 return (iIndex);
1379 /* Warn only if it isn't parametric option */
1380 if (strchr(pszParmName, ':') == NULL)
1381 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1382 /* We do return 'fail' for parametric options as well because they are
1383 stored in different storage
1385 return (-1);
1390 return the parameter structure for a parameter
1392 struct parm_struct *lp_parm_struct(const char *name)
1394 int parmnum = map_parameter(name);
1395 if (parmnum == -1) return NULL;
1396 return &parm_table[parmnum];
1400 return the parameter pointer for a parameter
1402 void *lp_parm_ptr(int snum, struct parm_struct *parm)
1404 if (snum == -1) {
1405 return parm->ptr;
1407 return ((char *)ServicePtrs[snum]) + PTR_DIFF(parm->ptr, &sDefault);
1410 /***************************************************************************
1411 Find a service by name. Otherwise works like get_service.
1412 ***************************************************************************/
1414 static int getservicebyname(const char *pszServiceName, service * pserviceDest)
1416 int iService;
1418 for (iService = iNumServices - 1; iService >= 0; iService--)
1419 if (VALID(iService) &&
1420 strwicmp(ServicePtrs[iService]->szService, pszServiceName) == 0) {
1421 if (pserviceDest != NULL)
1422 copy_service(pserviceDest, ServicePtrs[iService], NULL);
1423 break;
1426 return (iService);
1429 /***************************************************************************
1430 Copy a service structure to another.
1431 If pcopymapDest is NULL then copy all fields
1432 ***************************************************************************/
1434 static void copy_service(service * pserviceDest, service * pserviceSource, int *pcopymapDest)
1436 int i;
1437 BOOL bcopyall = (pcopymapDest == NULL);
1438 struct param_opt *data, *pdata, *paramo;
1439 BOOL not_added;
1441 for (i = 0; parm_table[i].label; i++)
1442 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1443 (bcopyall || pcopymapDest[i])) {
1444 void *def_ptr = parm_table[i].ptr;
1445 void *src_ptr =
1446 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
1447 &sDefault);
1448 void *dest_ptr =
1449 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
1450 &sDefault);
1452 switch (parm_table[i].type) {
1453 case P_BOOL:
1454 *(int *)dest_ptr = *(int *)src_ptr;
1455 break;
1457 case P_INTEGER:
1458 case P_ENUM:
1459 *(int *)dest_ptr = *(int *)src_ptr;
1460 break;
1462 case P_STRING:
1463 string_set(dest_ptr,
1464 *(char **)src_ptr);
1465 break;
1467 case P_USTRING:
1468 string_set(dest_ptr,
1469 *(char **)src_ptr);
1470 strupper(*(char **)dest_ptr);
1471 break;
1472 case P_LIST:
1473 *(const char ***)dest_ptr = str_list_copy(talloc_autofree_context(),
1474 *(const char ***)src_ptr);
1475 break;
1476 default:
1477 break;
1481 if (bcopyall) {
1482 init_copymap(pserviceDest);
1483 if (pserviceSource->copymap)
1484 memcpy((void *)pserviceDest->copymap,
1485 (void *)pserviceSource->copymap,
1486 sizeof(int) * NUMPARAMETERS);
1489 data = pserviceSource->param_opt;
1490 while (data) {
1491 not_added = True;
1492 pdata = pserviceDest->param_opt;
1493 /* Traverse destination */
1494 while (pdata) {
1495 /* If we already have same option, override it */
1496 if (strcmp(pdata->key, data->key) == 0) {
1497 string_free(&pdata->value);
1498 pdata->value = strdup(data->value);
1499 not_added = False;
1500 break;
1502 pdata = pdata->next;
1504 if (not_added) {
1505 paramo = malloc_p(struct param_opt);
1506 if (!paramo)
1507 smb_panic("OOM");
1508 paramo->key = strdup(data->key);
1509 paramo->value = strdup(data->value);
1510 DLIST_ADD(pserviceDest->param_opt, paramo);
1512 data = data->next;
1516 /***************************************************************************
1517 Check a service for consistency. Return False if the service is in any way
1518 incomplete or faulty, else True.
1519 ***************************************************************************/
1521 static BOOL service_ok(int iService)
1523 BOOL bRetval;
1525 bRetval = True;
1526 if (ServicePtrs[iService]->szService[0] == '\0') {
1527 DEBUG(0, ("The following message indicates an internal error:\n"));
1528 DEBUG(0, ("No service name in service entry.\n"));
1529 bRetval = False;
1532 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1533 /* I can't see why you'd want a non-printable printer service... */
1534 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
1535 if (!ServicePtrs[iService]->bPrint_ok) {
1536 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
1537 ServicePtrs[iService]->szService));
1538 ServicePtrs[iService]->bPrint_ok = True;
1539 update_server_announce_as_printserver();
1541 /* [printers] service must also be non-browsable. */
1542 if (ServicePtrs[iService]->bBrowseable)
1543 ServicePtrs[iService]->bBrowseable = False;
1546 /* If a service is flagged unavailable, log the fact at level 0. */
1547 if (!ServicePtrs[iService]->bAvailable)
1548 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
1549 ServicePtrs[iService]->szService));
1551 return (bRetval);
1554 static struct file_lists {
1555 struct file_lists *next;
1556 char *name;
1557 char *subfname;
1558 time_t modtime;
1559 } *file_lists = NULL;
1561 /*******************************************************************
1562 Keep a linked list of all config files so we know when one has changed
1563 it's date and needs to be reloaded.
1564 ********************************************************************/
1566 static void add_to_file_list(const char *fname, const char *subfname)
1568 struct file_lists *f = file_lists;
1570 while (f) {
1571 if (f->name && !strcmp(f->name, fname))
1572 break;
1573 f = f->next;
1576 if (!f) {
1577 f = malloc_p(struct file_lists);
1578 if (!f)
1579 return;
1580 f->next = file_lists;
1581 f->name = strdup(fname);
1582 if (!f->name) {
1583 SAFE_FREE(f);
1584 return;
1586 f->subfname = strdup(subfname);
1587 if (!f->subfname) {
1588 SAFE_FREE(f);
1589 return;
1591 file_lists = f;
1592 f->modtime = file_modtime(subfname);
1593 } else {
1594 time_t t = file_modtime(subfname);
1595 if (t)
1596 f->modtime = t;
1600 /*******************************************************************
1601 Check if a config file has changed date.
1602 ********************************************************************/
1604 BOOL lp_file_list_changed(void)
1606 struct file_lists *f = file_lists;
1607 DEBUG(6, ("lp_file_list_changed()\n"));
1609 while (f) {
1610 pstring n2;
1611 time_t mod_time;
1613 pstrcpy(n2, f->name);
1614 standard_sub_basic(n2,sizeof(n2));
1616 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
1617 f->name, n2, ctime(&f->modtime)));
1619 mod_time = file_modtime(n2);
1621 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
1622 DEBUGADD(6,
1623 ("file %s modified: %s\n", n2,
1624 ctime(&mod_time)));
1625 f->modtime = mod_time;
1626 SAFE_FREE(f->subfname);
1627 f->subfname = strdup(n2);
1628 return (True);
1630 f = f->next;
1632 return (False);
1635 /***************************************************************************
1636 Handle the include operation.
1637 ***************************************************************************/
1639 static BOOL handle_include(const char *pszParmValue, char **ptr)
1641 pstring fname;
1642 pstrcpy(fname, pszParmValue);
1644 standard_sub_basic(fname,sizeof(fname));
1646 add_to_file_list(pszParmValue, fname);
1648 string_set(ptr, fname);
1650 if (file_exist(fname))
1651 return (pm_process(fname, do_section, do_parameter, NULL));
1653 DEBUG(2, ("Can't find include file %s\n", fname));
1655 return (False);
1658 /***************************************************************************
1659 Handle the interpretation of the copy parameter.
1660 ***************************************************************************/
1662 static BOOL handle_copy(const char *pszParmValue, char **ptr)
1664 BOOL bRetval;
1665 int iTemp;
1666 service serviceTemp;
1668 string_set(ptr, pszParmValue);
1670 init_service(&serviceTemp);
1672 bRetval = False;
1674 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
1676 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
1677 if (iTemp == iServiceIndex) {
1678 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
1679 } else {
1680 copy_service(ServicePtrs[iServiceIndex],
1681 &serviceTemp,
1682 ServicePtrs[iServiceIndex]->copymap);
1683 bRetval = True;
1685 } else {
1686 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
1687 bRetval = False;
1690 free_service(&serviceTemp);
1691 return (bRetval);
1694 /***************************************************************************
1695 Initialise a copymap.
1696 ***************************************************************************/
1698 static void init_copymap(service * pservice)
1700 int i;
1701 SAFE_FREE(pservice->copymap);
1702 pservice->copymap = malloc_array_p(int, NUMPARAMETERS);
1703 if (!pservice->copymap)
1704 DEBUG(0,
1705 ("Couldn't allocate copymap!! (size %d)\n",
1706 (int)NUMPARAMETERS));
1707 else
1708 for (i = 0; i < NUMPARAMETERS; i++)
1709 pservice->copymap[i] = True;
1712 /***************************************************************************
1713 Return the local pointer to a parameter given the service number and the
1714 pointer into the default structure.
1715 ***************************************************************************/
1717 void *lp_local_ptr(int snum, void *ptr)
1719 return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
1723 /***************************************************************************
1724 Process a parametric option
1725 ***************************************************************************/
1726 static BOOL lp_do_parameter_parametric(int snum, const char *pszParmName, const char *pszParmValue, int flags)
1728 struct param_opt *paramo, *data;
1729 char *name;
1731 while (isspace((unsigned char)*pszParmName)) {
1732 pszParmName++;
1735 name = strdup(pszParmName);
1736 if (!name) return False;
1738 strlower(name);
1740 if (snum < 0) {
1741 data = Globals.param_opt;
1742 } else {
1743 data = ServicePtrs[snum]->param_opt;
1746 /* Traverse destination */
1747 for (paramo=data; paramo; paramo=paramo->next) {
1748 /* If we already have the option set, override it unless
1749 it was a command line option and the new one isn't */
1750 if (strcmp(paramo->key, name) == 0) {
1751 if ((paramo->flags & FLAG_CMDLINE) &&
1752 !(flags & FLAG_CMDLINE)) {
1753 return True;
1756 free(paramo->value);
1757 paramo->value = strdup(pszParmValue);
1758 paramo->flags = flags;
1759 free(name);
1760 return True;
1764 paramo = malloc_p(struct param_opt);
1765 if (!paramo)
1766 smb_panic("OOM");
1767 paramo->key = strdup(name);
1768 paramo->value = strdup(pszParmValue);
1769 paramo->flags = flags;
1770 if (snum < 0) {
1771 DLIST_ADD(Globals.param_opt, paramo);
1772 } else {
1773 DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
1776 free(name);
1778 return True;
1781 /***************************************************************************
1782 Process a parameter for a particular service number. If snum < 0
1783 then assume we are in the globals.
1784 ***************************************************************************/
1785 BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
1787 int parmnum, i;
1788 void *parm_ptr = NULL; /* where we are going to store the result */
1789 void *def_ptr = NULL;
1791 parmnum = map_parameter(pszParmName);
1793 if (parmnum < 0) {
1794 if (strchr(pszParmName, ':')) {
1795 return lp_do_parameter_parametric(snum, pszParmName, pszParmValue, 0);
1797 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1798 return (True);
1801 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1802 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1803 pszParmName));
1806 /* if the flag has been set on the command line, then don't allow override,
1807 but don't report an error */
1808 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1809 return True;
1812 def_ptr = parm_table[parmnum].ptr;
1814 /* we might point at a service, the default service or a global */
1815 if (snum < 0) {
1816 parm_ptr = def_ptr;
1817 } else {
1818 if (parm_table[parmnum].class == P_GLOBAL) {
1819 DEBUG(0,
1820 ("Global parameter %s found in service section!\n",
1821 pszParmName));
1822 return (True);
1824 parm_ptr =
1825 ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
1826 &sDefault);
1829 if (snum >= 0) {
1830 if (!ServicePtrs[snum]->copymap)
1831 init_copymap(ServicePtrs[snum]);
1833 /* this handles the aliases - set the copymap for other entries with
1834 the same data pointer */
1835 for (i = 0; parm_table[i].label; i++)
1836 if (parm_table[i].ptr == parm_table[parmnum].ptr)
1837 ServicePtrs[snum]->copymap[i] = False;
1840 /* if it is a special case then go ahead */
1841 if (parm_table[parmnum].special) {
1842 parm_table[parmnum].special(pszParmValue, (char **)parm_ptr);
1843 return (True);
1846 /* now switch on the type of variable it is */
1847 switch (parm_table[parmnum].type)
1849 case P_BOOL:
1850 if (!set_boolean(pszParmValue, parm_ptr)) {
1851 DEBUG(0,("lp_do_parameter(%s): value is not boolean!\n", pszParmValue));
1852 return False;
1854 break;
1856 case P_INTEGER:
1857 *(int *)parm_ptr = atoi(pszParmValue);
1858 break;
1860 case P_BYTES:
1862 uint64_t val;
1863 if (conv_str_size(pszParmValue, &val)) {
1864 if (val <= INT_MAX) {
1865 *(int *)parm_ptr = (int)val;
1866 break;
1870 DEBUG(0,("lp_do_parameter(%s): value is not "
1871 "a valid size specifier!\n", pszParmValue));
1872 return False;
1875 case P_LIST:
1876 *(const char ***)parm_ptr = str_list_make(talloc_autofree_context(),
1877 pszParmValue, NULL);
1878 break;
1880 case P_STRING:
1881 string_set(parm_ptr, pszParmValue);
1882 break;
1884 case P_USTRING:
1885 string_set(parm_ptr, pszParmValue);
1886 strupper(*(char **)parm_ptr);
1887 break;
1889 case P_ENUM:
1890 for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
1891 if (strequal
1892 (pszParmValue,
1893 parm_table[parmnum].enum_list[i].name)) {
1894 *(int *)parm_ptr =
1895 parm_table[parmnum].
1896 enum_list[i].value;
1897 break;
1900 if (!parm_table[parmnum].enum_list[i].name) {
1901 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n",
1902 pszParmValue, pszParmName));
1903 return False;
1905 break;
1906 case P_SEP:
1907 break;
1910 if (parm_table[parmnum].flags & FLAG_DEFAULT) {
1911 parm_table[parmnum].flags &= ~FLAG_DEFAULT;
1912 /* we have to also unset FLAG_DEFAULT on aliases */
1913 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1914 parm_table[i].flags &= ~FLAG_DEFAULT;
1916 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1917 parm_table[i].flags &= ~FLAG_DEFAULT;
1921 return (True);
1924 /***************************************************************************
1925 Process a parameter.
1926 ***************************************************************************/
1928 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue, void *userdata)
1930 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
1931 pszParmName, pszParmValue));
1935 variable argument do parameter
1937 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
1939 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...)
1941 char *s;
1942 BOOL ret;
1943 va_list ap;
1945 va_start(ap, fmt);
1946 s = talloc_vasprintf(NULL, fmt, ap);
1947 va_end(ap);
1948 ret = do_parameter(pszParmName, s, NULL);
1949 talloc_free(s);
1950 return ret;
1955 set a parameter from the commandline - this is called from command line parameter
1956 parsing code. It sets the parameter then marks the parameter as unable to be modified
1957 by smb.conf processing
1959 BOOL lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
1961 int parmnum = map_parameter(pszParmName);
1962 int i;
1964 while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
1967 if (parmnum < 0 && strchr(pszParmName, ':')) {
1968 /* set a parametric option */
1969 return lp_do_parameter_parametric(-1, pszParmName, pszParmValue, FLAG_CMDLINE);
1972 if (parmnum < 0) {
1973 DEBUG(0,("Unknown option '%s'\n", pszParmName));
1974 return False;
1977 /* reset the CMDLINE flag in case this has been called before */
1978 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
1980 if (!lp_do_parameter(-2, pszParmName, pszParmValue)) {
1981 return False;
1984 parm_table[parmnum].flags |= FLAG_CMDLINE;
1986 /* we have to also set FLAG_CMDLINE on aliases */
1987 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1988 parm_table[i].flags |= FLAG_CMDLINE;
1990 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1991 parm_table[i].flags |= FLAG_CMDLINE;
1994 return True;
1998 set a option from the commandline in 'a=b' format. Use to support --option
2000 BOOL lp_set_option(const char *option)
2002 char *p, *s;
2003 BOOL ret;
2005 s = strdup(option);
2006 if (!s) {
2007 return False;
2010 p = strchr(s, '=');
2011 if (!p) {
2012 free(s);
2013 return False;
2016 *p = 0;
2018 ret = lp_set_cmdline(s, p+1);
2019 free(s);
2020 return ret;
2024 #define BOOLSTR(b) ((b) ? "Yes" : "No")
2026 /***************************************************************************
2027 Print a parameter of the specified type.
2028 ***************************************************************************/
2030 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
2032 int i;
2033 switch (p->type)
2035 case P_ENUM:
2036 for (i = 0; p->enum_list[i].name; i++) {
2037 if (*(int *)ptr == p->enum_list[i].value) {
2038 fprintf(f, "%s",
2039 p->enum_list[i].name);
2040 break;
2043 break;
2045 case P_BOOL:
2046 fprintf(f, "%s", BOOLSTR((BOOL)*(int *)ptr));
2047 break;
2049 case P_INTEGER:
2050 case P_BYTES:
2051 fprintf(f, "%d", *(int *)ptr);
2052 break;
2054 case P_LIST:
2055 if ((char ***)ptr && *(char ***)ptr) {
2056 char **list = *(char ***)ptr;
2058 for (; *list; list++)
2059 fprintf(f, "%s%s", *list,
2060 ((*(list+1))?", ":""));
2062 break;
2064 case P_STRING:
2065 case P_USTRING:
2066 if (*(char **)ptr) {
2067 fprintf(f, "%s", *(char **)ptr);
2069 break;
2070 case P_SEP:
2071 break;
2075 /***************************************************************************
2076 Check if two parameters are equal.
2077 ***************************************************************************/
2079 static BOOL equal_parameter(parm_type type, void *ptr1, void *ptr2)
2081 switch (type) {
2082 case P_BOOL:
2083 return (*((int *)ptr1) == *((int *)ptr2));
2085 case P_INTEGER:
2086 case P_BYTES:
2087 case P_ENUM:
2088 return (*((int *)ptr1) == *((int *)ptr2));
2090 case P_LIST:
2091 return str_list_equal((const char **)(*(char ***)ptr1),
2092 (const char **)(*(char ***)ptr2));
2094 case P_STRING:
2095 case P_USTRING:
2097 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
2098 if (p1 && !*p1)
2099 p1 = NULL;
2100 if (p2 && !*p2)
2101 p2 = NULL;
2102 return (p1 == p2 || strequal(p1, p2));
2104 case P_SEP:
2105 break;
2107 return (False);
2110 /***************************************************************************
2111 Process a new section (service). At this stage all sections are services.
2112 Later we'll have special sections that permit server parameters to be set.
2113 Returns True on success, False on failure.
2114 ***************************************************************************/
2116 static BOOL do_section(const char *pszSectionName, void *userdata)
2118 BOOL bRetval;
2119 BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2120 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2121 bRetval = False;
2123 /* if we've just struck a global section, note the fact. */
2124 bInGlobalSection = isglobal;
2126 /* check for multiple global sections */
2127 if (bInGlobalSection) {
2128 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2129 return (True);
2132 /* if we have a current service, tidy it up before moving on */
2133 bRetval = True;
2135 if (iServiceIndex >= 0)
2136 bRetval = service_ok(iServiceIndex);
2138 /* if all is still well, move to the next record in the services array */
2139 if (bRetval) {
2140 /* We put this here to avoid an odd message order if messages are */
2141 /* issued by the post-processing of a previous section. */
2142 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2144 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
2145 < 0) {
2146 DEBUG(0, ("Failed to add a new service\n"));
2147 return (False);
2151 return (bRetval);
2155 /***************************************************************************
2156 Determine if a partcular base parameter is currentl set to the default value.
2157 ***************************************************************************/
2159 static BOOL is_default(int i)
2161 if (!defaults_saved)
2162 return False;
2163 switch (parm_table[i].type) {
2164 case P_LIST:
2165 return str_list_equal((const char **)parm_table[i].def.lvalue,
2166 (const char **)(*(char ***)parm_table[i].ptr));
2167 case P_STRING:
2168 case P_USTRING:
2169 return strequal(parm_table[i].def.svalue,
2170 *(char **)parm_table[i].ptr);
2171 case P_BOOL:
2172 return parm_table[i].def.bvalue ==
2173 *(int *)parm_table[i].ptr;
2174 case P_INTEGER:
2175 case P_BYTES:
2176 case P_ENUM:
2177 return parm_table[i].def.ivalue ==
2178 *(int *)parm_table[i].ptr;
2179 case P_SEP:
2180 break;
2182 return False;
2185 /***************************************************************************
2186 Display the contents of the global structure.
2187 ***************************************************************************/
2189 static void dump_globals(FILE *f, BOOL show_defaults)
2191 int i;
2192 struct param_opt *data;
2194 fprintf(f, "# Global parameters\n[global]\n");
2196 for (i = 0; parm_table[i].label; i++)
2197 if (parm_table[i].class == P_GLOBAL &&
2198 parm_table[i].ptr &&
2199 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2200 if (!show_defaults && (parm_table[i].flags & FLAG_DEFAULT))
2201 continue;
2202 fprintf(f, "\t%s = ", parm_table[i].label);
2203 print_parameter(&parm_table[i], parm_table[i].ptr, f);
2204 fprintf(f, "\n");
2206 if (Globals.param_opt != NULL) {
2207 data = Globals.param_opt;
2208 while(data) {
2209 fprintf(f, "\t%s = %s\n", data->key, data->value);
2210 data = data->next;
2216 /***************************************************************************
2217 Display the contents of a single services record.
2218 ***************************************************************************/
2220 static void dump_a_service(service * pService, FILE * f)
2222 int i;
2223 struct param_opt *data;
2225 if (pService != &sDefault)
2226 fprintf(f, "\n[%s]\n", pService->szService);
2228 for (i = 0; parm_table[i].label; i++)
2229 if (parm_table[i].class == P_LOCAL &&
2230 parm_table[i].ptr &&
2231 (*parm_table[i].label != '-') &&
2232 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2233 int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
2235 if (pService == &sDefault) {
2236 if (defaults_saved && is_default(i))
2237 continue;
2238 } else {
2239 if (equal_parameter(parm_table[i].type,
2240 ((char *)pService) +
2241 pdiff,
2242 ((char *)&sDefault) +
2243 pdiff))
2244 continue;
2247 fprintf(f, "\t%s = ", parm_table[i].label);
2248 print_parameter(&parm_table[i],
2249 ((char *)pService) + pdiff, f);
2250 fprintf(f, "\n");
2252 if (pService->param_opt != NULL) {
2253 data = pService->param_opt;
2254 while(data) {
2255 fprintf(f, "\t%s = %s\n", data->key, data->value);
2256 data = data->next;
2261 BOOL lp_dump_a_parameter(int snum, char *parm_name, FILE * f, BOOL isGlobal)
2263 service * pService = ServicePtrs[snum];
2264 struct parm_struct *parm;
2265 void *ptr;
2267 parm = lp_parm_struct(parm_name);
2268 if (!parm) {
2269 return False;
2272 if (isGlobal)
2273 ptr = parm->ptr;
2274 else
2275 ptr = ((char *)pService) +
2276 PTR_DIFF(parm->ptr, &sDefault);
2278 print_parameter(parm,
2279 ptr, f);
2280 fprintf(f, "\n");
2281 return True;
2284 /***************************************************************************
2285 Return info about the next service in a service. snum==-1 gives the globals.
2286 Return NULL when out of parameters.
2287 ***************************************************************************/
2289 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
2291 if (snum == -1) {
2292 /* do the globals */
2293 for (; parm_table[*i].label; (*i)++) {
2294 if (parm_table[*i].class == P_SEPARATOR)
2295 return &parm_table[(*i)++];
2297 if (!parm_table[*i].ptr
2298 || (*parm_table[*i].label == '-'))
2299 continue;
2301 if ((*i) > 0
2302 && (parm_table[*i].ptr ==
2303 parm_table[(*i) - 1].ptr))
2304 continue;
2306 return &parm_table[(*i)++];
2308 } else {
2309 service *pService = ServicePtrs[snum];
2311 for (; parm_table[*i].label; (*i)++) {
2312 if (parm_table[*i].class == P_SEPARATOR)
2313 return &parm_table[(*i)++];
2315 if (parm_table[*i].class == P_LOCAL &&
2316 parm_table[*i].ptr &&
2317 (*parm_table[*i].label != '-') &&
2318 ((*i) == 0 ||
2319 (parm_table[*i].ptr !=
2320 parm_table[(*i) - 1].ptr)))
2322 int pdiff =
2323 PTR_DIFF(parm_table[*i].ptr,
2324 &sDefault);
2326 if (allparameters ||
2327 !equal_parameter(parm_table[*i].type,
2328 ((char *)pService) +
2329 pdiff,
2330 ((char *)&sDefault) +
2331 pdiff))
2333 return &parm_table[(*i)++];
2339 return NULL;
2343 /***************************************************************************
2344 Return TRUE if the passed service number is within range.
2345 ***************************************************************************/
2347 BOOL lp_snum_ok(int iService)
2349 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
2352 /***************************************************************************
2353 Auto-load some home services.
2354 ***************************************************************************/
2356 static void lp_add_auto_services(const char *str)
2358 return;
2361 /***************************************************************************
2362 Announce ourselves as a print server.
2363 ***************************************************************************/
2365 void update_server_announce_as_printserver(void)
2367 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
2370 /***************************************************************************
2371 Have we loaded a services file yet?
2372 ***************************************************************************/
2374 BOOL lp_loaded(void)
2376 return (bLoaded);
2379 /***************************************************************************
2380 Unload unused services.
2381 ***************************************************************************/
2383 void lp_killunused(struct smbsrv_connection *smb, BOOL (*snumused) (struct smbsrv_connection *, int))
2385 int i;
2386 for (i = 0; i < iNumServices; i++) {
2387 if (!VALID(i))
2388 continue;
2390 if (!snumused || !snumused(smb, i)) {
2391 ServicePtrs[i]->valid = False;
2392 free_service(ServicePtrs[i]);
2397 /***************************************************************************
2398 Unload a service.
2399 ***************************************************************************/
2401 void lp_killservice(int iServiceIn)
2403 if (VALID(iServiceIn)) {
2404 ServicePtrs[iServiceIn]->valid = False;
2405 free_service(ServicePtrs[iServiceIn]);
2409 /***************************************************************************
2410 Load the services array from the services file. Return True on success,
2411 False on failure.
2412 ***************************************************************************/
2414 BOOL lp_load(void)
2416 pstring n2;
2417 BOOL bRetval;
2418 struct param_opt *data;
2420 bRetval = False;
2422 bInGlobalSection = True;
2424 if (Globals.param_opt != NULL) {
2425 struct param_opt *next;
2426 for (data=Globals.param_opt; data; data=next) {
2427 next = data->next;
2428 if (data->flags & FLAG_CMDLINE) continue;
2429 free(data->key);
2430 free(data->value);
2431 DLIST_REMOVE(Globals.param_opt, data);
2432 free(data);
2436 init_globals();
2438 pstrcpy(n2, lp_configfile());
2439 standard_sub_basic(n2,sizeof(n2));
2440 DEBUG(2, ("lp_load: refreshing parameters from %s\n", n2));
2442 add_to_file_list(lp_configfile(), n2);
2444 /* We get sections first, so have to start 'behind' to make up */
2445 iServiceIndex = -1;
2446 bRetval = pm_process(n2, do_section, do_parameter, NULL);
2448 /* finish up the last section */
2449 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
2450 if (bRetval)
2451 if (iServiceIndex >= 0)
2452 bRetval = service_ok(iServiceIndex);
2454 lp_add_auto_services(lp_auto_services());
2456 lp_add_hidden("IPC$", "IPC");
2457 lp_add_hidden("ADMIN$", "DISK");
2459 set_default_server_announce_type();
2461 bLoaded = True;
2463 if (!Globals.szWINSservers && Globals.bWINSsupport) {
2464 lp_do_parameter(-1, "wins server", "127.0.0.1");
2467 init_iconv();
2469 return (bRetval);
2472 /***************************************************************************
2473 Reset the max number of services.
2474 ***************************************************************************/
2476 void lp_resetnumservices(void)
2478 iNumServices = 0;
2481 /***************************************************************************
2482 Return the max number of services.
2483 ***************************************************************************/
2485 int lp_numservices(void)
2487 return (iNumServices);
2490 /***************************************************************************
2491 Display the contents of the services array in human-readable form.
2492 ***************************************************************************/
2494 void lp_dump(FILE *f, BOOL show_defaults, int maxtoprint)
2496 int iService;
2498 if (show_defaults)
2499 defaults_saved = False;
2501 dump_globals(f, show_defaults);
2503 dump_a_service(&sDefault, f);
2505 for (iService = 0; iService < maxtoprint; iService++)
2506 lp_dump_one(f, show_defaults, iService);
2509 /***************************************************************************
2510 Display the contents of one service in human-readable form.
2511 ***************************************************************************/
2513 void lp_dump_one(FILE * f, BOOL show_defaults, int snum)
2515 if (VALID(snum)) {
2516 if (ServicePtrs[snum]->szService[0] == '\0')
2517 return;
2518 dump_a_service(ServicePtrs[snum], f);
2522 /***************************************************************************
2523 Return the number of the service with the given name, or -1 if it doesn't
2524 exist. Note that this is a DIFFERENT ANIMAL from the internal function
2525 getservicebyname()! This works ONLY if all services have been loaded, and
2526 does not copy the found service.
2527 ***************************************************************************/
2529 int lp_servicenumber(const char *pszServiceName)
2531 int iService;
2532 fstring serviceName;
2535 for (iService = iNumServices - 1; iService >= 0; iService--) {
2536 if (VALID(iService) && ServicePtrs[iService]->szService) {
2538 * The substitution here is used to support %U is
2539 * service names
2541 fstrcpy(serviceName, ServicePtrs[iService]->szService);
2542 standard_sub_basic(serviceName,sizeof(serviceName));
2543 if (strequal(serviceName, pszServiceName))
2544 break;
2548 if (iService < 0)
2549 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
2551 return (iService);
2554 int lp_find_valid_service(const char *pszServiceName)
2556 int iService;
2558 iService = lp_servicenumber(pszServiceName);
2560 if (iService >= 0 && !lp_snum_ok(iService)) {
2561 DEBUG(0,("lp_find_valid_service: Invalid snum %d for '%s'\n",iService, pszServiceName));
2562 iService = -1;
2565 if (iService == -1) {
2566 DEBUG(3,("lp_find_valid_service: failed to find service '%s'\n", pszServiceName));
2569 return iService;
2572 /*******************************************************************
2573 A useful volume label function.
2574 ********************************************************************/
2575 const char *volume_label(int snum)
2577 const char *ret = lp_volume(snum);
2578 if (!*ret)
2579 return lp_servicename(snum);
2580 return (ret);
2584 /*******************************************************************
2585 Set the server type we will announce as via nmbd.
2586 ********************************************************************/
2588 static void set_default_server_announce_type(void)
2590 default_server_announce = 0;
2591 default_server_announce |= SV_TYPE_WORKSTATION;
2592 default_server_announce |= SV_TYPE_SERVER;
2593 default_server_announce |= SV_TYPE_SERVER_UNIX;
2595 switch (lp_announce_as()) {
2596 case ANNOUNCE_AS_NT_SERVER:
2597 default_server_announce |= SV_TYPE_SERVER_NT;
2598 /* fall through... */
2599 case ANNOUNCE_AS_NT_WORKSTATION:
2600 default_server_announce |= SV_TYPE_NT;
2601 break;
2602 case ANNOUNCE_AS_WIN95:
2603 default_server_announce |= SV_TYPE_WIN95_PLUS;
2604 break;
2605 case ANNOUNCE_AS_WFW:
2606 default_server_announce |= SV_TYPE_WFW;
2607 break;
2608 default:
2609 break;
2612 switch (lp_server_role()) {
2613 case ROLE_DOMAIN_MEMBER:
2614 default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
2615 break;
2616 case ROLE_DOMAIN_PDC:
2617 default_server_announce |= SV_TYPE_DOMAIN_CTRL;
2618 break;
2619 case ROLE_DOMAIN_BDC:
2620 default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
2621 break;
2622 case ROLE_STANDALONE:
2623 default:
2624 break;
2626 if (lp_time_server())
2627 default_server_announce |= SV_TYPE_TIME_SOURCE;
2629 if (lp_host_msdfs())
2630 default_server_announce |= SV_TYPE_DFS_SERVER;
2632 /* TODO: only announce us as print server when we are a print server */
2633 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
2636 /***********************************************************
2637 If we are PDC then prefer us as DMB
2638 ************************************************************/
2640 BOOL lp_domain_master(void)
2642 return (lp_server_role() == ROLE_DOMAIN_PDC);
2645 /***********************************************************
2646 If we are PDC then prefer us as DMB
2647 ************************************************************/
2649 BOOL lp_domain_logons(void)
2651 return (lp_server_role() == ROLE_DOMAIN_PDC) || (lp_server_role() == ROLE_DOMAIN_BDC);
2654 /***********************************************************
2655 If we are DMB then prefer us as LMB
2656 ************************************************************/
2658 BOOL lp_preferred_master(void)
2660 return (lp_local_master() && lp_domain_master());
2663 /*******************************************************************
2664 Remove a service.
2665 ********************************************************************/
2667 void lp_remove_service(int snum)
2669 ServicePtrs[snum]->valid = False;
2672 /*******************************************************************
2673 Copy a service.
2674 ********************************************************************/
2676 void lp_copy_service(int snum, const char *new_name)
2678 const char *oldname = lp_servicename(snum);
2679 do_section(new_name, NULL);
2680 if (snum >= 0) {
2681 snum = lp_servicenumber(new_name);
2682 if (snum >= 0)
2683 lp_do_parameter(snum, "copy", oldname);
2688 /*******************************************************************
2689 Get the default server type we will announce as via nmbd.
2690 ********************************************************************/
2691 int lp_default_server_announce(void)
2693 return default_server_announce;
2696 const char *lp_printername(int snum)
2698 const char *ret = _lp_printername(snum);
2699 if (ret == NULL || (ret != NULL && *ret == '\0'))
2700 ret = lp_const_servicename(snum);
2702 return ret;
2706 /*******************************************************************
2707 Return the max print jobs per queue.
2708 ********************************************************************/
2710 int lp_maxprintjobs(int snum)
2712 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
2713 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
2714 maxjobs = PRINT_MAX_JOBID - 1;
2716 return maxjobs;