#include #include #include #include #define MAX_SIGNALS 32 #define print(fmt, ...) fprintf(stderr, "test_program: "fmt, ##__VA_ARGS__) _Bool do_raise = 0; int raise_signal; _Bool do_Com_Error = 0; _Bool recursive = 0; enum { DEFAULT = 0, CATCH, IGNORE }; int handle[MAX_SIGNALS] = {0}; _Bool handle_any = 0; _Bool verbose = 0; static int read_args(int argc, char **argv) { for (int i = 1; i < argc; i++) { if (!strcmp(argv[i], "--raise")) { if (i + 1 >= argc) goto needs_argument; do_raise = 1; raise_signal = atoi(argv[i + 1]); i++; } else if (!strcmp(argv[i], "--Com_Error")) { do_Com_Error = 1; } else if (!strcmp(argv[i], "--recursive")) { recursive = 1; } else if (!strcmp(argv[i], "--catch") || !strcmp(argv[i], "--ignore")) { int sig; if (i + 1 >= argc) goto needs_argument; sig = atoi(argv[i + 1]); if (sig < 0 || sig >= MAX_SIGNALS) { print("invalid argument for --catch/--ignore: %i\n", sig); return 1; } if (!strcmp(argv[i], "--catch")) handle[sig] = CATCH; else handle[sig] = IGNORE; handle_any = 1; i++; } else if (!strcmp(argv[i], "--ignore")) { } else if (!strcmp(argv[i], "--verbose")) { verbose = 1; } else { print("invalid option '%s'\n", argv[i]); return 1; } continue; needs_argument: print("option '%s' needs an argument\n", argv[i]); return 1; } if (do_Com_Error && do_raise) { print("--raise and --Com_Error are mutually exclusive.\n"); return 1; } return 0; } _Noreturn void graceful_exit(void) { print("Graceful exit.\n"); exit(0); } void signal_catcher(int sig) { print("Caught signal %i.\n", sig); if (recursive) { if (verbose) print("Raising signal %i from within the handler.\n", raise_signal); raise(raise_signal); } graceful_exit(); } _Noreturn void Com_Error(int type, const char *str) { print("Com_Error: %s\n", str); if (recursive) Com_Error(666, "Error while erroring"); graceful_exit(); } int main(int argc, char **argv) { int rv; rv = read_args(argc, argv); if (rv) return rv; for (int i = 0; i < MAX_SIGNALS; i++) { void (*fun)(int); switch (handle[i]) { case DEFAULT: continue; case CATCH: fun = signal_catcher; if (verbose) print("Signal %i will be caught.\n", i); break; case IGNORE: fun = SIG_IGN; if (verbose) print("Signal %i will be ignored.\n", i); break; } if (signal(i, fun) == SIG_ERR) { print("For signal %i: ", i); perror("signal"); return 1; } } if (do_raise) { print("Raising signal %i.\n", raise_signal); raise(raise_signal); } if (do_Com_Error) Com_Error(123, "Some error string"); print("Reached the end of main().\n"); graceful_exit(); }