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