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