diff options
Diffstat (limited to 'src/doveadm/doveadm-instance.c')
-rw-r--r-- | src/doveadm/doveadm-instance.c | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/src/doveadm/doveadm-instance.c b/src/doveadm/doveadm-instance.c new file mode 100644 index 0000000..cd3d55e --- /dev/null +++ b/src/doveadm/doveadm-instance.c @@ -0,0 +1,155 @@ +/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "master-instance.h" +#include "master-service-settings.h" +#include "doveadm.h" +#include "doveadm-print.h" + +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include <signal.h> + +extern struct doveadm_cmd_ver2 doveadm_cmd_instance[]; + +static void instance_cmd_help(const struct doveadm_cmd_ver2 *cmd) ATTR_NORETURN; + +static bool pid_file_read(const char *path) +{ + char buf[32]; + int fd; + ssize_t ret; + pid_t pid; + bool found = FALSE; + + fd = open(path, O_RDONLY); + if (fd == -1) { + if (errno != ENOENT) + i_error("open(%s) failed: %m", path); + return FALSE; + } + + ret = read(fd, buf, sizeof(buf)); + if (ret < 0) + i_error("read(%s) failed: %m", path); + else if (ret > 0 && buf[ret-1] == '\n') { + buf[ret-1] = '\0'; + if (str_to_pid(buf, &pid) == 0) { + found = !(pid == getpid() || + (kill(pid, 0) < 0 && errno == ESRCH)); + } + } + i_close_fd(&fd); + return found; +} + +static void cmd_instance_list(struct doveadm_cmd_context *cctx) +{ + struct master_instance_list *list; + struct master_instance_list_iter *iter; + const struct master_instance *inst; + const char *instance_path, *pidfile_path; + bool show_config = FALSE; + const char *name = NULL; + + (void)doveadm_cmd_param_bool(cctx, "show-config", &show_config); + (void)doveadm_cmd_param_str(cctx, "name", &name); + + if (!show_config) { + doveadm_print_init(DOVEADM_PRINT_TYPE_TABLE); + doveadm_print_header("path", "path", DOVEADM_PRINT_HEADER_FLAG_EXPAND); + doveadm_print_header_simple("name"); + doveadm_print_header_simple("last used"); + doveadm_print_header_simple("running"); + } + + instance_path = t_strconcat(service_set->state_dir, + "/"MASTER_INSTANCE_FNAME, NULL); + list = master_instance_list_init(instance_path); + iter = master_instance_list_iterate_init(list); + while ((inst = master_instance_iterate_list_next(iter)) != NULL) { + if (name != NULL && strcmp(name, inst->name) != 0) + continue; + + if (show_config) { + printf("%s\n", inst->config_path == NULL ? "" : + inst->config_path); + continue; + } + doveadm_print(inst->base_dir); + doveadm_print(inst->name); + doveadm_print(unixdate2str(inst->last_used)); + pidfile_path = t_strconcat(inst->base_dir, "/master.pid", NULL); + if (pid_file_read(pidfile_path)) + doveadm_print("yes"); + else + doveadm_print("no"); + } + master_instance_iterate_list_deinit(&iter); + master_instance_list_deinit(&list); +} + +static void cmd_instance_remove(struct doveadm_cmd_context *cctx) +{ + struct master_instance_list *list; + const struct master_instance *inst; + const char *base_dir, *instance_path, *name; + int ret; + + if (!doveadm_cmd_param_str(cctx, "name", &name)) + instance_cmd_help(cctx->cmd); + + instance_path = t_strconcat(service_set->state_dir, + "/"MASTER_INSTANCE_FNAME, NULL); + list = master_instance_list_init(instance_path); + inst = master_instance_list_find_by_name(list, name); + base_dir = inst != NULL ? inst->base_dir : name; + if ((ret = master_instance_list_remove(list, base_dir)) < 0) { + i_error("Failed to remove instance"); + doveadm_exit_code = EX_TEMPFAIL; + } else if (ret == 0) { + i_error("Instance already didn't exist"); + doveadm_exit_code = DOVEADM_EX_NOTFOUND; + } + master_instance_list_deinit(&list); +} + +struct doveadm_cmd_ver2 doveadm_cmd_instance[] = { +{ + .name = "instance list", + .cmd = cmd_instance_list, + .usage = "[-c] [<name>]", +DOVEADM_CMD_PARAMS_START +DOVEADM_CMD_PARAM('c', "show-config", CMD_PARAM_BOOL, 0) +DOVEADM_CMD_PARAM('\0', "name", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAMS_END +}, +{ + .name = "instance remove", + .cmd = cmd_instance_remove, + .usage = "<name> | <base dir>", +DOVEADM_CMD_PARAMS_START +DOVEADM_CMD_PARAM('\0', "name", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAMS_END +} +}; + +static void instance_cmd_help(const struct doveadm_cmd_ver2 *cmd) +{ + unsigned int i; + + for (i = 0; i < N_ELEMENTS(doveadm_cmd_instance); i++) { + if (doveadm_cmd_instance[i].cmd == cmd->cmd) + help_ver2(&doveadm_cmd_instance[i]); + } + i_unreached(); +} + +void doveadm_register_instance_commands(void) +{ + unsigned int i; + + for (i = 0; i < N_ELEMENTS(doveadm_cmd_instance); i++) + doveadm_cmd_register_ver2(&doveadm_cmd_instance[i]); +} |