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; }
static int _read_extensions(struct sieve_binary_block *sblock) { struct sieve_binary *sbin = sblock->sbin; sieve_size_t offset = 0; unsigned int i, count; bool result = 1; if ( !sieve_binary_read_unsigned(sblock, &offset, &count) ) return -1; for ( i = 0; result > 0 && i < count; i++ ) { T_BEGIN { string_t *extension; const struct sieve_extension *ext; unsigned int version; if ( sieve_binary_read_string(sblock, &offset, &extension) ) { ext = sieve_extension_get_by_name(sbin->svinst, str_c(extension)); if ( ext == NULL ) { sieve_sys_error(sbin->svinst, "binary open: binary %s requires unknown extension `%s'", sbin->path, str_sanitize(str_c(extension), 128)); result = 0; } else { struct sieve_binary_extension_reg *ereg = NULL; (void) sieve_binary_extension_register(sbin, ext, &ereg); if ( !sieve_binary_read_unsigned(sblock, &offset, &version) || !sieve_binary_read_unsigned(sblock, &offset, &ereg->block_id) ) { result = -1; } else if ( !sieve_extension_version_is(ext, version) ) { sieve_sys_debug(sbin->svinst, "binary open: binary %s was compiled with different version " "of the `%s' extension (compiled v%d, expected v%d;" "automatically fixed when re-compiled)", sbin->path, sieve_extension_name(ext), version, sieve_extension_version(ext)); result = 0; } } } else result = -1; } T_END; } return result; }
static bool _sieve_binary_save (struct sieve_binary *sbin, struct ostream *stream) { struct sieve_binary_header header; struct sieve_binary_extension_reg *const *regs; struct sieve_binary_block *ext_block; unsigned int ext_count, blk_count, i; uoff_t block_index; blk_count = sieve_binary_block_count(sbin); /* Signal all extensions to finish generating their blocks */ regs = array_get(&sbin->extensions, &ext_count); for ( i = 0; i < ext_count; i++ ) { const struct sieve_binary_extension *binext = regs[i]->binext; if ( binext != NULL && binext->binary_save != NULL ) binext->binary_save(regs[i]->extension, sbin, regs[i]->context); } /* Create header */ header.magic = SIEVE_BINARY_MAGIC; header.version_major = SIEVE_BINARY_VERSION_MAJOR; header.version_minor = SIEVE_BINARY_VERSION_MINOR; header.blocks = blk_count; if ( !_save_aligned(sbin, stream, &header, sizeof(header), NULL) ) { sieve_sys_error(sbin->svinst, "binary save: failed to save header"); return FALSE; } /* Skip block index for now */ if ( !_save_skip_aligned(sbin, stream, sizeof(struct sieve_binary_block_index) * blk_count, &block_index) ) return FALSE; /* Create block containing all used extensions */ ext_block = sieve_binary_block_get(sbin, SBIN_SYSBLOCK_EXTENSIONS); i_assert( ext_block != NULL ); sieve_binary_block_clear(ext_block); ext_count = array_count(&sbin->linked_extensions); sieve_binary_emit_unsigned(ext_block, ext_count); for ( i = 0; i < ext_count; i++ ) { struct sieve_binary_extension_reg * const *ext = array_idx(&sbin->linked_extensions, i); sieve_binary_emit_cstring (ext_block, sieve_extension_name((*ext)->extension)); sieve_binary_emit_unsigned (ext_block, sieve_extension_version((*ext)->extension)); sieve_binary_emit_unsigned(ext_block, (*ext)->block_id); } /* Save all blocks into the binary */ for ( i = 0; i < blk_count; i++ ) { if ( !_save_block(sbin, stream, i) ) return FALSE; } /* Create the block index */ o_stream_seek(stream, block_index); for ( i = 0; i < blk_count; i++ ) { if ( !_save_block_index_record(sbin, stream, i) ) return FALSE; } return TRUE; }