]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Pass remote/local IPs to mail_users. Standalone mail programs now log with mail_log_p...
authorTimo Sirainen <tss@iki.fi>
Mon, 20 Apr 2009 23:07:24 +0000 (19:07 -0400)
committerTimo Sirainen <tss@iki.fi>
Mon, 20 Apr 2009 23:07:24 +0000 (19:07 -0400)
--HG--
branch : HEAD

13 files changed:
src/imap/main.c
src/lda/main.c
src/lib-storage/mail-storage-service.c
src/lib-storage/mail-storage-service.h
src/lib-storage/mail-storage-settings.c
src/lib-storage/mail-storage-settings.h
src/lib-storage/mail-user.c
src/lib/failures.c
src/lmtp/commands.c
src/plugins/convert/convert-tool.c
src/plugins/expire/expire-tool.c
src/pop3/main.c
src/util/doveadm.c

index 518047471d6e3fc2724a46dc8b2a4f50b12ed9c6..44eccc34892a0a2add267933ef0e1a02ba5724e7 100644 (file)
@@ -138,10 +138,11 @@ int main(int argc, char *argv[], char *envp[])
        };
        enum master_service_flags service_flags = 0;
        enum mail_storage_service_flags storage_service_flags = 0;
+       struct mail_storage_service_input input;
        struct mail_user *mail_user;
        const struct imap_settings *set;
-       const char *user;
        bool dump_capability;
+       const char *value;
        int c;
 
 #ifdef DEBUG
@@ -172,18 +173,23 @@ int main(int argc, char *argv[], char *envp[])
                        i_fatal("Unknown argument: %c", c);
        }
 
-       user = getenv("USER");
-       if (user == NULL) {
+       memset(&input, 0, sizeof(input));
+       input.username = getenv("USER");
+       if (input.username == NULL) {
                if (IS_STANDALONE())
-                       user = getlogin();
-               if (user == NULL)
+                       input.username = getlogin();
+               if (input.username == NULL)
                        i_fatal("USER environment missing");
        }
+       if ((value = getenv("IP")) != NULL)
+               net_addr2ip(value, &input.remote_ip);
+       if ((value = getenv("LOCAL_IP")) != NULL)
+               net_addr2ip(value, &input.local_ip);
 
        /* plugins may want to add commands, so this needs to be called early */
        commands_init();
 
-       mail_user = mail_storage_service_init_user(service, user, set_roots,
+       mail_user = mail_storage_service_init_user(service, &input, set_roots,
                                                   storage_service_flags);
        set = mail_storage_service_get_settings(service);
        restrict_access_allow_coredumps(TRUE);
index c7fe0fb99fede505dfa9b773a19a97992a21da3f..0b8d0af83c8ecbb677f1ac655d3443f0b496820d 100644 (file)
@@ -183,6 +183,7 @@ int main(int argc, char *argv[])
        struct mail_deliver_context ctx;
        enum mail_storage_service_flags service_flags = 0;
        const char *user, *errstr, *path, *getopt_str;
+       struct mail_storage_service_input service_input;
        struct mail_user *raw_mail_user;
        struct mail_namespace *raw_ns;
        struct mail_namespace_settings raw_ns_set;
@@ -317,8 +318,12 @@ int main(int argc, char *argv[])
                        "destination user parameter (-d user) not given");
        }
 
+       memset(&service_input, 0, sizeof(service_input));
+       service_input.username = user;
+
        service_flags |= MAIL_STORAGE_SERVICE_FLAG_DISALLOW_ROOT;
