#include "lib/param/param_global.h"
-#define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
-
-/* we don't need a special handler for "dos charset" and "unix charset" */
-#define handle_dos_charset NULL
-#define handle_charset NULL
-
-/* these are parameter handlers which are not needed in the
- * non-source3 code
- */
-#define handle_netbios_aliases NULL
-#define handle_printing NULL
-#define handle_ldap_debug_level NULL
-#define handle_idmap_backend NULL
-#define handle_idmap_uid NULL
-#define handle_idmap_gid NULL
-
-#ifndef N_
-#define N_(x) x
-#endif
-
-/* prototypes for the special type handlers */
-static bool handle_include(struct loadparm_context *lp_ctx, int unused,
- const char *pszParmValue, char **ptr);
-static bool handle_copy(struct loadparm_context *lp_ctx, int unused,
- const char *pszParmValue, char **ptr);
-
-#include "lib/param/param_table.c"
-
-/* local variables */
-struct loadparm_context {
- const char *szConfigFile;
- struct loadparm_global *globals;
- struct loadparm_service **services;
- struct loadparm_service *sDefault;
- struct smb_iconv_handle *iconv_handle;
- int iNumServices;
- struct loadparm_service *currentService;
- bool bInGlobalSection;
- struct file_lists {
- struct file_lists *next;
- char *name;
- char *subfname;
- time_t modtime;
- } *file_lists;
- unsigned int flags[NUMPARAMETERS];
- bool loaded;
- bool refuse_free;
- bool global; /* Is this the global context, which may set
- * global variables such as debug level etc? */
- const struct loadparm_s3_helpers *s3_fns;
-};
-
+#define NUMPARAMETERS (num_parameters())
struct loadparm_service *lpcfg_default_service(struct loadparm_context *lp_ctx)
{
FN_GLOBAL_CONST_STRING(dnsdomain, dnsdomain)
/* local prototypes */
-static struct loadparm_service *getservicebyname(struct loadparm_context *lp_ctx,
+static struct loadparm_service *lpcfg_getservicebyname(struct loadparm_context *lp_ctx,
const char *pszServiceName);
-static void copy_service(struct loadparm_service *pserviceDest,
- const struct loadparm_service *pserviceSource,
- struct bitmap *pcopymapDest);
static bool lpcfg_service_ok(struct loadparm_service *service);
static bool do_section(const char *pszSectionName, void *);
-static void init_copymap(struct loadparm_service *pservice);
/* This is a helper function for parametrical options support. */
/* It returns a pointer to parametrical option value if it exists or NULL otherwise */
return NULL;
if (lp_ctx->s3_fns) {
- return lp_ctx->s3_fns->get_parametric(service, type, option);
+ return lp_ctx->s3_fns->get_parametric(service, type, option, NULL);
}
data = (service == NULL ? lp_ctx->globals->param_opt : service->param_opt);
/**
* convenience routine to return int parameters.
*/
-static int lp_int(const char *s)
+int lp_int(const char *s)
{
- if (!s) {
+ if (!s || !*s) {
DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
return -1;
}
/**
* convenience routine to return unsigned long parameters.
*/
-static unsigned long lp_ulong(const char *s)
+unsigned long lp_ulong(const char *s)
{
- if (!s) {
+ if (!s || !*s) {
DEBUG(0,("lp_ulong(%s): is called with NULL!\n",s));
return -1;
}
/**
* convenience routine to return boolean parameters.
*/
-static bool lp_bool(const char *s)
+bool lp_bool(const char *s)
{
bool ret = false;
- if (!s) {
+ if (!s || !*s) {
DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
return false;
}
return ret;
}
-
/**
* Return parametric option from a given service. Type is a part of option before ':'
* Parametric option has following syntax: 'Type: option = value'
* Set a string value, deallocating any existing space, and allocing the space
* for the string
*/
-bool lpcfg_string_set_upper(TALLOC_CTX *mem_ctx, char **dest, const char *src)
+static bool lpcfg_string_set_upper(TALLOC_CTX *mem_ctx, char **dest, const char *src)
{
talloc_free(*dest);
/* it might already exist */
if (name) {
- struct loadparm_service *service = getservicebyname(lp_ctx,
+ struct loadparm_service *service = lpcfg_getservicebyname(lp_ctx,
name);
if (service != NULL) {
/* Clean all parametric options for service */
* Find a service by name. Otherwise works like get_service.
*/
-static struct loadparm_service *getservicebyname(struct loadparm_context *lp_ctx,
+static struct loadparm_service *lpcfg_getservicebyname(struct loadparm_context *lp_ctx,
const char *pszServiceName)
{
int iService;
* If pcopymapDest is NULL then copy all fields
*/
-static void copy_service(struct loadparm_service *pserviceDest,
- const struct loadparm_service *pserviceSource,
- struct bitmap *pcopymapDest)
+void copy_service(struct loadparm_service *pserviceDest,
+ const struct loadparm_service *pserviceSource,
+ struct bitmap *pcopymapDest)
{
int i;
bool bcopyall = (pcopymapDest == NULL);
(char **)dest_ptr,
*(const char * const *)src_ptr);
break;
+ case P_CMDLIST:
case P_LIST:
TALLOC_FREE(*((char ***)dest_ptr));
*(const char * const **)dest_ptr = (const char * const *)str_list_copy(pserviceDest,
it's date and needs to be reloaded.
********************************************************************/
-static void add_to_file_list(struct loadparm_context *lp_ctx,
+void add_to_file_list(TALLOC_CTX *mem_ctx, struct file_lists **list,
const char *fname, const char *subfname)
{
- struct file_lists *f = lp_ctx->file_lists;
+ struct file_lists *f = *list;
while (f) {
if (f->name && !strcmp(f->name, fname))
}
if (!f) {
- f = talloc(lp_ctx, struct file_lists);
+ f = talloc(mem_ctx, struct file_lists);
if (!f)
- return;
- f->next = lp_ctx->file_lists;
+ goto fail;
+ f->next = *list;
f->name = talloc_strdup(f, fname);
if (!f->name) {
- talloc_free(f);
- return;
+ TALLOC_FREE(f);
+ goto fail;
}
f->subfname = talloc_strdup(f, subfname);
if (!f->subfname) {
- talloc_free(f);
- return;
+ TALLOC_FREE(f);
+ goto fail;
}
- lp_ctx->file_lists = f;
+ *list = f;
f->modtime = file_modtime(subfname);
} else {
time_t t = file_modtime(subfname);
if (t)
f->modtime = t;
}
+ return;
+
+fail:
+ DEBUG(0, ("Unable to add file to file list: %s\n", fname));
+
}
/*******************************************************************
return false;
}
+/*
+ * set the value for a P_ENUM
+ */
+bool lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
+ int *ptr )
+{
+ int i;
+
+ for (i = 0; parm->enum_list[i].name; i++) {
+ if ( strequal(pszParmValue, parm->enum_list[i].name)) {
+ *ptr = parm->enum_list[i].value;
+ return true;
+ }
+ }
+ DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
+ pszParmValue, parm->label));
+ return false;
+}
+
+
/***************************************************************************
Handle the "realm" parameter
***************************************************************************/
Handle the include operation.
***************************************************************************/
-static bool handle_include(struct loadparm_context *lp_ctx, int unused,
+bool handle_include(struct loadparm_context *lp_ctx, int unused,
const char *pszParmValue, char **ptr)
{
- char *fname = standard_sub_basic(lp_ctx, pszParmValue);
+ char *fname;
+
+ if (lp_ctx->s3_fns) {
+ return lp_ctx->s3_fns->lp_include(lp_ctx, unused, pszParmValue, ptr);
+ }
- add_to_file_list(lp_ctx, pszParmValue, fname);
+ fname = standard_sub_basic(lp_ctx, pszParmValue);
+
+ add_to_file_list(lp_ctx, &lp_ctx->file_lists, pszParmValue, fname);
lpcfg_string_set(lp_ctx, ptr, fname);
Handle the interpretation of the copy parameter.
***************************************************************************/
-static bool handle_copy(struct loadparm_context *lp_ctx, int unused,
+bool handle_copy(struct loadparm_context *lp_ctx, int snum,
const char *pszParmValue, char **ptr)
{
bool bRetval;
- struct loadparm_service *serviceTemp;
-
- lpcfg_string_set(lp_ctx, ptr, pszParmValue);
+ struct loadparm_service *serviceTemp = NULL;
+ struct loadparm_service *current = NULL;
bRetval = false;
DEBUG(3, ("Copying service from service %s\n", pszParmValue));
- if ((serviceTemp = getservicebyname(lp_ctx, pszParmValue)) != NULL) {
- if (serviceTemp == lp_ctx->currentService) {
+ serviceTemp = lpcfg_getservicebyname(lp_ctx, pszParmValue);
+ if (lp_ctx->s3_fns != NULL) {
+ current = lp_ctx->s3_fns->get_servicebynum(snum);
+ } else {
+ current = lp_ctx->currentService;
+ }
+
+ if (current == NULL) {
+ DEBUG(0, ("Unable to copy service - invalid service destination"));
+ return false;
+ }
+
+ if (serviceTemp != NULL) {
+ if (serviceTemp == current) {
DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
} else {
- copy_service(lp_ctx->currentService,
+ copy_service(current,
serviceTemp,
- lp_ctx->currentService->copymap);
+ current->copymap);
+ lpcfg_string_set(current, ptr, pszParmValue);
+
bRetval = true;
}
} else {
return true;
}
+/*
+ * These special charset handling methods only run in the source3 code.
+ */
+
+bool handle_charset(struct loadparm_context *lp_ctx, int snum,
+ const char *pszParmValue, char **ptr)
+{
+ if (lp_ctx->s3_fns) {
+ if (*ptr == NULL || strcmp(*ptr, pszParmValue) != 0) {
+ lp_ctx->s3_fns->lp_string_set(ptr, pszParmValue);
+ global_iconv_handle = smb_iconv_handle_reinit(NULL,
+ lpcfg_dos_charset(lp_ctx),
+ lpcfg_unix_charset(lp_ctx),
+ true, global_iconv_handle);
+ }
+
+ return true;
+ }
+ return lpcfg_string_set(lp_ctx, ptr, pszParmValue);
+
+}
+
+bool handle_dos_charset(struct loadparm_context *lp_ctx, int snum,
+ const char *pszParmValue, char **ptr)
+{
+ bool is_utf8 = false;
+ size_t len = strlen(pszParmValue);
+
+ if (lp_ctx->s3_fns) {
+ if (len == 4 || len == 5) {
+ /* Don't use StrCaseCmp here as we don't want to
+ initialize iconv. */
+ if ((toupper_m(pszParmValue[0]) == 'U') &&
+ (toupper_m(pszParmValue[1]) == 'T') &&
+ (toupper_m(pszParmValue[2]) == 'F')) {
+ if (len == 4) {
+ if (pszParmValue[3] == '8') {
+ is_utf8 = true;
+ }
+ } else {
+ if (pszParmValue[3] == '-' &&
+ pszParmValue[4] == '8') {
+ is_utf8 = true;
+ }
+ }
+ }
+ }
+
+ if (*ptr == NULL || strcmp(*ptr, pszParmValue) != 0) {
+ if (is_utf8) {
+ DEBUG(0,("ERROR: invalid DOS charset: 'dos charset' must not "
+ "be UTF8, using (default value) %s instead.\n",
+ DEFAULT_DOS_CHARSET));
+ pszParmValue = DEFAULT_DOS_CHARSET;
+ }
+ lp_ctx->s3_fns->lp_string_set(ptr, pszParmValue);
+ global_iconv_handle = smb_iconv_handle_reinit(NULL,
+ lpcfg_dos_charset(lp_ctx),
+ lpcfg_unix_charset(lp_ctx),
+ true, global_iconv_handle);
+ }
+ return true;
+ }
+
+ return lpcfg_string_set(lp_ctx, ptr, pszParmValue);
+}
+
+bool handle_printing(struct loadparm_context *lp_ctx, int snum,
+ const char *pszParmValue, char **ptr)
+{
+ static int parm_num = -1;
+ struct loadparm_service *s;
+
+ if (parm_num == -1) {
+ parm_num = lpcfg_map_parameter("printing");
+ }
+
+ if (!lp_set_enum_parm(&parm_table[parm_num], pszParmValue, (int*)ptr)) {
+ return false;
+ }
+
+ if (lp_ctx->s3_fns) {
+ if ( snum < 0 ) {
+ s = lp_ctx->sDefault;
+ lp_ctx->s3_fns->init_printer_values(lp_ctx->globals->ctx, s);
+ } else {
+ s = lp_ctx->services[snum];
+ lp_ctx->s3_fns->init_printer_values(s, s);
+ }
+ }
+
+ return true;
+}
+
+bool handle_ldap_debug_level(struct loadparm_context *lp_ctx, int snum, const char *pszParmValue, char **ptr)
+{
+ lp_ctx->globals->ldap_debug_level = lp_int(pszParmValue);
+
+ if (lp_ctx->s3_fns) {
+ lp_ctx->s3_fns->init_ldap_debugging();
+ }
+ return true;
+}
+
+bool handle_netbios_aliases(struct loadparm_context *lp_ctx, int snum, const char *pszParmValue, char **ptr)
+{
+ TALLOC_FREE(lp_ctx->globals->netbios_aliases);
+ lp_ctx->globals->netbios_aliases = (const char **)str_list_make_v3(lp_ctx->globals->ctx,
+ pszParmValue, NULL);
+
+ if (lp_ctx->s3_fns) {
+ return lp_ctx->s3_fns->set_netbios_aliases(lp_ctx->globals->netbios_aliases);
+ }
+ return true;
+}
+
+/*
+ * idmap related parameters
+ */
+
+bool handle_idmap_backend(struct loadparm_context *lp_ctx, int snum, const char *pszParmValue, char **ptr)
+{
+ if (lp_ctx->s3_fns) {
+ return lp_ctx->s3_fns->lp_do_parameter(snum, "idmap config * : backend", pszParmValue);
+ }
+
+ return lpcfg_string_set(lp_ctx, ptr, pszParmValue);
+}
+
+bool handle_idmap_uid(struct loadparm_context *lp_ctx, int snum, const char *pszParmValue, char **ptr)
+{
+ if (lp_ctx->s3_fns) {
+ return lp_ctx->s3_fns->lp_do_parameter(snum, "idmap config * : range", pszParmValue);
+ }
+
+ return lpcfg_string_set(lp_ctx, ptr, pszParmValue);
+}
+
+bool handle_idmap_gid(struct loadparm_context *lp_ctx, int snum, const char *pszParmValue, char **ptr)
+{
+ if (lp_ctx->s3_fns) {
+ return lp_ctx->s3_fns->lp_do_parameter(snum, "idmap config * : range", pszParmValue);
+ }
+
+ return lpcfg_string_set(lp_ctx, ptr, pszParmValue);
+}
+
/***************************************************************************
Initialise a copymap.
***************************************************************************/
-static void init_copymap(struct loadparm_service *pservice)
+void init_copymap(struct loadparm_service *pservice)
{
int i;
const char *pszParmName,
const char *pszParmValue, int flags)
{
- struct parmlist_entry *paramo, *data;
+ struct parmlist_entry **data;
char *name;
TALLOC_CTX *mem_ctx;
if (!name) return false;
if (service == NULL) {
- data = lp_ctx->globals->param_opt;
+ data = &lp_ctx->globals->param_opt;
mem_ctx = lp_ctx->globals;
} else {
- data = service->param_opt;
+ data = &service->param_opt;
mem_ctx = service;
}
- /* Traverse destination */
- for (paramo=data; paramo; paramo=paramo->next) {
- /* If we already have the option set, override it unless
- it was a command line option and the new one isn't */
- if (strcmp(paramo->key, name) == 0) {
- if ((paramo->priority & FLAG_CMDLINE) &&
- !(flags & FLAG_CMDLINE)) {
- talloc_free(name);
- return true;
- }
-
- talloc_free(paramo->value);
- paramo->value = talloc_strdup(paramo, pszParmValue);
- paramo->priority = flags;
- talloc_free(name);
- return true;
- }
- }
-
- paramo = talloc_zero(mem_ctx, struct parmlist_entry);
- if (!paramo)
- smb_panic("OOM");
- paramo->key = talloc_strdup(paramo, name);
- paramo->value = talloc_strdup(paramo, pszParmValue);
- paramo->priority = flags;
- if (service == NULL) {
- DLIST_ADD(lp_ctx->globals->param_opt, paramo);
- } else {
- DLIST_ADD(service->param_opt, paramo);
- }
+ set_param_opt(mem_ctx, data, name, pszParmValue, flags);
talloc_free(name);
break;
case P_ENUM:
- for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
- if (strequal
- (pszParmValue,
- parm_table[parmnum].enum_list[i].name)) {
- *(int *)parm_ptr =
- parm_table[parmnum].
- enum_list[i].value;
- break;
- }
- }
- if (!parm_table[parmnum].enum_list[i].name) {
- DEBUG(0,("Unknown enumerated value '%s' for '%s'\n",
- pszParmValue, pszParmName));
+ if (!lp_set_enum_parm(&parm_table[parmnum], pszParmValue, (int*)parm_ptr)) {
return false;
}
break;
int parmnum;
int i;
+ while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
+
if (lp_ctx->s3_fns) {
return lp_ctx->s3_fns->set_cmdline(pszParmName, pszParmValue);
}
parmnum = lpcfg_map_parameter(pszParmName);
- while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
-
-
if (parmnum < 0 && strchr(pszParmName, ':')) {
/* set a parametric option */
return lp_do_parameter_parametric(lp_ctx, NULL, pszParmName,
talloc_set_destructor(lp_ctx, lpcfg_destructor);
lp_ctx->bInGlobalSection = true;
lp_ctx->globals = talloc_zero(lp_ctx, struct loadparm_global);
+ /* This appears odd, but globals in s3 isn't a pointer */
+ lp_ctx->globals->ctx = lp_ctx->globals;
lp_ctx->sDefault = talloc_zero(lp_ctx, struct loadparm_service);
+ lp_ctx->flags = talloc_zero_array(lp_ctx, unsigned int, NUMPARAMETERS);
lp_ctx->sDefault->iMaxPrintJobs = 1000;
lp_ctx->sDefault->bAvailable = true;
n2 = standard_sub_basic(lp_ctx, lp_ctx->szConfigFile);
DEBUG(2, ("lpcfg_load: refreshing parameters from %s\n", n2));
- add_to_file_list(lp_ctx, lp_ctx->szConfigFile, n2);
+ add_to_file_list(lp_ctx, &lp_ctx->file_lists, lp_ctx->szConfigFile, n2);
/* We get sections first, so have to start 'behind' to make up */
lp_ctx->currentService = NULL;