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