# 2.11BSD#431 - /usr/src/bin/tcsh/sh.proc.c

##### Functions

    dobg              X
    dobg1             X
    dofg              X
    dofg1             X
    dojobs            X
    dokill            X
    donotify          X
    dostop            X
    dowait            X
    palloc            X
    panystop          X
    pchild            X
    pendjob           X
    pfind             X
    pfork             X
    pgetty            X
    pjwait            X
    pnote             X
    prestjob          X
    psavejob          X
    pstart            X
    pwait             X

##### Macros

    BIGINDEX          X
    BSDWAIT           X
    HZ                X
    NSIG              X
    RUSAGE_CHILDREN   X
    WCOREDUMP         X
    WEXITSTATUS       X
    WSTOPSIG          X
    WTERMSIG          X
    _BSD              X
    _CLASSIC_POSIX_TYPESX
    timercmp          X

       1: /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/sh.proc.c,v 3.1 1991/07/05 02:00:43 christos Exp $ */
       2: /*
       3:  * sh.proc.c: Job manipulations
       4:  */
       5: /*-
       6:  * Copyright (c) 1980, 1991 The Regents of the University of California.
       7:  * All rights reserved.
       8:  *
       9:  * Redistribution and use in source and binary forms, with or without
      10:  * modification, are permitted provided that the following conditions
      11:  * are met:
      12:  * 1. Redistributions of source code must retain the above copyright
      13:  *    notice, this list of conditions and the following disclaimer.
      14:  * 2. Redistributions in binary form must reproduce the above copyright
      15:  *    notice, this list of conditions and the following disclaimer in the
      16:  *    documentation and/or other materials provided with the distribution.
      17:  * 3. All advertising materials mentioning features or use of this software
      18:  *    must display the following acknowledgement:
      19:  *	This product includes software developed by the University of
      20:  *	California, Berkeley and its contributors.
      21:  * 4. Neither the name of the University nor the names of its contributors
      22:  *    may be used to endorse or promote products derived from this software
      23:  *    without specific prior written permission.
      24:  *
      25:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      26:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      27:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      28:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      29:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      30:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      31:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      32:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      33:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      34:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      35:  * SUCH DAMAGE.
      36:  */
      37: #include "config.h"
      38: #if !defined(lint) && !defined(pdp11)
      39: static char *rcsid()
      40:     { return "$Id: sh.proc.c,v 3.1 1991/07/05 02:00:43 christos Exp $"; }
      41: #endif
      42:
      43: #include "sh.h"
      44: #include "ed.h"
      45:
      46: /*
      47:  * a little complicated #include <sys/wait.h>! :-(
      48:  */
      49: #if SVID > 0
      50: # ifdef hpux
      51: #  ifndef __hpux
      52: #   include "tc.wait.h" /* 6.5 broke <sys/wait.h> */
      53: #  else
      54: #   ifndef POSIX
      55: #    define _BSD
      56: #   endif
      57: #   ifndef _CLASSIC_POSIX_TYPES
      58: #    define _CLASSIC_POSIX_TYPES
      59: #   endif
      60: #   include <sys/wait.h> /* 7.0 fixed it again */
      61: #  endif /* __hpux */
      62: # else /* hpux */
      63: #  if defined(OREO) || defined(IRIS4D) || defined(POSIX)
      64: #   include <sys/wait.h>
      65: #  else /* OREO || IRIS4D || POSIX */
      66: #   include "tc.wait.h"
      67: #  endif /* OREO || IRIS4D || POSIX */
      68: # endif	/* hpux */
      69: #else /* SVID == 0 */
      70: # include <sys/wait.h>
      71: #endif /* SVID == 0 */
      72:
      73: #if !defined(NSIG) && defined(SIGMAX)
      74: # define NSIG (SIGMAX+1)
      75: #endif /* !NSIG && SIGMAX */
      76:
      77: #ifdef aiws
      78: # undef HZ
      79: # define HZ 16
      80: #endif /* aiws */
      81:
      82: #ifndef HZ
      83: # define HZ 100     /* for division into seconds */
      84: #endif
      85:
      86: #ifndef WTERMSIG
      87: # define WTERMSIG(w)    (((union wait *) &(w))->w_termsig)
      88: # define BSDWAIT
      89: #endif /* !WTERMSIG */
      90: #ifndef WEXITSTATUS
      91: # define WEXITSTATUS(w) (((union wait *) &(w))->w_retcode)
      92: #endif /* !WEXITSTATUS */
      93: #ifndef WSTOPSIG
      94: # define WSTOPSIG(w)    (((union wait *) &(w))->w_stopsig)
      95: #endif /* WSTOPSIG */
      96:
      97: #ifndef WCOREDUMP
      98: # ifdef BSDWAIT
      99: #  define WCOREDUMP(w)  (((union wait *) &(w))->w_coredump)
     100: # else /* !BSDWAIT */
     101: #  define WCOREDUMP(w)  ((w) & 0200)
     102: # endif /* !BSDWAIT */
     103: #endif /* !WCOREDUMP */
     104:
     105: /*
     106:  * C Shell - functions that manage processes, handling hanging, termination
     107:  */
     108:
     109: #define BIGINDEX    9   /* largest desirable job index */
     110:
     111: #ifdef BSDTIMES
     112: # if defined(sun) || defined(hp9000)
     113: static struct rusage zru = {{0L, 0L}, {0L, 0L}, 0L, 0L, 0L, 0L,
     114:                 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L};
     115:
     116: # else /* !sun && !hp9000 */
     117: #  ifdef masscomp
     118: /*
     119:  * Initialization of this structure under RTU 4.1A & RTU 5.0 is problematic
     120:  * because the first two elements are unions of a time_t and a struct timeval.
     121:  * So we'll just have to trust the loader to do the "right thing", DAS DEC-90.
     122:  */
     123: static struct rusage zru;
     124: #  else /* masscomp */
     125: static struct rusage zru = {{0L, 0L}, {0L, 0L}, 0, 0, 0, 0, 0, 0, 0,
     126:                 0, 0, 0, 0, 0, 0};
     127: #  endif /* masscomp */
     128: # endif	/* !sun && !hp9000 */
     129: #else /* ! BSDTIMES */
     130: # ifdef _SEQUENT_
     131: static struct pro_stats zru = {{0L, 0L}, {0L, 0L}, 0, 0, 0, 0, 0, 0, 0,
     132:                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
     133: # else /* !_SEQUENT_ */
     134: static struct tms zru = {0L, 0L, 0L, 0L}, lru = {0L, 0L, 0L, 0L};
     135: # endif	/* !_SEQUENT_ */
     136: #endif /* !BSDTIMES */
     137:
     138: #ifndef RUSAGE_CHILDREN
     139: # define    RUSAGE_CHILDREN -1
     140: #endif
     141:
     142: static  void         pflushall  __P((void));
     143: static  void         pflush     __P((struct process *));
     144: static  void         pclrcurr   __P((struct process *));
     145: static  void         padd       __P((struct command *));
     146: static  int      pprint     __P((struct process *, int));
     147: static  void         ptprint    __P((struct process *));
     148: static  void         pads       __P((Char *));
     149: static  void         pkill      __P((Char **v, int));
     150: static  struct process  *pgetcurr   __P((struct process *));
     151: static  void         okpcntl    __P((void));
     152:
     153: /*
     154:  * pchild - called at interrupt level by the SIGCHLD signal
     155:  *	indicating that at least one child has terminated or stopped
     156:  *	thus at least one wait system call will definitely return a
     157:  *	childs status.  Top level routines (like pwait) must be sure
     158:  *	to mask interrupts when playing with the proclist data structures!
     159:  */
     160: sigret_t
     161: /*ARGSUSED*/
     162: pchild(snum)
     163: int snum;
     164: {
     165:     register struct process *pp;
     166:     register struct process *fp;
     167:     register int pid;
     168:     extern int insource;
     169: #ifdef BSDWAIT
     170:     union wait w;
     171: #else /* !BSDWAIT */
     172:     int     w;
     173: #endif /* !BSDWAIT */
     174:     int     jobflags;
     175: #ifdef BSDTIMES
     176:     struct rusage ru;
     177: #else /* !BSDTIMES */
     178: # ifdef _SEQUENT_
     179:     struct pro_stats ru;
     180:     struct pro_stats cpst1, cpst2;
     181:     tmval_t tv;
     182: # else /* !_SEQUENT_ */
     183:     struct tms proctimes;
     184:
     185:     if (!timesdone) {
     186:     timesdone++;
     187:     (void) times(&shtimes);
     188:     }
     189: # endif	/* _SEQUENT_ */
     190: #endif /* BSDTIMES */
     191:
     192: #ifdef JOBDEBUG
     193:     xprintf("pchild()\n");
     194: #endif	/* JOBDEBUG */
     195:
     196: /* Christos on where the signal(SIGCHLD, pchild) shoud be:
     197:  *
     198:  * I think that it should go *after* the wait, unlike most signal handlers.
     199:  *
     200:  * In release two (for which I have manuals), it says that wait will remove
     201:  * the first child from the queue of dead children.
     202:  * All the rest of the children that die while in the signal handler of the
     203:  * SIGC(H)LD, will be placed in the queue. If signal is called to re-establish
     204:  * the signal handler, and there are items in the queue, the process will
     205:  * receive another SIGC(H)LD before signal returns. BTW this is from the
     206:  * manual page on comp-sim... Maybe it is not applicable to the hp's, but
     207:  * I read on the news in comp.unix.wizards or comp.unix.questions yesterday
     208:  * that another person was claiming the the signal() call should be after
     209:  * the wait().
     210:  */
     211:
     212: loop:
     213:     errno = 0;          /* reset, just in case */
     214: #ifdef JOBDEBUG
     215:     xprintf("Waiting...\n");
     216:     flush();
     217: #endif
     218: #ifdef BSDJOBS
     219: # ifdef BSDTIMES
     220:     /* both a wait3 and rusage */
     221: #  ifndef BSDWAIT
     222:     pid = wait3(&w,
     223:        (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru);
     224: #  else /* BSDWAIT */
     225:     pid = wait3(&w.w_status,
     226:        (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru);
     227: #  endif /* BSDWAIT */
     228: # else /* !BSDTIMES */
     229: #  ifdef _SEQUENT_
     230:     (void) get_pro_stats(&tv, PS_SELF, 0, &cpst1);
     231:     pid = waitpid(-1, &w,
     232:         (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG));
     233:     (void) get_pro_stats(&tv, PS_SELF, 0, &cpst2);
     234:     pr_stat_sub(&cpst2, &cpst1, &ru);
     235: #  else /* !_SEQUENT_ */
     236: #   ifndef POSIX
     237:     /* we have a wait3, but no rusage stuff */
     238:     pid = wait3(&w.w_status,
     239:      (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), 0);
     240: #   else /* POSIX */
     241:     pid = waitpid(-1, &w,
     242:         (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG));
     243: #   endif /* POSIX */
     244: #  endif /* !_SEQUENT_ */
     245: # endif	/* !BSDTIMES */
     246: #else /* !BSDJOBS */
     247: # ifdef BSDTIMES
     248:     /* both a wait3 and rusage */
     249: #  ifdef hpux
     250:     pid = wait3(&w.w_status, WNOHANG, 0);
     251: #  else /* !hpux */
     252:     pid = wait3(&w.w_status, WNOHANG, &ru);
     253: #  endif /* !hpux */
     254: # else /* !BSDTIMES */
     255: #  if SVID < 3
     256:     /* no wait3, therefore no rusage */
     257:     /* on Sys V, this may hang.  I hope it's not going to be a problem */
     258:     pid = ourwait(&w.w_status);
     259: #  else /* SVID >= 3 */
     260:     /*
     261:      * XXX: for greater than 3 we should use waitpid().
     262:      * but then again, SVR4 falls into the POSIX/BSDJOBS category.
     263:      */
     264:     pid = wait(&w.w_status);
     265: #  endif /* SVID >= 3 */
     266: # endif	/* BSDTIMES */
     267: #endif /* BSDJOBS */
     268:
     269: #ifdef JOBDEBUG
     270:     {
     271:     char    buffer[100];
     272:     xsprintf(buffer, "pid %d, retval %x termsig %x retcode %x\n",
     273:          pid, w, WTERMSIG(w), WEXITSTATUS(w));
     274:     xprintf(buffer);
     275:     flush();
     276:     }
     277: #endif /* JOBDEBUG */
     278:
     279:     if (pid <= 0) {
     280: #ifdef JOBDEBUG
     281:     xprintf("errno == %d\n", errno);
     282: #endif
     283:     if (errno == EINTR) {
     284:         errno = 0;
     285:         goto loop;
     286:     }
     287:     pnoprocesses = pid == -1;
     288: #ifndef SIGVOID
     289:     return (0);
     290: #else /* !SIGVOID */
     291:     return;
     292: #endif /* SIGVOID */
     293:     }
     294:     for (pp = proclist.p_next; pp != PNULL; pp = pp->p_next)
     295:     if (pid == pp->p_pid)
     296:         goto found;
     297: #ifndef BSDJOBS
     298:     /* this should never have happened */
     299:     stderror(ERR_SYNC, pid);
     300:     xexit(0);
     301: #else /* BSDJOBS */
     302:     goto loop;
     303: #endif /* BSDJOBS */
     304: found:
     305:     if (pid == atoi(short2str(value(STRchild))))
     306:     unsetv(STRchild);
     307:     pp->p_flags &= ~(PRUNNING | PSTOPPED | PREPORTED);
     308:     if (WIFSTOPPED(w)) {
     309:     pp->p_flags |= PSTOPPED;
     310:     pp->p_reason = WSTOPSIG(w);
     311:     }
     312:     else {
     313:     if (pp->p_flags & (PTIME | PPTIME) || adrof(STRtime))
     314: #ifndef BSDTIMES
     315: # ifdef _SEQUENT_
     316:         (void) get_pro_stats(&pp->p_etime, PS_SELF, NULL, NULL);
     317: # else  /* !_SEQUENT_ */
     318:         pp->p_etime = times(&proctimes);
     319: # endif	/* !_SEQUENT_ */
     320: #else /* BSDTIMES */
     321:         (void) gettimeofday(&pp->p_etime, NULL);
     322: #endif /* BSDTIMES */
     323:
     324:
     325: #if defined(BSDTIMES) || defined(_SEQUENT_)
     326:     pp->p_rusage = ru;
     327: #else /* !BSDTIMES && !_SEQUENT_ */
     328:     (void) times(&proctimes);
     329:     pp->p_utime = proctimes.tms_cutime - shtimes.tms_cutime;
     330:     pp->p_stime = proctimes.tms_cstime - shtimes.tms_cstime;
     331:     shtimes = proctimes;
     332: #endif /* !BSDTIMES && !_SEQUENT_ */
     333:     if (WIFSIGNALED(w)) {
     334:         if (WTERMSIG(w) == SIGINT)
     335:         pp->p_flags |= PINTERRUPTED;
     336:         else
     337:         pp->p_flags |= PSIGNALED;
     338:         if (WCOREDUMP(w))
     339:         pp->p_flags |= PDUMPED;
     340:         pp->p_reason = WTERMSIG(w);
     341:     }
     342:     else {
     343:         pp->p_reason = WEXITSTATUS(w);
     344:         if (pp->p_reason != 0)
     345:         pp->p_flags |= PAEXITED;
     346:         else
     347:         pp->p_flags |= PNEXITED;
     348:     }
     349:     }
     350:     jobflags = 0;
     351:     fp = pp;
     352:     do {
     353:     if ((fp->p_flags & (PPTIME | PRUNNING | PSTOPPED)) == 0 &&
     354:         !child && adrof(STRtime) &&
     355: #ifdef BSDTIMES
     356:         fp->p_rusage.ru_utime.tv_sec + fp->p_rusage.ru_stime.tv_sec
     357: #else /* !BSDTIMES */
     358: # ifdef _SEQUENT_
     359:         fp->p_rusage.ps_utime.tv_sec + fp->p_rusage.ps_stime.tv_sec
     360: # else /* !_SEQUENT_ */
     361: #  ifndef POSIX
     362:         (fp->p_utime + fp->p_stime) / HZ
     363: #  else /* POSIX */
     364:         (fp->p_utime + fp->p_stime) / CLK_TCK
     365: #  endif /* POSIX */
     366: # endif /* !_SEQUENT_ */
     367: #endif /* !BSDTIMES */
     368:         >= atoi(short2str(value(STRtime))))
     369:         fp->p_flags |= PTIME;
     370:     jobflags |= fp->p_flags;
     371:     } while ((fp = fp->p_friends) != pp);
     372:     pp->p_flags &= ~PFOREGND;
     373:     if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
     374:     pp->p_flags &= ~PPTIME;
     375:     pp->p_flags |= PTIME;
     376:     }
     377:     if ((jobflags & (PRUNNING | PREPORTED)) == 0) {
     378:     fp = pp;
     379:     do {
     380:         if (fp->p_flags & PSTOPPED)
     381:         fp->p_flags |= PREPORTED;
     382:     } while ((fp = fp->p_friends) != pp);
     383:     while (fp->p_pid != fp->p_jobid)
     384:         fp = fp->p_friends;
     385:     if (jobflags & PSTOPPED) {
     386:         if (pcurrent && pcurrent != fp)
     387:         pprevious = pcurrent;
     388:         pcurrent = fp;
     389:     }
     390:     else
     391:         pclrcurr(fp);
     392:     if (jobflags & PFOREGND) {
     393:         if (jobflags & (PSIGNALED | PSTOPPED | PPTIME) ||
     394: #ifdef IIASA
     395:         jobflags & PAEXITED ||
     396: #endif /* IIASA */
     397:         !eq(dcwd->di_name, fp->p_cwd->di_name)) {
     398:         ;       /* print in pjwait */
     399:         }
     400:         /* PWP: print a newline after ^C */
     401:         else if (jobflags & PINTERRUPTED)
     402: #ifdef SHORT_STRINGS
     403:         xputchar('\r' | QUOTE), xputchar('\n');
     404: #else /* !SHORT_STRINGS */
     405:         xprintf("\215\n");  /* \215 is a quoted ^M */
     406: #endif /* !SHORT_STRINGS */
     407: #ifdef notdef
     408:         else if ((jobflags & (PTIME|PSTOPPED)) == PTIME)
     409:                 ptprint(fp);
     410: #endif
     411:     }
     412:     else {
     413:         if (jobflags & PNOTIFY || adrof(STRnotify)) {
     414: #ifdef SHORT_STRINGS
     415:         xputchar('\r' | QUOTE), xputchar('\n');
     416: #else /* !SHORT_STRINGS */
     417:         xprintf("\215\n");  /* \215 is a quoted ^M */
     418: #endif /* !SHORT_STRINGS */
     419:         (void) pprint(pp, NUMBER | NAME | REASON);
     420:         if ((jobflags & PSTOPPED) == 0)
     421:             pflush(pp);
     422:         {
     423:             extern Char GettingInput;
     424:
     425:             if (GettingInput) {
     426:             errno = 0;
     427:             (void) Rawmode();
     428:             ClearLines();
     429:             ClearDisp();
     430:             Refresh();
     431:             }
     432:         }
     433:         }
     434:         else {
     435:         fp->p_flags |= PNEEDNOTE;
     436:         neednote++;
     437:         }
     438:     }
     439:     }
     440: #ifdef BSDJOBS
     441:     goto loop;
     442: #endif /* BSDJOBS */
     443: }
     444:
     445: void
     446: pnote()
     447: {
     448:     register struct process *pp;
     449:     int     flags;
     450: #ifdef BSDSIGS
     451:     sigmask_t omask;
     452: #endif /* BSDSIGS */
     453:
     454:     neednote = 0;
     455:     for (pp = proclist.p_next; pp != PNULL; pp = pp->p_next) {
     456:     if (pp->p_flags & PNEEDNOTE) {
     457: #ifdef BSDSIGS
     458:         omask = sigblock(sigmask(SIGCHLD));
     459: #else /* !BSDSIGS */
     460:         (void) sighold(SIGCHLD);
     461: #endif /* !BSDSIGS */
     462:         pp->p_flags &= ~PNEEDNOTE;
     463:         flags = pprint(pp, NUMBER | NAME | REASON);
     464:         if ((flags & (PRUNNING | PSTOPPED)) == 0)
     465:         pflush(pp);
     466: #ifdef BSDSIGS
     467:         (void) sigsetmask(omask);
     468: #else /* !BSDSIGS */
     469:         (void) sigrelse(SIGCHLD);
     470: #endif /* !BSDSIGS */
     471:     }
     472:     }
     473: }
     474:
     475: /*
     476:  * pwait - wait for current job to terminate, maintaining integrity
     477:  *	of current and previous job indicators.
     478:  */
     479: void
     480: pwait()
     481: {
     482:     register struct process *fp, *pp;
     483: #ifdef BSDSIGS
     484:     sigmask_t omask;
     485: #endif /* BSDSIGS */
     486:
     487:     /*
     488:      * Here's where dead procs get flushed.
     489:      */
     490: #ifdef BSDSIGS
     491:     omask = sigblock(sigmask(SIGCHLD));
     492: #else /* !BSDSIGS */
     493:     (void) sighold(SIGCHLD);
     494: #endif /* !BSDSIGS */
     495:     for (pp = (fp = &proclist)->p_next; pp != PNULL; pp = (fp = pp)->p_next)
     496:     if (pp->p_pid == 0) {
     497:         fp->p_next = pp->p_next;
     498:         xfree((ptr_t) pp->p_command);
     499:         if (pp->p_cwd && --pp->p_cwd->di_count == 0)
     500:         if (pp->p_cwd->di_next == 0)
     501:             dfree(pp->p_cwd);
     502:         xfree((ptr_t) pp);
     503:         pp = fp;
     504:     }
     505: #ifdef BSDSIGS
     506:     (void) sigsetmask(omask);
     507: #else /* !BSDSIGS */
     508:     (void) sigrelse(SIGCHLD);
     509: # ifdef notdef
     510:     if (setintr)
     511:     sigignore(SIGINT);
     512: # endif
     513: #endif /* !BSDSIGS */
     514:     pjwait(pcurrjob);
     515: }
     516:
     517:
     518: /*
     519:  * pjwait - wait for a job to finish or become stopped
     520:  *	It is assumed to be in the foreground state (PFOREGND)
     521:  */
     522: void
     523: pjwait(pp)
     524:     register struct process *pp;
     525: {
     526:     register struct process *fp;
     527:     int     jobflags, reason;
     528: #ifdef BSDSIGS
     529:     sigmask_t omask;
     530: #endif /* BSDSIGS */
     531:
     532:     while (pp->p_pid != pp->p_jobid)
     533:     pp = pp->p_friends;
     534:     fp = pp;
     535:
     536:     do {
     537:     if ((fp->p_flags & (PFOREGND | PRUNNING)) == PRUNNING)
     538:         xprintf("BUG: waiting for background job!\n");
     539:     } while ((fp = fp->p_friends) != pp);
     540:     /*
     541:      * Now keep pausing as long as we are not interrupted (SIGINT), and the
     542:      * target process, or any of its friends, are running
     543:      */
     544:     fp = pp;
     545: #ifdef BSDSIGS
     546:     omask = sigblock(sigmask(SIGCHLD));
     547: #endif /* BSDSIGS */
     548:     for (;;) {
     549: #ifndef BSDSIGS
     550:     (void) sighold(SIGCHLD);
     551: #endif /* !BSDSIGS */
     552:     jobflags = 0;
     553:     do
     554:         jobflags |= fp->p_flags;
     555:     while ((fp = (fp->p_friends)) != pp);
     556:     if ((jobflags & PRUNNING) == 0)
     557:         break;
     558: #ifdef JOBDEBUG
     559:     xprintf("starting to sigpause for  SIGCHLD on %d\n", fp->p_pid);
     560: #endif /* JOBDEBUG */
     561: #ifdef BSDSIGS
     562:     /* sigpause(sigblock((sigmask_t) 0) &~ sigmask(SIGCHLD)); */
     563:     (void) sigpause(omask & ~sigmask(SIGCHLD));
     564: #else /* !BSDSIGS */
     565:     (void) sigpause(SIGCHLD);
     566: #endif /* !BSDSIGS */
     567:     }
     568: #ifdef BSDSIGS
     569:     (void) sigsetmask(omask);
     570: #else /* !BSDSIGS */
     571:     (void) sigrelse(SIGCHLD);
     572: #endif /* !BSDSIGS */
     573: #ifdef BSDJOBS
     574:     if (tpgrp > 0)      /* get tty back */
     575:     (void) tcsetpgrp(FSHTTY, tpgrp);
     576: #endif /* BSDJOBS */
     577:     if ((jobflags & (PSIGNALED | PSTOPPED | PTIME)) ||
     578:     !eq(dcwd->di_name, fp->p_cwd->di_name)) {
     579:     if (jobflags & PSTOPPED) {
     580:         xprintf("\n");
     581:         if (adrof(STRl_jobs)) {
     582:         Char   *jobcommand[3];
     583:
     584:         jobcommand[0] = STRjobs;
     585:         if (eq(value(STRl_jobs), STRlong))
     586:             jobcommand[1] = STRml;
     587:         else
     588:             jobcommand[1] = NULL;
     589:         jobcommand[2] = NULL;
     590:
     591:         dojobs(jobcommand);
     592:         (void) pprint(pp, SHELLDIR);
     593:         }
     594:         else
     595:         (void) pprint(pp, AREASON | SHELLDIR);
     596:     }
     597:     else
     598:         (void) pprint(pp, AREASON | SHELLDIR);
     599:     }
     600:     if ((jobflags & (PINTERRUPTED | PSTOPPED)) && setintr &&
     601:     (!gointr || !eq(gointr, STRminus))) {
     602:     if ((jobflags & PSTOPPED) == 0)
     603:         pflush(pp);
     604:     pintr1(0);
     605:     /* NOTREACHED */
     606:     }
     607:     reason = 0;
     608:     fp = pp;
     609:     do {
     610:     if (fp->p_reason)
     611:         reason = fp->p_flags & (PSIGNALED | PINTERRUPTED) ?
     612:         fp->p_reason | META : fp->p_reason;
     613:     } while ((fp = fp->p_friends) != pp);
     614:     if ((reason != 0) && (adrof(STRprintexitvalue)))    /* PWP */
     615:     xprintf("Exit %d\n", reason);
     616:     set(STRstatus, putn(reason));
     617:     if (reason && exiterr)
     618:     exitstat();
     619:     pflush(pp);
     620:     /* cwd_cmd(); *//* (PWP) this is what pre_cmd is for! */
     621: }
     622:
     623: /*
     624:  * dowait - wait for all processes to finish
     625:  */
     626: void
     627: dowait()
     628: {
     629:     register struct process *pp;
     630: #ifdef BSDSIGS
     631:     sigmask_t omask;
     632: #endif /* BSDSIGS */
     633:
     634:     pjobs++;
     635: #ifdef BSDSIGS
     636:     omask = sigblock(sigmask(SIGCHLD));
     637: loop:
     638: #else /* !BSDSIGS */
     639:     if (setintr)
     640:     (void) sigrelse(SIGINT);
     641: loop:
     642:     (void) sighold(SIGCHLD);
     643: #endif /* !BSDSIGS */
     644:     for (pp = proclist.p_next; pp; pp = pp->p_next)
     645:     if (pp->p_pid &&    /* pp->p_pid == pp->p_jobid && */
     646:         pp->p_flags & PRUNNING) {
     647: #ifdef BSDSIGS
     648:         (void) sigpause((sigmask_t) 0);
     649: #else /* !BSDSIGS */
     650:         (void) sigpause(SIGCHLD);
     651: #endif /* !BSDSIGS */
     652:         goto loop;
     653:     }
     654: #ifdef BSDSIGS
     655:     (void) sigsetmask(omask);
     656: #else /* !BSDSIGS */
     657:     (void) sigrelse(SIGCHLD);
     658: #endif /* !BSDSIGS */
     659:     pjobs = 0;
     660: }
     661:
     662: /*
     663:  * pflushall - flush all jobs from list (e.g. at fork())
     664:  */
     665: static void
     666: pflushall()
     667: {
     668:     register struct process *pp;
     669:
     670:     for (pp = proclist.p_next; pp != PNULL; pp = pp->p_next)
     671:     if (pp->p_pid)
     672:         pflush(pp);
     673: }
     674:
     675: /*
     676:  * pflush - flag all process structures in the same job as the
     677:  *	the argument process for deletion.  The actual free of the
     678:  *	space is not done here since pflush is called at interrupt level.
     679:  */
     680: static void
     681: pflush(pp)
     682:     register struct process *pp;
     683: {
     684:     register struct process *np;
     685:     register int idx;
     686:
     687:     if (pp->p_pid == 0) {
     688:     xprintf("BUG: process flushed twice");
     689:     return;
     690:     }
     691:     while (pp->p_pid != pp->p_jobid)
     692:     pp = pp->p_friends;
     693:     pclrcurr(pp);
     694:     if (pp == pcurrjob)
     695:     pcurrjob = 0;
     696:     idx = pp->p_index;
     697:     np = pp;
     698:     do {
     699:     np->p_index = np->p_pid = 0;
     700:     np->p_flags &= ~PNEEDNOTE;
     701:     } while ((np = np->p_friends) != pp);
     702:     if (idx == pmaxindex) {
     703:     for (np = proclist.p_next, idx = 0; np; np = np->p_next)
     704:         if (np->p_index > idx)
     705:         idx = np->p_index;
     706:     pmaxindex = idx;
     707:     }
     708: }
     709:
     710: /*
     711:  * pclrcurr - make sure the given job is not the current or previous job;
     712:  *	pp MUST be the job leader
     713:  */
     714: static void
     715: pclrcurr(pp)
     716:     register struct process *pp;
     717: {
     718:     if (pp == pcurrent)
     719:     if (pprevious != PNULL) {
     720:         pcurrent = pprevious;
     721:         pprevious = pgetcurr(pp);
     722:     }
     723:     else {
     724:         pcurrent = pgetcurr(pp);
     725:         pprevious = pgetcurr(pp);
     726:     }
     727:     else if (pp == pprevious)
     728:     pprevious = pgetcurr(pp);
     729: }
     730:
     731: /* +4 here is 1 for '\0', 1 ea for << >& >> */
     732: static Char command[PMAXLEN + 4];
     733: static int cmdlen;
     734: static Char *cmdp;
     735:
     736: /*
     737:  * palloc - allocate a process structure and fill it up.
     738:  *	an important assumption is made that the process is running.
     739:  */
     740: void
     741: palloc(pid, t)
     742:     int     pid;
     743:     register struct command *t;
     744: {
     745:     register struct process *pp;
     746:     int     i;
     747:
     748:     pp = (struct process *) xcalloc(1, (size_t) sizeof(struct process));
     749:     pp->p_pid = pid;
     750:     pp->p_flags = t->t_dflg & F_AMPERSAND ? PRUNNING : PRUNNING | PFOREGND;
     751:     if (t->t_dflg & F_TIME)
     752:     pp->p_flags |= PPTIME;
     753:     cmdp = command;
     754:     cmdlen = 0;
     755:     padd(t);
     756:     *cmdp++ = 0;
     757:     if (t->t_dflg & F_PIPEOUT) {
     758:     pp->p_flags |= PPOU;
     759:     if (t->t_dflg & F_STDERR)
     760:         pp->p_flags |= PDIAG;
     761:     }
     762:     pp->p_command = Strsave(command);
     763:     if (pcurrjob) {
     764:     struct process *fp;
     765:
     766:     /* careful here with interrupt level */
     767:     pp->p_cwd = 0;
     768:     pp->p_index = pcurrjob->p_index;
     769:     pp->p_friends = pcurrjob;
     770:     pp->p_jobid = pcurrjob->p_pid;
     771:     for (fp = pcurrjob; fp->p_friends != pcurrjob; fp = fp->p_friends);
     772:     fp->p_friends = pp;
     773:     }
     774:     else {
     775:     pcurrjob = pp;
     776:     pp->p_jobid = pid;
     777:     pp->p_friends = pp;
     778:     pp->p_cwd = dcwd;
     779:     dcwd->di_count++;
     780:     if (pmaxindex < BIGINDEX)
     781:         pp->p_index = ++pmaxindex;
     782:     else {
     783:         struct process *np;
     784:
     785:         for (i = 1;; i++) {
     786:         for (np = proclist.p_next; np; np = np->p_next)
     787:             if (np->p_index == i)
     788:             goto tryagain;
     789:         pp->p_index = i;
     790:         if (i > pmaxindex)
     791:             pmaxindex = i;
     792:         break;
     793:     tryagain:;
     794:         }
     795:     }
     796:     if (pcurrent == PNULL)
     797:         pcurrent = pp;
     798:     else if (pprevious == PNULL)
     799:         pprevious = pp;
     800:     }
     801:     pp->p_next = proclist.p_next;
     802:     proclist.p_next = pp;
     803: #ifdef BSDTIMES
     804:     (void) gettimeofday(&pp->p_btime, NULL);
     805: #else /* !BSDTIMES */
     806: # ifdef _SEQUENT_
     807:     (void) get_pro_stats(&pp->p_btime, PS_SELF, NULL, NULL);
     808: # else /* !_SEQUENT_ */
     809:     {
     810:     struct tms tmptimes;
     811:
     812:     pp->p_btime = times(&tmptimes);
     813:     }
     814: # endif /* !_SEQUENT_ */
     815: #endif /* !BSDTIMES */
     816: }
     817:
     818: static void
     819: padd(t)
     820:     register struct command *t;
     821: {
     822:     Char  **argp;
     823:
     824:     if (t == 0)
     825:     return;
     826:     switch (t->t_dtyp) {
     827:
     828:     case NODE_PAREN:
     829:     pads(STRL_parensp);
     830:     padd(t->t_dspr);
     831:     pads(STRspRparen);
     832:     break;
     833:
     834:     case NODE_COMMAND:
     835:     for (argp = t->t_dcom; *argp; argp++) {
     836:         pads(*argp);
     837:         if (argp[1])
     838:         pads(STRspace);
     839:     }
     840:     break;
     841:
     842:     case NODE_OR:
     843:     case NODE_AND:
     844:     case NODE_PIPE:
     845:     case NODE_LIST:
     846:     padd(t->t_dcar);
     847:     switch (t->t_dtyp) {
     848:     case NODE_OR:
     849:         pads(STRsP2sp);
     850:         break;
     851:     case NODE_AND:
     852:         pads(STRspand2sp);
     853:         break;
     854:     case NODE_PIPE:
     855:         pads(STRsPsp);
     856:         break;
     857:     case NODE_LIST:
     858:         pads(STRsmsp);
     859:         break;
     860:     }
     861:     padd(t->t_dcdr);
     862:     return;
     863:     }
     864:     if ((t->t_dflg & F_PIPEIN) == 0 && t->t_dlef) {
     865:     pads((t->t_dflg & F_READ) ? STRspL_arrow2sp : STRspLarrowsp);
     866:     pads(t->t_dlef);
     867:     }
     868:     if ((t->t_dflg & F_PIPEOUT) == 0 && t->t_drit) {
     869:     pads((t->t_dflg & F_APPEND) ? STRspR_arrow2 : STRspRarrow);
     870:     if (t->t_dflg & F_STDERR)
     871:         pads(STRand);
     872:     pads(STRspace);
     873:     pads(t->t_drit);
     874:     }
     875: }
     876:
     877: static void
     878: pads(cp)
     879:     Char   *cp;
     880: {
     881:     register int i;
     882:
     883:     /*
     884:      * Avoid the Quoted Space alias hack! Reported by:
     885:      * sam@john-bigboote.ICS.UCI.EDU (Sam Horrocks)
     886:      */
     887:     if (cp[0] == STRQNULL[0])
     888:     cp++;
     889:
     890:     i = Strlen(cp);
     891:
     892:     if (cmdlen >= PMAXLEN)
     893:     return;
     894:     if (cmdlen + i >= PMAXLEN) {
     895:     (void) Strcpy(cmdp, STRsp3dots);
     896:     cmdlen = PMAXLEN;
     897:     cmdp += 4;
     898:     return;
     899:     }
     900:     (void) Strcpy(cmdp, cp);
     901:     cmdp += i;
     902:     cmdlen += i;
     903: }
     904:
     905: /*
     906:  * psavejob - temporarily save the current job on a one level stack
     907:  *	so another job can be created.  Used for { } in exp6
     908:  *	and `` in globbing.
     909:  */
     910: void
     911: psavejob()
     912: {
     913:     pholdjob = pcurrjob;
     914:     pcurrjob = PNULL;
     915: }
     916:
     917: /*
     918:  * prestjob - opposite of psavejob.  This may be missed if we are interrupted
     919:  *	somewhere, but pendjob cleans up anyway.
     920:  */
     921: void
     922: prestjob()
     923: {
     924:     pcurrjob = pholdjob;
     925:     pholdjob = PNULL;
     926: }
     927:
     928: /*
     929:  * pendjob - indicate that a job (set of commands) has been completed
     930:  *	or is about to begin.
     931:  */
     932: void
     933: pendjob()
     934: {
     935:     register struct process *pp, *tp;
     936:
     937:     if (pcurrjob && (pcurrjob->p_flags & (PFOREGND | PSTOPPED)) == 0) {
     938:     pp = pcurrjob;
     939:     while (pp->p_pid != pp->p_jobid)
     940:         pp = pp->p_friends;
     941:     xprintf("[%d]", pp->p_index);
     942:     tp = pp;
     943:     do {
     944:         xprintf(" %d", pp->p_pid);
     945:         pp = pp->p_friends;
     946:     } while (pp != tp);
     947:     xprintf("\n");
     948:     }
     949:     pholdjob = pcurrjob = 0;
     950: }
     951:
     952: /*
     953:  * pprint - print a job
     954:  */
     955: static int
     956: pprint(pp, flag)
     957:     register struct process *pp;
     958:     bool    flag;
     959: {
     960:     register status, reason;
     961:     struct process *tp;
     962:     extern char *linp, linbuf[];
     963:     int     jobflags, pstatus;
     964:     char   *format;
     965:
     966:     while (pp->p_pid != pp->p_jobid)
     967:     pp = pp->p_friends;
     968:     if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
     969:     pp->p_flags &= ~PPTIME;
     970:     pp->p_flags |= PTIME;
     971:     }
     972:     tp = pp;
     973:     status = reason = -1;
     974:     jobflags = 0;
     975:     do {
     976:     jobflags |= pp->p_flags;
     977:     pstatus = pp->p_flags & PALLSTATES;
     978:     if (tp != pp && linp != linbuf && !(flag & FANCY) &&
     979:         (pstatus == status && pp->p_reason == reason ||
     980:          !(flag & REASON)))
     981:         xprintf(" ");
     982:     else {
     983:         if (tp != pp && linp != linbuf)
     984:         xprintf("\n");
     985:         if (flag & NUMBER)
     986:         if (pp == tp)
     987:             xprintf("[%d]%s %c ", pp->p_index,
     988:                 pp->p_index < 10 ? " " : "",
     989:                 pp == pcurrent ? '+' :
     990:                 (pp == pprevious ? '-' : ' '));
     991:         else
     992:             xprintf("       ");
     993:         if (flag & FANCY) {
     994: #ifdef TCF
     995:         extern char *sitename();
     996:
     997: #endif /* TCF */
     998:         xprintf("%5d ", pp->p_pid);
     999: #ifdef TCF
    1000:         xprintf("%11s ", sitename(pp->p_pid));
    1001: #endif /* TCF */
    1002:         }
    1003:         if (flag & (REASON | AREASON)) {
    1004:         if (flag & NAME)
    1005: #ifdef SUSPENDED
    1006:             format = "%-23s";
    1007: #else /* !SUSPENDED */
    1008:             format = "%-21s";
    1009: #endif /* !SUSPENDED */
    1010:         else
    1011:             format = "%s";
    1012:         if (pstatus == status)
    1013:             if (pp->p_reason == reason) {
    1014:             xprintf(format, "");
    1015:             goto prcomd;
    1016:             }
    1017:             else
    1018:             reason = pp->p_reason;
    1019:         else {
    1020:             status = pstatus;
    1021:             reason = pp->p_reason;
    1022:         }
    1023:         switch (status) {
    1024:
    1025:         case PRUNNING:
    1026:             xprintf(format, "Running ");
    1027:             break;
    1028:
    1029:         case PINTERRUPTED:
    1030:         case PSTOPPED:
    1031:         case PSIGNALED:
    1032:             /*
    1033: 		     * tell what happened to the background job
    1034: 		     * From: Michael Schroeder
    1035: 		     * <mlschroe@immd4.informatik.uni-erlangen.de>
    1036: 		     */
    1037:             if ((flag & REASON)
    1038:             || ((flag & AREASON)
    1039:                 && reason != SIGINT
    1040:                 && (reason != SIGPIPE
    1041:                 || (pp->p_flags & PPOU) == 0)))
    1042:             xprintf(format, mesg[pp->p_reason].pname);
    1043:             else
    1044:             reason = -1;
    1045:             break;
    1046:
    1047:         case PNEXITED:
    1048:         case PAEXITED:
    1049:             if (flag & REASON)
    1050:             if (pp->p_reason)
    1051: #ifdef SUSPENDED
    1052:                 xprintf("Exit %-18d", pp->p_reason);
    1053: #else /* SUSPENDED */
    1054:                 xprintf("Exit %-16d", pp->p_reason);
    1055: #endif /* SUSPENDED */
    1056:             else
    1057:                 xprintf(format, "Done");
    1058:             break;
    1059:
    1060:         default:
    1061:             xprintf("BUG: status=%-9o", status);
    1062:         }
    1063:         }
    1064:     }
    1065: prcomd:
    1066:     if (flag & NAME) {
    1067:         xprintf("%s", short2str(pp->p_command));
    1068:         if (pp->p_flags & PPOU)
    1069:         xprintf(" |");
    1070:         if (pp->p_flags & PDIAG)
    1071:         xprintf("&");
    1072:     }
    1073:     if (flag & (REASON | AREASON) && pp->p_flags & PDUMPED)
    1074:         xprintf(" (core dumped)");
    1075:     if (tp == pp->p_friends) {
    1076:         if (flag & AMPERSAND)
    1077:         xprintf(" &");
    1078:         if (flag & JOBDIR &&
    1079:         !eq(tp->p_cwd->di_name, dcwd->di_name)) {
    1080:         xprintf(" (wd: ");
    1081:         dtildepr(value(STRhome), tp->p_cwd->di_name);
    1082:         xprintf(")");
    1083:         }
    1084:     }
    1085:     if (pp->p_flags & PPTIME && !(status & (PSTOPPED | PRUNNING))) {
    1086:         if (linp != linbuf)
    1087:         xprintf("\n\t");
    1088: #if defined(BSDTIMES) || defined(_SEQUENT_)
    1089:         prusage(&zru, &pp->p_rusage, &pp->p_etime,
    1090:             &pp->p_btime);
    1091: #else /* !BSDTIMES && !SEQUENT */
    1092:         lru.tms_utime = pp->p_utime;
    1093:         lru.tms_stime = pp->p_stime;
    1094:         lru.tms_cutime = 0;
    1095:         lru.tms_cstime = 0;
    1096:         prusage(&zru, &lru, pp->p_etime,
    1097:             pp->p_btime);
    1098: #endif /* !BSDTIMES && !SEQUENT */
    1099:
    1100:     }
    1101:     if (tp == pp->p_friends) {
    1102:         if (linp != linbuf)
    1103:         xprintf("\n");
    1104:         if (flag & SHELLDIR && !eq(tp->p_cwd->di_name, dcwd->di_name)) {
    1105:         xprintf("(wd now: ");
    1106:         dtildepr(value(STRhome), dcwd->di_name);
    1107:         xprintf(")\n");
    1108:         }
    1109:     }
    1110:     } while ((pp = pp->p_friends) != tp);
    1111:     if (jobflags & PTIME && (jobflags & (PSTOPPED | PRUNNING)) == 0) {
    1112:     if (jobflags & NUMBER)
    1113:         xprintf("       ");
    1114:     ptprint(tp);
    1115:     }
    1116:     return (jobflags);
    1117: }
    1118:
    1119: static void
    1120: ptprint(tp)
    1121:     register struct process *tp;
    1122: {
    1123: #ifdef BSDTIMES
    1124:     struct timeval tetime, diff;
    1125:     static struct timeval ztime;
    1126:     struct rusage ru;
    1127:     static struct rusage zru;
    1128:     register struct process *pp = tp;
    1129:
    1130:     ru = zru;
    1131:     tetime = ztime;
    1132:     do {
    1133:     ruadd(&ru, &pp->p_rusage);
    1134:     tvsub(&diff, &pp->p_etime, &pp->p_btime);
    1135:     if (timercmp(&diff, &tetime, >))
    1136:         tetime = diff;
    1137:     } while ((pp = pp->p_friends) != tp);
    1138:     prusage(&zru, &ru, &tetime, &ztime);
    1139: #else /* !BSDTIMES */
    1140: # ifdef _SEQUENT_
    1141: #  define timercmp(tvp, uvp, cmp) \
    1142:       ((tvp)->tv_sec cmp (uvp)->tv_sec || \
    1143:        (tvp)->tv_sec == (uvp)->tv_sec && (tvp)->tv_usec cmp (uvp)->tv_usec)
    1144:     tmval_t tetime, diff;
    1145:     static tmval_t ztime;
    1146:     struct pro_stats ru;
    1147:     static struct pro_stats zru;
    1148:     register struct process *pp = tp;
    1149:
    1150:     ru = zru;
    1151:     tetime = ztime;
    1152:     do {
    1153:     ruadd(&ru, &pp->p_rusage);
    1154:     tvsub(&diff, &pp->p_etime, &pp->p_btime);
    1155:     if (timercmp(&diff, &tetime, >))
    1156:         tetime = diff;
    1157:     } while ((pp = pp->p_friends) != tp);
    1158:     prusage(&zru, &ru, &tetime, &ztime);
    1159: # else /* !_SEQUENT_ */
    1160: #  ifndef POSIX
    1161:     static time_t ztime = 0;
    1162:     static time_t zu_time = 0;
    1163:     static time_t zs_time = 0;
    1164:     time_t  tetime, diff;
    1165:     time_t  u_time, s_time;
    1166:
    1167: #  else /* POSIX */
    1168:     static clock_t ztime = 0;
    1169:     static clock_t zu_time = 0;
    1170:     static clock_t zs_time = 0;
    1171:     clock_t tetime, diff;
    1172:     clock_t u_time, s_time;
    1173:
    1174: #  endif /* POSIX */
    1175:     struct tms zts, rts;
    1176:     register struct process *pp = tp;
    1177:
    1178:     u_time = zu_time;
    1179:     s_time = zs_time;
    1180:     tetime = ztime;
    1181:     do {
    1182:     u_time += pp->p_utime;
    1183:     s_time += pp->p_stime;
    1184:     diff = pp->p_etime - pp->p_btime;
    1185:     if (diff > tetime)
    1186:         tetime = diff;
    1187:     } while ((pp = pp->p_friends) != tp);
    1188:     zts.tms_utime = zu_time;
    1189:     zts.tms_stime = zs_time;
    1190:     zts.tms_cutime = 0;
    1191:     zts.tms_cstime = 0;
    1192:     rts.tms_utime = u_time;
    1193:     rts.tms_stime = s_time;
    1194:     rts.tms_cutime = 0;
    1195:     rts.tms_cstime = 0;
    1196:     prusage(&zts, &rts, tetime, ztime);
    1197: # endif /* !_SEQUENT_ */
    1198: #endif	/* !BSDTIMES */
    1199: }
    1200:
    1201: /*
    1202:  * dojobs - print all jobs
    1203:  */
    1204: void
    1205: dojobs(v)
    1206:     Char  **v;
    1207: {
    1208:     register struct process *pp;
    1209:     register int flag = NUMBER | NAME | REASON;
    1210:     int     i;
    1211:
    1212:     if (chkstop)
    1213:     chkstop = 2;
    1214:     if (*++v) {
    1215:     if (v[1] || !eq(*v, STRml))
    1216:         stderror(ERR_JOBS);
    1217:     flag |= FANCY | JOBDIR;
    1218:     }
    1219:     for (i = 1; i <= pmaxindex; i++)
    1220:     for (pp = proclist.p_next; pp; pp = pp->p_next)
    1221:         if (pp->p_index == i && pp->p_pid == pp->p_jobid) {
    1222:         pp->p_flags &= ~PNEEDNOTE;
    1223:         if (!(pprint(pp, flag) & (PRUNNING | PSTOPPED)))
    1224:             pflush(pp);
    1225:         break;
    1226:         }
    1227: }
    1228:
    1229: /*
    1230:  * dofg - builtin - put the job into the foreground
    1231:  */
    1232: void
    1233: dofg(v)
    1234:     Char  **v;
    1235: {
    1236:     register struct process *pp;
    1237:
    1238:     okpcntl();
    1239:     ++v;
    1240:     do {
    1241:     pp = pfind(*v);
    1242:     pstart(pp, 1);
    1243: #ifndef BSDSIGS
    1244: # ifdef notdef
    1245:     if (setintr)
    1246:         sigignore(SIGINT);
    1247: # endif
    1248: #endif /* !BSDSIGS */
    1249:     pjwait(pp);
    1250:     } while (*v && *++v);
    1251: }
    1252:
    1253: /*
    1254:  * %... - builtin - put the job into the foreground
    1255:  */
    1256: void
    1257: dofg1(v)
    1258:     Char  **v;
    1259: {
    1260:     register struct process *pp;
    1261:
    1262:     okpcntl();
    1263:     pp = pfind(v[0]);
    1264:     pstart(pp, 1);
    1265: #ifndef BSDSIGS
    1266: # ifdef notdef
    1267:     if (setintr)
    1268:     sigignore(SIGINT);
    1269: # endif
    1270: #endif /* !BSDSIGS */
    1271:     pjwait(pp);
    1272: }
    1273:
    1274: /*
    1275:  * dobg - builtin - put the job into the background
    1276:  */
    1277: void
    1278: dobg(v)
    1279:     Char  **v;
    1280: {
    1281:     register struct process *pp;
    1282:
    1283:     okpcntl();
    1284:     ++v;
    1285:     do {
    1286:     pp = pfind(*v);
    1287:     pstart(pp, 0);
    1288:     } while (*v && *++v);
    1289: }
    1290:
    1291: /*
    1292:  * %... & - builtin - put the job into the background
    1293:  */
    1294: void
    1295: dobg1(v)
    1296:     Char  **v;
    1297: {
    1298:     register struct process *pp;
    1299:
    1300:     pp = pfind(v[0]);
    1301:     pstart(pp, 0);
    1302: }
    1303:
    1304: /*
    1305:  * dostop - builtin - stop the job
    1306:  */
    1307: void
    1308: dostop(v)
    1309:     Char  **v;
    1310: {
    1311: #ifdef BSDJOBS
    1312:     pkill(++v, SIGSTOP);
    1313: #endif /* BSDJOBS */
    1314: }
    1315:
    1316: /*
    1317:  * dokill - builtin - superset of kill (1)
    1318:  */
    1319: void
    1320: dokill(v)
    1321:     Char  **v;
    1322: {
    1323:     register int signum, len = 0;
    1324:     register char *name;
    1325:     extern int T_Cols;
    1326:
    1327:     v++;
    1328:     if (v[0] && v[0][0] == '-') {
    1329:     if (v[0][1] == 'l') {
    1330:         for (signum = 1; signum <= NSIG; signum++) {
    1331:         if ((name = mesg[signum].iname) != NULL) {
    1332:             len += strlen(name) + 1;
    1333:             if (len >= T_Cols - 1) {
    1334:             xprintf("\n");
    1335:             len = strlen(name) + 1;
    1336:             }
    1337:             xprintf("%s ", name);
    1338:         }
    1339:         }
    1340:         xprintf("\n");
    1341:         return;
    1342:     }
    1343:     if (Isdigit(v[0][1])) {
    1344:         signum = atoi(short2str(v[0] + 1));
    1345:         if (signum < 0 || signum > NSIG)
    1346:         stderror(ERR_NAME | ERR_BADSIG);
    1347:     }
    1348:     else {
    1349:         for (signum = 1; signum <= NSIG; signum++)
    1350:         if (mesg[signum].iname &&
    1351:             eq(&v[0][1], str2short(mesg[signum].iname)))
    1352:             goto gotsig;
    1353:         setname(short2str(&v[0][1]));
    1354:         stderror(ERR_NAME | ERR_UNKSIG);
    1355:     }
    1356: gotsig:
    1357:     v++;
    1358:     }
    1359:     else
    1360:     signum = SIGTERM;
    1361:     pkill(v, signum);
    1362: }
    1363:
    1364: static void
    1365: pkill(v, signum)
    1366:     Char  **v;
    1367:     int     signum;
    1368: {
    1369:     register struct process *pp, *np;
    1370:     register int jobflags = 0;
    1371:     int     pid, err1 = 0;
    1372: #ifdef BSDSIGS
    1373:     sigmask_t omask;
    1374: #endif /* BSDSIGS */
    1375:     Char   *cp;
    1376:
    1377: #ifdef BSDSIGS
    1378:     omask = sigmask(SIGCHLD);
    1379:     if (setintr)
    1380:     omask |= sigmask(SIGINT);
    1381:     omask = sigblock(omask) & ~omask;
    1382: #else /* !BSDSIGS */
    1383:     if (setintr)
    1384:     (void) sighold(SIGINT);
    1385:     (void) sighold(SIGCHLD);
    1386: #endif /* !BSDSIGS */
    1387:     gflag = 0, tglob(v);
    1388:     if (gflag) {
    1389:     v = globall(v);
    1390:     if (v == 0)
    1391:         stderror(ERR_NAME | ERR_NOMATCH);
    1392:     }
    1393:     else {
    1394:     v = gargv = saveblk(v);
    1395:     trim(v);
    1396:     }
    1397:
    1398:     while (v && (cp = *v)) {
    1399:     if (*cp == '%') {
    1400:         np = pp = pfind(cp);
    1401:         do
    1402:         jobflags |= np->p_flags;
    1403:         while ((np = np->p_friends) != pp);
    1404: #ifdef BSDJOBS
    1405:         switch (signum) {
    1406:
    1407:         case SIGSTOP:
    1408:         case SIGTSTP:
    1409:         case SIGTTIN:
    1410:         case SIGTTOU:
    1411:         if ((jobflags & PRUNNING) == 0) {
    1412: # ifdef SUSPENDED
    1413:             xprintf("%s: Already suspended\n",
    1414:                 short2str(cp));
    1415: # else /* !SUSPENDED */
    1416:             xprintf("%s: Already stopped\n",
    1417:                 short2str(cp));
    1418: # endif /* !SUSPENDED */
    1419:             err1++;
    1420:             goto cont;
    1421:         }
    1422:         break;
    1423:         /*
    1424: 		 * suspend a process, kill -CONT %, then type jobs; the shell
    1425: 		 * says it is suspended, but it is running; thanks jaap..
    1426: 		 */
    1427:         case SIGCONT:
    1428:         pstart(pp, 0);
    1429:         goto cont;
    1430:         }
    1431: #endif /* BSDJOBS */
    1432:         if (killpg((pid_t) pp->p_jobid, signum) < 0) {
    1433:         xprintf("%s: %s\n", short2str(cp), strerror(errno));
    1434:         err1++;
    1435:         }
    1436: #ifdef BSDJOBS
    1437:         if (signum == SIGTERM || signum == SIGHUP)
    1438:         (void) killpg((pid_t) pp->p_jobid, SIGCONT);
    1439: #endif /* BSDJOBS */
    1440:     }
    1441:     else if (!(Isdigit(*cp) || *cp == '-'))
    1442:         stderror(ERR_NAME | ERR_JOBARGS);
    1443:     else {
    1444:         pid = atoi(short2str(cp));
    1445:         if (kill((pid_t) pid, signum) < 0) {
    1446:         xprintf("%d: %s\n", pid, strerror(errno));
    1447:         err1++;
    1448:         goto cont;
    1449:         }
    1450: #ifdef BSDJOBS
    1451:         if (signum == SIGTERM || signum == SIGHUP)
    1452:         (void) kill((pid_t) pid, SIGCONT);
    1453: #endif /* BSDJOBS */
    1454:     }
    1455: cont:
    1456:     v++;
    1457:     }
    1458:     if (gargv)
    1459:     blkfree(gargv), gargv = 0;
    1460: #ifdef BSDSIGS
    1461:     (void) sigsetmask(omask);
    1462: #else /* !BSDSIGS */
    1463:     (void) sigrelse(SIGCHLD);
    1464:     if (setintr)
    1465:     (void) sigrelse(SIGINT);
    1466: #endif /* !BSDSIGS */
    1467:     if (err1)
    1468:     stderror(ERR_SILENT);
    1469: }
    1470:
    1471: /*
    1472:  * pstart - start the job in foreground/background
    1473:  */
    1474: void
    1475: pstart(pp, foregnd)
    1476:     register struct process *pp;
    1477:     int     foregnd;
    1478: {
    1479:     register struct process *np;
    1480: #ifdef BSDSIGS
    1481:     sigmask_t omask;
    1482: #endif /* BSDSIGS */
    1483:     long    jobflags = 0;
    1484:
    1485: #ifdef BSDSIGS
    1486:     omask = sigblock(sigmask(SIGCHLD));
    1487: #else /* !BSDSIGS */
    1488:     (void) sighold(SIGCHLD);
    1489: #endif
    1490:     np = pp;
    1491:     do {
    1492:     jobflags |= np->p_flags;
    1493:     if (np->p_flags & (PRUNNING | PSTOPPED)) {
    1494:         np->p_flags |= PRUNNING;
    1495:         np->p_flags &= ~PSTOPPED;
    1496:         if (foregnd)
    1497:         np->p_flags |= PFOREGND;
    1498:         else
    1499:         np->p_flags &= ~PFOREGND;
    1500:     }
    1501:     } while ((np = np->p_friends) != pp);
    1502:     if (!foregnd)
    1503:     pclrcurr(pp);
    1504:     (void) pprint(pp, foregnd ? NAME | JOBDIR : NUMBER | NAME | AMPERSAND);
    1505: #ifdef BSDJOBS
    1506:     if (foregnd)
    1507:     (void) tcsetpgrp(FSHTTY, pp->p_jobid);
    1508:     if (jobflags & PSTOPPED)
    1509:     (void) killpg((pid_t) pp->p_jobid, SIGCONT);
    1510: #endif /* BSDJOBS */
    1511: #ifdef BSDSIGS
    1512:     (void) sigsetmask(omask);
    1513: #else /* !BSDSIGS */
    1514:     (void) sigrelse(SIGCHLD);
    1515: #endif /* !BSDSIGS */
    1516: }
    1517:
    1518: void
    1519: panystop(neednl)
    1520:     bool    neednl;
    1521: {
    1522:     register struct process *pp;
    1523:
    1524:     chkstop = 2;
    1525:     for (pp = proclist.p_next; pp; pp = pp->p_next)
    1526:     if (pp->p_flags & PSTOPPED)
    1527:         stderror(ERR_STOPPED, neednl ? "\n" : "");
    1528: }
    1529:
    1530: struct process *
    1531: pfind(cp)
    1532:     Char   *cp;
    1533: {
    1534:     register struct process *pp, *np;
    1535:
    1536:     if (cp == 0 || cp[1] == 0 || eq(cp, STRc_2) || eq(cp, STRc_plus)) {
    1537:     if (pcurrent == PNULL)
    1538:         stderror(ERR_NAME | ERR_JOBCUR);
    1539:     return (pcurrent);
    1540:     }
    1541:     if (eq(cp, STRc_minus) || eq(cp, STRc_hash)) {
    1542:     if (pprevious == PNULL)
    1543:         stderror(ERR_NAME | ERR_JOBPREV);
    1544:     return (pprevious);
    1545:     }
    1546:     if (Isdigit(cp[1])) {
    1547:     int     idx = atoi(short2str(cp + 1));
    1548:
    1549:     for (pp = proclist.p_next; pp; pp = pp->p_next)
    1550:         if (pp->p_index == idx && pp->p_pid == pp->p_jobid)
    1551:         return (pp);
    1552:     stderror(ERR_NAME | ERR_NOSUCHJOB);
    1553:     }
    1554:     np = PNULL;
    1555:     for (pp = proclist.p_next; pp; pp = pp->p_next)
    1556:     if (pp->p_pid == pp->p_jobid) {
    1557:         if (cp[1] == '?') {
    1558:         register Char *dp;
    1559:
    1560:         for (dp = pp->p_command; *dp; dp++) {
    1561:             if (*dp != cp[2])
    1562:             continue;
    1563:             if (prefix(cp + 2, dp))
    1564:             goto match;
    1565:         }
    1566:         }
    1567:         else if (prefix(cp + 1, pp->p_command)) {
    1568:     match:
    1569:         if (np)
    1570:             stderror(ERR_NAME | ERR_AMBIG);
    1571:         np = pp;
    1572:         }
    1573:     }
    1574:     if (np)
    1575:     return (np);
    1576:     stderror(ERR_NAME | cp[1] == '?' ? ERR_JOBPAT : ERR_NOSUCHJOB);
    1577:     /* NOTREACHED */
    1578:     return (0);
    1579: }
    1580:
    1581:
    1582: /*
    1583:  * pgetcurr - find most recent job that is not pp, preferably stopped
    1584:  */
    1585: static struct process *
    1586: pgetcurr(pp)
    1587:     register struct process *pp;
    1588: {
    1589:     register struct process *np;
    1590:     register struct process *xp = PNULL;
    1591:
    1592:     for (np = proclist.p_next; np; np = np->p_next)
    1593:     if (np != pcurrent && np != pp && np->p_pid &&
    1594:         np->p_pid == np->p_jobid) {
    1595:         if (np->p_flags & PSTOPPED)
    1596:         return (np);
    1597:         if (xp == PNULL)
    1598:         xp = np;
    1599:     }
    1600:     return (xp);
    1601: }
    1602:
    1603: /*
    1604:  * donotify - flag the job so as to report termination asynchronously
    1605:  */
    1606: void
    1607: donotify(v)
    1608:     Char  **v;
    1609: {
    1610:     register struct process *pp;
    1611:
    1612:     pp = pfind(*++v);
    1613:     pp->p_flags |= PNOTIFY;
    1614: }
    1615:
    1616: /*
    1617:  * Do the fork and whatever should be done in the child side that
    1618:  * should not be done if we are not forking at all (like for simple builtin's)
    1619:  * Also do everything that needs any signals fiddled with in the parent side
    1620:  *
    1621:  * Wanttty tells whether process and/or tty pgrps are to be manipulated:
    1622:  *	-1:	leave tty alone; inherit pgrp from parent
    1623:  *	 0:	already have tty; manipulate process pgrps only
    1624:  *	 1:	want to claim tty; manipulate process and tty pgrps
    1625:  * It is usually just the value of tpgrp.
    1626:  */
    1627:
    1628: int
    1629: pfork(t, wanttty)
    1630:     struct command *t;      /* command we are forking for */
    1631:     int     wanttty;
    1632: {
    1633:     register int pid;
    1634:     bool    ignint = 0;
    1635:     int     pgrp;
    1636: #ifdef BSDSIGS
    1637:     sigmask_t omask;
    1638: #endif /* BSDSIGS */
    1639: #if SIGSYNCH
    1640:     sigvec_t osv;
    1641:     static sigvec_t nsv = {synch_handler, ~0, 0};
    1642: #endif /* SIGSYNCH */
    1643:
    1644:     /*
    1645:      * A child will be uninterruptible only under very special conditions.
    1646:      * Remember that the semantics of '&' is implemented by disconnecting the
    1647:      * process from the tty so signals do not need to ignored just for '&'.
    1648:      * Thus signals are set to default action for children unless: we have had
    1649:      * an "onintr -" (then specifically ignored) we are not playing with
    1650:      * signals (inherit action)
    1651:      */
    1652:     if (setintr)
    1653:     ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT))
    1654:         || (gointr && eq(gointr, STRminus));
    1655:     /*
    1656:      * Check for maximum nesting of 16 processes to avoid Forking loops
    1657:      */
    1658:     if (child == 16)
    1659:     stderror(ERR_NESTING, 16);
    1660:     /*
    1661:      * Hold SIGCHLD until we have the process installed in our table.
    1662:      */
    1663: #ifdef SIGSYNCH
    1664:     if (mysigvec(SIGSYNCH, &nsv, &osv))
    1665:     stderror(ERR_SYSTEM, "pfork: sigvec set", strerror(errno));
    1666: #endif /* SIGSYNCH */
    1667: #ifdef BSDSIGS
    1668:     omask = sigblock(sigmask(SIGCHLD));
    1669: #else /* !BSDSIGS */
    1670:     (void) sighold(SIGCHLD);
    1671: #endif /* !BSDSIGS */
    1672:     while ((pid = fork()) < 0)
    1673:     if (setintr == 0)
    1674:         (void) sleep(FORKSLEEP);
    1675:     else {
    1676: #ifdef BSDSIGS
    1677:         (void) sigsetmask(omask);
    1678: #else /* !BSDSIGS */
    1679:         (void) sigrelse(SIGINT);
    1680:         (void) sigrelse(SIGCHLD);
    1681: #endif /* !BSDSIGS */
    1682:         stderror(ERR_NOPROC);
    1683:     }
    1684:     if (pid == 0) {
    1685:     settimes();
    1686:     pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
    1687:     pflushall();
    1688:     pcurrjob = PNULL;
    1689: #if !defined(BSDTIMES) && !defined(_SEQUENT_)
    1690:     timesdone = 0;
    1691: #endif /* !defined(BSDTIMES) && !defined(_SEQUENT_) */
    1692:     child++;
    1693:     if (setintr) {
    1694:         setintr = 0;    /* until I think otherwise */
    1695: #ifndef BSDSIGS
    1696:         (void) sigrelse(SIGCHLD);
    1697: #endif /* !BSDSIGS */
    1698:         /*
    1699: 	     * Children just get blown away on SIGINT, SIGQUIT unless "onintr
    1700: 	     * -" seen.
    1701: 	     */
    1702:         (void) signal(SIGINT, ignint ? SIG_IGN : SIG_DFL);
    1703:         (void) signal(SIGQUIT, ignint ? SIG_IGN : SIG_DFL);
    1704: #ifdef BSDJOBS
    1705:         if (wanttty >= 0) {
    1706:         /* make stoppable */
    1707:         (void) signal(SIGTSTP, SIG_DFL);
    1708:         (void) signal(SIGTTIN, SIG_DFL);
    1709:         (void) signal(SIGTTOU, SIG_DFL);
    1710:         }
    1711: #endif /* BSDJOBS */
    1712:         (void) signal(SIGTERM, parterm);
    1713:     }
    1714:     else if (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) {
    1715:         (void) signal(SIGINT, SIG_IGN);
    1716:         (void) signal(SIGQUIT, SIG_IGN);
    1717:     }
    1718: #ifdef OREO
    1719:     sigignore(SIGIO);   /* ignore SIGIO in child too */
    1720: #endif /* OREO */
    1721:
    1722:     pgetty(wanttty, pgrp);
    1723:     /*
    1724: 	 * Nohup and nice apply only to NODE_COMMAND's but it would be nice
    1725: 	 * (?!?) if you could say "nohup (foo;bar)" Then the parser would have
    1726: 	 * to know about nice/nohup/time
    1727: 	 */
    1728:     if (t->t_dflg & F_NOHUP)
    1729:         (void) signal(SIGHUP, SIG_IGN);
    1730:     if (t->t_dflg & F_NICE)
    1731: #ifdef BSDNICE
    1732:         (void) setpriority(PRIO_PROCESS, 0, t->t_nice);
    1733: #else /* !BSDNICE */
    1734:         (void) nice(t->t_nice);
    1735: #endif /* !BSDNICE */
    1736: #ifdef F_VER
    1737:         if (t->t_dflg & F_VER) {
    1738:         Setenv(STRSYSTYPE, t->t_systype ? STRbsd43 : STRsys53);
    1739:         dohash();
    1740:     }
    1741: #endif /* F_VER */
    1742: #ifdef SIGSYNCH
    1743:     /* rfw 8/89 now parent can continue */
    1744:     if (kill(getppid(), SIGSYNCH))
    1745:         stderror(ERR_SYSTEM, "pfork child: kill", strerror(errno));
    1746: #endif /* SIGSYNCH */
    1747:
    1748:     }
    1749:     else {
    1750: #ifdef POSIXJOBS
    1751:     if (wanttty >= 0)
    1752:         (void) setpgid(pid, pcurrjob ? pcurrjob->p_jobid : pid);
    1753: #endif /* POSIXJOBS */
    1754:     palloc(pid, t);
    1755: #ifdef SIGSYNCH
    1756:     /*
    1757: 	 * rfw 8/89 Wait for child to own terminal.  Solves half of ugly
    1758: 	 * synchronization problem.  With this change, we know that the only
    1759: 	 * reason setpgrp to a previous process in a pipeline can fail is that
    1760: 	 * the previous process has already exited. Without this hack, he may
    1761: 	 * either have exited or not yet started to run.  Two uglies become
    1762: 	 * one.
    1763: 	 */
    1764:     sigpause(omask & ~SYNCHMASK);
    1765:     if (mysigvec(SIGSYNCH, &osv, NULL))
    1766:         stderror(ERR_SYSTEM, "pfork parent: sigvec restore",
    1767:              strerror(errno));
    1768: #endif /* SIGSYNCH */
    1769:
    1770: #ifdef BSDSIGS
    1771:     (void) sigsetmask(omask);
    1772: #else /* !BSDSIGS */
    1773:     (void) sigrelse(SIGCHLD);
    1774: #endif /* !BSDSIGS */
    1775:     }
    1776:     return (pid);
    1777: }
    1778:
    1779: static void
    1780: okpcntl()
    1781: {
    1782:     if (tpgrp == -1)
    1783:     stderror(ERR_JOBCONTROL);
    1784:     if (tpgrp == 0)
    1785:     stderror(ERR_JOBCTRLSUB);
    1786: }
    1787:
    1788: /*
    1789:  * if we don't have vfork(), things can still go in the wrong order
    1790:  * resulting in the famous 'Stopped (tty output)'. But some systems
    1791:  * don't permit the setpgid() call, (these are more recent secure
    1792:  * systems such as ibm's aix), when they do. Then we'd rather print
    1793:  * an error message than hang the shell!
    1794:  * I am open to suggestions how to fix that.
    1795:  */
    1796: void
    1797: pgetty(wanttty, pgrp)
    1798:     int     wanttty, pgrp;
    1799: {
    1800: #ifdef BSDJOBS
    1801: # if defined(BSDSIGS) && defined(POSIXJOBS)
    1802:     sigmask_t omask = 0;
    1803: # endif /* BSDSIGS && POSIXJOBS */
    1804:
    1805: # ifdef JOBDEBUG
    1806:     xprintf("wanttty %d\n", wanttty);
    1807: # endif
    1808:
    1809: # ifdef POSIXJOBS
    1810:     /*
    1811:      * christos: I am blocking the tty signals till I've set things
    1812:      * correctly....
    1813:      */
    1814:     if (wanttty > 0)
    1815: #  ifdef BSDSIGS
    1816:     omask = sigblock(sigmask(SIGTSTP)|sigmask(SIGTTIN)|sigmask(SIGTTOU));
    1817: #  else /* !BSDSIGS */
    1818:     {
    1819:     (void) sighold(SIGTSTP);
    1820:     (void) sighold(SIGTTIN);
    1821:     (void) sighold(SIGTTOU);
    1822:     }
    1823: #  endif /* !BSDSIGS */
    1824:
    1825:     /*
    1826:      * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de>
    1827:      * Don't check for tpgrp >= 0 so even non-interactive shells give
    1828:      * background jobs process groups Same for the comparison in the other part
    1829:      * of the #ifdef
    1830:      */
    1831:     if (wanttty >= 0)
    1832:     if (setpgid(0, pgrp) == -1) {
    1833:         xprintf("tcsh: setpgid error.\n");
    1834:         xexit(0);
    1835:     }
    1836: # endif /* POSIXJOBS */
    1837:
    1838:     if (wanttty > 0)
    1839:     (void) tcsetpgrp(FSHTTY, pgrp);
    1840:
    1841: # ifndef POSIXJOBS
    1842:     if (wanttty >= 0)
    1843:     if (setpgid(0, pgrp) == -1) {
    1844:         xprintf("tcsh: setpgid error.\n");
    1845:         xexit(0);
    1846:     }
    1847: # else /* POSIXJOBS */
    1848:     if (wanttty > 0)
    1849: #  ifdef BSDSIGS
    1850:     (void) sigsetmask(omask);
    1851: #  else /* BSDSIGS */
    1852:     {
    1853:     (void) sigrelse(SIGTSTP);
    1854:     (void) sigrelse(SIGTTIN);
    1855:     (void) sigrelse(SIGTTOU);
    1856:     }
    1857: #  endif /* !BSDSIGS */
    1858: # endif /* POSIXJOBS */
    1859:
    1860:     if (tpgrp > 0)
    1861:     tpgrp = 0;      /* gave tty away */
    1862: #endif /* BSDJOBS */
    1863: }

