r13121: Tag 4.0.0TP1
[Samba.git] / source / param / loadparm.c
blobae0e4b3bf0db31394ea9ec422aa4fb1d46a3752d
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/iconv.h"
62 #include "librpc/gen_ndr/ndr_svcctl.h"
63 #include "librpc/gen_ndr/ndr_samr.h"
64 #include "dlinklist.h"
65 #include "param/loadparm.h"
67 static BOOL bLoaded = False;
69 /* some helpful bits */
70 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && ServicePtrs[(i)]->valid)
71 #define VALID(i) ServicePtrs[i]->valid
73 static BOOL do_parameter(const char *, const char *, void *);
74 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...);
76 static BOOL defaults_saved = False;
79 struct param_opt {
80 struct param_opt *prev, *next;
81 char *key;
82 char *value;
83 int flags;
86 /*
87 * This structure describes global (ie., server-wide) parameters.
89 typedef struct
91 int server_role;
93 char **smb_ports;
94 char *dos_charset;
95 char *unix_charset;
96 char *ncalrpc_dir;
97 char *display_charset;
98 char *szLockDir;
99 char *szPidDir;
100 char *szSetupDir;
101 char *szServerString;
102 char *szAutoServices;
103 char *szPasswdChat;
104 char *szLogFile;
105 char *szConfigFile;
106 char *szSAM_URL;
107 char *szSPOOLSS_URL;
108 char *szWINS_CONFIG_URL;
109 char *szWINS_URL;
110 char *szPrivateDir;
111 char **jsInclude;
112 char **szPasswordServers;
113 char *szSocketOptions;
114 char *szRealm;
115 char **szWINSservers;
116 char **szInterfaces;
117 char *szSocketAddress;
118 char *szAnnounceVersion; /* This is initialised in init_globals */
119 char *szWorkgroup;
120 char *szNetbiosName;
121 char **szNetbiosAliases;
122 char *szNetbiosScope;
123 char *szDomainOtherSIDs;
124 char **szNameResolveOrder;
125 char *szPanicAction;
126 char **dcerpc_ep_servers;
127 char **server_services;
128 char *ntptr_providor;
129 char *szWinbindSeparator;
130 BOOL bWinbindSealedPipes;
131 char *swat_directory;
132 BOOL tls_enabled;
133 char *tls_keyfile;
134 char *tls_certfile;
135 char *tls_cafile;
136 char *tls_crlfile;
137 int max_mux;
138 int max_xmit;
139 int pwordlevel;
140 int maxprotocol;
141 int minprotocol;
142 int security;
143 char **AuthMethods;
144 BOOL paranoid_server_security;
145 int max_wins_ttl;
146 int min_wins_ttl;
147 int announce_as; /* This is initialised in init_globals */
148 int nbt_port;
149 int dgram_port;
150 int cldap_port;
151 int krb5_port;
152 int kpasswd_port;
153 int web_port;
154 char *socket_options;
155 BOOL bWINSsupport;
156 BOOL bWINSdnsProxy;
157 char *szWINSHook;
158 BOOL bLocalMaster;
159 BOOL bPreferredMaster;
160 BOOL bEncryptPasswords;
161 BOOL bNullPasswords;
162 BOOL bObeyPamRestrictions;
163 BOOL bLargeReadwrite;
164 BOOL bReadRaw;
165 BOOL bWriteRaw;
166 BOOL bTimeServer;
167 BOOL bBindInterfacesOnly;
168 BOOL bNTSmbSupport;
169 BOOL bNTStatusSupport;
170 BOOL bLanmanAuth;
171 BOOL bNTLMAuth;
172 BOOL bUseSpnego;
173 int server_signing;
174 int client_signing;
175 BOOL bClientPlaintextAuth;
176 BOOL bClientLanManAuth;
177 BOOL bClientNTLMv2Auth;
178 BOOL client_use_spnego_principal;
179 BOOL bHostMSDfs;
180 BOOL bUnicode;
181 BOOL bUnixExtensions;
182 BOOL bDisableNetbios;
183 BOOL bRpcBigEndian;
184 struct param_opt *param_opt;
186 global;
188 static global Globals;
191 * This structure describes a single service.
193 typedef struct
195 BOOL valid;
196 char *szService;
197 char *szPath;
198 char *szCopy;
199 char *szInclude;
200 char *szPrintername;
201 char **szHostsallow;
202 char **szHostsdeny;
203 char *comment;
204 char *volume;
205 char *fstype;
206 char **ntvfs_handler;
207 int iMaxPrintJobs;
208 int iMaxConnections;
209 int iCSCPolicy;
210 BOOL bAvailable;
211 BOOL bBrowseable;
212 BOOL bRead_only;
213 BOOL bPrint_ok;
214 BOOL bMap_system;
215 BOOL bMap_hidden;
216 BOOL bMap_archive;
217 BOOL bStrictLocking;
218 BOOL *copymap;
219 BOOL bMSDfsRoot;
220 BOOL bStrictSync;
221 BOOL bCIFileSystem;
222 struct param_opt *param_opt;
224 char dummy[3]; /* for alignment */
226 service;
229 /* This is a default service used to prime a services structure */
230 static service sDefault = {
231 True, /* valid */
232 NULL, /* szService */
233 NULL, /* szPath */
234 NULL, /* szCopy */
235 NULL, /* szInclude */
236 NULL, /* szPrintername */
237 NULL, /* szHostsallow */
238 NULL, /* szHostsdeny */
239 NULL, /* comment */
240 NULL, /* volume */
241 NULL, /* fstype */
242 NULL, /* ntvfs_handler */
243 1000, /* iMaxPrintJobs */
244 0, /* iMaxConnections */
245 0, /* iCSCPolicy */
246 True, /* bAvailable */
247 True, /* bBrowseable */
248 True, /* bRead_only */
249 False, /* bPrint_ok */
250 False, /* bMap_system */
251 False, /* bMap_hidden */
252 True, /* bMap_archive */
253 True, /* bStrictLocking */
254 NULL, /* copymap */
255 False, /* bMSDfsRoot */
256 False, /* bStrictSync */
257 False, /* bCIFileSystem */
258 NULL, /* Parametric options */
260 "" /* dummy */
263 /* local variables */
264 static service **ServicePtrs = NULL;
265 static int iNumServices = 0;
266 static int iServiceIndex = 0;
267 static BOOL bInGlobalSection = True;
268 static int default_server_announce;
270 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
272 /* prototypes for the special type handlers */
273 static BOOL handle_include(const char *pszParmValue, char **ptr);
274 static BOOL handle_copy(const char *pszParmValue, char **ptr);
276 static void set_default_server_announce_type(void);
278 static const struct enum_list enum_protocol[] = {
279 {PROTOCOL_NT1, "NT1"},
280 {PROTOCOL_LANMAN2, "LANMAN2"},
281 {PROTOCOL_LANMAN1, "LANMAN1"},
282 {PROTOCOL_CORE, "CORE"},
283 {PROTOCOL_COREPLUS, "COREPLUS"},
284 {PROTOCOL_COREPLUS, "CORE+"},
285 {-1, NULL}
288 static const struct enum_list enum_security[] = {
289 {SEC_SHARE, "SHARE"},
290 {SEC_USER, "USER"},
291 {-1, NULL}
294 /* Types of machine we can announce as. */
295 #define ANNOUNCE_AS_NT_SERVER 1
296 #define ANNOUNCE_AS_WIN95 2
297 #define ANNOUNCE_AS_WFW 3
298 #define ANNOUNCE_AS_NT_WORKSTATION 4
300 static const struct enum_list enum_announce_as[] = {
301 {ANNOUNCE_AS_NT_SERVER, "NT"},
302 {ANNOUNCE_AS_NT_SERVER, "NT Server"},
303 {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"},
304 {ANNOUNCE_AS_WIN95, "win95"},
305 {ANNOUNCE_AS_WFW, "WfW"},
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_BDC, "bdc"},
359 {ROLE_DOMAIN_PDC, "pdc"},
360 {-1, NULL}
364 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
366 * Note: We have a flag called FLAG_DEVELOPER but is not used at this time, it
367 * is implied in current control logic. This may change at some later time. A
368 * flag value of 0 means - show as development option only.
370 * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
371 * screen in SWAT. This is used to exclude parameters as well as to squash all
372 * parameters that have been duplicated by pseudonyms.
374 static struct parm_struct parm_table[] = {
375 {"Base Options", P_SEP, P_SEPARATOR},
377 {"server role", P_ENUM, P_GLOBAL, &Globals.server_role, NULL, enum_server_role, FLAG_BASIC},
379 {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
380 {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
381 {"ncalrpc dir", P_STRING, P_GLOBAL, &Globals.ncalrpc_dir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
382 {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
383 {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
384 {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
385 {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE},
386 {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkgroup, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
387 {"realm", P_STRING, P_GLOBAL, &Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
388 {"netbios name", P_USTRING, P_GLOBAL, &Globals.szNetbiosName, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
389 {"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
390 {"netbios scope", P_USTRING, P_GLOBAL, &Globals.szNetbiosScope, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
391 {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
392 {"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
393 {"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
394 {"ntvfs handler", P_LIST, P_LOCAL, &sDefault.ntvfs_handler, NULL, NULL, FLAG_ADVANCED},
395 {"ntptr providor", P_STRING, P_GLOBAL, &Globals.ntptr_providor, NULL, NULL, FLAG_ADVANCED},
396 {"dcerpc endpoint servers", P_LIST, P_GLOBAL, &Globals.dcerpc_ep_servers, NULL, NULL, FLAG_ADVANCED},
397 {"server services", P_LIST, P_GLOBAL, &Globals.server_services, NULL, NULL, FLAG_ADVANCED},
399 {"Security Options", P_SEP, P_SEPARATOR},
401 {"security", P_ENUM, P_GLOBAL, &Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
402 {"auth methods", P_LIST, P_GLOBAL, &Globals.AuthMethods, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
403 {"encrypt passwords", P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
404 {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
405 {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
406 {"password server", P_LIST, P_GLOBAL, &Globals.szPasswordServers, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
407 {"sam database", P_STRING, P_GLOBAL, &Globals.szSAM_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
408 {"spoolss database", P_STRING, P_GLOBAL, &Globals.szSPOOLSS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
409 {"wins config database", P_STRING, P_GLOBAL, &Globals.szWINS_CONFIG_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
410 {"wins database", P_STRING, P_GLOBAL, &Globals.szWINS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
411 {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
412 {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
413 {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
414 {"lanman auth", P_BOOL, P_GLOBAL, &Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
415 {"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
416 {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
417 {"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
418 {"client plaintext auth", P_BOOL, P_GLOBAL, &Globals.bClientPlaintextAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
419 {"client use spnego principal", P_BOOL, P_GLOBAL, &Globals.client_use_spnego_principal, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
421 {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE},
423 {"hosts allow", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
424 {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
426 {"Logging Options", P_SEP, P_SEPARATOR},
428 {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
429 {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_HIDE},
430 {"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
432 {"Protocol Options", P_SEP, P_SEPARATOR},
434 {"smb ports", P_LIST, P_GLOBAL, &Globals.smb_ports, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
435 {"nbt port", P_INTEGER, P_GLOBAL, &Globals.nbt_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
436 {"dgram port", P_INTEGER, P_GLOBAL, &Globals.dgram_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
437 {"cldap port", P_INTEGER, P_GLOBAL, &Globals.cldap_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
438 {"krb5 port", P_INTEGER, P_GLOBAL, &Globals.krb5_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
439 {"kpasswd port", P_INTEGER, P_GLOBAL, &Globals.kpasswd_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
440 {"web port", P_INTEGER, P_GLOBAL, &Globals.web_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
441 {"tls enabled", P_BOOL, P_GLOBAL, &Globals.tls_enabled, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
442 {"tls keyfile", P_STRING, P_GLOBAL, &Globals.tls_keyfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
443 {"tls certfile", P_STRING, P_GLOBAL, &Globals.tls_certfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
444 {"tls cafile", P_STRING, P_GLOBAL, &Globals.tls_cafile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
445 {"tls crlfile", P_STRING, P_GLOBAL, &Globals.tls_crlfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
446 {"swat directory", P_STRING, P_GLOBAL, &Globals.swat_directory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
447 {"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, FLAG_DEVELOPER},
448 {"max protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
449 {"min protocol", P_ENUM, P_GLOBAL, &Globals.minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
450 {"unicode", P_BOOL, P_GLOBAL, &Globals.bUnicode, NULL, NULL, FLAG_DEVELOPER},
451 {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL, NULL, FLAG_DEVELOPER},
452 {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL, NULL, FLAG_DEVELOPER},
453 {"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
455 {"nt status support", P_BOOL, P_GLOBAL, &Globals.bNTStatusSupport, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
457 {"announce version", P_STRING, P_GLOBAL, &Globals.szAnnounceVersion, NULL, NULL, FLAG_DEVELOPER},
458 {"announce as", P_ENUM, P_GLOBAL, &Globals.announce_as, NULL, enum_announce_as, FLAG_DEVELOPER},
459 {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
460 {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
462 {"name resolve order", P_LIST, P_GLOBAL, &Globals.szNameResolveOrder, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
463 {"max wins ttl", P_INTEGER, P_GLOBAL, &Globals.max_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
464 {"min wins ttl", P_INTEGER, P_GLOBAL, &Globals.min_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
465 {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
466 {"unix extensions", P_BOOL, P_GLOBAL, &Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
467 {"use spnego", P_BOOL, P_GLOBAL, &Globals.bUseSpnego, NULL, NULL, FLAG_DEVELOPER},
468 {"server signing", P_ENUM, P_GLOBAL, &Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
469 {"client signing", P_ENUM, P_GLOBAL, &Globals.client_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
470 {"rpc big endian", P_BOOL, P_GLOBAL, &Globals.bRpcBigEndian, NULL, NULL, FLAG_DEVELOPER},
472 {"Tuning Options", P_SEP, P_SEPARATOR},
474 {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL, NULL, FLAG_SHARE},
475 {"paranoid server security", P_BOOL, P_GLOBAL, &Globals.paranoid_server_security, NULL, NULL, FLAG_DEVELOPER},
476 {"socket options", P_STRING, P_GLOBAL, &Globals.socket_options, NULL, NULL, FLAG_DEVELOPER},
478 {"strict sync", P_BOOL, P_LOCAL, &sDefault.bStrictSync, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
479 {"case insensitive filesystem", P_BOOL, P_LOCAL, &sDefault.bCIFileSystem, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
481 {"Printing Options", P_SEP, P_SEPARATOR},
483 {"max print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxPrintJobs, NULL, NULL, FLAG_PRINT},
484 {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_PRINT},
485 {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_HIDE},
487 {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_PRINT},
488 {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_HIDE},
490 {"Filename Handling", P_SEP, P_SEPARATOR},
492 {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
493 {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
494 {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
496 {"Domain Options", P_SEP, P_SEPARATOR},
498 {"Logon Options", P_SEP, P_SEPARATOR},
501 {"Browse Options", P_SEP, P_SEPARATOR},
503 {"preferred master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
504 {"prefered master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_HIDE},
505 {"local master", P_BOOL, P_GLOBAL, &Globals.bLocalMaster, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
506 {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
507 {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_HIDE},
509 {"WINS Options", P_SEP, P_SEPARATOR},
511 {"wins server", P_LIST, P_GLOBAL, &Globals.szWINSservers, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
512 {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
513 {"dns proxy", P_BOOL, P_GLOBAL, &Globals.bWINSdnsProxy, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
514 {"wins hook", P_STRING, P_GLOBAL, &Globals.szWINSHook, NULL, NULL, FLAG_ADVANCED},
516 {"Locking Options", P_SEP, P_SEPARATOR},
518 {"csc policy", P_ENUM, P_LOCAL, &sDefault.iCSCPolicy, NULL, enum_csc_policy, FLAG_SHARE | FLAG_GLOBAL},
520 {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
522 {"Miscellaneous Options", P_SEP, P_SEPARATOR},
524 {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE},
525 {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
526 {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
527 {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_HIDE},
528 {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
529 {"pid directory", P_STRING, P_GLOBAL, &Globals.szPidDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
530 {"js include", P_LIST, P_GLOBAL, &Globals.jsInclude, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
531 {"setup directory", P_STRING, P_GLOBAL, &Globals.szSetupDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
533 {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL, NULL, FLAG_DEVELOPER},
534 {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL, NULL, FLAG_HIDE},
536 {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy, NULL, FLAG_HIDE},
537 {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include, NULL, FLAG_HIDE},
539 {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
540 {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_SHARE },
541 {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_SHARE},
543 {"panic action", P_STRING, P_GLOBAL, &Globals.szPanicAction, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
545 {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_SHARE},
546 {"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
547 {"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
548 {"winbind sealed pipes", P_BOOL, P_GLOBAL, &Globals.bWinbindSealedPipes, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
550 {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
555 return the parameter table
557 struct parm_struct *lp_parm_table(void)
559 return parm_table;
562 /***************************************************************************
563 Initialise the global parameter structure.
564 ***************************************************************************/
565 static void init_globals(void)
567 int i;
568 char *myname;
570 DEBUG(3, ("Initialising global parameters\n"));
572 for (i = 0; parm_table[i].label; i++) {
573 if ((parm_table[i].type == P_STRING ||
574 parm_table[i].type == P_USTRING) &&
575 parm_table[i].ptr &&
576 !(parm_table[i].flags & FLAG_CMDLINE)) {
577 string_set(parm_table[i].ptr, "");
581 do_parameter("config file", dyn_CONFIGFILE, NULL);
583 do_parameter("server role", "standalone", NULL);
585 /* options that can be set on the command line must be initialised via
586 the slower do_parameter() to ensure that FLAG_CMDLINE is obeyed */
587 #ifdef TCP_NODELAY
588 do_parameter("socket options", "TCP_NODELAY", NULL);
589 #endif
590 do_parameter("workgroup", DEFAULT_WORKGROUP, NULL);
591 myname = get_myname();
592 do_parameter("netbios name", myname, NULL);
593 SAFE_FREE(myname);
594 do_parameter("max protocol", "NT1", NULL);
595 do_parameter("name resolve order", "lmhosts wins host bcast", NULL);
597 do_parameter("fstype", FSTYPE_STRING, NULL);
598 do_parameter("ntvfs handler", "unixuid default", NULL);
599 do_parameter("max connections", "-1", NULL);
601 do_parameter("dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup", NULL);
602 do_parameter("server services", "smb rpc nbt wrepl ldap cldap web kdc", NULL);
603 do_parameter("ntptr providor", "simple_ldb", NULL);
604 do_parameter("auth methods", "anonymous sam_ignoredomain", NULL);
605 do_parameter("private dir", dyn_PRIVATE_DIR, NULL);
606 do_parameter("sam database", "sam.ldb", NULL);
607 do_parameter("spoolss database", "spoolss.ldb", NULL);
608 do_parameter("wins config database", "wins_config.ldb", NULL);
609 do_parameter("wins database", "wins.ldb", NULL);
610 do_parameter("registry:HKEY_LOCAL_MACHINE", "hklm.ldb", NULL);
612 /* This hive should be dynamically generated by Samba using
613 data from the sam, but for the moment leave it in a tdb to
614 keep regedt32 from popping up an annoying dialog. */
615 do_parameter("registry:HKEY_USERS", "hku.ldb", NULL);
617 /* using UTF8 by default allows us to support all chars */
618 do_parameter("unix charset", "UTF8", NULL);
620 /* Use codepage 850 as a default for the dos character set */
621 do_parameter("dos charset", "CP850", NULL);
624 * Allow the default PASSWD_CHAT to be overridden in local.h.
626 do_parameter("passwd chat", DEFAULT_PASSWD_CHAT, NULL);
628 do_parameter("pid directory", dyn_PIDDIR, NULL);
629 do_parameter("lock dir", dyn_LOCKDIR, NULL);
630 do_parameter("ncalrpc dir", dyn_NCALRPCDIR, NULL);
632 do_parameter("socket address", "0.0.0.0", NULL);
633 do_parameter_var("server string", "Samba %s", SAMBA_VERSION_STRING);
635 do_parameter_var("announce version", "%d.%d",
636 DEFAULT_MAJOR_VERSION,
637 DEFAULT_MINOR_VERSION);
639 do_parameter("password server", "*", NULL);
641 do_parameter("max mux", "50", NULL);
642 do_parameter("max xmit", "12288", NULL);
643 do_parameter("password level", "0", NULL);
644 do_parameter("LargeReadwrite", "True", NULL);
645 do_parameter("minprotocol", "CORE", NULL);
646 do_parameter("security", "USER", NULL);
647 do_parameter("paranoid server security", "True", NULL);
648 do_parameter("EncryptPasswords", "True", NULL);
649 do_parameter("ReadRaw", "True", NULL);
650 do_parameter("WriteRaw", "True", NULL);
651 do_parameter("NullPasswords", "False", NULL);
652 do_parameter("ObeyPamRestrictions", "False", NULL);
653 do_parameter("announce as", "NT SERVER", NULL);
655 do_parameter("TimeServer", "False", NULL);
656 do_parameter("BindInterfacesOnly", "False", NULL);
657 do_parameter("Unicode", "True", NULL);
658 do_parameter("ClientLanManAuth", "True", NULL);
659 do_parameter("LanmanAuth", "True", NULL);
660 do_parameter("NTLMAuth", "True", NULL);
661 do_parameter("client use spnego principal", "False", NULL);
663 do_parameter("UnixExtensions", "False", NULL);
665 do_parameter("PreferredMaster", "Auto", NULL);
666 do_parameter("LocalMaster", "True", NULL);
668 do_parameter("wins support", "False", NULL);
669 do_parameter("dns proxy", "True", NULL);
671 do_parameter("winbind separator", "\\", NULL);
672 do_parameter("winbind sealed pipes", "True", NULL);
674 do_parameter("client signing", "Yes", NULL);
675 do_parameter("server signing", "auto", NULL);
677 do_parameter("use spnego", "True", NULL);
679 do_parameter("smb ports", SMB_PORTS, NULL);
680 do_parameter("nbt port", "137", NULL);
681 do_parameter("dgram port", "138", NULL);
682 do_parameter("cldap port", "389", NULL);
683 do_parameter("krb5 port", "88", NULL);
684 do_parameter("kpasswd port", "464", NULL);
685 do_parameter("web port", "901", NULL);
686 do_parameter("swat directory", dyn_SWATDIR, NULL);
688 do_parameter("nt status support", "True", NULL);
690 do_parameter("max wins ttl", "518400", NULL); /* 6 days */
691 do_parameter("min wins ttl", "10", NULL);
693 do_parameter("tls enabled", "True", NULL);
694 do_parameter("tls keyfile", "tls/key.pem", NULL);
695 do_parameter("tls certfile", "tls/cert.pem", NULL);
696 do_parameter("tls cafile", "tls/ca.pem", NULL);
697 do_parameter_var("js include", "%s/js", dyn_LIBDIR);
698 do_parameter_var("setup directory", "%s/setup", dyn_LIBDIR);
700 for (i = 0; parm_table[i].label; i++) {
701 if (!(parm_table[i].flags & FLAG_CMDLINE)) {
702 parm_table[i].flags |= FLAG_DEFAULT;
707 static TALLOC_CTX *lp_talloc;
709 /******************************************************************* a
710 Free up temporary memory - called from the main loop.
711 ********************************************************************/
713 void lp_talloc_free(void)
715 if (!lp_talloc)
716 return;
717 talloc_free(lp_talloc);
718 lp_talloc = NULL;
721 /*******************************************************************
722 Convenience routine to grab string parameters into temporary memory
723 and run standard_sub_basic on them. The buffers can be written to by
724 callers without affecting the source string.
725 ********************************************************************/
727 static const char *lp_string(const char *s)
729 #if 0 /* until REWRITE done to make thread-safe */
730 size_t len = s ? strlen(s) : 0;
731 char *ret;
732 #endif
734 /* The follow debug is useful for tracking down memory problems
735 especially if you have an inner loop that is calling a lp_*()
736 function that returns a string. Perhaps this debug should be
737 present all the time? */
739 #if 0
740 DEBUG(10, ("lp_string(%s)\n", s));
741 #endif
743 #if 0 /* until REWRITE done to make thread-safe */
744 if (!lp_talloc)
745 lp_talloc = talloc_init("lp_talloc");
747 ret = talloc_array(lp_talloc, char, len + 100); /* leave room for substitution */
749 if (!ret)
750 return NULL;
752 if (!s)
753 *ret = 0;
754 else
755 StrnCpy(ret, s, len);
757 if (trim_string(ret, "\"", "\"")) {
758 if (strchr(ret,'"') != NULL)
759 StrnCpy(ret, s, len);
762 standard_sub_basic(ret,len+100);
763 return (ret);
764 #endif
765 return s;
769 In this section all the functions that are used to access the
770 parameters from the rest of the program are defined
773 #define FN_GLOBAL_STRING(fn_name,ptr) \
774 const char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
775 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
776 const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");}
777 #define FN_GLOBAL_LIST(fn_name,ptr) \
778 const char **fn_name(void) {return(*(const char ***)(ptr));}
779 #define FN_GLOBAL_BOOL(fn_name,ptr) \
780 BOOL fn_name(void) {return(*(BOOL *)(ptr));}
781 #define FN_GLOBAL_CHAR(fn_name,ptr) \
782 char fn_name(void) {return(*(char *)(ptr));}
783 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
784 int fn_name(void) {return(*(int *)(ptr));}
786 #define FN_LOCAL_STRING(fn_name,val) \
787 const char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
788 #define FN_LOCAL_CONST_STRING(fn_name,val) \
789 const char *fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
790 #define FN_LOCAL_LIST(fn_name,val) \
791 const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
792 #define FN_LOCAL_BOOL(fn_name,val) \
793 BOOL fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
794 #define FN_LOCAL_CHAR(fn_name,val) \
795 char fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
796 #define FN_LOCAL_INTEGER(fn_name,val) \
797 int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
799 FN_GLOBAL_INTEGER(lp_server_role, &Globals.server_role)
800 FN_GLOBAL_LIST(lp_smb_ports, &Globals.smb_ports)
801 FN_GLOBAL_INTEGER(lp_nbt_port, &Globals.nbt_port)
802 FN_GLOBAL_INTEGER(lp_dgram_port, &Globals.dgram_port)
803 FN_GLOBAL_INTEGER(lp_cldap_port, &Globals.cldap_port)
804 FN_GLOBAL_INTEGER(lp_krb5_port, &Globals.krb5_port)
805 FN_GLOBAL_INTEGER(lp_kpasswd_port, &Globals.kpasswd_port)
806 FN_GLOBAL_INTEGER(lp_web_port, &Globals.web_port)
807 FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
808 FN_GLOBAL_STRING(lp_swat_directory, &Globals.swat_directory)
809 FN_GLOBAL_BOOL(lp_tls_enabled, &Globals.tls_enabled)
810 FN_GLOBAL_STRING(lp_tls_keyfile, &Globals.tls_keyfile)
811 FN_GLOBAL_STRING(lp_tls_certfile, &Globals.tls_certfile)
812 FN_GLOBAL_STRING(lp_tls_cafile, &Globals.tls_cafile)
813 FN_GLOBAL_STRING(lp_tls_crlfile, &Globals.tls_crlfile)
814 FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
815 FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset)
816 FN_GLOBAL_STRING(lp_logfile, &Globals.szLogFile)
817 FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
818 FN_GLOBAL_STRING(lp_sam_url, &Globals.szSAM_URL)
819 FN_GLOBAL_STRING(lp_spoolss_url, &Globals.szSPOOLSS_URL)
820 FN_GLOBAL_STRING(lp_wins_config_url, &Globals.szWINS_CONFIG_URL)
821 FN_GLOBAL_STRING(lp_wins_url, &Globals.szWINS_URL)
822 FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
823 FN_GLOBAL_BOOL(lp_winbind_sealed_pipes, &Globals.bWinbindSealedPipes)
824 FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
825 FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
826 FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
827 FN_GLOBAL_STRING(lp_setupdir, &Globals.szSetupDir)
828 FN_GLOBAL_STRING(lp_ncalrpc_dir, &Globals.ncalrpc_dir)
829 FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
830 FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, &Globals.dcerpc_ep_servers)
831 FN_GLOBAL_LIST(lp_server_services, &Globals.server_services)
832 FN_GLOBAL_STRING(lp_ntptr_providor, &Globals.ntptr_providor)
833 FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
834 FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
835 FN_GLOBAL_LIST(lp_passwordserver, &Globals.szPasswordServers)
836 FN_GLOBAL_LIST(lp_name_resolve_order, &Globals.szNameResolveOrder)
837 FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
838 FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
839 FN_GLOBAL_STRING(lp_workgroup, &Globals.szWorkgroup)
840 FN_GLOBAL_STRING(lp_netbios_name, &Globals.szNetbiosName)
841 FN_GLOBAL_STRING(lp_netbios_scope, &Globals.szNetbiosScope)
842 FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
843 FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
844 FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
845 FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
846 FN_GLOBAL_STRING(lp_panic_action, &Globals.szPanicAction)
848 FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
849 FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
850 FN_GLOBAL_BOOL(lp_wins_dns_proxy, &Globals.bWINSdnsProxy)
851 FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
852 FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
853 FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
854 FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
855 FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw)
856 FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords)
857 FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions)
858 FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
859 static FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
860 FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
861 FN_GLOBAL_BOOL(lp_unicode, &Globals.bUnicode)
862 FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
863 FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
864 FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
865 FN_GLOBAL_BOOL(lp_client_plaintext_auth, &Globals.bClientPlaintextAuth)
866 FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
867 FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
868 FN_GLOBAL_BOOL(lp_client_use_spnego_principal, &Globals.client_use_spnego_principal)
869 FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
870 FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions)
871 FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
872 FN_GLOBAL_BOOL(lp_rpc_big_endian, &Globals.bRpcBigEndian)
873 FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
874 FN_GLOBAL_INTEGER(lp_min_wins_ttl, &Globals.min_wins_ttl)
875 FN_GLOBAL_INTEGER(lp_maxmux, &Globals.max_mux)
876 FN_GLOBAL_INTEGER(lp_max_xmit, &Globals.max_xmit)
877 FN_GLOBAL_INTEGER(lp_passwordlevel, &Globals.pwordlevel)
878 FN_GLOBAL_INTEGER(lp_maxprotocol, &Globals.maxprotocol)
879 FN_GLOBAL_INTEGER(lp_minprotocol, &Globals.minprotocol)
880 FN_GLOBAL_INTEGER(lp_security, &Globals.security)
881 FN_GLOBAL_LIST(lp_auth_methods, &Globals.AuthMethods)
882 FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security)
883 static FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as)
884 FN_GLOBAL_LIST(lp_js_include, &Globals.jsInclude)
887 FN_LOCAL_STRING(lp_servicename, szService)
888 FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
889 FN_LOCAL_STRING(lp_pathname, szPath)
890 static FN_LOCAL_STRING(_lp_printername, szPrintername)
891 FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
892 FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
893 FN_LOCAL_STRING(lp_comment, comment)
894 FN_LOCAL_STRING(lp_fstype, fstype)
895 static FN_LOCAL_STRING(lp_volume, volume)
896 FN_LOCAL_LIST(lp_ntvfs_handler, ntvfs_handler)
897 FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
898 FN_LOCAL_BOOL(lp_browseable, bBrowseable)
899 FN_LOCAL_BOOL(lp_readonly, bRead_only)
900 FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
901 FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
902 FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
903 FN_LOCAL_BOOL(lp_strict_locking, bStrictLocking)
904 FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
905 FN_LOCAL_BOOL(lp_ci_filesystem, bCIFileSystem)
906 FN_LOCAL_BOOL(lp_map_system, bMap_system)
907 FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
908 FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
909 FN_GLOBAL_INTEGER(lp_server_signing, &Globals.server_signing)
910 FN_GLOBAL_INTEGER(lp_client_signing, &Globals.client_signing)
912 /* local prototypes */
914 static int map_parameter(const char *pszParmName);
915 static BOOL set_boolean(BOOL *pb, const char *pszParmValue);
916 static int getservicebyname(const char *pszServiceName,
917 service * pserviceDest);
918 static void copy_service(service * pserviceDest,
919 service * pserviceSource, BOOL *pcopymapDest);
920 static BOOL service_ok(int iService);
921 static BOOL do_section(const char *pszSectionName, void *);
922 static void init_copymap(service * pservice);
924 /* This is a helper function for parametrical options support. */
925 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
926 /* Actual parametrical functions are quite simple */
927 const char *lp_get_parametric(int lookup_service, const char *type, const char *option)
929 char *vfskey;
930 struct param_opt *data;
932 if (lookup_service >= iNumServices) return NULL;
934 data = (lookup_service < 0) ?
935 Globals.param_opt : ServicePtrs[lookup_service]->param_opt;
937 asprintf(&vfskey, "%s:%s", type, option);
938 strlower(vfskey);
940 while (data) {
941 if (strcmp(data->key, vfskey) == 0) {
942 free(vfskey);
943 return data->value;
945 data = data->next;
948 if (lookup_service >= 0) {
949 /* Try to fetch the same option but from globals */
950 /* but only if we are not already working with Globals */
951 data = Globals.param_opt;
952 while (data) {
953 if (strcmp(data->key, vfskey) == 0) {
954 free(vfskey);
955 return data->value;
957 data = data->next;
961 free(vfskey);
963 return NULL;
967 /*******************************************************************
968 convenience routine to return int parameters.
969 ********************************************************************/
970 static int lp_int(const char *s)
973 if (!s) {
974 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
975 return (-1);
978 return strtol(s, NULL, 0);
981 /*******************************************************************
982 convenience routine to return unsigned long parameters.
983 ********************************************************************/
984 static int lp_ulong(const char *s)
987 if (!s) {
988 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
989 return (-1);
992 return strtoul(s, NULL, 0);
995 /*******************************************************************
996 convenience routine to return boolean parameters.
997 ********************************************************************/
998 static BOOL lp_bool(const char *s)
1000 BOOL ret = False;
1002 if (!s) {
1003 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
1004 return False;
1007 if (!set_boolean(&ret,s)) {
1008 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1009 return False;
1012 return ret;
1016 /* Return parametric option from a given service. Type is a part of option before ':' */
1017 /* Parametric option has following syntax: 'Type: option = value' */
1018 /* Returned value is allocated in 'lp_talloc' context */
1020 const char *lp_parm_string(int lookup_service, const char *type, const char *option)
1022 const char *value = lp_get_parametric(lookup_service, type, option);
1024 if (value)
1025 return lp_string(value);
1027 return NULL;
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_list(int lookup_service, const char *type, const char *option,
1035 const char *separator)
1037 const char *value = lp_get_parametric(lookup_service, type, option);
1039 if (value)
1040 return str_list_make(talloc_autofree_context(), value, separator);
1042 return NULL;
1045 /* Return parametric option from a given service. Type is a part of option before ':' */
1046 /* Parametric option has following syntax: 'Type: option = value' */
1048 int lp_parm_int(int lookup_service, const char *type, const char *option, int default_v)
1050 const char *value = lp_get_parametric(lookup_service, type, option);
1052 if (value)
1053 return lp_int(value);
1055 return default_v;
1058 /* Return parametric option from a given service. Type is a part of option before ':' */
1059 /* Parametric option has following syntax: 'Type: option = value' */
1061 unsigned long lp_parm_ulong(int lookup_service, const char *type, const char *option, unsigned long default_v)
1063 const char *value = lp_get_parametric(lookup_service, type, option);
1065 if (value)
1066 return lp_ulong(value);
1068 return default_v;
1071 /* Return parametric option from a given service. Type is a part of option before ':' */
1072 /* Parametric option has following syntax: 'Type: option = value' */
1074 BOOL lp_parm_bool(int lookup_service, const char *type, const char *option, BOOL default_v)
1076 const char *value = lp_get_parametric(lookup_service, type, option);
1078 if (value)
1079 return lp_bool(value);
1081 return default_v;
1085 /***************************************************************************
1086 Initialise a service to the defaults.
1087 ***************************************************************************/
1089 static void init_service(service * pservice)
1091 memset((char *)pservice, '\0', sizeof(service));
1092 copy_service(pservice, &sDefault, NULL);
1095 /***************************************************************************
1096 Free the dynamically allocated parts of a service struct.
1097 ***************************************************************************/
1099 static void free_service(service *pservice)
1101 int i;
1102 struct param_opt *data, *pdata;
1103 if (!pservice)
1104 return;
1106 if (pservice->szService)
1107 DEBUG(5, ("free_service: Freeing service %s\n",
1108 pservice->szService));
1110 string_free(&pservice->szService);
1111 SAFE_FREE(pservice->copymap);
1113 for (i = 0; parm_table[i].label; i++) {
1114 if ((parm_table[i].type == P_STRING ||
1115 parm_table[i].type == P_USTRING) &&
1116 parm_table[i].class == P_LOCAL) {
1117 string_free((char **)
1118 (((char *)pservice) +
1119 PTR_DIFF(parm_table[i].ptr, &sDefault)));
1120 } else if (parm_table[i].type == P_LIST &&
1121 parm_table[i].class == P_LOCAL) {
1122 char ***listp = (char ***)(((char *)pservice) +
1123 PTR_DIFF(parm_table[i].ptr, &sDefault));
1124 talloc_free(*listp);
1125 *listp = NULL;
1129 DEBUG(5,("Freeing parametrics:\n"));
1130 data = pservice->param_opt;
1131 while (data) {
1132 DEBUG(5,("[%s = %s]\n", data->key, data->value));
1133 string_free(&data->key);
1134 string_free(&data->value);
1135 pdata = data->next;
1136 SAFE_FREE(data);
1137 data = pdata;
1140 ZERO_STRUCTP(pservice);
1143 /***************************************************************************
1144 Add a new service to the services array initialising it with the given
1145 service.
1146 ***************************************************************************/
1148 static int add_a_service(const service *pservice, const char *name)
1150 int i;
1151 service tservice;
1152 int num_to_alloc = iNumServices + 1;
1153 struct param_opt *data, *pdata;
1155 tservice = *pservice;
1157 /* it might already exist */
1158 if (name) {
1159 i = getservicebyname(name, NULL);
1160 if (i >= 0) {
1161 /* Clean all parametric options for service */
1162 /* They will be added during parsing again */
1163 data = ServicePtrs[i]->param_opt;
1164 while (data) {
1165 string_free(&data->key);
1166 string_free(&data->value);
1167 pdata = data->next;
1168 SAFE_FREE(data);
1169 data = pdata;
1171 ServicePtrs[i]->param_opt = NULL;
1172 return (i);
1176 /* find an invalid one */
1177 for (i = 0; i < iNumServices; i++)
1178 if (!ServicePtrs[i]->valid)
1179 break;
1181 /* if not, then create one */
1182 if (i == iNumServices) {
1183 service **tsp;
1185 tsp = realloc_p(ServicePtrs, service *, num_to_alloc);
1187 if (!tsp) {
1188 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1189 return (-1);
1191 else {
1192 ServicePtrs = tsp;
1193 ServicePtrs[iNumServices] = malloc_p(service);
1195 if (!ServicePtrs[iNumServices]) {
1196 DEBUG(0,("add_a_service: out of memory!\n"));
1197 return (-1);
1200 iNumServices++;
1201 } else
1202 free_service(ServicePtrs[i]);
1204 ServicePtrs[i]->valid = True;
1206 init_service(ServicePtrs[i]);
1207 copy_service(ServicePtrs[i], &tservice, NULL);
1208 if (name)
1209 string_set(&ServicePtrs[i]->szService, name);
1210 return (i);
1213 /***************************************************************************
1214 Add a new home service, with the specified home directory, defaults coming
1215 from service ifrom.
1216 ***************************************************************************/
1218 BOOL lp_add_home(const char *pszHomename, int iDefaultService,
1219 const char *user, const char *pszHomedir)
1221 int i;
1222 pstring newHomedir;
1224 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1226 if (i < 0)
1227 return (False);
1229 if (!(*(ServicePtrs[iDefaultService]->szPath))
1230 || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(-1))) {
1231 pstrcpy(newHomedir, pszHomedir);
1232 } else {
1233 pstrcpy(newHomedir, lp_pathname(iDefaultService));
1234 string_sub(newHomedir,"%H", pszHomedir, sizeof(newHomedir));
1237 string_set(&ServicePtrs[i]->szPath, newHomedir);
1239 if (!(*(ServicePtrs[i]->comment))) {
1240 pstring comment;
1241 slprintf(comment, sizeof(comment) - 1,
1242 "Home directory of %s", user);
1243 string_set(&ServicePtrs[i]->comment, comment);
1245 ServicePtrs[i]->bAvailable = sDefault.bAvailable;
1246 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1248 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1249 user, newHomedir));
1251 return (True);
1254 /***************************************************************************
1255 Add a new service, based on an old one.
1256 ***************************************************************************/
1258 int lp_add_service(const char *pszService, int iDefaultService)
1260 return (add_a_service(ServicePtrs[iDefaultService], pszService));
1263 /***************************************************************************
1264 Add the IPC service.
1265 ***************************************************************************/
1267 static BOOL lp_add_hidden(const char *name, const char *fstype)
1269 pstring comment;
1270 int i = add_a_service(&sDefault, name);
1272 if (i < 0)
1273 return (False);
1275 slprintf(comment, sizeof(comment) - 1,
1276 "%s Service (%s)", fstype, Globals.szServerString);
1278 string_set(&ServicePtrs[i]->szPath, tmpdir());
1279 string_set(&ServicePtrs[i]->comment, comment);
1280 string_set(&ServicePtrs[i]->fstype, fstype);
1281 ServicePtrs[i]->iMaxConnections = -1;
1282 ServicePtrs[i]->bAvailable = True;
1283 ServicePtrs[i]->bRead_only = True;
1284 ServicePtrs[i]->bPrint_ok = False;
1285 ServicePtrs[i]->bBrowseable = False;
1287 if (strcasecmp(fstype, "IPC") == 0) {
1288 lp_do_parameter(i, "ntvfs handler", "default");
1291 DEBUG(3, ("adding hidden service %s\n", name));
1293 return (True);
1296 /***************************************************************************
1297 Add a new printer service, with defaults coming from service iFrom.
1298 ***************************************************************************/
1300 BOOL lp_add_printer(const char *pszPrintername, int iDefaultService)
1302 const char *comment = "From Printcap";
1303 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1305 if (i < 0)
1306 return (False);
1308 /* note that we do NOT default the availability flag to True - */
1309 /* we take it from the default service passed. This allows all */
1310 /* dynamic printers to be disabled by disabling the [printers] */
1311 /* entry (if/when the 'available' keyword is implemented!). */
1313 /* the printer name is set to the service name. */
1314 string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1315 string_set(&ServicePtrs[i]->comment, comment);
1316 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1317 /* Printers cannot be read_only. */
1318 ServicePtrs[i]->bRead_only = False;
1319 /* Printer services must be printable. */
1320 ServicePtrs[i]->bPrint_ok = True;
1322 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1324 update_server_announce_as_printserver();
1326 return (True);
1329 /***************************************************************************
1330 Map a parameter's string representation to something we can use.
1331 Returns False if the parameter string is not recognised, else TRUE.
1332 ***************************************************************************/
1334 static int map_parameter(const char *pszParmName)
1336 int iIndex;
1338 if (*pszParmName == '-')
1339 return (-1);
1341 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1342 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1343 return (iIndex);
1345 /* Warn only if it isn't parametric option */
1346 if (strchr(pszParmName, ':') == NULL)
1347 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1348 /* We do return 'fail' for parametric options as well because they are
1349 stored in different storage
1351 return (-1);
1356 return the parameter structure for a parameter
1358 struct parm_struct *lp_parm_struct(const char *name)
1360 int parmnum = map_parameter(name);
1361 if (parmnum == -1) return NULL;
1362 return &parm_table[parmnum];
1366 return the parameter pointer for a parameter
1368 void *lp_parm_ptr(int snum, struct parm_struct *parm)
1370 if (snum == -1) {
1371 return parm->ptr;
1373 return ((char *)ServicePtrs[snum]) + PTR_DIFF(parm->ptr, &sDefault);
1376 /***************************************************************************
1377 Set a boolean variable from the text value stored in the passed string.
1378 Returns True in success, False if the passed string does not correctly
1379 represent a boolean.
1380 ***************************************************************************/
1382 static BOOL set_boolean(BOOL *pb, const char *pszParmValue)
1384 BOOL bRetval;
1386 bRetval = True;
1387 if (strwicmp(pszParmValue, "yes") == 0 ||
1388 strwicmp(pszParmValue, "true") == 0 ||
1389 strwicmp(pszParmValue, "1") == 0)
1390 *pb = True;
1391 else if (strwicmp(pszParmValue, "no") == 0 ||
1392 strwicmp(pszParmValue, "False") == 0 ||
1393 strwicmp(pszParmValue, "0") == 0)
1394 *pb = False;
1395 else {
1396 DEBUG(0,
1397 ("ERROR: Badly formed boolean in configuration file: \"%s\".\n",
1398 pszParmValue));
1399 bRetval = False;
1401 return (bRetval);
1404 /***************************************************************************
1405 Find a service by name. Otherwise works like get_service.
1406 ***************************************************************************/
1408 static int getservicebyname(const char *pszServiceName, service * pserviceDest)
1410 int iService;
1412 for (iService = iNumServices - 1; iService >= 0; iService--)
1413 if (VALID(iService) &&
1414 strwicmp(ServicePtrs[iService]->szService, pszServiceName) == 0) {
1415 if (pserviceDest != NULL)
1416 copy_service(pserviceDest, ServicePtrs[iService], NULL);
1417 break;
1420 return (iService);
1423 /***************************************************************************
1424 Copy a service structure to another.
1425 If pcopymapDest is NULL then copy all fields
1426 ***************************************************************************/
1428 static void copy_service(service * pserviceDest, service * pserviceSource, BOOL *pcopymapDest)
1430 int i;
1431 BOOL bcopyall = (pcopymapDest == NULL);
1432 struct param_opt *data, *pdata, *paramo;
1433 BOOL not_added;
1435 for (i = 0; parm_table[i].label; i++)
1436 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1437 (bcopyall || pcopymapDest[i])) {
1438 void *def_ptr = parm_table[i].ptr;
1439 void *src_ptr =
1440 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
1441 &sDefault);
1442 void *dest_ptr =
1443 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
1444 &sDefault);
1446 switch (parm_table[i].type) {
1447 case P_BOOL:
1448 *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
1449 break;
1451 case P_INTEGER:
1452 case P_ENUM:
1453 *(int *)dest_ptr = *(int *)src_ptr;
1454 break;
1456 case P_STRING:
1457 string_set(dest_ptr,
1458 *(char **)src_ptr);
1459 break;
1461 case P_USTRING:
1462 string_set(dest_ptr,
1463 *(char **)src_ptr);
1464 strupper(*(char **)dest_ptr);
1465 break;
1466 case P_LIST:
1467 *(const char ***)dest_ptr = str_list_copy(talloc_autofree_context(),
1468 *(const char ***)src_ptr);
1469 break;
1470 default:
1471 break;
1475 if (bcopyall) {
1476 init_copymap(pserviceDest);
1477 if (pserviceSource->copymap)
1478 memcpy((void *)pserviceDest->copymap,
1479 (void *)pserviceSource->copymap,
1480 sizeof(BOOL) * NUMPARAMETERS);
1483 data = pserviceSource->param_opt;
1484 while (data) {
1485 not_added = True;
1486 pdata = pserviceDest->param_opt;
1487 /* Traverse destination */
1488 while (pdata) {
1489 /* If we already have same option, override it */
1490 if (strcmp(pdata->key, data->key) == 0) {
1491 string_free(&pdata->value);
1492 pdata->value = strdup(data->value);
1493 not_added = False;
1494 break;
1496 pdata = pdata->next;
1498 if (not_added) {
1499 paramo = malloc_p(struct param_opt);
1500 if (!paramo)
1501 smb_panic("OOM");
1502 paramo->key = strdup(data->key);
1503 paramo->value = strdup(data->value);
1504 DLIST_ADD(pserviceDest->param_opt, paramo);
1506 data = data->next;
1510 /***************************************************************************
1511 Check a service for consistency. Return False if the service is in any way
1512 incomplete or faulty, else True.
1513 ***************************************************************************/
1515 static BOOL service_ok(int iService)
1517 BOOL bRetval;
1519 bRetval = True;
1520 if (ServicePtrs[iService]->szService[0] == '\0') {
1521 DEBUG(0, ("The following message indicates an internal error:\n"));
1522 DEBUG(0, ("No service name in service entry.\n"));
1523 bRetval = False;
1526 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1527 /* I can't see why you'd want a non-printable printer service... */
1528 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
1529 if (!ServicePtrs[iService]->bPrint_ok) {
1530 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
1531 ServicePtrs[iService]->szService));
1532 ServicePtrs[iService]->bPrint_ok = True;
1533 update_server_announce_as_printserver();
1535 /* [printers] service must also be non-browsable. */
1536 if (ServicePtrs[iService]->bBrowseable)
1537 ServicePtrs[iService]->bBrowseable = False;
1540 /* If a service is flagged unavailable, log the fact at level 0. */
1541 if (!ServicePtrs[iService]->bAvailable)
1542 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
1543 ServicePtrs[iService]->szService));
1545 return (bRetval);
1548 static struct file_lists {
1549 struct file_lists *next;
1550 char *name;
1551 char *subfname;
1552 time_t modtime;
1553 } *file_lists = NULL;
1555 /*******************************************************************
1556 Keep a linked list of all config files so we know when one has changed
1557 it's date and needs to be reloaded.
1558 ********************************************************************/
1560 static void add_to_file_list(const char *fname, const char *subfname)
1562 struct file_lists *f = file_lists;
1564 while (f) {
1565 if (f->name && !strcmp(f->name, fname))
1566 break;
1567 f = f->next;
1570 if (!f) {
1571 f = malloc_p(struct file_lists);
1572 if (!f)
1573 return;
1574 f->next = file_lists;
1575 f->name = strdup(fname);
1576 if (!f->name) {
1577 SAFE_FREE(f);
1578 return;
1580 f->subfname = strdup(subfname);
1581 if (!f->subfname) {
1582 SAFE_FREE(f);
1583 return;
1585 file_lists = f;
1586 f->modtime = file_modtime(subfname);
1587 } else {
1588 time_t t = file_modtime(subfname);
1589 if (t)
1590 f->modtime = t;
1594 /*******************************************************************
1595 Check if a config file has changed date.
1596 ********************************************************************/
1598 BOOL lp_file_list_changed(void)
1600 struct file_lists *f = file_lists;
1601 DEBUG(6, ("lp_file_list_changed()\n"));
1603 while (f) {
1604 pstring n2;
1605 time_t mod_time;
1607 pstrcpy(n2, f->name);
1608 standard_sub_basic(n2,sizeof(n2));
1610 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
1611 f->name, n2, ctime(&f->modtime)));
1613 mod_time = file_modtime(n2);
1615 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
1616 DEBUGADD(6,
1617 ("file %s modified: %s\n", n2,
1618 ctime(&mod_time)));
1619 f->modtime = mod_time;
1620 SAFE_FREE(f->subfname);
1621 f->subfname = strdup(n2);
1622 return (True);
1624 f = f->next;
1626 return (False);
1629 /***************************************************************************
1630 Handle the include operation.
1631 ***************************************************************************/
1633 static BOOL handle_include(const char *pszParmValue, char **ptr)
1635 pstring fname;
1636 pstrcpy(fname, pszParmValue);
1638 standard_sub_basic(fname,sizeof(fname));
1640 add_to_file_list(pszParmValue, fname);
1642 string_set(ptr, fname);
1644 if (file_exist(fname))
1645 return (pm_process(fname, do_section, do_parameter, NULL));
1647 DEBUG(2, ("Can't find include file %s\n", fname));
1649 return (False);
1652 /***************************************************************************
1653 Handle the interpretation of the copy parameter.
1654 ***************************************************************************/
1656 static BOOL handle_copy(const char *pszParmValue, char **ptr)
1658 BOOL bRetval;
1659 int iTemp;
1660 service serviceTemp;
1662 string_set(ptr, pszParmValue);
1664 init_service(&serviceTemp);
1666 bRetval = False;
1668 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
1670 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
1671 if (iTemp == iServiceIndex) {
1672 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
1673 } else {
1674 copy_service(ServicePtrs[iServiceIndex],
1675 &serviceTemp,
1676 ServicePtrs[iServiceIndex]->copymap);
1677 bRetval = True;
1679 } else {
1680 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
1681 bRetval = False;
1684 free_service(&serviceTemp);
1685 return (bRetval);
1688 /***************************************************************************
1689 Initialise a copymap.
1690 ***************************************************************************/
1692 static void init_copymap(service * pservice)
1694 int i;
1695 SAFE_FREE(pservice->copymap);
1696 pservice->copymap = malloc_array_p(BOOL, NUMPARAMETERS);
1697 if (!pservice->copymap)
1698 DEBUG(0,
1699 ("Couldn't allocate copymap!! (size %d)\n",
1700 (int)NUMPARAMETERS));
1701 else
1702 for (i = 0; i < NUMPARAMETERS; i++)
1703 pservice->copymap[i] = True;
1706 /***************************************************************************
1707 Return the local pointer to a parameter given the service number and the
1708 pointer into the default structure.
1709 ***************************************************************************/
1711 void *lp_local_ptr(int snum, void *ptr)
1713 return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
1717 /***************************************************************************
1718 Process a parametric option
1719 ***************************************************************************/
1720 static BOOL lp_do_parameter_parametric(int snum, const char *pszParmName, const char *pszParmValue, int flags)
1722 struct param_opt *paramo, *data;
1723 char *name;
1725 while (isspace((unsigned char)*pszParmName)) {
1726 pszParmName++;
1729 name = strdup(pszParmName);
1730 if (!name) return False;
1732 strlower(name);
1734 if (snum < 0) {
1735 data = Globals.param_opt;
1736 } else {
1737 data = ServicePtrs[snum]->param_opt;
1740 /* Traverse destination */
1741 for (paramo=data; paramo; paramo=paramo->next) {
1742 /* If we already have the option set, override it unless
1743 it was a command line option and the new one isn't */
1744 if (strcmp(paramo->key, name) == 0) {
1745 if ((paramo->flags & FLAG_CMDLINE) &&
1746 !(flags & FLAG_CMDLINE)) {
1747 return True;
1750 free(paramo->value);
1751 paramo->value = strdup(pszParmValue);
1752 paramo->flags = flags;
1753 free(name);
1754 return True;
1758 paramo = malloc_p(struct param_opt);
1759 if (!paramo)
1760 smb_panic("OOM");
1761 paramo->key = strdup(name);
1762 paramo->value = strdup(pszParmValue);
1763 paramo->flags = flags;
1764 if (snum < 0) {
1765 DLIST_ADD(Globals.param_opt, paramo);
1766 } else {
1767 DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
1770 free(name);
1772 return True;
1775 /***************************************************************************
1776 Process a parameter for a particular service number. If snum < 0
1777 then assume we are in the globals.
1778 ***************************************************************************/
1779 BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
1781 int parmnum, i;
1782 void *parm_ptr = NULL; /* where we are going to store the result */
1783 void *def_ptr = NULL;
1785 parmnum = map_parameter(pszParmName);
1787 if (parmnum < 0) {
1788 if (strchr(pszParmName, ':')) {
1789 return lp_do_parameter_parametric(snum, pszParmName, pszParmValue, 0);
1791 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1792 return (True);
1795 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1796 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1797 pszParmName));
1800 /* if the flag has been set on the command line, then don't allow override,
1801 but don't report an error */
1802 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1803 return True;
1806 def_ptr = parm_table[parmnum].ptr;
1808 /* we might point at a service, the default service or a global */
1809 if (snum < 0) {
1810 parm_ptr = def_ptr;
1811 } else {
1812 if (parm_table[parmnum].class == P_GLOBAL) {
1813 DEBUG(0,
1814 ("Global parameter %s found in service section!\n",
1815 pszParmName));
1816 return (True);
1818 parm_ptr =
1819 ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
1820 &sDefault);
1823 if (snum >= 0) {
1824 if (!ServicePtrs[snum]->copymap)
1825 init_copymap(ServicePtrs[snum]);
1827 /* this handles the aliases - set the copymap for other entries with
1828 the same data pointer */
1829 for (i = 0; parm_table[i].label; i++)
1830 if (parm_table[i].ptr == parm_table[parmnum].ptr)
1831 ServicePtrs[snum]->copymap[i] = False;
1834 /* if it is a special case then go ahead */
1835 if (parm_table[parmnum].special) {
1836 parm_table[parmnum].special(pszParmValue, (char **)parm_ptr);
1837 return (True);
1840 /* now switch on the type of variable it is */
1841 switch (parm_table[parmnum].type)
1843 case P_BOOL:
1844 set_boolean(parm_ptr, pszParmValue);
1845 break;
1847 case P_INTEGER:
1848 *(int *)parm_ptr = atoi(pszParmValue);
1849 break;
1851 case P_LIST:
1852 *(const char ***)parm_ptr = str_list_make(talloc_autofree_context(),
1853 pszParmValue, NULL);
1854 break;
1856 case P_STRING:
1857 string_set(parm_ptr, pszParmValue);
1858 break;
1860 case P_USTRING:
1861 string_set(parm_ptr, pszParmValue);
1862 strupper(*(char **)parm_ptr);
1863 break;
1865 case P_ENUM:
1866 for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
1867 if (strequal
1868 (pszParmValue,
1869 parm_table[parmnum].enum_list[i].name)) {
1870 *(int *)parm_ptr =
1871 parm_table[parmnum].
1872 enum_list[i].value;
1873 break;
1876 if (!parm_table[parmnum].enum_list[i].name) {
1877 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n",
1878 pszParmValue, pszParmName));
1879 return False;
1881 break;
1882 case P_SEP:
1883 break;
1886 if (parm_table[parmnum].flags & FLAG_DEFAULT) {
1887 parm_table[parmnum].flags &= ~FLAG_DEFAULT;
1888 /* we have to also unset FLAG_DEFAULT on aliases */
1889 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1890 parm_table[i].flags &= ~FLAG_DEFAULT;
1892 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1893 parm_table[i].flags &= ~FLAG_DEFAULT;
1897 return (True);
1900 /***************************************************************************
1901 Process a parameter.
1902 ***************************************************************************/
1904 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue, void *userdata)
1906 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
1907 pszParmName, pszParmValue));
1911 variable argument do parameter
1913 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
1915 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...)
1917 char *s;
1918 BOOL ret;
1919 va_list ap;
1921 va_start(ap, fmt);
1922 s = talloc_vasprintf(NULL, fmt, ap);
1923 va_end(ap);
1924 ret = do_parameter(pszParmName, s, NULL);
1925 talloc_free(s);
1926 return ret;
1931 set a parameter from the commandline - this is called from command line parameter
1932 parsing code. It sets the parameter then marks the parameter as unable to be modified
1933 by smb.conf processing
1935 BOOL lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
1937 int parmnum = map_parameter(pszParmName);
1938 int i;
1940 while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
1943 if (parmnum < 0 && strchr(pszParmName, ':')) {
1944 /* set a parametric option */
1945 return lp_do_parameter_parametric(-1, pszParmName, pszParmValue, FLAG_CMDLINE);
1948 if (parmnum < 0) {
1949 DEBUG(0,("Unknown option '%s'\n", pszParmName));
1950 return False;
1953 /* reset the CMDLINE flag in case this has been called before */
1954 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
1956 if (!lp_do_parameter(-2, pszParmName, pszParmValue)) {
1957 return False;
1960 parm_table[parmnum].flags |= FLAG_CMDLINE;
1962 /* we have to also set FLAG_CMDLINE on aliases */
1963 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1964 parm_table[i].flags |= FLAG_CMDLINE;
1966 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1967 parm_table[i].flags |= FLAG_CMDLINE;
1970 return True;
1974 set a option from the commandline in 'a=b' format. Use to support --option
1976 BOOL lp_set_option(const char *option)
1978 char *p, *s;
1979 BOOL ret;
1981 s = strdup(option);
1982 if (!s) {
1983 return False;
1986 p = strchr(s, '=');
1987 if (!p) {
1988 free(s);
1989 return False;
1992 *p = 0;
1994 ret = lp_set_cmdline(s, p+1);
1995 free(s);
1996 return ret;
2000 #define BOOLSTR(b) ((b) ? "Yes" : "No")
2002 /***************************************************************************
2003 Print a parameter of the specified type.
2004 ***************************************************************************/
2006 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
2008 int i;
2009 switch (p->type)
2011 case P_ENUM:
2012 for (i = 0; p->enum_list[i].name; i++) {
2013 if (*(int *)ptr == p->enum_list[i].value) {
2014 fprintf(f, "%s",
2015 p->enum_list[i].name);
2016 break;
2019 break;
2021 case P_BOOL:
2022 fprintf(f, "%s", BOOLSTR(*(BOOL *)ptr));
2023 break;
2025 case P_INTEGER:
2026 fprintf(f, "%d", *(int *)ptr);
2027 break;
2029 case P_LIST:
2030 if ((char ***)ptr && *(char ***)ptr) {
2031 char **list = *(char ***)ptr;
2033 for (; *list; list++)
2034 fprintf(f, "%s%s", *list,
2035 ((*(list+1))?", ":""));
2037 break;
2039 case P_STRING:
2040 case P_USTRING:
2041 if (*(char **)ptr) {
2042 fprintf(f, "%s", *(char **)ptr);
2044 break;
2045 case P_SEP:
2046 break;
2050 /***************************************************************************
2051 Check if two parameters are equal.
2052 ***************************************************************************/
2054 static BOOL equal_parameter(parm_type type, void *ptr1, void *ptr2)
2056 switch (type) {
2057 case P_BOOL:
2058 return (*((BOOL *)ptr1) == *((BOOL *)ptr2));
2060 case P_INTEGER:
2061 case P_ENUM:
2062 return (*((int *)ptr1) == *((int *)ptr2));
2064 case P_LIST:
2065 return str_list_equal((const char **)(*(char ***)ptr1),
2066 (const char **)(*(char ***)ptr2));
2068 case P_STRING:
2069 case P_USTRING:
2071 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
2072 if (p1 && !*p1)
2073 p1 = NULL;
2074 if (p2 && !*p2)
2075 p2 = NULL;
2076 return (p1 == p2 || strequal(p1, p2));
2078 case P_SEP:
2079 break;
2081 return (False);
2084 /***************************************************************************
2085 Process a new section (service). At this stage all sections are services.
2086 Later we'll have special sections that permit server parameters to be set.
2087 Returns True on success, False on failure.
2088 ***************************************************************************/
2090 static BOOL do_section(const char *pszSectionName, void *userdata)
2092 BOOL bRetval;
2093 BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2094 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2095 bRetval = False;
2097 /* if we've just struck a global section, note the fact. */
2098 bInGlobalSection = isglobal;
2100 /* check for multiple global sections */
2101 if (bInGlobalSection) {
2102 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2103 return (True);
2106 /* if we have a current service, tidy it up before moving on */
2107 bRetval = True;
2109 if (iServiceIndex >= 0)
2110 bRetval = service_ok(iServiceIndex);
2112 /* if all is still well, move to the next record in the services array */
2113 if (bRetval) {
2114 /* We put this here to avoid an odd message order if messages are */
2115 /* issued by the post-processing of a previous section. */
2116 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2118 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
2119 < 0) {
2120 DEBUG(0, ("Failed to add a new service\n"));
2121 return (False);
2125 return (bRetval);
2129 /***************************************************************************
2130 Determine if a partcular base parameter is currentl set to the default value.
2131 ***************************************************************************/
2133 static BOOL is_default(int i)
2135 if (!defaults_saved)
2136 return False;
2137 switch (parm_table[i].type) {
2138 case P_LIST:
2139 return str_list_equal((const char **)parm_table[i].def.lvalue,
2140 (const char **)(*(char ***)parm_table[i].ptr));
2141 case P_STRING:
2142 case P_USTRING:
2143 return strequal(parm_table[i].def.svalue,
2144 *(char **)parm_table[i].ptr);
2145 case P_BOOL:
2146 return parm_table[i].def.bvalue ==
2147 *(BOOL *)parm_table[i].ptr;
2148 case P_INTEGER:
2149 case P_ENUM:
2150 return parm_table[i].def.ivalue ==
2151 *(int *)parm_table[i].ptr;
2152 case P_SEP:
2153 break;
2155 return False;
2158 /***************************************************************************
2159 Display the contents of the global structure.
2160 ***************************************************************************/
2162 static void dump_globals(FILE *f, BOOL show_defaults)
2164 int i;
2165 struct param_opt *data;
2167 fprintf(f, "# Global parameters\n[global]\n");
2169 for (i = 0; parm_table[i].label; i++)
2170 if (parm_table[i].class == P_GLOBAL &&
2171 parm_table[i].ptr &&
2172 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2173 if (!show_defaults && (parm_table[i].flags & FLAG_DEFAULT))
2174 continue;
2175 fprintf(f, "\t%s = ", parm_table[i].label);
2176 print_parameter(&parm_table[i], parm_table[i].ptr, f);
2177 fprintf(f, "\n");
2179 if (Globals.param_opt != NULL) {
2180 data = Globals.param_opt;
2181 while(data) {
2182 fprintf(f, "\t%s = %s\n", data->key, data->value);
2183 data = data->next;
2189 /***************************************************************************
2190 Display the contents of a single services record.
2191 ***************************************************************************/
2193 static void dump_a_service(service * pService, FILE * f)
2195 int i;
2196 struct param_opt *data;
2198 if (pService != &sDefault)
2199 fprintf(f, "\n[%s]\n", pService->szService);
2201 for (i = 0; parm_table[i].label; i++)
2202 if (parm_table[i].class == P_LOCAL &&
2203 parm_table[i].ptr &&
2204 (*parm_table[i].label != '-') &&
2205 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2206 int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
2208 if (pService == &sDefault) {
2209 if (defaults_saved && is_default(i))
2210 continue;
2211 } else {
2212 if (equal_parameter(parm_table[i].type,
2213 ((char *)pService) +
2214 pdiff,
2215 ((char *)&sDefault) +
2216 pdiff))
2217 continue;
2220 fprintf(f, "\t%s = ", parm_table[i].label);
2221 print_parameter(&parm_table[i],
2222 ((char *)pService) + pdiff, f);
2223 fprintf(f, "\n");
2225 if (pService->param_opt != NULL) {
2226 data = pService->param_opt;
2227 while(data) {
2228 fprintf(f, "\t%s = %s\n", data->key, data->value);
2229 data = data->next;
2234 BOOL lp_dump_a_parameter(int snum, char *parm_name, FILE * f, BOOL isGlobal)
2236 service * pService = ServicePtrs[snum];
2237 parm_class p_class;
2238 unsigned flag = 0;
2239 struct parm_struct *parm;
2240 void *ptr;
2241 if (isGlobal) {
2242 p_class = P_GLOBAL;
2243 flag = FLAG_GLOBAL;
2244 } else
2245 p_class = P_LOCAL;
2247 parm = lp_parm_struct(parm_name);
2248 if (!parm) {
2249 return False;
2252 if (isGlobal)
2253 ptr = parm->ptr;
2254 else
2255 ptr = ((char *)pService) +
2256 PTR_DIFF(parm->ptr, &sDefault);
2258 print_parameter(parm,
2259 ptr, f);
2260 fprintf(f, "\n");
2261 return True;
2264 /***************************************************************************
2265 Return info about the next service in a service. snum==-1 gives the globals.
2266 Return NULL when out of parameters.
2267 ***************************************************************************/
2269 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
2271 if (snum == -1) {
2272 /* do the globals */
2273 for (; parm_table[*i].label; (*i)++) {
2274 if (parm_table[*i].class == P_SEPARATOR)
2275 return &parm_table[(*i)++];
2277 if (!parm_table[*i].ptr
2278 || (*parm_table[*i].label == '-'))
2279 continue;
2281 if ((*i) > 0
2282 && (parm_table[*i].ptr ==
2283 parm_table[(*i) - 1].ptr))
2284 continue;
2286 return &parm_table[(*i)++];
2288 } else {
2289 service *pService = ServicePtrs[snum];
2291 for (; parm_table[*i].label; (*i)++) {
2292 if (parm_table[*i].class == P_SEPARATOR)
2293 return &parm_table[(*i)++];
2295 if (parm_table[*i].class == P_LOCAL &&
2296 parm_table[*i].ptr &&
2297 (*parm_table[*i].label != '-') &&
2298 ((*i) == 0 ||
2299 (parm_table[*i].ptr !=
2300 parm_table[(*i) - 1].ptr)))
2302 int pdiff =
2303 PTR_DIFF(parm_table[*i].ptr,
2304 &sDefault);
2306 if (allparameters ||
2307 !equal_parameter(parm_table[*i].type,
2308 ((char *)pService) +
2309 pdiff,
2310 ((char *)&sDefault) +
2311 pdiff))
2313 return &parm_table[(*i)++];
2319 return NULL;
2323 /***************************************************************************
2324 Return TRUE if the passed service number is within range.
2325 ***************************************************************************/
2327 BOOL lp_snum_ok(int iService)
2329 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
2332 /***************************************************************************
2333 Auto-load some home services.
2334 ***************************************************************************/
2336 static void lp_add_auto_services(const char *str)
2338 return;
2341 /***************************************************************************
2342 Announce ourselves as a print server.
2343 ***************************************************************************/
2345 void update_server_announce_as_printserver(void)
2347 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
2350 /***************************************************************************
2351 Have we loaded a services file yet?
2352 ***************************************************************************/
2354 BOOL lp_loaded(void)
2356 return (bLoaded);
2359 /***************************************************************************
2360 Unload unused services.
2361 ***************************************************************************/
2363 void lp_killunused(struct smbsrv_connection *smb, BOOL (*snumused) (struct smbsrv_connection *, int))
2365 int i;
2366 for (i = 0; i < iNumServices; i++) {
2367 if (!VALID(i))
2368 continue;
2370 if (!snumused || !snumused(smb, i)) {
2371 ServicePtrs[i]->valid = False;
2372 free_service(ServicePtrs[i]);
2377 /***************************************************************************
2378 Unload a service.
2379 ***************************************************************************/
2381 void lp_killservice(int iServiceIn)
2383 if (VALID(iServiceIn)) {
2384 ServicePtrs[iServiceIn]->valid = False;
2385 free_service(ServicePtrs[iServiceIn]);
2389 /***************************************************************************
2390 Load the services array from the services file. Return True on success,
2391 False on failure.
2392 ***************************************************************************/
2394 BOOL lp_load(void)
2396 pstring n2;
2397 BOOL bRetval;
2398 struct param_opt *data;
2400 bRetval = False;
2402 bInGlobalSection = True;
2404 if (Globals.param_opt != NULL) {
2405 struct param_opt *next;
2406 for (data=Globals.param_opt; data; data=next) {
2407 next = data->next;
2408 if (data->flags & FLAG_CMDLINE) continue;
2409 free(data->key);
2410 free(data->value);
2411 DLIST_REMOVE(Globals.param_opt, data);
2412 free(data);
2416 init_globals();
2418 pstrcpy(n2, lp_configfile());
2419 standard_sub_basic(n2,sizeof(n2));
2420 DEBUG(2, ("lp_load: refreshing parameters from %s\n", n2));
2422 add_to_file_list(lp_configfile(), n2);
2424 /* We get sections first, so have to start 'behind' to make up */
2425 iServiceIndex = -1;
2426 bRetval = pm_process(n2, do_section, do_parameter, NULL);
2428 /* finish up the last section */
2429 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
2430 if (bRetval)
2431 if (iServiceIndex >= 0)
2432 bRetval = service_ok(iServiceIndex);
2434 lp_add_auto_services(lp_auto_services());
2436 lp_add_hidden("IPC$", "IPC");
2437 lp_add_hidden("ADMIN$", "DISK");
2439 set_default_server_announce_type();
2441 bLoaded = True;
2443 if (!Globals.szWINSservers && Globals.bWINSsupport) {
2444 lp_do_parameter(-1, "wins server", "127.0.0.1");
2447 init_iconv();
2449 return (bRetval);
2452 /***************************************************************************
2453 Reset the max number of services.
2454 ***************************************************************************/
2456 void lp_resetnumservices(void)
2458 iNumServices = 0;
2461 /***************************************************************************
2462 Return the max number of services.
2463 ***************************************************************************/
2465 int lp_numservices(void)
2467 return (iNumServices);
2470 /***************************************************************************
2471 Display the contents of the services array in human-readable form.
2472 ***************************************************************************/
2474 void lp_dump(FILE *f, BOOL show_defaults, int maxtoprint)
2476 int iService;
2478 if (show_defaults)
2479 defaults_saved = False;
2481 dump_globals(f, show_defaults);
2483 dump_a_service(&sDefault, f);
2485 for (iService = 0; iService < maxtoprint; iService++)
2486 lp_dump_one(f, show_defaults, iService);
2489 /***************************************************************************
2490 Display the contents of one service in human-readable form.
2491 ***************************************************************************/
2493 void lp_dump_one(FILE * f, BOOL show_defaults, int snum)
2495 if (VALID(snum)) {
2496 if (ServicePtrs[snum]->szService[0] == '\0')
2497 return;
2498 dump_a_service(ServicePtrs[snum], f);
2502 /***************************************************************************
2503 Return the number of the service with the given name, or -1 if it doesn't
2504 exist. Note that this is a DIFFERENT ANIMAL from the internal function
2505 getservicebyname()! This works ONLY if all services have been loaded, and
2506 does not copy the found service.
2507 ***************************************************************************/
2509 int lp_servicenumber(const char *pszServiceName)
2511 int iService;
2512 fstring serviceName;
2515 for (iService = iNumServices - 1; iService >= 0; iService--) {
2516 if (VALID(iService) && ServicePtrs[iService]->szService) {
2518 * The substitution here is used to support %U is
2519 * service names
2521 fstrcpy(serviceName, ServicePtrs[iService]->szService);
2522 standard_sub_basic(serviceName,sizeof(serviceName));
2523 if (strequal(serviceName, pszServiceName))
2524 break;
2528 if (iService < 0)
2529 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
2531 return (iService);
2534 /*******************************************************************
2535 A useful volume label function.
2536 ********************************************************************/
2537 const char *volume_label(int snum)
2539 const char *ret = lp_volume(snum);
2540 if (!*ret)
2541 return lp_servicename(snum);
2542 return (ret);
2546 /*******************************************************************
2547 Set the server type we will announce as via nmbd.
2548 ********************************************************************/
2550 static void set_default_server_announce_type(void)
2552 default_server_announce = 0;
2553 default_server_announce |= SV_TYPE_WORKSTATION;
2554 default_server_announce |= SV_TYPE_SERVER;
2555 default_server_announce |= SV_TYPE_SERVER_UNIX;
2557 switch (lp_announce_as()) {
2558 case ANNOUNCE_AS_NT_SERVER:
2559 default_server_announce |= SV_TYPE_SERVER_NT;
2560 /* fall through... */
2561 case ANNOUNCE_AS_NT_WORKSTATION:
2562 default_server_announce |= SV_TYPE_NT;
2563 break;
2564 case ANNOUNCE_AS_WIN95:
2565 default_server_announce |= SV_TYPE_WIN95_PLUS;
2566 break;
2567 case ANNOUNCE_AS_WFW:
2568 default_server_announce |= SV_TYPE_WFW;
2569 break;
2570 default:
2571 break;
2574 switch (lp_server_role()) {
2575 case ROLE_DOMAIN_MEMBER:
2576 default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
2577 break;
2578 case ROLE_DOMAIN_PDC:
2579 default_server_announce |= SV_TYPE_DOMAIN_CTRL;
2580 break;
2581 case ROLE_DOMAIN_BDC:
2582 default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
2583 break;
2584 case ROLE_STANDALONE:
2585 default:
2586 break;
2588 if (lp_time_server())
2589 default_server_announce |= SV_TYPE_TIME_SOURCE;
2591 if (lp_host_msdfs())
2592 default_server_announce |= SV_TYPE_DFS_SERVER;
2594 /* TODO: only announce us as print server when we are a print server */
2595 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
2598 /***********************************************************
2599 If we are PDC then prefer us as DMB
2600 ************************************************************/
2602 BOOL lp_domain_master(void)
2604 return (lp_server_role() == ROLE_DOMAIN_PDC);
2607 /***********************************************************
2608 If we are PDC then prefer us as DMB
2609 ************************************************************/
2611 BOOL lp_domain_logons(void)
2613 return (lp_server_role() == ROLE_DOMAIN_PDC) || (lp_server_role() == ROLE_DOMAIN_BDC);
2616 /***********************************************************
2617 If we are DMB then prefer us as LMB
2618 ************************************************************/
2620 BOOL lp_preferred_master(void)
2622 return (lp_local_master() && lp_domain_master());
2625 /*******************************************************************
2626 Remove a service.
2627 ********************************************************************/
2629 void lp_remove_service(int snum)
2631 ServicePtrs[snum]->valid = False;
2634 /*******************************************************************
2635 Copy a service.
2636 ********************************************************************/
2638 void lp_copy_service(int snum, const char *new_name)
2640 const char *oldname = lp_servicename(snum);
2641 do_section(new_name, NULL);
2642 if (snum >= 0) {
2643 snum = lp_servicenumber(new_name);
2644 if (snum >= 0)
2645 lp_do_parameter(snum, "copy", oldname);
2650 /*******************************************************************
2651 Get the default server type we will announce as via nmbd.
2652 ********************************************************************/
2653 int lp_default_server_announce(void)
2655 return default_server_announce;
2658 const char *lp_printername(int snum)
2660 const char *ret = _lp_printername(snum);
2661 if (ret == NULL || (ret != NULL && *ret == '\0'))
2662 ret = lp_const_servicename(snum);
2664 return ret;
2668 /*******************************************************************
2669 Return the max print jobs per queue.
2670 ********************************************************************/
2672 int lp_maxprintjobs(int snum)
2674 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
2675 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
2676 maxjobs = PRINT_MAX_JOBID - 1;
2678 return maxjobs;