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

📄 jobs.c

📁 Android 一些工具
💻 C
📖 第 1 页 / 共 3 页
字号:
}intjobscmd(int argc, char **argv){	int mode, m;	int sv = jobs_invalid;	jobs_invalid = 0;	mode = 0;	while ((m = nextopt("lp")))		if (m == 'l')			mode = SHOW_PID;		else			mode = SHOW_PGID;	if (*argptr)		do			showjob(out1, getjob(*argptr,0), mode);		while (*++argptr);	else		showjobs(out1, mode);	jobs_invalid = sv;	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(struct output *out, int mode){	int jobno;	struct job *jp;	int silent = 0, gotpid;	TRACE(("showjobs(%x) called\n", mode));	/* If not even one one job changed, there is nothing to do */	gotpid = dowait(0, NULL);	while (dowait(0, NULL) > 0)		continue;#ifdef JOBS	/*	 * Check if we are not in our foreground group, and if not	 * put us in it.	 */	if (mflag && gotpid != -1 && tcgetpgrp(ttyfd) != getpid()) {		if (tcsetpgrp(ttyfd, getpid()) == -1)			error("Cannot set tty process group (%s) at %d",			    strerror(errno), __LINE__);		TRACE(("repaired tty process group\n"));		silent = 1;	}#endif	if (jobs_invalid)		return;	for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) {		if (!jp->used)			continue;		if (jp->nprocs == 0) {			freejob(jp);			continue;		}		if ((mode & SHOW_CHANGED) && !jp->changed)			continue;		if (silent && jp->changed) {			jp->changed = 0;			continue;		}		showjob(out, jp, mode);	}}/* * Mark a job structure as unused. */STATIC voidfreejob(struct job *jp){	INTOFF;	if (jp->ps != &jp->ps0) {		ckfree(jp->ps);		jp->ps = &jp->ps0;	}	jp->nprocs = 0;	jp->used = 0;#if JOBS	set_curjob(jp, 0);#endif	INTON;}intwaitcmd(int argc, char **argv){	struct job *job;	int status, retval = 127;	struct job *jp;	nextopt("");	if (!*argptr) {		/* wait for all jobs */		jp = jobtab;		if (jobs_invalid)			return 0;		for (;;) {			if (jp >= jobtab + njobs) {				/* no running procs */				return 0;			}			if (!jp->used || jp->state != JOBRUNNING) {				jp++;				continue;			}			if (dowait(1, (struct job *)NULL) == -1)			       return 128 + SIGINT;			jp = jobtab;		}	}	for (; *argptr; argptr++) {		job = getjob(*argptr, 1);		if (!job) {			retval = 127;			continue;		}		/* loop until process terminated or stopped */		while (job->state == JOBRUNNING) {			if (dowait(1, (struct job *)NULL) == -1)			       return 128 + SIGINT;		}		status = job->ps[job->nprocs].status;		if (WIFEXITED(status))			retval = WEXITSTATUS(status);#if JOBS		else if (WIFSTOPPED(status))			retval = WSTOPSIG(status) + 128;#endif		else {			/* XXX: limits number of signals */			retval = WTERMSIG(status) + 128;		}		if (!iflag)			freejob(job);	}	return retval;}intjobidcmd(int argc, char **argv){	struct job *jp;	int i;	nextopt("");	jp = getjob(*argptr, 0);	for (i = 0 ; i < jp->nprocs ; ) {		out1fmt("%ld", (long)jp->ps[i].pid);		out1c(++i < jp->nprocs ? ' ' : '\n');	}	return 0;}intgetjobpgrp(const char *name){	struct job *jp;	jp = getjob(name, 1);	if (jp == 0)		return 0;	return -jp->ps[0].pid;}/* * Convert a job name to a job structure. */STATIC struct job *getjob(const char *name, int noerror){	int jobno = -1;	struct job *jp;	int pid;	int i;	const char *err_msg = "No such job: %s";			if (name == NULL) {#if JOBS		jobno = curjob;#endif		err_msg = "No current job";	} else if (name[0] == '%') {		if (is_number(name + 1)) {			jobno = number(name + 1) - 1;		} else if (!name[2]) {			switch (name[1]) {#if JOBS			case 0:			case '+':			case '%':				jobno = curjob;				err_msg = "No current job";				break;			case '-':				jobno = curjob;				if (jobno != -1)					jobno = jobtab[jobno].prev_job;				err_msg = "No previous job";				break;#endif			default:				goto check_pattern;			}		} else {			struct job *found;    check_pattern:			found = NULL;			for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {				if (!jp->used || jp->nprocs <= 0)					continue;				if ((name[1] == '?'					&& strstr(jp->ps[0].cmd, name + 2))				    || prefix(name + 1, jp->ps[0].cmd)) {					if (found) {						err_msg = "%s: ambiguous";						found = 0;						break;					}					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;		}	}	if (!jobs_invalid && jobno >= 0 && jobno < njobs) {		jp = jobtab + jobno;		if (jp->used)			return jp;	}	if (!noerror)		error(err_msg, name);	return 0;}/* * Return a new job structure, */struct job *makejob(union node *node, int nprocs){	int i;	struct job *jp;	if (jobs_invalid) {		for (i = njobs, jp = jobtab ; --i >= 0 ; jp++) {			if (jp->used)				freejob(jp);		}		jobs_invalid = 0;	}	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]);				memcpy(jp, jobtab, njobs * sizeof jp[0]);				/* Relocate `ps' pointers */				for (i = 0; i < njobs; i++)					if (jp[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 = JOBRUNNING;	jp->used = 1;	jp->changed = 0;	jp->nprocs = 0;#if JOBS	jp->jobctl = jobctl;	set_curjob(jp, 1);#endif	if (nprocs > 1) {		jp->ps = ckmalloc(nprocs * sizeof (struct procstat));	} else {		jp->ps = &jp->ps0;	}	INTON;	TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,	    jp - jobtab + 1));	return jp;}/* * Fork off 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(struct job *jp, union node *n, int mode){	int pid;	TRACE(("forkshell(%%%d, %p, %d) called\n", jp - jobtab, n, mode));	switch ((pid = fork())) {	case -1:		TRACE(("Fork failed, errno=%d\n", errno));		INTON;		error("Cannot fork");		break;	case 0:		forkchild(jp, n, mode, 0);		return 0;	default:		return forkparent(jp, n, mode, pid);	}}intforkparent(struct job *jp, union node *n, int mode, pid_t pid){	int pgrp;	if (rootshell && mode != FORK_NOJOB && mflag) {		if (jp == NULL || jp->nprocs == 0)			pgrp = pid;		else			pgrp = jp->ps[0].pid;#ifdef USE_PROCESS_GROUPS		/* This can fail because we are doing it in the child also */		(void)setpgid(pid, pgrp);#endif	}	if (mode == FORK_BG)		backgndpid = pid;		/* set $! */	if (jp) {		struct procstat *ps = &jp->ps[jp->nprocs++];		ps->pid = pid;		ps->status = -1;		ps->cmd[0] = 0;		if (/* iflag && rootshell && */ n)			commandtext(ps, n);	}	TRACE(("In parent shell:  child = %d\n", pid));	return pid;}voidforkchild(struct job *jp, union node *n, int mode, int vforked){	int wasroot;	int pgrp;	const char *devnull = _PATH_DEVNULL;	const char *nullerr = "Can't open %s";	wasroot = rootshell;	TRACE(("Child shell %d\n", getpid()));	if (!vforked)		rootshell = 0;	closescript(vforked);	clear_traps(vforked);#if JOBS	if (!vforked)		jobctl = 0;		/* do job control only in root shell */	if (wasroot && mode != FORK_NOJOB && mflag) {		if (jp == NULL || jp->nprocs == 0)			pgrp = getpid();		else			pgrp = jp->ps[0].pid;#ifdef USE_PROCESS_GROUPS		/* This can fail because we are doing it in the parent also */		(void)setpgid(0, pgrp);		if (mode == FORK_FG) {			if (tcsetpgrp(ttyfd, pgrp) == -1)				error("Cannot set tty process group (%s) at %d",				    strerror(errno), __LINE__);		}#endif		setsignal(SIGTSTP, vforked);		setsignal(SIGTTOU, vforked);	} else if (mode == FORK_BG) {		ignoresig(SIGINT, vforked);		ignoresig(SIGQUIT, vforked);		if ((jp == NULL || jp->nprocs == 0) &&		    ! fd0_redirected_p ()) {			close(0);			if (open(devnull, O_RDONLY) != 0)				error(nullerr, devnull);		}	}#else	if (mode == FORK_BG) {		ignoresig(SIGINT, vforked);		ignoresig(SIGQUIT, vforked);		if ((jp == NULL || jp->nprocs == 0) &&		    ! fd0_redirected_p ()) {			close(0);			if (open(devnull, O_RDONLY) != 0)				error(nullerr, devnull);		}	}#endif	if (wasroot && iflag) {		setsignal(SIGINT, vforked);		setsignal(SIGQUIT, vforked);		setsignal(SIGTERM, vforked);	}	if (!vforked)		jobs_invalid = 1;}/* * Wait for job to finish. * * Under job control we have the problem that while a child process is * running interrupts generated by the user are sent to the child but not * to the shell.  This means that an infinite loop started by an inter- * active user may be hard to kill.  With job control turned off, an * interactive user may place an interactive program inside a loop.  If * the interactive program catches interrupts, the user doesn't want * these interrupts to also abort the loop.  The approach we take here * is to have the shell ignore interrupt signals while waiting for a * forground process to terminate, and then send itself an interrupt * signal if the child process was terminated by an interrupt signal. * Unfortunately, some programs want to do a bit of cleanup and then * exit on interrupt; unless these processes terminate themselves by * sending a signal to themselves (instead of calling exit) they will * confuse this approach. */intwaitforjob(struct job *jp){#if JOBS	int mypgrp = getpgrp();#endif	int status;	int st;	INTOFF;	TRACE(("waitforjob(%%%d) called\n", jp - jobtab + 1));	while (jp->state == JOBRUNNING) {		dowait(1, jp);

⌨️ 快捷键说明

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