#include "driver/driver.h" #include #include #include #include #include #include #include #include #include #include #include void redirect(const char *exe, const char *out, const char *in) { if (!fork()) { static char buf[128]; snprintf(buf, sizeof buf, "sh >%s", out); setproctitle(buf); if (!freopen(out, "a+", stderr)) { fprintf(stdout, "couldn't open %s\n", out); exit(1); } if (!freopen(out, "a+", stdout)) err(1, "couldn't open %s", out); if (!freopen(in, "r", stdin)) err(1, "couldn't open %s", in); // TODO move to /dev/term/ MOUNT_AT("/") { fs_dirinject2((const char*[]){ "/term/", NULL }); } MOUNT_AT("/term/") { termcook(); } int fd = camellia_open("/term/stdin", OPEN_READ); if (fd < 0) { err(1, "open /term/stdin"); } _sys_dup(fd, 0, 0); close(fd); for (;;) { int pid = fork(); if (pid == 0) { // TODO shadow over /term/tokill, as it's an easy thing to miss when sandboxing const char *argv[] = {exe, NULL}; execv(exe, (void*)argv); fprintf(stderr, "init: couldn't start %s\n", exe); exit(1); } else { int len, fd; fd = camellia_open("/term/tokill", OPEN_WRITE); if (fd < 0) { _sys_intr("kill", 4); err(1, "open /term/tokill"); } len = snprintf(buf, sizeof buf, "/proc/%d/intrdown", pid); _sys_write(fd, buf, len, 0, 0); len = snprintf(buf, sizeof buf, "/proc/%d/intr", pid); _sys_write(fd, buf, len, 0, 0); close(fd); _sys_await(); _sys_sleep(1000); } } } } void shutdown(void) { printf("[init] intr\n"); _sys_intr(NULL, 0); _sys_sleep(1000); printf("[init] filicide\n"); _sys_filicide(); printf("[init] goodbye\n"); exit(0); } int main(void) { freopen("/dev/com1", "a+", stdout); freopen("/dev/com1", "a+", stderr); MOUNT_AT("/") { fs_dirinject2((const char*[]){ "/usr/", "/bin/", "/tmp/", "/net/", NULL }); } MOUNT_AT("/dev/keyboard") { MOUNT_AT("/") { fs_whitelist((const char*[]){"/dev/ps2/kb", NULL}); } ps2_drv(); } MOUNT_AT("/usr/") { fs_union((const char*[]){ "/init/usr/", NULL }); } MOUNT_AT("/bin/") { fs_union((const char*[]){ "/init/bin/amd64/", "/init/bin/sh/", "/init/usr/bin/", "/init/usr/local/bin/", NULL }); } MOUNT_AT("/tmp/") { const char *allow[] = {"/bin/tmpfs", NULL}; const char *argv[] = {"/bin/tmpfs", NULL}; MOUNT_AT("/") { fs_whitelist(allow); } execv(argv[0], (void*)argv); } MOUNT_AT("/dev/vtty") { const char *allow[] = {"/bin/vterm", "/dev/video/", "/dev/keyboard", "/init/usr/share/fonts/", NULL}; const char *argv[] = {"/bin/vterm", NULL}; MOUNT_AT("/") { fs_whitelist(allow); } execv(argv[0], (void*)argv); } MOUNT_AT("/net/") { const char *allow[] = {"/bin/netstack", "/dev/eth/", NULL}; const char *argv[] = {"/bin/netstack", "/dev/eth/", "192.168.0.11", "192.168.0.2", NULL}; MOUNT_AT("/") { fs_whitelist(allow); } execv(argv[0], (void*)argv); } MOUNT_AT("/dev/ntp") { const char *allow[] = {"/bin/ntpfs", "/net/connect/", NULL}; const char *argv[] = {"/bin/ntpfs", "/net/connect/0/10.69.0.1/udp/123", NULL}; MOUNT_AT("/") { fs_whitelist(allow); } _sys_sleep(1000); /* hack, waits until the network goes up */ execv(argv[0], (void*)argv); } if (!fork()) { redirect("/bin/shell", "/dev/com1", "/dev/com1"); redirect("/bin/shell", "/dev/vtty", "/dev/keyboard"); exit(1); } intr_set(shutdown); for (;;) { // TODO sleep(-1) to sleep forever // TODO maybe init should collect dead children? _sys_sleep(86400000); } }