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