aboutsummaryrefslogtreecommitdiff
path: root/initd
diff options
context:
space:
mode:
Diffstat (limited to 'initd')
-rw-r--r--initd/Makemodule.am4
-rw-r--r--initd/env.c137
-rw-r--r--initd/init.h39
-rw-r--r--initd/main.c14
-rw-r--r--initd/runlst.c120
-rw-r--r--initd/runsvc.c66
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;
+}