From 5f282897317df38bbd96ba567f3a4f1d2f259039 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Mon, 6 Apr 2020 18:27:48 +0200 Subject: cleanup: merge runsvc back into initd Signed-off-by: David Oberhollenzer --- initd/init.h | 3 +- initd/runsvc.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++++---- initd/supervisor.c | 4 +- 3 files changed, 155 insertions(+), 14 deletions(-) (limited to 'initd') diff --git a/initd/init.h b/initd/init.h index 9e8a1fd..c8b1c1d 100644 --- a/initd/init.h +++ b/initd/init.h @@ -24,7 +24,8 @@ #include "service.h" #include "config.h" -#define RUNSVCBIN SCRIPTDIR "/runsvc" +#define ENVFILE ETCPATH "/initd.env" +#define PROCFDDIR "/proc/self/fd" enum { STATUS_OK = 0, diff --git a/initd/runsvc.c b/initd/runsvc.c index 7c1dc36..c45f8ab 100644 --- a/initd/runsvc.c +++ b/initd/runsvc.c @@ -3,23 +3,154 @@ #include #include #include +#include #include +#include +#include +#include #include "init.h" +static int setup_env(void) +{ + int status = -1; + ssize_t ret; + FILE *fp; + + clearenv(); + + fp = fopen(ENVFILE, "r"); + if (fp == NULL) { + perror(ENVFILE); + return -1; + } + + do { + char *line = NULL; + size_t n = 0; + + errno = 0; + ret = getline(&line, &n, fp); + + if (ret < 0) { + if (errno == 0) { + status = 0; + } else { + perror(ENVFILE); + } + } else if (ret > 0 && putenv(line) != 0) { + perror("putenv"); + ret = -1; + } + + free(line); + } while (ret >= 0); + + fclose(fp); + return status; +} + +static int close_all_files(void) +{ + struct dirent *ent; + DIR *dir; + int fd; + + dir = opendir(PROCFDDIR); + if (dir == NULL) { + perror(PROCFDDIR); + return -1; + } + + while ((ent = readdir(dir)) != NULL) { + if (!isdigit(ent->d_name[0])) + continue; + + fd = atoi(ent->d_name); + close(fd); + } + + closedir(dir); + return 0; +} + +static int setup_tty(const char *tty, bool truncate) +{ + int fd; + + if (tty == NULL) + return 0; + + fd = open(tty, O_RDWR); + if (fd < 0) { + perror(tty); + return -1; + } + + if (truncate) + ftruncate(fd, 0); + + setsid(); + + dup2(fd, STDIN_FILENO); + dup2(fd, STDOUT_FILENO); + dup2(fd, STDERR_FILENO); + close(fd); + return 0; +} + +static __attribute__((noreturn)) void argv_exec(exec_t *e) +{ + char **argv = alloca(sizeof(char *) * (e->argc + 1)), *ptr; + int i; + + for (ptr = e->args, i = 0; i < e->argc; ++i, ptr += strlen(ptr) + 1) + argv[i] = ptr; + + argv[i] = NULL; + execvp(argv[0], argv); + perror(argv[0]); + exit(EXIT_FAILURE); +} + +static int run_sequentially(exec_t *list) +{ + pid_t ret, pid; + int status; + + for (; list != NULL; list = list->next) { + if (list->next == NULL) + argv_exec(list); + + pid = fork(); + + if (pid == 0) + argv_exec(list); + + if (pid == -1) { + perror("fork"); + return EXIT_FAILURE; + } + + do { + ret = waitpid(pid, &status, 0); + } while (ret != pid); + + if (!WIFEXITED(status)) + return EXIT_FAILURE; + + if (WEXITSTATUS(status) != EXIT_SUCCESS) + return WEXITSTATUS(status); + } + + return EXIT_SUCCESS; +} + pid_t runsvc(service_t *svc) { - char *argv[4], *envp[1]; sigset_t mask; pid_t pid; - argv[0] = (char *)RUNSVCBIN; - argv[1] = (char *)SVCDIR; - argv[2] = svc->fname; - argv[3] = NULL; - - envp[0] = NULL; - pid = fork(); if (pid == -1) @@ -29,9 +160,18 @@ pid_t runsvc(service_t *svc) sigemptyset(&mask); sigprocmask(SIG_SETMASK, &mask, NULL); - execve(argv[0], argv, envp); - perror(argv[0]); - exit(EXIT_FAILURE); + if (setup_env()) + exit(EXIT_FAILURE); + + if (close_all_files()) + exit(EXIT_FAILURE); + + if (setup_tty(svc->ctty, + (svc->flags & SVC_FLAG_TRUNCATE_OUT) != 0)) { + exit(EXIT_FAILURE); + } + + exit(run_sequentially(svc->exec)); } return pid; diff --git a/initd/supervisor.c b/initd/supervisor.c index 8ac69af..8d53416 100644 --- a/initd/supervisor.c +++ b/initd/supervisor.c @@ -175,7 +175,7 @@ void supervisor_init(void) { int status = STATUS_OK; - if (svcscan(SVCDIR, &cfg, RDSVC_NO_EXEC | RDSVC_NO_CTTY)) + if (svcscan(SVCDIR, &cfg, 0)) status = STATUS_FAIL; target = TGT_BOOT; @@ -191,7 +191,7 @@ void supervisor_reload_config(void) service_t *svc; int i; - if (svcscan(SVCDIR, &newcfg, RDSVC_NO_EXEC | RDSVC_NO_CTTY)) + if (svcscan(SVCDIR, &newcfg, 0)) return; for (i = 0; i < TGT_MAX; ++i) { -- cgit v1.2.3