static int doveadm_cmd_handle(struct client_connection *conn, const char *cmd_name, const struct mail_storage_service_input *input, int argc, char *argv[]) { struct ioloop *ioloop, *prev_ioloop = current_ioloop; const struct doveadm_cmd *cmd; const struct doveadm_mail_cmd *mail_cmd; struct doveadm_mail_cmd_context *ctx; cmd = doveadm_cmd_find(cmd_name, &argc, &argv); if (cmd == NULL) { mail_cmd = doveadm_mail_cmd_find(cmd_name); if (mail_cmd == NULL) { i_error("doveadm: Client sent unknown command: %s", cmd_name); return -1; } if (doveadm_mail_cmd_server_parse(mail_cmd, conn->set, input, argc, argv, &ctx) < 0) return -1; } /* some commands will want to call io_loop_run(), but we're already running one and we can't call the original one recursively, so create a new ioloop. */ ioloop = io_loop_create(); lib_signals_reset_ioloop(); if (cmd != NULL) doveadm_cmd_server_run(conn, cmd, argc, argv); else doveadm_mail_cmd_server_run(conn, ctx, input); io_loop_set_current(prev_ioloop); lib_signals_reset_ioloop(); o_stream_switch_ioloop(conn->output); io_loop_set_current(ioloop); io_loop_destroy(&ioloop); /* clear all headers */ doveadm_print_deinit(); doveadm_print_init(DOVEADM_PRINT_TYPE_SERVER); return 0; }
static bool client_handle_command(struct client_connection *conn, char **args) { struct mail_storage_service_input input; struct doveadm_mail_cmd_context *ctx; const char *flags, *cmd_name; unsigned int argc; memset(&input, 0, sizeof(input)); input.service = "doveadm"; for (argc = 0; args[argc] != NULL; argc++) args[argc] = str_tabunescape(args[argc]); if (argc < 3) { i_error("doveadm client: No command given"); return FALSE; } flags = args[0]; input.username = args[1]; cmd_name = args[2]; /* leave the command name as args[0] so getopt() works */ args += 2; argc -= 2; doveadm_debug = FALSE; doveadm_verbose = FALSE; for (; *flags != '\0'; flags++) { switch (*flags) { case 'D': doveadm_debug = TRUE; doveadm_verbose = TRUE; break; case 'v': doveadm_verbose = TRUE; break; default: i_error("doveadm client: Unknown flag: %c", *flags); return FALSE; } } if (!client_is_allowed_command(conn->set, cmd_name)) { i_error("doveadm client isn't allowed to use command: %s", cmd_name); return FALSE; } /* make sure client_connection_input() isn't called by the ioloop that is going to be run by doveadm_mail_cmd_server_run() */ io_remove(&conn->io); o_stream_cork(conn->output); ctx = doveadm_mail_cmd_server_parse(cmd_name, conn->set, &input, argc, args); if (ctx == NULL) o_stream_nsend(conn->output, "\n-\n", 3); else doveadm_mail_cmd_server_run(conn, ctx, &input); o_stream_uncork(conn->output); /* flush the output and disconnect */ net_set_nonblock(conn->fd, FALSE); (void)o_stream_flush(conn->output); net_set_nonblock(conn->fd, TRUE); conn->io = io_add(conn->fd, IO_READ, client_connection_input, conn); return TRUE; }