sh.proc.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,167 行 · 第 1/2 页

C
1,167
字号
	if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {		pp->p_flags &= ~PPTIME;		pp->p_flags |= PTIME;	}	tp = pp;	status = reason = -1; 	jobflags = 0;	/*	 Ring terminal bell, if requested.	 Characters must be quoted to keep from	 being echoed as ^x	*/	if (flag&NOISEOK && adrof("notify"))	    {	    register unsigned char *nmp;	    for (nmp = (unsigned char *)value("notify"); *nmp; nmp++)		{		if (*nmp == QUOTECHAR)	/* simply skip all quote chars */			nmp++;		putchar((int)(QUOTE|*nmp));	        }	    }	do {		jobflags |= pp->p_flags;		pstatus = pp->p_flags & PALLSTATES;		if (tp != pp && linp != linbuf && !(flag&FANCY) &&		    (pstatus == status && pp->p_reason == reason ||		     !(flag&REASON)))			csh_printf(" ");			/* 004 RNF */		else {			if (tp != pp && linp != linbuf)				csh_printf("\n");		/* 004 RNF */			if(flag&NUMBER)				if (pp == tp)			/* 004 RNF */	csh_printf("[%d]%s %c ", pp->p_index,					    pp->p_index < 10 ? " " : "",					    pp==pcurrent ? '+' :						(pp == pprevious ? '-' : ' '));				else					csh_printf("       ");	/* 004 RNF */			if (flag&FANCY)				csh_printf("%5d ", pp->p_pid);	/* 004 RNF */			if (flag&(REASON|AREASON)) {				if (flag&NAME)					format = "%-21s";				else					format = "%s";				if (pstatus == status)					if (pp->p_reason == reason) {						csh_printf(format, ""); /* 004 RNF */						goto prcomd;					} else						reason = pp->p_reason;				else {					status = pstatus;					reason = pp->p_reason;				}				switch (status) {				case PRUNNING:					csh_printf(format, "Running "); /* 004 RNF */					break;				case PINTERRUPTED:				case PSTOPPED:				case PSIGNALED:					if ((flag&(REASON|AREASON))					    && reason != SIGINT					    && reason != SIGPIPE)						csh_printf(format, mesg[pp->p_reason].pname); /* 004 RNF */					break;				case PNEXITED:				case PAEXITED:					if (flag & REASON)						if (pp->p_reason)							csh_printf("Exit %-16d", pp->p_reason); /* 004 RNF */						else							csh_printf(format, "Done"); /* 004 RNF */					break;				default:					csh_printf("BUG: status=%-9o", status); /* 004 RNF */				}			}		}prcomd:		if (flag&NAME) {			csh_printf("%s", pp->p_command); 	/* 004 RNF */			if (pp->p_flags & PPOU)				csh_printf(" |");		/* 004 RNF */			if (pp->p_flags & PDIAG)				csh_printf("&");		/* 004 RNF */		}		if (flag&(REASON|AREASON) && pp->p_flags&PDUMPED)			csh_printf(" (core dumped)");		/* 004 RNF */		if (tp == pp->p_friends) {			if (flag&AMPERSAND)				csh_printf(" &");		/* 004 RNF */			if (flag&JOBDIR &&			    !eq(tp->p_cwd->di_name, dcwd->di_name)) {				csh_printf(" (wd: ");		/* 004 RNF */				dtildepr(value("home"), tp->p_cwd->di_name);				csh_printf(")");		/* 004 RNF */			}		}		if (pp->p_flags&PPTIME && !(status&(PSTOPPED|PRUNNING))) {			if (linp != linbuf)				csh_printf("\n\t");		/* 004 RNF */			{ static struct rusage zru;			  prusage(&zru, &pp->p_rusage, &pp->p_etime,			    &pp->p_btime);			}		}		if (tp == pp->p_friends) {			if (linp != linbuf)				csh_printf("\n");		/* 004 RNF */			if (flag&SHELLDIR && !eq(tp->p_cwd->di_name, dcwd->di_name)) {				csh_printf("(wd now: ");	/* 004 RNF */				dtildepr(value("home"), dcwd->di_name);				csh_printf(")\n");		/* 004 RNF */			}		}	} while ((pp = pp->p_friends) != tp);	if (jobflags&PTIME && (jobflags&(PSTOPPED|PRUNNING)) == 0) {		if (jobflags & NUMBER)			csh_printf("       ");			/* 004 RNF */		ptprint(tp);	}	return (jobflags);}ptprint(tp)	register struct process *tp;{	struct timeval tetime, diff;	static struct timeval ztime;	struct rusage ru;	static struct rusage zru;	register struct process *pp = tp;	ru = zru;	tetime = ztime;	do {		ruadd(&ru, &pp->p_rusage);		tvsub(&diff, &pp->p_etime, &pp->p_btime);		if (timercmp(&diff, &tetime, >))			tetime = diff;	} while ((pp = pp->p_friends) != tp);	prusage(&zru, &ru, &tetime, &ztime);}/* * dojobs - print all jobs */dojobs(v)	char **v;{	register struct process *pp;	register int flag = NUMBER|NAME|REASON;	int i;	if (chkstop)		chkstop = 2;	if (*++v) {		if (v[1] || !eq(*v, "-l"))			error("Usage: jobs [ -l ]");		flag |= FANCY|JOBDIR;	}	for (i = 1; i <= pmaxindex; i++)		for (pp = proclist.p_next; pp; pp = pp->p_next)			if (pp->p_index == i && pp->p_pid == pp->p_jobid) {				pp->p_flags &= ~PNEEDNOTE;				if (!(pprint(pp, flag) & (PRUNNING|PSTOPPED)))					pflush(pp);				break;			}}/* * dofg - builtin - put the job into the foreground */dofg(v)	char **v;{	register struct process *pp;	okpcntl();	++v;	do {		pp = pfind(*v);		pstart(pp, 1);		pjwait(pp);	} while (*v && *++v);}/* * %... - builtin - put the job into the foreground */dofg1(v)	char **v;{	register struct process *pp;	okpcntl();	pp = pfind(v[0]);	pstart(pp, 1);	pjwait(pp);}/* * dobg - builtin - put the job into the background */dobg(v)	char **v;{	register struct process *pp;	okpcntl();	++v;	do {		pp = pfind(*v);		pstart(pp, 0);	} while (*v && *++v);}/* * %... & - builtin - put the job into the background */dobg1(v)	char **v;{	register struct process *pp;	pp = pfind(v[0]);	pstart(pp, 0);}/* * dostop - builtin - stop the job */dostop(v)	char **v;{	pkill(++v, SIGSTOP);}/* * dokill - builtin - superset of kill (1) */dokill(v)	char **v;{	register int signum;	register char *name;	v++;	if (v[0] && v[0][0] == '-') {		if (v[0][1] == 'l') {			for (signum = 1; signum <= NSIG; signum++) {				if (name = mesg[signum].iname)					csh_printf("%s ", name); /* 004 RNF */				if (signum == 16)					putchar('\n');			}			putchar('\n');			return;		}		if (digit(v[0][1])) {			signum = atoi(v[0]+1);			if (signum < 0 || signum > NSIG)				bferr("Bad signal number");		} else {			name = &v[0][1];			for (signum = 1; signum <= NSIG; signum++)			if (mesg[signum].iname &&			    eq(name, mesg[signum].iname))				goto gotsig;			setname(name);			bferr("Unknown signal; kill -l lists signals");		}gotsig:		v++;	} else		signum = SIGTERM;	pkill(v, signum);}pkill(v, signum)	char **v;	int signum;{	register struct process *pp, *np;	register int jobflags = 0;	int omask, pid, err = 0;	char *cp;	extern char *sys_errlist[];	omask = sigmask(SIGCHLD);	if (setintr)		omask |= sigmask(SIGINT);	omask = sigblock(omask) & ~omask;	while (*v) {		cp = globone(*v);		if (*cp == '%') {			np = pp = pfind(cp);			do				jobflags |= np->p_flags;			while ((np = np->p_friends) != pp);			switch (signum) {			case SIGCONT:				np->p_flags |= PRUNNING;				np->p_flags &= ~PSTOPPED;				break;			case SIGSTOP:			case SIGTSTP:			case SIGTTIN:			case SIGTTOU:				if ((jobflags & PRUNNING) == 0) {					csh_printf("%s: Already stopped\n", cp); /* 004 RNF */					err++;					goto cont;				}			}			if (killpg(pp->p_jobid, signum) < 0) {				csh_printf("%s: ", cp);		/* 004 RNF */				csh_printf("%s\n", sys_errlist[errno]); /* 004 RNF */				err++;			}			if (signum == SIGTERM || signum == SIGHUP)				(void) killpg(pp->p_jobid, SIGCONT);		} else if (!(digit(*cp) || *cp == '-'))			bferr("Arguments should be jobs or process id's");		else {			pid = atoi(cp);			if (kill(pid, signum) < 0) {				csh_printf("%d: ", pid);	/* 004 RNF */				csh_printf("%s\n", sys_errlist[errno]); /* 004 RNF */				err++;				goto cont;			}			if (signum == SIGTERM || signum == SIGHUP)				(void) kill(pid, SIGCONT);		}cont:		xfree(cp);		v++;	}	(void) sigsetmask(omask);	if (err)		error(NOSTR);}/* * pstart - start the job in foreground/background */pstart(pp, foregnd)	register struct process *pp;	int foregnd;{	register struct process *np;	int omask, jobflags = 0;	omask = sigblock(sigmask(SIGCHLD));	np = pp;	do {		jobflags |= np->p_flags;		if (np->p_flags&(PRUNNING|PSTOPPED)) {			np->p_flags |= PRUNNING;			np->p_flags &= ~PSTOPPED;			if (foregnd)				np->p_flags |= PFOREGND;			else				np->p_flags &= ~PFOREGND;		}	} while((np = np->p_friends) != pp);	if (!foregnd)		pclrcurr(pp);	(void) pprint(pp, foregnd ? NAME|JOBDIR : NUMBER|NAME|AMPERSAND);	if (foregnd)		(void) ioctl(FSHTTY, TIOCSPGRP, (char *)&pp->p_jobid);	/* 002 - GAG */	if (jobflags&PSTOPPED)		(void) killpg(pp->p_jobid, SIGCONT);	(void) sigsetmask(omask);}panystop(neednl){	register struct process *pp;	chkstop = 2;	for (pp = proclist.p_next; pp; pp = pp->p_next)		if (pp->p_flags & PSTOPPED)			error("\nThere are stopped jobs" + 1 - neednl);}struct process *pfind(cp)	char *cp;{	register struct process *pp, *np;	if (cp == 0 || cp[1] == 0 || eq(cp, "%%") || eq(cp, "%+")) {		if (pcurrent == PNULL)			bferr("No current job");		return (pcurrent);	}	if (eq(cp, "%-") || eq(cp, "%#")) {		if (pprevious == PNULL)			bferr("No previous job");		return (pprevious);	}	if (digit(cp[1])) {		int index = atoi(cp+1); 			/* 003 RNF */		for (pp = proclist.p_next; pp; pp = pp->p_next)			if (pp->p_index == index && pp->p_pid == pp->p_jobid)				return (pp);		bferr("No such job");	}	np = PNULL;	for (pp = proclist.p_next; pp; pp = pp->p_next)		if (pp->p_pid == pp->p_jobid) {			if (cp[1] == '?') {				register char *dp;				for (dp = pp->p_command; *dp; dp++) {					if (*dp != cp[2])						continue;					if (prefix(cp+2, dp))						goto match;				}			} else if (prefix(cp+1, pp->p_command)) {match:				if (np)					bferr("Ambiguous");				np = pp;			}		}	if (np)		return (np);	if (cp[1] == '?')		bferr("No job matches pattern");	else		bferr("No such job");	/*NOTREACHED*/}/* * pgetcurr - find most recent job that is not pp, preferably stopped */struct process *pgetcurr(pp)	register struct process *pp;{	register struct process *np;	register struct process *xp = PNULL;	for (np = proclist.p_next; np; np = np->p_next)		if (np != pcurrent && np != pp && np->p_pid &&		    np->p_pid == np->p_jobid) {			if (np->p_flags & PSTOPPED)				return (np);			if (xp == PNULL)				xp = np;		}	return (xp);}/* * donotify - flag the job so as to report termination asynchronously */donotify(v)	char **v;{	register struct process *pp;	pp = pfind(*++v);	pp->p_flags |= PNOTIFY;}/* * Do the fork and whatever should be done in the child side that * should not be done if we are not forking at all (like for simple builtin's) * Also do everything that needs any signals fiddled with in the parent side * * Wanttty tells whether process and/or tty pgrps are to be manipulated: *	-1:	leave tty alone; inherit pgrp from parent *	 0:	already have tty; manipulate process pgrps only *	 1:	want to claim tty; manipulate process and tty pgrps * It is usually just the value of tpgrp. */pfork(t, wanttty)	struct command *t;	/* command we are forking for */	int wanttty;{	register int pid;	bool ignint = 0;	int pgrp, omask;	/*	 * A child will be uninterruptible only under very special	 * conditions. Remember that the semantics of '&' is	 * implemented by disconnecting the process from the tty so	 * signals do not need to ignored just for '&'.	 * Thus signals are set to default action for children unless:	 *	we have had an "onintr -" (then specifically ignored)	 *	we are not playing with signals (inherit action)	 */	if (setintr)		ignint = (tpgrp == -1 && (t->t_dflg&FINT))		    || (gointr && eq(gointr, "-"));	/*	 * Hold SIGCHLD until we have the process installed in our table.	 */	omask = sigblock(sigmask(SIGCHLD));	while ((pid = fork()) < 0)		if (setintr == 0)			sleep(FORKSLEEP);		else {			(void) sigsetmask(omask);			error("No more processes");		}	if (pid == 0) {		settimes();		pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();		pflushall();		pcurrjob = PNULL;		child++;		if (setintr) {			setintr = 0;		/* until I think otherwise */			/*			 * Children just get blown away on SIGINT, SIGQUIT			 * unless "onintr -" seen.			 */			(void) signal(SIGINT, ignint ? SIG_IGN : SIG_DFL);			(void) signal(SIGQUIT, ignint ? SIG_IGN : SIG_DFL);			if (wanttty >= 0) {				/* make stoppable */				(void) signal(SIGTSTP, SIG_DFL);				(void) signal(SIGTTIN, SIG_DFL);				(void) signal(SIGTTOU, SIG_DFL);			}			(void) signal(SIGTERM, parterm);		} else if (tpgrp == -1 && (t->t_dflg&FINT)) {			(void) signal(SIGINT, SIG_IGN);			(void) signal(SIGQUIT, SIG_IGN);		}		if (wanttty > 0)			(void) ioctl(FSHTTY, TIOCSPGRP, (char *)&pgrp);	/* 002 - GAG */		if (wanttty >= 0 && tpgrp >= 0)			(void) setpgrp(0, pgrp);		if (tpgrp > 0)			tpgrp = 0;		/* gave tty away */		/*		 * Nohup and nice apply only to TCOM's but it would be		 * nice (?!?) if you could say "nohup (foo;bar)"		 * Then the parser would have to know about nice/nohup/time		 */		if (t->t_dflg & FNOHUP)			(void) signal(SIGHUP, SIG_IGN);		if (t->t_dflg & FNICE)			(void) setpriority(PRIO_PROCESS, 0, t->t_nice);	} else {		palloc(pid, t);		(void) sigsetmask(omask);	}	return (pid);}okpcntl(){	if (tpgrp == -1)		error("No job control in this shell");	if (tpgrp == 0)		error("No job control in subshells");}

⌨️ 快捷键说明

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