xref: /csrg-svn/old/init/init.c (revision 9869)
1*9869Spugs static	char *sccsid = "@(#)init.c	4.10 (Berkeley) 12/22/82";
21029Sbill #include <signal.h>
31029Sbill #include <sys/types.h>
41029Sbill #include <utmp.h>
51029Sbill #include <setjmp.h>
61403Sbill #include <sys/reboot.h>
72821Swnj #include <errno.h>
81029Sbill 
91029Sbill #define	LINSIZ	sizeof(wtmp.ut_line)
101029Sbill #define	TABSIZ	100
111029Sbill #define	ALL	p = &itab[0]; p < &itab[TABSIZ]; p++
121029Sbill #define	EVER	;;
131029Sbill #define SCPYN(a, b)	strncpy(a, b, sizeof(a))
141029Sbill #define SCMPN(a, b)	strncmp(a, b, sizeof(a))
151029Sbill 
161029Sbill char	shell[]	= "/bin/sh";
171403Sbill char	getty[]	 = "/etc/getty";
181029Sbill char	minus[]	= "-";
191029Sbill char	runc[]	= "/etc/rc";
201029Sbill char	ifile[]	= "/etc/ttys";
211029Sbill char	utmp[]	= "/etc/utmp";
221029Sbill char	wtmpf[]	= "/usr/adm/wtmp";
231029Sbill char	ctty[]	= "/dev/console";
241029Sbill char	dev[]	= "/dev/";
251029Sbill 
261029Sbill struct utmp wtmp;
271029Sbill struct
281029Sbill {
291029Sbill 	char	line[LINSIZ];
301029Sbill 	char	comn;
311029Sbill 	char	flag;
321029Sbill } line;
331029Sbill struct	tab
341029Sbill {
351029Sbill 	char	line[LINSIZ];
361029Sbill 	char	comn;
371029Sbill 	char	xflag;
381029Sbill 	int	pid;
395971Sroot 	time_t	gettytime;
405971Sroot 	int	gettycnt;
411029Sbill } itab[TABSIZ];
421029Sbill 
431029Sbill int	fi;
441029Sbill int	mergflag;
451029Sbill char	tty[20];
461429Sbill jmp_buf	sjbuf, shutpass;
472821Swnj time_t	time0;
481029Sbill 
491029Sbill int	reset();
502821Swnj int	idle();
511029Sbill char	*strcpy(), *strcat();
521029Sbill long	lseek();
531029Sbill 
54*9869Spugs #ifndef sun
551029Sbill main()
561029Sbill {
571403Sbill 	register int r11;		/* passed thru from boot */
58*9869Spugs #else sun
59*9869Spugs main(argc, argv)
60*9869Spugs 	char **argv;
61*9869Spugs {
62*9869Spugs #endif sun
631403Sbill 	int howto, oldhowto;
641403Sbill 
652821Swnj 	time0 = time(0);
66*9869Spugs #ifndef sun
671403Sbill 	howto = r11;
68*9869Spugs #else sun
69*9869Spugs 	if (argc > 1 && argv[1][0] == '-') {
70*9869Spugs 		char *cp;
71*9869Spugs 
72*9869Spugs 		howto = 0;
73*9869Spugs 		cp = &argv[1][1];
74*9869Spugs 		while (*cp) switch (*cp++) {
75*9869Spugs 		case 'a':
76*9869Spugs 			howto |= RB_ASKNAME;
77*9869Spugs 			break;
78*9869Spugs 		case 's':
79*9869Spugs 			howto |= RB_SINGLE;
80*9869Spugs 			break;
81*9869Spugs 		}
82*9869Spugs 	} else {
83*9869Spugs 		howto = RB_SINGLE;
84*9869Spugs 	}
85*9869Spugs #endif sun
861029Sbill 	setjmp(sjbuf);
871029Sbill 	signal(SIGTERM, reset);
882821Swnj 	signal(SIGTSTP, idle);
891029Sbill 	signal(SIGSTOP, SIG_IGN);
901029Sbill 	signal(SIGTTIN, SIG_IGN);
911029Sbill 	signal(SIGTTOU, SIG_IGN);
921029Sbill 	for(EVER) {
931403Sbill 		oldhowto = howto;
941403Sbill 		howto = RB_SINGLE;
951429Sbill 		if (setjmp(shutpass) == 0)
961429Sbill 			shutdown();
971403Sbill 		if (oldhowto & RB_SINGLE)
981403Sbill 			single();
991403Sbill 		if (runcom(oldhowto) == 0)
1001403Sbill 			continue;
1011029Sbill 		merge();
1021029Sbill 		multiple();
1031029Sbill 	}
1041029Sbill }
1051029Sbill 
1061429Sbill int	shutreset();
1071429Sbill 
1081029Sbill shutdown()
1091029Sbill {
1101029Sbill 	register i;
1111029Sbill 	register struct tab *p;
1121029Sbill 
1131029Sbill 	close(creat(utmp, 0644));
1141029Sbill 	signal(SIGHUP, SIG_IGN);
1151029Sbill 	for(ALL) {
1161029Sbill 		term(p);
1171029Sbill 		p->line[0] = 0;
1181029Sbill 	}
1191429Sbill 	signal(SIGALRM, shutreset);
1201429Sbill 	alarm(30);
1211029Sbill 	for(i=0; i<5; i++)
1221029Sbill 		kill(-1, SIGKILL);
1231029Sbill 	while(wait((int *)0) != -1)
1241029Sbill 		;
1251029Sbill 	alarm(0);
1261429Sbill 	shutend();
1271429Sbill }
1281429Sbill 
1291429Sbill char shutfailm[] = "WARNING: Something is hung (wont die); ps axl advised\n";
1301429Sbill 
1311429Sbill shutreset()
1321429Sbill {
1331429Sbill 	int status;
1341429Sbill 
1351429Sbill 	if (fork() == 0) {
1361429Sbill 		int ct = open(ctty, 1);
1371429Sbill 		write(ct, shutfailm, sizeof (shutfailm));
1381429Sbill 		sleep(5);
1391429Sbill 		exit(1);
1401429Sbill 	}
1411429Sbill 	sleep(5);
1421429Sbill 	shutend();
1431429Sbill 	longjmp(shutpass, 1);
1441429Sbill }
1451429Sbill 
1461429Sbill shutend()
1471429Sbill {
1482821Swnj 	register i, f;
1491429Sbill 
1502821Swnj 	acct(0);
1511029Sbill 	signal(SIGALRM, SIG_DFL);
1521029Sbill 	for(i=0; i<10; i++)
1531029Sbill 		close(i);
1542821Swnj 	f = open(wtmpf, 1);
1552821Swnj 	if (f >= 0) {
1562821Swnj 		lseek(f, 0L, 2);
1572821Swnj 		SCPYN(wtmp.ut_line, "~");
1582821Swnj 		SCPYN(wtmp.ut_name, "shutdown");
1592821Swnj 		time(&wtmp.ut_time);
1602821Swnj 		write(f, (char *)&wtmp, sizeof(wtmp));
1612821Swnj 		close(f);
1622821Swnj 	}
1632821Swnj 	return(1);
1641029Sbill }
1651029Sbill 
1661029Sbill single()
1671029Sbill {
1681029Sbill 	register pid;
1692821Swnj 	register xpid;
1702821Swnj 	extern	errno;
1711029Sbill 
1722821Swnj    do {
1731029Sbill 	pid = fork();
1741029Sbill 	if(pid == 0) {
1751029Sbill /*
1761029Sbill 		alarm(300);
1771029Sbill */
1781029Sbill 		signal(SIGTERM, SIG_DFL);
1791029Sbill 		signal(SIGHUP, SIG_DFL);
1801029Sbill 		signal(SIGALRM, SIG_DFL);
1811029Sbill 		open(ctty, 2);
1821029Sbill 		dup(0);
1831029Sbill 		dup(0);
1841029Sbill 		execl(shell, minus, (char *)0);
1851029Sbill 		exit(0);
1861029Sbill 	}
1872821Swnj 	while((xpid = wait((int *)0)) != pid)
1882821Swnj 		if (xpid == -1 && errno == ECHILD)
1892821Swnj 			break;
1902821Swnj    } while (xpid == -1);
1911029Sbill }
1921029Sbill 
1931403Sbill runcom(oldhowto)
1941403Sbill 	int oldhowto;
1951029Sbill {
1961029Sbill 	register pid, f;
1971403Sbill 	int status;
1981029Sbill 
1991029Sbill 	pid = fork();
2001029Sbill 	if(pid == 0) {
2011029Sbill 		open("/", 0);
2021029Sbill 		dup(0);
2031029Sbill 		dup(0);
2041403Sbill 		if (oldhowto & RB_SINGLE)
2051403Sbill 			execl(shell, shell, runc, (char *)0);
2061403Sbill 		else
2071403Sbill 			execl(shell, shell, runc, "autoboot", (char *)0);
2081403Sbill 		exit(1);
2091029Sbill 	}
2101403Sbill 	while(wait(&status) != pid)
2111029Sbill 		;
2121403Sbill 	if(status)
2131403Sbill 		return(0);
2141029Sbill 	f = open(wtmpf, 1);
2151029Sbill 	if (f >= 0) {
2161029Sbill 		lseek(f, 0L, 2);
2171029Sbill 		SCPYN(wtmp.ut_line, "~");
2181029Sbill 		SCPYN(wtmp.ut_name, "reboot");
2192821Swnj 		if (time0) {
2202821Swnj 			wtmp.ut_time = time0;
2212821Swnj 			time0 = 0;
2222821Swnj 		} else
2232821Swnj 			time(&wtmp.ut_time);
2241029Sbill 		write(f, (char *)&wtmp, sizeof(wtmp));
2251029Sbill 		close(f);
2261029Sbill 	}
2271403Sbill 	return(1);
2281029Sbill }
2291029Sbill 
2301029Sbill setmerge()
2311029Sbill {
2321029Sbill 
2331029Sbill 	signal(SIGHUP, setmerge);
2341029Sbill 	mergflag = 1;
2351029Sbill }
2361029Sbill 
2371029Sbill multiple()
2381029Sbill {
2391029Sbill 	register struct tab *p;
2401029Sbill 	register pid;
2411029Sbill 
2421029Sbill loop:
2431029Sbill 	mergflag = 0;
2441029Sbill 	signal(SIGHUP, setmerge);
2451029Sbill 	for(EVER) {
2461029Sbill 		pid = wait((int *)0);
2471029Sbill 		if(mergflag) {
2481029Sbill 			merge();
2491029Sbill 			goto loop;
2501029Sbill 		}
2511029Sbill 		if(pid == -1)
2521029Sbill 			return;
2531029Sbill 		for(ALL)
2541029Sbill 			if(p->pid == pid || p->pid == -1) {
2551029Sbill 				rmut(p);
2561029Sbill 				dfork(p);
2571029Sbill 			}
2581029Sbill 	}
2591029Sbill }
2601029Sbill 
2611029Sbill term(p)
2621029Sbill register struct tab *p;
2631029Sbill {
2641029Sbill 
2651029Sbill 	if(p->pid != 0) {
2661029Sbill 		rmut(p);
2671029Sbill 		kill(p->pid, SIGKILL);
2681029Sbill 	}
2691029Sbill 	p->pid = 0;
2701029Sbill }
2711029Sbill 
2721029Sbill rline()
2731029Sbill {
2741029Sbill 	register c, i;
2751029Sbill 
2761029Sbill loop:
2771029Sbill 	c = get();
2781029Sbill 	if(c < 0)
2791029Sbill 		return(0);
2801029Sbill 	if(c == 0)
2811029Sbill 		goto loop;
2821029Sbill 	line.flag = c;
2831029Sbill 	c = get();
2841029Sbill 	if(c <= 0)
2851029Sbill 		goto loop;
2861029Sbill 	line.comn = c;
2871029Sbill 	SCPYN(line.line, "");
2881029Sbill 	for (i=0; i<LINSIZ; i++) {
2891029Sbill 		c = get();
2901029Sbill 		if(c <= 0)
2911029Sbill 			break;
2921029Sbill 		line.line[i] = c;
2931029Sbill 	}
2941029Sbill 	while(c > 0)
2951029Sbill 		c = get();
2961029Sbill 	if(line.line[0] == 0)
2971029Sbill 		goto loop;
2981029Sbill 	if(line.flag == '0')
2991029Sbill 		goto loop;
3001029Sbill 	strcpy(tty, dev);
3011029Sbill 	strncat(tty, line.line, LINSIZ);
3021029Sbill 	if(access(tty, 06) < 0)
3031029Sbill 		goto loop;
3041029Sbill 	return(1);
3051029Sbill }
3061029Sbill 
3071029Sbill get()
3081029Sbill {
3091029Sbill 	char b;
3101029Sbill 
3111029Sbill 	if(read(fi, &b, 1) != 1)
3121029Sbill 		return(-1);
3131029Sbill 	if(b == '\n')
3141029Sbill 		return(0);
3151029Sbill 	return(b);
3161029Sbill }
3171029Sbill 
3181029Sbill #define	FOUND	1
3191029Sbill #define	CHANGE	2
3201029Sbill 
3211029Sbill merge()
3221029Sbill {
3231029Sbill 	register struct tab *p;
3241029Sbill 
3251029Sbill 	fi = open(ifile, 0);
3261029Sbill 	if(fi < 0)
3271029Sbill 		return;
3281029Sbill 	for(ALL)
3291029Sbill 		p->xflag = 0;
3301029Sbill 	while(rline()) {
3311029Sbill 		for(ALL) {
3321029Sbill 			if (SCMPN(p->line, line.line))
3331029Sbill 				continue;
3341029Sbill 			p->xflag |= FOUND;
3351029Sbill 			if(line.comn != p->comn) {
3361029Sbill 				p->xflag |= CHANGE;
3371029Sbill 				p->comn = line.comn;
3381029Sbill 			}
3391029Sbill 			goto contin1;
3401029Sbill 		}
3411029Sbill 		for(ALL) {
3421029Sbill 			if(p->line[0] != 0)
3431029Sbill 				continue;
3441029Sbill 			SCPYN(p->line, line.line);
3451029Sbill 			p->xflag |= FOUND|CHANGE;
3461029Sbill 			p->comn = line.comn;
3471029Sbill 			goto contin1;
3481029Sbill 		}
3491029Sbill 	contin1:
3501029Sbill 		;
3511029Sbill 	}
3521029Sbill 	close(fi);
3531029Sbill 	for(ALL) {
3541029Sbill 		if((p->xflag&FOUND) == 0) {
3551029Sbill 			term(p);
3561029Sbill 			p->line[0] = 0;
3571029Sbill 		}
3581029Sbill 		if((p->xflag&CHANGE) != 0) {
3591029Sbill 			term(p);
3601029Sbill 			dfork(p);
3611029Sbill 		}
3621029Sbill 	}
3631029Sbill }
3641029Sbill 
3656816Ssam #include <sys/ioctl.h>
3666816Ssam 
3671029Sbill dfork(p)
3681029Sbill struct tab *p;
3691029Sbill {
3701029Sbill 	register pid;
3715971Sroot 	time_t t;
3725971Sroot 	int dowait = 0;
3739579Spugs 	extern char *sys_errlist[];
3741029Sbill 
3755971Sroot 	time(&t);
3765971Sroot 	p->gettycnt++;
3775971Sroot 	if ((t - p->gettytime) >= 60) {
3785971Sroot 		p->gettytime = t;
3795971Sroot 		p->gettycnt = 1;
3805971Sroot 	} else {
3815971Sroot 		if (p->gettycnt >= 5) {
3825971Sroot 			dowait = 1;
3835971Sroot 			p->gettytime = t;
3845971Sroot 			p->gettycnt = 1;
3855971Sroot 		}
3865971Sroot 	}
3871029Sbill 	pid = fork();
3881029Sbill 	if(pid == 0) {
3896816Ssam 		int oerrno, f;
3906816Ssam 		extern int errno;
3916816Ssam 
3926816Ssam 		signal(SIGTERM, SIG_DFL);
3936816Ssam 		signal(SIGHUP, SIG_IGN);
3949579Spugs 		strcpy(tty, dev);
3959579Spugs 		strncat(tty, p->line, LINSIZ);
3965971Sroot 		if (dowait) {
3976816Ssam 			f = open("/dev/console", 1);
3985971Sroot 			write(f, "init: ", 6);
3995971Sroot 			write(f, tty, strlen(tty));
4005971Sroot 			write(f, ": getty failing, sleeping\n\r", 27);
4015971Sroot 			close(f);
4025971Sroot 			sleep(30);
4036816Ssam 			if ((f = open("/dev/tty", 2)) >= 0) {
4046816Ssam 				ioctl(f, TIOCNOTTY, 0);
4056816Ssam 				close(f);
4066816Ssam 			}
4075971Sroot 		}
4081029Sbill 		chown(tty, 0, 0);
4091029Sbill 		chmod(tty, 0622);
4103608Swnj 		if (open(tty, 2) < 0) {
4113608Swnj 			int repcnt = 0;
4123608Swnj 			do {
4136816Ssam 				oerrno = errno;
4143608Swnj 				if (repcnt % 10 == 0) {
4156816Ssam 					f = open("/dev/console", 1);
4163608Swnj 					write(f, "init: ", 6);
4179579Spugs 					write(f, tty, strlen(tty));
4189579Spugs 					write(f, ": ", 2);
4199579Spugs 					write(f, sys_errlist[oerrno],
4209579Spugs 						strlen(sys_errlist[oerrno]));
4219579Spugs 					write(f, "\n", 1);
4223608Swnj 					close(f);
4236816Ssam 					if ((f = open("/dev/tty", 2)) >= 0) {
4246816Ssam 						ioctl(f, TIOCNOTTY, 0);
4256816Ssam 						close(f);
4266816Ssam 					}
4273608Swnj 				}
4283608Swnj 				repcnt++;
4293608Swnj 				sleep(60);
4303608Swnj 			} while (open(tty, 2) < 0);
4313608Swnj 			exit(0);	/* have wrong control tty, start over */
4323608Swnj 		}
4331029Sbill 		vhangup();
4341029Sbill 		signal(SIGHUP, SIG_DFL);
4351029Sbill 		open(tty, 2);
4361029Sbill 		close(0);
4371029Sbill 		dup(1);
4381029Sbill 		dup(0);
4391029Sbill 		tty[0] = p->comn;
4401029Sbill 		tty[1] = 0;
4411029Sbill 		execl(getty, minus, tty, (char *)0);
4421029Sbill 		exit(0);
4431029Sbill 	}
4441029Sbill 	p->pid = pid;
4451029Sbill }
4461029Sbill 
4471029Sbill rmut(p)
4481029Sbill register struct tab *p;
4491029Sbill {
4501029Sbill 	register f;
4513608Swnj 	int found = 0;
4521029Sbill 
4531029Sbill 	f = open(utmp, 2);
4541029Sbill 	if(f >= 0) {
4551029Sbill 		while(read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) {
4563608Swnj 			if (SCMPN(wtmp.ut_line, p->line) || wtmp.ut_name[0]==0)
4571029Sbill 				continue;
4581029Sbill 			lseek(f, -(long)sizeof(wtmp), 1);
4591029Sbill 			SCPYN(wtmp.ut_name, "");
4601029Sbill 			time(&wtmp.ut_time);
4611029Sbill 			write(f, (char *)&wtmp, sizeof(wtmp));
4623608Swnj 			found++;
4631029Sbill 		}
4641029Sbill 		close(f);
4651029Sbill 	}
4663608Swnj 	if (found) {
4673608Swnj 		f = open(wtmpf, 1);
4683608Swnj 		if (f >= 0) {
4693608Swnj 			SCPYN(wtmp.ut_line, p->line);
4703608Swnj 			SCPYN(wtmp.ut_name, "");
4713608Swnj 			time(&wtmp.ut_time);
4723608Swnj 			lseek(f, (long)0, 2);
4733608Swnj 			write(f, (char *)&wtmp, sizeof(wtmp));
4743608Swnj 			close(f);
4753608Swnj 		}
4761029Sbill 	}
4771029Sbill }
4781029Sbill 
4791029Sbill reset()
4801029Sbill {
4811029Sbill 	longjmp(sjbuf, 1);
4821029Sbill }
4832821Swnj 
4842821Swnj idle()
4852821Swnj {
4862821Swnj 	register struct tab *p;
4872821Swnj 	register pid;
4882821Swnj 
4892821Swnj 	signal(SIGTSTP, idle);
4902821Swnj 	for (;;) {
4912821Swnj 		pid = wait((int *) 0);
4922821Swnj 		if (mergflag)
4932821Swnj 			return;
4942821Swnj 		if (pid == -1)
4952821Swnj 			pause();
4962821Swnj 		else {
4972821Swnj 			for (ALL)
4982821Swnj 				if (p->pid == pid) {
4992821Swnj 					rmut(p);
5002821Swnj 					p->pid = -1;
5012821Swnj 				}
5022821Swnj 		}
5032821Swnj 	}
5042821Swnj }
505