param: use a single copy_service function in lib/param
[sfrench/samba-autobuild/.git] / lib / param / loadparm.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Parameter loading functions
4    Copyright (C) Karl Auer 1993-1998
5
6    Largely re-written by Andrew Tridgell, September 1994
7
8    Copyright (C) Simo Sorce 2001
9    Copyright (C) Alexander Bokovoy 2002
10    Copyright (C) Stefan (metze) Metzmacher 2002
11    Copyright (C) Jim McDonough (jmcd@us.ibm.com)  2003.
12    Copyright (C) James Myers 2003 <myersjj@samba.org>
13    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
14    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 "tdb.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 #include "lib/param/param_global.h"
77
78 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
79
80 /* we don't need a special handler for "dos charset" and "unix charset" */
81 #define handle_dos_charset NULL
82 #define handle_charset NULL
83
84 /* these are parameter handlers which are not needed in the
85  * non-source3 code
86  */
87 #define handle_netbios_aliases NULL
88 #define handle_printing NULL
89 #define handle_ldap_debug_level NULL
90 #define handle_idmap_backend NULL
91 #define handle_idmap_uid NULL
92 #define handle_idmap_gid NULL
93
94 #ifndef N_
95 #define N_(x) x
96 #endif
97
98 /* prototypes for the special type handlers */
99 static bool handle_include(struct loadparm_context *lp_ctx, int unused,
100                            const char *pszParmValue, char **ptr);
101 static bool handle_copy(struct loadparm_context *lp_ctx, int unused,
102                         const char *pszParmValue, char **ptr);
103
104 #include "lib/param/param_table.c"
105
106 /* local variables */
107 struct loadparm_context {
108         const char *szConfigFile;
109         struct loadparm_global *globals;
110         struct loadparm_service **services;
111         struct loadparm_service *sDefault;
112         struct smb_iconv_handle *iconv_handle;
113         int iNumServices;
114         struct loadparm_service *currentService;
115         bool bInGlobalSection;
116         struct file_lists {
117                 struct file_lists *next;
118                 char *name;
119                 char *subfname;
120                 time_t modtime;
121         } *file_lists;
122         unsigned int flags[NUMPARAMETERS];
123         bool loaded;
124         bool refuse_free;
125         bool global; /* Is this the global context, which may set
126                       * global variables such as debug level etc? */
127         const struct loadparm_s3_helpers *s3_fns;
128 };
129
130
131 struct loadparm_service *lpcfg_default_service(struct loadparm_context *lp_ctx)
132 {
133         if (lp_ctx->s3_fns) {
134                 return lp_ctx->s3_fns->get_default_loadparm_service();
135         }
136         return lp_ctx->sDefault;
137 }
138
139 /**
140  * Convenience routine to grab string parameters into temporary memory
141  * and run standard_sub_basic on them.
142  *
143  * The buffers can be written to by
144  * callers without affecting the source string.
145  */
146
147 static const char *lpcfg_string(const char *s)
148 {
149 #if 0  /* until REWRITE done to make thread-safe */
150         size_t len = s ? strlen(s) : 0;
151         char *ret;
152 #endif
153
154         /* The follow debug is useful for tracking down memory problems
155            especially if you have an inner loop that is calling a lp_*()
156            function that returns a string.  Perhaps this debug should be
157            present all the time? */
158
159 #if 0
160         DEBUG(10, ("lpcfg_string(%s)\n", s));
161 #endif
162
163 #if 0  /* until REWRITE done to make thread-safe */
164         if (!lp_talloc)
165                 lp_talloc = talloc_init("lp_talloc");
166
167         ret = talloc_array(lp_talloc, char, len + 100); /* leave room for substitution */
168
169         if (!ret)
170                 return NULL;
171
172         if (!s)
173                 *ret = 0;
174         else
175                 strlcpy(ret, s, len);
176
177         if (trim_string(ret, "\"", "\"")) {
178                 if (strchr(ret,'"') != NULL)
179                         strlcpy(ret, s, len);
180         }
181
182         standard_sub_basic(ret,len+100);
183         return (ret);
184 #endif
185         return s;
186 }
187
188 /*
189    In this section all the functions that are used to access the
190    parameters from the rest of the program are defined
191 */
192
193 /*
194  * the creation of separate lpcfg_*() and lp_*() functions is to allow
195  * for code compatibility between existing Samba4 and Samba3 code.
196  */
197
198 /* this global context supports the lp_*() function varients */
199 static struct loadparm_context *global_loadparm_context;
200
201 #define lpcfg_default_service global_loadparm_context->sDefault
202 #define lpcfg_global_service(i) global_loadparm_context->services[i]
203
204 #define FN_GLOBAL_STRING(fn_name,var_name) \
205  _PUBLIC_ char *lpcfg_ ## fn_name(struct loadparm_context *lp_ctx, TALLOC_CTX *ctx) {\
206          if (lp_ctx == NULL) return NULL;                               \
207          if (lp_ctx->s3_fns) {                                          \
208                  return lp_ctx->globals->var_name ? lp_ctx->s3_fns->lp_string(ctx, lp_ctx->globals->var_name) : talloc_strdup(ctx, ""); \
209          }                                                              \
210          return lp_ctx->globals->var_name ? talloc_strdup(ctx, lpcfg_string(lp_ctx->globals->var_name)) : talloc_strdup(ctx, ""); \
211 }
212
213 #define FN_GLOBAL_CONST_STRING(fn_name,var_name)                                \
214  _PUBLIC_ const char *lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) { \
215         if (lp_ctx == NULL) return NULL;                                \
216         return lp_ctx->globals->var_name ? lpcfg_string(lp_ctx->globals->var_name) : ""; \
217 }
218
219 #define FN_GLOBAL_LIST(fn_name,var_name)                                \
220  _PUBLIC_ const char **lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) { \
221          if (lp_ctx == NULL) return NULL;                               \
222          return lp_ctx->globals->var_name;                              \
223  }
224
225 #define FN_GLOBAL_BOOL(fn_name,var_name) \
226  _PUBLIC_ bool lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) {\
227          if (lp_ctx == NULL) return false;                              \
228          return lp_ctx->globals->var_name;                              \
229 }
230
231 #define FN_GLOBAL_INTEGER(fn_name,var_name) \
232  _PUBLIC_ int lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) { \
233          return lp_ctx->globals->var_name;                              \
234  }
235
236 /* Local parameters don't need the ->s3_fns because the struct
237  * loadparm_service is shared and lpcfg_service() checks the ->s3_fns
238  * hook */
239 #define FN_LOCAL_STRING(fn_name,val) \
240  _PUBLIC_ char *lpcfg_ ## fn_name(struct loadparm_service *service, \
241                                         struct loadparm_service *sDefault, TALLOC_CTX *ctx) { \
242          return(talloc_strdup(ctx, lpcfg_string((const char *)((service != NULL && service->val != NULL) ? service->val : sDefault->val)))); \
243  }
244
245 #define FN_LOCAL_CONST_STRING(fn_name,val) \
246  _PUBLIC_ const char *lpcfg_ ## fn_name(struct loadparm_service *service, \
247                                         struct loadparm_service *sDefault) { \
248          return((const char *)((service != NULL && service->val != NULL) ? service->val : sDefault->val)); \
249  }
250
251 #define FN_LOCAL_LIST(fn_name,val) \
252  _PUBLIC_ const char **lpcfg_ ## fn_name(struct loadparm_service *service, \
253                                          struct loadparm_service *sDefault) {\
254          return(const char **)(service != NULL && service->val != NULL? service->val : sDefault->val); \
255  }
256
257 #define FN_LOCAL_PARM_BOOL(fn_name, val) FN_LOCAL_BOOL(fn_name, val)
258
259 #define FN_LOCAL_BOOL(fn_name,val) \
260  _PUBLIC_ bool lpcfg_ ## fn_name(struct loadparm_service *service, \
261                                  struct loadparm_service *sDefault) {   \
262          return((service != NULL)? service->val : sDefault->val); \
263  }
264
265 #define FN_LOCAL_INTEGER(fn_name,val) \
266  _PUBLIC_ int lpcfg_ ## fn_name(struct loadparm_service *service, \
267                                 struct loadparm_service *sDefault) {    \
268          return((service != NULL)? service->val : sDefault->val); \
269  }
270
271 #define FN_LOCAL_PARM_INTEGER(fn_name, val) FN_LOCAL_INTEGER(fn_name, val)
272
273 #define FN_LOCAL_PARM_CHAR(fn_name,val) \
274  _PUBLIC_ char lpcfg_ ## fn_name(struct loadparm_service *service, \
275                                 struct loadparm_service *sDefault) {    \
276          return((service != NULL)? service->val : sDefault->val); \
277  }
278
279 #include "lib/param/param_functions.c"
280
281 /* These functions cannot be auto-generated */
282 FN_LOCAL_BOOL(autoloaded, autoloaded)
283 FN_GLOBAL_CONST_STRING(dnsdomain, dnsdomain)
284
285 /* local prototypes */
286 static struct loadparm_service *getservicebyname(struct loadparm_context *lp_ctx,
287                                         const char *pszServiceName);
288 static bool lpcfg_service_ok(struct loadparm_service *service);
289 static bool do_section(const char *pszSectionName, void *);
290 static void init_copymap(struct loadparm_service *pservice);
291
292 /* This is a helper function for parametrical options support. */
293 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
294 /* Actual parametrical functions are quite simple */
295 const char *lpcfg_get_parametric(struct loadparm_context *lp_ctx,
296                               struct loadparm_service *service,
297                               const char *type, const char *option)
298 {
299         char *vfskey_tmp = NULL;
300         char *vfskey = NULL;
301         struct parmlist_entry *data;
302
303         if (lp_ctx == NULL)
304                 return NULL;
305
306         if (lp_ctx->s3_fns) {
307                 return lp_ctx->s3_fns->get_parametric(service, type, option);
308         }
309
310         data = (service == NULL ? lp_ctx->globals->param_opt : service->param_opt);
311
312         vfskey_tmp = talloc_asprintf(NULL, "%s:%s", type, option);
313         if (vfskey_tmp == NULL) return NULL;
314         vfskey = strlower_talloc(NULL, vfskey_tmp);
315         talloc_free(vfskey_tmp);
316
317         while (data) {
318                 if (strcmp(data->key, vfskey) == 0) {
319                         talloc_free(vfskey);
320                         return data->value;
321                 }
322                 data = data->next;
323         }
324
325         if (service != NULL) {
326                 /* Try to fetch the same option but from globals */
327                 /* but only if we are not already working with globals */
328                 for (data = lp_ctx->globals->param_opt; data;
329                      data = data->next) {
330                         if (strcmp(data->key, vfskey) == 0) {
331                                 talloc_free(vfskey);
332                                 return data->value;
333                         }
334                 }
335         }
336
337         talloc_free(vfskey);
338
339         return NULL;
340 }
341
342
343 /**
344  * convenience routine to return int parameters.
345  */
346 static int lp_int(const char *s)
347 {
348
349         if (!s) {
350                 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
351                 return -1;
352         }
353
354         return strtol(s, NULL, 0);
355 }
356
357 /**
358  * convenience routine to return unsigned long parameters.
359  */
360 static unsigned long lp_ulong(const char *s)
361 {
362
363         if (!s) {
364                 DEBUG(0,("lp_ulong(%s): is called with NULL!\n",s));
365                 return -1;
366         }
367
368         return strtoul(s, NULL, 0);
369 }
370
371 /**
372  * convenience routine to return unsigned long parameters.
373  */
374 static long lp_long(const char *s)
375 {
376
377         if (!s) {
378                 DEBUG(0,("lp_long(%s): is called with NULL!\n",s));
379                 return -1;
380         }
381
382         return strtol(s, NULL, 0);
383 }
384
385 /**
386  * convenience routine to return unsigned long parameters.
387  */
388 static double lp_double(const char *s)
389 {
390
391         if (!s) {
392                 DEBUG(0,("lp_double(%s): is called with NULL!\n",s));
393                 return -1;
394         }
395
396         return strtod(s, NULL);
397 }
398
399 /**
400  * convenience routine to return boolean parameters.
401  */
402 static bool lp_bool(const char *s)
403 {
404         bool ret = false;
405
406         if (!s) {
407                 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
408                 return false;
409         }
410
411         if (!set_boolean(s, &ret)) {
412                 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
413                 return false;
414         }
415
416         return ret;
417 }
418
419
420 /**
421  * Return parametric option from a given service. Type is a part of option before ':'
422  * Parametric option has following syntax: 'Type: option = value'
423  * Returned value is allocated in 'lp_talloc' context
424  */
425
426 const char *lpcfg_parm_string(struct loadparm_context *lp_ctx,
427                               struct loadparm_service *service, const char *type,
428                               const char *option)
429 {
430         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
431
432         if (value)
433                 return lpcfg_string(value);
434
435         return NULL;
436 }
437
438 /**
439  * Return parametric option from a given service. Type is a part of option before ':'
440  * Parametric option has following syntax: 'Type: option = value'
441  * Returned value is allocated in 'lp_talloc' context
442  */
443
444 const char **lpcfg_parm_string_list(TALLOC_CTX *mem_ctx,
445                                     struct loadparm_context *lp_ctx,
446                                     struct loadparm_service *service,
447                                     const char *type,
448                                     const char *option, const char *separator)
449 {
450         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
451
452         if (value != NULL)
453                 return (const char **)str_list_make(mem_ctx, value, separator);
454
455         return NULL;
456 }
457
458 /**
459  * Return parametric option from a given service. Type is a part of option before ':'
460  * Parametric option has following syntax: 'Type: option = value'
461  */
462
463 int lpcfg_parm_int(struct loadparm_context *lp_ctx,
464                    struct loadparm_service *service, const char *type,
465                    const char *option, int default_v)
466 {
467         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
468
469         if (value)
470                 return lp_int(value);
471
472         return default_v;
473 }
474
475 /**
476  * Return parametric option from a given service. Type is a part of
477  * option before ':'.
478  * Parametric option has following syntax: 'Type: option = value'.
479  */
480
481 int lpcfg_parm_bytes(struct loadparm_context *lp_ctx,
482                   struct loadparm_service *service, const char *type,
483                   const char *option, int default_v)
484 {
485         uint64_t bval;
486
487         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
488
489         if (value && conv_str_size_error(value, &bval)) {
490                 if (bval <= INT_MAX) {
491                         return (int)bval;
492                 }
493         }
494
495         return default_v;
496 }
497
498 /**
499  * Return parametric option from a given service.
500  * Type is a part of option before ':'
501  * Parametric option has following syntax: 'Type: option = value'
502  */
503 unsigned long lpcfg_parm_ulong(struct loadparm_context *lp_ctx,
504                             struct loadparm_service *service, const char *type,
505                             const char *option, unsigned long default_v)
506 {
507         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
508
509         if (value)
510                 return lp_ulong(value);
511
512         return default_v;
513 }
514
515 long lpcfg_parm_long(struct loadparm_context *lp_ctx,
516                      struct loadparm_service *service, const char *type,
517                      const char *option, long default_v)
518 {
519         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
520
521         if (value)
522                 return lp_long(value);
523
524         return default_v;
525 }
526
527 double lpcfg_parm_double(struct loadparm_context *lp_ctx,
528                       struct loadparm_service *service, const char *type,
529                       const char *option, double default_v)
530 {
531         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
532
533         if (value != NULL)
534                 return lp_double(value);
535
536         return default_v;
537 }
538
539 /**
540  * Return parametric option from a given service. Type is a part of option before ':'
541  * Parametric option has following syntax: 'Type: option = value'
542  */
543
544 bool lpcfg_parm_bool(struct loadparm_context *lp_ctx,
545                      struct loadparm_service *service, const char *type,
546                      const char *option, bool default_v)
547 {
548         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
549
550         if (value != NULL)
551                 return lp_bool(value);
552
553         return default_v;
554 }
555
556
557 /**
558  * Set a string value, deallocating any existing space, and allocing the space
559  * for the string
560  */
561 static bool lpcfg_string_set(TALLOC_CTX *mem_ctx, char **dest, const char *src)
562 {
563         talloc_free(*dest);
564
565         if (src == NULL)
566                 src = "";
567
568         *dest = talloc_strdup(mem_ctx, src);
569         if ((*dest) == NULL) {
570                 DEBUG(0,("Out of memory in string_set\n"));
571                 return false;
572         }
573
574         return true;
575 }
576
577 /**
578  * Set a string value, deallocating any existing space, and allocing the space
579  * for the string
580  */
581 static bool lpcfg_string_set_upper(TALLOC_CTX *mem_ctx, char **dest, const char *src)
582 {
583         talloc_free(*dest);
584
585         if (src == NULL)
586                 src = "";
587
588         *dest = strupper_talloc(mem_ctx, src);
589         if ((*dest) == NULL) {
590                 DEBUG(0,("Out of memory in string_set_upper\n"));
591                 return false;
592         }
593
594         return true;
595 }
596
597
598
599 /**
600  * Add a new service to the services array initialising it with the given
601  * service.
602  */
603
604 struct loadparm_service *lpcfg_add_service(struct loadparm_context *lp_ctx,
605                                            const struct loadparm_service *pservice,
606                                            const char *name)
607 {
608         int i;
609         int num_to_alloc = lp_ctx->iNumServices + 1;
610         struct parmlist_entry *data, *pdata;
611
612         if (pservice == NULL) {
613                 pservice = lp_ctx->sDefault;
614         }
615
616         /* it might already exist */
617         if (name) {
618                 struct loadparm_service *service = getservicebyname(lp_ctx,
619                                                                     name);
620                 if (service != NULL) {
621                         /* Clean all parametric options for service */
622                         /* They will be added during parsing again */
623                         data = service->param_opt;
624                         while (data) {
625                                 pdata = data->next;
626                                 talloc_free(data);
627                                 data = pdata;
628                         }
629                         service->param_opt = NULL;
630                         return service;
631                 }
632         }
633
634         /* find an invalid one */
635         for (i = 0; i < lp_ctx->iNumServices; i++)
636                 if (lp_ctx->services[i] == NULL)
637                         break;
638
639         /* if not, then create one */
640         if (i == lp_ctx->iNumServices) {
641                 struct loadparm_service **tsp;
642
643                 tsp = talloc_realloc(lp_ctx, lp_ctx->services, struct loadparm_service *, num_to_alloc);
644
645                 if (!tsp) {
646                         DEBUG(0,("lpcfg_add_service: failed to enlarge services!\n"));
647                         return NULL;
648                 } else {
649                         lp_ctx->services = tsp;
650                         lp_ctx->services[lp_ctx->iNumServices] = NULL;
651                 }
652
653                 lp_ctx->iNumServices++;
654         }
655
656         lp_ctx->services[i] = talloc_zero(lp_ctx->services, struct loadparm_service);
657         if (lp_ctx->services[i] == NULL) {
658                 DEBUG(0,("lpcfg_add_service: out of memory!\n"));
659                 return NULL;
660         }
661         copy_service(lp_ctx->services[i], pservice, NULL);
662         if (name != NULL)
663                 lpcfg_string_set(lp_ctx->services[i], &lp_ctx->services[i]->szService, name);
664         return lp_ctx->services[i];
665 }
666
667 /**
668  * Add a new home service, with the specified home directory, defaults coming
669  * from service ifrom.
670  */
671
672 bool lpcfg_add_home(struct loadparm_context *lp_ctx,
673                  const char *pszHomename,
674                  struct loadparm_service *default_service,
675                  const char *user, const char *pszHomedir)
676 {
677         struct loadparm_service *service;
678
679         service = lpcfg_add_service(lp_ctx, default_service, pszHomename);
680
681         if (service == NULL)
682                 return false;
683
684         if (!(*(default_service->path))
685             || strequal(default_service->path, lp_ctx->sDefault->path)) {
686                 service->path = talloc_strdup(service, pszHomedir);
687         } else {
688                 service->path = string_sub_talloc(service, lpcfg_path(default_service, lp_ctx->sDefault, service), "%H", pszHomedir);
689         }
690
691         if (!(*(service->comment))) {
692                 service->comment = talloc_asprintf(service, "Home directory of %s", user);
693         }
694         service->bAvailable = default_service->bAvailable;
695         service->browseable = default_service->browseable;
696
697         DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n",
698                   pszHomename, user, service->path));
699
700         return true;
701 }
702
703 /**
704  * Add a new printer service, with defaults coming from service iFrom.
705  */
706
707 bool lpcfg_add_printer(struct loadparm_context *lp_ctx,
708                        const char *pszPrintername,
709                        struct loadparm_service *default_service)
710 {
711         const char *comment = "From Printcap";
712         struct loadparm_service *service;
713         service = lpcfg_add_service(lp_ctx, default_service, pszPrintername);
714
715         if (service == NULL)
716                 return false;
717
718         /* note that we do NOT default the availability flag to True - */
719         /* we take it from the default service passed. This allows all */
720         /* dynamic printers to be disabled by disabling the [printers] */
721         /* entry (if/when the 'available' keyword is implemented!).    */
722
723         /* the printer name is set to the service name. */
724         lpcfg_string_set(service, &service->_printername, pszPrintername);
725         lpcfg_string_set(service, &service->comment, comment);
726         service->browseable = default_service->browseable;
727         /* Printers cannot be read_only. */
728         service->read_only = false;
729         /* Printer services must be printable. */
730         service->printable = true;
731
732         DEBUG(3, ("adding printer service %s\n", pszPrintername));
733
734         return true;
735 }
736
737 /**
738  * Map a parameter's string representation to something we can use.
739  * Returns False if the parameter string is not recognised, else TRUE.
740  */
741
742 int lpcfg_map_parameter(const char *pszParmName)
743 {
744         int iIndex;
745
746         for (iIndex = 0; parm_table[iIndex].label; iIndex++)
747                 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
748                         return iIndex;
749
750         /* Warn only if it isn't parametric option */
751         if (strchr(pszParmName, ':') == NULL)
752                 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
753         /* We do return 'fail' for parametric options as well because they are
754            stored in different storage
755          */
756         return -1;
757 }
758
759
760 /**
761   return the parameter structure for a parameter
762 */
763 struct parm_struct *lpcfg_parm_struct(struct loadparm_context *lp_ctx, const char *name)
764 {
765         int parmnum;
766
767         if (lp_ctx->s3_fns) {
768                 return lp_ctx->s3_fns->get_parm_struct(name);
769         }
770
771         parmnum = lpcfg_map_parameter(name);
772         if (parmnum == -1) return NULL;
773         return &parm_table[parmnum];
774 }
775
776 /**
777   return the parameter pointer for a parameter
778 */
779 void *lpcfg_parm_ptr(struct loadparm_context *lp_ctx,
780                   struct loadparm_service *service, struct parm_struct *parm)
781 {
782         if (lp_ctx->s3_fns) {
783                 return lp_ctx->s3_fns->get_parm_ptr(service, parm);
784         }
785
786         if (service == NULL) {
787                 if (parm->p_class == P_LOCAL)
788                         return ((char *)lp_ctx->sDefault)+parm->offset;
789                 else if (parm->p_class == P_GLOBAL)
790                         return ((char *)lp_ctx->globals)+parm->offset;
791                 else return NULL;
792         } else {
793                 return ((char *)service) + parm->offset;
794         }
795 }
796
797 /**
798   return the parameter pointer for a parameter
799 */
800 bool lpcfg_parm_is_cmdline(struct loadparm_context *lp_ctx, const char *name)
801 {
802         int parmnum;
803
804         if (lp_ctx->s3_fns) {
805                 struct parm_struct *parm = lp_ctx->s3_fns->get_parm_struct(name);
806                 if (parm) {
807                         return parm->flags & FLAG_CMDLINE;
808                 }
809                 return false;
810         }
811
812         parmnum = lpcfg_map_parameter(name);
813         if (parmnum == -1) return false;
814
815         return lp_ctx->flags[parmnum] & FLAG_CMDLINE;
816 }
817
818 /**
819  * Find a service by name. Otherwise works like get_service.
820  */
821
822 static struct loadparm_service *getservicebyname(struct loadparm_context *lp_ctx,
823                                         const char *pszServiceName)
824 {
825         int iService;
826
827         if (lp_ctx->s3_fns) {
828                 return lp_ctx->s3_fns->get_service(pszServiceName);
829         }
830
831         for (iService = lp_ctx->iNumServices - 1; iService >= 0; iService--)
832                 if (lp_ctx->services[iService] != NULL &&
833                     strwicmp(lp_ctx->services[iService]->szService, pszServiceName) == 0) {
834                         return lp_ctx->services[iService];
835                 }
836
837         return NULL;
838 }
839
840 /**
841  * Add a parametric option to a parmlist_entry,
842  * replacing old value, if already present.
843  */
844 void set_param_opt(TALLOC_CTX *mem_ctx,
845                    struct parmlist_entry **opt_list,
846                    const char *opt_name,
847                    const char *opt_value,
848                    unsigned priority)
849 {
850         struct parmlist_entry *new_opt, *opt;
851         bool not_added;
852
853         opt = *opt_list;
854         not_added = true;
855
856         /* Traverse destination */
857         while (opt) {
858                 /* If we already have same option, override it */
859                 if (strwicmp(opt->key, opt_name) == 0) {
860                         if ((opt->priority & FLAG_CMDLINE) &&
861                             !(priority & FLAG_CMDLINE)) {
862                                 /* it's been marked as not to be
863                                    overridden */
864                                 return;
865                         }
866                         TALLOC_FREE(opt->value);
867                         TALLOC_FREE(opt->list);
868                         opt->value = talloc_strdup(opt, opt_value);
869                         opt->priority = priority;
870                         not_added = false;
871                         break;
872                 }
873                 opt = opt->next;
874         }
875         if (not_added) {
876                 new_opt = talloc(mem_ctx, struct parmlist_entry);
877                 if (new_opt == NULL) {
878                         smb_panic("OOM");
879                 }
880
881                 new_opt->key = talloc_strdup(new_opt, opt_name);
882                 if (new_opt->key == NULL) {
883                         smb_panic("talloc_strdup failed");
884                 }
885
886                 new_opt->value = talloc_strdup(new_opt, opt_value);
887                 if (new_opt->value == NULL) {
888                         smb_panic("talloc_strdup failed");
889                 }
890
891                 new_opt->list = NULL;
892                 new_opt->priority = priority;
893                 DLIST_ADD(*opt_list, new_opt);
894         }
895 }
896
897 /**
898  * Copy a service structure to another.
899  * If pcopymapDest is NULL then copy all fields
900  */
901
902 void copy_service(struct loadparm_service *pserviceDest,
903                   const struct loadparm_service *pserviceSource,
904                   struct bitmap *pcopymapDest)
905 {
906         int i;
907         bool bcopyall = (pcopymapDest == NULL);
908         struct parmlist_entry *data;
909
910         for (i = 0; parm_table[i].label; i++)
911                 if (parm_table[i].p_class == P_LOCAL &&
912                     (bcopyall || bitmap_query(pcopymapDest, i))) {
913                         const void *src_ptr =
914                                 ((const char *)pserviceSource) + parm_table[i].offset;
915                         void *dest_ptr =
916                                 ((char *)pserviceDest) + parm_table[i].offset;
917
918                         switch (parm_table[i].type) {
919                                 case P_BOOL:
920                                 case P_BOOLREV:
921                                         *(bool *)dest_ptr = *(const bool *)src_ptr;
922                                         break;
923
924                                 case P_INTEGER:
925                                 case P_BYTES:
926                                 case P_OCTAL:
927                                 case P_ENUM:
928                                         *(int *)dest_ptr = *(const int *)src_ptr;
929                                         break;
930
931                                 case P_CHAR:
932                                         *(char *)dest_ptr = *(const char *)src_ptr;
933                                         break;
934
935                                 case P_STRING:
936                                         lpcfg_string_set(pserviceDest,
937                                                    (char **)dest_ptr,
938                                                    *(const char * const *)src_ptr);
939                                         break;
940
941                                 case P_USTRING:
942                                         lpcfg_string_set_upper(pserviceDest,
943                                                          (char **)dest_ptr,
944                                                          *(const char * const *)src_ptr);
945                                         break;
946                                 case P_LIST:
947                                         TALLOC_FREE(*((char ***)dest_ptr));
948                                         *(const char * const **)dest_ptr = (const char * const *)str_list_copy(pserviceDest,
949                                                                                   *(const char * * const *)src_ptr);
950                                         break;
951                                 default:
952                                         break;
953                         }
954                 }
955
956         if (bcopyall) {
957                 init_copymap(pserviceDest);
958                 if (pserviceSource->copymap)
959                         bitmap_copy(pserviceDest->copymap,
960                                     pserviceSource->copymap);
961         }
962
963         for (data = pserviceSource->param_opt; data != NULL; data = data->next) {
964                 set_param_opt(pserviceDest, &pserviceDest->param_opt,
965                               data->key, data->value, data->priority);
966         }
967 }
968
969 /**
970  * Check a service for consistency. Return False if the service is in any way
971  * incomplete or faulty, else True.
972  */
973 static bool lpcfg_service_ok(struct loadparm_service *service)
974 {
975         bool bRetval;
976
977         bRetval = true;
978         if (service->szService[0] == '\0') {
979                 DEBUG(0, ("The following message indicates an internal error:\n"));
980                 DEBUG(0, ("No service name in service entry.\n"));
981                 bRetval = false;
982         }
983
984         /* The [printers] entry MUST be printable. I'm all for flexibility, but */
985         /* I can't see why you'd want a non-printable printer service...        */
986         if (strwicmp(service->szService, PRINTERS_NAME) == 0) {
987                 if (!service->printable) {
988                         DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
989                                service->szService));
990                         service->printable = true;
991                 }
992                 /* [printers] service must also be non-browsable. */
993                 if (service->browseable)
994                         service->browseable = false;
995         }
996
997         /* If a service is flagged unavailable, log the fact at level 0. */
998         if (!service->bAvailable)
999                 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
1000                           service->szService));
1001
1002         return bRetval;
1003 }
1004
1005
1006 /*******************************************************************
1007  Keep a linked list of all config files so we know when one has changed
1008  it's date and needs to be reloaded.
1009 ********************************************************************/
1010
1011 static void add_to_file_list(struct loadparm_context *lp_ctx,
1012                              const char *fname, const char *subfname)
1013 {
1014         struct file_lists *f = lp_ctx->file_lists;
1015
1016         while (f) {
1017                 if (f->name && !strcmp(f->name, fname))
1018                         break;
1019                 f = f->next;
1020         }
1021
1022         if (!f) {
1023                 f = talloc(lp_ctx, struct file_lists);
1024                 if (!f)
1025                         return;
1026                 f->next = lp_ctx->file_lists;
1027                 f->name = talloc_strdup(f, fname);
1028                 if (!f->name) {
1029                         talloc_free(f);
1030                         return;
1031                 }
1032                 f->subfname = talloc_strdup(f, subfname);
1033                 if (!f->subfname) {
1034                         talloc_free(f);
1035                         return;
1036                 }
1037                 lp_ctx->file_lists = f;
1038                 f->modtime = file_modtime(subfname);
1039         } else {
1040                 time_t t = file_modtime(subfname);
1041                 if (t)
1042                         f->modtime = t;
1043         }
1044 }
1045
1046 /*******************************************************************
1047  Check if a config file has changed date.
1048 ********************************************************************/
1049 bool lpcfg_file_list_changed(struct loadparm_context *lp_ctx)
1050 {
1051         struct file_lists *f;
1052         DEBUG(6, ("lpcfg_file_list_changed()\n"));
1053
1054         for (f = lp_ctx->file_lists; f != NULL; f = f->next) {
1055                 char *n2;
1056                 time_t mod_time;
1057
1058                 n2 = standard_sub_basic(lp_ctx, f->name);
1059
1060                 DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
1061                              f->name, n2, ctime(&f->modtime)));
1062
1063                 mod_time = file_modtime(n2);
1064
1065                 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
1066                         DEBUGADD(6, ("file %s modified: %s\n", n2,
1067                                   ctime(&mod_time)));
1068                         f->modtime = mod_time;
1069                         talloc_free(f->subfname);
1070                         f->subfname = talloc_strdup(f, n2);
1071                         return true;
1072                 }
1073         }
1074         return false;
1075 }
1076
1077 /***************************************************************************
1078  Handle the "realm" parameter
1079 ***************************************************************************/
1080
1081 bool handle_realm(struct loadparm_context *lp_ctx, int unused,
1082                   const char *pszParmValue, char **ptr)
1083 {
1084         char *upper;
1085         char *lower;
1086
1087         upper = strupper_talloc(lp_ctx, pszParmValue);
1088         if (upper == NULL) {
1089                 return false;
1090         }
1091
1092         lower = strlower_talloc(lp_ctx, pszParmValue);
1093         if (lower == NULL) {
1094                 TALLOC_FREE(upper);
1095                 return false;
1096         }
1097
1098         if (lp_ctx->s3_fns != NULL) {
1099                 lp_ctx->s3_fns->lp_string_set(ptr, pszParmValue);
1100                 lp_ctx->s3_fns->lp_string_set(&lp_ctx->globals->realm, upper);
1101                 lp_ctx->s3_fns->lp_string_set(&lp_ctx->globals->dnsdomain, lower);
1102         } else {
1103                 lpcfg_string_set(lp_ctx, ptr, pszParmValue);
1104                 lpcfg_string_set(lp_ctx, &lp_ctx->globals->realm, upper);
1105                 lpcfg_string_set(lp_ctx, &lp_ctx->globals->dnsdomain, lower);
1106         }
1107
1108         return true;
1109 }
1110
1111 /***************************************************************************
1112  Handle the include operation.
1113 ***************************************************************************/
1114
1115 static bool handle_include(struct loadparm_context *lp_ctx, int unused,
1116                            const char *pszParmValue, char **ptr)
1117 {
1118         char *fname = standard_sub_basic(lp_ctx, pszParmValue);
1119
1120         add_to_file_list(lp_ctx, pszParmValue, fname);
1121
1122         lpcfg_string_set(lp_ctx, ptr, fname);
1123
1124         if (file_exist(fname))
1125                 return pm_process(fname, do_section, do_parameter, lp_ctx);
1126
1127         DEBUG(2, ("Can't find include file %s\n", fname));
1128
1129         return false;
1130 }
1131
1132 /***************************************************************************
1133  Handle the interpretation of the copy parameter.
1134 ***************************************************************************/
1135
1136 static bool handle_copy(struct loadparm_context *lp_ctx, int unused,
1137                         const char *pszParmValue, char **ptr)
1138 {
1139         bool bRetval;
1140         struct loadparm_service *serviceTemp;
1141
1142         lpcfg_string_set(lp_ctx, ptr, pszParmValue);
1143
1144         bRetval = false;
1145
1146         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
1147
1148         if ((serviceTemp = getservicebyname(lp_ctx, pszParmValue)) != NULL) {
1149                 if (serviceTemp == lp_ctx->currentService) {
1150                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
1151                 } else {
1152                         copy_service(lp_ctx->currentService,
1153                                      serviceTemp,
1154                                      lp_ctx->currentService->copymap);
1155                         bRetval = true;
1156                 }
1157         } else {
1158                 DEBUG(0, ("Unable to copy service - source not found: %s\n",
1159                           pszParmValue));
1160                 bRetval = false;
1161         }
1162
1163         return bRetval;
1164 }
1165
1166 bool handle_debug_list(struct loadparm_context *lp_ctx, int unused,
1167                         const char *pszParmValue, char **ptr)
1168 {
1169         if (lp_ctx->s3_fns != NULL) {
1170                 lp_ctx->s3_fns->lp_string_set(ptr, pszParmValue);
1171         } else {
1172                 lpcfg_string_set(lp_ctx, ptr, pszParmValue);
1173         }
1174
1175         return debug_parse_levels(pszParmValue);
1176 }
1177
1178 bool handle_logfile(struct loadparm_context *lp_ctx, int unused,
1179                     const char *pszParmValue, char **ptr)
1180 {
1181         if (lp_ctx->s3_fns != NULL) {
1182                 lp_ctx->s3_fns->lp_string_set(ptr, pszParmValue);
1183         } else {
1184                 debug_set_logfile(pszParmValue);
1185                 lpcfg_string_set(lp_ctx, ptr, pszParmValue);
1186         }
1187
1188         return true;
1189 }
1190
1191 /***************************************************************************
1192  Initialise a copymap.
1193 ***************************************************************************/
1194
1195 static void init_copymap(struct loadparm_service *pservice)
1196 {
1197         int i;
1198
1199         TALLOC_FREE(pservice->copymap);
1200
1201         pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
1202         if (!pservice->copymap)
1203                 DEBUG(0,
1204                       ("Couldn't allocate copymap!! (size %d)\n",
1205                        (int)NUMPARAMETERS));
1206         else
1207                 for (i = 0; i < NUMPARAMETERS; i++)
1208                         bitmap_set(pservice->copymap, i);
1209 }
1210
1211 /**
1212  * Process a parametric option
1213  */
1214 static bool lp_do_parameter_parametric(struct loadparm_context *lp_ctx,
1215                                        struct loadparm_service *service,
1216                                        const char *pszParmName,
1217                                        const char *pszParmValue, int flags)
1218 {
1219         struct parmlist_entry *paramo, *data;
1220         char *name;
1221         TALLOC_CTX *mem_ctx;
1222
1223         while (isspace((unsigned char)*pszParmName)) {
1224                 pszParmName++;
1225         }
1226
1227         name = strlower_talloc(lp_ctx, pszParmName);
1228         if (!name) return false;
1229
1230         if (service == NULL) {
1231                 data = lp_ctx->globals->param_opt;
1232                 mem_ctx = lp_ctx->globals;
1233         } else {
1234                 data = service->param_opt;
1235                 mem_ctx = service;
1236         }
1237
1238         /* Traverse destination */
1239         for (paramo=data; paramo; paramo=paramo->next) {
1240                 /* If we already have the option set, override it unless
1241                    it was a command line option and the new one isn't */
1242                 if (strcmp(paramo->key, name) == 0) {
1243                         if ((paramo->priority & FLAG_CMDLINE) &&
1244                             !(flags & FLAG_CMDLINE)) {
1245                                 talloc_free(name);
1246                                 return true;
1247                         }
1248
1249                         talloc_free(paramo->value);
1250                         paramo->value = talloc_strdup(paramo, pszParmValue);
1251                         paramo->priority = flags;
1252                         talloc_free(name);
1253                         return true;
1254                 }
1255         }
1256
1257         paramo = talloc_zero(mem_ctx, struct parmlist_entry);
1258         if (!paramo)
1259                 smb_panic("OOM");
1260         paramo->key = talloc_strdup(paramo, name);
1261         paramo->value = talloc_strdup(paramo, pszParmValue);
1262         paramo->priority = flags;
1263         if (service == NULL) {
1264                 DLIST_ADD(lp_ctx->globals->param_opt, paramo);
1265         } else {
1266                 DLIST_ADD(service->param_opt, paramo);
1267         }
1268
1269         talloc_free(name);
1270
1271         return true;
1272 }
1273
1274 static bool set_variable(TALLOC_CTX *mem_ctx, int parmnum, void *parm_ptr,
1275                          const char *pszParmName, const char *pszParmValue,
1276                          struct loadparm_context *lp_ctx, bool on_globals)
1277 {
1278         int i;
1279         /* if it is a special case then go ahead */
1280         if (parm_table[parmnum].special) {
1281                 bool ret;
1282                 ret = parm_table[parmnum].special(lp_ctx, -1, pszParmValue,
1283                                                   (char **)parm_ptr);
1284                 if (!ret) {
1285                         return false;
1286                 }
1287                 goto mark_non_default;
1288         }
1289
1290         /* now switch on the type of variable it is */
1291         switch (parm_table[parmnum].type)
1292         {
1293                 case P_BOOL: {
1294                         bool b;
1295                         if (!set_boolean(pszParmValue, &b)) {
1296                                 DEBUG(0, ("set_variable(%s): value is not "
1297                                           "boolean!\n", pszParmValue));
1298                                 return false;
1299                         }
1300                         *(bool *)parm_ptr = b;
1301                         }
1302                         break;
1303
1304                 case P_BOOLREV: {
1305                         bool b;
1306                         if (!set_boolean(pszParmValue, &b)) {
1307                                 DEBUG(0, ("set_variable(%s): value is not "
1308                                           "boolean!\n", pszParmValue));
1309                                 return false;
1310                         }
1311                         *(bool *)parm_ptr = !b;
1312                         }
1313                         break;
1314
1315                 case P_INTEGER:
1316                         *(int *)parm_ptr = atoi(pszParmValue);
1317                         break;
1318
1319                 case P_CHAR:
1320                         *(char *)parm_ptr = *pszParmValue;
1321                         break;
1322
1323                 case P_OCTAL:
1324                         *(int *)parm_ptr = strtol(pszParmValue, NULL, 8);
1325                         break;
1326
1327                 case P_BYTES:
1328                 {
1329                         uint64_t val;
1330                         if (conv_str_size_error(pszParmValue, &val)) {
1331                                 if (val <= INT_MAX) {
1332                                         *(int *)parm_ptr = (int)val;
1333                                         break;
1334                                 }
1335                         }
1336
1337                         DEBUG(0, ("set_variable(%s): value is not "
1338                                   "a valid size specifier!\n", pszParmValue));
1339                         return false;
1340                 }
1341
1342                 case P_CMDLIST:
1343                         *(const char * const **)parm_ptr
1344                                 = (const char * const *)str_list_make(mem_ctx,
1345                                                                       pszParmValue, NULL);
1346                         break;
1347                 case P_LIST:
1348                 {
1349                         char **new_list = str_list_make(mem_ctx,
1350                                                         pszParmValue, NULL);
1351                         for (i=0; new_list[i]; i++) {
1352                                 if (*(const char ***)parm_ptr != NULL &&
1353                                     new_list[i][0] == '+' &&
1354                                     new_list[i][1])
1355                                 {
1356                                         if (!str_list_check(*(const char ***)parm_ptr,
1357                                                             &new_list[i][1])) {
1358                                                 *(const char ***)parm_ptr = str_list_add(*(const char ***)parm_ptr,
1359                                                                                          &new_list[i][1]);
1360                                         }
1361                                 } else if (*(const char ***)parm_ptr != NULL &&
1362                                            new_list[i][0] == '-' &&
1363                                            new_list[i][1])
1364                                 {
1365                                         str_list_remove(*(const char ***)parm_ptr,
1366                                                         &new_list[i][1]);
1367                                 } else {
1368                                         if (i != 0) {
1369                                                 DEBUG(0, ("Unsupported list syntax for: %s = %s\n",
1370                                                           pszParmName, pszParmValue));
1371                                                 return false;
1372                                         }
1373                                         *(const char * const **)parm_ptr = (const char * const *) new_list;
1374                                         break;
1375                                 }
1376                         }
1377                         break;
1378                 }
1379                 case P_STRING:
1380                         lpcfg_string_set(mem_ctx, (char **)parm_ptr, pszParmValue);
1381                         break;
1382
1383                 case P_USTRING:
1384                         lpcfg_string_set_upper(mem_ctx, (char **)parm_ptr, pszParmValue);
1385                         break;
1386
1387                 case P_ENUM:
1388                         for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
1389                                 if (strequal
1390                                     (pszParmValue,
1391                                      parm_table[parmnum].enum_list[i].name)) {
1392                                         *(int *)parm_ptr =
1393                                                 parm_table[parmnum].
1394                                                 enum_list[i].value;
1395                                         break;
1396                                 }
1397                         }
1398                         if (!parm_table[parmnum].enum_list[i].name) {
1399                                 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n", 
1400                                          pszParmValue, pszParmName));
1401                                 return false;
1402                         }
1403                         break;
1404
1405                 case P_SEP:
1406                         break;
1407         }
1408
1409 mark_non_default:
1410         if (on_globals && (lp_ctx->flags[parmnum] & FLAG_DEFAULT)) {
1411                 lp_ctx->flags[parmnum] &= ~FLAG_DEFAULT;
1412                 /* we have to also unset FLAG_DEFAULT on aliases */
1413                 for (i=parmnum-1;i>=0 && parm_table[i].offset == parm_table[parmnum].offset;i--) {
1414                         lp_ctx->flags[i] &= ~FLAG_DEFAULT;
1415                 }
1416                 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset;i++) {
1417                         lp_ctx->flags[i] &= ~FLAG_DEFAULT;
1418                 }
1419         }
1420         return true;
1421 }
1422
1423
1424 bool lpcfg_do_global_parameter(struct loadparm_context *lp_ctx,
1425                                const char *pszParmName, const char *pszParmValue)
1426 {
1427         int parmnum = lpcfg_map_parameter(pszParmName);
1428         void *parm_ptr;
1429
1430         if (parmnum < 0) {
1431                 if (strchr(pszParmName, ':')) {
1432                         return lp_do_parameter_parametric(lp_ctx, NULL, pszParmName, pszParmValue, 0);
1433                 }
1434                 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1435                 return true;
1436         }
1437
1438         /* if the flag has been set on the command line, then don't allow override,
1439            but don't report an error */
1440         if (lp_ctx->flags[parmnum] & FLAG_CMDLINE) {
1441                 return true;
1442         }
1443
1444         parm_ptr = lpcfg_parm_ptr(lp_ctx, NULL, &parm_table[parmnum]);
1445
1446         return set_variable(lp_ctx->globals, parmnum, parm_ptr,
1447                             pszParmName, pszParmValue, lp_ctx, true);
1448 }
1449
1450 bool lpcfg_do_service_parameter(struct loadparm_context *lp_ctx,
1451                                 struct loadparm_service *service,
1452                                 const char *pszParmName, const char *pszParmValue)
1453 {
1454         void *parm_ptr;
1455         int i;
1456         int parmnum = lpcfg_map_parameter(pszParmName);
1457
1458         if (parmnum < 0) {
1459                 if (strchr(pszParmName, ':')) {
1460                         return lp_do_parameter_parametric(lp_ctx, service, pszParmName, pszParmValue, 0);
1461                 }
1462                 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1463                 return true;
1464         }
1465
1466         /* if the flag has been set on the command line, then don't allow override,
1467            but don't report an error */
1468         if (lp_ctx->flags[parmnum] & FLAG_CMDLINE) {
1469                 return true;
1470         }
1471
1472         if (parm_table[parmnum].p_class == P_GLOBAL) {
1473                 DEBUG(0,
1474                       ("Global parameter %s found in service section!\n",
1475                        pszParmName));
1476                 return true;
1477         }
1478         parm_ptr = ((char *)service) + parm_table[parmnum].offset;
1479
1480         if (!service->copymap)
1481                 init_copymap(service);
1482
1483         /* this handles the aliases - set the copymap for other
1484          * entries with the same data pointer */
1485         for (i = 0; parm_table[i].label; i++)
1486                 if (parm_table[i].offset == parm_table[parmnum].offset &&
1487                     parm_table[i].p_class == parm_table[parmnum].p_class)
1488                         bitmap_clear(service->copymap, i);
1489
1490         return set_variable(service, parmnum, parm_ptr, pszParmName,
1491                             pszParmValue, lp_ctx, false);
1492 }
1493
1494 /**
1495  * Process a parameter.
1496  */
1497
1498 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
1499                          void *userdata)
1500 {
1501         struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata;
1502
1503         if (lp_ctx->bInGlobalSection)
1504                 return lpcfg_do_global_parameter(lp_ctx, pszParmName,
1505                                               pszParmValue);
1506         else
1507                 return lpcfg_do_service_parameter(lp_ctx, lp_ctx->currentService,
1508                                                   pszParmName, pszParmValue);
1509 }
1510
1511 /*
1512   variable argument do parameter
1513 */
1514 bool lpcfg_do_global_parameter_var(struct loadparm_context *lp_ctx, const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4);
1515 bool lpcfg_do_global_parameter_var(struct loadparm_context *lp_ctx,
1516                                 const char *pszParmName, const char *fmt, ...)
1517 {
1518         char *s;
1519         bool ret;
1520         va_list ap;
1521
1522         va_start(ap, fmt);
1523         s = talloc_vasprintf(NULL, fmt, ap);
1524         va_end(ap);
1525         ret = lpcfg_do_global_parameter(lp_ctx, pszParmName, s);
1526         talloc_free(s);
1527         return ret;
1528 }
1529
1530
1531 /*
1532   set a parameter from the commandline - this is called from command line parameter
1533   parsing code. It sets the parameter then marks the parameter as unable to be modified
1534   by smb.conf processing
1535 */
1536 bool lpcfg_set_cmdline(struct loadparm_context *lp_ctx, const char *pszParmName,
1537                        const char *pszParmValue)
1538 {
1539         int parmnum;
1540         int i;
1541
1542         if (lp_ctx->s3_fns) {
1543                 return lp_ctx->s3_fns->set_cmdline(pszParmName, pszParmValue);
1544         }
1545
1546         parmnum = lpcfg_map_parameter(pszParmName);
1547
1548         while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
1549
1550
1551         if (parmnum < 0 && strchr(pszParmName, ':')) {
1552                 /* set a parametric option */
1553                 return lp_do_parameter_parametric(lp_ctx, NULL, pszParmName,
1554                                                   pszParmValue, FLAG_CMDLINE);
1555         }
1556
1557         if (parmnum < 0) {
1558                 DEBUG(0,("Unknown option '%s'\n", pszParmName));
1559                 return false;
1560         }
1561
1562         /* reset the CMDLINE flag in case this has been called before */
1563         lp_ctx->flags[parmnum] &= ~FLAG_CMDLINE;
1564
1565         if (!lpcfg_do_global_parameter(lp_ctx, pszParmName, pszParmValue)) {
1566                 return false;
1567         }
1568
1569         lp_ctx->flags[parmnum] |= FLAG_CMDLINE;
1570
1571         /* we have to also set FLAG_CMDLINE on aliases */
1572         for (i=parmnum-1;
1573              i>=0 && parm_table[i].p_class == parm_table[parmnum].p_class &&
1574              parm_table[i].offset == parm_table[parmnum].offset;
1575              i--) {
1576                 lp_ctx->flags[i] |= FLAG_CMDLINE;
1577         }
1578         for (i=parmnum+1;
1579              i<NUMPARAMETERS &&
1580              parm_table[i].p_class == parm_table[parmnum].p_class &&
1581              parm_table[i].offset == parm_table[parmnum].offset;
1582              i++) {
1583                 lp_ctx->flags[i] |= FLAG_CMDLINE;
1584         }
1585
1586         return true;
1587 }
1588
1589 /*
1590   set a option from the commandline in 'a=b' format. Use to support --option
1591 */
1592 bool lpcfg_set_option(struct loadparm_context *lp_ctx, const char *option)
1593 {
1594         char *p, *s;
1595         bool ret;
1596
1597         s = talloc_strdup(NULL, option);
1598         if (!s) {
1599                 return false;
1600         }
1601
1602         p = strchr(s, '=');
1603         if (!p) {
1604                 talloc_free(s);
1605                 return false;
1606         }
1607
1608         *p = 0;
1609
1610         ret = lpcfg_set_cmdline(lp_ctx, s, p+1);
1611         talloc_free(s);
1612         return ret;
1613 }
1614
1615
1616 #define BOOLSTR(b) ((b) ? "Yes" : "No")
1617
1618 /**
1619  * Print a parameter of the specified type.
1620  */
1621
1622 void lpcfg_print_parameter(struct parm_struct *p, void *ptr, FILE * f)
1623 {
1624         /* For the seperation of lists values that we print below */
1625         const char *list_sep = ", ";
1626         int i;
1627         switch (p->type)
1628         {
1629                 case P_ENUM:
1630                         for (i = 0; p->enum_list[i].name; i++) {
1631                                 if (*(int *)ptr == p->enum_list[i].value) {
1632                                         fprintf(f, "%s",
1633                                                 p->enum_list[i].name);
1634                                         break;
1635                                 }
1636                         }
1637                         break;
1638
1639                 case P_BOOL:
1640                         fprintf(f, "%s", BOOLSTR(*(bool *)ptr));
1641                         break;
1642
1643                 case P_BOOLREV:
1644                         fprintf(f, "%s", BOOLSTR(!*(bool *)ptr));
1645                         break;
1646
1647                 case P_INTEGER:
1648                 case P_BYTES:
1649                         fprintf(f, "%d", *(int *)ptr);
1650                         break;
1651
1652                 case P_CHAR:
1653                         fprintf(f, "%c", *(char *)ptr);
1654                         break;
1655
1656                 case P_OCTAL: {
1657                         int val = *(int *)ptr; 
1658                         if (val == -1) {
1659                                 fprintf(f, "-1");
1660                         } else {
1661                                 fprintf(f, "0%03o", val);
1662                         }
1663                         break;
1664                 }
1665
1666                 case P_CMDLIST:
1667                         list_sep = " ";
1668                         /* fall through */
1669                 case P_LIST:
1670                         if ((char ***)ptr && *(char ***)ptr) {
1671                                 char **list = *(char ***)ptr;
1672                                 for (; *list; list++) {
1673                                         /* surround strings with whitespace in double quotes */
1674                                         if (*(list+1) == NULL) {
1675                                                 /* last item, no extra separator */
1676                                                 list_sep = "";
1677                                         }
1678                                         if ( strchr_m( *list, ' ' ) ) {
1679                                                 fprintf(f, "\"%s\"%s", *list, list_sep);
1680                                         } else {
1681                                                 fprintf(f, "%s%s", *list, list_sep);
1682                                         }
1683                                 }
1684                         }
1685                         break;
1686
1687                 case P_STRING:
1688                 case P_USTRING:
1689                         if (*(char **)ptr) {
1690                                 fprintf(f, "%s", *(char **)ptr);
1691                         }
1692                         break;
1693                 case P_SEP:
1694                         break;
1695         }
1696 }
1697
1698 /**
1699  * Check if two parameters are equal.
1700  */
1701
1702  bool lpcfg_equal_parameter(parm_type type, void *ptr1, void *ptr2)
1703 {
1704         switch (type) {
1705                 case P_BOOL:
1706                 case P_BOOLREV:
1707                         return (*((bool *)ptr1) == *((bool *)ptr2));
1708
1709                 case P_INTEGER:
1710                 case P_ENUM:
1711                 case P_OCTAL:
1712                 case P_BYTES:
1713                         return (*((int *)ptr1) == *((int *)ptr2));
1714
1715                 case P_CHAR:
1716                         return (*((char *)ptr1) == *((char *)ptr2));
1717
1718                 case P_LIST:
1719                 case P_CMDLIST:
1720                         return str_list_equal(*(const char ***)ptr1, *(const char ***)ptr2);
1721
1722                 case P_STRING:
1723                 case P_USTRING:
1724                 {
1725                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
1726                         if (p1 && !*p1)
1727                                 p1 = NULL;
1728                         if (p2 && !*p2)
1729                                 p2 = NULL;
1730                         return (p1 == p2 || strequal(p1, p2));
1731                 }
1732                 case P_SEP:
1733                         break;
1734         }
1735         return false;
1736 }
1737
1738 /**
1739  * Process a new section (service).
1740  *
1741  * At this stage all sections are services.
1742  * Later we'll have special sections that permit server parameters to be set.
1743  * Returns True on success, False on failure.
1744  */
1745
1746 static bool do_section(const char *pszSectionName, void *userdata)
1747 {
1748         struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata;
1749         bool bRetval;
1750         bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
1751                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
1752         bRetval = false;
1753
1754         /* if we've just struck a global section, note the fact. */
1755         lp_ctx->bInGlobalSection = isglobal;
1756
1757         /* check for multiple global sections */
1758         if (lp_ctx->bInGlobalSection) {
1759                 DEBUG(4, ("Processing section \"[%s]\"\n", pszSectionName));
1760                 return true;
1761         }
1762
1763         /* if we have a current service, tidy it up before moving on */
1764         bRetval = true;
1765
1766         if (lp_ctx->currentService != NULL)
1767                 bRetval = lpcfg_service_ok(lp_ctx->currentService);
1768
1769         /* if all is still well, move to the next record in the services array */
1770         if (bRetval) {
1771                 /* We put this here to avoid an odd message order if messages are */
1772                 /* issued by the post-processing of a previous section. */
1773                 DEBUG(4, ("Processing section \"[%s]\"\n", pszSectionName));
1774
1775                 if ((lp_ctx->currentService = lpcfg_add_service(lp_ctx, lp_ctx->sDefault,
1776                                                                    pszSectionName))
1777                     == NULL) {
1778                         DEBUG(0, ("Failed to add a new service\n"));
1779                         return false;
1780                 }
1781         }
1782
1783         return bRetval;
1784 }
1785
1786
1787 /**
1788  * Determine if a particular base parameter is currently set to the default value.
1789  */
1790
1791 static bool is_default(struct loadparm_service *sDefault, int i)
1792 {
1793         void *def_ptr = ((char *)sDefault) + parm_table[i].offset;
1794         switch (parm_table[i].type) {
1795                 case P_CMDLIST:
1796                 case P_LIST:
1797                         return str_list_equal((const char * const *)parm_table[i].def.lvalue,
1798                                               (const char **)def_ptr);
1799                 case P_STRING:
1800                 case P_USTRING:
1801                         return strequal(parm_table[i].def.svalue,
1802                                         *(char **)def_ptr);
1803                 case P_BOOL:
1804                 case P_BOOLREV:
1805                         return parm_table[i].def.bvalue ==
1806                                 *(bool *)def_ptr;
1807                 case P_INTEGER:
1808                 case P_CHAR:
1809                 case P_OCTAL:
1810                 case P_BYTES:
1811                 case P_ENUM:
1812                         return parm_table[i].def.ivalue ==
1813                                 *(int *)def_ptr;
1814                 case P_SEP:
1815                         break;
1816         }
1817         return false;
1818 }
1819
1820 /**
1821  *Display the contents of the global structure.
1822  */
1823
1824 static void dump_globals(struct loadparm_context *lp_ctx, FILE *f,
1825                          bool show_defaults)
1826 {
1827         int i;
1828         struct parmlist_entry *data;
1829
1830         fprintf(f, "# Global parameters\n[global]\n");
1831
1832         for (i = 0; parm_table[i].label; i++)
1833                 if (parm_table[i].p_class == P_GLOBAL &&
1834                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
1835                         if (!show_defaults && (lp_ctx->flags[i] & FLAG_DEFAULT))
1836                                 continue;
1837                         fprintf(f, "\t%s = ", parm_table[i].label);
1838                         lpcfg_print_parameter(&parm_table[i], lpcfg_parm_ptr(lp_ctx, NULL, &parm_table[i]), f);
1839                         fprintf(f, "\n");
1840         }
1841         if (lp_ctx->globals->param_opt != NULL) {
1842                 for (data = lp_ctx->globals->param_opt; data;
1843                      data = data->next) {
1844                         if (!show_defaults && (data->priority & FLAG_DEFAULT)) {
1845                                 continue;
1846                         }
1847                         fprintf(f, "\t%s = %s\n", data->key, data->value);
1848                 }
1849         }
1850
1851 }
1852
1853 /**
1854  * Display the contents of a single services record.
1855  */
1856
1857 static void dump_a_service(struct loadparm_service * pService, struct loadparm_service *sDefault, FILE * f,
1858                            unsigned int *flags)
1859 {
1860         int i;
1861         struct parmlist_entry *data;
1862
1863         if (pService != sDefault)
1864                 fprintf(f, "\n[%s]\n", pService->szService);
1865
1866         for (i = 0; parm_table[i].label; i++) {
1867                 if (parm_table[i].p_class == P_LOCAL &&
1868                     (*parm_table[i].label != '-') &&
1869                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset)))
1870                 {
1871                         if (pService == sDefault) {
1872                                 if (flags && (flags[i] & FLAG_DEFAULT)) {
1873                                         continue;
1874                                 }
1875                                 if (defaults_saved) {
1876                                         if (is_default(sDefault, i)) {
1877                                                 continue;
1878                                         }
1879                                 }
1880                         } else {
1881                                 if (lpcfg_equal_parameter(parm_table[i].type,
1882                                                           ((char *)pService) +
1883                                                           parm_table[i].offset,
1884                                                           ((char *)sDefault) +
1885                                                           parm_table[i].offset))
1886                                         continue;
1887                         }
1888
1889                         fprintf(f, "\t%s = ", parm_table[i].label);
1890                         lpcfg_print_parameter(&parm_table[i],
1891                                         ((char *)pService) + parm_table[i].offset, f);
1892                         fprintf(f, "\n");
1893                 }
1894         }
1895         if (pService->param_opt != NULL) {
1896                 for (data = pService->param_opt; data; data = data->next) {
1897                         fprintf(f, "\t%s = %s\n", data->key, data->value);
1898                 }
1899         }
1900 }
1901
1902 bool lpcfg_dump_a_parameter(struct loadparm_context *lp_ctx,
1903                             struct loadparm_service *service,
1904                             const char *parm_name, FILE * f)
1905 {
1906         struct parm_struct *parm;
1907         void *ptr;
1908
1909         parm = lpcfg_parm_struct(lp_ctx, parm_name);
1910         if (!parm) {
1911                 return false;
1912         }
1913
1914         if (service != NULL && parm->p_class == P_GLOBAL) {
1915                 return false;
1916         }
1917
1918         ptr = lpcfg_parm_ptr(lp_ctx, service,parm);
1919
1920         lpcfg_print_parameter(parm, ptr, f);
1921         fprintf(f, "\n");
1922         return true;
1923 }
1924
1925 /**
1926  * Auto-load some home services.
1927  */
1928 static void lpcfg_add_auto_services(struct loadparm_context *lp_ctx,
1929                                     const char *str)
1930 {
1931         return;
1932 }
1933
1934
1935 /**
1936  * Unload unused services.
1937  */
1938
1939 void lpcfg_killunused(struct loadparm_context *lp_ctx,
1940                    struct smbsrv_connection *smb,
1941                    bool (*snumused) (struct smbsrv_connection *, int))
1942 {
1943         int i;
1944         for (i = 0; i < lp_ctx->iNumServices; i++) {
1945                 if (lp_ctx->services[i] == NULL)
1946                         continue;
1947
1948                 if (!snumused || !snumused(smb, i)) {
1949                         talloc_free(lp_ctx->services[i]);
1950                         lp_ctx->services[i] = NULL;
1951                 }
1952         }
1953 }
1954
1955
1956 static int lpcfg_destructor(struct loadparm_context *lp_ctx)
1957 {
1958         struct parmlist_entry *data;
1959
1960         if (lp_ctx->refuse_free) {
1961                 /* someone is trying to free the
1962                    global_loadparm_context.
1963                    We can't allow that. */
1964                 return -1;
1965         }
1966
1967         if (lp_ctx->globals->param_opt != NULL) {
1968                 struct parmlist_entry *next;
1969                 for (data = lp_ctx->globals->param_opt; data; data=next) {
1970                         next = data->next;
1971                         if (data->priority & FLAG_CMDLINE) continue;
1972                         DLIST_REMOVE(lp_ctx->globals->param_opt, data);
1973                         talloc_free(data);
1974                 }
1975         }
1976
1977         return 0;
1978 }
1979
1980 /**
1981  * Initialise the global parameter structure.
1982  *
1983  * Note that most callers should use loadparm_init_global() instead
1984  */
1985 struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
1986 {
1987         int i;
1988         char *myname;
1989         struct loadparm_context *lp_ctx;
1990         struct parmlist_entry *parm;
1991         char *logfile;
1992
1993         lp_ctx = talloc_zero(mem_ctx, struct loadparm_context);
1994         if (lp_ctx == NULL)
1995                 return NULL;
1996
1997         talloc_set_destructor(lp_ctx, lpcfg_destructor);
1998         lp_ctx->bInGlobalSection = true;
1999         lp_ctx->globals = talloc_zero(lp_ctx, struct loadparm_global);
2000         lp_ctx->sDefault = talloc_zero(lp_ctx, struct loadparm_service);
2001
2002         lp_ctx->sDefault->iMaxPrintJobs = 1000;
2003         lp_ctx->sDefault->bAvailable = true;
2004         lp_ctx->sDefault->browseable = true;
2005         lp_ctx->sDefault->read_only = true;
2006         lp_ctx->sDefault->map_archive = true;
2007         lp_ctx->sDefault->strict_locking = true;
2008         lp_ctx->sDefault->oplocks = true;
2009         lp_ctx->sDefault->create_mask = 0744;
2010         lp_ctx->sDefault->force_create_mode = 0000;
2011         lp_ctx->sDefault->directory_mask = 0755;
2012         lp_ctx->sDefault->force_directory_mode = 0000;
2013
2014         DEBUG(3, ("Initialising global parameters\n"));
2015
2016         for (i = 0; parm_table[i].label; i++) {
2017                 if ((parm_table[i].type == P_STRING ||
2018                      parm_table[i].type == P_USTRING) &&
2019                     !(lp_ctx->flags[i] & FLAG_CMDLINE)) {
2020                         char **r;
2021                         if (parm_table[i].p_class == P_LOCAL) {
2022                                 r = (char **)(((char *)lp_ctx->sDefault) + parm_table[i].offset);
2023                         } else {
2024                                 r = (char **)(((char *)lp_ctx->globals) + parm_table[i].offset);
2025                         }
2026                         *r = talloc_strdup(lp_ctx, "");
2027                 }
2028         }
2029
2030         logfile = talloc_asprintf(lp_ctx, "%s/log.samba", dyn_LOGFILEBASE);
2031         lpcfg_do_global_parameter(lp_ctx, "log file", logfile);
2032         talloc_free(logfile);
2033
2034         lpcfg_do_global_parameter(lp_ctx, "log level", "0");
2035
2036         lpcfg_do_global_parameter(lp_ctx, "syslog", "1");
2037         lpcfg_do_global_parameter(lp_ctx, "syslog only", "No");
2038         lpcfg_do_global_parameter(lp_ctx, "debug timestamp", "Yes");
2039         lpcfg_do_global_parameter(lp_ctx, "debug prefix timestamp", "No");
2040         lpcfg_do_global_parameter(lp_ctx, "debug hires timestamp", "Yes");
2041         lpcfg_do_global_parameter(lp_ctx, "debug pid", "No");
2042         lpcfg_do_global_parameter(lp_ctx, "debug uid", "No");
2043         lpcfg_do_global_parameter(lp_ctx, "debug class", "No");
2044
2045         lpcfg_do_global_parameter(lp_ctx, "share backend", "classic");
2046
2047         lpcfg_do_global_parameter(lp_ctx, "server role", "auto");
2048         lpcfg_do_global_parameter(lp_ctx, "domain logons", "No");
2049         lpcfg_do_global_parameter(lp_ctx, "domain master", "Auto");
2050
2051         /* options that can be set on the command line must be initialised via
2052            the slower lpcfg_do_global_parameter() to ensure that FLAG_CMDLINE is obeyed */
2053 #ifdef TCP_NODELAY
2054         lpcfg_do_global_parameter(lp_ctx, "socket options", "TCP_NODELAY");
2055 #endif
2056         lpcfg_do_global_parameter(lp_ctx, "workgroup", DEFAULT_WORKGROUP);
2057         myname = get_myname(lp_ctx);
2058         lpcfg_do_global_parameter(lp_ctx, "netbios name", myname);
2059         talloc_free(myname);
2060         lpcfg_do_global_parameter(lp_ctx, "name resolve order", "lmhosts wins host bcast");
2061
2062         lpcfg_do_global_parameter(lp_ctx, "fstype", "NTFS");
2063
2064         lpcfg_do_global_parameter(lp_ctx, "ntvfs handler", "unixuid default");
2065         lpcfg_do_global_parameter(lp_ctx, "max connections", "0");
2066
2067         lpcfg_do_global_parameter(lp_ctx, "dcerpc endpoint servers", "epmapper wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi dssetup unixinfo browser eventlog6 backupkey dnsserver");
2068         lpcfg_do_global_parameter(lp_ctx, "server services", "s3fs rpc nbt wrepl ldap cldap kdc drepl winbind ntp_signd kcc dnsupdate dns");
2069         lpcfg_do_global_parameter(lp_ctx, "kccsrv:samba_kcc", "true");
2070         /* the winbind method for domain controllers is for both RODC
2071            auth forwarding and for trusted domains */
2072         lpcfg_do_global_parameter(lp_ctx, "private dir", dyn_PRIVATE_DIR);
2073         lpcfg_do_global_parameter(lp_ctx, "registry:HKEY_LOCAL_MACHINE", "hklm.ldb");
2074
2075         /* This hive should be dynamically generated by Samba using
2076            data from the sam, but for the moment leave it in a tdb to
2077            keep regedt32 from popping up an annoying dialog. */
2078         lpcfg_do_global_parameter(lp_ctx, "registry:HKEY_USERS", "hku.ldb");
2079
2080         /* using UTF8 by default allows us to support all chars */
2081         lpcfg_do_global_parameter(lp_ctx, "unix charset", "UTF-8");
2082
2083         /* Use codepage 850 as a default for the dos character set */
2084         lpcfg_do_global_parameter(lp_ctx, "dos charset", "CP850");
2085
2086         /*
2087          * Allow the default PASSWD_CHAT to be overridden in local.h.
2088          */
2089         lpcfg_do_global_parameter(lp_ctx, "passwd chat", DEFAULT_PASSWD_CHAT);
2090
2091         lpcfg_do_global_parameter(lp_ctx, "pid directory", dyn_PIDDIR);
2092         lpcfg_do_global_parameter(lp_ctx, "lock dir", dyn_LOCKDIR);
2093         lpcfg_do_global_parameter(lp_ctx, "state directory", dyn_STATEDIR);
2094         lpcfg_do_global_parameter(lp_ctx, "cache directory", dyn_CACHEDIR);
2095         lpcfg_do_global_parameter(lp_ctx, "ncalrpc dir", dyn_NCALRPCDIR);
2096
2097         lpcfg_do_global_parameter(lp_ctx, "nbt client socket address", "0.0.0.0");
2098         lpcfg_do_global_parameter_var(lp_ctx, "server string",
2099                                    "Samba %s", SAMBA_VERSION_STRING);
2100
2101         lpcfg_do_global_parameter(lp_ctx, "password server", "*");
2102
2103         lpcfg_do_global_parameter(lp_ctx, "max mux", "50");
2104         lpcfg_do_global_parameter(lp_ctx, "max xmit", "16644");
2105         lpcfg_do_global_parameter(lp_ctx, "host msdfs", "true");
2106
2107         lpcfg_do_global_parameter(lp_ctx, "LargeReadwrite", "True");
2108         lpcfg_do_global_parameter(lp_ctx, "server min protocol", "LANMAN1");
2109         lpcfg_do_global_parameter(lp_ctx, "server max protocol", "SMB3");
2110         lpcfg_do_global_parameter(lp_ctx, "client min protocol", "CORE");
2111         lpcfg_do_global_parameter(lp_ctx, "client max protocol", "NT1");
2112         lpcfg_do_global_parameter(lp_ctx, "security", "AUTO");
2113         lpcfg_do_global_parameter(lp_ctx, "EncryptPasswords", "True");
2114         lpcfg_do_global_parameter(lp_ctx, "ReadRaw", "True");
2115         lpcfg_do_global_parameter(lp_ctx, "WriteRaw", "True");
2116         lpcfg_do_global_parameter(lp_ctx, "NullPasswords", "False");
2117         lpcfg_do_global_parameter(lp_ctx, "old password allowed period", "60");
2118         lpcfg_do_global_parameter(lp_ctx, "ObeyPamRestrictions", "False");
2119
2120         lpcfg_do_global_parameter(lp_ctx, "TimeServer", "False");
2121         lpcfg_do_global_parameter(lp_ctx, "BindInterfacesOnly", "False");
2122         lpcfg_do_global_parameter(lp_ctx, "Unicode", "True");
2123         lpcfg_do_global_parameter(lp_ctx, "ClientLanManAuth", "False");
2124         lpcfg_do_global_parameter(lp_ctx, "ClientNTLMv2Auth", "True");
2125         lpcfg_do_global_parameter(lp_ctx, "LanmanAuth", "False");
2126         lpcfg_do_global_parameter(lp_ctx, "NTLMAuth", "True");
2127         lpcfg_do_global_parameter(lp_ctx, "client use spnego principal", "False");
2128
2129         lpcfg_do_global_parameter(lp_ctx, "UnixExtensions", "True");
2130
2131         lpcfg_do_global_parameter(lp_ctx, "PreferredMaster", "Auto");
2132         lpcfg_do_global_parameter(lp_ctx, "LocalMaster", "True");
2133
2134         lpcfg_do_global_parameter(lp_ctx, "wins support", "False");
2135         lpcfg_do_global_parameter(lp_ctx, "dns proxy", "True");
2136
2137         lpcfg_do_global_parameter(lp_ctx, "winbind separator", "\\");
2138         lpcfg_do_global_parameter(lp_ctx, "winbind sealed pipes", "True");
2139         lpcfg_do_global_parameter(lp_ctx, "require strong key", "True");
2140         lpcfg_do_global_parameter(lp_ctx, "winbindd socket directory", dyn_WINBINDD_SOCKET_DIR);
2141         lpcfg_do_global_parameter(lp_ctx, "winbindd privileged socket directory", dyn_WINBINDD_PRIVILEGED_SOCKET_DIR);
2142         lpcfg_do_global_parameter(lp_ctx, "ntp signd socket directory", dyn_NTP_SIGND_SOCKET_DIR);
2143         lpcfg_do_global_parameter_var(lp_ctx, "dns update command", "%s/samba_dnsupdate", dyn_SCRIPTSBINDIR);
2144         lpcfg_do_global_parameter_var(lp_ctx, "spn update command", "%s/samba_spnupdate", dyn_SCRIPTSBINDIR);
2145         lpcfg_do_global_parameter_var(lp_ctx, "samba kcc command",
2146                                         "%s/samba_kcc", dyn_SCRIPTSBINDIR);
2147         lpcfg_do_global_parameter(lp_ctx, "template shell", "/bin/false");
2148         lpcfg_do_global_parameter(lp_ctx, "template homedir", "/home/%WORKGROUP%/%ACCOUNTNAME%");
2149
2150         lpcfg_do_global_parameter(lp_ctx, "client signing", "default");
2151         lpcfg_do_global_parameter(lp_ctx, "server signing", "default");
2152
2153         lpcfg_do_global_parameter(lp_ctx, "use spnego", "True");
2154
2155         lpcfg_do_global_parameter(lp_ctx, "use mmap", "True");
2156
2157         lpcfg_do_global_parameter(lp_ctx, "smb ports", "445 139");
2158         lpcfg_do_global_parameter(lp_ctx, "nbt port", "137");
2159         lpcfg_do_global_parameter(lp_ctx, "dgram port", "138");
2160         lpcfg_do_global_parameter(lp_ctx, "cldap port", "389");
2161         lpcfg_do_global_parameter(lp_ctx, "krb5 port", "88");
2162         lpcfg_do_global_parameter(lp_ctx, "kpasswd port", "464");
2163         lpcfg_do_global_parameter(lp_ctx, "web port", "901");
2164
2165         lpcfg_do_global_parameter(lp_ctx, "nt status support", "True");
2166
2167         lpcfg_do_global_parameter(lp_ctx, "max wins ttl", "518400"); /* 6 days */
2168         lpcfg_do_global_parameter(lp_ctx, "min wins ttl", "21600");
2169
2170         lpcfg_do_global_parameter(lp_ctx, "tls enabled", "True");
2171         lpcfg_do_global_parameter(lp_ctx, "tls keyfile", "tls/key.pem");
2172         lpcfg_do_global_parameter(lp_ctx, "tls certfile", "tls/cert.pem");
2173         lpcfg_do_global_parameter(lp_ctx, "tls cafile", "tls/ca.pem");
2174         lpcfg_do_global_parameter(lp_ctx, "prefork children:smb", "4");
2175
2176         lpcfg_do_global_parameter(lp_ctx, "rndc command", "/usr/sbin/rndc");
2177         lpcfg_do_global_parameter(lp_ctx, "nsupdate command", "/usr/bin/nsupdate -g");
2178
2179         lpcfg_do_global_parameter(lp_ctx, "allow dns updates", "secure only");
2180         lpcfg_do_global_parameter(lp_ctx, "dns forwarder", "");
2181
2182         lpcfg_do_global_parameter(lp_ctx, "algorithmic rid base", "1000");
2183
2184         lpcfg_do_global_parameter(lp_ctx, "enhanced browsing", "True");
2185
2186         lpcfg_do_global_parameter(lp_ctx, "winbind nss info", "template");
2187
2188         lpcfg_do_global_parameter(lp_ctx, "server schannel", "Auto");
2189
2190         lpcfg_do_global_parameter(lp_ctx, "short preserve case", "True");
2191
2192         lpcfg_do_global_parameter(lp_ctx, "max open files", "16384");
2193
2194         lpcfg_do_global_parameter(lp_ctx, "cups connection timeout", "30");
2195
2196         lpcfg_do_global_parameter(lp_ctx, "locking", "True");
2197
2198         lpcfg_do_global_parameter(lp_ctx, "block size", "1024");
2199
2200         lpcfg_do_global_parameter(lp_ctx, "client use spnego", "True");
2201
2202         lpcfg_do_global_parameter(lp_ctx, "change notify", "True");
2203
2204         lpcfg_do_global_parameter(lp_ctx, "name cache timeout", "660");
2205
2206         lpcfg_do_global_parameter(lp_ctx, "defer sharing violations", "True");
2207
2208         lpcfg_do_global_parameter(lp_ctx, "ldap replication sleep", "1000");
2209
2210         lpcfg_do_global_parameter(lp_ctx, "idmap backend", "tdb");
2211
2212         lpcfg_do_global_parameter(lp_ctx, "enable privileges", "True");
2213
2214         lpcfg_do_global_parameter_var(lp_ctx, "smb2 max write", "%u", DEFAULT_SMB2_MAX_WRITE);
2215
2216         lpcfg_do_global_parameter(lp_ctx, "passdb backend", "tdbsam");
2217
2218         lpcfg_do_global_parameter(lp_ctx, "getwd cache", "True");
2219
2220         lpcfg_do_global_parameter(lp_ctx, "winbind nested groups", "True");
2221
2222         lpcfg_do_global_parameter(lp_ctx, "mangled names", "True");
2223
2224         lpcfg_do_global_parameter_var(lp_ctx, "smb2 max credits", "%u", DEFAULT_SMB2_MAX_CREDITS);
2225
2226         lpcfg_do_global_parameter(lp_ctx, "ldap ssl", "start tls");
2227
2228         lpcfg_do_global_parameter(lp_ctx, "ldap deref", "auto");
2229
2230         lpcfg_do_global_parameter(lp_ctx, "lm interval", "60");
2231
2232         lpcfg_do_global_parameter(lp_ctx, "mangling method", "hash2");
2233
2234         lpcfg_do_global_parameter(lp_ctx, "hide dot files", "True");
2235
2236         lpcfg_do_global_parameter(lp_ctx, "browse list", "True");
2237
2238         lpcfg_do_global_parameter(lp_ctx, "passwd chat timeout", "2");
2239
2240         lpcfg_do_global_parameter(lp_ctx, "guest account", GUEST_ACCOUNT);
2241
2242         lpcfg_do_global_parameter(lp_ctx, "client schannel", "auto");
2243
2244         lpcfg_do_global_parameter(lp_ctx, "smb encrypt", "default");
2245
2246         lpcfg_do_global_parameter(lp_ctx, "max log size", "5000");
2247
2248         lpcfg_do_global_parameter(lp_ctx, "idmap negative cache time", "120");
2249
2250         lpcfg_do_global_parameter(lp_ctx, "ldap follow referral", "auto");
2251
2252         lpcfg_do_global_parameter(lp_ctx, "multicast dns register", "yes");
2253
2254         lpcfg_do_global_parameter(lp_ctx, "winbind reconnect delay", "30");
2255
2256         lpcfg_do_global_parameter(lp_ctx, "nt acl support", "yes");
2257
2258         lpcfg_do_global_parameter(lp_ctx, "acl check permissions", "yes");
2259
2260         lpcfg_do_global_parameter(lp_ctx, "keepalive", "300");
2261
2262         lpcfg_do_global_parameter(lp_ctx, "winbind cache time", "300");
2263
2264         lpcfg_do_global_parameter(lp_ctx, "level2 oplocks", "yes");
2265
2266         lpcfg_do_global_parameter(lp_ctx, "show add printer wizard", "yes");
2267
2268         lpcfg_do_global_parameter(lp_ctx, "allocation roundup size", "1048576");
2269
2270         lpcfg_do_global_parameter(lp_ctx, "ldap page size", "1024");
2271
2272         lpcfg_do_global_parameter(lp_ctx, "kernel share modes", "yes");
2273
2274         lpcfg_do_global_parameter(lp_ctx, "strict locking", "Auto");
2275
2276         lpcfg_do_global_parameter(lp_ctx, "map readonly", "yes");
2277
2278         lpcfg_do_global_parameter(lp_ctx, "allow trusted domains", "yes");
2279
2280         lpcfg_do_global_parameter(lp_ctx, "default devmode", "yes");
2281
2282         lpcfg_do_global_parameter(lp_ctx, "os level", "20");
2283
2284         lpcfg_do_global_parameter(lp_ctx, "dos filetimes", "yes");
2285
2286         lpcfg_do_global_parameter(lp_ctx, "mangling char", "~");
2287
2288         lpcfg_do_global_parameter(lp_ctx, "printcap cache time", "750");
2289
2290         lpcfg_do_global_parameter(lp_ctx, "create krb5 conf", "yes");
2291
2292         lpcfg_do_global_parameter(lp_ctx, "winbind max clients", "200");
2293
2294         lpcfg_do_global_parameter(lp_ctx, "acl map full control", "yes");
2295
2296         lpcfg_do_global_parameter(lp_ctx, "nt pipe support", "yes");
2297
2298         lpcfg_do_global_parameter(lp_ctx, "ldap debug threshold", "10");
2299
2300         lpcfg_do_global_parameter(lp_ctx, "follow symlinks", "yes");
2301
2302         lpcfg_do_global_parameter(lp_ctx, "machine password timeout", "604800");
2303
2304         lpcfg_do_global_parameter(lp_ctx, "ldap connection timeout", "2");
2305
2306         lpcfg_do_global_parameter(lp_ctx, "winbind expand groups", "1");
2307
2308         lpcfg_do_global_parameter(lp_ctx, "stat cache", "yes");
2309
2310         lpcfg_do_global_parameter(lp_ctx, "lpq cache time", "30");
2311
2312         lpcfg_do_global_parameter_var(lp_ctx, "smb2 max trans", "%u", DEFAULT_SMB2_MAX_TRANSACT);
2313
2314         lpcfg_do_global_parameter_var(lp_ctx, "smb2 max read", "%u", DEFAULT_SMB2_MAX_READ);
2315
2316         lpcfg_do_global_parameter(lp_ctx, "durable handles", "yes");
2317
2318         lpcfg_do_global_parameter(lp_ctx, "max stat cache size", "256");
2319
2320         lpcfg_do_global_parameter(lp_ctx, "ldap passwd sync", "no");
2321
2322         lpcfg_do_global_parameter(lp_ctx, "kernel change notify", "yes");
2323
2324         lpcfg_do_global_parameter(lp_ctx, "max ttl", "259200");
2325
2326         lpcfg_do_global_parameter(lp_ctx, "blocking locks", "yes");
2327
2328         lpcfg_do_global_parameter(lp_ctx, "oplock contention limit", "2");
2329
2330         lpcfg_do_global_parameter(lp_ctx, "load printers", "yes");
2331
2332         lpcfg_do_global_parameter(lp_ctx, "idmap cache time", "604800");
2333
2334         lpcfg_do_global_parameter(lp_ctx, "preserve case", "yes");
2335
2336         lpcfg_do_global_parameter(lp_ctx, "lm announce", "auto");
2337
2338         lpcfg_do_global_parameter(lp_ctx, "afs token lifetime", "604800");
2339
2340         lpcfg_do_global_parameter(lp_ctx, "enable core files", "yes");
2341
2342         lpcfg_do_global_parameter(lp_ctx, "winbind max domain connections", "1");
2343
2344         lpcfg_do_global_parameter(lp_ctx, "case sensitive", "auto");
2345
2346         lpcfg_do_global_parameter(lp_ctx, "ldap timeout", "15");
2347
2348         lpcfg_do_global_parameter(lp_ctx, "mangle prefix", "1");
2349
2350         lpcfg_do_global_parameter(lp_ctx, "posix locking", "yes");
2351
2352         lpcfg_do_global_parameter(lp_ctx, "lock spin time", "200");
2353
2354         lpcfg_do_global_parameter(lp_ctx, "directory name cache size", "100");
2355
2356         lpcfg_do_global_parameter(lp_ctx, "nmbd bind explicit broadcast", "yes");
2357
2358         lpcfg_do_global_parameter(lp_ctx, "init logon delay", "100");
2359
2360         lpcfg_do_global_parameter(lp_ctx, "usershare owner only", "yes");
2361
2362         lpcfg_do_global_parameter(lp_ctx, "-valid", "yes");
2363
2364         lpcfg_do_global_parameter_var(lp_ctx, "usershare path", "%s/usershares", get_dyn_STATEDIR());
2365
2366 #ifdef DEVELOPER
2367         lpcfg_do_global_parameter_var(lp_ctx, "panic action", "/bin/sleep 999999999");
2368 #endif
2369
2370         lpcfg_do_global_parameter(lp_ctx, "smb passwd file", get_dyn_SMB_PASSWD_FILE());
2371
2372         lpcfg_do_global_parameter(lp_ctx, "logon home", "\\\\%N\\%U");
2373
2374         lpcfg_do_global_parameter(lp_ctx, "logon path", "\\\\%N\\%U\\profile");
2375
2376         lpcfg_do_global_parameter(lp_ctx, "printjob username", "%U");
2377
2378         for (i = 0; parm_table[i].label; i++) {
2379                 if (!(lp_ctx->flags[i] & FLAG_CMDLINE)) {
2380                         lp_ctx->flags[i] |= FLAG_DEFAULT;
2381                 }
2382         }
2383
2384         for (parm=lp_ctx->globals->param_opt; parm; parm=parm->next) {
2385                 if (!(parm->priority & FLAG_CMDLINE)) {
2386                         parm->priority |= FLAG_DEFAULT;
2387                 }
2388         }
2389
2390         return lp_ctx;
2391 }
2392
2393 /**
2394  * Initialise the global parameter structure.
2395  */
2396 struct loadparm_context *loadparm_init_global(bool load_default)
2397 {
2398         if (global_loadparm_context == NULL) {
2399                 global_loadparm_context = loadparm_init(NULL);
2400         }
2401         if (global_loadparm_context == NULL) {
2402                 return NULL;
2403         }
2404         global_loadparm_context->global = true;
2405         if (load_default && !global_loadparm_context->loaded) {
2406                 lpcfg_load_default(global_loadparm_context);
2407         }
2408         global_loadparm_context->refuse_free = true;
2409         return global_loadparm_context;
2410 }
2411
2412 /**
2413  * Initialise the global parameter structure.
2414  */
2415 struct loadparm_context *loadparm_init_s3(TALLOC_CTX *mem_ctx, 
2416                                           const struct loadparm_s3_helpers *s3_fns)
2417 {
2418         struct loadparm_context *loadparm_context = talloc_zero(mem_ctx, struct loadparm_context);
2419         if (!loadparm_context) {
2420                 return NULL;
2421         }
2422         loadparm_context->s3_fns = s3_fns;
2423         loadparm_context->globals = s3_fns->globals;
2424         return loadparm_context;
2425 }
2426
2427 const char *lpcfg_configfile(struct loadparm_context *lp_ctx)
2428 {
2429         return lp_ctx->szConfigFile;
2430 }
2431
2432 const char *lp_default_path(void)
2433 {
2434     if (getenv("SMB_CONF_PATH"))
2435         return getenv("SMB_CONF_PATH");
2436     else
2437         return dyn_CONFIGFILE;
2438 }
2439
2440 /**
2441  * Update the internal state of a loadparm context after settings 
2442  * have changed.
2443  */
2444 static bool lpcfg_update(struct loadparm_context *lp_ctx)
2445 {
2446         struct debug_settings settings;
2447         TALLOC_CTX *tmp_ctx;
2448
2449         tmp_ctx = talloc_new(lp_ctx);
2450         if (tmp_ctx == NULL) {
2451                 return false;
2452         }
2453
2454         lpcfg_add_auto_services(lp_ctx, lpcfg_auto_services(lp_ctx, tmp_ctx));
2455
2456         if (!lp_ctx->globals->wins_server_list && lp_ctx->globals->we_are_a_wins_server) {
2457                 lpcfg_do_global_parameter(lp_ctx, "wins server", "127.0.0.1");
2458         }
2459
2460         if (!lp_ctx->global) {
2461                 TALLOC_FREE(tmp_ctx);
2462                 return true;
2463         }
2464
2465         panic_action = lp_ctx->globals->panic_action;
2466
2467         reload_charcnv(lp_ctx);
2468
2469         ZERO_STRUCT(settings);
2470         /* Add any more debug-related smb.conf parameters created in
2471          * future here */
2472         settings.syslog = lp_ctx->globals->syslog;
2473         settings.syslog_only = lp_ctx->globals->syslog_only;
2474         settings.timestamp_logs = lp_ctx->globals->timestamp_logs;
2475         settings.debug_prefix_timestamp = lp_ctx->globals->debug_prefix_timestamp;
2476         settings.debug_hires_timestamp = lp_ctx->globals->debug_hires_timestamp;
2477         settings.debug_pid = lp_ctx->globals->debug_pid;
2478         settings.debug_uid = lp_ctx->globals->debug_uid;
2479         settings.debug_class = lp_ctx->globals->debug_class;
2480         debug_set_settings(&settings);
2481
2482         /* FIXME: This is a bit of a hack, but we can't use a global, since 
2483          * not everything that uses lp also uses the socket library */
2484         if (lpcfg_parm_bool(lp_ctx, NULL, "socket", "testnonblock", false)) {
2485                 setenv("SOCKET_TESTNONBLOCK", "1", 1);
2486         } else {
2487                 unsetenv("SOCKET_TESTNONBLOCK");
2488         }
2489
2490         TALLOC_FREE(tmp_ctx);
2491         return true;
2492 }
2493
2494 bool lpcfg_load_default(struct loadparm_context *lp_ctx)
2495 {
2496     const char *path;
2497
2498     path = lp_default_path();
2499
2500     if (!file_exist(path)) {
2501             /* We allow the default smb.conf file to not exist, 
2502              * basically the equivalent of an empty file. */
2503             return lpcfg_update(lp_ctx);
2504     }
2505
2506     return lpcfg_load(lp_ctx, path);
2507 }
2508
2509 /**
2510  * Load the services array from the services file.
2511  *
2512  * Return True on success, False on failure.
2513  */
2514 bool lpcfg_load(struct loadparm_context *lp_ctx, const char *filename)
2515 {
2516         char *n2;
2517         bool bRetval;
2518
2519         filename = talloc_strdup(lp_ctx, filename);
2520
2521         lp_ctx->szConfigFile = filename;
2522
2523         if (lp_ctx->s3_fns) {
2524                 return lp_ctx->s3_fns->load(filename);
2525         }
2526
2527         lp_ctx->bInGlobalSection = true;
2528         n2 = standard_sub_basic(lp_ctx, lp_ctx->szConfigFile);
2529         DEBUG(2, ("lpcfg_load: refreshing parameters from %s\n", n2));
2530
2531         add_to_file_list(lp_ctx, lp_ctx->szConfigFile, n2);
2532
2533         /* We get sections first, so have to start 'behind' to make up */
2534         lp_ctx->currentService = NULL;
2535         bRetval = pm_process(n2, do_section, do_parameter, lp_ctx);
2536
2537         /* finish up the last section */
2538         DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
2539         if (bRetval)
2540                 if (lp_ctx->currentService != NULL)
2541                         bRetval = lpcfg_service_ok(lp_ctx->currentService);
2542
2543         bRetval = bRetval && lpcfg_update(lp_ctx);
2544
2545         /* we do this unconditionally, so that it happens even
2546            for a missing smb.conf */
2547         reload_charcnv(lp_ctx);
2548
2549         if (bRetval == true) {
2550                 /* set this up so that any child python tasks will
2551                    find the right smb.conf */
2552                 setenv("SMB_CONF_PATH", filename, 1);
2553
2554                 /* set the context used by the lp_*() function
2555                    varients */
2556                 global_loadparm_context = lp_ctx;
2557                 lp_ctx->loaded = true;
2558         }
2559
2560         return bRetval;
2561 }
2562
2563 /**
2564  * Return the max number of services.
2565  */
2566
2567 int lpcfg_numservices(struct loadparm_context *lp_ctx)
2568 {
2569         if (lp_ctx->s3_fns) {
2570                 return lp_ctx->s3_fns->get_numservices();
2571         }
2572
2573         return lp_ctx->iNumServices;
2574 }
2575
2576 /**
2577  * Display the contents of the services array in human-readable form.
2578  */
2579
2580 void lpcfg_dump(struct loadparm_context *lp_ctx, FILE *f, bool show_defaults,
2581              int maxtoprint)
2582 {
2583         int iService;
2584
2585         if (lp_ctx->s3_fns) {
2586                 lp_ctx->s3_fns->dump(f, show_defaults, maxtoprint);
2587                 return;
2588         }
2589
2590         defaults_saved = !show_defaults;
2591
2592         dump_globals(lp_ctx, f, show_defaults);
2593
2594         dump_a_service(lp_ctx->sDefault, lp_ctx->sDefault, f, lp_ctx->flags);
2595
2596         for (iService = 0; iService < maxtoprint; iService++)
2597                 lpcfg_dump_one(f, show_defaults, lp_ctx->services[iService], lp_ctx->sDefault);
2598 }
2599
2600 /**
2601  * Display the contents of one service in human-readable form.
2602  */
2603 void lpcfg_dump_one(FILE *f, bool show_defaults, struct loadparm_service *service, struct loadparm_service *sDefault)
2604 {
2605         if (service != NULL) {
2606                 if (service->szService[0] == '\0')
2607                         return;
2608                 dump_a_service(service, sDefault, f, NULL);
2609         }
2610 }
2611
2612 struct loadparm_service *lpcfg_servicebynum(struct loadparm_context *lp_ctx,
2613                                             int snum)
2614 {
2615         if (lp_ctx->s3_fns) {
2616                 return lp_ctx->s3_fns->get_servicebynum(snum);
2617         }
2618
2619         return lp_ctx->services[snum];
2620 }
2621
2622 struct loadparm_service *lpcfg_service(struct loadparm_context *lp_ctx,
2623                                     const char *service_name)
2624 {
2625         int iService;
2626         char *serviceName;
2627
2628         if (lp_ctx->s3_fns) {
2629                 return lp_ctx->s3_fns->get_service(service_name);
2630         }
2631
2632         for (iService = lp_ctx->iNumServices - 1; iService >= 0; iService--) {
2633                 if (lp_ctx->services[iService] &&
2634                     lp_ctx->services[iService]->szService) {
2635                         /*
2636                          * The substitution here is used to support %U is
2637                          * service names
2638                          */
2639                         serviceName = standard_sub_basic(
2640                                         lp_ctx->services[iService],
2641                                         lp_ctx->services[iService]->szService);
2642                         if (strequal(serviceName, service_name)) {
2643                                 talloc_free(serviceName);
2644                                 return lp_ctx->services[iService];
2645                         }
2646                         talloc_free(serviceName);
2647                 }
2648         }
2649
2650         DEBUG(7,("lpcfg_servicenumber: couldn't find %s\n", service_name));
2651         return NULL;
2652 }
2653
2654 const char *lpcfg_servicename(const struct loadparm_service *service)
2655 {
2656         return lpcfg_string((const char *)service->szService);
2657 }
2658
2659 /**
2660  * A useful volume label function.
2661  */
2662 const char *lpcfg_volume_label(struct loadparm_service *service, struct loadparm_service *sDefault)
2663 {
2664         const char *ret;
2665         ret = lpcfg_string((const char *)((service != NULL && service->volume != NULL) ?
2666                                        service->volume : sDefault->volume));
2667         if (!*ret)
2668                 return lpcfg_servicename(service);
2669         return ret;
2670 }
2671
2672 /**
2673  * Return the correct printer name.
2674  */
2675 const char *lpcfg_printername(struct loadparm_service *service, struct loadparm_service *sDefault)
2676 {
2677         const char *ret;
2678         ret = lpcfg_string((const char *)((service != NULL && service->_printername != NULL) ?
2679                                        service->_printername : sDefault->_printername));
2680         if (ret == NULL || (ret != NULL && *ret == '\0'))
2681                 ret = lpcfg_servicename(service);
2682
2683         return ret;
2684 }
2685
2686
2687 /**
2688  * Return the max print jobs per queue.
2689  */
2690 int lpcfg_maxprintjobs(struct loadparm_service *service, struct loadparm_service *sDefault)
2691 {
2692         int maxjobs = (service != NULL) ? service->iMaxPrintJobs : sDefault->iMaxPrintJobs;
2693         if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
2694                 maxjobs = PRINT_MAX_JOBID - 1;
2695
2696         return maxjobs;
2697 }
2698
2699 struct smb_iconv_handle *lpcfg_iconv_handle(struct loadparm_context *lp_ctx)
2700 {
2701         if (lp_ctx == NULL) {
2702                 return get_iconv_handle();
2703         }
2704         return lp_ctx->iconv_handle;
2705 }
2706
2707 _PUBLIC_ void reload_charcnv(struct loadparm_context *lp_ctx)
2708 {
2709         struct smb_iconv_handle *old_ic = lp_ctx->iconv_handle;
2710         if (!lp_ctx->global) {
2711                 return;
2712         }
2713
2714         if (old_ic == NULL) {
2715                 old_ic = global_iconv_handle;
2716         }
2717         lp_ctx->iconv_handle = smb_iconv_handle_reinit_lp(lp_ctx, lp_ctx, old_ic);
2718         global_iconv_handle = lp_ctx->iconv_handle;
2719 }
2720
2721 _PUBLIC_ char *lpcfg_tls_keyfile(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
2722 {
2723         return lpcfg_private_path(mem_ctx, lp_ctx, lpcfg__tls_keyfile(lp_ctx));
2724 }
2725
2726 _PUBLIC_ char *lpcfg_tls_certfile(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
2727 {
2728         return lpcfg_private_path(mem_ctx, lp_ctx, lpcfg__tls_certfile(lp_ctx));
2729 }
2730
2731 _PUBLIC_ char *lpcfg_tls_cafile(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
2732 {
2733         return lpcfg_private_path(mem_ctx, lp_ctx, lpcfg__tls_cafile(lp_ctx));
2734 }
2735
2736 _PUBLIC_ char *lpcfg_tls_crlfile(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
2737 {
2738         return lpcfg_private_path(mem_ctx, lp_ctx, lpcfg__tls_crlfile(lp_ctx));
2739 }
2740
2741 _PUBLIC_ char *lpcfg_tls_dhpfile(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
2742 {
2743         return lpcfg_private_path(mem_ctx, lp_ctx, lpcfg__tls_dhpfile(lp_ctx));
2744 }
2745
2746 struct gensec_settings *lpcfg_gensec_settings(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
2747 {
2748         struct gensec_settings *settings = talloc_zero(mem_ctx, struct gensec_settings);
2749         if (settings == NULL)
2750                 return NULL;
2751         SMB_ASSERT(lp_ctx != NULL);
2752         settings->lp_ctx = talloc_reference(settings, lp_ctx);
2753         settings->target_hostname = lpcfg_parm_string(lp_ctx, NULL, "gensec", "target_hostname");
2754         return settings;
2755 }
2756
2757 int lpcfg_server_role(struct loadparm_context *lp_ctx)
2758 {
2759         int domain_master = lpcfg__domain_master(lp_ctx);
2760
2761         return lp_find_server_role(lpcfg__server_role(lp_ctx),
2762                                    lpcfg__security(lp_ctx),
2763                                    lpcfg__domain_logons(lp_ctx),
2764                                    (domain_master == true) ||
2765                                    (domain_master == Auto));
2766 }
2767
2768 int lpcfg_security(struct loadparm_context *lp_ctx)
2769 {
2770         return lp_find_security(lpcfg__server_role(lp_ctx),
2771                                 lpcfg__security(lp_ctx));
2772 }
2773
2774 bool lpcfg_server_signing_allowed(struct loadparm_context *lp_ctx, bool *mandatory)
2775 {
2776         bool allowed = true;
2777         enum smb_signing_setting signing_setting = lpcfg_server_signing(lp_ctx);
2778
2779         *mandatory = false;
2780
2781         if (signing_setting == SMB_SIGNING_DEFAULT) {
2782                 /*
2783                  * If we are a domain controller, SMB signing is
2784                  * really important, as it can prevent a number of
2785                  * attacks on communications between us and the
2786                  * clients
2787                  *
2788                  * However, it really sucks (no sendfile, CPU
2789                  * overhead) performance-wise when used on a
2790                  * file server, so disable it by default
2791                  * on non-DCs
2792                  */
2793
2794                 if (lpcfg_server_role(lp_ctx) >= ROLE_ACTIVE_DIRECTORY_DC) {
2795                         signing_setting = SMB_SIGNING_REQUIRED;
2796                 } else {
2797                         signing_setting = SMB_SIGNING_OFF;
2798                 }
2799         }
2800
2801         switch (signing_setting) {
2802         case SMB_SIGNING_REQUIRED:
2803                 *mandatory = true;
2804                 break;
2805         case SMB_SIGNING_IF_REQUIRED:
2806                 break;
2807         case SMB_SIGNING_DEFAULT:
2808         case SMB_SIGNING_OFF:
2809                 allowed = false;
2810                 break;
2811         }
2812
2813         return allowed;
2814 }
2815
2816 int lpcfg_tdb_hash_size(struct loadparm_context *lp_ctx, const char *name)
2817 {
2818         const char *base;
2819
2820         if (name == NULL) {
2821                 return 0;
2822         }
2823
2824         base = strrchr_m(name, '/');
2825         if (base != NULL) {
2826                 base += 1;
2827         } else {
2828                 base = name;
2829         }
2830         return lpcfg_parm_int(lp_ctx, NULL, "tdb_hashsize", base, 0);
2831
2832 }
2833
2834 int lpcfg_tdb_flags(struct loadparm_context *lp_ctx, int tdb_flags)
2835 {
2836         if (!lpcfg_use_mmap(lp_ctx)) {
2837                 tdb_flags |= TDB_NOMMAP;
2838         }
2839         return tdb_flags;
2840 }