xref: /csrg-svn/old/init/init.c (revision 1403)
11029Sbill #include <signal.h>
21029Sbill #include <sys/types.h>
31029Sbill #include <utmp.h>
41029Sbill #include <setjmp.h>
5*1403Sbill #include <sys/reboot.h>
61029Sbill 
71029Sbill #define	LINSIZ	sizeof(wtmp.ut_line)
81029Sbill #define	TABSIZ	100
91029Sbill #define	ALL	p = &itab[0]; p < &itab[TABSIZ]; p++
101029Sbill #define	EVER	;;
111029Sbill #define SCPYN(a, b)	strncpy(a, b, sizeof(a))
121029Sbill #define SCMPN(a, b)	strncmp(a, b, sizeof(a))
131029Sbill 
141029Sbill char	shell[]	= "/bin/sh";
15*1403Sbill char	getty[]	 = "/etc/getty";
161029Sbill char	minus[]	= "-";
171029Sbill char	runc[]	= "/etc/rc";
181029Sbill char	ifile[]	= "/etc/ttys";
191029Sbill char	utmp[]	= "/etc/utmp";
201029Sbill char	wtmpf[]	= "/usr/adm/wtmp";
211029Sbill char	ctty[]	= "/dev/console";
221029Sbill char	dev[]	= "/dev/";
231029Sbill 
241029Sbill struct utmp wtmp;
251029Sbill struct
261029Sbill {
271029Sbill 	char	line[LINSIZ];
281029Sbill 	char	comn;
291029Sbill 	char	flag;
301029Sbill } line;
311029Sbill struct	tab
321029Sbill {
331029Sbill 	char	line[LINSIZ];
341029Sbill 	char	comn;
351029Sbill 	char	xflag;
361029Sbill 	int	pid;
371029Sbill } itab[TABSIZ];
381029Sbill 
391029Sbill int	fi;
401029Sbill int	mergflag;
411029Sbill char	tty[20];
421029Sbill jmp_buf	sjbuf;
431029Sbill 
441029Sbill int	reset();
451029Sbill char	*strcpy(), *strcat();
461029Sbill long	lseek();
471029Sbill 
481029Sbill main()
491029Sbill {
50*1403Sbill 	register int r11;		/* passed thru from boot */
51*1403Sbill 	int howto, oldhowto;
52*1403Sbill 
53*1403Sbill 	howto = r11;
541029Sbill 	setjmp(sjbuf);
551029Sbill 	signal(SIGTERM, reset);
561029Sbill 	signal(SIGSTOP, SIG_IGN);
571029Sbill 	signal(SIGTSTP, SIG_IGN);
581029Sbill 	signal(SIGTTIN, SIG_IGN);
591029Sbill 	signal(SIGTTOU, SIG_IGN);
601029Sbill 	for(EVER) {
61*1403Sbill 		oldhowto = howto;
62*1403Sbill 		howto = RB_SINGLE;
631029Sbill 		shutdown();
64*1403Sbill 		if (oldhowto & RB_SINGLE)
65*1403Sbill 			single();
66*1403Sbill 		if (runcom(oldhowto) == 0)
67*1403Sbill 			continue;
681029Sbill 		merge();
691029Sbill 		multiple();
701029Sbill 	}
711029Sbill }
721029Sbill 
731029Sbill shutdown()
741029Sbill {
751029Sbill 	register i;
761029Sbill 	register struct tab *p;
771029Sbill 
781029Sbill 	close(creat(utmp, 0644));
791029Sbill 	signal(SIGHUP, SIG_IGN);
801029Sbill 	for(ALL) {
811029Sbill 		term(p);
821029Sbill 		p->line[0] = 0;
831029Sbill 	}
841029Sbill 	signal(SIGALRM, reset);
851029Sbill 	alarm(60);
861029Sbill 	for(i=0; i<5; i++)
871029Sbill 		kill(-1, SIGKILL);
881029Sbill 	while(wait((int *)0) != -1)
891029Sbill 		;
901029Sbill 	alarm(0);
911029Sbill 	signal(SIGALRM, SIG_DFL);
921029Sbill 	for(i=0; i<10; i++)
931029Sbill 		close(i);
941029Sbill }
951029Sbill 
961029Sbill single()
971029Sbill {
981029Sbill 	register pid;
991029Sbill 
1001029Sbill 	pid = fork();
1011029Sbill 	if(pid == 0) {
1021029Sbill /*
1031029Sbill 		alarm(300);
1041029Sbill */
1051029Sbill 		signal(SIGTERM, SIG_DFL);
1061029Sbill 		signal(SIGHUP, SIG_DFL);
1071029Sbill 		signal(SIGALRM, SIG_DFL);
1081029Sbill 		open(ctty, 2);
1091029Sbill 		dup(0);
1101029Sbill 		dup(0);
1111029Sbill 		execl(shell, minus, (char *)0);
1121029Sbill 		exit(0);
1131029Sbill 	}
1141029Sbill 	while(wait((int *)0) != pid)
1151029Sbill 		;
1161029Sbill }
1171029Sbill 
118*1403Sbill runcom(oldhowto)
119*1403Sbill 	int oldhowto;
1201029Sbill {
1211029Sbill 	register pid, f;
122*1403Sbill 	int status;
1231029Sbill 
1241029Sbill 	pid = fork();
1251029Sbill 	if(pid == 0) {
1261029Sbill 		open("/", 0);
1271029Sbill 		dup(0);
1281029Sbill 		dup(0);
129*1403Sbill 		if (oldhowto & RB_SINGLE)
130*1403Sbill 			execl(shell, shell, runc, (char *)0);
131*1403Sbill 		else
132*1403Sbill 			execl(shell, shell, runc, "autoboot", (char *)0);
133*1403Sbill 		exit(1);
1341029Sbill 	}
135*1403Sbill 	while(wait(&status) != pid)
1361029Sbill 		;
137*1403Sbill 	if(status)
138*1403Sbill 		return(0);
1391029Sbill 	f = open(wtmpf, 1);
1401029Sbill 	if (f >= 0) {
1411029Sbill 		lseek(f, 0L, 2);
1421029Sbill 		SCPYN(wtmp.ut_line, "~");
1431029Sbill 		SCPYN(wtmp.ut_name, "reboot");
1441029Sbill 		time(&wtmp.ut_time);
1451029Sbill 		write(f, (char *)&wtmp, sizeof(wtmp));
1461029Sbill 		close(f);
1471029Sbill 	}
148*1403Sbill 	return(1);
1491029Sbill }
1501029Sbill 
1511029Sbill setmerge()
1521029Sbill {
1531029Sbill 
1541029Sbill 	signal(SIGHUP, setmerge);
1551029Sbill 	mergflag = 1;
1561029Sbill }
1571029Sbill 
1581029Sbill multiple()
1591029Sbill {
1601029Sbill 	register struct tab *p;
1611029Sbill 	register pid;
1621029Sbill 
1631029Sbill loop:
1641029Sbill 	mergflag = 0;
1651029Sbill 	signal(SIGHUP, setmerge);
1661029Sbill 	for(EVER) {
1671029Sbill 		pid = wait((int *)0);
1681029Sbill 		if(mergflag) {
1691029Sbill 			merge();
1701029Sbill 			goto loop;
1711029Sbill 		}
1721029Sbill 		if(pid == -1)
1731029Sbill 			return;
1741029Sbill 		for(ALL)
1751029Sbill 			if(p->pid == pid || p->pid == -1) {
1761029Sbill 				rmut(p);
1771029Sbill 				dfork(p);
1781029Sbill 			}
1791029Sbill 	}
1801029Sbill }
1811029Sbill 
1821029Sbill term(p)
1831029Sbill register struct tab *p;
1841029Sbill {
1851029Sbill 
1861029Sbill 	if(p->pid != 0) {
1871029Sbill 		rmut(p);
1881029Sbill 		kill(p->pid, SIGKILL);
1891029Sbill 	}
1901029Sbill 	p->pid = 0;
1911029Sbill }
1921029Sbill 
1931029Sbill rline()
1941029Sbill {
1951029Sbill 	register c, i;
1961029Sbill 
1971029Sbill loop:
1981029Sbill 	c = get();
1991029Sbill 	if(c < 0)
2001029Sbill 		return(0);
2011029Sbill 	if(c == 0)
2021029Sbill 		goto loop;
2031029Sbill 	line.flag = c;
2041029Sbill 	c = get();
2051029Sbill 	if(c <= 0)
2061029Sbill 		goto loop;
2071029Sbill 	line.comn = c;
2081029Sbill 	SCPYN(line.line, "");
2091029Sbill 	for (i=0; i<LINSIZ; i++) {
2101029Sbill 		c = get();
2111029Sbill 		if(c <= 0)
2121029Sbill 			break;
2131029Sbill 		line.line[i] = c;
2141029Sbill 	}
2151029Sbill 	while(c > 0)
2161029Sbill 		c = get();
2171029Sbill 	if(line.line[0] == 0)
2181029Sbill 		goto loop;
2191029Sbill 	if(line.flag == '0')
2201029Sbill 		goto loop;
2211029Sbill 	strcpy(tty, dev);
2221029Sbill 	strncat(tty, line.line, LINSIZ);
2231029Sbill 	if(access(tty, 06) < 0)
2241029Sbill 		goto loop;
2251029Sbill 	return(1);
2261029Sbill }
2271029Sbill 
2281029Sbill get()
2291029Sbill {
2301029Sbill 	char b;
2311029Sbill 
2321029Sbill 	if(read(fi, &b, 1) != 1)
2331029Sbill 		return(-1);
2341029Sbill 	if(b == '\n')
2351029Sbill 		return(0);
2361029Sbill 	return(b);
2371029Sbill }
2381029Sbill 
2391029Sbill #define	FOUND	1
2401029Sbill #define	CHANGE	2
2411029Sbill 
2421029Sbill merge()
2431029Sbill {
2441029Sbill 	register struct tab *p;
2451029Sbill 
2461029Sbill 	fi = open(ifile, 0);
2471029Sbill 	if(fi < 0)
2481029Sbill 		return;
2491029Sbill 	for(ALL)
2501029Sbill 		p->xflag = 0;
2511029Sbill 	while(rline()) {
2521029Sbill 		for(ALL) {
2531029Sbill 			if (SCMPN(p->line, line.line))
2541029Sbill 				continue;
2551029Sbill 			p->xflag |= FOUND;
2561029Sbill 			if(line.comn != p->comn) {
2571029Sbill 				p->xflag |= CHANGE;
2581029Sbill 				p->comn = line.comn;
2591029Sbill 			}
2601029Sbill 			goto contin1;
2611029Sbill 		}
2621029Sbill 		for(ALL) {
2631029Sbill 			if(p->line[0] != 0)
2641029Sbill 				continue;
2651029Sbill 			SCPYN(p->line, line.line);
2661029Sbill 			p->xflag |= FOUND|CHANGE;
2671029Sbill 			p->comn = line.comn;
2681029Sbill 			goto contin1;
2691029Sbill 		}
2701029Sbill 	contin1:
2711029Sbill 		;
2721029Sbill 	}
2731029Sbill 	close(fi);
2741029Sbill 	for(ALL) {
2751029Sbill 		if((p->xflag&FOUND) == 0) {
2761029Sbill 			term(p);
2771029Sbill 			p->line[0] = 0;
2781029Sbill 		}
2791029Sbill 		if((p->xflag&CHANGE) != 0) {
2801029Sbill 			term(p);
2811029Sbill 			dfork(p);
2821029Sbill 		}
2831029Sbill 	}
2841029Sbill }
2851029Sbill 
2861029Sbill dfork(p)
2871029Sbill struct tab *p;
2881029Sbill {
2891029Sbill 	register pid;
2901029Sbill 
2911029Sbill 	pid = fork();
2921029Sbill 	if(pid == 0) {
2931029Sbill 		signal(SIGTERM, SIG_DFL);
2941029Sbill 		signal(SIGHUP, SIG_IGN);
2951029Sbill 		strcpy(tty, dev);
2961029Sbill 		strncat(tty, p->line, LINSIZ);
2971029Sbill 		chown(tty, 0, 0);
2981029Sbill 		chmod(tty, 0622);
2991029Sbill 		open(tty, 2);
3001029Sbill 		vhangup();
3011029Sbill 		signal(SIGHUP, SIG_DFL);
3021029Sbill 		open(tty, 2);
3031029Sbill 		close(0);
3041029Sbill 		dup(1);
3051029Sbill 		dup(0);
3061029Sbill 		tty[0] = p->comn;
3071029Sbill 		tty[1] = 0;
3081029Sbill 		execl(getty, minus, tty, (char *)0);
3091029Sbill 		exit(0);
3101029Sbill 	}
3111029Sbill 	p->pid = pid;
3121029Sbill }
3131029Sbill 
3141029Sbill rmut(p)
3151029Sbill register struct tab *p;
3161029Sbill {
3171029Sbill 	register f;
3181029Sbill 
3191029Sbill 	f = open(utmp, 2);
3201029Sbill 	if(f >= 0) {
3211029Sbill 		while(read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) {
3221029Sbill 			if (SCMPN(wtmp.ut_line, p->line))
3231029Sbill 				continue;
3241029Sbill 			lseek(f, -(long)sizeof(wtmp), 1);
3251029Sbill 			SCPYN(wtmp.ut_name, "");
3261029Sbill 			time(&wtmp.ut_time);
3271029Sbill 			write(f, (char *)&wtmp, sizeof(wtmp));
3281029Sbill 		}
3291029Sbill 		close(f);
3301029Sbill 	}
3311029Sbill 	f = open(wtmpf, 1);
3321029Sbill 	if (f >= 0) {
3331029Sbill 		SCPYN(wtmp.ut_line, p->line);
3341029Sbill 		SCPYN(wtmp.ut_name, "");
3351029Sbill 		time(&wtmp.ut_time);
3361029Sbill 		lseek(f, (long)0, 2);
3371029Sbill 		write(f, (char *)&wtmp, sizeof(wtmp));
3381029Sbill 		close(f);
3391029Sbill 	}
3401029Sbill }
3411029Sbill 
3421029Sbill reset()
3431029Sbill {
3441029Sbill 	longjmp(sjbuf, 1);
3451029Sbill }
3461029Sbill 
3471029Sbill 
348