xref: /csrg-svn/old/init/init.c (revision 12682)
1*12682Ssam #ifndef lint
2*12682Ssam static	char *sccsid = "@(#)init.c	4.11 (Berkeley) 05/22/83";
3*12682Ssam #endif
4*12682Ssam 
51029Sbill #include <signal.h>
61029Sbill #include <sys/types.h>
71029Sbill #include <utmp.h>
81029Sbill #include <setjmp.h>
91403Sbill #include <sys/reboot.h>
102821Swnj #include <errno.h>
111029Sbill 
121029Sbill #define	LINSIZ	sizeof(wtmp.ut_line)
131029Sbill #define	TABSIZ	100
141029Sbill #define	ALL	p = &itab[0]; p < &itab[TABSIZ]; p++
151029Sbill #define	EVER	;;
161029Sbill #define SCPYN(a, b)	strncpy(a, b, sizeof(a))
171029Sbill #define SCMPN(a, b)	strncmp(a, b, sizeof(a))
181029Sbill 
191029Sbill char	shell[]	= "/bin/sh";
201403Sbill char	getty[]	 = "/etc/getty";
211029Sbill char	minus[]	= "-";
221029Sbill char	runc[]	= "/etc/rc";
231029Sbill char	ifile[]	= "/etc/ttys";
241029Sbill char	utmp[]	= "/etc/utmp";
251029Sbill char	wtmpf[]	= "/usr/adm/wtmp";
261029Sbill char	ctty[]	= "/dev/console";
271029Sbill char	dev[]	= "/dev/";
281029Sbill 
291029Sbill struct utmp wtmp;
301029Sbill struct
311029Sbill {
321029Sbill 	char	line[LINSIZ];
331029Sbill 	char	comn;
341029Sbill 	char	flag;
351029Sbill } line;
361029Sbill struct	tab
371029Sbill {
381029Sbill 	char	line[LINSIZ];
391029Sbill 	char	comn;
401029Sbill 	char	xflag;
411029Sbill 	int	pid;
425971Sroot 	time_t	gettytime;
435971Sroot 	int	gettycnt;
441029Sbill } itab[TABSIZ];
451029Sbill 
461029Sbill int	fi;
471029Sbill int	mergflag;
481029Sbill char	tty[20];
491429Sbill jmp_buf	sjbuf, shutpass;
502821Swnj time_t	time0;
511029Sbill 
521029Sbill int	reset();
532821Swnj int	idle();
541029Sbill char	*strcpy(), *strcat();
551029Sbill long	lseek();
561029Sbill 
579869Spugs #ifndef sun
581029Sbill main()
591029Sbill {
601403Sbill 	register int r11;		/* passed thru from boot */
619869Spugs #else sun
629869Spugs main(argc, argv)
639869Spugs 	char **argv;
649869Spugs {
659869Spugs #endif sun
661403Sbill 	int howto, oldhowto;
671403Sbill 
682821Swnj 	time0 = time(0);
699869Spugs #ifndef sun
701403Sbill 	howto = r11;
719869Spugs #else sun
729869Spugs 	if (argc > 1 && argv[1][0] == '-') {
739869Spugs 		char *cp;
749869Spugs 
759869Spugs 		howto = 0;
769869Spugs 		cp = &argv[1][1];
779869Spugs 		while (*cp) switch (*cp++) {
789869Spugs 		case 'a':
799869Spugs 			howto |= RB_ASKNAME;
809869Spugs 			break;
819869Spugs 		case 's':
829869Spugs 			howto |= RB_SINGLE;
839869Spugs 			break;
849869Spugs 		}
859869Spugs 	} else {
869869Spugs 		howto = RB_SINGLE;
879869Spugs 	}
889869Spugs #endif sun
891029Sbill 	setjmp(sjbuf);
901029Sbill 	signal(SIGTERM, reset);
912821Swnj 	signal(SIGTSTP, idle);
921029Sbill 	signal(SIGSTOP, SIG_IGN);
931029Sbill 	signal(SIGTTIN, SIG_IGN);
941029Sbill 	signal(SIGTTOU, SIG_IGN);
951029Sbill 	for(EVER) {
961403Sbill 		oldhowto = howto;
971403Sbill 		howto = RB_SINGLE;
981429Sbill 		if (setjmp(shutpass) == 0)
991429Sbill 			shutdown();
1001403Sbill 		if (oldhowto & RB_SINGLE)
1011403Sbill 			single();
1021403Sbill 		if (runcom(oldhowto) == 0)
1031403Sbill 			continue;
1041029Sbill 		merge();
1051029Sbill 		multiple();
1061029Sbill 	}
1071029Sbill }
1081029Sbill 
1091429Sbill int	shutreset();
1101429Sbill 
1111029Sbill shutdown()
1121029Sbill {
1131029Sbill 	register i;
1141029Sbill 	register struct tab *p;
1151029Sbill 
1161029Sbill 	close(creat(utmp, 0644));
1171029Sbill 	signal(SIGHUP, SIG_IGN);
1181029Sbill 	for(ALL) {
1191029Sbill 		term(p);
1201029Sbill 		p->line[0] = 0;
1211029Sbill 	}
1221429Sbill 	signal(SIGALRM, shutreset);
1231429Sbill 	alarm(30);
1241029Sbill 	for(i=0; i<5; i++)
1251029Sbill 		kill(-1, SIGKILL);
1261029Sbill 	while(wait((int *)0) != -1)
1271029Sbill 		;
1281029Sbill 	alarm(0);
1291429Sbill 	shutend();
1301429Sbill }
1311429Sbill 
1321429Sbill char shutfailm[] = "WARNING: Something is hung (wont die); ps axl advised\n";
1331429Sbill 
1341429Sbill shutreset()
1351429Sbill {
1361429Sbill 	int status;
1371429Sbill 
1381429Sbill 	if (fork() == 0) {
1391429Sbill 		int ct = open(ctty, 1);
1401429Sbill 		write(ct, shutfailm, sizeof (shutfailm));
1411429Sbill 		sleep(5);
1421429Sbill 		exit(1);
1431429Sbill 	}
1441429Sbill 	sleep(5);
1451429Sbill 	shutend();
1461429Sbill 	longjmp(shutpass, 1);
1471429Sbill }
1481429Sbill 
1491429Sbill shutend()
1501429Sbill {
1512821Swnj 	register i, f;
1521429Sbill 
1532821Swnj 	acct(0);
1541029Sbill 	signal(SIGALRM, SIG_DFL);
1551029Sbill 	for(i=0; i<10; i++)
1561029Sbill 		close(i);
1572821Swnj 	f = open(wtmpf, 1);
1582821Swnj 	if (f >= 0) {
1592821Swnj 		lseek(f, 0L, 2);
1602821Swnj 		SCPYN(wtmp.ut_line, "~");
1612821Swnj 		SCPYN(wtmp.ut_name, "shutdown");
162*12682Ssam 		SCPYN(wtmp.ut_host, "");
1632821Swnj 		time(&wtmp.ut_time);
1642821Swnj 		write(f, (char *)&wtmp, sizeof(wtmp));
1652821Swnj 		close(f);
1662821Swnj 	}
1672821Swnj 	return(1);
1681029Sbill }
1691029Sbill 
1701029Sbill single()
1711029Sbill {
1721029Sbill 	register pid;
1732821Swnj 	register xpid;
1742821Swnj 	extern	errno;
1751029Sbill 
1762821Swnj    do {
1771029Sbill 	pid = fork();
1781029Sbill 	if(pid == 0) {
1791029Sbill /*
1801029Sbill 		alarm(300);
1811029Sbill */
1821029Sbill 		signal(SIGTERM, SIG_DFL);
1831029Sbill 		signal(SIGHUP, SIG_DFL);
1841029Sbill 		signal(SIGALRM, SIG_DFL);
1851029Sbill 		open(ctty, 2);
1861029Sbill 		dup(0);
1871029Sbill 		dup(0);
1881029Sbill 		execl(shell, minus, (char *)0);
1891029Sbill 		exit(0);
1901029Sbill 	}
1912821Swnj 	while((xpid = wait((int *)0)) != pid)
1922821Swnj 		if (xpid == -1 && errno == ECHILD)
1932821Swnj 			break;
1942821Swnj    } while (xpid == -1);
1951029Sbill }
1961029Sbill 
1971403Sbill runcom(oldhowto)
1981403Sbill 	int oldhowto;
1991029Sbill {
2001029Sbill 	register pid, f;
2011403Sbill 	int status;
2021029Sbill 
2031029Sbill 	pid = fork();
2041029Sbill 	if(pid == 0) {
2051029Sbill 		open("/", 0);
2061029Sbill 		dup(0);
2071029Sbill 		dup(0);
2081403Sbill 		if (oldhowto & RB_SINGLE)
2091403Sbill 			execl(shell, shell, runc, (char *)0);
2101403Sbill 		else
2111403Sbill 			execl(shell, shell, runc, "autoboot", (char *)0);
2121403Sbill 		exit(1);
2131029Sbill 	}
2141403Sbill 	while(wait(&status) != pid)
2151029Sbill 		;
2161403Sbill 	if(status)
2171403Sbill 		return(0);
2181029Sbill 	f = open(wtmpf, 1);
2191029Sbill 	if (f >= 0) {
2201029Sbill 		lseek(f, 0L, 2);
2211029Sbill 		SCPYN(wtmp.ut_line, "~");
2221029Sbill 		SCPYN(wtmp.ut_name, "reboot");
223*12682Ssam 		SCPYN(wtmp.ut_host, "");
2242821Swnj 		if (time0) {
2252821Swnj 			wtmp.ut_time = time0;
2262821Swnj 			time0 = 0;
2272821Swnj 		} else
2282821Swnj 			time(&wtmp.ut_time);
2291029Sbill 		write(f, (char *)&wtmp, sizeof(wtmp));
2301029Sbill 		close(f);
2311029Sbill 	}
2321403Sbill 	return(1);
2331029Sbill }
2341029Sbill 
2351029Sbill setmerge()
2361029Sbill {
2371029Sbill 
2381029Sbill 	signal(SIGHUP, setmerge);
2391029Sbill 	mergflag = 1;
2401029Sbill }
2411029Sbill 
2421029Sbill multiple()
2431029Sbill {
2441029Sbill 	register struct tab *p;
2451029Sbill 	register pid;
2461029Sbill 
2471029Sbill loop:
2481029Sbill 	mergflag = 0;
2491029Sbill 	signal(SIGHUP, setmerge);
2501029Sbill 	for(EVER) {
2511029Sbill 		pid = wait((int *)0);
2521029Sbill 		if(mergflag) {
2531029Sbill 			merge();
2541029Sbill 			goto loop;
2551029Sbill 		}
2561029Sbill 		if(pid == -1)
2571029Sbill 			return;
2581029Sbill 		for(ALL)
2591029Sbill 			if(p->pid == pid || p->pid == -1) {
2601029Sbill 				rmut(p);
2611029Sbill 				dfork(p);
2621029Sbill 			}
2631029Sbill 	}
2641029Sbill }
2651029Sbill 
2661029Sbill term(p)
2671029Sbill register struct tab *p;
2681029Sbill {
2691029Sbill 
2701029Sbill 	if(p->pid != 0) {
2711029Sbill 		rmut(p);
2721029Sbill 		kill(p->pid, SIGKILL);
2731029Sbill 	}
2741029Sbill 	p->pid = 0;
2751029Sbill }
2761029Sbill 
2771029Sbill rline()
2781029Sbill {
2791029Sbill 	register c, i;
2801029Sbill 
2811029Sbill loop:
2821029Sbill 	c = get();
2831029Sbill 	if(c < 0)
2841029Sbill 		return(0);
2851029Sbill 	if(c == 0)
2861029Sbill 		goto loop;
2871029Sbill 	line.flag = c;
2881029Sbill 	c = get();
2891029Sbill 	if(c <= 0)
2901029Sbill 		goto loop;
2911029Sbill 	line.comn = c;
2921029Sbill 	SCPYN(line.line, "");
2931029Sbill 	for (i=0; i<LINSIZ; i++) {
2941029Sbill 		c = get();
2951029Sbill 		if(c <= 0)
2961029Sbill 			break;
2971029Sbill 		line.line[i] = c;
2981029Sbill 	}
2991029Sbill 	while(c > 0)
3001029Sbill 		c = get();
3011029Sbill 	if(line.line[0] == 0)
3021029Sbill 		goto loop;
3031029Sbill 	if(line.flag == '0')
3041029Sbill 		goto loop;
3051029Sbill 	strcpy(tty, dev);
3061029Sbill 	strncat(tty, line.line, LINSIZ);
3071029Sbill 	if(access(tty, 06) < 0)
3081029Sbill 		goto loop;
3091029Sbill 	return(1);
3101029Sbill }
3111029Sbill 
3121029Sbill get()
3131029Sbill {
3141029Sbill 	char b;
3151029Sbill 
3161029Sbill 	if(read(fi, &b, 1) != 1)
3171029Sbill 		return(-1);
3181029Sbill 	if(b == '\n')
3191029Sbill 		return(0);
3201029Sbill 	return(b);
3211029Sbill }
3221029Sbill 
3231029Sbill #define	FOUND	1
3241029Sbill #define	CHANGE	2
3251029Sbill 
3261029Sbill merge()
3271029Sbill {
3281029Sbill 	register struct tab *p;
3291029Sbill 
3301029Sbill 	fi = open(ifile, 0);
3311029Sbill 	if(fi < 0)
3321029Sbill 		return;
3331029Sbill 	for(ALL)
3341029Sbill 		p->xflag = 0;
3351029Sbill 	while(rline()) {
3361029Sbill 		for(ALL) {
3371029Sbill 			if (SCMPN(p->line, line.line))
3381029Sbill 				continue;
3391029Sbill 			p->xflag |= FOUND;
3401029Sbill 			if(line.comn != p->comn) {
3411029Sbill 				p->xflag |= CHANGE;
3421029Sbill 				p->comn = line.comn;
3431029Sbill 			}
3441029Sbill 			goto contin1;
3451029Sbill 		}
3461029Sbill 		for(ALL) {
3471029Sbill 			if(p->line[0] != 0)
3481029Sbill 				continue;
3491029Sbill 			SCPYN(p->line, line.line);
3501029Sbill 			p->xflag |= FOUND|CHANGE;
3511029Sbill 			p->comn = line.comn;
3521029Sbill 			goto contin1;
3531029Sbill 		}
3541029Sbill 	contin1:
3551029Sbill 		;
3561029Sbill 	}
3571029Sbill 	close(fi);
3581029Sbill 	for(ALL) {
3591029Sbill 		if((p->xflag&FOUND) == 0) {
3601029Sbill 			term(p);
3611029Sbill 			p->line[0] = 0;
3621029Sbill 		}
3631029Sbill 		if((p->xflag&CHANGE) != 0) {
3641029Sbill 			term(p);
3651029Sbill 			dfork(p);
3661029Sbill 		}
3671029Sbill 	}
3681029Sbill }
3691029Sbill 
3706816Ssam #include <sys/ioctl.h>
3716816Ssam 
3721029Sbill dfork(p)
3731029Sbill struct tab *p;
3741029Sbill {
3751029Sbill 	register pid;
3765971Sroot 	time_t t;
3775971Sroot 	int dowait = 0;
3789579Spugs 	extern char *sys_errlist[];
3791029Sbill 
3805971Sroot 	time(&t);
3815971Sroot 	p->gettycnt++;
3825971Sroot 	if ((t - p->gettytime) >= 60) {
3835971Sroot 		p->gettytime = t;
3845971Sroot 		p->gettycnt = 1;
3855971Sroot 	} else {
3865971Sroot 		if (p->gettycnt >= 5) {
3875971Sroot 			dowait = 1;
3885971Sroot 			p->gettytime = t;
3895971Sroot 			p->gettycnt = 1;
3905971Sroot 		}
3915971Sroot 	}
3921029Sbill 	pid = fork();
3931029Sbill 	if(pid == 0) {
3946816Ssam 		int oerrno, f;
3956816Ssam 		extern int errno;
3966816Ssam 
3976816Ssam 		signal(SIGTERM, SIG_DFL);
3986816Ssam 		signal(SIGHUP, SIG_IGN);
3999579Spugs 		strcpy(tty, dev);
4009579Spugs 		strncat(tty, p->line, LINSIZ);
4015971Sroot 		if (dowait) {
4026816Ssam 			f = open("/dev/console", 1);
4035971Sroot 			write(f, "init: ", 6);
4045971Sroot 			write(f, tty, strlen(tty));
4055971Sroot 			write(f, ": getty failing, sleeping\n\r", 27);
4065971Sroot 			close(f);
4075971Sroot 			sleep(30);
4086816Ssam 			if ((f = open("/dev/tty", 2)) >= 0) {
4096816Ssam 				ioctl(f, TIOCNOTTY, 0);
4106816Ssam 				close(f);
4116816Ssam 			}
4125971Sroot 		}
4131029Sbill 		chown(tty, 0, 0);
4141029Sbill 		chmod(tty, 0622);
4153608Swnj 		if (open(tty, 2) < 0) {
4163608Swnj 			int repcnt = 0;
4173608Swnj 			do {
4186816Ssam 				oerrno = errno;
4193608Swnj 				if (repcnt % 10 == 0) {
4206816Ssam 					f = open("/dev/console", 1);
4213608Swnj 					write(f, "init: ", 6);
4229579Spugs 					write(f, tty, strlen(tty));
4239579Spugs 					write(f, ": ", 2);
4249579Spugs 					write(f, sys_errlist[oerrno],
4259579Spugs 						strlen(sys_errlist[oerrno]));
4269579Spugs 					write(f, "\n", 1);
4273608Swnj 					close(f);
4286816Ssam 					if ((f = open("/dev/tty", 2)) >= 0) {
4296816Ssam 						ioctl(f, TIOCNOTTY, 0);
4306816Ssam 						close(f);
4316816Ssam 					}
4323608Swnj 				}
4333608Swnj 				repcnt++;
4343608Swnj 				sleep(60);
4353608Swnj 			} while (open(tty, 2) < 0);
4363608Swnj 			exit(0);	/* have wrong control tty, start over */
4373608Swnj 		}
4381029Sbill 		vhangup();
4391029Sbill 		signal(SIGHUP, SIG_DFL);
4401029Sbill 		open(tty, 2);
4411029Sbill 		close(0);
4421029Sbill 		dup(1);
4431029Sbill 		dup(0);
4441029Sbill 		tty[0] = p->comn;
4451029Sbill 		tty[1] = 0;
4461029Sbill 		execl(getty, minus, tty, (char *)0);
4471029Sbill 		exit(0);
4481029Sbill 	}
4491029Sbill 	p->pid = pid;
4501029Sbill }
4511029Sbill 
4521029Sbill rmut(p)
4531029Sbill register struct tab *p;
4541029Sbill {
4551029Sbill 	register f;
4563608Swnj 	int found = 0;
4571029Sbill 
4581029Sbill 	f = open(utmp, 2);
4591029Sbill 	if(f >= 0) {
4601029Sbill 		while(read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) {
4613608Swnj 			if (SCMPN(wtmp.ut_line, p->line) || wtmp.ut_name[0]==0)
4621029Sbill 				continue;
4631029Sbill 			lseek(f, -(long)sizeof(wtmp), 1);
4641029Sbill 			SCPYN(wtmp.ut_name, "");
465*12682Ssam 			SCPYN(wtmp.ut_host, "");
4661029Sbill 			time(&wtmp.ut_time);
4671029Sbill 			write(f, (char *)&wtmp, sizeof(wtmp));
4683608Swnj 			found++;
4691029Sbill 		}
4701029Sbill 		close(f);
4711029Sbill 	}
4723608Swnj 	if (found) {
4733608Swnj 		f = open(wtmpf, 1);
4743608Swnj 		if (f >= 0) {
4753608Swnj 			SCPYN(wtmp.ut_line, p->line);
4763608Swnj 			SCPYN(wtmp.ut_name, "");
477*12682Ssam 			SCPYN(wtmp.ut_host, "");
4783608Swnj 			time(&wtmp.ut_time);
4793608Swnj 			lseek(f, (long)0, 2);
4803608Swnj 			write(f, (char *)&wtmp, sizeof(wtmp));
4813608Swnj 			close(f);
4823608Swnj 		}
4831029Sbill 	}
4841029Sbill }
4851029Sbill 
4861029Sbill reset()
4871029Sbill {
4881029Sbill 	longjmp(sjbuf, 1);
4891029Sbill }
4902821Swnj 
4912821Swnj idle()
4922821Swnj {
4932821Swnj 	register struct tab *p;
4942821Swnj 	register pid;
4952821Swnj 
4962821Swnj 	signal(SIGTSTP, idle);
4972821Swnj 	for (;;) {
4982821Swnj 		pid = wait((int *) 0);
4992821Swnj 		if (mergflag)
5002821Swnj 			return;
5012821Swnj 		if (pid == -1)
5022821Swnj 			pause();
5032821Swnj 		else {
5042821Swnj 			for (ALL)
5052821Swnj 				if (p->pid == pid) {
5062821Swnj 					rmut(p);
5072821Swnj 					p->pid = -1;
5082821Swnj 				}
5092821Swnj 		}
5102821Swnj 	}
5112821Swnj }
512