xref: /csrg-svn/old/init/init.c (revision 1429)
1*1429Sbill static	char *sccsid = "@(#)init.c	4.3 (Berkeley) 10/13/80";
21029Sbill #include <signal.h>
31029Sbill #include <sys/types.h>
41029Sbill #include <utmp.h>
51029Sbill #include <setjmp.h>
61403Sbill #include <sys/reboot.h>
71029Sbill 
81029Sbill #define	LINSIZ	sizeof(wtmp.ut_line)
91029Sbill #define	TABSIZ	100
101029Sbill #define	ALL	p = &itab[0]; p < &itab[TABSIZ]; p++
111029Sbill #define	EVER	;;
121029Sbill #define SCPYN(a, b)	strncpy(a, b, sizeof(a))
131029Sbill #define SCMPN(a, b)	strncmp(a, b, sizeof(a))
141029Sbill 
151029Sbill char	shell[]	= "/bin/sh";
161403Sbill char	getty[]	 = "/etc/getty";
171029Sbill char	minus[]	= "-";
181029Sbill char	runc[]	= "/etc/rc";
191029Sbill char	ifile[]	= "/etc/ttys";
201029Sbill char	utmp[]	= "/etc/utmp";
211029Sbill char	wtmpf[]	= "/usr/adm/wtmp";
221029Sbill char	ctty[]	= "/dev/console";
231029Sbill char	dev[]	= "/dev/";
241029Sbill 
251029Sbill struct utmp wtmp;
261029Sbill struct
271029Sbill {
281029Sbill 	char	line[LINSIZ];
291029Sbill 	char	comn;
301029Sbill 	char	flag;
311029Sbill } line;
321029Sbill struct	tab
331029Sbill {
341029Sbill 	char	line[LINSIZ];
351029Sbill 	char	comn;
361029Sbill 	char	xflag;
371029Sbill 	int	pid;
381029Sbill } itab[TABSIZ];
391029Sbill 
401029Sbill int	fi;
411029Sbill int	mergflag;
421029Sbill char	tty[20];
43*1429Sbill jmp_buf	sjbuf, shutpass;
441029Sbill 
451029Sbill int	reset();
461029Sbill char	*strcpy(), *strcat();
471029Sbill long	lseek();
481029Sbill 
491029Sbill main()
501029Sbill {
511403Sbill 	register int r11;		/* passed thru from boot */
521403Sbill 	int howto, oldhowto;
531403Sbill 
541403Sbill 	howto = r11;
551029Sbill 	setjmp(sjbuf);
561029Sbill 	signal(SIGTERM, reset);
571029Sbill 	signal(SIGSTOP, SIG_IGN);
581029Sbill 	signal(SIGTSTP, SIG_IGN);
591029Sbill 	signal(SIGTTIN, SIG_IGN);
601029Sbill 	signal(SIGTTOU, SIG_IGN);
611029Sbill 	for(EVER) {
621403Sbill 		oldhowto = howto;
631403Sbill 		howto = RB_SINGLE;
64*1429Sbill 		if (setjmp(shutpass) == 0)
65*1429Sbill 			shutdown();
661403Sbill 		if (oldhowto & RB_SINGLE)
671403Sbill 			single();
681403Sbill 		if (runcom(oldhowto) == 0)
691403Sbill 			continue;
701029Sbill 		merge();
711029Sbill 		multiple();
721029Sbill 	}
731029Sbill }
741029Sbill 
75*1429Sbill int	shutreset();
76*1429Sbill 
771029Sbill shutdown()
781029Sbill {
791029Sbill 	register i;
801029Sbill 	register struct tab *p;
811029Sbill 
821029Sbill 	close(creat(utmp, 0644));
831029Sbill 	signal(SIGHUP, SIG_IGN);
841029Sbill 	for(ALL) {
851029Sbill 		term(p);
861029Sbill 		p->line[0] = 0;
871029Sbill 	}
88*1429Sbill 	signal(SIGALRM, shutreset);
89*1429Sbill 	alarm(30);
901029Sbill 	for(i=0; i<5; i++)
911029Sbill 		kill(-1, SIGKILL);
921029Sbill 	while(wait((int *)0) != -1)
931029Sbill 		;
941029Sbill 	alarm(0);
95*1429Sbill 	shutend();
96*1429Sbill }
97*1429Sbill 
98*1429Sbill char shutfailm[] = "WARNING: Something is hung (wont die); ps axl advised\n";
99*1429Sbill 
100*1429Sbill shutreset()
101*1429Sbill {
102*1429Sbill 	int status;
103*1429Sbill 
104*1429Sbill 	if (fork() == 0) {
105*1429Sbill 		int ct = open(ctty, 1);
106*1429Sbill 		write(ct, shutfailm, sizeof (shutfailm));
107*1429Sbill 		sleep(5);
108*1429Sbill 		exit(1);
109*1429Sbill 	}
110*1429Sbill 	sleep(5);
111*1429Sbill 	shutend();
112*1429Sbill 	longjmp(shutpass, 1);
113*1429Sbill }
114*1429Sbill 
115*1429Sbill shutend()
116*1429Sbill {
117*1429Sbill 	register i;
118*1429Sbill 
1191029Sbill 	signal(SIGALRM, SIG_DFL);
1201029Sbill 	for(i=0; i<10; i++)
1211029Sbill 		close(i);
1221029Sbill }
1231029Sbill 
1241029Sbill single()
1251029Sbill {
1261029Sbill 	register pid;
1271029Sbill 
1281029Sbill 	pid = fork();
1291029Sbill 	if(pid == 0) {
1301029Sbill /*
1311029Sbill 		alarm(300);
1321029Sbill */
1331029Sbill 		signal(SIGTERM, SIG_DFL);
1341029Sbill 		signal(SIGHUP, SIG_DFL);
1351029Sbill 		signal(SIGALRM, SIG_DFL);
1361029Sbill 		open(ctty, 2);
1371029Sbill 		dup(0);
1381029Sbill 		dup(0);
1391029Sbill 		execl(shell, minus, (char *)0);
1401029Sbill 		exit(0);
1411029Sbill 	}
1421029Sbill 	while(wait((int *)0) != pid)
1431029Sbill 		;
1441029Sbill }
1451029Sbill 
1461403Sbill runcom(oldhowto)
1471403Sbill 	int oldhowto;
1481029Sbill {
1491029Sbill 	register pid, f;
1501403Sbill 	int status;
1511029Sbill 
1521029Sbill 	pid = fork();
1531029Sbill 	if(pid == 0) {
1541029Sbill 		open("/", 0);
1551029Sbill 		dup(0);
1561029Sbill 		dup(0);
1571403Sbill 		if (oldhowto & RB_SINGLE)
1581403Sbill 			execl(shell, shell, runc, (char *)0);
1591403Sbill 		else
1601403Sbill 			execl(shell, shell, runc, "autoboot", (char *)0);
1611403Sbill 		exit(1);
1621029Sbill 	}
1631403Sbill 	while(wait(&status) != pid)
1641029Sbill 		;
1651403Sbill 	if(status)
1661403Sbill 		return(0);
1671029Sbill 	f = open(wtmpf, 1);
1681029Sbill 	if (f >= 0) {
1691029Sbill 		lseek(f, 0L, 2);
1701029Sbill 		SCPYN(wtmp.ut_line, "~");
1711029Sbill 		SCPYN(wtmp.ut_name, "reboot");
1721029Sbill 		time(&wtmp.ut_time);
1731029Sbill 		write(f, (char *)&wtmp, sizeof(wtmp));
1741029Sbill 		close(f);
1751029Sbill 	}
1761403Sbill 	return(1);
1771029Sbill }
1781029Sbill 
1791029Sbill setmerge()
1801029Sbill {
1811029Sbill 
1821029Sbill 	signal(SIGHUP, setmerge);
1831029Sbill 	mergflag = 1;
1841029Sbill }
1851029Sbill 
1861029Sbill multiple()
1871029Sbill {
1881029Sbill 	register struct tab *p;
1891029Sbill 	register pid;
1901029Sbill 
1911029Sbill loop:
1921029Sbill 	mergflag = 0;
1931029Sbill 	signal(SIGHUP, setmerge);
1941029Sbill 	for(EVER) {
1951029Sbill 		pid = wait((int *)0);
1961029Sbill 		if(mergflag) {
1971029Sbill 			merge();
1981029Sbill 			goto loop;
1991029Sbill 		}
2001029Sbill 		if(pid == -1)
2011029Sbill 			return;
2021029Sbill 		for(ALL)
2031029Sbill 			if(p->pid == pid || p->pid == -1) {
2041029Sbill 				rmut(p);
2051029Sbill 				dfork(p);
2061029Sbill 			}
2071029Sbill 	}
2081029Sbill }
2091029Sbill 
2101029Sbill term(p)
2111029Sbill register struct tab *p;
2121029Sbill {
2131029Sbill 
2141029Sbill 	if(p->pid != 0) {
2151029Sbill 		rmut(p);
2161029Sbill 		kill(p->pid, SIGKILL);
2171029Sbill 	}
2181029Sbill 	p->pid = 0;
2191029Sbill }
2201029Sbill 
2211029Sbill rline()
2221029Sbill {
2231029Sbill 	register c, i;
2241029Sbill 
2251029Sbill loop:
2261029Sbill 	c = get();
2271029Sbill 	if(c < 0)
2281029Sbill 		return(0);
2291029Sbill 	if(c == 0)
2301029Sbill 		goto loop;
2311029Sbill 	line.flag = c;
2321029Sbill 	c = get();
2331029Sbill 	if(c <= 0)
2341029Sbill 		goto loop;
2351029Sbill 	line.comn = c;
2361029Sbill 	SCPYN(line.line, "");
2371029Sbill 	for (i=0; i<LINSIZ; i++) {
2381029Sbill 		c = get();
2391029Sbill 		if(c <= 0)
2401029Sbill 			break;
2411029Sbill 		line.line[i] = c;
2421029Sbill 	}
2431029Sbill 	while(c > 0)
2441029Sbill 		c = get();
2451029Sbill 	if(line.line[0] == 0)
2461029Sbill 		goto loop;
2471029Sbill 	if(line.flag == '0')
2481029Sbill 		goto loop;
2491029Sbill 	strcpy(tty, dev);
2501029Sbill 	strncat(tty, line.line, LINSIZ);
2511029Sbill 	if(access(tty, 06) < 0)
2521029Sbill 		goto loop;
2531029Sbill 	return(1);
2541029Sbill }
2551029Sbill 
2561029Sbill get()
2571029Sbill {
2581029Sbill 	char b;
2591029Sbill 
2601029Sbill 	if(read(fi, &b, 1) != 1)
2611029Sbill 		return(-1);
2621029Sbill 	if(b == '\n')
2631029Sbill 		return(0);
2641029Sbill 	return(b);
2651029Sbill }
2661029Sbill 
2671029Sbill #define	FOUND	1
2681029Sbill #define	CHANGE	2
2691029Sbill 
2701029Sbill merge()
2711029Sbill {
2721029Sbill 	register struct tab *p;
2731029Sbill 
2741029Sbill 	fi = open(ifile, 0);
2751029Sbill 	if(fi < 0)
2761029Sbill 		return;
2771029Sbill 	for(ALL)
2781029Sbill 		p->xflag = 0;
2791029Sbill 	while(rline()) {
2801029Sbill 		for(ALL) {
2811029Sbill 			if (SCMPN(p->line, line.line))
2821029Sbill 				continue;
2831029Sbill 			p->xflag |= FOUND;
2841029Sbill 			if(line.comn != p->comn) {
2851029Sbill 				p->xflag |= CHANGE;
2861029Sbill 				p->comn = line.comn;
2871029Sbill 			}
2881029Sbill 			goto contin1;
2891029Sbill 		}
2901029Sbill 		for(ALL) {
2911029Sbill 			if(p->line[0] != 0)
2921029Sbill 				continue;
2931029Sbill 			SCPYN(p->line, line.line);
2941029Sbill 			p->xflag |= FOUND|CHANGE;
2951029Sbill 			p->comn = line.comn;
2961029Sbill 			goto contin1;
2971029Sbill 		}
2981029Sbill 	contin1:
2991029Sbill 		;
3001029Sbill 	}
3011029Sbill 	close(fi);
3021029Sbill 	for(ALL) {
3031029Sbill 		if((p->xflag&FOUND) == 0) {
3041029Sbill 			term(p);
3051029Sbill 			p->line[0] = 0;
3061029Sbill 		}
3071029Sbill 		if((p->xflag&CHANGE) != 0) {
3081029Sbill 			term(p);
3091029Sbill 			dfork(p);
3101029Sbill 		}
3111029Sbill 	}
3121029Sbill }
3131029Sbill 
3141029Sbill dfork(p)
3151029Sbill struct tab *p;
3161029Sbill {
3171029Sbill 	register pid;
3181029Sbill 
3191029Sbill 	pid = fork();
3201029Sbill 	if(pid == 0) {
3211029Sbill 		signal(SIGTERM, SIG_DFL);
3221029Sbill 		signal(SIGHUP, SIG_IGN);
3231029Sbill 		strcpy(tty, dev);
3241029Sbill 		strncat(tty, p->line, LINSIZ);
3251029Sbill 		chown(tty, 0, 0);
3261029Sbill 		chmod(tty, 0622);
3271029Sbill 		open(tty, 2);
3281029Sbill 		vhangup();
3291029Sbill 		signal(SIGHUP, SIG_DFL);
3301029Sbill 		open(tty, 2);
3311029Sbill 		close(0);
3321029Sbill 		dup(1);
3331029Sbill 		dup(0);
3341029Sbill 		tty[0] = p->comn;
3351029Sbill 		tty[1] = 0;
3361029Sbill 		execl(getty, minus, tty, (char *)0);
3371029Sbill 		exit(0);
3381029Sbill 	}
3391029Sbill 	p->pid = pid;
3401029Sbill }
3411029Sbill 
3421029Sbill rmut(p)
3431029Sbill register struct tab *p;
3441029Sbill {
3451029Sbill 	register f;
3461029Sbill 
3471029Sbill 	f = open(utmp, 2);
3481029Sbill 	if(f >= 0) {
3491029Sbill 		while(read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) {
3501029Sbill 			if (SCMPN(wtmp.ut_line, p->line))
3511029Sbill 				continue;
3521029Sbill 			lseek(f, -(long)sizeof(wtmp), 1);
3531029Sbill 			SCPYN(wtmp.ut_name, "");
3541029Sbill 			time(&wtmp.ut_time);
3551029Sbill 			write(f, (char *)&wtmp, sizeof(wtmp));
3561029Sbill 		}
3571029Sbill 		close(f);
3581029Sbill 	}
3591029Sbill 	f = open(wtmpf, 1);
3601029Sbill 	if (f >= 0) {
3611029Sbill 		SCPYN(wtmp.ut_line, p->line);
3621029Sbill 		SCPYN(wtmp.ut_name, "");
3631029Sbill 		time(&wtmp.ut_time);
3641029Sbill 		lseek(f, (long)0, 2);
3651029Sbill 		write(f, (char *)&wtmp, sizeof(wtmp));
3661029Sbill 		close(f);
3671029Sbill 	}
3681029Sbill }
3691029Sbill 
3701029Sbill reset()
3711029Sbill {
3721029Sbill 	longjmp(sjbuf, 1);
3731029Sbill }
374