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

📄 proc.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/*- * Copyright (c) 1980, 1991, 1993 *	The Regents of the University of California.  All rights reserved. * * 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[] = "@(#)proc.c	8.1 (Berkeley) 5/31/93";#endif /* not lint */#include <sys/types.h>#include <sys/wait.h>#include <errno.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#if __STDC__# include <stdarg.h>#else# include <varargs.h>#endif#include "csh.h"#include "dir.h"#include "proc.h"#include "extern.h"#define BIGINDEX	9	/* largest desirable job index */static struct rusage zru;static void	 pflushall __P((void));static void	 pflush __P((struct process *));static void	 pclrcurr __P((struct process *));static void	 padd __P((struct command *));static int	 pprint __P((struct process *, int));static void	 ptprint __P((struct process *));static void	 pads __P((Char *));static void	 pkill __P((Char **v, int));static struct	process		*pgetcurr __P((struct process *));static void	 okpcntl __P((void));/* * pchild - called at interrupt level by the SIGCHLD signal *	indicating that at least one child has terminated or stopped *	thus at least one wait system call will definitely return a *	childs status.  Top level routines (like pwait) must be sure *	to mask interrupts when playing with the proclist data structures! *//* ARGUSED */voidpchild(notused)	int notused;{    register struct process *pp;    register struct process *fp;    register int pid;    extern int insource;    union wait w;    int     jobflags;    struct rusage ru;loop:    errno = 0;			/* reset, just in case */    pid = wait3(&w.w_status,       (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru);    if (pid <= 0) {	if (errno == EINTR) {	    errno = 0;	    goto loop;	}	pnoprocesses = pid == -1;	return;    }    for (pp = proclist.p_next; pp != NULL; pp = pp->p_next)	if (pid == pp->p_pid)	    goto found;    goto loop;found:    if (pid == atoi(short2str(value(STRchild))))	unsetv(STRchild);    pp->p_flags &= ~(PRUNNING | PSTOPPED | PREPORTED);    if (WIFSTOPPED(w)) {	pp->p_flags |= PSTOPPED;	pp->p_reason = w.w_stopsig;    }    else {	if (pp->p_flags & (PTIME | PPTIME) || adrof(STRtime))	    (void) gettimeofday(&pp->p_etime, NULL);	pp->p_rusage = ru;	if (WIFSIGNALED(w)) {	    if (w.w_termsig == SIGINT)		pp->p_flags |= PINTERRUPTED;	    else		pp->p_flags |= PSIGNALED;	    if (w.w_coredump)		pp->p_flags |= PDUMPED;	    pp->p_reason = w.w_termsig;	}	else {	    pp->p_reason = w.w_retcode;	    if (pp->p_reason != 0)		pp->p_flags |= PAEXITED;	    else		pp->p_flags |= PNEXITED;	}    }    jobflags = 0;    fp = pp;    do {	if ((fp->p_flags & (PPTIME | PRUNNING | PSTOPPED)) == 0 &&	    !child && adrof(STRtime) &&	    fp->p_rusage.ru_utime.tv_sec + fp->p_rusage.ru_stime.tv_sec	    >= atoi(short2str(value(STRtime))))	    fp->p_flags |= PTIME;	jobflags |= fp->p_flags;    } while ((fp = fp->p_friends) != pp);    pp->p_flags &= ~PFOREGND;    if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {	pp->p_flags &= ~PPTIME;	pp->p_flags |= PTIME;    }    if ((jobflags & (PRUNNING | PREPORTED)) == 0) {	fp = pp;	do {	    if (fp->p_flags & PSTOPPED)		fp->p_flags |= PREPORTED;	} while ((fp = fp->p_friends) != pp);	while (fp->p_pid != fp->p_jobid)	    fp = fp->p_friends;	if (jobflags & PSTOPPED) {	    if (pcurrent && pcurrent != fp)		pprevious = pcurrent;	    pcurrent = fp;	}	else	    pclrcurr(fp);	if (jobflags & PFOREGND) {	    if (jobflags & (PSIGNALED | PSTOPPED | PPTIME) ||#ifdef IIASA		jobflags & PAEXITED ||#endif		!eq(dcwd->di_name, fp->p_cwd->di_name)) {		;		/* print in pjwait */	    }	    /* PWP: print a newline after ^C */	    else if (jobflags & PINTERRUPTED) {		(void) vis_fputc('\r' | QUOTE, cshout);		(void) fputc('\n', cshout);	    }	}	else {	    if (jobflags & PNOTIFY || adrof(STRnotify)) {		(void) vis_fputc('\r' | QUOTE, cshout);		(void) fputc('\n', cshout);		(void) pprint(pp, NUMBER | NAME | REASON);		if ((jobflags & PSTOPPED) == 0)		    pflush(pp);	    }	    else {		fp->p_flags |= PNEEDNOTE;		neednote++;	    }	}    }    goto loop;}voidpnote(){    register struct process *pp;    int     flags;    sigset_t omask;    neednote = 0;    for (pp = proclist.p_next; pp != NULL; pp = pp->p_next) {	if (pp->p_flags & PNEEDNOTE) {	    omask = sigblock(sigmask(SIGCHLD));	    pp->p_flags &= ~PNEEDNOTE;	    flags = pprint(pp, NUMBER | NAME | REASON);	    if ((flags & (PRUNNING | PSTOPPED)) == 0)		pflush(pp);	    (void) sigsetmask(omask);	}    }}/* * pwait - wait for current job to terminate, maintaining integrity *	of current and previous job indicators. */voidpwait(){    register struct process *fp, *pp;    sigset_t omask;    /*     * Here's where dead procs get flushed.     */    omask = sigblock(sigmask(SIGCHLD));    for (pp = (fp = &proclist)->p_next; pp != NULL; pp = (fp = pp)->p_next)	if (pp->p_pid == 0) {	    fp->p_next = pp->p_next;	    xfree((ptr_t) pp->p_command);	    if (pp->p_cwd && --pp->p_cwd->di_count == 0)		if (pp->p_cwd->di_next == 0)		    dfree(pp->p_cwd);	    xfree((ptr_t) pp);	    pp = fp;	}    (void) sigsetmask(omask);    pjwait(pcurrjob);}/* * pjwait - wait for a job to finish or become stopped *	It is assumed to be in the foreground state (PFOREGND) */voidpjwait(pp)    register struct process *pp;{    register struct process *fp;    int     jobflags, reason;    sigset_t omask;    while (pp->p_pid != pp->p_jobid)	pp = pp->p_friends;    fp = pp;    do {	if ((fp->p_flags & (PFOREGND | PRUNNING)) == PRUNNING)	    (void) fprintf(csherr, "BUG: waiting for background job!\n");    } while ((fp = fp->p_friends) != pp);    /*     * Now keep pausing as long as we are not interrupted (SIGINT), and the     * target process, or any of its friends, are running     */    fp = pp;    omask = sigblock(sigmask(SIGCHLD));    for (;;) {	(void) sigblock(sigmask(SIGCHLD));	jobflags = 0;	do	    jobflags |= fp->p_flags;	while ((fp = (fp->p_friends)) != pp);	if ((jobflags & PRUNNING) == 0)	    break;#ifdef JOBDEBUG	(void) fprintf(csherr, "starting to sigpause for  SIGCHLD on %d\n",		       fp->p_pid);#endif				/* JOBDEBUG */	(void) sigpause(omask & ~sigmask(SIGCHLD));    }    (void) sigsetmask(omask);    if (tpgrp > 0)		/* get tty back */	(void) tcsetpgrp(FSHTTY, tpgrp);    if ((jobflags & (PSIGNALED | PSTOPPED | PTIME)) ||	!eq(dcwd->di_name, fp->p_cwd->di_name)) {	if (jobflags & PSTOPPED) {	    (void) fputc('\n', cshout);	    if (adrof(STRlistjobs)) {		Char   *jobcommand[3];		jobcommand[0] = STRjobs;		if (eq(value(STRlistjobs), STRlong))		    jobcommand[1] = STRml;		else		    jobcommand[1] = NULL;		jobcommand[2] = NULL;		dojobs(jobcommand, NULL);		(void) pprint(pp, SHELLDIR);	    }	    else		(void) pprint(pp, AREASON | SHELLDIR);	}	else	    (void) pprint(pp, AREASON | SHELLDIR);    }    if ((jobflags & (PINTERRUPTED | PSTOPPED)) && setintr &&	(!gointr || !eq(gointr, STRminus))) {	if ((jobflags & PSTOPPED) == 0)	    pflush(pp);	pintr1(0);	/* NOTREACHED */    }    reason = 0;    fp = pp;    do {	if (fp->p_reason)	    reason = fp->p_flags & (PSIGNALED | PINTERRUPTED) ?		fp->p_reason | META : fp->p_reason;    } while ((fp = fp->p_friends) != pp);    if ((reason != 0) && (adrof(STRprintexitvalue))) {	(void) fprintf(cshout, "Exit %d\n", reason);    }    set(STRstatus, putn(reason));    if (reason && exiterr)	exitstat();    pflush(pp);}/* * dowait - wait for all processes to finish */void/*ARGSUSED*/dowait(v, t)    Char **v;    struct command *t;{    register struct process *pp;    sigset_t omask;    pjobs++;    omask = sigblock(sigmask(SIGCHLD));loop:    for (pp = proclist.p_next; pp; pp = pp->p_next)	if (pp->p_pid &&	/* pp->p_pid == pp->p_jobid && */	    pp->p_flags & PRUNNING) {	    (void) sigpause((sigset_t) 0);	    goto loop;	}    (void) sigsetmask(omask);    pjobs = 0;}/* * pflushall - flush all jobs from list (e.g. at fork()) */static voidpflushall(){    register struct process *pp;    for (pp = proclist.p_next; pp != NULL; pp = pp->p_next)	if (pp->p_pid)	    pflush(pp);}/* * pflush - flag all process structures in the same job as the *	the argument process for deletion.  The actual free of the *	space is not done here since pflush is called at interrupt level. */static voidpflush(pp)    register struct process *pp;{    register struct process *np;    register int idx;    if (pp->p_pid == 0) {	(void) fprintf(csherr, "BUG: process flushed twice");	return;    }    while (pp->p_pid != pp->p_jobid)	pp = pp->p_friends;    pclrcurr(pp);    if (pp == pcurrjob)	pcurrjob = 0;    idx = pp->p_index;    np = pp;    do {	np->p_index = np->p_pid = 0;	np->p_flags &= ~PNEEDNOTE;    } while ((np = np->p_friends) != pp);    if (idx == pmaxindex) {	for (np = proclist.p_next, idx = 0; np; np = np->p_next)	    if (np->p_index > idx)		idx = np->p_index;	pmaxindex = idx;    }}/* * pclrcurr - make sure the given job is not the current or previous job; *	pp MUST be the job leader */static voidpclrcurr(pp)    register struct process *pp;{    if (pp == pcurrent)	if (pprevious != NULL) {	    pcurrent = pprevious;	    pprevious = pgetcurr(pp);	}	else {	    pcurrent = pgetcurr(pp);	    pprevious = pgetcurr(pp);	}    else if (pp == pprevious)	pprevious = pgetcurr(pp);}/* +4 here is 1 for '\0', 1 ea for << >& >> */static Char command[PMAXLEN + 4];static int cmdlen;static Char *cmdp;/* * palloc - allocate a process structure and fill it up. *	an important assumption is made that the process is running. */voidpalloc(pid, t)    int     pid;    register struct command *t;{    register struct process *pp;    int     i;    pp = (struct process *) xcalloc(1, (size_t) sizeof(struct process));    pp->p_pid = pid;    pp->p_flags = t->t_dflg & F_AMPERSAND ? PRUNNING : PRUNNING | PFOREGND;    if (t->t_dflg & F_TIME)	pp->p_flags |= PPTIME;

⌨️ 快捷键说明

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