struct sieve_extprograms_config *sieve_extprograms_config_init
(const struct sieve_extension *ext)
{
	struct sieve_instance *svinst = ext->svinst;
	struct sieve_extprograms_config *ext_config;
	const char *extname = sieve_extension_name(ext);
	const char *bin_dir, *socket_dir, *input_eol;
	sieve_number_t execute_timeout;

	extname = strrchr(extname, '.');
	i_assert(extname != NULL);
	extname++;

	bin_dir = sieve_setting_get
		(svinst, t_strdup_printf("sieve_%s_bin_dir", extname));
	socket_dir = sieve_setting_get
		(svinst, t_strdup_printf("sieve_%s_socket_dir", extname));
	input_eol = sieve_setting_get
		(svinst, t_strdup_printf("sieve_%s_input_eol", extname));
	
	ext_config = i_new(struct sieve_extprograms_config, 1);
	ext_config->execute_timeout = 
		SIEVE_EXTPROGRAMS_DEFAULT_EXEC_TIMEOUT_SECS;

	if ( bin_dir == NULL && socket_dir == NULL ) {
		if ( svinst->debug ) {
			sieve_sys_debug(svinst, "%s extension: "
				"no bin or socket directory specified; extension is unconfigured "
				"(both sieve_%s_bin_dir and sieve_%s_socket_dir are not set)",
				sieve_extension_name(ext), extname, extname);
		}
	} else {
		ext_config->bin_dir = i_strdup(bin_dir);
		ext_config->socket_dir = i_strdup(socket_dir);

		if (sieve_setting_get_duration_value
			(svinst, t_strdup_printf("sieve_%s_exec_timeout", extname),
				&execute_timeout)) {
			ext_config->execute_timeout = execute_timeout;
		}

		ext_config->default_input_eol = SIEVE_EXTPROGRAMS_EOL_CRLF;
		if (input_eol != NULL && strcasecmp(input_eol, "lf") == 0)
			ext_config->default_input_eol = SIEVE_EXTPROGRAMS_EOL_LF;
	}

	if ( sieve_extension_is(ext, vnd_pipe_extension) ) 
		ext_config->copy_ext = sieve_ext_copy_get_extension(ext->svinst);
	if ( sieve_extension_is(ext, vnd_execute_extension) ) 
		ext_config->var_ext = sieve_ext_variables_get_extension(ext->svinst);
	return ext_config;
}
bool ext_vacation_load
(const struct sieve_extension *ext, void **context)
{
	struct sieve_instance *svinst = ext->svinst;
	struct ext_vacation_config *config;
	sieve_number_t min_period, max_period, default_period;
	bool use_original_recipient, dont_check_recipient, send_from_recipient;

	if ( *context != NULL ) {
		ext_vacation_unload(ext);
	}

	if ( !sieve_setting_get_duration_value
		(svinst, "sieve_vacation_min_period", &min_period) ) {
		min_period = EXT_VACATION_DEFAULT_MIN_PERIOD;
	}

	if ( !sieve_setting_get_duration_value
		(svinst, "sieve_vacation_max_period", &max_period) ) {
		max_period = EXT_VACATION_DEFAULT_MAX_PERIOD;
	}

	if ( !sieve_setting_get_duration_value
		(svinst, "sieve_vacation_default_period", &default_period) ) {
		default_period = EXT_VACATION_DEFAULT_PERIOD;
	}

	if ( max_period > 0
		&& (min_period > max_period || default_period < min_period
			|| default_period > max_period) ) {
		min_period = EXT_VACATION_DEFAULT_MIN_PERIOD;
		max_period = EXT_VACATION_DEFAULT_MAX_PERIOD;
		default_period = EXT_VACATION_DEFAULT_PERIOD;

		sieve_sys_warning(svinst,
			"vacation extension: invalid settings: violated "
			"sieve_vacation_min_period < sieve_vacation_default_period < "
			"sieve_vacation_max_period");
	}

	if ( !sieve_setting_get_bool_value
		(svinst, "sieve_vacation_use_original_recipient", &use_original_recipient) ) {
		use_original_recipient = FALSE;
	}

	if ( !sieve_setting_get_bool_value
		(svinst, "sieve_vacation_dont_check_recipient", &dont_check_recipient) ) {
		dont_check_recipient = FALSE;
	}

	if ( !sieve_setting_get_bool_value
		(svinst, "sieve_vacation_send_from_recipient", &send_from_recipient) ) {
		send_from_recipient = FALSE;
	}

	config = i_new(struct ext_vacation_config, 1);
	config->min_period = min_period;
	config->max_period = max_period;
	config->default_period = default_period;
	config->use_original_recipient = use_original_recipient;
	config->dont_check_recipient = dont_check_recipient;
	config->send_from_recipient = send_from_recipient;

	*context = (void *) config;

	return TRUE;
}