sh.proc.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,167 行 · 第 1/2 页
C
1,167 行
#ifndef lintstatic char *sccsid = "@(#)sh.proc.c 4.3 (ULTRIX) 11/13/90";#endif/************************************************************************ * * * Copyright (c) 1988 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//* ------------------------------------------------------------------ *//* | Copyright Unpublished, MIPS Computer Systems, Inc. All Rights | *//* | Reserved. This software contains proprietary and confidential | *//* | information of MIPS and its suppliers. Use, disclosure or | *//* | reproduction is prohibited without the prior express written | *//* | consent of MIPS. | *//* ------------------------------------------------------------------ *//* $Header: sh.proc.c,v 1.4 87/04/06 21:00:16 dce Exp $ */#include "sh.h"#include "sh.dir.h"#include "sh.proc.h"#include <sys/wait.h>#include <sys/ioctl.h>/* * C Shell - functions that manage processes, handling hanging, termination * Modification History * * 005 - Bob Fontaine - Mon Oct 22 13:46:48 EDT 1990 * Fix typo from 003. Must increment the pointer to the users input * so that the % sign is not part of the job number. * * 004 - Bob Fontaine - Fri Jun 22 09:53:01 EDT 1990 * Changed call to internal printf routine to csh_printf to avoid * confusion with library routine. * * 003 - Bob Fontaine - Thu Jun 21 10:22:20 EDT 1990 * pstart routine used to just search for a job in the proc list * that matched the second digit in the job number entered by the user. * (ie job 11 would map to job 1). Fix is to look at the entire * string the user entered. QAR # 957 * * 002 - Gary A. Gaudet - Tue Jan 2 11:56:15 EST 1990 * added retrun value checks fro ioctl() * added some (castings) * * 01 Sat Aug 13 15:28:57 EDT 1988, Gary A. Gaudet * merging mips & ultrix for 8 bit clean and bug fixes */#define BIGINDEX 9 /* largest desirable job index *//* * 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! */pchild(){ register struct process *pp; register struct process *fp; register int pid; union wait w; int jobflags; struct rusage ru;loop: pid = wait3(&w, ((setintr && intty) ? WNOHANG|WUNTRACED:WNOHANG), &ru); if (pid <= 0) { if (errno == EINTR) { errno = 0; goto loop; } pnoprocesses = pid == -1; return; } for (pp = proclist.p_next; pp != PNULL; pp = pp->p_next) if (pid == pp->p_pid) goto found; goto loop;found: if (pid == atoi(value("child"))) unsetv("child"); 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("time")) (void) gettimeofday(&pp->p_etime, (struct timezone *)0); 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("time") && fp->p_rusage.ru_utime.tv_sec+fp->p_rusage.ru_stime.tv_sec >= atoi(value("time"))) 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 */ }/* else if ((jobflags & (PTIME|PSTOPPED)) == PTIME) ptprint(fp);*/ } else { if (jobflags&PNOTIFY || adrof("notify")) { putchar ('\r' | QUOTE); putchar ('\n'); (void) pprint(pp, NUMBER|NAME|REASON|NOISEOK); if ((jobflags&PSTOPPED) == 0) pflush(pp); } else { fp->p_flags |= PNEEDNOTE; neednote++; } } } goto loop;}pnote(){ register struct process *pp; int flags, omask; neednote = 0; for (pp = proclist.p_next; pp != PNULL; pp = pp->p_next) { if (pp->p_flags & PNEEDNOTE) { omask = sigblock(sigmask(SIGCHLD)); pp->p_flags &= ~PNEEDNOTE; flags = pprint(pp, NUMBER|NAME|REASON|NOISEOK); 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. */pwait(){ register struct process *fp, *pp; int omask; /* * Here's where dead procs get flushed. */ omask = sigblock(sigmask(SIGCHLD)); for (pp = (fp = &proclist)->p_next; pp != PNULL; pp = (fp = pp)->p_next) if (pp->p_pid == 0) { fp->p_next = pp->p_next; xfree(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((char *)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) */pjwait(pp) register struct process *pp;{ register struct process *fp; int jobflags, reason, omask; while (pp->p_pid != pp->p_jobid) pp = pp->p_friends; fp = pp; do { if ((fp->p_flags&(PFOREGND|PRUNNING)) == PRUNNING) csh_printf("BUG: waiting for background job!\n"); /* 004 RNF */ } 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 (;;) { jobflags = 0; do jobflags |= fp->p_flags; while ((fp = (fp->p_friends)) != pp); if ((jobflags & PRUNNING) == 0) break; sigpause(sigblock(0) &~ sigmask(SIGCHLD)); } (void) sigsetmask(omask); if (tpgrp > 0) /* get tty back */ if (ioctl(FSHTTY, TIOCSPGRP, (char *)&tpgrp)) { /* 002 - GAG */ Perror ("ioctl"); } if ((jobflags&(PSIGNALED|PSTOPPED|PTIME)) || !eq(dcwd->di_name, fp->p_cwd->di_name)) { if (jobflags&PSTOPPED) csh_printf("\n"); /* 004 RNF */ (void) pprint(pp, AREASON|SHELLDIR); } if ((jobflags&(PINTERRUPTED|PSTOPPED)) && setintr && (!gointr || !eq(gointr, "-"))) { 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 | QUOTE : fp->p_reason; } while ((fp = fp->p_friends) != pp); set("status", putn(reason)); if (reason && exiterr) exitstat(); pflush(pp);}/* * dowait - wait for all processes to finish */dowait(){ register struct process *pp; int 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) { sigpause(0); goto loop; } (void) sigsetmask(omask); pjobs = 0;}/* * pflushall - flush all jobs from list (e.g. at fork()) */pflushall(){ register struct process *pp; for (pp = proclist.p_next; pp != PNULL; 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. */pflush(pp) register struct process *pp;{ register struct process *np; register int index; if (pp->p_pid == 0) { csh_printf("BUG: process flushed twice"); /* 004 RNF */ return; } while (pp->p_pid != pp->p_jobid) pp = pp->p_friends; pclrcurr(pp); if (pp == pcurrjob) pcurrjob = 0; index = pp->p_index; np = pp; do { np->p_index = np->p_pid = 0; np->p_flags &= ~PNEEDNOTE; } while ((np = np->p_friends) != pp); if (index == pmaxindex) { for (np = proclist.p_next, index = 0; np; np = np->p_next) if (np->p_index > index) index = np->p_index; pmaxindex = index; }}/* * pclrcurr - make sure the given job is not the current or previous job; * pp MUST be the job leader */pclrcurr(pp) register struct process *pp;{ if (pp == pcurrent) if (pprevious != PNULL) { 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 << >& >> */char command[PMAXLEN+4];int cmdlen;char *cmdp;/* * palloc - allocate a process structure and fill it up. * an important assumption is made that the process is running. */palloc(pid, t) int pid; register struct command *t;{ register struct process *pp; int i; pp = (struct process *)calloc((unsigned)1, (unsigned)sizeof(struct process)); pp->p_pid = pid; pp->p_flags = t->t_dflg & FAND ? PRUNNING : PRUNNING|PFOREGND; if (t->t_dflg & FTIME) pp->p_flags |= PPTIME; cmdp = command; cmdlen = 0; padd(t); *cmdp++ = 0; if (t->t_dflg & FPOU) { pp->p_flags |= PPOU; if (t->t_dflg & FDIAG) pp->p_flags |= PDIAG; } pp->p_command = savestr(command); if (pcurrjob) { struct process *fp; /* careful here with interrupt level */ pp->p_cwd = 0; pp->p_index = pcurrjob->p_index; pp->p_friends = pcurrjob; pp->p_jobid = pcurrjob->p_pid; for (fp = pcurrjob; fp->p_friends != pcurrjob; fp = fp->p_friends) ; fp->p_friends = pp; } else { pcurrjob = pp; pp->p_jobid = pid; pp->p_friends = pp; pp->p_cwd = dcwd; dcwd->di_count++; if (pmaxindex < BIGINDEX) pp->p_index = ++pmaxindex; else { struct process *np; for (i = 1; ; i++) { for (np = proclist.p_next; np; np = np->p_next) if (np->p_index == i) goto tryagain; pp->p_index = i; if (i > pmaxindex) pmaxindex = i; break; tryagain:; } } if (pcurrent == PNULL) pcurrent = pp; else if (pprevious == PNULL) pprevious = pp; } pp->p_next = proclist.p_next; proclist.p_next = pp; (void) gettimeofday(&pp->p_btime, (struct timezone *)0);}padd(t) register struct command *t;{ char **argp; if (t == 0) return; switch (t->t_dtyp) { case TPAR: pads("( "); padd(t->t_dspr); pads(" )"); break; case TCOM: for (argp = t->t_dcom; *argp; argp++) { pads(*argp); if (argp[1]) pads(" "); } break; case TOR: case TAND: case TFIL: case TLST: padd(t->t_dcar); switch (t->t_dtyp) { case TOR: pads(" || "); break; case TAND: pads(" && "); break; case TFIL: pads(" | "); break; case TLST: pads("; "); break; } padd(t->t_dcdr); return; } if ((t->t_dflg & FPIN) == 0 && t->t_dlef) { pads((t->t_dflg & FHERE) ? " << " : " < "); pads(t->t_dlef); } if ((t->t_dflg & FPOU) == 0 && t->t_drit) { pads((t->t_dflg & FCAT) ? " >>" : " >"); if (t->t_dflg & FDIAG) pads("&"); pads(" "); pads(t->t_drit); }}pads(cp) char *cp;{ register int i = strlen(cp); if (cmdlen >= PMAXLEN) return; if (cmdlen + i >= PMAXLEN) { (void) strcpy(cmdp, " ..."); cmdlen = PMAXLEN; cmdp += 4; return; } (void) strcpy(cmdp, cp); cmdp += i; cmdlen += i;}/* * psavejob - temporarily save the current job on a one level stack * so another job can be created. Used for { } in exp6 * and `` in globbing. */psavejob(){ pholdjob = pcurrjob; pcurrjob = PNULL;}/* * prestjob - opposite of psavejob. This may be missed if we are interrupted * somewhere, but pendjob cleans up anyway. */prestjob(){ pcurrjob = pholdjob; pholdjob = PNULL;}/* * pendjob - indicate that a job (set of commands) has been completed * or is about to begin. */pendjob(){ register struct process *pp, *tp; if (pcurrjob && (pcurrjob->p_flags&(PFOREGND|PSTOPPED)) == 0) { pp = pcurrjob; while (pp->p_pid != pp->p_jobid) pp = pp->p_friends; csh_printf("[%d]", pp->p_index); /* 004 RNF */ tp = pp; do { csh_printf(" %d", pp->p_pid); /* 004 RNF */ pp = pp->p_friends; } while (pp != tp); csh_printf("\n"); /* 004 RNF */ } pholdjob = pcurrjob = 0;}/* * pprint - print a job */pprint(pp, flag) register struct process *pp;{ register status, reason; struct process *tp; extern char *linp, linbuf[]; int jobflags, pstatus; char *format; while (pp->p_pid != pp->p_jobid) pp = pp->p_friends;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?