From 4121113688f321fdaa02a7ee178a2ba999dd992d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rgen=20Sigvardsson?= Date: Sun, 13 Feb 2022 13:28:44 +0100 Subject: [PATCH] Added implementation for the new command INIT_CMD_SIGNAL. The implementation looks up the named service by using `svc_parse_jobstr`. The callbacks for `svc_parse_jobstr` has been augmented to accept a user data parameter. For this use case, a carrier for the actual signal was needed. The address of the signal parameter is taken and passed on as a `void *`. The callback then simply deferences it as an int - the signal number. --- .gitignore | 2 +- src/api.c | 48 +++++++++++++++++++++++++++++++++++++++--------- src/svc.c | 18 +++++++++--------- src/svc.h | 2 +- 4 files changed, 50 insertions(+), 20 deletions(-) diff --git a/.gitignore b/.gitignore index 55b889b1..4bc8a37a 100644 --- a/.gitignore +++ b/.gitignore @@ -47,4 +47,4 @@ GTAGS /.built # VS Code user settings -.vscode \ No newline at end of file +.vscode diff --git a/src/api.c b/src/api.c index 7a0198f1..f78497f0 100644 --- a/src/api.c +++ b/src/api.c @@ -51,12 +51,12 @@ extern svc_t *wdog; static uev_t api_watcher; -static int call(int (*action)(svc_t *), char *buf, size_t len) +static int call(int (*action)(svc_t *, void *), char *buf, size_t len) { - return svc_parse_jobstr(buf, len, action, NULL); + return svc_parse_jobstr(buf, len, NULL, action, NULL); } -static int stop(svc_t *svc) +static int stop(svc_t *svc, void *user_data) { if (!svc) return 1; @@ -67,7 +67,7 @@ static int stop(svc_t *svc) return 0; } -static int start(svc_t *svc) +static int start(svc_t *svc, void *user_data) { if (!svc) return 1; @@ -83,7 +83,7 @@ static int start(svc_t *svc) * responsibility of initctl to do. Otherwise we'd block PID 1, * or introduce some nasty race conditions. */ -static int restart(svc_t *svc) +static int restart(svc_t *svc, void *user_data) { if (!svc) return 1; @@ -95,7 +95,7 @@ static int restart(svc_t *svc) return 0; } -static int reload(svc_t *svc) +static int reload(svc_t *svc, void *user_data) { if (!svc) return 1; @@ -114,8 +114,32 @@ static int do_start (char *buf, size_t len) { return call(start, buf, len); } static int do_restart(char *buf, size_t len) { return call(restart, buf, len); } static int do_reload (char *buf, size_t len) { return call(reload, buf, len); } +static int do_signal_svc(svc_t *svc, void *user_data) +{ + if (!svc) + return 1; + + if (!svc_is_running(svc)) + return 1; + + int sig = *(int *)user_data; + if (kill(svc->pid, sig)) + return 1; + + return 0; +} + +static int do_signal(char *buf, size_t len, int sig) +{ + /* Sanity check: Do we know this signal!? */ + if (!*sig2str(sig)) + return 1; + + return svc_parse_jobstr(buf, len, &sig, do_signal_svc, NULL); +} + static char query_buf[368]; -static int missing(char *job, char *id) +static int missing(char *job, char *id, void *user_data) { char buf[20]; @@ -133,7 +157,7 @@ static int missing(char *job, char *id) static int do_query(char *buf, size_t len) { query_buf[0] = 0; - if (svc_parse_jobstr(buf, len, NULL, missing)) { + if (svc_parse_jobstr(buf, len, NULL, NULL, missing)) { memcpy(buf, query_buf, len); return 1; } @@ -407,7 +431,7 @@ static void api_cb(uev_t *w, void *arg, int events) if (wdog->protect) { logit(LOG_NOTICE, "Stopping and deleting built-in watchdog."); - stop(wdog); + stop(wdog, NULL); svc_del(wdog); } } @@ -443,6 +467,12 @@ static void api_cb(uev_t *w, void *arg, int events) send_svc(sd, do_find_byc(rq.data, sizeof(rq.data))); goto leave; + case INIT_CMD_SIGNAL: + _d("svc signal %d: %s", rq.runlevel, rq.data); + strterm(rq.data, sizeof(rq.data)); + result = do_signal(rq.data, sizeof(rq.data), rq.runlevel /* runlevel is reused for signal! */); + break; + default: _d("Unsupported cmd: %d", rq.cmd); break; diff --git a/src/svc.c b/src/svc.c index ae61e880..a27ee54f 100644 --- a/src/svc.c +++ b/src/svc.c @@ -650,7 +650,7 @@ static char *tokstr(char *str, size_t len) /* * Used by api.c (to start/stop/restart) and initctl.c (for input validation) */ -int svc_parse_jobstr(char *str, size_t len, int (*found)(svc_t *), int (not_found)(char *, char *)) +int svc_parse_jobstr(char *str, size_t len, void *user_data, int (*found)(svc_t *, void *), int (not_found)(char *, char *, void *)) { char *input, *token; int result = 0; @@ -686,11 +686,11 @@ int svc_parse_jobstr(char *str, size_t len, int (*found)(svc_t *), int (not_foun if (!ptr) { svc = svc_job_iterator(&iter, 1, job); if (!svc && not_found) - result += not_found(NULL, token); + result += not_found(NULL, token, user_data); while (svc) { if (found) - result += found(svc); + result += found(svc, user_data); svc = svc_job_iterator(&iter, 0, job); } } else { @@ -699,19 +699,19 @@ int svc_parse_jobstr(char *str, size_t len, int (*found)(svc_t *), int (not_foun svc = svc_find_by_jobid(job, id); if (!svc && not_found) - result += not_found(token, id); + result += not_found(token, id, user_data); else if (found) - result += found(svc); + result += found(svc, user_data); } } else { if (!ptr) { svc = svc_named_iterator(&iter, 1, token); if (!svc && not_found) - result += not_found(token, id); + result += not_found(token, id, user_data); while (svc) { if (found) - result += found(svc); + result += found(svc, user_data); svc = svc_named_iterator(&iter, 0, token); } } else { @@ -720,9 +720,9 @@ int svc_parse_jobstr(char *str, size_t len, int (*found)(svc_t *), int (not_foun svc = svc_find_by_nameid(token, id); if (!svc && not_found) - result += not_found(token, id); + result += not_found(token, id, user_data); else if (found) - result += found(svc); + result += found(svc, user_data); } } diff --git a/src/svc.h b/src/svc.h index 107acdc8..3a670fe4 100644 --- a/src/svc.h +++ b/src/svc.h @@ -222,7 +222,7 @@ void svc_prune_bootstrap (void); void svc_enable (svc_t *svc); int svc_enabled (svc_t *svc); -int svc_parse_jobstr (char *str, size_t len, int (*found)(svc_t *), int (not_found)(char *, char *)); +int svc_parse_jobstr (char *str, size_t len, void *user_data, int (*found)(svc_t *, void *), int (not_found)(char *, char *, void *)); static inline int svc_is_daemon (svc_t *svc) { return svc && SVC_TYPE_SERVICE == svc->type; } static inline int svc_is_sysv (svc_t *svc) { return svc && SVC_TYPE_SYSV == svc->type; }