sh.proc.c revision 145479
1/* $Header: /src/pub/tcsh/sh.proc.c,v 3.90 2005/03/03 19:57:07 kim Exp $ */
2/*
3 * sh.proc.c: Job manipulations
4 */
5/*-
6 * Copyright (c) 1980, 1991 The Regents of the University of California.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33#include "sh.h"
34
35RCSID("$Id: sh.proc.c,v 3.90 2005/03/03 19:57:07 kim Exp $")
36
37#include "ed.h"
38#include "tc.h"
39#include "tc.wait.h"
40
41#ifdef WINNT_NATIVE
42#undef POSIX
43#define POSIX
44#endif /* WINNT_NATIVE */
45#ifdef aiws
46# undef HZ
47# define HZ 16
48#endif /* aiws */
49
50#if defined(_BSD) || (defined(IRIS4D) && __STDC__) || defined(__lucid) || defined(linux) || defined(__GNU__) || defined(__GLIBC__)
51# define BSDWAIT
52#endif /* _BSD || (IRIS4D && __STDC__) || __lucid || glibc */
53#ifndef WTERMSIG
54# define WTERMSIG(w)	(((union wait *) &(w))->w_termsig)
55# ifndef BSDWAIT
56#  define BSDWAIT
57# endif /* !BSDWAIT */
58#endif /* !WTERMSIG */
59#ifndef WEXITSTATUS
60# define WEXITSTATUS(w)	(((union wait *) &(w))->w_retcode)
61#endif /* !WEXITSTATUS */
62#ifndef WSTOPSIG
63# define WSTOPSIG(w)	(((union wait *) &(w))->w_stopsig)
64#endif /* !WSTOPSIG */
65
66#ifdef __osf__
67# ifndef WCOREDUMP
68#  define WCOREDUMP(x) (_W_INT(x) & WCOREFLAG)
69# endif
70#endif
71
72#ifndef WCOREDUMP
73# ifdef BSDWAIT
74#  define WCOREDUMP(w)	(((union wait *) &(w))->w_coredump)
75# else /* !BSDWAIT */
76#  define WCOREDUMP(w)	((w) & 0200)
77# endif /* !BSDWAIT */
78#endif /* !WCOREDUMP */
79
80/*
81 * C Shell - functions that manage processes, handling hanging, termination
82 */
83
84#define BIGINDEX	9	/* largest desirable job index */
85
86#ifdef BSDTIMES
87# ifdef convex
88/* use 'cvxrusage' to get parallel statistics */
89static struct cvxrusage zru = {{0L, 0L}, {0L, 0L}, 0L, 0L, 0L, 0L,
90				0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L,
91				{0L, 0L}, 0LL, 0LL, 0LL, 0LL, 0L, 0L, 0L,
92				0LL, 0LL, {0L, 0L, 0L, 0L, 0L}};
93# else
94static struct rusage zru;
95# endif /* convex */
96#else /* !BSDTIMES */
97# ifdef _SEQUENT_
98static struct process_stats zru = {{0L, 0L}, {0L, 0L}, 0, 0, 0, 0, 0, 0, 0,
99				   0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
100# else /* !_SEQUENT_ */
101#  ifdef _SX
102static struct tms zru = {0, 0, 0, 0}, lru = {0, 0, 0, 0};
103#  else	/* !_SX */
104static struct tms zru = {0L, 0L, 0L, 0L}, lru = {0L, 0L, 0L, 0L};
105#  endif	/* !_SX */
106# endif	/* !_SEQUENT_ */
107#endif /* !BSDTIMES */
108
109#ifndef RUSAGE_CHILDREN
110# define	RUSAGE_CHILDREN	-1
111#endif /* RUSAGE_CHILDREN */
112
113static	void		 pflushall	__P((void));
114static	void		 pflush		__P((struct process *));
115static	void		 pfree		__P((struct process *));
116static	void		 pclrcurr	__P((struct process *));
117static	void		 padd		__P((struct command *));
118static	int		 pprint		__P((struct process *, int));
119static	void		 ptprint	__P((struct process *));
120static	void		 pads		__P((Char *));
121static	void		 pkill		__P((Char **, int));
122static	struct process	*pgetcurr	__P((struct process *));
123static	void		 okpcntl	__P((void));
124static	void		 setttypgrp	__P((int));
125
126/*
127 * pchild - called at interrupt level by the SIGCHLD signal
128 *	indicating that at least one child has terminated or stopped
129 *	thus at least one wait system call will definitely return a
130 *	childs status.  Top level routines (like pwait) must be sure
131 *	to mask interrupts when playing with the proclist data structures!
132 */
133RETSIGTYPE
134/*ARGSUSED*/
135pchild(snum)
136int snum;
137{
138    struct process *pp;
139    struct process *fp;
140    int pid;
141#ifdef BSDWAIT
142    union wait w;
143#else /* !BSDWAIT */
144    int     w;
145#endif /* !BSDWAIT */
146    int     jobflags;
147#ifdef BSDTIMES
148    struct sysrusage ru;
149#else /* !BSDTIMES */
150# ifdef _SEQUENT_
151    struct process_stats ru;
152    struct process_stats cpst1, cpst2;
153    timeval_t tv;
154# else /* !_SEQUENT_ */
155    struct tms proctimes;
156
157    if (!timesdone) {
158	timesdone++;
159	(void) times(&shtimes);
160    }
161# endif	/* !_SEQUENT_ */
162#endif /* !BSDTIMES */
163
164    USE(snum);
165#ifdef JOBDEBUG
166    xprintf("pchild()\n");
167#endif	/* JOBDEBUG */
168
169/* Christos on where the signal(SIGCHLD, pchild) shoud be:
170 *
171 * I think that it should go *after* the wait, unlike most signal handlers.
172 *
173 * In release two (for which I have manuals), it says that wait will remove
174 * the first child from the queue of dead children.
175 * All the rest of the children that die while in the signal handler of the
176 * SIGC(H)LD, will be placed in the queue. If signal is called to re-establish
177 * the signal handler, and there are items in the queue, the process will
178 * receive another SIGC(H)LD before signal returns. BTW this is from the
179 * manual page on comp-sim... Maybe it is not applicable to the hp's, but
180 * I read on the news in comp.unix.wizards or comp.unix.questions yesterday
181 * that another person was claiming the the signal() call should be after
182 * the wait().
183 */
184
185loop:
186    errno = 0;			/* reset, just in case */
187#ifdef JOBDEBUG
188    xprintf("Waiting...\n");
189    flush();
190#endif /* JOBDEBUG */
191#ifndef WINNT_NATIVE
192# ifdef BSDJOBS
193#  ifdef BSDTIMES
194#   ifdef convex
195    /* use 'cvxwait' to get parallel statistics */
196    pid = cvxwait(&w,
197        (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru);
198#   else
199    /* both a wait3 and rusage */
200#    if !defined(BSDWAIT) || defined(NeXT) || defined(MACH) || defined(linux) || defined(__GNU__) || defined(__GLIBC__) || (defined(IRIS4D) && (__STDC__ || defined(PROTOTYPES)) && SYSVREL <= 3) || defined(__lucid) || defined(__osf__)
201    pid = wait3(&w,
202       (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru);
203#    else /* BSDWAIT */
204    pid = wait3(&w.w_status,
205       (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru);
206#    endif /* BSDWAIT */
207#   endif /* convex */
208#  else /* !BSDTIMES */
209#   ifdef _SEQUENT_
210    (void) get_process_stats(&tv, PS_SELF, 0, &cpst1);
211    pid = waitpid(-1, &w,
212	    (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG));
213    (void) get_process_stats(&tv, PS_SELF, 0, &cpst2);
214    pr_stat_sub(&cpst2, &cpst1, &ru);
215#   else	/* !_SEQUENT_ */
216#    ifndef POSIX
217    /* we have a wait3, but no rusage stuff */
218    pid = wait3(&w.w_status,
219	 (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), 0);
220#    else /* POSIX */
221    pid = waitpid(-1, &w,
222	    (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG));
223#    endif /* POSIX */
224#   endif /* !_SEQUENT_ */
225#  endif	/* !BSDTIMES */
226# else /* !BSDJOBS */
227#  ifdef BSDTIMES
228#   define HAVEwait3
229    /* both a wait3 and rusage */
230#   ifdef hpux
231    pid = wait3(&w.w_status, WNOHANG, 0);
232#   else	/* !hpux */
233    pid = wait3(&w.w_status, WNOHANG, &ru);
234#   endif /* !hpux */
235#  else /* !BSDTIMES */
236#   ifdef ODT  /* For Sco Unix 3.2.0 or ODT 1.0 */
237#    define HAVEwait3
238     pid = waitpid(-1, &w,
239 	    (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG));
240#   endif /* ODT */
241#   if defined(aiws) || defined(uts)
242#    define HAVEwait3
243    pid = wait3(&w.w_status,
244	(setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), 0);
245#   endif /* aiws || uts */
246#   ifndef HAVEwait3
247#    ifdef UNRELSIGS
248     /* no wait3, therefore no rusage */
249     /* on Sys V, this may hang.  I hope it's not going to be a problem */
250#     ifdef _MINIX
251      pid = wait(&w);
252#     else /* !_MINIX */
253      pid = ourwait(&w.w_status);
254#     endif /* _MINIX */
255#    else /* !UNRELSIGS */
256     /*
257      * XXX: for greater than 3 we should use waitpid().
258      * but then again, SVR4 falls into the POSIX/BSDJOBS category.
259      */
260     pid = wait(&w.w_status);
261#    endif /* !UNRELSIGS */
262#   endif /* !HAVEwait3 */
263#  endif	/* !BSDTIMES */
264#  ifndef BSDSIGS
265    (void) sigset(SIGCHLD, pchild);
266#  endif /* !BSDSIGS */
267# endif /* !BSDJOBS */
268#else /* WINNT_NATIVE */
269    {
270	extern int insource;
271	pid = waitpid(-1, &w,
272	    (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG));
273    }
274#endif /* WINNT_NATIVE */
275
276#ifdef JOBDEBUG
277    xprintf("parent %d pid %d, retval %x termsig %x retcode %x\n",
278	    getpid(), pid, w, WTERMSIG(w), WEXITSTATUS(w));
279    flush();
280#endif /* JOBDEBUG */
281
282    if ((pid == 0) || (pid == -1)) {
283#ifdef JOBDEBUG
284	xprintf("errno == %d\n", errno);
285#endif /* JOBDEBUG */
286	if (errno == EINTR) {
287	    errno = 0;
288	    goto loop;
289	}
290	pnoprocesses = pid == -1;
291	goto end;
292    }
293    for (pp = proclist.p_next; pp != NULL; pp = pp->p_next)
294	if (pid == pp->p_procid)
295	    goto found;
296#if !defined(BSDJOBS) && !defined(WINNT_NATIVE)
297    /* this should never have happened */
298    stderror(ERR_SYNC, pid);
299    xexit(0);
300#else /* BSDJOBS || WINNT_NATIVE */
301    goto loop;
302#endif /* !BSDJOBS && !WINNT_NATIVE */
303found:
304    pp->p_flags &= ~(PRUNNING | PSTOPPED | PREPORTED);
305    if (WIFSTOPPED(w)) {
306	pp->p_flags |= PSTOPPED;
307	pp->p_reason = WSTOPSIG(w);
308    }
309    else {
310	if (pp->p_flags & (PTIME | PPTIME) || adrof(STRtime))
311#ifndef BSDTIMES
312# ifdef _SEQUENT_
313	    (void) get_process_stats(&pp->p_etime, PS_SELF, NULL, NULL);
314# else	/* !_SEQUENT_ */
315#  ifndef COHERENT
316	    pp->p_etime = times(&proctimes);
317#  else /* COHERENT */
318	    pp->p_etime = HZ * time(NULL);
319	    times(&proctimes);
320#  endif /* COHERENT */
321# endif	/* !_SEQUENT_ */
322#else /* BSDTIMES */
323	    (void) gettimeofday(&pp->p_etime, NULL);
324#endif /* BSDTIMES */
325
326
327#if defined(BSDTIMES) || defined(_SEQUENT_)
328	pp->p_rusage = ru;
329#else /* !BSDTIMES && !_SEQUENT_ */
330	(void) times(&proctimes);
331	pp->p_utime = proctimes.tms_cutime - shtimes.tms_cutime;
332	pp->p_stime = proctimes.tms_cstime - shtimes.tms_cstime;
333	shtimes = proctimes;
334#endif /* !BSDTIMES && !_SEQUENT_ */
335	if (WIFSIGNALED(w)) {
336	    if (WTERMSIG(w) == SIGINT)
337		pp->p_flags |= PINTERRUPTED;
338	    else
339		pp->p_flags |= PSIGNALED;
340	    if (WCOREDUMP(w))
341		pp->p_flags |= PDUMPED;
342	    pp->p_reason = WTERMSIG(w);
343	}
344	else {
345	    pp->p_reason = WEXITSTATUS(w);
346	    if (pp->p_reason != 0)
347		pp->p_flags |= PAEXITED;
348	    else
349		pp->p_flags |= PNEXITED;
350	}
351    }
352    jobflags = 0;
353    fp = pp;
354    do {
355	if ((fp->p_flags & (PPTIME | PRUNNING | PSTOPPED)) == 0 &&
356	    !child && adrof(STRtime) &&
357#ifdef BSDTIMES
358	    fp->p_rusage.ru_utime.tv_sec + fp->p_rusage.ru_stime.tv_sec
359#else /* !BSDTIMES */
360# ifdef _SEQUENT_
361	    fp->p_rusage.ps_utime.tv_sec + fp->p_rusage.ps_stime.tv_sec
362# else /* !_SEQUENT_ */
363#  ifndef POSIX
364	    (fp->p_utime + fp->p_stime) / HZ
365#  else /* POSIX */
366	    (fp->p_utime + fp->p_stime) / clk_tck
367#  endif /* POSIX */
368# endif /* !_SEQUENT_ */
369#endif /* !BSDTIMES */
370	    >= atoi(short2str(varval(STRtime))))
371	    fp->p_flags |= PTIME;
372	jobflags |= fp->p_flags;
373    } while ((fp = fp->p_friends) != pp);
374    pp->p_flags &= ~PFOREGND;
375    if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
376	pp->p_flags &= ~PPTIME;
377	pp->p_flags |= PTIME;
378    }
379    if ((jobflags & (PRUNNING | PREPORTED)) == 0) {
380	fp = pp;
381	do {
382	    if (fp->p_flags & PSTOPPED)
383		fp->p_flags |= PREPORTED;
384	} while ((fp = fp->p_friends) != pp);
385	while (fp->p_procid != fp->p_jobid)
386	    fp = fp->p_friends;
387	if (jobflags & PSTOPPED) {
388	    if (pcurrent && pcurrent != fp)
389		pprevious = pcurrent;
390	    pcurrent = fp;
391	}
392	else
393	    pclrcurr(fp);
394	if (jobflags & PFOREGND) {
395	    if (!(jobflags & (PSIGNALED | PSTOPPED | PPTIME) ||
396#ifdef notdef
397		jobflags & PAEXITED ||
398#endif /* notdef */
399		!eq(dcwd->di_name, fp->p_cwd->di_name))) {
400	    /* PWP: print a newline after ^C */
401		if (jobflags & PINTERRUPTED) {
402#ifdef SHORT_STRINGS
403		    xputchar('\r' | QUOTE), xputchar('\n');
404#else /* !SHORT_STRINGS */
405		    xprintf("\215\n");	/* \215 is a quoted ^M */
406#endif /* !SHORT_STRINGS */
407		}
408#ifdef notdef
409		else if ((jobflags & (PTIME|PSTOPPED)) == PTIME)
410		    ptprint(fp);
411#endif /* notdef */
412	    }
413	}
414	else {
415	    if (jobflags & PNOTIFY || adrof(STRnotify)) {
416#ifdef SHORT_STRINGS
417		xputchar('\r' | QUOTE), xputchar('\n');
418#else /* !SHORT_STRINGS */
419		xprintf("\215\n");	/* \215 is a quoted ^M */
420#endif /* !SHORT_STRINGS */
421		(void) pprint(pp, NUMBER | NAME | REASON);
422		if ((jobflags & PSTOPPED) == 0)
423		    pflush(pp);
424		{
425		    if (GettingInput) {
426			errno = 0;
427			(void) Rawmode();
428#ifdef notdef
429			/*
430			 * don't really want to do that, because it
431			 * will erase our message in case of multi-line
432			 * input
433			 */
434			ClearLines();
435#endif /* notdef */
436			ClearDisp();
437			Refresh();
438		    }
439		}
440	    }
441	    else {
442		fp->p_flags |= PNEEDNOTE;
443		neednote++;
444	    }
445	}
446    }
447#if defined(BSDJOBS) || defined(HAVEwait3)
448    goto loop;
449#endif /* BSDJOBS || HAVEwait3 */
450 end:
451    ;
452}
453
454void
455pnote()
456{
457    struct process *pp;
458    int     flags;
459#ifdef BSDSIGS
460    sigmask_t omask;
461#endif /* BSDSIGS */
462
463    neednote = 0;
464    for (pp = proclist.p_next; pp != NULL; pp = pp->p_next) {
465	if (pp->p_flags & PNEEDNOTE) {
466#ifdef BSDSIGS
467	    omask = sigblock(sigmask(SIGCHLD));
468#else /* !BSDSIGS */
469	    (void) sighold(SIGCHLD);
470#endif /* !BSDSIGS */
471	    pp->p_flags &= ~PNEEDNOTE;
472	    flags = pprint(pp, NUMBER | NAME | REASON);
473	    if ((flags & (PRUNNING | PSTOPPED)) == 0)
474		pflush(pp);
475#ifdef BSDSIGS
476	    (void) sigsetmask(omask);
477#else /* !BSDSIGS */
478	    (void) sigrelse(SIGCHLD);
479#endif /* !BSDSIGS */
480	}
481    }
482}
483
484
485static void
486pfree(pp)
487    struct process *pp;
488{
489    xfree((ptr_t) pp->p_command);
490    if (pp->p_cwd && --pp->p_cwd->di_count == 0)
491	if (pp->p_cwd->di_next == 0)
492	    dfree(pp->p_cwd);
493    xfree((ptr_t) pp);
494}
495
496
497/*
498 * pwait - wait for current job to terminate, maintaining integrity
499 *	of current and previous job indicators.
500 */
501void
502pwait()
503{
504    struct process *fp, *pp;
505#ifdef BSDSIGS
506    sigmask_t omask;
507#endif /* BSDSIGS */
508
509    /*
510     * Here's where dead procs get flushed.
511     */
512#ifdef BSDSIGS
513    omask = sigblock(sigmask(SIGCHLD));
514#else /* !BSDSIGS */
515    (void) sighold(SIGCHLD);
516#endif /* !BSDSIGS */
517    for (pp = (fp = &proclist)->p_next; pp != NULL; pp = (fp = pp)->p_next)
518	if (pp->p_procid == 0) {
519	    fp->p_next = pp->p_next;
520	    pfree(pp);
521	    pp = fp;
522	}
523#ifdef BSDSIGS
524    (void) sigsetmask(omask);
525#else /* !BSDSIGS */
526    (void) sigrelse(SIGCHLD);
527# ifdef notdef
528    if (setintr)
529	sigignore(SIGINT);
530# endif /* notdef */
531#endif /* !BSDSIGS */
532    pjwait(pcurrjob);
533}
534
535
536/*
537 * pjwait - wait for a job to finish or become stopped
538 *	It is assumed to be in the foreground state (PFOREGND)
539 */
540void
541pjwait(pp)
542    struct process *pp;
543{
544    struct process *fp;
545    int     jobflags, reason;
546#ifdef BSDSIGS
547    sigmask_t omask;
548#endif /* BSDSIGS */
549#ifdef UNRELSIGS
550    signalfun_t inthandler;
551#endif /* UNRELSIGS */
552    while (pp->p_procid != pp->p_jobid)
553	pp = pp->p_friends;
554    fp = pp;
555
556    do {
557	if ((fp->p_flags & (PFOREGND | PRUNNING)) == PRUNNING)
558	    xprintf(CGETS(17, 1, "BUG: waiting for background job!\n"));
559    } while ((fp = fp->p_friends) != pp);
560    /*
561     * Now keep pausing as long as we are not interrupted (SIGINT), and the
562     * target process, or any of its friends, are running
563     */
564    fp = pp;
565#ifdef BSDSIGS
566    omask = sigblock(sigmask(SIGCHLD));
567#endif /* BSDSIGS */
568#ifdef UNRELSIGS
569    if (setintr)
570        inthandler = signal(SIGINT, SIG_IGN);
571#endif /* UNRELSIGS */
572    for (;;) {
573#ifndef BSDSIGS
574	(void) sighold(SIGCHLD);
575#endif /* !BSDSIGS */
576	jobflags = 0;
577	do
578	    jobflags |= fp->p_flags;
579	while ((fp = (fp->p_friends)) != pp);
580	if ((jobflags & PRUNNING) == 0)
581	    break;
582#ifdef JOBDEBUG
583	xprintf("%d starting to sigpause for SIGCHLD on %d\n",
584		getpid(), fp->p_procid);
585#endif /* JOBDEBUG */
586#ifdef BSDSIGS
587	/* (void) sigpause(sigblock((sigmask_t) 0) &~ sigmask(SIGCHLD)); */
588	(void) sigpause(omask & ~sigmask(SIGCHLD));
589#else /* !BSDSIGS */
590	(void) sigpause(SIGCHLD);
591#endif /* !BSDSIGS */
592    }
593#ifdef JOBDEBUG
594	xprintf("%d returned from sigpause loop\n", getpid());
595#endif /* JOBDEBUG */
596#ifdef BSDSIGS
597    (void) sigsetmask(omask);
598#else /* !BSDSIGS */
599    (void) sigrelse(SIGCHLD);
600#endif /* !BSDSIGS */
601#ifdef UNRELSIGS
602    if (setintr)
603        (void) signal(SIGINT, inthandler);
604#endif /* UNRELSIGS */
605#ifdef BSDJOBS
606    if (tpgrp > 0)		/* get tty back */
607	(void) tcsetpgrp(FSHTTY, tpgrp);
608#endif /* BSDJOBS */
609    if ((jobflags & (PSIGNALED | PSTOPPED | PTIME)) ||
610	!eq(dcwd->di_name, fp->p_cwd->di_name)) {
611	if (jobflags & PSTOPPED) {
612	    xputchar('\n');
613	    if (adrof(STRlistjobs)) {
614		Char   *jobcommand[3];
615
616		jobcommand[0] = STRjobs;
617		if (eq(varval(STRlistjobs), STRlong))
618		    jobcommand[1] = STRml;
619		else
620		    jobcommand[1] = NULL;
621		jobcommand[2] = NULL;
622
623		dojobs(jobcommand, NULL);
624		(void) pprint(pp, SHELLDIR);
625	    }
626	    else
627		(void) pprint(pp, AREASON | SHELLDIR);
628	}
629	else
630	    (void) pprint(pp, AREASON | SHELLDIR);
631    }
632    if ((jobflags & (PINTERRUPTED | PSTOPPED)) && setintr &&
633	(!gointr || !eq(gointr, STRminus))) {
634	if ((jobflags & PSTOPPED) == 0)
635	    pflush(pp);
636	pintr1(0);
637	/* NOTREACHED */
638    }
639    reason = 0;
640    fp = pp;
641    do {
642	if (fp->p_reason)
643	    reason = fp->p_flags & (PSIGNALED | PINTERRUPTED) ?
644		fp->p_reason | META : fp->p_reason;
645    } while ((fp = fp->p_friends) != pp);
646    /*
647     * Don't report on backquoted jobs, cause it will mess up
648     * their output.
649     */
650    if ((reason != 0) && (adrof(STRprintexitvalue)) &&
651	(pp->p_flags & PBACKQ) == 0)
652	xprintf(CGETS(17, 2, "Exit %d\n"), reason);
653    set(STRstatus, putn(reason), VAR_READWRITE);
654    if (reason && exiterr)
655	exitstat();
656    pflush(pp);
657}
658
659/*
660 * dowait - wait for all processes to finish
661 */
662
663/*ARGSUSED*/
664void
665dowait(v, c)
666    Char **v;
667    struct command *c;
668{
669    struct process *pp;
670#ifdef BSDSIGS
671    sigmask_t omask;
672#endif /* BSDSIGS */
673
674    USE(c);
675    USE(v);
676    pjobs++;
677#ifdef BSDSIGS
678    omask = sigblock(sigmask(SIGCHLD));
679loop:
680#else /* !BSDSIGS */
681    if (setintr)
682	(void) sigrelse(SIGINT);
683loop:
684    (void) sighold(SIGCHLD);
685#endif /* !BSDSIGS */
686    for (pp = proclist.p_next; pp; pp = pp->p_next)
687	if (pp->p_procid &&	/* pp->p_procid == pp->p_jobid && */
688	    pp->p_flags & PRUNNING) {
689#ifdef BSDSIGS
690	    (void) sigpause((sigmask_t) 0);
691#else /* !BSDSIGS */
692	    (void) sigpause(SIGCHLD);
693#endif /* !BSDSIGS */
694	    goto loop;
695	}
696#ifdef BSDSIGS
697    (void) sigsetmask(omask);
698#else /* !BSDSIGS */
699    (void) sigrelse(SIGCHLD);
700#endif /* !BSDSIGS */
701    pjobs = 0;
702}
703
704/*
705 * pflushall - flush all jobs from list (e.g. at fork())
706 */
707static void
708pflushall()
709{
710    struct process *pp;
711
712    for (pp = proclist.p_next; pp != NULL; pp = pp->p_next)
713	if (pp->p_procid)
714	    pflush(pp);
715}
716
717/*
718 * pflush - flag all process structures in the same job as the
719 *	the argument process for deletion.  The actual free of the
720 *	space is not done here since pflush is called at interrupt level.
721 */
722static void
723pflush(pp)
724    struct process *pp;
725{
726    struct process *np;
727    int idx;
728
729    if (pp->p_procid == 0) {
730	xprintf(CGETS(17, 3, "BUG: process flushed twice"));
731	return;
732    }
733    while (pp->p_procid != pp->p_jobid)
734	pp = pp->p_friends;
735    pclrcurr(pp);
736    if (pp == pcurrjob)
737	pcurrjob = 0;
738    idx = pp->p_index;
739    np = pp;
740    do {
741	np->p_index = np->p_procid = 0;
742	np->p_flags &= ~PNEEDNOTE;
743    } while ((np = np->p_friends) != pp);
744    if (idx == pmaxindex) {
745	for (np = proclist.p_next, idx = 0; np; np = np->p_next)
746	    if (np->p_index > idx)
747		idx = np->p_index;
748	pmaxindex = idx;
749    }
750}
751
752/*
753 * pclrcurr - make sure the given job is not the current or previous job;
754 *	pp MUST be the job leader
755 */
756static void
757pclrcurr(pp)
758    struct process *pp;
759{
760    if (pp == pcurrent) {
761	if (pprevious != NULL) {
762	    pcurrent = pprevious;
763	    pprevious = pgetcurr(pp);
764	}
765	else {
766	    pcurrent = pgetcurr(pp);
767	    pprevious = pgetcurr(pp);
768	}
769    }
770    else if (pp == pprevious)
771	pprevious = pgetcurr(pp);
772}
773
774/* +4 here is 1 for '\0', 1 ea for << >& >> */
775static Char command[PMAXLEN + 4];
776static int cmdlen;
777static Char *cmdp;
778
779/* GrP
780 * unparse - Export padd() functionality
781 */
782Char *
783unparse(t)
784    struct command *t;
785{
786    cmdp = command;
787    cmdlen = 0;
788    padd(t);
789    *cmdp++ = '\0';
790    return Strsave(command);
791}
792
793
794/*
795 * palloc - allocate a process structure and fill it up.
796 *	an important assumption is made that the process is running.
797 */
798void
799palloc(pid, t)
800    int     pid;
801    struct command *t;
802{
803    struct process *pp;
804    int     i;
805
806    pp = (struct process *) xcalloc(1, (size_t) sizeof(struct process));
807    pp->p_procid = pid;
808    pp->p_flags = ((t->t_dflg & F_AMPERSAND) ? 0 : PFOREGND) | PRUNNING;
809    if (t->t_dflg & F_TIME)
810	pp->p_flags |= PPTIME;
811    if (t->t_dflg & F_BACKQ)
812	pp->p_flags |= PBACKQ;
813    if (t->t_dflg & F_HUP)
814	pp->p_flags |= PHUP;
815    cmdp = command;
816    cmdlen = 0;
817    padd(t);
818    *cmdp++ = 0;
819    if (t->t_dflg & F_PIPEOUT) {
820	pp->p_flags |= PPOU;
821	if (t->t_dflg & F_STDERR)
822	    pp->p_flags |= PDIAG;
823    }
824    pp->p_command = Strsave(command);
825    if (pcurrjob) {
826	struct process *fp;
827
828	/* careful here with interrupt level */
829	pp->p_cwd = 0;
830	pp->p_index = pcurrjob->p_index;
831	pp->p_friends = pcurrjob;
832	pp->p_jobid = pcurrjob->p_procid;
833	for (fp = pcurrjob; fp->p_friends != pcurrjob; fp = fp->p_friends)
834	    continue;
835	fp->p_friends = pp;
836    }
837    else {
838	pcurrjob = pp;
839	pp->p_jobid = pid;
840	pp->p_friends = pp;
841	pp->p_cwd = dcwd;
842	dcwd->di_count++;
843	if (pmaxindex < BIGINDEX)
844	    pp->p_index = ++pmaxindex;
845	else {
846	    struct process *np;
847
848	    for (i = 1;; i++) {
849		for (np = proclist.p_next; np; np = np->p_next)
850		    if (np->p_index == i)
851			goto tryagain;
852		pp->p_index = i;
853		if (i > pmaxindex)
854		    pmaxindex = i;
855		break;
856	tryagain:;
857	    }
858	}
859	if (pcurrent == NULL)
860	    pcurrent = pp;
861	else if (pprevious == NULL)
862	    pprevious = pp;
863    }
864    pp->p_next = proclist.p_next;
865    proclist.p_next = pp;
866#ifdef BSDTIMES
867    (void) gettimeofday(&pp->p_btime, NULL);
868#else /* !BSDTIMES */
869# ifdef _SEQUENT_
870    (void) get_process_stats(&pp->p_btime, PS_SELF, NULL, NULL);
871# else /* !_SEQUENT_ */
872    {
873	struct tms tmptimes;
874
875#  ifndef COHERENT
876	pp->p_btime = times(&tmptimes);
877#  else /* !COHERENT */
878	pp->p_btime = HZ * time(NULL);
879	times(&tmptimes);
880#  endif /* !COHERENT */
881    }
882# endif /* !_SEQUENT_ */
883#endif /* !BSDTIMES */
884}
885
886static void
887padd(t)
888    struct command *t;
889{
890    Char  **argp;
891
892    if (t == 0)
893	return;
894    switch (t->t_dtyp) {
895
896    case NODE_PAREN:
897	pads(STRLparensp);
898	padd(t->t_dspr);
899	pads(STRspRparen);
900	break;
901
902    case NODE_COMMAND:
903	for (argp = t->t_dcom; *argp; argp++) {
904	    pads(*argp);
905	    if (argp[1])
906		pads(STRspace);
907	}
908	break;
909
910    case NODE_OR:
911    case NODE_AND:
912    case NODE_PIPE:
913    case NODE_LIST:
914	padd(t->t_dcar);
915	switch (t->t_dtyp) {
916	case NODE_OR:
917	    pads(STRspor2sp);
918	    break;
919	case NODE_AND:
920	    pads(STRspand2sp);
921	    break;
922	case NODE_PIPE:
923	    pads(STRsporsp);
924	    break;
925	case NODE_LIST:
926	    pads(STRsemisp);
927	    break;
928	default:
929	    break;
930	}
931	padd(t->t_dcdr);
932	return;
933
934    default:
935	break;
936    }
937    if ((t->t_dflg & F_PIPEIN) == 0 && t->t_dlef) {
938	pads((t->t_dflg & F_READ) ? STRspLarrow2sp : STRspLarrowsp);
939	pads(t->t_dlef);
940    }
941    if ((t->t_dflg & F_PIPEOUT) == 0 && t->t_drit) {
942	pads((t->t_dflg & F_APPEND) ? STRspRarrow2 : STRspRarrow);
943	if (t->t_dflg & F_STDERR)
944	    pads(STRand);
945	pads(STRspace);
946	pads(t->t_drit);
947    }
948}
949
950static void
951pads(cp)
952    Char   *cp;
953{
954    int i;
955
956    /*
957     * Avoid the Quoted Space alias hack! Reported by:
958     * sam@john-bigboote.ICS.UCI.EDU (Sam Horrocks)
959     */
960    if (cp[0] == STRQNULL[0])
961	cp++;
962
963    i = (int) Strlen(cp);
964
965    if (cmdlen >= PMAXLEN)
966	return;
967    if (cmdlen + i >= PMAXLEN) {
968	(void) Strcpy(cmdp, STRsp3dots);
969	cmdlen = PMAXLEN;
970	cmdp += 4;
971	return;
972    }
973    (void) Strcpy(cmdp, cp);
974    cmdp += i;
975    cmdlen += i;
976}
977
978/*
979 * psavejob - temporarily save the current job on a one level stack
980 *	so another job can be created.  Used for { } in exp6
981 *	and `` in globbing.
982 */
983void
984psavejob()
985{
986    pholdjob = pcurrjob;
987    pcurrjob = NULL;
988}
989
990/*
991 * prestjob - opposite of psavejob.  This may be missed if we are interrupted
992 *	somewhere, but pendjob cleans up anyway.
993 */
994void
995prestjob()
996{
997    pcurrjob = pholdjob;
998    pholdjob = NULL;
999}
1000
1001/*
1002 * pendjob - indicate that a job (set of commands) has been completed
1003 *	or is about to begin.
1004 */
1005void
1006pendjob()
1007{
1008    struct process *pp, *tp;
1009
1010    if (pcurrjob && (pcurrjob->p_flags & (PFOREGND | PSTOPPED)) == 0) {
1011	pp = pcurrjob;
1012	while (pp->p_procid != pp->p_jobid)
1013	    pp = pp->p_friends;
1014	xprintf("[%d]", pp->p_index);
1015	tp = pp;
1016	do {
1017	    xprintf(" %d", pp->p_procid);
1018	    pp = pp->p_friends;
1019	} while (pp != tp);
1020	xputchar('\n');
1021    }
1022    pholdjob = pcurrjob = 0;
1023}
1024
1025/*
1026 * pprint - print a job
1027 */
1028
1029/*
1030 * Hacks have been added for SVR4 to deal with pipe's being spawned in
1031 * reverse order
1032 *
1033 * David Dawes (dawes@physics.su.oz.au) Oct 1991
1034 */
1035
1036static int
1037pprint(pp, flag)
1038    struct process *pp;
1039    int    flag;
1040{
1041    int status, reason;
1042    struct process *tp;
1043    int     jobflags, pstatus, pcond;
1044    const char *format;
1045
1046#ifdef BACKPIPE
1047    struct process *pipehead = NULL, *pipetail = NULL, *pmarker = NULL;
1048    int inpipe = 0;
1049#endif /* BACKPIPE */
1050
1051    while (pp->p_procid != pp->p_jobid)
1052	pp = pp->p_friends;
1053    if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
1054	pp->p_flags &= ~PPTIME;
1055	pp->p_flags |= PTIME;
1056    }
1057    tp = pp;
1058    status = reason = -1;
1059    jobflags = 0;
1060    do {
1061#ifdef BACKPIPE
1062	/*
1063	 * The pipeline is reversed, so locate the real head of the pipeline
1064	 * if pp is at the tail of a pipe (and not already in a pipeline)
1065	 */
1066	if ((pp->p_friends->p_flags & PPOU) && !inpipe && (flag & NAME)) {
1067	    inpipe = 1;
1068	    pipetail = pp;
1069	    do
1070		pp = pp->p_friends;
1071	    while (pp->p_friends->p_flags & PPOU);
1072	    pipehead = pp;
1073	    pmarker = pp;
1074	/*
1075	 * pmarker is used to hold the place of the proc being processed, so
1076	 * we can search for the next one downstream later.
1077	 */
1078	}
1079	pcond = (int) (tp != pp || (inpipe && tp == pp));
1080#else /* !BACKPIPE */
1081	pcond = (int) (tp != pp);
1082#endif /* BACKPIPE */
1083
1084	jobflags |= pp->p_flags;
1085	pstatus = (int) (pp->p_flags & PALLSTATES);
1086	if (pcond && linp != linbuf && !(flag & FANCY) &&
1087	    ((pstatus == status && pp->p_reason == reason) ||
1088	     !(flag & REASON)))
1089	    xputchar(' ');
1090	else {
1091	    if (pcond && linp != linbuf)
1092		xputchar('\n');
1093	    if (flag & NUMBER) {
1094#ifdef BACKPIPE
1095		pcond = ((pp == tp && !inpipe) ||
1096			 (inpipe && pipetail == tp && pp == pipehead));
1097#else /* BACKPIPE */
1098		pcond = (pp == tp);
1099#endif /* BACKPIPE */
1100		if (pcond)
1101		    xprintf("[%d]%s %c ", pp->p_index,
1102			    pp->p_index < 10 ? " " : "",
1103			    pp == pcurrent ? '+' :
1104			    (pp == pprevious ? '-' : ' '));
1105		else
1106		    xprintf("       ");
1107	    }
1108	    if (flag & FANCY) {
1109#ifdef TCF
1110		extern char *sitename();
1111
1112#endif /* TCF */
1113		xprintf("%5d ", pp->p_procid);
1114#ifdef TCF
1115		xprintf("%11s ", sitename(pp->p_procid));
1116#endif /* TCF */
1117	    }
1118	    if (flag & (REASON | AREASON)) {
1119		if (flag & NAME)
1120		    format = "%-30s";
1121		else
1122		    format = "%s";
1123		if (pstatus == status) {
1124		    if (pp->p_reason == reason) {
1125			xprintf(format, "");
1126			goto prcomd;
1127		    }
1128		    else
1129			reason = (int) pp->p_reason;
1130		}
1131		else {
1132		    status = pstatus;
1133		    reason = (int) pp->p_reason;
1134		}
1135		switch (status) {
1136
1137		case PRUNNING:
1138		    xprintf(format, CGETS(17, 4, "Running "));
1139		    break;
1140
1141		case PINTERRUPTED:
1142		case PSTOPPED:
1143		case PSIGNALED:
1144		    /*
1145		     * tell what happened to the background job
1146		     * From: Michael Schroeder
1147		     * <mlschroe@immd4.informatik.uni-erlangen.de>
1148		     */
1149		    if ((flag & REASON)
1150			|| ((flag & AREASON)
1151			    && reason != SIGINT
1152			    && (reason != SIGPIPE
1153				|| (pp->p_flags & PPOU) == 0))) {
1154			const char *ptr;
1155			char buf[1024];
1156
1157			if ((ptr = mesg[pp->p_reason & ASCII].pname) == NULL) {
1158			    xsnprintf(buf, sizeof(buf), "%s %d",
1159				CGETS(17, 5, "Signal"), pp->p_reason & ASCII);
1160			    ptr = buf;
1161			}
1162			xprintf(format, ptr);
1163		    }
1164		    else
1165			reason = -1;
1166		    break;
1167
1168		case PNEXITED:
1169		case PAEXITED:
1170		    if (flag & REASON) {
1171			if (pp->p_reason)
1172			    xprintf(CGETS(17, 6, "Exit %-25d"), pp->p_reason);
1173			else
1174			    xprintf(format, CGETS(17, 7, "Done"));
1175		    }
1176		    break;
1177
1178		default:
1179		    xprintf(CGETS(17, 8, "BUG: status=%-9o"),
1180			    status);
1181		}
1182	    }
1183	}
1184prcomd:
1185	if (flag & NAME) {
1186	    xprintf("%S", pp->p_command);
1187	    if (pp->p_flags & PPOU)
1188		xprintf(" |");
1189	    if (pp->p_flags & PDIAG)
1190		xprintf("&");
1191	}
1192	if (flag & (REASON | AREASON) && pp->p_flags & PDUMPED)
1193	    xprintf(CGETS(17, 9, " (core dumped)"));
1194	if (tp == pp->p_friends) {
1195	    if (flag & AMPERSAND)
1196		xprintf(" &");
1197	    if (flag & JOBDIR &&
1198		!eq(tp->p_cwd->di_name, dcwd->di_name)) {
1199		xprintf(CGETS(17, 10, " (wd: "));
1200		dtildepr(tp->p_cwd->di_name);
1201		xprintf(")");
1202	    }
1203	}
1204	if (pp->p_flags & PPTIME && !(status & (PSTOPPED | PRUNNING))) {
1205	    if (linp != linbuf)
1206		xprintf("\n\t");
1207#if defined(BSDTIMES) || defined(_SEQUENT_)
1208	    prusage(&zru, &pp->p_rusage, &pp->p_etime,
1209		    &pp->p_btime);
1210#else /* !BSDTIMES && !SEQUENT */
1211	    lru.tms_utime = pp->p_utime;
1212	    lru.tms_stime = pp->p_stime;
1213	    lru.tms_cutime = 0;
1214	    lru.tms_cstime = 0;
1215	    prusage(&zru, &lru, pp->p_etime,
1216		    pp->p_btime);
1217#endif /* !BSDTIMES && !SEQUENT */
1218
1219	}
1220#ifdef BACKPIPE
1221	pcond = ((tp == pp->p_friends && !inpipe) ||
1222		 (inpipe && pipehead->p_friends == tp && pp == pipetail));
1223#else  /* !BACKPIPE */
1224	pcond = (tp == pp->p_friends);
1225#endif /* BACKPIPE */
1226	if (pcond) {
1227	    if (linp != linbuf)
1228		xputchar('\n');
1229	    if (flag & SHELLDIR && !eq(tp->p_cwd->di_name, dcwd->di_name)) {
1230		xprintf(CGETS(17, 11, "(wd now: "));
1231		dtildepr(dcwd->di_name);
1232		xprintf(")\n");
1233	    }
1234	}
1235#ifdef BACKPIPE
1236	if (inpipe) {
1237	    /*
1238	     * if pmaker == pipetail, we are finished that pipeline, and
1239	     * can now skip to past the head
1240	     */
1241	    if (pmarker == pipetail) {
1242		inpipe = 0;
1243		pp = pipehead;
1244	    }
1245	    else {
1246	    /*
1247	     * set pp to one before the one we want next, so the while below
1248	     * increments to the correct spot.
1249	     */
1250		do
1251		    pp = pp->p_friends;
1252	    	while (pp->p_friends->p_friends != pmarker);
1253	    	pmarker = pp->p_friends;
1254	    }
1255	}
1256	pcond = ((pp = pp->p_friends) != tp || inpipe);
1257#else /* !BACKPIPE */
1258	pcond = ((pp = pp->p_friends) != tp);
1259#endif /* BACKPIPE */
1260    } while (pcond);
1261
1262    if (jobflags & PTIME && (jobflags & (PSTOPPED | PRUNNING)) == 0) {
1263	if (jobflags & NUMBER)
1264	    xprintf("       ");
1265	ptprint(tp);
1266    }
1267    return (jobflags);
1268}
1269
1270/*
1271 * All 4.3 BSD derived implementations are buggy and I've had enough.
1272 * The following implementation produces similar code and works in all
1273 * cases. The 4.3BSD one works only for <, >, !=
1274 */
1275# undef timercmp
1276#  define timercmp(tvp, uvp, cmp) \
1277      (((tvp)->tv_sec == (uvp)->tv_sec) ? \
1278	   ((tvp)->tv_usec cmp (uvp)->tv_usec) : \
1279	   ((tvp)->tv_sec  cmp (uvp)->tv_sec))
1280
1281static void
1282ptprint(tp)
1283    struct process *tp;
1284{
1285#ifdef BSDTIMES
1286    struct timeval tetime, diff;
1287    static struct timeval ztime;
1288    struct sysrusage ru;
1289    struct process *pp = tp;
1290
1291    ru = zru;
1292    tetime = ztime;
1293    do {
1294	ruadd(&ru, &pp->p_rusage);
1295	tvsub(&diff, &pp->p_etime, &pp->p_btime);
1296	if (timercmp(&diff, &tetime, >))
1297	    tetime = diff;
1298    } while ((pp = pp->p_friends) != tp);
1299    prusage(&zru, &ru, &tetime, &ztime);
1300#else /* !BSDTIMES */
1301# ifdef _SEQUENT_
1302    timeval_t tetime, diff;
1303    static timeval_t ztime;
1304    struct process_stats ru;
1305    struct process *pp = tp;
1306
1307    ru = zru;
1308    tetime = ztime;
1309    do {
1310	ruadd(&ru, &pp->p_rusage);
1311	tvsub(&diff, &pp->p_etime, &pp->p_btime);
1312	if (timercmp(&diff, &tetime, >))
1313	    tetime = diff;
1314    } while ((pp = pp->p_friends) != tp);
1315    prusage(&zru, &ru, &tetime, &ztime);
1316# else /* !_SEQUENT_ */
1317#  ifndef POSIX
1318    static time_t ztime = 0;
1319    static time_t zu_time = 0;
1320    static time_t zs_time = 0;
1321    time_t  tetime, diff;
1322    time_t  u_time, s_time;
1323
1324#  else	/* POSIX */
1325    static clock_t ztime = 0;
1326    static clock_t zu_time = 0;
1327    static clock_t zs_time = 0;
1328    clock_t tetime, diff;
1329    clock_t u_time, s_time;
1330
1331#  endif /* POSIX */
1332    struct tms zts, rts;
1333    struct process *pp = tp;
1334
1335    u_time = zu_time;
1336    s_time = zs_time;
1337    tetime = ztime;
1338    do {
1339	u_time += pp->p_utime;
1340	s_time += pp->p_stime;
1341	diff = pp->p_etime - pp->p_btime;
1342	if (diff > tetime)
1343	    tetime = diff;
1344    } while ((pp = pp->p_friends) != tp);
1345    zts.tms_utime = zu_time;
1346    zts.tms_stime = zs_time;
1347    zts.tms_cutime = 0;
1348    zts.tms_cstime = 0;
1349    rts.tms_utime = u_time;
1350    rts.tms_stime = s_time;
1351    rts.tms_cutime = 0;
1352    rts.tms_cstime = 0;
1353    prusage(&zts, &rts, tetime, ztime);
1354# endif /* !_SEQUENT_ */
1355#endif	/* !BSDTIMES */
1356}
1357
1358/*
1359 * dojobs - print all jobs
1360 */
1361/*ARGSUSED*/
1362void
1363dojobs(v, c)
1364    Char  **v;
1365    struct command *c;
1366{
1367    struct process *pp;
1368    int flag = NUMBER | NAME | REASON;
1369    int     i;
1370
1371    USE(c);
1372    if (chkstop)
1373	chkstop = 2;
1374    if (*++v) {
1375	if (v[1] || !eq(*v, STRml))
1376	    stderror(ERR_JOBS);
1377	flag |= FANCY | JOBDIR;
1378    }
1379    for (i = 1; i <= pmaxindex; i++)
1380	for (pp = proclist.p_next; pp; pp = pp->p_next)
1381	    if (pp->p_index == i && pp->p_procid == pp->p_jobid) {
1382		pp->p_flags &= ~PNEEDNOTE;
1383		if (!(pprint(pp, flag) & (PRUNNING | PSTOPPED)))
1384		    pflush(pp);
1385		break;
1386	    }
1387}
1388
1389/*
1390 * dofg - builtin - put the job into the foreground
1391 */
1392/*ARGSUSED*/
1393void
1394dofg(v, c)
1395    Char  **v;
1396    struct command *c;
1397{
1398    struct process *pp;
1399
1400    USE(c);
1401    okpcntl();
1402    ++v;
1403    do {
1404	pp = pfind(*v);
1405	if (!pstart(pp, 1)) {
1406	    pp->p_procid = 0;
1407	    stderror(ERR_NAME|ERR_BADJOB, pp->p_command, strerror(errno));
1408	    continue;
1409	}
1410#ifndef BSDSIGS
1411# ifdef notdef
1412	if (setintr)
1413	    sigignore(SIGINT);
1414# endif
1415#endif /* !BSDSIGS */
1416	pjwait(pp);
1417    } while (*v && *++v);
1418}
1419
1420/*
1421 * %... - builtin - put the job into the foreground
1422 */
1423/*ARGSUSED*/
1424void
1425dofg1(v, c)
1426    Char  **v;
1427    struct command *c;
1428{
1429    struct process *pp;
1430
1431    USE(c);
1432    okpcntl();
1433    pp = pfind(v[0]);
1434    if (!pstart(pp, 1)) {
1435	pp->p_procid = 0;
1436	stderror(ERR_NAME|ERR_BADJOB, pp->p_command, strerror(errno));
1437	return;
1438    }
1439#ifndef BSDSIGS
1440# ifdef notdef
1441    if (setintr)
1442	sigignore(SIGINT);
1443# endif
1444#endif /* !BSDSIGS */
1445    pjwait(pp);
1446}
1447
1448/*
1449 * dobg - builtin - put the job into the background
1450 */
1451/*ARGSUSED*/
1452void
1453dobg(v, c)
1454    Char  **v;
1455    struct command *c;
1456{
1457    struct process *pp;
1458
1459    USE(c);
1460    okpcntl();
1461    ++v;
1462    do {
1463	pp = pfind(*v);
1464	if (!pstart(pp, 0)) {
1465	    pp->p_procid = 0;
1466	    stderror(ERR_NAME|ERR_BADJOB, pp->p_command, strerror(errno));
1467	}
1468    } while (*v && *++v);
1469}
1470
1471/*
1472 * %... & - builtin - put the job into the background
1473 */
1474/*ARGSUSED*/
1475void
1476dobg1(v, c)
1477    Char  **v;
1478    struct command *c;
1479{
1480    struct process *pp;
1481
1482    USE(c);
1483    pp = pfind(v[0]);
1484    if (!pstart(pp, 0)) {
1485	pp->p_procid = 0;
1486	stderror(ERR_NAME|ERR_BADJOB, pp->p_command, strerror(errno));
1487    }
1488}
1489
1490/*
1491 * dostop - builtin - stop the job
1492 */
1493/*ARGSUSED*/
1494void
1495dostop(v, c)
1496    Char  **v;
1497    struct command *c;
1498{
1499    USE(c);
1500#ifdef BSDJOBS
1501    pkill(++v, SIGSTOP);
1502#endif /* BSDJOBS */
1503}
1504
1505/*
1506 * dokill - builtin - superset of kill (1)
1507 */
1508/*ARGSUSED*/
1509void
1510dokill(v, c)
1511    Char  **v;
1512    struct command *c;
1513{
1514    int signum, len = 0;
1515    const char *name;
1516    Char *sigptr;
1517
1518    USE(c);
1519    v++;
1520    if (v[0] && v[0][0] == '-') {
1521	if (v[0][1] == 'l') {
1522	    for (signum = 0; signum <= nsig; signum++) {
1523		if ((name = mesg[signum].iname) != NULL) {
1524		    len += strlen(name) + 1;
1525		    if (len >= T_Cols - 1) {
1526			xputchar('\n');
1527			len = strlen(name) + 1;
1528		    }
1529		    xprintf("%s ", name);
1530		}
1531	    }
1532	    xputchar('\n');
1533	    return;
1534	}
1535 	sigptr = &v[0][1];
1536 	if (v[0][1] == 's') {
1537 	    if (v[1]) {
1538 		v++;
1539 		sigptr = &v[0][0];
1540 	    } else {
1541 		stderror(ERR_NAME | ERR_TOOFEW);
1542 	    }
1543 	}
1544 	if (Isdigit(*sigptr)) {
1545	    char *ep;
1546 	    signum = strtoul(short2str(sigptr), &ep, 0);
1547	    if (*ep || signum < 0 || signum > (MAXSIG-1))
1548		stderror(ERR_NAME | ERR_BADSIG);
1549	}
1550	else {
1551	    for (signum = 0; signum <= nsig; signum++)
1552		if (mesg[signum].iname &&
1553 		    eq(sigptr, str2short(mesg[signum].iname)))
1554		    goto gotsig;
1555 	    setname(short2str(sigptr));
1556	    stderror(ERR_NAME | ERR_UNKSIG);
1557	}
1558gotsig:
1559	v++;
1560    }
1561    else
1562	signum = SIGTERM;
1563    pkill(v, signum);
1564}
1565
1566static void
1567pkill(v, signum)
1568    Char  **v;
1569    int     signum;
1570{
1571    struct process *pp, *np;
1572    int jobflags = 0, err1 = 0;
1573    pid_t     pid;
1574#ifdef BSDSIGS
1575    sigmask_t omask;
1576#endif /* BSDSIGS */
1577    Char   *cp, **vp;
1578
1579#ifdef BSDSIGS
1580    omask = sigmask(SIGCHLD);
1581    if (setintr)
1582	omask |= sigmask(SIGINT);
1583    omask = sigblock(omask) & ~omask;
1584#else /* !BSDSIGS */
1585    if (setintr)
1586	(void) sighold(SIGINT);
1587    (void) sighold(SIGCHLD);
1588#endif /* !BSDSIGS */
1589
1590    /* Avoid globbing %?x patterns */
1591    for (vp = v; vp && *vp; vp++)
1592	if (**vp == '%')
1593	    (void) quote(*vp);
1594
1595    gflag = 0, tglob(v);
1596    if (gflag) {
1597	v = globall(v);
1598	if (v == 0)
1599	    stderror(ERR_NAME | ERR_NOMATCH);
1600    }
1601    else {
1602	v = gargv = saveblk(v);
1603	trim(v);
1604    }
1605
1606
1607    while (v && (cp = *v)) {
1608	if (*cp == '%') {
1609	    np = pp = pfind(cp);
1610	    do
1611		jobflags |= np->p_flags;
1612	    while ((np = np->p_friends) != pp);
1613#ifdef BSDJOBS
1614	    switch (signum) {
1615
1616	    case SIGSTOP:
1617	    case SIGTSTP:
1618	    case SIGTTIN:
1619	    case SIGTTOU:
1620		if ((jobflags & PRUNNING) == 0) {
1621# ifdef SUSPENDED
1622		    xprintf(CGETS(17, 12, "%S: Already suspended\n"), cp);
1623# else /* !SUSPENDED */
1624		    xprintf(CGETS(17, 13, "%S: Already stopped\n"), cp);
1625# endif /* !SUSPENDED */
1626		    err1++;
1627		    goto cont;
1628		}
1629		break;
1630		/*
1631		 * suspend a process, kill -CONT %, then type jobs; the shell
1632		 * says it is suspended, but it is running; thanks jaap..
1633		 */
1634	    case SIGCONT:
1635		if (!pstart(pp, 0)) {
1636		    pp->p_procid = 0;
1637		    stderror(ERR_NAME|ERR_BADJOB, pp->p_command,
1638			     strerror(errno));
1639		}
1640		goto cont;
1641	    default:
1642		break;
1643	    }
1644#endif /* BSDJOBS */
1645	    if (killpg(pp->p_jobid, signum) < 0) {
1646		xprintf("%S: %s\n", cp, strerror(errno));
1647		err1++;
1648	    }
1649#ifdef BSDJOBS
1650	    if (signum == SIGTERM || signum == SIGHUP)
1651		(void) killpg(pp->p_jobid, SIGCONT);
1652#endif /* BSDJOBS */
1653	}
1654	else if (!(Isdigit(*cp) || *cp == '-'))
1655	    stderror(ERR_NAME | ERR_JOBARGS);
1656	else {
1657	    char *ep;
1658#ifndef WINNT_NATIVE
1659	    pid = strtol(short2str(cp), &ep, 10);
1660#else
1661	    pid = strtoul(short2str(cp), &ep, 0);
1662#endif /* WINNT_NATIVE */
1663	    if (*ep)
1664		stderror(ERR_NAME | ERR_JOBARGS);
1665	    else if (kill(pid, signum) < 0) {
1666		xprintf("%d: %s\n", pid, strerror(errno));
1667		err1++;
1668		goto cont;
1669	    }
1670#ifdef BSDJOBS
1671	    if (signum == SIGTERM || signum == SIGHUP)
1672		(void) kill(pid, SIGCONT);
1673#endif /* BSDJOBS */
1674	}
1675cont:
1676	v++;
1677    }
1678    if (gargv)
1679	blkfree(gargv), gargv = 0;
1680#ifdef BSDSIGS
1681    (void) sigsetmask(omask);
1682#else /* !BSDSIGS */
1683    (void) sigrelse(SIGCHLD);
1684    if (setintr)
1685	(void) sigrelse(SIGINT);
1686#endif /* !BSDSIGS */
1687    if (err1)
1688	stderror(ERR_SILENT);
1689}
1690
1691/*
1692 * pstart - start the job in foreground/background
1693 */
1694int
1695pstart(pp, foregnd)
1696    struct process *pp;
1697    int     foregnd;
1698{
1699    int rv = 0;
1700    struct process *np;
1701#ifdef BSDSIGS
1702    sigmask_t omask;
1703#endif /* BSDSIGS */
1704    /* We don't use jobflags in this function right now (see below) */
1705    /* long    jobflags = 0; */
1706
1707#ifdef BSDSIGS
1708    omask = sigblock(sigmask(SIGCHLD));
1709#else /* !BSDSIGS */
1710    (void) sighold(SIGCHLD);
1711#endif
1712    np = pp;
1713    do {
1714	/* We don't use jobflags in this function right now (see below) */
1715	/* jobflags |= np->p_flags; */
1716	if (np->p_flags & (PRUNNING | PSTOPPED)) {
1717	    np->p_flags |= PRUNNING;
1718	    np->p_flags &= ~PSTOPPED;
1719	    if (foregnd)
1720		np->p_flags |= PFOREGND;
1721	    else
1722		np->p_flags &= ~PFOREGND;
1723	}
1724    } while ((np = np->p_friends) != pp);
1725    if (!foregnd)
1726	pclrcurr(pp);
1727    (void) pprint(pp, foregnd ? NAME | JOBDIR : NUMBER | NAME | AMPERSAND);
1728
1729    /* GrP run jobcmd hook if foregrounding */
1730    if (foregnd) {
1731	job_cmd(pp->p_command);
1732    }
1733
1734#ifdef BSDJOBS
1735    if (foregnd) {
1736	rv = tcsetpgrp(FSHTTY, pp->p_jobid);
1737    }
1738    /*
1739     * 1. child process of csh (shell script) receives SIGTTIN/SIGTTOU
1740     * 2. parent process (csh) receives SIGCHLD
1741     * 3. The "csh" signal handling function pchild() is invoked
1742     *    with a SIGCHLD signal.
1743     * 4. pchild() calls wait3(WNOHANG) which returns 0.
1744     *    The child process is NOT ready to be waited for at this time.
1745     *    pchild() returns without picking-up the correct status
1746     *    for the child process which generated the SIGCHILD.
1747     * 5. CONSEQUENCE : csh is UNaware that the process is stopped
1748     * 6. THIS LINE HAS BEEN COMMENTED OUT : if (jobflags&PSTOPPED)
1749     * 	  (beto@aixwiz.austin.ibm.com - aug/03/91)
1750     * 7. I removed the line completely and added extra checks for
1751     *    pstart, so that if a job gets attached to and dies inside
1752     *    a debugger it does not confuse the shell. [christos]
1753     * 8. on the nec sx-4 there seems to be a problem, which requires
1754     *    a syscall(151, getpid(), getpid()) in osinit. Don't ask me
1755     *    what this is doing. [schott@rzg.mpg.de]
1756     */
1757
1758    if (rv != -1)
1759	rv = killpg(pp->p_jobid, SIGCONT);
1760#endif /* BSDJOBS */
1761#ifdef BSDSIGS
1762    (void) sigsetmask(omask);
1763#else /* !BSDSIGS */
1764    (void) sigrelse(SIGCHLD);
1765#endif /* !BSDSIGS */
1766    return rv != -1;
1767}
1768
1769void
1770panystop(neednl)
1771    int    neednl;
1772{
1773    struct process *pp;
1774
1775    chkstop = 2;
1776    for (pp = proclist.p_next; pp; pp = pp->p_next)
1777	if (pp->p_flags & PSTOPPED)
1778	    stderror(ERR_STOPPED, neednl ? "\n" : "");
1779}
1780
1781struct process *
1782pfind(cp)
1783    Char   *cp;
1784{
1785    struct process *pp, *np;
1786
1787    if (cp == 0 || cp[1] == 0 || eq(cp, STRcent2) || eq(cp, STRcentplus)) {
1788	if (pcurrent == NULL)
1789	    stderror(ERR_NAME | ERR_JOBCUR);
1790	return (pcurrent);
1791    }
1792    if (eq(cp, STRcentminus) || eq(cp, STRcenthash)) {
1793	if (pprevious == NULL)
1794	    stderror(ERR_NAME | ERR_JOBPREV);
1795	return (pprevious);
1796    }
1797    if (Isdigit(cp[1])) {
1798	int     idx = atoi(short2str(cp + 1));
1799
1800	for (pp = proclist.p_next; pp; pp = pp->p_next)
1801	    if (pp->p_index == idx && pp->p_procid == pp->p_jobid)
1802		return (pp);
1803	stderror(ERR_NAME | ERR_NOSUCHJOB);
1804    }
1805    np = NULL;
1806    for (pp = proclist.p_next; pp; pp = pp->p_next)
1807	if (pp->p_procid == pp->p_jobid) {
1808	    if (cp[1] == '?') {
1809		Char *dp;
1810
1811		for (dp = pp->p_command; *dp; dp++) {
1812		    if (*dp != cp[2])
1813			continue;
1814		    if (prefix(cp + 2, dp))
1815			goto match;
1816		}
1817	    }
1818	    else if (prefix(cp + 1, pp->p_command)) {
1819	match:
1820		if (np)
1821		    stderror(ERR_NAME | ERR_AMBIG);
1822		np = pp;
1823	    }
1824	}
1825    if (np)
1826	return (np);
1827    stderror(ERR_NAME | (cp[1] == '?' ? ERR_JOBPAT : ERR_NOSUCHJOB));
1828    /* NOTREACHED */
1829    return (0);
1830}
1831
1832
1833/*
1834 * pgetcurr - find most recent job that is not pp, preferably stopped
1835 */
1836static struct process *
1837pgetcurr(pp)
1838    struct process *pp;
1839{
1840    struct process *np;
1841    struct process *xp = NULL;
1842
1843    for (np = proclist.p_next; np; np = np->p_next)
1844	if (np != pcurrent && np != pp && np->p_procid &&
1845	    np->p_procid == np->p_jobid) {
1846	    if (np->p_flags & PSTOPPED)
1847		return (np);
1848	    if (xp == NULL)
1849		xp = np;
1850	}
1851    return (xp);
1852}
1853
1854/*
1855 * donotify - flag the job so as to report termination asynchronously
1856 */
1857/*ARGSUSED*/
1858void
1859donotify(v, c)
1860    Char  **v;
1861    struct command *c;
1862{
1863    struct process *pp;
1864
1865    USE(c);
1866    pp = pfind(*++v);
1867    pp->p_flags |= PNOTIFY;
1868}
1869
1870/*
1871 * Do the fork and whatever should be done in the child side that
1872 * should not be done if we are not forking at all (like for simple builtin's)
1873 * Also do everything that needs any signals fiddled with in the parent side
1874 *
1875 * Wanttty tells whether process and/or tty pgrps are to be manipulated:
1876 *	-1:	leave tty alone; inherit pgrp from parent
1877 *	 0:	already have tty; manipulate process pgrps only
1878 *	 1:	want to claim tty; manipulate process and tty pgrps
1879 * It is usually just the value of tpgrp.
1880 */
1881
1882int
1883pfork(t, wanttty)
1884    struct command *t;		/* command we are forking for */
1885    int     wanttty;
1886{
1887    int pid;
1888    int    ignint = 0;
1889    int     pgrp;
1890#ifdef BSDSIGS
1891    sigmask_t omask = 0;
1892#endif /* BSDSIGS */
1893#ifdef SIGSYNCH
1894    sigvec_t osv;
1895    static sigvec_t nsv = {synch_handler, (sigset_t) ~0, 0};
1896#endif /* SIGSYNCH */
1897
1898    /*
1899     * A child will be uninterruptible only under very special conditions.
1900     * Remember that the semantics of '&' is implemented by disconnecting the
1901     * process from the tty so signals do not need to ignored just for '&'.
1902     * Thus signals are set to default action for children unless: we have had
1903     * an "onintr -" (then specifically ignored) we are not playing with
1904     * signals (inherit action)
1905     */
1906    if (setintr)
1907	ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT))
1908	    || (gointr && eq(gointr, STRminus));
1909
1910#ifdef COHERENT
1911    ignint |= gointr && eq(gointr, STRminus);
1912#endif /* COHERENT */
1913
1914    /*
1915     * Check for maximum nesting of 16 processes to avoid Forking loops
1916     */
1917    if (child == 16)
1918	stderror(ERR_NESTING, 16);
1919#ifdef SIGSYNCH
1920    if (mysigvec(SIGSYNCH, &nsv, &osv))
1921	stderror(ERR_SYSTEM, "pfork: sigvec set", strerror(errno));
1922#endif /* SIGSYNCH */
1923    /*
1924     * Hold SIGCHLD until we have the process installed in our table.
1925     */
1926    if (wanttty < 0) {
1927#ifdef BSDSIGS
1928	omask = sigblock(sigmask(SIGCHLD));
1929#else /* !BSDSIGS */
1930	(void) sighold(SIGCHLD);
1931#endif /* !BSDSIGS */
1932    }
1933    while ((pid = fork()) == -1)
1934	if (setintr == 0)
1935	    (void) sleep(FORKSLEEP);
1936	else {
1937	    if (wanttty < 0)
1938#ifdef BSDSIGS
1939		(void) sigsetmask(omask);
1940#else /* !BSDSIGS */
1941		(void) sigrelse(SIGCHLD);
1942	    (void) sigrelse(SIGINT);
1943#endif /* !BSDSIGS */
1944	    stderror(ERR_NOPROC);
1945	}
1946    if (pid == 0) {
1947	settimes();
1948	pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
1949	pflushall();
1950	pcurrjob = NULL;
1951#if !defined(BSDTIMES) && !defined(_SEQUENT_)
1952	timesdone = 0;
1953#endif /* !defined(BSDTIMES) && !defined(_SEQUENT_) */
1954	child++;
1955	if (setintr) {
1956	    setintr = 0;	/* until I think otherwise */
1957#ifndef BSDSIGS
1958	    if (wanttty < 0)
1959		(void) sigrelse(SIGCHLD);
1960#endif /* !BSDSIGS */
1961	    /*
1962	     * Children just get blown away on SIGINT, SIGQUIT unless "onintr
1963	     * -" seen.
1964	     */
1965	    (void) signal(SIGINT, ignint ? SIG_IGN : SIG_DFL);
1966	    (void) signal(SIGQUIT, ignint ? SIG_IGN : SIG_DFL);
1967#ifdef BSDJOBS
1968	    if (wanttty >= 0) {
1969		/* make stoppable */
1970		(void) signal(SIGTSTP, SIG_DFL);
1971		(void) signal(SIGTTIN, SIG_DFL);
1972		(void) signal(SIGTTOU, SIG_DFL);
1973	    }
1974#endif /* BSDJOBS */
1975	    (void) signal(SIGTERM, parterm);
1976	}
1977	else if (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) {
1978	    (void) signal(SIGINT, SIG_IGN);
1979	    (void) signal(SIGQUIT, SIG_IGN);
1980	}
1981#ifdef OREO
1982	sigignore(SIGIO);	/* ignore SIGIO in child too */
1983#endif /* OREO */
1984
1985	pgetty(wanttty, pgrp);
1986	/*
1987	 * Nohup and nice apply only to NODE_COMMAND's but it would be nice
1988	 * (?!?) if you could say "nohup (foo;bar)" Then the parser would have
1989	 * to know about nice/nohup/time
1990	 */
1991	if (t->t_dflg & F_NOHUP)
1992	    (void) signal(SIGHUP, SIG_IGN);
1993	if (t->t_dflg & F_NICE) {
1994	    int nval = SIGN_EXTEND_CHAR(t->t_nice);
1995#ifdef HAVE_SETPRIORITY
1996	    if (setpriority(PRIO_PROCESS, 0, nval) == -1 && errno)
1997		    stderror(ERR_SYSTEM, "setpriority", strerror(errno));
1998#else /* !HAVE_SETPRIORITY */
1999	    (void) nice(nval);
2000#endif /* !HAVE_SETPRIORITY */
2001	}
2002#ifdef F_VER
2003        if (t->t_dflg & F_VER) {
2004	    tsetenv(STRSYSTYPE, t->t_systype ? STRbsd43 : STRsys53);
2005	    dohash(NULL, NULL);
2006	}
2007#endif /* F_VER */
2008#ifdef SIGSYNCH
2009	/* rfw 8/89 now parent can continue */
2010	if (kill(getppid(), SIGSYNCH))
2011	    stderror(ERR_SYSTEM, "pfork child: kill", strerror(errno));
2012#endif /* SIGSYNCH */
2013
2014    }
2015    else {
2016#ifdef POSIXJOBS
2017        if (wanttty >= 0) {
2018	    /*
2019	     * `Walking' process group fix from Beto Appleton.
2020	     * (beto@aixwiz.austin.ibm.com)
2021	     * If setpgid fails at this point that means that
2022	     * our process leader has died. We flush the current
2023	     * job and become the process leader ourselves.
2024	     * The parent will figure that out later.
2025	     */
2026	    pgrp = pcurrjob ? pcurrjob->p_jobid : pid;
2027	    if (setpgid(pid, pgrp) == -1 && errno == EPERM) {
2028		pcurrjob = NULL;
2029		/*
2030		 * We don't care if this causes an error here;
2031		 * then we are already in the right process group
2032		 */
2033		(void) setpgid(pid, pgrp = pid);
2034	    }
2035	}
2036#endif /* POSIXJOBS */
2037	palloc(pid, t);
2038#ifdef SIGSYNCH
2039	/*
2040	 * rfw 8/89 Wait for child to own terminal.  Solves half of ugly
2041	 * synchronization problem.  With this change, we know that the only
2042	 * reason setpgrp to a previous process in a pipeline can fail is that
2043	 * the previous process has already exited. Without this hack, he may
2044	 * either have exited or not yet started to run.  Two uglies become
2045	 * one.
2046	 */
2047	(void) sigpause(omask & ~SYNCHMASK);
2048	if (mysigvec(SIGSYNCH, &osv, NULL))
2049	    stderror(ERR_SYSTEM, "pfork parent: sigvec restore",
2050		     strerror(errno));
2051#endif /* SIGSYNCH */
2052
2053	if (wanttty < 0) {
2054#ifdef BSDSIGS
2055	    (void) sigsetmask(omask);
2056#else /* !BSDSIGS */
2057	    (void) sigrelse(SIGCHLD);
2058#endif /* !BSDSIGS */
2059	}
2060    }
2061    return (pid);
2062}
2063
2064static void
2065okpcntl()
2066{
2067    if (tpgrp == -1)
2068	stderror(ERR_JOBCONTROL);
2069    if (tpgrp == 0)
2070	stderror(ERR_JOBCTRLSUB);
2071}
2072
2073
2074static void
2075setttypgrp(pgrp)
2076    int pgrp;
2077{
2078    /*
2079     * If we are piping out a builtin, eg. 'echo | more' things can go
2080     * out of sequence, i.e. the more can run before the echo. This
2081     * can happen even if we have vfork, since the echo will be forked
2082     * with the regular fork. In this case, we need to set the tty
2083     * pgrp ourselves. If that happens, then the process will be still
2084     * alive. And the tty process group will already be set.
2085     * This should fix the famous sequent problem as a side effect:
2086     *    The controlling terminal is lost if all processes in the
2087     *    terminal process group are zombies. In this case tcgetpgrp()
2088     *    returns 0. If this happens we must set the terminal process
2089     *    group again.
2090     */
2091    if (tcgetpgrp(FSHTTY) != pgrp) {
2092#ifdef POSIXJOBS
2093        /*
2094	 * tcsetpgrp will set SIGTTOU to all the the processes in
2095	 * the background according to POSIX... We ignore this here.
2096	 */
2097	signalfun_t old = sigset(SIGTTOU, SIG_IGN);
2098#endif
2099	(void) tcsetpgrp(FSHTTY, pgrp);
2100# ifdef POSIXJOBS
2101	(void) sigset(SIGTTOU, old);
2102# endif
2103
2104    }
2105}
2106
2107
2108/*
2109 * if we don't have vfork(), things can still go in the wrong order
2110 * resulting in the famous 'Stopped (tty output)'. But some systems
2111 * don't permit the setpgid() call, (these are more recent secure
2112 * systems such as ibm's aix), when they do. Then we'd rather print
2113 * an error message than hang the shell!
2114 * I am open to suggestions how to fix that.
2115 */
2116void
2117pgetty(wanttty, pgrp)
2118    int     wanttty, pgrp;
2119{
2120#ifdef BSDJOBS
2121# if defined(BSDSIGS) && defined(POSIXJOBS)
2122    sigmask_t omask = 0;
2123# endif /* BSDSIGS && POSIXJOBS */
2124
2125# ifdef JOBDEBUG
2126    xprintf("wanttty %d pid %d opgrp%d pgrp %d tpgrp %d\n",
2127	    wanttty, getpid(), pgrp, mygetpgrp(), tcgetpgrp(FSHTTY));
2128# endif /* JOBDEBUG */
2129# ifdef POSIXJOBS
2130    /*
2131     * christos: I am blocking the tty signals till I've set things
2132     * correctly....
2133     */
2134    if (wanttty > 0)
2135#  ifdef BSDSIGS
2136	omask = sigblock(sigmask(SIGTSTP)|sigmask(SIGTTIN));
2137#  else /* !BSDSIGS */
2138    {
2139	(void) sighold(SIGTSTP);
2140	(void) sighold(SIGTTIN);
2141    }
2142#  endif /* !BSDSIGS */
2143# endif /* POSIXJOBS */
2144
2145# ifndef POSIXJOBS
2146    if (wanttty > 0)
2147	setttypgrp(pgrp);
2148# endif /* !POSIXJOBS */
2149
2150    /*
2151     * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de>
2152     * Don't check for tpgrp >= 0 so even non-interactive shells give
2153     * background jobs process groups Same for the comparison in the other part
2154     * of the #ifdef
2155     */
2156    if (wanttty >= 0) {
2157	if (setpgid(0, pgrp) == -1) {
2158# ifdef POSIXJOBS
2159	    /* Walking process group fix; see above */
2160	    if (setpgid(0, pgrp = getpid()) == -1) {
2161# endif /* POSIXJOBS */
2162		stderror(ERR_SYSTEM, "setpgid child:\n", strerror(errno));
2163		xexit(0);
2164# ifdef POSIXJOBS
2165	    }
2166	    wanttty = pgrp;  /* Now we really want the tty, since we became the
2167			      * the process group leader
2168			      */
2169# endif /* POSIXJOBS */
2170	}
2171    }
2172
2173# ifdef POSIXJOBS
2174    if (wanttty > 0)
2175	setttypgrp(pgrp);
2176#  ifdef BSDSIGS
2177    (void) sigsetmask(omask);
2178#  else /* BSDSIGS */
2179    (void) sigrelse(SIGTSTP);
2180    (void) sigrelse(SIGTTIN);
2181#  endif /* !BSDSIGS */
2182# endif /* POSIXJOBS */
2183
2184# ifdef JOBDEBUG
2185    xprintf("wanttty %d pid %d pgrp %d tpgrp %d\n",
2186	    wanttty, getpid(), mygetpgrp(), tcgetpgrp(FSHTTY));
2187# endif /* JOBDEBUG */
2188
2189    if (tpgrp > 0)
2190	tpgrp = 0;		/* gave tty away */
2191#endif /* BSDJOBS */
2192}
2193