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