diff options
Diffstat (limited to 'src/genrc.c')
-rw-r--r-- | src/genrc.c | 85 |
1 files changed, 56 insertions, 29 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; | |||
16 | int genrc_signal_reload = SIGHUP; | 16 | int genrc_signal_reload = SIGHUP; |
17 | GENRC_PID_CLOSURE *genrc_pid_closure; | 17 | GENRC_PID_CLOSURE *genrc_pid_closure; |
18 | char *genrc_create_pidfile; | 18 | char *genrc_create_pidfile; |
19 | int genrc_verbose; | 19 | int genrc_verbose; |
20 | 20 | ||
21 | 21 | ||
22 | enum { | 22 | enum { |
23 | OPT_USAGE = 256, | 23 | OPT_USAGE = 256, |
24 | OPT_VERSION, | 24 | OPT_VERSION, |
25 | OPT_SIGNAL_RELOAD, | 25 | OPT_SIGNAL_RELOAD, |
26 | OPT_NO_RELOAD, | 26 | OPT_NO_RELOAD, |
27 | OPT_SIGNAL_STOP, | 27 | OPT_SIGNAL_STOP, |
28 | OPT_CREATE_PIDFILE | 28 | OPT_CREATE_PIDFILE, |
29 | OPT_RESTART_ON_EXIT, | ||
30 | OPT_RESTART_ON_SIGNAL, | ||
29 | }; | 31 | }; |
30 | 32 | ||
31 | struct option longopts[] = { | 33 | struct option longopts[] = { |
32 | { "help", no_argument, 0, 'h' }, | 34 | { "help", no_argument, 0, 'h' }, |
33 | { "usage", no_argument, 0, OPT_USAGE }, | 35 | { "usage", no_argument, 0, OPT_USAGE }, |
34 | { "command", required_argument, 0, 'c' }, | 36 | { "command", required_argument, 0, 'c' }, |
35 | { "program", required_argument, 0, 'p' }, | 37 | { "program", required_argument, 0, 'p' }, |
36 | { "pid-from", required_argument, 0, 'P' }, | 38 | { "pid-from", required_argument, 0, 'P' }, |
37 | { "pidfile", required_argument, 0, 'F' }, | 39 | { "pidfile", required_argument, 0, 'F' }, |
38 | { "timeout", required_argument, 0, 't' }, | 40 | { "timeout", required_argument, 0, 't' }, |
39 | { "signal-reload", required_argument, 0, OPT_SIGNAL_RELOAD }, | 41 | { "signal-reload", required_argument, 0, OPT_SIGNAL_RELOAD }, |
40 | { "no-reload", no_argument, 0, OPT_NO_RELOAD }, | 42 | { "no-reload", no_argument, 0, OPT_NO_RELOAD }, |
41 | { "signal-stop", required_argument, 0, OPT_SIGNAL_STOP }, | 43 | { "signal-stop", required_argument, 0, OPT_SIGNAL_STOP }, |
42 | { "sentinel", no_argument, 0, 'S' }, | 44 | { "sentinel", no_argument, 0, 'S' }, |
43 | { "create-pidfile", required_argument, 0, OPT_CREATE_PIDFILE }, | 45 | { "create-pidfile", required_argument, 0, OPT_CREATE_PIDFILE }, |
44 | { "version", no_argument, 0, OPT_VERSION }, | 46 | { "version", no_argument, 0, OPT_VERSION }, |
45 | { "verbose", no_argument, 0, 'v' }, | 47 | { "verbose", no_argument, 0, 'v' }, |
46 | { "user", required_argument, 0, 'u' }, | 48 | { "user", required_argument, 0, 'u' }, |
47 | { "group", required_argument, 0, 'g' }, | 49 | { "group", required_argument, 0, 'g' }, |
50 | { "restart-on-exit", required_argument, 0, OPT_RESTART_ON_EXIT }, | ||
51 | { "restart-on-signal", required_argument, 0, OPT_RESTART_ON_SIGNAL }, | ||
48 | { NULL } | 52 | { NULL } |
49 | }; | 53 | }; |
50 | char shortopts[] = "c:hF:g:P:p:St:u:v"; | 54 | char shortopts[] = "c:hF:g:P:p:St:u:v"; |
51 | 55 | ||
52 | struct sigdefn { | 56 | struct sigdefn { |
53 | char const *sig_name; | 57 | char const *sig_name; |
54 | int sig_no; | 58 | int sig_no; |
55 | }; | 59 | }; |
56 | 60 | ||
57 | #define S(s) { #s, s } | 61 | #define S(s) { #s, s } |
58 | static struct sigdefn sigdefn[] = { | 62 | static struct sigdefn sigdefn[] = { |
59 | S (SIGHUP), | 63 | S (SIGHUP), |
@@ -118,34 +122,40 @@ static struct sigdefn sigdefn[] = { | |||
118 | static int | 122 | static int |
119 | is_numeric_str(char const *s) | 123 | is_numeric_str(char const *s) |
120 | { | 124 | { |
121 | while (*s) { | 125 | while (*s) { |
122 | if (!isdigit(*s)) | 126 | if (!isdigit(*s)) |
123 | return 0; | 127 | return 0; |
124 | s++; | 128 | s++; |
125 | } | 129 | } |
126 | return 1; | 130 | return 1; |
127 | } | 131 | } |
128 | 132 | ||
129 | int | 133 | int |
130 | sig_name_to_str(char const *s) | 134 | str_to_int(char const *s) |
135 | { | ||
136 | char *end; | ||
137 | unsigned long n; | ||
138 | errno = 0; | ||
139 | n = strtoul(s, &end, 10); | ||
140 | if (errno || *end || n > UINT_MAX) | ||
141 | return -1; | ||
142 | return n; | ||
143 | } | ||
144 | |||
145 | int | ||
146 | str_to_sig(char const *s) | ||
131 | { | 147 | { |
132 | if (is_numeric_str(s)) { | 148 | if (is_numeric_str(s)) { |
133 | char *end; | 149 | return str_to_int(s); |
134 | unsigned long n; | ||
135 | errno = 0; | ||
136 | n = strtoul(s, &end, 10); | ||
137 | if (errno || *end || n > UINT_MAX) | ||
138 | return -1; | ||
139 | return n; | ||
140 | } else { | 150 | } else { |
141 | struct sigdefn *sd; | 151 | struct sigdefn *sd; |
142 | 152 | ||
143 | for (sd = sigdefn; sd->sig_name; sd++) { | 153 | for (sd = sigdefn; sd->sig_name; sd++) { |
144 | if (s[0] == 's' || s[0] == 'S') { | 154 | if (s[0] == 's' || s[0] == 'S') { |
145 | if (strcasecmp(sd->sig_name, s) == 0) | 155 | if (strcasecmp(sd->sig_name, s) == 0) |
146 | return sd->sig_no; | 156 | return sd->sig_no; |
147 | } else if (strcasecmp(sd->sig_name + 3, s) == 0) | 157 | } else if (strcasecmp(sd->sig_name + 3, s) == 0) |
148 | return sd->sig_no; | 158 | return sd->sig_no; |
149 | } | 159 | } |
150 | } | 160 | } |
151 | return -1; | 161 | return -1; |
@@ -174,35 +184,44 @@ char const *help_msg[] = { | |||
174 | " first word (in the shell sense) in COMMAND.", | 184 | " first word (in the shell sense) in COMMAND.", |
175 | "", | 185 | "", |
176 | "Runtime privileges:", | 186 | "Runtime privileges:", |
177 | "", | 187 | "", |
178 | " -u, --user=NAME run with this user privileges", | 188 | " -u, --user=NAME run with this user privileges", |
179 | " -g, --group=GROUP[,GROUP...]]", | 189 | " -g, --group=GROUP[,GROUP...]]", |
180 | " run with this group(s) privileges", | 190 | " run with this group(s) privileges", |
181 | "", | 191 | "", |
182 | "Additional configuration:", | 192 | "Additional configuration:", |
183 | "", | 193 | "", |
184 | " -t, --timeout=SECONDS time to wait for the program to start up or", | 194 | " -t, --timeout=SECONDS time to wait for the program to start up or", |
185 | " terminate", | 195 | " terminate", |
186 | " --sentinel PROGRAM runs in foreground; disconnect from the", | ||
187 | " controlling terminal, run it and act as a sentinel", | ||
188 | " -P, --pid-from=SOURCE where to look for PIDs of the running programs", | 196 | " -P, --pid-from=SOURCE where to look for PIDs of the running programs", |
189 | " -F, --pidfile=NAME name of the PID file", | 197 | " -F, --pidfile=NAME name of the PID file", |
190 | " (same as --pid-from=FILE:NAME)", | 198 | " (same as --pid-from=FILE:NAME)", |
191 | " --signal-reload=SIG signal to send on reload (default: SIGHUP)", | 199 | " --signal-reload=SIG signal to send on reload (default: SIGHUP)", |
192 | " setting to 0 is equivalent to --no-reload", | 200 | " setting to 0 is equivalent to --no-reload", |
193 | " --no-reload makes reload equivalent to restart", | 201 | " --no-reload makes reload equivalent to restart", |
194 | " --signal-stop=SIG signal to send in order to terminate the program", | 202 | " --signal-stop=SIG signal to send in order to terminate the program", |
195 | " (default: SIGTERM)", | 203 | " (default: SIGTERM)", |
196 | "", | 204 | "", |
205 | "Sentinel mode:", | ||
206 | "", | ||
207 | " --sentinel PROGRAM runs in foreground; disconnect from the", | ||
208 | " controlling terminal, run it and act as a sentinel", | ||
209 | " --restart-on-exit=[!]CODE[,...]", | ||
210 | " restart the program if it exits with one of the", | ||
211 | " listed status codes", | ||
212 | " --restart-on-signal=[!]SIG[,...]", | ||
213 | " restart the program if it terminates on one of the", | ||
214 | " listed signals", | ||
215 | "", | ||
197 | "Informational options:", | 216 | "Informational options:", |
198 | "", | 217 | "", |
199 | " -h, --help display this help list", | 218 | " -h, --help display this help list", |
200 | " --usage display short usage information", | 219 | " --usage display short usage information", |
201 | " --version display program version and exist", | 220 | " --version display program version and exist", |
202 | "", | 221 | "", |
203 | "Influential environment variables and corresponding options:", | 222 | "Influential environment variables and corresponding options:", |
204 | "", | 223 | "", |
205 | " GENRC_COMMAND=COMMAND --command=COMMAND", | 224 | " GENRC_COMMAND=COMMAND --command=COMMAND", |
206 | " GENRC_PROGRAM=NAME --program=NAME", | 225 | " GENRC_PROGRAM=NAME --program=NAME", |
207 | " GENRC_PID_FROM=SOURCE --pid-from=SOURCE", | 226 | " GENRC_PID_FROM=SOURCE --pid-from=SOURCE", |
208 | " GENRC_TIMEOUT=SECONDS --timeout=SECONDS", | 227 | " GENRC_TIMEOUT=SECONDS --timeout=SECONDS", |
@@ -263,24 +282,26 @@ char const *usage_msg[] = { | |||
263 | "[-c COMMAND]", | 282 | "[-c COMMAND]", |
264 | "[-g GROUP[,GROUP...]]", | 283 | "[-g GROUP[,GROUP...]]", |
265 | "[-p PROGRAM]", | 284 | "[-p PROGRAM]", |
266 | "[-t SECONDS]", | 285 | "[-t SECONDS]", |
267 | "[-u USER]", | 286 | "[-u USER]", |
268 | "[--command=COMMAND]", | 287 | "[--command=COMMAND]", |
269 | "[--group GROUP[,GROUP...]]", | 288 | "[--group GROUP[,GROUP...]]", |
270 | "[--help]", | 289 | "[--help]", |
271 | "[--no-reload]", | 290 | "[--no-reload]", |
272 | "[--pid-from=SOURCE]", | 291 | "[--pid-from=SOURCE]", |
273 | "[--pidfile=PIDFILE]", | 292 | "[--pidfile=PIDFILE]", |
274 | "[--program=PROGRAM]", | 293 | "[--program=PROGRAM]", |
294 | "[--restart-on-exit=[!]CODE[,...]]", | ||
295 | "[--restart-on-signal=[!]SIG[,...]]", | ||
275 | "[--sentinel]", | 296 | "[--sentinel]", |
276 | "[--signal-reload=SIG]", | 297 | "[--signal-reload=SIG]", |
277 | "[--signal-stop=SIG]", | 298 | "[--signal-stop=SIG]", |
278 | "[--timeout=SECONDS]", | 299 | "[--timeout=SECONDS]", |
279 | "[--usage]", | 300 | "[--usage]", |
280 | "[--user=USER]", | 301 | "[--user=USER]", |
281 | "{", | 302 | "{", |
282 | "start", | 303 | "start", |
283 | "|", | 304 | "|", |
284 | "stop", | 305 | "stop", |
285 | "|", | 306 | "|", |
286 | "restart", | 307 | "restart", |
@@ -413,24 +434,30 @@ main(int argc, char **argv) | |||
413 | case 'g': | 434 | case 'g': |
414 | setenv("GENRC_GROUP", optarg, 1); | 435 | setenv("GENRC_GROUP", optarg, 1); |
415 | break; | 436 | break; |
416 | case OPT_CREATE_PIDFILE: | 437 | case OPT_CREATE_PIDFILE: |