r20949: Looking over some lcov output, try and walk some error paths.
[Samba.git] / source / param / loadparm.c
blob98724a107dd84bd1971f0dc36ae07ed0e9fefc0c
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 "version.h"
57 #include "dynconfig.h"
58 #include "pstring.h"
59 #include "system/time.h"
60 #include "system/locale.h"
61 #include "system/network.h" /* needed for TCP_NODELAY */
62 #include "smb_server/smb_server.h"
63 #include "libcli/raw/signing.h"
64 #include "lib/util/dlinklist.h"
65 #include "param/loadparm.h"
67 static BOOL bLoaded = False;
69 #define standard_sub_basic(str,len)
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 *szShareBackend;
109 char *szSAM_URL;
110 char *szSECRETS_URL;
111 char *szSPOOLSS_URL;
112 char *szWINS_CONFIG_URL;
113 char *szWINS_URL;
114 char *szPrivateDir;
115 char **jsInclude;
116 char *jsonrpcServicesDir;
117 char **szPasswordServers;
118 char *szSocketOptions;
119 char *szRealm;
120 char **szWINSservers;
121 char **szInterfaces;
122 char *szSocketAddress;
123 char *szAnnounceVersion; /* This is initialised in init_globals */
124 char *szWorkgroup;
125 char *szNetbiosName;
126 char **szNetbiosAliases;
127 char *szNetbiosScope;
128 char *szDomainOtherSIDs;
129 char **szNameResolveOrder;
130 char **dcerpc_ep_servers;
131 char **server_services;
132 char *ntptr_providor;
133 char *szWinbindSeparator;
134 char *szWinbinddSocketDirectory;
135 int bWinbindSealedPipes;
136 char *webapps_directory;
137 int tls_enabled;
138 char *tls_keyfile;
139 char *tls_certfile;
140 char *tls_cafile;
141 char *tls_crlfile;
142 char *tls_dhpfile;
143 int max_mux;
144 int max_xmit;
145 int pwordlevel;
146 int srv_maxprotocol;
147 int srv_minprotocol;
148 int cli_maxprotocol;
149 int cli_minprotocol;
150 int security;
151 char **AuthMethods;
152 int paranoid_server_security;
153 int max_wins_ttl;
154 int min_wins_ttl;
155 int announce_as; /* This is initialised in init_globals */
156 int nbt_port;
157 int dgram_port;
158 int cldap_port;
159 int krb5_port;
160 int kpasswd_port;
161 int web_port;
162 char *socket_options;
163 int bWINSsupport;
164 int bWINSdnsProxy;
165 char *szWINSHook;
166 int bLocalMaster;
167 int bPreferredMaster;
168 int bEncryptPasswords;
169 int bNullPasswords;
170 int bObeyPamRestrictions;
171 int bLargeReadwrite;
172 int bReadRaw;
173 int bWriteRaw;
174 int bTimeServer;
175 int bBindInterfacesOnly;
176 int bNTSmbSupport;
177 int bNTStatusSupport;
178 int bLanmanAuth;
179 int bNTLMAuth;
180 int bUseSpnego;
181 int server_signing;
182 int client_signing;
183 int bClientPlaintextAuth;
184 int bClientLanManAuth;
185 int bClientNTLMv2Auth;
186 int client_use_spnego_principal;
187 int bHostMSDfs;
188 int bUnicode;
189 int bUnixExtensions;
190 int bDisableNetbios;
191 int bRpcBigEndian;
192 struct param_opt *param_opt;
194 global;
196 static global Globals;
199 * This structure describes a single service.
201 typedef struct
203 int valid;
204 char *szService;
205 char *szPath;
206 char *szCopy;
207 char *szInclude;
208 char *szPrintername;
209 char **szHostsallow;
210 char **szHostsdeny;
211 char *comment;
212 char *volume;
213 char *fstype;
214 char **ntvfs_handler;
215 int iMaxPrintJobs;
216 int iMaxConnections;
217 int iCSCPolicy;
218 int bAvailable;
219 int bBrowseable;
220 int bRead_only;
221 int bPrint_ok;
222 int bMap_system;
223 int bMap_hidden;
224 int bMap_archive;
225 int bStrictLocking;
226 int *copymap;
227 int bMSDfsRoot;
228 int bStrictSync;
229 int bCIFileSystem;
230 struct param_opt *param_opt;
232 char dummy[3]; /* for alignment */
234 service;
237 /* This is a default service used to prime a services structure */
238 static service sDefault = {
239 True, /* valid */
240 NULL, /* szService */
241 NULL, /* szPath */
242 NULL, /* szCopy */
243 NULL, /* szInclude */
244 NULL, /* szPrintername */
245 NULL, /* szHostsallow */
246 NULL, /* szHostsdeny */
247 NULL, /* comment */
248 NULL, /* volume */
249 NULL, /* fstype */
250 NULL, /* ntvfs_handler */
251 1000, /* iMaxPrintJobs */
252 0, /* iMaxConnections */
253 0, /* iCSCPolicy */
254 True, /* bAvailable */
255 True, /* bBrowseable */
256 True, /* bRead_only */
257 False, /* bPrint_ok */
258 False, /* bMap_system */
259 False, /* bMap_hidden */
260 True, /* bMap_archive */
261 True, /* bStrictLocking */
262 NULL, /* copymap */
263 False, /* bMSDfsRoot */
264 False, /* bStrictSync */
265 False, /* bCIFileSystem */
266 NULL, /* Parametric options */
268 "" /* dummy */
271 /* local variables */
272 static service **ServicePtrs = NULL;
273 static int iNumServices = 0;
274 static int iServiceIndex = 0;
275 static BOOL bInGlobalSection = True;
277 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
279 /* prototypes for the special type handlers */
280 static BOOL handle_include(const char *pszParmValue, char **ptr);
281 static BOOL handle_copy(const char *pszParmValue, char **ptr);
283 static const struct enum_list enum_protocol[] = {
284 {PROTOCOL_SMB2, "SMB2"},
285 {PROTOCOL_NT1, "NT1"},
286 {PROTOCOL_LANMAN2, "LANMAN2"},
287 {PROTOCOL_LANMAN1, "LANMAN1"},
288 {PROTOCOL_CORE, "CORE"},
289 {PROTOCOL_COREPLUS, "COREPLUS"},
290 {PROTOCOL_COREPLUS, "CORE+"},
291 {-1, NULL}
294 static const struct enum_list enum_security[] = {
295 {SEC_SHARE, "SHARE"},
296 {SEC_USER, "USER"},
297 {-1, NULL}
300 static const struct enum_list enum_announce_as[] = {
301 {ANNOUNCE_AS_NT_SERVER, "NT"},
302 {ANNOUNCE_AS_NT_SERVER, "NT Server"},
303 {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"},
304 {ANNOUNCE_AS_WIN95, "win95"},
305 {ANNOUNCE_AS_WFW, "WfW"},
306 {-1, NULL}
309 static const struct enum_list enum_bool_auto[] = {
310 {False, "No"},
311 {False, "False"},
312 {False, "0"},
313 {True, "Yes"},
314 {True, "True"},
315 {True, "1"},
316 {Auto, "Auto"},
317 {-1, NULL}
320 /* Client-side offline caching policy types */
321 #define CSC_POLICY_MANUAL 0
322 #define CSC_POLICY_DOCUMENTS 1
323 #define CSC_POLICY_PROGRAMS 2
324 #define CSC_POLICY_DISABLE 3
326 static const struct enum_list enum_csc_policy[] = {
327 {CSC_POLICY_MANUAL, "manual"},
328 {CSC_POLICY_DOCUMENTS, "documents"},
329 {CSC_POLICY_PROGRAMS, "programs"},
330 {CSC_POLICY_DISABLE, "disable"},
331 {-1, NULL}
334 /* SMB signing types. */
335 static const struct enum_list enum_smb_signing_vals[] = {
336 {SMB_SIGNING_OFF, "No"},
337 {SMB_SIGNING_OFF, "False"},
338 {SMB_SIGNING_OFF, "0"},
339 {SMB_SIGNING_OFF, "Off"},
340 {SMB_SIGNING_OFF, "disabled"},
341 {SMB_SIGNING_SUPPORTED, "Yes"},
342 {SMB_SIGNING_SUPPORTED, "True"},
343 {SMB_SIGNING_SUPPORTED, "1"},
344 {SMB_SIGNING_SUPPORTED, "On"},
345 {SMB_SIGNING_SUPPORTED, "enabled"},
346 {SMB_SIGNING_REQUIRED, "required"},
347 {SMB_SIGNING_REQUIRED, "mandatory"},
348 {SMB_SIGNING_REQUIRED, "force"},
349 {SMB_SIGNING_REQUIRED, "forced"},
350 {SMB_SIGNING_REQUIRED, "enforced"},
351 {SMB_SIGNING_AUTO, "auto"},
352 {-1, NULL}
355 static const struct enum_list enum_server_role[] = {
356 {ROLE_STANDALONE, "standalone"},
357 {ROLE_DOMAIN_MEMBER, "member server"},
358 {ROLE_DOMAIN_CONTROLLER, "domain controller"},
359 {-1, NULL}
363 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
365 * Note: We have a flag called FLAG_DEVELOPER but is not used at this time, it
366 * is implied in current control logic. This may change at some later time. A
367 * flag value of 0 means - show as development option only.
369 * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
370 * screen in SWAT. This is used to exclude parameters as well as to squash all
371 * parameters that have been duplicated by pseudonyms.
373 static struct parm_struct parm_table[] = {
374 {"Base Options", P_SEP, P_SEPARATOR},
376 {"server role", P_ENUM, P_GLOBAL, &Globals.server_role, NULL, enum_server_role, FLAG_BASIC},
378 {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
379 {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
380 {"ncalrpc dir", P_STRING, P_GLOBAL, &Globals.ncalrpc_dir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
381 {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
382 {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
383 {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
384 {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE},
385 {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkgroup, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
386 {"realm", P_STRING, P_GLOBAL, &Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
387 {"netbios name", P_USTRING, P_GLOBAL, &Globals.szNetbiosName, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
388 {"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
389 {"netbios scope", P_USTRING, P_GLOBAL, &Globals.szNetbiosScope, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
390 {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
391 {"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
392 {"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
393 {"ntvfs handler", P_LIST, P_LOCAL, &sDefault.ntvfs_handler, NULL, NULL, FLAG_ADVANCED},
394 {"ntptr providor", P_STRING, P_GLOBAL, &Globals.ntptr_providor, NULL, NULL, FLAG_ADVANCED},
395 {"dcerpc endpoint servers", P_LIST, P_GLOBAL, &Globals.dcerpc_ep_servers, NULL, NULL, FLAG_ADVANCED},
396 {"server services", P_LIST, P_GLOBAL, &Globals.server_services, NULL, NULL, FLAG_ADVANCED},
398 {"Security Options", P_SEP, P_SEPARATOR},
400 {"security", P_ENUM, P_GLOBAL, &Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
401 {"auth methods", P_LIST, P_GLOBAL, &Globals.AuthMethods, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
402 {"encrypt passwords", P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
403 {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
404 {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
405 {"password server", P_LIST, P_GLOBAL, &Globals.szPasswordServers, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
406 {"sam database", P_STRING, P_GLOBAL, &Globals.szSAM_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
407 {"secrets database", P_STRING, P_GLOBAL, &Globals.szSECRETS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
408 {"spoolss database", P_STRING, P_GLOBAL, &Globals.szSPOOLSS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
409 {"wins config database", P_STRING, P_GLOBAL, &Globals.szWINS_CONFIG_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
410 {"wins database", P_STRING, P_GLOBAL, &Globals.szWINS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
411 {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
412 {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
413 {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
414 {"lanman auth", P_BOOL, P_GLOBAL, &Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
415 {"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
416 {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
417 {"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
418 {"client plaintext auth", P_BOOL, P_GLOBAL, &Globals.bClientPlaintextAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
419 {"client use spnego principal", P_BOOL, P_GLOBAL, &Globals.client_use_spnego_principal, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
421 {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE},
423 {"hosts allow", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
424 {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
426 {"Logging Options", P_SEP, P_SEPARATOR},
428 {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
429 {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_HIDE},
430 {"log file", P_STRING, P_GLOBAL, &logfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
432 {"Protocol Options", P_SEP, P_SEPARATOR},
434 {"smb ports", P_LIST, P_GLOBAL, &Globals.smb_ports, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
435 {"nbt port", P_INTEGER, P_GLOBAL, &Globals.nbt_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
436 {"dgram port", P_INTEGER, P_GLOBAL, &Globals.dgram_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
437 {"cldap port", P_INTEGER, P_GLOBAL, &Globals.cldap_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
438 {"krb5 port", P_INTEGER, P_GLOBAL, &Globals.krb5_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
439 {"kpasswd port", P_INTEGER, P_GLOBAL, &Globals.kpasswd_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
440 {"web port", P_INTEGER, P_GLOBAL, &Globals.web_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
441 {"tls enabled", P_BOOL, P_GLOBAL, &Globals.tls_enabled, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
442 {"tls keyfile", P_STRING, P_GLOBAL, &Globals.tls_keyfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
443 {"tls certfile", P_STRING, P_GLOBAL, &Globals.tls_certfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
444 {"tls cafile", P_STRING, P_GLOBAL, &Globals.tls_cafile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
445 {"tls crlfile", P_STRING, P_GLOBAL, &Globals.tls_crlfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
446 {"tls dh params file", P_STRING, P_GLOBAL, &Globals.tls_dhpfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
447 {"web application directory", P_STRING, P_GLOBAL, &Globals.webapps_directory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
448 {"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, FLAG_DEVELOPER},
449 {"server max protocol", P_ENUM, P_GLOBAL, &Globals.srv_maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
450 {"server min protocol", P_ENUM, P_GLOBAL, &Globals.srv_minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
451 {"client max protocol", P_ENUM, P_GLOBAL, &Globals.cli_maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
452 {"client min protocol", P_ENUM, P_GLOBAL, &Globals.cli_minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
453 {"unicode", P_BOOL, P_GLOBAL, &Globals.bUnicode, NULL, NULL, FLAG_DEVELOPER},
454 {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL, NULL, FLAG_DEVELOPER},
455 {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL, NULL, FLAG_DEVELOPER},
456 {"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
458 {"nt status support", P_BOOL, P_GLOBAL, &Globals.bNTStatusSupport, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
460 {"announce version", P_STRING, P_GLOBAL, &Globals.szAnnounceVersion, NULL, NULL, FLAG_DEVELOPER},
461 {"announce as", P_ENUM, P_GLOBAL, &Globals.announce_as, NULL, enum_announce_as, FLAG_DEVELOPER},
462 {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
463 {"max xmit", P_BYTES, P_GLOBAL, &Globals.max_xmit, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
465 {"name resolve order", P_LIST, P_GLOBAL, &Globals.szNameResolveOrder, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
466 {"max wins ttl", P_INTEGER, P_GLOBAL, &Globals.max_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
467 {"min wins ttl", P_INTEGER, P_GLOBAL, &Globals.min_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
468 {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
469 {"unix extensions", P_BOOL, P_GLOBAL, &Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
470 {"use spnego", P_BOOL, P_GLOBAL, &Globals.bUseSpnego, NULL, NULL, FLAG_DEVELOPER},
471 {"server signing", P_ENUM, P_GLOBAL, &Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
472 {"client signing", P_ENUM, P_GLOBAL, &Globals.client_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
473 {"rpc big endian", P_BOOL, P_GLOBAL, &Globals.bRpcBigEndian, NULL, NULL, FLAG_DEVELOPER},
475 {"Tuning Options", P_SEP, P_SEPARATOR},
477 {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL, NULL, FLAG_SHARE},
478 {"paranoid server security", P_BOOL, P_GLOBAL, &Globals.paranoid_server_security, NULL, NULL, FLAG_DEVELOPER},
479 {"socket options", P_STRING, P_GLOBAL, &Globals.socket_options, NULL, NULL, FLAG_DEVELOPER},
481 {"strict sync", P_BOOL, P_LOCAL, &sDefault.bStrictSync, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
482 {"case insensitive filesystem", P_BOOL, P_LOCAL, &sDefault.bCIFileSystem, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
484 {"Printing Options", P_SEP, P_SEPARATOR},
486 {"max print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxPrintJobs, NULL, NULL, FLAG_PRINT},
487 {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_PRINT},
488 {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_HIDE},
490 {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_PRINT},
491 {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_HIDE},
493 {"Filename Handling", P_SEP, P_SEPARATOR},
495 {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
496 {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
497 {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
499 {"Domain Options", P_SEP, P_SEPARATOR},
501 {"Logon Options", P_SEP, P_SEPARATOR},
504 {"Browse Options", P_SEP, P_SEPARATOR},
506 {"preferred master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
507 {"prefered master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_HIDE},
508 {"local master", P_BOOL, P_GLOBAL, &Globals.bLocalMaster, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
509 {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
510 {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_HIDE},
512 {"WINS Options", P_SEP, P_SEPARATOR},
514 {"wins server", P_LIST, P_GLOBAL, &Globals.szWINSservers, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
515 {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
516 {"dns proxy", P_BOOL, P_GLOBAL, &Globals.bWINSdnsProxy, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
517 {"wins hook", P_STRING, P_GLOBAL, &Globals.szWINSHook, NULL, NULL, FLAG_ADVANCED},
519 {"Locking Options", P_SEP, P_SEPARATOR},
521 {"csc policy", P_ENUM, P_LOCAL, &sDefault.iCSCPolicy, NULL, enum_csc_policy, FLAG_SHARE | FLAG_GLOBAL},
523 {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
525 {"Miscellaneous Options", P_SEP, P_SEPARATOR},
527 {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE},
528 {"share backend", P_STRING, P_GLOBAL, &Globals.szShareBackend, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
529 {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
530 {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
531 {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_HIDE},
532 {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
533 {"modules dir", P_STRING, P_GLOBAL, &Globals.szModulesDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
534 {"pid directory", P_STRING, P_GLOBAL, &Globals.szPidDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
535 {"js include", P_LIST, P_GLOBAL, &Globals.jsInclude, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
536 {"jsonrpc services directory", P_STRING, P_GLOBAL, &Globals.jsonrpcServicesDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
537 {"setup directory", P_STRING, P_GLOBAL, &Globals.szSetupDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
539 {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL, NULL, FLAG_DEVELOPER},
540 {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL, NULL, FLAG_HIDE},
542 {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy, NULL, FLAG_HIDE},
543 {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include, NULL, FLAG_HIDE},
545 {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
546 {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_SHARE },
547 {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_SHARE},
549 {"panic action", P_STRING, P_GLOBAL, &panic_action, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
551 {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_SHARE},
552 {"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
553 {"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
554 {"winbindd socket directory", P_STRING, P_GLOBAL, &Globals.szWinbinddSocketDirectory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
555 {"winbind sealed pipes", P_BOOL, P_GLOBAL, &Globals.bWinbindSealedPipes, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
557 {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
562 return the parameter table
564 struct parm_struct *lp_parm_table(void)
566 return parm_table;
569 /***************************************************************************
570 Initialise the global parameter structure.
571 ***************************************************************************/
572 static void init_globals(void)
574 int i;
575 char *myname;
577 DEBUG(3, ("Initialising global parameters\n"));
579 for (i = 0; parm_table[i].label; i++) {
580 if ((parm_table[i].type == P_STRING ||
581 parm_table[i].type == P_USTRING) &&
582 parm_table[i].ptr &&
583 !(parm_table[i].flags & FLAG_CMDLINE)) {
584 string_set(parm_table[i].ptr, "");
588 do_parameter("config file", dyn_CONFIGFILE, NULL);
590 do_parameter("share backend", "classic", 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 unixinfo", 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("secrets database", "secrets.ldb", NULL);
616 do_parameter("spoolss database", "spoolss.ldb", NULL);
617 do_parameter("wins config database", "wins_config.ldb", NULL);
618 do_parameter("wins database", "wins.ldb", NULL);
619 do_parameter("registry:HKEY_LOCAL_MACHINE", "hklm.ldb", NULL);
621 /* This hive should be dynamically generated by Samba using
622 data from the sam, but for the moment leave it in a tdb to
623 keep regedt32 from popping up an annoying dialog. */
624 do_parameter("registry:HKEY_USERS", "hku.ldb", NULL);
626 /* using UTF8 by default allows us to support all chars */
627 do_parameter("unix charset", "UTF8", NULL);
629 /* Use codepage 850 as a default for the dos character set */
630 do_parameter("dos charset", "CP850", NULL);
633 * Allow the default PASSWD_CHAT to be overridden in local.h.
635 do_parameter("passwd chat", DEFAULT_PASSWD_CHAT, NULL);
637 do_parameter("pid directory", dyn_PIDDIR, NULL);
638 do_parameter("lock dir", dyn_LOCKDIR, NULL);
639 do_parameter("modules dir", dyn_MODULESDIR, NULL);
640 do_parameter("ncalrpc dir", dyn_NCALRPCDIR, NULL);
642 do_parameter("socket address", "0.0.0.0", NULL);
643 do_parameter_var("server string", "Samba %s", SAMBA_VERSION_STRING);
645 do_parameter_var("announce version", "%d.%d",
646 DEFAULT_MAJOR_VERSION,
647 DEFAULT_MINOR_VERSION);
649 do_parameter("password server", "*", NULL);
651 do_parameter("max mux", "50", NULL);
652 do_parameter("max xmit", "12288", NULL);
653 do_parameter("password level", "0", NULL);
654 do_parameter("LargeReadwrite", "True", NULL);
655 do_parameter("server min protocol", "CORE", NULL);
656 do_parameter("server max protocol", "NT1", NULL);
657 do_parameter("client min protocol", "CORE", NULL);
658 do_parameter("client max protocol", "NT1", NULL);
659 do_parameter("security", "USER", NULL);
660 do_parameter("paranoid server security", "True", NULL);
661 do_parameter("EncryptPasswords", "True", NULL);
662 do_parameter("ReadRaw", "True", NULL);
663 do_parameter("WriteRaw", "True", NULL);
664 do_parameter("NullPasswords", "False", NULL);
665 do_parameter("ObeyPamRestrictions", "False", NULL);
666 do_parameter("announce as", "NT SERVER", NULL);
668 do_parameter("TimeServer", "False", NULL);
669 do_parameter("BindInterfacesOnly", "False", NULL);
670 do_parameter("Unicode", "True", NULL);
671 do_parameter("ClientLanManAuth", "True", NULL);
672 do_parameter("LanmanAuth", "True", NULL);
673 do_parameter("NTLMAuth", "True", NULL);
674 do_parameter("client use spnego principal", "False", NULL);
676 do_parameter("UnixExtensions", "False", NULL);
678 do_parameter("PreferredMaster", "Auto", NULL);
679 do_parameter("LocalMaster", "True", NULL);
681 do_parameter("wins support", "False", NULL);
682 do_parameter("dns proxy", "True", NULL);
684 do_parameter("winbind separator", "\\", NULL);
685 do_parameter("winbind sealed pipes", "True", NULL);
686 do_parameter("winbindd socket directory", dyn_WINBINDD_SOCKET_DIR, NULL);
688 do_parameter("client signing", "Yes", NULL);
689 do_parameter("server signing", "auto", NULL);
691 do_parameter("use spnego", "True", NULL);
693 do_parameter("smb ports", "445 139", NULL);
694 do_parameter("nbt port", "137", NULL);
695 do_parameter("dgram port", "138", NULL);
696 do_parameter("cldap port", "389", NULL);
697 do_parameter("krb5 port", "88", NULL);
698 do_parameter("kpasswd port", "464", NULL);
699 do_parameter("web port", "901", NULL);
700 do_parameter("web application directory", dyn_WEBAPPSDIR, NULL);
701 do_parameter("jsonrpc services directory", dyn_SERVICESDIR, NULL);
703 do_parameter("nt status support", "True", NULL);
705 do_parameter("max wins ttl", "518400", NULL); /* 6 days */
706 do_parameter("min wins ttl", "10", NULL);
708 do_parameter("tls enabled", "True", NULL);
709 do_parameter("tls keyfile", "tls/key.pem", NULL);
710 do_parameter("tls certfile", "tls/cert.pem", NULL);
711 do_parameter("tls cafile", "tls/ca.pem", NULL);
712 do_parameter_var("js include", "%s", dyn_JSDIR);
713 do_parameter_var("setup directory", "%s", dyn_SETUPDIR);
715 for (i = 0; parm_table[i].label; i++) {
716 if (!(parm_table[i].flags & FLAG_CMDLINE)) {
717 parm_table[i].flags |= FLAG_DEFAULT;
722 static TALLOC_CTX *lp_talloc;
724 /******************************************************************* a
725 Free up temporary memory - called from the main loop.
726 ********************************************************************/
728 void lp_talloc_free(void)
730 if (!lp_talloc)
731 return;
732 talloc_free(lp_talloc);
733 lp_talloc = NULL;
736 /*******************************************************************
737 Convenience routine to grab string parameters into temporary memory
738 and run standard_sub_basic on them. The buffers can be written to by
739 callers without affecting the source string.
740 ********************************************************************/
742 static const char *lp_string(const char *s)
744 #if 0 /* until REWRITE done to make thread-safe */
745 size_t len = s ? strlen(s) : 0;
746 char *ret;
747 #endif
749 /* The follow debug is useful for tracking down memory problems
750 especially if you have an inner loop that is calling a lp_*()
751 function that returns a string. Perhaps this debug should be
752 present all the time? */
754 #if 0
755 DEBUG(10, ("lp_string(%s)\n", s));
756 #endif
758 #if 0 /* until REWRITE done to make thread-safe */
759 if (!lp_talloc)
760 lp_talloc = talloc_init("lp_talloc");
762 ret = talloc_array(lp_talloc, char, len + 100); /* leave room for substitution */
764 if (!ret)
765 return NULL;
767 if (!s)
768 *ret = 0;
769 else
770 strlcpy(ret, s, len);
772 if (trim_string(ret, "\"", "\"")) {
773 if (strchr(ret,'"') != NULL)
774 strlcpy(ret, s, len);
777 standard_sub_basic(ret,len+100);
778 return (ret);
779 #endif
780 return s;
784 In this section all the functions that are used to access the
785 parameters from the rest of the program are defined
788 #define FN_GLOBAL_STRING(fn_name,ptr) \
789 const char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
790 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
791 const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");}
792 #define FN_GLOBAL_LIST(fn_name,ptr) \
793 const char **fn_name(void) {return(*(const char ***)(ptr));}
794 #define FN_GLOBAL_BOOL(fn_name,ptr) \
795 BOOL fn_name(void) {return((BOOL)*(int *)(ptr));}
796 #if 0 /* unused */
797 #define FN_GLOBAL_CHAR(fn_name,ptr) \
798 char fn_name(void) {return(*(char *)(ptr));}
799 #endif
800 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
801 int fn_name(void) {return(*(int *)(ptr));}
803 #define FN_LOCAL_STRING(fn_name,val) \
804 const char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
805 #define FN_LOCAL_CONST_STRING(fn_name,val) \
806 const char *fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
807 #define FN_LOCAL_LIST(fn_name,val) \
808 const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
809 #define FN_LOCAL_BOOL(fn_name,val) \
810 BOOL fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
811 #if 0 /* unused */
812 #define FN_LOCAL_CHAR(fn_name,val) \
813 char fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
814 #endif
815 #define FN_LOCAL_INTEGER(fn_name,val) \
816 int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
818 _PUBLIC_ FN_GLOBAL_INTEGER(lp_server_role, &Globals.server_role)
819 _PUBLIC_ FN_GLOBAL_LIST(lp_smb_ports, &Globals.smb_ports)
820 _PUBLIC_ FN_GLOBAL_INTEGER(lp_nbt_port, &Globals.nbt_port)
821 _PUBLIC_ FN_GLOBAL_INTEGER(lp_dgram_port, &Globals.dgram_port)
822 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cldap_port, &Globals.cldap_port)
823 _PUBLIC_ FN_GLOBAL_INTEGER(lp_krb5_port, &Globals.krb5_port)
824 _PUBLIC_ FN_GLOBAL_INTEGER(lp_kpasswd_port, &Globals.kpasswd_port)
825 _PUBLIC_ FN_GLOBAL_INTEGER(lp_web_port, &Globals.web_port)
826 _PUBLIC_ FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
827 _PUBLIC_ FN_GLOBAL_STRING(lp_webapps_directory, &Globals.webapps_directory)
828 _PUBLIC_ FN_GLOBAL_BOOL(lp_tls_enabled, &Globals.tls_enabled)
829 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_keyfile, &Globals.tls_keyfile)
830 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_certfile, &Globals.tls_certfile)
831 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_cafile, &Globals.tls_cafile)
832 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_crlfile, &Globals.tls_crlfile)
833 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_dhpfile, &Globals.tls_dhpfile)
834 _PUBLIC_ FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
835 _PUBLIC_ FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset)
836 _PUBLIC_ FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
837 _PUBLIC_ FN_GLOBAL_STRING(lp_share_backend, &Globals.szShareBackend)
838 _PUBLIC_ FN_GLOBAL_STRING(lp_sam_url, &Globals.szSAM_URL)
839 _PUBLIC_ FN_GLOBAL_STRING(lp_secrets_url, &Globals.szSECRETS_URL)
840 _PUBLIC_ FN_GLOBAL_STRING(lp_spoolss_url, &Globals.szSPOOLSS_URL)
841 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_config_url, &Globals.szWINS_CONFIG_URL)
842 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_url, &Globals.szWINS_URL)
843 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
844 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_winbindd_socket_directory, &Globals.szWinbinddSocketDirectory)
845 _PUBLIC_ FN_GLOBAL_BOOL(lp_winbind_sealed_pipes, &Globals.bWinbindSealedPipes)
846 _PUBLIC_ FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
847 _PUBLIC_ FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
848 _PUBLIC_ FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
849 _PUBLIC_ FN_GLOBAL_STRING(lp_modulesdir, &Globals.szModulesDir)
850 _PUBLIC_ FN_GLOBAL_STRING(lp_setupdir, &Globals.szSetupDir)
851 _PUBLIC_ FN_GLOBAL_STRING(lp_ncalrpc_dir, &Globals.ncalrpc_dir)
852 _PUBLIC_ FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
853 _PUBLIC_ FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, &Globals.dcerpc_ep_servers)
854 _PUBLIC_ FN_GLOBAL_LIST(lp_server_services, &Globals.server_services)
855 _PUBLIC_ FN_GLOBAL_STRING(lp_ntptr_providor, &Globals.ntptr_providor)
856 _PUBLIC_ FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
857 _PUBLIC_ FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
858 _PUBLIC_ FN_GLOBAL_LIST(lp_passwordserver, &Globals.szPasswordServers)
859 _PUBLIC_ FN_GLOBAL_LIST(lp_name_resolve_order, &Globals.szNameResolveOrder)
860 _PUBLIC_ FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
861 _PUBLIC_ FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
862 _PUBLIC_ FN_GLOBAL_STRING(lp_workgroup, &Globals.szWorkgroup)
863 _PUBLIC_ FN_GLOBAL_STRING(lp_netbios_name, &Globals.szNetbiosName)
864 _PUBLIC_ FN_GLOBAL_STRING(lp_netbios_scope, &Globals.szNetbiosScope)
865 _PUBLIC_ FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
866 _PUBLIC_ FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
867 _PUBLIC_ FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
868 _PUBLIC_ FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
870 _PUBLIC_ FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
871 _PUBLIC_ FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
872 _PUBLIC_ FN_GLOBAL_BOOL(lp_wins_dns_proxy, &Globals.bWINSdnsProxy)
873 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
874 _PUBLIC_ FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
875 _PUBLIC_ FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
876 _PUBLIC_ FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
877 _PUBLIC_ FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw)
878 _PUBLIC_ FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords)
879 _PUBLIC_ FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions)
880 _PUBLIC_ FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
881 _PUBLIC_ FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
882 _PUBLIC_ FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
883 _PUBLIC_ FN_GLOBAL_BOOL(lp_unicode, &Globals.bUnicode)
884 _PUBLIC_ FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
885 _PUBLIC_ FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
886 _PUBLIC_ FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
887 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_plaintext_auth, &Globals.bClientPlaintextAuth)
888 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
889 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
890 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_use_spnego_principal, &Globals.client_use_spnego_principal)
891 _PUBLIC_ FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
892 _PUBLIC_ FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions)
893 _PUBLIC_ FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
894 _PUBLIC_ FN_GLOBAL_BOOL(lp_rpc_big_endian, &Globals.bRpcBigEndian)
895 _PUBLIC_ FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
896 _PUBLIC_ FN_GLOBAL_INTEGER(lp_min_wins_ttl, &Globals.min_wins_ttl)
897 _PUBLIC_ FN_GLOBAL_INTEGER(lp_maxmux, &Globals.max_mux)
898 _PUBLIC_ FN_GLOBAL_INTEGER(lp_max_xmit, &Globals.max_xmit)
899 _PUBLIC_ FN_GLOBAL_INTEGER(lp_passwordlevel, &Globals.pwordlevel)
900 _PUBLIC_ FN_GLOBAL_INTEGER(lp_srv_maxprotocol, &Globals.srv_maxprotocol)
901 _PUBLIC_ FN_GLOBAL_INTEGER(lp_srv_minprotocol, &Globals.srv_minprotocol)
902 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cli_maxprotocol, &Globals.cli_maxprotocol)
903 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cli_minprotocol, &Globals.cli_minprotocol)
904 _PUBLIC_ FN_GLOBAL_INTEGER(lp_security, &Globals.security)
905 _PUBLIC_ FN_GLOBAL_LIST(lp_auth_methods, &Globals.AuthMethods)
906 _PUBLIC_ FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security)
907 _PUBLIC_ FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as)
908 _PUBLIC_ FN_GLOBAL_LIST(lp_js_include, &Globals.jsInclude)
909 _PUBLIC_ FN_GLOBAL_STRING(lp_jsonrpc_services_dir, &Globals.jsonrpcServicesDir)
910 _PUBLIC_
911 _PUBLIC_
912 _PUBLIC_ FN_LOCAL_STRING(lp_servicename, szService)
913 _PUBLIC_ FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
914 _PUBLIC_ FN_LOCAL_STRING(lp_pathname, szPath)
915 static FN_LOCAL_STRING(_lp_printername, szPrintername)
916 _PUBLIC_ FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
917 _PUBLIC_ FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
918 _PUBLIC_ FN_LOCAL_STRING(lp_comment, comment)
919 _PUBLIC_ FN_LOCAL_STRING(lp_fstype, fstype)
920 static FN_LOCAL_STRING(lp_volume, volume)
921 _PUBLIC_ FN_LOCAL_LIST(lp_ntvfs_handler, ntvfs_handler)
922 _PUBLIC_ FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
923 _PUBLIC_ FN_LOCAL_BOOL(lp_browseable, bBrowseable)
924 _PUBLIC_ FN_LOCAL_BOOL(lp_readonly, bRead_only)
925 _PUBLIC_ FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
926 _PUBLIC_ FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
927 _PUBLIC_ FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
928 _PUBLIC_ FN_LOCAL_BOOL(lp_strict_locking, bStrictLocking)
929 _PUBLIC_ FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
930 _PUBLIC_ FN_LOCAL_BOOL(lp_ci_filesystem, bCIFileSystem)
931 _PUBLIC_ FN_LOCAL_BOOL(lp_map_system, bMap_system)
932 _PUBLIC_ FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
933 _PUBLIC_ FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
934 _PUBLIC_ FN_GLOBAL_INTEGER(lp_server_signing, &Globals.server_signing)
935 _PUBLIC_ FN_GLOBAL_INTEGER(lp_client_signing, &Globals.client_signing)
937 /* local prototypes */
939 static int map_parameter(const char *pszParmName);
940 static int getservicebyname(const char *pszServiceName,
941 service * pserviceDest);
942 static void copy_service(service * pserviceDest,
943 service * pserviceSource, int *pcopymapDest);
944 static BOOL service_ok(int iService);
945 static BOOL do_section(const char *pszSectionName, void *);
946 static void init_copymap(service * pservice);
948 /* This is a helper function for parametrical options support. */
949 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
950 /* Actual parametrical functions are quite simple */
951 const char *lp_get_parametric(int lookup_service, const char *type, const char *option)
953 char *vfskey;
954 struct param_opt *data;
956 if (lookup_service >= iNumServices) return NULL;
958 data = (lookup_service < 0) ?
959 Globals.param_opt : ServicePtrs[lookup_service]->param_opt;
961 asprintf(&vfskey, "%s:%s", type, option);
962 strlower(vfskey);
964 while (data) {
965 if (strcmp(data->key, vfskey) == 0) {
966 free(vfskey);
967 return data->value;
969 data = data->next;
972 if (lookup_service >= 0) {
973 /* Try to fetch the same option but from globals */
974 /* but only if we are not already working with Globals */
975 data = Globals.param_opt;
976 while (data) {
977 if (strcmp(data->key, vfskey) == 0) {
978 free(vfskey);
979 return data->value;
981 data = data->next;
985 free(vfskey);
987 return NULL;
991 /*******************************************************************
992 convenience routine to return int parameters.
993 ********************************************************************/
994 static int lp_int(const char *s)
997 if (!s) {
998 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
999 return (-1);
1002 return strtol(s, NULL, 0);
1005 /*******************************************************************
1006 convenience routine to return unsigned long parameters.
1007 ********************************************************************/
1008 static int lp_ulong(const char *s)
1011 if (!s) {
1012 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
1013 return (-1);
1016 return strtoul(s, NULL, 0);
1019 /*******************************************************************
1020 convenience routine to return boolean parameters.
1021 ********************************************************************/
1022 static BOOL lp_bool(const char *s)
1024 BOOL ret = False;
1026 if (!s) {
1027 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
1028 return False;
1031 if (!set_boolean(s, &ret)) {
1032 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1033 return False;
1036 return ret;
1040 /* Return parametric option from a given service. Type is a part of option before ':' */
1041 /* Parametric option has following syntax: 'Type: option = value' */
1042 /* Returned value is allocated in 'lp_talloc' context */
1044 const char *lp_parm_string(int lookup_service, const char *type, const char *option)
1046 const char *value = lp_get_parametric(lookup_service, type, option);
1048 if (value)
1049 return lp_string(value);
1051 return NULL;
1054 /* Return parametric option from a given service. Type is a part of option before ':' */
1055 /* Parametric option has following syntax: 'Type: option = value' */
1056 /* Returned value is allocated in 'lp_talloc' context */
1058 const char **lp_parm_string_list(int lookup_service, const char *type, const char *option,
1059 const char *separator)
1061 const char *value = lp_get_parametric(lookup_service, type, option);
1063 if (value)
1064 return str_list_make(talloc_autofree_context(), value, separator);
1066 return NULL;
1069 /* Return parametric option from a given service. Type is a part of option before ':' */
1070 /* Parametric option has following syntax: 'Type: option = value' */
1072 int lp_parm_int(int lookup_service, const char *type, const char *option, int default_v)
1074 const char *value = lp_get_parametric(lookup_service, type, option);
1076 if (value)
1077 return lp_int(value);
1079 return default_v;
1082 /* Return parametric option from a given service. Type is a part of
1083 * option before ':'.
1084 * Parametric option has following syntax: 'Type: option = value'.
1087 int lp_parm_bytes(int lookup_service, const char *type, const char *option, int default_v)
1089 uint64_t bval;
1091 const char *value = lp_get_parametric(lookup_service, type, option);
1093 if (value && conv_str_size(value, &bval)) {
1094 if (bval <= INT_MAX) {
1095 return (int)bval;
1099 return default_v;
1102 /* Return parametric option from a given service. Type is a part of option before ':' */
1103 /* Parametric option has following syntax: 'Type: option = value' */
1105 unsigned long lp_parm_ulong(int lookup_service, const char *type, const char *option, unsigned long default_v)
1107 const char *value = lp_get_parametric(lookup_service, type, option);
1109 if (value)
1110 return lp_ulong(value);
1112 return default_v;
1115 /* Return parametric option from a given service. Type is a part of option before ':' */
1116 /* Parametric option has following syntax: 'Type: option = value' */
1118 BOOL lp_parm_bool(int lookup_service, const char *type, const char *option, BOOL default_v)
1120 const char *value = lp_get_parametric(lookup_service, type, option);
1122 if (value)
1123 return lp_bool(value);
1125 return default_v;
1129 /***************************************************************************
1130 Initialise a service to the defaults.
1131 ***************************************************************************/
1133 static void init_service(service * pservice)
1135 memset((char *)pservice, '\0', sizeof(service));
1136 copy_service(pservice, &sDefault, NULL);
1139 /***************************************************************************
1140 Free the dynamically allocated parts of a service struct.
1141 ***************************************************************************/
1143 static void free_service(service *pservice)
1145 int i;
1146 struct param_opt *data, *pdata;
1147 if (!pservice)
1148 return;
1150 if (pservice->szService)
1151 DEBUG(5, ("free_service: Freeing service %s\n",
1152 pservice->szService));
1154 string_free(&pservice->szService);
1155 SAFE_FREE(pservice->copymap);
1157 for (i = 0; parm_table[i].label; i++) {
1158 if ((parm_table[i].type == P_STRING ||
1159 parm_table[i].type == P_USTRING) &&
1160 parm_table[i].class == P_LOCAL) {
1161 string_free((char **)
1162 (((char *)pservice) +
1163 PTR_DIFF(parm_table[i].ptr, &sDefault)));
1164 } else if (parm_table[i].type == P_LIST &&
1165 parm_table[i].class == P_LOCAL) {
1166 char ***listp = (char ***)(((char *)pservice) +
1167 PTR_DIFF(parm_table[i].ptr, &sDefault));
1168 talloc_free(*listp);
1169 *listp = NULL;
1173 DEBUG(5,("Freeing parametrics:\n"));
1174 data = pservice->param_opt;
1175 while (data) {
1176 DEBUG(5,("[%s = %s]\n", data->key, data->value));
1177 string_free(&data->key);
1178 string_free(&data->value);
1179 pdata = data->next;
1180 SAFE_FREE(data);
1181 data = pdata;
1184 ZERO_STRUCTP(pservice);
1187 /***************************************************************************
1188 Add a new service to the services array initialising it with the given
1189 service.
1190 ***************************************************************************/
1192 static int add_a_service(const service *pservice, const char *name)
1194 int i;
1195 service tservice;
1196 int num_to_alloc = iNumServices + 1;
1197 struct param_opt *data, *pdata;
1199 tservice = *pservice;
1201 /* it might already exist */
1202 if (name) {
1203 i = getservicebyname(name, NULL);
1204 if (i >= 0) {
1205 /* Clean all parametric options for service */
1206 /* They will be added during parsing again */
1207 data = ServicePtrs[i]->param_opt;
1208 while (data) {
1209 string_free(&data->key);
1210 string_free(&data->value);
1211 pdata = data->next;
1212 SAFE_FREE(data);
1213 data = pdata;
1215 ServicePtrs[i]->param_opt = NULL;
1216 return (i);
1220 /* find an invalid one */
1221 for (i = 0; i < iNumServices; i++)
1222 if (!ServicePtrs[i]->valid)
1223 break;
1225 /* if not, then create one */
1226 if (i == iNumServices) {
1227 service **tsp;
1229 tsp = realloc_p(ServicePtrs, service *, num_to_alloc);
1231 if (!tsp) {
1232 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1233 return (-1);
1235 else {
1236 ServicePtrs = tsp;
1237 ServicePtrs[iNumServices] = malloc_p(service);
1239 if (!ServicePtrs[iNumServices]) {
1240 DEBUG(0,("add_a_service: out of memory!\n"));
1241 return (-1);
1244 iNumServices++;
1245 } else
1246 free_service(ServicePtrs[i]);
1248 ServicePtrs[i]->valid = True;
1250 init_service(ServicePtrs[i]);
1251 copy_service(ServicePtrs[i], &tservice, NULL);
1252 if (name)
1253 string_set(&ServicePtrs[i]->szService, name);
1254 return (i);
1257 /***************************************************************************
1258 Add a new home service, with the specified home directory, defaults coming
1259 from service ifrom.
1260 ***************************************************************************/
1262 BOOL lp_add_home(const char *pszHomename, int iDefaultService,
1263 const char *user, const char *pszHomedir)
1265 int i;
1266 pstring newHomedir;
1268 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1270 if (i < 0)
1271 return (False);
1273 if (!(*(ServicePtrs[iDefaultService]->szPath))
1274 || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(-1))) {
1275 pstrcpy(newHomedir, pszHomedir);
1276 } else {
1277 pstrcpy(newHomedir, lp_pathname(iDefaultService));
1278 string_sub(newHomedir,"%H", pszHomedir, sizeof(newHomedir));
1281 string_set(&ServicePtrs[i]->szPath, newHomedir);
1283 if (!(*(ServicePtrs[i]->comment))) {
1284 pstring comment;
1285 slprintf(comment, sizeof(comment) - 1,
1286 "Home directory of %s", user);
1287 string_set(&ServicePtrs[i]->comment, comment);
1289 ServicePtrs[i]->bAvailable = sDefault.bAvailable;
1290 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1292 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1293 user, newHomedir));
1295 return (True);
1298 /***************************************************************************
1299 Add a new service, based on an old one.
1300 ***************************************************************************/
1302 int lp_add_service(const char *pszService, int iDefaultService)
1304 return (add_a_service(ServicePtrs[iDefaultService], pszService));
1307 /***************************************************************************
1308 Add the IPC service.
1309 ***************************************************************************/
1311 static BOOL lp_add_hidden(const char *name, const char *fstype)
1313 pstring comment;
1314 int i = add_a_service(&sDefault, name);
1316 if (i < 0)
1317 return (False);
1319 slprintf(comment, sizeof(comment) - 1,
1320 "%s Service (%s)", fstype, Globals.szServerString);
1322 string_set(&ServicePtrs[i]->szPath, tmpdir());
1323 string_set(&ServicePtrs[i]->comment, comment);
1324 string_set(&ServicePtrs[i]->fstype, fstype);
1325 ServicePtrs[i]->iMaxConnections = -1;
1326 ServicePtrs[i]->bAvailable = True;
1327 ServicePtrs[i]->bRead_only = True;
1328 ServicePtrs[i]->bPrint_ok = False;
1329 ServicePtrs[i]->bBrowseable = False;
1331 if (strcasecmp(fstype, "IPC") == 0) {
1332 lp_do_parameter(i, "ntvfs handler", "default");
1335 DEBUG(3, ("adding hidden service %s\n", name));
1337 return (True);
1340 /***************************************************************************
1341 Add a new printer service, with defaults coming from service iFrom.
1342 ***************************************************************************/
1344 BOOL lp_add_printer(const char *pszPrintername, int iDefaultService)
1346 const char *comment = "From Printcap";
1347 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1349 if (i < 0)
1350 return (False);
1352 /* note that we do NOT default the availability flag to True - */
1353 /* we take it from the default service passed. This allows all */
1354 /* dynamic printers to be disabled by disabling the [printers] */
1355 /* entry (if/when the 'available' keyword is implemented!). */
1357 /* the printer name is set to the service name. */
1358 string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1359 string_set(&ServicePtrs[i]->comment, comment);
1360 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1361 /* Printers cannot be read_only. */
1362 ServicePtrs[i]->bRead_only = False;
1363 /* Printer services must be printable. */
1364 ServicePtrs[i]->bPrint_ok = True;
1366 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1368 return (True);
1371 /***************************************************************************
1372 Map a parameter's string representation to something we can use.
1373 Returns False if the parameter string is not recognised, else TRUE.
1374 ***************************************************************************/
1376 static int map_parameter(const char *pszParmName)
1378 int iIndex;
1380 if (*pszParmName == '-')
1381 return (-1);
1383 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1384 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1385 return (iIndex);
1387 /* Warn only if it isn't parametric option */
1388 if (strchr(pszParmName, ':') == NULL)
1389 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1390 /* We do return 'fail' for parametric options as well because they are
1391 stored in different storage
1393 return (-1);
1398 return the parameter structure for a parameter
1400 struct parm_struct *lp_parm_struct(const char *name)
1402 int parmnum = map_parameter(name);
1403 if (parmnum == -1) return NULL;
1404 return &parm_table[parmnum];
1408 return the parameter pointer for a parameter
1410 void *lp_parm_ptr(int snum, struct parm_struct *parm)
1412 if (snum == -1) {
1413 return parm->ptr;
1415 return ((char *)ServicePtrs[snum]) + PTR_DIFF(parm->ptr, &sDefault);
1418 /***************************************************************************
1419 Find a service by name. Otherwise works like get_service.
1420 ***************************************************************************/
1422 static int getservicebyname(const char *pszServiceName, service * pserviceDest)
1424 int iService;
1426 for (iService = iNumServices - 1; iService >= 0; iService--)
1427 if (VALID(iService) &&
1428 strwicmp(ServicePtrs[iService]->szService, pszServiceName) == 0) {
1429 if (pserviceDest != NULL)
1430 copy_service(pserviceDest, ServicePtrs[iService], NULL);
1431 break;
1434 return (iService);
1437 /***************************************************************************
1438 Copy a service structure to another.
1439 If pcopymapDest is NULL then copy all fields
1440 ***************************************************************************/
1442 static void copy_service(service * pserviceDest, service * pserviceSource, int *pcopymapDest)
1444 int i;
1445 BOOL bcopyall = (pcopymapDest == NULL);
1446 struct param_opt *data, *pdata, *paramo;
1447 BOOL not_added;
1449 for (i = 0; parm_table[i].label; i++)
1450 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1451 (bcopyall || pcopymapDest[i])) {
1452 void *def_ptr = parm_table[i].ptr;
1453 void *src_ptr =
1454 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
1455 &sDefault);
1456 void *dest_ptr =
1457 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
1458 &sDefault);
1460 switch (parm_table[i].type) {
1461 case P_BOOL:
1462 *(int *)dest_ptr = *(int *)src_ptr;
1463 break;
1465 case P_INTEGER:
1466 case P_ENUM:
1467 *(int *)dest_ptr = *(int *)src_ptr;
1468 break;
1470 case P_STRING:
1471 string_set(dest_ptr,
1472 *(char **)src_ptr);
1473 break;
1475 case P_USTRING:
1476 string_set(dest_ptr,
1477 *(char **)src_ptr);
1478 strupper(*(char **)dest_ptr);
1479 break;
1480 case P_LIST:
1481 *(const char ***)dest_ptr = str_list_copy(talloc_autofree_context(),
1482 *(const char ***)src_ptr);
1483 break;
1484 default:
1485 break;
1489 if (bcopyall) {
1490 init_copymap(pserviceDest);
1491 if (pserviceSource->copymap)
1492 memcpy((void *)pserviceDest->copymap,
1493 (void *)pserviceSource->copymap,
1494 sizeof(int) * NUMPARAMETERS);
1497 data = pserviceSource->param_opt;
1498 while (data) {
1499 not_added = True;
1500 pdata = pserviceDest->param_opt;
1501 /* Traverse destination */
1502 while (pdata) {
1503 /* If we already have same option, override it */
1504 if (strcmp(pdata->key, data->key) == 0) {
1505 string_free(&pdata->value);
1506 pdata->value = strdup(data->value);
1507 not_added = False;
1508 break;
1510 pdata = pdata->next;
1512 if (not_added) {
1513 paramo = malloc_p(struct param_opt);
1514 if (!paramo)
1515 smb_panic("OOM");
1516 paramo->key = strdup(data->key);
1517 paramo->value = strdup(data->value);
1518 DLIST_ADD(pserviceDest->param_opt, paramo);
1520 data = data->next;
1524 /***************************************************************************
1525 Check a service for consistency. Return False if the service is in any way
1526 incomplete or faulty, else True.
1527 ***************************************************************************/
1529 static BOOL service_ok(int iService)
1531 BOOL bRetval;
1533 bRetval = True;
1534 if (ServicePtrs[iService]->szService[0] == '\0') {
1535 DEBUG(0, ("The following message indicates an internal error:\n"));
1536 DEBUG(0, ("No service name in service entry.\n"));
1537 bRetval = False;
1540 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1541 /* I can't see why you'd want a non-printable printer service... */
1542 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
1543 if (!ServicePtrs[iService]->bPrint_ok) {
1544 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
1545 ServicePtrs[iService]->szService));
1546 ServicePtrs[iService]->bPrint_ok = True;
1548 /* [printers] service must also be non-browsable. */
1549 if (ServicePtrs[iService]->bBrowseable)
1550 ServicePtrs[iService]->bBrowseable = False;
1553 /* If a service is flagged unavailable, log the fact at level 0. */
1554 if (!ServicePtrs[iService]->bAvailable)
1555 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
1556 ServicePtrs[iService]->szService));
1558 return (bRetval);
1561 static struct file_lists {
1562 struct file_lists *next;
1563 char *name;
1564 char *subfname;
1565 time_t modtime;
1566 } *file_lists = NULL;
1568 /*******************************************************************
1569 Keep a linked list of all config files so we know when one has changed
1570 it's date and needs to be reloaded.
1571 ********************************************************************/
1573 static void add_to_file_list(const char *fname, const char *subfname)
1575 struct file_lists *f = file_lists;
1577 while (f) {
1578 if (f->name && !strcmp(f->name, fname))
1579 break;
1580 f = f->next;
1583 if (!f) {
1584 f = malloc_p(struct file_lists);
1585 if (!f)
1586 return;
1587 f->next = file_lists;
1588 f->name = strdup(fname);
1589 if (!f->name) {
1590 SAFE_FREE(f);
1591 return;
1593 f->subfname = strdup(subfname);
1594 if (!f->subfname) {
1595 SAFE_FREE(f);
1596 return;
1598 file_lists = f;
1599 f->modtime = file_modtime(subfname);
1600 } else {
1601 time_t t = file_modtime(subfname);
1602 if (t)
1603 f->modtime = t;
1607 /*******************************************************************
1608 Check if a config file has changed date.
1609 ********************************************************************/
1611 BOOL lp_file_list_changed(void)
1613 struct file_lists *f = file_lists;
1614 DEBUG(6, ("lp_file_list_changed()\n"));
1616 while (f) {
1617 pstring n2;
1618 time_t mod_time;
1620 pstrcpy(n2, f->name);
1621 standard_sub_basic(n2,sizeof(n2));
1623 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
1624 f->name, n2, ctime(&f->modtime)));
1626 mod_time = file_modtime(n2);
1628 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
1629 DEBUGADD(6,
1630 ("file %s modified: %s\n", n2,
1631 ctime(&mod_time)));
1632 f->modtime = mod_time;
1633 SAFE_FREE(f->subfname);
1634 f->subfname = strdup(n2);
1635 return (True);
1637 f = f->next;
1639 return (False);
1642 /***************************************************************************
1643 Handle the include operation.
1644 ***************************************************************************/
1646 static BOOL handle_include(const char *pszParmValue, char **ptr)
1648 pstring fname;
1649 pstrcpy(fname, pszParmValue);
1651 standard_sub_basic(fname,sizeof(fname));
1653 add_to_file_list(pszParmValue, fname);
1655 string_set(ptr, fname);
1657 if (file_exist(fname))
1658 return (pm_process(fname, do_section, do_parameter, NULL));
1660 DEBUG(2, ("Can't find include file %s\n", fname));
1662 return (False);
1665 /***************************************************************************
1666 Handle the interpretation of the copy parameter.
1667 ***************************************************************************/
1669 static BOOL handle_copy(const char *pszParmValue, char **ptr)
1671 BOOL bRetval;
1672 int iTemp;
1673 service serviceTemp;
1675 string_set(ptr, pszParmValue);
1677 init_service(&serviceTemp);
1679 bRetval = False;
1681 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
1683 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
1684 if (iTemp == iServiceIndex) {
1685 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
1686 } else {
1687 copy_service(ServicePtrs[iServiceIndex],
1688 &serviceTemp,
1689 ServicePtrs[iServiceIndex]->copymap);
1690 bRetval = True;
1692 } else {
1693 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
1694 bRetval = False;
1697 free_service(&serviceTemp);
1698 return (bRetval);
1701 /***************************************************************************
1702 Initialise a copymap.
1703 ***************************************************************************/
1705 static void init_copymap(service * pservice)
1707 int i;
1708 SAFE_FREE(pservice->copymap);
1709 pservice->copymap = malloc_array_p(int, NUMPARAMETERS);
1710 if (!pservice->copymap)
1711 DEBUG(0,
1712 ("Couldn't allocate copymap!! (size %d)\n",
1713 (int)NUMPARAMETERS));
1714 else
1715 for (i = 0; i < NUMPARAMETERS; i++)
1716 pservice->copymap[i] = True;
1719 #if 0 /* not used anywhere */
1720 /***************************************************************************
1721 Return the local pointer to a parameter given the service number and the
1722 pointer into the default structure.
1723 ***************************************************************************/
1725 void *lp_local_ptr(int snum, void *ptr)
1727 return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
1729 #endif
1731 /***************************************************************************
1732 Process a parametric option
1733 ***************************************************************************/
1734 static BOOL lp_do_parameter_parametric(int snum, const char *pszParmName, const char *pszParmValue, int flags)
1736 struct param_opt *paramo, *data;
1737 char *name;
1739 while (isspace((unsigned char)*pszParmName)) {
1740 pszParmName++;
1743 name = strdup(pszParmName);
1744 if (!name) return False;
1746 strlower(name);
1748 if (snum < 0) {
1749 data = Globals.param_opt;
1750 } else {
1751 data = ServicePtrs[snum]->param_opt;
1754 /* Traverse destination */
1755 for (paramo=data; paramo; paramo=paramo->next) {
1756 /* If we already have the option set, override it unless
1757 it was a command line option and the new one isn't */
1758 if (strcmp(paramo->key, name) == 0) {
1759 if ((paramo->flags & FLAG_CMDLINE) &&
1760 !(flags & FLAG_CMDLINE)) {
1761 return True;
1764 free(paramo->value);
1765 paramo->value = strdup(pszParmValue);
1766 paramo->flags = flags;
1767 free(name);
1768 return True;
1772 paramo = malloc_p(struct param_opt);
1773 if (!paramo)
1774 smb_panic("OOM");
1775 paramo->key = strdup(name);
1776 paramo->value = strdup(pszParmValue);
1777 paramo->flags = flags;
1778 if (snum < 0) {
1779 DLIST_ADD(Globals.param_opt, paramo);
1780 } else {
1781 DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
1784 free(name);
1786 return True;
1789 /***************************************************************************
1790 Process a parameter for a particular service number. If snum < 0
1791 then assume we are in the globals.
1792 ***************************************************************************/
1793 BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
1795 int parmnum, i;
1796 void *parm_ptr = NULL; /* where we are going to store the result */
1797 void *def_ptr = NULL;
1799 parmnum = map_parameter(pszParmName);
1801 if (parmnum < 0) {
1802 if (strchr(pszParmName, ':')) {
1803 return lp_do_parameter_parametric(snum, pszParmName, pszParmValue, 0);
1805 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1806 return (True);
1809 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1810 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1811 pszParmName));
1814 /* if the flag has been set on the command line, then don't allow override,
1815 but don't report an error */
1816 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1817 return True;
1820 def_ptr = parm_table[parmnum].ptr;
1822 /* we might point at a service, the default service or a global */
1823 if (snum < 0) {
1824 parm_ptr = def_ptr;
1825 } else {
1826 if (parm_table[parmnum].class == P_GLOBAL) {
1827 DEBUG(0,
1828 ("Global parameter %s found in service section!\n",
1829 pszParmName));
1830 return (True);
1832 parm_ptr =
1833 ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
1834 &sDefault);
1837 if (snum >= 0) {
1838 if (!ServicePtrs[snum]->copymap)
1839 init_copymap(ServicePtrs[snum]);
1841 /* this handles the aliases - set the copymap for other entries with
1842 the same data pointer */
1843 for (i = 0; parm_table[i].label; i++)
1844 if (parm_table[i].ptr == parm_table[parmnum].ptr)
1845 ServicePtrs[snum]->copymap[i] = False;
1848 /* if it is a special case then go ahead */
1849 if (parm_table[parmnum].special) {
1850 parm_table[parmnum].special(pszParmValue, (char **)parm_ptr);
1851 return (True);
1854 /* now switch on the type of variable it is */
1855 switch (parm_table[parmnum].type)
1857 case P_BOOL: {
1858 BOOL b;
1859 if (!set_boolean(pszParmValue, &b)) {
1860 DEBUG(0,("lp_do_parameter(%s): value is not boolean!\n", pszParmValue));
1861 return False;
1863 *(int *)parm_ptr = b;
1865 break;
1867 case P_INTEGER:
1868 *(int *)parm_ptr = atoi(pszParmValue);
1869 break;
1871 case P_BYTES:
1873 uint64_t val;
1874 if (conv_str_size(pszParmValue, &val)) {
1875 if (val <= INT_MAX) {
1876 *(int *)parm_ptr = (int)val;
1877 break;
1881 DEBUG(0,("lp_do_parameter(%s): value is not "
1882 "a valid size specifier!\n", pszParmValue));
1883 return False;
1886 case P_LIST:
1887 *(const char ***)parm_ptr = str_list_make(talloc_autofree_context(),
1888 pszParmValue, NULL);
1889 break;
1891 case P_STRING:
1892 string_set(parm_ptr, pszParmValue);
1893 break;
1895 case P_USTRING:
1896 string_set(parm_ptr, pszParmValue);
1897 strupper(*(char **)parm_ptr);
1898 break;
1900 case P_ENUM:
1901 for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
1902 if (strequal
1903 (pszParmValue,
1904 parm_table[parmnum].enum_list[i].name)) {
1905 *(int *)parm_ptr =
1906 parm_table[parmnum].
1907 enum_list[i].value;
1908 break;
1911 if (!parm_table[parmnum].enum_list[i].name) {
1912 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n",
1913 pszParmValue, pszParmName));
1914 return False;
1916 break;
1917 case P_SEP:
1918 break;
1921 if (parm_table[parmnum].flags & FLAG_DEFAULT) {
1922 parm_table[parmnum].flags &= ~FLAG_DEFAULT;
1923 /* we have to also unset FLAG_DEFAULT on aliases */
1924 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1925 parm_table[i].flags &= ~FLAG_DEFAULT;
1927 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1928 parm_table[i].flags &= ~FLAG_DEFAULT;
1932 return (True);
1935 /***************************************************************************
1936 Process a parameter.
1937 ***************************************************************************/
1939 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue, void *userdata)
1941 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
1942 pszParmName, pszParmValue));
1946 variable argument do parameter
1948 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
1950 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...)
1952 char *s;
1953 BOOL ret;
1954 va_list ap;
1956 va_start(ap, fmt);
1957 s = talloc_vasprintf(NULL, fmt, ap);
1958 va_end(ap);
1959 ret = do_parameter(pszParmName, s, NULL);
1960 talloc_free(s);
1961 return ret;
1966 set a parameter from the commandline - this is called from command line parameter
1967 parsing code. It sets the parameter then marks the parameter as unable to be modified
1968 by smb.conf processing
1970 BOOL lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
1972 int parmnum = map_parameter(pszParmName);
1973 int i;
1975 while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
1978 if (parmnum < 0 && strchr(pszParmName, ':')) {
1979 /* set a parametric option */
1980 return lp_do_parameter_parametric(-1, pszParmName, pszParmValue, FLAG_CMDLINE);
1983 if (parmnum < 0) {
1984 DEBUG(0,("Unknown option '%s'\n", pszParmName));
1985 return False;
1988 /* reset the CMDLINE flag in case this has been called before */
1989 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
1991 if (!lp_do_parameter(-2, pszParmName, pszParmValue)) {
1992 return False;
1995 parm_table[parmnum].flags |= FLAG_CMDLINE;
1997 /* we have to also set FLAG_CMDLINE on aliases */
1998 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1999 parm_table[i].flags |= FLAG_CMDLINE;
2001 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
2002 parm_table[i].flags |= FLAG_CMDLINE;
2005 return True;
2009 set a option from the commandline in 'a=b' format. Use to support --option
2011 BOOL lp_set_option(const char *option)
2013 char *p, *s;
2014 BOOL ret;
2016 s = strdup(option);
2017 if (!s) {
2018 return False;
2021 p = strchr(s, '=');
2022 if (!p) {
2023 free(s);
2024 return False;
2027 *p = 0;
2029 ret = lp_set_cmdline(s, p+1);
2030 free(s);
2031 return ret;
2035 #define BOOLSTR(b) ((b) ? "Yes" : "No")
2037 /***************************************************************************
2038 Print a parameter of the specified type.
2039 ***************************************************************************/
2041 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
2043 int i;
2044 switch (p->type)
2046 case P_ENUM:
2047 for (i = 0; p->enum_list[i].name; i++) {
2048 if (*(int *)ptr == p->enum_list[i].value) {
2049 fprintf(f, "%s",
2050 p->enum_list[i].name);
2051 break;
2054 break;
2056 case P_BOOL:
2057 fprintf(f, "%s", BOOLSTR((BOOL)*(int *)ptr));
2058 break;
2060 case P_INTEGER:
2061 case P_BYTES:
2062 fprintf(f, "%d", *(int *)ptr);
2063 break;
2065 case P_LIST:
2066 if ((char ***)ptr && *(char ***)ptr) {
2067 char **list = *(char ***)ptr;
2069 for (; *list; list++)
2070 fprintf(f, "%s%s", *list,
2071 ((*(list+1))?", ":""));
2073 break;
2075 case P_STRING:
2076 case P_USTRING:
2077 if (*(char **)ptr) {
2078 fprintf(f, "%s", *(char **)ptr);
2080 break;
2081 case P_SEP:
2082 break;
2086 /***************************************************************************
2087 Check if two parameters are equal.
2088 ***************************************************************************/
2090 static BOOL equal_parameter(parm_type type, void *ptr1, void *ptr2)
2092 switch (type) {
2093 case P_BOOL:
2094 return (*((int *)ptr1) == *((int *)ptr2));
2096 case P_INTEGER:
2097 case P_BYTES:
2098 case P_ENUM:
2099 return (*((int *)ptr1) == *((int *)ptr2));
2101 case P_LIST:
2102 return str_list_equal((const char **)(*(char ***)ptr1),
2103 (const char **)(*(char ***)ptr2));
2105 case P_STRING:
2106 case P_USTRING:
2108 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
2109 if (p1 && !*p1)
2110 p1 = NULL;
2111 if (p2 && !*p2)
2112 p2 = NULL;
2113 return (p1 == p2 || strequal(p1, p2));
2115 case P_SEP:
2116 break;
2118 return (False);
2121 /***************************************************************************
2122 Process a new section (service). At this stage all sections are services.
2123 Later we'll have special sections that permit server parameters to be set.
2124 Returns True on success, False on failure.
2125 ***************************************************************************/
2127 static BOOL do_section(const char *pszSectionName, void *userdata)
2129 BOOL bRetval;
2130 BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2131 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2132 bRetval = False;
2134 /* if we've just struck a global section, note the fact. */
2135 bInGlobalSection = isglobal;
2137 /* check for multiple global sections */
2138 if (bInGlobalSection) {
2139 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2140 return (True);
2143 /* if we have a current service, tidy it up before moving on */
2144 bRetval = True;
2146 if (iServiceIndex >= 0)
2147 bRetval = service_ok(iServiceIndex);
2149 /* if all is still well, move to the next record in the services array */
2150 if (bRetval) {
2151 /* We put this here to avoid an odd message order if messages are */
2152 /* issued by the post-processing of a previous section. */
2153 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2155 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
2156 < 0) {
2157 DEBUG(0, ("Failed to add a new service\n"));
2158 return (False);
2162 return (bRetval);
2166 /***************************************************************************
2167 Determine if a partcular base parameter is currentl set to the default value.
2168 ***************************************************************************/
2170 static BOOL is_default(int i)
2172 if (!defaults_saved)
2173 return False;
2174 switch (parm_table[i].type) {
2175 case P_LIST:
2176 return str_list_equal((const char **)parm_table[i].def.lvalue,
2177 (const char **)(*(char ***)parm_table[i].ptr));
2178 case P_STRING:
2179 case P_USTRING:
2180 return strequal(parm_table[i].def.svalue,
2181 *(char **)parm_table[i].ptr);
2182 case P_BOOL:
2183 return parm_table[i].def.bvalue ==
2184 *(int *)parm_table[i].ptr;
2185 case P_INTEGER:
2186 case P_BYTES:
2187 case P_ENUM:
2188 return parm_table[i].def.ivalue ==
2189 *(int *)parm_table[i].ptr;
2190 case P_SEP:
2191 break;
2193 return False;
2196 /***************************************************************************
2197 Display the contents of the global structure.
2198 ***************************************************************************/
2200 static void dump_globals(FILE *f, BOOL show_defaults)
2202 int i;
2203 struct param_opt *data;
2205 fprintf(f, "# Global parameters\n[global]\n");
2207 for (i = 0; parm_table[i].label; i++)
2208 if (parm_table[i].class == P_GLOBAL &&
2209 parm_table[i].ptr &&
2210 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2211 if (!show_defaults && (parm_table[i].flags & FLAG_DEFAULT))
2212 continue;
2213 fprintf(f, "\t%s = ", parm_table[i].label);
2214 print_parameter(&parm_table[i], parm_table[i].ptr, f);
2215 fprintf(f, "\n");
2217 if (Globals.param_opt != NULL) {
2218 data = Globals.param_opt;
2219 while(data) {
2220 fprintf(f, "\t%s = %s\n", data->key, data->value);
2221 data = data->next;
2227 /***************************************************************************
2228 Display the contents of a single services record.
2229 ***************************************************************************/
2231 static void dump_a_service(service * pService, FILE * f)
2233 int i;
2234 struct param_opt *data;
2236 if (pService != &sDefault)
2237 fprintf(f, "\n[%s]\n", pService->szService);
2239 for (i = 0; parm_table[i].label; i++)
2240 if (parm_table[i].class == P_LOCAL &&
2241 parm_table[i].ptr &&
2242 (*parm_table[i].label != '-') &&
2243 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2244 int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
2246 if (pService == &sDefault) {
2247 if (defaults_saved && is_default(i))
2248 continue;
2249 } else {
2250 if (equal_parameter(parm_table[i].type,
2251 ((char *)pService) +
2252 pdiff,
2253 ((char *)&sDefault) +
2254 pdiff))
2255 continue;
2258 fprintf(f, "\t%s = ", parm_table[i].label);
2259 print_parameter(&parm_table[i],
2260 ((char *)pService) + pdiff, f);
2261 fprintf(f, "\n");
2263 if (pService->param_opt != NULL) {
2264 data = pService->param_opt;
2265 while(data) {
2266 fprintf(f, "\t%s = %s\n", data->key, data->value);
2267 data = data->next;
2272 BOOL lp_dump_a_parameter(int snum, char *parm_name, FILE * f, BOOL isGlobal)
2274 service * pService = ServicePtrs[snum];
2275 struct parm_struct *parm;
2276 void *ptr;
2278 parm = lp_parm_struct(parm_name);
2279 if (!parm) {
2280 return False;
2283 if (isGlobal)
2284 ptr = parm->ptr;
2285 else
2286 ptr = ((char *)pService) +
2287 PTR_DIFF(parm->ptr, &sDefault);
2289 print_parameter(parm,
2290 ptr, f);
2291 fprintf(f, "\n");
2292 return True;
2295 /***************************************************************************
2296 Return info about the next service in a service. snum==-1 gives the globals.
2297 Return NULL when out of parameters.
2298 ***************************************************************************/
2300 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
2302 if (snum == -1) {
2303 /* do the globals */
2304 for (; parm_table[*i].label; (*i)++) {
2305 if (parm_table[*i].class == P_SEPARATOR)
2306 return &parm_table[(*i)++];
2308 if (!parm_table[*i].ptr
2309 || (*parm_table[*i].label == '-'))
2310 continue;
2312 if ((*i) > 0
2313 && (parm_table[*i].ptr ==
2314 parm_table[(*i) - 1].ptr))
2315 continue;
2317 return &parm_table[(*i)++];
2319 } else {
2320 service *pService = ServicePtrs[snum];
2322 for (; parm_table[*i].label; (*i)++) {
2323 if (parm_table[*i].class == P_SEPARATOR)
2324 return &parm_table[(*i)++];
2326 if (parm_table[*i].class == P_LOCAL &&
2327 parm_table[*i].ptr &&
2328 (*parm_table[*i].label != '-') &&
2329 ((*i) == 0 ||
2330 (parm_table[*i].ptr !=
2331 parm_table[(*i) - 1].ptr)))
2333 int pdiff =
2334 PTR_DIFF(parm_table[*i].ptr,
2335 &sDefault);
2337 if (allparameters ||
2338 !equal_parameter(parm_table[*i].type,
2339 ((char *)pService) +
2340 pdiff,
2341 ((char *)&sDefault) +
2342 pdiff))
2344 return &parm_table[(*i)++];
2350 return NULL;
2354 /***************************************************************************
2355 Return TRUE if the passed service number is within range.
2356 ***************************************************************************/
2358 BOOL lp_snum_ok(int iService)
2360 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
2363 /***************************************************************************
2364 Auto-load some home services.
2365 ***************************************************************************/
2367 static void lp_add_auto_services(const char *str)
2369 return;
2372 /***************************************************************************
2373 Have we loaded a services file yet?
2374 ***************************************************************************/
2376 BOOL lp_loaded(void)
2378 return (bLoaded);
2381 /***************************************************************************
2382 Unload unused services.
2383 ***************************************************************************/
2385 void lp_killunused(struct smbsrv_connection *smb, BOOL (*snumused) (struct smbsrv_connection *, int))
2387 int i;
2388 for (i = 0; i < iNumServices; i++) {
2389 if (!VALID(i))
2390 continue;
2392 if (!snumused || !snumused(smb, i)) {
2393 ServicePtrs[i]->valid = False;
2394 free_service(ServicePtrs[i]);
2399 /***************************************************************************
2400 Unload a service.
2401 ***************************************************************************/
2403 void lp_killservice(int iServiceIn)
2405 if (VALID(iServiceIn)) {
2406 ServicePtrs[iServiceIn]->valid = False;
2407 free_service(ServicePtrs[iServiceIn]);
2411 /***************************************************************************
2412 Load the services array from the services file. Return True on success,
2413 False on failure.
2414 ***************************************************************************/
2416 BOOL lp_load(void)
2418 pstring n2;
2419 BOOL bRetval;
2420 struct param_opt *data;
2422 bRetval = False;
2424 bInGlobalSection = True;
2426 if (Globals.param_opt != NULL) {
2427 struct param_opt *next;
2428 for (data=Globals.param_opt; data; data=next) {
2429 next = data->next;
2430 if (data->flags & FLAG_CMDLINE) continue;
2431 free(data->key);
2432 free(data->value);
2433 DLIST_REMOVE(Globals.param_opt, data);
2434 free(data);
2438 init_globals();
2440 pstrcpy(n2, lp_configfile());
2441 standard_sub_basic(n2,sizeof(n2));
2442 DEBUG(2, ("lp_load: refreshing parameters from %s\n", n2));
2444 add_to_file_list(lp_configfile(), n2);
2446 /* We get sections first, so have to start 'behind' to make up */
2447 iServiceIndex = -1;
2448 bRetval = pm_process(n2, do_section, do_parameter, NULL);
2450 /* finish up the last section */
2451 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
2452 if (bRetval)
2453 if (iServiceIndex >= 0)
2454 bRetval = service_ok(iServiceIndex);
2456 lp_add_auto_services(lp_auto_services());
2458 lp_add_hidden("IPC$", "IPC");
2459 lp_add_hidden("ADMIN$", "DISK");
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 If we are PDC then prefer us as DMB
2586 ************************************************************/
2588 BOOL lp_domain_logons(void)
2590 return (lp_server_role() == ROLE_DOMAIN_CONTROLLER);
2593 /*******************************************************************
2594 Remove a service.
2595 ********************************************************************/
2597 void lp_remove_service(int snum)
2599 ServicePtrs[snum]->valid = False;
2602 /*******************************************************************
2603 Copy a service.
2604 ********************************************************************/
2606 void lp_copy_service(int snum, const char *new_name)
2608 const char *oldname = lp_servicename(snum);
2609 do_section(new_name, NULL);
2610 if (snum >= 0) {
2611 snum = lp_servicenumber(new_name);
2612 if (snum >= 0)
2613 lp_do_parameter(snum, "copy", oldname);
2617 const char *lp_printername(int snum)
2619 const char *ret = _lp_printername(snum);
2620 if (ret == NULL || (ret != NULL && *ret == '\0'))
2621 ret = lp_const_servicename(snum);
2623 return ret;
2627 /*******************************************************************
2628 Return the max print jobs per queue.
2629 ********************************************************************/
2631 int lp_maxprintjobs(int snum)
2633 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
2634 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
2635 maxjobs = PRINT_MAX_JOBID - 1;
2637 return maxjobs;