From eab3d16253bf91cb96fc7ebd99220f3445b7c33d Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Mon, 3 May 2010 20:02:55 +0200
Subject: [PATCH] Made command line tools return proper exit status upon
 failure.

---
 src/sieve-tools/sieve-test.c     | 10 ++++++++--
 src/sieve-tools/sievec.c         | 27 ++++++++++++++++-----------
 src/sieve-tools/sieved.c         | 18 ++++++++++++------
 src/testsuite/testsuite-common.c |  6 +++---
 src/testsuite/testsuite-common.h |  2 +-
 src/testsuite/testsuite.c        |  5 ++++-
 6 files changed, 44 insertions(+), 24 deletions(-)

diff --git a/src/sieve-tools/sieve-test.c b/src/sieve-tools/sieve-test.c
index a0bc77310..d0f8da97f 100644
--- a/src/sieve-tools/sieve-test.c
+++ b/src/sieve-tools/sieve-test.c
@@ -124,6 +124,7 @@ int main(int argc, char **argv)
 	struct ostream *teststream = NULL;
 	bool force_compile = FALSE, execute = FALSE;
 	bool trace = FALSE;
+	int exit_status = EXIT_SUCCESS;
 	int ret, c;
 
 	master_service = master_service_init("sieve-test", 
@@ -266,7 +267,9 @@ int main(int argc, char **argv)
 		main_sbin = sieve_tool_script_open(scriptfile);
 	}
 
-	if ( main_sbin != NULL ) {
+	if ( main_sbin == NULL ) {
+		exit_status = EXIT_FAILURE;
+	} else {
 		struct mail_user *mail_user = NULL;
 
 		/* Dump script */
@@ -422,11 +425,14 @@ int main(int argc, char **argv)
 			(void) unlink(sieve_binary_path(sbin));
 		case SIEVE_EXEC_FAILURE:
 			i_info("final result: failed; resolved with successful implicit keep");
+			exit_status = EXIT_FAILURE;
 			break;
 		case SIEVE_EXEC_KEEP_FAILED:
 			i_info("final result: utter failure");
+			exit_status = EXIT_FAILURE;
 			break;
 		default:
+			exit_status = EXIT_FAILURE;
 			i_info("final result: unrecognized return value?!");	
 		}
 
@@ -461,5 +467,5 @@ int main(int argc, char **argv)
 	mail_storage_service_deinit(&storage_service);
 	master_service_deinit(&master_service);
 	
-	return 0;
+	return exit_status;
 }
diff --git a/src/sieve-tools/sievec.c b/src/sieve-tools/sievec.c
index 32f0a029f..4556a8cf9 100644
--- a/src/sieve-tools/sievec.c
+++ b/src/sieve-tools/sievec.c
@@ -19,6 +19,7 @@
 #include <unistd.h>
 #include <stdio.h>
 #include <dirent.h>
+#include <sysexits.h>
 
 /*
  * Print help
@@ -44,6 +45,7 @@ int main(int argc, char **argv)
 	struct sieve_binary *sbin;
 	bool dump = FALSE;
 	const char *scriptfile, *outfile, *extensions;
+	int exit_status = EXIT_SUCCESS;
 		
 	sieve_tool_init(TRUE);
 
@@ -59,7 +61,7 @@ int main(int argc, char **argv)
 			i++;
 			if (i == argc) {
 				print_help();
-				i_fatal("Missing -x argument");
+				i_fatal_status(EX_USAGE, "Missing -x argument");
 			}
 			extensions = argv[i];
 		} else if (strcmp(argv[i], "-P") == 0) {
@@ -69,7 +71,7 @@ int main(int argc, char **argv)
 			i++;
 			if (i == argc) {
 				print_help();
-				i_fatal("Missing -P argument");
+				i_fatal_status(EX_USAGE, "Missing -P argument");
 			}
 
 			plugin = t_strdup(argv[i]);
@@ -80,13 +82,13 @@ int main(int argc, char **argv)
 			outfile = argv[i];
 		} else {
 			print_help();
-			i_fatal("Unknown argument: %s", argv[i]);
+			i_fatal_status(EX_USAGE, "Unknown argument: %s", argv[i]);
 		}
 	}
 	
 	if ( scriptfile == NULL ) {
 		print_help();
-		i_fatal("Missing <script-file> argument");
+		i_fatal_status(EX_USAGE, "Missing <script-file> argument");
 	}
 	
 	if ( outfile == NULL && dump )
@@ -113,11 +115,12 @@ int main(int argc, char **argv)
 		/* Sanity checks on some of the arguments */
 		
 		if ( dump )
-			i_fatal("the -d option is not allowed when scriptfile is a directory."); 
+			i_fatal_status(EX_USAGE, 
+				"the -d option is not allowed when scriptfile is a directory."); 
 		
 		if ( outfile != NULL )
-			i_fatal("the outfile argument is not allowed when scriptfile is a "
-				"directory."); 
+			i_fatal_status(EX_USAGE, 
+				"the outfile argument is not allowed when scriptfile is a directory."); 
 		
 		/* Open the directory */
 		if ( (dirp = opendir(scriptfile)) == NULL )
