diff options
Diffstat (limited to 'sinit.c')
-rw-r--r-- | sinit.c | 119 |
1 files changed, 114 insertions, 5 deletions
@@ -1,18 +1,27 @@ /* See LICENSE file for copyright and license details. */ +#include <sys/reboot.h> #include <sys/types.h> #include <sys/wait.h> +#include <sys/mount.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <grp.h> +#include <err.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> +#include <time.h> #define LEN(x) (sizeof (x) / sizeof *(x)) static void sigpoweroff(void); static void sigreap(void); static void sigreboot(void); -static void spawn(char *const []); +static void spawn(int (*)(), char *const []); +static void spawn_as(uid_t, gid_t, char *const [], char *const []); +static void mounts(void); static struct { int sig; @@ -35,10 +44,24 @@ main(void) if (getpid() != 1) return 1; + +#ifdef PERF + spawn(NULL, perf); +#endif + chdir("/"); + sethostname(HOSTNAME, sizeof(HOSTNAME)-1); + mounts(); sigfillset(&set); sigprocmask(SIG_BLOCK, &set, NULL); - spawn(rcinitcmd); + ioctl(STDIN_FILENO, TIOCNOTTY, 0); + + for (i=0;i < LEN(init_procs);i++) { + spawn(init_procs[i].dep, init_procs[i].argv); + } + for (i=0;i < LEN(user_procs);i++) { + spawn_as(uid, gid, user_env, user_procs[i]); + } while (1) { sigwait(&set, &sig); for (i = 0; i < LEN(sigmap); i++) { @@ -53,9 +76,25 @@ main(void) } static void +kill_wait(void) +{ + int i; + + for (i=0;i < 4 && kill(-1, i>=3 ? SIGKILL:SIGTERM) == 0;i++) { + /* printf("killall %d\n", i); */ + sleep(1); + } +} + +static void sigpoweroff(void) { - spawn(rcpoweroffcmd); + sigprocmask(SIG_BLOCK, &set, NULL); + kill_wait(); + sync(); + reboot(RB_POWER_OFF); + /* only reachable on error */ + perror("poweroff"); } static void @@ -68,16 +107,31 @@ sigreap(void) static void sigreboot(void) { - spawn(rcrebootcmd); + sigprocmask(SIG_BLOCK, &set, NULL); + kill_wait(); + sync(); + reboot(RB_AUTOBOOT); + /* only reachable on error */ + perror("reboot"); } static void -spawn(char *const argv[]) +spawn(int (*dep)(), char *const argv[]) + { + struct timespec delay = { + .tv_nsec = 1000, + .tv_sec = 0, + }; + switch (fork()) { case 0: sigprocmask(SIG_UNBLOCK, &set, NULL); setsid(); + if (dep != NULL) { + while (!dep()) nanosleep(&delay, NULL); + } + /* printf("spawn: %s\n", argv[0]); */ execvp(argv[0], argv); perror("execvp"); _exit(1); @@ -85,3 +139,58 @@ spawn(char *const argv[]) perror("fork"); } } + +static void +spawn_as(uid_t uid, gid_t gid, char *const env[], char *const argv[]) +{ + /* printf("spawn_as %d,%d: %s\n", uid, gid, argv[0]); */ + switch (fork()) { + case 0: + chdir("/home/nick"); + sigprocmask(SIG_UNBLOCK, &set, NULL); + setsid(); + ioctl(STDIN_FILENO, TIOCSCTTY, 0); + setgid(gid); + setgroups(LEN(groups), groups); + setuid(uid); + execve(argv[0], argv, env); + perror("execve"); + _exit(1); + case -1: + perror("fork"); + } +} + +static void +mounts(void) +{ + int i; + mkdir("/dev/pts", 0755); + mkdir("/dev/shm", 0755); + for (i=0;i < LEN(static_mounts);i++) { + if (mount(static_mounts[i].source, + static_mounts[i].target, + static_mounts[i].type, + static_mounts[i].flags, + static_mounts[i].data) != 0) + { + warn("mount %s", static_mounts[i].target); + } + + } +} + +int +wpa_started(void) +{ + return ! access("/var/run/wpa_supplicant/wlan0", O_RDONLY); +} + +int +udev_settled(void) +{ + struct stat info; + if (stat("/dev/input/event4", &info)) + return 0; + return info.st_gid == 97; /* input group */ +} |