summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'sys-apps/busybox/files/ginit.c')
-rw-r--r--sys-apps/busybox/files/ginit.c124
1 files changed, 124 insertions, 0 deletions
diff --git a/sys-apps/busybox/files/ginit.c b/sys-apps/busybox/files/ginit.c
new file mode 100644
index 000000000000..de98e4ac4110
--- /dev/null
+++ b/sys-apps/busybox/files/ginit.c
@@ -0,0 +1,124 @@
+/*
+ * simple init to bootstrap sep-/usr
+ *
+ * Copyright (C) 2012-2013 Mike Frysinger <vapier@gentoo.org>
+ *
+ * Licensed under GPLv2 or later
+ */
+
+//applet:IF_GINIT(APPLET(ginit, BB_DIR_SBIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_GINIT) += ginit.o
+
+//config:config GINIT
+//config: bool "ginit"
+//config: default y
+//config: select MKDIR
+//config: select MDEV
+//config: select MOUNT
+//config: select MOUNTPOINT
+//config: help
+//config: sep-/usr bootstrapper
+
+//usage:#define ginit_trivial_usage NOUSAGE_STR
+//usage:#define ginit_full_usage ""
+
+#include "libbb.h"
+
+#define eprintf(fmt, args...) printf("%s" fmt, "sep-usr init: ", ## args)
+
+static void process_args(char **args)
+{
+ size_t i;
+
+ eprintf("running: ");
+ for (i = 0; args[i]; ++i) {
+ /* String needs to be writable, so dupe it */
+ args[i] = xstrdup(args[i]);
+ printf("'%s' ", args[i]);
+ }
+ printf("\n");
+}
+
+int ginit_main(int argc UNUSED_PARAM, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int ginit_main(int argc UNUSED_PARAM, char **argv)
+{
+ FILE *mntlist;
+ bool ismnted_dev, ismnted_sys, ismnted_usr;
+ struct mntent *mntent;
+
+ /*
+ int fd = open("/dev/console", O_RDWR);
+ if (fd >= 0) {
+ dup2(fd, 0);
+ dup2(fd, 1);
+ dup2(fd, 2);
+ }
+ */
+
+ /* If given an argv[] with an applet name, run it instead.
+ * Makes recovering simple by doing: init=/ginit bb
+ */
+ if (argv[1] && argv[1][0] != '/') {
+ eprintf("running user requested applet %s\n", argv[1]);
+ return spawn_and_wait(argv+1);
+ }
+
+#define saw(argv...) \
+ ({ \
+ static const char *args[] = { argv, NULL }; \
+ /* These casts are fine -- see process_args for mem setup */ \
+ process_args((void *)args); \
+ spawn_and_wait((void *)args); \
+ })
+
+ /* First setup basic /dev */
+ if (saw("mountpoint", "-q", "/dev") != 0) {
+ /* Try /etc/fstab */
+ if (saw("mount", "-n", "/dev"))
+ /* Then devtmpfs */
+ if (saw("mount", "-n", "-t", "devtmpfs", "devtmpfs", "/dev"))
+ /* Finally normal tmpfs */
+ saw("mount", "-n", "-t", "tmpfs", "dev", "/dev");
+ } else {
+ eprintf("%s appears to be mounted; skipping its setup\n", "/dev");
+ }
+
+ /* If /dev is empty (e.g. tmpfs), run mdev to seed things */
+ if (access("/dev/console", F_OK) != 0) {
+ if (saw("mountpoint", "-q", "/sys") != 0) {
+ if (saw("mount", "-n", "/sys"))
+ saw("mount", "-n", "-t", "sysfs", "sysfs", "/sys");
+ } else {
+ eprintf("%s appears to be mounted; skipping its setup\n", "/sys");
+ }
+
+ /* Mount /proc as mdev will fork+exec /proc/self/exe */
+ if (saw("mountpoint", "-q", "/proc") != 0) {
+ /* Try /etc/fstab */
+ if (saw("mount", "-n", "/proc"))
+ saw("mount", "-n", "-t", "proc", "proc", "/proc");
+ }
+
+ saw("mdev", "-s");
+ }
+
+ /* Then seed the stuff we care about */
+ saw("mkdir", "-p", "/dev/pts", "/dev/shm");
+
+ /* Then mount /usr */
+ if (saw("mountpoint", "-q", "/usr") != 0) {
+ saw("mount", "-n", "/usr", "-o", "ro");
+ } else {
+ eprintf("%s appears to be mounted; skipping its setup\n", "/usr");
+ }
+
+ /* Now that we're all done, exec the real init */
+ if (!argv[1]) {
+ argv[0] = (void *)"/sbin/init";
+ argv[1] = NULL;
+ } else
+ ++argv;
+ process_args(argv);
+ return execv(argv[0], argv);
+}