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