ba0f738f0e4cf9a0c649baba056e3d53115ef124
[kai/samba.git] / lib / param / loadparm.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Parameter loading functions
4    Copyright (C) Karl Auer 1993-1998
5
6    Largely re-written by Andrew Tridgell, September 1994
7
8    Copyright (C) Simo Sorce 2001
9    Copyright (C) Alexander Bokovoy 2002
10    Copyright (C) Stefan (metze) Metzmacher 2002
11    Copyright (C) Jim McDonough (jmcd@us.ibm.com)  2003.
12    Copyright (C) James Myers 2003 <myersjj@samba.org>
13    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
14
15    This program is free software; you can redistribute it and/or modify
16    it under the terms of the GNU General Public License as published by
17    the Free Software Foundation; either version 3 of the License, or
18    (at your option) any later version.
19
20    This program is distributed in the hope that it will be useful,
21    but WITHOUT ANY WARRANTY; without even the implied warranty of
22    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23    GNU General Public License for more details.
24
25    You should have received a copy of the GNU General Public License
26    along with this program.  If not, see <http://www.gnu.org/licenses/>.
27 */
28
29 /*
30  *  Load parameters.
31  *
32  *  This module provides suitable callback functions for the params
33  *  module. It builds the internal table of service details which is
34  *  then used by the rest of the server.
35  *
36  * To add a parameter:
37  *
38  * 1) add it to the global or service structure definition
39  * 2) add it to the parm_table
40  * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
41  * 4) If it's a global then initialise it in init_globals. If a local
42  *    (ie. service) parameter then initialise it in the sDefault structure
43  *
44  *
45  * Notes:
46  *   The configuration file is processed sequentially for speed. It is NOT
47  *   accessed randomly as happens in 'real' Windows. For this reason, there
48  *   is a fair bit of sequence-dependent code here - ie., code which assumes
49  *   that certain things happen before others. In particular, the code which
50  *   happens at the boundary between sections is delicately poised, so be
51  *   careful!
52  *
53  */
54
55 #include "includes.h"
56 #include "version.h"
57 #include "dynconfig/dynconfig.h"
58 #include "system/time.h"
59 #include "system/locale.h"
60 #include "system/network.h" /* needed for TCP_NODELAY */
61 #include "../lib/util/dlinklist.h"
62 #include "lib/param/param.h"
63 #include "lib/param/loadparm.h"
64 #include "auth/gensec/gensec.h"
65 #include "s3_param.h"
66 #include "lib/util/bitmap.h"
67 #include "libcli/smb/smb_constants.h"
68 #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(bind_interfaces_only, bBindInterfacesOnly)
1535 FN_GLOBAL_BOOL(client_lanman_auth, bClientLanManAuth)
1536 FN_GLOBAL_BOOL(client_ntlmv2_auth, bClientNTLMv2Auth)
1537 FN_GLOBAL_BOOL(client_plaintext_auth, bClientPlaintextAuth)
1538 FN_GLOBAL_BOOL(client_use_spnego_principal, client_use_spnego_principal)
1539 FN_GLOBAL_BOOL(disable_netbios, bDisableNetbios)
1540 FN_GLOBAL_BOOL(dns_recursive_queries, dns_recursive_queries)
1541 FN_GLOBAL_BOOL(encrypted_passwords, bEncryptPasswords)
1542 FN_GLOBAL_BOOL(host_msdfs, bHostMSDfs)
1543 FN_GLOBAL_BOOL(idmap_trusted_only, bIdmapTrustedOnly)
1544 FN_GLOBAL_BOOL(lanman_auth, bLanmanAuth)
1545 FN_GLOBAL_BOOL(large_readwrite, bLargeReadwrite)
1546 FN_GLOBAL_BOOL(local_master, bLocalMaster)
1547 FN_GLOBAL_BOOL(ntlm_auth, bNTLMAuth)
1548 FN_GLOBAL_BOOL(nt_status_support, bNTStatusSupport)
1549 FN_GLOBAL_BOOL(null_passwords, bNullPasswords)
1550 FN_GLOBAL_BOOL(obey_pam_restrictions, bObeyPamRestrictions)
1551 FN_GLOBAL_BOOL(paranoid_server_security, paranoid_server_security)
1552 FN_GLOBAL_BOOL(readraw, bReadRaw)
1553 FN_GLOBAL_BOOL(rpc_big_endian, bRpcBigEndian)
1554 FN_GLOBAL_BOOL(time_server, bTimeServer)
1555 FN_GLOBAL_BOOL(tls_enabled, tls_enabled)
1556 FN_GLOBAL_BOOL(unicode, bUnicode)
1557 FN_GLOBAL_BOOL(unix_extensions, bUnixExtensions)
1558 FN_GLOBAL_BOOL(use_mmap, bUseMmap)
1559 FN_GLOBAL_BOOL(use_spnego, bUseSpnego)
1560 FN_GLOBAL_BOOL(we_are_a_wins_server, bWINSsupport)
1561 FN_GLOBAL_BOOL(winbind_sealed_pipes, bWinbindSealedPipes)
1562 FN_GLOBAL_BOOL(wins_dns_proxy, bWINSdnsProxy)
1563 FN_GLOBAL_BOOL(writeraw, bWriteRaw)
1564 FN_GLOBAL_CONST_STRING(dns_forwarder, dns_forwarder)
1565 FN_GLOBAL_CONST_STRING(ntp_signd_socket_directory, szNTPSignDSocketDirectory)
1566 FN_GLOBAL_CONST_STRING(passwordserver, szPasswordServer)
1567 FN_GLOBAL_CONST_STRING(template_homedir, szTemplateHomedir)
1568 FN_GLOBAL_CONST_STRING(template_shell, szTemplateShell)
1569 FN_GLOBAL_CONST_STRING(winbindd_privileged_socket_directory, szWinbinddPrivilegedSocketDirectory)
1570 FN_GLOBAL_CONST_STRING(winbindd_socket_directory, szWinbinddSocketDirectory)
1571 FN_GLOBAL_CONST_STRING(winbind_separator, szWinbindSeparator)
1572 FN_GLOBAL_INTEGER(allow_dns_updates, allow_dns_updates)
1573 FN_GLOBAL_INTEGER(cldap_port, cldap_port)
1574 FN_GLOBAL_INTEGER(client_signing, client_signing)
1575 FN_GLOBAL_INTEGER(cli_maxprotocol, cli_maxprotocol)
1576 FN_GLOBAL_INTEGER(cli_minprotocol, cli_minprotocol)
1577 FN_GLOBAL_INTEGER(dgram_port, dgram_port)
1578 FN_GLOBAL_INTEGER(kpasswd_port, kpasswd_port)
1579 FN_GLOBAL_INTEGER(krb5_port, krb5_port)
1580 FN_GLOBAL_INTEGER(maxmux, max_mux)
1581 FN_GLOBAL_INTEGER(max_wins_ttl, max_wins_ttl)
1582 FN_GLOBAL_INTEGER(max_xmit, max_xmit)
1583 FN_GLOBAL_INTEGER(min_wins_ttl, min_wins_ttl)
1584 FN_GLOBAL_INTEGER(nbt_port, nbt_port)
1585 FN_GLOBAL_INTEGER(passwordlevel, pwordlevel)
1586 FN_GLOBAL_INTEGER(server_signing, server_signing)
1587 FN_GLOBAL_INTEGER(srv_maxprotocol, srv_maxprotocol)
1588 FN_GLOBAL_INTEGER(srv_minprotocol, srv_minprotocol)
1589 FN_GLOBAL_INTEGER(web_port, web_port)
1590 FN_GLOBAL_LIST(dcerpc_endpoint_servers, dcerpc_ep_servers)
1591 FN_GLOBAL_LIST(dns_update_command, szDNSUpdateCommand)
1592 FN_GLOBAL_LIST(interfaces, szInterfaces)
1593 FN_GLOBAL_LIST(name_resolve_order, szNameResolveOrder)
1594 FN_GLOBAL_LIST(netbios_aliases, szNetbiosAliases)
1595 FN_GLOBAL_LIST(nsupdate_command, szNSUpdateCommand)
1596 FN_GLOBAL_LIST(rndc_command, szRNDCCommand)
1597 FN_GLOBAL_LIST(samba_kcc_command, szSambaKCCCommand)
1598 FN_GLOBAL_LIST(server_services, server_services)
1599 FN_GLOBAL_LIST(smb_ports, smb_ports)
1600 FN_GLOBAL_LIST(spn_update_command, szSPNUpdateCommand)
1601 FN_GLOBAL_LIST(wins_server_list, szWINSservers)
1602 FN_GLOBAL_STRING(auto_services, szAutoServices)
1603 FN_GLOBAL_STRING(cachedir, szCacheDir)
1604 FN_GLOBAL_STRING(dnsdomain, szRealm_lower)
1605 FN_GLOBAL_STRING(dos_charset, dos_charset)
1606 FN_GLOBAL_STRING(lockdir, szLockDir)
1607 FN_GLOBAL_STRING(logfile, logfile)
1608 FN_GLOBAL_STRING(ncalrpc_dir, ncalrpc_dir)
1609 FN_GLOBAL_STRING(netbios_name, szNetbiosName)
1610 FN_GLOBAL_STRING(netbios_scope, szNetbiosScope)
1611 FN_GLOBAL_STRING(ntptr_providor, ntptr_providor)
1612 FN_GLOBAL_STRING(passdb_backend, passdb_backend)
1613 FN_GLOBAL_STRING(passwd_chat, szPasswdChat)
1614 FN_GLOBAL_STRING(piddir, szPidDir)
1615 FN_GLOBAL_STRING(private_dir, szPrivateDir)
1616 FN_GLOBAL_STRING(realm, szRealm_upper)
1617 FN_GLOBAL_STRING(serverstring, szServerString)
1618 FN_GLOBAL_STRING(share_backend, szShareBackend)
1619 FN_GLOBAL_STRING(socket_address, szSocketAddress)
1620 FN_GLOBAL_STRING(socket_options, socket_options)
1621 FN_GLOBAL_STRING(statedir, szStateDir)
1622 FN_GLOBAL_STRING(unix_charset, unix_charset)
1623 FN_GLOBAL_STRING(wins_hook, szWINSHook)
1624 FN_GLOBAL_STRING(workgroup, szWorkgroup)
1625
1626 /* local prototypes */
1627 static int map_parameter(const char *pszParmName);
1628 static struct loadparm_service *getservicebyname(struct loadparm_context *lp_ctx,
1629                                         const char *pszServiceName);
1630 static void copy_service(struct loadparm_service *pserviceDest,
1631                          struct loadparm_service *pserviceSource,
1632                          struct bitmap *pcopymapDest);
1633 static bool lpcfg_service_ok(struct loadparm_service *service);
1634 static bool do_section(const char *pszSectionName, void *);
1635 static void init_copymap(struct loadparm_service *pservice);
1636
1637 /* This is a helper function for parametrical options support. */
1638 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
1639 /* Actual parametrical functions are quite simple */
1640 const char *lpcfg_get_parametric(struct loadparm_context *lp_ctx,
1641                               struct loadparm_service *service,
1642                               const char *type, const char *option)
1643 {
1644         char *vfskey_tmp = NULL;
1645         char *vfskey = NULL;
1646         struct parmlist_entry *data;
1647
1648         if (lp_ctx == NULL)
1649                 return NULL;
1650
1651         if (lp_ctx->s3_fns) {
1652                 return lp_ctx->s3_fns->get_parametric(service, type, option);
1653         }
1654
1655         data = (service == NULL ? lp_ctx->globals->param_opt : service->param_opt);
1656
1657         vfskey_tmp = talloc_asprintf(NULL, "%s:%s", type, option);
1658         if (vfskey_tmp == NULL) return NULL;
1659         vfskey = strlower_talloc(NULL, vfskey_tmp);
1660         talloc_free(vfskey_tmp);
1661
1662         while (data) {
1663                 if (strcmp(data->key, vfskey) == 0) {
1664                         talloc_free(vfskey);
1665                         return data->value;
1666                 }
1667                 data = data->next;
1668         }
1669
1670         if (service != NULL) {
1671                 /* Try to fetch the same option but from globals */
1672                 /* but only if we are not already working with globals */
1673                 for (data = lp_ctx->globals->param_opt; data;
1674                      data = data->next) {
1675                         if (strcmp(data->key, vfskey) == 0) {
1676                                 talloc_free(vfskey);
1677                                 return data->value;
1678                         }
1679                 }
1680         }
1681
1682         talloc_free(vfskey);
1683
1684         return NULL;
1685 }
1686
1687
1688 /**
1689  * convenience routine to return int parameters.
1690  */
1691 static int lp_int(const char *s)
1692 {
1693
1694         if (!s) {
1695                 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
1696                 return -1;
1697         }
1698
1699         return strtol(s, NULL, 0);
1700 }
1701
1702 /**
1703  * convenience routine to return unsigned long parameters.
1704  */
1705 static unsigned long lp_ulong(const char *s)
1706 {
1707
1708         if (!s) {
1709                 DEBUG(0,("lp_ulong(%s): is called with NULL!\n",s));
1710                 return -1;
1711         }
1712
1713         return strtoul(s, NULL, 0);
1714 }
1715
1716 /**
1717  * convenience routine to return unsigned long parameters.
1718  */
1719 static long lp_long(const char *s)
1720 {
1721
1722         if (!s) {
1723                 DEBUG(0,("lp_long(%s): is called with NULL!\n",s));
1724                 return -1;
1725         }
1726
1727         return strtol(s, NULL, 0);
1728 }
1729
1730 /**
1731  * convenience routine to return unsigned long parameters.
1732  */
1733 static double lp_double(const char *s)
1734 {
1735
1736         if (!s) {
1737                 DEBUG(0,("lp_double(%s): is called with NULL!\n",s));
1738                 return -1;
1739         }
1740
1741         return strtod(s, NULL);
1742 }
1743
1744 /**
1745  * convenience routine to return boolean parameters.
1746  */
1747 static bool lp_bool(const char *s)
1748 {
1749         bool ret = false;
1750
1751         if (!s) {
1752                 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
1753                 return false;
1754         }
1755
1756         if (!set_boolean(s, &ret)) {
1757                 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1758                 return false;
1759         }
1760
1761         return ret;
1762 }
1763
1764
1765 /**
1766  * Return parametric option from a given service. Type is a part of option before ':'
1767  * Parametric option has following syntax: 'Type: option = value'
1768  * Returned value is allocated in 'lp_talloc' context
1769  */
1770
1771 const char *lpcfg_parm_string(struct loadparm_context *lp_ctx,
1772                               struct loadparm_service *service, const char *type,
1773                               const char *option)
1774 {
1775         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
1776
1777         if (value)
1778                 return lp_string(value);
1779
1780         return NULL;
1781 }
1782
1783 /**
1784  * Return parametric option from a given service. Type is a part of option before ':'
1785  * Parametric option has following syntax: 'Type: option = value'
1786  * Returned value is allocated in 'lp_talloc' context
1787  */
1788
1789 const char **lpcfg_parm_string_list(TALLOC_CTX *mem_ctx,
1790                                     struct loadparm_context *lp_ctx,
1791                                     struct loadparm_service *service,
1792                                     const char *type,
1793                                     const char *option, const char *separator)
1794 {
1795         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
1796
1797         if (value != NULL)
1798                 return (const char **)str_list_make(mem_ctx, value, separator);
1799
1800         return NULL;
1801 }
1802
1803 /**
1804  * Return parametric option from a given service. Type is a part of option before ':'
1805  * Parametric option has following syntax: 'Type: option = value'
1806  */
1807
1808 int lpcfg_parm_int(struct loadparm_context *lp_ctx,
1809                    struct loadparm_service *service, const char *type,
1810                    const char *option, int default_v)
1811 {
1812         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
1813
1814         if (value)
1815                 return lp_int(value);
1816
1817         return default_v;
1818 }
1819
1820 /**
1821  * Return parametric option from a given service. Type is a part of
1822  * option before ':'.
1823  * Parametric option has following syntax: 'Type: option = value'.
1824  */
1825
1826 int lpcfg_parm_bytes(struct loadparm_context *lp_ctx,
1827                   struct loadparm_service *service, const char *type,
1828                   const char *option, int default_v)
1829 {
1830         uint64_t bval;
1831
1832         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
1833
1834         if (value && conv_str_size_error(value, &bval)) {
1835                 if (bval <= INT_MAX) {
1836                         return (int)bval;
1837                 }
1838         }
1839
1840         return default_v;
1841 }
1842
1843 /**
1844  * Return parametric option from a given service.
1845  * Type is a part of option before ':'
1846  * Parametric option has following syntax: 'Type: option = value'
1847  */
1848 unsigned long lpcfg_parm_ulong(struct loadparm_context *lp_ctx,
1849                             struct loadparm_service *service, const char *type,
1850                             const char *option, unsigned long default_v)
1851 {
1852         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
1853
1854         if (value)
1855                 return lp_ulong(value);
1856
1857         return default_v;
1858 }
1859
1860 long lpcfg_parm_long(struct loadparm_context *lp_ctx,
1861                      struct loadparm_service *service, const char *type,
1862                      const char *option, long default_v)
1863 {
1864         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
1865
1866         if (value)
1867                 return lp_long(value);
1868
1869         return default_v;
1870 }
1871
1872 double lpcfg_parm_double(struct loadparm_context *lp_ctx,
1873                       struct loadparm_service *service, const char *type,
1874                       const char *option, double default_v)
1875 {
1876         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
1877
1878         if (value != NULL)
1879                 return lp_double(value);
1880
1881         return default_v;
1882 }
1883
1884 /**
1885  * Return parametric option from a given service. Type is a part of option before ':'
1886  * Parametric option has following syntax: 'Type: option = value'
1887  */
1888
1889 bool lpcfg_parm_bool(struct loadparm_context *lp_ctx,
1890                      struct loadparm_service *service, const char *type,
1891                      const char *option, bool default_v)
1892 {
1893         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
1894
1895         if (value != NULL)
1896                 return lp_bool(value);
1897
1898         return default_v;
1899 }
1900
1901
1902 /**
1903  * Initialise a service to the defaults.
1904  */
1905
1906 static struct loadparm_service *init_service(TALLOC_CTX *mem_ctx, struct loadparm_service *sDefault)
1907 {
1908         struct loadparm_service *pservice =
1909                 talloc_zero(mem_ctx, struct loadparm_service);
1910         copy_service(pservice, sDefault, NULL);
1911         return pservice;
1912 }
1913
1914 /**
1915  * Set a string value, deallocating any existing space, and allocing the space
1916  * for the string
1917  */
1918 static bool lpcfg_string_set(TALLOC_CTX *mem_ctx, char **dest, const char *src)
1919 {
1920         talloc_free(*dest);
1921
1922         if (src == NULL)
1923                 src = "";
1924
1925         *dest = talloc_strdup(mem_ctx, src);
1926         if ((*dest) == NULL) {
1927                 DEBUG(0,("Out of memory in string_set\n"));
1928                 return false;
1929         }
1930
1931         return true;
1932 }
1933
1934 /**
1935  * Set a string value, deallocating any existing space, and allocing the space
1936  * for the string
1937  */
1938 static bool lpcfg_string_set_upper(TALLOC_CTX *mem_ctx, char **dest, const char *src)
1939 {
1940         talloc_free(*dest);
1941
1942         if (src == NULL)
1943                 src = "";
1944
1945         *dest = strupper_talloc(mem_ctx, src);
1946         if ((*dest) == NULL) {
1947                 DEBUG(0,("Out of memory in string_set_upper\n"));
1948                 return false;
1949         }
1950
1951         return true;
1952 }
1953
1954
1955
1956 /**
1957  * Add a new service to the services array initialising it with the given
1958  * service.
1959  */
1960
1961 struct loadparm_service *lpcfg_add_service(struct loadparm_context *lp_ctx,
1962                                            const struct loadparm_service *pservice,
1963                                            const char *name)
1964 {
1965         int i;
1966         struct loadparm_service tservice;
1967         int num_to_alloc = lp_ctx->iNumServices + 1;
1968         struct parmlist_entry *data, *pdata;
1969
1970         if (pservice == NULL) {
1971                 pservice = lp_ctx->sDefault;
1972         }
1973
1974         tservice = *pservice;
1975
1976         /* it might already exist */
1977         if (name) {
1978                 struct loadparm_service *service = getservicebyname(lp_ctx,
1979                                                                     name);
1980                 if (service != NULL) {
1981                         /* Clean all parametric options for service */
1982                         /* They will be added during parsing again */
1983                         data = service->param_opt;
1984                         while (data) {
1985                                 pdata = data->next;
1986                                 talloc_free(data);
1987                                 data = pdata;
1988                         }
1989                         service->param_opt = NULL;
1990                         return service;
1991                 }
1992         }
1993
1994         /* find an invalid one */
1995         for (i = 0; i < lp_ctx->iNumServices; i++)
1996                 if (lp_ctx->services[i] == NULL)
1997                         break;
1998
1999         /* if not, then create one */
2000         if (i == lp_ctx->iNumServices) {
2001                 struct loadparm_service **tsp;
2002
2003                 tsp = talloc_realloc(lp_ctx, lp_ctx->services, struct loadparm_service *, num_to_alloc);
2004
2005                 if (!tsp) {
2006                         DEBUG(0,("lpcfg_add_service: failed to enlarge services!\n"));
2007                         return NULL;
2008                 } else {
2009                         lp_ctx->services = tsp;
2010                         lp_ctx->services[lp_ctx->iNumServices] = NULL;
2011                 }
2012
2013                 lp_ctx->iNumServices++;
2014         }
2015
2016         lp_ctx->services[i] = init_service(lp_ctx->services, lp_ctx->sDefault);
2017         if (lp_ctx->services[i] == NULL) {
2018                 DEBUG(0,("lpcfg_add_service: out of memory!\n"));
2019                 return NULL;
2020         }
2021         copy_service(lp_ctx->services[i], &tservice, NULL);
2022         if (name != NULL)
2023                 lpcfg_string_set(lp_ctx->services[i], &lp_ctx->services[i]->szService, name);
2024         return lp_ctx->services[i];
2025 }
2026
2027 /**
2028  * Add a new home service, with the specified home directory, defaults coming
2029  * from service ifrom.
2030  */
2031
2032 bool lpcfg_add_home(struct loadparm_context *lp_ctx,
2033                  const char *pszHomename,
2034                  struct loadparm_service *default_service,
2035                  const char *user, const char *pszHomedir)
2036 {
2037         struct loadparm_service *service;
2038
2039         service = lpcfg_add_service(lp_ctx, default_service, pszHomename);
2040
2041         if (service == NULL)
2042                 return false;
2043
2044         if (!(*(default_service->szPath))
2045             || strequal(default_service->szPath, lp_ctx->sDefault->szPath)) {
2046                 service->szPath = talloc_strdup(service, pszHomedir);
2047         } else {
2048                 service->szPath = string_sub_talloc(service, lpcfg_pathname(default_service, lp_ctx->sDefault), "%H", pszHomedir);
2049         }
2050
2051         if (!(*(service->comment))) {
2052                 service->comment = talloc_asprintf(service, "Home directory of %s", user);
2053         }
2054         service->bAvailable = default_service->bAvailable;
2055         service->bBrowseable = default_service->bBrowseable;
2056
2057         DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n",
2058                   pszHomename, user, service->szPath));
2059
2060         return true;
2061 }
2062
2063 /**
2064  * Add a new printer service, with defaults coming from service iFrom.
2065  */
2066
2067 bool lpcfg_add_printer(struct loadparm_context *lp_ctx,
2068                        const char *pszPrintername,
2069                        struct loadparm_service *default_service)
2070 {
2071         const char *comment = "From Printcap";
2072         struct loadparm_service *service;
2073         service = lpcfg_add_service(lp_ctx, default_service, pszPrintername);
2074
2075         if (service == NULL)
2076                 return false;
2077
2078         /* note that we do NOT default the availability flag to True - */
2079         /* we take it from the default service passed. This allows all */
2080         /* dynamic printers to be disabled by disabling the [printers] */
2081         /* entry (if/when the 'available' keyword is implemented!).    */
2082
2083         /* the printer name is set to the service name. */
2084         lpcfg_string_set(service, &service->szPrintername, pszPrintername);
2085         lpcfg_string_set(service, &service->comment, comment);
2086         service->bBrowseable = default_service->bBrowseable;
2087         /* Printers cannot be read_only. */
2088         service->bRead_only = false;
2089         /* Printer services must be printable. */
2090         service->bPrint_ok = true;
2091
2092         DEBUG(3, ("adding printer service %s\n", pszPrintername));
2093
2094         return true;
2095 }
2096
2097 /**
2098  * Map a parameter's string representation to something we can use.
2099  * Returns False if the parameter string is not recognised, else TRUE.
2100  */
2101
2102 static int map_parameter(const char *pszParmName)
2103 {
2104         int iIndex;
2105
2106         if (*pszParmName == '-')
2107                 return -1;
2108
2109         for (iIndex = 0; parm_table[iIndex].label; iIndex++)
2110                 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
2111                         return iIndex;
2112
2113         /* Warn only if it isn't parametric option */
2114         if (strchr(pszParmName, ':') == NULL)
2115                 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
2116         /* We do return 'fail' for parametric options as well because they are
2117            stored in different storage
2118          */
2119         return -1;
2120 }
2121
2122
2123 /**
2124   return the parameter structure for a parameter
2125 */
2126 struct parm_struct *lpcfg_parm_struct(struct loadparm_context *lp_ctx, const char *name)
2127 {
2128         int parmnum;
2129
2130         if (lp_ctx->s3_fns) {
2131                 return lp_ctx->s3_fns->get_parm_struct(name);
2132         }
2133
2134         parmnum = map_parameter(name);
2135         if (parmnum == -1) return NULL;
2136         return &parm_table[parmnum];
2137 }
2138
2139 /**
2140   return the parameter pointer for a parameter
2141 */
2142 void *lpcfg_parm_ptr(struct loadparm_context *lp_ctx,
2143                   struct loadparm_service *service, struct parm_struct *parm)
2144 {
2145         if (lp_ctx->s3_fns) {
2146                 return lp_ctx->s3_fns->get_parm_ptr(service, parm);
2147         }
2148
2149         if (service == NULL) {
2150                 if (parm->p_class == P_LOCAL)
2151                         return ((char *)lp_ctx->sDefault)+parm->offset;
2152                 else if (parm->p_class == P_GLOBAL)
2153                         return ((char *)lp_ctx->globals)+parm->offset;
2154                 else return NULL;
2155         } else {
2156                 return ((char *)service) + parm->offset;
2157         }
2158 }
2159
2160 /**
2161   return the parameter pointer for a parameter
2162 */
2163 bool lpcfg_parm_is_cmdline(struct loadparm_context *lp_ctx, const char *name)
2164 {
2165         int parmnum;
2166
2167         if (lp_ctx->s3_fns) {
2168                 struct parm_struct *parm = lp_ctx->s3_fns->get_parm_struct(name);
2169                 if (parm) {
2170                         return parm->flags & FLAG_CMDLINE;
2171                 }
2172                 return false;
2173         }
2174
2175         parmnum = map_parameter(name);
2176         if (parmnum == -1) return false;
2177
2178         return lp_ctx->flags[parmnum] & FLAG_CMDLINE;
2179 }
2180
2181 /**
2182  * Find a service by name. Otherwise works like get_service.
2183  */
2184
2185 static struct loadparm_service *getservicebyname(struct loadparm_context *lp_ctx,
2186                                         const char *pszServiceName)
2187 {
2188         int iService;
2189
2190         if (lp_ctx->s3_fns) {
2191                 return lp_ctx->s3_fns->get_service(pszServiceName);
2192         }
2193
2194         for (iService = lp_ctx->iNumServices - 1; iService >= 0; iService--)
2195                 if (lp_ctx->services[iService] != NULL &&
2196                     strwicmp(lp_ctx->services[iService]->szService, pszServiceName) == 0) {
2197                         return lp_ctx->services[iService];
2198                 }
2199
2200         return NULL;
2201 }
2202
2203 /**
2204  * Copy a service structure to another.
2205  * If pcopymapDest is NULL then copy all fields
2206  */
2207
2208 static void copy_service(struct loadparm_service *pserviceDest,
2209                          struct loadparm_service *pserviceSource,
2210                          struct bitmap *pcopymapDest)
2211 {
2212         int i;
2213         bool bcopyall = (pcopymapDest == NULL);
2214         struct parmlist_entry *data, *pdata, *paramo;
2215         bool not_added;
2216
2217         for (i = 0; parm_table[i].label; i++)
2218                 if (parm_table[i].p_class == P_LOCAL &&
2219                     (bcopyall || bitmap_query(pcopymapDest, i))) {
2220                         void *src_ptr =
2221                                 ((char *)pserviceSource) + parm_table[i].offset;
2222                         void *dest_ptr =
2223                                 ((char *)pserviceDest) + parm_table[i].offset;
2224
2225                         switch (parm_table[i].type) {
2226                                 case P_BOOL:
2227                                         *(bool *)dest_ptr = *(bool *)src_ptr;
2228                                         break;
2229
2230                                 case P_INTEGER:
2231                                 case P_BYTES:
2232                                 case P_OCTAL:
2233                                 case P_ENUM:
2234                                         *(int *)dest_ptr = *(int *)src_ptr;
2235                                         break;
2236
2237                                 case P_STRING:
2238                                         lpcfg_string_set(pserviceDest,
2239                                                    (char **)dest_ptr,
2240                                                    *(char **)src_ptr);
2241                                         break;
2242
2243                                 case P_USTRING:
2244                                         lpcfg_string_set_upper(pserviceDest,
2245                                                          (char **)dest_ptr,
2246                                                          *(char **)src_ptr);
2247                                         break;
2248                                 case P_LIST:
2249                                         *(const char ***)dest_ptr = (const char **)str_list_copy(pserviceDest, 
2250                                                                                   *(const char ***)src_ptr);
2251                                         break;
2252                                 default:
2253                                         break;
2254                         }
2255                 }
2256
2257         if (bcopyall) {
2258                 init_copymap(pserviceDest);
2259                 if (pserviceSource->copymap)
2260                         bitmap_copy(pserviceDest->copymap,
2261                                     pserviceSource->copymap);
2262         }
2263
2264         data = pserviceSource->param_opt;
2265         while (data) {
2266                 not_added = true;
2267                 pdata = pserviceDest->param_opt;
2268                 /* Traverse destination */
2269                 while (pdata) {
2270                         /* If we already have same option, override it */
2271                         if (strcmp(pdata->key, data->key) == 0) {
2272                                 talloc_free(pdata->value);
2273                                 pdata->value = talloc_strdup(pdata,
2274                                                              data->value);
2275                                 not_added = false;
2276                                 break;
2277                         }
2278                         pdata = pdata->next;
2279                 }
2280                 if (not_added) {
2281                         paramo = talloc_zero(pserviceDest, struct parmlist_entry);
2282                         if (paramo == NULL)
2283                                 smb_panic("OOM");
2284                         paramo->key = talloc_strdup(paramo, data->key);
2285                         paramo->value = talloc_strdup(paramo, data->value);
2286                         DLIST_ADD(pserviceDest->param_opt, paramo);
2287                 }
2288                 data = data->next;
2289         }
2290 }
2291
2292 /**
2293  * Check a service for consistency. Return False if the service is in any way
2294  * incomplete or faulty, else True.
2295  */
2296 static bool lpcfg_service_ok(struct loadparm_service *service)
2297 {
2298         bool bRetval;
2299
2300         bRetval = true;
2301         if (service->szService[0] == '\0') {
2302                 DEBUG(0, ("The following message indicates an internal error:\n"));
2303                 DEBUG(0, ("No service name in service entry.\n"));
2304                 bRetval = false;
2305         }
2306
2307         /* The [printers] entry MUST be printable. I'm all for flexibility, but */
2308         /* I can't see why you'd want a non-printable printer service...        */
2309         if (strwicmp(service->szService, PRINTERS_NAME) == 0) {
2310                 if (!service->bPrint_ok) {
2311                         DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
2312                                service->szService));
2313                         service->bPrint_ok = true;
2314                 }
2315                 /* [printers] service must also be non-browsable. */
2316                 if (service->bBrowseable)
2317                         service->bBrowseable = false;
2318         }
2319
2320         /* If a service is flagged unavailable, log the fact at level 0. */
2321         if (!service->bAvailable)
2322                 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
2323                           service->szService));
2324
2325         return bRetval;
2326 }
2327
2328
2329 /*******************************************************************
2330  Keep a linked list of all config files so we know when one has changed
2331  it's date and needs to be reloaded.
2332 ********************************************************************/
2333
2334 static void add_to_file_list(struct loadparm_context *lp_ctx,
2335                              const char *fname, const char *subfname)
2336 {
2337         struct file_lists *f = lp_ctx->file_lists;
2338
2339         while (f) {
2340                 if (f->name && !strcmp(f->name, fname))
2341                         break;
2342                 f = f->next;
2343         }
2344
2345         if (!f) {
2346                 f = talloc(lp_ctx, struct file_lists);
2347                 if (!f)
2348                         return;
2349                 f->next = lp_ctx->file_lists;
2350                 f->name = talloc_strdup(f, fname);
2351                 if (!f->name) {
2352                         talloc_free(f);
2353                         return;
2354                 }
2355                 f->subfname = talloc_strdup(f, subfname);
2356                 if (!f->subfname) {
2357                         talloc_free(f);
2358                         return;
2359                 }
2360                 lp_ctx->file_lists = f;
2361                 f->modtime = file_modtime(subfname);
2362         } else {
2363                 time_t t = file_modtime(subfname);
2364                 if (t)
2365                         f->modtime = t;
2366         }
2367 }
2368
2369 /*******************************************************************
2370  Check if a config file has changed date.
2371 ********************************************************************/
2372 bool lpcfg_file_list_changed(struct loadparm_context *lp_ctx)
2373 {
2374         struct file_lists *f;
2375         DEBUG(6, ("lp_file_list_changed()\n"));
2376
2377         for (f = lp_ctx->file_lists; f != NULL; f = f->next) {
2378                 char *n2;
2379                 time_t mod_time;
2380
2381                 n2 = standard_sub_basic(lp_ctx, f->name);
2382
2383                 DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
2384                              f->name, n2, ctime(&f->modtime)));
2385
2386                 mod_time = file_modtime(n2);
2387
2388                 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
2389                         DEBUGADD(6, ("file %s modified: %s\n", n2,
2390                                   ctime(&mod_time)));
2391                         f->modtime = mod_time;
2392                         talloc_free(f->subfname);
2393                         f->subfname = talloc_strdup(f, n2);
2394                         return true;
2395                 }
2396         }
2397         return false;
2398 }
2399
2400 /***************************************************************************
2401  Handle the "realm" parameter
2402 ***************************************************************************/
2403
2404 static bool handle_realm(struct loadparm_context *lp_ctx, int unused,
2405                          const char *pszParmValue, char **ptr)
2406 {
2407         lpcfg_string_set(lp_ctx, ptr, pszParmValue);
2408
2409         talloc_free(lp_ctx->globals->szRealm_upper);
2410         talloc_free(lp_ctx->globals->szRealm_lower);
2411
2412         lp_ctx->globals->szRealm_upper = strupper_talloc(lp_ctx, pszParmValue);
2413         lp_ctx->globals->szRealm_lower = strlower_talloc(lp_ctx, pszParmValue);
2414
2415         return true;
2416 }
2417
2418 /***************************************************************************
2419  Handle the include operation.
2420 ***************************************************************************/
2421
2422 static bool handle_include(struct loadparm_context *lp_ctx, int unused,
2423                            const char *pszParmValue, char **ptr)
2424 {
2425         char *fname = standard_sub_basic(lp_ctx, pszParmValue);
2426
2427         add_to_file_list(lp_ctx, pszParmValue, fname);
2428
2429         lpcfg_string_set(lp_ctx, ptr, fname);
2430
2431         if (file_exist(fname))
2432                 return pm_process(fname, do_section, do_parameter, lp_ctx);
2433
2434         DEBUG(2, ("Can't find include file %s\n", fname));
2435
2436         return false;
2437 }
2438
2439 /***************************************************************************
2440  Handle the interpretation of the copy parameter.
2441 ***************************************************************************/
2442
2443 static bool handle_copy(struct loadparm_context *lp_ctx, int unused,
2444                         const char *pszParmValue, char **ptr)
2445 {
2446         bool bRetval;
2447         struct loadparm_service *serviceTemp;
2448
2449         lpcfg_string_set(lp_ctx, ptr, pszParmValue);
2450
2451         bRetval = false;
2452
2453         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
2454
2455         if ((serviceTemp = getservicebyname(lp_ctx, pszParmValue)) != NULL) {
2456                 if (serviceTemp == lp_ctx->currentService) {
2457                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
2458                 } else {
2459                         copy_service(lp_ctx->currentService,
2460                                      serviceTemp,
2461                                      lp_ctx->currentService->copymap);
2462                         bRetval = true;
2463                 }
2464         } else {
2465                 DEBUG(0, ("Unable to copy service - source not found: %s\n",
2466                           pszParmValue));
2467                 bRetval = false;
2468         }
2469
2470         return bRetval;
2471 }
2472
2473 static bool handle_debuglevel(struct loadparm_context *lp_ctx, int unused,
2474                         const char *pszParmValue, char **ptr)
2475 {
2476
2477         lpcfg_string_set(lp_ctx, ptr, pszParmValue);
2478         if (lp_ctx->global) {
2479                 return debug_parse_levels(pszParmValue);
2480         }
2481         return true;
2482 }
2483
2484 static bool handle_logfile(struct loadparm_context *lp_ctx, int unused,
2485                         const char *pszParmValue, char **ptr)
2486 {
2487         debug_set_logfile(pszParmValue);
2488         if (lp_ctx->global) {
2489                 lpcfg_string_set(lp_ctx, ptr, pszParmValue);
2490         }
2491         return true;
2492 }
2493
2494 /***************************************************************************
2495  Initialise a copymap.
2496 ***************************************************************************/
2497
2498 static void init_copymap(struct loadparm_service *pservice)
2499 {
2500         int i;
2501
2502         TALLOC_FREE(pservice->copymap);
2503
2504         pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
2505         if (!pservice->copymap)
2506                 DEBUG(0,
2507                       ("Couldn't allocate copymap!! (size %d)\n",
2508                        (int)NUMPARAMETERS));
2509         else
2510                 for (i = 0; i < NUMPARAMETERS; i++)
2511                         bitmap_set(pservice->copymap, i);
2512 }
2513
2514 /**
2515  * Process a parametric option
2516  */
2517 static bool lp_do_parameter_parametric(struct loadparm_context *lp_ctx,
2518                                        struct loadparm_service *service,
2519                                        const char *pszParmName,
2520                                        const char *pszParmValue, int flags)
2521 {
2522         struct parmlist_entry *paramo, *data;
2523         char *name;
2524         TALLOC_CTX *mem_ctx;
2525
2526         while (isspace((unsigned char)*pszParmName)) {
2527                 pszParmName++;
2528         }
2529
2530         name = strlower_talloc(lp_ctx, pszParmName);
2531         if (!name) return false;
2532
2533         if (service == NULL) {
2534                 data = lp_ctx->globals->param_opt;
2535                 mem_ctx = lp_ctx->globals;
2536         } else {
2537                 data = service->param_opt;
2538                 mem_ctx = service;
2539         }
2540
2541         /* Traverse destination */
2542         for (paramo=data; paramo; paramo=paramo->next) {
2543                 /* If we already have the option set, override it unless
2544                    it was a command line option and the new one isn't */
2545                 if (strcmp(paramo->key, name) == 0) {
2546                         if ((paramo->priority & FLAG_CMDLINE) &&
2547                             !(flags & FLAG_CMDLINE)) {
2548                                 talloc_free(name);
2549                                 return true;
2550                         }
2551
2552                         talloc_free(paramo->value);
2553                         paramo->value = talloc_strdup(paramo, pszParmValue);
2554                         paramo->priority = flags;
2555                         talloc_free(name);
2556                         return true;
2557                 }
2558         }
2559
2560         paramo = talloc_zero(mem_ctx, struct parmlist_entry);
2561         if (!paramo)
2562                 smb_panic("OOM");
2563         paramo->key = talloc_strdup(paramo, name);
2564         paramo->value = talloc_strdup(paramo, pszParmValue);
2565         paramo->priority = flags;
2566         if (service == NULL) {
2567                 DLIST_ADD(lp_ctx->globals->param_opt, paramo);
2568         } else {
2569                 DLIST_ADD(service->param_opt, paramo);
2570         }
2571
2572         talloc_free(name);
2573
2574         return true;
2575 }
2576
2577 static bool set_variable(TALLOC_CTX *mem_ctx, int parmnum, void *parm_ptr,
2578                          const char *pszParmName, const char *pszParmValue,
2579                          struct loadparm_context *lp_ctx, bool on_globals)
2580 {
2581         int i;
2582         /* if it is a special case then go ahead */
2583         if (parm_table[parmnum].special) {
2584                 bool ret;
2585                 ret = parm_table[parmnum].special(lp_ctx, -1, pszParmValue,
2586                                                   (char **)parm_ptr);
2587                 if (!ret) {
2588                         return false;
2589                 }
2590                 goto mark_non_default;
2591         }
2592
2593         /* now switch on the type of variable it is */
2594         switch (parm_table[parmnum].type)
2595         {
2596                 case P_BOOL: {
2597                         bool b;
2598                         if (!set_boolean(pszParmValue, &b)) {
2599                                 DEBUG(0,("lp_do_parameter(%s): value is not boolean!\n", pszParmValue));
2600                                 return false;
2601                         }
2602                         *(bool *)parm_ptr = b;
2603                         }
2604                         break;
2605
2606                 case P_BOOLREV: {
2607                         bool b;
2608                         if (!set_boolean(pszParmValue, &b)) {
2609                                 DEBUG(0,("lp_do_parameter(%s): value is not boolean!\n", pszParmValue));
2610                                 return false;
2611                         }
2612                         *(bool *)parm_ptr = !b;
2613                         }
2614                         break;
2615
2616                 case P_INTEGER:
2617                         *(int *)parm_ptr = atoi(pszParmValue);
2618                         break;
2619
2620                 case P_CHAR:
2621                         *(char *)parm_ptr = *pszParmValue;
2622                         break;
2623
2624                 case P_OCTAL:
2625                         *(int *)parm_ptr = strtol(pszParmValue, NULL, 8);
2626                         break;
2627
2628                 case P_BYTES:
2629                 {
2630                         uint64_t val;
2631                         if (conv_str_size_error(pszParmValue, &val)) {
2632                                 if (val <= INT_MAX) {
2633                                         *(int *)parm_ptr = (int)val;
2634                                         break;
2635                                 }
2636                         }
2637
2638                         DEBUG(0,("lp_do_parameter(%s): value is not "
2639                             "a valid size specifier!\n", pszParmValue));
2640                         return false;
2641                 }
2642
2643                 case P_CMDLIST:
2644                         *(const char ***)parm_ptr = (const char **)str_list_make(mem_ctx,
2645                                                                   pszParmValue, NULL);
2646                         break;
2647                 case P_LIST:
2648                 {
2649                         char **new_list = str_list_make(mem_ctx,
2650                                                         pszParmValue, NULL);
2651                         for (i=0; new_list[i]; i++) {
2652                                 if (new_list[i][0] == '+' && new_list[i][1]) {
2653                                         if (!str_list_check(*(const char ***)parm_ptr,
2654                                                             &new_list[i][1])) {
2655                                                 *(const char ***)parm_ptr = str_list_add(*(const char ***)parm_ptr,
2656                                                                                          &new_list[i][1]);
2657                                         }
2658                                 } else if (new_list[i][0] == '-' && new_list[i][1]) {
2659                                         str_list_remove(*(const char ***)parm_ptr,
2660                                                         &new_list[i][1]);
2661                                 } else {
2662                                         if (i != 0) {
2663                                                 DEBUG(0, ("Unsupported list syntax for: %s = %s\n",
2664                                                           pszParmName, pszParmValue));
2665                                                 return false;
2666                                         }
2667                                         *(const char ***)parm_ptr = (const char **) new_list;
2668                                         break;
2669                                 }
2670                         }
2671                         break;
2672                 }
2673                 case P_STRING:
2674                         lpcfg_string_set(mem_ctx, (char **)parm_ptr, pszParmValue);
2675                         break;
2676
2677                 case P_USTRING:
2678                         lpcfg_string_set_upper(mem_ctx, (char **)parm_ptr, pszParmValue);
2679                         break;
2680
2681                 case P_ENUM:
2682                         for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
2683                                 if (strequal
2684                                     (pszParmValue,
2685                                      parm_table[parmnum].enum_list[i].name)) {
2686                                         *(int *)parm_ptr =
2687                                                 parm_table[parmnum].
2688                                                 enum_list[i].value;
2689                                         break;
2690                                 }
2691                         }
2692                         if (!parm_table[parmnum].enum_list[i].name) {
2693                                 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n", 
2694                                          pszParmValue, pszParmName));
2695                                 return false;
2696                         }
2697                         break;
2698
2699                 case P_SEP:
2700                         break;
2701         }
2702
2703 mark_non_default:
2704         if (on_globals && (lp_ctx->flags[parmnum] & FLAG_DEFAULT)) {
2705                 lp_ctx->flags[parmnum] &= ~FLAG_DEFAULT;
2706                 /* we have to also unset FLAG_DEFAULT on aliases */
2707                 for (i=parmnum-1;i>=0 && parm_table[i].offset == parm_table[parmnum].offset;i--) {
2708                         lp_ctx->flags[i] &= ~FLAG_DEFAULT;
2709                 }
2710                 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset;i++) {
2711                         lp_ctx->flags[i] &= ~FLAG_DEFAULT;
2712                 }
2713         }
2714         return true;
2715 }
2716
2717
2718 bool lpcfg_do_global_parameter(struct loadparm_context *lp_ctx,
2719                                const char *pszParmName, const char *pszParmValue)
2720 {
2721         int parmnum = map_parameter(pszParmName);
2722         void *parm_ptr;
2723
2724         if (parmnum < 0) {
2725                 if (strchr(pszParmName, ':')) {
2726                         return lp_do_parameter_parametric(lp_ctx, NULL, pszParmName, pszParmValue, 0);
2727                 }
2728                 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
2729                 return true;
2730         }
2731
2732         /* if the flag has been set on the command line, then don't allow override,
2733            but don't report an error */
2734         if (lp_ctx->flags[parmnum] & FLAG_CMDLINE) {
2735                 return true;
2736         }
2737
2738         parm_ptr = lpcfg_parm_ptr(lp_ctx, NULL, &parm_table[parmnum]);
2739
2740         return set_variable(lp_ctx->globals, parmnum, parm_ptr,
2741                             pszParmName, pszParmValue, lp_ctx, true);
2742 }
2743
2744 bool lpcfg_do_service_parameter(struct loadparm_context *lp_ctx,
2745                                 struct loadparm_service *service,
2746                                 const char *pszParmName, const char *pszParmValue)
2747 {
2748         void *parm_ptr;
2749         int i;
2750         int parmnum = map_parameter(pszParmName);
2751
2752         if (parmnum < 0) {
2753                 if (strchr(pszParmName, ':')) {
2754                         return lp_do_parameter_parametric(lp_ctx, service, pszParmName, pszParmValue, 0);
2755                 }
2756                 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
2757                 return true;
2758         }
2759
2760         /* if the flag has been set on the command line, then don't allow override,
2761            but don't report an error */
2762         if (lp_ctx->flags[parmnum] & FLAG_CMDLINE) {
2763                 return true;
2764         }
2765
2766         if (parm_table[parmnum].p_class == P_GLOBAL) {
2767                 DEBUG(0,
2768                       ("Global parameter %s found in service section!\n",
2769                        pszParmName));
2770                 return true;
2771         }
2772         parm_ptr = ((char *)service) + parm_table[parmnum].offset;
2773
2774         if (!service->copymap)
2775                 init_copymap(service);
2776
2777         /* this handles the aliases - set the copymap for other
2778          * entries with the same data pointer */
2779         for (i = 0; parm_table[i].label; i++)
2780                 if (parm_table[i].offset == parm_table[parmnum].offset &&
2781                     parm_table[i].p_class == parm_table[parmnum].p_class)
2782                         bitmap_clear(service->copymap, i);
2783
2784         return set_variable(service, parmnum, parm_ptr, pszParmName,
2785                             pszParmValue, lp_ctx, false);
2786 }
2787
2788 /**
2789  * Process a parameter.
2790  */
2791
2792 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
2793                          void *userdata)
2794 {
2795         struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata;
2796
2797         if (lp_ctx->bInGlobalSection)
2798                 return lpcfg_do_global_parameter(lp_ctx, pszParmName,
2799                                               pszParmValue);
2800         else
2801                 return lpcfg_do_service_parameter(lp_ctx, lp_ctx->currentService,
2802                                                   pszParmName, pszParmValue);
2803 }
2804
2805 /*
2806   variable argument do parameter
2807 */
2808 bool lpcfg_do_global_parameter_var(struct loadparm_context *lp_ctx, const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4);
2809 bool lpcfg_do_global_parameter_var(struct loadparm_context *lp_ctx,
2810                                 const char *pszParmName, const char *fmt, ...)
2811 {
2812         char *s;
2813         bool ret;
2814         va_list ap;
2815
2816         va_start(ap, fmt);
2817         s = talloc_vasprintf(NULL, fmt, ap);
2818         va_end(ap);
2819         ret = lpcfg_do_global_parameter(lp_ctx, pszParmName, s);
2820         talloc_free(s);
2821         return ret;
2822 }
2823
2824
2825 /*
2826   set a parameter from the commandline - this is called from command line parameter
2827   parsing code. It sets the parameter then marks the parameter as unable to be modified
2828   by smb.conf processing
2829 */
2830 bool lpcfg_set_cmdline(struct loadparm_context *lp_ctx, const char *pszParmName,
2831                        const char *pszParmValue)
2832 {
2833         int parmnum;
2834         int i;
2835
2836         if (lp_ctx->s3_fns) {
2837                 return lp_ctx->s3_fns->set_cmdline(pszParmName, pszParmValue);
2838         }
2839
2840         parmnum = map_parameter(pszParmName);
2841
2842         while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
2843
2844
2845         if (parmnum < 0 && strchr(pszParmName, ':')) {
2846                 /* set a parametric option */
2847                 return lp_do_parameter_parametric(lp_ctx, NULL, pszParmName,
2848                                                   pszParmValue, FLAG_CMDLINE);
2849         }
2850
2851         if (parmnum < 0) {
2852                 DEBUG(0,("Unknown option '%s'\n", pszParmName));
2853                 return false;
2854         }
2855
2856         /* reset the CMDLINE flag in case this has been called before */
2857         lp_ctx->flags[parmnum] &= ~FLAG_CMDLINE;
2858
2859         if (!lpcfg_do_global_parameter(lp_ctx, pszParmName, pszParmValue)) {
2860                 return false;
2861         }
2862
2863         lp_ctx->flags[parmnum] |= FLAG_CMDLINE;
2864
2865         /* we have to also set FLAG_CMDLINE on aliases */
2866         for (i=parmnum-1;i>=0 && parm_table[i].offset == parm_table[parmnum].offset;i--) {
2867                 lp_ctx->flags[i] |= FLAG_CMDLINE;
2868         }
2869         for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset;i++) {
2870                 lp_ctx->flags[i] |= FLAG_CMDLINE;
2871         }
2872
2873         return true;
2874 }
2875
2876 /*
2877   set a option from the commandline in 'a=b' format. Use to support --option
2878 */
2879 bool lpcfg_set_option(struct loadparm_context *lp_ctx, const char *option)
2880 {
2881         char *p, *s;
2882         bool ret;
2883
2884         s = talloc_strdup(NULL, option);
2885         if (!s) {
2886                 return false;
2887         }
2888
2889         p = strchr(s, '=');
2890         if (!p) {
2891                 talloc_free(s);
2892                 return false;
2893         }
2894
2895         *p = 0;
2896
2897         ret = lpcfg_set_cmdline(lp_ctx, s, p+1);
2898         talloc_free(s);
2899         return ret;
2900 }
2901
2902
2903 #define BOOLSTR(b) ((b) ? "Yes" : "No")
2904
2905 /**
2906  * Print a parameter of the specified type.
2907  */
2908
2909 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
2910 {
2911         /* For the seperation of lists values that we print below */
2912         const char *list_sep = ", ";
2913         int i;
2914         switch (p->type)
2915         {
2916                 case P_ENUM:
2917                         for (i = 0; p->enum_list[i].name; i++) {
2918                                 if (*(int *)ptr == p->enum_list[i].value) {
2919                                         fprintf(f, "%s",
2920                                                 p->enum_list[i].name);
2921                                         break;
2922                                 }
2923                         }
2924                         break;
2925
2926                 case P_BOOL:
2927                         fprintf(f, "%s", BOOLSTR(*(bool *)ptr));
2928                         break;
2929
2930                 case P_BOOLREV:
2931                         fprintf(f, "%s", BOOLSTR(!*(bool *)ptr));
2932                         break;
2933
2934                 case P_INTEGER:
2935                 case P_BYTES:
2936                         fprintf(f, "%d", *(int *)ptr);
2937                         break;
2938
2939                 case P_CHAR:
2940                         fprintf(f, "%c", *(char *)ptr);
2941                         break;
2942
2943                 case P_OCTAL: {
2944                         int val = *(int *)ptr; 
2945                         if (val == -1) {
2946                                 fprintf(f, "-1");
2947                         } else {
2948                                 fprintf(f, "0%o", val);
2949                         }
2950                         break;
2951                 }
2952
2953                 case P_CMDLIST:
2954                         list_sep = " ";
2955                         /* fall through */
2956                 case P_LIST:
2957                         if ((char ***)ptr && *(char ***)ptr) {
2958                                 char **list = *(char ***)ptr;
2959                                 for (; *list; list++) {
2960                                         /* surround strings with whitespace in double quotes */
2961                                         if (*(list+1) == NULL) {
2962                                                 /* last item, no extra separator */
2963                                                 list_sep = "";
2964                                         }
2965                                         if ( strchr_m( *list, ' ' ) ) {
2966                                                 fprintf(f, "\"%s\"%s", *list, list_sep);
2967                                         } else {
2968                                                 fprintf(f, "%s%s", *list, list_sep);
2969                                         }
2970                                 }
2971                         }
2972                         break;
2973
2974                 case P_STRING:
2975                 case P_USTRING:
2976                         if (*(char **)ptr) {
2977                                 fprintf(f, "%s", *(char **)ptr);
2978                         }
2979                         break;
2980                 case P_SEP:
2981                         break;
2982         }
2983 }
2984
2985 /**
2986  * Check if two parameters are equal.
2987  */
2988
2989 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
2990 {
2991         switch (type) {
2992                 case P_BOOL:
2993                 case P_BOOLREV:
2994                         return (*((bool *)ptr1) == *((bool *)ptr2));
2995
2996                 case P_INTEGER:
2997                 case P_ENUM:
2998                 case P_OCTAL:
2999                 case P_BYTES:
3000                         return (*((int *)ptr1) == *((int *)ptr2));
3001
3002                 case P_CHAR:
3003                         return (*((char *)ptr1) == *((char *)ptr2));
3004
3005                 case P_LIST:
3006                 case P_CMDLIST:
3007                         return str_list_equal(*(const char ***)ptr1, *(const char ***)ptr2);
3008
3009                 case P_STRING:
3010                 case P_USTRING:
3011                 {
3012                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
3013                         if (p1 && !*p1)
3014                                 p1 = NULL;
3015                         if (p2 && !*p2)
3016                                 p2 = NULL;
3017                         return (p1 == p2 || strequal(p1, p2));
3018                 }
3019                 case P_SEP:
3020                         break;
3021         }
3022         return false;
3023 }
3024
3025 /**
3026  * Process a new section (service).
3027  *
3028  * At this stage all sections are services.
3029  * Later we'll have special sections that permit server parameters to be set.
3030  * Returns True on success, False on failure.
3031  */
3032
3033 static bool do_section(const char *pszSectionName, void *userdata)
3034 {
3035         struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata;
3036         bool bRetval;
3037         bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
3038                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
3039         bRetval = false;
3040
3041         /* if we've just struck a global section, note the fact. */
3042         lp_ctx->bInGlobalSection = isglobal;
3043
3044         /* check for multiple global sections */
3045         if (lp_ctx->bInGlobalSection) {
3046                 DEBUG(4, ("Processing section \"[%s]\"\n", pszSectionName));
3047                 return true;
3048         }
3049
3050         /* if we have a current service, tidy it up before moving on */
3051         bRetval = true;
3052
3053         if (lp_ctx->currentService != NULL)
3054                 bRetval = lpcfg_service_ok(lp_ctx->currentService);
3055
3056         /* if all is still well, move to the next record in the services array */
3057         if (bRetval) {
3058                 /* We put this here to avoid an odd message order if messages are */
3059                 /* issued by the post-processing of a previous section. */
3060                 DEBUG(4, ("Processing section \"[%s]\"\n", pszSectionName));
3061
3062                 if ((lp_ctx->currentService = lpcfg_add_service(lp_ctx, lp_ctx->sDefault,
3063                                                                    pszSectionName))
3064                     == NULL) {
3065                         DEBUG(0, ("Failed to add a new service\n"));
3066                         return false;
3067                 }
3068         }
3069
3070         return bRetval;
3071 }
3072
3073
3074 /**
3075  * Determine if a particular base parameter is currently set to the default value.
3076  */
3077
3078 static bool is_default(struct loadparm_service *sDefault, int i)
3079 {
3080         void *def_ptr = ((char *)sDefault) + parm_table[i].offset;
3081         if (!defaults_saved)
3082                 return false;
3083         switch (parm_table[i].type) {
3084                 case P_CMDLIST:
3085                 case P_LIST:
3086                         return str_list_equal((const char **)parm_table[i].def.lvalue, 
3087                                               (const char **)def_ptr);
3088                 case P_STRING:
3089                 case P_USTRING:
3090                         return strequal(parm_table[i].def.svalue,
3091                                         *(char **)def_ptr);
3092                 case P_BOOL:
3093                 case P_BOOLREV:
3094                         return parm_table[i].def.bvalue ==
3095                                 *(bool *)def_ptr;
3096                 case P_INTEGER:
3097                 case P_CHAR:
3098                 case P_OCTAL:
3099                 case P_BYTES:
3100                 case P_ENUM:
3101                         return parm_table[i].def.ivalue ==
3102                                 *(int *)def_ptr;
3103                 case P_SEP:
3104                         break;
3105         }
3106         return false;
3107 }
3108
3109 /**
3110  *Display the contents of the global structure.
3111  */
3112
3113 static void dump_globals(struct loadparm_context *lp_ctx, FILE *f,
3114                          bool show_defaults)
3115 {
3116         int i;
3117         struct parmlist_entry *data;
3118
3119         fprintf(f, "# Global parameters\n[global]\n");
3120
3121         for (i = 0; parm_table[i].label; i++)
3122                 if (parm_table[i].p_class == P_GLOBAL &&
3123                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
3124                         if (!show_defaults && (lp_ctx->flags[i] & FLAG_DEFAULT))
3125                                 continue;
3126                         fprintf(f, "\t%s = ", parm_table[i].label);
3127                         print_parameter(&parm_table[i], lpcfg_parm_ptr(lp_ctx, NULL, &parm_table[i]), f);
3128                         fprintf(f, "\n");
3129         }
3130         if (lp_ctx->globals->param_opt != NULL) {
3131                 for (data = lp_ctx->globals->param_opt; data;
3132                      data = data->next) {
3133                         if (!show_defaults && (data->priority & FLAG_DEFAULT)) {
3134                                 continue;
3135                         }
3136                         fprintf(f, "\t%s = %s\n", data->key, data->value);
3137                 }
3138         }
3139
3140 }
3141
3142 /**
3143  * Display the contents of a single services record.
3144  */
3145
3146 static void dump_a_service(struct loadparm_service * pService, struct loadparm_service *sDefault, FILE * f,
3147                            unsigned int *flags)
3148 {
3149         int i;
3150         struct parmlist_entry *data;
3151
3152         if (pService != sDefault)
3153                 fprintf(f, "\n[%s]\n", pService->szService);
3154
3155         for (i = 0; parm_table[i].label; i++) {
3156                 if (parm_table[i].p_class == P_LOCAL &&
3157                     (*parm_table[i].label != '-') &&
3158                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset)))
3159                 {
3160                         if (pService == sDefault) {
3161                                 if (flags && (flags[i] & FLAG_DEFAULT)) {
3162                                         continue;
3163                                 }
3164                                 if (defaults_saved) {
3165                                         if (is_default(sDefault, i)) {
3166                                                 continue;
3167                                         }
3168                                 }
3169                         } else {
3170                                 if (equal_parameter(parm_table[i].type,
3171                                                     ((char *)pService) +
3172                                                     parm_table[i].offset,
3173                                                     ((char *)sDefault) +
3174                                                     parm_table[i].offset))
3175                                         continue;
3176                         }
3177
3178                         fprintf(f, "\t%s = ", parm_table[i].label);
3179                         print_parameter(&parm_table[i],
3180                                         ((char *)pService) + parm_table[i].offset, f);
3181                         fprintf(f, "\n");
3182                 }
3183         }
3184         if (pService->param_opt != NULL) {
3185                 for (data = pService->param_opt; data; data = data->next) {
3186                         fprintf(f, "\t%s = %s\n", data->key, data->value);
3187                 }
3188         }
3189 }
3190
3191 bool lpcfg_dump_a_parameter(struct loadparm_context *lp_ctx,
3192                             struct loadparm_service *service,
3193                             const char *parm_name, FILE * f)
3194 {
3195         struct parm_struct *parm;
3196         void *ptr;
3197
3198         parm = lpcfg_parm_struct(lp_ctx, parm_name);
3199         if (!parm) {
3200                 return false;
3201         }
3202
3203         ptr = lpcfg_parm_ptr(lp_ctx, service,parm);
3204
3205         print_parameter(parm, ptr, f);
3206         fprintf(f, "\n");
3207         return true;
3208 }
3209
3210 /**
3211  * Return info about the next parameter in a service.
3212  * snum==-1 gives the globals.
3213  * Return NULL when out of parameters.
3214  */
3215
3216
3217 struct parm_struct *lpcfg_next_parameter(struct loadparm_context *lp_ctx, int snum, int *i,
3218                                          int allparameters)
3219 {
3220         if (snum == -1) {
3221                 /* do the globals */
3222                 for (; parm_table[*i].label; (*i)++) {
3223                         if ((*parm_table[*i].label == '-'))
3224                                 continue;
3225
3226                         if ((*i) > 0
3227                             && (parm_table[*i].offset ==
3228                                 parm_table[(*i) - 1].offset)
3229                             && (parm_table[*i].p_class ==
3230                                 parm_table[(*i) - 1].p_class))
3231                                 continue;
3232
3233                         return &parm_table[(*i)++];
3234                 }
3235         } else {
3236                 struct loadparm_service *pService = lp_ctx->services[snum];
3237
3238                 for (; parm_table[*i].label; (*i)++) {
3239                         if (parm_table[*i].p_class == P_LOCAL &&
3240                             (*parm_table[*i].label != '-') &&
3241                             ((*i) == 0 ||
3242                              (parm_table[*i].offset !=
3243                               parm_table[(*i) - 1].offset)))
3244                         {
3245                                 if (allparameters ||
3246                                     !equal_parameter(parm_table[*i].type,
3247                                                      ((char *)pService) +
3248                                                      parm_table[*i].offset,
3249                                                      ((char *)lp_ctx->sDefault) +
3250                                                      parm_table[*i].offset))
3251                                 {
3252                                         return &parm_table[(*i)++];
3253                                 }
3254                         }
3255                 }
3256         }
3257
3258         return NULL;
3259 }
3260
3261
3262 /**
3263  * Auto-load some home services.
3264  */
3265 static void lpcfg_add_auto_services(struct loadparm_context *lp_ctx,
3266                                     const char *str)
3267 {
3268         return;
3269 }
3270
3271
3272 /**
3273  * Unload unused services.
3274  */
3275
3276 void lpcfg_killunused(struct loadparm_context *lp_ctx,
3277                    struct smbsrv_connection *smb,
3278                    bool (*snumused) (struct smbsrv_connection *, int))
3279 {
3280         int i;
3281         for (i = 0; i < lp_ctx->iNumServices; i++) {
3282                 if (lp_ctx->services[i] == NULL)
3283                         continue;
3284
3285                 if (!snumused || !snumused(smb, i)) {
3286                         talloc_free(lp_ctx->services[i]);
3287                         lp_ctx->services[i] = NULL;
3288                 }
3289         }
3290 }
3291
3292
3293 static int lpcfg_destructor(struct loadparm_context *lp_ctx)
3294 {
3295         struct parmlist_entry *data;
3296
3297         if (lp_ctx->refuse_free) {
3298                 /* someone is trying to free the
3299                    global_loadparm_context.
3300                    We can't allow that. */
3301                 return -1;
3302         }
3303
3304         if (lp_ctx->globals->param_opt != NULL) {
3305                 struct parmlist_entry *next;
3306                 for (data = lp_ctx->globals->param_opt; data; data=next) {
3307                         next = data->next;
3308                         if (data->priority & FLAG_CMDLINE) continue;
3309                         DLIST_REMOVE(lp_ctx->globals->param_opt, data);
3310                         talloc_free(data);
3311                 }
3312         }
3313
3314         return 0;
3315 }
3316
3317 /**
3318  * Initialise the global parameter structure.
3319  *
3320  * Note that most callers should use loadparm_init_global() instead
3321  */
3322 struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
3323 {
3324         int i;
3325         char *myname;
3326         struct loadparm_context *lp_ctx;
3327         struct parmlist_entry *parm;
3328         char *logfile;
3329
3330         lp_ctx = talloc_zero(mem_ctx, struct loadparm_context);
3331         if (lp_ctx == NULL)
3332                 return NULL;
3333
3334         talloc_set_destructor(lp_ctx, lpcfg_destructor);
3335         lp_ctx->bInGlobalSection = true;
3336         lp_ctx->globals = talloc_zero(lp_ctx, struct loadparm_global);
3337         lp_ctx->sDefault = talloc_zero(lp_ctx, struct loadparm_service);
3338
3339         lp_ctx->sDefault->iMaxPrintJobs = 1000;
3340         lp_ctx->sDefault->bAvailable = true;
3341         lp_ctx->sDefault->bBrowseable = true;
3342         lp_ctx->sDefault->bRead_only = true;
3343         lp_ctx->sDefault->bMap_archive = true;
3344         lp_ctx->sDefault->iStrictLocking = true;
3345         lp_ctx->sDefault->bOpLocks = true;
3346         lp_ctx->sDefault->iCreate_mask = 0744;
3347         lp_ctx->sDefault->iCreate_force_mode = 0000;
3348         lp_ctx->sDefault->iDir_mask = 0755;
3349         lp_ctx->sDefault->iDir_force_mode = 0000;
3350
3351         DEBUG(3, ("Initialising global parameters\n"));
3352
3353         for (i = 0; parm_table[i].label; i++) {
3354                 if ((parm_table[i].type == P_STRING ||
3355                      parm_table[i].type == P_USTRING) &&
3356                     !(lp_ctx->flags[i] & FLAG_CMDLINE)) {
3357                         char **r;
3358                         if (parm_table[i].p_class == P_LOCAL) {
3359                                 r = (char **)(((char *)lp_ctx->sDefault) + parm_table[i].offset);
3360                         } else {
3361                                 r = (char **)(((char *)lp_ctx->globals) + parm_table[i].offset);
3362                         }
3363                         *r = talloc_strdup(lp_ctx, "");
3364                 }
3365         }
3366
3367         logfile = talloc_asprintf(lp_ctx, "%s/log.samba", dyn_LOGFILEBASE);
3368         lpcfg_do_global_parameter(lp_ctx, "log file", logfile);
3369         talloc_free(logfile);
3370
3371         lpcfg_do_global_parameter(lp_ctx, "log level", "0");
3372
3373         lpcfg_do_global_parameter(lp_ctx, "share backend", "classic");
3374
3375         lpcfg_do_global_parameter(lp_ctx, "server role", "auto");
3376         lpcfg_do_global_parameter(lp_ctx, "domain logons", "No");
3377         lpcfg_do_global_parameter(lp_ctx, "domain master", "Auto");
3378
3379         /* options that can be set on the command line must be initialised via
3380            the slower lpcfg_do_global_parameter() to ensure that FLAG_CMDLINE is obeyed */
3381 #ifdef TCP_NODELAY
3382         lpcfg_do_global_parameter(lp_ctx, "socket options", "TCP_NODELAY");
3383 #endif
3384         lpcfg_do_global_parameter(lp_ctx, "workgroup", DEFAULT_WORKGROUP);
3385         myname = get_myname(lp_ctx);
3386         lpcfg_do_global_parameter(lp_ctx, "netbios name", myname);
3387         talloc_free(myname);
3388         lpcfg_do_global_parameter(lp_ctx, "name resolve order", "wins host bcast");
3389
3390         lpcfg_do_global_parameter(lp_ctx, "fstype", "NTFS");
3391
3392         lpcfg_do_global_parameter(lp_ctx, "ntvfs handler", "unixuid default");
3393         lpcfg_do_global_parameter(lp_ctx, "max connections", "-1");
3394
3395         lpcfg_do_global_parameter(lp_ctx, "dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup unixinfo browser eventlog6 backupkey dnsserver");
3396         lpcfg_do_global_parameter(lp_ctx, "server services", "smb rpc nbt wrepl ldap cldap kdc drepl winbind ntp_signd kcc dnsupdate");
3397         lpcfg_do_global_parameter(lp_ctx, "ntptr providor", "simple_ldb");
3398         /* the winbind method for domain controllers is for both RODC
3399            auth forwarding and for trusted domains */
3400         lpcfg_do_global_parameter(lp_ctx, "private dir", dyn_PRIVATE_DIR);
3401         lpcfg_do_global_parameter(lp_ctx, "registry:HKEY_LOCAL_MACHINE", "hklm.ldb");
3402
3403         /* This hive should be dynamically generated by Samba using
3404            data from the sam, but for the moment leave it in a tdb to
3405            keep regedt32 from popping up an annoying dialog. */
3406         lpcfg_do_global_parameter(lp_ctx, "registry:HKEY_USERS", "hku.ldb");
3407
3408         /* using UTF8 by default allows us to support all chars */
3409         lpcfg_do_global_parameter(lp_ctx, "unix charset", "UTF8");
3410
3411         /* Use codepage 850 as a default for the dos character set */
3412         lpcfg_do_global_parameter(lp_ctx, "dos charset", "CP850");
3413
3414         /*
3415          * Allow the default PASSWD_CHAT to be overridden in local.h.
3416          */
3417         lpcfg_do_global_parameter(lp_ctx, "passwd chat", DEFAULT_PASSWD_CHAT);
3418
3419         lpcfg_do_global_parameter(lp_ctx, "pid directory", dyn_PIDDIR);
3420         lpcfg_do_global_parameter(lp_ctx, "lock dir", dyn_LOCKDIR);
3421         lpcfg_do_global_parameter(lp_ctx, "state directory", dyn_STATEDIR);
3422         lpcfg_do_global_parameter(lp_ctx, "cache directory", dyn_CACHEDIR);
3423         lpcfg_do_global_parameter(lp_ctx, "ncalrpc dir", dyn_NCALRPCDIR);
3424
3425         lpcfg_do_global_parameter(lp_ctx, "socket address", "");
3426         lpcfg_do_global_parameter_var(lp_ctx, "server string",
3427                                    "Samba %s", SAMBA_VERSION_STRING);
3428
3429         lpcfg_do_global_parameter(lp_ctx, "password server", "*");
3430
3431         lpcfg_do_global_parameter(lp_ctx, "max mux", "50");
3432         lpcfg_do_global_parameter(lp_ctx, "max xmit", "12288");
3433         lpcfg_do_global_parameter(lp_ctx, "host msdfs", "true");
3434
3435         lpcfg_do_global_parameter(lp_ctx, "password level", "0");
3436         lpcfg_do_global_parameter(lp_ctx, "LargeReadwrite", "True");
3437         lpcfg_do_global_parameter(lp_ctx, "server min protocol", "CORE");
3438         lpcfg_do_global_parameter(lp_ctx, "server max protocol", "NT1");
3439         lpcfg_do_global_parameter(lp_ctx, "client min protocol", "CORE");
3440         lpcfg_do_global_parameter(lp_ctx, "client max protocol", "NT1");
3441         lpcfg_do_global_parameter(lp_ctx, "security", "AUTO");
3442         lpcfg_do_global_parameter(lp_ctx, "paranoid server security", "True");
3443         lpcfg_do_global_parameter(lp_ctx, "EncryptPasswords", "True");
3444         lpcfg_do_global_parameter(lp_ctx, "ReadRaw", "True");
3445         lpcfg_do_global_parameter(lp_ctx, "WriteRaw", "True");
3446         lpcfg_do_global_parameter(lp_ctx, "NullPasswords", "False");
3447         lpcfg_do_global_parameter(lp_ctx, "ObeyPamRestrictions", "False");
3448
3449         lpcfg_do_global_parameter(lp_ctx, "TimeServer", "False");
3450         lpcfg_do_global_parameter(lp_ctx, "BindInterfacesOnly", "False");
3451         lpcfg_do_global_parameter(lp_ctx, "Unicode", "True");
3452         lpcfg_do_global_parameter(lp_ctx, "ClientLanManAuth", "False");
3453         lpcfg_do_global_parameter(lp_ctx, "ClientNTLMv2Auth", "True");
3454         lpcfg_do_global_parameter(lp_ctx, "LanmanAuth", "False");
3455         lpcfg_do_global_parameter(lp_ctx, "NTLMAuth", "True");
3456         lpcfg_do_global_parameter(lp_ctx, "client use spnego principal", "False");
3457
3458         lpcfg_do_global_parameter(lp_ctx, "UnixExtensions", "False");
3459
3460         lpcfg_do_global_parameter(lp_ctx, "PreferredMaster", "Auto");
3461         lpcfg_do_global_parameter(lp_ctx, "LocalMaster", "True");
3462
3463         lpcfg_do_global_parameter(lp_ctx, "wins support", "False");
3464         lpcfg_do_global_parameter(lp_ctx, "dns proxy", "True");
3465
3466         lpcfg_do_global_parameter(lp_ctx, "winbind separator", "\\");
3467         lpcfg_do_global_parameter(lp_ctx, "winbind sealed pipes", "True");
3468         lpcfg_do_global_parameter(lp_ctx, "winbindd socket directory", dyn_WINBINDD_SOCKET_DIR);
3469 #if _SAMBA_BUILD_ >= 4
3470         lpcfg_do_global_parameter(lp_ctx, "winbindd privileged socket directory", dyn_WINBINDD_PRIVILEGED_SOCKET_DIR);
3471         lpcfg_do_global_parameter(lp_ctx, "ntp signd socket directory", dyn_NTP_SIGND_SOCKET_DIR);
3472         lpcfg_do_global_parameter_var(lp_ctx, "dns update command", "%s/samba_dnsupdate", dyn_SCRIPTSBINDIR);
3473         lpcfg_do_global_parameter_var(lp_ctx, "spn update command", "%s/samba_spnupdate", dyn_SCRIPTSBINDIR);
3474         lpcfg_do_global_parameter_var(lp_ctx, "samba kcc command",
3475                                         "%s/samba_kcc", dyn_SCRIPTSBINDIR);
3476 #endif
3477         lpcfg_do_global_parameter(lp_ctx, "template shell", "/bin/false");
3478         lpcfg_do_global_parameter(lp_ctx, "template homedir", "/home/%WORKGROUP%/%ACCOUNTNAME%");
3479         lpcfg_do_global_parameter(lp_ctx, "idmap trusted only", "False");
3480
3481         lpcfg_do_global_parameter(lp_ctx, "client signing", "default");
3482         lpcfg_do_global_parameter(lp_ctx, "server signing", "default");
3483
3484         lpcfg_do_global_parameter(lp_ctx, "use spnego", "True");
3485
3486         lpcfg_do_global_parameter(lp_ctx, "use mmap", "True");
3487
3488         lpcfg_do_global_parameter(lp_ctx, "smb ports", "445 139");
3489         lpcfg_do_global_parameter(lp_ctx, "nbt port", "137");
3490         lpcfg_do_global_parameter(lp_ctx, "dgram port", "138");
3491         lpcfg_do_global_parameter(lp_ctx, "cldap port", "389");
3492         lpcfg_do_global_parameter(lp_ctx, "krb5 port", "88");
3493         lpcfg_do_global_parameter(lp_ctx, "kpasswd port", "464");
3494         lpcfg_do_global_parameter(lp_ctx, "web port", "901");
3495
3496         lpcfg_do_global_parameter(lp_ctx, "nt status support", "True");
3497
3498         lpcfg_do_global_parameter(lp_ctx, "max wins ttl", "518400"); /* 6 days */
3499         lpcfg_do_global_parameter(lp_ctx, "min wins ttl", "10");
3500
3501         lpcfg_do_global_parameter(lp_ctx, "tls enabled", "True");
3502         lpcfg_do_global_parameter(lp_ctx, "tls keyfile", "tls/key.pem");
3503         lpcfg_do_global_parameter(lp_ctx, "tls certfile", "tls/cert.pem");
3504         lpcfg_do_global_parameter(lp_ctx, "tls cafile", "tls/ca.pem");
3505         lpcfg_do_global_parameter(lp_ctx, "prefork children:smb", "4");
3506
3507         lpcfg_do_global_parameter(lp_ctx, "rndc command", "/usr/sbin/rndc");
3508         lpcfg_do_global_parameter(lp_ctx, "nsupdate command", "/usr/bin/nsupdate -g");
3509
3510         lpcfg_do_global_parameter(lp_ctx, "allow dns updates", "False");
3511         lpcfg_do_global_parameter(lp_ctx, "dns recursive queries", "False");
3512         lpcfg_do_global_parameter(lp_ctx, "dns forwarder", "");
3513
3514         for (i = 0; parm_table[i].label; i++) {
3515                 if (!(lp_ctx->flags[i] & FLAG_CMDLINE)) {
3516                         lp_ctx->flags[i] |= FLAG_DEFAULT;
3517                 }
3518         }
3519
3520         for (parm=lp_ctx->globals->param_opt; parm; parm=parm->next) {
3521                 if (!(parm->priority & FLAG_CMDLINE)) {
3522                         parm->priority |= FLAG_DEFAULT;
3523                 }
3524         }
3525
3526         return lp_ctx;
3527 }
3528
3529 /**
3530  * Initialise the global parameter structure.
3531  */
3532 struct loadparm_context *loadparm_init_global(bool load_default)
3533 {
3534         if (global_loadparm_context == NULL) {
3535                 global_loadparm_context = loadparm_init(NULL);
3536         }
3537         if (global_loadparm_context == NULL) {
3538                 return NULL;
3539         }
3540         global_loadparm_context->global = true;
3541         if (load_default && !global_loadparm_context->loaded) {
3542                 lpcfg_load_default(global_loadparm_context);
3543         }
3544         global_loadparm_context->refuse_free = true;
3545         return global_loadparm_context;
3546 }
3547
3548 /**
3549  * Initialise the global parameter structure.
3550  */
3551 struct loadparm_context *loadparm_init_s3(TALLOC_CTX *mem_ctx, 
3552                                           const struct loadparm_s3_context *s3_fns)
3553 {
3554         struct loadparm_context *loadparm_context = talloc_zero(mem_ctx, struct loadparm_context);
3555         if (!loadparm_context) {
3556                 return NULL;
3557         }
3558         loadparm_context->s3_fns = s3_fns;
3559         return loadparm_context;
3560 }
3561
3562 const char *lpcfg_configfile(struct loadparm_context *lp_ctx)
3563 {
3564         return lp_ctx->szConfigFile;
3565 }
3566
3567 const char *lp_default_path(void)
3568 {
3569     if (getenv("SMB_CONF_PATH"))
3570         return getenv("SMB_CONF_PATH");
3571     else
3572         return dyn_CONFIGFILE;
3573 }
3574
3575 /**
3576  * Update the internal state of a loadparm context after settings 
3577  * have changed.
3578  */
3579 static bool lpcfg_update(struct loadparm_context *lp_ctx)
3580 {
3581         struct debug_settings settings;
3582         lpcfg_add_auto_services(lp_ctx, lpcfg_auto_services(lp_ctx));
3583
3584         if (!lp_ctx->globals->szWINSservers && lp_ctx->globals->bWINSsupport) {
3585