@@ -144,8 +147,7 @@ int main(int argc, char **argv)
 				sbin = sieve_tool_script_compile(file, dp->d_name);
 
 				if ( sbin != NULL ) {
-					sieve_save(sbin, NULL);
-		
+					sieve_save(sbin, NULL);		
 					sieve_close(&sbin);
 				}
 			}
@@ -153,8 +155,7 @@ int main(int argc, char **argv)
    
 		/* Close the directory */
 		if ( closedir(dirp) < 0 ) 
-			i_fatal("closedir(%s) failed: %m", scriptfile);
- 	
+			i_fatal("closedir(%s) failed: %m", scriptfile); 	
 	} else {
 		/* Script file (i.e. not a directory)
 		 * 
@@ -170,8 +171,12 @@ int main(int argc, char **argv)
 			}
 		
 			sieve_close(&sbin);
+		} else {
+			exit_status = EXIT_FAILURE;
 		}
 	}
 		
 	sieve_tool_deinit();
+
+	return exit_status;
 }
diff --git a/src/sieve-tools/sieved.c b/src/sieve-tools/sieved.c
index 5f5055b6c..9f3490120 100644
--- a/src/sieve-tools/sieved.c
+++ b/src/sieve-tools/sieved.c
@@ -17,6 +17,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <stdio.h>
+#include <sysexits.h>
 
 /*
  * Print help
@@ -40,6 +41,7 @@ int main(int argc, char **argv)
 	int i;
 	struct sieve_binary *sbin;
 	const char *binfile, *outfile, *extensions;
+	int exit_status = EXIT_SUCCESS;
 	
 	sieve_tool_init(TRUE);
 
@@ -52,7 +54,7 @@ int main(int argc, char **argv)
 			i++;
 			if (i == argc) {
 				print_help();
-				i_fatal("Missing -x argument");
+				i_fatal_status(EX_USAGE, "Missing -x argument");
 			}
 			extensions = argv[i];
 		} else if (strcmp(argv[i], "-P") == 0) {
@@ -62,7 +64,7 @@ int main(int argc, char **argv)
 			i++;
 			if (i == argc) {
 				print_help();
-				i_fatal("Missing -P argument");
+				i_fatal_status(EX_USAGE, "Missing -P argument");
 			}
 
 			plugin = t_strdup(argv[i]);
@@ -73,13 +75,13 @@ int main(int argc, char **argv)
 			outfile = argv[i];
 		} else {
 			print_help();
-			i_fatal("unknown argument: %s", argv[i]);
+			i_fatal_status(EX_USAGE, "unknown argument: %s", argv[i]);
 		}
 	}
 	
 	if ( binfile == NULL ) {
 		print_help();
-		i_fatal("missing <sieve-binary> argument");
+		i_fatal_status(EX_USAGE, "missing <sieve-binary> argument");
 	}
 
 	sieve_tool_sieve_init(NULL);
@@ -101,9 +103,13 @@ int main(int argc, char **argv)
 		sieve_tool_dump_binary_to(sbin, outfile == NULL ? "-" : outfile);
 	
 		sieve_close(&sbin);
-	} else 
+	} else {
 		i_error("failed to load binary: %s", binfile);
-	
+		exit_status = EXIT_FAILURE;
+	}
+
 	sieve_tool_deinit();
+
+	return exit_status;
 }
 
diff --git a/src/testsuite/testsuite-common.c b/src/testsuite/testsuite-common.c
index 3de9afc8b..1df391fd5 100644
--- a/src/testsuite/testsuite-common.c
+++ b/src/testsuite/testsuite-common.c
@@ -186,15 +186,15 @@ static void testsuite_test_context_deinit(void)
 	str_free(&test_name);
 }
 
-int testsuite_testcase_result(void)
+bool testsuite_testcase_result(void)
 {
 	if ( test_failures > 0 ) {
 		printf("\nFAIL: %d of %d tests failed.\n\n", test_failures, test_index);
-		return 1;
+		return FALSE;
 	}
 
 	printf("\nPASS: %d tests succeeded.\n\n", test_index);
-	return 0;
+	return TRUE;
 }
 
 /*
diff --git a/src/testsuite/testsuite-common.h b/src/testsuite/testsuite-common.h
index 778747363..a336de73c 100644
--- a/src/testsuite/testsuite-common.h
+++ b/src/testsuite/testsuite-common.h
@@ -142,7 +142,7 @@ void testsuite_test_fail_cstr(const char *reason);
 void testsuite_test_succeed(string_t *reason);
 
 void testsuite_testcase_fail(const char *reason);
-int testsuite_testcase_result(void);
+bool testsuite_testcase_result(void);
 
 /*
  * Testsuite temporary directory
diff --git a/src/testsuite/testsuite.c b/src/testsuite/testsuite.c
index 30287cf4d..acef28322 100644
--- a/src/testsuite/testsuite.c
+++ b/src/testsuite/testsuite.c
@@ -290,5 +290,8 @@ int main(int argc, char **argv)
 	mail_storage_service_deinit(&storage_service);
 	master_service_deinit(&master_service);
 
-	return testsuite_testcase_result();
+	if ( !testsuite_testcase_result() )
+		return EXIT_FAILURE;
+
+	return EXIT_SUCCESS;
 }
-- 
GitLab