aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--cmd/Makemodule.am8
-rw-r--r--cmd/runsvc/env.c (renamed from initd/env.c)9
-rw-r--r--cmd/runsvc/runsvc.c (renamed from initd/runlst.c)72
-rw-r--r--cmd/runsvc/runsvc.h36
-rw-r--r--initd/Makemodule.am4
-rw-r--r--initd/init.h39
-rw-r--r--initd/main.c14
-rw-r--r--initd/runsvc.c66
-rw-r--r--services/sysinit2
-rw-r--r--services/vfs2
11 files changed, 172 insertions, 81 deletions
diff --git a/.gitignore b/.gitignore
index a0967e2..6c13aba 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,6 +19,7 @@ service
reboot
shutdown
killall5
+runsvc
services/sigkill
services/sigterm
diff --git a/cmd/Makemodule.am b/cmd/Makemodule.am
index f0ae3f9..83d6174 100644
--- a/cmd/Makemodule.am
+++ b/cmd/Makemodule.am
@@ -10,6 +10,12 @@ reboot_CFLAGS = $(AM_CFLAGS)
reboot_LDFLAGS = $(AM_LDFLAGS)
reboot_LDADD = libinit.a
+runsvc_SOURCES = cmd/runsvc/runsvc.c cmd/runsvc/env.c cmd/runsvc/runsvc.h
+runsvc_CPPFLAGS = $(AM_CPPFLAGS)
+runsvc_CFLAGS = $(AM_CFLAGS)
+runsvc_LDFLAGS = $(AM_LDFLAGS)
+runsvc_LDADD = libinit.a
+
killall5_SOURCES = cmd/killall5.c
killall5_CPPFLAGS = $(AM_CPPFLAGS)
killall5_CFLAGS = $(AM_CFLAGS)
@@ -29,4 +35,4 @@ service_LDADD = libinit.a
EXTRA_DIST += $(SRVHEADERS)
sbin_PROGRAMS += service reboot shutdown
-helper_PROGRAMS += killall5
+helper_PROGRAMS += killall5 runsvc
diff --git a/initd/env.c b/cmd/runsvc/env.c
index c6a9e65..4fe2368 100644
--- a/initd/env.c
+++ b/cmd/runsvc/env.c
@@ -15,14 +15,7 @@
* 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"
+#include "runsvc.h"
struct entry {
struct entry *next;
diff --git a/initd/runlst.c b/cmd/runsvc/runsvc.c
index 83823f9..a8e5bb2 100644
--- a/initd/runlst.c
+++ b/cmd/runsvc/runsvc.c
@@ -15,21 +15,12 @@
* 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 "runsvc.h"
-#include "init.h"
-
-static int child_setup(const char *ctty)
+static int setup_tty(const char *ctty)
{
int fd;
- sigreset();
-
if (ctty != NULL) {
fd = open(ctty, O_RDWR);
if (fd < 0) {
@@ -52,6 +43,8 @@ static int child_setup(const char *ctty)
return 0;
}
+/*****************************************************************************/
+
static NORETURN void argv_exec(exec_t *e)
{
char **argv = alloca(e->argc + 1), *ptr;
@@ -66,7 +59,7 @@ static NORETURN void argv_exec(exec_t *e)
exit(EXIT_FAILURE);
}
-int runlst_wait(exec_t *list, const char *ctty)
+static int runlst_wait(exec_t *list)
{
pid_t ret, pid;
int status;
@@ -74,11 +67,8 @@ int runlst_wait(exec_t *list, const char *ctty)
for (; list != NULL; list = list->next) {
pid = fork();
- if (pid == 0) {
- if (child_setup(ctty))
- exit(EXIT_FAILURE);
+ if (pid == 0)
argv_exec(list);
- }
if (pid == -1) {
perror("fork");
@@ -99,22 +89,50 @@ int runlst_wait(exec_t *list, const char *ctty)
return EXIT_SUCCESS;
}
-pid_t runlst(exec_t *list, const char *ctty)
+/*****************************************************************************/
+
+int main(int argc, char **argv)
{
- pid_t pid = fork();
+ int dirfd, ret = EXIT_FAILURE;
+ service_t *svc = NULL;
+
+ if (argc != 3) {
+ fputs("usage: runsvc <directory> <filename>\n", stderr);
+ goto out;
+ }
+
+ if (getppid() != 1) {
+ fputs("must be run by init!\n", stderr);
+ goto out;
+ }
- if (pid == 0) {
- if (child_setup(ctty))
- exit(EXIT_FAILURE);
+ dirfd = open(argv[1], O_RDONLY | O_DIRECTORY);
+ if (dirfd < 0) {
+ perror(argv[1]);
+ goto out;
+ }
- if (list->next != NULL)
- exit(runlst_wait(list, NULL));
+ svc = rdsvc(dirfd, argv[2], RDSVC_NO_FNAME | RDSVC_NO_DEPS);
+ close(dirfd);
+ if (svc == NULL)
+ goto out;
- argv_exec(list);
+ if (svc->exec == NULL) {
+ ret = EXIT_SUCCESS;
+ goto out;
}
- if (pid == -1)
- perror("fork");
+ if (initenv())
+ goto out;
+
+ if (setup_tty(svc->ctty))
+ goto out;
+
+ if (svc->exec->next == NULL)
+ argv_exec(svc->exec);
- return pid;
+ ret = runlst_wait(svc->exec);
+out:
+ delsvc(svc);
+ return ret;
}
diff --git a/cmd/runsvc/runsvc.h b/cmd/runsvc/runsvc.h
new file mode 100644
index 0000000..15785d3
--- /dev/null
+++ b/cmd/runsvc/runsvc.h
@@ -0,0 +1,36 @@
+/* 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/>.
+ */
+#ifndef RUNSVC_H
+#define RUNSVC_H
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <fcntl.h>
+
+#include "service.h"
+#include "util.h"
+
+#define ENVFILE ETCPATH "/initd.env"
+
+int initenv(void);
+
+#endif /* RUNSVC_H */
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/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/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;
+}
diff --git a/services/sysinit b/services/sysinit
index cb5eb6b..0429dfe 100644
--- a/services/sysinit
+++ b/services/sysinit
@@ -1,3 +1,3 @@
description basic system initialization
-type once
+type wait
target boot
diff --git a/services/vfs b/services/vfs
index 27cc9e9..471d8c1 100644
--- a/services/vfs
+++ b/services/vfs
@@ -1,3 +1,3 @@
description VFS setup done
-type once
+type wait
target boot