diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c index b8c59a86c3e1abb9042abb29df9a29e803a12c43..474b8a2961ba28d50c3af04727e681d0174933f9 100644 --- a/src/lib-sieve/sieve.c +++ b/src/lib-sieve/sieve.c @@ -29,6 +29,7 @@ #include <stdlib.h> #include <unistd.h> #include <stdio.h> +#include <dirent.h> /* * Main Sieve library interface @@ -345,11 +346,15 @@ struct sieve_multiscript { const struct sieve_message_data *msgdata; const struct sieve_script_env *scriptenv; struct sieve_error_handler *ehandler; + int status; bool active; + bool ended; + + struct ostream *teststream; }; -struct sieve_multiscript *sieve_multiscript_start +struct sieve_multiscript *sieve_multiscript_start_execute (const struct sieve_message_data *msgdata, const struct sieve_script_env *senv, struct sieve_error_handler *ehandler) { @@ -373,40 +378,49 @@ struct sieve_multiscript *sieve_multiscript_start return mscript; } -bool sieve_multiscript_test -(struct sieve_multiscript *mscript, struct sieve_binary *sbin, - bool final, struct ostream *stream) -{ - if ( !mscript->active ) return FALSE; +struct sieve_multiscript *sieve_multiscript_start_test +(const struct sieve_message_data *msgdata, const struct sieve_script_env *senv, + struct sieve_error_handler *ehandler, struct ostream *stream) +{ + struct sieve_multiscript *mscript = + sieve_multiscript_start_execute(msgdata, senv, ehandler); - if ( final ) - sieve_result_set_keep_action(mscript->result, &act_store); + mscript->teststream = stream; - /* Run the script */ - mscript->status = sieve_run(sbin, &mscript->result, mscript->msgdata, - mscript->scriptenv, mscript->ehandler); - - /* Print result if successful */ - if ( mscript->status > 0 ) { - bool keep = FALSE; + return mscript; +} + +static void sieve_multiscript_test +(struct sieve_multiscript *mscript) +{ + bool keep = FALSE; + + mscript->status = sieve_result_print + (mscript->result, mscript->scriptenv, mscript->teststream, &keep); + + mscript->active = ( mscript->active && keep ); - mscript->status = sieve_result_print - (mscript->result, mscript->scriptenv, stream, &keep); + sieve_result_mark_executed(mscript->result); +} + +static void sieve_multiscript_execute +(struct sieve_multiscript *mscript) +{ + bool keep = FALSE; - mscript->active = ( mscript->active && keep ); + if ( mscript->status > 0 ) + mscript->status = sieve_result_execute + (mscript->result, mscript->msgdata, mscript->scriptenv, &keep); + else { + if ( !sieve_result_implicit_keep + (mscript->result, mscript->msgdata, mscript->scriptenv) ) + mscript->status = SIEVE_EXEC_KEEP_FAILED; } - if ( mscript->status <= 0 ) { - mscript->active = FALSE; - return FALSE; - } - - sieve_result_mark_executed(mscript->result); - - return mscript->active; + mscript->active = ( mscript->active && keep ); } -bool sieve_multiscript_execute +bool sieve_multiscript_run (struct sieve_multiscript *mscript, struct sieve_binary *sbin, bool final) { @@ -414,43 +428,142 @@ bool sieve_multiscript_execute if ( final ) sieve_result_set_keep_action(mscript->result, &act_store); - + /* Run the script */ mscript->status = sieve_run(sbin, &mscript->result, mscript->msgdata, mscript->scriptenv, mscript->ehandler); - + if ( mscript->status >= 0 ) { - bool keep = FALSE; - - if ( mscript->status > 0 ) - mscript->status = sieve_result_execute - (mscript->result, mscript->msgdata, mscript->scriptenv, &keep); - else { - if ( !sieve_result_implicit_keep - (mscript->result, mscript->msgdata, mscript->scriptenv) ) - mscript->status = SIEVE_EXEC_KEEP_FAILED; - } - - mscript->active = ( mscript->active && keep ); - } + if ( mscript->teststream != NULL ) + sieve_multiscript_test(mscript); + else + sieve_multiscript_execute(mscript); + + if ( final ) mscript->active = FALSE; + } - if ( mscript->status <= 0 ) { - mscript->active = FALSE; + if ( mscript->status <= 0 ) return FALSE; - } - + return mscript->active; } +int sieve_multiscript_status(struct sieve_multiscript *mscript) +{ + return mscript->status; +} + int sieve_multiscript_finish(struct sieve_multiscript **mscript) { struct sieve_result *result = (*mscript)->result; int ret = (*mscript)->status; + + if ( (*mscript)->active ) { + ret = SIEVE_EXEC_FAILURE; + + if ( (*mscript)->teststream ) { + } else { + if ( !sieve_result_implicit_keep + ((*mscript)->result, (*mscript)->msgdata, (*mscript)->scriptenv) ) + ret = SIEVE_EXEC_KEEP_FAILED; + } + } /* Cleanup */ sieve_result_unref(&result); *mscript = NULL; return ret; -} +} + +/* + * Script directory + */ + +struct sieve_directory { + DIR *dirp; + + const char *path; +}; + +struct sieve_directory *sieve_directory_open(const char *path) +{ + struct sieve_directory *sdir = NULL; + DIR *dirp; + struct stat st; + + /* Specified path can either be a regular file or a directory */ + if ( stat(path, &st) != 0 ) + return NULL; + + if ( S_ISDIR(st.st_mode) ) { + + /* Open the directory */ + if ( (dirp = opendir(path)) == NULL ) { + sieve_sys_error("opendir(%s) failed: %m", path); + return NULL; + } + + /* Create object */ + sdir = t_new(struct sieve_directory, 1); + sdir->path = path; + sdir->dirp = dirp; + } else { + sdir = t_new(struct sieve_directory, 1); + sdir->path = path; + sdir->dirp = NULL; + } + + return sdir; +} + +const char *sieve_directory_get_scriptfile(struct sieve_directory *sdir) +{ + const char *script = NULL; + struct dirent *dp; + + if ( sdir->dirp != NULL ) { + while ( script == NULL ) { + const char *file; + struct stat st; + + errno = 0; + if ( (dp = readdir(sdir->dirp)) == NULL ) { + if ( errno != 0 ) { + sieve_sys_error("readdir(%s) failed: %m", sdir->path); + continue; + } else + return NULL; + } + + if ( !sieve_script_file_has_extension(dp->d_name) ) + continue; + + if ( sdir->path[strlen(sdir->path)-1] == '/' ) + file = t_strconcat(sdir->path, dp->d_name, NULL); + else + file = t_strconcat(sdir->path, "/", dp->d_name, NULL); + + if ( stat(file, &st) != 0 || !S_ISREG(st.st_mode) ) + continue; + + script = file; + } + } else { + script = sdir->path; + sdir->path = NULL; + } + + return script; +} + +void sieve_directory_close(struct sieve_directory **sdir) +{ + /* Close the directory */ + if ( (*sdir)->dirp != NULL && closedir((*sdir)->dirp) < 0 ) + sieve_sys_error("closedir(%s) failed: %m", (*sdir)->path); + + *sdir = NULL; +} + diff --git a/src/lib-sieve/sieve.h b/src/lib-sieve/sieve.h index 54fb1a80aeeb5db907797656516c197e7253844b..fa236e6a7e0136972093caf92847d37790519a54 100644 --- a/src/lib-sieve/sieve.h +++ b/src/lib-sieve/sieve.h @@ -120,17 +120,28 @@ int sieve_execute struct sieve_multiscript; -struct sieve_multiscript *sieve_multiscript_start +struct sieve_multiscript *sieve_multiscript_start_execute (const struct sieve_message_data *msgdata, const struct sieve_script_env *senv, struct sieve_error_handler *ehandler); - -bool sieve_multiscript_test - (struct sieve_multiscript *mscript, struct sieve_binary *sbin, - bool final, struct ostream *stream); -bool sieve_multiscript_execute - (struct sieve_multiscript *mscript, struct sieve_binary *sbin, - bool final); - +struct sieve_multiscript *sieve_multiscript_start_test + (const struct sieve_message_data *msgdata, const struct sieve_script_env *senv, + struct sieve_error_handler *ehandler, struct ostream *stream); + +bool sieve_multiscript_run + (struct sieve_multiscript *mscript, struct sieve_binary *sbin, bool final); + +int sieve_multiscript_status(struct sieve_multiscript *mscript); + int sieve_multiscript_finish(struct sieve_multiscript **mscript); +/* + * Script directory + */ + +struct sieve_directory; + +struct sieve_directory *sieve_directory_open(const char *path); +const char *sieve_directory_get_scriptfile(struct sieve_directory *sdir); +void sieve_directory_close(struct sieve_directory **sdir); + #endif diff --git a/src/plugins/lda-sieve/lda-sieve-plugin.c b/src/plugins/lda-sieve/lda-sieve-plugin.c index 4055c23d80e8048a6f32c9caa40a2ec172f640a9..03cbc3e0d1038afe5c90d22bdd4ae9f55fb28393 100644 --- a/src/plugins/lda-sieve/lda-sieve-plugin.c +++ b/src/plugins/lda-sieve/lda-sieve-plugin.c @@ -2,16 +2,19 @@ */ #include "lib.h" +#include "array.h" #include "home-expand.h" #include "deliver.h" #include "duplicate.h" #include "smtp-client.h" + #include "sieve.h" #include "lda-sieve-plugin.h" #include <stdlib.h> #include <sys/stat.h> +#include <dirent.h> /* * Configuration @@ -27,6 +30,8 @@ static deliver_mail_func_t *next_deliver_mail; +static bool lda_sieve_debug = FALSE; + /* * Mail transmission */ @@ -60,8 +65,8 @@ static const char *lda_sieve_get_path(void) if (script_path != NULL) { if (*script_path == '\0') { /* disabled */ - if (getenv("DEBUG") != NULL) - sieve_sys_info("empty script path, disabled"); + if ( lda_sieve_debug ) + sieve_sys_info("empty script path, disabled"); return NULL; } @@ -101,37 +106,22 @@ static const char *lda_sieve_get_path(void) return script_path; } -static int lda_sieve_run -(struct mail_namespace *namespaces, struct mail *mail, const char *script_path, - const char *destaddr, const char *username, const char *mailbox, - struct mail_storage **storage_r) +static int lda_sieve_open +(const char *script_path, struct sieve_error_handler *ehandler, + const char *scriptlog, struct sieve_binary **sbin) { - bool debug = ( getenv("DEBUG") != NULL ); - struct sieve_message_data msgdata; - struct sieve_script_env scriptenv; - struct sieve_exec_status estatus; - struct sieve_error_handler *ehandler; - struct sieve_binary *sbin; - const char *scriptlog; bool exists = TRUE; int ret = 0; - *storage_r = NULL; - - /* Create error handler */ - scriptlog = t_strconcat(script_path, ".log", NULL); - ehandler = sieve_logfile_ehandler_create(scriptlog, LDA_SIEVE_MAX_ERRORS); - - /* Open the script */ - - if ( debug ) + if ( lda_sieve_debug ) sieve_sys_info("opening script %s", script_path); - if ( (sbin=sieve_open(script_path, "main script", ehandler, &exists)) == NULL ) { + if ( (*sbin=sieve_open(script_path, "main script", ehandler, &exists)) + == NULL ) { ret = sieve_get_errors(ehandler) > 0 ? -1 : 0; - if ( debug ) { + if ( lda_sieve_debug ) { if ( !exists && ret == 0 ) sieve_sys_info ("script file %s is missing; reverting to default delivery", @@ -148,6 +138,261 @@ static int lda_sieve_run return ret; } + return 1; +} + +static struct sieve_binary *lda_sieve_recompile +(const char *script_path, struct sieve_error_handler *ehandler, + const char *scriptlog) +{ + struct sieve_binary *sbin; + + /* Warn */ + sieve_sys_warning("encountered corrupt binary: recompiling script %s", + script_path); + + /* Recompile */ + + sieve_error_handler_copy_masterlog(ehandler, FALSE); + + if ( (sbin=sieve_compile(script_path, NULL, ehandler)) == NULL ) { + sieve_sys_error + ("failed to compile script %s " + "(view logfile %s for more information); " + "reverting to default delivery", + script_path, scriptlog); + sieve_error_handler_unref(&ehandler); + return NULL; + } + + sieve_error_handler_copy_masterlog(ehandler, TRUE); + + return sbin; +} + +static int lda_sieve_handle_exec_status(const char *script_path, int status) +{ + int ret; + + switch ( status ) { + case SIEVE_EXEC_FAILURE: + sieve_sys_error + ("execution of script %s failed, but implicit keep was successful", + script_path); + ret = 1; + break; + case SIEVE_EXEC_BIN_CORRUPT: + sieve_sys_error + ("!!BUG!!: binary compiled from %s is still corrupt; " + "bailing out and reverting to default delivery", + script_path); + ret = -1; + break; + case SIEVE_EXEC_KEEP_FAILED: + sieve_sys_error + ("script %s failed with unsuccessful implicit keep", script_path); + ret = -1; + break; + default: + ret = status > 0 ? 1 : -1; + break; + } + + return ret; +} + +static int lda_sieve_singlescript_execute +(const char *script_path, struct sieve_binary **sbin, + const struct sieve_message_data *msgdata, const struct sieve_script_env *senv, + struct sieve_error_handler *ehandler, const char *scriptlog) +{ + int ret; + + if ( lda_sieve_debug ) + sieve_sys_info("executing compiled script %s", script_path); + + /* Execute */ + + ret = sieve_execute(*sbin, msgdata, senv, ehandler); + + /* Recompile corrupt binary */ + + if ( ret == SIEVE_EXEC_BIN_CORRUPT ) { + /* Close corrupt script */ + sieve_close(sbin); + + /* Recompile */ + if ( (*sbin=lda_sieve_recompile(script_path, ehandler, scriptlog)) == NULL ) + return -1; + + /* Execute again */ + + ret = sieve_execute(*sbin, msgdata, senv, ehandler); + + /* Save new version */ + + if ( ret != SIEVE_EXEC_BIN_CORRUPT ) + sieve_save(*sbin, NULL); + } + + /* Report status */ + + return lda_sieve_handle_exec_status(script_path, ret); +} + +static int lda_sieve_multiscript_execute_script +(struct sieve_multiscript *mscript, const char *script, bool final, + struct sieve_error_handler *ehandler, const char *scriptlog) +{ + struct sieve_binary *sbin = NULL; + bool more = FALSE; + + if ( lda_sieve_open(script, ehandler, scriptlog, &sbin) <= 0 ) + return -1; + + if ( !(more=sieve_multiscript_run(mscript, sbin, final)) ) { + if ( sieve_multiscript_status(mscript) == SIEVE_EXEC_BIN_CORRUPT ) { + /* Close corrupt script */ + sieve_close(&sbin); + + /* Recompile */ + + if ( (sbin=lda_sieve_recompile(script, ehandler, scriptlog)) == NULL ) + return -1; + + /* Execute again */ + + more = sieve_multiscript_run(mscript, sbin, final); + + /* Save new version */ + + if ( more && + sieve_multiscript_status(mscript) != SIEVE_EXEC_BIN_CORRUPT ) + sieve_save(sbin, NULL); + } + } + + return (int) more; +} + +static void lda_sieve_multiscript_get_scriptfiles +(const char *script_path, ARRAY_TYPE(const_string) *scriptfiles) +{ + struct sieve_directory *sdir = sieve_directory_open(script_path); + + if ( sdir != NULL ) { + const char *file; + + while ( (file=sieve_directory_get_scriptfile(sdir)) != NULL ) { + array_append(scriptfiles, &file, 1); + } + + sieve_directory_close(&sdir); + } +} + +static int lda_sieve_multiscript_execute_scripts +(struct sieve_multiscript *mscript, ARRAY_TYPE(const_string) *scripts, + bool final, struct sieve_error_handler *ehandler, const char *scriptlog) +{ + const char *const *scriptfiles; + unsigned int count, i; + int ret = 0; + + scriptfiles = array_get(scripts, &count); + for ( i = 0; i < count; i++ ) { + if ( (ret=lda_sieve_multiscript_execute_script + (mscript, scriptfiles[i], ( final && i == count - 1 ), ehandler, + scriptlog)) <= 0 ) + return ret; + } + + return 1; +} + +static int lda_sieve_multiscript_execute +(const char *script_path, struct sieve_binary **main_sbin, + ARRAY_TYPE (const_string) *scripts_before, + ARRAY_TYPE (const_string) *scripts_after, + const struct sieve_message_data *msgdata, const struct sieve_script_env *senv, + struct sieve_error_handler *ehandler,const char *scriptlog) +{ + /* Multiple scripts */ + struct sieve_multiscript *mscript = sieve_multiscript_start_execute + (msgdata, senv, ehandler); + int ret = 1; + + /* Execute scripts before main script */ + ret = lda_sieve_multiscript_execute_scripts + (mscript, scripts_before, FALSE, ehandler, scriptlog); + + /* Execute main script */ + if ( ret > 0 ) { + bool final = ( array_count(scripts_after) == 0 ); + + if ( !(ret=sieve_multiscript_run(mscript, *main_sbin, final)) ) { + + if ( sieve_multiscript_status(mscript) == SIEVE_EXEC_BIN_CORRUPT ) { + /* Close corrupt script */ + sieve_close(main_sbin); + + /* Recompile */ + if ( (*main_sbin=lda_sieve_recompile(script_path, ehandler, scriptlog)) + == NULL ) { + ret = -1; + } else { + + /* Execute again */ + + ret = sieve_multiscript_run(mscript, *main_sbin, final); + + /* Save new version */ + + if ( sieve_multiscript_status(mscript) != SIEVE_EXEC_BIN_CORRUPT ) + sieve_save(*main_sbin, NULL); + } + } + } + } + + /* Execute scripts after main script */ + if ( ret > 0 ) + ret = lda_sieve_multiscript_execute_scripts + (mscript, scripts_after, TRUE, ehandler, scriptlog); + + /* Finish execution */ + ret = sieve_multiscript_finish(&mscript); + + return lda_sieve_handle_exec_status(script_path, ret); +} + +static int lda_sieve_run +(struct mail_namespace *namespaces, struct mail *mail, const char *script_path, + const char *destaddr, const char *username, const char *mailbox, + struct mail_storage **storage_r) +{ + struct sieve_message_data msgdata; + struct sieve_script_env scriptenv; + struct sieve_exec_status estatus; + struct sieve_error_handler *ehandler; + struct sieve_binary *sbin = NULL; + const char *scriptlog, *sieve_before, *sieve_after; + ARRAY_TYPE (const_string) scripts_before; + ARRAY_TYPE (const_string) scripts_after; + int ret = 0; + + *storage_r = NULL; + + /* Create error handler */ + + scriptlog = t_strconcat(script_path, ".log", NULL); + ehandler = sieve_logfile_ehandler_create(scriptlog, LDA_SIEVE_MAX_ERRORS); + + /* Open the script */ + + if ( (ret=lda_sieve_open(script_path, ehandler, scriptlog, &sbin)) <= 0 ) + return ret; + /* Log the messages to the system error handlers as well from this moment * on. */ @@ -176,85 +421,36 @@ static int lda_sieve_run scriptenv.duplicate_check = duplicate_check; scriptenv.exec_status = &estatus; - /* Execute the script */ - - if ( debug ) - sieve_sys_info("executing compiled script %s", script_path); - - ret = sieve_execute(sbin, &msgdata, &scriptenv, ehandler); + /* Check for multiscript */ - /* Record status */ + t_array_init(&scripts_after, 16); + t_array_init(&scripts_before, 16); - tried_default_save = estatus.tried_default_save; - *storage_r = estatus.last_storage; + sieve_before = getenv("SIEVE_BEFORE"); + sieve_after = getenv("SIEVE_AFTER"); - /* Evaluate result */ + if ( sieve_before != NULL || *sieve_before != '\0' ) + lda_sieve_multiscript_get_scriptfiles(sieve_before, &scripts_before); - if ( ret == SIEVE_EXEC_BIN_CORRUPT ) { - sieve_sys_warning("encountered corrupt binary: recompiling script %s", - script_path); + if ( sieve_after != NULL || *sieve_after != '\0' ) + lda_sieve_multiscript_get_scriptfiles(sieve_after, &scripts_after); - /* - * Try again; possibly author forgot to increase binary version number - */ + if ( array_count(&scripts_before) == 0 && array_count(&scripts_after) == 0 ) + ret = lda_sieve_singlescript_execute + (script_path, &sbin, &msgdata, &scriptenv, ehandler, scriptlog); + else + ret = lda_sieve_multiscript_execute + (script_path, &sbin, &scripts_before, &scripts_after, &msgdata, + &scriptenv, ehandler, scriptlog); - /* Close corrupt script */ - sieve_close(&sbin); - - /* Recompile */ - - sieve_error_handler_copy_masterlog(ehandler, FALSE); - - if ( (sbin=sieve_compile(script_path, NULL, ehandler)) == NULL ) { - sieve_sys_error - ("failed to compile script %s " - "(view logfile %s for more information); " - "reverting to default delivery", - script_path, scriptlog); - sieve_error_handler_unref(&ehandler); - return -1; - } - - sieve_error_handler_copy_masterlog(ehandler, TRUE); - - /* Execute again */ - - ret = sieve_execute(sbin, &msgdata, &scriptenv, ehandler); - - /* Record status */ - - tried_default_save = estatus.tried_default_save; - *storage_r = estatus.last_storage; - - /* Save new version */ - - if ( ret != SIEVE_EXEC_BIN_CORRUPT ) - sieve_save(sbin, NULL); - } + /* Record status */ - switch ( ret ) { - case SIEVE_EXEC_FAILURE: - sieve_sys_error - ("execution of script %s failed, but implicit keep was successful", - script_path); - ret = SIEVE_EXEC_OK; - break; - case SIEVE_EXEC_BIN_CORRUPT: - sieve_sys_error - ("!!BUG!!: binary compiled from %s is still corrupt; " - "bailing out and reverting to default delivery", - script_path); - break; - case SIEVE_EXEC_KEEP_FAILED: - sieve_sys_error - ("script %s failed with unsuccessful implicit keep", script_path); - break; - default: - break; - } + tried_default_save = estatus.tried_default_save; + *storage_r = estatus.last_storage; /* Clean up */ - sieve_close(&sbin); + if ( sbin != NULL ) + sieve_close(&sbin); sieve_error_handler_unref(&ehandler); return ret; @@ -271,14 +467,14 @@ static int lda_sieve_deliver_mail script_path = lda_sieve_get_path(); if (script_path == NULL) { - if (getenv("DEBUG") != NULL) + if ( lda_sieve_debug ) sieve_sys_info("no valid sieve script path specified: " "reverting to default delivery."); return 0; } - if (getenv("DEBUG") != NULL) + if ( lda_sieve_debug ) sieve_sys_info("using sieve path: %s", script_path); /* Run the script */ @@ -308,6 +504,9 @@ void sieve_plugin_init(void) sieve_set_extensions(extensions); } + /* Debug mode */ + lda_sieve_debug = getenv("DEBUG"); + /* Hook into the delivery process */ next_deliver_mail = deliver_mail; deliver_mail = lda_sieve_deliver_mail; diff --git a/src/sieve-tools/sieve-test.c b/src/sieve-tools/sieve-test.c index e3fefff7ee8ca5d66f0578f3def4dc874d7b257d..b5a56c667cbe419a8fcc1c79d6d2d042354d5227 100644 --- a/src/sieve-tools/sieve-test.c +++ b/src/sieve-tools/sieve-test.c @@ -277,7 +277,7 @@ int main(int argc, char **argv) sieve_error_handler_accept_infolog(ehandler, TRUE); /* Run the test */ - + ret = 1; if ( array_count(&scriptfiles) == 0 ) { /* Single script */ sbin = main_sbin; @@ -292,13 +292,20 @@ int main(int argc, char **argv) /* Multiple scripts */ const char *const *sfiles; unsigned int i, count; - struct sieve_multiscript *mscript = sieve_multiscript_start - (&msgdata, &scriptenv, ehandler); - int result = 1; + struct sieve_multiscript *mscript; + bool more = TRUE; + int result; + + if ( execute ) + mscript = sieve_multiscript_start_execute + (&msgdata, &scriptenv, ehandler); + else + mscript = sieve_multiscript_start_test + (&msgdata, &scriptenv, ehandler, teststream); /* Execute scripts sequentially */ sfiles = array_get(&scriptfiles, &count); - for ( i = 0; i < count && result > 0; i++ ) { + for ( i = 0; i < count && more; i++ ) { if ( teststream != NULL ) o_stream_send_str(teststream, t_strdup_printf("\n## Executing script: %s\n", sfiles[i])); @@ -316,20 +323,16 @@ int main(int argc, char **argv) } if ( sbin == NULL ) { - result = -1; + ret = SIEVE_EXEC_FAILURE; break; } /* Execute/Test script */ - if ( execute ) - result = sieve_multiscript_execute(mscript, sbin, FALSE); - else - result = sieve_multiscript_test(mscript, sbin, FALSE, teststream); + more = sieve_multiscript_run(mscript, sbin, FALSE); } /* Execute/Test main script */ - switch ( result ) { - case TRUE: + if ( more && ret > 0 ) { if ( teststream != NULL ) o_stream_send_str(teststream, t_strdup_printf("## Executing script: %s\n", scriptfile)); @@ -341,18 +344,12 @@ int main(int argc, char **argv) sbin = main_sbin; main_sbin = NULL; - if ( execute ) - (void)sieve_multiscript_execute(mscript, sbin, TRUE); - else - (void)sieve_multiscript_test(mscript, sbin, TRUE, teststream); - - case FALSE: - ret = sieve_multiscript_finish(&mscript); - break; - - default: - ret = SIEVE_EXEC_FAILURE; + sieve_multiscript_run(mscript, sbin, TRUE); } + + result = sieve_multiscript_finish(&mscript); + + ret = ret > 0 ? result : ret; } /* Run */