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

📄 jobs.c

📁 Android 一些工具
💻 C
📖 第 1 页 / 共 3 页
字号:
/*	$NetBSD: jobs.c,v 1.62 2003/12/18 00:56:05 christos Exp $	*//*- * Copyright (c) 1991, 1993 *	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. 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. */#include <sys/cdefs.h>#ifndef lint#if 0static char sccsid[] = "@(#)jobs.c	8.5 (Berkeley) 5/4/95";#else__RCSID("$NetBSD: jobs.c,v 1.62 2003/12/18 00:56:05 christos Exp $");#endif#endif /* not lint */#include <fcntl.h>#include <signal.h>#include <errno.h>#include <unistd.h>#include <stdlib.h>#define _PATH_DEVNULL "/dev/null"#include <sys/types.h>#include <sys/param.h>#ifdef BSD#include <sys/wait.h>#include <sys/time.h>#include <sys/resource.h>#endif#include <sys/wait.h>#define killpg(s,i) kill(-(s),i)#include <sys/ioctl.h>#include "shell.h"#if JOBS#if OLD_TTY_DRIVER#include "sgtty.h"#else#include <termios.h>#endif#undef CEOF			/* syntax.h redefines this */#endif#include "redir.h"#include "show.h"#include "main.h"#include "parser.h"#include "nodes.h"#include "jobs.h"#include "options.h"#include "trap.h"#include "syntax.h"#include "input.h"#include "output.h"#include "memalloc.h"#include "error.h"#include "mystring.h"// Use of process groups is disabled to allow adb shell children to terminate when the shell dies#define USE_PROCESS_GROUPSstatic struct job *jobtab;		/* array of jobs */static int njobs;			/* size of array */static int jobs_invalid;		/* set in child */MKINIT pid_t backgndpid = -1;	/* pid of last background process */#if JOBSint initialpgrp;		/* pgrp of shell on invocation */static int curjob = -1;		/* current job */#endifstatic int ttyfd = -1;STATIC void restartjob(struct job *);STATIC void freejob(struct job *);STATIC struct job *getjob(const char *, int);STATIC int dowait(int, struct job *);STATIC int onsigchild(void);STATIC int waitproc(int, struct job *, int *);STATIC void cmdtxt(union node *);STATIC void cmdlist(union node *, int);STATIC void cmdputs(const char *);#ifdef OLD_TTY_DRIVERstatic pid_t tcgetpgrp(int fd);static int tcsetpgrp(int fd, pid_t pgrp);static pid_ttcgetpgrp(int fd){	pid_t pgrp;	if (ioctl(fd, TIOCGPGRP, (char *)&pgrp) == -1)		return -1;	else		return pgrp;}static inttcsetpgrp(int fd, pid_tpgrp){	return ioctl(fd, TIOCSPGRP, (char *)&pgrp);}#endif/* * 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(int on){#ifdef OLD_TTY_DRIVER	int ldisc;#endif	if (on == jobctl || rootshell == 0)		return;	if (on) {#if defined(FIOCLEX) || defined(FD_CLOEXEC)		int err;		int i;		if (ttyfd != -1)			close(ttyfd);		if ((ttyfd = open("/dev/tty", O_RDWR)) == -1) {			for (i = 0; i < 3; i++) {				if (isatty(i) && (ttyfd = dup(i)) != -1)					break;			}			if (i == 3)				goto out;		}		/* Move to a high fd */		for (i = 10; i > 2; i--) {			if ((err = fcntl(ttyfd, F_DUPFD, (1 << i) - 1)) != -1)				break;		}		if (err != -1) {			close(ttyfd);			ttyfd = err;		}#ifdef FIOCLEX		err = ioctl(ttyfd, FIOCLEX, 0);#elif FD_CLOEXEC		err = fcntl(ttyfd, F_SETFD,		    fcntl(ttyfd, F_GETFD, 0) | FD_CLOEXEC);#endif		if (err == -1) {			close(ttyfd);			ttyfd = -1;			goto out;		}#else		out2str("sh: Need FIOCLEX or FD_CLOEXEC to support job control");		goto out;#endif		do { /* while we are in the background */			if ((initialpgrp = tcgetpgrp(ttyfd)) < 0) {out:				out2str("sh: can't access tty; job control turned off\n");				mflag = 0;				return;			}			if (initialpgrp == -1)				initialpgrp = getpgrp();			else if (initialpgrp != getpgrp()) {				killpg(0, SIGTTIN);				continue;			}		} while (0);#ifdef OLD_TTY_DRIVER		if (ioctl(ttyfd, TIOCGETD, (char *)&ldisc) < 0		    || ldisc != NTTYDISC) {			out2str("sh: need new tty driver to run job control; job control turned off\n");			mflag = 0;			return;		}#endif		setsignal(SIGTSTP, 0);		setsignal(SIGTTOU, 0);		setsignal(SIGTTIN, 0);#ifdef USE_PROCESS_GROUPS		if (getpgid(0) != rootpid && setpgid(0, rootpid) == -1)			error("Cannot set process group (%s) at %d",			    strerror(errno), __LINE__);		if (tcsetpgrp(ttyfd, rootpid) == -1)			error("Cannot set tty process group (%s) at %d",			    strerror(errno), __LINE__);#endif	} else { /* turning job control off */#ifdef USE_PROCESS_GROUPS		if (getpgid(0) != initialpgrp && setpgid(0, initialpgrp) == -1)			error("Cannot set process group (%s) at %d",			    strerror(errno), __LINE__);		if (tcsetpgrp(ttyfd, initialpgrp) == -1)			error("Cannot set tty process group (%s) at %d",			    strerror(errno), __LINE__);#endif		close(ttyfd);		ttyfd = -1;		setsignal(SIGTSTP, 0);		setsignal(SIGTTOU, 0);		setsignal(SIGTTIN, 0);	}	jobctl = on;}#ifdef mkinitINCLUDE <stdlib.h>SHELLPROC {	backgndpid = -1;#if JOBS	jobctl = 0;#endif}#endif#if JOBSintfgcmd(int argc, char **argv){	struct job *jp;	int i;	int status;	nextopt("");	jp = getjob(*argptr, 0);	if (jp->jobctl == 0)		error("job not created under job control");	out1fmt("%s", jp->ps[0].cmd);	for (i = 1; i < jp->nprocs; i++)		out1fmt(" | %s", jp->ps[i].cmd );	out1c('\n');	flushall();	for (i = 0; i < jp->nprocs; i++)	    if (tcsetpgrp(ttyfd, jp->ps[i].pid) != -1)		    break;	if (i >= jp->nprocs) {		error("Cannot set tty process group (%s) at %d",		    strerror(errno), __LINE__);	}	restartjob(jp);	INTOFF;	status = waitforjob(jp);	INTON;	return status;}static voidset_curjob(struct job *jp, int mode){	struct job *jp1, *jp2;	int i, ji;	ji = jp - jobtab;	/* first remove from list */	if (ji == curjob)		curjob = jp->prev_job;	else {		for (i = 0; i < njobs; i++) {			if (jobtab[i].prev_job != ji)				continue;			jobtab[i].prev_job = jp->prev_job;			break;		}	}	/* Then re-insert in correct position */	switch (mode) {	case 0:	/* job being deleted */		jp->prev_job = -1;		break;	case 1:	/* newly created job or backgrounded job,		   put after all stopped jobs. */		if (curjob != -1 && jobtab[curjob].state == JOBSTOPPED) {			for (jp1 = jobtab + curjob; ; jp1 = jp2) {				if (jp1->prev_job == -1)					break;				jp2 = jobtab + jp1->prev_job;				if (jp2->state != JOBSTOPPED)					break;			}			jp->prev_job = jp1->prev_job;			jp1->prev_job = ji;			break;		}		/* FALLTHROUGH */	case 2:	/* newly stopped job - becomes curjob */		jp->prev_job = curjob;		curjob = ji;		break;	}}intbgcmd(int argc, char **argv){	struct job *jp;	int i;	nextopt("");	do {		jp = getjob(*argptr, 0);		if (jp->jobctl == 0)			error("job not created under job control");		set_curjob(jp, 1);		out1fmt("[%ld] %s", (long)(jp - jobtab + 1), jp->ps[0].cmd);		for (i = 1; i < jp->nprocs; i++)			out1fmt(" | %s", jp->ps[i].cmd );		out1c('\n');		flushall();		restartjob(jp);	} while (*argptr && *++argptr);	return 0;}STATIC voidrestartjob(struct job *jp){	struct procstat *ps;	int i;	if (jp->state == JOBDONE)		return;	INTOFF;	for (i = 0; i < jp->nprocs; i++)		if (killpg(jp->ps[i].pid, SIGCONT) != -1)			break;	if (i >= jp->nprocs)		error("Cannot continue job (%s)", strerror(errno));	for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) {		if (WIFSTOPPED(ps->status)) {			ps->status = -1;			jp->state = JOBRUNNING;		}	}	INTON;}#endifstatic voidshowjob(struct output *out, struct job *jp, int mode){	int procno;	int st;	struct procstat *ps;	int col;	char s[64];#if JOBS	if (mode & SHOW_PGID) {		/* just output process (group) id of pipeline */		outfmt(out, "%ld\n", (long)jp->ps->pid);		return;	}#endif	procno = jp->nprocs;	if (!procno)		return;	if (mode & SHOW_PID)		mode |= SHOW_MULTILINE;	if ((procno > 1 && !(mode & SHOW_MULTILINE))	    || (mode & SHOW_SIGNALLED)) {		/* See if we have more than one status to report */		ps = jp->ps;		st = ps->status;		do {			int st1 = ps->status;			if (st1 != st)				/* yes - need multi-line output */				mode |= SHOW_MULTILINE;			if (st1 == -1 || !(mode & SHOW_SIGNALLED) || WIFEXITED(st1))				continue;			if (WIFSTOPPED(st1) || ((st1 = WTERMSIG(st1) & 0x7f)			    && st1 != SIGINT && st1 != SIGPIPE))				mode |= SHOW_ISSIG;		} while (ps++, --procno);		procno = jp->nprocs;	}	if (mode & SHOW_SIGNALLED && !(mode & SHOW_ISSIG)) {		if (jp->state == JOBDONE && !(mode & SHOW_NO_FREE)) {			TRACE(("showjob: freeing job %d\n", jp - jobtab + 1));			freejob(jp);		}		return;	}	for (ps = jp->ps; --procno >= 0; ps++) {	/* for each process */		if (ps == jp->ps)			fmtstr(s, 16, "[%ld] %c ",				(long)(jp - jobtab + 1),#if JOBS				jp == jobtab + curjob ? '+' :				curjob != -1 && jp == jobtab +					    jobtab[curjob].prev_job ? '-' :#endif				' ');		else			fmtstr(s, 16, "      " );		col = strlen(s);		if (mode & SHOW_PID) {			fmtstr(s + col, 16, "%ld ", (long)ps->pid);			     col += strlen(s + col);		}		if (ps->status == -1) {			scopy("Running", s + col);		} else if (WIFEXITED(ps->status)) {			st = WEXITSTATUS(ps->status);			if (st)				fmtstr(s + col, 16, "Done(%d)", st);			else				fmtstr(s + col, 16, "Done");		} else {#if JOBS			if (WIFSTOPPED(ps->status)) 				st = WSTOPSIG(ps->status);			else /* WIFSIGNALED(ps->status) */#endif				st = WTERMSIG(ps->status);			st &= 0x7f;			if (st < NSIG && sys_siglist[st])				scopyn(sys_siglist[st], s + col, 32);			else				fmtstr(s + col, 16, "Signal %d", st);			if (WCOREDUMP(ps->status)) {				col += strlen(s + col);				scopyn(" (core dumped)", s + col,  64 - col);			}		}		col += strlen(s + col);		outstr(s, out);		do {			outc(' ', out);			col++;		} while (col < 30);		outstr(ps->cmd, out);		if (mode & SHOW_MULTILINE) {			if (procno > 0) {				outc(' ', out);				outc('|', out);			}		} else {			while (--procno >= 0)				outfmt(out, " | %s", (++ps)->cmd );		}		outc('\n', out);	}	flushout(out);	jp->changed = 0;	if (jp->state == JOBDONE && !(mode & SHOW_NO_FREE))		freejob(jp);

⌨️ 快捷键说明

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