/* * simple init to bootstrap sep-/usr * * Copyright (C) 2012-2013 Mike Frysinger * * 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); }