summaryrefslogtreecommitdiffstats
path: root/src/doveadm/doveadm-instance.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/doveadm/doveadm-instance.c')
-rw-r--r--src/doveadm/doveadm-instance.c155
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]);
+}