xref: /original-bsd/bin/csh/proc.c (revision d54be081)
1 /*-
2  * Copyright (c) 1980, 1991 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)proc.c	5.22 (Berkeley) 06/14/91";
10 #endif /* not lint */
11 
12 #include <sys/types.h>
13 #include <sys/wait.h>
14 #include <errno.h>
15 #include <unistd.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #if __STDC__
19 # include <stdarg.h>
20 #else
21 # include <varargs.h>
22 #endif
23 
24 #include "csh.h"
25 #include "dir.h"
26 #include "proc.h"
27 #include "extern.h"
28 
29 #define BIGINDEX	9	/* largest desirable job index */
30 
31 static struct rusage zru;
32 
33 static void	 pflushall __P((void));
34 static void	 pflush __P((struct process *));
35 static void	 pclrcurr __P((struct process *));
36 static void	 padd __P((struct command *));
37 static int	 pprint __P((struct process *, int));
38 static void	 ptprint __P((struct process *));
39 static void	 pads __P((Char *));
40 static void	 pkill __P((Char **v, int));
41 static struct	process
42 		*pgetcurr __P((struct process *));
43 static void	 okpcntl __P((void));
44 
45 /*
46  * pchild - called at interrupt level by the SIGCHLD signal
47  *	indicating that at least one child has terminated or stopped
48  *	thus at least one wait system call will definitely return a
49  *	childs status.  Top level routines (like pwait) must be sure
50  *	to mask interrupts when playing with the proclist data structures!
51  */
52 /* ARGUSED */
53 void
54 pchild(notused)
55 	int notused;
56 {
57     register struct process *pp;
58     register struct process *fp;
59     register int pid;
60     extern int insource;
61     union wait w;
62     int     jobflags;
63     struct rusage ru;
64 
65 loop:
66     errno = 0;			/* reset, just in case */
67     pid = wait3(&w.w_status,
68        (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru);
69 
70     if (pid <= 0) {
71 	if (errno == EINTR) {
72 	    errno = 0;
73 	    goto loop;
74 	}
75 	pnoprocesses = pid == -1;
76 	return;
77     }
78     for (pp = proclist.p_next; pp != NULL; pp = pp->p_next)
79 	if (pid == pp->p_pid)
80 	    goto found;
81     goto loop;
82 found:
83     if (pid == atoi(short2str(value(STRchild))))
84 	unsetv(STRchild);
85     pp->p_flags &= ~(PRUNNING | PSTOPPED | PREPORTED);
86     if (WIFSTOPPED(w)) {
87 	pp->p_flags |= PSTOPPED;
88 	pp->p_reason = w.w_stopsig;
89     }
90     else {
91 	if (pp->p_flags & (PTIME | PPTIME) || adrof(STRtime))
92 	    (void) gettimeofday(&pp->p_etime, NULL);
93 
94 	pp->p_rusage = ru;
95 	if (WIFSIGNALED(w)) {
96 	    if (w.w_termsig == SIGINT)
97 		pp->p_flags |= PINTERRUPTED;
98 	    else
99 		pp->p_flags |= PSIGNALED;
100 	    if (w.w_coredump)
101 		pp->p_flags |= PDUMPED;
102 	    pp->p_reason = w.w_termsig;
103 	}
104 	else {
105 	    pp->p_reason = w.w_retcode;
106 	    if (pp->p_reason != 0)
107 		pp->p_flags |= PAEXITED;
108 	    else
109 		pp->p_flags |= PNEXITED;
110 	}
111     }
112     jobflags = 0;
113     fp = pp;
114     do {
115 	if ((fp->p_flags & (PPTIME | PRUNNING | PSTOPPED)) == 0 &&
116 	    !child && adrof(STRtime) &&
117 	    fp->p_rusage.ru_utime.tv_sec + fp->p_rusage.ru_stime.tv_sec
118 	    >= atoi(short2str(value(STRtime))))
119 	    fp->p_flags |= PTIME;
120 	jobflags |= fp->p_flags;
121     } while ((fp = fp->p_friends) != pp);
122     pp->p_flags &= ~PFOREGND;
123     if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
124 	pp->p_flags &= ~PPTIME;
125 	pp->p_flags |= PTIME;
126     }
127     if ((jobflags & (PRUNNING | PREPORTED)) == 0) {
128 	fp = pp;
129 	do {
130 	    if (fp->p_flags & PSTOPPED)
131 		fp->p_flags |= PREPORTED;
132 	} while ((fp = fp->p_friends) != pp);
133 	while (fp->p_pid != fp->p_jobid)
134 	    fp = fp->p_friends;
135 	if (jobflags & PSTOPPED) {
136 	    if (pcurrent && pcurrent != fp)
137 		pprevious = pcurrent;
138 	    pcurrent = fp;
139 	}
140 	else
141 	    pclrcurr(fp);
142 	if (jobflags & PFOREGND) {
143 	    if (jobflags & (PSIGNALED | PSTOPPED | PPTIME) ||
144 #ifdef IIASA
145 		jobflags & PAEXITED ||
146 #endif
147 		!eq(dcwd->di_name, fp->p_cwd->di_name)) {
148 		;		/* print in pjwait */
149 	    }
150 	    /* PWP: print a newline after ^C */
151 	    else if (jobflags & PINTERRUPTED)
152 		xputchar('\r' | QUOTE), xputchar('\n');
153 	}
154 	else {
155 	    if (jobflags & PNOTIFY || adrof(STRnotify)) {
156 		xputchar('\r' | QUOTE), xputchar('\n');
157 		(void) pprint(pp, NUMBER | NAME | REASON);
158 		if ((jobflags & PSTOPPED) == 0)
159 		    pflush(pp);
160 	    }
161 	    else {
162 		fp->p_flags |= PNEEDNOTE;
163 		neednote++;
164 	    }
165 	}
166     }
167     goto loop;
168 }
169 
170 void
171 pnote()
172 {
173     register struct process *pp;
174     int     flags;
175     sigset_t omask;
176 
177     neednote = 0;
178     for (pp = proclist.p_next; pp != NULL; pp = pp->p_next) {
179 	if (pp->p_flags & PNEEDNOTE) {
180 	    omask = sigblock(sigmask(SIGCHLD));
181 	    pp->p_flags &= ~PNEEDNOTE;
182 	    flags = pprint(pp, NUMBER | NAME | REASON);
183 	    if ((flags & (PRUNNING | PSTOPPED)) == 0)
184 		pflush(pp);
185 	    (void) sigsetmask(omask);
186 	}
187     }
188 }
189 
190 /*
191  * pwait - wait for current job to terminate, maintaining integrity
192  *	of current and previous job indicators.
193  */
194 void
195 pwait()
196 {
197     register struct process *fp, *pp;
198     sigset_t omask;
199 
200     /*
201      * Here's where dead procs get flushed.
202      */
203     omask = sigblock(sigmask(SIGCHLD));
204     for (pp = (fp = &proclist)->p_next; pp != NULL; pp = (fp = pp)->p_next)
205 	if (pp->p_pid == 0) {
206 	    fp->p_next = pp->p_next;
207 	    xfree((ptr_t) pp->p_command);
208 	    if (pp->p_cwd && --pp->p_cwd->di_count == 0)
209 		if (pp->p_cwd->di_next == 0)
210 		    dfree(pp->p_cwd);
211 	    xfree((ptr_t) pp);
212 	    pp = fp;
213 	}
214     (void) sigsetmask(omask);
215     pjwait(pcurrjob);
216 }
217 
218 
219 /*
220  * pjwait - wait for a job to finish or become stopped
221  *	It is assumed to be in the foreground state (PFOREGND)
222  */
223 void
224 pjwait(pp)
225     register struct process *pp;
226 {
227     register struct process *fp;
228     int     jobflags, reason;
229     sigset_t omask;
230 
231     while (pp->p_pid != pp->p_jobid)
232 	pp = pp->p_friends;
233     fp = pp;
234 
235     do {
236 	if ((fp->p_flags & (PFOREGND | PRUNNING)) == PRUNNING)
237 	    xprintf("BUG: waiting for background job!\n");
238     } while ((fp = fp->p_friends) != pp);
239     /*
240      * Now keep pausing as long as we are not interrupted (SIGINT), and the
241      * target process, or any of its friends, are running
242      */
243     fp = pp;
244     omask = sigblock(sigmask(SIGCHLD));
245     for (;;) {
246 	(void) sigblock(sigmask(SIGCHLD));
247 	jobflags = 0;
248 	do
249 	    jobflags |= fp->p_flags;
250 	while ((fp = (fp->p_friends)) != pp);
251 	if ((jobflags & PRUNNING) == 0)
252 	    break;
253 #ifdef JOBDEBUG
254 	xprintf("starting to sigpause for  SIGCHLD on %d\n", fp->p_pid);
255 #endif				/* JOBDEBUG */
256 	(void) sigpause(omask & ~sigmask(SIGCHLD));
257     }
258     (void) sigsetmask(omask);
259     if (tpgrp > 0)		/* get tty back */
260 	(void) tcsetpgrp(FSHTTY, tpgrp);
261     if ((jobflags & (PSIGNALED | PSTOPPED | PTIME)) ||
262 	!eq(dcwd->di_name, fp->p_cwd->di_name)) {
263 	if (jobflags & PSTOPPED) {
264 	    xprintf("\n");
265 	    if (adrof(STRlistjobs)) {
266 		Char   *jobcommand[3];
267 
268 		jobcommand[0] = STRjobs;
269 		if (eq(value(STRlistjobs), STRlong))
270 		    jobcommand[1] = STRml;
271 		else
272 		    jobcommand[1] = NULL;
273 		jobcommand[2] = NULL;
274 
275 		dojobs(jobcommand);
276 		(void) pprint(pp, SHELLDIR);
277 	    }
278 	    else
279 		(void) pprint(pp, AREASON | SHELLDIR);
280 	}
281 	else
282 	    (void) pprint(pp, AREASON | SHELLDIR);
283     }
284     if ((jobflags & (PINTERRUPTED | PSTOPPED)) && setintr &&
285 	(!gointr || !eq(gointr, STRminus))) {
286 	if ((jobflags & PSTOPPED) == 0)
287 	    pflush(pp);
288 	pintr1(0);
289 	/* NOTREACHED */
290     }
291     reason = 0;
292     fp = pp;
293     do {
294 	if (fp->p_reason)
295 	    reason = fp->p_flags & (PSIGNALED | PINTERRUPTED) ?
296 		fp->p_reason | META : fp->p_reason;
297     } while ((fp = fp->p_friends) != pp);
298     if ((reason != 0) && (adrof(STRprintexitvalue)))
299 	xprintf("Exit %d\n", reason);
300     set(STRstatus, putn(reason));
301     if (reason && exiterr)
302 	exitstat();
303     pflush(pp);
304 }
305 
306 /*
307  * dowait - wait for all processes to finish
308  */
309 void
310 dowait()
311 {
312     register struct process *pp;
313     sigset_t omask;
314 
315     pjobs++;
316     omask = sigblock(sigmask(SIGCHLD));
317 loop:
318     for (pp = proclist.p_next; pp; pp = pp->p_next)
319 	if (pp->p_pid &&	/* pp->p_pid == pp->p_jobid && */
320 	    pp->p_flags & PRUNNING) {
321 	    (void) sigpause((sigset_t) 0);
322 	    goto loop;
323 	}
324     (void) sigsetmask(omask);
325     pjobs = 0;
326 }
327 
328 /*
329  * pflushall - flush all jobs from list (e.g. at fork())
330  */
331 static void
332 pflushall()
333 {
334     register struct process *pp;
335 
336     for (pp = proclist.p_next; pp != NULL; pp = pp->p_next)
337 	if (pp->p_pid)
338 	    pflush(pp);
339 }
340 
341 /*
342  * pflush - flag all process structures in the same job as the
343  *	the argument process for deletion.  The actual free of the
344  *	space is not done here since pflush is called at interrupt level.
345  */
346 static void
347 pflush(pp)
348     register struct process *pp;
349 {
350     register struct process *np;
351     register int idx;
352 
353     if (pp->p_pid == 0) {
354 	xprintf("BUG: process flushed twice");
355 	return;
356     }
357     while (pp->p_pid != pp->p_jobid)
358 	pp = pp->p_friends;
359     pclrcurr(pp);
360     if (pp == pcurrjob)
361 	pcurrjob = 0;
362     idx = pp->p_index;
363     np = pp;
364     do {
365 	np->p_index = np->p_pid = 0;
366 	np->p_flags &= ~PNEEDNOTE;
367     } while ((np = np->p_friends) != pp);
368     if (idx == pmaxindex) {
369 	for (np = proclist.p_next, idx = 0; np; np = np->p_next)
370 	    if (np->p_index > idx)
371 		idx = np->p_index;
372 	pmaxindex = idx;
373     }
374 }
375 
376 /*
377  * pclrcurr - make sure the given job is not the current or previous job;
378  *	pp MUST be the job leader
379  */
380 static void
381 pclrcurr(pp)
382     register struct process *pp;
383 {
384 
385     if (pp == pcurrent)
386 	if (pprevious != NULL) {
387 	    pcurrent = pprevious;
388 	    pprevious = pgetcurr(pp);
389 	}
390 	else {
391 	    pcurrent = pgetcurr(pp);
392 	    pprevious = pgetcurr(pp);
393 	}
394     else if (pp == pprevious)
395 	pprevious = pgetcurr(pp);
396 }
397 
398 /* +4 here is 1 for '\0', 1 ea for << >& >> */
399 static Char command[PMAXLEN + 4];
400 static int cmdlen;
401 static Char *cmdp;
402 
403 /*
404  * palloc - allocate a process structure and fill it up.
405  *	an important assumption is made that the process is running.
406  */
407 void
408 palloc(pid, t)
409     int     pid;
410     register struct command *t;
411 {
412     register struct process *pp;
413     int     i;
414 
415     pp = (struct process *) xcalloc(1, (size_t) sizeof(struct process));
416     pp->p_pid = pid;
417     pp->p_flags = t->t_dflg & F_AMPERSAND ? PRUNNING : PRUNNING | PFOREGND;
418     if (t->t_dflg & F_TIME)
419 	pp->p_flags |= PPTIME;
420     cmdp = command;
421     cmdlen = 0;
422     padd(t);
423     *cmdp++ = 0;
424     if (t->t_dflg & F_PIPEOUT) {
425 	pp->p_flags |= PPOU;
426 	if (t->t_dflg & F_STDERR)
427 	    pp->p_flags |= PDIAG;
428     }
429     pp->p_command = Strsave(command);
430     if (pcurrjob) {
431 	struct process *fp;
432 
433 	/* careful here with interrupt level */
434 	pp->p_cwd = 0;
435 	pp->p_index = pcurrjob->p_index;
436 	pp->p_friends = pcurrjob;
437 	pp->p_jobid = pcurrjob->p_pid;
438 	for (fp = pcurrjob; fp->p_friends != pcurrjob; fp = fp->p_friends);
439 	fp->p_friends = pp;
440     }
441     else {
442 	pcurrjob = pp;
443 	pp->p_jobid = pid;
444 	pp->p_friends = pp;
445 	pp->p_cwd = dcwd;
446 	dcwd->di_count++;
447 	if (pmaxindex < BIGINDEX)
448 	    pp->p_index = ++pmaxindex;
449 	else {
450 	    struct process *np;
451 
452 	    for (i = 1;; i++) {
453 		for (np = proclist.p_next; np; np = np->p_next)
454 		    if (np->p_index == i)
455 			goto tryagain;
456 		pp->p_index = i;
457 		if (i > pmaxindex)
458 		    pmaxindex = i;
459 		break;
460 	tryagain:;
461 	    }
462 	}
463 	if (pcurrent == NULL)
464 	    pcurrent = pp;
465 	else if (pprevious == NULL)
466 	    pprevious = pp;
467     }
468     pp->p_next = proclist.p_next;
469     proclist.p_next = pp;
470     (void) gettimeofday(&pp->p_btime, NULL);
471 }
472 
473 static void
474 padd(t)
475     register struct command *t;
476 {
477     Char  **argp;
478 
479     if (t == 0)
480 	return;
481     switch (t->t_dtyp) {
482 
483     case NODE_PAREN:
484 	pads(STRLparensp);
485 	padd(t->t_dspr);
486 	pads(STRspRparen);
487 	break;
488 
489     case NODE_COMMAND:
490 	for (argp = t->t_dcom; *argp; argp++) {
491 	    pads(*argp);
492 	    if (argp[1])
493 		pads(STRspace);
494 	}
495 	break;
496 
497     case NODE_OR:
498     case NODE_AND:
499     case NODE_PIPE:
500     case NODE_LIST:
501 	padd(t->t_dcar);
502 	switch (t->t_dtyp) {
503 	case NODE_OR:
504 	    pads(STRspor2sp);
505 	    break;
506 	case NODE_AND:
507 	    pads(STRspand2sp);
508 	    break;
509 	case NODE_PIPE:
510 	    pads(STRsporsp);
511 	    break;
512 	case NODE_LIST:
513 	    pads(STRsemisp);
514 	    break;
515 	}
516 	padd(t->t_dcdr);
517 	return;
518     }
519     if ((t->t_dflg & F_PIPEIN) == 0 && t->t_dlef) {
520 	pads((t->t_dflg & F_READ) ? STRspLarrow2sp : STRspLarrowsp);
521 	pads(t->t_dlef);
522     }
523     if ((t->t_dflg & F_PIPEOUT) == 0 && t->t_drit) {
524 	pads((t->t_dflg & F_APPEND) ? STRspRarrow2 : STRspRarrow);
525 	if (t->t_dflg & F_STDERR)
526 	    pads(STRand);
527 	pads(STRspace);
528 	pads(t->t_drit);
529     }
530 }
531 
532 static void
533 pads(cp)
534     Char   *cp;
535 {
536     register int i;
537 
538     /*
539      * Avoid the Quoted Space alias hack! Reported by:
540      * sam@john-bigboote.ICS.UCI.EDU (Sam Horrocks)
541      */
542     if (cp[0] == STRQNULL[0])
543 	cp++;
544 
545     i = Strlen(cp);
546 
547     if (cmdlen >= PMAXLEN)
548 	return;
549     if (cmdlen + i >= PMAXLEN) {
550 	(void) Strcpy(cmdp, STRsp3dots);
551 	cmdlen = PMAXLEN;
552 	cmdp += 4;
553 	return;
554     }
555     (void) Strcpy(cmdp, cp);
556     cmdp += i;
557     cmdlen += i;
558 }
559 
560 /*
561  * psavejob - temporarily save the current job on a one level stack
562  *	so another job can be created.  Used for { } in exp6
563  *	and `` in globbing.
564  */
565 void
566 psavejob()
567 {
568 
569     pholdjob = pcurrjob;
570     pcurrjob = NULL;
571 }
572 
573 /*
574  * prestjob - opposite of psavejob.  This may be missed if we are interrupted
575  *	somewhere, but pendjob cleans up anyway.
576  */
577 void
578 prestjob()
579 {
580 
581     pcurrjob = pholdjob;
582     pholdjob = NULL;
583 }
584 
585 /*
586  * pendjob - indicate that a job (set of commands) has been completed
587  *	or is about to begin.
588  */
589 void
590 pendjob()
591 {
592     register struct process *pp, *tp;
593 
594     if (pcurrjob && (pcurrjob->p_flags & (PFOREGND | PSTOPPED)) == 0) {
595 	pp = pcurrjob;
596 	while (pp->p_pid != pp->p_jobid)
597 	    pp = pp->p_friends;
598 	xprintf("[%d]", pp->p_index);
599 	tp = pp;
600 	do {
601 	    xprintf(" %d", pp->p_pid);
602 	    pp = pp->p_friends;
603 	} while (pp != tp);
604 	xprintf("\n");
605     }
606     pholdjob = pcurrjob = 0;
607 }
608 
609 /*
610  * pprint - print a job
611  */
612 static int
613 pprint(pp, flag)
614     register struct process *pp;
615     bool    flag;
616 {
617     register status, reason;
618     struct process *tp;
619     extern char *linp, linbuf[];
620     int     jobflags, pstatus;
621     char   *format;
622 
623     while (pp->p_pid != pp->p_jobid)
624 	pp = pp->p_friends;
625     if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
626 	pp->p_flags &= ~PPTIME;
627 	pp->p_flags |= PTIME;
628     }
629     tp = pp;
630     status = reason = -1;
631     jobflags = 0;
632     do {
633 	jobflags |= pp->p_flags;
634 	pstatus = pp->p_flags & PALLSTATES;
635 	if (tp != pp && linp != linbuf && !(flag & FANCY) &&
636 	    (pstatus == status && pp->p_reason == reason ||
637 	     !(flag & REASON)))
638 	    xprintf(" ");
639 	else {
640 	    if (tp != pp && linp != linbuf)
641 		xprintf("\n");
642 	    if (flag & NUMBER)
643 		if (pp == tp)
644 		    xprintf("[%d]%s %c ", pp->p_index,
645 			    pp->p_index < 10 ? " " : "",
646 			    pp == pcurrent ? '+' :
647 			    (pp == pprevious ? '-' : ' '));
648 		else
649 		    xprintf("       ");
650 	    if (flag & FANCY) {
651 		xprintf("%5d ", pp->p_pid);
652 	    }
653 	    if (flag & (REASON | AREASON)) {
654 		if (flag & NAME)
655 		    format = "%-23s";
656 		else
657 		    format = "%s";
658 		if (pstatus == status)
659 		    if (pp->p_reason == reason) {
660 			xprintf(format, "");
661 			goto prcomd;
662 		    }
663 		    else
664 			reason = pp->p_reason;
665 		else {
666 		    status = pstatus;
667 		    reason = pp->p_reason;
668 		}
669 		switch (status) {
670 
671 		case PRUNNING:
672 		    xprintf(format, "Running ");
673 		    break;
674 
675 		case PINTERRUPTED:
676 		case PSTOPPED:
677 		case PSIGNALED:
678 		    if ((flag & REASON) ||
679 			((flag & AREASON) && reason != SIGINT
680 			 && reason != SIGPIPE))
681 			xprintf(format, mesg[pp->p_reason].pname);
682 		    break;
683 
684 		case PNEXITED:
685 		case PAEXITED:
686 		    if (flag & REASON)
687 			if (pp->p_reason)
688 			    xprintf("Exit %-18d", pp->p_reason);
689 			else
690 			    xprintf(format, "Done");
691 		    break;
692 
693 		default:
694 		    xprintf("BUG: status=%-9o", status);
695 		}
696 	    }
697 	}
698 prcomd:
699 	if (flag & NAME) {
700 	    xprintf("%s", short2str(pp->p_command));
701 	    if (pp->p_flags & PPOU)
702 		xprintf(" |");
703 	    if (pp->p_flags & PDIAG)
704 		xprintf("&");
705 	}
706 	if (flag & (REASON | AREASON) && pp->p_flags & PDUMPED)
707 	    xprintf(" (core dumped)");
708 	if (tp == pp->p_friends) {
709 	    if (flag & AMPERSAND)
710 		xprintf(" &");
711 	    if (flag & JOBDIR &&
712 		!eq(tp->p_cwd->di_name, dcwd->di_name)) {
713 		xprintf(" (wd: ");
714 		dtildepr(value(STRhome), tp->p_cwd->di_name);
715 		xprintf(")");
716 	    }
717 	}
718 	if (pp->p_flags & PPTIME && !(status & (PSTOPPED | PRUNNING))) {
719 	    if (linp != linbuf)
720 		xprintf("\n\t");
721 	    prusage(&zru, &pp->p_rusage, &pp->p_etime,
722 		    &pp->p_btime);
723 	}
724 	if (tp == pp->p_friends) {
725 	    if (linp != linbuf)
726 		xprintf("\n");
727 	    if (flag & SHELLDIR && !eq(tp->p_cwd->di_name, dcwd->di_name)) {
728 		xprintf("(wd now: ");
729 		dtildepr(value(STRhome), dcwd->di_name);
730 		xprintf(")\n");
731 	    }
732 	}
733     } while ((pp = pp->p_friends) != tp);
734     if (jobflags & PTIME && (jobflags & (PSTOPPED | PRUNNING)) == 0) {
735 	if (jobflags & NUMBER)
736 	    xprintf("       ");
737 	ptprint(tp);
738     }
739     return (jobflags);
740 }
741 
742 static void
743 ptprint(tp)
744     register struct process *tp;
745 {
746     struct timeval tetime, diff;
747     static struct timeval ztime;
748     struct rusage ru;
749     static struct rusage zru;
750     register struct process *pp = tp;
751 
752     ru = zru;
753     tetime = ztime;
754     do {
755 	ruadd(&ru, &pp->p_rusage);
756 	tvsub(&diff, &pp->p_etime, &pp->p_btime);
757 	if (timercmp(&diff, &tetime, >))
758 	    tetime = diff;
759     } while ((pp = pp->p_friends) != tp);
760     prusage(&zru, &ru, &tetime, &ztime);
761 }
762 
763 /*
764  * dojobs - print all jobs
765  */
766 void
767 dojobs(v)
768     Char  **v;
769 {
770     register struct process *pp;
771     register int flag = NUMBER | NAME | REASON;
772     int     i;
773 
774     if (chkstop)
775 	chkstop = 2;
776     if (*++v) {
777 	if (v[1] || !eq(*v, STRml))
778 	    stderror(ERR_JOBS);
779 	flag |= FANCY | JOBDIR;
780     }
781     for (i = 1; i <= pmaxindex; i++)
782 	for (pp = proclist.p_next; pp; pp = pp->p_next)
783 	    if (pp->p_index == i && pp->p_pid == pp->p_jobid) {
784 		pp->p_flags &= ~PNEEDNOTE;
785 		if (!(pprint(pp, flag) & (PRUNNING | PSTOPPED)))
786 		    pflush(pp);
787 		break;
788 	    }
789 }
790 
791 /*
792  * dofg - builtin - put the job into the foreground
793  */
794 void
795 dofg(v)
796     Char  **v;
797 {
798     register struct process *pp;
799 
800     okpcntl();
801     ++v;
802     do {
803 	pp = pfind(*v);
804 	pstart(pp, 1);
805 	pjwait(pp);
806     } while (*v && *++v);
807 }
808 
809 /*
810  * %... - builtin - put the job into the foreground
811  */
812 void
813 dofg1(v)
814     Char  **v;
815 {
816     register struct process *pp;
817 
818     okpcntl();
819     pp = pfind(v[0]);
820     pstart(pp, 1);
821     pjwait(pp);
822 }
823 
824 /*
825  * dobg - builtin - put the job into the background
826  */
827 void
828 dobg(v)
829     Char  **v;
830 {
831     register struct process *pp;
832 
833     okpcntl();
834     ++v;
835     do {
836 	pp = pfind(*v);
837 	pstart(pp, 0);
838     } while (*v && *++v);
839 }
840 
841 /*
842  * %... & - builtin - put the job into the background
843  */
844 void
845 dobg1(v)
846     Char  **v;
847 {
848     register struct process *pp;
849 
850     pp = pfind(v[0]);
851     pstart(pp, 0);
852 }
853 
854 /*
855  * dostop - builtin - stop the job
856  */
857 void
858 dostop(v)
859     Char  **v;
860 {
861     pkill(++v, SIGSTOP);
862 }
863 
864 /*
865  * dokill - builtin - superset of kill (1)
866  */
867 void
868 dokill(v)
869     Char  **v;
870 {
871     register int signum, len = 0;
872     register char *name;
873 
874     v++;
875     if (v[0] && v[0][0] == '-') {
876 	if (v[0][1] == 'l') {
877 	    for (signum = 1; signum <= NSIG; signum++) {
878 		if ((name = mesg[signum].iname) != NULL) {
879 		    len += strlen(name) + 1;
880 		    if (len >= 80 - 1) {
881 			xprintf("\n");
882 			len = strlen(name) + 1;
883 		    }
884 		    xprintf("%s ", name);
885 		}
886 	    }
887 	    xprintf("\n");
888 	    return;
889 	}
890 	if (Isdigit(v[0][1])) {
891 	    signum = atoi(short2str(v[0] + 1));
892 	    if (signum < 0 || signum > NSIG)
893 		stderror(ERR_NAME | ERR_BADSIG);
894 	}
895 	else {
896 	    for (signum = 1; signum <= NSIG; signum++)
897 		if (mesg[signum].iname &&
898 		    eq(&v[0][1], str2short(mesg[signum].iname)))
899 		    goto gotsig;
900 	    setname(short2str(&v[0][1]));
901 	    stderror(ERR_NAME | ERR_UNKSIG);
902 	}
903 gotsig:
904 	v++;
905     }
906     else
907 	signum = SIGTERM;
908     pkill(v, signum);
909 }
910 
911 static void
912 pkill(v, signum)
913     Char  **v;
914     int     signum;
915 {
916     register struct process *pp, *np;
917     register int jobflags = 0;
918     int     pid, err1 = 0;
919     sigset_t omask;
920     Char   *cp;
921 
922     omask = sigmask(SIGCHLD);
923     if (setintr)
924 	omask |= sigmask(SIGINT);
925     omask = sigblock(omask) & ~omask;
926     gflag = 0, tglob(v);
927     if (gflag) {
928 	v = globall(v);
929 	if (v == 0)
930 	    stderror(ERR_NAME | ERR_NOMATCH);
931     }
932     else {
933 	v = gargv = saveblk(v);
934 	trim(v);
935     }
936 
937     while (v && (cp = *v)) {
938 	if (*cp == '%') {
939 	    np = pp = pfind(cp);
940 	    do
941 		jobflags |= np->p_flags;
942 	    while ((np = np->p_friends) != pp);
943 	    switch (signum) {
944 
945 	    case SIGSTOP:
946 	    case SIGTSTP:
947 	    case SIGTTIN:
948 	    case SIGTTOU:
949 		if ((jobflags & PRUNNING) == 0) {
950 		    xprintf("%s: Already suspended\n", short2str(cp));
951 		    err1++;
952 		    goto cont;
953 		}
954 		break;
955 		/*
956 		 * suspend a process, kill -CONT %, then type jobs; the shell
957 		 * says it is suspended, but it is running; thanks jaap..
958 		 */
959 	    case SIGCONT:
960 		pstart(pp, 0);
961 		goto cont;
962 	    }
963 	    if (killpg((pid_t) pp->p_jobid, signum) < 0) {
964 		xprintf("%s: %s\n", short2str(cp), strerror(errno));
965 		err1++;
966 	    }
967 	    if (signum == SIGTERM || signum == SIGHUP)
968 		(void) killpg((pid_t) pp->p_jobid, SIGCONT);
969 	}
970 	else if (!(Isdigit(*cp) || *cp == '-'))
971 	    stderror(ERR_NAME | ERR_JOBARGS);
972 	else {
973 	    pid = atoi(short2str(cp));
974 	    if (kill((pid_t) pid, signum) < 0) {
975 		xprintf("%d: %s\n", pid, strerror(errno));
976 		err1++;
977 		goto cont;
978 	    }
979 	    if (signum == SIGTERM || signum == SIGHUP)
980 		(void) kill((pid_t) pid, SIGCONT);
981 	}
982 cont:
983 	v++;
984     }
985     if (gargv)
986 	blkfree(gargv), gargv = 0;
987     (void) sigsetmask(omask);
988     if (err1)
989 	stderror(ERR_SILENT);
990 }
991 
992 /*
993  * pstart - start the job in foreground/background
994  */
995 void
996 pstart(pp, foregnd)
997     register struct process *pp;
998     int     foregnd;
999 {
1000     register struct process *np;
1001     sigset_t omask;
1002     long    jobflags = 0;
1003 
1004     omask = sigblock(sigmask(SIGCHLD));
1005     np = pp;
1006     do {
1007 	jobflags |= np->p_flags;
1008 	if (np->p_flags & (PRUNNING | PSTOPPED)) {
1009 	    np->p_flags |= PRUNNING;
1010 	    np->p_flags &= ~PSTOPPED;
1011 	    if (foregnd)
1012 		np->p_flags |= PFOREGND;
1013 	    else
1014 		np->p_flags &= ~PFOREGND;
1015 	}
1016     } while ((np = np->p_friends) != pp);
1017     if (!foregnd)
1018 	pclrcurr(pp);
1019     (void) pprint(pp, foregnd ? NAME | JOBDIR : NUMBER | NAME | AMPERSAND);
1020     if (foregnd)
1021 	(void) tcsetpgrp(FSHTTY, pp->p_jobid);
1022     if (jobflags & PSTOPPED)
1023 	(void) killpg((pid_t) pp->p_jobid, SIGCONT);
1024     (void) sigsetmask(omask);
1025 }
1026 
1027 void
1028 panystop(neednl)
1029     bool    neednl;
1030 {
1031     register struct process *pp;
1032 
1033     chkstop = 2;
1034     for (pp = proclist.p_next; pp; pp = pp->p_next)
1035 	if (pp->p_flags & PSTOPPED)
1036 	    stderror(ERR_STOPPED, neednl ? "\n" : "");
1037 }
1038 
1039 struct process *
1040 pfind(cp)
1041     Char   *cp;
1042 {
1043     register struct process *pp, *np;
1044 
1045     if (cp == 0 || cp[1] == 0 || eq(cp, STRcent2) || eq(cp, STRcentplus)) {
1046 	if (pcurrent == NULL)
1047 	    stderror(ERR_NAME | ERR_JOBCUR);
1048 	return (pcurrent);
1049     }
1050     if (eq(cp, STRcentminus) || eq(cp, STRcenthash)) {
1051 	if (pprevious == NULL)
1052 	    stderror(ERR_NAME | ERR_JOBPREV);
1053 	return (pprevious);
1054     }
1055     if (Isdigit(cp[1])) {
1056 	int     idx = atoi(short2str(cp + 1));
1057 
1058 	for (pp = proclist.p_next; pp; pp = pp->p_next)
1059 	    if (pp->p_index == idx && pp->p_pid == pp->p_jobid)
1060 		return (pp);
1061 	stderror(ERR_NAME | ERR_NOSUCHJOB);
1062     }
1063     np = NULL;
1064     for (pp = proclist.p_next; pp; pp = pp->p_next)
1065 	if (pp->p_pid == pp->p_jobid) {
1066 	    if (cp[1] == '?') {
1067 		register Char *dp;
1068 
1069 		for (dp = pp->p_command; *dp; dp++) {
1070 		    if (*dp != cp[2])
1071 			continue;
1072 		    if (prefix(cp + 2, dp))
1073 			goto match;
1074 		}
1075 	    }
1076 	    else if (prefix(cp + 1, pp->p_command)) {
1077 	match:
1078 		if (np)
1079 		    stderror(ERR_NAME | ERR_AMBIG);
1080 		np = pp;
1081 	    }
1082 	}
1083     if (np)
1084 	return (np);
1085     stderror(ERR_NAME | cp[1] == '?' ? ERR_JOBPAT : ERR_NOSUCHJOB);
1086     /* NOTREACHED */
1087     return (0);
1088 }
1089 
1090 
1091 /*
1092  * pgetcurr - find most recent job that is not pp, preferably stopped
1093  */
1094 static struct process *
1095 pgetcurr(pp)
1096     register struct process *pp;
1097 {
1098     register struct process *np;
1099     register struct process *xp = NULL;
1100 
1101     for (np = proclist.p_next; np; np = np->p_next)
1102 	if (np != pcurrent && np != pp && np->p_pid &&
1103 	    np->p_pid == np->p_jobid) {
1104 	    if (np->p_flags & PSTOPPED)
1105 		return (np);
1106 	    if (xp == NULL)
1107 		xp = np;
1108 	}
1109     return (xp);
1110 }
1111 
1112 /*
1113  * donotify - flag the job so as to report termination asynchronously
1114  */
1115 void
1116 donotify(v)
1117     Char  **v;
1118 {
1119     register struct process *pp;
1120 
1121     pp = pfind(*++v);
1122     pp->p_flags |= PNOTIFY;
1123 }
1124 
1125 /*
1126  * Do the fork and whatever should be done in the child side that
1127  * should not be done if we are not forking at all (like for simple builtin's)
1128  * Also do everything that needs any signals fiddled with in the parent side
1129  *
1130  * Wanttty tells whether process and/or tty pgrps are to be manipulated:
1131  *	-1:	leave tty alone; inherit pgrp from parent
1132  *	 0:	already have tty; manipulate process pgrps only
1133  *	 1:	want to claim tty; manipulate process and tty pgrps
1134  * It is usually just the value of tpgrp.
1135  */
1136 
1137 int
1138 pfork(t, wanttty)
1139     struct command *t;		/* command we are forking for */
1140     int     wanttty;
1141 {
1142     register int pid;
1143     bool    ignint = 0;
1144     int     pgrp;
1145     sigset_t omask;
1146 
1147     /*
1148      * A child will be uninterruptible only under very special conditions.
1149      * Remember that the semantics of '&' is implemented by disconnecting the
1150      * process from the tty so signals do not need to ignored just for '&'.
1151      * Thus signals are set to default action for children unless: we have had
1152      * an "onintr -" (then specifically ignored) we are not playing with
1153      * signals (inherit action)
1154      */
1155     if (setintr)
1156 	ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT))
1157 	    || (gointr && eq(gointr, STRminus));
1158     /*
1159      * Check for maximum nesting of 16 processes to avoid Forking loops
1160      */
1161     if (child == 16)
1162 	stderror(ERR_NESTING, 16);
1163     /*
1164      * Hold SIGCHLD until we have the process installed in our table.
1165      */
1166     omask = sigblock(sigmask(SIGCHLD));
1167     while ((pid = fork()) < 0)
1168 	if (setintr == 0)
1169 	    (void) sleep(FORKSLEEP);
1170 	else {
1171 	    (void) sigsetmask(omask);
1172 	    stderror(ERR_NOPROC);
1173 	}
1174     if (pid == 0) {
1175 	settimes();
1176 	pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
1177 	pflushall();
1178 	pcurrjob = NULL;
1179 	child++;
1180 	if (setintr) {
1181 	    setintr = 0;	/* until I think otherwise */
1182 	    /*
1183 	     * Children just get blown away on SIGINT, SIGQUIT unless "onintr
1184 	     * -" seen.
1185 	     */
1186 	    (void) signal(SIGINT, ignint ? SIG_IGN : SIG_DFL);
1187 	    (void) signal(SIGQUIT, ignint ? SIG_IGN : SIG_DFL);
1188 	    if (wanttty >= 0) {
1189 		/* make stoppable */
1190 		(void) signal(SIGTSTP, SIG_DFL);
1191 		(void) signal(SIGTTIN, SIG_DFL);
1192 		(void) signal(SIGTTOU, SIG_DFL);
1193 	    }
1194 	    (void) signal(SIGTERM, parterm);
1195 	}
1196 	else if (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) {
1197 	    (void) signal(SIGINT, SIG_IGN);
1198 	    (void) signal(SIGQUIT, SIG_IGN);
1199 	}
1200 	pgetty(wanttty, pgrp);
1201 	/*
1202 	 * Nohup and nice apply only to NODE_COMMAND's but it would be nice
1203 	 * (?!?) if you could say "nohup (foo;bar)" Then the parser would have
1204 	 * to know about nice/nohup/time
1205 	 */
1206 	if (t->t_dflg & F_NOHUP)
1207 	    (void) signal(SIGHUP, SIG_IGN);
1208 	if (t->t_dflg & F_NICE)
1209 	    (void) setpriority(PRIO_PROCESS, 0, t->t_nice);
1210     }
1211     else {
1212 	if (wanttty >= 0)
1213 	    (void) setpgid(pid, pcurrjob ? pcurrjob->p_jobid : pid);
1214 	palloc(pid, t);
1215 	(void) sigsetmask(omask);
1216     }
1217 
1218     return (pid);
1219 }
1220 
1221 static void
1222 okpcntl()
1223 {
1224     if (tpgrp == -1)
1225 	stderror(ERR_JOBCONTROL);
1226     if (tpgrp == 0)
1227 	stderror(ERR_JOBCTRLSUB);
1228 }
1229 
1230 /*
1231  * if we don't have vfork(), things can still go in the wrong order
1232  * resulting in the famous 'Stopped (tty output)'. But some systems
1233  * don't permit the setpgid() call, (these are more recent secure
1234  * systems such as ibm's aix). Then we'd rather print an error message
1235  * than hang the shell!
1236  * I am open to suggestions how to fix that.
1237  */
1238 void
1239 pgetty(wanttty, pgrp)
1240     int     wanttty, pgrp;
1241 {
1242     sigset_t omask = 0;
1243 
1244     /*
1245      * christos: I am blocking the tty signals till I've set things
1246      * correctly....
1247      */
1248     if (wanttty > 0)
1249 	omask = sigblock(sigmask(SIGTSTP)|sigmask(SIGTTIN)|sigmask(SIGTTOU));
1250     /*
1251      * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de>
1252      * Don't check for tpgrp >= 0 so even non-interactive shells give
1253      * background jobs process groups Same for the comparison in the other part
1254      * of the #ifdef
1255      */
1256     if (wanttty >= 0)
1257 	if (setpgid(0, pgrp) == -1) {
1258 	    xprintf("csh: setpgid error.\n");
1259 	    xexit(0);
1260 	}
1261 
1262     if (wanttty > 0) {
1263 	(void) tcsetpgrp(FSHTTY, pgrp);
1264 	(void) sigsetmask(omask);
1265     }
1266 
1267     if (tpgrp > 0)
1268 	tpgrp = 0;		/* gave tty away */
1269 }
1270