xref: /titanic_52/usr/src/cmd/csh/sh.proc.c (revision eaacacc0c33d7b79a8156d9b3e07dbb4354eb2d6)
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