⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 init.c

📁 早期freebsd实现
💻 C
字号:
/* * Copyright (c) 1980,1986 Regents of the University of California. * All rights reserved.  The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */#ifndef lintstatic char sccsid[] = "@(#)init.c	5.6 (Berkeley) 5/26/86";#endif not lint#include <signal.h>#include <sys/types.h>#include <utmp.h>#include <setjmp.h>#include <sys/reboot.h>#include <errno.h>#include <sys/file.h>#include <ttyent.h>#include <sys/syslog.h>#include <sys/stat.h>#define	LINSIZ	sizeof(wtmp.ut_line)#define	CMDSIZ	200	/* max string length for getty or window command*/#define	ALL	p = itab; p ; p = p->next#define	EVER	;;#define SCPYN(a, b)	strncpy(a, b, sizeof(a))#define SCMPN(a, b)	strncmp(a, b, sizeof(a))char	shell[]	= "/bin/sh";char	minus[]	= "-";char	runc[]	= "/etc/rc";char	utmpf[]	= "/etc/utmp";char	wtmpf[]	= "/usr/adm/wtmp";char	ctty[]	= "/dev/console";struct utmp wtmp;struct	tab{	char	line[LINSIZ];	char	comn[CMDSIZ];	char	xflag;	int	pid;	int	wpid;		/* window system pid for SIGHUP	*/	char	wcmd[CMDSIZ];	/* command to start window system process */	time_t	gettytime;	int	gettycnt;	time_t	windtime;	int	windcnt;	struct	tab *next;} *itab;int	fi;int	mergflag;char	tty[20];jmp_buf	sjbuf, shutpass;time_t	time0;int	reset();int	idle();char	*strcpy(), *strcat();long	lseek();struct	sigvec rvec = { reset, sigmask(SIGHUP), 0 };#if defined(vax) || defined(ns32000)main(){	register int r11;		/* passed thru from boot */#elsemain(argc, argv)	char **argv;{#endif	int howto, oldhowto;	time0 = time(0);#if defined(vax) || defined(ns32000)	howto = r11;#else	if (argc > 1 && argv[1][0] == '-') {		char *cp;		howto = 0;		cp = &argv[1][1];		while (*cp) switch (*cp++) {		case 'a':			howto |= RB_ASKNAME;			break;		case 's':			howto |= RB_SINGLE;			break;		}	} else {		howto = RB_SINGLE;	}#endif	openlog("init", LOG_CONS|LOG_ODELAY, LOG_AUTH);	sigvec(SIGTERM, &rvec, (struct sigvec *)0);	signal(SIGTSTP, idle);	signal(SIGSTOP, SIG_IGN);	signal(SIGTTIN, SIG_IGN);	signal(SIGTTOU, SIG_IGN);	(void) setjmp(sjbuf);	for (EVER) {		oldhowto = howto;		howto = RB_SINGLE;		if (setjmp(shutpass) == 0)			shutdown();		if (oldhowto & RB_SINGLE)			single();		if (runcom(oldhowto) == 0) 			continue;		merge();		multiple();	}}int	shutreset();shutdown(){	register i;	register struct tab *p, *p1;	close(creat(utmpf, 0644));	signal(SIGHUP, SIG_IGN);	for (p = itab; p ; ) {		term(p);		p1 = p->next;		free(p);		p = p1;	}	itab = (struct tab *)0;	signal(SIGALRM, shutreset);	(void) kill(-1, SIGTERM);	/* one chance to catch it */	sleep(5);	alarm(30);	for (i = 0; i < 5; i++)		kill(-1, SIGKILL);	while (wait((int *)0) != -1)		;	alarm(0);	shutend();}char shutfailm[] = "WARNING: Something is hung (wont die); ps axl advised\n";shutreset(){	int status;	if (fork() == 0) {		int ct = open(ctty, 1);		write(ct, shutfailm, sizeof (shutfailm));		sleep(5);		exit(1);	}	sleep(5);	shutend();	longjmp(shutpass, 1);}shutend(){	register i, f;	acct(0);	signal(SIGALRM, SIG_DFL);	for (i = 0; i < 10; i++)		close(i);	f = open(wtmpf, O_WRONLY|O_APPEND);	if (f >= 0) {		SCPYN(wtmp.ut_line, "~");		SCPYN(wtmp.ut_name, "shutdown");		SCPYN(wtmp.ut_host, "");		time(&wtmp.ut_time);		write(f, (char *)&wtmp, sizeof(wtmp));		close(f);	}	return (1);}single(){	register pid;	register xpid;	extern	errno;	do {		pid = fork();		if (pid == 0) {			signal(SIGTERM, SIG_DFL);			signal(SIGHUP, SIG_DFL);			signal(SIGALRM, SIG_DFL);			signal(SIGTSTP, SIG_IGN);			(void) open(ctty, O_RDWR);			dup2(0, 1);			dup2(0, 2);			execl(shell, minus, (char *)0);			exit(0);		}		while ((xpid = wait((int *)0)) != pid)			if (xpid == -1 && errno == ECHILD)				break;	} while (xpid == -1);}runcom(oldhowto)	int oldhowto;{	register pid, f;	int status;	pid = fork();	if (pid == 0) {		(void) open("/", O_RDONLY);		dup2(0, 1);		dup2(0, 2);		if (oldhowto & RB_SINGLE)			execl(shell, shell, runc, (char *)0);		else			execl(shell, shell, runc, "autoboot", (char *)0);		exit(1);	}	while (wait(&status) != pid)		;	if (status)		return (0);	f = open(wtmpf, O_WRONLY|O_APPEND);	if (f >= 0) {		SCPYN(wtmp.ut_line, "~");		SCPYN(wtmp.ut_name, "reboot");		SCPYN(wtmp.ut_host, "");		if (time0) {			wtmp.ut_time = time0;			time0 = 0;		} else			time(&wtmp.ut_time);		write(f, (char *)&wtmp, sizeof(wtmp));		close(f);	}	return (1);}struct	sigvec	mvec = { merge, sigmask(SIGTERM), 0 };/* * Multi-user.  Listen for users leaving, SIGHUP's * which indicate ttys has changed, and SIGTERM's which * are used to shutdown the system. */multiple(){	register struct tab *p;	register pid;	int omask;	sigvec(SIGHUP, &mvec, (struct sigvec *)0);	for (EVER) {		pid = wait((int *)0);		if (pid == -1)			return;		omask = sigblock(SIGHUP);		for (ALL) {			/* must restart window system BEFORE emulator */			if (p->wpid == pid || p->wpid == -1)				wstart(p);			if (p->pid == pid || p->pid == -1) {				/* disown the window system */				if (p->wpid)					kill(p->wpid, SIGHUP);				rmut(p);				dfork(p);			}		}		sigsetmask(omask);	}}/* * Merge current contents of ttys file * into in-core table of configured tty lines. * Entered as signal handler for SIGHUP. */#define	FOUND	1#define	CHANGE	2#define WCHANGE 4merge(){	register struct tab *p;	register struct ttyent *t;	register struct tab *p1;	for (ALL)		p->xflag = 0;	setttyent();	while (t = getttyent()) {		if ((t->ty_status & TTY_ON) == 0)			continue;		for (ALL) {			if (SCMPN(p->line, t->ty_name))				continue;			p->xflag |= FOUND;			if (SCMPN(p->comn, t->ty_getty)) {				p->xflag |= CHANGE;				SCPYN(p->comn, t->ty_getty);			}			if (SCMPN(p->wcmd, t->ty_window)) {				p->xflag |= WCHANGE|CHANGE;				SCPYN(p->wcmd, t->ty_window);			}			goto contin1;		}		/*		 * Make space for a new one		 */		p1 = (struct tab *)calloc(1, sizeof(*p1));		if (!p1) {			syslog(LOG_ERR, "no space for '%s' !?!", t->ty_name);			goto contin1;		}		/*		 * Put new terminal at the end of the linked list.		 */		if (itab) {			for (p = itab; p->next ; p = p->next)				;			p->next = p1;		} else			itab = p1;		p = p1;		SCPYN(p->line, t->ty_name);		p->xflag |= FOUND|CHANGE;		SCPYN(p->comn, t->ty_getty);		if (strcmp(t->ty_window, "") != 0) {			p->xflag |= WCHANGE;			SCPYN(p->wcmd, t->ty_window);		}	contin1:		;	}	endttyent();	p1 = (struct tab *)0;	for (ALL) {		if ((p->xflag&FOUND) == 0) {			term(p);			wterm(p);			if (p1)				p1->next = p->next;			else				itab = p->next;			free(p);			p = p1 ? p1 : itab;		} else {			/* window system should be started first */			if (p->xflag&WCHANGE) {				wterm(p);				wstart(p);			}			if (p->xflag&CHANGE) {				term(p);				dfork(p);			}		}		p1 = p;	}}term(p)	register struct tab *p;{	if (p->pid != 0) {		rmut(p);		kill(p->pid, SIGKILL);	}	p->pid = 0;	/* send SIGHUP to get rid of connections */	if (p->wpid > 0)		kill(p->wpid, SIGHUP);}#include <sys/ioctl.h>dfork(p)	struct tab *p;{	register pid;	time_t t;	int dowait = 0;	time(&t);	p->gettycnt++;	if ((t - p->gettytime) >= 60) {		p->gettytime = t;		p->gettycnt = 1;	} else if (p->gettycnt >= 5) {		dowait = 1;		p->gettytime = t;		p->gettycnt = 1;	}	pid = fork();	if (pid == 0) {		signal(SIGTERM, SIG_DFL);		signal(SIGHUP, SIG_IGN);		sigsetmask(0);	/* since can be called from masked code */		if (dowait) {			syslog(LOG_ERR, "'%s %s' failing, sleeping", p->comn, p->line);			closelog();			sleep(30);		}		execit(p->comn, p->line);		exit(0);	}	p->pid = pid;}/* * Remove utmp entry. */rmut(p)	register struct tab *p;{	register f;	int found = 0;	static unsigned utmpsize;	static struct utmp *utmp;	register struct utmp *u;	int nutmp;	struct stat statbf;	f = open(utmpf, O_RDWR);	if (f >= 0) {		fstat(f, &statbf);		if (utmpsize < statbf.st_size) {			utmpsize = statbf.st_size + 10 * sizeof(struct utmp);			if (utmp)				utmp = (struct utmp *)realloc(utmp, utmpsize);			else				utmp = (struct utmp *)malloc(utmpsize);			if (!utmp)				syslog(LOG_ERR, "utmp malloc failed");		}		if (statbf.st_size && utmp) {			nutmp = read(f, utmp, statbf.st_size);			nutmp /= sizeof(struct utmp);			for (u = utmp ; u < &utmp[nutmp] ; u++) {				if (SCMPN(u->ut_line, p->line) ||				    u->ut_name[0]==0)					continue;				lseek(f, ((long)u)-((long)utmp), L_SET);				SCPYN(u->ut_name, "");				SCPYN(u->ut_host, "");				time(&u->ut_time);				write(f, (char *)u, sizeof(*u));				found++;			}		}		close(f);	}	if (found) {		f = open(wtmpf, O_WRONLY|O_APPEND);		if (f >= 0) {			SCPYN(wtmp.ut_line, p->line);			SCPYN(wtmp.ut_name, "");			SCPYN(wtmp.ut_host, "");			time(&wtmp.ut_time);			write(f, (char *)&wtmp, sizeof(wtmp));			close(f);		}		/*		 * After a proper login force reset		 * of error detection code in dfork.		 */		p->gettytime = 0;		p->windtime = 0;	}}reset(){	longjmp(sjbuf, 1);}jmp_buf	idlebuf;idlehup(){	longjmp(idlebuf, 1);}idle(){	register struct tab *p;	register pid;	signal(SIGHUP, idlehup);	for (EVER) {		if (setjmp(idlebuf))			return;		pid = wait((int *) 0);		if (pid == -1) {			sigpause(0);			continue;		}		for (ALL) {			/* if window system dies, mark it for restart */			if (p->wpid == pid)				p->wpid = -1;			if (p->pid == pid) {				rmut(p);				p->pid = -1;			}		}	}}wterm(p)	register struct tab *p;{	if (p->wpid != 0) {		kill(p->wpid, SIGKILL);	}	p->wpid = 0;}wstart(p)	register struct tab *p;{	register pid;	time_t t;	int dowait = 0;	time(&t);	p->windcnt++;	if ((t - p->windtime) >= 60) {		p->windtime = t;		p->windcnt = 1;	} else if (p->windcnt >= 5) {		dowait = 1;		p->windtime = t;		p->windcnt = 1;	}	pid = fork();	if (pid == 0) {		signal(SIGTERM, SIG_DFL);		signal(SIGHUP,  SIG_IGN);		sigsetmask(0);	/* since can be called from masked code */		if (dowait) {			syslog(LOG_ERR, "'%s %s' failing, sleeping", p->wcmd, p->line);			closelog();			sleep(30);		}		execit(p->wcmd, p->line);		exit(0);	}	p->wpid = pid;}#define NARGS	20	/* must be at least 4 */#define ARGLEN	512	/* total size for all the argument strings */execit(s, arg)	char *s;	char *arg;	/* last argument on line */{	char *argv[NARGS], args[ARGLEN], *envp[1];	register char *sp = s;	register char *ap = args;	register char c;	register int i;	/*	 * First we have to set up the argument vector.	 * "prog arg1 arg2" maps to exec("prog", "-", "arg1", "arg2"). 	 */	for (i = 1; i < NARGS - 2; i++) {		argv[i] = ap;		for (EVER) {			if ((c = *sp++) == '\0' || ap >= &args[ARGLEN-1]) {				*ap = '\0';				goto done;			}			if (c == ' ') {				*ap++ = '\0';				while (*sp == ' ')					sp++;				if (*sp == '\0')					goto done;				break;			}			*ap++ = c;		}	}done:	argv[0] = argv[1];	argv[1] = "-";	argv[i+1] = arg;	argv[i+2] = 0;	envp[0] = 0;	execve(argv[0], &argv[1], envp);	/* report failure of exec */	syslog(LOG_ERR, "%s: %m", argv[0]);	closelog();	sleep(10);	/* prevent failures from eating machine */}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -