aboutsummaryrefslogtreecommitdiff
path: root/sinit.c
diff options
context:
space:
mode:
Diffstat (limited to 'sinit.c')
-rw-r--r--sinit.c119
1 files changed, 114 insertions, 5 deletions
diff --git a/sinit.c b/sinit.c
index 93f9925..6e3c5d8 100644
--- a/sinit.c
+++ b/sinit.c
@@ -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 */
+}