Mercurial > dovecot > core-2.2
changeset 10001:a02c1d9df1bf HEAD
Moved doveadm to a separate directory and made it a bit more easily extensible.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 08 Oct 2009 17:58:38 -0400 |
parents | c610321584ca |
children | d9cb9d03e50e |
files | .hgignore configure.in src/Makefile.am src/doveadm/Makefile.am src/doveadm/doveadm-mail.c src/doveadm/doveadm-mail.h src/doveadm/doveadm.c src/doveadm/doveadm.h src/util/Makefile.am src/util/doveadm.c |
diffstat | 10 files changed, 389 insertions(+), 260 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgignore Thu Oct 08 13:02:25 2009 -0400 +++ b/.hgignore Thu Oct 08 17:58:38 2009 -0400 @@ -59,6 +59,7 @@ src/config/doveconf src/lda/dovecot-lda src/dict/dict +src/doveadm/doveadm src/dsync/dsync src/imap-login/imap-login src/imap/imap @@ -78,7 +79,6 @@ src/pop3-login/pop3-login src/pop3/pop3 src/util/authtest -src/util/doveadm src/util/dovecotpw src/util/gdbhelper src/util/idxview
--- a/configure.in Thu Oct 08 13:02:25 2009 -0400 +++ b/configure.in Thu Oct 08 17:58:38 2009 -0400 @@ -2496,6 +2496,7 @@ src/anvil/Makefile src/auth/Makefile src/config/Makefile +src/doveadm/Makefile src/dsync/Makefile src/lda/Makefile src/log/Makefile
--- a/src/Makefile.am Thu Oct 08 13:02:25 2009 -0400 +++ b/src/Makefile.am Thu Oct 08 17:58:38 2009 -0400 @@ -32,6 +32,7 @@ log \ config \ util \ + doveadm \ dsync \ ssl-params \ plugins
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/doveadm/Makefile.am Thu Oct 08 17:58:38 2009 -0400 @@ -0,0 +1,25 @@ +bin_PROGRAMS = doveadm + +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/lib \ + -I$(top_srcdir)/src/lib-auth \ + -I$(top_srcdir)/src/lib-dict \ + -I$(top_srcdir)/src/lib-master \ + -I$(top_srcdir)/src/lib-mail \ + -I$(top_srcdir)/src/lib-imap \ + -I$(top_srcdir)/src/lib-index \ + -I$(top_srcdir)/src/lib-storage \ + -I$(top_srcdir)/src/auth \ + -DPKG_RUNDIR=\""$(rundir)"\" + +doveadm_LDADD = \ + $(LIBDOVECOT_STORAGE) \ + $(LIBDOVECOT) \ + $(MODULE_LIBS) +doveadm_DEPENDENCIES = $(LIBDOVECOT_STORAGE) $(LIBDOVECOT) +doveadm_SOURCES = \ + doveadm.c \ + doveadm-mail.c + +noinst_HEADERS = \ + doveadm-mail.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/doveadm/doveadm-mail.c Thu Oct 08 17:58:38 2009 -0400 @@ -0,0 +1,280 @@ +/* Copyright (c) 2009 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "array.h" +#include "lib-signals.h" +#include "ioloop.h" +#include "master-service.h" +#include "mail-user.h" +#include "mail-namespace.h" +#include "mail-storage.h" +#include "mail-storage-settings.h" +#include "mail-storage-service.h" +#include "doveadm.h" +#include "doveadm-mail.h" + +#include <stdio.h> + +ARRAY_TYPE(doveadm_mail_cmd) doveadm_mail_cmds; + +static int killed_signo = 0; + +static void cmd_purge(struct mail_user *user, const char *args[] ATTR_UNUSED) +{ + struct mail_namespace *ns; + + for (ns = user->namespaces; ns != NULL; ns = ns->next) { + if (ns->type != NAMESPACE_PRIVATE || ns->alias_for != NULL) + continue; + + if (mail_storage_purge(ns->storage) < 0) { + i_error("Purging namespace '%s' failed: %s", ns->prefix, + mail_storage_get_last_error(ns->storage, NULL)); + } + } +} + +static struct mailbox * +mailbox_find_and_open(struct mail_user *user, const char *mailbox) +{ + struct mail_namespace *ns; + struct mailbox *box; + const char *orig_mailbox = mailbox; + + ns = mail_namespace_find(user->namespaces, &mailbox); + if (ns == NULL) + i_fatal("Can't find namespace for mailbox %s", mailbox); + + box = mailbox_alloc(ns->list, mailbox, NULL, MAILBOX_FLAG_KEEP_RECENT | + MAILBOX_FLAG_IGNORE_ACLS); + if (mailbox_open(box) < 0) { + i_fatal("Opening mailbox %s failed: %s", orig_mailbox, + mail_storage_get_last_error(mailbox_get_storage(box), + NULL)); + } + return box; +} + +static void cmd_force_resync(struct mail_user *user, const char *args[]) +{ + const char *mailbox = args[0]; + struct mail_storage *storage; + struct mailbox *box; + + if (mailbox == NULL) + usage(); + + box = mailbox_find_and_open(user, mailbox); + storage = mailbox_get_storage(box); + if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FORCE_RESYNC | + MAILBOX_SYNC_FLAG_FIX_INCONSISTENT, 0, NULL) < 0) { + i_fatal("Forcing a resync on mailbox %s failed: %s", mailbox, + mail_storage_get_last_error(storage, NULL)); + } + mailbox_close(&box); +} + +static void +doveadm_mail_single_user(doveadm_mail_command_t *cmd, const char *username, + enum mail_storage_service_flags service_flags, + const char *args[]) +{ + struct mail_storage_service_input input; + struct mail_user *mail_user; + + if (username == NULL) + i_fatal("USER environment is missing and -u option not used"); + + memset(&input, 0, sizeof(input)); + input.username = username; + mail_user = mail_storage_service_init_user(master_service, &input, NULL, + service_flags); + cmd(mail_user, args); + mail_user_unref(&mail_user); + mail_storage_service_deinit_user(); +} + +static int +doveadm_mail_next_user(doveadm_mail_command_t *cmd, + struct mail_storage_service_multi_ctx *multi, + const struct mail_storage_service_input *input, + pool_t pool, const char *args[]) +{ + struct mail_storage_service_multi_user *multi_user; + struct mail_user *mail_user; + const char *error; + int ret; + + i_set_failure_prefix(t_strdup_printf("doveadm(%s): ", input->username)); + ret = mail_storage_service_multi_lookup(multi, input, pool, + &multi_user, &error); + if (ret <= 0) { + if (ret == 0) { + i_info("User no longer exists, skipping"); + return 0; + } else { + i_error("User lookup failed: %s", error); + return -1; + } + } + if (mail_storage_service_multi_next(multi, multi_user, + &mail_user, &error) < 0) { + i_error("User init failed: %s", error); + mail_storage_service_multi_user_free(multi_user); + return -1; + } + mail_storage_service_multi_user_free(multi_user); + cmd(mail_user, args); + mail_user_unref(&mail_user); + return 0; +} + +static void sig_die(const siginfo_t *si, void *context ATTR_UNUSED) +{ + killed_signo = si->si_signo; +} + +static void +doveadm_mail_all_users(doveadm_mail_command_t *cmd, + enum mail_storage_service_flags service_flags, + const char *args[]) +{ + struct mail_storage_service_input input; + struct mail_storage_service_multi_ctx *multi; + unsigned int user_idx, user_count, interval, n; + const char *user; + pool_t pool; + int ret; + + service_flags |= MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP; + + memset(&input, 0, sizeof(input)); + input.service = "doveadm"; + + multi = mail_storage_service_multi_init(master_service, NULL, + service_flags); + pool = pool_alloconly_create("multi user", 8192); + + lib_signals_set_handler(SIGINT, FALSE, sig_die, NULL); + lib_signals_set_handler(SIGTERM, FALSE, sig_die, NULL); + + user_count = mail_storage_service_multi_all_init(multi); + n = user_count / 10000; + for (interval = 10; n > 0 && interval < 1000; interval *= 10) + n /= 10; + + user_idx = 0; + while ((ret = mail_storage_service_multi_all_next(multi, &user)) > 0) { + p_clear(pool); + input.username = user; + T_BEGIN { + ret = doveadm_mail_next_user(cmd, multi, &input, + pool, args); + } T_END; + if (ret < 0) + break; + if ((service_flags & MAIL_STORAGE_SERVICE_FLAG_DEBUG) != 0) { + if (++user_idx % interval == 0) { + printf("\r%d / %d", user_idx, user_count); + fflush(stdout); + } + } + if (killed_signo != 0) { + i_warning("Killed with signal %d", killed_signo); + ret = -1; + break; + } + } + if ((service_flags & MAIL_STORAGE_SERVICE_FLAG_DEBUG) != 0) + printf("\n"); + i_set_failure_prefix("doveadm: "); + if (ret < 0) + i_error("Failed to iterate through some users"); + mail_storage_service_multi_deinit(&multi); + pool_unref(&pool); +} + +static void +doveadm_mail_cmd(doveadm_mail_command_t *cmd, int argc, char *argv[]) +{ + enum mail_storage_service_flags service_flags = 0; + const char *username; + bool all_users = FALSE; + int c; + + while ((c = getopt(argc, argv, "av")) > 0) { + switch (c) { + case 'a': + all_users = TRUE; + break; + case 'v': + service_flags |= MAIL_STORAGE_SERVICE_FLAG_DEBUG; + break; + default: + if (!master_service_parse_option(master_service, + c, optarg)) + usage(); + } + } + if (!all_users) { + if (optind == argc) + usage(); + service_flags |= MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP; + username = argv[optind++]; + doveadm_mail_single_user(cmd, username, service_flags, + (const char **)argv + optind); + } else { + doveadm_mail_all_users(cmd, service_flags, + (const char **)argv + optind); + } +} + +bool doveadm_mail_try_run(const char *cmd_name, int argc, char *argv[]) +{ + const struct doveadm_mail_cmd *cmd; + + array_foreach(&doveadm_mail_cmds, cmd) { + if (strcmp(cmd->name, cmd_name) == 0) { + doveadm_mail_cmd(cmd->cmd, argc, argv); + return TRUE; + } + } + return FALSE; +} + +void doveadm_mail_register_cmd(const struct doveadm_mail_cmd *cmd) +{ + /* for now we'll just assume that cmd will be permanently in memory */ + array_append(&doveadm_mail_cmds, cmd, 1); +} + +void doveadm_mail_usage(void) +{ + const struct doveadm_mail_cmd *cmd; + + array_foreach(&doveadm_mail_cmds, cmd) { + fprintf(stderr, " %s <user>|-a", cmd->name); + if (cmd->usage_args != NULL) + fprintf(stderr, " %s", cmd->usage_args); + fputc('\n', stderr); + } +} + +static struct doveadm_mail_cmd mail_commands[] = { + { cmd_purge, "purge", NULL }, + { cmd_force_resync, "force-resync", "<mailbox>" } +}; + +void doveadm_mail_init(void) +{ + unsigned int i; + + i_array_init(&doveadm_mail_cmds, 32); + for (i = 0; i < N_ELEMENTS(mail_commands); i++) + doveadm_mail_register_cmd(&mail_commands[i]); +} + +void doveadm_mail_deinit(void) +{ + array_free(&doveadm_mail_cmds); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/doveadm/doveadm-mail.h Thu Oct 08 17:58:38 2009 -0400 @@ -0,0 +1,25 @@ +#ifndef DOVEADM_MAIL_H +#define DOVEADM_MAIL_H + +struct mail_user; + +typedef void doveadm_mail_command_t(struct mail_user *mail_user, + const char *args[]); + +struct doveadm_mail_cmd { + doveadm_mail_command_t *cmd; + const char *name; + const char *usage_args; +}; +ARRAY_DEFINE_TYPE(doveadm_mail_cmd, struct doveadm_mail_cmd); + +extern ARRAY_TYPE(doveadm_mail_cmd) doveadm_mail_cmds; + +bool doveadm_mail_try_run(const char *cmd_name, int argc, char *argv[]); +void doveadm_mail_register_cmd(const struct doveadm_mail_cmd *cmd); +void doveadm_mail_usage(void); + +void doveadm_mail_init(void); +void doveadm_mail_deinit(void); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/doveadm/doveadm.c Thu Oct 08 17:58:38 2009 -0400 @@ -0,0 +1,49 @@ +/* Copyright (c) 2009 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "master-service.h" +#include "doveadm-mail.h" +#include "doveadm.h" + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +void usage(void) +{ + fprintf(stderr, "usage: doveadm\n"); + doveadm_mail_usage(); + exit(1); +} + +int main(int argc, char *argv[]) +{ + const char *cmd_name, *getopt_str; + int c; + + master_service = master_service_init("doveadm", + MASTER_SERVICE_FLAG_STANDALONE, + argc, argv); + doveadm_mail_init(); + + /* "+" is GNU extension to stop at the first non-option. + others just accept -+ option. */ + getopt_str = t_strconcat("+", master_service_getopt_string(), NULL); + while ((c = getopt(argc, argv, getopt_str)) > 0) { + if (!master_service_parse_option(master_service, c, optarg)) + usage(); + } + if (optind == argc) + usage(); + + cmd_name = argv[optind]; + argc -= optind; + argv += optind; + + if (!doveadm_mail_try_run(cmd_name, argc, argv)) + usage(); + + master_service_deinit(&master_service); + doveadm_mail_deinit(); + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/doveadm/doveadm.h Thu Oct 08 17:58:38 2009 -0400 @@ -0,0 +1,6 @@ +#ifndef DOVEADM_H +#define DOVEADM_H + +void usage(void); + +#endif
--- a/src/util/Makefile.am Thu Oct 08 13:02:25 2009 -0400 +++ b/src/util/Makefile.am Thu Oct 08 17:58:38 2009 -0400 @@ -12,7 +12,7 @@ maildirlock \ threadview -sbin_PROGRAMS = dovecotpw doveadm +sbin_PROGRAMS = dovecotpw AM_CPPFLAGS = \ -I$(top_srcdir)/src/lib \ @@ -89,11 +89,3 @@ dovecotpw_SOURCES = \ dovecotpw.c - -doveadm_LDADD = \ - $(LIBDOVECOT_STORAGE) \ - $(LIBDOVECOT) \ - $(MODULE_LIBS) -doveadm_DEPENDENCIES = $(LIBDOVECOT_STORAGE) $(LIBDOVECOT) -doveadm_SOURCES = \ - doveadm.c
--- a/src/util/doveadm.c Thu Oct 08 13:02:25 2009 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,250 +0,0 @@ -/* Copyright (c) 2009 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "lib-signals.h" -#include "ioloop.h" -#include "env-util.h" -#include "master-service.h" -#include "mail-user.h" -#include "mail-namespace.h" -#include "mail-storage.h" -#include "mail-storage-settings.h" -#include "mail-storage-service.h" - -#include <stdio.h> -#include <stdlib.h> - -static struct mail_user *mail_user; -static int killed_signo = 0; - -static void ATTR_NORETURN -usage(void) -{ - i_fatal( -"usage: doveadm \n" -" purge <user>\n" -" force-resync <user> <mailbox>\n" -); -} - -static void sig_die(const siginfo_t *si, void *context ATTR_UNUSED) -{ - killed_signo = si->si_signo; -} - -static void cmd_purge(struct mail_user *user) -{ - struct mail_namespace *ns; - - for (ns = user->namespaces; ns != NULL; ns = ns->next) { - if (ns->type != NAMESPACE_PRIVATE || ns->alias_for != NULL) - continue; - - if (mail_storage_purge(ns->storage) < 0) { - i_error("Purging namespace '%s' failed: %s", ns->prefix, - mail_storage_get_last_error(ns->storage, NULL)); - } - } -} - -static struct mailbox * -mailbox_find_and_open(struct mail_user *user, const char *mailbox) -{ - struct mail_namespace *ns; - struct mailbox *box; - const char *orig_mailbox = mailbox; - - ns = mail_namespace_find(user->namespaces, &mailbox); - if (ns == NULL) - i_fatal("Can't find namespace for mailbox %s", mailbox); - - box = mailbox_alloc(ns->list, mailbox, NULL, MAILBOX_FLAG_KEEP_RECENT | - MAILBOX_FLAG_IGNORE_ACLS); - if (mailbox_open(box) < 0) { - i_fatal("Opening mailbox %s failed: %s", orig_mailbox, - mail_storage_get_last_error(mailbox_get_storage(box), - NULL)); - } - return box; -} - -static void cmd_force_resync(struct mail_user *user, const char *mailbox) -{ - struct mail_storage *storage; - struct mailbox *box; - - if (mailbox == NULL) - usage(); - - box = mailbox_find_and_open(user, mailbox); - storage = mailbox_get_storage(box); - if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FORCE_RESYNC | - MAILBOX_SYNC_FLAG_FIX_INCONSISTENT, 0, NULL) < 0) { - i_fatal("Forcing a resync on mailbox %s failed: %s", mailbox, - mail_storage_get_last_error(storage, NULL)); - } - mailbox_close(&box); -} - -static void handle_command(struct mail_user *mail_user, const char *cmd, - char *args[]) -{ - if (strcmp(cmd, "purge") == 0) - cmd_purge(mail_user); - else if (strcmp(cmd, "force-resync") == 0) - cmd_force_resync(mail_user, args[0]); - else - usage(); -} - -static void -handle_single_user(struct master_service *service, const char *username, - enum mail_storage_service_flags service_flags, char *argv[]) -{ - struct mail_storage_service_input input; - - if (username == NULL) - i_fatal("USER environment is missing and -u option not used"); - - memset(&input, 0, sizeof(input)); - input.username = username; - mail_user = mail_storage_service_init_user(service, &input, NULL, - service_flags); - handle_command(mail_user, argv[0], argv+1); - mail_user_unref(&mail_user); - mail_storage_service_deinit_user(); -} - -static int -handle_next_user(struct mail_storage_service_multi_ctx *multi, - const struct mail_storage_service_input *input, - pool_t pool, char *argv[]) -{ - struct mail_storage_service_multi_user *multi_user; - const char *error; - int ret; - - i_set_failure_prefix(t_strdup_printf("doveadm(%s): ", input->username)); - ret = mail_storage_service_multi_lookup(multi, input, pool, - &multi_user, &error); - if (ret <= 0) { - if (ret == 0) { - i_info("User no longer exists, skipping"); - return 0; - } else { - i_error("User lookup failed: %s", error); - return -1; - } - } - if (mail_storage_service_multi_next(multi, multi_user, - &mail_user, &error) < 0) { - i_error("User init failed: %s", error); - mail_storage_service_multi_user_free(multi_user); - return -1; - } - mail_storage_service_multi_user_free(multi_user); - handle_command(mail_user, argv[0], argv+1); - mail_user_unref(&mail_user); - return 0; -} - -static void -handle_all_users(struct master_service *service, - enum mail_storage_service_flags service_flags, char *argv[]) -{ - struct mail_storage_service_input input; - struct mail_storage_service_multi_ctx *multi; - unsigned int user_idx, user_count, interval, n; - const char *user; - pool_t pool; - int ret; - - service_flags |= MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP; - - memset(&input, 0, sizeof(input)); - input.service = "doveadm"; - - multi = mail_storage_service_multi_init(service, NULL, service_flags); - pool = pool_alloconly_create("multi user", 8192); - - lib_signals_set_handler(SIGINT, FALSE, sig_die, NULL); - lib_signals_set_handler(SIGTERM, FALSE, sig_die, NULL); - - user_count = mail_storage_service_multi_all_init(multi); - n = user_count / 10000; - for (interval = 10; n > 0 && interval < 1000; interval *= 10) - n /= 10; - - user_idx = 0; - while ((ret = mail_storage_service_multi_all_next(multi, &user)) > 0) { - p_clear(pool); - input.username = user; - T_BEGIN { - ret = handle_next_user(multi, &input, pool, argv); - } T_END; - if (ret < 0) - break; - if ((service_flags & MAIL_STORAGE_SERVICE_FLAG_DEBUG) != 0) { - if (++user_idx % interval == 0) { - printf("\r%d / %d", user_idx, user_count); - fflush(stdout); - } - } - if (killed_signo != 0) { - i_warning("Killed with signal %d", killed_signo); - ret = -1; - break; - } - } - if ((service_flags & MAIL_STORAGE_SERVICE_FLAG_DEBUG) != 0) - printf("\n"); - i_set_failure_prefix("doveadm: "); - if (ret < 0) - i_error("Failed to iterate through some users"); - mail_storage_service_multi_deinit(&multi); - pool_unref(&pool); -} - -int main(int argc, char *argv[]) -{ - enum mail_storage_service_flags service_flags = 0; - const char *getopt_str, *username; - bool all_users = FALSE; - int c; - - master_service = master_service_init("doveadm", - MASTER_SERVICE_FLAG_STANDALONE, - argc, argv); - - username = getenv("USER"); - getopt_str = t_strconcat("au:v", master_service_getopt_string(), NULL); - while ((c = getopt(argc, argv, getopt_str)) > 0) { - switch (c) { - case 'a': - all_users = TRUE; - break; - case 'u': - username = optarg; - service_flags |= MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP; - break; - case 'v': - service_flags |= MAIL_STORAGE_SERVICE_FLAG_DEBUG; - break; - default: - if (!master_service_parse_option(master_service, - c, optarg)) - usage(); - } - } - if (optind == argc) - usage(); - - if (!all_users) { - handle_single_user(master_service, username, service_flags, - argv + optind); - } else { - handle_all_users(master_service, service_flags, argv + optind); - } - master_service_deinit(&master_service); - return 0; -}