From 7e9c559c75901f391b4151ed6cabba74e60f80af Mon Sep 17 00:00:00 2001
From: Justus Winter <4winter@informatik.uni-hamburg.de>
Date: Wed, 18 Sep 2013 15:29:36 +0200
Subject: 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.
---
init/Makefile | 24 +++++++++
init/init.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 179 insertions(+)
create mode 100644 init/Makefile
create mode 100644 init/init.c
(limited to 'init')
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 .
+
+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 . */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+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;
+}
--
cgit v1.2.3