#### Defined functions

dobg defined in line 1277; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 56

dobg1 defined in line 1294; used 1 times

- in /usr/src/bin/tcsh/sh.func.c line 79

dofg defined in line 1232; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 79

dofg1 defined in line 1256; used 1 times

- in /usr/src/bin/tcsh/sh.func.c line 78

dojobs defined in line 1204; used 3 times

- in line 591
- in /usr/src/bin/tcsh/sh.init.c line 98
- in /usr/src/bin/tcsh/sh.proc.c line 591

dokill defined in line 1319; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 99

donotify defined in line 1606; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 116

dostop defined in line 1307; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 143

dowait defined in line 626; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 160

okpcntl defined in line 1779; used 3 times

- in line 1238, 1262, 1283

padd defined in line 818; used 4 times

- in line 755, 830, 846, 861

pads defined in line 877; used 14 times

- in line 829-838(4), 849-858(4), 865-873(6)

palloc defined in line 740; used 3 times

- in line 1754
- in /usr/src/bin/tcsh/sh.proc.c line 1754
- in /usr/src/bin/tcsh/sh.sem.c line 384

panystop defined in line 1518; used 5 times

- in /usr/src/bin/tcsh/sh.exec.c line 410
- in /usr/src/bin/tcsh/sh.func.c line 272, 285, 410
- in /usr/src/bin/tcsh/sh.lex.c line 1387

