Mercurial > dovecot > core-2.2
view src/util/doveadm.c @ 9869:464c01ae9f0c HEAD
lmtp, expire-tool, doveadm: Set service for config lookups.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Fri, 04 Sep 2009 14:30:29 -0400 |
parents | 653183a81b6c |
children |
line wrap: on
line source
/* 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; }