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