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