pfixtools 0.5.
[apps/pfixtools.git] / postlicyd / main-postlicyd.c
index 50c19d5..2019f6c 100644 (file)
@@ -44,7 +44,7 @@
 #include "query.h"
 
 #define DAEMON_NAME             "postlicyd"
-#define DAEMON_VERSION          "0.3"
+#define DAEMON_VERSION          "0.5"
 #define DEFAULT_PORT            10000
 #define RUNAS_USER              "nobody"
 #define RUNAS_GROUP             "nogroup"
@@ -83,7 +83,10 @@ static bool config_refresh(void *mconfig)
     if (filter_running > 0) {
         return true;
     }
+    log_state = "refreshing ";
+    info("reloading configuration");
     bool ret = config_reload(mconfig);
+    log_state = "";
     foreach (client_t **server, busy) {
         client_io_ro(*server);
     }}
@@ -100,21 +103,8 @@ static void policy_answer(client_t *pcy, const char *message)
 
     /* Write reply "action=ACTION [text]" */
     buffer_addstr(buf, "action=");
-    buffer_ensure(buf, m_strlen(message) + 64);
-
-    ssize_t size = array_size(*buf) - array_len(*buf);
-    ssize_t format_size = query_format(array_ptr(*buf, array_len(*buf)),
-                                       size, message, query);
-    if (format_size == -1) {
+    if (!query_format_buffer(buf, message, query)) {
         buffer_addstr(buf, message);
-    } else if (format_size > size) {
-        buffer_ensure(buf, format_size + 1);
-        query_format(array_ptr(*buf, array_len(*buf)),
-                     array_size(*buf) - array_len(*buf),
-                     message, query);
-        array_len(*buf) += format_size;
-    } else {
-        array_len(*buf) += format_size;
     }
     buffer_addstr(buf, "\n\n");
 
@@ -126,53 +116,49 @@ static void policy_answer(client_t *pcy, const char *message)
 
 static const filter_t *next_filter(client_t *pcy, const filter_t *filter,
                                    const query_t *query, const filter_hook_t *hook, bool *ok) {
+    char log_prefix[BUFSIZ];
+    log_prefix[0] = '\0';
+
+#define log_reply(Level, Msg, ...)                                             \
+    if (log_level >= LOG_ ## Level) {                                          \
+        if (log_prefix[0] == '\0') {                                           \
+            query_format(log_prefix, BUFSIZ,                                   \
+                         config->log_format && config->log_format[0] ?         \
+                            config->log_format : DEFAULT_LOG_FORMAT, query);   \
+        }                                                                      \
+        __log(LOG_ ## Level, "%s: " Msg, log_prefix, ##__VA_ARGS__);           \
+    }
+
     if (hook != NULL) {
         query_context_t *context = client_data(pcy);
         if (hook->counter >= 0 && hook->counter < MAX_COUNTERS && hook->cost > 0) {
             context->context.counters[hook->counter] += hook->cost;
-            debug("request client=%s, from=<%s>, to=<%s>: added %d to counter %d (now %u)",
-                  query->client_name,
-                  query->sender == NULL ? "undefined" : query->sender,
-                  query->recipient == NULL ? "undefined" : query->recipient,
-                  hook->cost, hook->counter, context->context.counters[hook->counter]);
+            log_reply(DEBUG, "added %d to counter %d (now %u)",
+                      hook->cost, hook->counter,
+                      context->context.counters[hook->counter]);
         }
     }
     if (hook == NULL) {
-        warn("request client=%s, from=<%s>, to=<%s>: aborted",
-             query->client_name,
-             query->sender == NULL ? "undefined" : query->sender,
-             query->recipient == NULL ? "undefined" : query->recipient);
+        log_reply(WARNING, "aborted");
         *ok = false;
         return NULL;
     } else if (hook->async) {
-        debug("request client=%s, from=<%s>, to=<%s>: "
-              "asynchronous filter from filter %s",
-               query->client_name,
-               query->sender == NULL ? "undefined" : query->sender,
-               query->recipient == NULL ? "undefined" : query->recipient,
-               filter->name);
+        log_reply(WARNING, "asynchronous filter from filter %s", filter->name);
         *ok = true;
         return NULL;
     } else if (hook->postfix) {
-        info("request client=%s, from=<%s>, to=<%s>: "
-             "awswer %s from filter %s: \"%s\"",
-             query->client_name,
-             query->sender == NULL ? "undefined" : query->sender,
-             query->recipient == NULL ? "undefined" : query->recipient,
-             htokens[hook->type], filter->name, hook->value);
+        log_reply(INFO, "awswer %s from filter %s: \"%s\"",
+                  htokens[hook->type], filter->name, hook->value);
         policy_answer(pcy, hook->value);
         *ok = true;
         return NULL;
     } else {
-        debug("request client=%s, from=<%s>, to=<%s>: "
-               "awswer %s from filter %s: next filter %s",
-               query->client_name,
-               query->sender == NULL ? "undefined" : query->sender,
-               query->recipient == NULL ? "undefined" : query->recipient,
-               htokens[hook->type], filter->name,
-               (array_ptr(config->filters, hook->filter_id))->name);
+        log_reply(DEBUG,  "awswer %s from filter %s: next filter %s",
+                  htokens[hook->type], filter->name,
+                  (array_ptr(config->filters, hook->filter_id))->name);
         return array_ptr(config->filters, hook->filter_id);
     }
+#undef log_reply
 }
 
 static bool policy_process(client_t *pcy, const config_t *mconfig)
@@ -181,7 +167,7 @@ static bool policy_process(client_t *pcy, const config_t *mconfig)
     const query_t* query = &context->query;
     const filter_t *filter;
     if (mconfig->entry_points[query->state] == -1) {
-        warn("no filter defined for current protocol_state (%d)", query->state);
+        warn("no filter defined for current protocol_state (%s)", smtp_state_names[query->state].str);
         return false;
     }
     if (context->context.current_filter != NULL) {
@@ -239,9 +225,10 @@ static int policy_run(client_t *pcy, void* vconfig)
     query->eoq = eoq + strlen("\n\n");
 
     /* The instance changed => reset the static context */
-    if (query->instance == NULL || strcmp(context->context.instance, query->instance) != 0) {
+    if (query->instance.str == NULL || query->instance.len == 0
+        || strcmp(context->context.instance, query->instance.str) != 0) {
         filter_context_clean(&context->context);
-        m_strcat(context->context.instance, 64, query->instance);
+        m_strcat(context->context.instance, 64, query->instance.str);
     }
     client_io_none(pcy);
     return policy_process(pcy, mconfig) ? 0 : -1;
@@ -293,6 +280,7 @@ void usage(void)
           "    -f           stay in foreground\n"
           "    -d           grow logging level\n"
           "    -u           unsafe mode (don't drop privileges)\n"
+          "    -c           check-conf\n"
          , stderr);
 }
 
@@ -305,8 +293,9 @@ int main(int argc, char *argv[])
     bool daemonize = true;
     int port = DEFAULT_PORT;
     bool port_from_cli = false;
+    bool check_conf = false;
 
-    for (int c = 0; (c = getopt(argc, argv, "ufd" "l:p:")) >= 0; ) {
+    for (int c = 0; (c = getopt(argc, argv, "ufdc" "l:p:")) >= 0; ) {
         switch (c) {
           case 'p':
             pidfile = optarg;
@@ -324,6 +313,11 @@ int main(int argc, char *argv[])
           case 'd':
             ++log_level;
             break;
+          case 'c':
+            check_conf = true;
+            daemonize  = false;
+            unsafe     = true;
+            break;
           default:
             usage();
             return EXIT_FAILURE;
@@ -339,7 +333,10 @@ int main(int argc, char *argv[])
         return EXIT_FAILURE;
     }
 
-    info("starting %s v%s...", DAEMON_NAME, DAEMON_VERSION);
+    if (check_conf) {
+        return config_check(argv[optind]) ? EXIT_SUCCESS : EXIT_FAILURE;
+    }
+    info("%s v%s...", DAEMON_NAME, DAEMON_VERSION);
 
     if (pidfile_open(pidfile) < 0) {
         crit("unable to write pidfile %s", pidfile);