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