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