pchild defined in line 160; used 4 times

- in /usr/src/bin/tcsh/tc.sig.c line 186-190(2), 205, 214

pclrcurr defined in line 714; used 3 times

- in line 391, 693, 1503

pendjob defined in line 932; used 3 times

- in /usr/src/bin/tcsh/sh.sem.c line 557
- in /usr/src/bin/tcsh/tc.func.c line 457, 708

pfind defined in line 1530; used 13 times

- in line 1241, 1263, 1286, 1300, 1400, 1612
- in /usr/src/bin/tcsh/sh.proc.c line 1241, 1263, 1286, 1300, 1400, 1612
- in /usr/src/bin/tcsh/tc.os.c line 464

pflush defined in line 680; used 6 times

- in line 421, 465, 603, 619, 672, 1224

pflushall defined in line 665; used 1 times

- in line 1687

pfork defined in line 1628; used 3 times

- in /usr/src/bin/tcsh/sh.exp.c line 478
- in /usr/src/bin/tcsh/sh.glob.c line 671
- in /usr/src/bin/tcsh/sh.sem.c line 238

pgetcurr defined in line 1585; used 4 times

- in line 721-728(4)

pgetty defined in line 1796; used 4 times

- in line 1722
- in /usr/src/bin/tcsh/sh.proc.c line 1722
- in /usr/src/bin/tcsh/sh.sem.c line 450-452(2)

