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