xref: /csrg-svn/old/init/init.c (revision 6816)
1*6816Ssam static	char *sccsid = "@(#)init.c	4.6 (Berkeley) 2/26/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 
541029Sbill main()
551029Sbill {
561403Sbill 	register int r11;		/* passed thru from boot */
571403Sbill 	int howto, oldhowto;
581403Sbill 
592821Swnj 	time0 = time(0);
601403Sbill 	howto = r11;
611029Sbill 	setjmp(sjbuf);
621029Sbill 	signal(SIGTERM, reset);
632821Swnj 	signal(SIGTSTP, idle);
641029Sbill 	signal(SIGSTOP, SIG_IGN);
651029Sbill 	signal(SIGTTIN, SIG_IGN);
661029Sbill 	signal(SIGTTOU, SIG_IGN);
671029Sbill 	for(EVER) {
681403Sbill 		oldhowto = howto;
691403Sbill 		howto = RB_SINGLE;
701429Sbill 		if (setjmp(shutpass) == 0)
711429Sbill 			shutdown();
721403Sbill 		if (oldhowto & RB_SINGLE)
731403Sbill 			single();
741403Sbill 		if (runcom(oldhowto) == 0)
751403Sbill 			continue;
761029Sbill 		merge();
771029Sbill 		multiple();
781029Sbill 	}
791029Sbill }
801029Sbill 
811429Sbill int	shutreset();
821429Sbill 
831029Sbill shutdown()
841029Sbill {
851029Sbill 	register i;
861029Sbill 	register struct tab *p;
871029Sbill 
881029Sbill 	close(creat(utmp, 0644));
891029Sbill 	signal(SIGHUP, SIG_IGN);
901029Sbill 	for(ALL) {
911029Sbill 		term(p);
921029Sbill 		p->line[0] = 0;
931029Sbill 	}
941429Sbill 	signal(SIGALRM, shutreset);
951429Sbill 	alarm(30);
961029Sbill 	for(i=0; i<5; i++)
971029Sbill 		kill(-1, SIGKILL);
981029Sbill 	while(wait((int *)0) != -1)
991029Sbill 		;
1001029Sbill 	alarm(0);
1011429Sbill 	shutend();
1021429Sbill }
1031429Sbill 
1041429Sbill char shutfailm[] = "WARNING: Something is hung (wont die); ps axl advised\n";
1051429Sbill 
1061429Sbill shutreset()
1071429Sbill {
1081429Sbill 	int status;
1091429Sbill 
1101429Sbill 	if (fork() == 0) {
1111429Sbill 		int ct = open(ctty, 1);
1121429Sbill 		write(ct, shutfailm, sizeof (shutfailm));
1131429Sbill 		sleep(5);
1141429Sbill 		exit(1);
1151429Sbill 	}
1161429Sbill 	sleep(5);
1171429Sbill 	shutend();
1181429Sbill 	longjmp(shutpass, 1);
1191429Sbill }
1201429Sbill 
1211429Sbill shutend()
1221429Sbill {
1232821Swnj 	register i, f;
1241429Sbill 
1252821Swnj 	acct(0);
1261029Sbill 	signal(SIGALRM, SIG_DFL);
1271029Sbill 	for(i=0; i<10; i++)
1281029Sbill 		close(i);
1292821Swnj 	f = open(wtmpf, 1);
1302821Swnj 	if (f >= 0) {
1312821Swnj 		lseek(f, 0L, 2);
1322821Swnj 		SCPYN(wtmp.ut_line, "~");
1332821Swnj 		SCPYN(wtmp.ut_name, "shutdown");
1342821Swnj 		time(&wtmp.ut_time);
1352821Swnj 		write(f, (char *)&wtmp, sizeof(wtmp));
1362821Swnj 		close(f);
1372821Swnj 	}
1382821Swnj 	return(1);
1391029Sbill }
1401029Sbill 
1411029Sbill single()
1421029Sbill {
1431029Sbill 	register pid;
1442821Swnj 	register xpid;
1452821Swnj 	extern	errno;
1461029Sbill 
1472821Swnj    do {
1481029Sbill 	pid = fork();
1491029Sbill 	if(pid == 0) {
1501029Sbill /*
1511029Sbill 		alarm(300);
1521029Sbill */
1531029Sbill 		signal(SIGTERM, SIG_DFL);
1541029Sbill 		signal(SIGHUP, SIG_DFL);
1551029Sbill 		signal(SIGALRM, SIG_DFL);
1561029Sbill 		open(ctty, 2);
1571029Sbill 		dup(0);
1581029Sbill 		dup(0);
1591029Sbill 		execl(shell, minus, (char *)0);
1601029Sbill 		exit(0);
1611029Sbill 	}
1622821Swnj 	while((xpid = wait((int *)0)) != pid)
1632821Swnj 		if (xpid == -1 && errno == ECHILD)
1642821Swnj 			break;
1652821Swnj    } while (xpid == -1);
1661029Sbill }
1671029Sbill 
1681403Sbill runcom(oldhowto)
1691403Sbill 	int oldhowto;
1701029Sbill {
1711029Sbill 	register pid, f;
1721403Sbill 	int status;
1731029Sbill 
1741029Sbill 	pid = fork();
1751029Sbill 	if(pid == 0) {
1761029Sbill 		open("/", 0);
1771029Sbill 		dup(0);
1781029Sbill 		dup(0);
1791403Sbill 		if (oldhowto & RB_SINGLE)
1801403Sbill 			execl(shell, shell, runc, (char *)0);
1811403Sbill 		else
1821403Sbill 			execl(shell, shell, runc, "autoboot", (char *)0);
1831403Sbill 		exit(1);
1841029Sbill 	}
1851403Sbill 	while(wait(&status) != pid)
1861029Sbill 		;
1871403Sbill 	if(status)
1881403Sbill 		return(0);
1891029Sbill 	f = open(wtmpf, 1);
1901029Sbill 	if (f >= 0) {
1911029Sbill 		lseek(f, 0L, 2);
1921029Sbill 		SCPYN(wtmp.ut_line, "~");
1931029Sbill 		SCPYN(wtmp.ut_name, "reboot");
1942821Swnj 		if (time0) {
1952821Swnj 			wtmp.ut_time = time0;
1962821Swnj 			time0 = 0;
1972821Swnj 		} else
1982821Swnj 			time(&wtmp.ut_time);
1991029Sbill 		write(f, (char *)&wtmp, sizeof(wtmp));
2001029Sbill 		close(f);
2011029Sbill 	}
2021403Sbill 	return(1);
2031029Sbill }
2041029Sbill 
2051029Sbill setmerge()
2061029Sbill {
2071029Sbill 
2081029Sbill 	signal(SIGHUP, setmerge);
2091029Sbill 	mergflag = 1;
2101029Sbill }
2111029Sbill 
2121029Sbill multiple()
2131029Sbill {
2141029Sbill 	register struct tab *p;
2151029Sbill 	register pid;
2161029Sbill 
2171029Sbill loop:
2181029Sbill 	mergflag = 0;
2191029Sbill 	signal(SIGHUP, setmerge);
2201029Sbill 	for(EVER) {
2211029Sbill 		pid = wait((int *)0);
2221029Sbill 		if(mergflag) {
2231029Sbill 			merge();
2241029Sbill 			goto loop;
2251029Sbill 		}
2261029Sbill 		if(pid == -1)
2271029Sbill 			return;
2281029Sbill 		for(ALL)
2291029Sbill 			if(p->pid == pid || p->pid == -1) {
2301029Sbill 				rmut(p);
2311029Sbill 				dfork(p);
2321029Sbill 			}
2331029Sbill 	}
2341029Sbill }
2351029Sbill 
2361029Sbill term(p)
2371029Sbill register struct tab *p;
2381029Sbill {
2391029Sbill 
2401029Sbill 	if(p->pid != 0) {
2411029Sbill 		rmut(p);
2421029Sbill 		kill(p->pid, SIGKILL);
2431029Sbill 	}
2441029Sbill 	p->pid = 0;
2451029Sbill }
2461029Sbill 
2471029Sbill rline()
2481029Sbill {
2491029Sbill 	register c, i;
2501029Sbill 
2511029Sbill loop:
2521029Sbill 	c = get();
2531029Sbill 	if(c < 0)
2541029Sbill 		return(0);
2551029Sbill 	if(c == 0)
2561029Sbill 		goto loop;
2571029Sbill 	line.flag = c;
2581029Sbill 	c = get();
2591029Sbill 	if(c <= 0)
2601029Sbill 		goto loop;
2611029Sbill 	line.comn = c;
2621029Sbill 	SCPYN(line.line, "");
2631029Sbill 	for (i=0; i<LINSIZ; i++) {
2641029Sbill 		c = get();
2651029Sbill 		if(c <= 0)
2661029Sbill 			break;
2671029Sbill 		line.line[i] = c;
2681029Sbill 	}
2691029Sbill 	while(c > 0)
2701029Sbill 		c = get();
2711029Sbill 	if(line.line[0] == 0)
2721029Sbill 		goto loop;
2731029Sbill 	if(line.flag == '0')
2741029Sbill 		goto loop;
2751029Sbill 	strcpy(tty, dev);
2761029Sbill 	strncat(tty, line.line, LINSIZ);
2771029Sbill 	if(access(tty, 06) < 0)
2781029Sbill 		goto loop;
2791029Sbill 	return(1);
2801029Sbill }
2811029Sbill 
2821029Sbill get()
2831029Sbill {
2841029Sbill 	char b;
2851029Sbill 
2861029Sbill 	if(read(fi, &b, 1) != 1)
2871029Sbill 		return(-1);
2881029Sbill 	if(b == '\n')
2891029Sbill 		return(0);
2901029Sbill 	return(b);
2911029Sbill }
2921029Sbill 
2931029Sbill #define	FOUND	1
2941029Sbill #define	CHANGE	2
2951029Sbill 
2961029Sbill merge()
2971029Sbill {
2981029Sbill 	register struct tab *p;
2991029Sbill 
3001029Sbill 	fi = open(ifile, 0);
3011029Sbill 	if(fi < 0)
3021029Sbill 		return;
3031029Sbill 	for(ALL)
3041029Sbill 		p->xflag = 0;
3051029Sbill 	while(rline()) {
3061029Sbill 		for(ALL) {
3071029Sbill 			if (SCMPN(p->line, line.line))
3081029Sbill 				continue;
3091029Sbill 			p->xflag |= FOUND;
3101029Sbill 			if(line.comn != p->comn) {
3111029Sbill 				p->xflag |= CHANGE;
3121029Sbill 				p->comn = line.comn;
3131029Sbill 			}
3141029Sbill 			goto contin1;
3151029Sbill 		}
3161029Sbill 		for(ALL) {
3171029Sbill 			if(p->line[0] != 0)
3181029Sbill 				continue;
3191029Sbill 			SCPYN(p->line, line.line);
3201029Sbill 			p->xflag |= FOUND|CHANGE;
3211029Sbill 			p->comn = line.comn;
3221029Sbill 			goto contin1;
3231029Sbill 		}
3241029Sbill 	contin1:
3251029Sbill 		;
3261029Sbill 	}
3271029Sbill 	close(fi);
3281029Sbill 	for(ALL) {
3291029Sbill 		if((p->xflag&FOUND) == 0) {
3301029Sbill 			term(p);
3311029Sbill 			p->line[0] = 0;
3321029Sbill 		}
3331029Sbill 		if((p->xflag&CHANGE) != 0) {
3341029Sbill 			term(p);
3351029Sbill 			dfork(p);
3361029Sbill 		}
3371029Sbill 	}
3381029Sbill }
3391029Sbill 
340*6816Ssam #include <sys/ioctl.h>
341*6816Ssam 
3421029Sbill dfork(p)
3431029Sbill struct tab *p;
3441029Sbill {
3451029Sbill 	register pid;
3465971Sroot 	time_t t;
3475971Sroot 	int dowait = 0;
3481029Sbill 
3495971Sroot 	time(&t);
3505971Sroot 	p->gettycnt++;
3515971Sroot 	if ((t - p->gettytime) >= 60) {
3525971Sroot 		p->gettytime = t;
3535971Sroot 		p->gettycnt = 1;
3545971Sroot 	} else {
3555971Sroot 		if (p->gettycnt >= 5) {
3565971Sroot 			dowait = 1;
3575971Sroot 			p->gettytime = t;
3585971Sroot 			p->gettycnt = 1;
3595971Sroot 		}
3605971Sroot 	}
3611029Sbill 	pid = fork();
3621029Sbill 	if(pid == 0) {
363*6816Ssam 		int oerrno, f;
364*6816Ssam 		extern int errno;
365*6816Ssam 
366*6816Ssam 		signal(SIGTERM, SIG_DFL);
367*6816Ssam 		signal(SIGHUP, SIG_IGN);
3685971Sroot 		if (dowait) {
369*6816Ssam 			f = open("/dev/console", 1);
3705971Sroot 			write(f, "init: ", 6);
3715971Sroot 			write(f, tty, strlen(tty));
3725971Sroot 			write(f, ": getty failing, sleeping\n\r", 27);
3735971Sroot 			close(f);
3745971Sroot 			sleep(30);
375*6816Ssam 			if ((f = open("/dev/tty", 2)) >= 0) {
376*6816Ssam 				ioctl(f, TIOCNOTTY, 0);
377*6816Ssam 				close(f);
378*6816Ssam 			}
3795971Sroot 		}
3801029Sbill 		strcpy(tty, dev);
3811029Sbill 		strncat(tty, p->line, LINSIZ);
3821029Sbill 		chown(tty, 0, 0);
3831029Sbill 		chmod(tty, 0622);
3843608Swnj 		if (open(tty, 2) < 0) {
3853608Swnj 			int repcnt = 0;
3863608Swnj 			do {
387*6816Ssam 				oerrno = errno;
3883608Swnj 				if (repcnt % 10 == 0) {
389*6816Ssam 					f = open("/dev/console", 1);
3903608Swnj 					write(f, "init: ", 6);
391*6816Ssam 					errno = oerrno, perror(tty);
3923608Swnj 					close(f);
393*6816Ssam 					if ((f = open("/dev/tty", 2)) >= 0) {
394*6816Ssam 						ioctl(f, TIOCNOTTY, 0);
395*6816Ssam 						close(f);
396*6816Ssam 					}
3973608Swnj 				}
3983608Swnj 				repcnt++;
3993608Swnj 				sleep(60);
4003608Swnj 			} while (open(tty, 2) < 0);
4013608Swnj 			exit(0);	/* have wrong control tty, start over */
4023608Swnj 		}
4031029Sbill 		vhangup();
4041029Sbill 		signal(SIGHUP, SIG_DFL);
4051029Sbill 		open(tty, 2);
4061029Sbill 		close(0);
4071029Sbill 		dup(1);
4081029Sbill 		dup(0);
4091029Sbill 		tty[0] = p->comn;
4101029Sbill 		tty[1] = 0;
4111029Sbill 		execl(getty, minus, tty, (char *)0);
4121029Sbill 		exit(0);
4131029Sbill 	}
4141029Sbill 	p->pid = pid;
4151029Sbill }
4161029Sbill 
4171029Sbill rmut(p)
4181029Sbill register struct tab *p;
4191029Sbill {
4201029Sbill 	register f;
4213608Swnj 	int found = 0;
4221029Sbill 
4231029Sbill 	f = open(utmp, 2);
4241029Sbill 	if(f >= 0) {
4251029Sbill 		while(read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) {
4263608Swnj 			if (SCMPN(wtmp.ut_line, p->line) || wtmp.ut_name[0]==0)
4271029Sbill 				continue;
4281029Sbill 			lseek(f, -(long)sizeof(wtmp), 1);
4291029Sbill 			SCPYN(wtmp.ut_name, "");
4301029Sbill 			time(&wtmp.ut_time);
4311029Sbill 			write(f, (char *)&wtmp, sizeof(wtmp));
4323608Swnj 			found++;
4331029Sbill 		}
4341029Sbill 		close(f);
4351029Sbill 	}
4363608Swnj 	if (found) {
4373608Swnj 		f = open(wtmpf, 1);
4383608Swnj 		if (f >= 0) {
4393608Swnj 			SCPYN(wtmp.ut_line, p->line);
4403608Swnj 			SCPYN(wtmp.ut_name, "");
4413608Swnj 			time(&wtmp.ut_time);
4423608Swnj 			lseek(f, (long)0, 2);
4433608Swnj 			write(f, (char *)&wtmp, sizeof(wtmp));
4443608Swnj 			close(f);
4453608Swnj 		}
4461029Sbill 	}
4471029Sbill }
4481029Sbill 
4491029Sbill reset()
4501029Sbill {
4511029Sbill 	longjmp(sjbuf, 1);
4521029Sbill }
4532821Swnj 
4542821Swnj idle()
4552821Swnj {
4562821Swnj 	register struct tab *p;
4572821Swnj 	register pid;
4582821Swnj 
4592821Swnj 	signal(SIGTSTP, idle);
4602821Swnj 	for (;;) {
4612821Swnj 		pid = wait((int *) 0);
4622821Swnj 		if (mergflag)
4632821Swnj 			return;
4642821Swnj 		if (pid == -1)
4652821Swnj 			pause();
4662821Swnj 		else {
4672821Swnj 			for (ALL)
4682821Swnj 				if (p->pid == pid) {
4692821Swnj 					rmut(p);
4702821Swnj 					p->pid = -1;
4712821Swnj 				}
4722821Swnj 		}
4732821Swnj 	}
4742821Swnj }
475