xref: /plan9/sys/src/cmd/init.c (revision 8498559bac70ac8118e6f36ad9d674181f43f45d)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include <auth.h>
49a747e4fSDavid du Colombier #include <authsrv.h>
53e12c5d1SDavid du Colombier 
69a747e4fSDavid du Colombier char*	readenv(char*);
73e12c5d1SDavid du Colombier void	setenv(char*, char*);
83e12c5d1SDavid du Colombier void	cpenv(char*, char*);
93e12c5d1SDavid du Colombier void	closefds(void);
103e12c5d1SDavid du Colombier void	fexec(void(*)(void));
113e12c5d1SDavid du Colombier void	rcexec(void);
123e12c5d1SDavid du Colombier void	cpustart(void);
133e12c5d1SDavid du Colombier void	pass(int);
143e12c5d1SDavid du Colombier 
153e12c5d1SDavid du Colombier char	*service;
163e12c5d1SDavid du Colombier char	*cmd;
179a747e4fSDavid du Colombier char	*cpu;
189a747e4fSDavid du Colombier char	*systemname;
193e12c5d1SDavid du Colombier int	manual;
203e12c5d1SDavid du Colombier int	iscpu;
213e12c5d1SDavid du Colombier 
223e12c5d1SDavid du Colombier void
main(int argc,char * argv[])233e12c5d1SDavid du Colombier main(int argc, char *argv[])
243e12c5d1SDavid du Colombier {
259a747e4fSDavid du Colombier 	char *user;
269a747e4fSDavid du Colombier 	int fd;
279a747e4fSDavid du Colombier 	char ctl[128];
283e12c5d1SDavid du Colombier 
293e12c5d1SDavid du Colombier 	closefds();
30*8498559bSDavid du Colombier 	alarm(0);
313e12c5d1SDavid du Colombier 
323e12c5d1SDavid du Colombier 	service = "cpu";
333e12c5d1SDavid du Colombier 	manual = 0;
343e12c5d1SDavid du Colombier 	ARGBEGIN{
353e12c5d1SDavid du Colombier 	case 'c':
363e12c5d1SDavid du Colombier 		service = "cpu";
373e12c5d1SDavid du Colombier 		break;
383e12c5d1SDavid du Colombier 	case 'm':
393e12c5d1SDavid du Colombier 		manual = 1;
403e12c5d1SDavid du Colombier 		break;
413e12c5d1SDavid du Colombier 	case 't':
423e12c5d1SDavid du Colombier 		service = "terminal";
433e12c5d1SDavid du Colombier 		break;
443e12c5d1SDavid du Colombier 	}ARGEND
453e12c5d1SDavid du Colombier 	cmd = *argv;
463e12c5d1SDavid du Colombier 
479a747e4fSDavid du Colombier 	snprint(ctl, sizeof(ctl), "#p/%d/ctl", getpid());
489a747e4fSDavid du Colombier 	fd = open(ctl, OWRITE);
499a747e4fSDavid du Colombier 	if(fd < 0)
509a747e4fSDavid du Colombier 		print("init: warning: can't open %s: %r\n", ctl);
519a747e4fSDavid du Colombier 	else
529a747e4fSDavid du Colombier 		if(write(fd, "pri 10", 6) != 6)
539a747e4fSDavid du Colombier 			print("init: warning: can't set priority: %r\n");
549a747e4fSDavid du Colombier 	close(fd);
559a747e4fSDavid du Colombier 
569a747e4fSDavid du Colombier 	cpu = readenv("#e/cputype");
573e12c5d1SDavid du Colombier 	setenv("#e/objtype", cpu);
583e12c5d1SDavid du Colombier 	setenv("#e/service", service);
593e12c5d1SDavid du Colombier 	cpenv("/adm/timezone/local", "#e/timezone");
609a747e4fSDavid du Colombier 	user = readenv("#c/user");
619a747e4fSDavid du Colombier 	systemname = readenv("#c/sysname");
623e12c5d1SDavid du Colombier 
633e12c5d1SDavid du Colombier 	newns(user, 0);
643e12c5d1SDavid du Colombier 	iscpu = strcmp(service, "cpu")==0;
653e12c5d1SDavid du Colombier 
66219b2ee8SDavid du Colombier 	if(iscpu && manual == 0)
673e12c5d1SDavid du Colombier 		fexec(cpustart);
683e12c5d1SDavid du Colombier 
693e12c5d1SDavid du Colombier 	for(;;){
703e12c5d1SDavid du Colombier 		print("\ninit: starting /bin/rc\n");
713e12c5d1SDavid du Colombier 		fexec(rcexec);
723e12c5d1SDavid du Colombier 		manual = 1;
733e12c5d1SDavid du Colombier 		cmd = 0;
743e12c5d1SDavid du Colombier 		sleep(1000);
753e12c5d1SDavid du Colombier 	}
763e12c5d1SDavid du Colombier }
773e12c5d1SDavid du Colombier 
783e12c5d1SDavid du Colombier void
pass(int fd)793e12c5d1SDavid du Colombier pass(int fd)
803e12c5d1SDavid du Colombier {
813e12c5d1SDavid du Colombier 	char key[DESKEYLEN];
823e12c5d1SDavid du Colombier 	char typed[32];
833e12c5d1SDavid du Colombier 	char crypted[DESKEYLEN];
843e12c5d1SDavid du Colombier 	int i;
853e12c5d1SDavid du Colombier 
863e12c5d1SDavid du Colombier 	for(;;){
877dd7cddfSDavid du Colombier 		print("\n%s password:", systemname);
883e12c5d1SDavid du Colombier 		for(i=0; i<sizeof typed; i++){
893e12c5d1SDavid du Colombier 			if(read(0, typed+i, 1) != 1){
903e12c5d1SDavid du Colombier 				print("init: can't read password; insecure\n");
913e12c5d1SDavid du Colombier 				return;
923e12c5d1SDavid du Colombier 			}
933e12c5d1SDavid du Colombier 			if(typed[i] == '\n'){
943e12c5d1SDavid du Colombier 				typed[i] = 0;
953e12c5d1SDavid du Colombier 				break;
963e12c5d1SDavid du Colombier 			}
973e12c5d1SDavid du Colombier 		}
983e12c5d1SDavid du Colombier 		if(i == sizeof typed)
993e12c5d1SDavid du Colombier 			continue;
1003e12c5d1SDavid du Colombier 		if(passtokey(crypted, typed) == 0)
1013e12c5d1SDavid du Colombier 			continue;
1023e12c5d1SDavid du Colombier 		seek(fd, 0, 0);
1033e12c5d1SDavid du Colombier 		if(read(fd, key, DESKEYLEN) != DESKEYLEN){
1043e12c5d1SDavid du Colombier 			print("init: can't read key; insecure\n");
1053e12c5d1SDavid du Colombier 			return;
1063e12c5d1SDavid du Colombier 		}
1073e12c5d1SDavid du Colombier 		if(memcmp(crypted, key, sizeof key))
1083e12c5d1SDavid du Colombier 			continue;
1093e12c5d1SDavid du Colombier 		/* clean up memory */
1103e12c5d1SDavid du Colombier 		memset(crypted, 0, sizeof crypted);
1113e12c5d1SDavid du Colombier 		memset(key, 0, sizeof key);
1123e12c5d1SDavid du Colombier 		return;
1133e12c5d1SDavid du Colombier 	}
1143e12c5d1SDavid du Colombier }
1153e12c5d1SDavid du Colombier 
1167c2ab1f1SDavid du Colombier static int gotnote;
1177c2ab1f1SDavid du Colombier 
1187c2ab1f1SDavid du Colombier void
pinhead(void *,char * msg)1197c2ab1f1SDavid du Colombier pinhead(void*, char *msg)
1207c2ab1f1SDavid du Colombier {
1217c2ab1f1SDavid du Colombier 	gotnote = 1;
1227c2ab1f1SDavid du Colombier 	fprint(2, "init got note '%s'\n", msg);
1237c2ab1f1SDavid du Colombier 	noted(NCONT);
1247c2ab1f1SDavid du Colombier }
1257c2ab1f1SDavid du Colombier 
1263e12c5d1SDavid du Colombier void
fexec(void (* execfn)(void))1273e12c5d1SDavid du Colombier fexec(void (*execfn)(void))
1283e12c5d1SDavid du Colombier {
1299a747e4fSDavid du Colombier 	Waitmsg *w;
1309a747e4fSDavid du Colombier 	int pid;
1313e12c5d1SDavid du Colombier 
1323e12c5d1SDavid du Colombier 	switch(pid=fork()){
1333e12c5d1SDavid du Colombier 	case 0:
1347dd7cddfSDavid du Colombier 		rfork(RFNOTEG);
1353e12c5d1SDavid du Colombier 		(*execfn)();
1363e12c5d1SDavid du Colombier 		print("init: exec error: %r\n");
1373e12c5d1SDavid du Colombier 		exits("exec");
1383e12c5d1SDavid du Colombier 	case -1:
1393e12c5d1SDavid du Colombier 		print("init: fork error: %r\n");
1403e12c5d1SDavid du Colombier 		exits("fork");
1413e12c5d1SDavid du Colombier 	default:
1423e12c5d1SDavid du Colombier 	casedefault:
1437c2ab1f1SDavid du Colombier 		notify(pinhead);
1447c2ab1f1SDavid du Colombier 		gotnote = 0;
1459a747e4fSDavid du Colombier 		w = wait();
1469a747e4fSDavid du Colombier 		if(w == nil){
1477c2ab1f1SDavid du Colombier 			if(gotnote)
1487c2ab1f1SDavid du Colombier 				goto casedefault;
1493e12c5d1SDavid du Colombier 			print("init: wait error: %r\n");
1509a747e4fSDavid du Colombier 			break;
1519a747e4fSDavid du Colombier 		}
1529a747e4fSDavid du Colombier 		if(w->pid != pid){
1539a747e4fSDavid du Colombier 			free(w);
1543e12c5d1SDavid du Colombier 			goto casedefault;
1559a747e4fSDavid du Colombier 		}
1569a747e4fSDavid du Colombier 		if(strstr(w->msg, "exec error") != 0){
1579a747e4fSDavid du Colombier 			print("init: exit string %s\n", w->msg);
1583e12c5d1SDavid du Colombier 			print("init: sleeping because exec failed\n");
1599a747e4fSDavid du Colombier 			free(w);
1603e12c5d1SDavid du Colombier 			for(;;)
1613e12c5d1SDavid du Colombier 				sleep(1000);
1623e12c5d1SDavid du Colombier 		}
1639a747e4fSDavid du Colombier 		if(w->msg[0])
1649a747e4fSDavid du Colombier 			print("init: rc exit status: %s\n", w->msg);
1659a747e4fSDavid du Colombier 		free(w);
1663e12c5d1SDavid du Colombier 		break;
1673e12c5d1SDavid du Colombier 	}
1683e12c5d1SDavid du Colombier }
1693e12c5d1SDavid du Colombier 
1703e12c5d1SDavid du Colombier void
rcexec(void)1713e12c5d1SDavid du Colombier rcexec(void)
1723e12c5d1SDavid du Colombier {
1733e12c5d1SDavid du Colombier 	if(cmd)
174f19e7b74SDavid du Colombier 		execl("/bin/rc", "rc", "-c", cmd, nil);
1753e12c5d1SDavid du Colombier 	else if(manual || iscpu)
176f19e7b74SDavid du Colombier 		execl("/bin/rc", "rc", nil);
1773e12c5d1SDavid du Colombier 	else if(strcmp(service, "terminal") == 0)
178f19e7b74SDavid du Colombier 		execl("/bin/rc", "rc", "-c", ". /rc/bin/termrc; home=/usr/$user; cd; . lib/profile", nil);
1793e12c5d1SDavid du Colombier 	else
180f19e7b74SDavid du Colombier 		execl("/bin/rc", "rc", nil);
1813e12c5d1SDavid du Colombier }
1823e12c5d1SDavid du Colombier 
1833e12c5d1SDavid du Colombier void
cpustart(void)1843e12c5d1SDavid du Colombier cpustart(void)
1853e12c5d1SDavid du Colombier {
186f19e7b74SDavid du Colombier 	execl("/bin/rc", "rc", "-c", "/rc/bin/cpurc", nil);
1873e12c5d1SDavid du Colombier }
1883e12c5d1SDavid du Colombier 
1899a747e4fSDavid du Colombier char*
readenv(char * name)1909a747e4fSDavid du Colombier readenv(char *name)
1913e12c5d1SDavid du Colombier {
1929a747e4fSDavid du Colombier 	int f, len;
1939a747e4fSDavid du Colombier 	Dir *d;
1949a747e4fSDavid du Colombier 	char *val;
1953e12c5d1SDavid du Colombier 
1963e12c5d1SDavid du Colombier 	f = open(name, OREAD);
1973e12c5d1SDavid du Colombier 	if(f < 0){
1989a747e4fSDavid du Colombier 		print("init: can't open %s: %r\n", name);
1999a747e4fSDavid du Colombier 		return "*unknown*";
2003e12c5d1SDavid du Colombier 	}
2019a747e4fSDavid du Colombier 	d = dirfstat(f);
2029a747e4fSDavid du Colombier 	if(d == nil){
2039a747e4fSDavid du Colombier 		print("init: can't stat %s: %r\n", name);
2049a747e4fSDavid du Colombier 		return "*unknown*";
2059a747e4fSDavid du Colombier 	}
2069a747e4fSDavid du Colombier 	len = d->length;
2079a747e4fSDavid du Colombier 	free(d);
2089a747e4fSDavid du Colombier 	if(len == 0)	/* device files can be zero length but have contents */
2099a747e4fSDavid du Colombier 		len = 64;
2109a747e4fSDavid du Colombier 	val = malloc(len+1);
2119a747e4fSDavid du Colombier 	if(val == nil){
2129a747e4fSDavid du Colombier 		print("init: can't malloc %s: %r\n", name);
2139a747e4fSDavid du Colombier 		return "*unknown*";
2149a747e4fSDavid du Colombier 	}
2159a747e4fSDavid du Colombier 	len = read(f, val, len);
2163e12c5d1SDavid du Colombier 	close(f);
2179a747e4fSDavid du Colombier 	if(len < 0){
2189a747e4fSDavid du Colombier 		print("init: can't read %s: %r\n", name);
2199a747e4fSDavid du Colombier 		return "*unknown*";
2209a747e4fSDavid du Colombier 	}else
2213e12c5d1SDavid du Colombier 		val[len] = '\0';
2229a747e4fSDavid du Colombier 	return val;
2233e12c5d1SDavid du Colombier }
2243e12c5d1SDavid du Colombier 
2253e12c5d1SDavid du Colombier void
setenv(char * var,char * val)2263e12c5d1SDavid du Colombier setenv(char *var, char *val)
2273e12c5d1SDavid du Colombier {
2283e12c5d1SDavid du Colombier 	int fd;
2293e12c5d1SDavid du Colombier 
2303e12c5d1SDavid du Colombier 	fd = create(var, OWRITE, 0644);
2313e12c5d1SDavid du Colombier 	if(fd < 0)
2323e12c5d1SDavid du Colombier 		print("init: can't open %s\n", var);
2333e12c5d1SDavid du Colombier 	else{
2343e12c5d1SDavid du Colombier 		fprint(fd, val);
2353e12c5d1SDavid du Colombier 		close(fd);
2363e12c5d1SDavid du Colombier 	}
2373e12c5d1SDavid du Colombier }
2383e12c5d1SDavid du Colombier 
2393e12c5d1SDavid du Colombier void
cpenv(char * file,char * var)2403e12c5d1SDavid du Colombier cpenv(char *file, char *var)
2413e12c5d1SDavid du Colombier {
2423e12c5d1SDavid du Colombier 	int i, fd;
2433e12c5d1SDavid du Colombier 	char buf[8192];
2443e12c5d1SDavid du Colombier 
2453e12c5d1SDavid du Colombier 	fd = open(file, OREAD);
2463e12c5d1SDavid du Colombier 	if(fd < 0)
2473e12c5d1SDavid du Colombier 		print("init: can't open %s\n", file);
2483e12c5d1SDavid du Colombier 	else{
2493e12c5d1SDavid du Colombier 		i = read(fd, buf, sizeof(buf)-1);
2503e12c5d1SDavid du Colombier 		if(i <= 0)
2513e12c5d1SDavid du Colombier 			print("init: can't read %s: %r\n", file);
2523e12c5d1SDavid du Colombier 		else{
2533e12c5d1SDavid du Colombier 			close(fd);
2543e12c5d1SDavid du Colombier 			buf[i] = 0;
2553e12c5d1SDavid du Colombier 			setenv(var, buf);
2563e12c5d1SDavid du Colombier 		}
2573e12c5d1SDavid du Colombier 	}
2583e12c5d1SDavid du Colombier }
2593e12c5d1SDavid du Colombier 
2603e12c5d1SDavid du Colombier /*
2613e12c5d1SDavid du Colombier  *  clean up after /boot
2623e12c5d1SDavid du Colombier  */
2633e12c5d1SDavid du Colombier void
closefds(void)2643e12c5d1SDavid du Colombier closefds(void)
2653e12c5d1SDavid du Colombier {
2663e12c5d1SDavid du Colombier 	int i;
2673e12c5d1SDavid du Colombier 
2683e12c5d1SDavid du Colombier 	for(i = 3; i < 30; i++)
2693e12c5d1SDavid du Colombier 		close(i);
2703e12c5d1SDavid du Colombier }
271