pjwait defined in line 522; used 7 times

- in line 514, 1249, 1271
- in /usr/src/bin/tcsh/sh.proc.c line 514, 1249, 1271
- in /usr/src/bin/tcsh/tc.func.c line 459

pkill defined in line 1364; used 2 times

- in line 1312, 1361

pnote defined in line 445; never used
pprint defined in line 955; used 7 times

- in line 419, 463, 592-598(3), 1223, 1504

prestjob defined in line 921; used 3 times

- in /usr/src/bin/tcsh/sh.exp.c line 484
- in /usr/src/bin/tcsh/sh.glob.c line 763
- in /usr/src/bin/tcsh/tc.func.c line 707

psavejob defined in line 910; used 3 times

- in /usr/src/bin/tcsh/sh.exp.c line 477
- in /usr/src/bin/tcsh/sh.glob.c line 663
- in /usr/src/bin/tcsh/tc.func.c line 671

pstart defined in line 1474; used 11 times

- in line 1242, 1264, 1287, 1301, 1428
- in /usr/src/bin/tcsh/sh.proc.c line 1242, 1264, 1287, 1301, 1428
- in /usr/src/bin/tcsh/tc.func.c line 458

ptprint defined in line 1119; used 2 times

- in line 409, 1114

pwait defined in line 479; used 3 times

