#include "eacces-error.h"
#include "env-util.h"
#include "execv-const.h"
+#include "var-expand.h"
#include "settings-parser.h"
#include "stats-client.h"
#include "master-service-private.h"
return &mpool->pool;
}
+static void
+master_service_var_expand_init(struct event *event,
+ const struct var_expand_table **tab_r,
+ const struct var_expand_func_table **func_tab_r,
+ void **func_context_r)
+{
+ *tab_r = NULL;
+ *func_tab_r = NULL;
+
+ while (event != NULL) {
+ master_service_settings_var_expand_t *callback =
+ event_get_ptr(event, MASTER_SERVICE_VAR_EXPAND_CALLBACK);
+ if (callback != NULL) {
+ callback(event, tab_r, func_tab_r);
+ break;
+ }
+
+ *tab_r = event_get_ptr(event, MASTER_SERVICE_VAR_EXPAND_TABLE);
+ *func_tab_r = event_get_ptr(event, MASTER_SERVICE_VAR_EXPAND_FUNC_TABLE);
+ if (*tab_r != NULL || *func_tab_r != NULL)
+ break;
+ event = event_get_parent(event);
+ }
+ if (*tab_r == NULL)
+ *tab_r = t_new(struct var_expand_table, 1);
+ *func_context_r = event == NULL ? NULL :
+ event_get_ptr(event, MASTER_SERVICE_VAR_EXPAND_FUNC_CONTEXT);
+}
+
+#undef master_service_settings_parser_get
+int master_service_settings_parser_get(struct event *event,
+ struct setting_parser_context *set_parser,
+ const struct setting_parser_info *info,
+ enum master_service_settings_get_flags flags,
+ const void **set_r, const char **error_r)
+{
+ int ret;
+
+ i_assert(info->pool_offset1 != 0);
+
+ pool_t set_pool = pool_alloconly_create("master service settings parser", 1024);
+ void *set = settings_parser_get_root_set(set_parser, info);
+ set = settings_dup_with_pointers(info, set, set_pool);
+
+ pool_t *pool_p = PTR_OFFSET(set, info->pool_offset1 - 1);
+ *pool_p = set_pool;
+ pool_ref(*pool_p);
+
+ if ((flags & MASTER_SERVICE_SETTINGS_GET_FLAG_NO_CHECK) == 0) {
+ if (!settings_check(info, *pool_p, set, error_r)) {
+ *error_r = t_strdup_printf("Invalid %s settings: %s",
+ info->module_name, *error_r);
+ return -1;
+ }
+ }
+
+ if ((flags & MASTER_SERVICE_SETTINGS_GET_FLAG_NO_EXPAND) != 0)
+ ret = 1;
+ else T_BEGIN {
+ const struct var_expand_table *tab;
+ const struct var_expand_func_table *func_tab;
+ void *func_context;
+
+ master_service_var_expand_init(event, &tab, &func_tab,
+ &func_context);
+ ret = settings_var_expand_with_funcs(info, set, *pool_p, tab,
+ func_tab, func_context,
+ error_r);
+ } T_END_PASS_STR_IF(ret <= 0, error_r);
+ if (ret <= 0) {
+ *error_r = t_strdup_printf(
+ "Failed to expand %s setting variables: %s",
+ info->module_name, *error_r);
+ return -1;
+ }
+
+ *set_r = set;
+ return 0;
+}
+
+#undef master_service_settings_get
+int master_service_settings_get(struct event *event,
+ const struct setting_parser_info *info,
+ enum master_service_settings_get_flags flags,
+ const void **set_r, const char **error_r)
+{
+ return master_service_settings_parser_get(event,
+ master_service->set_parser, info, flags, set_r, error_r);
+}
+
+const void *
+master_service_settings_get_or_fatal(struct event *event,
+ const struct setting_parser_info *info)
+{
+ const void *set;
+ const char *error;
+
+ if (master_service_settings_get(event, info, 0, &set, &error) < 0)
+ i_fatal("%s", error);
+ return set;
+}
+
void *master_service_settings_get_root_set(struct master_service *service,
const struct setting_parser_info *root)
{
#include "net.h"
+struct var_expand_table;
+struct var_expand_func_table;
struct setting_parser_info;
struct setting_parser_context;
struct master_service;
struct master_settings_mmap;
+enum master_service_settings_get_flags {
+ /* Don't call check_func()s */
+ MASTER_SERVICE_SETTINGS_GET_FLAG_NO_CHECK = BIT(0),
+ /* Don't expand %variables in settings */
+ MASTER_SERVICE_SETTINGS_GET_FLAG_NO_EXPAND = BIT(1),
+};
+
struct master_service_settings {
const char *base_dir;
const char *state_dir;
bool permission_denied:1;
};
+/* Set struct var_expand_table to be used for settings expansion. The table is
+ expected to be accessible until the event is freed or the table is cleared
+ from the event. Usage:
+
+ event_set_ptr(event, MASTER_SERVICE_VAR_EXPAND_TABLE, var_expand_table);
+*/
+#define MASTER_SERVICE_VAR_EXPAND_TABLE \
+ "master_service_var_expand_table"
+/* Set struct var_expand_func_table and its function context pointer to be used
+ for settings expansion. The table is expected to be accessible until the
+ event is freed or the table is cleared from the event. Usage:
+
+ event_set_ptr(event, MASTER_SERVICE_VAR_EXPAND_FUNC_TABLE, func_table);
+ event_set_ptr(event, MASTER_SERVICE_VAR_EXPAND_FUNC_CONTEXT, func_context);
+
+ You can set either or both of MASTER_SERVICE_VAR_EXPAND_TABLE and
+ MASTER_SERVICE_VAR_EXPAND_FUNC_TABLE for the same event. The parent events
+ won't be searched for either of them if either one is set.
+*/
+#define MASTER_SERVICE_VAR_EXPAND_FUNC_TABLE \
+ "master_service_var_expand_func_table"
+#define MASTER_SERVICE_VAR_EXPAND_FUNC_CONTEXT \
+ "master_service_var_expand_func_context"
+
+/* Set a master_service_settings_var_expand_t callback that returns
+ var_expand_[func_]table for settings expansion. This can be used instead of
+ MASTER_SERVICE_VAR_EXPAND_[FUNC_]TABLE to dynamically generate the table
+ on-demand. If this is found from the event, all other MASTER_SERVICE_VAR_*
+ fields are ignored in this and the parent events. Usage:
+
+ event_set_ptr(event, MASTER_SERVICE_VAR_EXPAND_CALLBACK, callback);
+ event_set_ptr(event, MASTER_SERVICE_VAR_EXPAND_FUNC_CONTEXT, func_context);
+*/
+#define MASTER_SERVICE_VAR_EXPAND_CALLBACK \
+ "master_service_var_expand_callback"
+/* Callback function used with MASTER_SERVICE_VAR_EXPAND_CALLBACK. The function
+ can return either or both of tab_r and func_tab_r, using NULL for the field
+ that isn't needed. */
+typedef void
+master_service_settings_var_expand_t(struct event *event,
+ const struct var_expand_table **tab_r,
+ const struct var_expand_func_table **func_tab_r);
+
extern const struct setting_parser_info master_service_setting_parser_info;
void master_settings_mmap_ref(struct master_settings_mmap *mmap);
const struct master_service_settings *
master_service_get_service_settings(struct master_service *service);
+
+/* Get the wanted settings and check that the settings are valid.
+ The settings struct must have pool_t (info->pool_offset1), which the caller
+ must unreference when done with the settings. master_service_settings_free()
+ macro can be used to do the freeing in a nice way.
+
+ Settings have their %variables expanded, unless
+ MASTER_SERVICE_SETTINGS_GET_FLAG_NO_EXPAND is used. The event and its
+ parents are scanned for MASTER_SERVICE_VAR_EXPAND_* pointers. The first
+ callback or tables that are found in the event hierarchy are used for the
+ expansion. See MASTER_SERVICE_VAR_EXPAND_* macros for more details. */
+int master_service_settings_get(struct event *event,
+ const struct setting_parser_info *info,
+ enum master_service_settings_get_flags flags,
+ const void **set_r, const char **error_r);
+#ifdef HAVE_TYPE_CHECKS
+# define master_service_settings_get(event, info, flags, set_r, error_r) \
+ master_service_settings_get(event, info, flags, (void *)set_r, 1 ? (error_r) : \
+ COMPILE_ERROR_IF_TRUE( \
+ !__builtin_types_compatible_p(typeof((*set_r)->pool), pool_t)))
+#else
+# define master_service_settings_get(event, info, flags, set_r, error_r) \
+ master_service_settings_get(event, info, flags, (void *)set_r, error_r)
+#endif
+
+/* Like master_service_settings_get(), but get settings from the specified
+ parser. */
+int master_service_settings_parser_get(struct event *event,
+ struct setting_parser_context *set_parser,
+ const struct setting_parser_info *info,
+ enum master_service_settings_get_flags flags,
+ const void **set_r, const char **error_r);
+#ifdef HAVE_TYPE_CHECKS
+# define master_service_settings_parser_get(event, set_parser, \
+ info, flags, set_r, error_r) \
+ master_service_settings_parser_get(event, set_parser, \
+ info, flags, (void *)set_r, 1 ? (error_r) : \
+ COMPILE_ERROR_IF_TRUE( \
+ !__builtin_types_compatible_p(typeof((*set_r)->pool), pool_t)))
+#else
+# define master_service_settings_parser_get(event, set_parser, \
+ info, flags, set_r, error_r) \
+ master_service_settings_parser_get(event, set_parser, \
+ info, flags, (void *)set_r, error_r)
+#endif
+
+/* Like master_service_settings_get(), but i_fatal() if there are any errors
+ in settings. */
+const void *
+master_service_settings_get_or_fatal(struct event *event,
+ const struct setting_parser_info *info);
+#define master_service_settings_free(set) \
+ STMT_START { \
+ if ((set) != NULL) { \
+ pool_t pool_copy = set->pool; \
+ pool_unref(&pool_copy); \
+ (set) = NULL; \
+ } \
+ } STMT_END
void *master_service_settings_get_root_set(struct master_service *service,
const struct setting_parser_info *root);
void *master_service_settings_get_root_set_dup(struct master_service *service,