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

📄 jobs.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*- * Copyright (c) 1991 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char sccsid[] = "@(#)jobs.c	5.1 (Berkeley) 3/7/91";#endif /* not lint */#include "shell.h"#if JOBS#include "sgtty.h"#undef CEOF			/* syntax.h redefines this */#endif#include "main.h"#include "parser.h"#include "nodes.h"#include "jobs.h"#include "options.h"#include "trap.h"#include "signames.h"#include "syntax.h"#include "input.h"#include "output.h"#include "memalloc.h"#include "error.h"#include "mystring.h"#include "redir.h"#include <sys/types.h>#include <fcntl.h>#include <signal.h>#include <errno.h>#ifdef BSD#include <sys/types.h>#include <sys/wait.h>#include <sys/time.h>#include <sys/resource.h>#endif#if POSIX#include <sys/wait.h>#endifstruct job *jobtab;		/* array of jobs */int njobs;			/* size of array */MKINIT short backgndpid = -1;	/* pid of last background process */#if JOBSint initialpgrp;		/* pgrp of shell on invocation */short curjob;			/* current job */#endif#ifdef __STDC__STATIC void restartjob(struct job *);STATIC struct job *getjob(char *);STATIC void freejob(struct job *);STATIC int procrunning(int);STATIC int dowait(int, struct job *);STATIC int waitproc(int, int *);STATIC char *commandtext(union node *);#elseSTATIC void restartjob();STATIC struct job *getjob();STATIC void freejob();STATIC int procrunning();STATIC int dowait();STATIC int waitproc();STATIC char *commandtext();#endif #if JOBS/* * Turn job control on and off. * * Note:  This code assumes that the third arg to ioctl is a character * pointer, which is true on Berkeley systems but not System V.  Since * System V doesn't have job control yet, this isn't a problem now. */MKINIT int jobctl;voidsetjobctl(on) {	int ldisc;	if (on == jobctl || rootshell == 0)		return;	if (on) {		do { /* while we are in the background */			if (ioctl(2, TIOCGPGRP, (char *)&initialpgrp) < 0) {				out2str("ash: can't access tty; job control turned off\n");				jflag = 0;				return;			}			if (initialpgrp == -1)				initialpgrp = getpgrp(0);			else if (initialpgrp != getpgrp(0)) {				killpg(initialpgrp, SIGTTIN);				continue;			}		} while (0);		if (ioctl(2, TIOCGETD, (char *)&ldisc) < 0 || ldisc != NTTYDISC) {			out2str("ash: need new tty driver to run job control; job control turned off\n");			jflag = 0;			return;		}		setsignal(SIGTSTP);		setsignal(SIGTTOU);		setpgrp(0, rootpid);		ioctl(2, TIOCSPGRP, (char *)&rootpid);	} else { /* turning job control off */		setpgrp(0, initialpgrp);		ioctl(2, TIOCSPGRP, (char *)&initialpgrp);		setsignal(SIGTSTP);		setsignal(SIGTTOU);	}	jobctl = on;}#endif#ifdef mkinitSHELLPROC {	backgndpid = -1;#if JOBS	jobctl = 0;#endif}#endif#if JOBSfgcmd(argc, argv)  char **argv; {	struct job *jp;	int pgrp;	int status;	jp = getjob(argv[1]);	if (jp->jobctl == 0)		error("job not created under job control");	pgrp = jp->ps[0].pid;	ioctl(2, TIOCSPGRP, (char *)&pgrp);	restartjob(jp);	INTOFF;	status = waitforjob(jp);	INTON;	return status;}bgcmd(argc, argv)  char **argv; {	struct job *jp;	do {		jp = getjob(*++argv);		if (jp->jobctl == 0)			error("job not created under job control");		restartjob(jp);	} while (--argc > 1);	return 0;}STATIC voidrestartjob(jp)	struct job *jp;	{	struct procstat *ps;	int i;	if (jp->state == JOBDONE)		return;	INTOFF;	killpg(jp->ps[0].pid, SIGCONT);	for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) {		if ((ps->status & 0377) == 0177) {			ps->status = -1;			jp->state = 0;		}	}	INTON;}#endifintjobscmd(argc, argv)  char **argv; {	showjobs(0);	return 0;}/* * Print a list of jobs.  If "change" is nonzero, only print jobs whose * statuses have changed since the last call to showjobs. * * If the shell is interrupted in the process of creating a job, the * result may be a job structure containing zero processes.  Such structures * will be freed here. */voidshowjobs(change) {	int jobno;	int procno;	int i;	struct job *jp;	struct procstat *ps;	int col;	char s[64];	TRACE(("showjobs(%d) called\n", change));	while (dowait(0, (struct job *)NULL) > 0);	for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) {		if (! jp->used)			continue;		if (jp->nprocs == 0) {			freejob(jp);			continue;		}		if (change && ! jp->changed)			continue;		procno = jp->nprocs;		for (ps = jp->ps ; ; ps++) {	/* for each process */			if (ps == jp->ps)				fmtstr(s, 64, "[%d] %d ", jobno, ps->pid);			else				fmtstr(s, 64, "    %d ", ps->pid);			out1str(s);			col = strlen(s);			s[0] = '\0';			if (ps->status == -1) {				/* don't print anything */			} else if ((ps->status & 0xFF) == 0) {				fmtstr(s, 64, "Exit %d", ps->status >> 8);			} else {				i = ps->status;#if JOBS				if ((i & 0xFF) == 0177)					i >>= 8;#endif				if ((i & 0x7F) <= MAXSIG && sigmesg[i & 0x7F])					scopy(sigmesg[i & 0x7F], s);				else					fmtstr(s, 64, "Signal %d", i & 0x7F);				if (i & 0x80)					strcat(s, " (core dumped)");			}			out1str(s);			col += strlen(s);			do {				out1c(' ');				col++;			} while (col < 30);			out1str(ps->cmd);			out1c('\n');			if (--procno <= 0)				break;		}		jp->changed = 0;		if (jp->state == JOBDONE) {			freejob(jp);		}	}}/* * Mark a job structure as unused. */STATIC voidfreejob(jp)	struct job *jp;	{	struct procstat *ps;	int i;	INTOFF;	for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {		if (ps->cmd != nullstr)			ckfree(ps->cmd);	}	if (jp->ps != &jp->ps0)		ckfree(jp->ps);	jp->used = 0;#if JOBS	if (curjob == jp - jobtab + 1)		curjob = 0;#endif	INTON;}intwaitcmd(argc, argv)  char **argv; {	struct job *job;	int status;	struct job *jp;	if (argc > 1) {		job = getjob(argv[1]);	} else {		job = NULL;	}	for (;;) {	/* loop until process terminated or stopped */		if (job != NULL) {			if (job->state) {				status = job->ps[job->nprocs - 1].status;				if ((status & 0xFF) == 0)					status = status >> 8 & 0xFF;#if JOBS				else if ((status & 0xFF) == 0177)					status = (status >> 8 & 0x7F) + 128;#endif				else					status = (status & 0x7F) + 128;				if (! iflag)					freejob(job);				return status;			}		} else {			for (jp = jobtab ; ; jp++) {				if (jp >= jobtab + njobs) {	/* no running procs */					return 0;				}				if (jp->used && jp->state == 0)					break;			}		}		dowait(1, (struct job *)NULL);	}}jobidcmd(argc, argv)  char **argv; {	struct job *jp;	int i;	jp = getjob(argv[1]);	for (i = 0 ; i < jp->nprocs ; ) {		out1fmt("%d", jp->ps[i].pid);		out1c(++i < jp->nprocs? ' ' : '\n');	}	return 0;}/* * Convert a job name to a job structure. */STATIC struct job *getjob(name)	char *name;	{	int jobno;	register struct job *jp;	int pid;	int i;	if (name == NULL) {#if JOBScurrentjob:		if ((jobno = curjob) == 0 || jobtab[jobno - 1].used == 0)			error("No current job");		return &jobtab[jobno - 1];#else		error("No current job");#endif	} else if (name[0] == '%') {		if (is_digit(name[1])) {			jobno = number(name + 1);			if (jobno > 0 && jobno <= njobs			 && jobtab[jobno - 1].used != 0)				return &jobtab[jobno - 1];#if JOBS		} else if (name[1] == '%' && name[2] == '\0') {			goto currentjob;#endif		} else {			register struct job *found = NULL;			for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {				if (jp->used && jp->nprocs > 0				 && prefix(name + 1, jp->ps[0].cmd)) {					if (found)						error("%s: ambiguous", name);					found = jp;				}			}			if (found)				return found;		}	} else if (is_number(name)) {		pid = number(name);		for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {			if (jp->used && jp->nprocs > 0			 && jp->ps[jp->nprocs - 1].pid == pid)				return jp;		}	}	error("No such job: %s", name);}/* * Return a new job structure, */struct job *makejob(node, nprocs)	union node *node;	{	int i;	struct job *jp;	for (i = njobs, jp = jobtab ; ; jp++) {		if (--i < 0) {			INTOFF;			if (njobs == 0) {				jobtab = ckmalloc(4 * sizeof jobtab[0]);			} else {				jp = ckmalloc((njobs + 4) * sizeof jobtab[0]);				bcopy(jobtab, jp, njobs * sizeof jp[0]);				for (i= 0; i<njobs; i++)				{					if (jobtab[i].ps == &jobtab[i].ps0)						jp[i].ps= &jp[i].ps0;				}				ckfree(jobtab);				jobtab = jp;			}			jp = jobtab + njobs;			for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0);			INTON;			break;		}		if (jp->used == 0)			break;	}	INTOFF;	jp->state = 0;	jp->used = 1;	jp->changed = 0;	jp->nprocs = 0;#if JOBS	jp->jobctl = jobctl;#endif	if (nprocs > 1) {		jp->ps = ckmalloc(nprocs * sizeof (struct procstat));	} else {		jp->ps = &jp->ps0;	}	INTON;	TRACE(("makejob(0x%x, %d) returns %%%d\n", (int)node, nprocs, jp - jobtab + 1));	return jp;}	/* * Fork of a subshell.  If we are doing job control, give the subshell its * own process group.  Jp is a job structure that the job is to be added to. * N is the command that will be evaluated by the child.  Both jp and n may * be NULL.  The mode parameter can be one of the following: *	FORK_FG - Fork off a foreground process. *	FORK_BG - Fork off a background process. *	FORK_NOJOB - Like FORK_FG, but don't give the process its own *		     process group even if job control is on. * * When job control is turned off, background processes have their standard * input redirected to /dev/null (except for the second and later processes * in a pipeline). */intforkshell(jp, n, mode)	union node *n;	struct job *jp;

⌨️ 快捷键说明

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