param: Add "domain logons" and "domain master" parameters
[samba.git] / lib / 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/dynconfig.h"
58 #include "system/time.h"
59 #include "system/locale.h"
60 #include "system/network.h" /* needed for TCP_NODELAY */
61 #include "../lib/util/dlinklist.h"
62 #include "lib/param/param.h"
63 #include "lib/param/loadparm.h"
64 #include "auth/gensec/gensec.h"
65 #include "s3_param.h"
66 #include "lib/util/bitmap.h"
67 #include "libcli/smb/smb_constants.h"
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 #define LOADPARM_EXTRA_GLOBALS \
75         struct parmlist_entry *param_opt;                               \
76         char *szRealm;                                                  \
77         char *tls_keyfile;                                              \
78         char *tls_certfile;                                             \
79         char *tls_cafile;                                               \
80         char *tls_crlfile;                                              \
81         char *tls_dhpfile;                                              \
82         char *loglevel;                                                 \
83         char *panic_action;                                             \
84         int bPreferredMaster;
85
86 #include "param_global.h"
87
88 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
89
90
91 /* prototypes for the special type handlers */
92 static bool handle_include(struct loadparm_context *lp_ctx, int unused,
93                            const char *pszParmValue, char **ptr);
94 static bool handle_realm(struct loadparm_context *lp_ctx, int unused,
95                          const char *pszParmValue, char **ptr);
96 static bool handle_copy(struct loadparm_context *lp_ctx, int unused,
97                         const char *pszParmValue, char **ptr);
98 static bool handle_debuglevel(struct loadparm_context *lp_ctx, int unused,
99                               const char *pszParmValue, char **ptr);
100 static bool handle_logfile(struct loadparm_context *lp_ctx, int unused,
101                            const char *pszParmValue, char **ptr);
102
103 static const struct enum_list enum_protocol[] = {
104         {PROTOCOL_SMB2_02, "SMB2"},
105         {PROTOCOL_SMB2_02, "SMB2_02"},
106         {PROTOCOL_NT1, "NT1"},
107         {PROTOCOL_LANMAN2, "LANMAN2"},
108         {PROTOCOL_LANMAN1, "LANMAN1"},
109         {PROTOCOL_CORE, "CORE"},
110         {PROTOCOL_COREPLUS, "COREPLUS"},
111         {PROTOCOL_COREPLUS, "CORE+"},
112         {-1, NULL}
113 };
114
115 static const struct enum_list enum_security[] = {
116         {SEC_SHARE, "SHARE"},
117         {SEC_USER, "USER"},
118         {SEC_ADS, "ADS"},
119         {-1, NULL}
120 };
121
122 static const struct enum_list enum_bool_auto[] = {
123         {false, "No"},
124         {false, "False"},
125         {false, "0"},
126         {true, "Yes"},
127         {true, "True"},
128         {true, "1"},
129         {Auto, "Auto"},
130         {-1, NULL}
131 };
132
133 /* Client-side offline caching policy types */
134
135 static const struct enum_list enum_csc_policy[] = {
136         {CSC_POLICY_MANUAL, "manual"},
137         {CSC_POLICY_DOCUMENTS, "documents"},
138         {CSC_POLICY_PROGRAMS, "programs"},
139         {CSC_POLICY_DISABLE, "disable"},
140         {-1, NULL}
141 };
142
143 /* SMB signing types. */
144 static const struct enum_list enum_smb_signing_vals[] = {
145         {SMB_SIGNING_DEFAULT, "default"},
146         {SMB_SIGNING_OFF, "No"},
147         {SMB_SIGNING_OFF, "False"},
148         {SMB_SIGNING_OFF, "0"},
149         {SMB_SIGNING_OFF, "Off"},
150         {SMB_SIGNING_OFF, "disabled"},
151         {SMB_SIGNING_IF_REQUIRED, "if_required"},
152         {SMB_SIGNING_IF_REQUIRED, "Yes"},
153         {SMB_SIGNING_IF_REQUIRED, "True"},
154         {SMB_SIGNING_IF_REQUIRED, "1"},
155         {SMB_SIGNING_IF_REQUIRED, "On"},
156         {SMB_SIGNING_IF_REQUIRED, "enabled"},
157         {SMB_SIGNING_IF_REQUIRED, "auto"},
158         {SMB_SIGNING_REQUIRED, "required"},
159         {SMB_SIGNING_REQUIRED, "mandatory"},
160         {SMB_SIGNING_REQUIRED, "force"},
161         {SMB_SIGNING_REQUIRED, "forced"},
162         {SMB_SIGNING_REQUIRED, "enforced"},
163         {-1, NULL}
164 };
165
166 static const struct enum_list enum_server_role[] = {
167         {ROLE_STANDALONE, "standalone"},
168         {ROLE_DOMAIN_MEMBER, "member server"},
169         {ROLE_DOMAIN_MEMBER, "member"},
170         {ROLE_DOMAIN_CONTROLLER, "domain controller"},
171         {ROLE_DOMAIN_CONTROLLER, "dc"},
172         {-1, NULL}
173 };
174
175 #define GLOBAL_VAR(name) offsetof(struct loadparm_global, name)
176 #define LOCAL_VAR(name) offsetof(struct loadparm_service, name)
177
178 static struct parm_struct parm_table[] = {
179         {
180                 .label          = "server role",
181                 .type           = P_ENUM,
182                 .p_class        = P_GLOBAL,
183                 .offset         = GLOBAL_VAR(server_role),
184                 .special        = NULL,
185                 .enum_list      = enum_server_role
186         },
187         {
188                 .label          = "domain logons",
189                 .type           = P_ENUM,
190                 .p_class        = P_GLOBAL,
191                 .offset         = GLOBAL_VAR(domain_logons),
192                 .special        = NULL,
193                 .enum_list      = enum_bool_auto
194         },
195         {
196                 .label          = "domain master",
197                 .type           = P_ENUM,
198                 .p_class        = P_GLOBAL,
199                 .offset         = GLOBAL_VAR(domain_master),
200                 .special        = NULL,
201                 .enum_list      = enum_bool_auto
202         },
203         {
204                 .label          = "dos charset",
205                 .type           = P_STRING,
206                 .p_class        = P_GLOBAL,
207                 .offset         = GLOBAL_VAR(dos_charset),
208                 .special        = NULL,
209                 .enum_list      = NULL
210         },
211         {
212                 .label          = "unix charset",
213                 .type           = P_STRING,
214                 .p_class        = P_GLOBAL,
215                 .offset         = GLOBAL_VAR(unix_charset),
216                 .special        = NULL,
217                 .enum_list      = NULL
218         },
219         {
220                 .label          = "ncalrpc dir",
221                 .type           = P_STRING,
222                 .p_class        = P_GLOBAL,
223                 .offset         = GLOBAL_VAR(ncalrpc_dir),
224                 .special        = NULL,
225                 .enum_list      = NULL
226         },
227         {
228                 .label          = "comment",
229                 .type           = P_STRING,
230                 .p_class        = P_LOCAL,
231                 .offset         = LOCAL_VAR(comment),
232                 .special        = NULL,
233                 .enum_list      = NULL
234         },
235         {
236                 .label          = "path",
237                 .type           = P_STRING,
238                 .p_class        = P_LOCAL,
239                 .offset         = LOCAL_VAR(szPath),
240                 .special        = NULL,
241                 .enum_list      = NULL
242         },
243         {
244                 .label          = "directory",
245                 .type           = P_STRING,
246                 .p_class        = P_LOCAL,
247                 .offset         = LOCAL_VAR(szPath),
248                 .special        = NULL,
249                 .enum_list      = NULL
250         },
251         {
252                 .label          = "workgroup",
253                 .type           = P_USTRING,
254                 .p_class        = P_GLOBAL,
255                 .offset         = GLOBAL_VAR(szWorkgroup),
256                 .special        = NULL,
257                 .enum_list      = NULL
258         },
259         {
260                 .label          = "realm",
261                 .type           = P_STRING,
262                 .p_class        = P_GLOBAL,
263                 .offset         = GLOBAL_VAR(szRealm),
264                 .special        = handle_realm,
265                 .enum_list      = NULL
266         },
267         {
268                 .label          = "netbios name",
269                 .type           = P_USTRING,
270                 .p_class        = P_GLOBAL,
271                 .offset         = GLOBAL_VAR(szNetbiosName),
272                 .special        = NULL,
273                 .enum_list      = NULL
274         },
275         {
276                 .label          = "netbios aliases",
277                 .type           = P_LIST,
278                 .p_class        = P_GLOBAL,
279                 .offset         = GLOBAL_VAR(szNetbiosAliases),
280                 .special        = NULL,
281                 .enum_list      = NULL
282         },
283         {
284                 .label          = "netbios scope",
285                 .type           = P_USTRING,
286                 .p_class        = P_GLOBAL,
287                 .offset         = GLOBAL_VAR(szNetbiosScope),
288                 .special        = NULL,
289                 .enum_list      = NULL
290         },
291         {
292                 .label          = "server string",
293                 .type           = P_STRING,
294                 .p_class        = P_GLOBAL,
295                 .offset         = GLOBAL_VAR(szServerString),
296                 .special        = NULL,
297                 .enum_list      = NULL
298         },
299         {
300                 .label          = "interfaces",
301                 .type           = P_LIST,
302                 .p_class        = P_GLOBAL,
303                 .offset         = GLOBAL_VAR(szInterfaces),
304                 .special        = NULL,
305                 .enum_list      = NULL
306         },
307         {
308                 .label          = "bind interfaces only",
309                 .type           = P_BOOL,
310                 .p_class        = P_GLOBAL,
311                 .offset         = GLOBAL_VAR(bBindInterfacesOnly),
312                 .special        = NULL,
313                 .enum_list      = NULL
314         },
315         {
316                 .label          = "ntvfs handler",
317                 .type           = P_LIST,
318                 .p_class        = P_LOCAL,
319                 .offset         = LOCAL_VAR(ntvfs_handler),
320                 .special        = NULL,
321                 .enum_list      = NULL
322         },
323         {
324                 .label          = "ntptr providor",
325                 .type           = P_STRING,
326                 .p_class        = P_GLOBAL,
327                 .offset         = GLOBAL_VAR(ntptr_providor),
328                 .special        = NULL,
329                 .enum_list      = NULL
330         },
331         {
332                 .label          = "passdb backend",
333                 .type           = P_STRING,
334                 .p_class        = P_GLOBAL,
335                 .offset         = GLOBAL_VAR(passdb_backend),
336                 .special        = NULL,
337                 .enum_list      = NULL
338         },
339         {
340                 .label          = "dcerpc endpoint servers",
341                 .type           = P_LIST,
342                 .p_class        = P_GLOBAL,
343                 .offset         = GLOBAL_VAR(dcerpc_ep_servers),
344                 .special        = NULL,
345                 .enum_list      = NULL
346         },
347         {
348                 .label          = "server services",
349                 .type           = P_LIST,
350                 .p_class        = P_GLOBAL,
351                 .offset         = GLOBAL_VAR(server_services),
352                 .special        = NULL,
353                 .enum_list      = NULL
354         },
355
356         {
357                 .label          = "security",
358                 .type           = P_ENUM,
359                 .p_class        = P_GLOBAL,
360                 .offset         = GLOBAL_VAR(security),
361                 .special        = NULL,
362                 .enum_list      = enum_security
363         },
364         {
365                 .label          = "encrypt passwords",
366                 .type           = P_BOOL,
367                 .p_class        = P_GLOBAL,
368                 .offset         = GLOBAL_VAR(bEncryptPasswords),
369                 .special        = NULL,
370                 .enum_list      = NULL
371         },
372         {
373                 .label          = "null passwords",
374                 .type           = P_BOOL,
375                 .p_class        = P_GLOBAL,
376                 .offset         = GLOBAL_VAR(bNullPasswords),
377                 .special        = NULL,
378                 .enum_list      = NULL
379         },
380         {
381                 .label          = "obey pam restrictions",
382                 .type           = P_BOOL,
383                 .p_class        = P_GLOBAL,
384                 .offset         = GLOBAL_VAR(bObeyPamRestrictions),
385                 .special        = NULL,
386                 .enum_list      = NULL
387         },
388         {
389                 .label          = "password server",
390                 .type           = P_LIST,
391                 .p_class        = P_GLOBAL,
392                 .offset         = GLOBAL_VAR(szPasswordServers),
393                 .special        = NULL,
394                 .enum_list      = NULL
395         },
396         {
397                 .label          = "private dir",
398                 .type           = P_STRING,
399                 .p_class        = P_GLOBAL,
400                 .offset         = GLOBAL_VAR(szPrivateDir),
401                 .special        = NULL,
402                 .enum_list      = NULL
403         },
404         {
405                 .label          = "passwd chat",
406                 .type           = P_STRING,
407                 .p_class        = P_GLOBAL,
408                 .offset         = GLOBAL_VAR(szPasswdChat),
409                 .special        = NULL,
410                 .enum_list      = NULL
411         },
412         {
413                 .label          = "password level",
414                 .type           = P_INTEGER,
415                 .p_class        = P_GLOBAL,
416                 .offset         = GLOBAL_VAR(pwordlevel),
417                 .special        = NULL,
418                 .enum_list      = NULL
419         },
420         {
421                 .label          = "lanman auth",
422                 .type           = P_BOOL,
423                 .p_class        = P_GLOBAL,
424                 .offset         = GLOBAL_VAR(bLanmanAuth),
425                 .special        = NULL,
426                 .enum_list      = NULL
427         },
428         {
429                 .label          = "ntlm auth",
430                 .type           = P_BOOL,
431                 .p_class        = P_GLOBAL,
432                 .offset         = GLOBAL_VAR(bNTLMAuth),
433                 .special        = NULL,
434                 .enum_list      = NULL
435         },
436         {
437                 .label          = "client NTLMv2 auth",
438                 .type           = P_BOOL,
439                 .p_class        = P_GLOBAL,
440                 .offset         = GLOBAL_VAR(bClientNTLMv2Auth),
441                 .special        = NULL,
442                 .enum_list      = NULL
443         },
444         {
445                 .label          = "client lanman auth",
446                 .type           = P_BOOL,
447                 .p_class        = P_GLOBAL,
448                 .offset         = GLOBAL_VAR(bClientLanManAuth),
449                 .special        = NULL,
450                 .enum_list      = NULL
451         },
452         {
453                 .label          = "client plaintext auth",
454                 .type           = P_BOOL,
455                 .p_class        = P_GLOBAL,
456                 .offset         = GLOBAL_VAR(bClientPlaintextAuth),
457                 .special        = NULL,
458                 .enum_list      = NULL
459         },
460         {
461                 .label          = "client use spnego principal",
462                 .type           = P_BOOL,
463                 .p_class        = P_GLOBAL,
464                 .offset         = GLOBAL_VAR(client_use_spnego_principal),
465                 .special        = NULL,
466                 .enum_list      = NULL
467         },
468
469         {
470                 .label          = "read only",
471                 .type           = P_BOOL,
472                 .p_class        = P_LOCAL,
473                 .offset         = LOCAL_VAR(bRead_only),
474                 .special        = NULL,
475                 .enum_list      = NULL
476         },
477
478         {
479                 .label          = "create mask",
480                 .type           = P_OCTAL,
481                 .p_class        = P_LOCAL,
482                 .offset         = LOCAL_VAR(iCreate_mask),
483                 .special        = NULL,
484                 .enum_list      = NULL
485         },
486         {
487                 .label          = "force create mode",
488                 .type           = P_OCTAL,
489                 .p_class        = P_LOCAL,
490                 .offset         = LOCAL_VAR(iCreate_force_mode),
491                 .special        = NULL,
492                 .enum_list      = NULL
493         },
494         {
495                 .label          = "directory mask",
496                 .type           = P_OCTAL,
497                 .p_class        = P_LOCAL,
498                 .offset         = LOCAL_VAR(iDir_mask),
499                 .special        = NULL,
500                 .enum_list      = NULL
501         },
502         {
503                 .label          = "force directory mode",
504                 .type           = P_OCTAL,
505                 .p_class        = P_LOCAL,
506                 .offset         = LOCAL_VAR(iDir_force_mode),
507                 .special        = NULL,
508                 .enum_list      = NULL
509         },
510
511         {
512                 .label          = "hosts allow",
513                 .type           = P_LIST,
514                 .p_class        = P_LOCAL,
515                 .offset         = LOCAL_VAR(szHostsallow),
516                 .special        = NULL,
517                 .enum_list      = NULL
518         },
519         {
520                 .label          = "hosts deny",
521                 .type           = P_LIST,
522                 .p_class        = P_LOCAL,
523                 .offset         = LOCAL_VAR(szHostsdeny),
524                 .special        = NULL,
525                 .enum_list      = NULL
526         },
527
528         {
529                 .label          = "log level",
530                 .type           = P_STRING,
531                 .p_class        = P_GLOBAL,
532                 .offset         = GLOBAL_VAR(loglevel),
533                 .special        = handle_debuglevel,
534                 .enum_list      = NULL
535         },
536         {
537                 .label          = "debuglevel",
538                 .type           = P_STRING,
539                 .p_class        = P_GLOBAL,
540                 .offset         = GLOBAL_VAR(loglevel),
541                 .special        = handle_debuglevel,
542                 .enum_list      = NULL
543         },
544         {
545                 .label          = "log file",
546                 .type           = P_STRING,
547                 .p_class        = P_GLOBAL,
548                 .offset         = GLOBAL_VAR(logfile),
549                 .special        = handle_logfile,
550                 .enum_list      = NULL
551         },
552
553         {
554                 .label          = "smb ports",
555                 .type           = P_LIST,
556                 .p_class        = P_GLOBAL,
557                 .offset         = GLOBAL_VAR(smb_ports),
558                 .special        = NULL,
559                 .enum_list      = NULL
560         },
561         {
562                 .label          = "nbt port",
563                 .type           = P_INTEGER,
564                 .p_class        = P_GLOBAL,
565                 .offset         = GLOBAL_VAR(nbt_port),
566                 .special        = NULL,
567                 .enum_list      = NULL
568         },
569         {
570                 .label          = "dgram port",
571                 .type           = P_INTEGER,
572                 .p_class        = P_GLOBAL,
573                 .offset         = GLOBAL_VAR(dgram_port),
574                 .special        = NULL,
575                 .enum_list      = NULL
576         },
577         {
578                 .label          = "cldap port",
579                 .type           = P_INTEGER,
580                 .p_class        = P_GLOBAL,
581                 .offset         = GLOBAL_VAR(cldap_port),
582                 .special        = NULL,
583                 .enum_list      = NULL
584         },
585         {
586                 .label          = "krb5 port",
587                 .type           = P_INTEGER,
588                 .p_class        = P_GLOBAL,
589                 .offset         = GLOBAL_VAR(krb5_port),
590                 .special        = NULL,
591                 .enum_list      = NULL
592         },
593         {
594                 .label          = "kpasswd port",
595                 .type           = P_INTEGER,
596                 .p_class        = P_GLOBAL,
597                 .offset         = GLOBAL_VAR(kpasswd_port),
598                 .special        = NULL,
599                 .enum_list      = NULL
600         },
601         {
602                 .label          = "web port",
603                 .type           = P_INTEGER,
604                 .p_class        = P_GLOBAL,
605                 .offset         = GLOBAL_VAR(web_port),
606                 .special        = NULL,
607                 .enum_list      = NULL
608         },
609         {
610                 .label          = "tls enabled",
611                 .type           = P_BOOL,
612                 .p_class        = P_GLOBAL,
613                 .offset         = GLOBAL_VAR(tls_enabled),
614                 .special        = NULL,
615                 .enum_list      = NULL
616         },
617         {
618                 .label          = "tls keyfile",
619                 .type           = P_STRING,
620                 .p_class        = P_GLOBAL,
621                 .offset         = GLOBAL_VAR(tls_keyfile),
622                 .special        = NULL,
623                 .enum_list      = NULL
624         },
625         {
626                 .label          = "tls certfile",
627                 .type           = P_STRING,
628                 .p_class        = P_GLOBAL,
629                 .offset         = GLOBAL_VAR(tls_certfile),
630                 .special        = NULL,
631                 .enum_list      = NULL
632         },
633         {
634                 .label          = "tls cafile",
635                 .type           = P_STRING,
636                 .p_class        = P_GLOBAL,
637                 .offset         = GLOBAL_VAR(tls_cafile),
638                 .special        = NULL,
639                 .enum_list      = NULL
640         },
641         {
642                 .label          = "tls crlfile",
643                 .type           = P_STRING,
644                 .p_class        = P_GLOBAL,
645                 .offset         = GLOBAL_VAR(tls_crlfile),
646                 .special        = NULL,
647                 .enum_list      = NULL
648         },
649         {
650                 .label          = "tls dh params file",
651                 .type           = P_STRING,
652                 .p_class        = P_GLOBAL,
653                 .offset         = GLOBAL_VAR(tls_dhpfile),
654                 .special        = NULL,
655                 .enum_list      = NULL
656         },
657         {
658                 .label          = "large readwrite",
659                 .type           = P_BOOL,
660                 .p_class        = P_GLOBAL,
661                 .offset         = GLOBAL_VAR(bLargeReadwrite),
662                 .special        = NULL,
663                 .enum_list      = NULL
664         },
665         {
666                 .label          = "server max protocol",
667                 .type           = P_ENUM,
668                 .p_class        = P_GLOBAL,
669                 .offset         = GLOBAL_VAR(srv_maxprotocol),
670                 .special        = NULL,
671                 .enum_list      = enum_protocol
672         },
673         {
674                 .label          = "server min protocol",
675                 .type           = P_ENUM,
676                 .p_class        = P_GLOBAL,
677                 .offset         = GLOBAL_VAR(srv_minprotocol),
678                 .special        = NULL,
679                 .enum_list      = enum_protocol
680         },
681         {
682                 .label          = "client max protocol",
683                 .type           = P_ENUM,
684                 .p_class        = P_GLOBAL,
685                 .offset         = GLOBAL_VAR(cli_maxprotocol),
686                 .special        = NULL,
687                 .enum_list      = enum_protocol
688         },
689         {
690                 .label          = "client min protocol",
691                 .type           = P_ENUM,
692                 .p_class        = P_GLOBAL,
693                 .offset         = GLOBAL_VAR(cli_minprotocol),
694                 .special        = NULL,
695                 .enum_list      = enum_protocol
696         },
697         {
698                 .label          = "unicode",
699                 .type           = P_BOOL,
700                 .p_class        = P_GLOBAL,
701                 .offset         = GLOBAL_VAR(bUnicode),
702                 .special        = NULL,
703                 .enum_list      = NULL
704         },
705         {
706                 .label          = "read raw",
707                 .type           = P_BOOL,
708                 .p_class        = P_GLOBAL,
709                 .offset         = GLOBAL_VAR(bReadRaw),
710                 .special        = NULL,
711                 .enum_list      = NULL
712         },
713         {
714                 .label          = "write raw",
715                 .type           = P_BOOL,
716                 .p_class        = P_GLOBAL,
717                 .offset         = GLOBAL_VAR(bWriteRaw),
718                 .special        = NULL,
719                 .enum_list      = NULL
720         },
721         {
722                 .label          = "disable netbios",
723                 .type           = P_BOOL,
724                 .p_class        = P_GLOBAL,
725                 .offset         = GLOBAL_VAR(bDisableNetbios),
726                 .special        = NULL,
727                 .enum_list      = NULL
728         },
729
730         {
731                 .label          = "nt status support",
732                 .type           = P_BOOL,
733                 .p_class        = P_GLOBAL,
734                 .offset         = GLOBAL_VAR(bNTStatusSupport),
735                 .special        = NULL,
736                 .enum_list      = NULL
737         },
738
739         {
740                 .label          = "max mux",
741                 .type           = P_INTEGER,
742                 .p_class        = P_GLOBAL,
743                 .offset         = GLOBAL_VAR(max_mux),
744                 .special        = NULL,
745                 .enum_list      = NULL
746         },
747         {
748                 .label          = "max xmit",
749                 .type           = P_BYTES,
750                 .p_class        = P_GLOBAL,
751                 .offset         = GLOBAL_VAR(max_xmit),
752                 .special        = NULL,
753                 .enum_list      = NULL
754         },
755
756         {
757                 .label          = "name resolve order",
758                 .type           = P_LIST,
759                 .p_class        = P_GLOBAL,
760                 .offset         = GLOBAL_VAR(szNameResolveOrder),
761                 .special        = NULL,
762                 .enum_list      = NULL
763         },
764         {
765                 .label          = "max wins ttl",
766                 .type           = P_INTEGER,
767                 .p_class        = P_GLOBAL,
768                 .offset         = GLOBAL_VAR(max_wins_ttl),
769                 .special        = NULL,
770                 .enum_list      = NULL
771         },
772         {
773                 .label          = "min wins ttl",
774                 .type           = P_INTEGER,
775                 .p_class        = P_GLOBAL,
776                 .offset         = GLOBAL_VAR(min_wins_ttl),
777                 .special        = NULL,
778                 .enum_list      = NULL
779         },
780         {
781                 .label          = "time server",
782                 .type           = P_BOOL,
783                 .p_class        = P_GLOBAL,
784                 .offset         = GLOBAL_VAR(bTimeServer),
785                 .special        = NULL,
786                 .enum_list      = NULL
787         },
788         {
789                 .label          = "unix extensions",
790                 .type           = P_BOOL,
791                 .p_class        = P_GLOBAL,
792                 .offset         = GLOBAL_VAR(bUnixExtensions),
793                 .special        = NULL,
794                 .enum_list      = NULL
795         },
796         {
797                 .label          = "use spnego",
798                 .type           = P_BOOL,
799                 .p_class        = P_GLOBAL,
800                 .offset         = GLOBAL_VAR(bUseSpnego),
801                 .special        = NULL,
802                 .enum_list      = NULL
803         },
804         {
805                 .label          = "server signing",
806                 .type           = P_ENUM,
807                 .p_class        = P_GLOBAL,
808                 .offset         = GLOBAL_VAR(server_signing),
809                 .special        = NULL,
810                 .enum_list      = enum_smb_signing_vals
811         },
812         {
813                 .label          = "client signing",
814                 .type           = P_ENUM,
815                 .p_class        = P_GLOBAL,
816                 .offset         = GLOBAL_VAR(client_signing),
817                 .special        = NULL,
818                 .enum_list      = enum_smb_signing_vals
819         },
820         {
821                 .label          = "rpc big endian",
822                 .type           = P_BOOL,
823                 .p_class        = P_GLOBAL,
824                 .offset         = GLOBAL_VAR(bRpcBigEndian),
825                 .special        = NULL,
826                 .enum_list      = NULL
827         },
828
829         {
830                 .label          = "max connections",
831                 .type           = P_INTEGER,
832                 .p_class        = P_LOCAL,
833                 .offset         = LOCAL_VAR(iMaxConnections),
834                 .special        = NULL,
835                 .enum_list      = NULL
836         },
837         {
838                 .label          = "paranoid server security",
839                 .type           = P_BOOL,
840                 .p_class        = P_GLOBAL,
841                 .offset         = GLOBAL_VAR(paranoid_server_security),
842                 .special        = NULL,
843                 .enum_list      = NULL
844         },
845         {
846                 .label          = "socket options",
847                 .type           = P_STRING,
848                 .p_class        = P_GLOBAL,
849                 .offset         = GLOBAL_VAR(socket_options),
850                 .special        = NULL,
851                 .enum_list      = NULL
852         },
853
854         {
855                 .label          = "strict sync",
856                 .type           = P_BOOL,
857                 .p_class        = P_LOCAL,
858                 .offset         = LOCAL_VAR(bStrictSync),
859                 .special        = NULL,
860                 .enum_list      = NULL
861         },
862         {
863                 .label          = "use mmap",
864                 .type           = P_BOOL,
865                 .p_class        = P_GLOBAL,
866                 .offset         = GLOBAL_VAR(bUseMmap),
867                 .special        = NULL,
868                 .enum_list      = NULL,
869                 .flags          = FLAG_ADVANCED,
870         },
871         {
872                 .label          = "case insensitive filesystem",
873                 .type           = P_BOOL,
874                 .p_class        = P_LOCAL,
875                 .offset         = LOCAL_VAR(bCIFileSystem),
876                 .special        = NULL,
877                 .enum_list      = NULL
878         },
879
880         {
881                 .label          = "max print jobs",
882                 .type           = P_INTEGER,
883                 .p_class        = P_LOCAL,
884                 .offset         = LOCAL_VAR(iMaxPrintJobs),
885                 .special        = NULL,
886                 .enum_list      = NULL
887         },
888         {
889                 .label          = "printable",
890                 .type           = P_BOOL,
891                 .p_class        = P_LOCAL,
892                 .offset         = LOCAL_VAR(bPrint_ok),
893                 .special        = NULL,
894                 .enum_list      = NULL
895         },
896         {
897                 .label          = "print ok",
898                 .type           = P_BOOL,
899                 .p_class        = P_LOCAL,
900                 .offset         = LOCAL_VAR(bPrint_ok),
901                 .special        = NULL,
902                 .enum_list      = NULL
903         },
904
905         {
906                 .label          = "printer name",
907                 .type           = P_STRING,
908                 .p_class        = P_LOCAL,
909                 .offset         = LOCAL_VAR(szPrintername),
910                 .special        = NULL,
911                 .enum_list      = NULL
912         },
913         {
914                 .label          = "printer",
915                 .type           = P_STRING,
916                 .p_class        = P_LOCAL,
917                 .offset         = LOCAL_VAR(szPrintername),
918                 .special        = NULL,
919                 .enum_list      = NULL
920         },
921
922         {
923                 .label          = "map system",
924                 .type           = P_BOOL,
925                 .p_class        = P_LOCAL,
926                 .offset         = LOCAL_VAR(bMap_system),
927                 .special        = NULL,
928                 .enum_list      = NULL
929         },
930         {
931                 .label          = "map hidden",
932                 .type           = P_BOOL,
933                 .p_class        = P_LOCAL,
934                 .offset         = LOCAL_VAR(bMap_hidden),
935                 .special        = NULL,
936                 .enum_list      = NULL
937         },
938         {
939                 .label          = "map archive",
940                 .type           = P_BOOL,
941                 .p_class        = P_LOCAL,
942                 .offset         = LOCAL_VAR(bMap_archive),
943                 .special        = NULL,
944                 .enum_list      = NULL
945         },
946
947         {
948                 .label          = "preferred master",
949                 .type           = P_ENUM,
950                 .p_class        = P_GLOBAL,
951                 .offset         = GLOBAL_VAR(bPreferredMaster),
952                 .special        = NULL,
953                 .enum_list      = enum_bool_auto
954         },
955         {
956                 .label          = "prefered master",
957                 .type           = P_ENUM,
958                 .p_class        = P_GLOBAL,
959                 .offset         = GLOBAL_VAR(bPreferredMaster),
960                 .special        = NULL,
961                 .enum_list      = enum_bool_auto
962         },
963         {
964                 .label          = "local master",
965                 .type           = P_BOOL,
966                 .p_class        = P_GLOBAL,
967                 .offset         = GLOBAL_VAR(bLocalMaster),
968                 .special        = NULL,
969                 .enum_list      = NULL
970         },
971         {
972                 .label          = "browseable",
973                 .type           = P_BOOL,
974                 .p_class        = P_LOCAL,
975                 .offset         = LOCAL_VAR(bBrowseable),
976                 .special        = NULL,
977                 .enum_list      = NULL
978         },
979         {
980                 .label          = "browsable",
981                 .type           = P_BOOL,
982                 .p_class        = P_LOCAL,
983                 .offset         = LOCAL_VAR(bBrowseable),
984                 .special        = NULL,
985                 .enum_list      = NULL
986         },
987
988         {
989                 .label          = "wins server",
990                 .type           = P_LIST,
991                 .p_class        = P_GLOBAL,
992                 .offset         = GLOBAL_VAR(szWINSservers),
993                 .special        = NULL,
994                 .enum_list      = NULL
995         },
996         {
997                 .label          = "wins support",
998                 .type           = P_BOOL,
999                 .p_class        = P_GLOBAL,
1000                 .offset         = GLOBAL_VAR(bWINSsupport),
1001                 .special        = NULL,
1002                 .enum_list      = NULL
1003         },
1004         {
1005                 .label          = "dns proxy",
1006                 .type           = P_BOOL,
1007                 .p_class        = P_GLOBAL,
1008                 .offset         = GLOBAL_VAR(bWINSdnsProxy),
1009                 .special        = NULL,
1010                 .enum_list      = NULL
1011         },
1012         {
1013                 .label          = "wins hook",
1014                 .type           = P_STRING,
1015                 .p_class        = P_GLOBAL,
1016                 .offset         = GLOBAL_VAR(szWINSHook),
1017                 .special        = NULL,
1018                 .enum_list      = NULL
1019         },
1020
1021         {
1022                 .label          = "csc policy",
1023                 .type           = P_ENUM,
1024                 .p_class        = P_LOCAL,
1025                 .offset         = LOCAL_VAR(iCSCPolicy),
1026                 .special        = NULL,
1027                 .enum_list      = enum_csc_policy
1028         },
1029
1030         {
1031                 .label          = "strict locking",
1032                 .type           = P_BOOL,
1033                 .p_class        = P_LOCAL,
1034                 .offset         = LOCAL_VAR(iStrictLocking),
1035                 .special        = NULL,
1036                 .enum_list      = NULL
1037         },
1038         {
1039                 .label          = "oplocks",
1040                 .type           = P_BOOL,
1041                 .p_class        = P_LOCAL,
1042                 .offset         = LOCAL_VAR(bOpLocks),
1043                 .special        = NULL,
1044                 .enum_list      = NULL
1045         },
1046
1047         {
1048                 .label          = "share backend",
1049                 .type           = P_STRING,
1050                 .p_class        = P_GLOBAL,
1051                 .offset         = GLOBAL_VAR(szShareBackend),
1052                 .special        = NULL,
1053                 .enum_list      = NULL
1054         },
1055         {
1056                 .label          = "preload",
1057                 .type           = P_STRING,
1058                 .p_class        = P_GLOBAL,
1059                 .offset         = GLOBAL_VAR(szAutoServices),
1060                 .special        = NULL,
1061                 .enum_list      = NULL
1062         },
1063         {
1064                 .label          = "auto services",
1065                 .type           = P_STRING,
1066                 .p_class        = P_GLOBAL,
1067                 .offset         = GLOBAL_VAR(szAutoServices),
1068                 .special        = NULL,
1069                 .enum_list      = NULL
1070         },
1071         {
1072                 .label          = "lock dir",
1073                 .type           = P_STRING,
1074                 .p_class        = P_GLOBAL,
1075                 .offset         = GLOBAL_VAR(szLockDir),
1076                 .special        = NULL,
1077                 .enum_list      = NULL
1078         },
1079         {
1080                 .label          = "lock directory",
1081                 .type           = P_STRING,
1082                 .p_class        = P_GLOBAL,
1083                 .offset         = GLOBAL_VAR(szLockDir),
1084                 .special        = NULL,
1085                 .enum_list      = NULL
1086         },
1087         {
1088                 .label          = "state directory",
1089                 .type           = P_STRING,
1090                 .p_class        = P_GLOBAL,
1091                 .offset         = GLOBAL_VAR(szStateDir),
1092                 .special        = NULL,
1093                 .enum_list      = NULL
1094         },
1095         {
1096                 .label          = "cache directory",
1097                 .type           = P_STRING,
1098                 .p_class        = P_GLOBAL,
1099                 .offset         = GLOBAL_VAR(szCacheDir),
1100                 .special        = NULL,
1101                 .enum_list      = NULL
1102         },
1103         {
1104                 .label          = "pid directory",
1105                 .type           = P_STRING,
1106                 .p_class        = P_GLOBAL,
1107                 .offset         = GLOBAL_VAR(szPidDir),
1108                 .special        = NULL,
1109                 .enum_list      = NULL
1110         },
1111
1112         {
1113                 .label          = "socket address",
1114                 .type           = P_STRING,
1115                 .p_class        = P_GLOBAL,
1116                 .offset         = GLOBAL_VAR(szSocketAddress),
1117                 .special        = NULL,
1118                 .enum_list      = NULL
1119         },
1120         {
1121                 .label          = "copy",
1122                 .type           = P_STRING,
1123                 .p_class        = P_LOCAL,
1124                 .offset         = LOCAL_VAR(szCopy),
1125                 .special        = handle_copy,
1126                 .enum_list      = NULL
1127         },
1128         {
1129                 .label          = "include",
1130                 .type           = P_STRING,
1131                 .p_class        = P_LOCAL,
1132                 .offset         = LOCAL_VAR(szInclude),
1133                 .special        = handle_include,
1134                 .enum_list      = NULL
1135         },
1136
1137         {
1138                 .label          = "available",
1139                 .type           = P_BOOL,
1140                 .p_class        = P_LOCAL,
1141                 .offset         = LOCAL_VAR(bAvailable),
1142                 .special        = NULL,
1143                 .enum_list      = NULL
1144         },
1145         {
1146                 .label          = "volume",
1147                 .type           = P_STRING,
1148                 .p_class        = P_LOCAL,
1149                 .offset         = LOCAL_VAR(volume),
1150                 .special        = NULL,
1151                 .enum_list      = NULL
1152         },
1153         {
1154                 .label          = "fstype",
1155                 .type           = P_STRING,
1156                 .p_class        = P_LOCAL,
1157                 .offset         = LOCAL_VAR(fstype),
1158                 .special        = NULL,
1159                 .enum_list      = NULL
1160         },
1161
1162         {
1163                 .label          = "panic action",
1164                 .type           = P_STRING,
1165                 .p_class        = P_GLOBAL,
1166                 .offset         = GLOBAL_VAR(panic_action),
1167                 .special        = NULL,
1168                 .enum_list      = NULL
1169         },
1170
1171         {
1172                 .label          = "msdfs root",
1173                 .type           = P_BOOL,
1174                 .p_class        = P_LOCAL,
1175                 .offset         = LOCAL_VAR(bMSDfsRoot),
1176                 .special        = NULL,
1177                 .enum_list      = NULL
1178         },
1179         {
1180                 .label          = "host msdfs",
1181                 .type           = P_BOOL,
1182                 .p_class        = P_GLOBAL,
1183                 .offset         = GLOBAL_VAR(bHostMSDfs),
1184                 .special        = NULL,
1185                 .enum_list      = NULL
1186         },
1187         {
1188                 .label          = "winbind separator",
1189                 .type           = P_STRING,
1190                 .p_class        = P_GLOBAL,
1191                 .offset         = GLOBAL_VAR(szWinbindSeparator),
1192                 .special        = NULL,
1193                 .enum_list      = NULL
1194         },
1195         {
1196                 .label          = "winbindd socket directory",
1197                 .type           = P_STRING,
1198                 .p_class        = P_GLOBAL,
1199                 .offset         = GLOBAL_VAR(szWinbinddSocketDirectory),
1200                 .special        = NULL,
1201                 .enum_list      = NULL
1202         },
1203         {
1204                 .label          = "winbindd privileged socket directory",
1205                 .type           = P_STRING,
1206                 .p_class        = P_GLOBAL,
1207                 .offset         = GLOBAL_VAR(szWinbinddPrivilegedSocketDirectory),
1208                 .special        = NULL,
1209                 .enum_list      = NULL
1210         },
1211         {
1212                 .label          = "winbind sealed pipes",
1213                 .type           = P_BOOL,
1214                 .p_class        = P_GLOBAL,
1215                 .offset         = GLOBAL_VAR(bWinbindSealedPipes),
1216                 .special        = NULL,
1217                 .enum_list      = NULL
1218         },
1219         {
1220                 .label          = "template shell",
1221                 .type           = P_STRING,
1222                 .p_class        = P_GLOBAL,
1223                 .offset         = GLOBAL_VAR(szTemplateShell),
1224                 .special        = NULL,
1225                 .enum_list      = NULL
1226         },
1227         {
1228                 .label          = "template homedir",
1229                 .type           = P_STRING,
1230                 .p_class        = P_GLOBAL,
1231                 .offset         = GLOBAL_VAR(szTemplateHomedir),
1232                 .special        = NULL,
1233                 .enum_list      = NULL
1234         },
1235         {
1236                 .label          = "idmap trusted only",
1237                 .type           = P_BOOL,
1238                 .p_class        = P_GLOBAL,
1239                 .offset         = GLOBAL_VAR(bIdmapTrustedOnly),
1240                 .special        = NULL,
1241                 .enum_list      = NULL
1242         },
1243
1244         {
1245                 .label          = "ntp signd socket directory",
1246                 .type           = P_STRING,
1247                 .p_class        = P_GLOBAL,
1248                 .offset         = GLOBAL_VAR(szNTPSignDSocketDirectory),
1249                 .special        = NULL,
1250                 .enum_list      = NULL
1251         },
1252         {
1253                 .label          = "rndc command",
1254                 .type           = P_CMDLIST,
1255                 .p_class        = P_GLOBAL,
1256                 .offset         = GLOBAL_VAR(szRNDCCommand),
1257                 .special        = NULL,
1258                 .enum_list      = NULL
1259         },
1260         {
1261                 .label          = "dns update command",
1262                 .type           = P_CMDLIST,
1263                 .p_class        = P_GLOBAL,
1264                 .offset         = GLOBAL_VAR(szDNSUpdateCommand),
1265                 .special        = NULL,
1266                 .enum_list      = NULL
1267         },
1268         {
1269                 .label          = "spn update command",
1270                 .type           = P_CMDLIST,
1271                 .p_class        = P_GLOBAL,
1272                 .offset         = GLOBAL_VAR(szSPNUpdateCommand),
1273                 .special        = NULL,
1274                 .enum_list      = NULL
1275         },
1276         {
1277                 .label          = "nsupdate command",
1278                 .type           = P_CMDLIST,
1279                 .p_class        = P_GLOBAL,
1280                 .offset         = GLOBAL_VAR(szNSUpdateCommand),
1281                 .special        = NULL,
1282                 .enum_list      = NULL
1283         },
1284
1285         {NULL,  P_BOOL,  P_NONE,  0,  NULL,  NULL,  0}
1286 };
1287
1288
1289 /* local variables */
1290 struct loadparm_context {
1291         const char *szConfigFile;
1292         struct loadparm_global *globals;
1293         struct loadparm_service **services;
1294         struct loadparm_service *sDefault;
1295         struct smb_iconv_handle *iconv_handle;
1296         int iNumServices;
1297         struct loadparm_service *currentService;
1298         bool bInGlobalSection;
1299         struct file_lists {
1300                 struct file_lists *next;
1301                 char *name;
1302                 char *subfname;
1303                 time_t modtime;
1304         } *file_lists;
1305         unsigned int flags[NUMPARAMETERS];
1306         bool loaded;
1307         bool refuse_free;
1308         bool global; /* Is this the global context, which may set
1309                       * global variables such as debug level etc? */
1310         const struct loadparm_s3_context *s3_fns;
1311 };
1312
1313
1314 struct loadparm_service *lpcfg_default_service(struct loadparm_context *lp_ctx)
1315 {
1316         if (lp_ctx->s3_fns) {
1317                 return lp_ctx->s3_fns->get_default_loadparm_service();
1318         }
1319         return lp_ctx->sDefault;
1320 }
1321
1322 /**
1323  * Convenience routine to grab string parameters into temporary memory
1324  * and run standard_sub_basic on them.
1325  *
1326  * The buffers can be written to by
1327  * callers without affecting the source string.
1328  */
1329
1330 static const char *lp_string(const char *s)
1331 {
1332 #if 0  /* until REWRITE done to make thread-safe */
1333         size_t len = s ? strlen(s) : 0;
1334         char *ret;
1335 #endif
1336
1337         /* The follow debug is useful for tracking down memory problems
1338            especially if you have an inner loop that is calling a lp_*()
1339            function that returns a string.  Perhaps this debug should be
1340            present all the time? */
1341
1342 #if 0
1343         DEBUG(10, ("lp_string(%s)\n", s));
1344 #endif
1345
1346 #if 0  /* until REWRITE done to make thread-safe */
1347         if (!lp_talloc)
1348                 lp_talloc = talloc_init("lp_talloc");
1349
1350         ret = talloc_array(lp_talloc, char, len + 100); /* leave room for substitution */
1351
1352         if (!ret)
1353                 return NULL;
1354
1355         if (!s)
1356                 *ret = 0;
1357         else
1358                 strlcpy(ret, s, len);
1359
1360         if (trim_string(ret, "\"", "\"")) {
1361                 if (strchr(ret,'"') != NULL)
1362                         strlcpy(ret, s, len);
1363         }
1364
1365         standard_sub_basic(ret,len+100);
1366         return (ret);
1367 #endif
1368         return s;
1369 }
1370
1371 /*
1372    In this section all the functions that are used to access the
1373    parameters from the rest of the program are defined
1374 */
1375
1376 /*
1377  * the creation of separate lpcfg_*() and lp_*() functions is to allow
1378  * for code compatibility between existing Samba4 and Samba3 code.
1379  */
1380
1381 /* this global context supports the lp_*() function varients */
1382 static struct loadparm_context *global_loadparm_context;
1383
1384 #define lpcfg_default_service global_loadparm_context->sDefault
1385 #define lpcfg_global_service(i) global_loadparm_context->services[i]
1386
1387 #define FN_GLOBAL_STRING(fn_name,var_name)                              \
1388  _PUBLIC_ const char *lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) { \
1389         if (lp_ctx == NULL) return NULL;                                \
1390         if (lp_ctx->s3_fns) {                                           \
1391                 SMB_ASSERT(lp_ctx->s3_fns->fn_name);                    \
1392                 return lp_ctx->s3_fns->fn_name();                       \
1393         }                                                               \
1394         return lp_ctx->globals->var_name ? lp_string(lp_ctx->globals->var_name) : ""; \
1395 }
1396
1397 #define FN_GLOBAL_CONST_STRING(fn_name,var_name) \
1398  _PUBLIC_ const char *lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) {\
1399          if (lp_ctx == NULL) return NULL;                               \
1400          if (lp_ctx->s3_fns) {                                          \
1401                  SMB_ASSERT(lp_ctx->s3_fns->fn_name);                   \
1402                  return lp_ctx->s3_fns->fn_name();                      \
1403          }                                                              \
1404          return lp_ctx->globals->var_name ? lp_string(lp_ctx->globals->var_name) : ""; \
1405  }
1406
1407 #define FN_GLOBAL_LIST(fn_name,var_name)                                \
1408  _PUBLIC_ const char **lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) { \
1409          if (lp_ctx == NULL) return NULL;                               \
1410          if (lp_ctx->s3_fns) {                                          \
1411                  SMB_ASSERT(lp_ctx->s3_fns->fn_name);                   \
1412                  return lp_ctx->s3_fns->fn_name();                      \
1413          }                                                              \
1414          return lp_ctx->globals->var_name;                              \
1415  }
1416
1417 #define FN_GLOBAL_BOOL(fn_name,var_name) \
1418  _PUBLIC_ bool lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) {\
1419          if (lp_ctx == NULL) return false;                              \
1420          if (lp_ctx->s3_fns) {                                          \
1421                  SMB_ASSERT(lp_ctx->s3_fns->fn_name);                   \
1422                  return lp_ctx->s3_fns->fn_name();                      \
1423          }                                                              \
1424          return lp_ctx->globals->var_name;                              \
1425 }
1426
1427 #define FN_GLOBAL_INTEGER(fn_name,var_name) \
1428  _PUBLIC_ int lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) { \
1429          if (lp_ctx->s3_fns) {                                          \
1430                  SMB_ASSERT(lp_ctx->s3_fns->fn_name);                   \
1431                  return lp_ctx->s3_fns->fn_name();                      \
1432          }                                                              \
1433          return lp_ctx->globals->var_name;                              \
1434  }
1435
1436 /* Local parameters don't need the ->s3_fns because the struct
1437  * loadparm_service is shared and lpcfg_service() checks the ->s3_fns
1438  * hook */
1439 #define FN_LOCAL_STRING(fn_name,val) \
1440  _PUBLIC_ const char *lpcfg_ ## fn_name(struct loadparm_service *service, \
1441                                         struct loadparm_service *sDefault) { \
1442          return(lp_string((const char *)((service != NULL && service->val != NULL) ? service->val : sDefault->val))); \
1443  }
1444
1445 #define FN_LOCAL_CONST_STRING(fn_name,val) FN_LOCAL_STRING(fn_name, val)
1446
1447 #define FN_LOCAL_LIST(fn_name,val) \
1448  _PUBLIC_ const char **lpcfg_ ## fn_name(struct loadparm_service *service, \
1449                                          struct loadparm_service *sDefault) {\
1450          return(const char **)(service != NULL && service->val != NULL? service->val : sDefault->val); \
1451  }
1452
1453 #define FN_LOCAL_PARM_BOOL(fn_name, val) FN_LOCAL_BOOL(fn_name, val)
1454
1455 #define FN_LOCAL_BOOL(fn_name,val) \
1456  _PUBLIC_ bool lpcfg_ ## fn_name(struct loadparm_service *service, \
1457                                  struct loadparm_service *sDefault) {   \
1458          return((service != NULL)? service->val : sDefault->val); \
1459  }
1460
1461 #define FN_LOCAL_INTEGER(fn_name,val) \
1462  _PUBLIC_ int lpcfg_ ## fn_name(struct loadparm_service *service, \
1463                                 struct loadparm_service *sDefault) {    \
1464          return((service != NULL)? service->val : sDefault->val); \
1465  }
1466
1467 #define FN_LOCAL_PARM_INTEGER(fn_name, val) FN_LOCAL_INTEGER(fn_name, val)
1468
1469 #define FN_LOCAL_PARM_CHAR(fn_name, val) FN_LOCAL_CHAR(fn_name, val)
1470
1471 #define FN_LOCAL_CHAR(fn_name,val) \
1472  _PUBLIC_ char lpcfg_ ## fn_name(struct loadparm_service *service, \
1473                                 struct loadparm_service *sDefault) {    \
1474          return((service != NULL)? service->val : sDefault->val); \
1475  }
1476
1477 #include "lib/param/param_functions.c"
1478
1479 FN_GLOBAL_INTEGER(server_role, server_role)
1480 FN_GLOBAL_BOOL(domain_logons, domain_logons)
1481 FN_GLOBAL_INTEGER(domain_master, domain_master)
1482 FN_GLOBAL_LIST(smb_ports, smb_ports)
1483 FN_GLOBAL_INTEGER(nbt_port, nbt_port)
1484 FN_GLOBAL_INTEGER(dgram_port, dgram_port)
1485 FN_GLOBAL_INTEGER(cldap_port, cldap_port)
1486 FN_GLOBAL_INTEGER(krb5_port, krb5_port)
1487 FN_GLOBAL_INTEGER(kpasswd_port, kpasswd_port)
1488 FN_GLOBAL_INTEGER(web_port, web_port)
1489 FN_GLOBAL_BOOL(tls_enabled, tls_enabled)
1490 FN_GLOBAL_STRING(logfile, logfile)
1491 FN_GLOBAL_STRING(share_backend, szShareBackend)
1492 FN_GLOBAL_CONST_STRING(winbind_separator, szWinbindSeparator)
1493 FN_GLOBAL_CONST_STRING(winbindd_socket_directory, szWinbinddSocketDirectory)
1494 FN_GLOBAL_CONST_STRING(winbindd_privileged_socket_directory, szWinbinddPrivilegedSocketDirectory)
1495 FN_GLOBAL_CONST_STRING(template_shell, szTemplateShell)
1496 FN_GLOBAL_CONST_STRING(template_homedir, szTemplateHomedir)
1497 FN_GLOBAL_BOOL(winbind_sealed_pipes, bWinbindSealedPipes)
1498 FN_GLOBAL_BOOL(idmap_trusted_only, bIdmapTrustedOnly)
1499 FN_GLOBAL_STRING(private_dir, szPrivateDir)
1500 FN_GLOBAL_STRING(serverstring, szServerString)
1501 FN_GLOBAL_STRING(lockdir, szLockDir)
1502 FN_GLOBAL_STRING(statedir, szStateDir)
1503 FN_GLOBAL_STRING(cachedir, szCacheDir)
1504 FN_GLOBAL_STRING(ncalrpc_dir, ncalrpc_dir)
1505 FN_GLOBAL_STRING(dos_charset, dos_charset)
1506 FN_GLOBAL_STRING(unix_charset, unix_charset)
1507 FN_GLOBAL_STRING(piddir, szPidDir)
1508 FN_GLOBAL_LIST(rndc_command, szRNDCCommand)
1509 FN_GLOBAL_LIST(dns_update_command, szDNSUpdateCommand)
1510 FN_GLOBAL_LIST(spn_update_command, szSPNUpdateCommand)
1511 FN_GLOBAL_LIST(nsupdate_command, szNSUpdateCommand)
1512 FN_GLOBAL_LIST(dcerpc_endpoint_servers, dcerpc_ep_servers)
1513 FN_GLOBAL_LIST(server_services, server_services)
1514 FN_GLOBAL_STRING(ntptr_providor, ntptr_providor)
1515 FN_GLOBAL_STRING(passdb_backend, passdb_backend)
1516 FN_GLOBAL_STRING(auto_services, szAutoServices)
1517 FN_GLOBAL_STRING(passwd_chat, szPasswdChat)
1518 FN_GLOBAL_LIST(passwordserver, szPasswordServers)
1519 FN_GLOBAL_LIST(name_resolve_order, szNameResolveOrder)
1520 FN_GLOBAL_STRING(realm, szRealm_upper)
1521 FN_GLOBAL_STRING(dnsdomain, szRealm_lower)
1522 FN_GLOBAL_STRING(socket_options, socket_options)
1523 FN_GLOBAL_STRING(workgroup, szWorkgroup)
1524 FN_GLOBAL_STRING(netbios_name, szNetbiosName)
1525 FN_GLOBAL_STRING(netbios_scope, szNetbiosScope)
1526 FN_GLOBAL_LIST(wins_server_list, szWINSservers)
1527 FN_GLOBAL_LIST(interfaces, szInterfaces)
1528 FN_GLOBAL_STRING(socket_address, szSocketAddress)
1529 FN_GLOBAL_LIST(netbios_aliases, szNetbiosAliases)
1530 FN_GLOBAL_BOOL(disable_netbios, bDisableNetbios)
1531 FN_GLOBAL_BOOL(we_are_a_wins_server, bWINSsupport)
1532 FN_GLOBAL_BOOL(wins_dns_proxy, bWINSdnsProxy)
1533 FN_GLOBAL_STRING(wins_hook, szWINSHook)
1534 FN_GLOBAL_BOOL(local_master, bLocalMaster)
1535 FN_GLOBAL_BOOL(readraw, bReadRaw)
1536 FN_GLOBAL_BOOL(large_readwrite, bLargeReadwrite)
1537 FN_GLOBAL_BOOL(writeraw, bWriteRaw)
1538 FN_GLOBAL_BOOL(null_passwords, bNullPasswords)
1539 FN_GLOBAL_BOOL(obey_pam_restrictions, bObeyPamRestrictions)
1540 FN_GLOBAL_BOOL(encrypted_passwords, bEncryptPasswords)
1541 FN_GLOBAL_BOOL(time_server, bTimeServer)
1542 FN_GLOBAL_BOOL(bind_interfaces_only, bBindInterfacesOnly)
1543 FN_GLOBAL_BOOL(unicode, bUnicode)
1544 FN_GLOBAL_BOOL(nt_status_support, bNTStatusSupport)
1545 FN_GLOBAL_BOOL(lanman_auth, bLanmanAuth)
1546 FN_GLOBAL_BOOL(ntlm_auth, bNTLMAuth)
1547 FN_GLOBAL_BOOL(client_plaintext_auth, bClientPlaintextAuth)
1548 FN_GLOBAL_BOOL(client_lanman_auth, bClientLanManAuth)
1549 FN_GLOBAL_BOOL(client_ntlmv2_auth, bClientNTLMv2Auth)
1550 FN_GLOBAL_BOOL(client_use_spnego_principal, client_use_spnego_principal)
1551 FN_GLOBAL_BOOL(host_msdfs, bHostMSDfs)
1552 FN_GLOBAL_BOOL(unix_extensions, bUnixExtensions)
1553 FN_GLOBAL_BOOL(use_spnego, bUseSpnego)
1554 FN_GLOBAL_BOOL(use_mmap, bUseMmap)
1555 FN_GLOBAL_BOOL(rpc_big_endian, bRpcBigEndian)
1556 FN_GLOBAL_INTEGER(max_wins_ttl, max_wins_ttl)
1557 FN_GLOBAL_INTEGER(min_wins_ttl, min_wins_ttl)
1558 FN_GLOBAL_INTEGER(maxmux, max_mux)
1559 FN_GLOBAL_INTEGER(max_xmit, max_xmit)
1560 FN_GLOBAL_INTEGER(passwordlevel, pwordlevel)
1561 FN_GLOBAL_INTEGER(srv_maxprotocol, srv_maxprotocol)
1562 FN_GLOBAL_INTEGER(srv_minprotocol, srv_minprotocol)
1563 FN_GLOBAL_INTEGER(cli_maxprotocol, cli_maxprotocol)
1564 FN_GLOBAL_INTEGER(cli_minprotocol, cli_minprotocol)
1565 FN_GLOBAL_INTEGER(security, security)
1566 FN_GLOBAL_BOOL(paranoid_server_security, paranoid_server_security)
1567
1568 FN_GLOBAL_INTEGER(server_signing, server_signing)
1569 FN_GLOBAL_INTEGER(client_signing, client_signing)
1570
1571 FN_GLOBAL_CONST_STRING(ntp_signd_socket_directory, szNTPSignDSocketDirectory)
1572
1573 /* local prototypes */
1574 static int map_parameter(const char *pszParmName);
1575 static struct loadparm_service *getservicebyname(struct loadparm_context *lp_ctx,
1576                                         const char *pszServiceName);
1577 static void copy_service(struct loadparm_service *pserviceDest,
1578                          struct loadparm_service *pserviceSource,
1579                          struct bitmap *pcopymapDest);
1580 static bool lpcfg_service_ok(struct loadparm_service *service);
1581 static bool do_section(const char *pszSectionName, void *);
1582 static void init_copymap(struct loadparm_service *pservice);
1583
1584 /* This is a helper function for parametrical options support. */
1585 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
1586 /* Actual parametrical functions are quite simple */
1587 const char *lpcfg_get_parametric(struct loadparm_context *lp_ctx,
1588                               struct loadparm_service *service,
1589                               const char *type, const char *option)
1590 {
1591         char *vfskey_tmp = NULL;
1592         char *vfskey = NULL;
1593         struct parmlist_entry *data;
1594
1595         if (lp_ctx == NULL)
1596                 return NULL;
1597
1598         if (lp_ctx->s3_fns) {
1599                 return lp_ctx->s3_fns->get_parametric(service, type, option);
1600         }
1601
1602         data = (service == NULL ? lp_ctx->globals->param_opt : service->param_opt);
1603
1604         vfskey_tmp = talloc_asprintf(NULL, "%s:%s", type, option);
1605         if (vfskey_tmp == NULL) return NULL;
1606         vfskey = strlower_talloc(NULL, vfskey_tmp);
1607         talloc_free(vfskey_tmp);
1608
1609         while (data) {
1610                 if (strcmp(data->key, vfskey) == 0) {
1611                         talloc_free(vfskey);
1612                         return data->value;
1613                 }
1614                 data = data->next;
1615         }
1616
1617         if (service != NULL) {
1618                 /* Try to fetch the same option but from globals */
1619                 /* but only if we are not already working with globals */
1620                 for (data = lp_ctx->globals->param_opt; data;
1621                      data = data->next) {
1622                         if (strcmp(data->key, vfskey) == 0) {
1623                                 talloc_free(vfskey);
1624                                 return data->value;
1625                         }
1626                 }
1627         }
1628
1629         talloc_free(vfskey);
1630
1631         return NULL;
1632 }
1633
1634
1635 /**
1636  * convenience routine to return int parameters.
1637  */
1638 static int lp_int(const char *s)
1639 {
1640
1641         if (!s) {
1642                 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
1643                 return -1;
1644         }
1645
1646         return strtol(s, NULL, 0);
1647 }
1648
1649 /**
1650  * convenience routine to return unsigned long parameters.
1651  */
1652 static int lp_ulong(const char *s)
1653 {
1654
1655         if (!s) {
1656                 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
1657                 return -1;
1658         }
1659
1660         return strtoul(s, NULL, 0);
1661 }
1662
1663 /**
1664  * convenience routine to return unsigned long parameters.
1665  */
1666 static double lp_double(const char *s)
1667 {
1668
1669         if (!s) {
1670                 DEBUG(0,("lp_double(%s): is called with NULL!\n",s));
1671                 return -1;
1672         }
1673
1674         return strtod(s, NULL);
1675 }
1676
1677 /**
1678  * convenience routine to return boolean parameters.
1679  */
1680 static bool lp_bool(const char *s)
1681 {
1682         bool ret = false;
1683
1684         if (!s) {
1685                 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
1686                 return false;
1687         }
1688
1689         if (!set_boolean(s, &ret)) {
1690                 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1691                 return false;
1692         }
1693
1694         return ret;
1695 }
1696
1697
1698 /**
1699  * Return parametric option from a given service. Type is a part of option before ':'
1700  * Parametric option has following syntax: 'Type: option = value'
1701  * Returned value is allocated in 'lp_talloc' context
1702  */
1703
1704 const char *lpcfg_parm_string(struct loadparm_context *lp_ctx,
1705                               struct loadparm_service *service, const char *type,
1706                               const char *option)
1707 {
1708         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
1709
1710         if (value)
1711                 return lp_string(value);
1712
1713         return NULL;
1714 }
1715
1716 /**
1717  * Return parametric option from a given service. Type is a part of option before ':'
1718  * Parametric option has following syntax: 'Type: option = value'
1719  * Returned value is allocated in 'lp_talloc' context
1720  */
1721
1722 const char **lpcfg_parm_string_list(TALLOC_CTX *mem_ctx,
1723                                     struct loadparm_context *lp_ctx,
1724                                     struct loadparm_service *service,
1725                                     const char *type,
1726                                     const char *option, const char *separator)
1727 {
1728         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
1729
1730         if (value != NULL)
1731                 return (const char **)str_list_make(mem_ctx, value, separator);
1732
1733         return NULL;
1734 }
1735
1736 /**
1737  * Return parametric option from a given service. Type is a part of option before ':'
1738  * Parametric option has following syntax: 'Type: option = value'
1739  */
1740
1741 int lpcfg_parm_int(struct loadparm_context *lp_ctx,
1742                    struct loadparm_service *service, const char *type,
1743                    const char *option, int default_v)
1744 {
1745         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
1746
1747         if (value)
1748                 return lp_int(value);
1749
1750         return default_v;
1751 }
1752
1753 /**
1754  * Return parametric option from a given service. Type is a part of
1755  * option before ':'.
1756  * Parametric option has following syntax: 'Type: option = value'.
1757  */
1758
1759 int lpcfg_parm_bytes(struct loadparm_context *lp_ctx,
1760                   struct loadparm_service *service, const char *type,
1761                   const char *option, int default_v)
1762 {
1763         uint64_t bval;
1764
1765         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
1766
1767         if (value && conv_str_size_error(value, &bval)) {
1768                 if (bval <= INT_MAX) {
1769                         return (int)bval;
1770                 }
1771         }
1772
1773         return default_v;
1774 }
1775
1776 /**
1777  * Return parametric option from a given service.
1778  * Type is a part of option before ':'
1779  * Parametric option has following syntax: 'Type: option = value'
1780  */
1781 unsigned long lpcfg_parm_ulong(struct loadparm_context *lp_ctx,
1782                             struct loadparm_service *service, const char *type,
1783                             const char *option, unsigned long default_v)
1784 {
1785         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
1786
1787         if (value)
1788                 return lp_ulong(value);
1789
1790         return default_v;
1791 }
1792
1793
1794 double lpcfg_parm_double(struct loadparm_context *lp_ctx,
1795                       struct loadparm_service *service, const char *type,
1796                       const char *option, double default_v)
1797 {
1798         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
1799
1800         if (value != NULL)
1801                 return lp_double(value);
1802
1803         return default_v;
1804 }
1805
1806 /**
1807  * Return parametric option from a given service. Type is a part of option before ':'
1808  * Parametric option has following syntax: 'Type: option = value'
1809  */
1810
1811 bool lpcfg_parm_bool(struct loadparm_context *lp_ctx,
1812                      struct loadparm_service *service, const char *type,
1813                      const char *option, bool default_v)
1814 {
1815         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
1816
1817         if (value != NULL)
1818                 return lp_bool(value);
1819
1820         return default_v;
1821 }
1822
1823
1824 /**
1825  * Initialise a service to the defaults.
1826  */
1827
1828 static struct loadparm_service *init_service(TALLOC_CTX *mem_ctx, struct loadparm_service *sDefault)
1829 {
1830         struct loadparm_service *pservice =
1831                 talloc_zero(mem_ctx, struct loadparm_service);
1832         copy_service(pservice, sDefault, NULL);
1833         return pservice;
1834 }
1835
1836 /**
1837  * Set a string value, deallocating any existing space, and allocing the space
1838  * for the string
1839  */
1840 static bool lpcfg_string_set(TALLOC_CTX *mem_ctx, char **dest, const char *src)
1841 {
1842         talloc_free(*dest);
1843
1844         if (src == NULL)
1845                 src = "";
1846
1847         *dest = talloc_strdup(mem_ctx, src);
1848         if ((*dest) == NULL) {
1849                 DEBUG(0,("Out of memory in string_set\n"));
1850                 return false;
1851         }
1852
1853         return true;
1854 }
1855
1856 /**
1857  * Set a string value, deallocating any existing space, and allocing the space
1858  * for the string
1859  */
1860 static bool lpcfg_string_set_upper(TALLOC_CTX *mem_ctx, char **dest, const char *src)
1861 {
1862         talloc_free(*dest);
1863
1864         if (src == NULL)
1865                 src = "";
1866
1867         *dest = strupper_talloc(mem_ctx, src);
1868         if ((*dest) == NULL) {
1869                 DEBUG(0,("Out of memory in string_set_upper\n"));
1870                 return false;
1871         }
1872
1873         return true;
1874 }
1875
1876
1877
1878 /**
1879  * Add a new service to the services array initialising it with the given
1880  * service.
1881  */
1882
1883 struct loadparm_service *lpcfg_add_service(struct loadparm_context *lp_ctx,
1884                                            const struct loadparm_service *pservice,
1885                                            const char *name)
1886 {
1887         int i;
1888         struct loadparm_service tservice;
1889         int num_to_alloc = lp_ctx->iNumServices + 1;
1890         struct parmlist_entry *data, *pdata;
1891
1892         if (pservice == NULL) {
1893                 pservice = lp_ctx->sDefault;
1894         }
1895
1896         tservice = *pservice;
1897
1898         /* it might already exist */
1899         if (name) {
1900                 struct loadparm_service *service = getservicebyname(lp_ctx,
1901                                                                     name);
1902                 if (service != NULL) {
1903                         /* Clean all parametric options for service */
1904                         /* They will be added during parsing again */
1905                         data = service->param_opt;
1906                         while (data) {
1907                                 pdata = data->next;
1908                                 talloc_free(data);
1909                                 data = pdata;
1910                         }
1911                         service->param_opt = NULL;
1912                         return service;
1913                 }
1914         }
1915
1916         /* find an invalid one */
1917         for (i = 0; i < lp_ctx->iNumServices; i++)
1918                 if (lp_ctx->services[i] == NULL)
1919                         break;
1920
1921         /* if not, then create one */
1922         if (i == lp_ctx->iNumServices) {
1923                 struct loadparm_service **tsp;
1924
1925                 tsp = talloc_realloc(lp_ctx, lp_ctx->services, struct loadparm_service *, num_to_alloc);
1926
1927                 if (!tsp) {
1928                         DEBUG(0,("lpcfg_add_service: failed to enlarge services!\n"));
1929                         return NULL;
1930                 } else {
1931                         lp_ctx->services = tsp;
1932                         lp_ctx->services[lp_ctx->iNumServices] = NULL;
1933                 }
1934
1935                 lp_ctx->iNumServices++;
1936         }
1937
1938         lp_ctx->services[i] = init_service(lp_ctx->services, lp_ctx->sDefault);
1939         if (lp_ctx->services[i] == NULL) {
1940                 DEBUG(0,("lpcfg_add_service: out of memory!\n"));
1941                 return NULL;
1942         }
1943         copy_service(lp_ctx->services[i], &tservice, NULL);
1944         if (name != NULL)
1945                 lpcfg_string_set(lp_ctx->services[i], &lp_ctx->services[i]->szService, name);
1946         return lp_ctx->services[i];
1947 }
1948
1949 /**
1950  * Add a new home service, with the specified home directory, defaults coming
1951  * from service ifrom.
1952  */
1953
1954 bool lpcfg_add_home(struct loadparm_context *lp_ctx,
1955                  const char *pszHomename,
1956                  struct loadparm_service *default_service,
1957                  const char *user, const char *pszHomedir)
1958 {
1959         struct loadparm_service *service;
1960
1961         service = lpcfg_add_service(lp_ctx, default_service, pszHomename);
1962
1963         if (service == NULL)
1964                 return false;
1965
1966         if (!(*(default_service->szPath))
1967             || strequal(default_service->szPath, lp_ctx->sDefault->szPath)) {
1968                 service->szPath = talloc_strdup(service, pszHomedir);
1969         } else {
1970                 service->szPath = string_sub_talloc(service, lpcfg_pathname(default_service, lp_ctx->sDefault), "%H", pszHomedir);
1971         }
1972
1973         if (!(*(service->comment))) {
1974                 service->comment = talloc_asprintf(service, "Home directory of %s", user);
1975         }
1976         service->bAvailable = default_service->bAvailable;
1977         service->bBrowseable = default_service->bBrowseable;
1978
1979         DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n",
1980                   pszHomename, user, service->szPath));
1981
1982         return true;
1983 }
1984
1985 /**
1986  * Add a new printer service, with defaults coming from service iFrom.
1987  */
1988
1989 bool lpcfg_add_printer(struct loadparm_context *lp_ctx,
1990                        const char *pszPrintername,
1991                        struct loadparm_service *default_service)
1992 {
1993         const char *comment = "From Printcap";
1994         struct loadparm_service *service;
1995         service = lpcfg_add_service(lp_ctx, default_service, pszPrintername);
1996
1997         if (service == NULL)
1998                 return false;
1999
2000         /* note that we do NOT default the availability flag to True - */
2001         /* we take it from the default service passed. This allows all */
2002         /* dynamic printers to be disabled by disabling the [printers] */
2003         /* entry (if/when the 'available' keyword is implemented!).    */
2004
2005         /* the printer name is set to the service name. */
2006         lpcfg_string_set(service, &service->szPrintername, pszPrintername);
2007         lpcfg_string_set(service, &service->comment, comment);
2008         service->bBrowseable = default_service->bBrowseable;
2009         /* Printers cannot be read_only. */
2010         service->bRead_only = false;
2011         /* Printer services must be printable. */
2012         service->bPrint_ok = true;
2013
2014         DEBUG(3, ("adding printer service %s\n", pszPrintername));
2015
2016         return true;
2017 }
2018
2019 /**
2020  * Map a parameter's string representation to something we can use.
2021  * Returns False if the parameter string is not recognised, else TRUE.
2022  */
2023
2024 static int map_parameter(const char *pszParmName)
2025 {
2026         int iIndex;
2027
2028         if (*pszParmName == '-')
2029                 return -1;
2030
2031         for (iIndex = 0; parm_table[iIndex].label; iIndex++)
2032                 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
2033                         return iIndex;
2034
2035         /* Warn only if it isn't parametric option */
2036         if (strchr(pszParmName, ':') == NULL)
2037                 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
2038         /* We do return 'fail' for parametric options as well because they are
2039            stored in different storage
2040          */
2041         return -1;
2042 }
2043
2044
2045 /**
2046   return the parameter structure for a parameter
2047 */
2048 struct parm_struct *lpcfg_parm_struct(struct loadparm_context *lp_ctx, const char *name)
2049 {
2050         int parmnum;
2051
2052         if (lp_ctx->s3_fns) {
2053                 return lp_ctx->s3_fns->get_parm_struct(name);
2054         }
2055
2056         parmnum = map_parameter(name);
2057         if (parmnum == -1) return NULL;
2058         return &parm_table[parmnum];
2059 }
2060
2061 /**
2062   return the parameter pointer for a parameter
2063 */
2064 void *lpcfg_parm_ptr(struct loadparm_context *lp_ctx,
2065                   struct loadparm_service *service, struct parm_struct *parm)
2066 {
2067         if (lp_ctx->s3_fns) {
2068                 return lp_ctx->s3_fns->get_parm_ptr(service, parm);
2069         }
2070
2071         if (service == NULL) {
2072                 if (parm->p_class == P_LOCAL)
2073                         return ((char *)lp_ctx->sDefault)+parm->offset;
2074                 else if (parm->p_class == P_GLOBAL)
2075                         return ((char *)lp_ctx->globals)+parm->offset;
2076                 else return NULL;
2077         } else {
2078                 return ((char *)service) + parm->offset;
2079         }
2080 }
2081
2082 /**
2083   return the parameter pointer for a parameter
2084 */
2085 bool lpcfg_parm_is_cmdline(struct loadparm_context *lp_ctx, const char *name)
2086 {
2087         int parmnum;
2088
2089         if (lp_ctx->s3_fns) {
2090                 struct parm_struct *parm = lp_ctx->s3_fns->get_parm_struct(name);
2091                 if (parm) {
2092                         return parm->flags & FLAG_CMDLINE;
2093                 }
2094                 return false;
2095         }
2096
2097         parmnum = map_parameter(name);
2098         if (parmnum == -1) return false;
2099
2100         return lp_ctx->flags[parmnum] & FLAG_CMDLINE;
2101 }
2102
2103 /**
2104  * Find a service by name. Otherwise works like get_service.
2105  */
2106
2107 static struct loadparm_service *getservicebyname(struct loadparm_context *lp_ctx,
2108                                         const char *pszServiceName)
2109 {
2110         int iService;
2111
2112         if (lp_ctx->s3_fns) {
2113                 return lp_ctx->s3_fns->get_service(pszServiceName);
2114         }
2115
2116         for (iService = lp_ctx->iNumServices - 1; iService >= 0; iService--)
2117                 if (lp_ctx->services[iService] != NULL &&
2118                     strwicmp(lp_ctx->services[iService]->szService, pszServiceName) == 0) {
2119                         return lp_ctx->services[iService];
2120                 }
2121
2122         return NULL;
2123 }
2124
2125 /**
2126  * Copy a service structure to another.
2127  * If pcopymapDest is NULL then copy all fields
2128  */
2129
2130 static void copy_service(struct loadparm_service *pserviceDest,
2131                          struct loadparm_service *pserviceSource,
2132                          struct bitmap *pcopymapDest)
2133 {
2134         int i;
2135         bool bcopyall = (pcopymapDest == NULL);
2136         struct parmlist_entry *data, *pdata, *paramo;
2137         bool not_added;
2138
2139         for (i = 0; parm_table[i].label; i++)
2140                 if (parm_table[i].p_class == P_LOCAL &&
2141                     (bcopyall || bitmap_query(pcopymapDest, i))) {
2142                         void *src_ptr =
2143                                 ((char *)pserviceSource) + parm_table[i].offset;
2144                         void *dest_ptr =
2145                                 ((char *)pserviceDest) + parm_table[i].offset;
2146
2147                         switch (parm_table[i].type) {
2148                                 case P_BOOL:
2149                                         *(bool *)dest_ptr = *(bool *)src_ptr;
2150                                         break;
2151
2152                                 case P_INTEGER:
2153                                 case P_OCTAL:
2154                                 case P_ENUM:
2155                                         *(int *)dest_ptr = *(int *)src_ptr;
2156                                         break;
2157
2158                                 case P_STRING:
2159                                         lpcfg_string_set(pserviceDest,
2160                                                    (char **)dest_ptr,
2161                                                    *(char **)src_ptr);
2162                                         break;
2163
2164                                 case P_USTRING:
2165                                         lpcfg_string_set_upper(pserviceDest,
2166                                                          (char **)dest_ptr,
2167                                                          *(char **)src_ptr);
2168                                         break;
2169                                 case P_LIST:
2170                                         *(const char ***)dest_ptr = (const char **)str_list_copy(pserviceDest, 
2171                                                                                   *(const char ***)src_ptr);
2172                                         break;
2173                                 default:
2174                                         break;
2175                         }
2176                 }
2177
2178         if (bcopyall) {
2179                 init_copymap(pserviceDest);
2180                 if (pserviceSource->copymap)
2181                         bitmap_copy(pserviceDest->copymap,
2182                                     pserviceSource->copymap);
2183         }
2184
2185         data = pserviceSource->param_opt;
2186         while (data) {
2187                 not_added = true;
2188                 pdata = pserviceDest->param_opt;
2189                 /* Traverse destination */
2190                 while (pdata) {
2191                         /* If we already have same option, override it */
2192                         if (strcmp(pdata->key, data->key) == 0) {
2193                                 talloc_free(pdata->value);
2194                                 pdata->value = talloc_reference(pdata,
2195                                                              data->value);
2196                                 not_added = false;
2197                                 break;
2198                         }
2199                         pdata = pdata->next;
2200                 }
2201                 if (not_added) {
2202                         paramo = talloc_zero(pserviceDest, struct parmlist_entry);
2203                         if (paramo == NULL)
2204                                 smb_panic("OOM");
2205                         paramo->key = talloc_reference(paramo, data->key);
2206                         paramo->value = talloc_reference(paramo, data->value);
2207                         DLIST_ADD(pserviceDest->param_opt, paramo);
2208                 }
2209                 data = data->next;
2210         }
2211 }
2212
2213 /**
2214  * Check a service for consistency. Return False if the service is in any way
2215  * incomplete or faulty, else True.
2216  */
2217 static bool lpcfg_service_ok(struct loadparm_service *service)
2218 {
2219         bool bRetval;
2220
2221         bRetval = true;
2222         if (service->szService[0] == '\0') {
2223                 DEBUG(0, ("The following message indicates an internal error:\n"));
2224                 DEBUG(0, ("No service name in service entry.\n"));
2225                 bRetval = false;
2226         }
2227
2228         /* The [printers] entry MUST be printable. I'm all for flexibility, but */
2229         /* I can't see why you'd want a non-printable printer service...        */
2230         if (strwicmp(service->szService, PRINTERS_NAME) == 0) {
2231                 if (!service->bPrint_ok) {
2232                         DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
2233                                service->szService));
2234                         service->bPrint_ok = true;
2235                 }
2236                 /* [printers] service must also be non-browsable. */
2237                 if (service->bBrowseable)
2238                         service->bBrowseable = false;
2239         }
2240
2241         /* If a service is flagged unavailable, log the fact at level 0. */
2242         if (!service->bAvailable)
2243                 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
2244                           service->szService));
2245
2246         return bRetval;
2247 }
2248
2249
2250 /*******************************************************************
2251  Keep a linked list of all config files so we know when one has changed
2252  it's date and needs to be reloaded.
2253 ********************************************************************/
2254
2255 static void add_to_file_list(struct loadparm_context *lp_ctx,
2256                              const char *fname, const char *subfname)
2257 {
2258         struct file_lists *f = lp_ctx->file_lists;
2259
2260         while (f) {
2261                 if (f->name && !strcmp(f->name, fname))
2262                         break;
2263                 f = f->next;
2264         }
2265
2266         if (!f) {
2267                 f = talloc(lp_ctx, struct file_lists);
2268                 if (!f)
2269                         return;
2270                 f->next = lp_ctx->file_lists;
2271                 f->name = talloc_strdup(f, fname);
2272                 if (!f->name) {
2273                         talloc_free(f);
2274                         return;
2275                 }
2276                 f->subfname = talloc_strdup(f, subfname);
2277                 if (!f->subfname) {
2278                         talloc_free(f);
2279                         return;
2280                 }
2281                 lp_ctx->file_lists = f;
2282                 f->modtime = file_modtime(subfname);
2283         } else {
2284                 time_t t = file_modtime(subfname);
2285                 if (t)
2286                         f->modtime = t;
2287         }
2288 }
2289
2290 /*******************************************************************
2291  Check if a config file has changed date.
2292 ********************************************************************/
2293 bool lpcfg_file_list_changed(struct loadparm_context *lp_ctx)
2294 {
2295         struct file_lists *f;
2296         DEBUG(6, ("lp_file_list_changed()\n"));
2297
2298         for (f = lp_ctx->file_lists; f != NULL; f = f->next) {
2299                 char *n2;
2300                 time_t mod_time;
2301
2302                 n2 = standard_sub_basic(lp_ctx, f->name);
2303
2304                 DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
2305                              f->name, n2, ctime(&f->modtime)));
2306
2307                 mod_time = file_modtime(n2);
2308
2309                 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
2310                         DEBUGADD(6, ("file %s modified: %s\n", n2,
2311                                   ctime(&mod_time)));
2312                         f->modtime = mod_time;
2313                         talloc_free(f->subfname);
2314                         f->subfname = talloc_strdup(f, n2);
2315                         return true;
2316                 }
2317         }
2318         return false;
2319 }
2320
2321 /***************************************************************************
2322  Handle the "realm" parameter
2323 ***************************************************************************/
2324
2325 static bool handle_realm(struct loadparm_context *lp_ctx, int unused,
2326                          const char *pszParmValue, char **ptr)
2327 {
2328         lpcfg_string_set(lp_ctx, ptr, pszParmValue);
2329
2330         talloc_free(lp_ctx->globals->szRealm_upper);
2331         talloc_free(lp_ctx->globals->szRealm_lower);
2332
2333         lp_ctx->globals->szRealm_upper = strupper_talloc(lp_ctx, pszParmValue);
2334         lp_ctx->globals->szRealm_lower = strlower_talloc(lp_ctx, pszParmValue);
2335
2336         return true;
2337 }
2338
2339 /***************************************************************************
2340  Handle the include operation.
2341 ***************************************************************************/
2342
2343 static bool handle_include(struct loadparm_context *lp_ctx, int unused,
2344                            const char *pszParmValue, char **ptr)
2345 {
2346         char *fname = standard_sub_basic(lp_ctx, pszParmValue);
2347
2348         add_to_file_list(lp_ctx, pszParmValue, fname);
2349
2350         lpcfg_string_set(lp_ctx, ptr, fname);
2351
2352         if (file_exist(fname))
2353                 return pm_process(fname, do_section, do_parameter, lp_ctx);
2354
2355         DEBUG(2, ("Can't find include file %s\n", fname));
2356
2357         return false;
2358 }
2359
2360 /***************************************************************************
2361  Handle the interpretation of the copy parameter.
2362 ***************************************************************************/
2363
2364 static bool handle_copy(struct loadparm_context *lp_ctx, int unused,
2365                         const char *pszParmValue, char **ptr)
2366 {
2367         bool bRetval;
2368         struct loadparm_service *serviceTemp;
2369
2370         lpcfg_string_set(lp_ctx, ptr, pszParmValue);
2371
2372         bRetval = false;
2373
2374         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
2375
2376         if ((serviceTemp = getservicebyname(lp_ctx, pszParmValue)) != NULL) {
2377                 if (serviceTemp == lp_ctx->currentService) {
2378                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
2379                 } else {
2380                         copy_service(lp_ctx->currentService,
2381                                      serviceTemp,
2382                                      lp_ctx->currentService->copymap);
2383                         bRetval = true;
2384                 }
2385         } else {
2386                 DEBUG(0, ("Unable to copy service - source not found: %s\n",
2387                           pszParmValue));
2388                 bRetval = false;
2389         }
2390
2391         return bRetval;
2392 }
2393
2394 static bool handle_debuglevel(struct loadparm_context *lp_ctx, int unused,
2395                         const char *pszParmValue, char **ptr)
2396 {
2397
2398         lpcfg_string_set(lp_ctx, ptr, pszParmValue);
2399         if (lp_ctx->global) {
2400                 return debug_parse_levels(pszParmValue);
2401         }
2402         return true;
2403 }
2404
2405 static bool handle_logfile(struct loadparm_context *lp_ctx, int unused,
2406                         const char *pszParmValue, char **ptr)
2407 {
2408         debug_set_logfile(pszParmValue);
2409         if (lp_ctx->global) {
2410                 lpcfg_string_set(lp_ctx, ptr, pszParmValue);
2411         }
2412         return true;
2413 }
2414
2415 /***************************************************************************
2416  Initialise a copymap.
2417 ***************************************************************************/
2418
2419 static void init_copymap(struct loadparm_service *pservice)
2420 {
2421         int i;
2422
2423         TALLOC_FREE(pservice->copymap);
2424
2425         pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
2426         if (!pservice->copymap)
2427                 DEBUG(0,
2428                       ("Couldn't allocate copymap!! (size %d)\n",
2429                        (int)NUMPARAMETERS));
2430         else
2431                 for (i = 0; i < NUMPARAMETERS; i++)
2432                         bitmap_set(pservice->copymap, i);
2433 }
2434
2435 /**
2436  * Process a parametric option
2437  */
2438 static bool lp_do_parameter_parametric(struct loadparm_context *lp_ctx,
2439                                        struct loadparm_service *service,
2440                                        const char *pszParmName,
2441                                        const char *pszParmValue, int flags)
2442 {
2443         struct parmlist_entry *paramo, *data;
2444         char *name;
2445         TALLOC_CTX *mem_ctx;
2446
2447         while (isspace((unsigned char)*pszParmName)) {
2448                 pszParmName++;
2449         }
2450
2451         name = strlower_talloc(lp_ctx, pszParmName);
2452         if (!name) return false;
2453
2454         if (service == NULL) {
2455                 data = lp_ctx->globals->param_opt;
2456                 mem_ctx = lp_ctx->globals;
2457         } else {
2458                 data = service->param_opt;
2459                 mem_ctx = service;
2460         }
2461
2462         /* Traverse destination */
2463         for (paramo=data; paramo; paramo=paramo->next) {
2464                 /* If we already have the option set, override it unless
2465                    it was a command line option and the new one isn't */
2466                 if (strcmp(paramo->key, name) == 0) {
2467                         if ((paramo->priority & FLAG_CMDLINE) &&
2468                             !(flags & FLAG_CMDLINE)) {
2469                                 talloc_free(name);
2470                                 return true;
2471                         }
2472
2473                         talloc_free(paramo->value);
2474                         paramo->value = talloc_strdup(paramo, pszParmValue);
2475                         paramo->priority = flags;
2476                         talloc_free(name);
2477                         return true;
2478                 }
2479         }
2480
2481         paramo = talloc_zero(mem_ctx, struct parmlist_entry);
2482         if (!paramo)
2483                 smb_panic("OOM");
2484         paramo->key = talloc_strdup(paramo, name);
2485         paramo->value = talloc_strdup(paramo, pszParmValue);
2486         paramo->priority = flags;
2487         if (service == NULL) {
2488                 DLIST_ADD(lp_ctx->globals->param_opt, paramo);
2489         } else {
2490                 DLIST_ADD(service->param_opt, paramo);
2491         }
2492
2493         talloc_free(name);
2494
2495         return true;
2496 }
2497
2498 static bool set_variable(TALLOC_CTX *mem_ctx, int parmnum, void *parm_ptr,
2499                          const char *pszParmName, const char *pszParmValue,
2500                          struct loadparm_context *lp_ctx, bool on_globals)
2501 {
2502         int i;
2503         /* if it is a special case then go ahead */
2504         if (parm_table[parmnum].special) {
2505                 bool ret;
2506                 ret = parm_table[parmnum].special(lp_ctx, -1, pszParmValue,
2507                                                   (char **)parm_ptr);
2508                 if (!ret) {
2509                         return false;
2510                 }
2511                 goto mark_non_default;
2512         }
2513
2514         /* now switch on the type of variable it is */
2515         switch (parm_table[parmnum].type)
2516         {
2517                 case P_BOOL: {
2518                         bool b;
2519                         if (!set_boolean(pszParmValue, &b)) {
2520                                 DEBUG(0,("lp_do_parameter(%s): value is not boolean!\n", pszParmValue));
2521                                 return false;
2522                         }
2523                         *(bool *)parm_ptr = b;
2524                         }
2525                         break;
2526
2527                 case P_BOOLREV: {
2528                         bool b;
2529                         if (!set_boolean(pszParmValue, &b)) {
2530                                 DEBUG(0,("lp_do_parameter(%s): value is not boolean!\n", pszParmValue));
2531                                 return false;
2532                         }
2533                         *(bool *)parm_ptr = !b;
2534                         }
2535                         break;
2536
2537                 case P_INTEGER:
2538                         *(int *)parm_ptr = atoi(pszParmValue);
2539                         break;
2540
2541                 case P_CHAR:
2542                         *(char *)parm_ptr = *pszParmValue;
2543                         break;
2544
2545                 case P_OCTAL:
2546                         *(int *)parm_ptr = strtol(pszParmValue, NULL, 8);
2547                         break;
2548
2549                 case P_BYTES:
2550                 {
2551                         uint64_t val;
2552                         if (conv_str_size_error(pszParmValue, &val)) {
2553                                 if (val <= INT_MAX) {
2554                                         *(int *)parm_ptr = (int)val;
2555                                         break;
2556                                 }
2557                         }
2558
2559                         DEBUG(0,("lp_do_parameter(%s): value is not "
2560                             "a valid size specifier!\n", pszParmValue));
2561                         return false;
2562                 }
2563
2564                 case P_CMDLIST:
2565                         *(const char ***)parm_ptr = (const char **)str_list_make(mem_ctx,
2566                                                                   pszParmValue, NULL);
2567                         break;
2568                 case P_LIST:
2569                 {
2570                         char **new_list = str_list_make(mem_ctx,
2571                                                         pszParmValue, NULL);
2572                         for (i=0; new_list[i]; i++) {
2573                                 if (new_list[i][0] == '+' && new_list[i][1] &&
2574                                     (!str_list_check(*(const char ***)parm_ptr,
2575                                                      &new_list[i][1]))) {
2576                                         *(const char ***)parm_ptr = str_list_add(*(const char ***)parm_ptr,
2577                                                                                  &new_list[i][1]);
2578                                 } else if (new_list[i][0] == '-' && new_list[i][1]) {
2579 #if 0 /* This is commented out because we sometimes parse the list
2580        * twice, and so we can't assert on this */
2581                                         if (!str_list_check(*(const char ***)parm_ptr,
2582                                                             &new_list[i][1])) {
2583                                                 DEBUG(0, ("Unsupported value for: %s = %s, %s is not in the original list [%s]\n",
2584                                                           pszParmName, pszParmValue, new_list[i],
2585                                                           str_list_join_shell(mem_ctx, *(const char ***)parm_ptr, ' ')));
2586                                                 return false;
2587
2588                                         }
2589 #endif
2590                                         str_list_remove(*(const char ***)parm_ptr,
2591                                                         &new_list[i][1]);
2592                                 } else {
2593                                         if (i != 0) {
2594                                                 DEBUG(0, ("Unsupported list syntax for: %s = %s\n",
2595                                                           pszParmName, pszParmValue));
2596                                                 return false;
2597                                         }
2598                                         *(const char ***)parm_ptr = (const char **) new_list;
2599                                         break;
2600                                 }
2601                         }
2602                         break;
2603                 }
2604                 case P_STRING:
2605                         lpcfg_string_set(mem_ctx, (char **)parm_ptr, pszParmValue);
2606                         break;
2607
2608                 case P_USTRING:
2609                         lpcfg_string_set_upper(mem_ctx, (char **)parm_ptr, pszParmValue);
2610                         break;
2611
2612                 case P_ENUM:
2613                         for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
2614                                 if (strequal
2615                                     (pszParmValue,
2616                                      parm_table[parmnum].enum_list[i].name)) {
2617                                         *(int *)parm_ptr =
2618                                                 parm_table[parmnum].
2619                                                 enum_list[i].value;
2620                                         break;
2621                                 }
2622                         }
2623                         if (!parm_table[parmnum].enum_list[i].name) {
2624                                 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n", 
2625                                          pszParmValue, pszParmName));
2626                                 return false;
2627                         }
2628                         break;
2629         }
2630
2631 mark_non_default:
2632         if (on_globals && (lp_ctx->flags[parmnum] & FLAG_DEFAULT)) {
2633                 lp_ctx->flags[parmnum] &= ~FLAG_DEFAULT;
2634                 /* we have to also unset FLAG_DEFAULT on aliases */
2635                 for (i=parmnum-1;i>=0 && parm_table[i].offset == parm_table[parmnum].offset;i--) {
2636                         lp_ctx->flags[i] &= ~FLAG_DEFAULT;
2637                 }
2638                 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset;i++) {
2639                         lp_ctx->flags[i] &= ~FLAG_DEFAULT;
2640                 }
2641         }
2642         return true;
2643 }
2644
2645
2646 bool lpcfg_do_global_parameter(struct loadparm_context *lp_ctx,
2647                                const char *pszParmName, const char *pszParmValue)
2648 {
2649         int parmnum = map_parameter(pszParmName);
2650         void *parm_ptr;
2651
2652         if (parmnum < 0) {
2653                 if (strchr(pszParmName, ':')) {
2654                         return lp_do_parameter_parametric(lp_ctx, NULL, pszParmName, pszParmValue, 0);
2655                 }
2656                 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
2657                 return true;
2658         }
2659
2660         /* if the flag has been set on the command line, then don't allow override,
2661            but don't report an error */
2662         if (lp_ctx->flags[parmnum] & FLAG_CMDLINE) {
2663                 return true;
2664         }
2665
2666         parm_ptr = lpcfg_parm_ptr(lp_ctx, NULL, &parm_table[parmnum]);
2667
2668         return set_variable(lp_ctx->globals, parmnum, parm_ptr,
2669                             pszParmName, pszParmValue, lp_ctx, true);
2670 }
2671
2672 bool lpcfg_do_service_parameter(struct loadparm_context *lp_ctx,
2673                                 struct loadparm_service *service,
2674                                 const char *pszParmName, const char *pszParmValue)
2675 {
2676         void *parm_ptr;
2677         int i;
2678         int parmnum = map_parameter(pszParmName);
2679
2680         if (parmnum < 0) {
2681                 if (strchr(pszParmName, ':')) {
2682                         return lp_do_parameter_parametric(lp_ctx, service, pszParmName, pszParmValue, 0);
2683                 }
2684                 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
2685                 return true;
2686         }
2687
2688         /* if the flag has been set on the command line, then don't allow override,
2689            but don't report an error */
2690         if (lp_ctx->flags[parmnum] & FLAG_CMDLINE) {
2691                 return true;
2692         }
2693
2694         if (parm_table[parmnum].p_class == P_GLOBAL) {
2695                 DEBUG(0,
2696                       ("Global parameter %s found in service section!\n",
2697                        pszParmName));
2698                 return true;
2699         }
2700         parm_ptr = ((char *)service) + parm_table[parmnum].offset;
2701
2702         if (!service->copymap)
2703                 init_copymap(service);
2704
2705         /* this handles the aliases - set the copymap for other
2706          * entries with the same data pointer */
2707         for (i = 0; parm_table[i].label; i++)
2708                 if (parm_table[i].offset == parm_table[parmnum].offset &&
2709                     parm_table[i].p_class == parm_table[parmnum].p_class)
2710                         bitmap_clear(service->copymap, i);
2711
2712         return set_variable(service, parmnum, parm_ptr, pszParmName,
2713                             pszParmValue, lp_ctx, false);
2714 }
2715
2716 /**
2717  * Process a parameter.
2718  */
2719
2720 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
2721                          void *userdata)
2722 {
2723         struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata;
2724
2725         if (lp_ctx->bInGlobalSection)
2726                 return lpcfg_do_global_parameter(lp_ctx, pszParmName,
2727                                               pszParmValue);
2728         else
2729                 return lpcfg_do_service_parameter(lp_ctx, lp_ctx->currentService,
2730                                                   pszParmName, pszParmValue);
2731 }
2732
2733 /*
2734   variable argument do parameter
2735 */
2736 bool lpcfg_do_global_parameter_var(struct loadparm_context *lp_ctx, const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4);
2737 bool lpcfg_do_global_parameter_var(struct loadparm_context *lp_ctx,
2738                                 const char *pszParmName, const char *fmt, ...)
2739 {
2740         char *s;
2741         bool ret;
2742         va_list ap;
2743
2744         va_start(ap, fmt);
2745         s = talloc_vasprintf(NULL, fmt, ap);
2746         va_end(ap);
2747         ret = lpcfg_do_global_parameter(lp_ctx, pszParmName, s);
2748         talloc_free(s);
2749         return ret;
2750 }
2751
2752
2753 /*
2754   set a parameter from the commandline - this is called from command line parameter
2755   parsing code. It sets the parameter then marks the parameter as unable to be modified
2756   by smb.conf processing
2757 */
2758 bool lpcfg_set_cmdline(struct loadparm_context *lp_ctx, const char *pszParmName,
2759                        const char *pszParmValue)
2760 {
2761         int parmnum;
2762         int i;
2763
2764         if (lp_ctx->s3_fns) {
2765                 return lp_ctx->s3_fns->set_cmdline(pszParmName, pszParmValue);
2766         }
2767
2768         parmnum = map_parameter(pszParmName);
2769
2770         while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
2771
2772
2773         if (parmnum < 0 && strchr(pszParmName, ':')) {
2774                 /* set a parametric option */
2775                 return lp_do_parameter_parametric(lp_ctx, NULL, pszParmName,
2776                                                   pszParmValue, FLAG_CMDLINE);
2777         }
2778
2779         if (parmnum < 0) {
2780                 DEBUG(0,("Unknown option '%s'\n", pszParmName));
2781                 return false;
2782         }
2783
2784         /* reset the CMDLINE flag in case this has been called before */
2785         lp_ctx->flags[parmnum] &= ~FLAG_CMDLINE;
2786
2787         if (!lpcfg_do_global_parameter(lp_ctx, pszParmName, pszParmValue)) {
2788                 return false;
2789         }
2790
2791         lp_ctx->flags[parmnum] |= FLAG_CMDLINE;
2792
2793         /* we have to also set FLAG_CMDLINE on aliases */
2794         for (i=parmnum-1;i>=0 && parm_table[i].offset == parm_table[parmnum].offset;i--) {
2795                 lp_ctx->flags[i] |= FLAG_CMDLINE;
2796         }
2797         for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset;i++) {
2798                 lp_ctx->flags[i] |= FLAG_CMDLINE;
2799         }
2800
2801         return true;
2802 }
2803
2804 /*
2805   set a option from the commandline in 'a=b' format. Use to support --option
2806 */
2807 bool lpcfg_set_option(struct loadparm_context *lp_ctx, const char *option)
2808 {
2809         char *p, *s;
2810         bool ret;
2811
2812         s = talloc_strdup(NULL, option);
2813         if (!s) {
2814                 return false;
2815         }
2816
2817         p = strchr(s, '=');
2818         if (!p) {
2819                 talloc_free(s);
2820                 return false;
2821         }
2822
2823         *p = 0;
2824
2825         ret = lpcfg_set_cmdline(lp_ctx, s, p+1);
2826         talloc_free(s);
2827         return ret;
2828 }
2829
2830
2831 #define BOOLSTR(b) ((b) ? "Yes" : "No")
2832
2833 /**
2834  * Print a parameter of the specified type.
2835  */
2836
2837 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
2838 {
2839         /* For the seperation of lists values that we print below */
2840         const char *list_sep = ", ";
2841         int i;
2842         switch (p->type)
2843         {
2844                 case P_ENUM:
2845                         for (i = 0; p->enum_list[i].name; i++) {
2846                                 if (*(int *)ptr == p->enum_list[i].value) {
2847                                         fprintf(f, "%s",
2848                                                 p->enum_list[i].name);
2849                                         break;
2850                                 }
2851                         }
2852                         break;
2853
2854                 case P_BOOL:
2855                         fprintf(f, "%s", BOOLSTR(*(bool *)ptr));
2856                         break;
2857
2858                 case P_BOOLREV:
2859                         fprintf(f, "%s", BOOLSTR(!*(bool *)ptr));
2860                         break;
2861
2862                 case P_INTEGER:
2863                 case P_BYTES:
2864                         fprintf(f, "%d", *(int *)ptr);
2865                         break;
2866
2867                 case P_CHAR:
2868                         fprintf(f, "%c", *(char *)ptr);
2869                         break;
2870
2871                 case P_OCTAL: {
2872                         int val = *(int *)ptr; 
2873                         if (val == -1) {
2874                                 fprintf(f, "-1");
2875                         } else {
2876                                 fprintf(f, "0%o", val);
2877                         }
2878                         break;
2879                 }
2880
2881                 case P_CMDLIST:
2882                         list_sep = " ";
2883                         /* fall through */
2884                 case P_LIST:
2885                         if ((char ***)ptr && *(char ***)ptr) {
2886                                 char **list = *(char ***)ptr;
2887                                 for (; *list; list++) {
2888                                         /* surround strings with whitespace in double quotes */
2889                                         if (*(list+1) == NULL) {
2890                                                 /* last item, no extra separator */
2891                                                 list_sep = "";
2892                                         }
2893                                         if ( strchr_m( *list, ' ' ) ) {
2894                                                 fprintf(f, "\"%s\"%s", *list, list_sep);
2895                                         } else {
2896                                                 fprintf(f, "%s%s", *list, list_sep);
2897                                         }
2898                                 }
2899                         }
2900                         break;
2901
2902                 case P_STRING:
2903                 case P_USTRING:
2904                         if (*(char **)ptr) {
2905                                 fprintf(f, "%s", *(char **)ptr);
2906                         }
2907                         break;
2908                 case P_SEP:
2909                         break;
2910         }
2911 }
2912
2913 /**
2914  * Check if two parameters are equal.
2915  */
2916
2917 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
2918 {
2919         switch (type) {
2920                 case P_BOOL:
2921                 case P_BOOLREV:
2922                         return (*((bool *)ptr1) == *((bool *)ptr2));
2923
2924                 case P_INTEGER:
2925                 case P_ENUM:
2926                 case P_OCTAL:
2927                 case P_BYTES:
2928                         return (*((int *)ptr1) == *((int *)ptr2));
2929
2930                 case P_CHAR:
2931                         return (*((char *)ptr1) == *((char *)ptr2));
2932
2933                 case P_LIST:
2934                 case P_CMDLIST:
2935                         return str_list_equal(*(const char ***)ptr1, *(const char ***)ptr2);
2936
2937                 case P_STRING:
2938                 case P_USTRING:
2939                 {
2940                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
2941                         if (p1 && !*p1)
2942                                 p1 = NULL;
2943                         if (p2 && !*p2)
2944                                 p2 = NULL;
2945                         return (p1 == p2 || strequal(p1, p2));
2946                 }
2947                 case P_SEP:
2948                         break;
2949         }
2950         return false;
2951 }
2952
2953 /**
2954  * Process a new section (service).
2955  *
2956  * At this stage all sections are services.
2957  * Later we'll have special sections that permit server parameters to be set.
2958  * Returns True on success, False on failure.
2959  */
2960
2961 static bool do_section(const char *pszSectionName, void *userdata)
2962 {
2963         struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata;
2964         bool bRetval;
2965         bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2966                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2967         bRetval = false;
2968
2969         /* if we've just struck a global section, note the fact. */
2970         lp_ctx->bInGlobalSection = isglobal;
2971
2972         /* check for multiple global sections */
2973         if (lp_ctx->bInGlobalSection) {
2974                 DEBUG(4, ("Processing section \"[%s]\"\n", pszSectionName));
2975                 return true;
2976         }
2977
2978         /* if we have a current service, tidy it up before moving on */
2979         bRetval = true;
2980
2981         if (lp_ctx->currentService != NULL)
2982                 bRetval = lpcfg_service_ok(lp_ctx->currentService);
2983
2984         /* if all is still well, move to the next record in the services array */
2985         if (bRetval) {
2986                 /* We put this here to avoid an odd message order if messages are */
2987                 /* issued by the post-processing of a previous section. */
2988                 DEBUG(4, ("Processing section \"[%s]\"\n", pszSectionName));
2989
2990                 if ((lp_ctx->currentService = lpcfg_add_service(lp_ctx, lp_ctx->sDefault,
2991                                                                    pszSectionName))
2992                     == NULL) {
2993                         DEBUG(0, ("Failed to add a new service\n"));
2994                         return false;
2995                 }
2996         }
2997
2998         return bRetval;
2999 }
3000
3001
3002 /**
3003  * Determine if a particular base parameter is currently set to the default value.
3004  */
3005
3006 static bool is_default(struct loadparm_service *sDefault, int i)
3007 {
3008         void *def_ptr = ((char *)sDefault) + parm_table[i].offset;
3009         if (!defaults_saved)
3010                 return false;
3011         switch (parm_table[i].type) {
3012                 case P_CMDLIST:
3013                 case P_LIST:
3014                         return str_list_equal((const char **)parm_table[i].def.lvalue, 
3015                                               (const char **)def_ptr);
3016                 case P_STRING:
3017                 case P_USTRING:
3018                         return strequal(parm_table[i].def.svalue,
3019                                         *(char **)def_ptr);
3020                 case P_BOOL:
3021                 case P_BOOLREV:
3022                         return parm_table[i].def.bvalue ==
3023                                 *(bool *)def_ptr;
3024                 case P_INTEGER:
3025                 case P_CHAR:
3026                 case P_OCTAL:
3027                 case P_BYTES:
3028                 case P_ENUM:
3029                         return parm_table[i].def.ivalue ==
3030                                 *(int *)def_ptr;
3031         }
3032         return false;
3033 }
3034
3035 /**
3036  *Display the contents of the global structure.
3037  */
3038
3039 static void dump_globals(struct loadparm_context *lp_ctx, FILE *f,
3040                          bool show_defaults)
3041 {
3042         int i;
3043         struct parmlist_entry *data;
3044
3045         fprintf(f, "# Global parameters\n[global]\n");
3046
3047         for (i = 0; parm_table[i].label; i++)
3048                 if (parm_table[i].p_class == P_GLOBAL &&
3049                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
3050                         if (!show_defaults && (lp_ctx->flags[i] & FLAG_DEFAULT))
3051                                 continue;
3052                         fprintf(f, "\t%s = ", parm_table[i].label);
3053                         print_parameter(&parm_table[i], lpcfg_parm_ptr(lp_ctx, NULL, &parm_table[i]), f);
3054                         fprintf(f, "\n");
3055         }
3056         if (lp_ctx->globals->param_opt != NULL) {
3057                 for (data = lp_ctx->globals->param_opt; data;
3058                      data = data->next) {
3059                         if (!show_defaults && (data->priority & FLAG_DEFAULT)) {
3060                                 continue;
3061                         }
3062                         fprintf(f, "\t%s = %s\n", data->key, data->value);
3063                 }
3064         }
3065
3066 }
3067
3068 /**
3069  * Display the contents of a single services record.
3070  */
3071
3072 static void dump_a_service(struct loadparm_service * pService, struct loadparm_service *sDefault, FILE * f,
3073                            unsigned int *flags)
3074 {
3075         int i;
3076         struct parmlist_entry *data;
3077
3078         if (pService != sDefault)
3079                 fprintf(f, "\n[%s]\n", pService->szService);
3080
3081         for (i = 0; parm_table[i].label; i++) {
3082                 if (parm_table[i].p_class == P_LOCAL &&
3083                     (*parm_table[i].label != '-') &&
3084                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset)))
3085                 {
3086                         if (pService == sDefault) {
3087                                 if (flags && (flags[i] & FLAG_DEFAULT)) {
3088                                         continue;
3089                                 }
3090                                 if (defaults_saved) {
3091                                         if (is_default(sDefault, i)) {
3092                                                 continue;
3093                                         }
3094                                 }
3095                         } else {
3096                                 if (equal_parameter(parm_table[i].type,
3097                                                     ((char *)pService) +
3098                                                     parm_table[i].offset,
3099                                                     ((char *)sDefault) +
3100                                                     parm_table[i].offset))
3101                                         continue;
3102                         }
3103
3104                         fprintf(f, "\t%s = ", parm_table[i].label);
3105                         print_parameter(&parm_table[i],
3106                                         ((char *)pService) + parm_table[i].offset, f);
3107                         fprintf(f, "\n");
3108                 }
3109         }
3110         if (pService->param_opt != NULL) {
3111                 for (data = pService->param_opt; data; data = data->next) {
3112                         fprintf(f, "\t%s = %s\n", data->key, data->value);
3113                 }
3114         }
3115 }
3116
3117 bool lpcfg_dump_a_parameter(struct loadparm_context *lp_ctx,
3118                             struct loadparm_service *service,
3119                             const char *parm_name, FILE * f)
3120 {
3121         struct parm_struct *parm;
3122         void *ptr;
3123
3124         parm = lpcfg_parm_struct(lp_ctx, parm_name);
3125         if (!parm) {
3126                 return false;
3127         }
3128
3129         ptr = lpcfg_parm_ptr(lp_ctx, service,parm);
3130
3131         print_parameter(parm, ptr, f);
3132         fprintf(f, "\n");
3133         return true;
3134 }
3135
3136 /**
3137  * Return info about the next parameter in a service.
3138  * snum==-1 gives the globals.
3139  * Return NULL when out of parameters.
3140  */
3141
3142
3143 struct parm_struct *lpcfg_next_parameter(struct loadparm_context *lp_ctx, int snum, int *i,
3144                                          int allparameters)
3145 {
3146         if (snum == -1) {
3147                 /* do the globals */
3148                 for (; parm_table[*i].label; (*i)++) {
3149                         if ((*parm_table[*i].label == '-'))
3150                                 continue;
3151
3152                         if ((*i) > 0
3153                             && (parm_table[*i].offset ==
3154                                 parm_table[(*i) - 1].offset)
3155                             && (parm_table[*i].p_class ==
3156                                 parm_table[(*i) - 1].p_class))
3157                                 continue;
3158
3159                         return &parm_table[(*i)++];
3160                 }
3161         } else {
3162                 struct loadparm_service *pService = lp_ctx->services[snum];
3163
3164                 for (; parm_table[*i].label; (*i)++) {
3165                         if (parm_table[*i].p_class == P_LOCAL &&
3166                             (*parm_table[*i].label != '-') &&
3167                             ((*i) == 0 ||
3168                              (parm_table[*i].offset !=
3169                               parm_table[(*i) - 1].offset)))
3170                         {
3171                                 if (allparameters ||
3172                                     !equal_parameter(parm_table[*i].type,
3173                                                      ((char *)pService) +
3174                                                      parm_table[*i].offset,
3175                                                      ((char *)lp_ctx->sDefault) +
3176                                                      parm_table[*i].offset))
3177                                 {
3178                                         return &parm_table[(*i)++];
3179                                 }
3180                         }
3181                 }
3182         }
3183
3184         return NULL;
3185 }
3186
3187
3188 /**
3189  * Auto-load some home services.
3190  */
3191 static void lpcfg_add_auto_services(struct loadparm_context *lp_ctx,
3192                                     const char *str)
3193 {
3194         return;
3195 }
3196
3197
3198 /**
3199  * Unload unused services.
3200  */
3201
3202 void lpcfg_killunused(struct loadparm_context *lp_ctx,
3203                    struct smbsrv_connection *smb,
3204                    bool (*snumused) (struct smbsrv_connection *, int))
3205 {
3206         int i;
3207         for (i = 0; i < lp_ctx->iNumServices; i++) {
3208                 if (lp_ctx->services[i] == NULL)
3209                         continue;
3210
3211                 if (!snumused || !snumused(smb, i)) {
3212                         talloc_free(lp_ctx->services[i]);
3213                         lp_ctx->services[i] = NULL;
3214                 }
3215         }
3216 }
3217
3218
3219 static int lpcfg_destructor(struct loadparm_context *lp_ctx)
3220 {
3221         struct parmlist_entry *data;
3222
3223         if (lp_ctx->refuse_free) {
3224                 /* someone is trying to free the
3225                    global_loadparm_context.
3226                    We can't allow that. */
3227                 return -1;
3228         }
3229
3230         if (lp_ctx->globals->param_opt != NULL) {
3231                 struct parmlist_entry *next;
3232                 for (data = lp_ctx->globals->param_opt; data; data=next) {
3233                         next = data->next;
3234                         if (data->priority & FLAG_CMDLINE) continue;
3235                         DLIST_REMOVE(lp_ctx->globals->param_opt, data);
3236                         talloc_free(data);
3237                 }
3238         }
3239
3240         return 0;
3241 }
3242
3243 /**
3244  * Initialise the global parameter structure.
3245  *
3246  * Note that most callers should use loadparm_init_global() instead
3247  */
3248 struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
3249 {
3250         int i;
3251         char *myname;
3252         struct loadparm_context *lp_ctx;
3253         struct parmlist_entry *parm;
3254         char *logfile;
3255
3256         lp_ctx = talloc_zero(mem_ctx, struct loadparm_context);
3257         if (lp_ctx == NULL)
3258                 return NULL;
3259
3260         talloc_set_destructor(lp_ctx, lpcfg_destructor);
3261         lp_ctx->bInGlobalSection = true;
3262         lp_ctx->globals = talloc_zero(lp_ctx, struct loadparm_global);
3263         lp_ctx->sDefault&n