Home | History | Annotate | Line # | Download | only in csh
proc.c revision 1.1.1.1
      1 /*-
      2  * Copyright (c) 1980, 1991 The Regents of the University of California.
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  * 3. All advertising materials mentioning features or use of this software
     14  *    must display the following acknowledgement:
     15  *	This product includes software developed by the University of
     16  *	California, Berkeley and its contributors.
     17  * 4. Neither the name of the University nor the names of its contributors
     18  *    may be used to endorse or promote products derived from this software
     19  *    without specific prior written permission.
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     31  * SUCH DAMAGE.
     32  */
     33 
     34 #ifndef lint
     35 static char sccsid[] = "@(#)proc.c	5.22 (Berkeley) 6/14/91";
     36 #endif /* not lint */
     37 
     38 #include <sys/types.h>
     39 #include <sys/wait.h>
     40 #include <errno.h>
     41 #include <unistd.h>
     42 #include <stdlib.h>
     43 #include <string.h>
     44 #if __STDC__
     45 # include <stdarg.h>
     46 #else
     47 # include <varargs.h>
     48 #endif
     49 
     50 #include "csh.h"
     51 #include "dir.h"
     52 #include "proc.h"
     53 #include "extern.h"
     54 
     55 #define BIGINDEX	9	/* largest desirable job index */
     56 
     57 static struct rusage zru;
     58 
     59 static void	 pflushall __P((void));
     60 static void	 pflush __P((struct process *));
     61 static void	 pclrcurr __P((struct process *));
     62 static void	 padd __P((struct command *));
     63 static int	 pprint __P((struct process *, int));
     64 static void	 ptprint __P((struct process *));
     65 static void	 pads __P((Char *));
     66 static void	 pkill __P((Char **v, int));
     67 static struct	process
     68 		*pgetcurr __P((struct process *));
     69 static void	 okpcntl __P((void));
     70 
     71 /*
     72  * pchild - called at interrupt level by the SIGCHLD signal
     73  *	indicating that at least one child has terminated or stopped
     74  *	thus at least one wait system call will definitely return a
     75  *	childs status.  Top level routines (like pwait) must be sure
     76  *	to mask interrupts when playing with the proclist data structures!
     77  */
     78 /* ARGUSED */
     79 void
     80 pchild(notused)
     81 	int notused;
     82 {
     83     register struct process *pp;
     84     register struct process *fp;
     85     register int pid;
     86     extern int insource;
     87     union wait w;
     88     int     jobflags;
     89     struct rusage ru;
     90 
     91 loop:
     92     errno = 0;			/* reset, just in case */
     93     pid = wait3(&w.w_status,
     94        (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru);
     95 
     96     if (pid <= 0) {
     97 	if (errno == EINTR) {
     98 	    errno = 0;
     99 	    goto loop;
    100 	}
    101 	pnoprocesses = pid == -1;
    102 	return;
    103     }
    104     for (pp = proclist.p_next; pp != NULL; pp = pp->p_next)
    105 	if (pid == pp->p_pid)
    106 	    goto found;
    107     goto loop;
    108 found:
    109     if (pid == atoi(short2str(value(STRchild))))
    110 	unsetv(STRchild);
    111     pp->p_flags &= ~(PRUNNING | PSTOPPED | PREPORTED);
    112     if (WIFSTOPPED(w)) {
    113 	pp->p_flags |= PSTOPPED;
    114 	pp->p_reason = w.w_stopsig;
    115     }
    116     else {
    117 	if (pp->p_flags & (PTIME | PPTIME) || adrof(STRtime))
    118 	    (void) gettimeofday(&pp->p_etime, NULL);
    119 
    120 	pp->p_rusage = ru;
    121 	if (WIFSIGNALED(w)) {
    122 	    if (w.w_termsig == SIGINT)
    123 		pp->p_flags |= PINTERRUPTED;
    124 	    else
    125 		pp->p_flags |= PSIGNALED;
    126 	    if (w.w_coredump)
    127 		pp->p_flags |= PDUMPED;
    128 	    pp->p_reason = w.w_termsig;
    129 	}
    130 	else {
    131 	    pp->p_reason = w.w_retcode;
    132 	    if (pp->p_reason != 0)
    133 		pp->p_flags |= PAEXITED;
    134 	    else
    135 		pp->p_flags |= PNEXITED;
    136 	}
    137     }
    138     jobflags = 0;
    139     fp = pp;
    140     do {
    141 	if ((fp->p_flags & (PPTIME | PRUNNING | PSTOPPED)) == 0 &&
    142 	    !child && adrof(STRtime) &&
    143 	    fp->p_rusage.ru_utime.tv_sec + fp->p_rusage.ru_stime.tv_sec
    144 	    >= atoi(short2str(value(STRtime))))
    145 	    fp->p_flags |= PTIME;
    146 	jobflags |= fp->p_flags;
    147     } while ((fp = fp->p_friends) != pp);
    148     pp->p_flags &= ~PFOREGND;
    149     if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
    150 	pp->p_flags &= ~PPTIME;
    151 	pp->p_flags |= PTIME;
    152     }
    153     if ((jobflags & (PRUNNING | PREPORTED)) == 0) {
    154 	fp = pp;
    155 	do {
    156 	    if (fp->p_flags & PSTOPPED)
    157 		fp->p_flags |= PREPORTED;
    158 	} while ((fp = fp->p_friends) != pp);
    159 	while (fp->p_pid != fp->p_jobid)
    160 	    fp = fp->p_friends;
    161 	if (jobflags & PSTOPPED) {
    162 	    if (pcurrent && pcurrent != fp)
    163 		pprevious = pcurrent;
    164 	    pcurrent = fp;
    165 	}
    166 	else
    167 	    pclrcurr(fp);
    168 	if (jobflags & PFOREGND) {
    169 	    if (jobflags & (PSIGNALED | PSTOPPED | PPTIME) ||
    170 #ifdef IIASA
    171 		jobflags & PAEXITED ||
    172 #endif
    173 		!eq(dcwd->di_name, fp->p_cwd->di_name)) {
    174 		;		/* print in pjwait */
    175 	    }
    176 	    /* PWP: print a newline after ^C */
    177 	    else if (jobflags & PINTERRUPTED)
    178 		xputchar('\r' | QUOTE), xputchar('\n');
    179 	}
    180 	else {
    181 	    if (jobflags & PNOTIFY || adrof(STRnotify)) {
    182 		xputchar('\r' | QUOTE), xputchar('\n');
    183 		(void) pprint(pp, NUMBER | NAME | REASON);
    184 		if ((jobflags & PSTOPPED) == 0)
    185 		    pflush(pp);
    186 	    }
    187 	    else {
    188 		fp->p_flags |= PNEEDNOTE;
    189 		neednote++;
    190 	    }
    191 	}
    192     }
    193     goto loop;
    194 }
    195 
    196 void
    197 pnote()
    198 {
    199     register struct process *pp;
    200     int     flags;
    201     sigset_t omask;
    202 
    203     neednote = 0;
    204     for (pp = proclist.p_next; pp != NULL; pp = pp->p_next) {
    205 	if (pp->p_flags & PNEEDNOTE) {
    206 	    omask = sigblock(sigmask(SIGCHLD));
    207 	    pp->p_flags &= ~PNEEDNOTE;
    208 	    flags = pprint(pp, NUMBER | NAME | REASON);
    209 	    if ((flags & (PRUNNING | PSTOPPED)) == 0)
    210 		pflush(pp);
    211 	    (void) sigsetmask(omask);
    212 	}
    213     }
    214 }
    215 
    216 /*
    217  * pwait - wait for current job to terminate, maintaining integrity
    218  *	of current and previous job indicators.
    219  */
    220 void
    221 pwait()
    222 {
    223     register struct process *fp, *pp;
    224     sigset_t omask;
    225 
    226     /*
    227      * Here's where dead procs get flushed.
    228      */
    229     omask = sigblock(sigmask(SIGCHLD));
    230     for (pp = (fp = &proclist)->p_next; pp != NULL; pp = (fp = pp)->p_next)
    231 	if (pp->p_pid == 0) {
    232 	    fp->p_next = pp->p_next;
    233 	    xfree((ptr_t) pp->p_command);
    234 	    if (pp->p_cwd && --pp->p_cwd->di_count == 0)
    235 		if (pp->p_cwd->di_next == 0)
    236 		    dfree(pp->p_cwd);
    237 	    xfree((ptr_t) pp);
    238 	    pp = fp;
    239 	}
    240     (void) sigsetmask(omask);
    241     pjwait(pcurrjob);
    242 }
    243 
    244 
    245 /*
    246  * pjwait - wait for a job to finish or become stopped
    247  *	It is assumed to be in the foreground state (PFOREGND)
    248  */
    249 void
    250 pjwait(pp)
    251     register struct process *pp;
    252 {
    253     register struct process *fp;
    254     int     jobflags, reason;
    255     sigset_t omask;
    256 
    257     while (pp->p_pid != pp->p_jobid)
    258 	pp = pp->p_friends;
    259     fp = pp;
    260 
    261     do {
    262 	if ((fp->p_flags & (PFOREGND | PRUNNING)) == PRUNNING)
    263 	    xprintf("BUG: waiting for background job!\n");
    264     } while ((fp = fp->p_friends) != pp);
    265     /*
    266      * Now keep pausing as long as we are not interrupted (SIGINT), and the
    267      * target process, or any of its friends, are running
    268      */
    269     fp = pp;
    270     omask = sigblock(sigmask(SIGCHLD));
    271     for (;;) {
    272 	(void) sigblock(sigmask(SIGCHLD));
    273 	jobflags = 0;
    274 	do
    275 	    jobflags |= fp->p_flags;
    276 	while ((fp = (fp->p_friends)) != pp);
    277 	if ((jobflags & PRUNNING) == 0)
    278 	    break;
    279 #ifdef JOBDEBUG
    280 	xprintf("starting to sigpause for  SIGCHLD on %d\n", fp->p_pid);
    281 #endif				/* JOBDEBUG */
    282 	(void) sigpause(omask & ~sigmask(SIGCHLD));
    283     }
    284     (void) sigsetmask(omask);
    285     if (tpgrp > 0)		/* get tty back */
    286 	(void) tcsetpgrp(FSHTTY, tpgrp);
    287     if ((jobflags & (PSIGNALED | PSTOPPED | PTIME)) ||
    288 	!eq(dcwd->di_name, fp->p_cwd->di_name)) {
    289 	if (jobflags & PSTOPPED) {
    290 	    xprintf("\n");
    291 	    if (adrof(STRlistjobs)) {
    292 		Char   *jobcommand[3];
    293 
    294 		jobcommand[0] = STRjobs;
    295 		if (eq(value(STRlistjobs), STRlong))
    296 		    jobcommand[1] = STRml;
    297 		else
    298 		    jobcommand[1] = NULL;
    299 		jobcommand[2] = NULL;
    300 
    301 		dojobs(jobcommand);
    302 		(void) pprint(pp, SHELLDIR);
    303 	    }
    304 	    else
    305 		(void) pprint(pp, AREASON | SHELLDIR);
    306 	}
    307 	else
    308 	    (void) pprint(pp, AREASON | SHELLDIR);
    309     }
    310     if ((jobflags & (PINTERRUPTED | PSTOPPED)) && setintr &&
    311 	(!gointr || !eq(gointr, STRminus))) {
    312 	if ((jobflags & PSTOPPED) == 0)
    313 	    pflush(pp);
    314 	pintr1(0);
    315 	/* NOTREACHED */
    316     }
    317     reason = 0;
    318     fp = pp;
    319     do {
    320 	if (fp->p_reason)
    321 	    reason = fp->p_flags & (PSIGNALED | PINTERRUPTED) ?
    322 		fp->p_reason | META : fp->p_reason;
    323     } while ((fp = fp->p_friends) != pp);
    324     if ((reason != 0) && (adrof(STRprintexitvalue)))
    325 	xprintf("Exit %d\n", reason);
    326     set(STRstatus, putn(reason));
    327     if (reason && exiterr)
    328 	exitstat();
    329     pflush(pp);
    330 }
    331 
    332 /*
    333  * dowait - wait for all processes to finish
    334  */
    335 void
    336 dowait()
    337 {
    338     register struct process *pp;
    339     sigset_t omask;
    340 
    341     pjobs++;
    342     omask = sigblock(sigmask(SIGCHLD));
    343 loop:
    344     for (pp = proclist.p_next; pp; pp = pp->p_next)
    345 	if (pp->p_pid &&	/* pp->p_pid == pp->p_jobid && */
    346 	    pp->p_flags & PRUNNING) {
    347 	    (void) sigpause((sigset_t) 0);
    348 	    goto loop;
    349 	}
    350     (void) sigsetmask(omask);
    351     pjobs = 0;
    352 }
    353 
    354 /*
    355  * pflushall - flush all jobs from list (e.g. at fork())
    356  */
    357 static void
    358 pflushall()
    359 {
    360     register struct process *pp;
    361 
    362     for (pp = proclist.p_next; pp != NULL; pp = pp->p_next)
    363 	if (pp->p_pid)
    364 	    pflush(pp);
    365 }
    366 
    367 /*
    368  * pflush - flag all process structures in the same job as the
    369  *	the argument process for deletion.  The actual free of the
    370  *	space is not done here since pflush is called at interrupt level.
    371  */
    372 static void
    373 pflush(pp)
    374     register struct process *pp;
    375 {
    376     register struct process *np;
    377     register int idx;
    378 
    379     if (pp->p_pid == 0) {
    380 	xprintf("BUG: process flushed twice");
    381 	return;
    382     }
    383     while (pp->p_pid != pp->p_jobid)
    384 	pp = pp->p_friends;
    385     pclrcurr(pp);
    386     if (pp == pcurrjob)
    387 	pcurrjob = 0;
    388     idx = pp->p_index;
    389     np = pp;
    390     do {
    391 	np->p_index = np->p_pid = 0;
    392 	np->p_flags &= ~PNEEDNOTE;
    393     } while ((np = np->p_friends) != pp);
    394     if (idx == pmaxindex) {
    395 	for (np = proclist.p_next, idx = 0; np; np = np->p_next)
    396 	    if (np->p_index > idx)
    397 		idx = np->p_index;
    398 	pmaxindex = idx;
    399     }
    400 }
    401 
    402 /*
    403  * pclrcurr - make sure the given job is not the current or previous job;
    404  *	pp MUST be the job leader
    405  */
    406 static void
    407 pclrcurr(pp)
    408     register struct process *pp;
    409 {
    410 
    411     if (pp == pcurrent)
    412 	if (pprevious != NULL) {
    413 	    pcurrent = pprevious;
    414 	    pprevious = pgetcurr(pp);
    415 	}
    416 	else {
    417 	    pcurrent = pgetcurr(pp);
    418 	    pprevious = pgetcurr(pp);
    419 	}
    420     else if (pp == pprevious)
    421 	pprevious = pgetcurr(pp);
    422 }
    423 
    424 /* +4 here is 1 for '\0', 1 ea for << >& >> */
    425 static Char command[PMAXLEN + 4];
    426 static int cmdlen;
    427 static Char *cmdp;
    428 
    429 /*
    430  * palloc - allocate a process structure and fill it up.
    431  *	an important assumption is made that the process is running.
    432  */
    433 void
    434 palloc(pid, t)
    435     int     pid;
    436     register struct command *t;
    437 {
    438     register struct process *pp;
    439     int     i;
    440 
    441     pp = (struct process *) xcalloc(1, (size_t) sizeof(struct process));
    442     pp->p_pid = pid;
    443     pp->p_flags = t->t_dflg & F_AMPERSAND ? PRUNNING : PRUNNING | PFOREGND;
    444     if (t->t_dflg & F_TIME)
    445 	pp->p_flags |= PPTIME;
    446     cmdp = command;
    447     cmdlen = 0;
    448     padd(t);
    449     *cmdp++ = 0;
    450     if (t->t_dflg & F_PIPEOUT) {
    451 	pp->p_flags |= PPOU;
    452 	if (t->t_dflg & F_STDERR)
    453 	    pp->p_flags |= PDIAG;
    454     }
    455     pp->p_command = Strsave(command);
    456     if (pcurrjob) {
    457 	struct process *fp;
    458 
    459 	/* careful here with interrupt level */
    460 	pp->p_cwd = 0;
    461 	pp->p_index = pcurrjob->p_index;
    462 	pp->p_friends = pcurrjob;
    463 	pp->p_jobid = pcurrjob->p_pid;
    464 	for (fp = pcurrjob; fp->p_friends != pcurrjob; fp = fp->p_friends);
    465 	fp->p_friends = pp;
    466     }
    467     else {
    468 	pcurrjob = pp;
    469 	pp->p_jobid = pid;
    470 	pp->p_friends = pp;
    471 	pp->p_cwd = dcwd;
    472 	dcwd->di_count++;
    473 	if (pmaxindex < BIGINDEX)
    474 	    pp->p_index = ++pmaxindex;
    475 	else {
    476 	    struct process *np;
    477 
    478 	    for (i = 1;; i++) {
    479 		for (np = proclist.p_next; np; np = np->p_next)
    480 		    if (np->p_index == i)
    481 			goto tryagain;
    482 		pp->p_index = i;
    483 		if (i > pmaxindex)
    484 		    pmaxindex = i;
    485 		break;
    486 	tryagain:;
    487 	    }
    488 	}
    489 	if (pcurrent == NULL)
    490 	    pcurrent = pp;
    491 	else if (pprevious == NULL)
    492 	    pprevious = pp;
    493     }
    494     pp->p_next = proclist.p_next;
    495     proclist.p_next = pp;
    496     (void) gettimeofday(&pp->p_btime, NULL);
    497 }
    498 
    499 static void
    500 padd(t)
    501     register struct command *t;
    502 {
    503     Char  **argp;
    504 
    505     if (t == 0)
    506 	return;
    507     switch (t->t_dtyp) {
    508 
    509     case NODE_PAREN:
    510 	pads(STRLparensp);
    511 	padd(t->t_dspr);
    512 	pads(STRspRparen);
    513 	break;
    514 
    515     case NODE_COMMAND:
    516 	for (argp = t->t_dcom; *argp; argp++) {
    517 	    pads(*argp);
    518 	    if (argp[1])
    519 		pads(STRspace);
    520 	}
    521 	break;
    522 
    523     case NODE_OR:
    524     case NODE_AND:
    525     case NODE_PIPE:
    526     case NODE_LIST:
    527 	padd(t->t_dcar);
    528 	switch (t->t_dtyp) {
    529 	case NODE_OR:
    530 	    pads(STRspor2sp);
    531 	    break;
    532 	case NODE_AND:
    533 	    pads(STRspand2sp);
    534 	    break;
    535 	case NODE_PIPE:
    536 	    pads(STRsporsp);
    537 	    break;
    538 	case NODE_LIST:
    539 	    pads(STRsemisp);
    540 	    break;
    541 	}
    542 	padd(t->t_dcdr);
    543 	return;
    544     }
    545     if ((t->t_dflg & F_PIPEIN) == 0 && t->t_dlef) {
    546 	pads((t->t_dflg & F_READ) ? STRspLarrow2sp : STRspLarrowsp);
    547 	pads(t->t_dlef);
    548     }
    549     if ((t->t_dflg & F_PIPEOUT) == 0 && t->t_drit) {
    550 	pads((t->t_dflg & F_APPEND) ? STRspRarrow2 : STRspRarrow);
    551 	if (t->t_dflg & F_STDERR)
    552 	    pads(STRand);
    553 	pads(STRspace);
    554 	pads(t->t_drit);
    555     }
    556 }
    557 
    558 static void
    559 pads(cp)
    560     Char   *cp;
    561 {
    562     register int i;
    563 
    564     /*
    565      * Avoid the Quoted Space alias hack! Reported by:
    566      * sam (at) john-bigboote.ICS.UCI.EDU (Sam Horrocks)
    567      */
    568     if (cp[0] == STRQNULL[0])
    569 	cp++;
    570 
    571     i = Strlen(cp);
    572 
    573     if (cmdlen >= PMAXLEN)
    574 	return;
    575     if (cmdlen + i >= PMAXLEN) {
    576 	(void) Strcpy(cmdp, STRsp3dots);
    577 	cmdlen = PMAXLEN;
    578 	cmdp += 4;
    579 	return;
    580     }
    581     (void) Strcpy(cmdp, cp);
    582     cmdp += i;
    583     cmdlen += i;
    584 }
    585 
    586 /*
    587  * psavejob - temporarily save the current job on a one level stack
    588  *	so another job can be created.  Used for { } in exp6
    589  *	and `` in globbing.
    590  */
    591 void
    592 psavejob()
    593 {
    594 
    595     pholdjob = pcurrjob;
    596     pcurrjob = NULL;
    597 }
    598 
    599 /*
    600  * prestjob - opposite of psavejob.  This may be missed if we are interrupted
    601  *	somewhere, but pendjob cleans up anyway.
    602  */
    603 void
    604 prestjob()
    605 {
    606 
    607     pcurrjob = pholdjob;
    608     pholdjob = NULL;
    609 }
    610 
    611 /*
    612  * pendjob - indicate that a job (set of commands) has been completed
    613  *	or is about to begin.
    614  */
    615 void
    616 pendjob()
    617 {
    618     register struct process *pp, *tp;
    619 
    620     if (pcurrjob && (pcurrjob->p_flags & (PFOREGND | PSTOPPED)) == 0) {
    621 	pp = pcurrjob;
    622 	while (pp->p_pid != pp->p_jobid)
    623 	    pp = pp->p_friends;
    624 	xprintf("[%d]", pp->p_index);
    625 	tp = pp;
    626 	do {
    627 	    xprintf(" %d", pp->p_pid);
    628 	    pp = pp->p_friends;
    629 	} while (pp != tp);
    630 	xprintf("\n");
    631     }
    632     pholdjob = pcurrjob = 0;
    633 }
    634 
    635 /*
    636  * pprint - print a job
    637  */
    638 static int
    639 pprint(pp, flag)
    640     register struct process *pp;
    641     bool    flag;
    642 {
    643     register status, reason;
    644     struct process *tp;
    645     extern char *linp, linbuf[];
    646     int     jobflags, pstatus;
    647     char   *format;
    648 
    649     while (pp->p_pid != pp->p_jobid)
    650 	pp = pp->p_friends;
    651     if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
    652 	pp->p_flags &= ~PPTIME;
    653 	pp->p_flags |= PTIME;
    654     }
    655     tp = pp;
    656     status = reason = -1;
    657     jobflags = 0;
    658     do {
    659 	jobflags |= pp->p_flags;
    660 	pstatus = pp->p_flags & PALLSTATES;
    661 	if (tp != pp && linp != linbuf && !(flag & FANCY) &&
    662 	    (pstatus == status && pp->p_reason == reason ||
    663 	     !(flag & REASON)))
    664 	    xprintf(" ");
    665 	else {
    666 	    if (tp != pp && linp != linbuf)
    667 		xprintf("\n");
    668 	    if (flag & NUMBER)
    669 		if (pp == tp)
    670 		    xprintf("[%d]%s %c ", pp->p_index,
    671 			    pp->p_index < 10 ? " " : "",
    672 			    pp == pcurrent ? '+' :
    673 			    (pp == pprevious ? '-' : ' '));
    674 		else
    675 		    xprintf("       ");
    676 	    if (flag & FANCY) {
    677 		xprintf("%5d ", pp->p_pid);
    678 	    }
    679 	    if (flag & (REASON | AREASON)) {
    680 		if (flag & NAME)
    681 		    format = "%-23s";
    682 		else
    683 		    format = "%s";
    684 		if (pstatus == status)
    685 		    if (pp->p_reason == reason) {
    686 			xprintf(format, "");
    687 			goto prcomd;
    688 		    }
    689 		    else
    690 			reason = pp->p_reason;
    691 		else {
    692 		    status = pstatus;
    693 		    reason = pp->p_reason;
    694 		}
    695 		switch (status) {
    696 
    697 		case PRUNNING:
    698 		    xprintf(format, "Running ");
    699 		    break;
    700 
    701 		case PINTERRUPTED:
    702 		case PSTOPPED:
    703 		case PSIGNALED:
    704 		    if ((flag & REASON) ||
    705 			((flag & AREASON) && reason != SIGINT
    706 			 && reason != SIGPIPE))
    707 			xprintf(format, mesg[pp->p_reason].pname);
    708 		    break;
    709 
    710 		case PNEXITED:
    711 		case PAEXITED:
    712 		    if (flag & REASON)
    713 			if (pp->p_reason)
    714 			    xprintf("Exit %-18d", pp->p_reason);
    715 			else
    716 			    xprintf(format, "Done");
    717 		    break;
    718 
    719 		default:
    720 		    xprintf("BUG: status=%-9o", status);
    721 		}
    722 	    }
    723 	}
    724 prcomd:
    725 	if (flag & NAME) {
    726 	    xprintf("%s", short2str(pp->p_command));
    727 	    if (pp->p_flags & PPOU)
    728 		xprintf(" |");
    729 	    if (pp->p_flags & PDIAG)
    730 		xprintf("&");
    731 	}
    732 	if (flag & (REASON | AREASON) && pp->p_flags & PDUMPED)
    733 	    xprintf(" (core dumped)");
    734 	if (tp == pp->p_friends) {
    735 	    if (flag & AMPERSAND)
    736 		xprintf(" &");
    737 	    if (flag & JOBDIR &&
    738 		!eq(tp->p_cwd->di_name, dcwd->di_name)) {
    739 		xprintf(" (wd: ");
    740 		dtildepr(value(STRhome), tp->p_cwd->di_name);
    741 		xprintf(")");
    742 	    }
    743 	}
    744 	if (pp->p_flags & PPTIME && !(status & (PSTOPPED | PRUNNING))) {
    745 	    if (linp != linbuf)
    746 		xprintf("\n\t");
    747 	    prusage(&zru, &pp->p_rusage, &pp->p_etime,
    748 		    &pp->p_btime);
    749 	}
    750 	if (tp == pp->p_friends) {
    751 	    if (linp != linbuf)
    752 		xprintf("\n");
    753 	    if (flag & SHELLDIR && !eq(tp->p_cwd->di_name, dcwd->di_name)) {
    754 		xprintf("(wd now: ");
    755 		dtildepr(value(STRhome), dcwd->di_name);
    756 		xprintf(")\n");
    757 	    }
    758 	}
    759     } while ((pp = pp->p_friends) != tp);
    760     if (jobflags & PTIME && (jobflags & (PSTOPPED | PRUNNING)) == 0) {
    761 	if (jobflags & NUMBER)
    762 	    xprintf("       ");
    763 	ptprint(tp);
    764     }
    765     return (jobflags);
    766 }
    767 
    768 static void
    769 ptprint(tp)
    770     register struct process *tp;
    771 {
    772     struct timeval tetime, diff;
    773     static struct timeval ztime;
    774     struct rusage ru;
    775     static struct rusage zru;
    776     register struct process *pp = tp;
    777 
    778     ru = zru;
    779     tetime = ztime;
    780     do {
    781 	ruadd(&ru, &pp->p_rusage);
    782 	tvsub(&diff, &pp->p_etime, &pp->p_btime);
    783 	if (timercmp(&diff, &tetime, >))
    784 	    tetime = diff;
    785     } while ((pp = pp->p_friends) != tp);
    786     prusage(&zru, &ru, &tetime, &ztime);
    787 }
    788 
    789 /*
    790  * dojobs - print all jobs
    791  */
    792 void
    793 dojobs(v)
    794     Char  **v;
    795 {
    796     register struct process *pp;
    797     register int flag = NUMBER | NAME | REASON;
    798     int     i;
    799 
    800     if (chkstop)
    801 	chkstop = 2;
    802     if (*++v) {
    803 	if (v[1] || !eq(*v, STRml))
    804 	    stderror(ERR_JOBS);
    805 	flag |= FANCY | JOBDIR;
    806     }
    807     for (i = 1; i <= pmaxindex; i++)
    808 	for (pp = proclist.p_next; pp; pp = pp->p_next)
    809 	    if (pp->p_index == i && pp->p_pid == pp->p_jobid) {
    810 		pp->p_flags &= ~PNEEDNOTE;
    811 		if (!(pprint(pp, flag) & (PRUNNING | PSTOPPED)))
    812 		    pflush(pp);
    813 		break;
    814 	    }
    815 }
    816 
    817 /*
    818  * dofg - builtin - put the job into the foreground
    819  */
    820 void
    821 dofg(v)
    822     Char  **v;
    823 {
    824     register struct process *pp;
    825 
    826     okpcntl();
    827     ++v;
    828     do {
    829 	pp = pfind(*v);
    830 	pstart(pp, 1);
    831 	pjwait(pp);
    832     } while (*v && *++v);
    833 }
    834 
    835 /*
    836  * %... - builtin - put the job into the foreground
    837  */
    838 void
    839 dofg1(v)
    840     Char  **v;
    841 {
    842     register struct process *pp;
    843 
    844     okpcntl();
    845     pp = pfind(v[0]);
    846     pstart(pp, 1);
    847     pjwait(pp);
    848 }
    849 
    850 /*
    851  * dobg - builtin - put the job into the background
    852  */
    853 void
    854 dobg(v)
    855     Char  **v;
    856 {
    857     register struct process *pp;
    858 
    859     okpcntl();
    860     ++v;
    861     do {
    862 	pp = pfind(*v);
    863 	pstart(pp, 0);
    864     } while (*v && *++v);
    865 }
    866 
    867 /*
    868  * %... & - builtin - put the job into the background
    869  */
    870 void
    871 dobg1(v)
    872     Char  **v;
    873 {
    874     register struct process *pp;
    875 
    876     pp = pfind(v[0]);
    877     pstart(pp, 0);
    878 }
    879 
    880 /*
    881  * dostop - builtin - stop the job
    882  */
    883 void
    884 dostop(v)
    885     Char  **v;
    886 {
    887     pkill(++v, SIGSTOP);
    888 }
    889 
    890 /*
    891  * dokill - builtin - superset of kill (1)
    892  */
    893 void
    894 dokill(v)
    895     Char  **v;
    896 {
    897     register int signum, len = 0;
    898     register char *name;
    899 
    900     v++;
    901     if (v[0] && v[0][0] == '-') {
    902 	if (v[0][1] == 'l') {
    903 	    for (signum = 1; signum <= NSIG; signum++) {
    904 		if ((name = mesg[signum].iname) != NULL) {
    905 		    len += strlen(name) + 1;
    906 		    if (len >= 80 - 1) {
    907 			xprintf("\n");
    908 			len = strlen(name) + 1;
    909 		    }
    910 		    xprintf("%s ", name);
    911 		}
    912 	    }
    913 	    xprintf("\n");
    914 	    return;
    915 	}
    916 	if (Isdigit(v[0][1])) {
    917 	    signum = atoi(short2str(v[0] + 1));
    918 	    if (signum < 0 || signum > NSIG)
    919 		stderror(ERR_NAME | ERR_BADSIG);
    920 	}
    921 	else {
    922 	    for (signum = 1; signum <= NSIG; signum++)
    923 		if (mesg[signum].iname &&
    924 		    eq(&v[0][1], str2short(mesg[signum].iname)))
    925 		    goto gotsig;
    926 	    setname(short2str(&v[0][1]));
    927 	    stderror(ERR_NAME | ERR_UNKSIG);
    928 	}
    929 gotsig:
    930 	v++;
    931     }
    932     else
    933 	signum = SIGTERM;
    934     pkill(v, signum);
    935 }
    936 
    937 static void
    938 pkill(v, signum)
    939     Char  **v;
    940     int     signum;
    941 {
    942     register struct process *pp, *np;
    943     register int jobflags = 0;
    944     int     pid, err1 = 0;
    945     sigset_t omask;
    946     Char   *cp;
    947 
    948     omask = sigmask(SIGCHLD);
    949     if (setintr)
    950 	omask |= sigmask(SIGINT);
    951     omask = sigblock(omask) & ~omask;
    952     gflag = 0, tglob(v);
    953     if (gflag) {
    954 	v = globall(v);
    955 	if (v == 0)
    956 	    stderror(ERR_NAME | ERR_NOMATCH);
    957     }
    958     else {
    959 	v = gargv = saveblk(v);
    960 	trim(v);
    961     }
    962 
    963     while (v && (cp = *v)) {
    964 	if (*cp == '%') {
    965 	    np = pp = pfind(cp);
    966 	    do
    967 		jobflags |= np->p_flags;
    968 	    while ((np = np->p_friends) != pp);
    969 	    switch (signum) {
    970 
    971 	    case SIGSTOP:
    972 	    case SIGTSTP:
    973 	    case SIGTTIN:
    974 	    case SIGTTOU:
    975 		if ((jobflags & PRUNNING) == 0) {
    976 		    xprintf("%s: Already suspended\n", short2str(cp));
    977 		    err1++;
    978 		    goto cont;
    979 		}
    980 		break;
    981 		/*
    982 		 * suspend a process, kill -CONT %, then type jobs; the shell
    983 		 * says it is suspended, but it is running; thanks jaap..
    984 		 */
    985 	    case SIGCONT:
    986 		pstart(pp, 0);
    987 		goto cont;
    988 	    }
    989 	    if (killpg((pid_t) pp->p_jobid, signum) < 0) {
    990 		xprintf("%s: %s\n", short2str(cp), strerror(errno));
    991 		err1++;
    992 	    }
    993 	    if (signum == SIGTERM || signum == SIGHUP)
    994 		(void) killpg((pid_t) pp->p_jobid, SIGCONT);
    995 	}
    996 	else if (!(Isdigit(*cp) || *cp == '-'))
    997 	    stderror(ERR_NAME | ERR_JOBARGS);
    998 	else {
    999 	    pid = atoi(short2str(cp));
   1000 	    if (kill((pid_t) pid, signum) < 0) {
   1001 		xprintf("%d: %s\n", pid, strerror(errno));
   1002 		err1++;
   1003 		goto cont;
   1004 	    }
   1005 	    if (signum == SIGTERM || signum == SIGHUP)
   1006 		(void) kill((pid_t) pid, SIGCONT);
   1007 	}
   1008 cont:
   1009 	v++;
   1010     }
   1011     if (gargv)
   1012 	blkfree(gargv), gargv = 0;
   1013     (void) sigsetmask(omask);
   1014     if (err1)
   1015 	stderror(ERR_SILENT);
   1016 }
   1017 
   1018 /*
   1019  * pstart - start the job in foreground/background
   1020  */
   1021 void
   1022 pstart(pp, foregnd)
   1023     register struct process *pp;
   1024     int     foregnd;
   1025 {
   1026     register struct process *np;
   1027     sigset_t omask;
   1028     long    jobflags = 0;
   1029 
   1030     omask = sigblock(sigmask(SIGCHLD));
   1031     np = pp;
   1032     do {
   1033 	jobflags |= np->p_flags;
   1034 	if (np->p_flags & (PRUNNING | PSTOPPED)) {
   1035 	    np->p_flags |= PRUNNING;
   1036 	    np->p_flags &= ~PSTOPPED;
   1037 	    if (foregnd)
   1038 		np->p_flags |= PFOREGND;
   1039 	    else
   1040 		np->p_flags &= ~PFOREGND;
   1041 	}
   1042     } while ((np = np->p_friends) != pp);
   1043     if (!foregnd)
   1044 	pclrcurr(pp);
   1045     (void) pprint(pp, foregnd ? NAME | JOBDIR : NUMBER | NAME | AMPERSAND);
   1046     if (foregnd)
   1047 	(void) tcsetpgrp(FSHTTY, pp->p_jobid);
   1048     if (jobflags & PSTOPPED)
   1049 	(void) killpg((pid_t) pp->p_jobid, SIGCONT);
   1050     (void) sigsetmask(omask);
   1051 }
   1052 
   1053 void
   1054 panystop(neednl)
   1055     bool    neednl;
   1056 {
   1057     register struct process *pp;
   1058 
   1059     chkstop = 2;
   1060     for (pp = proclist.p_next; pp; pp = pp->p_next)
   1061 	if (pp->p_flags & PSTOPPED)
   1062 	    stderror(ERR_STOPPED, neednl ? "\n" : "");
   1063 }
   1064 
   1065 struct process *
   1066 pfind(cp)
   1067     Char   *cp;
   1068 {
   1069     register struct process *pp, *np;
   1070 
   1071     if (cp == 0 || cp[1] == 0 || eq(cp, STRcent2) || eq(cp, STRcentplus)) {
   1072 	if (pcurrent == NULL)
   1073 	    stderror(ERR_NAME | ERR_JOBCUR);
   1074 	return (pcurrent);
   1075     }
   1076     if (eq(cp, STRcentminus) || eq(cp, STRcenthash)) {
   1077 	if (pprevious == NULL)
   1078 	    stderror(ERR_NAME | ERR_JOBPREV);
   1079 	return (pprevious);
   1080     }
   1081     if (Isdigit(cp[1])) {
   1082 	int     idx = atoi(short2str(cp + 1));
   1083 
   1084 	for (pp = proclist.p_next; pp; pp = pp->p_next)
   1085 	    if (pp->p_index == idx && pp->p_pid == pp->p_jobid)
   1086 		return (pp);
   1087 	stderror(ERR_NAME | ERR_NOSUCHJOB);
   1088     }
   1089     np = NULL;
   1090     for (pp = proclist.p_next; pp; pp = pp->p_next)
   1091 	if (pp->p_pid == pp->p_jobid) {
   1092 	    if (cp[1] == '?') {
   1093 		register Char *dp;
   1094 
   1095 		for (dp = pp->p_command; *dp; dp++) {
   1096 		    if (*dp != cp[2])
   1097 			continue;
   1098 		    if (prefix(cp + 2, dp))
   1099 			goto match;
   1100 		}
   1101 	    }
   1102 	    else if (prefix(cp + 1, pp->p_command)) {
   1103 	match:
   1104 		if (np)
   1105 		    stderror(ERR_NAME | ERR_AMBIG);
   1106 		np = pp;
   1107 	    }
   1108 	}
   1109     if (np)
   1110 	return (np);
   1111     stderror(ERR_NAME | cp[1] == '?' ? ERR_JOBPAT : ERR_NOSUCHJOB);
   1112     /* NOTREACHED */
   1113     return (0);
   1114 }
   1115 
   1116 
   1117 /*
   1118  * pgetcurr - find most recent job that is not pp, preferably stopped
   1119  */
   1120 static struct process *
   1121 pgetcurr(pp)
   1122     register struct process *pp;
   1123 {
   1124     register struct process *np;
   1125     register struct process *xp = NULL;
   1126 
   1127     for (np = proclist.p_next; np; np = np->p_next)
   1128 	if (np != pcurrent && np != pp && np->p_pid &&
   1129 	    np->p_pid == np->p_jobid) {
   1130 	    if (np->p_flags & PSTOPPED)
   1131 		return (np);
   1132 	    if (xp == NULL)
   1133 		xp = np;
   1134 	}
   1135     return (xp);
   1136 }
   1137 
   1138 /*
   1139  * donotify - flag the job so as to report termination asynchronously
   1140  */
   1141 void
   1142 donotify(v)
   1143     Char  **v;
   1144 {
   1145     register struct process *pp;
   1146 
   1147     pp = pfind(*++v);
   1148     pp->p_flags |= PNOTIFY;
   1149 }
   1150 
   1151 /*
   1152  * Do the fork and whatever should be done in the child side that
   1153  * should not be done if we are not forking at all (like for simple builtin's)
   1154  * Also do everything that needs any signals fiddled with in the parent side
   1155  *
   1156  * Wanttty tells whether process and/or tty pgrps are to be manipulated:
   1157  *	-1:	leave tty alone; inherit pgrp from parent
   1158  *	 0:	already have tty; manipulate process pgrps only
   1159  *	 1:	want to claim tty; manipulate process and tty pgrps
   1160  * It is usually just the value of tpgrp.
   1161  */
   1162 
   1163 int
   1164 pfork(t, wanttty)
   1165     struct command *t;		/* command we are forking for */
   1166     int     wanttty;
   1167 {
   1168     register int pid;
   1169     bool    ignint = 0;
   1170     int     pgrp;
   1171     sigset_t omask;
   1172 
   1173     /*
   1174      * A child will be uninterruptible only under very special conditions.
   1175      * Remember that the semantics of '&' is implemented by disconnecting the
   1176      * process from the tty so signals do not need to ignored just for '&'.
   1177      * Thus signals are set to default action for children unless: we have had
   1178      * an "onintr -" (then specifically ignored) we are not playing with
   1179      * signals (inherit action)
   1180      */
   1181     if (setintr)
   1182 	ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT))
   1183 	    || (gointr && eq(gointr, STRminus));
   1184     /*
   1185      * Check for maximum nesting of 16 processes to avoid Forking loops
   1186      */
   1187     if (child == 16)
   1188 	stderror(ERR_NESTING, 16);
   1189     /*
   1190      * Hold SIGCHLD until we have the process installed in our table.
   1191      */
   1192     omask = sigblock(sigmask(SIGCHLD));
   1193     while ((pid = fork()) < 0)
   1194 	if (setintr == 0)
   1195 	    (void) sleep(FORKSLEEP);
   1196 	else {
   1197 	    (void) sigsetmask(omask);
   1198 	    stderror(ERR_NOPROC);
   1199 	}
   1200     if (pid == 0) {
   1201 	settimes();
   1202 	pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
   1203 	pflushall();
   1204 	pcurrjob = NULL;
   1205 	child++;
   1206 	if (setintr) {
   1207 	    setintr = 0;	/* until I think otherwise */
   1208 	    /*
   1209 	     * Children just get blown away on SIGINT, SIGQUIT unless "onintr
   1210 	     * -" seen.
   1211 	     */
   1212 	    (void) signal(SIGINT, ignint ? SIG_IGN : SIG_DFL);
   1213 	    (void) signal(SIGQUIT, ignint ? SIG_IGN : SIG_DFL);
   1214 	    if (wanttty >= 0) {
   1215 		/* make stoppable */
   1216 		(void) signal(SIGTSTP, SIG_DFL);
   1217 		(void) signal(SIGTTIN, SIG_DFL);
   1218 		(void) signal(SIGTTOU, SIG_DFL);
   1219 	    }
   1220 	    (void) signal(SIGTERM, parterm);
   1221 	}
   1222 	else if (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) {
   1223 	    (void) signal(SIGINT, SIG_IGN);
   1224 	    (void) signal(SIGQUIT, SIG_IGN);
   1225 	}
   1226 	pgetty(wanttty, pgrp);
   1227 	/*
   1228 	 * Nohup and nice apply only to NODE_COMMAND's but it would be nice
   1229 	 * (?!?) if you could say "nohup (foo;bar)" Then the parser would have
   1230 	 * to know about nice/nohup/time
   1231 	 */
   1232 	if (t->t_dflg & F_NOHUP)
   1233 	    (void) signal(SIGHUP, SIG_IGN);
   1234 	if (t->t_dflg & F_NICE)
   1235 	    (void) setpriority(PRIO_PROCESS, 0, t->t_nice);
   1236     }
   1237     else {
   1238 	if (wanttty >= 0)
   1239 	    (void) setpgid(pid, pcurrjob ? pcurrjob->p_jobid : pid);
   1240 	palloc(pid, t);
   1241 	(void) sigsetmask(omask);
   1242     }
   1243 
   1244     return (pid);
   1245 }
   1246 
   1247 static void
   1248 okpcntl()
   1249 {
   1250     if (tpgrp == -1)
   1251 	stderror(ERR_JOBCONTROL);
   1252     if (tpgrp == 0)
   1253 	stderror(ERR_JOBCTRLSUB);
   1254 }
   1255 
   1256 /*
   1257  * if we don't have vfork(), things can still go in the wrong order
   1258  * resulting in the famous 'Stopped (tty output)'. But some systems
   1259  * don't permit the setpgid() call, (these are more recent secure
   1260  * systems such as ibm's aix). Then we'd rather print an error message
   1261  * than hang the shell!
   1262  * I am open to suggestions how to fix that.
   1263  */
   1264 void
   1265 pgetty(wanttty, pgrp)
   1266     int     wanttty, pgrp;
   1267 {
   1268     sigset_t omask = 0;
   1269 
   1270     /*
   1271      * christos: I am blocking the tty signals till I've set things
   1272      * correctly....
   1273      */
   1274     if (wanttty > 0)
   1275 	omask = sigblock(sigmask(SIGTSTP)|sigmask(SIGTTIN)|sigmask(SIGTTOU));
   1276     /*
   1277      * From: Michael Schroeder <mlschroe (at) immd4.informatik.uni-erlangen.de>
   1278      * Don't check for tpgrp >= 0 so even non-interactive shells give
   1279      * background jobs process groups Same for the comparison in the other part
   1280      * of the #ifdef
   1281      */
   1282     if (wanttty >= 0)
   1283 	if (setpgid(0, pgrp) == -1) {
   1284 	    xprintf("csh: setpgid error.\n");
   1285 	    xexit(0);
   1286 	}
   1287 
   1288     if (wanttty > 0) {
   1289 	(void) tcsetpgrp(FSHTTY, pgrp);
   1290 	(void) sigsetmask(omask);
   1291     }
   1292 
   1293     if (tpgrp > 0)
   1294 	tpgrp = 0;		/* gave tty away */
   1295 }
   1296