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