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