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