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