static int
cmd_sieve_activate_run(struct doveadm_sieve_cmd_context *_ctx)
{
	struct doveadm_sieve_activate_cmd_context *ctx =
		(struct doveadm_sieve_activate_cmd_context *)_ctx;
	struct sieve_storage *storage = _ctx->storage;
	struct sieve_script *script;
	enum sieve_error error;
	int ret = 0;

	script = sieve_storage_open_script
		(storage, ctx->scriptname, NULL);
	if ( script == NULL ) {
		i_error("Failed to activate Sieve script: %s",
			sieve_storage_get_last_error(storage, &error));
		doveadm_sieve_cmd_failed_error(_ctx, error);
		return -1;
	}

	if ( sieve_script_is_active(script) <= 0 ) {
		/* Script is first being activated; compile it again without the UPLOAD
		 * flag.
		 */
		struct sieve_error_handler *ehandler;
		enum sieve_compile_flags cpflags =
			SIEVE_COMPILE_FLAG_NOGLOBAL | SIEVE_COMPILE_FLAG_ACTIVATED;
		struct sieve_binary *sbin;
		enum sieve_error error;

		/* Compile */
		ehandler = sieve_master_ehandler_create(ctx->ctx.svinst, NULL, 0);
		if ( (sbin=sieve_compile_script
			(script, ehandler, cpflags, &error)) == NULL ) {
			doveadm_sieve_cmd_failed_error(_ctx, error);
			ret = -1;
		} else {
			sieve_close(&sbin);
		}
		sieve_error_handler_unref(&ehandler);
	}

	/* Activate only when script is valid (or already active) */
	if ( ret == 0 ) {
		/* Refresh activation no matter what; this can also resolve some erroneous
		 * situations.
		 */
		ret = sieve_script_activate(script, (time_t)-1);
		if ( ret < 0 ) {
			i_error("Failed to activate Sieve script: %s",
				sieve_storage_get_last_error(storage, &error));
			doveadm_sieve_cmd_failed_error(_ctx, error);
			ret = -1;
		}
	}

	sieve_script_unref(&script);
	return ret;
}
void doveadm_sieve_cmd_failed_storage
(struct doveadm_sieve_cmd_context *ctx,	 struct sieve_storage *storage)
{
	enum sieve_error error;

	(void)sieve_storage_get_last_error(storage, &error);
	doveadm_sieve_cmd_failed_error(ctx, error);
}
static int cmd_sieve_deactivate_run
(struct doveadm_sieve_cmd_context *_ctx)
{
	struct sieve_storage *storage = _ctx->storage;
	enum sieve_error error;

	if (sieve_storage_deactivate(storage, (time_t)-1) < 0) {
		i_error("Failed to deactivate Sieve script: %s",
			sieve_storage_get_last_error(storage, &error));
		doveadm_sieve_cmd_failed_error(_ctx, error);
		return -1;
	}
	return 0;
}
static int
doveadm_sieve_cmd_run
(struct doveadm_mail_cmd_context *_ctx,
	struct mail_user *user)
{
	struct doveadm_sieve_cmd_context *ctx =
		(struct doveadm_sieve_cmd_context *)_ctx;
	struct sieve_environment svenv;
	enum sieve_error error;
	int ret;

	memset((void*)&svenv, 0, sizeof(svenv));
	svenv.username = user->username;
	(void)mail_user_get_home(user, &svenv.home_dir);
	svenv.base_dir = user->set->base_dir;
	svenv.flags = SIEVE_FLAG_HOME_RELATIVE;

	ctx->svinst = sieve_init
		(&svenv, &sieve_callbacks, (void *)ctx, user->mail_debug);

	ctx->storage = sieve_storage_create_main
		(ctx->svinst, user, SIEVE_STORAGE_FLAG_READWRITE, &error);
	if ( ctx->storage == NULL ) {
		switch ( error ) {
		case SIEVE_ERROR_NOT_FOUND:
			i_error("Failed to open Sieve storage: Sieve disabled for user");
			break;
		default:
			i_error("Failed to open Sieve storage.");
		}
		doveadm_sieve_cmd_failed_error(ctx, error);
		ret =  -1;

	} else {
		i_assert( ctx->v.run != NULL );
		ret = ctx->v.run(ctx);
		sieve_storage_unref(&ctx->storage);
	}

	sieve_deinit(&ctx->svinst);
	return ret;
}
static int
cmd_sieve_get_run(struct doveadm_sieve_cmd_context *_ctx)
{
	struct doveadm_sieve_get_cmd_context *ctx =
		(struct doveadm_sieve_get_cmd_context *)_ctx;
	struct sieve_script *script;
	struct istream *input;
	enum sieve_error error;

	script = sieve_storage_open_script
		(_ctx->storage, ctx->scriptname, &error);
	if ( script == NULL || sieve_script_get_stream
		(script, &input, &error) < 0 ) {
		i_error("Failed to open Sieve script: %s",
			sieve_storage_get_last_error(_ctx->storage, &error));
		doveadm_sieve_cmd_failed_error(_ctx, error);
		if (script != NULL)
			sieve_script_unref(&script);
		return -1;
	}

	return doveadm_print_istream(input);
}
static int
cmd_sieve_delete_run(struct doveadm_sieve_cmd_context *_ctx)
{
	struct doveadm_sieve_delete_cmd_context *ctx =
		(struct doveadm_sieve_delete_cmd_context *)_ctx;
	struct sieve_storage *storage = _ctx->storage;
	const ARRAY_TYPE(const_string) *scriptnames = &ctx->scriptnames;
	const char *const *namep;
	struct sieve_script *script;
	enum sieve_error error;
	int ret = 0;

	array_foreach(scriptnames, namep) {
		const char *scriptname = *namep;
		int sret = 0;

		script = sieve_storage_open_script
			(storage, scriptname, NULL);
		if (script == NULL) {
			sret =  -1;
		} else {
			if (sieve_script_delete(script, ctx->ignore_active) < 0) {
				(void)sieve_storage_get_last_error(storage, &error);
				sret = -1;
			}
			sieve_script_unref(&script);
		}
			
		if (sret < 0) {
			i_error("Failed to delete Sieve script: %s",
				sieve_storage_get_last_error(storage, &error));
			doveadm_sieve_cmd_failed_error(_ctx, error);
			ret = -1;
		}
	}
	return ret;
}