diff options
Diffstat (limited to 'src/genrc.c')
-rw-r--r-- | src/genrc.c | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/src/genrc.c b/src/genrc.c index ae3070d..9052987 100644 --- a/src/genrc.c +++ b/src/genrc.c @@ -16,44 +16,48 @@ int genrc_signal_stop = SIGTERM; int genrc_signal_reload = SIGHUP; GENRC_PID_CLOSURE *genrc_pid_closure; char *genrc_create_pidfile; int genrc_verbose; enum { OPT_USAGE = 256, OPT_VERSION, OPT_SIGNAL_RELOAD, OPT_NO_RELOAD, OPT_SIGNAL_STOP, - OPT_CREATE_PIDFILE + OPT_CREATE_PIDFILE, + OPT_RESTART_ON_EXIT, + OPT_RESTART_ON_SIGNAL, }; struct option longopts[] = { { "help", no_argument, 0, 'h' }, { "usage", no_argument, 0, OPT_USAGE }, { "command", required_argument, 0, 'c' }, { "program", required_argument, 0, 'p' }, { "pid-from", required_argument, 0, 'P' }, { "pidfile", required_argument, 0, 'F' }, { "timeout", required_argument, 0, 't' }, { "signal-reload", required_argument, 0, OPT_SIGNAL_RELOAD }, { "no-reload", no_argument, 0, OPT_NO_RELOAD }, { "signal-stop", required_argument, 0, OPT_SIGNAL_STOP }, { "sentinel", no_argument, 0, 'S' }, { "create-pidfile", required_argument, 0, OPT_CREATE_PIDFILE }, { "version", no_argument, 0, OPT_VERSION }, { "verbose", no_argument, 0, 'v' }, { "user", required_argument, 0, 'u' }, { "group", required_argument, 0, 'g' }, + { "restart-on-exit", required_argument, 0, OPT_RESTART_ON_EXIT }, + { "restart-on-signal", required_argument, 0, OPT_RESTART_ON_SIGNAL }, { NULL } }; char shortopts[] = "c:hF:g:P:p:St:u:v"; struct sigdefn { char const *sig_name; int sig_no; }; #define S(s) { #s, s } static struct sigdefn sigdefn[] = { S (SIGHUP), @@ -118,34 +122,40 @@ static struct sigdefn sigdefn[] = { static int is_numeric_str(char const *s) { while (*s) { if (!isdigit(*s)) return 0; s++; } return 1; } int -sig_name_to_str(char const *s) +str_to_int(char const *s) { - if (is_numeric_str(s)) { char *end; unsigned long n; errno = 0; n = strtoul(s, &end, 10); if (errno || *end || n > UINT_MAX) return -1; return n; +} + +int +str_to_sig(char const *s) +{ + if (is_numeric_str(s)) { + return str_to_int(s); } else { struct sigdefn *sd; for (sd = sigdefn; sd->sig_name; sd++) { if (s[0] == 's' || s[0] == 'S') { if (strcasecmp(sd->sig_name, s) == 0) return sd->sig_no; } else if (strcasecmp(sd->sig_name + 3, s) == 0) return sd->sig_no; } } return -1; @@ -174,35 +184,44 @@ char const *help_msg[] = { " first word (in the shell sense) in COMMAND.", "", "Runtime privileges:", "", " -u, --user=NAME run with this user privileges", " -g, --group=GROUP[,GROUP...]]", " run with this group(s) privileges", "", "Additional configuration:", "", " -t, --timeout=SECONDS time to wait for the program to start up or", " terminate", - " --sentinel PROGRAM runs in foreground; disconnect from the", - " controlling terminal, run it and act as a sentinel", " -P, --pid-from=SOURCE where to look for PIDs of the running programs", " -F, --pidfile=NAME name of the PID file", " (same as --pid-from=FILE:NAME)", " --signal-reload=SIG signal to send on reload (default: SIGHUP)", " setting to 0 is equivalent to --no-reload", " --no-reload makes reload equivalent to restart", " --signal-stop=SIG signal to send in order to terminate the program", " (default: SIGTERM)", "", + "Sentinel mode:", + "", + " --sentinel PROGRAM runs in foreground; disconnect from the", + " controlling terminal, run it and act as a sentinel", + " --restart-on-exit=[!]CODE[,...]", + " restart the program if it exits with one of the", + " listed status codes", + " --restart-on-signal=[!]SIG[,...]", + " restart the program if it terminates on one of the", + " listed signals", + "", "Informational options:", "", " -h, --help display this help list", " --usage display short usage information", " --version display program version and exist", "", "Influential environment variables and corresponding options:", "", " GENRC_COMMAND=COMMAND --command=COMMAND", " GENRC_PROGRAM=NAME --program=NAME", " GENRC_PID_FROM=SOURCE --pid-from=SOURCE", " GENRC_TIMEOUT=SECONDS --timeout=SECONDS", @@ -263,24 +282,26 @@ char const *usage_msg[] = { "[-c COMMAND]", "[-g GROUP[,GROUP...]]", "[-p PROGRAM]", "[-t SECONDS]", "[-u USER]", "[--command=COMMAND]", "[--group GROUP[,GROUP...]]", "[--help]", "[--no-reload]", "[--pid-from=SOURCE]", "[--pidfile=PIDFILE]", "[--program=PROGRAM]", + "[--restart-on-exit=[!]CODE[,...]]", + "[--restart-on-signal=[!]SIG[,...]]", "[--sentinel]", "[--signal-reload=SIG]", "[--signal-stop=SIG]", "[--timeout=SECONDS]", "[--usage]", "[--user=USER]", "{", "start", "|", "stop", "|", "restart", @@ -413,24 +434,30 @@ main(int argc, char **argv) case 'g': setenv("GENRC_GROUP", optarg, 1); break; case OPT_CREATE_PIDFILE: setenv("GENRC_CREATE_PIDFILE", optarg, 1); break; case 't': setenv("GENRC_TIMEOUT", optarg, 1); break; case 'S': setenv("GENRC_SENTINEL", "1", 1); break; + case OPT_RESTART_ON_EXIT: + add_restart_condition(RESTART_ON_EXIT, optarg); + break; + case OPT_RESTART_ON_SIGNAL: + add_restart_condition(RESTART_ON_SIGNAL, optarg); + break; case OPT_NO_RELOAD: no_reload = 1; break; case OPT_SIGNAL_RELOAD: setenv("GENRC_SIGNAL_RELOAD", optarg, 1); break; case OPT_SIGNAL_STOP: setenv("GENRC_SIGNAL_STOP", optarg, 1); break; case 'u': setenv("GENRC_USER", optarg, 1); break; @@ -441,33 +468,33 @@ main(int argc, char **argv) exit(1); } } if ((p = getenv("GENRC_COMMAND")) != NULL) genrc_command = p; if ((p = getenv("GENRC_PROGRAM")) != NULL) genrc_program = p; if (no_reload) genrc_no_reload = 1; else if ((p = getenv("GENRC_SIGNAL_RELOAD")) != NULL) { - genrc_signal_reload = sig_name_to_str(p); + genrc_signal_reload = str_to_sig(p); if (genrc_signal_reload == -1) usage_error("%s: invalid signal number", p); else if (genrc_signal_reload == 0) genrc_no_reload = 1; } if ((p = getenv("GENRC_SIGNAL_STOP")) != NULL) { - genrc_signal_stop = sig_name_to_str(p); + genrc_signal_stop = str_to_sig(p); if (genrc_signal_stop <= 0) usage_error("%s: invalid signal number", p); } if ((p = getenv("GENRC_TIMEOUT")) != NULL) { char *end; unsigned long n; errno = 0; n = strtoul(p, &end, 10); if (errno || *p || n > UINT_MAX) usage_error("%s: invalid timeout", p); if (n == 0) |