lib/param: Merge "WINS Options" section from source3/param
[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    Copyright (C) Andrew Bartlett 2011-2012
15
16    This program is free software; you can redistribute it and/or modify
17    it under the terms of the GNU General Public License as published by
18    the Free Software Foundation; either version 3 of the License, or
19    (at your option) any later version.
20
21    This program is distributed in the hope that it will be useful,
22    but WITHOUT ANY WARRANTY; without even the implied warranty of
23    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24    GNU General Public License for more details.
25
26    You should have received a copy of the GNU General Public License
27    along with this program.  If not, see <http://www.gnu.org/licenses/>.
28 */
29
30 /*
31  *  Load parameters.
32  *
33  *  This module provides suitable callback functions for the params
34  *  module. It builds the internal table of service details which is
35  *  then used by the rest of the server.
36  *
37  * To add a parameter:
38  *
39  * 1) add it to the global or service structure definition
40  * 2) add it to the parm_table
41  * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
42  * 4) If it's a global then initialise it in init_globals. If a local
43  *    (ie. service) parameter then initialise it in the sDefault structure
44  *
45  *
46  * Notes:
47  *   The configuration file is processed sequentially for speed. It is NOT
48  *   accessed randomly as happens in 'real' Windows. For this reason, there
49  *   is a fair bit of sequence-dependent code here - ie., code which assumes
50  *   that certain things happen before others. In particular, the code which
51  *   happens at the boundary between sections is delicately poised, so be
52  *   careful!
53  *
54  */
55
56 #include "includes.h"
57 #include "version.h"
58 #include "dynconfig/dynconfig.h"
59 #include "system/time.h"
60 #include "system/locale.h"
61 #include "system/network.h" /* needed for TCP_NODELAY */
62 #include "../lib/util/dlinklist.h"
63 #include "lib/param/param.h"
64 #include "lib/param/loadparm.h"
65 #include "auth/gensec/gensec.h"
66 #include "lib/param/s3_param.h"
67 #include "lib/util/bitmap.h"
68 #include "libcli/smb/smb_constants.h"
69 #include "source4/dns_server/dns_update.h"
70
71 #define standard_sub_basic talloc_strdup
72
73 static bool do_parameter(const char *, const char *, void *);
74 static bool defaults_saved = false;
75
76 #define LOADPARM_EXTRA_GLOBALS \
77         struct parmlist_entry *param_opt;                               \
78         char *szRealm;                                                  \
79         char *szConfigFile;                                             \
80         char *szLdapMachineSuffix;                                      \
81         char *szLdapUserSuffix;                                         \
82         char *szLdapIdmapSuffix;                                        \
83         char *szLdapGroupSuffix;                                        \
84         char *szUsershareTemplateShare;                                 \
85         char *szIdmapUID;                                               \
86         char *szIdmapGID;                                               \
87         int winbindMaxDomainConnections;                                \
88         char *tls_keyfile;                                              \
89         char *tls_certfile;                                             \
90         char *tls_cafile;                                               \
91         char *tls_crlfile;                                              \
92         char *tls_dhpfile;                                              \
93         char *loglevel;                                                 \
94         char *panic_action;                                             \
95         int bPreferredMaster;
96
97 #include "lib/param/param_global.h"
98
99 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
100
101 /* we don't need a special handler for "dos charset" and "unix charset" */
102 #define handle_dos_charset NULL
103 #define handle_charset NULL
104
105 /* these are parameter handlers which are not needed in the
106  * non-source3 code
107  */
108 #define handle_netbios_aliases NULL
109 #define handle_debug_list NULL
110 #define handle_printing NULL
111 #define handle_ldap_debug_level NULL
112 #define handle_idmap_backend NULL
113 #define handle_idmap_uid NULL
114 #define handle_idmap_gid NULL
115
116 #ifndef N_
117 #define N_(x) x
118 #endif
119
120 /* prototypes for the special type handlers */
121 static bool handle_include(struct loadparm_context *lp_ctx, int unused,
122                            const char *pszParmValue, char **ptr);
123 static bool handle_realm(struct loadparm_context *lp_ctx, int unused,
124                          const char *pszParmValue, char **ptr);
125 static bool handle_copy(struct loadparm_context *lp_ctx, int unused,
126                         const char *pszParmValue, char **ptr);
127 static bool handle_debuglevel(struct loadparm_context *lp_ctx, int unused,
128                               const char *pszParmValue, char **ptr);
129 static bool handle_logfile(struct loadparm_context *lp_ctx, int unused,
130                            const char *pszParmValue, char **ptr);
131
132 #include "lib/param/param_table.c"
133
134 #define GLOBAL_VAR(name) offsetof(struct loadparm_global, name)
135 #define LOCAL_VAR(name) offsetof(struct loadparm_service, name)
136
137 static struct parm_struct parm_table[] = {
138         {
139                 .label          = "server role",
140                 .type           = P_ENUM,
141                 .p_class        = P_GLOBAL,
142                 .offset         = GLOBAL_VAR(server_role),
143                 .special        = NULL,
144                 .enum_list      = enum_server_role
145         },
146         {
147                 .label          = "domain logons",
148                 .type           = P_ENUM,
149                 .p_class        = P_GLOBAL,
150                 .offset         = GLOBAL_VAR(bDomainLogons),
151                 .special        = NULL,
152                 .enum_list      = enum_bool_auto
153         },
154         {
155                 .label          = "domain master",
156                 .type           = P_ENUM,
157                 .p_class        = P_GLOBAL,
158                 .offset         = GLOBAL_VAR(domain_master),
159                 .special        = NULL,
160                 .enum_list      = enum_bool_auto
161         },
162         {
163                 .label          = "dos charset",
164                 .type           = P_STRING,
165                 .p_class        = P_GLOBAL,
166                 .offset         = GLOBAL_VAR(dos_charset),
167                 .special        = NULL,
168                 .enum_list      = NULL
169         },
170         {
171                 .label          = "unix charset",
172                 .type           = P_STRING,
173                 .p_class        = P_GLOBAL,
174                 .offset         = GLOBAL_VAR(unix_charset),
175                 .special        = NULL,
176                 .enum_list      = NULL
177         },
178         {
179                 .label          = "comment",
180                 .type           = P_STRING,
181                 .p_class        = P_LOCAL,
182                 .offset         = LOCAL_VAR(comment),
183                 .special        = NULL,
184                 .enum_list      = NULL,
185                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT
186         },
187         {
188                 .label          = "path",
189                 .type           = P_STRING,
190                 .p_class        = P_LOCAL,
191                 .offset         = LOCAL_VAR(szPath),
192                 .special        = NULL,
193                 .enum_list      = NULL,
194                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
195         },
196         {
197                 .label          = "directory",
198                 .type           = P_STRING,
199                 .p_class        = P_LOCAL,
200                 .offset         = LOCAL_VAR(szPath),
201                 .special        = NULL,
202                 .enum_list      = NULL,
203                 .flags          = FLAG_HIDE,
204         },
205         {
206                 .label          = "workgroup",
207                 .type           = P_USTRING,
208                 .p_class        = P_GLOBAL,
209                 .offset         = GLOBAL_VAR(szWorkgroup),
210                 .special        = NULL,
211                 .enum_list      = NULL,
212                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD,
213         },
214         {
215                 .label          = "realm",
216                 .type           = P_STRING,
217                 .p_class        = P_GLOBAL,
218                 .offset         = GLOBAL_VAR(szRealm),
219                 .special        = handle_realm,
220                 .enum_list      = NULL,
221                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD,
222         },
223         {
224                 .label          = "netbios name",
225                 .type           = P_USTRING,
226                 .p_class        = P_GLOBAL,
227                 .offset         = GLOBAL_VAR(szNetbiosName),
228                 .special        = NULL,
229                 .enum_list      = NULL,
230                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD,
231         },
232         {
233                 .label          = "netbios aliases",
234                 .type           = P_LIST,
235                 .p_class        = P_GLOBAL,
236                 .offset         = GLOBAL_VAR(szNetbiosAliases),
237                 .special        = NULL,
238                 .enum_list      = NULL
239         },
240         {
241                 .label          = "netbios scope",
242                 .type           = P_USTRING,
243                 .p_class        = P_GLOBAL,
244                 .offset         = GLOBAL_VAR(szNetbiosScope),
245                 .special        = NULL,
246                 .enum_list      = NULL,
247                 .flags          = FLAG_ADVANCED,
248         },
249         {
250                 .label          = "server string",
251                 .type           = P_STRING,
252                 .p_class        = P_GLOBAL,
253                 .offset         = GLOBAL_VAR(szServerString),
254                 .special        = NULL,
255                 .enum_list      = NULL,
256                 .flags          = FLAG_BASIC | FLAG_ADVANCED,
257         },
258         {
259                 .label          = "interfaces",
260                 .type           = P_LIST,
261                 .p_class        = P_GLOBAL,
262                 .offset         = GLOBAL_VAR(szInterfaces),
263                 .special        = NULL,
264                 .enum_list      = NULL,
265                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD,
266         },
267         {
268                 .label          = "bind interfaces only",
269                 .type           = P_BOOL,
270                 .p_class        = P_GLOBAL,
271                 .offset         = GLOBAL_VAR(bBindInterfacesOnly),
272                 .special        = NULL,
273                 .enum_list      = NULL,
274                 .flags          = FLAG_ADVANCED | FLAG_WIZARD,
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         {
286                 .label          = "security",
287                 .type           = P_ENUM,
288                 .p_class        = P_GLOBAL,
289                 .offset         = GLOBAL_VAR(security),
290                 .special        = NULL,
291                 .enum_list      = enum_security
292         },
293         {
294                 .label          = "encrypt passwords",
295                 .type           = P_BOOL,
296                 .p_class        = P_GLOBAL,
297                 .offset         = GLOBAL_VAR(bEncryptPasswords),
298                 .special        = NULL,
299                 .enum_list      = NULL
300         },
301         {
302                 .label          = "null passwords",
303                 .type           = P_BOOL,
304                 .p_class        = P_GLOBAL,
305                 .offset         = GLOBAL_VAR(bNullPasswords),
306                 .special        = NULL,
307                 .enum_list      = NULL,
308                 .flags          = FLAG_ADVANCED | FLAG_DEPRECATED,
309         },
310         {
311                 .label          = "obey pam restrictions",
312                 .type           = P_BOOL,
313                 .p_class        = P_GLOBAL,
314                 .offset         = GLOBAL_VAR(bObeyPamRestrictions),
315                 .special        = NULL,
316                 .enum_list      = NULL,
317                 .flags          = FLAG_ADVANCED,
318         },
319         {
320                 .label          = "password server",
321                 .type           = P_STRING,
322                 .p_class        = P_GLOBAL,
323                 .offset         = GLOBAL_VAR(szPasswordServer),
324                 .special        = NULL,
325                 .enum_list      = NULL
326         },
327         {
328                 .label          = "private dir",
329                 .type           = P_STRING,
330                 .p_class        = P_GLOBAL,
331                 .offset         = GLOBAL_VAR(szPrivateDir),
332                 .special        = NULL,
333                 .enum_list      = NULL
334         },
335         {
336                 .label          = "passwd chat",
337                 .type           = P_STRING,
338                 .p_class        = P_GLOBAL,
339                 .offset         = GLOBAL_VAR(szPasswdChat),
340                 .special        = NULL,
341                 .enum_list      = NULL
342         },
343         {
344                 .label          = "password level",
345                 .type           = P_INTEGER,
346                 .p_class        = P_GLOBAL,
347                 .offset         = GLOBAL_VAR(pwordlevel),
348                 .special        = NULL,
349                 .enum_list      = NULL
350         },
351         {
352                 .label          = "lanman auth",
353                 .type           = P_BOOL,
354                 .p_class        = P_GLOBAL,
355                 .offset         = GLOBAL_VAR(bLanmanAuth),
356                 .special        = NULL,
357                 .enum_list      = NULL,
358                 .flags          = FLAG_ADVANCED,
359         },
360         {
361                 .label          = "ntlm auth",
362                 .type           = P_BOOL,
363                 .p_class        = P_GLOBAL,
364                 .offset         = GLOBAL_VAR(bNTLMAuth),
365                 .special        = NULL,
366                 .enum_list      = NULL,
367                 .flags          = FLAG_ADVANCED,
368         },
369         {
370                 .label          = "client NTLMv2 auth",
371                 .type           = P_BOOL,
372                 .p_class        = P_GLOBAL,
373                 .offset         = GLOBAL_VAR(bClientNTLMv2Auth),
374                 .special        = NULL,
375                 .enum_list      = NULL,
376                 .flags          = FLAG_ADVANCED,
377         },
378         {
379                 .label          = "client lanman auth",
380                 .type           = P_BOOL,
381                 .p_class        = P_GLOBAL,
382                 .offset         = GLOBAL_VAR(bClientLanManAuth),
383                 .special        = NULL,
384                 .enum_list      = NULL,
385                 .flags          = FLAG_ADVANCED,
386         },
387         {
388                 .label          = "client plaintext auth",
389                 .type           = P_BOOL,
390                 .p_class        = P_GLOBAL,
391                 .offset         = GLOBAL_VAR(bClientPlaintextAuth),
392                 .special        = NULL,
393                 .enum_list      = NULL,
394                 .flags          = FLAG_ADVANCED,
395         },
396         {
397                 .label          = "client use spnego principal",
398                 .type           = P_BOOL,
399                 .p_class        = P_GLOBAL,
400                 .offset         = GLOBAL_VAR(client_use_spnego_principal),
401                 .special        = NULL,
402                 .enum_list      = NULL
403         },
404
405         {
406                 .label          = "read only",
407                 .type           = P_BOOL,
408                 .p_class        = P_LOCAL,
409                 .offset         = LOCAL_VAR(bRead_only),
410                 .special        = NULL,
411                 .enum_list      = NULL
412         },
413
414         {
415                 .label          = "create mask",
416                 .type           = P_OCTAL,
417                 .p_class        = P_LOCAL,
418                 .offset         = LOCAL_VAR(iCreate_mask),
419                 .special        = NULL,
420                 .enum_list      = NULL
421         },
422         {
423                 .label          = "force create mode",
424                 .type           = P_OCTAL,
425                 .p_class        = P_LOCAL,
426                 .offset         = LOCAL_VAR(iCreate_force_mode),
427                 .special        = NULL,
428                 .enum_list      = NULL
429         },
430         {
431                 .label          = "directory mask",
432                 .type           = P_OCTAL,
433                 .p_class        = P_LOCAL,
434                 .offset         = LOCAL_VAR(iDir_mask),
435                 .special        = NULL,
436                 .enum_list      = NULL
437         },
438         {
439                 .label          = "force directory mode",
440                 .type           = P_OCTAL,
441                 .p_class        = P_LOCAL,
442                 .offset         = LOCAL_VAR(iDir_force_mode),
443                 .special        = NULL,
444                 .enum_list      = NULL
445         },
446
447         {
448                 .label          = "hosts allow",
449                 .type           = P_LIST,
450                 .p_class        = P_LOCAL,
451                 .offset         = LOCAL_VAR(szHostsallow),
452                 .special        = NULL,
453                 .enum_list      = NULL
454         },
455         {
456                 .label          = "hosts deny",
457                 .type           = P_LIST,
458                 .p_class        = P_LOCAL,
459                 .offset         = LOCAL_VAR(szHostsdeny),
460                 .special        = NULL,
461                 .enum_list      = NULL
462         },
463
464         {
465                 .label          = "log level",
466                 .type           = P_STRING,
467                 .p_class        = P_GLOBAL,
468                 .offset         = GLOBAL_VAR(loglevel),
469                 .special        = handle_debuglevel,
470                 .enum_list      = NULL
471         },
472         {
473                 .label          = "debuglevel",
474                 .type           = P_STRING,
475                 .p_class        = P_GLOBAL,
476                 .offset         = GLOBAL_VAR(loglevel),
477                 .special        = handle_debuglevel,
478                 .enum_list      = NULL
479         },
480         {
481                 .label          = "log file",
482                 .type           = P_STRING,
483                 .p_class        = P_GLOBAL,
484                 .offset         = GLOBAL_VAR(logfile),
485                 .special        = handle_logfile,
486                 .enum_list      = NULL,
487                 .flags          = FLAG_ADVANCED,
488         },
489
490         {
491                 .label          = "smb ports",
492                 .type           = P_LIST,
493                 .p_class        = P_GLOBAL,
494                 .offset         = GLOBAL_VAR(smb_ports),
495                 .special        = NULL,
496                 .enum_list      = NULL
497         },
498         {
499                 .label          = "nbt port",
500                 .type           = P_INTEGER,
501                 .p_class        = P_GLOBAL,
502                 .offset         = GLOBAL_VAR(nbt_port),
503                 .special        = NULL,
504                 .enum_list      = NULL
505         },
506         {
507                 .label          = "dgram port",
508                 .type           = P_INTEGER,
509                 .p_class        = P_GLOBAL,
510                 .offset         = GLOBAL_VAR(dgram_port),
511                 .special        = NULL,
512                 .enum_list      = NULL
513         },
514         {
515                 .label          = "cldap port",
516                 .type           = P_INTEGER,
517                 .p_class        = P_GLOBAL,
518                 .offset         = GLOBAL_VAR(cldap_port),
519                 .special        = NULL,
520                 .enum_list      = NULL
521         },
522         {
523                 .label          = "krb5 port",
524                 .type           = P_INTEGER,
525                 .p_class        = P_GLOBAL,
526                 .offset         = GLOBAL_VAR(krb5_port),
527                 .special        = NULL,
528                 .enum_list      = NULL
529         },
530         {
531                 .label          = "kpasswd port",
532                 .type           = P_INTEGER,
533                 .p_class        = P_GLOBAL,
534                 .offset         = GLOBAL_VAR(kpasswd_port),
535                 .special        = NULL,
536                 .enum_list      = NULL
537         },
538         {
539                 .label          = "web port",
540                 .type           = P_INTEGER,
541                 .p_class        = P_GLOBAL,
542                 .offset         = GLOBAL_VAR(web_port),
543                 .special        = NULL,
544                 .enum_list      = NULL
545         },
546         {
547                 .label          = "large readwrite",
548                 .type           = P_BOOL,
549                 .p_class        = P_GLOBAL,
550                 .offset         = GLOBAL_VAR(bLargeReadwrite),
551                 .special        = NULL,
552                 .enum_list      = NULL,
553                 .flags          = FLAG_ADVANCED,
554         },
555         {
556                 .label          = "server max protocol",
557                 .type           = P_ENUM,
558                 .p_class        = P_GLOBAL,
559                 .offset         = GLOBAL_VAR(srv_maxprotocol),
560                 .special        = NULL,
561                 .enum_list      = enum_protocol,
562                 .flags          = FLAG_ADVANCED,
563         },
564         {
565                 .label          = "max protocol",
566                 .type           = P_ENUM,
567                 .p_class        = P_GLOBAL,
568                 .offset         = GLOBAL_VAR(srv_maxprotocol),
569                 .special        = NULL,
570                 .enum_list      = enum_protocol,
571                 .flags          = FLAG_ADVANCED,
572         },
573         {
574                 .label          = "protocol",
575                 .type           = P_ENUM,
576                 .p_class        = P_GLOBAL,
577                 .offset         = GLOBAL_VAR(srv_maxprotocol),
578                 .special        = NULL,
579                 .enum_list      = enum_protocol,
580                 .flags          = FLAG_ADVANCED,
581         },
582         {
583                 .label          = "server min protocol",
584                 .type           = P_ENUM,
585                 .p_class        = P_GLOBAL,
586                 .offset         = GLOBAL_VAR(srv_minprotocol),
587                 .special        = NULL,
588                 .enum_list      = enum_protocol,
589                 .flags          = FLAG_ADVANCED,
590         },
591         {
592                 .label          = "min protocol",
593                 .type           = P_ENUM,
594                 .p_class        = P_GLOBAL,
595                 .offset         = GLOBAL_VAR(srv_minprotocol),
596                 .special        = NULL,
597                 .enum_list      = enum_protocol,
598                 .flags          = FLAG_ADVANCED,
599         },
600         {
601                 .label          = "client max protocol",
602                 .type           = P_ENUM,
603                 .p_class        = P_GLOBAL,
604                 .offset         = GLOBAL_VAR(cli_maxprotocol),
605                 .special        = NULL,
606                 .enum_list      = enum_protocol
607         },
608         {
609                 .label          = "client min protocol",
610                 .type           = P_ENUM,
611                 .p_class        = P_GLOBAL,
612                 .offset         = GLOBAL_VAR(cli_minprotocol),
613                 .special        = NULL,
614                 .enum_list      = enum_protocol
615         },
616         {
617                 .label          = "unicode",
618                 .type           = P_BOOL,
619                 .p_class        = P_GLOBAL,
620                 .offset         = GLOBAL_VAR(bUnicode),
621                 .special        = NULL,
622                 .enum_list      = NULL
623         },
624         {
625                 .label          = "read raw",
626                 .type           = P_BOOL,
627                 .p_class        = P_GLOBAL,
628                 .offset         = GLOBAL_VAR(bReadRaw),
629                 .special        = NULL,
630                 .enum_list      = NULL
631         },
632         {
633                 .label          = "write raw",
634                 .type           = P_BOOL,
635                 .p_class        = P_GLOBAL,
636                 .offset         = GLOBAL_VAR(bWriteRaw),
637                 .special        = NULL,
638                 .enum_list      = NULL
639         },
640         {
641                 .label          = "disable netbios",
642                 .type           = P_BOOL,
643                 .p_class        = P_GLOBAL,
644                 .offset         = GLOBAL_VAR(bDisableNetbios),
645                 .special        = NULL,
646                 .enum_list      = NULL
647         },
648
649         {
650                 .label          = "nt status support",
651                 .type           = P_BOOL,
652                 .p_class        = P_GLOBAL,
653                 .offset         = GLOBAL_VAR(bNTStatusSupport),
654                 .special        = NULL,
655                 .enum_list      = NULL
656         },
657
658         {
659                 .label          = "max mux",
660                 .type           = P_INTEGER,
661                 .p_class        = P_GLOBAL,
662                 .offset         = GLOBAL_VAR(max_mux),
663                 .special        = NULL,
664                 .enum_list      = NULL,
665                 .flags          = FLAG_ADVANCED,
666         },
667         {
668                 .label          = "max xmit",
669                 .type           = P_BYTES,
670                 .p_class        = P_GLOBAL,
671                 .offset         = GLOBAL_VAR(max_xmit),
672                 .special        = NULL,
673                 .enum_list      = NULL,
674                 .flags          = FLAG_ADVANCED,
675         },
676
677         {
678                 .label          = "name resolve order",
679                 .type           = P_LIST,
680                 .p_class        = P_GLOBAL,
681                 .offset         = GLOBAL_VAR(szNameResolveOrder),
682                 .special        = NULL,
683                 .enum_list      = NULL
684         },
685         {
686                 .label          = "max wins ttl",
687                 .type           = P_INTEGER,
688                 .p_class        = P_GLOBAL,
689                 .offset         = GLOBAL_VAR(max_wins_ttl),
690                 .special        = NULL,
691                 .enum_list      = NULL,
692                 .flags          = FLAG_ADVANCED,
693         },
694         {
695                 .label          = "min wins ttl",
696                 .type           = P_INTEGER,
697                 .p_class        = P_GLOBAL,
698                 .offset         = GLOBAL_VAR(min_wins_ttl),
699                 .special        = NULL,
700                 .enum_list      = NULL,
701                 .flags          = FLAG_ADVANCED,
702         },
703         {
704                 .label          = "time server",
705                 .type           = P_BOOL,
706                 .p_class        = P_GLOBAL,
707                 .offset         = GLOBAL_VAR(bTimeServer),
708                 .special        = NULL,
709                 .enum_list      = NULL,
710                 .flags          = FLAG_ADVANCED,
711         },
712         {
713                 .label          = "unix extensions",
714                 .type           = P_BOOL,
715                 .p_class        = P_GLOBAL,
716                 .offset         = GLOBAL_VAR(bUnixExtensions),
717                 .special        = NULL,
718                 .enum_list      = NULL,
719                 .flags          = FLAG_ADVANCED,
720         },
721         {
722                 .label          = "use spnego",
723                 .type           = P_BOOL,
724                 .p_class        = P_GLOBAL,
725                 .offset         = GLOBAL_VAR(bUseSpnego),
726                 .special        = NULL,
727                 .enum_list      = NULL
728         },
729         {
730                 .label          = "server signing",
731                 .type           = P_ENUM,
732                 .p_class        = P_GLOBAL,
733                 .offset         = GLOBAL_VAR(server_signing),
734                 .special        = NULL,
735                 .enum_list      = enum_smb_signing_vals,
736                 .flags          = FLAG_ADVANCED,
737         },
738         {
739                 .label          = "client signing",
740                 .type           = P_ENUM,
741                 .p_class        = P_GLOBAL,
742                 .offset         = GLOBAL_VAR(client_signing),
743                 .special        = NULL,
744                 .enum_list      = enum_smb_signing_vals
745         },
746         {
747                 .label          = "rpc big endian",
748                 .type           = P_BOOL,
749                 .p_class        = P_GLOBAL,
750                 .offset         = GLOBAL_VAR(bRpcBigEndian),
751                 .special        = NULL,
752                 .enum_list      = NULL
753         },
754
755         {
756                 .label          = "max connections",
757                 .type           = P_INTEGER,
758                 .p_class        = P_LOCAL,
759                 .offset         = LOCAL_VAR(iMaxConnections),
760                 .special        = NULL,
761                 .enum_list      = NULL,
762                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
763         },
764         {
765                 .label          = "paranoid server security",
766                 .type           = P_BOOL,
767                 .p_class        = P_GLOBAL,
768                 .offset         = GLOBAL_VAR(paranoid_server_security),
769                 .special        = NULL,
770                 .enum_list      = NULL
771         },
772         {
773                 .label          = "socket options",
774                 .type           = P_STRING,
775                 .p_class        = P_GLOBAL,
776                 .offset         = GLOBAL_VAR(socket_options),
777                 .special        = NULL,
778                 .enum_list      = NULL
779         },
780
781         {
782                 .label          = "strict sync",
783                 .type           = P_BOOL,
784                 .p_class        = P_LOCAL,
785                 .offset         = LOCAL_VAR(bStrictSync),
786                 .special        = NULL,
787                 .enum_list      = NULL
788         },
789         {
790                 .label          = "use mmap",
791                 .type           = P_BOOL,
792                 .p_class        = P_GLOBAL,
793                 .offset         = GLOBAL_VAR(bUseMmap),
794                 .special        = NULL,
795                 .enum_list      = NULL,
796                 .flags          = FLAG_ADVANCED,
797         },
798
799         {
800                 .label          = "max print jobs",
801                 .type           = P_INTEGER,
802                 .p_class        = P_LOCAL,
803                 .offset         = LOCAL_VAR(iMaxPrintJobs),
804                 .special        = NULL,
805                 .enum_list      = NULL
806         },
807         {
808                 .label          = "printable",
809                 .type           = P_BOOL,
810                 .p_class        = P_LOCAL,
811                 .offset         = LOCAL_VAR(bPrint_ok),
812                 .special        = NULL,
813                 .enum_list      = NULL
814         },
815         {
816                 .label          = "print ok",
817                 .type           = P_BOOL,
818                 .p_class        = P_LOCAL,
819                 .offset         = LOCAL_VAR(bPrint_ok),
820                 .special        = NULL,
821                 .enum_list      = NULL
822         },
823
824         {
825                 .label          = "printer name",
826                 .type           = P_STRING,
827                 .p_class        = P_LOCAL,
828                 .offset         = LOCAL_VAR(szPrintername),
829                 .special        = NULL,
830                 .enum_list      = NULL,
831                 .flags          = FLAG_ADVANCED | FLAG_PRINT,
832         },
833         {
834                 .label          = "printer",
835                 .type           = P_STRING,
836                 .p_class        = P_LOCAL,
837                 .offset         = LOCAL_VAR(szPrintername),
838                 .special        = NULL,
839                 .enum_list      = NULL,
840                 .flags          = FLAG_HIDE,
841         },
842
843         {
844                 .label          = "map system",
845                 .type           = P_BOOL,
846                 .p_class        = P_LOCAL,
847                 .offset         = LOCAL_VAR(bMap_system),
848                 .special        = NULL,
849                 .enum_list      = NULL
850         },
851         {
852                 .label          = "map hidden",
853                 .type           = P_BOOL,
854                 .p_class        = P_LOCAL,
855                 .offset         = LOCAL_VAR(bMap_hidden),
856                 .special        = NULL,
857                 .enum_list      = NULL
858         },
859         {
860                 .label          = "map archive",
861                 .type           = P_BOOL,
862                 .p_class        = P_LOCAL,
863                 .offset         = LOCAL_VAR(bMap_archive),
864                 .special        = NULL,
865                 .enum_list      = NULL
866         },
867
868         {
869                 .label          = "preferred master",
870                 .type           = P_ENUM,
871                 .p_class        = P_GLOBAL,
872                 .offset         = GLOBAL_VAR(bPreferredMaster),
873                 .special        = NULL,
874                 .enum_list      = enum_bool_auto,
875                 .flags          = FLAG_BASIC | FLAG_ADVANCED,
876         },
877         {
878                 .label          = "prefered master",
879                 .type           = P_ENUM,
880                 .p_class        = P_GLOBAL,
881                 .offset         = GLOBAL_VAR(bPreferredMaster),
882                 .special        = NULL,
883                 .enum_list      = enum_bool_auto,
884                 .flags          = FLAG_HIDE,
885         },
886         {
887                 .label          = "local master",
888                 .type           = P_BOOL,
889                 .p_class        = P_GLOBAL,
890                 .offset         = GLOBAL_VAR(bLocalMaster),
891                 .special        = NULL,
892                 .enum_list      = NULL
893         },
894         {
895                 .label          = "browseable",
896                 .type           = P_BOOL,
897                 .p_class        = P_LOCAL,
898                 .offset         = LOCAL_VAR(bBrowseable),
899                 .special        = NULL,
900                 .enum_list      = NULL,
901                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
902         },
903         {
904                 .label          = "browsable",
905                 .type           = P_BOOL,
906                 .p_class        = P_LOCAL,
907                 .offset         = LOCAL_VAR(bBrowseable),
908                 .special        = NULL,
909                 .enum_list      = NULL
910         },
911
912         {N_("WINS Options"), P_SEP, P_SEPARATOR},
913
914         {
915                 .label          = "dns proxy",
916                 .type           = P_BOOL,
917                 .p_class        = P_GLOBAL,
918                 .offset         = GLOBAL_VAR(bWINSdnsProxy),
919                 .special        = NULL,
920                 .enum_list      = NULL,
921                 .flags          = FLAG_ADVANCED,
922         },
923         {
924                 .label          = "wins proxy",
925                 .type           = P_BOOL,
926                 .p_class        = P_GLOBAL,
927                 .offset         = GLOBAL_VAR(bWINSproxy),
928                 .special        = NULL,
929                 .enum_list      = NULL,
930                 .flags          = FLAG_ADVANCED,
931         },
932         {
933                 .label          = "wins server",
934                 .type           = P_LIST,
935                 .p_class        = P_GLOBAL,
936                 .offset         = GLOBAL_VAR(szWINSservers),
937                 .special        = NULL,
938                 .enum_list      = NULL,
939                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD,
940         },
941         {
942                 .label          = "wins support",
943                 .type           = P_BOOL,
944                 .p_class        = P_GLOBAL,
945                 .offset         = GLOBAL_VAR(bWINSsupport),
946                 .special        = NULL,
947                 .enum_list      = NULL,
948                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD,
949         },
950         {
951                 .label          = "wins hook",
952                 .type           = P_STRING,
953                 .p_class        = P_GLOBAL,
954                 .offset         = GLOBAL_VAR(szWINSHook),
955                 .special        = NULL,
956                 .enum_list      = NULL,
957                 .flags          = FLAG_ADVANCED,
958         },
959
960         {N_("Locking Options"), P_SEP, P_SEPARATOR},
961
962         {
963                 .label          = "blocking locks",
964                 .type           = P_BOOL,
965                 .p_class        = P_LOCAL,
966                 .offset         = LOCAL_VAR(bBlockingLocks),
967                 .special        = NULL,
968                 .enum_list      = NULL,
969                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
970         },
971         {
972                 .label          = "csc policy",
973                 .type           = P_ENUM,
974                 .p_class        = P_LOCAL,
975                 .offset         = LOCAL_VAR(iCSCPolicy),
976                 .special        = NULL,
977                 .enum_list      = enum_csc_policy,
978                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
979         },
980         {
981                 .label          = "fake oplocks",
982                 .type           = P_BOOL,
983                 .p_class        = P_LOCAL,
984                 .offset         = LOCAL_VAR(bFakeOplocks),
985                 .special        = NULL,
986                 .enum_list      = NULL,
987                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
988         },
989         {
990                 .label          = "kernel oplocks",
991                 .type           = P_BOOL,
992                 .p_class        = P_LOCAL,
993                 .offset         = LOCAL_VAR(bKernelOplocks),
994                 .special        = NULL,
995                 .enum_list      = NULL,
996                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
997         },
998         {
999                 .label          = "locking",
1000                 .type           = P_BOOL,
1001                 .p_class        = P_LOCAL,
1002                 .offset         = LOCAL_VAR(bLocking),
1003                 .special        = NULL,
1004                 .enum_list      = NULL,
1005                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
1006         },
1007         {
1008                 .label          = "lock spin time",
1009                 .type           = P_INTEGER,
1010                 .p_class        = P_GLOBAL,
1011                 .offset         = GLOBAL_VAR(iLockSpinTime),
1012                 .special        = NULL,
1013                 .enum_list      = NULL,
1014                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
1015         },
1016         {
1017                 .label          = "oplocks",
1018                 .type           = P_BOOL,
1019                 .p_class        = P_LOCAL,
1020                 .offset         = LOCAL_VAR(bOpLocks),
1021                 .special        = NULL,
1022                 .enum_list      = NULL,
1023                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
1024         },
1025         {
1026                 .label          = "level2 oplocks",
1027                 .type           = P_BOOL,
1028                 .p_class        = P_LOCAL,
1029                 .offset         = LOCAL_VAR(bLevel2OpLocks),
1030                 .special        = NULL,
1031                 .enum_list      = NULL,
1032                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
1033         },
1034         {
1035                 .label          = "oplock break wait time",
1036                 .type           = P_INTEGER,
1037                 .p_class        = P_GLOBAL,
1038                 .offset         = GLOBAL_VAR(oplock_break_wait_time),
1039                 .special        = NULL,
1040                 .enum_list      = NULL,
1041                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
1042         },
1043         {
1044                 .label          = "oplock contention limit",
1045                 .type           = P_INTEGER,
1046                 .p_class        = P_LOCAL,
1047                 .offset         = LOCAL_VAR(iOplockContentionLimit),
1048                 .special        = NULL,
1049                 .enum_list      = NULL,
1050                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
1051         },
1052         {
1053                 .label          = "posix locking",
1054                 .type           = P_BOOL,
1055                 .p_class        = P_LOCAL,
1056                 .offset         = LOCAL_VAR(bPosixLocking),
1057                 .special        = NULL,
1058                 .enum_list      = NULL,
1059                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
1060         },
1061         {
1062                 .label          = "strict locking",
1063                 .type           = P_ENUM,
1064                 .p_class        = P_LOCAL,
1065                 .offset         = LOCAL_VAR(iStrictLocking),
1066                 .special        = NULL,
1067                 .enum_list      = enum_bool_auto,
1068                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
1069         },
1070
1071         {N_("Ldap Options"), P_SEP, P_SEPARATOR},
1072
1073         {
1074                 .label          = "ldap admin dn",
1075                 .type           = P_STRING,
1076                 .p_class        = P_GLOBAL,
1077                 .offset         = GLOBAL_VAR(szLdapAdminDn),
1078                 .special        = NULL,
1079                 .enum_list      = NULL,
1080                 .flags          = FLAG_ADVANCED,
1081         },
1082         {
1083                 .label          = "ldap delete dn",
1084                 .type           = P_BOOL,
1085                 .p_class        = P_GLOBAL,
1086                 .offset         = GLOBAL_VAR(ldap_delete_dn),
1087                 .special        = NULL,
1088                 .enum_list      = NULL,
1089                 .flags          = FLAG_ADVANCED,
1090         },
1091         {
1092                 .label          = "ldap group suffix",
1093                 .type           = P_STRING,
1094                 .p_class        = P_GLOBAL,
1095                 .offset         = GLOBAL_VAR(szLdapGroupSuffix),
1096                 .special        = NULL,
1097                 .enum_list      = NULL,
1098                 .flags          = FLAG_ADVANCED,
1099         },
1100         {
1101                 .label          = "ldap idmap suffix",
1102                 .type           = P_STRING,
1103                 .p_class        = P_GLOBAL,
1104                 .offset         = GLOBAL_VAR(szLdapIdmapSuffix),
1105                 .special        = NULL,
1106                 .enum_list      = NULL,
1107                 .flags          = FLAG_ADVANCED,
1108         },
1109         {
1110                 .label          = "ldap machine suffix",
1111                 .type           = P_STRING,
1112                 .p_class        = P_GLOBAL,
1113                 .offset         = GLOBAL_VAR(szLdapMachineSuffix),
1114                 .special        = NULL,
1115                 .enum_list      = NULL,
1116                 .flags          = FLAG_ADVANCED,
1117         },
1118         {
1119                 .label          = "ldap passwd sync",
1120                 .type           = P_ENUM,
1121                 .p_class        = P_GLOBAL,
1122                 .offset         = GLOBAL_VAR(ldap_passwd_sync),
1123                 .special        = NULL,
1124                 .enum_list      = enum_ldap_passwd_sync,
1125                 .flags          = FLAG_ADVANCED,
1126         },
1127         {
1128                 .label          = "ldap password sync",
1129                 .type           = P_ENUM,
1130                 .p_class        = P_GLOBAL,
1131                 .offset         = GLOBAL_VAR(ldap_passwd_sync),
1132                 .special        = NULL,
1133                 .enum_list      = enum_ldap_passwd_sync,
1134                 .flags          = FLAG_HIDE,
1135         },
1136         {
1137                 .label          = "ldap replication sleep",
1138                 .type           = P_INTEGER,
1139                 .p_class        = P_GLOBAL,
1140                 .offset         = GLOBAL_VAR(ldap_replication_sleep),
1141                 .special        = NULL,
1142                 .enum_list      = NULL,
1143                 .flags          = FLAG_ADVANCED,
1144         },
1145         {
1146                 .label          = "ldap suffix",
1147                 .type           = P_STRING,
1148                 .p_class        = P_GLOBAL,
1149                 .offset         = GLOBAL_VAR(szLdapSuffix),
1150                 .special        = NULL,
1151                 .enum_list      = NULL,
1152                 .flags          = FLAG_ADVANCED,
1153         },
1154         {
1155                 .label          = "ldap ssl",
1156                 .type           = P_ENUM,
1157                 .p_class        = P_GLOBAL,
1158                 .offset         = GLOBAL_VAR(ldap_ssl),
1159                 .special        = NULL,
1160                 .enum_list      = enum_ldap_ssl,
1161                 .flags          = FLAG_ADVANCED,
1162         },
1163         {
1164                 .label          = "ldap ssl ads",
1165                 .type           = P_BOOL,
1166                 .p_class        = P_GLOBAL,
1167                 .offset         = GLOBAL_VAR(ldap_ssl_ads),
1168                 .special        = NULL,
1169                 .enum_list      = NULL,
1170                 .flags          = FLAG_ADVANCED,
1171         },
1172         {
1173                 .label          = "ldap deref",
1174                 .type           = P_ENUM,
1175                 .p_class        = P_GLOBAL,
1176                 .offset         = GLOBAL_VAR(ldap_deref),
1177                 .special        = NULL,
1178                 .enum_list      = enum_ldap_deref,
1179                 .flags          = FLAG_ADVANCED,
1180         },
1181         {
1182                 .label          = "ldap follow referral",
1183                 .type           = P_ENUM,
1184                 .p_class        = P_GLOBAL,
1185                 .offset         = GLOBAL_VAR(ldap_follow_referral),
1186                 .special        = NULL,
1187                 .enum_list      = enum_bool_auto,
1188                 .flags          = FLAG_ADVANCED,
1189         },
1190         {
1191                 .label          = "ldap timeout",
1192                 .type           = P_INTEGER,
1193                 .p_class        = P_GLOBAL,
1194                 .offset         = GLOBAL_VAR(ldap_timeout),
1195                 .special        = NULL,
1196                 .enum_list      = NULL,
1197                 .flags          = FLAG_ADVANCED,
1198         },
1199         {
1200                 .label          = "ldap connection timeout",
1201                 .type           = P_INTEGER,
1202                 .p_class        = P_GLOBAL,
1203                 .offset         = GLOBAL_VAR(ldap_connection_timeout),
1204                 .special        = NULL,
1205                 .enum_list      = NULL,
1206                 .flags          = FLAG_ADVANCED,
1207         },
1208         {
1209                 .label          = "ldap page size",
1210                 .type           = P_INTEGER,
1211                 .p_class        = P_GLOBAL,
1212                 .offset         = GLOBAL_VAR(ldap_page_size),
1213                 .special        = NULL,
1214                 .enum_list      = NULL,
1215                 .flags          = FLAG_ADVANCED,
1216         },
1217         {
1218                 .label          = "ldap user suffix",
1219                 .type           = P_STRING,
1220                 .p_class        = P_GLOBAL,
1221                 .offset         = GLOBAL_VAR(szLdapUserSuffix),
1222                 .special        = NULL,
1223                 .enum_list      = NULL,
1224                 .flags          = FLAG_ADVANCED,
1225         },
1226         {
1227                 .label          = "ldap debug level",
1228                 .type           = P_INTEGER,
1229                 .p_class        = P_GLOBAL,
1230                 .offset         = GLOBAL_VAR(ldap_debug_level),
1231                 .special        = handle_ldap_debug_level,
1232                 .enum_list      = NULL,
1233                 .flags          = FLAG_ADVANCED,
1234         },
1235         {
1236                 .label          = "ldap debug threshold",
1237                 .type           = P_INTEGER,
1238                 .p_class        = P_GLOBAL,
1239                 .offset         = GLOBAL_VAR(ldap_debug_threshold),
1240                 .special        = NULL,
1241                 .enum_list      = NULL,
1242                 .flags          = FLAG_ADVANCED,
1243         },
1244
1245         {N_("EventLog Options"), P_SEP, P_SEPARATOR},
1246
1247         {
1248                 .label          = "eventlog list",
1249                 .type           = P_LIST,
1250                 .p_class        = P_GLOBAL,
1251                 .offset         = GLOBAL_VAR(szEventLogs),
1252                 .special        = NULL,
1253                 .enum_list      = NULL,
1254                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1255         },
1256
1257         {N_("Miscellaneous Options"), P_SEP, P_SEPARATOR},
1258
1259         {
1260                 .label          = "add share command",
1261                 .type           = P_STRING,
1262                 .p_class        = P_GLOBAL,
1263                 .offset         = GLOBAL_VAR(szAddShareCommand),
1264                 .special        = NULL,
1265                 .enum_list      = NULL,
1266                 .flags          = FLAG_ADVANCED,
1267         },
1268         {
1269                 .label          = "change share command",
1270                 .type           = P_STRING,
1271                 .p_class        = P_GLOBAL,
1272                 .offset         = GLOBAL_VAR(szChangeShareCommand),
1273                 .special        = NULL,
1274                 .enum_list      = NULL,
1275                 .flags          = FLAG_ADVANCED,
1276         },
1277         {
1278                 .label          = "delete share command",
1279                 .type           = P_STRING,
1280                 .p_class        = P_GLOBAL,
1281                 .offset         = GLOBAL_VAR(szDeleteShareCommand),
1282                 .special        = NULL,
1283                 .enum_list      = NULL,
1284                 .flags          = FLAG_ADVANCED,
1285         },
1286         {
1287                 .label          = "config file",
1288                 .type           = P_STRING,
1289                 .p_class        = P_GLOBAL,
1290                 .offset         = GLOBAL_VAR(szConfigFile),
1291                 .special        = NULL,
1292                 .enum_list      = NULL,
1293                 .flags          = FLAG_HIDE|FLAG_META,
1294         },
1295         {
1296                 .label          = "preload",
1297                 .type           = P_STRING,
1298                 .p_class        = P_GLOBAL,
1299                 .offset         = GLOBAL_VAR(szAutoServices),
1300                 .special        = NULL,
1301                 .enum_list      = NULL,
1302                 .flags          = FLAG_ADVANCED,
1303         },
1304         {
1305                 .label          = "auto services",
1306                 .type           = P_STRING,
1307                 .p_class        = P_GLOBAL,
1308                 .offset         = GLOBAL_VAR(szAutoServices),
1309                 .special        = NULL,
1310                 .enum_list      = NULL,
1311                 .flags          = FLAG_ADVANCED,
1312         },
1313         {
1314                 .label          = "lock directory",
1315                 .type           = P_STRING,
1316                 .p_class        = P_GLOBAL,
1317                 .offset         = GLOBAL_VAR(szLockDir),
1318                 .special        = NULL,
1319                 .enum_list      = NULL,
1320                 .flags          = FLAG_ADVANCED,
1321         },
1322         {
1323                 .label          = "lock dir",
1324                 .type           = P_STRING,
1325                 .p_class        = P_GLOBAL,
1326                 .offset         = GLOBAL_VAR(szLockDir),
1327                 .special        = NULL,
1328                 .enum_list      = NULL,
1329                 .flags          = FLAG_HIDE,
1330         },
1331         {
1332                 .label          = "state directory",
1333                 .type           = P_STRING,
1334                 .p_class        = P_GLOBAL,
1335                 .offset         = GLOBAL_VAR(szStateDir),
1336                 .special        = NULL,
1337                 .enum_list      = NULL,
1338                 .flags          = FLAG_ADVANCED,
1339         },
1340         {
1341                 .label          = "cache directory",
1342                 .type           = P_STRING,
1343                 .p_class        = P_GLOBAL,
1344                 .offset         = GLOBAL_VAR(szCacheDir),
1345                 .special        = NULL,
1346                 .enum_list      = NULL,
1347                 .flags          = FLAG_ADVANCED,
1348         },
1349         {
1350                 .label          = "pid directory",
1351                 .type           = P_STRING,
1352                 .p_class        = P_GLOBAL,
1353                 .offset         = GLOBAL_VAR(szPidDir),
1354                 .special        = NULL,
1355                 .enum_list      = NULL,
1356                 .flags          = FLAG_ADVANCED,
1357         },
1358         {
1359                 .label          = "ntp signd socket directory",
1360                 .type           = P_STRING,
1361                 .p_class        = P_GLOBAL,
1362                 .offset         = GLOBAL_VAR(szNTPSignDSocketDirectory),
1363                 .special        = NULL,
1364                 .enum_list      = NULL,
1365                 .flags          = FLAG_ADVANCED,
1366         },
1367
1368 #ifdef WITH_UTMP
1369         {
1370                 .label          = "utmp directory",
1371                 .type           = P_STRING,
1372                 .p_class        = P_GLOBAL,
1373                 .offset         = GLOBAL_VAR(szUtmpDir),
1374                 .special        = NULL,
1375                 .enum_list      = NULL,
1376                 .flags          = FLAG_ADVANCED,
1377         },
1378         {
1379                 .label          = "wtmp directory",
1380                 .type           = P_STRING,
1381                 .p_class        = P_GLOBAL,
1382                 .offset         = GLOBAL_VAR(szWtmpDir),
1383                 .special        = NULL,
1384                 .enum_list      = NULL,
1385                 .flags          = FLAG_ADVANCED,
1386         },
1387         {
1388                 .label          = "utmp",
1389                 .type           = P_BOOL,
1390                 .p_class        = P_GLOBAL,
1391                 .offset         = GLOBAL_VAR(bUtmp),
1392                 .special        = NULL,
1393                 .enum_list      = NULL,
1394                 .flags          = FLAG_ADVANCED,
1395         },
1396 #endif
1397         {
1398                 .label          = "default service",
1399                 .type           = P_STRING,
1400                 .p_class        = P_GLOBAL,
1401                 .offset         = GLOBAL_VAR(szDefaultService),
1402                 .special        = NULL,
1403                 .enum_list      = NULL,
1404                 .flags          = FLAG_ADVANCED,
1405         },
1406         {
1407                 .label          = "default",
1408                 .type           = P_STRING,
1409                 .p_class        = P_GLOBAL,
1410                 .offset         = GLOBAL_VAR(szDefaultService),
1411                 .special        = NULL,
1412                 .enum_list      = NULL,
1413                 .flags          = FLAG_ADVANCED,
1414         },
1415         {
1416                 .label          = "message command",
1417                 .type           = P_STRING,
1418                 .p_class        = P_GLOBAL,
1419                 .offset         = GLOBAL_VAR(szMsgCommand),
1420                 .special        = NULL,
1421                 .enum_list      = NULL,
1422                 .flags          = FLAG_ADVANCED,
1423         },
1424         {
1425                 .label          = "dfree cache time",
1426                 .type           = P_INTEGER,
1427                 .p_class        = P_LOCAL,
1428                 .offset         = LOCAL_VAR(iDfreeCacheTime),
1429                 .special        = NULL,
1430                 .enum_list      = NULL,
1431                 .flags          = FLAG_ADVANCED,
1432         },
1433         {
1434                 .label          = "dfree command",
1435                 .type           = P_STRING,
1436                 .p_class        = P_LOCAL,
1437                 .offset         = LOCAL_VAR(szDfree),
1438                 .special        = NULL,
1439                 .enum_list      = NULL,
1440                 .flags          = FLAG_ADVANCED,
1441         },
1442         {
1443                 .label          = "get quota command",
1444                 .type           = P_STRING,
1445                 .p_class        = P_GLOBAL,
1446                 .offset         = GLOBAL_VAR(szGetQuota),
1447                 .special        = NULL,
1448                 .enum_list      = NULL,
1449                 .flags          = FLAG_ADVANCED,
1450         },
1451         {
1452                 .label          = "set quota command",
1453                 .type           = P_STRING,
1454                 .p_class        = P_GLOBAL,
1455                 .offset         = GLOBAL_VAR(szSetQuota),
1456                 .special        = NULL,
1457                 .enum_list      = NULL,
1458                 .flags          = FLAG_ADVANCED,
1459         },
1460         {
1461                 .label          = "remote announce",
1462                 .type           = P_STRING,
1463                 .p_class        = P_GLOBAL,
1464                 .offset         = GLOBAL_VAR(szRemoteAnnounce),
1465                 .special        = NULL,
1466                 .enum_list      = NULL,
1467                 .flags          = FLAG_ADVANCED,
1468         },
1469         {
1470                 .label          = "remote browse sync",
1471                 .type           = P_STRING,
1472                 .p_class        = P_GLOBAL,
1473                 .offset         = GLOBAL_VAR(szRemoteBrowseSync),
1474                 .special        = NULL,
1475                 .enum_list      = NULL,
1476                 .flags          = FLAG_ADVANCED,
1477         },
1478         {
1479                 .label          = "socket address",
1480                 .type           = P_STRING,
1481                 .p_class        = P_GLOBAL,
1482                 .offset         = GLOBAL_VAR(szSocketAddress),
1483                 .special        = NULL,
1484                 .enum_list      = NULL,
1485                 .flags          = FLAG_ADVANCED,
1486         },
1487         {
1488                 .label          = "nmbd bind explicit broadcast",
1489                 .type           = P_BOOL,
1490                 .p_class        = P_GLOBAL,
1491                 .offset         = GLOBAL_VAR(bNmbdBindExplicitBroadcast),
1492                 .special        = NULL,
1493                 .enum_list      = NULL,
1494                 .flags          = FLAG_ADVANCED,
1495         },
1496         {
1497                 .label          = "homedir map",
1498                 .type           = P_STRING,
1499                 .p_class        = P_GLOBAL,
1500                 .offset         = GLOBAL_VAR(szNISHomeMapName),
1501                 .special        = NULL,
1502                 .enum_list      = NULL,
1503                 .flags          = FLAG_ADVANCED,
1504         },
1505         {
1506                 .label          = "afs username map",
1507                 .type           = P_STRING,
1508                 .p_class        = P_GLOBAL,
1509                 .offset         = GLOBAL_VAR(szAfsUsernameMap),
1510                 .special        = NULL,
1511                 .enum_list      = NULL,
1512                 .flags          = FLAG_ADVANCED,
1513         },
1514         {
1515                 .label          = "afs token lifetime",
1516                 .type           = P_INTEGER,
1517                 .p_class        = P_GLOBAL,
1518                 .offset         = GLOBAL_VAR(iAfsTokenLifetime),
1519                 .special        = NULL,
1520                 .enum_list      = NULL,
1521                 .flags          = FLAG_ADVANCED,
1522         },
1523         {
1524                 .label          = "log nt token command",
1525                 .type           = P_STRING,
1526                 .p_class        = P_GLOBAL,
1527                 .offset         = GLOBAL_VAR(szLogNtTokenCommand),
1528                 .special        = NULL,
1529                 .enum_list      = NULL,
1530                 .flags          = FLAG_ADVANCED,
1531         },
1532         {
1533                 .label          = "NIS homedir",
1534                 .type           = P_BOOL,
1535                 .p_class        = P_GLOBAL,
1536                 .offset         = GLOBAL_VAR(bNISHomeMap),
1537                 .special        = NULL,
1538                 .enum_list      = NULL,
1539                 .flags          = FLAG_ADVANCED,
1540         },
1541         {
1542                 .label          = "-valid",
1543                 .type           = P_BOOL,
1544                 .p_class        = P_LOCAL,
1545                 .offset         = LOCAL_VAR(valid),
1546                 .special        = NULL,
1547                 .enum_list      = NULL,
1548                 .flags          = FLAG_HIDE,
1549         },
1550         {
1551                 .label          = "copy",
1552                 .type           = P_STRING,
1553                 .p_class        = P_LOCAL,
1554                 .offset         = LOCAL_VAR(szCopy),
1555                 .special        = handle_copy,
1556                 .enum_list      = NULL,
1557                 .flags          = FLAG_HIDE,
1558         },
1559         {
1560                 .label          = "include",
1561                 .type           = P_STRING,
1562                 .p_class        = P_LOCAL,
1563                 .offset         = LOCAL_VAR(szInclude),
1564                 .special        = handle_include,
1565                 .enum_list      = NULL,
1566                 .flags          = FLAG_HIDE|FLAG_META,
1567         },
1568         {
1569                 .label          = "preexec",
1570                 .type           = P_STRING,
1571                 .p_class        = P_LOCAL,
1572                 .offset         = LOCAL_VAR(szPreExec),
1573                 .special        = NULL,
1574                 .enum_list      = NULL,
1575                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
1576         },
1577         {
1578                 .label          = "exec",
1579                 .type           = P_STRING,
1580                 .p_class        = P_LOCAL,
1581                 .offset         = LOCAL_VAR(szPreExec),
1582                 .special        = NULL,
1583                 .enum_list      = NULL,
1584                 .flags          = FLAG_ADVANCED,
1585         },
1586         {
1587                 .label          = "preexec close",
1588                 .type           = P_BOOL,
1589                 .p_class        = P_LOCAL,
1590                 .offset         = LOCAL_VAR(bPreexecClose),
1591                 .special        = NULL,
1592                 .enum_list      = NULL,
1593                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
1594         },
1595         {
1596                 .label          = "postexec",
1597                 .type           = P_STRING,
1598                 .p_class        = P_LOCAL,
1599                 .offset         = LOCAL_VAR(szPostExec),
1600                 .special        = NULL,
1601                 .enum_list      = NULL,
1602                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
1603         },
1604         {
1605                 .label          = "root preexec",
1606                 .type           = P_STRING,
1607                 .p_class        = P_LOCAL,
1608                 .offset         = LOCAL_VAR(szRootPreExec),
1609                 .special        = NULL,
1610                 .enum_list      = NULL,
1611                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
1612         },
1613         {
1614                 .label          = "root preexec close",
1615                 .type           = P_BOOL,
1616                 .p_class        = P_LOCAL,
1617                 .offset         = LOCAL_VAR(bRootpreexecClose),
1618                 .special        = NULL,
1619                 .enum_list      = NULL,
1620                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
1621         },
1622         {
1623                 .label          = "root postexec",
1624                 .type           = P_STRING,
1625                 .p_class        = P_LOCAL,
1626                 .offset         = LOCAL_VAR(szRootPostExec),
1627                 .special        = NULL,
1628                 .enum_list      = NULL,
1629                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
1630         },
1631         {
1632                 .label          = "available",
1633                 .type           = P_BOOL,
1634                 .p_class        = P_LOCAL,
1635                 .offset         = LOCAL_VAR(bAvailable),
1636                 .special        = NULL,
1637                 .enum_list      = NULL,
1638                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
1639         },
1640         {
1641                 .label          = "registry shares",
1642                 .type           = P_BOOL,
1643                 .p_class        = P_GLOBAL,
1644                 .offset         = GLOBAL_VAR(bRegistryShares),
1645                 .special        = NULL,
1646                 .enum_list      = NULL,
1647                 .flags          = FLAG_ADVANCED,
1648         },
1649         {
1650                 .label          = "usershare allow guests",
1651                 .type           = P_BOOL,
1652                 .p_class        = P_GLOBAL,
1653                 .offset         = GLOBAL_VAR(bUsershareAllowGuests),
1654                 .special        = NULL,
1655                 .enum_list      = NULL,
1656                 .flags          = FLAG_ADVANCED,
1657         },
1658         {
1659                 .label          = "usershare max shares",
1660                 .type           = P_INTEGER,
1661                 .p_class        = P_GLOBAL,
1662                 .offset         = GLOBAL_VAR(iUsershareMaxShares),
1663                 .special        = NULL,
1664                 .enum_list      = NULL,
1665                 .flags          = FLAG_ADVANCED,
1666         },
1667         {
1668                 .label          = "usershare owner only",
1669                 .type           = P_BOOL,
1670                 .p_class        = P_GLOBAL,
1671                 .offset         = GLOBAL_VAR(bUsershareOwnerOnly),
1672                 .special        = NULL,
1673                 .enum_list      = NULL,
1674                 .flags          = FLAG_ADVANCED,
1675         },
1676         {
1677                 .label          = "usershare path",
1678                 .type           = P_STRING,
1679                 .p_class        = P_GLOBAL,
1680                 .offset         = GLOBAL_VAR(szUsersharePath),
1681                 .special        = NULL,
1682                 .enum_list      = NULL,
1683                 .flags          = FLAG_ADVANCED,
1684         },
1685         {
1686                 .label          = "usershare prefix allow list",
1687                 .type           = P_LIST,
1688                 .p_class        = P_GLOBAL,
1689                 .offset         = GLOBAL_VAR(szUsersharePrefixAllowList),
1690                 .special        = NULL,
1691                 .enum_list      = NULL,
1692                 .flags          = FLAG_ADVANCED,
1693         },
1694         {
1695                 .label          = "usershare prefix deny list",
1696                 .type           = P_LIST,
1697                 .p_class        = P_GLOBAL,
1698                 .offset         = GLOBAL_VAR(szUsersharePrefixDenyList),
1699                 .special        = NULL,
1700                 .enum_list      = NULL,
1701                 .flags          = FLAG_ADVANCED,
1702         },
1703         {
1704                 .label          = "usershare template share",
1705                 .type           = P_STRING,
1706                 .p_class        = P_GLOBAL,
1707                 .offset         = GLOBAL_VAR(szUsershareTemplateShare),
1708                 .special        = NULL,
1709                 .enum_list      = NULL,
1710                 .flags          = FLAG_ADVANCED,
1711         },
1712         {
1713                 .label          = "volume",
1714                 .type           = P_STRING,
1715                 .p_class        = P_LOCAL,
1716                 .offset         = LOCAL_VAR(volume),
1717                 .special        = NULL,
1718                 .enum_list      = NULL,
1719                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
1720         },
1721         {
1722                 .label          = "fstype",
1723                 .type           = P_STRING,
1724                 .p_class        = P_LOCAL,
1725                 .offset         = LOCAL_VAR(fstype),
1726                 .special        = NULL,
1727                 .enum_list      = NULL,
1728                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
1729         },
1730         {
1731                 .label          = "set directory",
1732                 .type           = P_BOOLREV,
1733                 .p_class        = P_LOCAL,
1734                 .offset         = LOCAL_VAR(bNo_set_dir),
1735                 .special        = NULL,
1736                 .enum_list      = NULL,
1737                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
1738         },
1739         {
1740                 .label          = "allow insecure wide links",
1741                 .type           = P_BOOL,
1742                 .p_class        = P_GLOBAL,
1743                 .offset         = GLOBAL_VAR(bAllowInsecureWidelinks),
1744                 .special        = NULL,
1745                 .enum_list      = NULL,
1746                 .flags          = FLAG_ADVANCED,
1747         },
1748         {
1749                 .label          = "wide links",
1750                 .type           = P_BOOL,
1751                 .p_class        = P_LOCAL,
1752                 .offset         = LOCAL_VAR(bWidelinks),
1753                 .special        = NULL,
1754                 .enum_list      = NULL,
1755                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
1756         },
1757         {
1758                 .label          = "follow symlinks",
1759                 .type           = P_BOOL,
1760                 .p_class        = P_LOCAL,
1761                 .offset         = LOCAL_VAR(bSymlinks),
1762                 .special        = NULL,
1763                 .enum_list      = NULL,
1764                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
1765         },
1766         {
1767                 .label          = "dont descend",
1768                 .type           = P_STRING,
1769                 .p_class        = P_LOCAL,
1770                 .offset         = LOCAL_VAR(szDontdescend),
1771                 .special        = NULL,
1772                 .enum_list      = NULL,
1773                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
1774         },
1775         {
1776                 .label          = "magic script",
1777                 .type           = P_STRING,
1778                 .p_class        = P_LOCAL,
1779                 .offset         = LOCAL_VAR(szMagicScript),
1780                 .special        = NULL,
1781                 .enum_list      = NULL,
1782                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
1783         },
1784         {
1785                 .label          = "magic output",
1786                 .type           = P_STRING,
1787                 .p_class        = P_LOCAL,
1788                 .offset         = LOCAL_VAR(szMagicOutput),
1789                 .special        = NULL,
1790                 .enum_list      = NULL,
1791                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
1792         },
1793         {
1794                 .label          = "delete readonly",
1795                 .type           = P_BOOL,
1796                 .p_class        = P_LOCAL,
1797                 .offset         = LOCAL_VAR(bDeleteReadonly),
1798                 .special        = NULL,
1799                 .enum_list      = NULL,
1800                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
1801         },
1802         {
1803                 .label          = "dos filemode",
1804                 .type           = P_BOOL,
1805                 .p_class        = P_LOCAL,
1806                 .offset         = LOCAL_VAR(bDosFilemode),
1807                 .special        = NULL,
1808                 .enum_list      = NULL,
1809                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
1810         },
1811         {
1812                 .label          = "dos filetimes",
1813                 .type           = P_BOOL,
1814                 .p_class        = P_LOCAL,
1815                 .offset         = LOCAL_VAR(bDosFiletimes),
1816                 .special        = NULL,
1817                 .enum_list      = NULL,
1818                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
1819         },
1820         {
1821                 .label          = "dos filetime resolution",
1822                 .type           = P_BOOL,
1823                 .p_class        = P_LOCAL,
1824                 .offset         = LOCAL_VAR(bDosFiletimeResolution),
1825                 .special        = NULL,
1826                 .enum_list      = NULL,
1827                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
1828         },
1829         {
1830                 .label          = "fake directory create times",
1831                 .type           = P_BOOL,
1832                 .p_class        = P_LOCAL,
1833                 .offset         = LOCAL_VAR(bFakeDirCreateTimes),
1834                 .special        = NULL,
1835                 .enum_list      = NULL,
1836                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
1837         },
1838         {
1839                 .label          = "async smb echo handler",
1840                 .type           = P_BOOL,
1841                 .p_class        = P_GLOBAL,
1842                 .offset         = GLOBAL_VAR(bAsyncSMBEchoHandler),
1843                 .special        = NULL,
1844                 .enum_list      = NULL,
1845                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
1846         },
1847         {
1848                 .label          = "panic action",
1849                 .type           = P_STRING,
1850                 .p_class        = P_GLOBAL,
1851                 .offset         = GLOBAL_VAR(szPanicAction),
1852                 .special        = NULL,
1853                 .enum_list      = NULL,
1854                 .flags          = FLAG_ADVANCED,
1855         },
1856         {
1857                 .label          = "perfcount module",
1858                 .type           = P_STRING,
1859                 .p_class        = P_GLOBAL,
1860                 .offset         = GLOBAL_VAR(szSMBPerfcountModule),
1861                 .special        = NULL,
1862                 .enum_list      = NULL,
1863                 .flags          = FLAG_ADVANCED,
1864         },
1865
1866         {N_("VFS module options"), P_SEP, P_SEPARATOR},
1867
1868         {
1869                 .label          = "vfs objects",
1870                 .type           = P_LIST,
1871                 .p_class        = P_LOCAL,
1872                 .offset         = LOCAL_VAR(szVfsObjects),
1873                 .special        = NULL,
1874                 .enum_list      = NULL,
1875                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
1876         },
1877         {
1878                 .label          = "vfs object",
1879                 .type           = P_LIST,
1880                 .p_class        = P_LOCAL,
1881                 .offset         = LOCAL_VAR(szVfsObjects),
1882                 .special        = NULL,
1883                 .enum_list      = NULL,
1884                 .flags          = FLAG_HIDE,
1885         },
1886
1887
1888         {N_("MSDFS options"), P_SEP, P_SEPARATOR},
1889
1890         {
1891                 .label          = "msdfs root",
1892                 .type           = P_BOOL,
1893                 .p_class        = P_LOCAL,
1894                 .offset         = LOCAL_VAR(bMSDfsRoot),
1895                 .special        = NULL,
1896                 .enum_list      = NULL,
1897                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
1898         },
1899         {
1900                 .label          = "msdfs proxy",
1901                 .type           = P_STRING,
1902                 .p_class        = P_LOCAL,
1903                 .offset         = LOCAL_VAR(szMSDfsProxy),
1904                 .special        = NULL,
1905                 .enum_list      = NULL,
1906                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
1907         },
1908         {
1909                 .label          = "host msdfs",
1910                 .type           = P_BOOL,
1911                 .p_class        = P_GLOBAL,
1912                 .offset         = GLOBAL_VAR(bHostMSDfs),
1913                 .special        = NULL,
1914                 .enum_list      = NULL,
1915                 .flags          = FLAG_ADVANCED,
1916         },
1917
1918         {N_("Winbind options"), P_SEP, P_SEPARATOR},
1919
1920         {
1921                 .label          = "passdb expand explicit",
1922                 .type           = P_BOOL,
1923                 .p_class        = P_GLOBAL,
1924                 .offset         = GLOBAL_VAR(bPassdbExpandExplicit),
1925                 .special        = NULL,
1926                 .enum_list      = NULL,
1927                 .flags          = FLAG_ADVANCED,
1928         },
1929         {
1930                 .label          = "idmap backend",
1931                 .type           = P_STRING,
1932                 .p_class        = P_GLOBAL,
1933                 .offset         = GLOBAL_VAR(szIdmapBackend),
1934                 .special        = handle_idmap_backend,
1935                 .enum_list      = NULL,
1936                 .flags          = FLAG_ADVANCED | FLAG_DEPRECATED,
1937         },
1938         {
1939                 .label          = "idmap cache time",
1940                 .type           = P_INTEGER,
1941                 .p_class        = P_GLOBAL,
1942                 .offset         = GLOBAL_VAR(iIdmapCacheTime),
1943                 .special        = NULL,
1944                 .enum_list      = NULL,
1945                 .flags          = FLAG_ADVANCED,
1946         },
1947         {
1948                 .label          = "idmap negative cache time",
1949                 .type           = P_INTEGER,
1950                 .p_class        = P_GLOBAL,
1951                 .offset         = GLOBAL_VAR(iIdmapNegativeCacheTime),
1952                 .special        = NULL,
1953                 .enum_list      = NULL,
1954                 .flags          = FLAG_ADVANCED,
1955         },
1956         {
1957                 .label          = "idmap uid",
1958                 .type           = P_STRING,
1959                 .p_class        = P_GLOBAL,
1960                 .offset         = GLOBAL_VAR(szIdmapUID),
1961                 .special        = handle_idmap_uid,
1962                 .enum_list      = NULL,
1963                 .flags          = FLAG_ADVANCED | FLAG_DEPRECATED,
1964         },
1965         {
1966                 .label          = "winbind uid",
1967                 .type           = P_STRING,
1968                 .p_class        = P_GLOBAL,
1969                 .offset         = GLOBAL_VAR(szIdmapUID),
1970                 .special        = handle_idmap_uid,
1971                 .enum_list      = NULL,
1972                 .flags          = FLAG_HIDE,
1973         },
1974         {
1975                 .label          = "idmap gid",
1976                 .type           = P_STRING,
1977                 .p_class        = P_GLOBAL,
1978                 .offset         = GLOBAL_VAR(szIdmapGID),
1979                 .special        = handle_idmap_gid,
1980                 .enum_list      = NULL,
1981                 .flags          = FLAG_ADVANCED | FLAG_DEPRECATED,
1982         },
1983         {
1984                 .label          = "winbind gid",
1985                 .type           = P_STRING,
1986                 .p_class        = P_GLOBAL,
1987                 .offset         = GLOBAL_VAR(szIdmapGID),
1988                 .special        = handle_idmap_gid,
1989                 .enum_list      = NULL,
1990                 .flags          = FLAG_HIDE,
1991         },
1992         {
1993                 .label          = "template homedir",
1994                 .type           = P_STRING,
1995                 .p_class        = P_GLOBAL,
1996                 .offset         = GLOBAL_VAR(szTemplateHomedir),
1997                 .special        = NULL,
1998                 .enum_list      = NULL,
1999                 .flags          = FLAG_ADVANCED,
2000         },
2001         {
2002                 .label          = "template shell",
2003                 .type           = P_STRING,
2004                 .p_class        = P_GLOBAL,
2005                 .offset         = GLOBAL_VAR(szTemplateShell),
2006                 .special        = NULL,
2007                 .enum_list      = NULL,
2008                 .flags          = FLAG_ADVANCED,
2009         },
2010         {
2011                 .label          = "winbind separator",
2012                 .type           = P_STRING,
2013                 .p_class        = P_GLOBAL,
2014                 .offset         = GLOBAL_VAR(szWinbindSeparator),
2015                 .special        = NULL,
2016                 .enum_list      = NULL,
2017                 .flags          = FLAG_ADVANCED,
2018         },
2019         {
2020                 .label          = "winbind cache time",
2021                 .type           = P_INTEGER,
2022                 .p_class        = P_GLOBAL,
2023                 .offset         = GLOBAL_VAR(winbind_cache_time),
2024                 .special        = NULL,
2025                 .enum_list      = NULL,
2026                 .flags          = FLAG_ADVANCED,
2027         },
2028         {
2029                 .label          = "winbind reconnect delay",
2030                 .type           = P_INTEGER,
2031                 .p_class        = P_GLOBAL,
2032                 .offset         = GLOBAL_VAR(winbind_reconnect_delay),
2033                 .special        = NULL,
2034                 .enum_list      = NULL,
2035                 .flags          = FLAG_ADVANCED,
2036         },
2037         {
2038                 .label          = "winbind max clients",
2039                 .type           = P_INTEGER,
2040                 .p_class        = P_GLOBAL,
2041                 .offset         = GLOBAL_VAR(winbind_max_clients),
2042                 .special        = NULL,
2043                 .enum_list      = NULL,
2044                 .flags          = FLAG_ADVANCED,
2045         },
2046         {
2047                 .label          = "winbind enum users",
2048                 .type           = P_BOOL,
2049                 .p_class        = P_GLOBAL,
2050                 .offset         = GLOBAL_VAR(bWinbindEnumUsers),
2051                 .special        = NULL,
2052                 .enum_list      = NULL,
2053                 .flags          = FLAG_ADVANCED,
2054         },
2055         {
2056                 .label          = "winbind enum groups",
2057                 .type           = P_BOOL,
2058                 .p_class        = P_GLOBAL,
2059                 .offset         = GLOBAL_VAR(bWinbindEnumGroups),
2060                 .special        = NULL,
2061                 .enum_list      = NULL,
2062                 .flags          = FLAG_ADVANCED,
2063         },
2064         {
2065                 .label          = "winbind use default domain",
2066                 .type           = P_BOOL,
2067                 .p_class        = P_GLOBAL,
2068                 .offset         = GLOBAL_VAR(bWinbindUseDefaultDomain),
2069                 .special        = NULL,
2070                 .enum_list      = NULL,
2071                 .flags          = FLAG_ADVANCED,
2072         },
2073         {
2074                 .label          = "winbind trusted domains only",
2075                 .type           = P_BOOL,
2076                 .p_class        = P_GLOBAL,
2077                 .offset         = GLOBAL_VAR(bWinbindTrustedDomainsOnly),
2078                 .special        = NULL,
2079                 .enum_list      = NULL,
2080                 .flags          = FLAG_ADVANCED,
2081         },
2082         {
2083                 .label          = "winbind nested groups",
2084                 .type           = P_BOOL,
2085                 .p_class        = P_GLOBAL,
2086                 .offset         = GLOBAL_VAR(bWinbindNestedGroups),
2087                 .special        = NULL,
2088                 .enum_list      = NULL,
2089                 .flags          = FLAG_ADVANCED,
2090         },
2091         {
2092                 .label          = "winbind expand groups",
2093                 .type           = P_INTEGER,
2094                 .p_class        = P_GLOBAL,
2095                 .offset         = GLOBAL_VAR(winbind_expand_groups),
2096                 .special        = NULL,
2097                 .enum_list      = NULL,
2098                 .flags          = FLAG_ADVANCED,
2099         },
2100         {
2101                 .label          = "winbind nss info",
2102                 .type           = P_LIST,
2103                 .p_class        = P_GLOBAL,
2104                 .offset         = GLOBAL_VAR(szWinbindNssInfo),
2105                 .special        = NULL,
2106                 .enum_list      = NULL,
2107                 .flags          = FLAG_ADVANCED,
2108         },
2109         {
2110                 .label          = "winbind refresh tickets",
2111                 .type           = P_BOOL,
2112                 .p_class        = P_GLOBAL,
2113                 .offset         = GLOBAL_VAR(bWinbindRefreshTickets),
2114                 .special        = NULL,
2115                 .enum_list      = NULL,
2116                 .flags          = FLAG_ADVANCED,
2117         },
2118         {
2119                 .label          = "winbind offline logon",
2120                 .type           = P_BOOL,
2121                 .p_class        = P_GLOBAL,
2122                 .offset         = GLOBAL_VAR(bWinbindOfflineLogon),
2123                 .special        = NULL,
2124                 .enum_list      = NULL,
2125                 .flags          = FLAG_ADVANCED,
2126         },
2127         {
2128                 .label          = "winbind normalize names",
2129                 .type           = P_BOOL,
2130                 .p_class        = P_GLOBAL,
2131                 .offset         = GLOBAL_VAR(bWinbindNormalizeNames),
2132                 .special        = NULL,
2133                 .enum_list      = NULL,
2134                 .flags          = FLAG_ADVANCED,
2135         },
2136         {
2137                 .label          = "winbind rpc only",
2138                 .type           = P_BOOL,
2139                 .p_class        = P_GLOBAL,
2140                 .offset         = GLOBAL_VAR(bWinbindRpcOnly),
2141                 .special        = NULL,
2142                 .enum_list      = NULL,
2143                 .flags          = FLAG_ADVANCED,
2144         },
2145         {
2146                 .label          = "create krb5 conf",
2147                 .type           = P_BOOL,
2148                 .p_class        = P_GLOBAL,
2149                 .offset         = GLOBAL_VAR(bCreateKrb5Conf),
2150                 .special        = NULL,
2151                 .enum_list      = NULL,
2152                 .flags          = FLAG_ADVANCED,
2153         },
2154         {
2155                 .label          = "ncalrpc dir",
2156                 .type           = P_STRING,
2157                 .p_class        = P_GLOBAL,
2158                 .offset         = GLOBAL_VAR(ncalrpc_dir),
2159                 .special        = NULL,
2160                 .enum_list      = NULL,
2161                 .flags          = FLAG_ADVANCED,
2162         },
2163         {
2164                 .label          = "winbind max domain connections",
2165                 .type           = P_INTEGER,
2166                 .p_class        = P_GLOBAL,
2167                 .offset         = GLOBAL_VAR(winbindMaxDomainConnections),
2168                 .special        = NULL,
2169                 .enum_list      = NULL,
2170                 .flags          = FLAG_ADVANCED,
2171         },
2172         {
2173                 .label          = "winbindd socket directory",
2174                 .type           = P_STRING,
2175                 .p_class        = P_GLOBAL,
2176                 .offset         = GLOBAL_VAR(szWinbinddSocketDirectory),
2177                 .special        = NULL,
2178                 .enum_list      = NULL,
2179                 .flags          = FLAG_ADVANCED,
2180         },
2181         {
2182                 .label          = "winbindd privileged socket directory",
2183                 .type           = P_STRING,
2184                 .p_class        = P_GLOBAL,
2185                 .offset         = GLOBAL_VAR(szWinbinddPrivilegedSocketDirectory),
2186                 .special        = NULL,
2187                 .enum_list      = NULL,
2188                 .flags          = FLAG_ADVANCED,
2189         },
2190         {
2191                 .label          = "winbind sealed pipes",
2192                 .type           = P_BOOL,
2193                 .p_class        = P_GLOBAL,
2194                 .offset         = GLOBAL_VAR(bWinbindSealedPipes),
2195                 .special        = NULL,
2196                 .enum_list      = NULL,
2197                 .flags          = FLAG_ADVANCED,
2198         },
2199
2200         {N_("DNS options"), P_SEP, P_SEPARATOR},
2201         {
2202                 .label          = "allow dns updates",
2203                 .type           = P_ENUM,
2204                 .p_class        = P_GLOBAL,
2205                 .offset         = GLOBAL_VAR(allow_dns_updates),
2206                 .special        = NULL,
2207                 .enum_list      = enum_dns_update_settings,
2208                 .flags          = FLAG_ADVANCED,
2209         },
2210         {
2211                 .label          = "dns forwarder",
2212                 .type           = P_STRING,
2213                 .p_class        = P_GLOBAL,
2214                 .offset         = GLOBAL_VAR(dns_forwarder),
2215                 .special        = NULL,
2216                 .enum_list      = NULL,
2217                 .flags          = FLAG_ADVANCED,
2218         },
2219         {
2220                 .label          = "dns recursive queries",
2221                 .type           = P_BOOL,
2222                 .p_class        = P_GLOBAL,
2223                 .offset         = GLOBAL_VAR(dns_recursive_queries),
2224                 .special        = NULL,
2225                 .enum_list      = NULL
2226         },
2227         {
2228                 .label          = "dns update command",
2229                 .type           = P_CMDLIST,
2230                 .p_class        = P_GLOBAL,
2231                 .offset         = GLOBAL_VAR(szDNSUpdateCommand),
2232                 .special        = NULL,
2233                 .enum_list      = NULL,
2234                 .flags          = FLAG_ADVANCED,
2235         },
2236         {
2237                 .label          = "nsupdate command",
2238                 .type           = P_CMDLIST,
2239                 .p_class        = P_GLOBAL,
2240                 .offset         = GLOBAL_VAR(szNSUpdateCommand),
2241                 .special        = NULL,
2242                 .enum_list      = NULL,
2243                 .flags          = FLAG_ADVANCED,
2244         },
2245         {
2246                 .label          = "rndc command",
2247                 .type           = P_CMDLIST,
2248                 .p_class        = P_GLOBAL,
2249                 .offset         = GLOBAL_VAR(szRNDCCommand),
2250                 .special        = NULL,
2251                 .enum_list      = NULL,
2252                 .flags          = FLAG_ADVANCED,
2253         },
2254         {
2255                 .label          = "multicast dns register",
2256                 .type           = P_BOOL,
2257                 .p_class        = P_GLOBAL,
2258                 .offset         = GLOBAL_VAR(bMulticastDnsRegister),
2259                 .special        = NULL,
2260                 .enum_list      = NULL,
2261                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
2262         },
2263
2264         {N_("AD DC options"), P_SEP, P_SEPARATOR},
2265
2266         {
2267                 .label          = "samba kcc command",
2268                 .type           = P_CMDLIST,
2269                 .p_class        = P_GLOBAL,
2270                 .offset         = GLOBAL_VAR(szSambaKCCCommand),
2271                 .special        = NULL,
2272                 .enum_list      = NULL,
2273                 .flags          = FLAG_ADVANCED,
2274         },
2275         {
2276                 .label          = "server services",
2277                 .type           = P_LIST,
2278                 .p_class        = P_GLOBAL,
2279                 .offset         = GLOBAL_VAR(server_services),
2280                 .special        = NULL,
2281                 .enum_list      = NULL
2282         },
2283         {
2284                 .label          = "dcerpc endpoint servers",
2285                 .type           = P_LIST,
2286                 .p_class        = P_GLOBAL,
2287                 .offset         = GLOBAL_VAR(dcerpc_ep_servers),
2288                 .special        = NULL,
2289                 .enum_list      = NULL
2290         },
2291         {
2292                 .label          = "spn update command",
2293                 .type           = P_CMDLIST,
2294                 .p_class        = P_GLOBAL,
2295                 .offset         = GLOBAL_VAR(szSPNUpdateCommand),
2296                 .special        = NULL,
2297                 .enum_list      = NULL,
2298                 .flags          = FLAG_ADVANCED,
2299         },
2300         {
2301                 .label          = "share backend",
2302                 .type           = P_STRING,
2303                 .p_class        = P_GLOBAL,
2304                 .offset         = GLOBAL_VAR(szShareBackend),
2305                 .special        = NULL,
2306                 .enum_list      = NULL
2307         },
2308         {
2309                 .label          = "ntvfs handler",
2310                 .type           = P_LIST,
2311                 .p_class        = P_LOCAL,
2312                 .offset         = LOCAL_VAR(ntvfs_handler),
2313                 .special        = NULL,
2314                 .enum_list      = NULL
2315         },
2316
2317         {N_("TLS options"), P_SEP, P_SEPARATOR},
2318
2319         {
2320                 .label          = "tls enabled",
2321                 .type           = P_BOOL,
2322                 .p_class        = P_GLOBAL,
2323                 .offset         = GLOBAL_VAR(tls_enabled),
2324                 .special        = NULL,
2325                 .enum_list      = NULL
2326         },
2327         {
2328                 .label          = "tls keyfile",
2329                 .type           = P_STRING,
2330                 .p_class        = P_GLOBAL,
2331                 .offset         = GLOBAL_VAR(tls_keyfile),
2332                 .special        = NULL,
2333                 .enum_list      = NULL
2334         },
2335         {
2336                 .label          = "tls certfile",
2337                 .type           = P_STRING,
2338                 .p_class        = P_GLOBAL,
2339                 .offset         = GLOBAL_VAR(tls_certfile),
2340                 .special        = NULL,
2341                 .enum_list      = NULL
2342         },
2343         {
2344                 .label          = "tls cafile",
2345                 .type           = P_STRING,
2346                 .p_class        = P_GLOBAL,
2347                 .offset         = GLOBAL_VAR(tls_cafile),
2348                 .special        = NULL,
2349                 .enum_list      = NULL
2350         },
2351         {
2352                 .label          = "tls crlfile",
2353                 .type           = P_STRING,
2354                 .p_class        = P_GLOBAL,
2355                 .offset         = GLOBAL_VAR(tls_crlfile),
2356                 .special        = NULL,
2357                 .enum_list      = NULL
2358         },
2359         {
2360                 .label          = "tls dh params file",
2361                 .type           = P_STRING,
2362                 .p_class        = P_GLOBAL,
2363                 .offset         = GLOBAL_VAR(tls_dhpfile),
2364                 .special        = NULL,
2365                 .enum_list      = NULL
2366         },
2367
2368         {NULL,  P_BOOL,  P_NONE,  0,  NULL,  NULL,  0}
2369 };
2370
2371
2372 /* local variables */
2373 struct loadparm_context {
2374         const char *szConfigFile;
2375         struct loadparm_global *globals;
2376         struct loadparm_service **services;
2377         struct loadparm_service *sDefault;
2378         struct smb_iconv_handle *iconv_handle;
2379         int iNumServices;
2380         struct loadparm_service *currentService;
2381         bool bInGlobalSection;
2382         struct file_lists {
2383                 struct file_lists *next;
2384                 char *name;
2385                 char *subfname;
2386                 time_t modtime;
2387         } *file_lists;
2388         unsigned int flags[NUMPARAMETERS];
2389         bool loaded;
2390         bool refuse_free;
2391         bool global; /* Is this the global context, which may set
2392                       * global variables such as debug level etc? */
2393         const struct loadparm_s3_helpers *s3_fns;
2394 };
2395
2396
2397 struct loadparm_service *lpcfg_default_service(struct loadparm_context *lp_ctx)
2398 {
2399         if (lp_ctx->s3_fns) {
2400                 return lp_ctx->s3_fns->get_default_loadparm_service();
2401         }
2402         return lp_ctx->sDefault;
2403 }
2404
2405 /**
2406  * Convenience routine to grab string parameters into temporary memory
2407  * and run standard_sub_basic on them.
2408  *
2409  * The buffers can be written to by
2410  * callers without affecting the source string.
2411  */
2412
2413 static const char *lp_string(const char *s)
2414 {
2415 #if 0  /* until REWRITE done to make thread-safe */
2416         size_t len = s ? strlen(s) : 0;
2417         char *ret;
2418 #endif
2419
2420         /* The follow debug is useful for tracking down memory problems
2421            especially if you have an inner loop that is calling a lp_*()
2422            function that returns a string.  Perhaps this debug should be
2423            present all the time? */
2424
2425 #if 0
2426         DEBUG(10, ("lp_string(%s)\n", s));
2427 #endif
2428
2429 #if 0  /* until REWRITE done to make thread-safe */
2430         if (!lp_talloc)
2431                 lp_talloc = talloc_init("lp_talloc");
2432
2433         ret = talloc_array(lp_talloc, char, len + 100); /* leave room for substitution */
2434
2435         if (!ret)
2436                 return NULL;
2437
2438         if (!s)
2439                 *ret = 0;
2440         else
2441                 strlcpy(ret, s, len);
2442
2443         if (trim_string(ret, "\"", "\"")) {
2444                 if (strchr(ret,'"') != NULL)
2445                         strlcpy(ret, s, len);
2446         }
2447
2448         standard_sub_basic(ret,len+100);
2449         return (ret);
2450 #endif
2451         return s;
2452 }
2453
2454 /*
2455    In this section all the functions that are used to access the
2456    parameters from the rest of the program are defined
2457 */
2458
2459 /*
2460  * the creation of separate lpcfg_*() and lp_*() functions is to allow
2461  * for code compatibility between existing Samba4 and Samba3 code.
2462  */
2463
2464 /* this global context supports the lp_*() function varients */
2465 static struct loadparm_context *global_loadparm_context;
2466
2467 #define lpcfg_default_service global_loadparm_context->sDefault
2468 #define lpcfg_global_service(i) global_loadparm_context->services[i]
2469
2470 #define FN_GLOBAL_STRING(fn_name,var_name)                              \
2471  _PUBLIC_ const char *lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) { \
2472         if (lp_ctx == NULL) return NULL;                                \
2473         if (lp_ctx->s3_fns) {                                           \
2474                 SMB_ASSERT(lp_ctx->s3_fns->fn_name);                    \
2475                 return lp_ctx->s3_fns->fn_name();                       \
2476         }                                                               \
2477         return lp_ctx->globals->var_name ? lp_string(lp_ctx->globals->var_name) : ""; \
2478 }
2479
2480 #define FN_GLOBAL_CONST_STRING(fn_name,var_name) \
2481  _PUBLIC_ const char *lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) {\
2482          if (lp_ctx == NULL) return NULL;                               \
2483          if (lp_ctx->s3_fns) {                                          \
2484                  SMB_ASSERT(lp_ctx->s3_fns->fn_name);                   \
2485                  return lp_ctx->s3_fns->fn_name();                      \
2486          }                                                              \
2487          return lp_ctx->globals->var_name ? lp_string(lp_ctx->globals->var_name) : ""; \
2488  }
2489
2490 #define FN_GLOBAL_LIST(fn_name,var_name)                                \
2491  _PUBLIC_ const char **lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) { \
2492          if (lp_ctx == NULL) return NULL;                               \
2493          if (lp_ctx->s3_fns) {                                          \
2494                  SMB_ASSERT(lp_ctx->s3_fns->fn_name);                   \
2495                  return lp_ctx->s3_fns->fn_name();                      \
2496          }                                                              \
2497          return lp_ctx->globals->var_name;                              \
2498  }
2499
2500 #define FN_GLOBAL_BOOL(fn_name,var_name) \
2501  _PUBLIC_ bool lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) {\
2502          if (lp_ctx == NULL) return false;                              \
2503          if (lp_ctx->s3_fns) {                                          \
2504                  SMB_ASSERT(lp_ctx->s3_fns->fn_name);                   \
2505                  return lp_ctx->s3_fns->fn_name();                      \
2506          }                                                              \
2507          return lp_ctx->globals->var_name;                              \
2508 }
2509
2510 #define FN_GLOBAL_INTEGER(fn_name,var_name) \
2511  _PUBLIC_ int lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) { \
2512          if (lp_ctx->s3_fns) {                                          \
2513                  SMB_ASSERT(lp_ctx->s3_fns->fn_name);                   \
2514                  return lp_ctx->s3_fns->fn_name();                      \
2515          }                                                              \
2516          return lp_ctx->globals->var_name;                              \
2517  }
2518
2519 /* Local parameters don't need the ->s3_fns because the struct
2520  * loadparm_service is shared and lpcfg_service() checks the ->s3_fns
2521  * hook */
2522 #define FN_LOCAL_STRING(fn_name,val) \
2523  _PUBLIC_ const char *lpcfg_ ## fn_name(struct loadparm_service *service, \
2524                                         struct loadparm_service *sDefault) { \
2525          return(lp_string((const char *)((service != NULL && service->val != NULL) ? service->val : sDefault->val))); \
2526  }
2527
2528 #define FN_LOCAL_CONST_STRING(fn_name,val) FN_LOCAL_STRING(fn_name, val)
2529
2530 #define FN_LOCAL_LIST(fn_name,val) \
2531  _PUBLIC_ const char **lpcfg_ ## fn_name(struct loadparm_service *service, \
2532                                          struct loadparm_service *sDefault) {\
2533          return(const char **)(service != NULL && service->val != NULL? service->val : sDefault->val); \
2534  }
2535
2536 #define FN_LOCAL_PARM_BOOL(fn_name, val) FN_LOCAL_BOOL(fn_name, val)
2537
2538 #define FN_LOCAL_BOOL(fn_name,val) \
2539  _PUBLIC_ bool lpcfg_ ## fn_name(struct loadparm_service *service, \
2540                                  struct loadparm_service *sDefault) {   \
2541          return((service != NULL)? service->val : sDefault->val); \
2542  }
2543
2544 #define FN_LOCAL_INTEGER(fn_name,val) \
2545  _PUBLIC_ int lpcfg_ ## fn_name(struct loadparm_service *service, \
2546                                 struct loadparm_service *sDefault) {    \
2547          return((service != NULL)? service->val : sDefault->val); \
2548  }
2549
2550 #define FN_LOCAL_PARM_INTEGER(fn_name, val) FN_LOCAL_INTEGER(fn_name, val)
2551
2552 #define FN_LOCAL_PARM_CHAR(fn_name, val) FN_LOCAL_CHAR(fn_name, val)
2553
2554 #define FN_LOCAL_CHAR(fn_name,val) \
2555  _PUBLIC_ char lpcfg_ ## fn_name(struct loadparm_service *service, \
2556                                 struct loadparm_service *sDefault) {    \
2557          return((service != NULL)? service->val : sDefault->val); \
2558  }
2559
2560 #include "lib/param/param_functions.c"
2561
2562 /* These functions remain only in lib/param for now */
2563 FN_GLOBAL_BOOL(readraw, bReadRaw)
2564 FN_GLOBAL_BOOL(writeraw, bWriteRaw)
2565 FN_GLOBAL_STRING(cachedir, szCacheDir)
2566 FN_GLOBAL_STRING(socket_address, szSocketAddress)
2567 FN_GLOBAL_STRING(statedir, szStateDir)
2568
2569 /* local prototypes */
2570 static int map_parameter(const char *pszParmName);
2571 static struct loadparm_service *getservicebyname(struct loadparm_context *lp_ctx,
2572                                         const char *pszServiceName);
2573 static void copy_service(struct loadparm_service *pserviceDest,
2574                          struct loadparm_service *pserviceSource,
2575                          struct bitmap *pcopymapDest);
2576 static bool lpcfg_service_ok(struct loadparm_service *service);
2577 static bool do_section(const char *pszSectionName, void *);
2578 static void init_copymap(struct loadparm_service *pservice);
2579
2580 /* This is a helper function for parametrical options support. */
2581 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
2582 /* Actual parametrical functions are quite simple */
2583 const char *lpcfg_get_parametric(struct loadparm_context *lp_ctx,
2584                               struct loadparm_service *service,
2585                               const char *type, const char *option)
2586 {
2587         char *vfskey_tmp = NULL;
2588         char *vfskey = NULL;
2589         struct parmlist_entry *data;
2590
2591         if (lp_ctx == NULL)
2592                 return NULL;
2593
2594         if (lp_ctx->s3_fns) {
2595                 return lp_ctx->s3_fns->get_parametric(service, type, option);
2596         }
2597
2598         data = (service == NULL ? lp_ctx->globals->param_opt : service->param_opt);
2599
2600         vfskey_tmp = talloc_asprintf(NULL, "%s:%s", type, option);
2601         if (vfskey_tmp == NULL) return NULL;
2602         vfskey = strlower_talloc(NULL, vfskey_tmp);
2603         talloc_free(vfskey_tmp);
2604
2605         while (data) {
2606                 if (strcmp(data->key, vfskey) == 0) {
2607                         talloc_free(vfskey);
2608                         return data->value;
2609                 }
2610                 data = data->next;
2611         }
2612
2613         if (service != NULL) {
2614                 /* Try to fetch the same option but from globals */
2615                 /* but only if we are not already working with globals */
2616                 for (data = lp_ctx->globals->param_opt; data;
2617                      data = data->next) {
2618                         if (strcmp(data->key, vfskey) == 0) {
2619                                 talloc_free(vfskey);
2620                                 return data->value;
2621                         }
2622                 }
2623         }
2624
2625         talloc_free(vfskey);
2626
2627         return NULL;
2628 }
2629
2630
2631 /**
2632  * convenience routine to return int parameters.
2633  */
2634 static int lp_int(const char *s)
2635 {
2636
2637         if (!s) {
2638                 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
2639                 return -1;
2640         }
2641
2642         return strtol(s, NULL, 0);
2643 }
2644
2645 /**
2646  * convenience routine to return unsigned long parameters.
2647  */
2648 static unsigned long lp_ulong(const char *s)
2649 {
2650
2651         if (!s) {
2652                 DEBUG(0,("lp_ulong(%s): is called with NULL!\n",s));
2653                 return -1;
2654         }
2655
2656         return strtoul(s, NULL, 0);
2657 }
2658
2659 /**
2660  * convenience routine to return unsigned long parameters.
2661  */
2662 static long lp_long(const char *s)
2663 {
2664
2665         if (!s) {
2666                 DEBUG(0,("lp_long(%s): is called with NULL!\n",s));
2667                 return -1;
2668         }
2669
2670         return strtol(s, NULL, 0);
2671 }
2672
2673 /**
2674  * convenience routine to return unsigned long parameters.
2675  */
2676 static double lp_double(const char *s)
2677 {
2678
2679         if (!s) {
2680                 DEBUG(0,("lp_double(%s): is called with NULL!\n",s));
2681                 return -1;
2682         }
2683
2684         return strtod(s, NULL);
2685 }
2686
2687 /**
2688  * convenience routine to return boolean parameters.
2689  */
2690 static bool lp_bool(const char *s)
2691 {
2692         bool ret = false;
2693
2694         if (!s) {
2695                 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
2696                 return false;
2697         }
2698
2699         if (!set_boolean(s, &ret)) {
2700                 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
2701                 return false;
2702         }
2703
2704         return ret;
2705 }
2706
2707
2708 /**
2709  * Return parametric option from a given service. Type is a part of option before ':'
2710  * Parametric option has following syntax: 'Type: option = value'
2711  * Returned value is allocated in 'lp_talloc' context
2712  */
2713
2714 const char *lpcfg_parm_string(struct loadparm_context *lp_ctx,
2715                               struct loadparm_service *service, const char *type,
2716                               const char *option)
2717 {
2718         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
2719
2720         if (value)
2721                 return lp_string(value);
2722
2723         return NULL;
2724 }
2725
2726 /**
2727  * Return parametric option from a given service. Type is a part of option before ':'
2728  * Parametric option has following syntax: 'Type: option = value'
2729  * Returned value is allocated in 'lp_talloc' context
2730  */
2731
2732 const char **lpcfg_parm_string_list(TALLOC_CTX *mem_ctx,
2733                                     struct loadparm_context *lp_ctx,
2734                                     struct loadparm_service *service,
2735                                     const char *type,
2736                                     const char *option, const char *separator)
2737 {
2738         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
2739
2740         if (value != NULL)
2741                 return (const char **)str_list_make(mem_ctx, value, separator);
2742
2743         return NULL;
2744 }
2745
2746 /**
2747  * Return parametric option from a given service. Type is a part of option before ':'
2748  * Parametric option has following syntax: 'Type: option = value'
2749  */
2750
2751 int lpcfg_parm_int(struct loadparm_context *lp_ctx,
2752                    struct loadparm_service *service, const char *type,
2753                    const char *option, int default_v)
2754 {
2755         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
2756
2757         if (value)
2758                 return lp_int(value);
2759
2760         return default_v;
2761 }
2762
2763 /**
2764  * Return parametric option from a given service. Type is a part of
2765  * option before ':'.
2766  * Parametric option has following syntax: 'Type: option = value'.
2767  */
2768
2769 int lpcfg_parm_bytes(struct loadparm_context *lp_ctx,
2770                   struct loadparm_service *service, const char *type,
2771                   const char *option, int default_v)
2772 {
2773         uint64_t bval;
2774
2775         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
2776
2777         if (value && conv_str_size_error(value, &bval)) {
2778                 if (bval <= INT_MAX) {
2779                         return (int)bval;
2780                 }
2781         }
2782
2783         return default_v;
2784 }
2785
2786 /**
2787  * Return parametric option from a given service.
2788  * Type is a part of option before ':'
2789  * Parametric option has following syntax: 'Type: option = value'
2790  */
2791 unsigned long lpcfg_parm_ulong(struct loadparm_context *lp_ctx,
2792                             struct loadparm_service *service, const char *type,
2793                             const char *option, unsigned long default_v)
2794 {
2795         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
2796
2797         if (value)
2798                 return lp_ulong(value);
2799
2800         return default_v;
2801 }
2802
2803 long lpcfg_parm_long(struct loadparm_context *lp_ctx,
2804                      struct loadparm_service *service, const char *type,
2805                      const char *option, long default_v)
2806 {
2807         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
2808
2809         if (value)
2810                 return lp_long(value);
2811
2812         return default_v;
2813 }
2814
2815 double lpcfg_parm_double(struct loadparm_context *lp_ctx,
2816                       struct loadparm_service *service, const char *type,
2817                       const char *option, double default_v)
2818 {
2819         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
2820
2821         if (value != NULL)
2822                 return lp_double(value);
2823
2824         return default_v;
2825 }
2826
2827 /**
2828  * Return parametric option from a given service. Type is a part of option before ':'
2829  * Parametric option has following syntax: 'Type: option = value'
2830  */
2831
2832 bool lpcfg_parm_bool(struct loadparm_context *lp_ctx,
2833                      struct loadparm_service *service, const char *type,
2834                      const char *option, bool default_v)
2835 {
2836         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
2837
2838         if (value != NULL)
2839                 return lp_bool(value);
2840
2841         return default_v;
2842 }
2843
2844
2845 /**
2846  * Initialise a service to the defaults.
2847  */
2848
2849 static struct loadparm_service *init_service(TALLOC_CTX *mem_ctx, struct loadparm_service *sDefault)
2850 {
2851         struct loadparm_service *pservice =
2852                 talloc_zero(mem_ctx, struct loadparm_service);
2853         copy_service(pservice, sDefault, NULL);
2854         return pservice;
2855 }
2856
2857 /**
2858  * Set a string value, deallocating any existing space, and allocing the space
2859  * for the string
2860  */
2861 static bool lpcfg_string_set(TALLOC_CTX *mem_ctx, char **dest, const char *src)
2862 {
2863         talloc_free(*dest);
2864
2865         if (src == NULL)
2866                 src = "";
2867
2868         *dest = talloc_strdup(mem_ctx, src);
2869         if ((*dest) == NULL) {
2870                 DEBUG(0,("Out of memory in string_set\n"));
2871                 return false;
2872         }
2873
2874         return true;
2875 }
2876
2877 /**
2878  * Set a string value, deallocating any existing space, and allocing the space
2879  * for the string
2880  */
2881 static bool lpcfg_string_set_upper(TALLOC_CTX *mem_ctx, char **dest, const char *src)
2882 {
2883         talloc_free(*dest);
2884
2885         if (src == NULL)
2886                 src = "";
2887
2888         *dest = strupper_talloc(mem_ctx, src);
2889         if ((*dest) == NULL) {
2890                 DEBUG(0,("Out of memory in string_set_upper\n"));
2891                 return false;
2892         }
2893
2894         return true;
2895 }
2896
2897
2898
2899 /**
2900  * Add a new service to the services array initialising it with the given
2901  * service.
2902  */
2903
2904 struct loadparm_service *lpcfg_add_service(struct loadparm_context *lp_ctx,
2905                                            const struct loadparm_service *pservice,
2906                                            const char *name)
2907 {
2908         int i;
2909         struct loadparm_service tservice;
2910         int num_to_alloc = lp_ctx->iNumServices + 1;
2911         struct parmlist_entry *data, *pdata;
2912
2913         if (pservice == NULL) {
2914                 pservice = lp_ctx->sDefault;
2915         }
2916
2917         tservice = *pservice;
2918
2919         /* it might already exist */
2920         if (name) {
2921                 struct loadparm_service *service = getservicebyname(lp_ctx,
2922                                                                     name);
2923                 if (service != NULL) {
2924                         /* Clean all parametric options for service */
2925                         /* They will be added during parsing again */
2926                         data = service->param_opt;
2927                         while (data) {
2928                                 pdata = data->next;
2929                                 talloc_free(data);
2930                                 data = pdata;
2931                         }
2932                         service->param_opt = NULL;
2933                         return service;
2934                 }
2935         }
2936
2937         /* find an invalid one */
2938         for (i = 0; i < lp_ctx->iNumServices; i++)
2939                 if (lp_ctx->services[i] == NULL)
2940                         break;
2941
2942         /* if not, then create one */
2943         if (i == lp_ctx->iNumServices) {
2944                 struct loadparm_service **tsp;
2945
2946                 tsp = talloc_realloc(lp_ctx, lp_ctx->services, struct loadparm_service *, num_to_alloc);
2947
2948                 if (!tsp) {
2949                         DEBUG(0,("lpcfg_add_service: failed to enlarge services!\n"));
2950                         return NULL;
2951                 } else {
2952                         lp_ctx->services = tsp;
2953                         lp_ctx->services[lp_ctx->iNumServices] = NULL;
2954                 }
2955
2956                 lp_ctx->iNumServices++;
2957         }
2958
2959         lp_ctx->services[i] = init_service(lp_ctx->services, lp_ctx->sDefault);
2960         if (lp_ctx->services[i] == NULL) {
2961                 DEBUG(0,("lpcfg_add_service: out of memory!\n"));
2962                 return NULL;
2963         }
2964         copy_service(lp_ctx->services[i], &tservice, NULL);
2965         if (name != NULL)
2966                 lpcfg_string_set(lp_ctx->services[i], &lp_ctx->services[i]->szService, name);
2967         return lp_ctx->services[i];
2968 }
2969
2970 /**
2971  * Add a new home service, with the specified home directory, defaults coming
2972  * from service ifrom.
2973  */
2974
2975 bool lpcfg_add_home(struct loadparm_context *lp_ctx,
2976                  const char *pszHomename,
2977                  struct loadparm_service *default_service,
2978                  const char *user, const char *pszHomedir)
2979 {
2980         struct loadparm_service *service;
2981
2982         service = lpcfg_add_service(lp_ctx, default_service, pszHomename);
2983
2984         if (service == NULL)
2985                 return false;
2986
2987         if (!(*(default_service->szPath))
2988             || strequal(default_service->szPath, lp_ctx->sDefault->szPath)) {
2989                 service->szPath = talloc_strdup(service, pszHomedir);
2990         } else {
2991                 service->szPath = string_sub_talloc(service, lpcfg_pathname(default_service, lp_ctx->sDefault), "%H", pszHomedir);
2992         }
2993
2994         if (!(*(service->comment))) {
2995                 service->comment = talloc_asprintf(service, "Home directory of %s", user);
2996         }
2997         service->bAvailable = default_service->bAvailable;
2998         service->bBrowseable = default_service->bBrowseable;
2999
3000         DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n",
3001                   pszHomename, user, service->szPath));
3002
3003         return true;
3004 }
3005
3006 /**
3007  * Add a new printer service, with defaults coming from service iFrom.
3008  */
3009
3010 bool lpcfg_add_printer(struct loadparm_context *lp_ctx,
3011                        const char *pszPrintername,
3012                        struct loadparm_service *default_service)
3013 {
3014         const char *comment = "From Printcap";
3015         struct loadparm_service *service;
3016         service = lpcfg_add_service(lp_ctx, default_service, pszPrintername);
3017
3018         if (service == NULL)
3019                 return false;
3020
3021         /* note that we do NOT default the availability flag to True - */
3022         /* we take it from the default service passed. This allows all */
3023         /* dynamic printers to be disabled by disabling the [printers] */
3024         /* entry (if/when the 'available' keyword is implemented!).    */
3025
3026         /* the printer name is set to the service name. */
3027         lpcfg_string_set(service, &service->szPrintername, pszPrintername);
3028         lpcfg_string_set(service, &service->comment, comment);
3029         service->bBrowseable = default_service->bBrowseable;
3030         /* Printers cannot be read_only. */
3031         service->bRead_only = false;
3032         /* Printer services must be printable. */
3033         service->bPrint_ok = true;
3034
3035         DEBUG(3, ("adding printer service %s\n", pszPrintername));
3036
3037         return true;
3038 }
3039
3040 /**
3041  * Map a parameter's string representation to something we can use.
3042  * Returns False if the parameter string is not recognised, else TRUE.
3043  */
3044
3045 static int map_parameter(const char *pszParmName)
3046 {
3047         int iIndex;
3048
3049         if (*pszParmName == '-')
3050                 return -1;
3051
3052         for (iIndex = 0; parm_table[iIndex].label; iIndex++)
3053                 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
3054                         return iIndex;
3055
3056         /* Warn only if it isn't parametric option */
3057         if (strchr(pszParmName, ':') == NULL)
3058                 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
3059         /* We do return 'fail' for parametric options as well because they are
3060            stored in different storage
3061          */
3062         return -1;
3063 }
3064
3065
3066 /**
3067   return the parameter structure for a parameter
3068 */
3069 struct parm_struct *lpcfg_parm_struct(struct loadparm_context *lp_ctx, const char *name)
3070 {
3071         int parmnum;
3072
3073         if (lp_ctx->s3_fns) {
3074                 return lp_ctx->s3_fns->get_parm_struct(name);
3075         }
3076
3077         parmnum = map_parameter(name);
3078         if (parmnum == -1) return NULL;
3079         return &parm_table[parmnum];
3080 }
3081
3082 /**
3083   return the parameter pointer for a parameter
3084 */
3085 void *lpcfg_parm_ptr(struct loadparm_context *lp_ctx,
3086                   struct loadparm_service *service, struct parm_struct *parm)
3087 {
3088         if (lp_ctx->s3_fns) {
3089                 return lp_ctx->s3_fns->get_parm_ptr(service, parm);
3090         }
3091
3092         if (service == NULL) {
3093                 if (parm->p_class == P_LOCAL)
3094                         return ((char *)lp_ctx->sDefault)+parm->offset;
3095                 else if (parm->p_class == P_GLOBAL)
3096                         return ((char *)lp_ctx->globals)+parm->offset;
3097                 else return NULL;
3098         } else {
3099                 return ((char *)service) + parm->offset;
3100         }
3101 }
3102
3103 /**
3104   return the parameter pointer for a parameter
3105 */
3106 bool lpcfg_parm_is_cmdline(struct loadparm_context *lp_ctx, const char *name)
3107 {
3108         int parmnum;
3109
3110         if (lp_ctx->s3_fns) {
3111                 struct parm_struct *parm = lp_ctx->s3_fns->get_parm_struct(name);
3112                 if (parm) {
3113                         return parm->flags & FLAG_CMDLINE;
3114                 }
3115                 return false;
3116         }
3117
3118         parmnum = map_parameter(name);
3119         if (parmnum == -1) return false;
3120
3121         return lp_ctx->flags[parmnum] & FLAG_CMDLINE;
3122 }
3123
3124 /**
3125  * Find a service by name. Otherwise works like get_service.
3126  */
3127
3128 static struct loadparm_service *getservicebyname(struct loadparm_context *lp_ctx,
3129                                         const char *pszServiceName)
3130 {
3131         int iService;
3132
3133         if (lp_ctx->s3_fns) {
3134                 return lp_ctx->s3_fns->get_service(pszServiceName);
3135         }
3136
3137         for (iService = lp_ctx->iNumServices - 1; iService >= 0; iService--)
3138                 if (lp_ctx->services[iService] != NULL &&
3139                     strwicmp(lp_ctx->services[iService]->szService, pszServiceName) == 0) {
3140                         return lp_ctx->services[iService];
3141                 }
3142
3143         return NULL;
3144 }
3145
3146 /**
3147  * Copy a service structure to another.
3148  * If pcopymapDest is NULL then copy all fields
3149  */
3150
3151 static void copy_service(struct loadparm_service *pserviceDest,
3152                          struct loadparm_service *pserviceSource,
3153                          struct bitmap *pcopymapDest)
3154 {
3155         int i;
3156         bool bcopyall = (pcopymapDest == NULL);
3157         struct parmlist_entry *data, *pdata, *paramo;
3158         bool not_added;
3159
3160         for (i = 0; parm_table[i].label; i++)
3161                 if (parm_table[i].p_class == P_LOCAL &&
3162                     (bcopyall || bitmap_query(pcopymapDest, i))) {
3163                         void *src_ptr =
3164                                 ((char *)pserviceSource) + parm_table[i].offset;
3165                         void *dest_ptr =
3166                                 ((char *)pserviceDest) + parm_table[i].offset;
3167
3168                         switch (parm_table[i].type) {
3169                                 case P_BOOL:
3170                                         *(bool *)dest_ptr = *(bool *)src_ptr;
3171                                         break;
3172
3173                                 case P_INTEGER:
3174                                 case P_BYTES:
3175                                 case P_OCTAL:
3176                                 case P_ENUM:
3177                                         *(int *)dest_ptr = *(int *)src_ptr;
3178                                         break;
3179
3180                                 case P_STRING:
3181                                         lpcfg_string_set(pserviceDest,
3182                                                    (char **)dest_ptr,
3183                                                    *(char **)src_ptr);
3184                                         break;
3185
3186                                 case P_USTRING:
3187                                         lpcfg_string_set_upper(pserviceDest,
3188                                                          (char **)dest_ptr,
3189                                                          *(char **)src_ptr);
3190                                         break;
3191                                 case P_LIST:
3192                                         *(const char ***)dest_ptr = (const char **)str_list_copy(pserviceDest, 
3193                                                                                   *(const char ***)src_ptr);
3194                                         break;
3195                                 default:
3196                                         break;
3197                         }
3198                 }
3199
3200         if (bcopyall) {
3201                 init_copymap(pserviceDest);
3202                 if (pserviceSource->copymap)
3203                         bitmap_copy(pserviceDest->copymap,
3204                                     pserviceSource->copymap);
3205         }
3206
3207         data = pserviceSource->param_opt;
3208         while (data) {
3209                 not_added = true;
3210                 pdata = pserviceDest->param_opt;
3211                 /* Traverse destination */
3212                 while (pdata) {
3213                         /* If we already have same option, override it */
3214                         if (strcmp(pdata->key, data->key) == 0) {
3215                                 talloc_free(pdata->value);
3216                                 pdata->value = talloc_strdup(pdata,
3217                                                              data->value);
3218                                 not_added = false;
3219                                 break;
3220                         }
3221                         pdata = pdata->next;
3222                 }
3223                 if (not_added) {
3224                         paramo = talloc_zero(pserviceDest, struct parmlist_entry);
3225                         if (paramo == NULL)
3226                                 smb_panic("OOM");
3227                         paramo->key = talloc_strdup(paramo, data->key);
3228                         paramo->value = talloc_strdup(paramo, data->value);
3229                         DLIST_ADD(pserviceDest->param_opt, paramo);
3230                 }
3231                 data = data->next;
3232         }
3233 }
3234
3235 /**
3236  * Check a service for consistency. Return False if the service is in any way
3237  * incomplete or faulty, else True.
3238  */
3239 static bool lpcfg_service_ok(struct loadparm_service *service)
3240 {
3241         bool bRetval;
3242
3243         bRetval = true;
3244         if (service->szService[0] == '\0') {
3245                 DEBUG(0, ("The following message indicates an internal error:\n"));
3246                 DEBUG(0, ("No service name in service entry.\n"));
3247                 bRetval = false;
3248         }
3249
3250         /* The [printers] entry MUST be printable. I'm all for flexibility, but */
3251         /* I can't see why you'd want a non-printable printer service...        */
3252         if (strwicmp(service->szService, PRINTERS_NAME) == 0) {
3253                 if (!service->bPrint_ok) {
3254                         DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
3255                                service->szService));
3256                         service->bPrint_ok = true;
3257                 }
3258                 /* [printers] service must also be non-browsable. */
3259                 if (service->bBrowseable)
3260                         service->bBrowseable = false;
3261         }
3262
3263         /* If a service is flagged unavailable, log the fact at level 0. */
3264         if (!service->bAvailable)
3265                 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
3266                           service->szService));
3267
3268         return bRetval;
3269 }
3270
3271
3272 /*******************************************************************
3273  Keep a linked list of all config files so we know when one has changed
3274  it's date and needs to be reloaded.
3275 ********************************************************************/
3276
3277 static void add_to_file_list(struct loadparm_context *lp_ctx,
3278                              const char *fname, const char *subfname)
3279 {
3280         struct file_lists *f = lp_ctx->file_lists;
3281
3282         while (f) {
3283                 if (f->name && !strcmp(f->name, fname))
3284                         break;
3285                 f = f->next;
3286         }
3287
3288         if (!f) {
3289                 f = talloc(lp_ctx, struct file_lists);
3290                 if (!f)
3291                         return;
3292                 f->next = lp_ctx->file_lists;
3293                 f->name = talloc_strdup(f, fname);
3294                 if (!f->name) {
3295                         talloc_free(f);
3296                         return;
3297                 }
3298                 f->subfname = talloc_strdup(f, subfname);
3299                 if (!f->subfname) {
3300                         talloc_free(f);
3301                         return;
3302                 }
3303                 lp_ctx->file_lists = f;
3304                 f->modtime = file_modtime(subfname);
3305         } else {
3306                 time_t t = file_modtime(subfname);
3307                 if (t)
3308                         f->modtime = t;
3309         }
3310 }
3311
3312 /*******************************************************************
3313  Check if a config file has changed date.
3314 ********************************************************************/
3315 bool lpcfg_file_list_changed(struct loadparm_context *lp_ctx)
3316 {
3317         struct file_lists *f;
3318         DEBUG(6, ("lp_file_list_changed()\n"));
3319
3320         for (f = lp_ctx->file_lists; f != NULL; f = f->next) {
3321                 char *n2;
3322                 time_t mod_time;
3323
3324                 n2 = standard_sub_basic(lp_ctx, f->name);
3325
3326                 DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
3327                              f->name, n2, ctime(&f->modtime)));
3328
3329                 mod_time = file_modtime(n2);
3330
3331                 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
3332                         DEBUGADD(6, ("file %s modified: %s\n", n2,
3333                                   ctime(&mod_time)));
3334                         f->modtime = mod_time;
3335                         talloc_free(f->subfname);
3336                         f->subfname = talloc_strdup(f, n2);
3337                         return true;
3338                 }
3339         }
3340         return false;
3341 }
3342
3343 /***************************************************************************
3344  Handle the "realm" parameter
3345 ***************************************************************************/
3346
3347 static bool handle_realm(struct loadparm_context *lp_ctx, int unused,
3348                          const char *pszParmValue, char **ptr)
3349 {
3350         lpcfg_string_set(lp_ctx, ptr, pszParmValue);
3351
3352         talloc_free(lp_ctx->globals->szRealm_upper);
3353         talloc_free(lp_ctx->globals->szRealm_lower);
3354
3355         lp_ctx->globals->szRealm_upper = strupper_talloc(lp_ctx, pszParmValue);
3356         lp_ctx->globals->szRealm_lower = strlower_talloc(lp_ctx, pszParmValue);
3357
3358         return true;
3359 }
3360
3361 /***************************************************************************
3362  Handle the include operation.
3363 ***************************************************************************/
3364
3365 static bool handle_include(struct loadparm_context *lp_ctx, int unused,
3366                            const char *pszParmValue, char **ptr)
3367 {
3368         char *fname = standard_sub_basic(lp_ctx, pszParmValue);
3369
3370         add_to_file_list(lp_ctx, pszParmValue, fname);
3371
3372         lpcfg_string_set(lp_ctx, ptr, fname);
3373
3374         if (file_exist(fname))
3375                 return pm_process(fname, do_section, do_parameter, lp_ctx);
3376
3377         DEBUG(2, ("Can't find include file %s\n", fname));
3378
3379         return false;
3380 }
3381
3382 /***************************************************************************
3383  Handle the interpretation of the copy parameter.
3384 ***************************************************************************/
3385
3386 static bool handle_copy(struct loadparm_context *lp_ctx, int unused,
3387                         const char *pszParmValue, char **ptr)
3388 {
3389         bool bRetval;
3390         struct loadparm_service *serviceTemp;
3391
3392         lpcfg_string_set(lp_ctx, ptr, pszParmValue);
3393
3394         bRetval = false;
3395
3396         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
3397
3398         if ((serviceTemp = getservicebyname(lp_ctx, pszParmValue)) != NULL) {
3399                 if (serviceTemp == lp_ctx->currentService) {
3400                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
3401                 } else {
3402                         copy_service(lp_ctx->currentService,
3403                                      serviceTemp,
3404                                      lp_ctx->currentService->copymap);
3405                         bRetval = true;
3406                 }
3407         } else {
3408                 DEBUG(0, ("Unable to copy service - source not found: %s\n",
3409                           pszParmValue));
3410                 bRetval = false;
3411         }
3412
3413         return bRetval;
3414 }
3415
3416 static bool handle_debuglevel(struct loadparm_context *lp_ctx, int unused,
3417                         const char *pszParmValue, char **ptr)
3418 {
3419
3420         lpcfg_string_set(lp_ctx, ptr, pszParmValue);
3421         if (lp_ctx->global) {
3422                 return debug_parse_levels(pszParmValue);
3423         }
3424         return true;
3425 }
3426
3427 static bool handle_logfile(struct loadparm_context *lp_ctx, int unused,
3428                         const char *pszParmValue, char **ptr)
3429 {
3430         debug_set_logfile(pszParmValue);
3431         if (lp_ctx->global) {
3432                 lpcfg_string_set(lp_ctx, ptr, pszParmValue);
3433         }
3434         return true;
3435 }
3436
3437 /***************************************************************************
3438  Initialise a copymap.
3439 ***************************************************************************/
3440
3441 static void init_copymap(struct loadparm_service *pservice)
3442 {
3443         int i;
3444
3445         TALLOC_FREE(pservice->copymap);
3446
3447         pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
3448         if (!pservice->copymap)
3449                 DEBUG(0,
3450                       ("Couldn't allocate copymap!! (size %d)\n",
3451                        (int)NUMPARAMETERS));
3452         else
3453                 for (i = 0; i < NUMPARAMETERS; i++)
3454                         bitmap_set(pservice->copymap, i);
3455 }
3456
3457 /**
3458  * Process a parametric option
3459  */
3460 static bool lp_do_parameter_parametric(struct loadparm_context *lp_ctx,
3461                                        struct loadparm_service *service,
3462                                        const char *pszParmName,
3463                                        const char *pszParmValue, int flags)
3464 {
3465         struct parmlist_entry *paramo, *data;
3466         char *name;
3467         TALLOC_CTX *mem_ctx;
3468
3469         while (isspace((unsigned char)*pszParmName)) {
3470                 pszParmName++;
3471         }
3472
3473         name = strlower_talloc(lp_ctx, pszParmName);
3474         if (!name) return false;
3475
3476         if (service == NULL) {
3477                 data = lp_ctx->globals->param_opt;
3478                 mem_ctx = lp_ctx->globals;
3479         } else {
3480                 data = service->param_opt;
3481                 mem_ctx = service;
3482         }
3483
3484         /* Traverse destination */
3485         for (paramo=data; paramo; paramo=paramo->next) {
3486                 /* If we already have the option set, override it unless
3487                    it was a command line option and the new one isn't */
3488                 if (strcmp(paramo->key, name) == 0) {
3489                         if ((paramo->priority & FLAG_CMDLINE) &&
3490                             !(flags & FLAG_CMDLINE)) {
3491                                 talloc_free(name);
3492                                 return true;
3493                         }
3494
3495                         talloc_free(paramo->value);
3496                         paramo->value = talloc_strdup(paramo, pszParmValue);
3497                         paramo->priority = flags;
3498                         talloc_free(name);
3499                         return true;
3500                 }
3501         }
3502
3503         paramo = talloc_zero(mem_ctx, struct parmlist_entry);
3504         if (!paramo)
3505                 smb_panic("OOM");
3506         paramo->key = talloc_strdup(paramo, name);
3507         paramo->value = talloc_strdup(paramo, pszParmValue);
3508         paramo->priority = flags;
3509         if (service == NULL) {
3510                 DLIST_ADD(lp_ctx->globals->param_opt, paramo);
3511         } else {
3512                 DLIST_ADD(service->param_opt, paramo);
3513         }
3514
3515         talloc_free(name);
3516
3517         return true;
3518 }
3519
3520 static bool set_variable(TALLOC_CTX *mem_ctx, int parmnum, void *parm_ptr,
3521                          const char *pszParmName, const char *pszParmValue,
3522                          struct loadparm_context *lp_ctx, bool on_globals)
3523 {
3524         int i;
3525         /* if it is a special case then go ahead */
3526         if (parm_table[parmnum].special) {
3527                 bool ret;
3528                 ret = parm_table[parmnum].special(lp_ctx, -1, pszParmValue,
3529                                                   (char **)parm_ptr);
3530                 if (!ret) {
3531                         return false;
3532                 }
3533                 goto mark_non_default;
3534         }
3535
3536         /* now switch on the type of variable it is */
3537         switch (parm_table[parmnum].type)
3538         {
3539                 case P_BOOL: {
3540                         bool b;
3541                         if (!set_boolean(pszParmValue, &b)) {
3542                                 DEBUG(0,("lp_do_parameter(%s): value is not boolean!\n", pszParmValue));
3543                                 return false;
3544                         }
3545                         *(bool *)parm_ptr = b;
3546                         }
3547                         break;
3548
3549                 case P_BOOLREV: {
3550                         bool b;
3551                         if (!set_boolean(pszParmValue, &b)) {
3552                                 DEBUG(0,("lp_do_parameter(%s): value is not boolean!\n", pszParmValue));
3553                                 return false;
3554                         }
3555                         *(bool *)parm_ptr = !b;
3556                         }
3557                         break;
3558
3559                 case P_INTEGER:
3560                         *(int *)parm_ptr = atoi(pszParmValue);
3561                         break;
3562
3563                 case P_CHAR:
3564                         *(char *)parm_ptr = *pszParmValue;
3565                         break;
3566
3567                 case P_OCTAL:
3568                         *(int *)parm_ptr = strtol(pszParmValue, NULL, 8);
3569                         break;
3570
3571                 case P_BYTES:
3572                 {
3573                         uint64_t val;
3574                         if (conv_str_size_error(pszParmValue, &val)) {
3575                                 if (val <= INT_MAX) {
3576                                         *(int *)parm_ptr = (int)val;
3577                                         break;
3578                                 }
3579                         }
3580
3581                         DEBUG(0,("lp_do_parameter(%s): value is not "
3582                             "a valid size specifier!\n", pszParmValue));
3583                         return false;
3584                 }
3585
3586                 case P_CMDLIST:
3587                         *(const char ***)parm_ptr = (const char **)str_list_make(mem_ctx,
3588                                                                   pszParmValue, NULL);
3589                         break;
3590                 case P_LIST:
3591                 {
3592                         char **new_list = str_list_make(mem_ctx,
3593                                                         pszParmValue, NULL);
3594                         for (i=0; new_list[i]; i++) {
3595                                 if (new_list[i][0] == '+' && new_list[i][1]) {
3596                                         if (!str_list_check(*(const char ***)parm_ptr,
3597                                                             &new_list[i][1])) {
3598                                                 *(const char ***)parm_ptr = str_list_add(*(const char ***)parm_ptr,
3599                                                                                          &new_list[i][1]);
3600                                         }
3601                                 } else if (new_list[i][0] == '-' && new_list[i][1]) {
3602                                         str_list_remove(*(const char ***)parm_ptr,
3603                                                         &new_list[i][1]);
3604                                 } else {
3605                                         if (i != 0) {
3606                                                 DEBUG(0, ("Unsupported list syntax for: %s = %s\n",
3607                                                           pszParmName, pszParmValue));
3608                                                 return false;
3609                                         }
3610                                         *(const char ***)parm_ptr = (const char **) new_list;
3611                                         break;
3612                                 }
3613                         }
3614                         break;
3615                 }
3616                 case P_STRING:
3617                         lpcfg_string_set(mem_ctx, (char **)parm_ptr, pszParmValue);
3618                         break;
3619
3620                 case P_USTRING:
3621                         lpcfg_string_set_upper(mem_ctx, (char **)parm_ptr, pszParmValue);
3622                         break;
3623
3624                 case P_ENUM:
3625                         for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
3626                                 if (strequal
3627                                     (pszParmValue,
3628                                      parm_table[parmnum].enum_list[i].name)) {
3629                                         *(int *)parm_ptr =
3630                                                 parm_table[parmnum].
3631                                                 enum_list[i].value;
3632                                         break;
3633                                 }
3634                         }
3635                         if (!parm_table[parmnum].enum_list[i].name) {
3636                                 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n", 
3637                                          pszParmValue, pszParmName));
3638                                 return false;
3639                         }
3640                         break;
3641
3642                 case P_SEP:
3643                         break;
3644         }
3645
3646 mark_non_default:
3647         if (on_globals && (lp_ctx->flags[parmnum] & FLAG_DEFAULT)) {
3648                 lp_ctx->flags[parmnum] &= ~FLAG_DEFAULT;
3649                 /* we have to also unset FLAG_DEFAULT on aliases */
3650                 for (i=parmnum-1;i>=0 && parm_table[i].offset == parm_table[parmnum].offset;i--) {
3651                         lp_ctx->flags[i] &= ~FLAG_DEFAULT;
3652                 }
3653                 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset;i++) {
3654                         lp_ctx->flags[i] &= ~FLAG_DEFAULT;
3655                 }
3656         }
3657         return true;
3658 }
3659
3660
3661 bool lpcfg_do_global_parameter(struct loadparm_context *lp_ctx,
3662                                const char *pszParmName, const char *pszParmValue)
3663 {
3664         int parmnum = map_parameter(pszParmName);
3665         void *parm_ptr;
3666
3667         if (parmnum < 0) {
3668                 if (strchr(pszParmName, ':')) {
3669                         return lp_do_parameter_parametric(lp_ctx, NULL, pszParmName, pszParmValue, 0);
3670                 }
3671                 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
3672                 return true;
3673         }
3674
3675         /* if the flag has been set on the command line, then don't allow override,
3676            but don't report an error */
3677         if (lp_ctx->flags[parmnum] & FLAG_CMDLINE) {
3678                 return true;
3679         }
3680
3681         parm_ptr = lpcfg_parm_ptr(lp_ctx, NULL, &parm_table[parmnum]);
3682
3683         return set_variable(lp_ctx->globals, parmnum, parm_ptr,
3684                             pszParmName, pszParmValue, lp_ctx, true);
3685 }
3686
3687 bool lpcfg_do_service_parameter(struct loadparm_context *lp_ctx,
3688                                 struct loadparm_service *service,
3689                                 const char *pszParmName, const char *pszParmValue)
3690 {
3691         void *parm_ptr;
3692         int i;
3693         int parmnum = map_parameter(pszParmName);
3694
3695         if (parmnum < 0) {
3696                 if (strchr(pszParmName, ':')) {
3697                         return lp_do_parameter_parametric(lp_ctx, service, pszParmName, pszParmValue, 0);
3698                 }
3699                 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
3700                 return true;
3701         }
3702
3703         /* if the flag has been set on the command line, then don't allow override,
3704            but don't report an error */
3705         if (lp_ctx->flags[parmnum] & FLAG_CMDLINE) {
3706                 return true;
3707         }
3708
3709         if (parm_table[parmnum].p_class == P_GLOBAL) {
3710                 DEBUG(0,
3711                       ("Global parameter %s found in service section!\n",
3712                        pszParmName));
3713                 return true;
3714         }
3715         parm_ptr = ((char *)service) + parm_table[parmnum].offset;
3716
3717         if (!service->copymap)
3718                 init_copymap(service);
3719
3720         /* this handles the aliases - set the copymap for other
3721          * entries with the same data pointer */
3722         for (i = 0; parm_table[i].label; i++)
3723                 if (parm_table[i].offset == parm_table[parmnum].offset &&
3724                     parm_table[i].p_class == parm_table[parmnum].p_class)
3725                         bitmap_clear(service->copymap, i);
3726
3727         return set_variable(service, parmnum, parm_ptr, pszParmName,
3728                             pszParmValue, lp_ctx, false);
3729 }
3730
3731 /**
3732  * Process a parameter.
3733  */
3734
3735 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
3736                          void *userdata)
3737 {
3738         struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata;
3739
3740         if (lp_ctx->bInGlobalSection)
3741                 return lpcfg_do_global_parameter(lp_ctx, pszParmName,
3742                                               pszParmValue);
3743         else
3744                 return lpcfg_do_service_parameter(lp_ctx, lp_ctx->currentService,
3745                                                   pszParmName, pszParmValue);
3746 }
3747
3748 /*
3749   variable argument do parameter
3750 */
3751 bool lpcfg_do_global_parameter_var(struct loadparm_context *lp_ctx, const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4);
3752 bool lpcfg_do_global_parameter_var(struct loadparm_context *lp_ctx,
3753                                 const char *pszParmName, const char *fmt, ...)
3754 {
3755         char *s;
3756         bool ret;
3757         va_list ap;
3758
3759         va_start(ap, fmt);
3760         s = talloc_vasprintf(NULL, fmt, ap);
3761         va_end(ap);
3762         ret = lpcfg_do_global_parameter(lp_ctx, pszParmName, s);
3763         talloc_free(s);
3764         return ret;
3765 }
3766
3767
3768 /*
3769   set a parameter from the commandline - this is called from command line parameter
3770   parsing code. It sets the parameter then marks the parameter as unable to be modified
3771   by smb.conf processing
3772 */
3773 bool lpcfg_set_cmdline(struct loadparm_context *lp_ctx, const char *pszParmName,
3774                        const char *pszParmValue)
3775 {
3776         int parmnum;
3777         int i;
3778
3779         if (lp_ctx->s3_fns) {
3780                 return lp_ctx->s3_fns->set_cmdline(pszParmName, pszParmValue);
3781         }
3782
3783         parmnum = map_parameter(pszParmName);
3784
3785         while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
3786
3787
3788         if (parmnum < 0 && strchr(pszParmName, ':')) {
3789                 /* set a parametric option */
3790                 return lp_do_parameter_parametric(lp_ctx, NULL, pszParmName,
3791                                                   pszParmValue, FLAG_CMDLINE);
3792         }
3793
3794         if (parmnum < 0) {
3795                 DEBUG(0,("Unknown option '%s'\n", pszParmName));
3796                 return false;
3797         }
3798
3799         /* reset the CMDLINE flag in case this has been called before */
3800         lp_ctx->flags[parmnum] &= ~FLAG_CMDLINE;
3801
3802         if (!lpcfg_do_global_parameter(lp_ctx, pszParmName, pszParmValue)) {
3803                 return false;
3804         }
3805
3806         lp_ctx->flags[parmnum] |= FLAG_CMDLINE;
3807
3808         /* we have to also set FLAG_CMDLINE on aliases */
3809         for (i=parmnum-1;i>=0 && parm_table[i].offset == parm_table[parmnum].offset;i--) {
3810                 lp_ctx->flags[i] |= FLAG_CMDLINE;
3811         }
3812         for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset;i++) {
3813                 lp_ctx->flags[i] |= FLAG_CMDLINE;
3814         }
3815
3816         return true;
3817 }
3818
3819 /*
3820   set a option from the commandline in 'a=b' format. Use to support --option
3821 */
3822 bool lpcfg_set_option(struct loadparm_context *lp_ctx, const char *option)
3823 {
3824         char *p, *s;
3825         bool ret;
3826
3827         s = talloc_strdup(NULL, option);
3828         if (!s) {
3829                 return false;
3830         }
3831
3832         p = strchr(s, '=');
3833         if (!p) {
3834                 talloc_free(s);
3835                 return false;
3836         }
3837
3838         *p = 0;
3839
3840         ret = lpcfg_set_cmdline(lp_ctx, s, p+1);
3841         talloc_free(s);
3842         return ret;
3843 }
3844
3845
3846 #define BOOLSTR(b) ((b) ? "Yes" : "No")
3847
3848 /**
3849  * Print a parameter of the specified type.
3850  */
3851
3852 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
3853 {
3854         /* For the seperation of lists values that we print below */
3855         const char *list_sep = ", ";
3856         int i;
3857         switch (p->type)
3858         {
3859                 case P_ENUM:
3860                         for (i = 0; p->enum_list[i].name; i++) {
3861                                 if (*(int *)ptr == p->enum_list[i].value) {
3862                                         fprintf(f, "%s",
3863                                                 p->enum_list[i].name);
3864                                         break;
3865                                 }
3866                         }
3867                         break;
3868
3869                 case P_BOOL:
3870                         fprintf(f, "%s", BOOLSTR(*(bool *)ptr));
3871                         break;
3872
3873                 case P_BOOLREV:
3874                         fprintf(f, "%s", BOOLSTR(!*(bool *)ptr));
3875                         break;
3876
3877                 case P_INTEGER:
3878                 case P_BYTES:
3879                         fprintf(f, "%d", *(int *)ptr);
3880                         break;
3881
3882                 case P_CHAR:
3883                         fprintf(f, "%c", *(char *)ptr);
3884                         break;
3885
3886                 case P_OCTAL: {
3887                         int val = *(int *)ptr; 
3888                         if (val == -1) {
3889                                 fprintf(f, "-1");
3890                         } else {
3891                                 fprintf(f, "0%o", val);
3892                         }
3893                         break;
3894                 }
3895
3896                 case P_CMDLIST:
3897                         list_sep = " ";
3898                         /* fall through */
3899                 case P_LIST:
3900                         if ((char ***)ptr && *(char ***)ptr) {
3901                                 char **list = *(char ***)ptr;
3902                                 for (; *list; list++) {
3903                                         /* surround strings with whitespace in double quotes */
3904                                         if (*(list+1) == NULL) {
3905                                                 /* last item, no extra separator */
3906                                                 list_sep = "";
3907                                         }
3908                                         if ( strchr_m( *list, ' ' ) ) {
3909                                                 fprintf(f, "\"%s\"%s", *list, list_sep);
3910                                         } else {
3911                                                 fprintf(f, "%s%s", *list, list_sep);
3912                                         }
3913                                 }
3914                         }
3915                         break;
3916
3917                 case P_STRING:
3918                 case P_USTRING:
3919                         if (*(char **)ptr) {
3920                                 fprintf(f, "%s", *(char **)ptr);
3921                         }
3922                         break;
3923                 case P_SEP:
3924                         break;
3925         }
3926 }
3927
3928 /**
3929  * Check if two parameters are equal.
3930  */
3931
3932 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
3933 {
3934         switch (type) {
3935                 case P_BOOL:
3936                 case P_BOOLREV:
3937                         return (*((bool *)ptr1) == *((bool *)ptr2));
3938
3939                 case P_INTEGER:
3940                 case P_ENUM:
3941                 case P_OCTAL:
3942                 case P_BYTES:
3943                         return (*((int *)ptr1) == *((int *)ptr2));
3944
3945                 case P_CHAR:
3946                         return (*((char *)ptr1) == *((char *)ptr2));
3947
3948                 case P_LIST:
3949                 case P_CMDLIST:
3950                         return str_list_equal(*(const char ***)ptr1, *(const char ***)ptr2);
3951
3952                 case P_STRING:
3953                 case P_USTRING:
3954                 {
3955                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
3956                         if (p1 && !*p1)
3957                                 p1 = NULL;
3958                         if (p2 && !*p2)
3959                                 p2 = NULL;
3960                         return (p1 == p2 || strequal(p1, p2));
3961                 }
3962                 case P_SEP:
3963                         break;
3964         }
3965         return false;
3966 }
3967
3968 /**
3969  * Process a new section (service).
3970  *
3971  * At this stage all sections are services.
3972  * Later we'll have special sections that permit server parameters to be set.
3973  * Returns True on success, False on failure.
3974  */
3975
3976 static bool do_section(const char *pszSectionName, void *userdata)
3977 {
3978         struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata;
3979         bool bRetval;
3980         bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
3981                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
3982         bRetval = false;
3983
3984         /* if we've just struck a global section, note the fact. */
3985         lp_ctx->bInGlobalSection = isglobal;
3986
3987         /* check for multiple global sections */
3988         if (lp_ctx->bInGlobalSection) {
3989                 DEBUG(4, ("Processing section \"[%s]\"\n", pszSectionName));
3990                 return true;
3991         }
3992
3993         /* if we have a current service, tidy it up before moving on */
3994         bRetval = true;
3995
3996         if (lp_ctx->currentService != NULL)
3997                 bRetval = lpcfg_service_ok(lp_ctx->currentService);
3998
3999         /* if all is still well, move to the next record in the services array */
4000         if (bRetval) {
4001                 /* We put this here to avoid an odd message order if messages are */
4002                 /* issued by the post-processing of a previous section. */
4003                 DEBUG(4, ("Processing section \"[%s]\"\n", pszSectionName));
4004
4005                 if ((lp_ctx->currentService = lpcfg_add_service(lp_ctx, lp_ctx->sDefault,
4006                                                                    pszSectionName))
4007                     == NULL) {
4008                         DEBUG(0, ("Failed to add a new service\n"));
4009                         return false;
4010                 }
4011         }
4012
4013         return bRetval;
4014 }
4015
4016
4017 /**
4018  * Determine if a particular base parameter is currently set to the default value.
4019  */
4020
4021 static bool is_default(struct loadparm_service *sDefault, int i)
4022 {
4023         void *def_ptr = ((char *)sDefault) + parm_table[i].offset;
4024         if (!defaults_saved)
4025                 return false;
4026         switch (parm_table[i].type) {
4027                 case P_CMDLIST:
4028                 case P_LIST:
4029                         return str_list_equal((const char **)parm_table[i].def.lvalue, 
4030                                               (const char **)def_ptr);
4031                 case P_STRING:
4032                 case P_USTRING:
4033                         return strequal(parm_table[i].def.svalue,
4034                                         *(char **)def_ptr);
4035                 case P_BOOL:
4036                 case P_BOOLREV:
4037                         return parm_table[i].def.bvalue ==
4038                                 *(bool *)def_ptr;
4039                 case P_INTEGER:
4040                 case P_CHAR:
4041                 case P_OCTAL:
4042                 case P_BYTES:
4043                 case P_ENUM:
4044                         return parm_table[i].def.ivalue ==
4045                                 *(int *)def_ptr;
4046                 case P_SEP:
4047                         break;
4048         }
4049         return false;
4050 }
4051
4052 /**
4053  *Display the contents of the global structure.
4054  */
4055
4056 static void dump_globals(struct loadparm_context *lp_ctx, FILE *f,
4057                          bool show_defaults)
4058 {
4059         int i;
4060         struct parmlist_entry *data;
4061
4062         fprintf(f, "# Global parameters\n[global]\n");
4063
4064         for (i = 0; parm_table[i].label; i++)
4065                 if (parm_table[i].p_class == P_GLOBAL &&
4066                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
4067                         if (!show_defaults && (lp_ctx->flags[i] & FLAG_DEFAULT))
4068                                 continue;
4069                         fprintf(f, "\t%s = ", parm_table[i].label);
4070                         print_parameter(&parm_table[i], lpcfg_parm_ptr(lp_ctx, NULL, &parm_table[i]), f);
4071                         fprintf(f, "\n");
4072         }
4073         if (lp_ctx->globals->param_opt != NULL) {
4074                 for (data = lp_ctx->globals->param_opt; data;
4075                      data = data->next) {
4076                         if (!show_defaults && (data->priority & FLAG_DEFAULT)) {
4077                                 continue;
4078                         }
4079                         fprintf(f, "\t%s = %s\n", data->key, data->value);
4080                 }
4081         }
4082
4083 }
4084
4085 /**
4086  * Display the contents of a single services record.
4087  */
4088
4089 static void dump_a_service(struct loadparm_service * pService, struct loadparm_service *sDefault, FILE * f,
4090                            unsigned int *flags)
4091 {
4092         int i;
4093         struct parmlist_entry *data;
4094
4095         if (pService != sDefault)
4096                 fprintf(f, "\n[%s]\n", pService->szService);
4097
4098         for (i = 0; parm_table[i].label; i++) {
4099                 if (parm_table[i].p_class == P_LOCAL &&
4100                     (*parm_table[i].label != '-') &&
4101                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset)))
4102                 {
4103                         if (pService == sDefault) {
4104                                 if (flags && (flags[i] & FLAG_DEFAULT)) {
4105                                         continue;
4106                                 }
4107                                 if (defaults_saved) {
4108                                         if (is_default(sDefault, i)) {
4109                                                 continue;
4110                                         }
4111                                 }
4112                         } else {
4113                                 if (equal_parameter(parm_table[i].type,
4114                                                     ((char *)pService) +
4115                                                     parm_table[i].offset,
4116                                                     ((char *)sDefault) +
4117                                                     parm_table[i].offset))
4118                                         continue;
4119                         }
4120
4121                         fprintf(f, "\t%s = ", parm_table[i].label);
4122                         print_parameter(&parm_table[i],
4123                                         ((char *)pService) + parm_table[i].offset, f);
4124                         fprintf(f, "\n");
4125                 }
4126         }
4127         if (pService->param_opt != NULL) {
4128                 for (data = pService->param_opt; data; data = data->next) {
4129                         fprintf(f, "\t%s = %s\n", data->key, data->value);
4130                 }
4131         }
4132 }
4133
4134 bool lpcfg_dump_a_parameter(struct loadparm_context *lp_ctx,
4135                             struct loadparm_service *service,
4136                             const char *parm_name, FILE * f)
4137 {
4138         struct parm_struct *parm;
4139         void *ptr;
4140
4141         parm = lpcfg_parm_struct(lp_ctx, parm_name);
4142         if (!parm) {
4143                 return false;
4144         }
4145
4146         ptr = lpcfg_parm_ptr(lp_ctx, service,parm);
4147
4148         print_parameter(parm, ptr, f);
4149         fprintf(f, "\n");
4150         return true;
4151 }
4152
4153 /**
4154  * Return info about the next parameter in a service.
4155  * snum==-1 gives the globals.
4156  * Return NULL when out of parameters.
4157  */
4158
4159
4160 struct parm_struct *lpcfg_next_parameter(struct loadparm_context *lp_ctx, int snum, int *i,
4161                                          int allparameters)
4162 {
4163         if (snum == -1) {
4164                 /* do the globals */
4165                 for (; parm_table[*i].label; (*i)++) {
4166                         if ((*parm_table[*i].label == '-'))
4167                                 continue;
4168
4169                         if ((*i) > 0
4170                             && (parm_table[*i].offset ==
4171                                 parm_table[(*i) - 1].offset)
4172                             && (parm_table[*i].p_class ==
4173                                 parm_table[(*i) - 1].p_class))
4174                                 continue;
4175
4176                         return &parm_table[(*i)++];
4177                 }
4178         } else {
4179                 struct loadparm_service *pService = lp_ctx->services[snum];
4180
4181                 for (; parm_table[*i].label; (*i)++) {
4182                         if (parm_table[*i].p_class == P_LOCAL &&
4183                             (*parm_table[*i].label != '-') &&
4184                             ((*i) == 0 ||
4185                              (parm_table[*i].offset !=
4186                               parm_table[(*i) - 1].offset)))
4187                         {
4188                                 if (allparameters ||
4189                                     !equal_parameter(parm_table[*i].type,
4190                                                      ((char *)pService) +
4191                                                      parm_table[*i].offset,
4192                                                      ((char *)lp_ctx->sDefault) +
4193                                                      parm_table[*i].offset))
4194                                 {
4195                                         return &parm_table[(*i)++];
4196                                 }
4197                         }
4198                 }
4199         }
4200
4201         return NULL;
4202 }
4203
4204
4205 /**
4206  * Auto-load some home services.
4207  */
4208 static void lpcfg_add_auto_services(struct loadparm_context *lp_ctx,
4209                                     const char *str)
4210 {
4211         return;
4212 }
4213
4214
4215 /**
4216  * Unload unused services.
4217  */
4218
4219 void lpcfg_killunused(struct loadparm_context *lp_ctx,
4220                    struct smbsrv_connection *smb,
4221                    bool (*snumused) (struct smbsrv_connection *, int))
4222 {
4223         int i;
4224         for (i = 0; i < lp_ctx->iNumServices; i++) {
4225                 if (lp_ctx->services[i] == NULL)
4226                         continue;
4227
4228                 if (!snumused || !snumused(smb, i)) {
4229                         talloc_free(lp_ctx->services[i]);
4230                         lp_ctx->services[i] = NULL;
4231                 }
4232         }
4233 }
4234
4235
4236 static int lpcfg_destructor(struct loadparm_context *lp_ctx)
4237 {
4238         struct parmlist_entry *data;
4239
4240         if (lp_ctx->refuse_free) {
4241                 /* someone is trying to free the
4242                    global_loadparm_context.
4243                    We can't allow that. */
4244                 return -1;
4245         }
4246
4247         if (lp_ctx->globals->param_opt != NULL) {
4248                 struct parmlist_entry *next;
4249                 for (data = lp_ctx->globals->param_opt; data; data=next) {
4250                         next = data->next;
4251                         if (data->priority & FLAG_CMDLINE) continue;
4252                         DLIST_REMOVE(lp_ctx->globals->param_opt, data);
4253                         talloc_free(data);
4254                 }
4255         }
4256
4257         return 0;
4258 }
4259
4260 /**
4261  * Initialise the global parameter structure.
4262  *
4263  * Note that most callers should use loadparm_init_global() instead
4264  */
4265 struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
4266 {
4267         int i;
4268         char *myname;
4269         struct loadparm_context *lp_ctx;
4270         struct parmlist_entry *parm;
4271         char *logfile;
4272
4273         lp_ctx = talloc_zero(mem_ctx, struct loadparm_context);
4274         if (lp_ctx == NULL)
4275                 return NULL;
4276
4277         talloc_set_destructor(lp_ctx, lpcfg_destructor);
4278         lp_ctx->bInGlobalSection = true;
4279         lp_ctx->globals = talloc_zero(lp_ctx, struct loadparm_global);
4280         lp_ctx->sDefault = talloc_zero(lp_ctx, struct loadparm_service);
4281
4282         lp_ctx->sDefault->iMaxPrintJobs = 1000;
4283         lp_ctx->sDefault->bAvailable = true;
4284         lp_ctx->sDefault->bBrowseable = true;
4285         lp_ctx->sDefault->bRead_only = true;
4286         lp_ctx->sDefault->bMap_archive = true;
4287         lp_ctx->sDefault->iStrictLocking = true;
4288         lp_ctx->sDefault->bOpLocks = true;
4289         lp_ctx->sDefault->iCreate_mask = 0744;
4290         lp_ctx->sDefault->iCreate_force_mode = 0000;
4291         lp_ctx->sDefault->iDir_mask = 0755;
4292         lp_ctx->sDefault->iDir_force_mode = 0000;
4293
4294         DEBUG(3, ("Initialising global parameters\n"));
4295
4296         for (i = 0; parm_table[i].label; i++) {
4297                 if ((parm_table[i].type == P_STRING ||
4298                      parm_table[i].type == P_USTRING) &&
4299                     !(lp_ctx->flags[i] & FLAG_CMDLINE)) {
4300                         char **r;
4301                         if (parm_table[i].p_class == P_LOCAL) {
4302                                 r = (char **)(((char *)lp_ctx->sDefault) + parm_table[i].offset);
4303                         } else {
4304                                 r = (char **)(((char *)lp_ctx->globals) + parm_table[i].offset);
4305                         }
4306                         *r = talloc_strdup(lp_ctx, "");
4307                 }
4308         }
4309
4310         logfile = talloc_asprintf(lp_ctx, "%s/log.samba", dyn_LOGFILEBASE);
4311         lpcfg_do_global_parameter(lp_ctx, "log file", logfile);
4312         talloc_free(logfile);
4313
4314         lpcfg_do_global_parameter(lp_ctx, "log level", "0");
4315
4316         lpcfg_do_global_parameter(lp_ctx, "share backend", "classic");
4317
4318         lpcfg_do_global_parameter(lp_ctx, "server role", "auto");
4319         lpcfg_do_global_parameter(lp_ctx, "domain logons", "No");
4320         lpcfg_do_global_parameter(lp_ctx, "domain master", "Auto");
4321
4322         /* options that can be set on the command line must be initialised via
4323            the slower lpcfg_do_global_parameter() to ensure that FLAG_CMDLINE is obeyed */
4324 #ifdef TCP_NODELAY
4325         lpcfg_do_global_parameter(lp_ctx, "socket options", "TCP_NODELAY");
4326 #endif
4327         lpcfg_do_global_parameter(lp_ctx, "workgroup", DEFAULT_WORKGROUP);
4328         myname = get_myname(lp_ctx);
4329         lpcfg_do_global_parameter(lp_ctx, "netbios name", myname);
4330         talloc_free(myname);
4331         lpcfg_do_global_parameter(lp_ctx, "name resolve order", "wins host bcast");
4332
4333         lpcfg_do_global_parameter(lp_ctx, "fstype", "NTFS");
4334
4335         lpcfg_do_global_parameter(lp_ctx, "ntvfs handler", "unixuid default");
4336         lpcfg_do_global_parameter(lp_ctx, "max connections", "-1");
4337
4338         lpcfg_do_global_parameter(lp_ctx, "dcerpc endpoint servers", "epmapper wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi dssetup unixinfo browser eventlog6 backupkey dnsserver");
4339         lpcfg_do_global_parameter(lp_ctx, "server services", "s3fs rpc nbt wrepl ldap cldap kdc drepl winbind ntp_signd kcc dnsupdate");
4340         /* the winbind method for domain controllers is for both RODC
4341            auth forwarding and for trusted domains */
4342         lpcfg_do_global_parameter(lp_ctx, "private dir", dyn_PRIVATE_DIR);
4343         lpcfg_do_global_parameter(lp_ctx, "registry:HKEY_LOCAL_MACHINE", "hklm.ldb");
4344
4345         /* This hive should be dynamically generated by Samba using
4346            data from the sam, but for the moment leave it in a tdb to
4347            keep regedt32 from popping up an annoying dialog. */
4348         lpcfg_do_global_parameter(lp_ctx, "registry:HKEY_USERS", "hku.ldb");
4349
4350         /* using UTF8 by default allows us to support all chars */
4351         lpcfg_do_global_parameter(lp_ctx, "unix charset", "UTF8");
4352
4353         /* Use codepage 850 as a default for the dos character set */
4354         lpcfg_do_global_parameter(lp_ctx, "dos charset", "CP850");
4355
4356         /*
4357          * Allow the default PASSWD_CHAT to be overridden in local.h.
4358          */
4359         lpcfg_do_global_parameter(lp_ctx, "passwd chat", DEFAULT_PASSWD_CHAT);
4360
4361         lpcfg_do_global_parameter(lp_ctx, "pid directory", dyn_PIDDIR);
4362         lpcfg_do_global_parameter(lp_ctx, "lock dir", dyn_LOCKDIR);
4363         lpcfg_do_global_parameter(lp_ctx, "state directory", dyn_STATEDIR);
4364         lpcfg_do_global_parameter(lp_ctx, "cache directory", dyn_CACHEDIR);
4365         lpcfg_do_global_parameter(lp_ctx, "ncalrpc dir", dyn_NCALRPCDIR);
4366
4367         lpcfg_do_global_parameter(lp_ctx, "socket address", "");
4368         lpcfg_do_global_parameter_var(lp_ctx, "server string",
4369                                    "Samba %s", SAMBA_VERSION_STRING);
4370
4371         lpcfg_do_global_parameter(lp_ctx, "password server", "*");
4372
4373         lpcfg_do_global_parameter(lp_ctx, "max mux", "50");
4374         lpcfg_do_global_parameter(lp_ctx, "max xmit", "12288");
4375         lpcfg_do_global_parameter(lp_ctx, "host msdfs", "true");
4376
4377         lpcfg_do_global_parameter(lp_ctx, "password level", "0");
4378         lpcfg_do_global_parameter(lp_ctx, "LargeReadwrite", "True");
4379         lpcfg_do_global_parameter(lp_ctx, "server min protocol", "CORE");
4380         lpcfg_do_global_parameter(lp_ctx, "server max protocol", "NT1");
4381         lpcfg_do_global_parameter(lp_ctx, "client min protocol", "CORE");
4382         lpcfg_do_global_parameter(lp_ctx, "client max protocol", "NT1");
4383         lpcfg_do_global_parameter(lp_ctx, "security", "AUTO");
4384         lpcfg_do_global_parameter(lp_ctx, "paranoid server security", "True");
4385         lpcfg_do_global_parameter(lp_ctx, "EncryptPasswords", "True");
4386         lpcfg_do_global_parameter(lp_ctx, "ReadRaw", "True");
4387         lpcfg_do_global_parameter(lp_ctx, "WriteRaw", "True");
4388         lpcfg_do_global_parameter(lp_ctx, "NullPasswords", "False");
4389         lpcfg_do_global_parameter(lp_ctx, "ObeyPamRestrictions", "False");
4390
4391         lpcfg_do_global_parameter(lp_ctx, "TimeServer", "False");
4392         lpcfg_do_global_parameter(lp_ctx, "BindInterfacesOnly", "False");
4393         lpcfg_do_global_parameter(lp_ctx, "Unicode", "True");
4394         lpcfg_do_global_parameter(lp_ctx, "ClientLanManAuth", "False");
4395         lpcfg_do_global_parameter(lp_ctx, "ClientNTLMv2Auth", "True");
4396         lpcfg_do_global_parameter(lp_ctx, "LanmanAuth", "False");
4397         lpcfg_do_global_parameter(lp_ctx, "NTLMAuth", "True");
4398         lpcfg_do_global_parameter(lp_ctx, "client use spnego principal", "False");
4399
4400         lpcfg_do_global_parameter(lp_ctx, "UnixExtensions", "False");
4401
4402         lpcfg_do_global_parameter(lp_ctx, "PreferredMaster", "Auto");
4403         lpcfg_do_global_parameter(lp_ctx, "LocalMaster", "True");
4404
4405         lpcfg_do_global_parameter(lp_ctx, "wins support", "False");
4406         lpcfg_do_global_parameter(lp_ctx, "dns proxy", "True");
4407
4408         lpcfg_do_global_parameter(lp_ctx, "winbind separator", "\\");
4409         lpcfg_do_global_parameter(lp_ctx, "winbind sealed pipes", "True");
4410         lpcfg_do_global_parameter(lp_ctx, "winbindd socket directory", dyn_WINBINDD_SOCKET_DIR);
4411 #if _SAMBA_BUILD_ >= 4
4412         lpcfg_do_global_parameter(lp_ctx, "winbindd privileged socket directory", dyn_WINBINDD_PRIVILEGED_SOCKET_DIR);
4413         lpcfg_do_global_parameter(lp_ctx, "ntp signd socket directory", dyn_NTP_SIGND_SOCKET_DIR);
4414         lpcfg_do_global_parameter_var(lp_ctx, "dns update command", "%s/samba_dnsupdate", dyn_SCRIPTSBINDIR);
4415         lpcfg_do_global_parameter_var(lp_ctx, "spn update command", "%s/samba_spnupdate", dyn_SCRIPTSBINDIR);
4416         lpcfg_do_global_parameter_var(lp_ctx, "samba kcc command",
4417                                         "%s/samba_kcc", dyn_SCRIPTSBINDIR);
4418 #endif
4419         lpcfg_do_global_parameter(lp_ctx, "template shell", "/bin/false");
4420         lpcfg_do_global_parameter(lp_ctx, "template homedir", "/home/%WORKGROUP%/%ACCOUNTNAME%");
4421
4422         lpcfg_do_global_parameter(lp_ctx, "client signing", "default");
4423         lpcfg_do_global_parameter(lp_ctx, "server signing", "default");
4424
4425         lpcfg_do_global_parameter(lp_ctx, "use spnego", "True");
4426
4427         lpcfg_do_global_parameter(lp_ctx, "use mmap", "True");
4428
4429         lpcfg_do_global_parameter(lp_ctx, "smb ports", "445 139");
4430         lpcfg_do_global_parameter(lp_ctx, "nbt port", "137");
4431         lpcfg_do_global_parameter(lp_ctx, "dgram port", "138");
4432         lpcfg_do_global_parameter(lp_ctx, "cldap port", "389");
4433         lpcfg_do_global_parameter(lp_ctx, "krb5 port", "88");
4434         lpcfg_do_global_parameter(lp_ctx, "kpasswd port", "464");
4435         lpcfg_do_global_parameter(lp_ctx, "web port", "901");
4436
4437         lpcfg_do_global_parameter(lp_ctx, "nt status support", "True");
4438
4439         lpcfg_do_global_parameter(lp_ctx, "max wins ttl", "518400"); /* 6 days */
4440         lpcfg_do_global_parameter(lp_ctx, "min wins ttl", "10");
4441
4442         lpcfg_do_global_parameter(lp_ctx, "tls enabled", "True");
4443         lpcfg_do_global_parameter(lp_ctx, "tls keyfile", "tls/key.pem");
4444         lpcfg_do_global_parameter(lp_ctx, "tls certfile", "tls/cert.pem");
4445         lpcfg_do_global_parameter(lp_ctx, "tls cafile", "tls/ca.pem");
4446         lpcfg_do_global_parameter(lp_ctx, "prefork children:smb", "4");
4447
4448         lpcfg_do_global_parameter(lp_ctx, "rndc command", "/usr/sbin/rndc");
4449         lpcfg_do_global_parameter(lp_ctx, "nsupdate command", "/usr/bin/nsupdate -g");
4450
4451         lpcfg_do_global_parameter(lp_ctx, "allow dns updates", "False");
4452         lpcfg_do_global_parameter(lp_ctx, "dns recursive queries", "False");
4453         lpcfg_do_global_parameter(lp_ctx, "dns forwarder", "");
4454
4455         for (i = 0; parm_table[i].label; i++) {
4456                 if (!(lp_ctx->flags[i] & FLAG_CMDLINE)) {
4457                         lp_ctx->flags[i] |= FLAG_DEFAULT;
4458                 }
4459         }
4460
4461         for (parm=lp_ctx->globals->param_opt; parm; parm=parm->next) {
4462                 if (!(parm->priority & FLAG_CMDLINE)) {
4463                         parm->priority |= FLAG_DEFAULT;
4464                 }
4465         }
4466
4467         return lp_ctx;
4468 }
4469
4470 /**
4471  * Initialise the global parameter structure.
4472  */
4473 struct loadparm_context *loadparm_init_global(bool load_default)
4474 {
4475         if (global_loadparm_context == NULL) {
4476                 global_loadparm_context = loadparm_init(NULL);
4477         }
4478         if (global_loadparm_context == NULL) {
4479                 return NULL;
4480         }
4481         global_loadparm_context->global = true;
4482         if (load_default && !global_loadparm_context->loaded) {
4483                 lpcfg_load_default(global_loadparm_context);
4484         }
4485         global_loadparm_context->refuse_free = true;
4486         return global_loadparm_context;
4487 }
4488
4489 /**
4490  * Initialise the global parameter structure.
4491  */
4492 struct loadparm_context *loadparm_init_s3(TALLOC_CTX *mem_ctx, 
4493                                           const struct loadparm_s3_helpers *s3_fns)
4494 {
4495         struct loadparm_context *loadparm_context = talloc_zero(mem_ctx, struct loadparm_context);
4496         if (!loadparm_context) {
4497                 return NULL;
4498         }
4499         loadparm_context->s3_fns = s3_fns;
4500         return loadparm_context;
4501 }
4502
4503 const char *lpcfg_configfile(struct loadparm_context *lp_ctx)
4504 {
4505         return lp_ctx->szConfigFile;
4506 }
4507
4508 const char *lp_default_path(void)
4509 {
4510     if (getenv("SMB_CONF_PATH"))
4511         return getenv("SMB_CONF_PATH");
4512     else
4513         return dyn_CONFIGFILE;
4514 }
4515
4516 /**
4517  * Update the internal state of a loadparm context after settings 
4518  * have changed.
4519  */
4520 static bool lpcfg_update(struct loadparm_context *lp_ctx)
4521 {
4522         struct debug_settings settings;
4523         lpcfg_add_auto_services(lp_ctx, lpcfg_auto_services(lp_ctx));
4524
4525         if (!lp_ctx->globals->szWINSservers && lp_ctx->globals->bWINSsupport) {
4526                 lpcfg_do_global_parameter(lp_ctx, "wins server", "127.0.0.1");
4527         }
4528
4529         if (!lp_ctx->global) {
4530                 return true;
4531         }
4532
4533         panic_action = lp_ctx->globals->panic_action;
4534
4535         reload_charcnv(lp_ctx);
4536
4537         ZERO_STRUCT(settings);
4538         /* Add any more debug-related smb.conf parameters created in
4539          * future here */
4540         settings.timestamp_logs = true;
4541         debug_set_settings(&settings);
4542
4543         /* FIXME: This is a bit of a hack, but we can't use a global, since 
4544          * not everything that uses lp also uses the socket library */
4545         if (lpcfg_parm_bool(lp_ctx, NULL, "socket", "testnonblock", false)) {
4546                 setenv("SOCKET_TESTNONBLOCK", "1", 1);
4547         } else {
4548                 unsetenv("SOCKET_TESTNONBLOCK");
4549         }
4550
4551         return true;
4552 }
4553
4554 bool lpcfg_load_default(struct loadparm_context *lp_ctx)
4555 {
4556     const char *path;
4557
4558     path = lp_default_path();
4559
4560     if (!file_exist(path)) {
4561             /* We allow the default smb.conf file to not exist, 
4562              * basically the equivalent of an empty file. */
4563             return lpcfg_update(lp_ctx);
4564     }
4565
4566     return lpcfg_load(lp_ctx, path);
4567 }
4568
4569 /**
4570  * Load the services array from the services file.
4571  *
4572  * Return True on success, False on failure.
4573  */
4574 bool lpcfg_load(struct loadparm_context *lp_ctx, const char *filename)
4575 {
4576         char *n2;
4577         bool bRetval;
4578
4579         filename = talloc_strdup(lp_ctx, filename);
4580
4581         lp_ctx->szConfigFile = filename;
4582
4583         if (lp_ctx->s3_fns) {
4584                 return lp_ctx->s3_fns->load(filename);
4585         }
4586
4587         lp_ctx->bInGlobalSection = true;
4588         n2 = standard_sub_basic(lp_ctx, lp_ctx->szConfigFile);
4589         DEBUG(2, ("lpcfg_load: refreshing parameters from %s\n", n2));
4590
4591         add_to_file_list(lp_ctx, lp_ctx->szConfigFile, n2);
4592
4593         /* We get sections first, so have to start 'behind' to make up */
4594         lp_ctx->currentService = NULL;
4595         bRetval = pm_process(n2, do_section, do_parameter, lp_ctx);
4596
4597         /* finish up the last section */
4598         DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
4599         if (bRetval)
4600                 if (lp_ctx->currentService != NULL)
4601                         bRetval = lpcfg_service_ok(lp_ctx->currentService);
4602
4603         bRetval = bRetval && lpcfg_update(lp_ctx);
4604
4605         /* we do this unconditionally, so that it happens even
4606            for a missing smb.conf */
4607         reload_charcnv(lp_ctx);
4608
4609         if (bRetval == true) {
4610                 /* set this up so that any child python tasks will
4611                    find the right smb.conf */
4612                 setenv("SMB_CONF_PATH", filename, 1);
4613
4614                 /* set the context used by the lp_*() function
4615                    varients */
4616                 global_loadparm_context = lp_ctx;
4617                 lp_ctx->loaded = true;
4618         }
4619
4620         return bRetval;
4621 }
4622
4623 /**
4624  * Return the max number of services.
4625  */
4626
4627 int lpcfg_numservices(struct loadparm_context *lp_ctx)
4628 {
4629         if (lp_ctx->s3_fns) {
4630                 return lp_ctx->s3_fns->get_numservices();
4631         }
4632
4633         return lp_ctx->iNumServices;
4634 }
4635
4636 /**
4637  * Display the contents of the services array in human-readable form.
4638  */
4639
4640 void lpcfg_dump(struct loadparm_context *lp_ctx, FILE *f, bool show_defaults,
4641              int maxtoprint)
4642 {
4643         int iService;
4644
4645         if (lp_ctx->s3_fns) {
4646                 lp_ctx->s3_fns->dump(f, show_defaults, maxtoprint);
4647                 return;
4648         }
4649
4650         defaults_saved = !show_defaults;
4651
4652         dump_globals(lp_ctx, f, show_defaults);
4653
4654         dump_a_service(lp_ctx->sDefault, lp_ctx->sDefault, f, lp_ctx->flags);
4655
4656         for (iService = 0; iService < maxtoprint; iService++)
4657                 lpcfg_dump_one(f, show_defaults, lp_ctx->services[iService], lp_ctx->sDefault);
4658 }
4659
4660 /**
4661  * Display the contents of one service in human-readable form.
4662  */
4663 void lpcfg_dump_one(FILE *f, bool show_defaults, struct loadparm_service *service, struct loadparm_service *sDefault)
4664 {
4665         if (service != NULL) {
4666                 if (service->szService[0] == '\0')
4667                         return;
4668                 dump_a_service(service, sDefault, f, NULL);
4669         }
4670 }
4671
4672 struct loadparm_service *lpcfg_servicebynum(struct loadparm_context *lp_ctx,
4673                                             int snum)
4674 {
4675         if (lp_ctx->s3_fns) {
4676                 return lp_ctx->s3_fns->get_servicebynum(snum);
4677         }
4678
4679         return lp_ctx->services[snum];
4680 }
4681
4682 struct loadparm_service *lpcfg_service(struct loadparm_context *lp_ctx,
4683                                     const char *service_name)
4684 {
4685         int iService;
4686         char *serviceName;
4687
4688         if (lp_ctx->s3_fns) {
4689                 return lp_ctx->s3_fns->get_service(service_name);
4690         }
4691
4692         for (iService = lp_ctx->iNumServices - 1; iService >= 0; iService--) {
4693                 if (lp_ctx->services[iService] &&
4694                     lp_ctx->services[iService]->szService) {
4695                         /*
4696                          * The substitution here is used to support %U is
4697                          * service names
4698                          */
4699                         serviceName = standard_sub_basic(
4700                                         lp_ctx->services[iService],
4701                                         lp_ctx->services[iService]->szService);
4702                         if (strequal(serviceName, service_name)) {
4703                                 talloc_free(serviceName);
4704                                 return lp_ctx->services[iService];
4705                         }
4706                         talloc_free(serviceName);
4707                 }
4708         }
4709
4710         DEBUG(7,("lpcfg_servicenumber: couldn't find %s\n", service_name));
4711         return NULL;
4712 }
4713
4714 const char *lpcfg_servicename(const struct loadparm_service *service)
4715 {
4716         return lp_string((const char *)service->szService);
4717 }
4718
4719 /**
4720  * A useful volume label function.
4721  */
4722 const char *lpcfg_volume_label(struct loadparm_service *service, struct loadparm_service *sDefault)
4723 {
4724         const char *ret;
4725         ret = lp_string((const char *)((service != NULL && service->volume != NULL) ?
4726                                        service->volume : sDefault->volume));
4727         if (!*ret)
4728                 return lpcfg_servicename(service);
4729         return ret;
4730 }
4731
4732 /**
4733  * If we are PDC then prefer us as DMB
4734  */
4735 const char *lpcfg_printername(struct loadparm_service *service, struct loadparm_service *sDefault)
4736 {
4737         const char *ret;
4738         ret = lp_string((const char *)((service != NULL && service->szPrintername != NULL) ?
4739                                        service->szPrintername : sDefault->szPrintername));
4740         if (ret == NULL || (ret != NULL && *ret == '\0'))
4741                 ret = lpcfg_servicename(service);
4742
4743         return ret;
4744 }
4745
4746
4747 /**
4748  * Return the max print jobs per queue.
4749  */
4750 int lpcfg_maxprintjobs(struct loadparm_service *service, struct loadparm_service *sDefault)
4751 {
4752         int maxjobs = (service != NULL) ? service->iMaxPrintJobs : sDefault->iMaxPrintJobs;
4753         if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
4754                 maxjobs = PRINT_MAX_JOBID - 1;
4755
4756         return maxjobs;
4757 }
4758
4759 struct smb_iconv_handle *lpcfg_iconv_handle(struct loadparm_context *lp_ctx)
4760 {
4761         if (lp_ctx == NULL) {
4762                 return get_iconv_handle();
4763         }
4764         return lp_ctx->iconv_handle;
4765 }
4766
4767 _PUBLIC_ void reload_charcnv(struct loadparm_context *lp_ctx)
4768 {
4769         struct smb_iconv_handle *old_ic = lp_ctx->iconv_handle;
4770         if (!lp_ctx->global) {
4771                 return;
4772         }
4773
4774         if (old_ic == NULL) {
4775                 old_ic = global_iconv_handle;
4776         }
4777         lp_ctx->iconv_handle = smb_iconv_handle_reinit_lp(lp_ctx, lp_ctx, old_ic);
4778         global_iconv_handle = lp_ctx->iconv_handle;
4779 }
4780
4781 _PUBLIC_ char *lpcfg_tls_keyfile(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
4782 {
4783         return lpcfg_private_path(mem_ctx, lp_ctx, lp_ctx->globals->tls_keyfile);
4784 }
4785
4786 _PUBLIC_ char *lpcfg_tls_certfile(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
4787 {
4788         return lpcfg_private_path(mem_ctx, lp_ctx, lp_ctx->globals->tls_certfile);
4789 }
4790
4791 _PUBLIC_ char *lpcfg_tls_cafile(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
4792 {
4793         return lpcfg_private_path(mem_ctx, lp_ctx, lp_ctx->globals->tls_cafile);
4794 }
4795
4796 _PUBLIC_ char *lpcfg_tls_crlfile(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
4797 {
4798         return lpcfg_private_path(mem_ctx, lp_ctx, lp_ctx->globals->tls_crlfile);
4799 }
4800
4801 _PUBLIC_ char *lpcfg_tls_dhpfile(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
4802 {
4803         return lpcfg_private_path(mem_ctx, lp_ctx, lp_ctx->globals->tls_dhpfile);
4804 }
4805
4806 struct gensec_settings *lpcfg_gensec_settings(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
4807 {
4808         struct gensec_settings *settings = talloc_zero(mem_ctx, struct gensec_settings);
4809         if (settings == NULL)
4810                 return NULL;
4811         SMB_ASSERT(lp_ctx != NULL);
4812         settings->lp_ctx = talloc_reference(settings, lp_ctx);
4813         settings->target_hostname = lpcfg_parm_string(lp_ctx, NULL, "gensec", "target_hostname");
4814         return settings;
4815 }
4816
4817 int lpcfg_server_role(struct loadparm_context *lp_ctx)
4818 {
4819         int domain_master = lpcfg__domain_master(lp_ctx);
4820
4821         return lp_find_server_role(lpcfg__server_role(lp_ctx),
4822                                    lpcfg__security(lp_ctx),
4823                                    lpcfg__domain_logons(lp_ctx),
4824                                    (domain_master == true) ||
4825                                    (domain_master == Auto));
4826 }
4827
4828 int lpcfg_security(struct loadparm_context *lp_ctx)
4829 {
4830         return lp_find_security(lpcfg__server_role(lp_ctx),
4831                                 lpcfg__security(lp_ctx));
4832 }