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