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