diff --git a/src/doveadm/doveadm-cmd.c b/src/doveadm/doveadm-cmd.c index 9ec9234a23..26901e209a 100644 --- a/src/doveadm/doveadm-cmd.c +++ b/src/doveadm/doveadm-cmd.c @@ -13,7 +13,6 @@ #include static struct doveadm_cmd *doveadm_commands[] = { - &doveadm_cmd_kick, &doveadm_cmd_mailbox_mutf7, &doveadm_cmd_sis_deduplicate, &doveadm_cmd_sis_find, @@ -25,6 +24,7 @@ static struct doveadm_cmd_ver2 *doveadm_commands_ver2[] = { &doveadm_cmd_stats_dump_ver2, &doveadm_cmd_stats_reset_ver2, &doveadm_cmd_penalty_ver2, + &doveadm_cmd_kick_ver2, &doveadm_cmd_who_ver2 }; diff --git a/src/doveadm/doveadm-cmd.h b/src/doveadm/doveadm-cmd.h index 7a79616701..58e91a3931 100644 --- a/src/doveadm/doveadm-cmd.h +++ b/src/doveadm/doveadm-cmd.h @@ -88,7 +88,6 @@ extern ARRAY_TYPE(doveadm_cmd_ver2) doveadm_cmds_ver2; extern struct doveadm_cmd doveadm_cmd_dump; extern struct doveadm_cmd doveadm_cmd_pw; -extern struct doveadm_cmd doveadm_cmd_kick; extern struct doveadm_cmd doveadm_cmd_mailbox_mutf7; extern struct doveadm_cmd doveadm_cmd_sis_deduplicate; extern struct doveadm_cmd doveadm_cmd_sis_find; @@ -148,6 +147,7 @@ extern struct doveadm_cmd_ver2 doveadm_cmd_stats_reset_ver2; extern struct doveadm_cmd_ver2 doveadm_cmd_stats_dump_ver2; extern struct doveadm_cmd_ver2 doveadm_cmd_stats_top_ver2; extern struct doveadm_cmd_ver2 doveadm_cmd_penalty_ver2; +extern struct doveadm_cmd_ver2 doveadm_cmd_kick_ver2; extern struct doveadm_cmd_ver2 doveadm_cmd_who_ver2; #endif diff --git a/src/doveadm/doveadm-kick.c b/src/doveadm/doveadm-kick.c index 29621eb3b6..5698c37cca 100644 --- a/src/doveadm/doveadm-kick.c +++ b/src/doveadm/doveadm-kick.c @@ -28,6 +28,7 @@ struct kick_pid { struct kick_context { struct who_context who; HASH_TABLE(void *, struct kick_pid *) pids; + bool cli; bool force_kick; ARRAY(const char *) kicked_users; }; @@ -102,16 +103,20 @@ kick_print_kicked(struct kick_context *ctx, const bool show_warning) const char *const *users; if (array_count(&ctx->kicked_users) == 0) { - printf("no users kicked\n"); + if (ctx->cli) + printf("no users kicked\n"); doveadm_exit_code = DOVEADM_EX_NOTFOUND; return; } - if (show_warning) { - printf("warning: other connections would also be " - "kicked from following users:\n"); - } else - printf("kicked connections from the following users:\n"); + if (ctx->cli) { + if (show_warning) { + printf("warning: other connections would also be " + "kicked from following users:\n"); + } else { + printf("kicked connections from the following users:\n"); + } + } array_sort(&ctx->kicked_users, i_strcmp_p); users = array_get(&ctx->kicked_users, &count); @@ -120,7 +125,8 @@ kick_print_kicked(struct kick_context *ctx, const bool show_warning) if (strcmp(users[i-1], users[i]) != 0) doveadm_print(users[i]); } - printf("\n"); + if (ctx->cli) + printf("\n"); if (show_warning) printf("Use the '-f' option to enforce the disconnect.\n"); @@ -168,37 +174,39 @@ static void kick_users(struct kick_context *ctx) kick_print_kicked(ctx, show_enforce_warning); } -static void cmd_kick(int argc, char *argv[]) +static void cmd_kick(struct doveadm_cmd_context *cctx) { + const char *const *masks; struct kick_context ctx; - int c; memset(&ctx, 0, sizeof(ctx)); - ctx.who.anvil_path = t_strconcat(doveadm_settings->base_dir, "/anvil", NULL); - ctx.force_kick = FALSE; + if (!doveadm_cmd_param_str(cctx, "socket-path", &(ctx.who.anvil_path))) + ctx.who.anvil_path = t_strconcat(doveadm_settings->base_dir, "/anvil", NULL); + (void)doveadm_cmd_param_bool(cctx, "force", &(ctx.force_kick)); + if (!doveadm_cmd_param_array(cctx, "mask", &masks)) { + doveadm_exit_code = EX_USAGE; + i_error("user and/or ip[/bits] must be specified."); + return; + } + ctx.cli = cctx->cli; + if (!ctx.cli) { + /* force-kick is a pretty ugly option. its output can't be + nicely translated to an API reply. it also wouldn't be very + useful in scripts, only for preventing a new admin from + accidentally kicking too many users. it's also useful only + in a non-recommended setup where processes are handling + multiple connections. so for now we'll preserve the option + for CLI, but always do a force-kick with non-CLI. */ + ctx.force_kick = TRUE; + } ctx.who.pool = pool_alloconly_create("kick pids", 10240); hash_table_create_direct(&ctx.pids, ctx.who.pool, 0); - while ((c = getopt(argc, argv, "a:f")) > 0) { - switch (c) { - case 'a': - ctx.who.anvil_path = optarg; - break; - case 'f': - ctx.force_kick = TRUE; - break; - default: - help(&doveadm_cmd_kick); - } - } - - argv += optind - 1; - if (argv[1] == NULL) { - i_fatal_status(EX_USAGE, - "user and/or ip[/bits] must be specified."); + if (who_parse_args(&ctx.who, masks)!=0) { + hash_table_destroy(&ctx.pids); + pool_unref(&ctx.who.pool); + return; } - if (who_parse_args(&ctx.who, (const char *const *)argv + 1) < 0) - help(&doveadm_cmd_kick); doveadm_print_init(DOVEADM_PRINT_TYPE_FORMATTED); doveadm_print_formatted_set_format("%{result} "); @@ -211,7 +219,13 @@ static void cmd_kick(int argc, char *argv[]) pool_unref(&ctx.who.pool); } -struct doveadm_cmd doveadm_cmd_kick = { - cmd_kick, "kick", - "[-a ] [-f] [|]" +struct doveadm_cmd_ver2 doveadm_cmd_kick_ver2 = { + .name = "kick", + .cmd = cmd_kick, + .usage = "[-a ] [|]", +DOVEADM_CMD_PARAMS_START +DOVEADM_CMD_PARAM('a',"socket-path",CMD_PARAM_STR,0) +DOVEADM_CMD_PARAM('f',"force",CMD_PARAM_BOOL,0) +DOVEADM_CMD_PARAM('\0',"mask",CMD_PARAM_ARRAY,CMD_PARAM_FLAG_POSITIONAL) +DOVEADM_CMD_PARAMS_END };