static inline config_t *config_new(void)
{
config_t *config = p_new(config_t, 1);
+ return config;
+}
+
+static void config_close(config_t *config)
+{
for (int i = 0 ; i < SMTP_count ; ++i) {
config->entry_points[i] = -1;
}
- return config;
+ array_deep_wipe(config->filters, filter_wipe);
+ array_deep_wipe(config->params, filter_params_wipe);
}
void config_delete(config_t **config)
{
if (*config) {
- array_deep_wipe((*config)->filters, filter_wipe);
- array_deep_wipe((*config)->params, filter_params_wipe);
+ config_close(*config);
p_delete(config);
}
}
return ok;
}
-config_t *config_read(const char *file)
+static bool config_load(config_t *config)
{
- config_t *config;
filter_t filter;
file_map_t map;
const char *p;
char value[BUFSIZ];
ssize_t key_len, value_len;
- if (!file_map_open(&map, file, false)) {
+ if (!file_map_open(&map, config->filename, false)) {
return false;
}
- config = config_new();
+ config_close(config);
filter_init(&filter);
linep = p = map.map;
#define READ_ERROR(Fmt, ...) \
do { \
- syslog(LOG_ERR, "config file %s:%d:%d: " Fmt, file, line + 1, \
- p - linep + 1, ##__VA_ARGS__); \
+ syslog(LOG_ERR, "config file %s:%d:%d: " Fmt, config->filename, \
+ line + 1, p - linep + 1, ##__VA_ARGS__); \
goto error; \
} while (0)
#define ADD_IN_BUFFER(Buffer, Len, Char) \
goto error;
}
file_map_close(&map);
- return config;
+ return true;
badeof:
syslog(LOG_ERR, "Unexpected end of file");
if (filter.name) {
filter_wipe(&filter);
}
- config_delete(&config);
file_map_close(&map);
- return NULL;
+ return false;
+}
+
+bool config_reload(config_t *config)
+{
+ return config_load(config);
+}
+
+config_t *config_read(const char *file)
+{
+ config_t *config = config_new();
+ config->filename = file;
+ if (!config_reload(config)) {
+ p_delete(&config);
+ return NULL;
+ }
+ return config;
}
typedef struct config_t config_t;
struct config_t {
- A(filter_t) filters;
+ /* SOURCE */
+ /* Root configuration file.
+ */
+ const char *filename;
+
+ /* Parameters.
+ */
A(filter_param_t) params;
+
+
+ /* INTERPRETED */
+ /* Filters.
+ */
+ A(filter_t) filters;
+
+ /* Entry point of the filters.
+ * (one per smtp state)
+ */
int entry_points[SMTP_count];
+
+ /* Port on which the program have to bind to.
+ * The parameter from CLI override the parameter from configuration file.
+ */
+ uint16_t port;
};
__attribute__((nonnull(1)))
config_t *config_read(const char *file);
+__attribute__((nonnull(1)))
+bool config_reload(config_t *config);
+
void config_delete(config_t **config);
#endif
return query_new();
}
+static bool config_refresh(void *config)
+{
+ return config_reload(config);
+}
+
static int postfix_parsejob(query_t *query, char *p)
{
#define PARSE_CHECK(expr, error, ...) \
const char *pidfile = NULL;
bool daemonize = true;
int port = DEFAULT_PORT;
+ bool port_from_cli = false;
for (int c = 0; (c = getopt(argc, argv, "hf" "l:p:")) >= 0; ) {
switch (c) {
break;
case 'l':
port = atoi(optarg);
+ port_from_cli = true;
break;
case 'f':
daemonize = false;
if (config == NULL) {
return EXIT_FAILURE;
}
+ if (port_from_cli || config->port == 0) {
+ config->port = port;
+ }
if (common_setup(pidfile, false, RUNAS_USER, RUNAS_GROUP,
daemonize) != EXIT_SUCCESS
- || start_listener(port) < 0) {
+ || start_listener(config->port) < 0) {
+ config_delete(&config);
return EXIT_FAILURE;
}
{
int res = server_loop(query_starter, (delete_client_t)query_delete,
- policy_run, NULL, config);
+ policy_run, config_refresh, config);
config_delete(&config);
return res;
}