DEF(SET_STR, mail_plugins),
DEF(SET_STR, mail_plugin_dir),
- DEF(SET_STR_VARS, mail_log_prefix),
DEF(SET_STR, postmaster_address),
DEF(SET_STR, hostname),
MEMBER(mail_plugins) "",
MEMBER(mail_plugin_dir) MODULEDIR"/lda",
- MEMBER(mail_log_prefix) "%Us(%u): ",
MEMBER(postmaster_address) "",
MEMBER(hostname) "",
const char *mail_plugins;
const char *mail_plugin_dir;
- const char *mail_log_prefix;
/* deliver: */
const char *postmaster_address;
DEF(SET_STR, mail_plugins),
DEF(SET_STR, mail_plugin_dir),
- DEF(SET_STR_VARS, mail_log_prefix),
DEF(SET_UINT, imap_max_line_length),
DEF(SET_STR, imap_capability),
MEMBER(mail_plugins) "",
MEMBER(mail_plugin_dir) MODULEDIR"/imap",
- MEMBER(mail_log_prefix) "%Us(%u): ",
/* RFC-2683 recommends at least 8000 bytes. Some clients however don't
break large message sets to multiple commands, so we're pretty
&mail_user_setting_parser_info
};
struct setting_parser_context *parser;
+ const char *const *expanded;
void **sets;
if (settings_pool == NULL)
roots, N_ELEMENTS(roots),
SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS);
- settings_parse_set_expanded(parser, TRUE);
if (settings_parse_environ(parser) < 0) {
i_fatal("Error reading configuration: %s",
settings_parser_get_error(parser));
}
+ expanded = t_strsplit(getenv("VARS_EXPANDED"), " ");
+ settings_parse_set_keys_expandeded(parser, settings_pool, expanded);
+
sets = settings_parser_get_list(parser);
*set_r = sets[0];
*user_set_r = sets[1];
const char *mail_plugins;
const char *mail_plugin_dir;
- const char *mail_log_prefix;
/* imap: */
unsigned int imap_max_line_length;
return -1;
}
-static int settings_parse_keyvalue(struct setting_parser_context *ctx,
- const char *key, const char *value)
+static bool
+settings_find_key(struct setting_parser_context *ctx, const char *key,
+ const struct setting_define **def_r,
+ struct setting_link **link_r)
{
- const struct setting_define *def = NULL;
+ const struct setting_define *def;
+ struct setting_link *link;
+ const char *end;
unsigned int i;
- int ret = 1;
/* try to find from roots */
for (i = 0; i < ctx->root_count; i++) {
def = setting_define_find(ctx->roots[i].info, key);
- if (def != NULL)
- break;
+ if (def != NULL) {
+ *def_r = def;
+ *link_r = &ctx->roots[i];
+ return TRUE;
+ }
}
- if (def != NULL) {
- if (settings_parse(ctx, &ctx->roots[i], def, key, value) < 0)
- ret = -1;
+
+ /* try to find from links */
+ end = strrchr(key, SETTINGS_SEPARATOR);
+ if (end == NULL)
+ return FALSE;
+
+ link = hash_table_lookup(ctx->links, t_strdup_until(key, end));
+ if (link == NULL)
+ return FALSE;
+
+ *link_r = link;
+ if (link->info == &strlist_info) {
+ *def_r = NULL;
+ return TRUE;
} else {
- /* try to find from links */
- const char *end = strrchr(key, SETTINGS_SEPARATOR);
- struct setting_link *link;
-
- link = end == NULL ? NULL :
- hash_table_lookup(ctx->links, t_strdup_until(key, end));
- if (link == NULL)
- def = NULL;
- else if (link->info == &strlist_info) {
+ *def_r = setting_define_find(link->info, end + 1);
+ return *def_r != NULL;
+ }
+}
+
+static int settings_parse_keyvalue(struct setting_parser_context *ctx,
+ const char *key, const char *value)
+{
+ const struct setting_define *def;
+ struct setting_link *link;
+
+ if (settings_find_key(ctx, key, &def, &link)) {
+ if (link->info == &strlist_info) {
void *vkey, *vvalue;
- vkey = p_strdup(ctx->set_pool, end + 1);
+ vkey = p_strdup(ctx->set_pool,
+ strrchr(key, SETTINGS_SEPARATOR) + 1);
vvalue = p_strdup(ctx->set_pool, value);
array_append(link->array, &vkey, 1);
array_append(link->array, &vvalue, 1);
return 1;
- } else {
- def = setting_define_find(link->info, end + 1);
- }
- if (def != NULL) {
- if (settings_parse(ctx, link, def, key, value) < 0)
- ret = -1;
- } else {
- ctx->error = p_strconcat(ctx->parser_pool,
- "Unknown setting: ", key, NULL);
- ret = 0;
}
+
+ if (settings_parse(ctx, link, def, key, value) < 0)
+ return -1;
+ return 1;
+ } else {
+ ctx->error = p_strconcat(ctx->parser_pool,
+ "Unknown setting: ", key, NULL);
+ return 0;
}
- return ret;
}
int settings_parse_line(struct setting_parser_context *ctx, const char *line)
}
}
+void settings_parse_set_keys_expandeded(struct setting_parser_context *ctx,
+ pool_t pool, const char *const *keys)
+{
+ const struct setting_define *def;
+ struct setting_link *link;
+ const char **val;
+
+ for (; *keys != NULL; keys++) {
+ if (!settings_find_key(ctx, *keys, &def, &link))
+ continue;
+
+ val = PTR_OFFSET(link->set_struct, def->offset);
+ if (def->type == SET_STR_VARS && *val != NULL) {
+ i_assert(**val == SETTING_STRVAR_UNEXPANDED[0] ||
+ **val == SETTING_STRVAR_EXPANDED[0]);
+ *val = p_strconcat(pool, SETTING_STRVAR_EXPANDED,
+ *val + 1, NULL);
+ }
+ }
+}
+
void settings_var_expand(const struct setting_parser_info *info,
void *set, pool_t pool,
const struct var_expand_table *table)
/* While parsing values, specifies if STR_VARS strings are already expanded. */
void settings_parse_set_expanded(struct setting_parser_context *ctx,
bool is_expanded);
+/* Mark all the parsed settings with given keys as being already expanded. */
+void settings_parse_set_keys_expandeded(struct setting_parser_context *ctx,
+ pool_t pool, const char *const *keys);
/* Expand all unexpanded variables using the given table. Update the string
pointers so that they can be used without skipping over the '1'. */
void settings_var_expand(const struct setting_parser_info *info,
static void
mail_process_set_environment(struct master_settings *set,
- const struct var_expand_table *table)
+ const struct var_expand_table *table,
+ string_t *expanded_vars)
{
const char **envs;
string_t *str;
unsigned int i, count;
- settings_var_expand(&master_setting_parser_info, set,
- system_pool, table);
+ str_append(expanded_vars, "VARS_EXPANDED=");
+
+ /* we don't know all the settings, so since we can't expand all of
+ them just let the mail process expand all of them internally.
+ except for plugin settings - we know all of them so expand them. */
+ master_settings_export_to_env(set);
(void)umask(set->umask);
}
str_truncate(str, 0);
var_expand(str, envs[i+1], table);
- envs[i+1] = t_strdup(str_c(str));
- }
+ env_put(t_strconcat(t_str_ucase(envs[i]), "=", str_c(str), NULL));
- master_settings_export_to_env(set);
+ str_append(expanded_vars, envs[i]);
+ str_append_c(expanded_vars, ' ');
+ }
}
void mail_process_exec(const char *protocol, const char **args)
const struct var_expand_table *var_expand_table;
struct master_settings *set;
const char *executable;
+ string_t *expanded_vars;
if (strcmp(protocol, "ext") == 0) {
/* external binary. section contains path for it. */
env_put(str_c(str));
}
- mail_process_set_environment(set, var_expand_table);
+ expanded_vars = t_str_new(128);
+ mail_process_set_environment(set, var_expand_table, expanded_vars);
+ env_put(str_c(expanded_vars));
+
if (args == NULL)
client_process_exec(executable, "");
else
{
const struct var_expand_table *var_expand_table;
const char *p, *addr, *mail, *chroot_dir, *home_dir, *full_home_dir;
- const char *system_user, *master_user;
+ const char *system_user, *master_user, *key;
struct mail_process_group *process_group;
char title[1024];
struct log_io *log;
- string_t *str;
+ string_t *str, *expanded_vars;
pid_t pid;
uid_t uid;
gid_t gid;
i_fatal("chdir(/tmp) failed: %m");
}
- mail_process_set_environment(set, var_expand_table);
+ expanded_vars = t_str_new(128);
+ mail_process_set_environment(set, var_expand_table, expanded_vars);
/* extra args. uppercase key value. */
args = array_get(&extra_args, &count);
p = strchr(args[i], '=');
if (p == NULL) {
/* boolean */
- env_put(t_strconcat(t_str_ucase(args[i]), "=1", NULL));
+ key = args[i];
+ env_put(t_strconcat(t_str_ucase(key), "=1", NULL));
} else {
/* key=value */
- env_put(t_strconcat(t_str_ucase(
- t_strdup_until(args[i], p)), p, NULL));
+ key = t_strdup_until(args[i], p);
+ env_put(t_strconcat(t_str_ucase(key), p, NULL));
}
+ str_append(expanded_vars, key);
+ str_append_c(expanded_vars, ' ');
}
+ env_put(str_c(expanded_vars));
if (nfs_check) {
/* ideally we should check all of the namespaces,
DEF(SET_STR, mail_executable),
DEF(SET_UINT, mail_process_size),
- DEF(SET_STR_VARS, mail_log_prefix),
+ DEF(SET_STR, mail_log_prefix),
DEF(SET_UINT, mail_log_max_lines_per_sec),
/* dict */
unsigned int i, count;
sets = array_get(&set->all_settings, &count);
- for (i = 0; i < count; i++)
- env_put(sets[i]);
+ for (i = 0; i < count; i++) {
+ if (strncmp(sets[i], "plugin/", 7) != 0)
+ env_put(sets[i]);
+ }
}
void master_settings_init(void)
DEF(SET_STR, mail_plugins),
DEF(SET_STR, mail_plugin_dir),
- DEF(SET_STR_VARS, mail_log_prefix),
DEF(SET_BOOL, pop3_no_flag_updates),
DEF(SET_BOOL, pop3_enable_last),
MEMBER(mail_plugins) "",
MEMBER(mail_plugin_dir) MODULEDIR"/pop3",
- MEMBER(mail_log_prefix) "%Us(%u): ",
MEMBER(pop3_no_flag_updates) FALSE,
MEMBER(pop3_enable_last) FALSE,
&mail_user_setting_parser_info
};
struct setting_parser_context *parser;
+ const char *const *expanded;
void **sets;
if (settings_pool == NULL)
roots, N_ELEMENTS(roots),
SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS);
- settings_parse_set_expanded(parser, TRUE);
if (settings_parse_environ(parser) < 0) {
i_fatal("Error reading configuration: %s",
settings_parser_get_error(parser));
}
+ expanded = t_strsplit(getenv("VARS_EXPANDED"), " ");
+ settings_parse_set_keys_expandeded(parser, settings_pool, expanded);
+
sets = settings_parser_get_list(parser);
*set_r = sets[0];
*user_set_r = sets[1];
const char *mail_plugins;
const char *mail_plugin_dir;
- const char *mail_log_prefix;
/* pop3: */
bool pop3_no_flag_updates;