From af59174e49b323de4b667e8c968925dbffd1e12c Mon Sep 17 00:00:00 2001 From: Joachim Nilsson Date: Sat, 6 Oct 2012 13:24:22 +0200 Subject: [PATCH] Prevent endless restart of non-existing services and support start-stop scripts Sometimes people type in the wrong path to a service directive in finit.conf, or the executable isn't installed. This commit makes sure to check if the command exists before attempting to start it. This also means that we now require service commands to start with / to indicate an absolute path. We used to search the PATH for a suitable executable, using execvp(), but that's rather insecure as well, so we now use only execv(). Also, added support for adding "start" or "stop" to entries found in /etc/finit.d starting with SNNname, or KNNname, where NN is a number. This makes it possible to simply import sysvinit style start scripts from /etc/rcS.d and /etc/rcN.d/. The alsa-utils plugin also had some minor fixes, added -g option to ignore non-existing soundcards and fixed cut-paste bug on the _d() debug messages. Signed-off-by: Joachim Nilsson --- helpers.c | 12 +++++++++--- plugins/alsa-utils.c | 8 ++++---- svc.c | 19 ++++++++++++++++++- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/helpers.c b/helpers.c index 04bd2cb5..ce9c2326 100644 --- a/helpers.c +++ b/helpers.c @@ -617,11 +617,17 @@ int run_parts(char *dir, ...) qsort(ent, num, sizeof(char *), cmp); for (i = 0; i < num; i++) { + int j = 0, status; pid_t pid = 0; - int status; - args[0] = ent[i]; - args[1] = NULL; + args[j++] = ent[i]; + /* Check if Sservice or Kservice notation is used */ + if (ent[i][0] == 'S' && isdigit(ent[i][1])) { + args[j++] = "start"; + } else if (ent[i][0] == 'K' && isdigit(ent[i][1])) { + args[j++] = "stop"; + } + args[j++] = NULL; pid = fork(); if (!pid) { diff --git a/plugins/alsa-utils.c b/plugins/alsa-utils.c index cf43e263..9100521a 100644 --- a/plugins/alsa-utils.c +++ b/plugins/alsa-utils.c @@ -27,14 +27,14 @@ static void save(void *UNUSED(arg)) { - _d("Saving system clock to RTC ..."); - run_interactive("/usr/sbin/alsactl store > /dev/null 2>&1", "Saving sound settings"); + _d("Saving sound settings ..."); + run_interactive("/usr/sbin/alsactl -g store", "Saving sound settings"); } static void restore(void *UNUSED(arg)) { - _d("Restoring system clock from RTC ..."); - run_interactive("/usr/sbin/alsactl restore > /dev/null 2>&1", "Restoring sound settings"); + _d("Restoring sound settings ..."); + run_interactive("/usr/sbin/alsactl -g restore", "Restoring sound settings"); } static plugin_t plugin = { diff --git a/svc.c b/svc.c index 63431bfd..92a4ee3d 100644 --- a/svc.c +++ b/svc.c @@ -273,6 +273,20 @@ int svc_start(svc_t *svc) sigset_t nmask, omask; char *args[MAX_NUM_SVC_ARGS]; + if (!svc) + return 0; + + /* Don't try and start service if it doesn't exist. */ + if (!fexist(svc->cmd)) { + char msg[80]; + + snprintf(msg, sizeof(msg), "Service %s does not exist!", svc->cmd); + print_desc("", msg); + print_result(1); + + return 0; + } + /* Ignore if finit is SIGSTOP'ed */ if (is_norespawn()) return 0; @@ -329,7 +343,10 @@ int svc_start(svc_t *svc) _e("%starting %s: %s", respawn ? "Res" : "S", svc->cmd, buf); } - execvp(svc->cmd, args); + /* XXX: Maybe change to use execve() to be able to launch scripts? */ + execv(svc->cmd, args); + + /* Only reach this point if exec() fails. */ exit(0); } svc->pid = pid;