- in /usr/src/bin/tcsh/sh.exp.c line 483
- in /usr/src/bin/tcsh/sh.glob.c line 762
- in /usr/src/bin/tcsh/sh.sem.c line 495

rcsid defined in line 39; never used

#### Defined variables

cmdlen defined in line 733; used 5 times

- in line 754, 892-896(3), 902

cmdp defined in line 734; used 6 times

- in line 753-756(2), 895-901(4)

command defined in line 732; used 2 times

- in line 753, 762

zru defined in line 134; used 8 times

- in line 1089, 1096, 1127-1130(2), 1138, 1147-1150(2), 1158

#### Defined macros

BIGINDEX defined in line 109; used 1 times

- in line 780

BSDWAIT defined in line 88; used 3 times

- in line 98, 169, 221

HZ defined in line 83; used 3 times

- in line 78-82(2), 362

NSIG defined in line 74; used 4 times

- in line 73, 1330, 1345-1349(2)

RUSAGE_CHILDREN defined in line 139; used 1 times

- in line 138

WCOREDUMP defined in line 101; used 2 times

- in line 97, 338

WEXITSTATUS defined in line 91; used 3 times

- in line 90, 273, 343

WSTOPSIG defined in line 94; used 2 times

- in line 93, 310

WTERMSIG defined in line 87; used 4 times

- in line 86, 273, 334, 340

_BSD defined in line 55; never used
_CLASSIC_POSIX_TYPES defined in line 58; used 1 times

- in line 57

timercmp defined in line 1141; used 2 times

- in line 1135, 1155

Last modified: 1991-08-20 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 4756 |