diff options
Diffstat (limited to 'sys-apps/busybox/files/ginit.c')
-rw-r--r-- | sys-apps/busybox/files/ginit.c | 124 |
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); +} |