Home | History | Annotate | Download | only in csh
      1 /*
      2  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
      3  * Use is subject to license terms.
      4  */
      5 
      6 /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
      7 /*	  All Rights Reserved  	*/
      8 
      9 /*
     10  * Copyright (c) 1980 Regents of the University of California.
     11  * All rights reserved. The Berkeley Software License Agreement
     12  * specifies the terms and conditions for redistribution.
     13  */
     14 
     15 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     16 
     17 #include "sh.h"
     18 #include "sh.dir.h"
     19 #include "sh.proc.h"
     20 #include "wait.h"
     21 #include "sh.tconst.h"
     22 
     23 /*
     24  * C Shell - functions that manage processes, handling hanging, termination
     25  */
     26 
     27 #define	BIGINDEX	9	/* largest desirable job index */
     28 
     29 void	pjwait(struct process *);
     30 void	pflush(struct process *);
     31 void	pclrcurr(struct process *);
     32 void	padd(struct command *);
     33 void	pads(tchar *);
     34 void	ptprint(struct process *);
     35 void	pkill(tchar **, int);
     36 void	pstart(struct process *, int);
     37 void	okpcntl(void);
     38 struct process	*pgetcurr(struct process *);
     39 struct process	*pfind(tchar *);
     40 
     41 /*
     42  * pchild - called at interrupt level by the SIGCHLD signal
     43  *	indicating that at least one child has terminated or stopped
     44  *	thus at least one wait system call will definitely return a
     45  *	childs status.  Top level routines (like pwait) must be sure
     46  *	to mask interrupts when playing with the proclist data structures!
     47  */
     48 void
     49 pchild(void)
     50 {
     51 	struct process *pp;
     52 	struct process	*fp;
     53 	int pid;
     54 	union wait w;
     55 	int jobflags;
     56 	struct rusage ru;
     57 
     58 #ifdef TRACE
     59 	tprintf("TRACE- pchile()\n");
     60 #endif
     61 loop:
     62 	pid = csh_wait3(&w, (setintr ? WNOHANG|WUNTRACED:WNOHANG), &ru);
     63 	/*
     64 	 * SysV sends a SIGCHLD when the child process
     65 	 * receives a SIGCONT, and result of that action is ignored here
     66 	 */
     67 	if (w.w_status == WCONTFLG)
     68 		return;
     69 	if (pid <= 0) {
     70 		if (errno == EINTR) {
     71 			errno = 0;
     72 			goto loop;
     73 		}
     74 		pnoprocesses = pid == -1;
     75 		return;
     76 	}
     77 	for (pp = proclist.p_next; pp != PNULL; pp = pp->p_next)
     78 		if (pid == pp->p_pid)
     79 			goto found;
     80 	goto loop;
     81 found:
     82 	if (pid == atoi_(value(S_child /* "child" */)))
     83 		unsetv(S_child /* "child" */);
     84 	pp->p_flags &= ~(PRUNNING|PSTOPPED|PREPORTED);
     85 	if (WIFSTOPPED(w)) {
     86 		pp->p_flags |= PSTOPPED;
     87 		pp->p_reason = w.w_stopsig;
     88 	} else {
     89 		if (pp->p_flags & (PTIME|PPTIME) || adrof(S_time /* "time" */))
     90 			(void) gettimeofday(&pp->p_etime, (struct timezone *)0);
     91 		pp->p_rusage = ru;
     92 		if (WIFSIGNALED(w)) {
     93 			if (w.w_termsig == SIGINT)
     94 				pp->p_flags |= PINTERRUPTED;
     95 			else
     96 				pp->p_flags |= PSIGNALED;
     97 			if (w.w_coredump)
     98 				pp->p_flags |= PDUMPED;
     99 			pp->p_reason = w.w_termsig;
    100 		} else {
    101 			pp->p_reason = w.w_retcode;
    102 			if (pp->p_reason != 0)
    103 				pp->p_flags |= PAEXITED;
    104 			else
    105 				pp->p_flags |= PNEXITED;
    106 		}
    107 	}
    108 	jobflags = 0;
    109 	fp = pp;
    110 	do {
    111 		if ((fp->p_flags & (PPTIME|PRUNNING|PSTOPPED)) == 0 &&
    112 		    !child && adrof(S_time /* "time" */) &&
    113 		    fp->p_rusage.ru_utime.tv_sec+fp->p_rusage.ru_stime.tv_sec >=
    114 		    atoi_(value(S_time /* "time" */)))
    115 			fp->p_flags |= PTIME;
    116 		jobflags |= fp->p_flags;
    117 	} while ((fp = fp->p_friends) != pp);
    118 	pp->p_flags &= ~PFOREGND;
    119 	if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
    120 		pp->p_flags &= ~PPTIME;
    121 		pp->p_flags |= PTIME;
    122 	}
    123 	if ((jobflags & (PRUNNING|PREPORTED)) == 0) {
    124 		fp = pp;
    125 		do {
    126 			if (fp->p_flags&PSTOPPED)
    127 				fp->p_flags |= PREPORTED;
    128 		} while ((fp = fp->p_friends) != pp);
    129 		while (fp->p_pid != fp->p_jobid)
    130 			fp = fp->p_friends;
    131 		if (jobflags&PSTOPPED) {
    132 			if (pcurrent && pcurrent != fp)
    133 				pprevious = pcurrent;
    134 			pcurrent = fp;
    135 		} else
    136 			pclrcurr(fp);
    137 		if (jobflags&PFOREGND) {
    138 			if (jobflags & (PSIGNALED|PSTOPPED|PPTIME) ||
    139 #ifdef IIASA
    140 			    jobflags & PAEXITED ||
    141 #endif
    142 			    !eq(dcwd->di_name, fp->p_cwd->di_name)) {
    143 				;	/* print in pjwait */
    144 			}
    145 		} else {
    146 			if (jobflags&PNOTIFY || adrof(S_notify /* "notify" */)) {
    147 				write_string("\015\n");
    148 				flush();
    149 				(void) pprint(pp, NUMBER|NAME|REASON);
    150 				if ((jobflags&PSTOPPED) == 0)
    151 					pflush(pp);
    152 			} else {
    153 				fp->p_flags |= PNEEDNOTE;
    154 				neednote++;
    155 			}
    156 		}
    157 	}
    158 	goto loop;
    159 }
    160 
    161 void
    162 pnote(void)
    163 {
    164 	struct process *pp;
    165 	int flags, omask;
    166 
    167 #ifdef TRACE
    168 	tprintf("TRACE- pnote()\n");
    169 #endif
    170 	neednote = 0;
    171 	for (pp = proclist.p_next; pp != PNULL; pp = pp->p_next) {
    172 		if (pp->p_flags & PNEEDNOTE) {
    173 			omask = sigblock(sigmask(SIGCHLD));
    174 			pp->p_flags &= ~PNEEDNOTE;
    175 			flags = pprint(pp, NUMBER|NAME|REASON);
    176 			if ((flags&(PRUNNING|PSTOPPED)) == 0)
    177 				pflush(pp);
    178 			(void) sigsetmask(omask);
    179 		}
    180 	}
    181 }
    182 
    183 /*
    184  * pwait - wait for current job to terminate, maintaining integrity
    185  *	of current and previous job indicators.
    186  */
    187 void
    188 pwait(void)
    189 {
    190 	struct process *fp, *pp;
    191 	int omask;
    192 
    193 #ifdef TRACE
    194 	tprintf("TRACE- pwait()\n");
    195 #endif
    196 	/*
    197 	 * Here's where dead procs get flushed.
    198 	 */
    199 	omask = sigblock(sigmask(SIGCHLD));
    200 	for (pp = (fp = &proclist)->p_next; pp != PNULL; pp = (fp = pp)->p_next)
    201 		if (pp->p_pid == 0) {
    202 			fp->p_next = pp->p_next;
    203 			xfree(pp->p_command);
    204 			if (pp->p_cwd && --pp->p_cwd->di_count == 0)
    205 				if (pp->p_cwd->di_next == 0)
    206 					dfree(pp->p_cwd);
    207 			xfree((tchar *)pp);
    208 			pp = fp;
    209 		}
    210 	(void) sigsetmask(omask);
    211 	pjwait(pcurrjob);
    212 }
    213 
    214 /*
    215  * pjwait - wait for a job to finish or become stopped
    216  *	It is assumed to be in the foreground state (PFOREGND)
    217  */
    218 void
    219 pjwait(struct process *pp)
    220 {
    221 	struct process *fp;
    222 	int jobflags, reason, omask;
    223 
    224 #ifdef TRACE
    225 	tprintf("TRACE- pjwait()\n");
    226 #endif
    227 	while (pp->p_pid != pp->p_jobid)
    228 		pp = pp->p_friends;
    229 	fp = pp;
    230 	do {
    231 		if ((fp->p_flags&(PFOREGND|PRUNNING)) == PRUNNING)
    232 			printf("BUG: waiting for background job!\n");
    233 	} while ((fp = fp->p_friends) != pp);
    234 	/*
    235 	 * Now keep pausing as long as we are not interrupted (SIGINT),
    236 	 * and the target process, or any of its friends, are running
    237 	 */
    238 	fp = pp;
    239 	omask = sigblock(sigmask(SIGCHLD));
    240 	for (;;) {
    241 		jobflags = 0;
    242 		do
    243 			jobflags |= fp->p_flags;
    244 		while ((fp = (fp->p_friends)) != pp);
    245 		if ((jobflags & PRUNNING) == 0)
    246 			break;
    247 		/*
    248 		 * At this point, csh used to call:
    249 		 *	sigpause(sigblock(0) &~ sigmask(SIGCHLD));
    250 		 * expecting to receive a SIGCHLD signal from the
    251 		 * termination of the child and to invoke the
    252 		 * signal handler, pchild(), as a result.
    253 		 *
    254 		 * However, vfork() now causes a vfork()'d child to
    255 		 * have all of its active signal handlers reset to
    256 		 * SIG_DFL, to forstall parent memory corruption due
    257 		 * to race conditions with signal handling.
    258 		 *
    259 		 * If this instance of csh is itself a child of vfork(),
    260 		 * which can happen when the top-level csh performs a
    261 		 * command substitution inside an i/o redirection, like:
    262 		 *	/bin/echo foo >`/bin/echo trash`
    263 		 * then we will never receive SIGCHLD.  To accommodate
    264 		 * this, we wait until one of our children terminates
    265 		 * (without actually reaping the child) and call the
    266 		 * SIGCHLD signal handler (pchild()) directly.
    267 		 */
    268 		if (csh_wait_noreap() > 0)
    269 			pchild();	/* simulate receipt of SIGCHLD */
    270 	}
    271 	(void) sigsetmask(omask);
    272 	if (tpgrp > 0)			/* get tty back */
    273 		(void) ioctl(FSHTTY, TIOCSPGRP,  (char *)&tpgrp);
    274 	if ((jobflags&(PSIGNALED|PSTOPPED|PTIME)) ||
    275 	    !eq(dcwd->di_name, fp->p_cwd->di_name)) {
    276 		if (jobflags&PSTOPPED)
    277 			printf("\n");
    278 		(void) pprint(pp, AREASON|SHELLDIR);
    279 	}
    280 	if ((jobflags&(PINTERRUPTED|PSTOPPED)) && setintr &&
    281 	    (!gointr || !eq(gointr, S_MINUS /* "-" */))) {
    282 		if ((jobflags & PSTOPPED) == 0)
    283 			pflush(pp);
    284 		pintr1(0);
    285 		/*NOTREACHED*/
    286 	}
    287 	reason = 0;
    288 	fp = pp;
    289 	do {
    290 		if (fp->p_reason)
    291 			reason = fp->p_flags & (PSIGNALED|PINTERRUPTED) ?
    292 				fp->p_reason | ABN_TERM : fp->p_reason;
    293 	} while ((fp = fp->p_friends) != pp);
    294 	set(S_status /* "status" */, putn(reason));
    295 	if (reason && exiterr)
    296 		exitstat();
    297 	pflush(pp);
    298 }
    299 
    300 /*
    301  * dowait - wait for all processes to finish
    302  */
    303 void
    304 dowait(void)
    305 {
    306 	struct process *pp;
    307 	int omask;
    308 
    309 #ifdef TRACE
    310 	tprintf("TRACE- dowait()\n");
    311 #endif
    312 	pjobs++;
    313 	omask = sigblock(sigmask(SIGCHLD));
    314 loop:
    315 	for (pp = proclist.p_next; pp; pp = pp->p_next)
    316 		if (pp->p_pid && /* pp->p_pid == pp->p_jobid && */
    317 		    pp->p_flags&PRUNNING) {
    318 			sigpause(0);
    319 			goto loop;
    320 		}
    321 	(void) sigsetmask(omask);
    322 	pjobs = 0;
    323 }
    324 
    325 /*
    326  * pflushall - flush all jobs from list (e.g. at fork())
    327  */
    328 void
    329 pflushall(void)
    330 {
    331 	struct process	*pp;
    332 
    333 #ifdef TRACE
    334 	tprintf("TRACE- pflush()\n");
    335 #endif
    336 	for (pp = proclist.p_next; pp != PNULL; pp = pp->p_next)
    337 		if (pp->p_pid)
    338 			pflush(pp);
    339 }
    340 
    341 /*
    342  * pflush - flag all process structures in the same job as the
    343  *	the argument process for deletion.  The actual free of the
    344  *	space is not done here since pflush is called at interrupt level.
    345  */
    346 void
    347 pflush(struct process *pp)
    348 {
    349 	struct process *np;
    350 	int index;
    351 
    352 #ifdef TRACE
    353 	tprintf("TRACE- pflush()\n");
    354 #endif
    355 	if (pp->p_pid == 0) {
    356 		printf("BUG: process flushed twice");
    357 		return;
    358 	}
    359 	while (pp->p_pid != pp->p_jobid)
    360 		pp = pp->p_friends;
    361 	pclrcurr(pp);
    362 	if (pp == pcurrjob)
    363 		pcurrjob = 0;
    364 	index = pp->p_index;
    365 	np = pp;
    366 	do {
    367 		np->p_index = np->p_pid = 0;
    368 		np->p_flags &= ~PNEEDNOTE;
    369 	} while ((np = np->p_friends) != pp);
    370 	if (index == pmaxindex) {
    371 		for (np = proclist.p_next, index = 0; np; np = np->p_next)
    372 			if (np->p_index > (tchar)index)
    373 				index = np->p_index;
    374 		pmaxindex = index;
    375 	}
    376 }
    377 
    378 /*
    379  * pclrcurr - make sure the given job is not the current or previous job;
    380  *	pp MUST be the job leader
    381  */
    382 void
    383 pclrcurr(struct process *pp)
    384 {
    385 
    386 #ifdef TRACE
    387 	tprintf("TRACE- pclrcurr()\n");
    388 #endif
    389 	if (pp == pcurrent)
    390 		if (pprevious != PNULL) {
    391 			pcurrent = pprevious;
    392 			pprevious = pgetcurr(pp);
    393 		} else {
    394 			pcurrent = pgetcurr(pp);
    395 			pprevious = pgetcurr(pp);
    396 		}
    397 	else if (pp == pprevious)
    398 		pprevious = pgetcurr(pp);
    399 }
    400 
    401 /* +4 here is 1 for '\0', 1 ea for << >& >> */
    402 tchar	command[PMAXLEN+4];
    403 int	cmdlen;
    404 tchar	*cmdp;
    405 /*
    406  * palloc - allocate a process structure and fill it up.
    407  *	an important assumption is made that the process is running.
    408  */
    409 void
    410 palloc(int pid, struct command *t)
    411 {
    412 	struct process	*pp;
    413 	int i;
    414 
    415 #ifdef TRACE
    416 	tprintf("TRACE- palloc()\n");
    417 #endif
    418 	pp = (struct process *)xcalloc(1, sizeof (struct process));
    419 	pp->p_pid = pid;
    420 	pp->p_flags = t->t_dflg & FAND ? PRUNNING : PRUNNING|PFOREGND;
    421 	if (t->t_dflg & FTIME)
    422 		pp->p_flags |= PPTIME;
    423 	cmdp = command;
    424 	cmdlen = 0;
    425 	padd(t);
    426 	*cmdp++ = 0;
    427 	if (t->t_dflg & FPOU) {
    428 		pp->p_flags |= PPOU;
    429 		if (t->t_dflg & FDIAG)
    430 			pp->p_flags |= PDIAG;
    431 	}
    432 	pp->p_command = savestr(command);
    433 	if (pcurrjob) {
    434 		struct process *fp;
    435 		/* careful here with interrupt level */
    436 		pp->p_cwd = 0;
    437 		pp->p_index = pcurrjob->p_index;
    438 		pp->p_friends = pcurrjob;
    439 		pp->p_jobid = pcurrjob->p_pid;
    440 		for (fp = pcurrjob; fp->p_friends != pcurrjob; fp = fp->p_friends)
    441 			;
    442 		fp->p_friends = pp;
    443 	} else {
    444 		pcurrjob = pp;
    445 		pp->p_jobid = pid;
    446 		pp->p_friends = pp;
    447 		pp->p_cwd = dcwd;
    448 		dcwd->di_count++;
    449 		if (pmaxindex < BIGINDEX)
    450 			pp->p_index = ++pmaxindex;
    451 		else {
    452 			struct process *np;
    453 
    454 			for (i = 1; ; i++) {
    455 				for (np = proclist.p_next; np; np = np->p_next)
    456 					if (np->p_index == i)
    457 						goto tryagain;
    458 				pp->p_index = i;
    459 				if (i > pmaxindex)
    460 					pmaxindex = i;
    461 				break;
    462 			tryagain:;
    463 			}
    464 		}
    465 		pprevious = pcurrent;
    466 		pcurrent = pp;
    467 	}
    468 	pp->p_next = proclist.p_next;
    469 	proclist.p_next = pp;
    470 	(void) gettimeofday(&pp->p_btime, (struct timezone *)0);
    471 }
    472 
    473 void
    474 padd(struct command *t)
    475 {
    476 	tchar **argp;
    477 
    478 #ifdef TRACE
    479 	tprintf("TRACE- padd()\n");
    480 #endif
    481 	if (t == 0)
    482 		return;
    483 	switch (t->t_dtyp) {
    484 
    485 	case TPAR:
    486 		pads(S_LBRASP /* "( " */);
    487 		padd(t->t_dspr);
    488 		pads(S_SPRBRA /* " )" */);
    489 		break;
    490 
    491 	case TCOM:
    492 		for (argp = t->t_dcom; *argp; argp++) {
    493 			pads(*argp);
    494 			if (argp[1])
    495 				pads(S_SP /* " " */);
    496 		}
    497 		break;
    498 
    499 	case TOR:
    500 	case TAND:
    501 	case TFIL:
    502 	case TLST:
    503 		padd(t->t_dcar);
    504 		switch (t->t_dtyp) {
    505 		case TOR:
    506 			pads(S_SPBARBARSP /* " || " */);
    507 			break;
    508 		case TAND:
    509 			pads(S_SPANDANDSP /* " && " */);
    510 			break;
    511 		case TFIL:
    512 			pads(S_SPBARSP /* " | " */);
    513 			break;
    514 		case TLST:
    515 			pads(S_SEMICOLONSP /* "; " */);
    516 			break;
    517 		}
    518 		padd(t->t_dcdr);
    519 		return;
    520 	}
    521 	if ((t->t_dflg & FPIN) == 0 && t->t_dlef) {
    522 		pads((t->t_dflg & FHERE) ? S_SPLESLESSP /* " << " */ : S_SPLESSP /* " < " */);
    523 		pads(t->t_dlef);
    524 	}
    525 	if ((t->t_dflg & FPOU) == 0 && t->t_drit) {
    526 		pads((t->t_dflg & FCAT) ? S_SPGTRGTRSP /* " >>" */ : S_SPGTR /* " >" */);
    527 		if (t->t_dflg & FDIAG)
    528 			pads(S_AND /* "&" */);
    529 		pads(S_SP /* " " */);
    530 		pads(t->t_drit);
    531 	}
    532 }
    533 
    534 void
    535 pads(tchar *cp)
    536 {
    537 	int i = strlen_(cp);
    538 
    539 #ifdef TRACE
    540 	tprintf("TRACE- pads()\n");
    541 #endif
    542 	if (cmdlen >= PMAXLEN)
    543 		return;
    544 	if (cmdlen + i >= PMAXLEN) {
    545 		(void) strcpy_(cmdp, S_SPPPP /* " ..." */);
    546 		cmdlen = PMAXLEN;
    547 		cmdp += 4;
    548 		return;
    549 	}
    550 	(void) strcpy_(cmdp, cp);
    551 	cmdp += i;
    552 	cmdlen += i;
    553 }
    554 
    555 /*
    556  * psavejob - temporarily save the current job on a one level stack
    557  *	so another job can be created.  Used for { } in exp6
    558  *	and `` in globbing.
    559  */
    560 void
    561 psavejob(void)
    562 {
    563 
    564 #ifdef TRACE
    565 	tprintf("TRACE- psavejob()\n");
    566 #endif
    567 	pholdjob = pcurrjob;
    568 	pcurrjob = PNULL;
    569 }
    570 
    571 /*
    572  * prestjob - opposite of psavejob.  This may be missed if we are interrupted
    573  *	somewhere, but pendjob cleans up anyway.
    574  */
    575 void
    576 prestjob(void)
    577 {
    578 
    579 #ifdef TRACE
    580 	tprintf("TRACE- prestjob()\n");
    581 #endif
    582 	pcurrjob = pholdjob;
    583 	pholdjob = PNULL;
    584 }
    585 
    586 /*
    587  * pendjob - indicate that a job (set of commands) has been completed
    588  *	or is about to begin.
    589  */
    590 void
    591 pendjob(void)
    592 {
    593 	struct process *pp, *tp;
    594 
    595 #ifdef TRACE
    596 	tprintf("TRACE- pendjob()\n");
    597 #endif
    598 	if (pcurrjob && (pcurrjob->p_flags&(PFOREGND|PSTOPPED)) == 0) {
    599 		pp = pcurrjob;
    600 		while (pp->p_pid != pp->p_jobid)
    601 			pp = pp->p_friends;
    602 		printf("[%d]", pp->p_index);
    603 		tp = pp;
    604 		do {
    605 			printf(" %d", pp->p_pid);
    606 			pp = pp->p_friends;
    607 		} while (pp != tp);
    608 		printf("\n");
    609 	}
    610 	pholdjob = pcurrjob = 0;
    611 }
    612 
    613 /*
    614  * pprint - print a job
    615  */
    616 int
    617 pprint(struct process *pp, int flag)
    618 {
    619 	int status, reason;
    620 	struct process *tp;
    621 	extern char *linp, linbuf[];
    622 	int jobflags, pstatus;
    623 	char *format;
    624 
    625 #ifdef TRACE
    626 	tprintf("TRACE- pprint()\n");
    627 #endif
    628 	while (pp->p_pid != pp->p_jobid)
    629 		pp = pp->p_friends;
    630 	if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
    631 		pp->p_flags &= ~PPTIME;
    632 		pp->p_flags |= PTIME;
    633 	}
    634 	tp = pp;
    635 	status = reason = -1;
    636 	jobflags = 0;
    637 	do {
    638 		jobflags |= pp->p_flags;
    639 		pstatus = pp->p_flags & PALLSTATES;
    640 		if (tp != pp && linp != linbuf && !(flag&FANCY) &&
    641 		    (pstatus == status && pp->p_reason == reason ||
    642 		    !(flag&REASON)))
    643 			printf(" ");
    644 		else {
    645 			if (tp != pp && linp != linbuf)
    646 				printf("\n");
    647 			if (flag&NUMBER)
    648 				if (pp == tp)
    649 					printf("[%d]%s %c ", pp->p_index,
    650 					    pp->p_index < 10 ? " " : "",
    651 					    pp == pcurrent ? '+' :
    652 						(pp == pprevious ? (tchar) '-'
    653 							: (tchar) ' '));
    654 				else
    655 					printf("       ");
    656 			if (flag&FANCY)
    657 				printf("%5d ", pp->p_pid);
    658 			if (flag&(REASON|AREASON)) {
    659 				if (flag&NAME)
    660 					format = "%-21s";
    661 				else
    662 					format = "%s";
    663 				if (pstatus == status)
    664 					if (pp->p_reason == reason) {
    665 						printf(format, "");
    666 						goto prcomd;
    667 					} else
    668 						reason = pp->p_reason;
    669 				else {
    670 					status = pstatus;
    671 					reason = pp->p_reason;
    672 				}
    673 				switch (status) {
    674 
    675 				case PRUNNING:
    676 					printf(format, "Running ");
    677 					break;
    678 
    679 				case PINTERRUPTED:
    680 				case PSTOPPED:
    681 				case PSIGNALED:
    682 					if ((flag&(REASON|AREASON))
    683 					    && reason != SIGINT
    684 					    && reason != SIGPIPE)
    685 						printf(format,
    686 						    strsignal(pp->p_reason));
    687 					break;
    688 
    689 				case PNEXITED:
    690 				case PAEXITED:
    691 					if (flag & REASON)
    692 						if (pp->p_reason)
    693 							printf("Exit %-16d", pp->p_reason);
    694 						else
    695 							printf(format, "Done");
    696 					break;
    697 
    698 				default:
    699 					printf("BUG: status=%-9o", status);
    700 				}
    701 			}
    702 		}
    703 prcomd:
    704 		if (flag&NAME) {
    705 			printf("%t", pp->p_command);
    706 			if (pp->p_flags & PPOU)
    707 				printf(" |");
    708 			if (pp->p_flags & PDIAG)
    709 				printf("&");
    710 		}
    711 		if (flag&(REASON|AREASON) && pp->p_flags&PDUMPED)
    712 			printf(" (core dumped)");
    713 		if (tp == pp->p_friends) {
    714 			if (flag&AMPERSAND)
    715 				printf(" &");
    716 			if (flag&JOBDIR &&
    717 			    !eq(tp->p_cwd->di_name, dcwd->di_name)) {
    718 				printf(" (wd: ");
    719 				dtildepr(value(S_home /* "home" */), tp->p_cwd->di_name);
    720 				printf(")");
    721 			}
    722 		}
    723 		if (pp->p_flags&PPTIME && !(status&(PSTOPPED|PRUNNING))) {
    724 			if (linp != linbuf)
    725 				printf("\n\t");
    726 			{ static struct rusage zru;
    727 			    prusage(&zru, &pp->p_rusage, &pp->p_etime,
    728 			    &pp->p_btime);
    729 			}
    730 		}
    731 		if (tp == pp->p_friends) {
    732 			if (linp != linbuf)
    733 				printf("\n");
    734 			if (flag&SHELLDIR && !eq(tp->p_cwd->di_name, dcwd->di_name)) {
    735 				printf("(wd now: ");
    736 				dtildepr(value(S_home /* "home" */), dcwd->di_name);
    737 				printf(")\n");
    738 			}
    739 		}
    740 	} while ((pp = pp->p_friends) != tp);
    741 	if (jobflags&PTIME && (jobflags&(PSTOPPED|PRUNNING)) == 0) {
    742 		if (jobflags & NUMBER)
    743 			printf("       ");
    744 		ptprint(tp);
    745 	}
    746 	return (jobflags);
    747 }
    748 
    749 void
    750 ptprint(struct process *tp)
    751 {
    752 	struct timeval tetime, diff;
    753 	static struct timeval ztime;
    754 	struct rusage ru;
    755 	static struct rusage zru;
    756 	struct process *pp = tp;
    757 
    758 #ifdef TRACE
    759 	tprintf("TRACE- ptprint()\n");
    760 #endif
    761 	ru = zru;
    762 	tetime = ztime;
    763 	do {
    764 		ruadd(&ru, &pp->p_rusage);
    765 		tvsub(&diff, &pp->p_etime, &pp->p_btime);
    766 		if (timercmp(&diff, &tetime, >))
    767 			tetime = diff;
    768 	} while ((pp = pp->p_friends) != tp);
    769 	prusage(&zru, &ru, &tetime, &ztime);
    770 }
    771 
    772 /*
    773  * dojobs - print all jobs
    774  */
    775 void
    776 dojobs(tchar **v)
    777 {
    778 	struct process *pp;
    779 	int flag = NUMBER|NAME|REASON;
    780 	int i;
    781 
    782 #ifdef TRACE
    783 	tprintf("TRACE- dojobs()\n");
    784 #endif
    785 	if (chkstop)
    786 		chkstop = 2;
    787 	if (*++v) {
    788 		if (v[1] || !eq(*v, S_DASHl /* "-l" */))
    789 			error("Usage: jobs [ -l ]");
    790 		flag |= FANCY|JOBDIR;
    791 	}
    792 	for (i = 1; i <= pmaxindex; i++)
    793 		for (pp = proclist.p_next; pp; pp = pp->p_next)
    794 			if (pp->p_index == i && pp->p_pid == pp->p_jobid) {
    795 				pp->p_flags &= ~PNEEDNOTE;
    796 				if (!(pprint(pp, flag) & (PRUNNING|PSTOPPED)))
    797 					pflush(pp);
    798 				break;
    799 			}
    800 }
    801 
    802 /*
    803  * dofg - builtin - put the job into the foreground
    804  */
    805 void
    806 dofg(tchar **v)
    807 {
    808 	struct process *pp;
    809 
    810 #ifdef TRACE
    811 	tprintf("TRACE- dofg()\n");
    812 #endif
    813 	okpcntl();
    814 	++v;
    815 	do {
    816 		pp = pfind(*v);
    817 		pstart(pp, 1);
    818 		pjwait(pp);
    819 	} while (*v && *++v);
    820 }
    821 
    822 /*
    823  * %... - builtin - put the job into the foreground
    824  */
    825 void
    826 dofg1(tchar **v)
    827 {
    828 	struct process *pp;
    829 
    830 #ifdef TRACE
    831 	tprintf("TRACE- untty()\n");
    832 #endif
    833 	okpcntl();
    834 	pp = pfind(v[0]);
    835 	pstart(pp, 1);
    836 	pjwait(pp);
    837 }
    838 
    839 /*
    840  * dobg - builtin - put the job into the background
    841  */
    842 void
    843 dobg(tchar **v)
    844 {
    845 	struct process *pp;
    846 
    847 #ifdef TRACE
    848 	tprintf("TRACE- dobg()\n");
    849 #endif
    850 	okpcntl();
    851 	++v;
    852 	do {
    853 		pp = pfind(*v);
    854 		pstart(pp, 0);
    855 	} while (*v && *++v);
    856 }
    857 
    858 /*
    859  * %... & - builtin - put the job into the background
    860  */
    861 void
    862 dobg1(tchar **v)
    863 {
    864 	struct process *pp;
    865 
    866 #ifdef TRACE
    867 	tprintf("TRACE- dobg1()\n");
    868 #endif
    869 	pp = pfind(v[0]);
    870 	pstart(pp, 0);
    871 }
    872 
    873 /*
    874  * dostop - builtin - stop the job
    875  */
    876 void
    877 dostop(tchar **v)
    878 {
    879 
    880 #ifdef TRACE
    881 	tprintf("TRACE- dostop()\n");
    882 #endif
    883 	pkill(++v, SIGSTOP);
    884 }
    885 
    886 /*
    887  * dokill - builtin - superset of kill (1)
    888  */
    889 void
    890 dokill(tchar **v)
    891 {
    892 	int signum;
    893 	tchar *name;
    894 
    895 #ifdef TRACE
    896 	tprintf("TRACE- dokill()\n");
    897 #endif
    898 	v++;
    899 	if (v[0] && v[0][0] == '-') {
    900 		if (v[0][1] == 'l') {
    901 			for (signum = 1; signum <= NSIG-1; signum++) {
    902 				char	sbuf[BUFSIZ];
    903 				if (sig2str(signum, sbuf) == 0)
    904 					printf("%s ", sbuf);
    905 				if (signum % 8 == 0)
    906 					Putchar('\n');
    907 			}
    908 			Putchar('\n');
    909 			return;
    910 		}
    911 		if (digit(v[0][1])) {
    912 			if (chkalldigit_(v[0]+1) != 0) {
    913 				setname(v[0]+1);
    914 				bferr("Unknown signal; kill -l lists signals");
    915 			}
    916 			signum = atoi_(v[0]+1);
    917 			if (signum < 0 || signum > NSIG)
    918 				bferr("Bad signal number");
    919 		} else {
    920 			int	signo;
    921 			char	sbuf[BUFSIZ];
    922 			name = &v[0][1];
    923 			tstostr(sbuf, name);
    924 			if (str2sig(sbuf, &signo) == 0) {
    925 				signum = signo;
    926 				goto gotsig;
    927 			}
    928 			if (eq(name, S_IOT /* "IOT" */)) {
    929 				signum = SIGABRT;
    930 				goto gotsig;
    931 			}
    932 			setname(name);
    933 			bferr("Unknown signal; kill -l lists signals");
    934 		}
    935 gotsig:
    936 		v++;
    937 	} else
    938 		signum = SIGTERM;
    939 	pkill(v, signum);
    940 }
    941 
    942 void
    943 pkill(tchar **v, int signum)
    944 {
    945 	struct process *pp, *np;
    946 	int jobflags = 0;
    947 	int omask, pid, err = 0;
    948 	tchar *cp;
    949 
    950 #ifdef TRACE
    951 	tprintf("TRACE- pkill()\n");
    952 #endif
    953 	omask = sigmask(SIGCHLD);
    954 	if (setintr)
    955 		omask |= sigmask(SIGINT);
    956 	omask = sigblock(omask) & ~omask;
    957 	while (*v) {
    958 		cp = globone(*v);
    959 		if (*cp == '%') {
    960 			np = pp = pfind(cp);
    961 			do
    962 				jobflags |= np->p_flags;
    963 			while ((np = np->p_friends) != pp);
    964 			switch (signum) {
    965 
    966 			case SIGSTOP:
    967 			case SIGTSTP:
    968 			case SIGTTIN:
    969 			case SIGTTOU:
    970 				if ((jobflags & PRUNNING) == 0) {
    971 					/* %s -> %t */
    972 					printf("%t: Already stopped\n", cp);
    973 					err++;
    974 					goto cont;
    975 				}
    976 			}
    977 			if (killpg(pp->p_jobid, signum) < 0) {
    978 				/* %s -> %t */
    979 				printf("%t: ", cp);
    980 				printf("%s\n", strerror(errno));
    981 				err++;
    982 			}
    983 			if (signum == SIGTERM || signum == SIGHUP)
    984 				(void) killpg(pp->p_jobid, SIGCONT);
    985 		} else if (!(digit(*cp) || *cp == '-'))
    986 			bferr("Arguments should be jobs or process id's");
    987 		else {
    988 			pid = atoi_(cp);
    989 			if (kill(pid, signum) < 0) {
    990 				printf("%d: ", pid);
    991 				printf("%s\n", strerror(errno));
    992 				err++;
    993 				goto cont;
    994 			}
    995 			if (signum == SIGTERM || signum == SIGHUP)
    996 				(void) kill(pid, SIGCONT);
    997 		}
    998 cont:
    999 		xfree(cp);
   1000 		v++;
   1001 	}
   1002 	(void) sigsetmask(omask);
   1003 	if (err)
   1004 		error(NULL);
   1005 }
   1006 
   1007 /*
   1008  * pstart - start the job in foreground/background
   1009  */
   1010 void
   1011 pstart(struct process *pp, int foregnd)
   1012 {
   1013 	struct process *np;
   1014 	int omask, jobflags = 0;
   1015 
   1016 #ifdef TRACE
   1017 	tprintf("TRACE- pstart()\n");
   1018 #endif
   1019 	omask = sigblock(sigmask(SIGCHLD));
   1020 	np = pp;
   1021 	do {
   1022 		jobflags |= np->p_flags;
   1023 		if (np->p_flags&(PRUNNING|PSTOPPED)) {
   1024 			np->p_flags |= PRUNNING;
   1025 			np->p_flags &= ~PSTOPPED;
   1026 			if (foregnd)
   1027 				np->p_flags |= PFOREGND;
   1028 			else
   1029 				np->p_flags &= ~PFOREGND;
   1030 		}
   1031 	} while ((np = np->p_friends) != pp);
   1032 
   1033 	if (foregnd)
   1034 		pclrcurr(pp);
   1035 	else
   1036 	{
   1037 		if (pprevious && (pprevious->p_flags & PSTOPPED))
   1038 		{
   1039 			pcurrent = pprevious;
   1040 			pprevious = pgetcurr(PNULL);
   1041 		}
   1042 		else
   1043 		{
   1044 			pcurrent = pgetcurr(pp);
   1045 			if (!pcurrent || (pcurrent->p_flags & PRUNNING))
   1046 				pcurrent = pp;
   1047 			else
   1048 				pprevious = pp;
   1049 		}
   1050 	}
   1051 	(void) pprint(pp, foregnd ? NAME|JOBDIR : NUMBER|NAME|AMPERSAND);
   1052 	if (foregnd)
   1053 		(void) ioctl(FSHTTY, TIOCSPGRP,  (char *)&pp->p_jobid);
   1054 	if (jobflags&PSTOPPED)
   1055 		(void) killpg(pp->p_jobid, SIGCONT);
   1056 	(void) sigsetmask(omask);
   1057 }
   1058 
   1059 void
   1060 panystop(int neednl)
   1061 {
   1062 	struct process *pp;
   1063 
   1064 #ifdef TRACE
   1065 	tprintf("TRACE- panystop()\n");
   1066 #endif
   1067 	chkstop = 2;
   1068 	for (pp = proclist.p_next; pp; pp = pp->p_next)
   1069 		if (pp->p_flags & PSTOPPED)
   1070 			error("\nThere are stopped jobs" + 1 - neednl);
   1071 }
   1072 
   1073 struct process *
   1074 pfind(tchar *cp)
   1075 {
   1076 	struct process *pp, *np;
   1077 
   1078 #ifdef TRACE
   1079 	tprintf("TRACE- pfind()\n");
   1080 #endif
   1081 	if (cp == 0 || cp[1] == 0 || eq(cp, S_PARCENTPARCENT /* "%%" */) ||
   1082 					eq(cp, S_PARCENTPLUS /* "%+" */)) {
   1083 		if (pcurrent == PNULL)
   1084 			if ((pcurrent = pgetcurr(PNULL)) == PNULL)
   1085 				bferr("No current job");
   1086 		return (pcurrent);
   1087 	}
   1088 	if (eq(cp, S_PARCENTMINUS /* "%-" */) ||
   1089 	    eq(cp, S_PARCENTSHARP /* "%#" */)) {
   1090 		if (pprevious == PNULL)
   1091 			bferr("No previous job");
   1092 		return (pprevious);
   1093 	}
   1094 	if (digit(cp[1])) {
   1095 		int index = atoi_(cp+1);
   1096 		for (pp = proclist.p_next; pp; pp = pp->p_next)
   1097 			if (pp->p_index == index && pp->p_pid == pp->p_jobid)
   1098 				return (pp);
   1099 		bferr("No such job");
   1100 	}
   1101 	np = PNULL;
   1102 	for (pp = proclist.p_next; pp; pp = pp->p_next)
   1103 		if (pp->p_pid == pp->p_jobid) {
   1104 			if (cp[1] == '?') {
   1105 				tchar *dp;
   1106 				for (dp = pp->p_command; *dp; dp++) {
   1107 					if (*dp != cp[2])
   1108 						continue;
   1109 					if (prefix(cp+2, dp))
   1110 						goto match;
   1111 				}
   1112 			} else if (prefix(cp+1, pp->p_command)) {
   1113 match:
   1114 				if (np)
   1115 					bferr("Ambiguous");
   1116 				np = pp;
   1117 			}
   1118 		}
   1119 	if (np)
   1120 		return (np);
   1121 	if (cp[1] == '?')
   1122 		bferr("No job matches pattern");
   1123 	else
   1124 		bferr("No such job");
   1125 	/*NOTREACHED*/
   1126 }
   1127 
   1128 /*
   1129  * pgetcurr - find most recent job that is not pp, preferably stopped
   1130  */
   1131 struct process *
   1132 pgetcurr(struct process *pp)
   1133 {
   1134 	struct process *np;
   1135 	struct process *xp = PNULL;
   1136 
   1137 #ifdef TRACE
   1138 	tprintf("TRACE- pgetcurr()\n");
   1139 #endif
   1140 	for (np = proclist.p_next; np; np = np->p_next)
   1141 		if (np != pcurrent && np != pp && np->p_pid &&
   1142 		    np->p_pid == np->p_jobid) {
   1143 			if (np->p_flags & PSTOPPED)
   1144 				return (np);
   1145 			if (xp == PNULL)
   1146 				xp = np;
   1147 		}
   1148 	return (xp);
   1149 }
   1150 
   1151 /*
   1152  * donotify - flag the job so as to report termination asynchronously
   1153  */
   1154 void
   1155 donotify(tchar **v)
   1156 {
   1157 	struct process *pp;
   1158 
   1159 #ifdef TRACE
   1160 	tprintf("TRACE- donotify()\n");
   1161 #endif
   1162 	pp = pfind(*++v);
   1163 	pp->p_flags |= PNOTIFY;
   1164 }
   1165 
   1166 /*
   1167  * Do the fork and whatever should be done in the child side that
   1168  * should not be done if we are not forking at all (like for simple builtin's)
   1169  * Also do everything that needs any signals fiddled with in the parent side
   1170  *
   1171  * Wanttty tells whether process and/or tty pgrps are to be manipulated:
   1172  *	-1:	leave tty alone; inherit pgrp from parent
   1173  *	 0:	already have tty; manipulate process pgrps only
   1174  *	 1:	want to claim tty; manipulate process and tty pgrps
   1175  * It is usually just the value of tpgrp.
   1176  *
   1177  * argument:
   1178  *	 t:	command we are forking for
   1179  */
   1180 int
   1181 pfork(struct command *t, int wanttty)
   1182 {
   1183 	int pid;
   1184 	bool ignint = 0;
   1185 	int pgrp, omask;
   1186 	int child_pid;
   1187 
   1188 #ifdef TRACE
   1189 	tprintf("TRACE- pfork()\n");
   1190 #endif
   1191 	/*
   1192 	 * A child will be uninterruptible only under very special
   1193 	 * conditions. Remember that the semantics of '&' is
   1194 	 * implemented by disconnecting the process from the tty so
   1195 	 * signals do not need to ignored just for '&'.
   1196 	 * Thus signals are set to default action for children unless:
   1197 	 *	we have had an "onintr -" (then specifically ignored)
   1198 	 *	we are not playing with signals (inherit action)
   1199 	 */
   1200 	if (setintr)
   1201 		ignint = (tpgrp == -1 && (t->t_dflg&FINT))
   1202 		    || (gointr && eq(gointr, S_MINUS /* "-" */));
   1203 	/*
   1204 	 * Hold SIGCHLD until we have the process installed in our table.
   1205 	 */
   1206 	omask = sigblock(sigmask(SIGCHLD));
   1207 	while ((pid = fork()) < 0)
   1208 		if (setintr == 0)
   1209 			sleep(FORKSLEEP);
   1210 		else {
   1211 			(void) sigsetmask(omask);
   1212 			error("Fork failed");
   1213 		}
   1214 
   1215 	/*
   1216 	 * setup the process group
   1217 	 */
   1218 	if (pid == 0)
   1219 		child_pid = getpid();
   1220 	else
   1221 		child_pid = pid;
   1222 	pgrp = pcurrjob ? pcurrjob->p_jobid : child_pid;
   1223 
   1224 	if (pid == 0) {
   1225 		int sigttou;
   1226 		settimes();
   1227 		pflushall();
   1228 		pcurrjob = PNULL;
   1229 		child++;
   1230 		if (setintr) {
   1231 			setintr = 0;		/* until I think otherwise */
   1232 			/*
   1233 			 * Children just get blown away on SIGINT, SIGQUIT
   1234 			 * unless "onintr -" seen.
   1235 			 */
   1236 			(void) signal(SIGINT, ignint ? SIG_IGN : SIG_DFL);
   1237 			(void) signal(SIGQUIT, ignint ? SIG_IGN : SIG_DFL);
   1238 			if (wanttty >= 0) {
   1239 				/* make stoppable */
   1240 				(void) signal(SIGTSTP, SIG_DFL);
   1241 				(void) signal(SIGTTIN, SIG_DFL);
   1242 				(void) signal(SIGTTOU, SIG_DFL);
   1243 			}
   1244 			(void) signal(SIGTERM, parterm);
   1245 		} else if (tpgrp == -1 && (t->t_dflg&FINT)) {
   1246 			(void) signal(SIGINT, SIG_IGN);
   1247 			(void) signal(SIGQUIT, SIG_IGN);
   1248 		}
   1249 		if (wanttty >= 0 && tpgrp >= 0)
   1250 			(void) setpgid(0, pgrp);
   1251 		if (wanttty > 0) {
   1252 			sigttou = sigblock(sigmask(SIGTTOU) |
   1253 					    sigmask(SIGTTIN) |
   1254 					    sigmask(SIGTSTP));
   1255 			(void) ioctl(FSHTTY, TIOCSPGRP,  (char *)&pgrp);
   1256 			sigsetmask(sigttou);
   1257 		}
   1258 		if (tpgrp > 0)
   1259 			tpgrp = 0;		/* gave tty away */
   1260 		/*
   1261 		 * Nohup and nice apply only to TCOM's but it would be
   1262 		 * nice (?!?) if you could say "nohup (foo;bar)"
   1263 		 * Then the parser would have to know about nice/nohup/time
   1264 		 */
   1265 		if (t->t_dflg & FNOHUP)
   1266 			(void) signal(SIGHUP, SIG_IGN);
   1267 		if (t->t_dflg & FNICE)
   1268 			(void) setpriority(PRIO_PROCESS, 0, t->t_nice);
   1269 	} else {
   1270 		if (wanttty >= 0 && tpgrp >= 0)
   1271 			setpgid(pid, pgrp);
   1272 		palloc(pid, t);
   1273 		(void) sigsetmask(omask);
   1274 	}
   1275 
   1276 	return (pid);
   1277 }
   1278 
   1279 void
   1280 okpcntl(void)
   1281 {
   1282 #ifdef TRACE
   1283 	tprintf("TRACE- okpcntl()\n");
   1284 #endif
   1285 
   1286 	if (tpgrp == -1)
   1287 		error("No job control in this shell");
   1288 	if (tpgrp == 0)
   1289 		error("No job control in subshells");
   1290 }
   1291 
   1292 void
   1293 hupforegnd(void)
   1294 {
   1295 	struct process *pp;
   1296 	int omask;
   1297 
   1298 	omask = sigblock(sigmask(SIGCHLD));
   1299 	for (pp = (&proclist)->p_next; pp != PNULL; pp = pp->p_next)
   1300 		if (pp->p_pid > 0) {
   1301 			if (pp->p_flags & PFOREGND)
   1302 				(void) kill(pp->p_pid, SIGHUP);
   1303 		}
   1304 	(void) sigsetmask(omask);
   1305 }
   1306