├── LICENSE ├── Makefile ├── README ├── init.c ├── shutdown.c └── spawn.c /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS=-Wall 2 | all: init shutdown spawn 3 | init: init.c 4 | shutdown: shutdown.c 5 | spawn: spawn.c 6 | 7 | clean: 8 | -rm -f init shutdown spawn 9 | 10 | install: 11 | -install -m 755 init $(DESTDIR)/sbin 12 | -install -m 755 shutdown $(DESTDIR)/sbin 13 | -install -m 755 spawn $(DESTDIR)/sbin 14 | -ln -sf shutdown $(DESTDIR)/sbin/reboot 15 | -ln -sf shutdown $(DESTDIR)/sbin/halt 16 | -ln -sf shutdown $(DESTDIR)/sbin/poweroff 17 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | uinit -- smallest init possible 2 | 3 | This init just executes scripts and reaps zombies. It does nothing more beyond that. 4 | 5 | Included programs are: 6 | shutdown: standard minimal shutdown(8) (also signals init when called as reboot, halt or poweroff) 7 | spawn: reexecutes specified program until killed 8 | 9 | The code is in public domain. 10 | Thanks to Rich Felker's EWONTFIX blog post (http://ewontfix.com/14/) about sane init system. 11 | Spawn program is inspired by ninit's spawn, but completely rewritten. 12 | -------------------------------------------------------------------------------- /init.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This code is in public domain 3 | */ 4 | 5 | #define _XOPEN_SOURCE 700 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | typedef void (*sighandler_t)(int); 14 | 15 | static void sighandl(int sig) 16 | { 17 | if (fork()) return; 18 | 19 | switch (sig) { 20 | case SIGINT: 21 | execv("/etc/init/cad", (char *[]){"cad", NULL}); 22 | break; 23 | 24 | case SIGALRM: 25 | execv("/etc/init/reboot", (char *[]){"reboot", NULL}); 26 | break; 27 | 28 | case SIGQUIT: 29 | execv("/etc/init/poweroff", (char *[]){"poweroff", NULL}); 30 | break; 31 | 32 | case SIGABRT: 33 | execv("/etc/init/shutdown", (char *[]){"shutdown", NULL}); 34 | break; 35 | 36 | #ifdef SIGPWR 37 | case SIGPWR: 38 | execv("/etc/init/pwrfail", (char *[]){"pwrfail", NULL}); 39 | break; 40 | #endif 41 | } 42 | } 43 | 44 | int main(void) 45 | { 46 | sigset_t set; 47 | int status; 48 | 49 | if (getpid() != 1) return 1; 50 | 51 | if (!access("/etc/init/altinit", X_OK) && !getenv("_INIT")) 52 | execv("/etc/init/altinit", (char *[]){"init", NULL}); 53 | 54 | reboot(RB_DISABLE_CAD); 55 | 56 | sigfillset(&set); 57 | sigprocmask(SIG_BLOCK, &set, NULL); 58 | 59 | if (fork()) { 60 | sigprocmask(SIG_UNBLOCK, &set, NULL); 61 | sigdelset(&set, SIGINT); 62 | sigdelset(&set, SIGALRM); 63 | sigdelset(&set, SIGQUIT); 64 | sigdelset(&set, SIGABRT); 65 | #ifdef SIGPWR 66 | sigdelset(&set, SIGPWR); 67 | #endif 68 | sigprocmask(SIG_BLOCK, &set, NULL); 69 | signal(SIGINT, sighandl); 70 | signal(SIGALRM, sighandl); 71 | signal(SIGQUIT, sighandl); 72 | signal(SIGABRT, sighandl); 73 | #ifdef SIGPWR 74 | signal(SIGPWR, sighandl); 75 | #endif 76 | 77 | for (;;) wait(&status); 78 | } 79 | 80 | sigprocmask(SIG_UNBLOCK, &set, NULL); 81 | 82 | setsid(); 83 | setpgid(0, 0); 84 | return execv("/etc/init/boot", (char *[]){"boot", NULL}); 85 | } 86 | -------------------------------------------------------------------------------- /shutdown.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This code is in public domain 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | static int usage(void) 15 | { 16 | puts("usage: shutdown [-rhpcCS] [-t sec]"); 17 | puts("usage: reboot"); 18 | puts("usage: halt"); 19 | puts("usage: poweroff"); 20 | puts(" -c: c-a-d INTs init"); 21 | puts(" -C: c-a-d quickly reboots"); 22 | puts(" -S: do not call sync()"); 23 | puts(" -t sec: delay shutdown by sec"); 24 | return 1; 25 | } 26 | 27 | int main(int argc, char **argv) 28 | { 29 | int c, r, h, p, S; 30 | int t; 31 | 32 | t = r = h = p = S = 0; 33 | 34 | if (!strcmp(basename(*argv), "reboot")) { kill(1, SIGALRM); return 0; } 35 | if (!strcmp(basename(*argv), "halt")) { kill(1, SIGABRT); return 0; } 36 | if (!strcmp(basename(*argv), "poweroff")) { kill(1, SIGQUIT); return 0; } 37 | 38 | while ((c = getopt(argc, argv, "rhpcCSt:")) != -1) { 39 | switch (c) { 40 | case 'r': r = 1; break; 41 | case 'h': h = 1; break; 42 | case 'p': p = 1; break; 43 | case 'c': r = 2; break; 44 | case 'C': r = 3; break; 45 | case 'S': S = 1; break; 46 | case 't': t = atoi(optarg); break; 47 | default: return usage(); 48 | } 49 | } 50 | 51 | if (t) sleep(t); 52 | 53 | if (!S) sync(); 54 | if (r) { 55 | if (r == 2) reboot(RB_DISABLE_CAD); 56 | else if (r == 3) reboot(RB_ENABLE_CAD); 57 | else reboot(RB_AUTOBOOT); 58 | } 59 | else if (h) reboot(RB_HALT_SYSTEM); 60 | else if (p) reboot(RB_POWER_OFF); 61 | else return usage(); 62 | 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /spawn.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This code is in public domain 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | typedef void (*sighandler_t)(int); 15 | 16 | static void sighandl(int sig) 17 | { 18 | switch (sig) { 19 | case SIGTERM: 20 | case SIGINT: 21 | exit(0); 22 | case SIGCHLD: 23 | while (waitpid(0, NULL, WNOHANG) >= 0); 24 | break; 25 | } 26 | } 27 | 28 | int main(int argc, char **argv) 29 | { 30 | sigset_t set; 31 | pid_t x, y; 32 | int f; 33 | int c; char *tty = "/dev/console"; int t = 0, T = -1; 34 | 35 | opterr = 0; 36 | while ((c = getopt(argc, argv, "c:t:T:")) != -1) { 37 | switch (c) { 38 | case 'c': tty = optarg; break; 39 | case 't': t = atoi(optarg); break; 40 | case 'T': T = atoi(optarg); break; 41 | default: exit(1); 42 | } 43 | } 44 | 45 | if (!*(argv+optind)) return 1; 46 | 47 | sigfillset(&set); 48 | sigdelset(&set, SIGCHLD); 49 | sigdelset(&set, SIGTERM); 50 | sigdelset(&set, SIGINT); 51 | sigprocmask(SIG_BLOCK, &set, NULL); 52 | signal(SIGCHLD, sighandl); 53 | signal(SIGTERM, sighandl); 54 | signal(SIGINT, sighandl); 55 | 56 | if (fork()) return 0; 57 | 58 | setsid(); 59 | while (1) { 60 | if ((x = fork())) { 61 | while (1) { 62 | y = waitpid(x, NULL, 0); 63 | if (y == x) break; 64 | if (y == -1 && errno != EINTR) break; 65 | } 66 | } 67 | else { 68 | setsid(); 69 | if ((f = open(tty, O_RDWR | O_NOCTTY)) != -1) { 70 | close(0); 71 | dup2(f, 0); 72 | close(1); 73 | dup2(f, 1); 74 | close(2); 75 | dup2(f, 2); 76 | if (f > 2) close(f); 77 | } 78 | else return 2; 79 | 80 | sigfillset(&set); 81 | sigprocmask(SIG_UNBLOCK, &set, NULL); 82 | 83 | argv += optind; 84 | execv(*argv, argv); 85 | return 127; 86 | } 87 | 88 | usleep(t); 89 | if (T != -1) T--; 90 | if (T == 0) break; 91 | } 92 | 93 | return 0; 94 | } 95 | --------------------------------------------------------------------------------