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