sh.proc.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,167 行 · 第 1/2 页
C
1,167 行
if (pp == pp->p_friends && (pp->p_flags & PPTIME)) { pp->p_flags &= ~PPTIME; pp->p_flags |= PTIME; } tp = pp; status = reason = -1; jobflags = 0; /* Ring terminal bell, if requested. Characters must be quoted to keep from being echoed as ^x */ if (flag&NOISEOK && adrof("notify")) { register unsigned char *nmp; for (nmp = (unsigned char *)value("notify"); *nmp; nmp++) { if (*nmp == QUOTECHAR) /* simply skip all quote chars */ nmp++; putchar((int)(QUOTE|*nmp)); } } do { jobflags |= pp->p_flags; pstatus = pp->p_flags & PALLSTATES; if (tp != pp && linp != linbuf && !(flag&FANCY) && (pstatus == status && pp->p_reason == reason || !(flag&REASON))) csh_printf(" "); /* 004 RNF */ else { if (tp != pp && linp != linbuf) csh_printf("\n"); /* 004 RNF */ if(flag&NUMBER) if (pp == tp) /* 004 RNF */ csh_printf("[%d]%s %c ", pp->p_index, pp->p_index < 10 ? " " : "", pp==pcurrent ? '+' : (pp == pprevious ? '-' : ' ')); else csh_printf(" "); /* 004 RNF */ if (flag&FANCY) csh_printf("%5d ", pp->p_pid); /* 004 RNF */ if (flag&(REASON|AREASON)) { if (flag&NAME) format = "%-21s"; else format = "%s"; if (pstatus == status) if (pp->p_reason == reason) { csh_printf(format, ""); /* 004 RNF */ goto prcomd; } else reason = pp->p_reason; else { status = pstatus; reason = pp->p_reason; } switch (status) { case PRUNNING: csh_printf(format, "Running "); /* 004 RNF */ break; case PINTERRUPTED: case PSTOPPED: case PSIGNALED: if ((flag&(REASON|AREASON)) && reason != SIGINT && reason != SIGPIPE) csh_printf(format, mesg[pp->p_reason].pname); /* 004 RNF */ break; case PNEXITED: case PAEXITED: if (flag & REASON) if (pp->p_reason) csh_printf("Exit %-16d", pp->p_reason); /* 004 RNF */ else csh_printf(format, "Done"); /* 004 RNF */ break; default: csh_printf("BUG: status=%-9o", status); /* 004 RNF */ } } }prcomd: if (flag&NAME) { csh_printf("%s", pp->p_command); /* 004 RNF */ if (pp->p_flags & PPOU) csh_printf(" |"); /* 004 RNF */ if (pp->p_flags & PDIAG) csh_printf("&"); /* 004 RNF */ } if (flag&(REASON|AREASON) && pp->p_flags&PDUMPED) csh_printf(" (core dumped)"); /* 004 RNF */ if (tp == pp->p_friends) { if (flag&ERSAND) csh_printf(" &"); /* 004 RNF */ if (flag&JOBDIR && !eq(tp->p_cwd->di_name, dcwd->di_name)) { csh_printf(" (wd: "); /* 004 RNF */ dtildepr(value("home"), tp->p_cwd->di_name); csh_printf(")"); /* 004 RNF */ } } if (pp->p_flags&PPTIME && !(status&(PSTOPPED|PRUNNING))) { if (linp != linbuf) csh_printf("\n\t"); /* 004 RNF */ { static struct rusage zru; prusage(&zru, &pp->p_rusage, &pp->p_etime, &pp->p_btime); } } if (tp == pp->p_friends) { if (linp != linbuf) csh_printf("\n"); /* 004 RNF */ if (flag&SHELLDIR && !eq(tp->p_cwd->di_name, dcwd->di_name)) { csh_printf("(wd now: "); /* 004 RNF */ dtildepr(value("home"), dcwd->di_name); csh_printf(")\n"); /* 004 RNF */ } } } while ((pp = pp->p_friends) != tp); if (jobflags&PTIME && (jobflags&(PSTOPPED|PRUNNING)) == 0) { if (jobflags & NUMBER) csh_printf(" "); /* 004 RNF */ ptprint(tp); } return (jobflags);}ptprint(tp) register struct process *tp;{ struct timeval tetime, diff; static struct timeval ztime; struct rusage ru; static struct rusage zru; register struct process *pp = tp; ru = zru; tetime = ztime; do { ruadd(&ru, &pp->p_rusage); tvsub(&diff, &pp->p_etime, &pp->p_btime); if (timercmp(&diff, &tetime, >)) tetime = diff; } while ((pp = pp->p_friends) != tp); prusage(&zru, &ru, &tetime, &ztime);}/* * dojobs - print all jobs */dojobs(v) char **v;{ register struct process *pp; register int flag = NUMBER|NAME|REASON; int i; if (chkstop) chkstop = 2; if (*++v) { if (v[1] || !eq(*v, "-l")) error("Usage: jobs [ -l ]"); flag |= FANCY|JOBDIR; } for (i = 1; i <= pmaxindex; i++) for (pp = proclist.p_next; pp; pp = pp->p_next) if (pp->p_index == i && pp->p_pid == pp->p_jobid) { pp->p_flags &= ~PNEEDNOTE; if (!(pprint(pp, flag) & (PRUNNING|PSTOPPED))) pflush(pp); break; }}/* * dofg - builtin - put the job into the foreground */dofg(v) char **v;{ register struct process *pp; okpcntl(); ++v; do { pp = pfind(*v); pstart(pp, 1); pjwait(pp); } while (*v && *++v);}/* * %... - builtin - put the job into the foreground */dofg1(v) char **v;{ register struct process *pp; okpcntl(); pp = pfind(v[0]); pstart(pp, 1); pjwait(pp);}/* * dobg - builtin - put the job into the background */dobg(v) char **v;{ register struct process *pp; okpcntl(); ++v; do { pp = pfind(*v); pstart(pp, 0); } while (*v && *++v);}/* * %... & - builtin - put the job into the background */dobg1(v) char **v;{ register struct process *pp; pp = pfind(v[0]); pstart(pp, 0);}/* * dostop - builtin - stop the job */dostop(v) char **v;{ pkill(++v, SIGSTOP);}/* * dokill - builtin - superset of kill (1) */dokill(v) char **v;{ register int signum; register char *name; v++; if (v[0] && v[0][0] == '-') { if (v[0][1] == 'l') { for (signum = 1; signum <= NSIG; signum++) { if (name = mesg[signum].iname) csh_printf("%s ", name); /* 004 RNF */ if (signum == 16) putchar('\n'); } putchar('\n'); return; } if (digit(v[0][1])) { signum = atoi(v[0]+1); if (signum < 0 || signum > NSIG) bferr("Bad signal number"); } else { name = &v[0][1]; for (signum = 1; signum <= NSIG; signum++) if (mesg[signum].iname && eq(name, mesg[signum].iname)) goto gotsig; setname(name); bferr("Unknown signal; kill -l lists signals"); }gotsig: v++; } else signum = SIGTERM; pkill(v, signum);}pkill(v, signum) char **v; int signum;{ register struct process *pp, *np; register int jobflags = 0; int omask, pid, err = 0; char *cp; extern char *sys_errlist[]; omask = sigmask(SIGCHLD); if (setintr) omask |= sigmask(SIGINT); omask = sigblock(omask) & ~omask; while (*v) { cp = globone(*v); if (*cp == '%') { np = pp = pfind(cp); do jobflags |= np->p_flags; while ((np = np->p_friends) != pp); switch (signum) { case SIGCONT: np->p_flags |= PRUNNING; np->p_flags &= ~PSTOPPED; break; case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU: if ((jobflags & PRUNNING) == 0) { csh_printf("%s: Already stopped\n", cp); /* 004 RNF */ err++; goto cont; } } if (killpg(pp->p_jobid, signum) < 0) { csh_printf("%s: ", cp); /* 004 RNF */ csh_printf("%s\n", sys_errlist[errno]); /* 004 RNF */ err++; } if (signum == SIGTERM || signum == SIGHUP) (void) killpg(pp->p_jobid, SIGCONT); } else if (!(digit(*cp) || *cp == '-')) bferr("Arguments should be jobs or process id's"); else { pid = atoi(cp); if (kill(pid, signum) < 0) { csh_printf("%d: ", pid); /* 004 RNF */ csh_printf("%s\n", sys_errlist[errno]); /* 004 RNF */ err++; goto cont; } if (signum == SIGTERM || signum == SIGHUP) (void) kill(pid, SIGCONT); }cont: xfree(cp); v++; } (void) sigsetmask(omask); if (err) error(NOSTR);}/* * pstart - start the job in foreground/background */pstart(pp, foregnd) register struct process *pp; int foregnd;{ register struct process *np; int omask, jobflags = 0; omask = sigblock(sigmask(SIGCHLD)); np = pp; do { jobflags |= np->p_flags; if (np->p_flags&(PRUNNING|PSTOPPED)) { np->p_flags |= PRUNNING; np->p_flags &= ~PSTOPPED; if (foregnd) np->p_flags |= PFOREGND; else np->p_flags &= ~PFOREGND; } } while((np = np->p_friends) != pp); if (!foregnd) pclrcurr(pp); (void) pprint(pp, foregnd ? NAME|JOBDIR : NUMBER|NAME|AMPERSAND); if (foregnd) (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&pp->p_jobid); /* 002 - GAG */ if (jobflags&PSTOPPED) (void) killpg(pp->p_jobid, SIGCONT); (void) sigsetmask(omask);}panystop(neednl){ register struct process *pp; chkstop = 2; for (pp = proclist.p_next; pp; pp = pp->p_next) if (pp->p_flags & PSTOPPED) error("\nThere are stopped jobs" + 1 - neednl);}struct process *pfind(cp) char *cp;{ register struct process *pp, *np; if (cp == 0 || cp[1] == 0 || eq(cp, "%%") || eq(cp, "%+")) { if (pcurrent == PNULL) bferr("No current job"); return (pcurrent); } if (eq(cp, "%-") || eq(cp, "%#")) { if (pprevious == PNULL) bferr("No previous job"); return (pprevious); } if (digit(cp[1])) { int index = atoi(cp+1); /* 003 RNF */ for (pp = proclist.p_next; pp; pp = pp->p_next) if (pp->p_index == index && pp->p_pid == pp->p_jobid) return (pp); bferr("No such job"); } np = PNULL; for (pp = proclist.p_next; pp; pp = pp->p_next) if (pp->p_pid == pp->p_jobid) { if (cp[1] == '?') { register char *dp; for (dp = pp->p_command; *dp; dp++) { if (*dp != cp[2]) continue; if (prefix(cp+2, dp)) goto match; } } else if (prefix(cp+1, pp->p_command)) {match: if (np) bferr("Ambiguous"); np = pp; } } if (np) return (np); if (cp[1] == '?') bferr("No job matches pattern"); else bferr("No such job"); /*NOTREACHED*/}/* * pgetcurr - find most recent job that is not pp, preferably stopped */struct process *pgetcurr(pp) register struct process *pp;{ register struct process *np; register struct process *xp = PNULL; for (np = proclist.p_next; np; np = np->p_next) if (np != pcurrent && np != pp && np->p_pid && np->p_pid == np->p_jobid) { if (np->p_flags & PSTOPPED) return (np); if (xp == PNULL) xp = np; } return (xp);}/* * donotify - flag the job so as to report termination asynchronously */donotify(v) char **v;{ register struct process *pp; pp = pfind(*++v); pp->p_flags |= PNOTIFY;}/* * Do the fork and whatever should be done in the child side that * should not be done if we are not forking at all (like for simple builtin's) * Also do everything that needs any signals fiddled with in the parent side * * Wanttty tells whether process and/or tty pgrps are to be manipulated: * -1: leave tty alone; inherit pgrp from parent * 0: already have tty; manipulate process pgrps only * 1: want to claim tty; manipulate process and tty pgrps * It is usually just the value of tpgrp. */pfork(t, wanttty) struct command *t; /* command we are forking for */ int wanttty;{ register int pid; bool ignint = 0; int pgrp, omask; /* * A child will be uninterruptible only under very special * conditions. Remember that the semantics of '&' is * implemented by disconnecting the process from the tty so * signals do not need to ignored just for '&'. * Thus signals are set to default action for children unless: * we have had an "onintr -" (then specifically ignored) * we are not playing with signals (inherit action) */ if (setintr) ignint = (tpgrp == -1 && (t->t_dflg&FINT)) || (gointr && eq(gointr, "-")); /* * Hold SIGCHLD until we have the process installed in our table. */ omask = sigblock(sigmask(SIGCHLD)); while ((pid = fork()) < 0) if (setintr == 0) sleep(FORKSLEEP); else { (void) sigsetmask(omask); error("No more processes"); } if (pid == 0) { settimes(); pgrp = pcurrjob ? pcurrjob->p_jobid : getpid(); pflushall(); pcurrjob = PNULL; child++; if (setintr) { setintr = 0; /* until I think otherwise */ /* * Children just get blown away on SIGINT, SIGQUIT * unless "onintr -" seen. */ (void) signal(SIGINT, ignint ? SIG_IGN : SIG_DFL); (void) signal(SIGQUIT, ignint ? SIG_IGN : SIG_DFL); if (wanttty >= 0) { /* make stoppable */ (void) signal(SIGTSTP, SIG_DFL); (void) signal(SIGTTIN, SIG_DFL); (void) signal(SIGTTOU, SIG_DFL); } (void) signal(SIGTERM, parterm); } else if (tpgrp == -1 && (t->t_dflg&FINT)) { (void) signal(SIGINT, SIG_IGN); (void) signal(SIGQUIT, SIG_IGN); } if (wanttty > 0) (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&pgrp); /* 002 - GAG */ if (wanttty >= 0 && tpgrp >= 0) (void) setpgrp(0, pgrp); if (tpgrp > 0) tpgrp = 0; /* gave tty away */ /* * Nohup and nice apply only to TCOM's but it would be * nice (?!?) if you could say "nohup (foo;bar)" * Then the parser would have to know about nice/nohup/time */ if (t->t_dflg & FNOHUP) (void) signal(SIGHUP, SIG_IGN); if (t->t_dflg & FNICE) (void) setpriority(PRIO_PROCESS, 0, t->t_nice); } else { palloc(pid, t); (void) sigsetmask(omask); } return (pid);}okpcntl(){ if (tpgrp == -1) error("No job control in this shell"); if (tpgrp == 0) error("No job control in subshells");}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?