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 */ +} | 
