doveadm-instance.c revision 6ea1de17b3d415f6ff2e6a2af8d34d8f6cf17636
e2586f58230ac2938db5ee91191108988b206e2fEugen Kuksa/* Copyright (c) 2012 Dovecot authors, see the included COPYING file */
e2586f58230ac2938db5ee91191108988b206e2fEugen Kuksa
d6cf50ae9519bdb5252081061b3d6a7e0ccde20bEugen Kuksa#include "lib.h"
d6cf50ae9519bdb5252081061b3d6a7e0ccde20bEugen Kuksa#include "master-instance.h"
e2586f58230ac2938db5ee91191108988b206e2fEugen Kuksa#include "doveadm.h"
e2586f58230ac2938db5ee91191108988b206e2fEugen Kuksa#include "doveadm-print.h"
d6cf50ae9519bdb5252081061b3d6a7e0ccde20bEugen Kuksa
d6cf50ae9519bdb5252081061b3d6a7e0ccde20bEugen Kuksa#include <stdio.h>
a446fc1729ca15222cd35f657ebe75152ac5a39cEugen Kuksa#include <unistd.h>
a446fc1729ca15222cd35f657ebe75152ac5a39cEugen Kuksa#include <fcntl.h>
a446fc1729ca15222cd35f657ebe75152ac5a39cEugen Kuksa#include <signal.h>
a446fc1729ca15222cd35f657ebe75152ac5a39cEugen Kuksa
a446fc1729ca15222cd35f657ebe75152ac5a39cEugen Kuksaextern struct doveadm_cmd doveadm_cmd_instance[];
a446fc1729ca15222cd35f657ebe75152ac5a39cEugen Kuksa
a446fc1729ca15222cd35f657ebe75152ac5a39cEugen Kuksastatic void instance_cmd_help(doveadm_command_t *cmd) ATTR_NORETURN;
a446fc1729ca15222cd35f657ebe75152ac5a39cEugen Kuksa
a446fc1729ca15222cd35f657ebe75152ac5a39cEugen Kuksastatic bool pid_file_read(const char *path)
a446fc1729ca15222cd35f657ebe75152ac5a39cEugen Kuksa{
a446fc1729ca15222cd35f657ebe75152ac5a39cEugen Kuksa char buf[32];
a446fc1729ca15222cd35f657ebe75152ac5a39cEugen Kuksa int fd;
a446fc1729ca15222cd35f657ebe75152ac5a39cEugen Kuksa ssize_t ret;
a446fc1729ca15222cd35f657ebe75152ac5a39cEugen Kuksa pid_t pid;
a446fc1729ca15222cd35f657ebe75152ac5a39cEugen Kuksa bool found = FALSE;
a446fc1729ca15222cd35f657ebe75152ac5a39cEugen Kuksa
d6cf50ae9519bdb5252081061b3d6a7e0ccde20bEugen Kuksa fd = open(path, O_RDONLY);
d6cf50ae9519bdb5252081061b3d6a7e0ccde20bEugen Kuksa if (fd == -1) {
d6cf50ae9519bdb5252081061b3d6a7e0ccde20bEugen Kuksa if (errno != ENOENT)
d6cf50ae9519bdb5252081061b3d6a7e0ccde20bEugen Kuksa i_error("open(%s) failed: %m", path);
b941d9b3af35eaf1562109312ce79aad8e2f783bEugen Kuksa return FALSE;
d6cf50ae9519bdb5252081061b3d6a7e0ccde20bEugen Kuksa }
cb1256dca3f095718f35c41530a136823dac0774Eugen Kuksa
cb1256dca3f095718f35c41530a136823dac0774Eugen Kuksa ret = read(fd, buf, sizeof(buf));
cb1256dca3f095718f35c41530a136823dac0774Eugen Kuksa if (ret < 0)
cb1256dca3f095718f35c41530a136823dac0774Eugen Kuksa i_error("read(%s) failed: %m", path);
de6c495f32f4fe2341971527e5fc1ccb9a21ed2fEugen Kuksa else if (ret > 0 && buf[ret-1] == '\n') {
cb1256dca3f095718f35c41530a136823dac0774Eugen Kuksa buf[ret-1] = '\0';
d6cf50ae9519bdb5252081061b3d6a7e0ccde20bEugen Kuksa if (str_to_pid(buf, &pid) == 0) {
d6cf50ae9519bdb5252081061b3d6a7e0ccde20bEugen Kuksa found = !(pid == getpid() ||
d6cf50ae9519bdb5252081061b3d6a7e0ccde20bEugen Kuksa (kill(pid, 0) < 0 && errno == ESRCH));
d6cf50ae9519bdb5252081061b3d6a7e0ccde20bEugen Kuksa }
13fc9a105393bc799a26cdba6f7e759435e3ec23Eugen Kuksa }
13fc9a105393bc799a26cdba6f7e759435e3ec23Eugen Kuksa (void)close(fd);
13fc9a105393bc799a26cdba6f7e759435e3ec23Eugen Kuksa return found;
13fc9a105393bc799a26cdba6f7e759435e3ec23Eugen Kuksa}
static void cmd_instance_list(int argc, char *argv[])
{
struct master_instance_list *list;
struct master_instance_list_iter *iter;
const struct master_instance *inst;
const char *pidfile_path;
bool show_config = FALSE;
int c;
while ((c = getopt(argc, argv, "c")) > 0) {
switch (c) {
case 'c':
show_config = TRUE;
break;
default:
help(&doveadm_cmd_instance[0]);
}
}
argv += optind;
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");
}
list = master_instance_list_init(MASTER_INSTANCE_PATH);
iter = master_instance_list_iterate_init(list);
while ((inst = master_instance_iterate_list_next(iter)) != NULL) {
if (argv[0] != NULL && strcmp(argv[0], 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(int argc, char *argv[])
{
struct master_instance_list *list;
const struct master_instance *inst;
const char *base_dir;
int ret;
if (argc != 2)
instance_cmd_help(cmd_instance_remove);
list = master_instance_list_init(MASTER_INSTANCE_PATH);
inst = master_instance_list_find_by_name(list, argv[1]);
base_dir = inst != NULL ? inst->base_dir : argv[1];
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 doveadm_cmd_instance[] = {
{ cmd_instance_list, "instance list", "[-c] [<name>]" },
{ cmd_instance_remove, "instance remove", "<name> | <base dir>" }
};
static void instance_cmd_help(doveadm_command_t *cmd)
{
unsigned int i;
for (i = 0; i < N_ELEMENTS(doveadm_cmd_instance); i++) {
if (doveadm_cmd_instance[i].cmd == cmd)
help(&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_register_cmd(&doveadm_cmd_instance[i]);
}