diff options
Diffstat (limited to 'initd')
-rw-r--r-- | initd/Makemodule.am | 4 | ||||
-rw-r--r-- | initd/env.c | 137 | ||||
-rw-r--r-- | initd/init.h | 39 | ||||
-rw-r--r-- | initd/main.c | 14 | ||||
-rw-r--r-- | initd/runlst.c | 120 | ||||
-rw-r--r-- | initd/runsvc.c | 66 |
6 files changed, 80 insertions, 300 deletions
diff --git a/initd/Makemodule.am b/initd/Makemodule.am index 67515cc..f188c80 100644 --- a/initd/Makemodule.am +++ b/initd/Makemodule.am @@ -1,5 +1,5 @@ -init_SOURCES = initd/main.c initd/runlst.c initd/init.h initd/signal_linux.c -init_SOURCES += initd/status.c initd/mksock.c initd/svclist.c initd/env.c +init_SOURCES = initd/main.c initd/init.h initd/signal_linux.c initd/runsvc.c +init_SOURCES += initd/status.c initd/mksock.c initd/svclist.c init_CPPFLAGS = $(AM_CPPFLAGS) init_CFLAGS = $(AM_CFLAGS) init_LDFLAGS = $(AM_LDFLAGS) diff --git a/initd/env.c b/initd/env.c deleted file mode 100644 index c6a9e65..0000000 --- a/initd/env.c +++ /dev/null @@ -1,137 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-or-later */ -/* - * Copyright (C) 2018 - David Oberhollenzer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - */ -#include <unistd.h> -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include <fcntl.h> - -#include "init.h" -#include "util.h" - -struct entry { - struct entry *next; - char data[]; -}; - -extern char **environ; - -static void free_list(struct entry *list) -{ - struct entry *e; - - while (list != NULL) { - e = list; - list = list->next; - free(e); - } -} - -static struct entry *parse_list(rdline_t *rd) -{ - struct entry *e, *list = NULL; - char *ptr; - - while (rdline(rd) == 0) { - ptr = rd->buffer; - - while (*ptr != '\0' && *ptr != ' ' && *ptr != '=') - ++ptr; - - if (*ptr == ' ') - memmove(ptr, ptr + 1, strlen(ptr + 1) + 1); - - if (*(ptr++) != '=') { - fprintf(stderr, "%s: %zu: line is not of the shape " - "'key = value', skipping\n", - rd->filename, rd->lineno); - continue; - } - - if (*ptr == ' ') - memmove(ptr, ptr + 1, strlen(ptr + 1) + 1); - - if (unescape(ptr)) { - fprintf(stderr, "%s: %zu: malformed string constant, " - "skipping\n", - rd->filename, rd->lineno); - continue; - } - - e = calloc(1, sizeof(*e) + strlen(rd->buffer) + 1); - if (e == NULL) - goto fail_oom; - - strcpy(e->data, rd->buffer); - e->next = list; - list = e; - } - - return list; -fail_oom: - fputs("out of memory\n", stderr); - free_list(list); - return NULL; -} - -static struct entry *list_from_file(void) -{ - struct entry *list; - rdline_t rd; - int fd; - - fd = open(ENVFILE, O_RDONLY); - if (fd < 0) { - perror(ENVFILE); - return NULL; - } - - rdline_init(&rd, fd, ENVFILE, 0, NULL); - list = parse_list(&rd); - close(fd); - return list; -} - -int initenv(void) -{ - struct entry *list, *e; - int i, count; - char **envp; - - list = list_from_file(); - if (list == NULL) - return -1; - - for (count = 0, e = list; e != NULL; e = e->next) - ++count; - - envp = malloc((count + 1) * sizeof(char *)); - if (envp == NULL) { - fputs("out of memory\n", stderr); - free_list(list); - return -1; - } - - for (i = 0, e = list; e != NULL; e = e->next) - envp[i] = e->data; - - envp[i] = NULL; - - environ = envp; - return 0; -} diff --git a/initd/init.h b/initd/init.h index 3510073..d07f310 100644 --- a/initd/init.h +++ b/initd/init.h @@ -27,7 +27,7 @@ #include "telinit.h" #include "util.h" -#define ENVFILE ETCPATH "/initd.env" +#define RUNSVCBIN SCRIPTDIR "/runsvc" enum { STATUS_OK = 0, @@ -36,35 +36,20 @@ enum { STATUS_STARTED, }; -/********** runlst.c **********/ +/********** runsvc.c **********/ /* - Plow through an array of strings and execute each one, i.e. do - a fork() and exec(). + Invoke the runsvc command to execute the comands of a service. - In the parent process, wait() until the child is done before - continuing through the list. - - If ctty is not NULL, open it and redirect all I/O of the child - process to that file. - - If everyhing works, the function returns EXIT_SUCCESS. If one child - does not exit with EXIT_SUCCESS, processing of the list is aborted - and the function returns the exit status of the failed process. + Returns the pid of the child process containing the runsvc instance. */ -int runlst_wait(exec_t *list, const char *ctty); +pid_t runsvc(service_t *svc); /* - Does basically the same as runlst_wait, but asynchronously. - - A child process is created that calls runlst_wait exits with the - result of runlst_wait. In the parent process, the function returns - immediately with the PID of the child process. - - Alternatively, if num is 1, the child process directly exec()s the - given command. + Start a service using runsvc, but wait until the child process + terminats and return its exit status. */ -pid_t runlst(exec_t *list, const char *ctty); +int runsvc_wait(service_t *svc); /********** status.c **********/ @@ -111,14 +96,6 @@ void svclist_add(service_t *svc); */ service_t *svclist_remove(pid_t pid); -/********** env.c **********/ - -/* - Read /etc/initd.env (actually ENVFILE defined above) - and setup environment variables for init. -*/ -int initenv(void); - /********** signal_<platform>.c **********/ /* diff --git a/initd/main.c b/initd/main.c index a1d6906..8adbe2f 100644 --- a/initd/main.c +++ b/initd/main.c @@ -48,7 +48,7 @@ static void handle_exited(service_t *svc) } } - svc->pid = runlst(svc->exec, svc->ctty); + svc->pid = runsvc(svc); if (svc->pid == -1) { print_status(svc->desc, STATUS_FAIL, false); break; @@ -104,16 +104,10 @@ static void start_runlevel(int level) svc = cfg.targets[level]; cfg.targets[level] = svc->next; - if (svc->exec == NULL) { - print_status(svc->desc, STATUS_OK, false); - delsvc(svc); - continue; - } - if (svc->type == SVC_WAIT) { print_status(svc->desc, STATUS_WAIT, false); - status = runlst_wait(svc->exec, svc->ctty); + status = runsvc_wait(svc); print_status(svc->desc, status == EXIT_SUCCESS ? @@ -121,7 +115,7 @@ static void start_runlevel(int level) true); delsvc(svc); } else { - svc->pid = runlst(svc->exec, svc->ctty); + svc->pid = runsvc(svc); if (svc->pid == -1) { print_status(svc->desc, STATUS_FAIL, false); delsvc(svc); @@ -193,7 +187,7 @@ int main(void) return EXIT_FAILURE; } - if (svcscan(SVCDIR, &cfg, 0)) { + if (svcscan(SVCDIR, &cfg, RDSVC_NO_EXEC | RDSVC_NO_CTTY)) { fputs("Error reading service list from " SVCDIR "\n" "Trying to continue anyway\n", stderr); } diff --git a/initd/runlst.c b/initd/runlst.c deleted file mode 100644 index 83823f9..0000000 --- a/initd/runlst.c +++ /dev/null @@ -1,120 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-or-later */ -/* - * Copyright (C) 2018 - David Oberhollenzer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - */ -#include <sys/wait.h> -#include <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <fcntl.h> - -#include "init.h" - -static int child_setup(const char *ctty) -{ - int fd; - - sigreset(); - - if (ctty != NULL) { - fd = open(ctty, O_RDWR); - if (fd < 0) { - perror(ctty); - return -1; - } - - close(STDIN_FILENO); - close(STDOUT_FILENO); - close(STDERR_FILENO); - - setsid(); - - dup2(fd, STDIN_FILENO); - dup2(fd, STDOUT_FILENO); - dup2(fd, STDERR_FILENO); - close(fd); - } - - return 0; -} - -static NORETURN void argv_exec(exec_t *e) -{ - char **argv = alloca(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); -} - -int runlst_wait(exec_t *list, const char *ctty) -{ - pid_t ret, pid; - int status; - - for (; list != NULL; list = list->next) { - pid = fork(); - - if (pid == 0) { - if (child_setup(ctty)) - exit(EXIT_FAILURE); - 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 runlst(exec_t *list, const char *ctty) -{ - pid_t pid = fork(); - - if (pid == 0) { - if (child_setup(ctty)) - exit(EXIT_FAILURE); - - if (list->next != NULL) - exit(runlst_wait(list, NULL)); - - argv_exec(list); - } - - if (pid == -1) - perror("fork"); - - return pid; -} diff --git a/initd/runsvc.c b/initd/runsvc.c new file mode 100644 index 0000000..aba83b1 --- /dev/null +++ b/initd/runsvc.c @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * Copyright (C) 2018 - David Oberhollenzer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> + +#include "init.h" + +pid_t runsvc(service_t *svc) +{ + char *argv[4], *envp[1]; + 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) + perror("fork"); + + if (pid == 0) { + sigreset(); + execve(argv[0], argv, envp); + perror(argv[0]); + exit(EXIT_FAILURE); + } + + return pid; +} + +int runsvc_wait(service_t *svc) +{ + pid_t ret, pid = runsvc(svc); + int status; + + if (pid == -1) + return EXIT_FAILURE; + + do { + ret = waitpid(pid, &status, 0); + } while (ret != pid); + + return WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE; +} |