summaryrefslogtreecommitdiff
path: root/init
diff options
context:
space:
mode:
authorJustus Winter <4winter@informatik.uni-hamburg.de>2013-09-18 15:29:36 +0200
committerJustus Winter <4winter@informatik.uni-hamburg.de>2014-11-21 05:49:03 +0100
commit7e9c559c75901f391b4151ed6cabba74e60f80af (patch)
tree12a5189c81b4a13d203a139f698ea15be6e41f8c /init
parent0224d569030e6838c63cf946ae7321be923afc23 (diff)
init: add a minimalist init program
This patch adds a minimalist init program. It is somewhat lacking in features, but is able to bring up a Hurd system with the runsystem and rc scripts. In fact, it roughly does what the former /hurd/init did, modulo all the very early bootstrapping stuff and the startup protocol. It is started when all the essential servers are up and running, so it can make use of most of the POSIX goodies, making its implementation much simpler. * Makefile (prog-subdirs): Add init. * daemons/runsystem.sh: Generalize runsystem so that it can start any init as specified on the kernel command line. By default, it starts /hurd/init. * daemons/runsystem.hurd: This is a verbatim copy of runsystem.sh. It is started by /hurd/init. * daemons/rc.sh: Do not start /hurd/mach-defpager as it is already started in runsystem.sh. * daemons/Makefile (SRCS): Add runsystem.hurd. * init/Makefile: New file. * init/init.c: Likewise.
Diffstat (limited to 'init')
-rw-r--r--init/Makefile24
-rw-r--r--init/init.c155
2 files changed, 179 insertions, 0 deletions
diff --git a/init/Makefile b/init/Makefile
new file mode 100644
index 00000000..07b80261
--- /dev/null
+++ b/init/Makefile
@@ -0,0 +1,24 @@
+#
+# Copyright (C) 2013 Free Software Foundation, Inc.
+#
+# 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 2, 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 <http://www.gnu.org/licenses/>.
+
+dir := init
+makemode := server
+
+SRCS = init.c
+OBJS = $(SRCS:.c=.o)
+target = init
+
+include ../Makeconf
diff --git a/init/init.c b/init/init.c
new file mode 100644
index 00000000..b3d33018
--- /dev/null
+++ b/init/init.c
@@ -0,0 +1,155 @@
+/* A minimalist init for the Hurd
+
+ Copyright (C) 2013,14 Free Software Foundation, Inc.
+ This file is part of the GNU Hurd.
+
+ The GNU Hurd 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 2, or (at your option)
+ any later version.
+
+ The GNU Hurd 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 the Hurd. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <argp.h>
+#include <error.h>
+#include <hurd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <version.h>
+
+const char *argp_program_version = STANDARD_HURD_VERSION (init);
+static pid_t child_pid;
+static int single;
+
+static struct argp_option
+options[] =
+{
+ /* XXX: Currently, -s does nothing. */
+ {"single-user", 's', NULL, 0, "Startup system in single-user mode", 0},
+ {NULL, 'a', NULL, 0, "Ignored for compatibility with sysvinit", 0},
+ {0}
+};
+
+static char doc[] = "A minimalist init for the Hurd";
+
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
+{
+ switch (key)
+ {
+ case 's':
+ single = 1;
+ break;
+
+ case 'a':
+ /* Ignored. */
+ break;
+
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+
+ return 0;
+}
+
+void
+sigchld_handler(int signal)
+{
+ /* A child died. Find its status. */
+ int status;
+ pid_t pid;
+
+ while (1)
+ {
+ pid = waitpid (WAIT_ANY, &status, WNOHANG | WUNTRACED);
+ if (pid <= 0)
+ break; /* No more children. */
+
+ /* Since we are init, orphaned processes get reparented to us and
+ alas, all our adopted children eventually die. Woe is us. We
+ just need to reap the zombies to relieve the proc server of
+ its burden, and then we can forget about the little varmints. */
+
+ if (pid == child_pid)
+ {
+ /* The big magilla bit the dust. */
+ child_pid = -1;
+
+ char *desc = NULL;
+ if (WIFSIGNALED (status))
+ asprintf (&desc, "terminated abnormally (%s)",
+ strsignal (WTERMSIG (status)));
+ else if (WIFSTOPPED (status))
+ asprintf (&desc, "stopped abnormally (%s)",
+ strsignal (WTERMSIG (status)));
+ else if (WEXITSTATUS (status) == 0)
+ desc = strdup ("finished");
+ else
+ asprintf (&desc, "exited with status %d",
+ WEXITSTATUS (status));
+
+ error (0, 0, "child %s", desc);
+ free (desc);
+
+ /* XXX: launch emergency shell. */
+ error (23, 0, "panic!!");
+ }
+ }
+}
+
+int
+main (int argc, char **argv)
+{
+ struct argp argp =
+ {
+ .options = options,
+ .parser = parse_opt,
+ .doc = doc,
+ };
+ argp_parse (&argp, argc, argv, 0, 0, 0);
+
+ if (getpid () != 1)
+ error (1, 0, "can only be run as PID 1");
+
+ struct sigaction sa;
+ sa.sa_handler = SIG_IGN;
+ sa.sa_flags = 0;
+ sigemptyset (&sa.sa_mask);
+
+ sigaction (SIGHUP, &sa, NULL);
+ sigaction (SIGINT, &sa, NULL);
+ sigaction (SIGQUIT, &sa, NULL);
+ sigaction (SIGTERM, &sa, NULL);
+ sigaction (SIGUSR1, &sa, NULL);
+ sigaction (SIGUSR2, &sa, NULL);
+ sigaction (SIGTSTP, &sa, NULL);
+
+ sa.sa_handler = sigchld_handler;
+ sa.sa_flags |= SA_RESTART;
+ sigaction (SIGCHLD, &sa, NULL);
+
+ char *args[] = { "/etc/hurd/runsystem.hurd", NULL };
+
+ switch (child_pid = fork ())
+ {
+ case -1:
+ error (1, errno, "failed to fork");
+ case 0:
+ execv (args[0], args);
+ error (2, errno, "failed to execv child");
+ }
+
+ select (0, NULL, NULL, NULL, NULL);
+ /* Not reached. */
+ return 0;
+}