From d0da3b8b98dfe7c2e6caab22ce72e3dbd4614d7e Mon Sep 17 00:00:00 2001 From: Joachim Nilsson Date: Sun, 21 Jun 2015 17:56:41 +0200 Subject: [PATCH] Followup to 'initctl with process name as well as JOBID' Signed-off-by: Joachim Nilsson --- api.c | 105 +++++++++++++++++++++++++----------------------------- helpers.c | 3 ++ svc.c | 23 ++++++++++++ svc.h | 1 + 4 files changed, 75 insertions(+), 57 deletions(-) diff --git a/api.c b/api.c index bfd540d8..3ffd0f05 100644 --- a/api.c +++ b/api.c @@ -41,12 +41,18 @@ uev_t api_watcher; +/* Allowed characters in job/id/name */ +static int isallowed(int ch) +{ + return isalnum(ch) || isspace(ch) || ch == ':'; +} + /* Sanitize user input, make sure to NUL terminate. */ static char *sanitize(char *arg, size_t len) { size_t i = 0; - while ((isalnum(arg[i]) || isspace(arg[i])) && i < len) + while (isallowed(arg[i]) && i < len) i++; if (i + 1 < len) { @@ -57,79 +63,65 @@ static char *sanitize(char *arg, size_t len) return NULL; } -static svc_t *convert(int noid, char *arg, size_t len) -{ - int job, id = 1; - char *token, *ptr; - - arg = sanitize(arg, len); - if (!arg) - return NULL; - - if (noid && (ptr = strchr(arg, ':'))) - ptr = 0; - - token = strtok(arg, ":"); - if (!token) { - job = atoi(arg); - } else { - job = atoi(token); - token = strtok(NULL, ""); - if (token) - id = atoi(token); - } - - _d("Got job %d id %d ...", job, id); - return svc_find_by_jobid(job, id); -} - static int call(int (*action)(svc_t *), char *buf, size_t len) { int result = 0; - char *job = strtok(sanitize(buf, len), " "); + char *input, *token, *pos; - while (job) { + input = sanitize(buf, len); + if (!input) + return -1; + + token = strtok_r(input, " ", &pos); + while (token) { svc_t *svc; - if (isdigit(job[0])) - result += action(convert(0, job, len)); - else - for (svc = svc_named_iterator(1, job); svc; svc = svc_named_iterator(0, job)) - result += action(svc); + if (isdigit(token[0])) { + int job = atonum(token); + char *ptr = strchr(token, ':'); - job = strtok(NULL, " "); + if (!ptr) { + svc = svc_job_iterator(1, job); + while (svc) { + result += action(svc); + svc = svc_job_iterator(0, job); + } + } else { + *ptr++ = 0; + job = atonum(token); + result += action(svc_find_by_jobid(job, atonum(ptr))); + } + + } else { + svc = svc_named_iterator(1, token); + while (svc) { + result += action(svc); + svc = svc_named_iterator(0, token); + } + } + + token = strtok_r(NULL, " ", &pos); } return result; } -static int do_start(char *buf, size_t len) -{ - return call(service_start, buf, len); -} - -static int do_stop(char *buf, size_t len) -{ - return call(service_stop, buf, len); -} - -static int do_reload(char *buf, size_t len) -{ - return call(service_reload, buf, len); -} - -static int do_restart(char *buf, size_t len) -{ - return call(service_restart, buf, len); -} +static int do_start (char *buf, size_t len) { return call(service_start, buf, len); } +static int do_stop (char *buf, size_t len) { return call(service_stop, buf, len); } +static int do_reload (char *buf, size_t len) { return call(service_reload, buf, len); } +static int do_restart(char *buf, size_t len) { return call(service_restart, buf, len); } static int do_query_inetd(char *buf, size_t len) { + char *input = sanitize(buf, len); svc_t *svc; - svc = convert(1, buf, len); + if (!input) + return -1; + + svc = svc_find_by_jobid(atonum(input), 1); if (!svc || !svc_is_inetd(svc)) { - _e("Cannot %s svc %s ...", !svc ? "find" : "query, not an inetd", buf); + _e("Cannot %s svc %s ...", !svc ? "find" : "query, not an inetd", input); return 1; } @@ -151,7 +143,6 @@ static void cb(uev_t *w, void *UNUSED(arg), int UNUSED(events)) int result = 0; ssize_t len; - memset(&rq, 0, sizeof(rq)); len = read(sd, &rq, sizeof(rq)); if (len <= 0) { if (-1 == len) { diff --git a/helpers.c b/helpers.c index bf4fba6b..7757eab8 100644 --- a/helpers.c +++ b/helpers.c @@ -115,6 +115,9 @@ int atonum(char *str) int val; char *end; + if (!str) + return -1; + errno = 0; val = strtol(str, &end, 10); if (errno || end == str) diff --git a/svc.c b/svc.c index f1757d3e..ba5b88f4 100644 --- a/svc.c +++ b/svc.c @@ -195,6 +195,29 @@ svc_t *svc_named_iterator(int first, char *cmd) } +/** + * svc_job_iterator - Iterates over all instances of a service. + * @first: Get first &svc_t object, or next until end. + * @job: Job to look for. + * + * Returns: + * The first matching &svc_t when @first is set, otherwise the next + * &svc_t instance with the same @job until the end when %NULL is + * returned. + */ +svc_t *svc_job_iterator(int first, int job) +{ + svc_t *svc; + + for (svc = svc_iterator(first); svc; svc = svc_iterator(0)) { + if (svc->job == job) + return svc; + } + + return NULL; +} + + /** * svc_foreach - Run a callback for each registered service * @cb: Callback to run for each service diff --git a/svc.h b/svc.h index 1472aafd..99d28245 100644 --- a/svc.h +++ b/svc.h @@ -122,6 +122,7 @@ svc_t *svc_iterator (int first); svc_t *svc_inetd_iterator (int first); svc_t *svc_dynamic_iterator (int first); svc_t *svc_named_iterator (int first, char *cmd); +svc_t *svc_job_iterator (int first, int job); void svc_foreach (void (*cb)(svc_t *)); void svc_foreach_dynamic (void (*cb)(svc_t *));