r23792: convert Samba4 to GPLv3
[jelmer/samba4-debian.git] / source / param / loadparm.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Parameter loading functions
4    Copyright (C) Karl Auer 1993-1998
5
6    Largely re-written by Andrew Tridgell, September 1994
7
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>
13    
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 3 of the License, or
17    (at your option) any later version.
18    
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.
23    
24    You should have received a copy of the GNU General Public License
25    along with this program.  If not, see <http://www.gnu.org/licenses/>.
26 */
27
28 /*
29  *  Load parameters.
30  *
31  *  This module provides suitable callback functions for the params
32  *  module. It builds the internal table of service details which is
33  *  then used by the rest of the server.
34  *
35  * To add a parameter:
36  *
37  * 1) add it to the global or service structure definition
38  * 2) add it to the parm_table
39  * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
40  * 4) If it's a global then initialise it in init_globals. If a local
41  *    (ie. service) parameter then initialise it in the sDefault structure
42  *  
43  *
44  * Notes:
45  *   The configuration file is processed sequentially for speed. It is NOT
46  *   accessed randomly as happens in 'real' Windows. For this reason, there
47  *   is a fair bit of sequence-dependent code here - ie., code which assumes
48  *   that certain things happen before others. In particular, the code which
49  *   happens at the boundary between sections is delicately poised, so be
50  *   careful!
51  *
52  */
53
54 #include "includes.h"
55 #include "version.h"
56 #include "dynconfig.h"
57 #include "pstring.h"
58 #include "system/time.h"
59 #include "system/locale.h"
60 #include "system/network.h" /* needed for TCP_NODELAY */
61 #include "smb_server/smb_server.h"
62 #include "libcli/raw/signing.h"
63 #include "lib/util/dlinklist.h"
64 #include "param/loadparm.h"
65
66 static BOOL bLoaded = False;
67
68 #define standard_sub_basic(str,len)
69
70 /* some helpful bits */
71 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && ServicePtrs[(i)]->valid)
72 #define VALID(i) ServicePtrs[i]->valid
73
74 static BOOL do_parameter(const char *, const char *, void *);
75 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...);
76
77 static BOOL defaults_saved = False;
78
79
80 struct param_opt {
81         struct param_opt *prev, *next;
82         char *key;
83         char *value;
84         int flags;
85 };
86
87 /* 
88  * This structure describes global (ie., server-wide) parameters.
89  */
90 typedef struct
91 {
92         int server_role;
93
94         char **smb_ports;
95         char *dos_charset;
96         char *unix_charset;
97         char *ncalrpc_dir;
98         char *display_charset;
99         char *szLockDir;
100         char *szModulesDir;
101         char *szPidDir;
102         char *szSetupDir;
103         char *szServerString;
104         char *szAutoServices;
105         char *szPasswdChat;
106         char *szConfigFile;
107         char *szShareBackend;
108         char *szSAM_URL;
109         char *szSECRETS_URL;
110         char *szSPOOLSS_URL;
111         char *szWINS_CONFIG_URL;
112         char *szWINS_URL;
113         char *szPrivateDir;
114         char **jsInclude;
115         char *jsonrpcServicesDir;
116         char **szPasswordServers;
117         char *szSocketOptions;
118         char *szRealm;
119         char **szWINSservers;
120         char **szInterfaces;
121         char *szSocketAddress;
122         char *szAnnounceVersion;        /* This is initialised in init_globals */
123         char *szWorkgroup;
124         char *szNetbiosName;
125         char **szNetbiosAliases;
126         char *szNetbiosScope;
127         char *szDomainOtherSIDs;
128         char **szNameResolveOrder;
129         char **dcerpc_ep_servers;
130         char **server_services;
131         char *ntptr_providor;
132         char *szWinbindSeparator;
133         char *szWinbinddSocketDirectory;
134         int bWinbindSealedPipes;
135         char *webapps_directory;
136         int tls_enabled;
137         char *tls_keyfile;
138         char *tls_certfile;
139         char *tls_cafile;
140         char *tls_crlfile;
141         char *tls_dhpfile;
142         int max_mux;
143         int max_xmit;
144         int pwordlevel;
145         int srv_maxprotocol;
146         int srv_minprotocol;
147         int cli_maxprotocol;
148         int cli_minprotocol;
149         int security;
150         char **AuthMethods;
151         int paranoid_server_security;
152         int max_wins_ttl;
153         int min_wins_ttl;
154         int announce_as;        /* This is initialised in init_globals */
155         int nbt_port;
156         int dgram_port;
157         int cldap_port;
158         int krb5_port;
159         int kpasswd_port;
160         int web_port;
161         char *socket_options;
162         int bWINSsupport;
163         int bWINSdnsProxy;
164         char *szWINSHook; 
165         int bLocalMaster;
166         int bPreferredMaster;
167         int bEncryptPasswords;
168         int bNullPasswords;
169         int bObeyPamRestrictions;
170         int bLargeReadwrite;
171         int bReadRaw;
172         int bWriteRaw;
173         int bTimeServer;
174         int bBindInterfacesOnly;
175         int bNTSmbSupport;
176         int bNTStatusSupport;
177         int bLanmanAuth;
178         int bNTLMAuth;
179         int bUseSpnego;
180         int  server_signing;
181         int  client_signing;
182         int bClientPlaintextAuth;
183         int bClientLanManAuth;
184         int bClientNTLMv2Auth;
185         int client_use_spnego_principal;
186         int bHostMSDfs;
187         int bUnicode;
188         int bUnixExtensions;
189         int bDisableNetbios;
190         int bRpcBigEndian;
191         struct param_opt *param_opt;
192 }
193 global;
194
195 static global Globals;
196
197 /* 
198  * This structure describes a single service. 
199  */
200 typedef struct
201 {
202         int valid;
203         char *szService;
204         char *szPath;
205         char *szCopy;
206         char *szInclude;
207         char *szPrintername;
208         char **szHostsallow;
209         char **szHostsdeny;
210         char *comment;
211         char *volume;
212         char *fstype;
213         char **ntvfs_handler;
214         int iMaxPrintJobs;
215         int iMaxConnections;
216         int iCSCPolicy;
217         int bAvailable;
218         int bBrowseable;
219         int bRead_only;
220         int bPrint_ok;
221         int bMap_system;
222         int bMap_hidden;
223         int bMap_archive;
224         int bStrictLocking;
225         int iCreate_mask;
226         int iCreate_force_mode;
227         int iDir_mask;
228         int iDir_force_mode;
229         int *copymap;
230         int bMSDfsRoot;
231         int bStrictSync;
232         int bCIFileSystem;
233         struct param_opt *param_opt;
234
235         char dummy[3];          /* for alignment */
236 }
237 service;
238
239
240 /* This is a default service used to prime a services structure */
241 static service sDefault = {
242         True,                   /* valid */
243         NULL,                   /* szService */
244         NULL,                   /* szPath */
245         NULL,                   /* szCopy */
246         NULL,                   /* szInclude */
247         NULL,                   /* szPrintername */
248         NULL,                   /* szHostsallow */
249         NULL,                   /* szHostsdeny */
250         NULL,                   /* comment */
251         NULL,                   /* volume */
252         NULL,                   /* fstype */
253         NULL,                   /* ntvfs_handler */
254         1000,                   /* iMaxPrintJobs */
255         0,                      /* iMaxConnections */
256         0,                      /* iCSCPolicy */
257         True,                   /* bAvailable */
258         True,                   /* bBrowseable */
259         True,                   /* bRead_only */
260         False,                  /* bPrint_ok */
261         False,                  /* bMap_system */
262         False,                  /* bMap_hidden */
263         True,                   /* bMap_archive */
264         True,                   /* bStrictLocking */
265         0744,                   /* iCreate_mask */
266         0000,                   /* iCreate_force_mode */
267         0755,                   /* iDir_mask */
268         0000,                   /* iDir_force_mode */   
269         NULL,                   /* copymap */
270         False,                  /* bMSDfsRoot */
271         False,                  /* bStrictSync */
272         False,                  /* bCIFileSystem */
273         NULL,                   /* Parametric options */
274
275         ""                      /* dummy */
276 };
277
278 /* local variables */
279 static service **ServicePtrs = NULL;
280 static int iNumServices = 0;
281 static int iServiceIndex = 0;
282 static BOOL bInGlobalSection = True;
283
284 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
285
286 /* prototypes for the special type handlers */
287 static BOOL handle_include(const char *pszParmValue, char **ptr);
288 static BOOL handle_copy(const char *pszParmValue, char **ptr);
289
290 static const struct enum_list enum_protocol[] = {
291         {PROTOCOL_SMB2, "SMB2"},
292         {PROTOCOL_NT1, "NT1"},
293         {PROTOCOL_LANMAN2, "LANMAN2"},
294         {PROTOCOL_LANMAN1, "LANMAN1"},
295         {PROTOCOL_CORE, "CORE"},
296         {PROTOCOL_COREPLUS, "COREPLUS"},
297         {PROTOCOL_COREPLUS, "CORE+"},
298         {-1, NULL}
299 };
300
301 static const struct enum_list enum_security[] = {
302         {SEC_SHARE, "SHARE"},
303         {SEC_USER, "USER"},
304         {-1, NULL}
305 };
306
307 static const struct enum_list enum_announce_as[] = {
308         {ANNOUNCE_AS_NT_SERVER, "NT"},
309         {ANNOUNCE_AS_NT_SERVER, "NT Server"},
310         {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"},
311         {ANNOUNCE_AS_WIN95, "win95"},
312         {ANNOUNCE_AS_WFW, "WfW"},
313         {-1, NULL}
314 };
315
316 static const struct enum_list enum_bool_auto[] = {
317         {False, "No"},
318         {False, "False"},
319         {False, "0"},
320         {True, "Yes"},
321         {True, "True"},
322         {True, "1"},
323         {Auto, "Auto"},
324         {-1, NULL}
325 };
326
327 /* Client-side offline caching policy types */
328 #define CSC_POLICY_MANUAL 0
329 #define CSC_POLICY_DOCUMENTS 1
330 #define CSC_POLICY_PROGRAMS 2
331 #define CSC_POLICY_DISABLE 3
332
333 static const struct enum_list enum_csc_policy[] = {
334         {CSC_POLICY_MANUAL, "manual"},
335         {CSC_POLICY_DOCUMENTS, "documents"},
336         {CSC_POLICY_PROGRAMS, "programs"},
337         {CSC_POLICY_DISABLE, "disable"},
338         {-1, NULL}
339 };
340
341 /* SMB signing types. */
342 static const struct enum_list enum_smb_signing_vals[] = {
343         {SMB_SIGNING_OFF, "No"},
344         {SMB_SIGNING_OFF, "False"},
345         {SMB_SIGNING_OFF, "0"},
346         {SMB_SIGNING_OFF, "Off"},
347         {SMB_SIGNING_OFF, "disabled"},
348         {SMB_SIGNING_SUPPORTED, "Yes"},
349         {SMB_SIGNING_SUPPORTED, "True"},
350         {SMB_SIGNING_SUPPORTED, "1"},
351         {SMB_SIGNING_SUPPORTED, "On"},
352         {SMB_SIGNING_SUPPORTED, "enabled"},
353         {SMB_SIGNING_REQUIRED, "required"},
354         {SMB_SIGNING_REQUIRED, "mandatory"},
355         {SMB_SIGNING_REQUIRED, "force"},
356         {SMB_SIGNING_REQUIRED, "forced"},
357         {SMB_SIGNING_REQUIRED, "enforced"},
358         {SMB_SIGNING_AUTO, "auto"},
359         {-1, NULL}
360 };
361
362 static const struct enum_list enum_server_role[] = {
363         {ROLE_STANDALONE, "standalone"},
364         {ROLE_DOMAIN_MEMBER, "member server"},
365         {ROLE_DOMAIN_CONTROLLER, "domain controller"},
366         {-1, NULL}
367 };
368
369
370 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
371  *
372  * Note: We have a flag called FLAG_DEVELOPER but is not used at this time, it
373  * is implied in current control logic. This may change at some later time. A
374  * flag value of 0 means - show as development option only.
375  *
376  * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
377  * screen in SWAT. This is used to exclude parameters as well as to squash all
378  * parameters that have been duplicated by pseudonyms.
379  */
380 static struct parm_struct parm_table[] = {
381         {"Base Options", P_SEP, P_SEPARATOR},
382
383         {"server role", P_ENUM, P_GLOBAL, &Globals.server_role, NULL, enum_server_role, FLAG_BASIC},
384
385         {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
386         {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
387         {"ncalrpc dir", P_STRING, P_GLOBAL, &Globals.ncalrpc_dir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
388         {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
389         {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
390         {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
391         {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE},
392         {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkgroup, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
393         {"realm", P_STRING, P_GLOBAL, &Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
394         {"netbios name", P_USTRING, P_GLOBAL, &Globals.szNetbiosName, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
395         {"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
396         {"netbios scope", P_USTRING, P_GLOBAL, &Globals.szNetbiosScope, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
397         {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED  | FLAG_DEVELOPER},
398         {"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
399         {"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
400         {"ntvfs handler", P_LIST, P_LOCAL, &sDefault.ntvfs_handler, NULL, NULL, FLAG_ADVANCED},
401         {"ntptr providor", P_STRING, P_GLOBAL, &Globals.ntptr_providor, NULL, NULL, FLAG_ADVANCED},
402         {"dcerpc endpoint servers", P_LIST, P_GLOBAL, &Globals.dcerpc_ep_servers, NULL, NULL, FLAG_ADVANCED},
403         {"server services", P_LIST, P_GLOBAL, &Globals.server_services, NULL, NULL, FLAG_ADVANCED},
404
405         {"Security Options", P_SEP, P_SEPARATOR},
406         
407         {"security", P_ENUM, P_GLOBAL, &Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
408         {"encrypt passwords", P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
409         {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
410         {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
411         {"password server", P_LIST, P_GLOBAL, &Globals.szPasswordServers, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
412         {"sam database", P_STRING, P_GLOBAL, &Globals.szSAM_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
413         {"secrets database", P_STRING, P_GLOBAL, &Globals.szSECRETS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
414         {"spoolss database", P_STRING, P_GLOBAL, &Globals.szSPOOLSS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
415         {"wins config database", P_STRING, P_GLOBAL, &Globals.szWINS_CONFIG_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
416         {"wins database", P_STRING, P_GLOBAL, &Globals.szWINS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
417         {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
418         {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
419         {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
420         {"lanman auth", P_BOOL, P_GLOBAL, &Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
421         {"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
422         {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
423         {"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
424         {"client plaintext auth", P_BOOL, P_GLOBAL, &Globals.bClientPlaintextAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
425         {"client use spnego principal", P_BOOL, P_GLOBAL, &Globals.client_use_spnego_principal, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
426         
427         {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE},
428
429         {"create mask", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
430         {"force create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
431         {"directory mask", P_OCTAL, P_LOCAL, &sDefault.iDir_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
432         {"force directory mode", P_OCTAL, P_LOCAL, &sDefault.iDir_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
433
434         {"hosts allow", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
435         {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
436
437         {"Logging Options", P_SEP, P_SEPARATOR},
438
439         {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
440         {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_HIDE},
441         {"log file", P_STRING, P_GLOBAL, &logfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
442         
443         {"Protocol Options", P_SEP, P_SEPARATOR},
444         
445         {"smb ports", P_LIST, P_GLOBAL, &Globals.smb_ports, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
446         {"nbt port", P_INTEGER, P_GLOBAL, &Globals.nbt_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
447         {"dgram port", P_INTEGER, P_GLOBAL, &Globals.dgram_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
448         {"cldap port", P_INTEGER, P_GLOBAL, &Globals.cldap_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
449         {"krb5 port", P_INTEGER, P_GLOBAL, &Globals.krb5_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
450         {"kpasswd port", P_INTEGER, P_GLOBAL, &Globals.kpasswd_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
451         {"web port", P_INTEGER, P_GLOBAL, &Globals.web_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
452         {"tls enabled", P_BOOL, P_GLOBAL, &Globals.tls_enabled, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
453         {"tls keyfile", P_STRING, P_GLOBAL, &Globals.tls_keyfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
454         {"tls certfile", P_STRING, P_GLOBAL, &Globals.tls_certfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
455         {"tls cafile", P_STRING, P_GLOBAL, &Globals.tls_cafile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
456         {"tls crlfile", P_STRING, P_GLOBAL, &Globals.tls_crlfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
457         {"tls dh params file", P_STRING, P_GLOBAL, &Globals.tls_dhpfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
458         {"web application directory", P_STRING, P_GLOBAL, &Globals.webapps_directory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
459         {"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, FLAG_DEVELOPER},
460         {"server max protocol", P_ENUM, P_GLOBAL, &Globals.srv_maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
461         {"server min protocol", P_ENUM, P_GLOBAL, &Globals.srv_minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
462         {"client max protocol", P_ENUM, P_GLOBAL, &Globals.cli_maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
463         {"client min protocol", P_ENUM, P_GLOBAL, &Globals.cli_minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
464         {"unicode", P_BOOL, P_GLOBAL, &Globals.bUnicode, NULL, NULL, FLAG_DEVELOPER},
465         {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL, NULL, FLAG_DEVELOPER},
466         {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL, NULL, FLAG_DEVELOPER},
467         {"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
468         
469         {"nt status support", P_BOOL, P_GLOBAL, &Globals.bNTStatusSupport, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
470
471         {"announce version", P_STRING, P_GLOBAL, &Globals.szAnnounceVersion, NULL, NULL, FLAG_DEVELOPER},
472         {"announce as", P_ENUM, P_GLOBAL, &Globals.announce_as, NULL, enum_announce_as, FLAG_DEVELOPER},
473         {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
474         {"max xmit", P_BYTES, P_GLOBAL, &Globals.max_xmit, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
475
476         {"name resolve order", P_LIST, P_GLOBAL, &Globals.szNameResolveOrder, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
477         {"max wins ttl", P_INTEGER, P_GLOBAL, &Globals.max_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
478         {"min wins ttl", P_INTEGER, P_GLOBAL, &Globals.min_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
479         {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
480         {"unix extensions", P_BOOL, P_GLOBAL, &Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
481         {"use spnego", P_BOOL, P_GLOBAL, &Globals.bUseSpnego, NULL, NULL, FLAG_DEVELOPER},
482         {"server signing", P_ENUM, P_GLOBAL, &Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED}, 
483         {"client signing", P_ENUM, P_GLOBAL, &Globals.client_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED}, 
484         {"rpc big endian", P_BOOL, P_GLOBAL, &Globals.bRpcBigEndian, NULL, NULL, FLAG_DEVELOPER},
485
486         {"Tuning Options", P_SEP, P_SEPARATOR},
487                 
488         {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL, NULL, FLAG_SHARE},
489         {"paranoid server security", P_BOOL, P_GLOBAL, &Globals.paranoid_server_security, NULL, NULL, FLAG_DEVELOPER},
490         {"socket options", P_STRING, P_GLOBAL, &Globals.socket_options, NULL, NULL, FLAG_DEVELOPER},
491
492         {"strict sync", P_BOOL, P_LOCAL, &sDefault.bStrictSync, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
493         {"case insensitive filesystem", P_BOOL, P_LOCAL, &sDefault.bCIFileSystem, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
494
495         {"Printing Options", P_SEP, P_SEPARATOR},
496         
497         {"max print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxPrintJobs, NULL, NULL, FLAG_PRINT},
498         {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_PRINT},
499         {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_HIDE},
500         
501         {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_PRINT},
502         {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_HIDE},
503
504         {"Filename Handling", P_SEP, P_SEPARATOR},
505         
506         {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
507         {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
508         {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
509
510         {"Domain Options", P_SEP, P_SEPARATOR},
511         
512         {"Logon Options", P_SEP, P_SEPARATOR},
513
514
515         {"Browse Options", P_SEP, P_SEPARATOR},
516         
517         {"preferred master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
518         {"prefered master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_HIDE},
519         {"local master", P_BOOL, P_GLOBAL, &Globals.bLocalMaster, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
520         {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
521         {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_HIDE},
522
523         {"WINS Options", P_SEP, P_SEPARATOR},
524         
525         {"wins server", P_LIST, P_GLOBAL, &Globals.szWINSservers, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
526         {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
527         {"dns proxy", P_BOOL, P_GLOBAL, &Globals.bWINSdnsProxy, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
528         {"wins hook", P_STRING, P_GLOBAL, &Globals.szWINSHook, NULL, NULL, FLAG_ADVANCED}, 
529
530         {"Locking Options", P_SEP, P_SEPARATOR},
531         
532         {"csc policy", P_ENUM, P_LOCAL, &sDefault.iCSCPolicy, NULL, enum_csc_policy, FLAG_SHARE | FLAG_GLOBAL},
533         
534         {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
535
536         {"Miscellaneous Options", P_SEP, P_SEPARATOR},
537         
538         {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE},
539         {"share backend", P_STRING, P_GLOBAL, &Globals.szShareBackend, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
540         {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
541         {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
542         {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_HIDE}, 
543         {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
544         {"modules dir", P_STRING, P_GLOBAL, &Globals.szModulesDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
545         {"pid directory", P_STRING, P_GLOBAL, &Globals.szPidDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, 
546         {"js include", P_LIST, P_GLOBAL, &Globals.jsInclude, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
547         {"jsonrpc services directory", P_STRING, P_GLOBAL, &Globals.jsonrpcServicesDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
548         {"setup directory", P_STRING, P_GLOBAL, &Globals.szSetupDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
549         
550         {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL, NULL, FLAG_DEVELOPER},
551         {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL, NULL, FLAG_HIDE},
552         
553         {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy, NULL, FLAG_HIDE},
554         {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include, NULL, FLAG_HIDE},
555         
556         {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
557         {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_SHARE },
558         {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_SHARE},
559
560         {"panic action", P_STRING, P_GLOBAL, &panic_action, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
561
562         {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_SHARE},
563         {"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
564         {"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
565         {"winbindd socket directory", P_STRING, P_GLOBAL, &Globals.szWinbinddSocketDirectory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
566         {"winbind sealed pipes", P_BOOL, P_GLOBAL, &Globals.bWinbindSealedPipes, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
567
568         {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
569 };
570
571
572 /*
573   return the parameter table
574 */
575 struct parm_struct *lp_parm_table(void)
576 {
577         return parm_table;
578 }
579
580 /***************************************************************************
581  Initialise the global parameter structure.
582 ***************************************************************************/
583 static void init_globals(void)
584 {
585         int i;
586         char *myname;
587
588         DEBUG(3, ("Initialising global parameters\n"));
589
590         for (i = 0; parm_table[i].label; i++) {
591                 if ((parm_table[i].type == P_STRING ||
592                      parm_table[i].type == P_USTRING) &&
593                     parm_table[i].ptr &&
594                     !(parm_table[i].flags & FLAG_CMDLINE)) {
595                         string_set(parm_table[i].ptr, "");
596                 }
597         }
598
599         do_parameter("config file", dyn_CONFIGFILE, NULL);
600
601         do_parameter("share backend", "classic", NULL);
602         
603         do_parameter("server role", "standalone", NULL);
604
605         /* options that can be set on the command line must be initialised via
606            the slower do_parameter() to ensure that FLAG_CMDLINE is obeyed */
607 #ifdef TCP_NODELAY
608         do_parameter("socket options", "TCP_NODELAY", NULL);
609 #endif
610         do_parameter("workgroup", DEFAULT_WORKGROUP, NULL);
611         myname = get_myname();
612         do_parameter("netbios name", myname, NULL);
613         SAFE_FREE(myname);
614         do_parameter("name resolve order", "lmhosts wins host bcast", NULL);
615
616         do_parameter("fstype", FSTYPE_STRING, NULL);
617         do_parameter("ntvfs handler", "unixuid default", NULL);
618         do_parameter("max connections", "-1", NULL);
619
620         do_parameter("dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup unixinfo", NULL);
621         do_parameter("server services", "smb rpc nbt wrepl ldap cldap web kdc drepl winbind", NULL);
622         do_parameter("ntptr providor", "simple_ldb", NULL);
623         do_parameter("auth methods:domain controller", "anonymous sam_ignoredomain", NULL);
624         do_parameter("auth methods:member server", "anonymous sam winbind", NULL);
625         do_parameter("auth methods:standalone", "anonymous sam_ignoredomain", NULL);
626         do_parameter("private dir", dyn_PRIVATE_DIR, NULL);
627         do_parameter("sam database", "sam.ldb", NULL);
628         do_parameter("secrets database", "secrets.ldb", NULL);
629         do_parameter("spoolss database", "spoolss.ldb", NULL);
630         do_parameter("wins config database", "wins_config.ldb", NULL);
631         do_parameter("wins database", "wins.ldb", NULL);
632         do_parameter("registry:HKEY_LOCAL_MACHINE", "hklm.ldb", NULL);
633
634         /* This hive should be dynamically generated by Samba using
635            data from the sam, but for the moment leave it in a tdb to
636            keep regedt32 from popping up an annoying dialog. */
637         do_parameter("registry:HKEY_USERS", "hku.ldb", NULL);
638         
639         /* using UTF8 by default allows us to support all chars */
640         do_parameter("unix charset", "UTF8", NULL);
641
642         /* Use codepage 850 as a default for the dos character set */
643         do_parameter("dos charset", "CP850", NULL);
644
645         /*
646          * Allow the default PASSWD_CHAT to be overridden in local.h.
647          */
648         do_parameter("passwd chat", DEFAULT_PASSWD_CHAT, NULL);
649
650         do_parameter("pid directory", dyn_PIDDIR, NULL);
651         do_parameter("lock dir", dyn_LOCKDIR, NULL);
652         do_parameter("modules dir", dyn_MODULESDIR, NULL);
653         do_parameter("ncalrpc dir", dyn_NCALRPCDIR, NULL);
654
655         do_parameter("socket address", "0.0.0.0", NULL);
656         do_parameter_var("server string", "Samba %s", SAMBA_VERSION_STRING);
657
658         do_parameter_var("announce version", "%d.%d", 
659                          DEFAULT_MAJOR_VERSION,
660                          DEFAULT_MINOR_VERSION);
661
662         do_parameter("password server", "*", NULL);
663
664         do_parameter("max mux", "50", NULL);
665         do_parameter("max xmit", "12288", NULL);
666         do_parameter("password level", "0", NULL);
667         do_parameter("LargeReadwrite", "True", NULL);
668         do_parameter("server min protocol", "CORE", NULL);
669         do_parameter("server max protocol", "NT1", NULL);
670         do_parameter("client min protocol", "CORE", NULL);
671         do_parameter("client max protocol", "NT1", NULL);
672         do_parameter("security", "USER", NULL);
673         do_parameter("paranoid server security", "True", NULL);
674         do_parameter("EncryptPasswords", "True", NULL);
675         do_parameter("ReadRaw", "True", NULL);
676         do_parameter("WriteRaw", "True", NULL);
677         do_parameter("NullPasswords", "False", NULL);
678         do_parameter("ObeyPamRestrictions", "False", NULL);
679         do_parameter("announce as", "NT SERVER", NULL);
680
681         do_parameter("TimeServer", "False", NULL);
682         do_parameter("BindInterfacesOnly", "False", NULL);
683         do_parameter("Unicode", "True", NULL);
684         do_parameter("ClientLanManAuth", "True", NULL);
685         do_parameter("LanmanAuth", "True", NULL);
686         do_parameter("NTLMAuth", "True", NULL);
687         do_parameter("client use spnego principal", "False", NULL);
688         
689         do_parameter("UnixExtensions", "False", NULL);
690
691         do_parameter("PreferredMaster", "Auto", NULL);
692         do_parameter("LocalMaster", "True", NULL);
693
694         do_parameter("wins support", "False", NULL);
695         do_parameter("dns proxy", "True", NULL);
696
697         do_parameter("winbind separator", "\\", NULL);
698         do_parameter("winbind sealed pipes", "True", NULL);
699         do_parameter("winbindd socket directory", dyn_WINBINDD_SOCKET_DIR, NULL);
700
701         do_parameter("client signing", "Yes", NULL);
702         do_parameter("server signing", "auto", NULL);
703
704         do_parameter("use spnego", "True", NULL);
705
706         do_parameter("smb ports", "445 139", NULL);
707         do_parameter("nbt port", "137", NULL);
708         do_parameter("dgram port", "138", NULL);
709         do_parameter("cldap port", "389", NULL);
710         do_parameter("krb5 port", "88", NULL);
711         do_parameter("kpasswd port", "464", NULL);
712         do_parameter("web port", "901", NULL);
713         do_parameter("web application directory", dyn_WEBAPPSDIR, NULL);
714         do_parameter("jsonrpc services directory", dyn_SERVICESDIR, NULL);
715
716         do_parameter("nt status support", "True", NULL);
717
718         do_parameter("max wins ttl", "518400", NULL); /* 6 days */
719         do_parameter("min wins ttl", "10", NULL);
720
721         do_parameter("tls enabled", "True", NULL);
722         do_parameter("tls keyfile", "tls/key.pem", NULL);
723         do_parameter("tls certfile", "tls/cert.pem", NULL);
724         do_parameter("tls cafile", "tls/ca.pem", NULL);
725         do_parameter_var("js include", "%s", dyn_JSDIR);
726         do_parameter_var("setup directory", "%s", dyn_SETUPDIR);
727
728         for (i = 0; parm_table[i].label; i++) {
729                 if (!(parm_table[i].flags & FLAG_CMDLINE)) {
730                         parm_table[i].flags |= FLAG_DEFAULT;
731                 }
732         }
733 }
734
735 static TALLOC_CTX *lp_talloc;
736
737 /******************************************************************* a
738  Free up temporary memory - called from the main loop.
739 ********************************************************************/
740
741 void lp_talloc_free(void)
742 {
743         if (!lp_talloc)
744                 return;
745         talloc_free(lp_talloc);
746         lp_talloc = NULL;
747 }
748
749 /*******************************************************************
750  Convenience routine to grab string parameters into temporary memory
751  and run standard_sub_basic on them. The buffers can be written to by
752  callers without affecting the source string.
753 ********************************************************************/
754
755 static const char *lp_string(const char *s)
756 {
757 #if 0  /* until REWRITE done to make thread-safe */
758         size_t len = s ? strlen(s) : 0;
759         char *ret;
760 #endif
761
762         /* The follow debug is useful for tracking down memory problems
763            especially if you have an inner loop that is calling a lp_*()
764            function that returns a string.  Perhaps this debug should be
765            present all the time? */
766
767 #if 0
768         DEBUG(10, ("lp_string(%s)\n", s));
769 #endif
770
771 #if 0  /* until REWRITE done to make thread-safe */
772         if (!lp_talloc)
773                 lp_talloc = talloc_init("lp_talloc");
774
775         ret = talloc_array(lp_talloc, char, len + 100); /* leave room for substitution */
776
777         if (!ret)
778                 return NULL;
779
780         if (!s)
781                 *ret = 0;
782         else
783                 strlcpy(ret, s, len);
784
785         if (trim_string(ret, "\"", "\"")) {
786                 if (strchr(ret,'"') != NULL)
787                         strlcpy(ret, s, len);
788         }
789
790         standard_sub_basic(ret,len+100);
791         return (ret);
792 #endif
793         return s;
794 }
795
796 /*
797    In this section all the functions that are used to access the 
798    parameters from the rest of the program are defined 
799 */
800
801 #define FN_GLOBAL_STRING(fn_name,ptr) \
802  const char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
803 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
804  const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");}
805 #define FN_GLOBAL_LIST(fn_name,ptr) \
806  const char **fn_name(void) {return(*(const char ***)(ptr));}
807 #define FN_GLOBAL_BOOL(fn_name,ptr) \
808  BOOL fn_name(void) {return((BOOL)*(int *)(ptr));}
809 #if 0 /* unused */
810 #define FN_GLOBAL_CHAR(fn_name,ptr) \
811  char fn_name(void) {return(*(char *)(ptr));}
812 #endif
813 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
814  int fn_name(void) {return(*(int *)(ptr));}
815
816 #define FN_LOCAL_STRING(fn_name,val) \
817  const char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
818 #define FN_LOCAL_CONST_STRING(fn_name,val) \
819  const char *fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
820 #define FN_LOCAL_LIST(fn_name,val) \
821  const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
822 #define FN_LOCAL_BOOL(fn_name,val) \
823  BOOL fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
824 #if 0 /* unused */
825 #define FN_LOCAL_CHAR(fn_name,val) \
826  char fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
827 #endif
828 #define FN_LOCAL_INTEGER(fn_name,val) \
829  int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
830
831 _PUBLIC_ FN_GLOBAL_INTEGER(lp_server_role, &Globals.server_role)
832 _PUBLIC_ FN_GLOBAL_LIST(lp_smb_ports, &Globals.smb_ports)
833 _PUBLIC_ FN_GLOBAL_INTEGER(lp_nbt_port, &Globals.nbt_port)
834 _PUBLIC_ FN_GLOBAL_INTEGER(lp_dgram_port, &Globals.dgram_port)
835 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cldap_port, &Globals.cldap_port)
836 _PUBLIC_ FN_GLOBAL_INTEGER(lp_krb5_port, &Globals.krb5_port)
837 _PUBLIC_ FN_GLOBAL_INTEGER(lp_kpasswd_port, &Globals.kpasswd_port)
838 _PUBLIC_ FN_GLOBAL_INTEGER(lp_web_port, &Globals.web_port)
839 _PUBLIC_ FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
840 _PUBLIC_ FN_GLOBAL_STRING(lp_webapps_directory, &Globals.webapps_directory)
841 _PUBLIC_ FN_GLOBAL_BOOL(lp_tls_enabled, &Globals.tls_enabled)
842 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_keyfile, &Globals.tls_keyfile)
843 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_certfile, &Globals.tls_certfile)
844 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_cafile, &Globals.tls_cafile)
845 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_crlfile, &Globals.tls_crlfile)
846 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_dhpfile, &Globals.tls_dhpfile)
847 _PUBLIC_ FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
848 _PUBLIC_ FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset)
849 _PUBLIC_ FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
850 _PUBLIC_ FN_GLOBAL_STRING(lp_share_backend, &Globals.szShareBackend)
851 _PUBLIC_ FN_GLOBAL_STRING(lp_sam_url, &Globals.szSAM_URL)
852 _PUBLIC_ FN_GLOBAL_STRING(lp_secrets_url, &Globals.szSECRETS_URL)
853 _PUBLIC_ FN_GLOBAL_STRING(lp_spoolss_url, &Globals.szSPOOLSS_URL)
854 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_config_url, &Globals.szWINS_CONFIG_URL)
855 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_url, &Globals.szWINS_URL)
856 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
857 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_winbindd_socket_directory, &Globals.szWinbinddSocketDirectory)
858 _PUBLIC_ FN_GLOBAL_BOOL(lp_winbind_sealed_pipes, &Globals.bWinbindSealedPipes)
859 _PUBLIC_ FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
860 _PUBLIC_ FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
861 _PUBLIC_ FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
862 _PUBLIC_ FN_GLOBAL_STRING(lp_modulesdir, &Globals.szModulesDir)
863 _PUBLIC_ FN_GLOBAL_STRING(lp_setupdir, &Globals.szSetupDir)
864 _PUBLIC_ FN_GLOBAL_STRING(lp_ncalrpc_dir, &Globals.ncalrpc_dir)
865 _PUBLIC_ FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
866 _PUBLIC_ FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, &Globals.dcerpc_ep_servers)
867 _PUBLIC_ FN_GLOBAL_LIST(lp_server_services, &Globals.server_services)
868 _PUBLIC_ FN_GLOBAL_STRING(lp_ntptr_providor, &Globals.ntptr_providor)
869 _PUBLIC_ FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
870 _PUBLIC_ FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
871 _PUBLIC_ FN_GLOBAL_LIST(lp_passwordserver, &Globals.szPasswordServers)
872 _PUBLIC_ FN_GLOBAL_LIST(lp_name_resolve_order, &Globals.szNameResolveOrder)
873 _PUBLIC_ FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
874 _PUBLIC_ FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
875 _PUBLIC_ FN_GLOBAL_STRING(lp_workgroup, &Globals.szWorkgroup)
876 _PUBLIC_ FN_GLOBAL_STRING(lp_netbios_name, &Globals.szNetbiosName)
877 _PUBLIC_ FN_GLOBAL_STRING(lp_netbios_scope, &Globals.szNetbiosScope)
878 _PUBLIC_ FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
879 _PUBLIC_ FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
880 _PUBLIC_ FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
881 _PUBLIC_ FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
882
883 _PUBLIC_ FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
884 _PUBLIC_ FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
885 _PUBLIC_ FN_GLOBAL_BOOL(lp_wins_dns_proxy, &Globals.bWINSdnsProxy)
886 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
887 _PUBLIC_ FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
888 _PUBLIC_ FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
889 _PUBLIC_ FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
890 _PUBLIC_ FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw)
891 _PUBLIC_ FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords)
892 _PUBLIC_ FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions)
893 _PUBLIC_ FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
894 _PUBLIC_ FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
895 _PUBLIC_ FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
896 _PUBLIC_ FN_GLOBAL_BOOL(lp_unicode, &Globals.bUnicode)
897 _PUBLIC_ FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
898 _PUBLIC_ FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
899 _PUBLIC_ FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
900 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_plaintext_auth, &Globals.bClientPlaintextAuth)
901 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
902 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
903 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_use_spnego_principal, &Globals.client_use_spnego_principal)
904 _PUBLIC_ FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
905 _PUBLIC_ FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions)
906 _PUBLIC_ FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
907 _PUBLIC_ FN_GLOBAL_BOOL(lp_rpc_big_endian, &Globals.bRpcBigEndian)
908 _PUBLIC_ FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
909 _PUBLIC_ FN_GLOBAL_INTEGER(lp_min_wins_ttl, &Globals.min_wins_ttl)
910 _PUBLIC_ FN_GLOBAL_INTEGER(lp_maxmux, &Globals.max_mux)
911 _PUBLIC_ FN_GLOBAL_INTEGER(lp_max_xmit, &Globals.max_xmit)
912 _PUBLIC_ FN_GLOBAL_INTEGER(lp_passwordlevel, &Globals.pwordlevel)
913 _PUBLIC_ FN_GLOBAL_INTEGER(lp_srv_maxprotocol, &Globals.srv_maxprotocol)
914 _PUBLIC_ FN_GLOBAL_INTEGER(lp_srv_minprotocol, &Globals.srv_minprotocol)
915 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cli_maxprotocol, &Globals.cli_maxprotocol)
916 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cli_minprotocol, &Globals.cli_minprotocol)
917 _PUBLIC_ FN_GLOBAL_INTEGER(lp_security, &Globals.security)
918 _PUBLIC_ FN_GLOBAL_LIST(lp_auth_methods, &Globals.AuthMethods)
919 _PUBLIC_ FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security)
920 _PUBLIC_ FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as)
921 _PUBLIC_ FN_GLOBAL_LIST(lp_js_include, &Globals.jsInclude)
922 _PUBLIC_ FN_GLOBAL_STRING(lp_jsonrpc_services_dir, &Globals.jsonrpcServicesDir)
923 _PUBLIC_ 
924 _PUBLIC_ 
925 _PUBLIC_ FN_LOCAL_STRING(lp_servicename, szService)
926 _PUBLIC_ FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
927 _PUBLIC_ FN_LOCAL_STRING(lp_pathname, szPath)
928 static FN_LOCAL_STRING(_lp_printername, szPrintername)
929 _PUBLIC_ FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
930 _PUBLIC_ FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
931 _PUBLIC_ FN_LOCAL_STRING(lp_comment, comment)
932 _PUBLIC_ FN_LOCAL_STRING(lp_fstype, fstype)
933 static FN_LOCAL_STRING(lp_volume, volume)
934 _PUBLIC_ FN_LOCAL_LIST(lp_ntvfs_handler, ntvfs_handler)
935 _PUBLIC_ FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
936 _PUBLIC_ FN_LOCAL_BOOL(lp_browseable, bBrowseable)
937 _PUBLIC_ FN_LOCAL_BOOL(lp_readonly, bRead_only)
938 _PUBLIC_ FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
939 _PUBLIC_ FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
940 _PUBLIC_ FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
941 _PUBLIC_ FN_LOCAL_BOOL(lp_strict_locking, bStrictLocking)
942 _PUBLIC_ FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
943 _PUBLIC_ FN_LOCAL_BOOL(lp_ci_filesystem, bCIFileSystem)
944 _PUBLIC_ FN_LOCAL_BOOL(lp_map_system, bMap_system)
945 _PUBLIC_ FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
946 _PUBLIC_ FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
947 _PUBLIC_ FN_LOCAL_INTEGER(lp_create_mask, iCreate_mask)
948 _PUBLIC_ FN_LOCAL_INTEGER(lp_force_create_mode, iCreate_force_mode)
949 _PUBLIC_ FN_LOCAL_INTEGER(lp_dir_mask, iDir_mask)
950 _PUBLIC_ FN_LOCAL_INTEGER(lp_force_dir_mode, iDir_force_mode)
951 _PUBLIC_ FN_GLOBAL_INTEGER(lp_server_signing, &Globals.server_signing)
952 _PUBLIC_ FN_GLOBAL_INTEGER(lp_client_signing, &Globals.client_signing)
953
954 /* local prototypes */
955
956 static int map_parameter(const char *pszParmName);
957 static int getservicebyname(const char *pszServiceName,
958                             service * pserviceDest);
959 static void copy_service(service * pserviceDest,
960                          service * pserviceSource, int *pcopymapDest);
961 static BOOL service_ok(int iService);
962 static BOOL do_section(const char *pszSectionName, void *);
963 static void init_copymap(service * pservice);
964
965 /* This is a helper function for parametrical options support. */
966 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
967 /* Actual parametrical functions are quite simple */
968 const char *lp_get_parametric(int lookup_service, const char *type, const char *option)
969 {
970         char *vfskey;
971         struct param_opt *data;
972         
973         if (lookup_service >= iNumServices) return NULL;
974         
975         data = (lookup_service < 0) ? 
976                 Globals.param_opt : ServicePtrs[lookup_service]->param_opt;
977     
978         asprintf(&vfskey, "%s:%s", type, option);
979         strlower(vfskey);
980
981         while (data) {
982                 if (strcmp(data->key, vfskey) == 0) {
983                         free(vfskey);
984                         return data->value;
985                 }
986                 data = data->next;
987         }
988
989         if (lookup_service >= 0) {
990                 /* Try to fetch the same option but from globals */
991                 /* but only if we are not already working with Globals */
992                 data = Globals.param_opt;
993                 while (data) {
994                         if (strcmp(data->key, vfskey) == 0) {
995                                 free(vfskey);
996                                 return data->value;
997                         }
998                         data = data->next;
999                 }
1000         }
1001
1002         free(vfskey);
1003         
1004         return NULL;
1005 }
1006
1007
1008 /*******************************************************************
1009 convenience routine to return int parameters.
1010 ********************************************************************/
1011 static int lp_int(const char *s)
1012 {
1013
1014         if (!s) {
1015                 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
1016                 return (-1);
1017         }
1018
1019         return strtol(s, NULL, 0); 
1020 }
1021
1022 /*******************************************************************
1023 convenience routine to return unsigned long parameters.
1024 ********************************************************************/
1025 static int lp_ulong(const char *s)
1026 {
1027
1028         if (!s) {
1029                 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
1030                 return (-1);
1031         }
1032
1033         return strtoul(s, NULL, 0);
1034 }
1035
1036 /*******************************************************************
1037 convenience routine to return unsigned long parameters.
1038 ********************************************************************/
1039 static double lp_double(const char *s)
1040 {
1041
1042         if (!s) {
1043                 DEBUG(0,("lp_double(%s): is called with NULL!\n",s));
1044                 return (-1);
1045         }
1046
1047         return strtod(s, NULL);
1048 }
1049
1050 /*******************************************************************
1051 convenience routine to return boolean parameters.
1052 ********************************************************************/
1053 static BOOL lp_bool(const char *s)
1054 {
1055         BOOL ret = False;
1056
1057         if (!s) {
1058                 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
1059                 return False;
1060         }
1061         
1062         if (!set_boolean(s, &ret)) {
1063                 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1064                 return False;
1065         }
1066
1067         return ret;
1068 }
1069
1070
1071 /* Return parametric option from a given service. Type is a part of option before ':' */
1072 /* Parametric option has following syntax: 'Type: option = value' */
1073 /* Returned value is allocated in 'lp_talloc' context */
1074
1075 const char *lp_parm_string(int lookup_service, const char *type, const char *option)
1076 {
1077         const char *value = lp_get_parametric(lookup_service, type, option);
1078
1079         if (value)
1080                 return lp_string(value);
1081
1082         return NULL;
1083 }
1084
1085 /* Return parametric option from a given service. Type is a part of option before ':' */
1086 /* Parametric option has following syntax: 'Type: option = value' */
1087 /* Returned value is allocated in 'lp_talloc' context */
1088
1089 const char **lp_parm_string_list(int lookup_service, const char *type, const char *option,
1090                                  const char *separator)
1091 {
1092         const char *value = lp_get_parametric(lookup_service, type, option);
1093         
1094         if (value)
1095                 return str_list_make(talloc_autofree_context(), value, separator);
1096
1097         return NULL;
1098 }
1099
1100 /* Return parametric option from a given service. Type is a part of option before ':' */
1101 /* Parametric option has following syntax: 'Type: option = value' */
1102
1103 int lp_parm_int(int lookup_service, const char *type, const char *option, int default_v)
1104 {
1105         const char *value = lp_get_parametric(lookup_service, type, option);
1106         
1107         if (value)
1108                 return lp_int(value);
1109
1110         return default_v;
1111 }
1112
1113 /* Return parametric option from a given service. Type is a part of
1114  * option before ':'.
1115  * Parametric option has following syntax: 'Type: option = value'.
1116  */
1117
1118 int lp_parm_bytes(int lookup_service, const char *type, const char *option, int default_v)
1119 {
1120         uint64_t bval;
1121
1122         const char *value = lp_get_parametric(lookup_service, type, option);
1123
1124         if (value && conv_str_size(value, &bval)) {
1125                 if (bval <= INT_MAX) {
1126                         return (int)bval;
1127                 }
1128         }
1129
1130         return default_v;
1131 }
1132
1133 /* Return parametric option from a given service. Type is a part of option before ':' */
1134 /* Parametric option has following syntax: 'Type: option = value' */
1135
1136 unsigned long lp_parm_ulong(int lookup_service, const char *type, const char *option, unsigned long default_v)
1137 {
1138         const char *value = lp_get_parametric(lookup_service, type, option);
1139         
1140         if (value)
1141                 return lp_ulong(value);
1142
1143         return default_v;
1144 }
1145
1146
1147 double lp_parm_double(int lookup_service, const char *type, const char *option, double default_v)
1148 {
1149         const char *value = lp_get_parametric(lookup_service, type, option);
1150         
1151         if (value)
1152                 return lp_double(value);
1153
1154         return default_v;
1155 }
1156
1157 /* Return parametric option from a given service. Type is a part of option before ':' */
1158 /* Parametric option has following syntax: 'Type: option = value' */
1159
1160 BOOL lp_parm_bool(int lookup_service, const char *type, const char *option, BOOL default_v)
1161 {
1162         const char *value = lp_get_parametric(lookup_service, type, option);
1163         
1164         if (value)
1165                 return lp_bool(value);
1166
1167         return default_v;
1168 }
1169
1170
1171 /***************************************************************************
1172  Initialise a service to the defaults.
1173 ***************************************************************************/
1174
1175 static void init_service(service * pservice)
1176 {
1177         memset((char *)pservice, '\0', sizeof(service));
1178         copy_service(pservice, &sDefault, NULL);
1179 }
1180
1181 /***************************************************************************
1182  Free the dynamically allocated parts of a service struct.
1183 ***************************************************************************/
1184
1185 static void free_service(service *pservice)
1186 {
1187         int i;
1188         struct param_opt *data, *pdata;
1189         if (!pservice)
1190                 return;
1191
1192         if (pservice->szService)
1193                 DEBUG(5, ("free_service: Freeing service %s\n",
1194                        pservice->szService));
1195
1196         string_free(&pservice->szService);
1197         SAFE_FREE(pservice->copymap);
1198
1199         for (i = 0; parm_table[i].label; i++) {
1200                 if ((parm_table[i].type == P_STRING ||
1201                      parm_table[i].type == P_USTRING) &&
1202                     parm_table[i].class == P_LOCAL) {
1203                         string_free((char **)
1204                                     (((char *)pservice) +
1205                                      PTR_DIFF(parm_table[i].ptr, &sDefault)));
1206                 } else if (parm_table[i].type == P_LIST &&
1207                            parm_table[i].class == P_LOCAL) {
1208                         char ***listp = (char ***)(((char *)pservice) + 
1209                                                    PTR_DIFF(parm_table[i].ptr, &sDefault));
1210                         talloc_free(*listp);
1211                         *listp = NULL;
1212                 }
1213         }
1214                                 
1215         DEBUG(5,("Freeing parametrics:\n"));
1216         data = pservice->param_opt;
1217         while (data) {
1218                 DEBUG(5,("[%s = %s]\n", data->key, data->value));
1219                 string_free(&data->key);
1220                 string_free(&data->value);
1221                 pdata = data->next;
1222                 SAFE_FREE(data);
1223                 data = pdata;
1224         }
1225
1226         ZERO_STRUCTP(pservice);
1227 }
1228
1229 /***************************************************************************
1230  Add a new service to the services array initialising it with the given 
1231  service. 
1232 ***************************************************************************/
1233
1234 static int add_a_service(const service *pservice, const char *name)
1235 {
1236         int i;
1237         service tservice;
1238         int num_to_alloc = iNumServices + 1;
1239         struct param_opt *data, *pdata;
1240
1241         tservice = *pservice;
1242
1243         /* it might already exist */
1244         if (name) {
1245                 i = getservicebyname(name, NULL);
1246                 if (i >= 0) {
1247                         /* Clean all parametric options for service */
1248                         /* They will be added during parsing again */
1249                         data = ServicePtrs[i]->param_opt;
1250                         while (data) {
1251                                 string_free(&data->key);
1252                                 string_free(&data->value);
1253                                 pdata = data->next;
1254                                 SAFE_FREE(data);
1255                                 data = pdata;
1256                         }
1257                         ServicePtrs[i]->param_opt = NULL;
1258                         return (i);
1259                 }
1260         }
1261
1262         /* find an invalid one */
1263         for (i = 0; i < iNumServices; i++)
1264                 if (!ServicePtrs[i]->valid)
1265                         break;
1266
1267         /* if not, then create one */
1268         if (i == iNumServices) {
1269                 service **tsp;
1270                 
1271                 tsp = realloc_p(ServicePtrs, service *, num_to_alloc);
1272                                            
1273                 if (!tsp) {
1274                         DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1275                         return (-1);
1276                 }
1277                 else {
1278                         ServicePtrs = tsp;
1279                         ServicePtrs[iNumServices] = malloc_p(service);
1280                 }
1281                 if (!ServicePtrs[iNumServices]) {
1282                         DEBUG(0,("add_a_service: out of memory!\n"));
1283                         return (-1);
1284                 }
1285
1286                 iNumServices++;
1287         } else
1288                 free_service(ServicePtrs[i]);
1289
1290         ServicePtrs[i]->valid = True;
1291
1292         init_service(ServicePtrs[i]);
1293         copy_service(ServicePtrs[i], &tservice, NULL);
1294         if (name)
1295                 string_set(&ServicePtrs[i]->szService, name);
1296         return (i);
1297 }
1298
1299 /***************************************************************************
1300  Add a new home service, with the specified home directory, defaults coming 
1301  from service ifrom.
1302 ***************************************************************************/
1303
1304 BOOL lp_add_home(const char *pszHomename, int iDefaultService, 
1305                  const char *user, const char *pszHomedir)
1306 {
1307         int i;
1308         pstring newHomedir;
1309
1310         i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1311
1312         if (i < 0)
1313                 return (False);
1314
1315         if (!(*(ServicePtrs[iDefaultService]->szPath))
1316             || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(-1))) {
1317                 pstrcpy(newHomedir, pszHomedir);
1318         } else {
1319                 pstrcpy(newHomedir, lp_pathname(iDefaultService));
1320                 string_sub(newHomedir,"%H", pszHomedir, sizeof(newHomedir)); 
1321         }
1322
1323         string_set(&ServicePtrs[i]->szPath, newHomedir);
1324
1325         if (!(*(ServicePtrs[i]->comment))) {
1326                 pstring comment;
1327                 slprintf(comment, sizeof(comment) - 1,
1328                          "Home directory of %s", user);
1329                 string_set(&ServicePtrs[i]->comment, comment);
1330         }
1331         ServicePtrs[i]->bAvailable = sDefault.bAvailable;
1332         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1333
1334         DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename, 
1335                user, newHomedir));
1336         
1337         return (True);
1338 }
1339
1340 /***************************************************************************
1341  Add a new service, based on an old one.
1342 ***************************************************************************/
1343
1344 int lp_add_service(const char *pszService, int iDefaultService)
1345 {
1346         return (add_a_service(ServicePtrs[iDefaultService], pszService));
1347 }
1348
1349 /***************************************************************************
1350  Add the IPC service.
1351 ***************************************************************************/
1352
1353 static BOOL lp_add_hidden(const char *name, const char *fstype)
1354 {
1355         pstring comment;
1356         int i = add_a_service(&sDefault, name);
1357
1358         if (i < 0)
1359                 return (False);
1360
1361         slprintf(comment, sizeof(comment) - 1,
1362                  "%s Service (%s)", fstype, Globals.szServerString);
1363
1364         string_set(&ServicePtrs[i]->szPath, tmpdir());
1365         string_set(&ServicePtrs[i]->comment, comment);
1366         string_set(&ServicePtrs[i]->fstype, fstype);
1367         ServicePtrs[i]->iMaxConnections = -1;
1368         ServicePtrs[i]->bAvailable = True;
1369         ServicePtrs[i]->bRead_only = True;
1370         ServicePtrs[i]->bPrint_ok = False;
1371         ServicePtrs[i]->bBrowseable = False;
1372
1373         if (strcasecmp(fstype, "IPC") == 0) {
1374                 lp_do_parameter(i, "ntvfs handler", "default");
1375         }
1376
1377         DEBUG(3, ("adding hidden service %s\n", name));
1378
1379         return (True);
1380 }
1381
1382 /***************************************************************************
1383  Add a new printer service, with defaults coming from service iFrom.
1384 ***************************************************************************/
1385
1386 BOOL lp_add_printer(const char *pszPrintername, int iDefaultService)
1387 {
1388         const char *comment = "From Printcap";
1389         int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1390
1391         if (i < 0)
1392                 return (False);
1393
1394         /* note that we do NOT default the availability flag to True - */
1395         /* we take it from the default service passed. This allows all */
1396         /* dynamic printers to be disabled by disabling the [printers] */
1397         /* entry (if/when the 'available' keyword is implemented!).    */
1398
1399         /* the printer name is set to the service name. */
1400         string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1401         string_set(&ServicePtrs[i]->comment, comment);
1402         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1403         /* Printers cannot be read_only. */
1404         ServicePtrs[i]->bRead_only = False;
1405         /* Printer services must be printable. */
1406         ServicePtrs[i]->bPrint_ok = True;
1407
1408         DEBUG(3, ("adding printer service %s\n", pszPrintername));
1409
1410         return (True);
1411 }
1412
1413 /***************************************************************************
1414  Map a parameter's string representation to something we can use. 
1415  Returns False if the parameter string is not recognised, else TRUE.
1416 ***************************************************************************/
1417
1418 static int map_parameter(const char *pszParmName)
1419 {
1420         int iIndex;
1421
1422         if (*pszParmName == '-')
1423                 return (-1);
1424
1425         for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1426                 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1427                         return (iIndex);
1428
1429         /* Warn only if it isn't parametric option */
1430         if (strchr(pszParmName, ':') == NULL)
1431                 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1432         /* We do return 'fail' for parametric options as well because they are
1433            stored in different storage
1434          */
1435         return (-1);
1436 }
1437
1438
1439 /*
1440   return the parameter structure for a parameter
1441 */
1442 struct parm_struct *lp_parm_struct(const char *name)
1443 {
1444         int parmnum = map_parameter(name);
1445         if (parmnum == -1) return NULL;
1446         return &parm_table[parmnum];
1447 }
1448
1449 /*
1450   return the parameter pointer for a parameter
1451 */
1452 void *lp_parm_ptr(int snum, struct parm_struct *parm)
1453 {
1454         if (snum == -1) {
1455                 return parm->ptr;
1456         }
1457         return ((char *)ServicePtrs[snum]) + PTR_DIFF(parm->ptr, &sDefault);
1458 }
1459
1460 /***************************************************************************
1461 Find a service by name. Otherwise works like get_service.
1462 ***************************************************************************/
1463
1464 static int getservicebyname(const char *pszServiceName, service * pserviceDest)
1465 {
1466         int iService;
1467
1468         for (iService = iNumServices - 1; iService >= 0; iService--)
1469                 if (VALID(iService) &&
1470                     strwicmp(ServicePtrs[iService]->szService, pszServiceName) == 0) {
1471                         if (pserviceDest != NULL)
1472                                 copy_service(pserviceDest, ServicePtrs[iService], NULL);
1473                         break;
1474                 }
1475
1476         return (iService);
1477 }
1478
1479 /***************************************************************************
1480  Copy a service structure to another.
1481  If pcopymapDest is NULL then copy all fields
1482 ***************************************************************************/
1483
1484 static void copy_service(service * pserviceDest, service * pserviceSource, int *pcopymapDest)
1485 {
1486         int i;
1487         BOOL bcopyall = (pcopymapDest == NULL);
1488         struct param_opt *data, *pdata, *paramo;
1489         BOOL not_added;
1490
1491         for (i = 0; parm_table[i].label; i++)
1492                 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1493                     (bcopyall || pcopymapDest[i])) {
1494                         void *def_ptr = parm_table[i].ptr;
1495                         void *src_ptr =
1496                                 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
1497                                                                     &sDefault);
1498                         void *dest_ptr =
1499                                 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
1500                                                                   &sDefault);
1501
1502                         switch (parm_table[i].type) {
1503                                 case P_BOOL:
1504                                         *(int *)dest_ptr = *(int *)src_ptr;
1505                                         break;
1506
1507                                 case P_INTEGER:
1508                                 case P_OCTAL:
1509                                 case P_ENUM:
1510                                         *(int *)dest_ptr = *(int *)src_ptr;
1511                                         break;
1512
1513                                 case P_STRING:
1514                                         string_set(dest_ptr,
1515                                                    *(char **)src_ptr);
1516                                         break;
1517
1518                                 case P_USTRING:
1519                                         string_set(dest_ptr,
1520                                                    *(char **)src_ptr);
1521                                         strupper(*(char **)dest_ptr);
1522                                         break;
1523                                 case P_LIST:
1524                                         *(const char ***)dest_ptr = str_list_copy(talloc_autofree_context(), 
1525                                                                                   *(const char ***)src_ptr);
1526                                         break;
1527                                 default:
1528                                         break;
1529                         }
1530                 }
1531
1532         if (bcopyall) {
1533                 init_copymap(pserviceDest);
1534                 if (pserviceSource->copymap)
1535                         memcpy((void *)pserviceDest->copymap,
1536                                (void *)pserviceSource->copymap,
1537                                sizeof(int) * NUMPARAMETERS);
1538         }
1539         
1540         data = pserviceSource->param_opt;
1541         while (data) {
1542                 not_added = True;
1543                 pdata = pserviceDest->param_opt;
1544                 /* Traverse destination */
1545                 while (pdata) {
1546                         /* If we already have same option, override it */
1547                         if (strcmp(pdata->key, data->key) == 0) {
1548                                 string_free(&pdata->value);
1549                                 pdata->value = strdup(data->value);
1550                                 not_added = False;
1551                                 break;
1552                         }
1553                         pdata = pdata->next;
1554                 }
1555                 if (not_added) {
1556                         paramo = malloc_p(struct param_opt);
1557                         if (!paramo)
1558                                 smb_panic("OOM");
1559                         paramo->key = strdup(data->key);
1560                         paramo->value = strdup(data->value);
1561                         DLIST_ADD(pserviceDest->param_opt, paramo);
1562                 }
1563                 data = data->next;
1564         }
1565 }
1566
1567 /***************************************************************************
1568 Check a service for consistency. Return False if the service is in any way
1569 incomplete or faulty, else True.
1570 ***************************************************************************/
1571
1572 static BOOL service_ok(int iService)
1573 {
1574         BOOL bRetval;
1575
1576         bRetval = True;
1577         if (ServicePtrs[iService]->szService[0] == '\0') {
1578                 DEBUG(0, ("The following message indicates an internal error:\n"));
1579                 DEBUG(0, ("No service name in service entry.\n"));
1580                 bRetval = False;
1581         }
1582
1583         /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1584         /* I can't see why you'd want a non-printable printer service...        */
1585         if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
1586                 if (!ServicePtrs[iService]->bPrint_ok) {
1587                         DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
1588                                ServicePtrs[iService]->szService));
1589                         ServicePtrs[iService]->bPrint_ok = True;
1590                 }
1591                 /* [printers] service must also be non-browsable. */
1592                 if (ServicePtrs[iService]->bBrowseable)
1593                         ServicePtrs[iService]->bBrowseable = False;
1594         }
1595
1596         /* If a service is flagged unavailable, log the fact at level 0. */
1597         if (!ServicePtrs[iService]->bAvailable)
1598                 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
1599                           ServicePtrs[iService]->szService));
1600
1601         return (bRetval);
1602 }
1603
1604 static struct file_lists {
1605         struct file_lists *next;
1606         char *name;
1607         char *subfname;
1608         time_t modtime;
1609 } *file_lists = NULL;
1610
1611 /*******************************************************************
1612  Keep a linked list of all config files so we know when one has changed 
1613  it's date and needs to be reloaded.
1614 ********************************************************************/
1615
1616 static void add_to_file_list(const char *fname, const char *subfname)
1617 {
1618         struct file_lists *f = file_lists;
1619
1620         while (f) {
1621                 if (f->name && !strcmp(f->name, fname))
1622                         break;
1623                 f = f->next;
1624         }
1625
1626         if (!f) {
1627                 f = malloc_p(struct file_lists);
1628                 if (!f)
1629                         return;
1630                 f->next = file_lists;
1631                 f->name = strdup(fname);
1632                 if (!f->name) {
1633                         SAFE_FREE(f);
1634                         return;
1635                 }
1636                 f->subfname = strdup(subfname);
1637                 if (!f->subfname) {
1638                         SAFE_FREE(f);
1639                         return;
1640                 }
1641                 file_lists = f;
1642                 f->modtime = file_modtime(subfname);
1643         } else {
1644                 time_t t = file_modtime(subfname);
1645                 if (t)
1646                         f->modtime = t;
1647         }
1648 }
1649
1650 /*******************************************************************
1651  Check if a config file has changed date.
1652 ********************************************************************/
1653
1654 BOOL lp_file_list_changed(void)
1655 {
1656         struct file_lists *f = file_lists;
1657         DEBUG(6, ("lp_file_list_changed()\n"));
1658
1659         while (f) {
1660                 pstring n2;
1661                 time_t mod_time;
1662
1663                 pstrcpy(n2, f->name);
1664                 standard_sub_basic(n2,sizeof(n2));
1665
1666                 DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
1667                              f->name, n2, ctime(&f->modtime)));
1668
1669                 mod_time = file_modtime(n2);
1670
1671                 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
1672                         DEBUGADD(6,
1673                                  ("file %s modified: %s\n", n2,
1674                                   ctime(&mod_time)));
1675                         f->modtime = mod_time;
1676                         SAFE_FREE(f->subfname);
1677                         f->subfname = strdup(n2);
1678                         return (True);
1679                 }
1680                 f = f->next;
1681         }
1682         return (False);
1683 }
1684
1685 /***************************************************************************
1686  Handle the include operation.
1687 ***************************************************************************/
1688
1689 static BOOL handle_include(const char *pszParmValue, char **ptr)
1690 {
1691         pstring fname;
1692         pstrcpy(fname, pszParmValue);
1693
1694         standard_sub_basic(fname,sizeof(fname));
1695
1696         add_to_file_list(pszParmValue, fname);
1697
1698         string_set(ptr, fname);
1699
1700         if (file_exist(fname))
1701                 return (pm_process(fname, do_section, do_parameter, NULL));
1702
1703         DEBUG(2, ("Can't find include file %s\n", fname));
1704
1705         return (False);
1706 }
1707
1708 /***************************************************************************
1709  Handle the interpretation of the copy parameter.
1710 ***************************************************************************/
1711
1712 static BOOL handle_copy(const char *pszParmValue, char **ptr)
1713 {
1714         BOOL bRetval;
1715         int iTemp;
1716         service serviceTemp;
1717
1718         string_set(ptr, pszParmValue);
1719
1720         init_service(&serviceTemp);
1721
1722         bRetval = False;
1723
1724         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
1725
1726         if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
1727                 if (iTemp == iServiceIndex) {
1728                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
1729                 } else {
1730                         copy_service(ServicePtrs[iServiceIndex],
1731                                      &serviceTemp,
1732                                      ServicePtrs[iServiceIndex]->copymap);
1733                         bRetval = True;
1734                 }
1735         } else {
1736                 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
1737                 bRetval = False;
1738         }
1739
1740         free_service(&serviceTemp);
1741         return (bRetval);
1742 }
1743
1744 /***************************************************************************
1745  Initialise a copymap.
1746 ***************************************************************************/
1747
1748 static void init_copymap(service * pservice)
1749 {
1750         int i;
1751         SAFE_FREE(pservice->copymap);
1752         pservice->copymap = malloc_array_p(int, NUMPARAMETERS);
1753         if (!pservice->copymap)
1754                 DEBUG(0,
1755                       ("Couldn't allocate copymap!! (size %d)\n",
1756                        (int)NUMPARAMETERS));
1757         else
1758                 for (i = 0; i < NUMPARAMETERS; i++)
1759                         pservice->copymap[i] = True;
1760 }
1761
1762 #if 0 /* not used anywhere */
1763 /***************************************************************************
1764  Return the local pointer to a parameter given the service number and the 
1765  pointer into the default structure.
1766 ***************************************************************************/
1767
1768 void *lp_local_ptr(int snum, void *ptr)
1769 {
1770         return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
1771 }
1772 #endif
1773
1774 /***************************************************************************
1775  Process a parametric option
1776 ***************************************************************************/
1777 static BOOL lp_do_parameter_parametric(int snum, const char *pszParmName, const char *pszParmValue, int flags)
1778 {
1779         struct param_opt *paramo, *data;
1780         char *name;
1781
1782         while (isspace((unsigned char)*pszParmName)) {
1783                 pszParmName++;
1784         }
1785
1786         name = strdup(pszParmName);
1787         if (!name) return False;
1788
1789         strlower(name);
1790
1791         if (snum < 0) {
1792                 data = Globals.param_opt;
1793         } else {
1794                 data = ServicePtrs[snum]->param_opt;
1795         }
1796
1797         /* Traverse destination */
1798         for (paramo=data; paramo; paramo=paramo->next) {
1799                 /* If we already have the option set, override it unless
1800                    it was a command line option and the new one isn't */
1801                 if (strcmp(paramo->key, name) == 0) {
1802                         if ((paramo->flags & FLAG_CMDLINE) &&
1803                             !(flags & FLAG_CMDLINE)) {
1804                                 return True;
1805                         }
1806
1807                         free(paramo->value);
1808                         paramo->value = strdup(pszParmValue);
1809                         paramo->flags = flags;
1810                         free(name);
1811                         return True;
1812                 }
1813         }
1814
1815         paramo = malloc_p(struct param_opt);
1816         if (!paramo)
1817                 smb_panic("OOM");
1818         paramo->key = strdup(name);
1819         paramo->value = strdup(pszParmValue);
1820         paramo->flags = flags;
1821         if (snum < 0) {
1822                 DLIST_ADD(Globals.param_opt, paramo);
1823         } else {
1824                 DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
1825         }
1826
1827         free(name);
1828         
1829         return True;
1830 }
1831
1832 /***************************************************************************
1833  Process a parameter for a particular service number. If snum < 0
1834  then assume we are in the globals.
1835 ***************************************************************************/
1836 BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
1837 {
1838         int parmnum, i;
1839         void *parm_ptr = NULL;  /* where we are going to store the result */
1840         void *def_ptr = NULL;
1841
1842         parmnum = map_parameter(pszParmName);
1843
1844         if (parmnum < 0) {
1845                 if (strchr(pszParmName, ':')) {
1846                         return lp_do_parameter_parametric(snum, pszParmName, pszParmValue, 0);
1847                 }
1848                 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1849                 return (True);
1850         }
1851
1852         if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1853                 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1854                           pszParmName));
1855         }
1856
1857         /* if the flag has been set on the command line, then don't allow override,
1858            but don't report an error */
1859         if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1860                 return True;
1861         }
1862
1863         def_ptr = parm_table[parmnum].ptr;
1864
1865         /* we might point at a service, the default service or a global */
1866         if (snum < 0) {
1867                 parm_ptr = def_ptr;
1868         } else {
1869                 if (parm_table[parmnum].class == P_GLOBAL) {
1870                         DEBUG(0,
1871                               ("Global parameter %s found in service section!\n",
1872                                pszParmName));
1873                         return (True);
1874                 }
1875                 parm_ptr =
1876                         ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
1877                                                             &sDefault);
1878         }
1879
1880         if (snum >= 0) {
1881                 if (!ServicePtrs[snum]->copymap)
1882                         init_copymap(ServicePtrs[snum]);
1883
1884                 /* this handles the aliases - set the copymap for other entries with
1885                    the same data pointer */
1886                 for (i = 0; parm_table[i].label; i++)
1887                         if (parm_table[i].ptr == parm_table[parmnum].ptr)
1888                                 ServicePtrs[snum]->copymap[i] = False;
1889         }
1890
1891         /* if it is a special case then go ahead */
1892         if (parm_table[parmnum].special) {
1893                 parm_table[parmnum].special(pszParmValue, (char **)parm_ptr);
1894                 return (True);
1895         }
1896
1897         /* now switch on the type of variable it is */
1898         switch (parm_table[parmnum].type)
1899         {
1900                 case P_BOOL: {
1901                         BOOL b;
1902                         if (!set_boolean(pszParmValue, &b)) {
1903                                 DEBUG(0,("lp_do_parameter(%s): value is not boolean!\n", pszParmValue));
1904                                 return False;
1905                         }
1906                         *(int *)parm_ptr = b;
1907                         }
1908                         break;
1909
1910                 case P_INTEGER:
1911                         *(int *)parm_ptr = atoi(pszParmValue);
1912                         break;
1913
1914                 case P_OCTAL:
1915                         *(int *)parm_ptr = strtol(pszParmValue, NULL, 8);
1916                         break;
1917
1918                 case P_BYTES:
1919                 {
1920                         uint64_t val;
1921                         if (conv_str_size(pszParmValue, &val)) {
1922                                 if (val <= INT_MAX) {
1923                                         *(int *)parm_ptr = (int)val;
1924                                         break;
1925                                 }
1926                         }
1927
1928                         DEBUG(0,("lp_do_parameter(%s): value is not "
1929                             "a valid size specifier!\n", pszParmValue));
1930                         return False;
1931                 }
1932
1933                 case P_LIST:
1934                         *(const char ***)parm_ptr = str_list_make(talloc_autofree_context(), 
1935                                                                   pszParmValue, NULL);
1936                         break;
1937
1938                 case P_STRING:
1939                         string_set(parm_ptr, pszParmValue);
1940                         break;
1941
1942                 case P_USTRING:
1943                         string_set(parm_ptr, pszParmValue);
1944                         strupper(*(char **)parm_ptr);
1945                         break;
1946
1947                 case P_ENUM:
1948                         for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
1949                                 if (strequal
1950                                     (pszParmValue,
1951                                      parm_table[parmnum].enum_list[i].name)) {
1952                                         *(int *)parm_ptr =
1953                                                 parm_table[parmnum].
1954                                                 enum_list[i].value;
1955                                         break;
1956                                 }
1957                         }
1958                         if (!parm_table[parmnum].enum_list[i].name) {
1959                                 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n", 
1960                                          pszParmValue, pszParmName));
1961                                 return False;
1962                         }
1963                         break;
1964                 case P_SEP:
1965                         break;
1966         }
1967
1968         if (parm_table[parmnum].flags & FLAG_DEFAULT) {
1969                 parm_table[parmnum].flags &= ~FLAG_DEFAULT;
1970                 /* we have to also unset FLAG_DEFAULT on aliases */
1971                 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1972                         parm_table[i].flags &= ~FLAG_DEFAULT;
1973                 }
1974                 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1975                         parm_table[i].flags &= ~FLAG_DEFAULT;
1976                 }
1977         }
1978
1979         return (True);
1980 }
1981
1982 /***************************************************************************
1983  Process a parameter.
1984 ***************************************************************************/
1985
1986 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue, void *userdata)
1987 {
1988         return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
1989                                 pszParmName, pszParmValue));
1990 }
1991
1992 /*
1993   variable argument do parameter
1994 */
1995 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
1996
1997 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...)
1998 {
1999         char *s;
2000         BOOL ret;
2001         va_list ap;
2002
2003         va_start(ap, fmt);      
2004         s = talloc_vasprintf(NULL, fmt, ap);
2005         va_end(ap);
2006         ret = do_parameter(pszParmName, s, NULL);
2007         talloc_free(s);
2008         return ret;
2009 }
2010
2011
2012 /*
2013   set a parameter from the commandline - this is called from command line parameter
2014   parsing code. It sets the parameter then marks the parameter as unable to be modified
2015   by smb.conf processing
2016 */
2017 BOOL lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
2018 {
2019         int parmnum = map_parameter(pszParmName);
2020         int i;
2021
2022         while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
2023
2024
2025         if (parmnum < 0 && strchr(pszParmName, ':')) {
2026                 /* set a parametric option */
2027                 return lp_do_parameter_parametric(-1, pszParmName, pszParmValue, FLAG_CMDLINE);
2028         }
2029
2030         if (parmnum < 0) {
2031                 DEBUG(0,("Unknown option '%s'\n", pszParmName));
2032                 return False;
2033         }
2034
2035         /* reset the CMDLINE flag in case this has been called before */
2036         parm_table[parmnum].flags &= ~FLAG_CMDLINE;
2037
2038         if (!lp_do_parameter(-2, pszParmName, pszParmValue)) {
2039                 return False;
2040         }
2041
2042         parm_table[parmnum].flags |= FLAG_CMDLINE;
2043
2044         /* we have to also set FLAG_CMDLINE on aliases */
2045         for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
2046                 parm_table[i].flags |= FLAG_CMDLINE;
2047         }
2048         for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
2049                 parm_table[i].flags |= FLAG_CMDLINE;
2050         }
2051
2052         return True;
2053 }
2054
2055 /*
2056   set a option from the commandline in 'a=b' format. Use to support --option
2057 */
2058 BOOL lp_set_option(const char *option)
2059 {
2060         char *p, *s;
2061         BOOL ret;
2062
2063         s = strdup(option);
2064         if (!s) {
2065                 return False;
2066         }
2067
2068         p = strchr(s, '=');
2069         if (!p) {
2070                 free(s);
2071                 return False;
2072         }
2073
2074         *p = 0;
2075
2076         ret = lp_set_cmdline(s, p+1);
2077         free(s);
2078         return ret;
2079 }
2080
2081
2082 #define BOOLSTR(b) ((b) ? "Yes" : "No")
2083
2084 /***************************************************************************
2085  Print a parameter of the specified type.
2086 ***************************************************************************/
2087
2088 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
2089 {
2090         int i;
2091         switch (p->type)
2092         {
2093                 case P_ENUM:
2094                         for (i = 0; p->enum_list[i].name; i++) {
2095                                 if (*(int *)ptr == p->enum_list[i].value) {
2096                                         fprintf(f, "%s",
2097                                                 p->enum_list[i].name);
2098                                         break;
2099                                 }
2100                         }
2101                         break;
2102
2103                 case P_BOOL:
2104                         fprintf(f, "%s", BOOLSTR((BOOL)*(int *)ptr));
2105                         break;
2106
2107                 case P_INTEGER:
2108                 case P_BYTES:
2109                         fprintf(f, "%d", *(int *)ptr);
2110                         break;
2111
2112                 case P_OCTAL:
2113                         fprintf(f, "0%o", *(int *)ptr);
2114                         break;
2115
2116                 case P_LIST:
2117                         if ((char ***)ptr && *(char ***)ptr) {
2118                                 char **list = *(char ***)ptr;
2119                                 
2120                                 for (; *list; list++)
2121                                         fprintf(f, "%s%s", *list,
2122                                                 ((*(list+1))?", ":""));
2123                         }
2124                         break;
2125
2126                 case P_STRING:
2127                 case P_USTRING:
2128                         if (*(char **)ptr) {
2129                                 fprintf(f, "%s", *(char **)ptr);
2130                         }
2131                         break;
2132                 case P_SEP:
2133                         break;
2134         }
2135 }
2136
2137 /***************************************************************************
2138  Check if two parameters are equal.
2139 ***************************************************************************/
2140
2141 static BOOL equal_parameter(parm_type type, void *ptr1, void *ptr2)
2142 {
2143         switch (type) {
2144                 case P_BOOL:
2145                         return (*((int *)ptr1) == *((int *)ptr2));
2146
2147                 case P_INTEGER:
2148                 case P_OCTAL:
2149                 case P_BYTES:
2150                 case P_ENUM:
2151                         return (*((int *)ptr1) == *((int *)ptr2));
2152
2153                 case P_LIST:
2154                         return str_list_equal((const char **)(*(char ***)ptr1), 
2155                                               (const char **)(*(char ***)ptr2));
2156
2157                 case P_STRING:
2158                 case P_USTRING:
2159                 {
2160                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
2161                         if (p1 && !*p1)
2162                                 p1 = NULL;
2163                         if (p2 && !*p2)
2164                                 p2 = NULL;
2165                         return (p1 == p2 || strequal(p1, p2));
2166                 }
2167                 case P_SEP:
2168                         break;
2169         }
2170         return (False);
2171 }
2172
2173 /***************************************************************************
2174  Process a new section (service). At this stage all sections are services.
2175  Later we'll have special sections that permit server parameters to be set.
2176  Returns True on success, False on failure. 
2177 ***************************************************************************/
2178
2179 static BOOL do_section(const char *pszSectionName, void *userdata)
2180 {
2181         BOOL bRetval;
2182         BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2183                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2184         bRetval = False;
2185
2186         /* if we've just struck a global section, note the fact. */
2187         bInGlobalSection = isglobal;
2188
2189         /* check for multiple global sections */
2190         if (bInGlobalSection) {
2191                 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2192                 return (True);
2193         }
2194
2195         /* if we have a current service, tidy it up before moving on */
2196         bRetval = True;
2197
2198         if (iServiceIndex >= 0)
2199                 bRetval = service_ok(iServiceIndex);
2200
2201         /* if all is still well, move to the next record in the services array */
2202         if (bRetval) {
2203                 /* We put this here to avoid an odd message order if messages are */
2204                 /* issued by the post-processing of a previous section. */
2205                 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2206
2207                 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
2208                     < 0) {
2209                         DEBUG(0, ("Failed to add a new service\n"));
2210                         return (False);
2211                 }
2212         }
2213
2214         return (bRetval);
2215 }
2216
2217
2218 /***************************************************************************
2219  Determine if a partcular base parameter is currentl set to the default value.
2220 ***************************************************************************/
2221
2222 static BOOL is_default(int i)
2223 {
2224         if (!defaults_saved)
2225                 return False;
2226         switch (parm_table[i].type) {
2227                 case P_LIST:
2228                         return str_list_equal((const char **)parm_table[i].def.lvalue, 
2229                                               (const char **)(*(char ***)parm_table[i].ptr));
2230                 case P_STRING:
2231                 case P_USTRING:
2232                         return strequal(parm_table[i].def.svalue,
2233                                         *(char **)parm_table[i].ptr);
2234                 case P_BOOL:
2235                         return parm_table[i].def.bvalue ==
2236                                 *(int *)parm_table[i].ptr;
2237                 case P_INTEGER:
2238                 case P_OCTAL:
2239                 case P_BYTES:
2240                 case P_ENUM:
2241                         return parm_table[i].def.ivalue ==
2242                                 *(int *)parm_table[i].ptr;
2243                 case P_SEP:
2244                         break;
2245         }
2246         return False;
2247 }
2248
2249 /***************************************************************************
2250 Display the contents of the global structure.
2251 ***************************************************************************/
2252
2253 static void dump_globals(FILE *f, BOOL show_defaults)
2254 {
2255         int i;
2256         struct param_opt *data;
2257         
2258         fprintf(f, "# Global parameters\n[global]\n");
2259
2260         for (i = 0; parm_table[i].label; i++)
2261                 if (parm_table[i].class == P_GLOBAL &&
2262                     parm_table[i].ptr &&
2263                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2264                         if (!show_defaults && (parm_table[i].flags & FLAG_DEFAULT)) 
2265                                 continue;
2266                         fprintf(f, "\t%s = ", parm_table[i].label);
2267                         print_parameter(&parm_table[i], parm_table[i].ptr, f);
2268                         fprintf(f, "\n");
2269         }
2270         if (Globals.param_opt != NULL) {
2271                 data = Globals.param_opt;
2272                 while(data) {
2273                         fprintf(f, "\t%s = %s\n", data->key, data->value);
2274                         data = data->next;
2275                 }
2276         }
2277
2278 }
2279
2280 /***************************************************************************
2281  Display the contents of a single services record.
2282 ***************************************************************************/
2283
2284 static void dump_a_service(service * pService, FILE * f)
2285 {
2286         int i;
2287         struct param_opt *data;
2288         
2289         if (pService != &sDefault)
2290                 fprintf(f, "\n[%s]\n", pService->szService);
2291
2292         for (i = 0; parm_table[i].label; i++)
2293                 if (parm_table[i].class == P_LOCAL &&
2294                     parm_table[i].ptr &&
2295                     (*parm_table[i].label != '-') &&
2296                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2297                         int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
2298
2299                         if (pService == &sDefault) {
2300                                 if (defaults_saved && is_default(i))
2301                                         continue;
2302                         } else {
2303                                 if (equal_parameter(parm_table[i].type,
2304                                                     ((char *)pService) +
2305                                                     pdiff,
2306                                                     ((char *)&sDefault) +
2307                                                     pdiff))
2308                                         continue;
2309                         }
2310
2311                         fprintf(f, "\t%s = ", parm_table[i].label);
2312                         print_parameter(&parm_table[i],
2313                                         ((char *)pService) + pdiff, f);
2314                         fprintf(f, "\n");
2315         }
2316         if (pService->param_opt != NULL) {
2317                 data = pService->param_opt;
2318                 while(data) {
2319                         fprintf(f, "\t%s = %s\n", data->key, data->value);
2320                         data = data->next;
2321                 }
2322         }
2323 }
2324
2325 BOOL lp_dump_a_parameter(int snum, char *parm_name, FILE * f, BOOL isGlobal)
2326 {
2327         service * pService = ServicePtrs[snum];
2328         struct parm_struct *parm;
2329         void *ptr;
2330         
2331         parm = lp_parm_struct(parm_name);
2332         if (!parm) {
2333                 return False;
2334         }
2335         
2336         if (isGlobal)
2337                 ptr = parm->ptr;
2338         else
2339                 ptr = ((char *)pService) +
2340                         PTR_DIFF(parm->ptr, &sDefault);
2341         
2342         print_parameter(parm,
2343                         ptr, f);
2344         fprintf(f, "\n");
2345         return True;
2346 }
2347
2348 /***************************************************************************
2349  Return info about the next service  in a service. snum==-1 gives the globals.
2350  Return NULL when out of parameters.
2351 ***************************************************************************/
2352
2353 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
2354 {
2355         if (snum == -1) {
2356                 /* do the globals */
2357                 for (; parm_table[*i].label; (*i)++) {
2358                         if (parm_table[*i].class == P_SEPARATOR)
2359                                 return &parm_table[(*i)++];
2360
2361                         if (!parm_table[*i].ptr
2362                             || (*parm_table[*i].label == '-'))
2363                                 continue;
2364
2365                         if ((*i) > 0
2366                             && (parm_table[*i].ptr ==
2367                                 parm_table[(*i) - 1].ptr))
2368                                 continue;
2369
2370                         return &parm_table[(*i)++];
2371                 }
2372         } else {
2373                 service *pService = ServicePtrs[snum];
2374
2375                 for (; parm_table[*i].label; (*i)++) {
2376                         if (parm_table[*i].class == P_SEPARATOR)
2377                                 return &parm_table[(*i)++];
2378
2379                         if (parm_table[*i].class == P_LOCAL &&
2380                             parm_table[*i].ptr &&
2381                             (*parm_table[*i].label != '-') &&
2382                             ((*i) == 0 ||
2383                              (parm_table[*i].ptr !=
2384                               parm_table[(*i) - 1].ptr)))
2385                         {
2386                                 int pdiff =
2387                                         PTR_DIFF(parm_table[*i].ptr,
2388                                                  &sDefault);
2389
2390                                 if (allparameters ||
2391                                     !equal_parameter(parm_table[*i].type,
2392                                                      ((char *)pService) +
2393                                                      pdiff,
2394                                                      ((char *)&sDefault) +
2395                                                      pdiff))
2396                                 {
2397                                         return &parm_table[(*i)++];
2398                                 }
2399                         }
2400                 }
2401         }
2402
2403         return NULL;
2404 }
2405
2406
2407 /***************************************************************************
2408  Return TRUE if the passed service number is within range.
2409 ***************************************************************************/
2410
2411 BOOL lp_snum_ok(int iService)
2412 {
2413         return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
2414 }
2415
2416 /***************************************************************************
2417  Auto-load some home services.
2418 ***************************************************************************/
2419
2420 static void lp_add_auto_services(const char *str)
2421 {
2422         return;
2423 }
2424
2425 /***************************************************************************
2426  Have we loaded a services file yet?
2427 ***************************************************************************/
2428
2429 BOOL lp_loaded(void)
2430 {
2431         return (bLoaded);
2432 }
2433
2434 /***************************************************************************
2435  Unload unused services.
2436 ***************************************************************************/
2437
2438 void lp_killunused(struct smbsrv_connection *smb, BOOL (*snumused) (struct smbsrv_connection *, int))
2439 {
2440         int i;
2441         for (i = 0; i < iNumServices; i++) {
2442                 if (!VALID(i))
2443                         continue;
2444
2445                 if (!snumused || !snumused(smb, i)) {
2446                         ServicePtrs[i]->valid = False;
2447                         free_service(ServicePtrs[i]);
2448                 }
2449         }
2450 }
2451
2452 /***************************************************************************
2453  Unload a service.
2454 ***************************************************************************/
2455
2456 void lp_killservice(int iServiceIn)
2457 {
2458         if (VALID(iServiceIn)) {
2459                 ServicePtrs[iServiceIn]->valid = False;
2460                 free_service(ServicePtrs[iServiceIn]);
2461         }
2462 }
2463
2464 /***************************************************************************
2465  Load the services array from the services file. Return True on success, 
2466  False on failure.
2467 ***************************************************************************/
2468
2469 BOOL lp_load(void)
2470 {
2471         pstring n2;
2472         BOOL bRetval;
2473         struct param_opt *data;
2474
2475         bRetval = False;
2476
2477         bInGlobalSection = True;
2478
2479         if (Globals.param_opt != NULL) {
2480                 struct param_opt *next;
2481                 for (data=Globals.param_opt; data; data=next) {
2482                         next = data->next;
2483                         if (data->flags & FLAG_CMDLINE) continue;
2484                         free(data->key);
2485                         free(data->value);
2486                         DLIST_REMOVE(Globals.param_opt, data);
2487                         free(data);
2488                 }
2489         }
2490         
2491         init_globals();
2492
2493         pstrcpy(n2, lp_configfile());
2494         standard_sub_basic(n2,sizeof(n2));
2495         DEBUG(2, ("lp_load: refreshing parameters from %s\n", n2));
2496         
2497         add_to_file_list(lp_configfile(), n2);
2498
2499         /* We get sections first, so have to start 'behind' to make up */
2500         iServiceIndex = -1;
2501         bRetval = pm_process(n2, do_section, do_parameter, NULL);
2502
2503         /* finish up the last section */
2504         DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
2505         if (bRetval)
2506                 if (iServiceIndex >= 0)
2507                         bRetval = service_ok(iServiceIndex);
2508
2509         lp_add_auto_services(lp_auto_services());
2510
2511         lp_add_hidden("IPC$", "IPC");
2512         lp_add_hidden("ADMIN$", "DISK");
2513
2514         bLoaded = True;
2515
2516         if (!Globals.szWINSservers && Globals.bWINSsupport) {
2517                 lp_do_parameter(-1, "wins server", "127.0.0.1");
2518         }
2519
2520         init_iconv();
2521
2522         return (bRetval);
2523 }
2524
2525 /***************************************************************************
2526  Reset the max number of services.
2527 ***************************************************************************/
2528
2529 void lp_resetnumservices(void)
2530 {
2531         iNumServices = 0;
2532 }
2533
2534 /***************************************************************************
2535  Return the max number of services.
2536 ***************************************************************************/
2537
2538 int lp_numservices(void)
2539 {
2540         return (iNumServices);
2541 }
2542
2543 /***************************************************************************
2544 Display the contents of the services array in human-readable form.
2545 ***************************************************************************/
2546
2547 void lp_dump(FILE *f, BOOL show_defaults, int maxtoprint)
2548 {
2549         int iService;
2550
2551         if (show_defaults)
2552                 defaults_saved = False;
2553
2554         dump_globals(f, show_defaults);
2555
2556         dump_a_service(&sDefault, f);
2557
2558         for (iService = 0; iService < maxtoprint; iService++)
2559                 lp_dump_one(f, show_defaults, iService);
2560 }
2561
2562 /***************************************************************************
2563 Display the contents of one service in human-readable form.
2564 ***************************************************************************/
2565
2566 void lp_dump_one(FILE * f, BOOL show_defaults, int snum)
2567 {
2568         if (VALID(snum)) {
2569                 if (ServicePtrs[snum]->szService[0] == '\0')
2570                         return;
2571                 dump_a_service(ServicePtrs[snum], f);
2572         }
2573 }
2574
2575 /***************************************************************************
2576 Return the number of the service with the given name, or -1 if it doesn't
2577 exist. Note that this is a DIFFERENT ANIMAL from the internal function
2578 getservicebyname()! This works ONLY if all services have been loaded, and
2579 does not copy the found service.
2580 ***************************************************************************/
2581
2582 int lp_servicenumber(const char *pszServiceName)
2583 {
2584         int iService;
2585         fstring serviceName;
2586  
2587  
2588         for (iService = iNumServices - 1; iService >= 0; iService--) {
2589                 if (VALID(iService) && ServicePtrs[iService]->szService) {
2590                         /*
2591                          * The substitution here is used to support %U is
2592                          * service names
2593                          */
2594                         fstrcpy(serviceName, ServicePtrs[iService]->szService);
2595                         standard_sub_basic(serviceName,sizeof(serviceName));
2596                         if (strequal(serviceName, pszServiceName))
2597                                 break;
2598                 }
2599         }
2600
2601         if (iService < 0)
2602                 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
2603
2604         return (iService);
2605 }
2606
2607 int lp_find_valid_service(const char *pszServiceName)
2608 {
2609         int iService;
2610
2611         iService = lp_servicenumber(pszServiceName);
2612
2613         if (iService >= 0 && !lp_snum_ok(iService)) {
2614                 DEBUG(0,("lp_find_valid_service: Invalid snum %d for '%s'\n",iService, pszServiceName));
2615                 iService = -1;
2616         }
2617
2618         if (iService == -1) {
2619                 DEBUG(3,("lp_find_valid_service: failed to find service '%s'\n", pszServiceName));
2620         }
2621
2622         return iService;
2623 }
2624
2625 /*******************************************************************
2626  A useful volume label function. 
2627 ********************************************************************/
2628 const char *volume_label(int snum)
2629 {
2630         const char *ret = lp_volume(snum);
2631         if (!*ret)
2632                 return lp_servicename(snum);
2633         return (ret);
2634 }
2635
2636
2637 /***********************************************************
2638  If we are PDC then prefer us as DMB
2639 ************************************************************/
2640
2641 BOOL lp_domain_logons(void)
2642 {
2643         return (lp_server_role() == ROLE_DOMAIN_CONTROLLER);
2644 }
2645
2646 /*******************************************************************
2647  Remove a service.
2648 ********************************************************************/
2649
2650 void lp_remove_service(int snum)
2651 {
2652         ServicePtrs[snum]->valid = False;
2653 }
2654
2655 /*******************************************************************
2656  Copy a service.
2657 ********************************************************************/
2658
2659 void lp_copy_service(int snum, const char *new_name)
2660 {
2661         const char *oldname = lp_servicename(snum);
2662         do_section(new_name, NULL);
2663         if (snum >= 0) {
2664                 snum = lp_servicenumber(new_name);
2665                 if (snum >= 0)
2666                         lp_do_parameter(snum, "copy", oldname);
2667         }
2668 }
2669
2670 const char *lp_printername(int snum)
2671 {
2672         const char *ret = _lp_printername(snum);
2673         if (ret == NULL || (ret != NULL && *ret == '\0'))
2674                 ret = lp_const_servicename(snum);
2675
2676         return ret;
2677 }
2678
2679
2680 /*******************************************************************
2681  Return the max print jobs per queue.
2682 ********************************************************************/
2683
2684 int lp_maxprintjobs(int snum)
2685 {
2686         int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
2687         if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
2688                 maxjobs = PRINT_MAX_JOBID - 1;
2689
2690         return maxjobs;
2691 }