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