-       ctx.dest_user = mail_storage_service_init_user(service, user, set_roots,
+       ctx.dest_user = mail_storage_service_init_user(service, &service_input,
+                                                      set_roots,
                                                       service_flags);
        ctx.set = mail_storage_service_get_settings(service);
         duplicate_init(mail_user_set_get_storage_set(ctx.dest_user->set));
index cff0c6d7295c34fca25e4cd5890276ba114392c6..db0b9b8b9c7d1ec79f4289cfde13cb4370decb6a 100644 (file)
@@ -31,7 +31,8 @@ struct mail_storage_service_multi_ctx {
 
 struct mail_storage_service_multi_user {
        pool_t pool;
-       const char *user;
+       struct mail_storage_service_input input;
+
        const char *system_groups_user;
        const struct mail_user_settings *user_set;
        struct setting_parser_context *set_parser;
@@ -178,7 +179,6 @@ service_auth_userdb_lookup(struct setting_parser_context *set_parser,
        if (ret > 0 && strcmp(*user, orig_user) != 0) {
                if (mail_user_set_get_storage_set(user_set)->mail_debug)
                        i_info("changed username to %s", *user);
-               i_set_failure_prefix(t_strdup_printf("%s(%s): ", name, *user));
        }
 
        auth_master_deinit(&conn);
@@ -336,7 +336,8 @@ mail_storage_service_init_settings(struct master_service *service,
 
 static int
 mail_storage_service_init_post(struct master_service *service,
-                              const char *user, const char *home,
+                              const struct mail_storage_service_input *input,
+                              const char *home,
                               const struct mail_user_settings *user_set,
                               bool setuid_root, struct mail_user **mail_user_r,
                               const char **error_r)
@@ -367,9 +368,10 @@ mail_storage_service_init_post(struct master_service *service,
                }
        }
 
-       mail_user = mail_user_alloc(user, user_set);
+       mail_user = mail_user_alloc(input->username, user_set);
        mail_user_set_home(mail_user, *home == '\0' ? NULL : home);
-       mail_user_set_vars(mail_user, geteuid(), service->name, NULL, NULL);
+       mail_user_set_vars(mail_user, geteuid(), service->name,
+                          &input->local_ip, &input->remote_ip);
        if (mail_user_init(mail_user, error_r) < 0) {
                mail_user_unref(&mail_user);
                return -1;
@@ -383,13 +385,16 @@ mail_storage_service_init_post(struct master_service *service,
 }
 
 static const struct var_expand_table *
-get_var_expand_table(struct master_service *service, const char *user)
+get_var_expand_table(struct master_service *service,
+                    struct mail_storage_service_input *input)
 {
        static struct var_expand_table static_tab[] = {
                { 'u', NULL, "user" },
                { 'n', NULL, "username" },
                { 'd', NULL, "domain" },
                { 's', NULL, "service" },
+               { 'l', NULL, "lip" },
+               { 'r', NULL, "rip" },
                { 'p', NULL, "pid" },
                { 'i', NULL, "uid" },
                { '\0', NULL, NULL }
@@ -399,19 +404,21 @@ get_var_expand_table(struct master_service *service, const char *user)
        tab = t_malloc(sizeof(static_tab));
        memcpy(tab, static_tab, sizeof(static_tab));
 
-       tab[0].value = user;
-       tab[1].value = t_strcut(user, '@');
-       tab[2].value = strchr(user, '@');
+       tab[0].value = input->username;
+       tab[1].value = t_strcut(input->username, '@');
+       tab[2].value = strchr(input->username, '@');
        if (tab[2].value != NULL) tab[2].value++;
        tab[3].value = service->name;
-       tab[4].value = my_pid;
-       tab[5].value = dec2str(geteuid());
+       tab[4].value = net_ip2addr(&input->local_ip);
+       tab[5].value = net_ip2addr(&input->remote_ip);
+       tab[6].value = my_pid;
+       tab[7].value = dec2str(geteuid());
        return tab;
 }
 
 static const char *
-user_expand_varstr(struct master_service *service, const char *user,
-                  const char *str)
+user_expand_varstr(struct master_service *service,
+                  struct mail_storage_service_input *input, const char *str)
 {
        string_t *ret;
 
@@ -421,21 +428,43 @@ user_expand_varstr(struct master_service *service, const char *user,
        i_assert(*str == SETTING_STRVAR_UNEXPANDED[0]);
 
        ret = t_str_new(256);
-       var_expand(ret, str + 1, get_var_expand_table(service, user));
+       var_expand(ret, str + 1, get_var_expand_table(service, input));
        return str_c(ret);
 }
 
+static void
+mail_storage_service_init_log(struct master_service *service,
+                             struct mail_storage_service_input *input)
+{
+       const struct mail_user_settings *user_set;
+       void **sets;
+
+       sets = master_service_settings_get_others(service);
+       user_set = sets[0];
+
+       T_BEGIN {
+               string_t *str;
+
+               str = t_str_new(256);
+               var_expand(str, user_set->mail_log_prefix,
+                          get_var_expand_table(service, input));
+               master_service_init_log(service, str_c(str));
+       } T_END;
+}
+
 struct mail_user *
-mail_storage_service_init_user(struct master_service *service, const char *user,
+mail_storage_service_init_user(struct master_service *service,
+                              const struct mail_storage_service_input *_input,
                               const struct setting_parser_info *set_roots[],
                               enum mail_storage_service_flags flags)
 {
+       struct mail_storage_service_input input = *_input;
        const struct master_service_settings *set;
        const struct mail_user_settings *user_set;
        const struct mail_storage_settings *mail_set;
        struct mail_user *mail_user;
        void **sets;
-       const char *orig_user, *home, *system_groups_user, *error;
+       const char *user, *orig_user, *home, *system_groups_user, *error;
        unsigned int len;
        bool userdb_lookup;
 
@@ -446,8 +475,7 @@ mail_storage_service_init_user(struct master_service *service, const char *user,
                set_keyval(service->set_parser, "mail_debug", "yes");
 
        /* now that we've read settings, we can set up logging */
-       master_service_init_log(service,
-               t_strdup_printf("%s(%s): ", service->name, user));
+       mail_storage_service_init_log(service, &input);
 
        set = master_service_settings_get(service);
        sets = master_service_settings_get_others(service);
@@ -457,17 +485,21 @@ mail_storage_service_init_user(struct master_service *service, const char *user,
        if (userdb_lookup) {
                /* userdb lookup may change settings, do it as soon as
                   possible. */
-               orig_user = user;
+               orig_user = user = input.username;
                if (service_auth_userdb_lookup(service->set_parser,
                                               service->name, user_set, &user,
                                               &system_groups_user,
                                               &error) <= 0)
                        i_fatal("%s", error);
+               input.username = user;
+
+               /* set up logging again in case username changed */
+               mail_storage_service_init_log(service, &input);
        }
 
        /* variable strings are expanded in mail_user_init(),
           but we need the home sooner so do it separately here. */
-       home = user_expand_varstr(service, user, user_set->mail_home);
+       home = user_expand_varstr(service, &input, user_set->mail_home);
 
        if (!userdb_lookup) {
                system_groups_user = NULL;
@@ -500,8 +532,8 @@ mail_storage_service_init_user(struct master_service *service, const char *user,
        dict_drivers_register_builtin();
        module_dir_init(modules);
        mail_users_init(user_set->auth_socket_path, mail_set->mail_debug);
-       if (mail_storage_service_init_post(service, user, home, user_set, FALSE,
-                                          &mail_user, &error) < 0)
+       if (mail_storage_service_init_post(service, &input, home, user_set,
+                                          FALSE, &mail_user, &error) < 0)
                i_fatal("%s", error);
        return mail_user;
 }
@@ -552,36 +584,37 @@ mail_storage_service_multi_init(struct master_service *service,
 }
 
 int mail_storage_service_multi_lookup(struct mail_storage_service_multi_ctx *ctx,
-                                     const char *username, pool_t pool,
+                                     const struct mail_storage_service_input *input,
+                                     pool_t pool,
                                      struct mail_storage_service_multi_user **user_r,
                                      const char **error_r)
 {
        struct mail_storage_service_multi_user *user;
-       const char *orig_user;
+       const char *orig_user, *username;
        void **sets;
        int ret;
 
        user = p_new(pool, struct mail_storage_service_multi_user, 1);
        memset(user_r, 0, sizeof(user_r));
        user->pool = pool;
-       user->user = username;
+       user->input = *input;
+       user->input.username = p_strdup(pool, input->username);
 
        user->set_parser = settings_parser_dup(ctx->service->set_parser, pool);
        sets = settings_parser_get_list(user->set_parser);
        user->user_set = sets[1];
 
        if ((ctx->flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) != 0) {
-               orig_user = user->user;
+               orig_user = username = user->input.username;
                ret = service_auth_userdb_lookup(user->set_parser,
                                                 ctx->service->name,
-                                                user->user_set,
-                                                &user->user,
+                                                user->user_set, &username,
                                                 &user->system_groups_user,
                                                 error_r);
                if (ret <= 0)
                        return ret;
+               user->input.username = p_strdup(pool, username);
        }
-       user->user = p_strdup(pool, user->user);
        *user_r = user;
        return 1;
 }
@@ -597,9 +630,11 @@ int mail_storage_service_multi_next(struct mail_storage_service_multi_ctx *ctx,
 
        /* variable strings are expanded in mail_user_init(),
           but we need the home sooner so do it separately here. */
-       home = user_expand_varstr(ctx->service, user->user,
+       home = user_expand_varstr(ctx->service, &user->input,
                                  user_set->mail_home);
 
+       mail_storage_service_init_log(ctx->service, &user->input);
+
        if ((ctx->flags & MAIL_STORAGE_SERVICE_FLAG_NO_RESTRICT_ACCESS) == 0) {
                service_drop_privileges(user_set, user->system_groups_user, home,
                        (ctx->flags & MAIL_STORAGE_SERVICE_FLAG_DISALLOW_ROOT) != 0,
@@ -622,8 +657,8 @@ int mail_storage_service_multi_next(struct mail_storage_service_multi_ctx *ctx,
                set_keyval(user->set_parser, "mail_home",
                        t_strconcat(user_set->mail_chroot, "/", home, NULL));
        }
-       if (mail_storage_service_init_post(ctx->service, user->user, home,
-                                          user_set, TRUE,
+       if (mail_storage_service_init_post(ctx->service, &user->input,
+                                          home, user_set, TRUE,
                                           mail_user_r, error_r) < 0)
                return -1;
        return 0;
index ce6dce5146654022fd494909ec30543882615c70..4933f5c1778e8ee3ca4ed0907bd4c8c5426bfc99 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef MAIL_STORAGE_SERVICE_H
 #define MAIL_STORAGE_SERVICE_H
 
+#include "network.h"
+
 struct master_service;
 
 enum mail_storage_service_flags {
@@ -14,11 +16,17 @@ enum mail_storage_service_flags {
        MAIL_STORAGE_SERVICE_FLAG_NO_RESTRICT_ACCESS    = 0x08
 };
 
+struct mail_storage_service_input {
+       const char *username;
+       struct ip_addr local_ip, remote_ip;
+};
+
 struct setting_parser_info;
 struct mail_storage_service_multi_user;
 
 struct mail_user *
-mail_storage_service_init_user(struct master_service *service, const char *user,
+mail_storage_service_init_user(struct master_service *service,
+                              const struct mail_storage_service_input *input,
                               const struct setting_parser_info *set_roots[],
                               enum mail_storage_service_flags flags);
 void mail_storage_service_deinit_user(void);
@@ -29,7 +37,8 @@ mail_storage_service_multi_init(struct master_service *service,
                                enum mail_storage_service_flags flags);
 /* Returns 1 if ok, 0 if user wasn't found, -1 if error. */
 int mail_storage_service_multi_lookup(struct mail_storage_service_multi_ctx *ctx,
-                                     const char *username, pool_t pool,
+                                     const struct mail_storage_service_input *input,
+                                     pool_t pool,
                                      struct mail_storage_service_multi_user **user_r,
                                      const char **error_r);
 int mail_storage_service_multi_next(struct mail_storage_service_multi_ctx *ctx,
index c5befd02c0426e38191adb76519a6ffabdbbe4a9..e0eece37a584f01602bc482b2c6d4bc854842e2d 100644 (file)
@@ -149,6 +149,8 @@ static struct setting_define mail_user_setting_defines[] = {
        DEF(SET_STR, mail_plugins),
        DEF(SET_STR, mail_plugin_dir),
 
+       DEF(SET_STR, mail_log_prefix),
+
        DEFLIST(namespaces, "namespace", &mail_namespace_setting_parser_info),
        { SET_STRLIST, "plugin", offsetof(struct mail_user_settings, plugin_envs), NULL },
 
@@ -175,6 +177,8 @@ static struct mail_user_settings mail_user_default_settings = {
        MEMBER(mail_plugins) "",
        MEMBER(mail_plugin_dir) MODULEDIR,
 
+       MEMBER(mail_log_prefix) "%Us(%u): ",
+
        MEMBER(namespaces) ARRAY_INIT,
        MEMBER(plugin_envs) ARRAY_INIT
 };
index d6f24d66f73ea5504675caa5ebafababd8868f30..dacea133915701108ea79d444a0b7feecad3a993 100644 (file)
@@ -57,6 +57,8 @@ struct mail_user_settings {
        const char *mail_plugins;
        const char *mail_plugin_dir;
 
+       const char *mail_log_prefix;
+
        ARRAY_DEFINE(namespaces, struct mail_namespace_settings *);
        ARRAY_DEFINE(plugin_envs, const char *);
 };
index 15d60ca7f6768808131d4574588a9cf52359a66b..28e80ed151166fd658f989f1f45c71116d85cf5c 100644 (file)
@@ -143,11 +143,11 @@ void mail_user_set_vars(struct mail_user *user, uid_t uid, const char *service,
 {
        user->uid = uid;
        user->service = p_strdup(user->pool, service);
-       if (local_ip != NULL) {
+       if (local_ip != NULL && local_ip->family != 0) {
                user->local_ip = p_new(user->pool, struct ip_addr, 1);
                *user->local_ip = *local_ip;
        }
-       if (remote_ip != NULL) {
+       if (remote_ip != NULL && remote_ip->family != 0) {
                user->remote_ip = p_new(user->pool, struct ip_addr, 1);
                *user->remote_ip = *remote_ip;
        }
index 776bbdfc952452e1b9b8fcf6bc02afc1dc1953ff..bba5e83e515a53fc5095b4a7e048437f83f9f3d4 100644 (file)
@@ -397,6 +397,7 @@ void i_set_failure_prefix(const char *prefix)
 {
        i_free(log_prefix);
        log_prefix = i_strdup(prefix);
+       i_warning("new prefix=%s", prefix);
 }
 
 static int ATTR_FORMAT(2, 0)
index 79169a3a811cfa1695dbe9f2a3fe58b54b9750c5..953d883df4cf747a3e3084059cb79bf385ccc406 100644 (file)
@@ -79,6 +79,7 @@ static bool rcpt_is_duplicate(struct client *client, const char *name)
 int cmd_rcpt(struct client *client, const char *args)
 {
        struct mail_recipient rcpt;
+       struct mail_storage_service_input input;
        const char *name, *error;
        unsigned int len;
        int ret;
@@ -102,7 +103,12 @@ int cmd_rcpt(struct client *client, const char *args)
                return 0;
        }
 
-       ret = mail_storage_service_multi_lookup(multi_service, name,
+       memset(&input, 0, sizeof(input));
+       input.username = name;
+       input.local_ip = client->local_ip;
+       input.remote_ip = client->remote_ip;
+
+       ret = mail_storage_service_multi_lookup(multi_service, &input,
                                                client->state_pool,
                                                &rcpt.multi_user, &error);
        if (ret < 0) {
index 0ba2de2f4b6d871ce9574fcf9d0d0113eb3b93d2..341103f62f4262b7e7cbf77e65d045534c14907b 100644 (file)
@@ -18,6 +18,7 @@
 int main(int argc, char *argv[])
 {
        struct master_service *service;
+       struct mail_storage_service_input input;
        struct mail_user *user;
        struct convert_plugin_settings set;
        struct mail_namespace *dest_ns;
@@ -50,9 +51,12 @@ int main(int argc, char *argv[])
                        i_fatal(USAGE_STRING);
        }
 
+       memset(&input, 0, sizeof(input));
+       input.username = argv[optind];
+
        master_service_init_log(service,
-               t_strdup_printf("convert-tool(%s): ", argv[optind]));
-       user = mail_storage_service_init_user(service, argv[optind], NULL, 0);
+               t_strdup_printf("convert-tool(%s): ", input.username));
+       user = mail_storage_service_init_user(service, &input, NULL, 0);
 
        memset(&ns_set, 0, sizeof(ns_set));
        ns_set.location = argv[4];
index 6a3238d67f455a68b8e5434be3c65fc685530a7e..df9ed618294671d3f0afa0f5e1d6b61715100e8b 100644 (file)
@@ -29,6 +29,7 @@ mailbox_delete_old_mails(struct expire_context *ctx, const char *user,
                         unsigned int expunge_secs, unsigned int altmove_secs,
                         time_t *oldest_r)
 {
+       struct mail_storage_service_input input;
        struct mail_storage_service_multi_user *multi_user;
        struct mail_namespace *ns;
        struct mail_storage *storage;
@@ -43,6 +44,9 @@ mailbox_delete_old_mails(struct expire_context *ctx, const char *user,
        enum mail_flags flags;
        int ret;
 
+       memset(&input, 0, sizeof(input));
+       input.username = user;
+
        *oldest_r = 0;
 
        if (ctx->mail_user != NULL &&
@@ -52,7 +56,7 @@ mailbox_delete_old_mails(struct expire_context *ctx, const char *user,
                i_set_failure_prefix(t_strdup_printf("expire-tool(%s): ",
                                                     user));
                p_clear(ctx->multi_user_pool);
-               ret = mail_storage_service_multi_lookup(ctx->multi, user,
+               ret = mail_storage_service_multi_lookup(ctx->multi, &input,
                                                        ctx->multi_user_pool,
                                                        &multi_user, &errstr);
                if (ret <= 0) {
index 5e68fa16c2083f9529699158e15bdb1c7eae14f0..1ff3db28b3d03f760930f83fdc6fd62625b70d6f 100644 (file)
@@ -146,9 +146,10 @@ int main(int argc, char *argv[], char *envp[])
        enum master_service_flags service_flags = 0;
        enum mail_storage_service_flags storage_service_flags =
                MAIL_STORAGE_SERVICE_FLAG_DISALLOW_ROOT;
+       struct mail_storage_service_input input;
        struct mail_user *mail_user;
        const struct pop3_settings *set;
-       const char *user;
+       const char *value;
        int c;
 
 #ifdef DEBUG
@@ -172,15 +173,21 @@ int main(int argc, char *argv[], char *envp[])
                if (!master_service_parse_option(service, c, optarg))
                        i_fatal("Unknown argument: %c", c);
        }
-       user = getenv("USER");
-       if (user == NULL) {
+
+       memset(&input, 0, sizeof(input));
+       input.username = getenv("USER");
+       if (input.username == NULL) {
                if (IS_STANDALONE())
-                       user = getlogin();
-               if (user == NULL)
+                       input.username = getlogin();
+               if (input.username == NULL)
                        i_fatal("USER environment missing");
        }
+       if ((value = getenv("IP")) != NULL)
+               net_addr2ip(value, &input.remote_ip);
+       if ((value = getenv("LOCAL_IP")) != NULL)
+               net_addr2ip(value, &input.local_ip);
 
-       mail_user = mail_storage_service_init_user(service, user, set_roots,
+       mail_user = mail_storage_service_init_user(service, &input, set_roots,
                                                   storage_service_flags);
        set = mail_storage_service_get_settings(service);
        restrict_access_allow_coredumps(TRUE);
index c6729cfde5d0913ae8e7e7df122562860644b08d..69471801c3a78e4f1f2fbbb2b5ff7a93b3902b01 100644 (file)
@@ -82,7 +82,8 @@ int main(int argc, char *argv[])
 {
        enum mail_storage_service_flags service_flags = 0;
        struct master_service *service;
-       const char *getopt_str, *user;
+       struct mail_storage_service_input input;
+       const char *getopt_str;
        int c;
 
        service = master_service_init("doveadm",
@@ -90,12 +91,13 @@ int main(int argc, char *argv[])
                                      MASTER_SERVICE_FLAG_LOG_TO_STDERR,
                                      argc, argv);
 
-       user = getenv("USER");
+       memset(&input, 0, sizeof(input));
+       input.username = getenv("USER");
        getopt_str = t_strconcat("u:v", master_service_getopt_string(), NULL);
        while ((c = getopt(argc, argv, getopt_str)) > 0) {
                switch (c) {
                case 'u':
-                       user = optarg;
+                       input.username = optarg;
                        service_flags |= MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
                        break;
                case 'v':
@@ -109,10 +111,10 @@ int main(int argc, char *argv[])
        if (optind == argc)
                usage();
 
-       if (user == NULL)
+       if (input.username == NULL)
                i_fatal("USER environment is missing and -u option not used");
 
-       mail_user = mail_storage_service_init_user(service, user, NULL,
+       mail_user = mail_storage_service_init_user(service, &input, NULL,
                                                   service_flags);
 
        if (strcmp(argv[optind], "purge") == 0)