xref: /illumos-gate/usr/src/contrib/ast/src/cmd/ksh93/sh/jobs.c (revision b30d193948be5a7794d7ae3ba0ed9c2f72c88e0f)
1*b30d1939SAndy Fiddaman /***********************************************************************
2*b30d1939SAndy Fiddaman *                                                                      *
3*b30d1939SAndy Fiddaman *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1982-2012 AT&T Intellectual Property          *
5*b30d1939SAndy Fiddaman *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
7*b30d1939SAndy Fiddaman *                    by AT&T Intellectual Property                     *
8*b30d1939SAndy Fiddaman *                                                                      *
9*b30d1939SAndy Fiddaman *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12*b30d1939SAndy Fiddaman *                                                                      *
13*b30d1939SAndy Fiddaman *              Information and Software Systems Research               *
14*b30d1939SAndy Fiddaman *                            AT&T Research                             *
15*b30d1939SAndy Fiddaman *                           Florham Park NJ                            *
16*b30d1939SAndy Fiddaman *                                                                      *
17*b30d1939SAndy Fiddaman *                  David Korn <dgk@research.att.com>                   *
18*b30d1939SAndy Fiddaman *                                                                      *
19*b30d1939SAndy Fiddaman ***********************************************************************/
20*b30d1939SAndy Fiddaman #pragma prototyped
21*b30d1939SAndy Fiddaman /*
22*b30d1939SAndy Fiddaman  *  Job control for UNIX Shell
23*b30d1939SAndy Fiddaman  *
24*b30d1939SAndy Fiddaman  *   David Korn
25*b30d1939SAndy Fiddaman  *   AT&T Labs
26*b30d1939SAndy Fiddaman  *
27*b30d1939SAndy Fiddaman  *  Written October, 1982
28*b30d1939SAndy Fiddaman  *  Rewritten April, 1988
29*b30d1939SAndy Fiddaman  *  Revised January, 1992
30*b30d1939SAndy Fiddaman  */
31*b30d1939SAndy Fiddaman 
32*b30d1939SAndy Fiddaman #include	"defs.h"
33*b30d1939SAndy Fiddaman #include	<wait.h>
34*b30d1939SAndy Fiddaman #include	"io.h"
35*b30d1939SAndy Fiddaman #include	"jobs.h"
36*b30d1939SAndy Fiddaman #include	"history.h"
37*b30d1939SAndy Fiddaman 
38*b30d1939SAndy Fiddaman #if !defined(WCONTINUED) || !defined(WIFCONTINUED)
39*b30d1939SAndy Fiddaman #   undef  WCONTINUED
40*b30d1939SAndy Fiddaman #   define WCONTINUED	0
41*b30d1939SAndy Fiddaman #   undef  WIFCONTINUED
42*b30d1939SAndy Fiddaman #   define WIFCONTINUED(wstat)	(0)
43*b30d1939SAndy Fiddaman #endif
44*b30d1939SAndy Fiddaman 
45*b30d1939SAndy Fiddaman #define	NJOB_SAVELIST	4
46*b30d1939SAndy Fiddaman 
47*b30d1939SAndy Fiddaman /*
48*b30d1939SAndy Fiddaman  * temporary hack to get W* macros to work
49*b30d1939SAndy Fiddaman  */
50*b30d1939SAndy Fiddaman #undef wait
51*b30d1939SAndy Fiddaman #define wait    ______wait
52*b30d1939SAndy Fiddaman /*
53*b30d1939SAndy Fiddaman  * This struct saves a link list of processes that have non-zero exit
54*b30d1939SAndy Fiddaman  * status, have had $! saved, but haven't been waited for
55*b30d1939SAndy Fiddaman  */
56*b30d1939SAndy Fiddaman struct jobsave
57*b30d1939SAndy Fiddaman {
58*b30d1939SAndy Fiddaman 	struct jobsave	*next;
59*b30d1939SAndy Fiddaman 	pid_t		pid;
60*b30d1939SAndy Fiddaman 	unsigned short	exitval;
61*b30d1939SAndy Fiddaman 	unsigned short	env;
62*b30d1939SAndy Fiddaman };
63*b30d1939SAndy Fiddaman 
64*b30d1939SAndy Fiddaman static struct jobsave *job_savelist;
65*b30d1939SAndy Fiddaman static int njob_savelist;
66*b30d1939SAndy Fiddaman static struct process *pwfg;
67*b30d1939SAndy Fiddaman static int jobfork;
68*b30d1939SAndy Fiddaman 
pid_fromstring(char * str)69*b30d1939SAndy Fiddaman pid_t	pid_fromstring(char *str)
70*b30d1939SAndy Fiddaman {
71*b30d1939SAndy Fiddaman 	pid_t	pid;
72*b30d1939SAndy Fiddaman 	char	*last;
73*b30d1939SAndy Fiddaman 	errno = 0;
74*b30d1939SAndy Fiddaman 	if(sizeof(pid)==sizeof(Sflong_t))
75*b30d1939SAndy Fiddaman 		pid = (pid_t)strtoll(str, &last, 10);
76*b30d1939SAndy Fiddaman 	else
77*b30d1939SAndy Fiddaman 		pid = (pid_t)strtol(str, &last, 10);
78*b30d1939SAndy Fiddaman 	if(errno==ERANGE || *last)
79*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_exit(1),"%s: invalid process id",str);
80*b30d1939SAndy Fiddaman 	return(pid);
81*b30d1939SAndy Fiddaman }
82*b30d1939SAndy Fiddaman 
init_savelist(void)83*b30d1939SAndy Fiddaman static void init_savelist(void)
84*b30d1939SAndy Fiddaman {
85*b30d1939SAndy Fiddaman 	register struct jobsave *jp;
86*b30d1939SAndy Fiddaman 	while(njob_savelist < NJOB_SAVELIST)
87*b30d1939SAndy Fiddaman 	{
88*b30d1939SAndy Fiddaman 		jp = newof(0,struct jobsave,1,0);
89*b30d1939SAndy Fiddaman 		jp->next = job_savelist;
90*b30d1939SAndy Fiddaman 		job_savelist = jp;
91*b30d1939SAndy Fiddaman 		njob_savelist++;
92*b30d1939SAndy Fiddaman 	}
93*b30d1939SAndy Fiddaman }
94*b30d1939SAndy Fiddaman 
95*b30d1939SAndy Fiddaman struct back_save
96*b30d1939SAndy Fiddaman {
97*b30d1939SAndy Fiddaman 	int		count;
98*b30d1939SAndy Fiddaman 	struct jobsave	*list;
99*b30d1939SAndy Fiddaman 	struct back_save *prev;
100*b30d1939SAndy Fiddaman };
101*b30d1939SAndy Fiddaman 
102*b30d1939SAndy Fiddaman #define BYTE(n)		(((n)+CHAR_BIT-1)/CHAR_BIT)
103*b30d1939SAndy Fiddaman #define MAXMSG	25
104*b30d1939SAndy Fiddaman #define SH_STOPSIG	(SH_EXITSIG<<1)
105*b30d1939SAndy Fiddaman 
106*b30d1939SAndy Fiddaman #ifdef VSUSP
107*b30d1939SAndy Fiddaman #   ifndef CNSUSP
108*b30d1939SAndy Fiddaman #	ifdef _POSIX_VDISABLE
109*b30d1939SAndy Fiddaman #	   define CNSUSP	_POSIX_VDISABLE
110*b30d1939SAndy Fiddaman #	else
111*b30d1939SAndy Fiddaman #	   define CNSUSP	0
112*b30d1939SAndy Fiddaman #	endif /* _POSIX_VDISABLE */
113*b30d1939SAndy Fiddaman #   endif /* CNSUSP */
114*b30d1939SAndy Fiddaman #   ifndef CSWTCH
115*b30d1939SAndy Fiddaman #	ifdef CSUSP
116*b30d1939SAndy Fiddaman #	    define CSWTCH	CSUSP
117*b30d1939SAndy Fiddaman #	else
118*b30d1939SAndy Fiddaman #	    define CSWTCH	('z'&037)
119*b30d1939SAndy Fiddaman #	endif /* CSUSP */
120*b30d1939SAndy Fiddaman #   endif /* CSWTCH */
121*b30d1939SAndy Fiddaman #endif /* VSUSP */
122*b30d1939SAndy Fiddaman 
123*b30d1939SAndy Fiddaman /* Process states */
124*b30d1939SAndy Fiddaman #define P_EXITSAVE	01
125*b30d1939SAndy Fiddaman #define P_STOPPED	02
126*b30d1939SAndy Fiddaman #define P_NOTIFY	04
127*b30d1939SAndy Fiddaman #define P_SIGNALLED	010
128*b30d1939SAndy Fiddaman #define P_STTY		020
129*b30d1939SAndy Fiddaman #define P_DONE		040
130*b30d1939SAndy Fiddaman #define P_COREDUMP	0100
131*b30d1939SAndy Fiddaman #define P_DISOWN	0200
132*b30d1939SAndy Fiddaman #define P_FG		0400
133*b30d1939SAndy Fiddaman #ifdef SHOPT_BGX
134*b30d1939SAndy Fiddaman #define P_BG		01000
135*b30d1939SAndy Fiddaman #endif /* SHOPT_BGX */
136*b30d1939SAndy Fiddaman 
137*b30d1939SAndy Fiddaman static int		job_chksave(pid_t,long);
138*b30d1939SAndy Fiddaman static struct process	*job_bypid(pid_t);
139*b30d1939SAndy Fiddaman static struct process	*job_byjid(int);
140*b30d1939SAndy Fiddaman static char		*job_sigmsg(int);
141*b30d1939SAndy Fiddaman static int		job_alloc(void);
142*b30d1939SAndy Fiddaman static void		job_free(int);
143*b30d1939SAndy Fiddaman static struct process	*job_unpost(struct process*,int);
144*b30d1939SAndy Fiddaman static void		job_unlink(struct process*);
145*b30d1939SAndy Fiddaman static void		job_prmsg(struct process*);
146*b30d1939SAndy Fiddaman static struct process	*freelist;
147*b30d1939SAndy Fiddaman static char		beenhere;
148*b30d1939SAndy Fiddaman static char		possible;
149*b30d1939SAndy Fiddaman static struct process	dummy;
150*b30d1939SAndy Fiddaman static char		by_number;
151*b30d1939SAndy Fiddaman static Sfio_t		*outfile;
152*b30d1939SAndy Fiddaman static pid_t		lastpid;
153*b30d1939SAndy Fiddaman static struct back_save	bck;
154*b30d1939SAndy Fiddaman 
155*b30d1939SAndy Fiddaman #ifdef JOBS
156*b30d1939SAndy Fiddaman     static void			job_set(struct process*);
157*b30d1939SAndy Fiddaman     static void			job_reset(struct process*);
158*b30d1939SAndy Fiddaman     static void			job_waitsafe(int);
159*b30d1939SAndy Fiddaman     static struct process	*job_byname(char*);
160*b30d1939SAndy Fiddaman     static struct process	*job_bystring(char*);
161*b30d1939SAndy Fiddaman     static struct termios	my_stty;  /* terminal state for shell */
162*b30d1939SAndy Fiddaman     static char			*job_string;
163*b30d1939SAndy Fiddaman #else
164*b30d1939SAndy Fiddaman     extern const char		e_coredump[];
165*b30d1939SAndy Fiddaman #endif /* JOBS */
166*b30d1939SAndy Fiddaman 
167*b30d1939SAndy Fiddaman #ifdef SIGTSTP
168*b30d1939SAndy Fiddaman     static void		job_unstop(struct process*);
169*b30d1939SAndy Fiddaman     static void		job_fgrp(struct process*, int);
170*b30d1939SAndy Fiddaman #   ifndef _lib_tcgetpgrp
171*b30d1939SAndy Fiddaman #	ifdef TIOCGPGRP
172*b30d1939SAndy Fiddaman 	   static int _i_;
173*b30d1939SAndy Fiddaman #	   define tcgetpgrp(a) (ioctl(a, TIOCGPGRP, &_i_)>=0?_i_:-1)
174*b30d1939SAndy Fiddaman #	endif /* TIOCGPGRP */
tcsetpgrp(int fd,pid_t pgrp)175*b30d1939SAndy Fiddaman 	int tcsetpgrp(int fd,pid_t pgrp)
176*b30d1939SAndy Fiddaman 	{
177*b30d1939SAndy Fiddaman 		int pgid = pgrp;
178*b30d1939SAndy Fiddaman #		ifdef TIOCGPGRP
179*b30d1939SAndy Fiddaman 			return(ioctl(fd, TIOCSPGRP, &pgid));
180*b30d1939SAndy Fiddaman #		else
181*b30d1939SAndy Fiddaman 			return(-1);
182*b30d1939SAndy Fiddaman #		endif /* TIOCGPGRP */
183*b30d1939SAndy Fiddaman 	}
184*b30d1939SAndy Fiddaman #   endif /* _lib_tcgetpgrp */
185*b30d1939SAndy Fiddaman #else
186*b30d1939SAndy Fiddaman #   define job_unstop(pw)
187*b30d1939SAndy Fiddaman #   undef CNSUSP
188*b30d1939SAndy Fiddaman #endif /* SIGTSTP */
189*b30d1939SAndy Fiddaman 
190*b30d1939SAndy Fiddaman #ifndef OTTYDISC
191*b30d1939SAndy Fiddaman #   undef NTTYDISC
192*b30d1939SAndy Fiddaman #endif /* OTTYDISC */
193*b30d1939SAndy Fiddaman 
194*b30d1939SAndy Fiddaman #ifdef JOBS
195*b30d1939SAndy Fiddaman 
196*b30d1939SAndy Fiddaman typedef int (*Waitevent_f)(int,long,int);
197*b30d1939SAndy Fiddaman 
198*b30d1939SAndy Fiddaman #ifdef SHOPT_BGX
job_chldtrap(Shell_t * shp,const char * trap,int unpost)199*b30d1939SAndy Fiddaman void job_chldtrap(Shell_t *shp, const char *trap, int unpost)
200*b30d1939SAndy Fiddaman {
201*b30d1939SAndy Fiddaman 	register struct process *pw,*pwnext;
202*b30d1939SAndy Fiddaman 	pid_t bckpid;
203*b30d1939SAndy Fiddaman 	int oldexit,trapnote;
204*b30d1939SAndy Fiddaman 	job_lock();
205*b30d1939SAndy Fiddaman 	shp->sigflag[SIGCHLD] &= ~SH_SIGTRAP;
206*b30d1939SAndy Fiddaman 	trapnote = shp->trapnote;
207*b30d1939SAndy Fiddaman 	shp->trapnote = 0;
208*b30d1939SAndy Fiddaman 	for(pw=job.pwlist;pw;pw=pwnext)
209*b30d1939SAndy Fiddaman 	{
210*b30d1939SAndy Fiddaman 		pwnext = pw->p_nxtjob;
211*b30d1939SAndy Fiddaman 		if((pw->p_flag&(P_BG|P_DONE)) != (P_BG|P_DONE))
212*b30d1939SAndy Fiddaman 			continue;
213*b30d1939SAndy Fiddaman 		pw->p_flag &= ~P_BG;
214*b30d1939SAndy Fiddaman 		bckpid = shp->bckpid;
215*b30d1939SAndy Fiddaman 		oldexit = shp->savexit;
216*b30d1939SAndy Fiddaman 		shp->bckpid = pw->p_pid;
217*b30d1939SAndy Fiddaman 		shp->savexit = pw->p_exit;
218*b30d1939SAndy Fiddaman 		if(pw->p_flag&P_SIGNALLED)
219*b30d1939SAndy Fiddaman 			shp->savexit |= SH_EXITSIG;
220*b30d1939SAndy Fiddaman 		sh_trap(trap,0);
221*b30d1939SAndy Fiddaman 		if(pw->p_pid==bckpid && unpost)
222*b30d1939SAndy Fiddaman 			job_unpost(pw,0);
223*b30d1939SAndy Fiddaman 		shp->savexit = oldexit;
224*b30d1939SAndy Fiddaman 		shp->bckpid = bckpid;
225*b30d1939SAndy Fiddaman 	}
226*b30d1939SAndy Fiddaman 	shp->trapnote = trapnote;
227*b30d1939SAndy Fiddaman 	job_unlock();
228*b30d1939SAndy Fiddaman }
229*b30d1939SAndy Fiddaman #endif /* SHOPT_BGX */
230*b30d1939SAndy Fiddaman 
231*b30d1939SAndy Fiddaman /*
232*b30d1939SAndy Fiddaman  * return next on link list of jobsave free list
233*b30d1939SAndy Fiddaman  */
jobsave_create(pid_t pid)234*b30d1939SAndy Fiddaman static struct jobsave *jobsave_create(pid_t pid)
235*b30d1939SAndy Fiddaman {
236*b30d1939SAndy Fiddaman 	register struct jobsave *jp = job_savelist;
237*b30d1939SAndy Fiddaman 	job_chksave(pid,-1);
238*b30d1939SAndy Fiddaman 	if(++bck.count > shgd->lim.child_max)
239*b30d1939SAndy Fiddaman 		job_chksave(0,-1);
240*b30d1939SAndy Fiddaman 	if(jp)
241*b30d1939SAndy Fiddaman 	{
242*b30d1939SAndy Fiddaman 		njob_savelist--;
243*b30d1939SAndy Fiddaman 		job_savelist = jp->next;
244*b30d1939SAndy Fiddaman 	}
245*b30d1939SAndy Fiddaman 	else
246*b30d1939SAndy Fiddaman 		jp = newof(0,struct jobsave,1,0);
247*b30d1939SAndy Fiddaman 	if(jp)
248*b30d1939SAndy Fiddaman 	{
249*b30d1939SAndy Fiddaman 		jp->pid = pid;
250*b30d1939SAndy Fiddaman 		jp->next = bck.list;
251*b30d1939SAndy Fiddaman 		bck.list = jp;
252*b30d1939SAndy Fiddaman 		jp->exitval = 0;
253*b30d1939SAndy Fiddaman 	}
254*b30d1939SAndy Fiddaman 	return(jp);
255*b30d1939SAndy Fiddaman }
256*b30d1939SAndy Fiddaman 
257*b30d1939SAndy Fiddaman #if SHOPT_COSHELL
sh_copid(struct cosh * csp)258*b30d1939SAndy Fiddaman     pid_t sh_copid(struct cosh *csp)
259*b30d1939SAndy Fiddaman     {
260*b30d1939SAndy Fiddaman 	return(COPID_BIT|(csp->id<<16)|csp->cojob->id);
261*b30d1939SAndy Fiddaman     }
262*b30d1939SAndy Fiddaman 
263*b30d1939SAndy Fiddaman 
sh_pid2str(Shell_t * shp,pid_t pid)264*b30d1939SAndy Fiddaman     char  *sh_pid2str(Shell_t *shp,pid_t pid)
265*b30d1939SAndy Fiddaman     {
266*b30d1939SAndy Fiddaman 	struct cosh  *csp=0;
267*b30d1939SAndy Fiddaman 	if(pid&COPID_BIT)
268*b30d1939SAndy Fiddaman 	{
269*b30d1939SAndy Fiddaman 		int id = (pid>>16) &0x3f;
270*b30d1939SAndy Fiddaman 		for(csp=job.colist; csp; csp = csp->next)
271*b30d1939SAndy Fiddaman 		{
272*b30d1939SAndy Fiddaman 			if(csp->id == id)
273*b30d1939SAndy Fiddaman 				break;
274*b30d1939SAndy Fiddaman 		}
275*b30d1939SAndy Fiddaman 	}
276*b30d1939SAndy Fiddaman 	if(csp)
277*b30d1939SAndy Fiddaman 		sfprintf(shp->strbuf,"%s.%d%c",csp->name,pid&0xff,0);
278*b30d1939SAndy Fiddaman 	else
279*b30d1939SAndy Fiddaman 		sfprintf(shp->strbuf,"%d%c",pid,0);
280*b30d1939SAndy Fiddaman 	return(sfstruse(shp->strbuf));
281*b30d1939SAndy Fiddaman     }
282*b30d1939SAndy Fiddaman 
job_cowalk(int (* fun)(struct process *,int),int arg,char * name)283*b30d1939SAndy Fiddaman     int job_cowalk(int (*fun)(struct process*,int),int arg,char *name)
284*b30d1939SAndy Fiddaman     {
285*b30d1939SAndy Fiddaman 	Shell_t		*shp = sh_getinterp();
286*b30d1939SAndy Fiddaman 	struct cosh	*csp;
287*b30d1939SAndy Fiddaman 	struct process	*pw,*pwnext;
288*b30d1939SAndy Fiddaman 	pid_t		val;
289*b30d1939SAndy Fiddaman 	int		n,r=0;
290*b30d1939SAndy Fiddaman 	char		*cp = strchr(name,'.');
291*b30d1939SAndy Fiddaman 	if(!cp)
292*b30d1939SAndy Fiddaman 		n = strlen(name);
293*b30d1939SAndy Fiddaman 	else
294*b30d1939SAndy Fiddaman 		n = cp-name;
295*b30d1939SAndy Fiddaman 	for(csp=(struct cosh*)job.colist;csp;csp=csp->next)
296*b30d1939SAndy Fiddaman 	{
297*b30d1939SAndy Fiddaman 		if(memcmp(name,csp->name,n)==0 && csp->name[n]==0)
298*b30d1939SAndy Fiddaman 			break;
299*b30d1939SAndy Fiddaman 	}
300*b30d1939SAndy Fiddaman 	if(!csp)
301*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_exit(1),e_jobusage,name);
302*b30d1939SAndy Fiddaman 	if(cp)
303*b30d1939SAndy Fiddaman 	{
304*b30d1939SAndy Fiddaman 		n = pid_fromstring(cp+1);
305*b30d1939SAndy Fiddaman 		val = (csp->id<<16)|n|COPID_BIT;
306*b30d1939SAndy Fiddaman 	}
307*b30d1939SAndy Fiddaman 	job_reap(SIGCHLD);
308*b30d1939SAndy Fiddaman 	for(n=0,pw=job.pwlist; pw; pw=pwnext)
309*b30d1939SAndy Fiddaman 	{
310*b30d1939SAndy Fiddaman 		pwnext = pw->p_nxtjob;
311*b30d1939SAndy Fiddaman 		if((cp && val==pw->p_pid) || (pw->p_cojob && pw->p_cojob->local==(void*)csp))
312*b30d1939SAndy Fiddaman 		{
313*b30d1939SAndy Fiddaman 			if(fun)
314*b30d1939SAndy Fiddaman 			{
315*b30d1939SAndy Fiddaman 				if(pw->p_flag&P_DONE)
316*b30d1939SAndy Fiddaman 					continue;
317*b30d1939SAndy Fiddaman 				r |= (*fun)(pw,arg);
318*b30d1939SAndy Fiddaman 			}
319*b30d1939SAndy Fiddaman 			else
320*b30d1939SAndy Fiddaman 				job_wait(-pw->p_pid);
321*b30d1939SAndy Fiddaman 			n++;
322*b30d1939SAndy Fiddaman 		}
323*b30d1939SAndy Fiddaman 	}
324*b30d1939SAndy Fiddaman 	if(!n)
325*b30d1939SAndy Fiddaman 		shp->exitval = fun?1:ERROR_NOENT;
326*b30d1939SAndy Fiddaman 	else if(fun)
327*b30d1939SAndy Fiddaman 		shp->exitval = r;
328*b30d1939SAndy Fiddaman 	return(r);
329*b30d1939SAndy Fiddaman     }
330*b30d1939SAndy Fiddaman 
331*b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
332*b30d1939SAndy Fiddaman 
333*b30d1939SAndy Fiddaman /*
334*b30d1939SAndy Fiddaman  * Reap one job
335*b30d1939SAndy Fiddaman  * When called with sig==0, it does a blocking wait
336*b30d1939SAndy Fiddaman  */
job_reap(register int sig)337*b30d1939SAndy Fiddaman int job_reap(register int sig)
338*b30d1939SAndy Fiddaman {
339*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
340*b30d1939SAndy Fiddaman 	register pid_t pid;
341*b30d1939SAndy Fiddaman 	register struct process *pw;
342*b30d1939SAndy Fiddaman 	struct process *px;
343*b30d1939SAndy Fiddaman 	register int flags;
344*b30d1939SAndy Fiddaman 	struct jobsave *jp;
345*b30d1939SAndy Fiddaman 	int nochild=0, oerrno, wstat;
346*b30d1939SAndy Fiddaman 	Waitevent_f waitevent = shp->gd->waitevent;
347*b30d1939SAndy Fiddaman 	static int wcontinued = WCONTINUED;
348*b30d1939SAndy Fiddaman #if SHOPT_COSHELL
349*b30d1939SAndy Fiddaman 	Cojob_t		*cjp;
350*b30d1939SAndy Fiddaman 	int		cojobs;
351*b30d1939SAndy Fiddaman 	long		cotimeout = sig?0:-1;
352*b30d1939SAndy Fiddaman 	for(pw=job.pwlist;pw;pw=pw->p_nxtjob)
353*b30d1939SAndy Fiddaman 	{
354*b30d1939SAndy Fiddaman 		if(pw->p_cojob && !(pw->p_flag&P_DONE))
355*b30d1939SAndy Fiddaman 			break;
356*b30d1939SAndy Fiddaman 	}
357*b30d1939SAndy Fiddaman 	cojobs = (pw!=0);
358*b30d1939SAndy Fiddaman 	pid = 0;
359*b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
360*b30d1939SAndy Fiddaman 	if (vmbusy())
361*b30d1939SAndy Fiddaman 	{
362*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_warn(0),"vmbusy() inside job_reap() -- should not happen");
363*b30d1939SAndy Fiddaman 		if (getenv("_AST_KSH_VMBUSY_ABORT"))
364*b30d1939SAndy Fiddaman 			abort();
365*b30d1939SAndy Fiddaman 	}
366*b30d1939SAndy Fiddaman #ifdef DEBUG
367*b30d1939SAndy Fiddaman 	if(sfprintf(sfstderr,"ksh: job line %4d: reap pid=%d critical=%d signal=%d\n",__LINE__,getpid(),job.in_critical,sig) <=0)
368*b30d1939SAndy Fiddaman 		write(2,"waitsafe\n",9);
369*b30d1939SAndy Fiddaman 	sfsync(sfstderr);
370*b30d1939SAndy Fiddaman #endif /* DEBUG */
371*b30d1939SAndy Fiddaman 	job.savesig = 0;
372*b30d1939SAndy Fiddaman 	if(sig)
373*b30d1939SAndy Fiddaman 		flags = WNOHANG|WUNTRACED|wcontinued;
374*b30d1939SAndy Fiddaman 	else
375*b30d1939SAndy Fiddaman 		flags = WUNTRACED|wcontinued;
376*b30d1939SAndy Fiddaman 	shp->gd->waitevent = 0;
377*b30d1939SAndy Fiddaman 	oerrno = errno;
378*b30d1939SAndy Fiddaman 	while(1)
379*b30d1939SAndy Fiddaman 	{
380*b30d1939SAndy Fiddaman 		if(!(flags&WNOHANG) && !sh.intrap && job.pwlist)
381*b30d1939SAndy Fiddaman 		{
382*b30d1939SAndy Fiddaman 			sh_onstate(SH_TTYWAIT);
383*b30d1939SAndy Fiddaman 			if(waitevent && (*waitevent)(-1,-1L,0))
384*b30d1939SAndy Fiddaman 				flags |= WNOHANG;
385*b30d1939SAndy Fiddaman 		}
386*b30d1939SAndy Fiddaman #if SHOPT_COSHELL
387*b30d1939SAndy Fiddaman 		if(cojobs)
388*b30d1939SAndy Fiddaman 		{
389*b30d1939SAndy Fiddaman 			if(cjp = cowait(0,0,cotimeout))
390*b30d1939SAndy Fiddaman 			{
391*b30d1939SAndy Fiddaman 				struct cosh *csp;
392*b30d1939SAndy Fiddaman 				csp = (struct cosh*)(cjp->coshell->data);
393*b30d1939SAndy Fiddaman 				csp->cojob = cjp;
394*b30d1939SAndy Fiddaman 				pid = sh_copid(csp);
395*b30d1939SAndy Fiddaman 				if(cjp->status < 256)
396*b30d1939SAndy Fiddaman 					wstat = cjp->status <<8;
397*b30d1939SAndy Fiddaman 				else
398*b30d1939SAndy Fiddaman 					wstat = cjp->status-256;
399*b30d1939SAndy Fiddaman 				cotimeout = 0;
400*b30d1939SAndy Fiddaman 				goto cojob;
401*b30d1939SAndy Fiddaman 			}
402*b30d1939SAndy Fiddaman 			else if(copending(0)==0)
403*b30d1939SAndy Fiddaman 				cojobs = 0;
404*b30d1939SAndy Fiddaman 			cotimeout = 0;
405*b30d1939SAndy Fiddaman 		}
406*b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
407*b30d1939SAndy Fiddaman 		pid = waitpid((pid_t)-1,&wstat,flags);
408*b30d1939SAndy Fiddaman 		sh_offstate(SH_TTYWAIT);
409*b30d1939SAndy Fiddaman #if SHOPT_COSHELL
410*b30d1939SAndy Fiddaman 	cojob:
411*b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
412*b30d1939SAndy Fiddaman 
413*b30d1939SAndy Fiddaman 		/*
414*b30d1939SAndy Fiddaman 		 * some systems (linux 2.6) may return EINVAL
415*b30d1939SAndy Fiddaman 		 * when there are no continued children
416*b30d1939SAndy Fiddaman 		 */
417*b30d1939SAndy Fiddaman 
418*b30d1939SAndy Fiddaman 		if (pid<0 && errno==EINVAL && (flags&WCONTINUED))
419*b30d1939SAndy Fiddaman 			pid = waitpid((pid_t)-1,&wstat,flags&=~WCONTINUED);
420*b30d1939SAndy Fiddaman 		sh_sigcheck(shp);
421*b30d1939SAndy Fiddaman 		if(pid<0 && errno==EINTR && (sig||job.savesig))
422*b30d1939SAndy Fiddaman 		{
423*b30d1939SAndy Fiddaman 			errno = 0;
424*b30d1939SAndy Fiddaman 			continue;
425*b30d1939SAndy Fiddaman 		}
426*b30d1939SAndy Fiddaman 		if(pid<=0)
427*b30d1939SAndy Fiddaman 			break;
428*b30d1939SAndy Fiddaman 		if(wstat==0)
429*b30d1939SAndy Fiddaman 			job_chksave(pid,-1);
430*b30d1939SAndy Fiddaman 		flags |= WNOHANG;
431*b30d1939SAndy Fiddaman 		job.waitsafe++;
432*b30d1939SAndy Fiddaman 		jp = 0;
433*b30d1939SAndy Fiddaman 		lastpid = pid;
434*b30d1939SAndy Fiddaman 		if(!(pw=job_bypid(pid)))
435*b30d1939SAndy Fiddaman 		{
436*b30d1939SAndy Fiddaman #ifdef DEBUG
437*b30d1939SAndy Fiddaman 			sfprintf(sfstderr,"ksh: job line %4d: reap pid=%d critical=%d unknown job pid=%d pw=%x\n",__LINE__,getpid(),job.in_critical,pid,pw);
438*b30d1939SAndy Fiddaman #endif /* DEBUG */
439*b30d1939SAndy Fiddaman 			if (WIFCONTINUED(wstat) && wcontinued)
440*b30d1939SAndy Fiddaman 				continue;
441*b30d1939SAndy Fiddaman 			pw = &dummy;
442*b30d1939SAndy Fiddaman 			pw->p_exit = 0;
443*b30d1939SAndy Fiddaman 			pw->p_pgrp = 0;
444*b30d1939SAndy Fiddaman 			pw->p_exitmin = 0;
445*b30d1939SAndy Fiddaman 			if(job.toclear)
446*b30d1939SAndy Fiddaman 				job_clear();
447*b30d1939SAndy Fiddaman 			jp = jobsave_create(pid);
448*b30d1939SAndy Fiddaman 			pw->p_flag = 0;
449*b30d1939SAndy Fiddaman 			lastpid = pw->p_pid = pid;
450*b30d1939SAndy Fiddaman 			px = 0;
451*b30d1939SAndy Fiddaman 			if(jp && WIFSTOPPED(wstat))
452*b30d1939SAndy Fiddaman 			{
453*b30d1939SAndy Fiddaman 				jp->exitval = SH_STOPSIG;
454*b30d1939SAndy Fiddaman 				continue;
455*b30d1939SAndy Fiddaman 			}
456*b30d1939SAndy Fiddaman 		}
457*b30d1939SAndy Fiddaman #ifdef SIGTSTP
458*b30d1939SAndy Fiddaman 		else
459*b30d1939SAndy Fiddaman 			px=job_byjid(pw->p_job);
460*b30d1939SAndy Fiddaman 		if (WIFCONTINUED(wstat) && wcontinued)
461*b30d1939SAndy Fiddaman 			pw->p_flag &= ~(P_NOTIFY|P_SIGNALLED|P_STOPPED);
462*b30d1939SAndy Fiddaman 		else if(WIFSTOPPED(wstat))
463*b30d1939SAndy Fiddaman 		{
464*b30d1939SAndy Fiddaman 			pw->p_flag |= (P_NOTIFY|P_SIGNALLED|P_STOPPED);
465*b30d1939SAndy Fiddaman 			pw->p_exit = WSTOPSIG(wstat);
466*b30d1939SAndy Fiddaman 			if(pw->p_pgrp && pw->p_pgrp==job.curpgid && sh_isstate(SH_STOPOK))
467*b30d1939SAndy Fiddaman 				kill(getpid(),pw->p_exit);
468*b30d1939SAndy Fiddaman 			if(px)
469*b30d1939SAndy Fiddaman 			{
470*b30d1939SAndy Fiddaman 				/* move to top of job list */
471*b30d1939SAndy Fiddaman 				job_unlink(px);
472*b30d1939SAndy Fiddaman 				px->p_nxtjob = job.pwlist;
473*b30d1939SAndy Fiddaman 				job.pwlist = px;
474*b30d1939SAndy Fiddaman 			}
475*b30d1939SAndy Fiddaman 			continue;
476*b30d1939SAndy Fiddaman 		}
477*b30d1939SAndy Fiddaman 		else
478*b30d1939SAndy Fiddaman #endif /* SIGTSTP */
479*b30d1939SAndy Fiddaman 		{
480*b30d1939SAndy Fiddaman 			/* check for coprocess completion */
481*b30d1939SAndy Fiddaman 			if(pid==shp->cpid)
482*b30d1939SAndy Fiddaman 			{
483*b30d1939SAndy Fiddaman 				sh_close(sh.coutpipe);
484*b30d1939SAndy Fiddaman 				sh_close(sh.cpipe[1]);
485*b30d1939SAndy Fiddaman 				sh.cpipe[1] = -1;
486*b30d1939SAndy Fiddaman 				sh.coutpipe = -1;
487*b30d1939SAndy Fiddaman 			}
488*b30d1939SAndy Fiddaman 			else if(shp->subshell)
489*b30d1939SAndy Fiddaman 				sh_subjobcheck(pid);
490*b30d1939SAndy Fiddaman 
491*b30d1939SAndy Fiddaman 			pw->p_flag &= ~(P_STOPPED|P_SIGNALLED);
492*b30d1939SAndy Fiddaman 			if (WIFSIGNALED(wstat))
493*b30d1939SAndy Fiddaman 			{
494*b30d1939SAndy Fiddaman 				pw->p_flag |= (P_DONE|P_NOTIFY|P_SIGNALLED);
495*b30d1939SAndy Fiddaman 				if (WTERMCORE(wstat))
496*b30d1939SAndy Fiddaman 					pw->p_flag |= P_COREDUMP;
497*b30d1939SAndy Fiddaman 				pw->p_exit = WTERMSIG(wstat);
498*b30d1939SAndy Fiddaman 				/* if process in current jobs terminates from
499*b30d1939SAndy Fiddaman 				 * an interrupt, propogate to parent shell
500*b30d1939SAndy Fiddaman 				 */
501*b30d1939SAndy Fiddaman 				if(pw->p_pgrp && pw->p_pgrp==job.curpgid && pw->p_exit==SIGINT && sh_isstate(SH_STOPOK))
502*b30d1939SAndy Fiddaman 				{
503*b30d1939SAndy Fiddaman 					pw->p_flag &= ~P_NOTIFY;
504*b30d1939SAndy Fiddaman 					sh_offstate(SH_STOPOK);
505*b30d1939SAndy Fiddaman 					kill(getpid(),SIGINT);
506*b30d1939SAndy Fiddaman 					sh_onstate(SH_STOPOK);
507*b30d1939SAndy Fiddaman 				}
508*b30d1939SAndy Fiddaman 			}
509*b30d1939SAndy Fiddaman 			else
510*b30d1939SAndy Fiddaman 			{
511*b30d1939SAndy Fiddaman 				pw->p_flag |= (P_DONE|P_NOTIFY);
512*b30d1939SAndy Fiddaman 				pw->p_exit =  pw->p_exitmin;
513*b30d1939SAndy Fiddaman 				if(WEXITSTATUS(wstat) > pw->p_exitmin)
514*b30d1939SAndy Fiddaman 					pw->p_exit = WEXITSTATUS(wstat);
515*b30d1939SAndy Fiddaman 			}
516*b30d1939SAndy Fiddaman #ifdef SHOPT_BGX
517*b30d1939SAndy Fiddaman 			if((pw->p_flag&P_DONE) && (pw->p_flag&P_BG))
518*b30d1939SAndy Fiddaman 			{
519*b30d1939SAndy Fiddaman 				job.numbjob--;
520*b30d1939SAndy Fiddaman 				if(shp->st.trapcom[SIGCHLD])
521*b30d1939SAndy Fiddaman 				{
522*b30d1939SAndy Fiddaman 					shp->sigflag[SIGCHLD] |= SH_SIGTRAP;
523*b30d1939SAndy Fiddaman 					if(sig==0)
524*b30d1939SAndy Fiddaman 						job_chldtrap(shp,shp->st.trapcom[SIGCHLD],0);
525*b30d1939SAndy Fiddaman 					else
526*b30d1939SAndy Fiddaman 						shp->trapnote |= SH_SIGTRAP;
527*b30d1939SAndy Fiddaman 				}
528*b30d1939SAndy Fiddaman 				else
529*b30d1939SAndy Fiddaman 					pw->p_flag &= ~P_BG;
530*b30d1939SAndy Fiddaman 			}
531*b30d1939SAndy Fiddaman #endif /* SHOPT_BGX */
532*b30d1939SAndy Fiddaman 			if(pw->p_pgrp==0)
533*b30d1939SAndy Fiddaman 				pw->p_flag &= ~P_NOTIFY;
534*b30d1939SAndy Fiddaman 		}
535*b30d1939SAndy Fiddaman 		if(jp && pw== &dummy)
536*b30d1939SAndy Fiddaman 		{
537*b30d1939SAndy Fiddaman 			jp->exitval = pw->p_exit;
538*b30d1939SAndy Fiddaman 			if(pw->p_flag&P_SIGNALLED)
539*b30d1939SAndy Fiddaman 				jp->exitval |= SH_EXITSIG;
540*b30d1939SAndy Fiddaman 		}
541*b30d1939SAndy Fiddaman #ifdef DEBUG
542*b30d1939SAndy Fiddaman 		sfprintf(sfstderr,"ksh: job line %4d: reap pid=%d critical=%d job %d with pid %d flags=%o complete with status=%x exit=%d\n",__LINE__,getpid(),job.in_critical,pw->p_job,pid,pw->p_flag,wstat,pw->p_exit);
543*b30d1939SAndy Fiddaman 		sfsync(sfstderr);
544*b30d1939SAndy Fiddaman #endif /* DEBUG*/
545*b30d1939SAndy Fiddaman 		/* only top-level process in job should have notify set */
546*b30d1939SAndy Fiddaman 		if(px && pw != px)
547*b30d1939SAndy Fiddaman 			pw->p_flag &= ~P_NOTIFY;
548*b30d1939SAndy Fiddaman 		if(pid==pw->p_fgrp && pid==tcgetpgrp(JOBTTY))
549*b30d1939SAndy Fiddaman 		{
550*b30d1939SAndy Fiddaman 			px = job_byjid((int)pw->p_job);
551*b30d1939SAndy Fiddaman 			for(; px && (px->p_flag&P_DONE); px=px->p_nxtproc);
552*b30d1939SAndy Fiddaman 			if(!px)
553*b30d1939SAndy Fiddaman 				tcsetpgrp(JOBTTY,job.mypid);
554*b30d1939SAndy Fiddaman 		}
555*b30d1939SAndy Fiddaman #ifndef SHOPT_BGX
556*b30d1939SAndy Fiddaman 		if(!shp->intrap && shp->st.trapcom[SIGCHLD] && pid>0 && (pwfg!=job_bypid(pid)))
557*b30d1939SAndy Fiddaman 		{
558*b30d1939SAndy Fiddaman 			shp->sigflag[SIGCHLD] |= SH_SIGTRAP;
559*b30d1939SAndy Fiddaman 			shp->trapnote |= SH_SIGTRAP;
560*b30d1939SAndy Fiddaman 		}
561*b30d1939SAndy Fiddaman #endif
562*b30d1939SAndy Fiddaman 	}
563*b30d1939SAndy Fiddaman 	if(errno==ECHILD)
564*b30d1939SAndy Fiddaman 	{
565*b30d1939SAndy Fiddaman 		errno = oerrno;
566*b30d1939SAndy Fiddaman #ifdef SHOPT_BGX
567*b30d1939SAndy Fiddaman 		job.numbjob = 0;
568*b30d1939SAndy Fiddaman #endif /* SHOPT_BGX */
569*b30d1939SAndy Fiddaman 		nochild = 1;
570*b30d1939SAndy Fiddaman 	}
571*b30d1939SAndy Fiddaman 	shp->gd->waitevent = waitevent;
572*b30d1939SAndy Fiddaman 	if(sh_isoption(SH_NOTIFY) && sh_isstate(SH_TTYWAIT))
573*b30d1939SAndy Fiddaman 	{
574*b30d1939SAndy Fiddaman 		outfile = sfstderr;
575*b30d1939SAndy Fiddaman 		job_list(pw,JOB_NFLAG|JOB_NLFLAG);
576*b30d1939SAndy Fiddaman 		job_unpost(pw,1);
577*b30d1939SAndy Fiddaman 		sfsync(sfstderr);
578*b30d1939SAndy Fiddaman 	}
579*b30d1939SAndy Fiddaman 	if(sig)
580*b30d1939SAndy Fiddaman 		signal(sig, job_waitsafe);
581*b30d1939SAndy Fiddaman 	return(nochild);
582*b30d1939SAndy Fiddaman }
583*b30d1939SAndy Fiddaman 
584*b30d1939SAndy Fiddaman /*
585*b30d1939SAndy Fiddaman  * This is the SIGCLD interrupt routine
586*b30d1939SAndy Fiddaman  */
job_waitsafe(int sig)587*b30d1939SAndy Fiddaman static void job_waitsafe(int sig)
588*b30d1939SAndy Fiddaman {
589*b30d1939SAndy Fiddaman 	if(job.in_critical || vmbusy())
590*b30d1939SAndy Fiddaman 	{
591*b30d1939SAndy Fiddaman 		job.savesig = sig;
592*b30d1939SAndy Fiddaman 		job.waitsafe++;
593*b30d1939SAndy Fiddaman 	}
594*b30d1939SAndy Fiddaman 	else
595*b30d1939SAndy Fiddaman 		job_reap(sig);
596*b30d1939SAndy Fiddaman }
597*b30d1939SAndy Fiddaman 
598*b30d1939SAndy Fiddaman /*
599*b30d1939SAndy Fiddaman  * initialize job control if possible
600*b30d1939SAndy Fiddaman  * if lflag is set the switching driver message will not print
601*b30d1939SAndy Fiddaman  */
job_init(Shell_t * shp,int lflag)602*b30d1939SAndy Fiddaman void job_init(Shell_t *shp, int lflag)
603*b30d1939SAndy Fiddaman {
604*b30d1939SAndy Fiddaman 	register int ntry=0;
605*b30d1939SAndy Fiddaman 	job.fd = JOBTTY;
606*b30d1939SAndy Fiddaman 	signal(SIGCHLD,job_waitsafe);
607*b30d1939SAndy Fiddaman #   if defined(SIGCLD) && (SIGCLD!=SIGCHLD)
608*b30d1939SAndy Fiddaman 	signal(SIGCLD,job_waitsafe);
609*b30d1939SAndy Fiddaman #   endif
610*b30d1939SAndy Fiddaman 	if(njob_savelist < NJOB_SAVELIST)
611*b30d1939SAndy Fiddaman 		init_savelist();
612*b30d1939SAndy Fiddaman 	if(!sh_isoption(SH_INTERACTIVE))
613*b30d1939SAndy Fiddaman 		return;
614*b30d1939SAndy Fiddaman 	/* use new line discipline when available */
615*b30d1939SAndy Fiddaman #ifdef NTTYDISC
616*b30d1939SAndy Fiddaman #   ifdef FIOLOOKLD
617*b30d1939SAndy Fiddaman 	if((job.linedisc = ioctl(JOBTTY, FIOLOOKLD, 0)) <0)
618*b30d1939SAndy Fiddaman #   else
619*b30d1939SAndy Fiddaman 	if(ioctl(JOBTTY,TIOCGETD,&job.linedisc) !=0)
620*b30d1939SAndy Fiddaman #   endif /* FIOLOOKLD */
621*b30d1939SAndy Fiddaman 		return;
622*b30d1939SAndy Fiddaman 	if(job.linedisc!=NTTYDISC && job.linedisc!=OTTYDISC)
623*b30d1939SAndy Fiddaman 	{
624*b30d1939SAndy Fiddaman 		/* no job control when running with MPX */
625*b30d1939SAndy Fiddaman #   if SHOPT_VSH
626*b30d1939SAndy Fiddaman 		sh_onoption(SH_VIRAW);
627*b30d1939SAndy Fiddaman #   endif /* SHOPT_VSH */
628*b30d1939SAndy Fiddaman 		return;
629*b30d1939SAndy Fiddaman 	}
630*b30d1939SAndy Fiddaman 	if(job.linedisc==NTTYDISC)
631*b30d1939SAndy Fiddaman 		job.linedisc = -1;
632*b30d1939SAndy Fiddaman #endif /* NTTYDISC */
633*b30d1939SAndy Fiddaman 
634*b30d1939SAndy Fiddaman 	job.mypgid = getpgrp();
635*b30d1939SAndy Fiddaman 	/* some systems have job control, but not initialized */
636*b30d1939SAndy Fiddaman 	if(job.mypgid<=0)
637*b30d1939SAndy Fiddaman         {
638*b30d1939SAndy Fiddaman 		/* Get a controlling terminal and set process group */
639*b30d1939SAndy Fiddaman 		/* This should have already been done by rlogin */
640*b30d1939SAndy Fiddaman                 register int fd;
641*b30d1939SAndy Fiddaman                 register char *ttynam;
642*b30d1939SAndy Fiddaman #ifndef SIGTSTP
643*b30d1939SAndy Fiddaman                 setpgid(0,shp->gd->pid);
644*b30d1939SAndy Fiddaman #endif /*SIGTSTP */
645*b30d1939SAndy Fiddaman                 if(job.mypgid<0 || !(ttynam=ttyname(JOBTTY)))
646*b30d1939SAndy Fiddaman                         return;
647*b30d1939SAndy Fiddaman                 close(JOBTTY);
648*b30d1939SAndy Fiddaman                 if((fd = open(ttynam,O_RDWR)) <0)
649*b30d1939SAndy Fiddaman                         return;
650*b30d1939SAndy Fiddaman                 if(fd!=JOBTTY)
651*b30d1939SAndy Fiddaman                         sh_iorenumber(shp,fd,JOBTTY);
652*b30d1939SAndy Fiddaman                 job.mypgid = shp->gd->pid;
653*b30d1939SAndy Fiddaman #ifdef SIGTSTP
654*b30d1939SAndy Fiddaman                 tcsetpgrp(JOBTTY,shp->gd->pid);
655*b30d1939SAndy Fiddaman                 setpgid(0,shp->gd->pid);
656*b30d1939SAndy Fiddaman #endif /* SIGTSTP */
657*b30d1939SAndy Fiddaman         }
658*b30d1939SAndy Fiddaman #ifdef SIGTSTP
659*b30d1939SAndy Fiddaman 	if(possible = (setpgid(0,job.mypgid)>=0) || errno==EPERM)
660*b30d1939SAndy Fiddaman 	{
661*b30d1939SAndy Fiddaman 		/* wait until we are in the foreground */
662*b30d1939SAndy Fiddaman 
663*b30d1939SAndy Fiddaman 		while((job.mytgid=tcgetpgrp(JOBTTY)) != job.mypgid)
664*b30d1939SAndy Fiddaman 		{
665*b30d1939SAndy Fiddaman 			if(job.mytgid <= 0)
666*b30d1939SAndy Fiddaman 				return;
667*b30d1939SAndy Fiddaman 			/* Stop this shell until continued */
668*b30d1939SAndy Fiddaman 			signal(SIGTTIN,SIG_DFL);
669*b30d1939SAndy Fiddaman 			kill(shp->gd->pid,SIGTTIN);
670*b30d1939SAndy Fiddaman 			/* resumes here after continue tries again */
671*b30d1939SAndy Fiddaman 			if(ntry++ > IOMAXTRY)
672*b30d1939SAndy Fiddaman 			{
673*b30d1939SAndy Fiddaman 				errormsg(SH_DICT,0,e_no_start);
674*b30d1939SAndy Fiddaman 				return;
675*b30d1939SAndy Fiddaman 			}
676*b30d1939SAndy Fiddaman 		}
677*b30d1939SAndy Fiddaman 	}
678*b30d1939SAndy Fiddaman #endif /* SIGTTIN */
679*b30d1939SAndy Fiddaman 
680*b30d1939SAndy Fiddaman #ifdef NTTYDISC
681*b30d1939SAndy Fiddaman 	/* set the line discipline */
682*b30d1939SAndy Fiddaman 	if(job.linedisc>=0)
683*b30d1939SAndy Fiddaman 	{
684*b30d1939SAndy Fiddaman 		int linedisc = NTTYDISC;
685*b30d1939SAndy Fiddaman #   ifdef FIOPUSHLD
686*b30d1939SAndy Fiddaman 		tty_get(JOBTTY,&my_stty);
687*b30d1939SAndy Fiddaman 		if (ioctl(JOBTTY, FIOPOPLD, 0) < 0)
688*b30d1939SAndy Fiddaman 			return;
689*b30d1939SAndy Fiddaman 		if (ioctl(JOBTTY, FIOPUSHLD, &linedisc) < 0)
690*b30d1939SAndy Fiddaman 		{
691*b30d1939SAndy Fiddaman 			ioctl(JOBTTY, FIOPUSHLD, &job.linedisc);
692*b30d1939SAndy Fiddaman 			return;
693*b30d1939SAndy Fiddaman 		}
694*b30d1939SAndy Fiddaman 		tty_set(JOBTTY,TCSANOW,&my_stty);
695*b30d1939SAndy Fiddaman #   else
696*b30d1939SAndy Fiddaman 		if(ioctl(JOBTTY,TIOCSETD,&linedisc) !=0)
697*b30d1939SAndy Fiddaman 			return;
698*b30d1939SAndy Fiddaman #   endif /* FIOPUSHLD */
699*b30d1939SAndy Fiddaman 		if(lflag==0)
700*b30d1939SAndy Fiddaman 			errormsg(SH_DICT,0,e_newtty);
701*b30d1939SAndy Fiddaman 		else
702*b30d1939SAndy Fiddaman 			job.linedisc = -1;
703*b30d1939SAndy Fiddaman 	}
704*b30d1939SAndy Fiddaman #endif /* NTTYDISC */
705*b30d1939SAndy Fiddaman 	if(!possible)
706*b30d1939SAndy Fiddaman 		return;
707*b30d1939SAndy Fiddaman 
708*b30d1939SAndy Fiddaman #ifdef SIGTSTP
709*b30d1939SAndy Fiddaman 	/* make sure that we are a process group leader */
710*b30d1939SAndy Fiddaman 	setpgid(0,shp->gd->pid);
711*b30d1939SAndy Fiddaman #   if defined(SA_NOCLDSTOP) || defined(SA_NOCLDWAIT)
712*b30d1939SAndy Fiddaman #   	if !defined(SA_NOCLDSTOP)
713*b30d1939SAndy Fiddaman #	    define SA_NOCLDSTOP	0
714*b30d1939SAndy Fiddaman #   	endif
715*b30d1939SAndy Fiddaman #   	if !defined(SA_NOCLDWAIT)
716*b30d1939SAndy Fiddaman #	    define SA_NOCLDWAIT	0
717*b30d1939SAndy Fiddaman #   	endif
718*b30d1939SAndy Fiddaman 	sigflag(SIGCHLD, SA_NOCLDSTOP|SA_NOCLDWAIT, 0);
719*b30d1939SAndy Fiddaman #   endif /* SA_NOCLDSTOP || SA_NOCLDWAIT */
720*b30d1939SAndy Fiddaman 	signal(SIGTTIN,SIG_IGN);
721*b30d1939SAndy Fiddaman 	signal(SIGTTOU,SIG_IGN);
722*b30d1939SAndy Fiddaman 	/* The shell now handles ^Z */
723*b30d1939SAndy Fiddaman 	signal(SIGTSTP,sh_fault);
724*b30d1939SAndy Fiddaman 	tcsetpgrp(JOBTTY,shp->gd->pid);
725*b30d1939SAndy Fiddaman #   ifdef CNSUSP
726*b30d1939SAndy Fiddaman 	/* set the switch character */
727*b30d1939SAndy Fiddaman 	tty_get(JOBTTY,&my_stty);
728*b30d1939SAndy Fiddaman 	job.suspend = (unsigned)my_stty.c_cc[VSUSP];
729*b30d1939SAndy Fiddaman 	if(job.suspend == (unsigned char)CNSUSP)
730*b30d1939SAndy Fiddaman 	{
731*b30d1939SAndy Fiddaman 		my_stty.c_cc[VSUSP] = CSWTCH;
732*b30d1939SAndy Fiddaman 		tty_set(JOBTTY,TCSAFLUSH,&my_stty);
733*b30d1939SAndy Fiddaman 	}
734*b30d1939SAndy Fiddaman #   endif /* CNSUSP */
735*b30d1939SAndy Fiddaman 	sh_onoption(SH_MONITOR);
736*b30d1939SAndy Fiddaman 	job.jobcontrol++;
737*b30d1939SAndy Fiddaman 	job.mypid = shp->gd->pid;
738*b30d1939SAndy Fiddaman #endif /* SIGTSTP */
739*b30d1939SAndy Fiddaman 	return;
740*b30d1939SAndy Fiddaman }
741*b30d1939SAndy Fiddaman 
742*b30d1939SAndy Fiddaman 
743*b30d1939SAndy Fiddaman /*
744*b30d1939SAndy Fiddaman  * see if there are any stopped jobs
745*b30d1939SAndy Fiddaman  * restore tty driver and pgrp
746*b30d1939SAndy Fiddaman  */
job_close(Shell_t * shp)747*b30d1939SAndy Fiddaman int job_close(Shell_t* shp)
748*b30d1939SAndy Fiddaman {
749*b30d1939SAndy Fiddaman 	register struct process *pw;
750*b30d1939SAndy Fiddaman 	register int count = 0, running = 0;
751*b30d1939SAndy Fiddaman 	if(possible && !job.jobcontrol)
752*b30d1939SAndy Fiddaman 		return(0);
753*b30d1939SAndy Fiddaman 	else if(!possible && (!sh_isstate(SH_MONITOR) || sh_isstate(SH_FORKED)))
754*b30d1939SAndy Fiddaman 		return(0);
755*b30d1939SAndy Fiddaman 	else if(getpid() != job.mypid)
756*b30d1939SAndy Fiddaman 		return(0);
757*b30d1939SAndy Fiddaman 	job_lock();
758*b30d1939SAndy Fiddaman 	if(!tty_check(0))
759*b30d1939SAndy Fiddaman 		beenhere++;
760*b30d1939SAndy Fiddaman 	for(pw=job.pwlist;pw;pw=pw->p_nxtjob)
761*b30d1939SAndy Fiddaman 	{
762*b30d1939SAndy Fiddaman 		if(!(pw->p_flag&P_STOPPED))
763*b30d1939SAndy Fiddaman 		{
764*b30d1939SAndy Fiddaman 			if(!(pw->p_flag&P_DONE))
765*b30d1939SAndy Fiddaman 				running++;
766*b30d1939SAndy Fiddaman 			continue;
767*b30d1939SAndy Fiddaman 		}
768*b30d1939SAndy Fiddaman 		if(beenhere)
769*b30d1939SAndy Fiddaman 			killpg(pw->p_pgrp,SIGTERM);
770*b30d1939SAndy Fiddaman 		count++;
771*b30d1939SAndy Fiddaman 	}
772*b30d1939SAndy Fiddaman 	if(beenhere++ == 0 && job.pwlist)
773*b30d1939SAndy Fiddaman 	{
774*b30d1939SAndy Fiddaman 		if(count)
775*b30d1939SAndy Fiddaman 		{
776*b30d1939SAndy Fiddaman 			errormsg(SH_DICT,0,e_terminate);
777*b30d1939SAndy Fiddaman 			return(-1);
778*b30d1939SAndy Fiddaman 		}
779*b30d1939SAndy Fiddaman 		else if(running && shp->login_sh)
780*b30d1939SAndy Fiddaman 		{
781*b30d1939SAndy Fiddaman 			errormsg(SH_DICT,0,e_jobsrunning);
782*b30d1939SAndy Fiddaman 			return(-1);
783*b30d1939SAndy Fiddaman 		}
784*b30d1939SAndy Fiddaman 	}
785*b30d1939SAndy Fiddaman 	job_unlock();
786*b30d1939SAndy Fiddaman #   ifdef SIGTSTP
787*b30d1939SAndy Fiddaman 	if(possible && setpgid(0,job.mypgid)>=0)
788*b30d1939SAndy Fiddaman 		tcsetpgrp(job.fd,job.mypgid);
789*b30d1939SAndy Fiddaman #   endif /* SIGTSTP */
790*b30d1939SAndy Fiddaman #   ifdef NTTYDISC
791*b30d1939SAndy Fiddaman 	if(job.linedisc>=0)
792*b30d1939SAndy Fiddaman 	{
793*b30d1939SAndy Fiddaman 		/* restore old line discipline */
794*b30d1939SAndy Fiddaman #	ifdef FIOPUSHLD
795*b30d1939SAndy Fiddaman 		tty_get(job.fd,&my_stty);
796*b30d1939SAndy Fiddaman 		if (ioctl(job.fd, FIOPOPLD, 0) < 0)
797*b30d1939SAndy Fiddaman 			return(0);
798*b30d1939SAndy Fiddaman 		if (ioctl(job.fd, FIOPUSHLD, &job.linedisc) < 0)
799*b30d1939SAndy Fiddaman 		{
800*b30d1939SAndy Fiddaman 			job.linedisc = NTTYDISC;
801*b30d1939SAndy Fiddaman 			ioctl(job.fd, FIOPUSHLD, &job.linedisc);
802*b30d1939SAndy Fiddaman 			return(0);
803*b30d1939SAndy Fiddaman 		}
804*b30d1939SAndy Fiddaman 		tty_set(job.fd,TCSAFLUSH,&my_stty);
805*b30d1939SAndy Fiddaman #	else
806*b30d1939SAndy Fiddaman 		if(ioctl(job.fd,TIOCSETD,&job.linedisc) !=0)
807*b30d1939SAndy Fiddaman 			return(0);
808*b30d1939SAndy Fiddaman #	endif /* FIOPUSHLD */
809*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,0,e_oldtty);
810*b30d1939SAndy Fiddaman 	}
811*b30d1939SAndy Fiddaman #   endif /* NTTYDISC */
812*b30d1939SAndy Fiddaman #   ifdef CNSUSP
813*b30d1939SAndy Fiddaman 	if(possible && job.suspend==CNSUSP)
814*b30d1939SAndy Fiddaman 	{
815*b30d1939SAndy Fiddaman 		tty_get(job.fd,&my_stty);
816*b30d1939SAndy Fiddaman 		my_stty.c_cc[VSUSP] = CNSUSP;
817*b30d1939SAndy Fiddaman 		tty_set(job.fd,TCSAFLUSH,&my_stty);
818*b30d1939SAndy Fiddaman 	}
819*b30d1939SAndy Fiddaman #   endif /* CNSUSP */
820*b30d1939SAndy Fiddaman 	job.jobcontrol = 0;
821*b30d1939SAndy Fiddaman 	return(0);
822*b30d1939SAndy Fiddaman }
823*b30d1939SAndy Fiddaman 
job_set(register struct process * pw)824*b30d1939SAndy Fiddaman static void job_set(register struct process *pw)
825*b30d1939SAndy Fiddaman {
826*b30d1939SAndy Fiddaman 	Shell_t *shp = pw->p_shp;
827*b30d1939SAndy Fiddaman 	/* save current terminal state */
828*b30d1939SAndy Fiddaman 	tty_get(job.fd,&my_stty);
829*b30d1939SAndy Fiddaman 	if(pw->p_flag&P_STTY)
830*b30d1939SAndy Fiddaman 	{
831*b30d1939SAndy Fiddaman 		/* restore terminal state for job */
832*b30d1939SAndy Fiddaman 		tty_set(job.fd,TCSAFLUSH,&pw->p_stty);
833*b30d1939SAndy Fiddaman 	}
834*b30d1939SAndy Fiddaman #ifdef SIGTSTP
835*b30d1939SAndy Fiddaman 	if((pw->p_flag&P_STOPPED) || tcgetpgrp(job.fd) == shp->gd->pid)
836*b30d1939SAndy Fiddaman 		tcsetpgrp(job.fd,pw->p_fgrp);
837*b30d1939SAndy Fiddaman 	/* if job is stopped, resume it in the background */
838*b30d1939SAndy Fiddaman 	if(!shp->forked)
839*b30d1939SAndy Fiddaman 		job_unstop(pw);
840*b30d1939SAndy Fiddaman 	shp->forked = 0;
841*b30d1939SAndy Fiddaman #endif	/* SIGTSTP */
842*b30d1939SAndy Fiddaman }
843*b30d1939SAndy Fiddaman 
job_reset(register struct process * pw)844*b30d1939SAndy Fiddaman static void job_reset(register struct process *pw)
845*b30d1939SAndy Fiddaman {
846*b30d1939SAndy Fiddaman 	/* save the terminal state for current job */
847*b30d1939SAndy Fiddaman #ifdef SIGTSTP
848*b30d1939SAndy Fiddaman 	job_fgrp(pw,tcgetpgrp(job.fd));
849*b30d1939SAndy Fiddaman 	if(tcsetpgrp(job.fd,job.mypid) !=0)
850*b30d1939SAndy Fiddaman 		return;
851*b30d1939SAndy Fiddaman #endif	/* SIGTSTP */
852*b30d1939SAndy Fiddaman 	/* force the following tty_get() to do a tcgetattr() unless fg */
853*b30d1939SAndy Fiddaman 	if(!(pw->p_flag&P_FG))
854*b30d1939SAndy Fiddaman 		tty_set(-1, 0, NIL(struct termios*));
855*b30d1939SAndy Fiddaman 	if(pw && (pw->p_flag&P_SIGNALLED) && pw->p_exit!=SIGHUP)
856*b30d1939SAndy Fiddaman 	{
857*b30d1939SAndy Fiddaman 		if(tty_get(job.fd,&pw->p_stty) == 0)
858*b30d1939SAndy Fiddaman 			pw->p_flag |= P_STTY;
859*b30d1939SAndy Fiddaman 		/* restore terminal state for job */
860*b30d1939SAndy Fiddaman 		tty_set(job.fd,TCSAFLUSH,&my_stty);
861*b30d1939SAndy Fiddaman 	}
862*b30d1939SAndy Fiddaman 	beenhere = 0;
863*b30d1939SAndy Fiddaman }
864*b30d1939SAndy Fiddaman #endif /* JOBS */
865*b30d1939SAndy Fiddaman 
866*b30d1939SAndy Fiddaman /*
867*b30d1939SAndy Fiddaman  * wait built-in command
868*b30d1939SAndy Fiddaman  */
869*b30d1939SAndy Fiddaman 
job_bwait(char ** jobs)870*b30d1939SAndy Fiddaman void job_bwait(char **jobs)
871*b30d1939SAndy Fiddaman {
872*b30d1939SAndy Fiddaman 	register char *jp;
873*b30d1939SAndy Fiddaman 	register struct process *pw;
874*b30d1939SAndy Fiddaman 	register pid_t pid;
875*b30d1939SAndy Fiddaman 	if(*jobs==0)
876*b30d1939SAndy Fiddaman 		job_wait((pid_t)-1);
877*b30d1939SAndy Fiddaman 	else while(jp = *jobs++)
878*b30d1939SAndy Fiddaman 	{
879*b30d1939SAndy Fiddaman #ifdef JOBS
880*b30d1939SAndy Fiddaman 		if(*jp == '%')
881*b30d1939SAndy Fiddaman 		{
882*b30d1939SAndy Fiddaman 			job_lock();
883*b30d1939SAndy Fiddaman 			pw = job_bystring(jp);
884*b30d1939SAndy Fiddaman 			job_unlock();
885*b30d1939SAndy Fiddaman 			if(pw)
886*b30d1939SAndy Fiddaman 				pid = pw->p_pid;
887*b30d1939SAndy Fiddaman 			else
888*b30d1939SAndy Fiddaman 				return;
889*b30d1939SAndy Fiddaman 		}
890*b30d1939SAndy Fiddaman #   if SHOPT_COSHELL
891*b30d1939SAndy Fiddaman 		else if(isalpha(*jp))
892*b30d1939SAndy Fiddaman 		{
893*b30d1939SAndy Fiddaman 			job_cowalk(NULL,0,jp);
894*b30d1939SAndy Fiddaman 			return;
895*b30d1939SAndy Fiddaman 		}
896*b30d1939SAndy Fiddaman #   endif /* SHOPT_COSHELL */
897*b30d1939SAndy Fiddaman 		else
898*b30d1939SAndy Fiddaman #endif /* JOBS */
899*b30d1939SAndy Fiddaman 			pid = pid_fromstring(jp);
900*b30d1939SAndy Fiddaman 		job_wait(-pid);
901*b30d1939SAndy Fiddaman 	}
902*b30d1939SAndy Fiddaman }
903*b30d1939SAndy Fiddaman 
904*b30d1939SAndy Fiddaman #ifdef JOBS
905*b30d1939SAndy Fiddaman /*
906*b30d1939SAndy Fiddaman  * execute function <fun> for each job
907*b30d1939SAndy Fiddaman  */
908*b30d1939SAndy Fiddaman 
job_walk(Sfio_t * file,int (* fun)(struct process *,int),int arg,char * joblist[])909*b30d1939SAndy Fiddaman int job_walk(Sfio_t *file,int (*fun)(struct process*,int),int arg,char *joblist[])
910*b30d1939SAndy Fiddaman {
911*b30d1939SAndy Fiddaman 	register struct process *pw;
912*b30d1939SAndy Fiddaman 	register int r = 0;
913*b30d1939SAndy Fiddaman 	register char *jobid, **jobs=joblist;
914*b30d1939SAndy Fiddaman 	register struct process *px;
915*b30d1939SAndy Fiddaman 	job_string = 0;
916*b30d1939SAndy Fiddaman 	outfile = file;
917*b30d1939SAndy Fiddaman 	by_number = 0;
918*b30d1939SAndy Fiddaman 	job_lock();
919*b30d1939SAndy Fiddaman 	pw = job.pwlist;
920*b30d1939SAndy Fiddaman 	job_waitsafe(SIGCHLD);
921*b30d1939SAndy Fiddaman 	if(jobs==0)
922*b30d1939SAndy Fiddaman 	{
923*b30d1939SAndy Fiddaman 		/* do all jobs */
924*b30d1939SAndy Fiddaman 		for(;pw;pw=px)
925*b30d1939SAndy Fiddaman 		{
926*b30d1939SAndy Fiddaman 			px = pw->p_nxtjob;
927*b30d1939SAndy Fiddaman 			if(pw->p_env != sh.jobenv)
928*b30d1939SAndy Fiddaman 				continue;
929*b30d1939SAndy Fiddaman 			if((*fun)(pw,arg))
930*b30d1939SAndy Fiddaman 				r = 2;
931*b30d1939SAndy Fiddaman 		}
932*b30d1939SAndy Fiddaman 	}
933*b30d1939SAndy Fiddaman 	else if(*jobs==0)	/* current job */
934*b30d1939SAndy Fiddaman 	{
935*b30d1939SAndy Fiddaman 		/* skip over non-stop jobs */
936*b30d1939SAndy Fiddaman 		while(pw && (pw->p_env!=sh.jobenv || pw->p_pgrp==0))
937*b30d1939SAndy Fiddaman 			pw = pw->p_nxtjob;
938*b30d1939SAndy Fiddaman 		if((*fun)(pw,arg))
939*b30d1939SAndy Fiddaman 			r = 2;
940*b30d1939SAndy Fiddaman 	}
941*b30d1939SAndy Fiddaman 	else while(jobid = *jobs++)
942*b30d1939SAndy Fiddaman 	{
943*b30d1939SAndy Fiddaman 		job_string = jobid;
944*b30d1939SAndy Fiddaman 		if(*jobid==0)
945*b30d1939SAndy Fiddaman 			errormsg(SH_DICT,ERROR_exit(1),e_jobusage,job_string);
946*b30d1939SAndy Fiddaman #if SHOPT_COSHELL
947*b30d1939SAndy Fiddaman 		if(isalpha(*jobid))
948*b30d1939SAndy Fiddaman 		{
949*b30d1939SAndy Fiddaman 			r = job_cowalk(fun,arg,jobid);
950*b30d1939SAndy Fiddaman 			by_number = 0;
951*b30d1939SAndy Fiddaman 			job_unlock();
952*b30d1939SAndy Fiddaman 			return(r);
953*b30d1939SAndy Fiddaman 		}
954*b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
955*b30d1939SAndy Fiddaman 		if(*jobid == '%')
956*b30d1939SAndy Fiddaman 			pw = job_bystring(jobid);
957*b30d1939SAndy Fiddaman 		else
958*b30d1939SAndy Fiddaman 		{
959*b30d1939SAndy Fiddaman 			int pid = pid_fromstring(jobid);
960*b30d1939SAndy Fiddaman 			if(!(pw = job_bypid(pid)))
961*b30d1939SAndy Fiddaman 			{
962*b30d1939SAndy Fiddaman 				pw = &dummy;
963*b30d1939SAndy Fiddaman 				pw->p_shp = sh_getinterp();
964*b30d1939SAndy Fiddaman 				pw->p_pid = pid;
965*b30d1939SAndy Fiddaman 				pw->p_pgrp = pid;
966*b30d1939SAndy Fiddaman 			}
967*b30d1939SAndy Fiddaman 			by_number = 1;
968*b30d1939SAndy Fiddaman 		}
969*b30d1939SAndy Fiddaman 		if((*fun)(pw,arg))
970*b30d1939SAndy Fiddaman 			r = 2;
971*b30d1939SAndy Fiddaman 		by_number = 0;
972*b30d1939SAndy Fiddaman 	}
973*b30d1939SAndy Fiddaman 	job_unlock();
974*b30d1939SAndy Fiddaman 	return(r);
975*b30d1939SAndy Fiddaman }
976*b30d1939SAndy Fiddaman 
977*b30d1939SAndy Fiddaman /*
978*b30d1939SAndy Fiddaman  * send signal <sig> to background process group if not disowned
979*b30d1939SAndy Fiddaman  */
job_terminate(register struct process * pw,register int sig)980*b30d1939SAndy Fiddaman int job_terminate(register struct process *pw,register int sig)
981*b30d1939SAndy Fiddaman {
982*b30d1939SAndy Fiddaman 	if(pw->p_pgrp && !(pw->p_flag&P_DISOWN))
983*b30d1939SAndy Fiddaman 		job_kill(pw,sig);
984*b30d1939SAndy Fiddaman 	return(0);
985*b30d1939SAndy Fiddaman }
986*b30d1939SAndy Fiddaman 
987*b30d1939SAndy Fiddaman /*
988*b30d1939SAndy Fiddaman  * list the given job
989*b30d1939SAndy Fiddaman  * flag JOB_LFLAG for long listing
990*b30d1939SAndy Fiddaman  * flag JOB_NFLAG for list only jobs marked for notification
991*b30d1939SAndy Fiddaman  * flag JOB_PFLAG for process id(s) only
992*b30d1939SAndy Fiddaman  */
993*b30d1939SAndy Fiddaman 
job_list(struct process * pw,register int flag)994*b30d1939SAndy Fiddaman int job_list(struct process *pw,register int flag)
995*b30d1939SAndy Fiddaman {
996*b30d1939SAndy Fiddaman 	Shell_t	*shp = sh_getinterp();
997*b30d1939SAndy Fiddaman 	register struct process *px = pw;
998*b30d1939SAndy Fiddaman 	register int  n;
999*b30d1939SAndy Fiddaman 	register const char *msg;
1000*b30d1939SAndy Fiddaman 	register int msize;
1001*b30d1939SAndy Fiddaman 	if(!pw || pw->p_job<=0)
1002*b30d1939SAndy Fiddaman 		return(1);
1003*b30d1939SAndy Fiddaman 	if(pw->p_env != shp->jobenv)
1004*b30d1939SAndy Fiddaman 		return(0);
1005*b30d1939SAndy Fiddaman 	if((flag&JOB_NFLAG) && (!(px->p_flag&P_NOTIFY)||px->p_pgrp==0))
1006*b30d1939SAndy Fiddaman 		return(0);
1007*b30d1939SAndy Fiddaman 	if((flag&JOB_PFLAG))
1008*b30d1939SAndy Fiddaman 	{
1009*b30d1939SAndy Fiddaman #if SHOPT_COSHELL
1010*b30d1939SAndy Fiddaman 		sfprintf(outfile,"%s\n",sh_pid2str(shp,px->p_pgrp?px->p_pgrp:px->p_pid));
1011*b30d1939SAndy Fiddaman #else
1012*b30d1939SAndy Fiddaman 		sfprintf(outfile,"%d\n",px->p_pgrp?px->p_pgrp:px->p_pid);
1013*b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
1014*b30d1939SAndy Fiddaman 		return(0);
1015*b30d1939SAndy Fiddaman 	}
1016*b30d1939SAndy Fiddaman 	if((px->p_flag&P_DONE) && job.waitall && !(flag&JOB_LFLAG))
1017*b30d1939SAndy Fiddaman 		return(0);
1018*b30d1939SAndy Fiddaman 	job_lock();
1019*b30d1939SAndy Fiddaman 	n = px->p_job;
1020*b30d1939SAndy Fiddaman 	if(px==job.pwlist)
1021*b30d1939SAndy Fiddaman 		msize = '+';
1022*b30d1939SAndy Fiddaman 	else if(px==job.pwlist->p_nxtjob)
1023*b30d1939SAndy Fiddaman 		msize = '-';
1024*b30d1939SAndy Fiddaman 	else
1025*b30d1939SAndy Fiddaman 		msize = ' ';
1026*b30d1939SAndy Fiddaman 	if(flag&JOB_NLFLAG)
1027*b30d1939SAndy Fiddaman 		sfputc(outfile,'\n');
1028*b30d1939SAndy Fiddaman 	sfprintf(outfile,"[%d] %c ",n, msize);
1029*b30d1939SAndy Fiddaman 	do
1030*b30d1939SAndy Fiddaman 	{
1031*b30d1939SAndy Fiddaman 		n = 0;
1032*b30d1939SAndy Fiddaman 		if(flag&JOB_LFLAG)
1033*b30d1939SAndy Fiddaman #if SHOPT_COSHELL
1034*b30d1939SAndy Fiddaman 			sfprintf(outfile,"%s\t",sh_pid2str(shp,px->p_pid));
1035*b30d1939SAndy Fiddaman #else
1036*b30d1939SAndy Fiddaman 			sfprintf(outfile,"%d\t",px->p_pid);
1037*b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
1038*b30d1939SAndy Fiddaman 		if(px->p_flag&P_SIGNALLED)
1039*b30d1939SAndy Fiddaman 			msg = job_sigmsg((int)(px->p_exit));
1040*b30d1939SAndy Fiddaman 		else if(px->p_flag&P_NOTIFY)
1041*b30d1939SAndy Fiddaman 		{
1042*b30d1939SAndy Fiddaman 			msg = sh_translate(e_done);
1043*b30d1939SAndy Fiddaman 			n = px->p_exit;
1044*b30d1939SAndy Fiddaman 		}
1045*b30d1939SAndy Fiddaman 		else
1046*b30d1939SAndy Fiddaman 			msg = sh_translate(e_running);
1047*b30d1939SAndy Fiddaman 		px->p_flag &= ~P_NOTIFY;
1048*b30d1939SAndy Fiddaman 		sfputr(outfile,msg,-1);
1049*b30d1939SAndy Fiddaman 		msize = strlen(msg);
1050*b30d1939SAndy Fiddaman 		if(n)
1051*b30d1939SAndy Fiddaman 		{
1052*b30d1939SAndy Fiddaman 			sfprintf(outfile,"(%d)",(int)n);
1053*b30d1939SAndy Fiddaman 			msize += (3+(n>10)+(n>100));
1054*b30d1939SAndy Fiddaman 		}
1055*b30d1939SAndy Fiddaman 		if(px->p_flag&P_COREDUMP)
1056*b30d1939SAndy Fiddaman 		{
1057*b30d1939SAndy Fiddaman 			msg = sh_translate(e_coredump);
1058*b30d1939SAndy Fiddaman 			sfputr(outfile, msg, -1);
1059*b30d1939SAndy Fiddaman 			msize += strlen(msg);
1060*b30d1939SAndy Fiddaman 		}
1061*b30d1939SAndy Fiddaman 		sfnputc(outfile,' ',MAXMSG>msize?MAXMSG-msize:1);
1062*b30d1939SAndy Fiddaman 		if(flag&JOB_LFLAG)
1063*b30d1939SAndy Fiddaman 			px = px->p_nxtproc;
1064*b30d1939SAndy Fiddaman 		else
1065*b30d1939SAndy Fiddaman 		{
1066*b30d1939SAndy Fiddaman 			while(px=px->p_nxtproc)
1067*b30d1939SAndy Fiddaman 				px->p_flag &= ~P_NOTIFY;
1068*b30d1939SAndy Fiddaman 			px = 0;
1069*b30d1939SAndy Fiddaman 		}
1070*b30d1939SAndy Fiddaman 		if(!px)
1071*b30d1939SAndy Fiddaman 			hist_list(shgd->hist_ptr,outfile,pw->p_name,0,";");
1072*b30d1939SAndy Fiddaman 		else
1073*b30d1939SAndy Fiddaman 			sfputr(outfile, e_nlspace, -1);
1074*b30d1939SAndy Fiddaman 	}
1075*b30d1939SAndy Fiddaman 	while(px);
1076*b30d1939SAndy Fiddaman 	job_unlock();
1077*b30d1939SAndy Fiddaman 	return(0);
1078*b30d1939SAndy Fiddaman }
1079*b30d1939SAndy Fiddaman 
1080*b30d1939SAndy Fiddaman /*
1081*b30d1939SAndy Fiddaman  * get the process group given the job number
1082*b30d1939SAndy Fiddaman  * This routine returns the process group number or -1
1083*b30d1939SAndy Fiddaman  */
job_bystring(register char * ajob)1084*b30d1939SAndy Fiddaman static struct process *job_bystring(register char *ajob)
1085*b30d1939SAndy Fiddaman {
1086*b30d1939SAndy Fiddaman 	register struct process *pw=job.pwlist;
1087*b30d1939SAndy Fiddaman 	register int c;
1088*b30d1939SAndy Fiddaman 	if(*ajob++ != '%' || !pw)
1089*b30d1939SAndy Fiddaman 		return(NIL(struct process*));
1090*b30d1939SAndy Fiddaman 	c = *ajob;
1091*b30d1939SAndy Fiddaman 	if(isdigit(c))
1092*b30d1939SAndy Fiddaman 		pw = job_byjid((int)strtol(ajob, (char**)0, 10));
1093*b30d1939SAndy Fiddaman 	else if(c=='+' || c=='%')
1094*b30d1939SAndy Fiddaman 		;
1095*b30d1939SAndy Fiddaman 	else if(c=='-')
1096*b30d1939SAndy Fiddaman 	{
1097*b30d1939SAndy Fiddaman 		if(pw)
1098*b30d1939SAndy Fiddaman 			pw = job.pwlist->p_nxtjob;
1099*b30d1939SAndy Fiddaman 	}
1100*b30d1939SAndy Fiddaman 	else
1101*b30d1939SAndy Fiddaman 		pw = job_byname(ajob);
1102*b30d1939SAndy Fiddaman 	if(pw && pw->p_flag)
1103*b30d1939SAndy Fiddaman 		return(pw);
1104*b30d1939SAndy Fiddaman 	return(NIL(struct process*));
1105*b30d1939SAndy Fiddaman }
1106*b30d1939SAndy Fiddaman 
1107*b30d1939SAndy Fiddaman /*
1108*b30d1939SAndy Fiddaman  * Kill a job or process
1109*b30d1939SAndy Fiddaman  */
1110*b30d1939SAndy Fiddaman 
job_kill(register struct process * pw,register int sig)1111*b30d1939SAndy Fiddaman int job_kill(register struct process *pw,register int sig)
1112*b30d1939SAndy Fiddaman {
1113*b30d1939SAndy Fiddaman 	Shell_t	*shp;
1114*b30d1939SAndy Fiddaman 	register pid_t pid;
1115*b30d1939SAndy Fiddaman 	register int r;
1116*b30d1939SAndy Fiddaman 	const char *msg;
1117*b30d1939SAndy Fiddaman #ifdef SIGTSTP
1118*b30d1939SAndy Fiddaman 	int stopsig = (sig==SIGSTOP||sig==SIGTSTP||sig==SIGTTIN||sig==SIGTTOU);
1119*b30d1939SAndy Fiddaman #else
1120*b30d1939SAndy Fiddaman #	define stopsig	1
1121*b30d1939SAndy Fiddaman #endif	/* SIGTSTP */
1122*b30d1939SAndy Fiddaman 	job_lock();
1123*b30d1939SAndy Fiddaman 	errno = ECHILD;
1124*b30d1939SAndy Fiddaman 	if(pw==0)
1125*b30d1939SAndy Fiddaman 		goto error;
1126*b30d1939SAndy Fiddaman 	shp = pw->p_shp;
1127*b30d1939SAndy Fiddaman 	pid = pw->p_pid;
1128*b30d1939SAndy Fiddaman #if SHOPT_COSHELL
1129*b30d1939SAndy Fiddaman 	if(pw->p_cojob)
1130*b30d1939SAndy Fiddaman 		r = cokill(pw->p_cojob->coshell,pw->p_cojob,sig);
1131*b30d1939SAndy Fiddaman 	else
1132*b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
1133*b30d1939SAndy Fiddaman 	if(by_number)
1134*b30d1939SAndy Fiddaman 	{
1135*b30d1939SAndy Fiddaman 		if(pid==0 && job.jobcontrol)
1136*b30d1939SAndy Fiddaman 			r = job_walk(outfile, job_kill,sig, (char**)0);
1137*b30d1939SAndy Fiddaman #ifdef SIGTSTP
1138*b30d1939SAndy Fiddaman 		if(sig==SIGSTOP && pid==shp->gd->pid && shp->gd->ppid==1)
1139*b30d1939SAndy Fiddaman 		{
1140*b30d1939SAndy Fiddaman 			/* can't stop login shell */
1141*b30d1939SAndy Fiddaman 			errno = EPERM;
1142*b30d1939SAndy Fiddaman 			r = -1;
1143*b30d1939SAndy Fiddaman 		}
1144*b30d1939SAndy Fiddaman 		else
1145*b30d1939SAndy Fiddaman 		{
1146*b30d1939SAndy Fiddaman 			if(pid>=0)
1147*b30d1939SAndy Fiddaman 			{
1148*b30d1939SAndy Fiddaman 				if((r = kill(pid,sig))>=0 && !stopsig)
1149*b30d1939SAndy Fiddaman 				{
1150*b30d1939SAndy Fiddaman 					if(pw->p_flag&P_STOPPED)
1151*b30d1939SAndy Fiddaman 						pw->p_flag &= ~(P_STOPPED|P_SIGNALLED);
1152*b30d1939SAndy Fiddaman 					if(sig)
1153*b30d1939SAndy Fiddaman 						kill(pid,SIGCONT);
1154*b30d1939SAndy Fiddaman 				}
1155*b30d1939SAndy Fiddaman 			}
1156*b30d1939SAndy Fiddaman 			else
1157*b30d1939SAndy Fiddaman 			{
1158*b30d1939SAndy Fiddaman 				if((r = killpg(-pid,sig))>=0 && !stopsig)
1159*b30d1939SAndy Fiddaman 				{
1160*b30d1939SAndy Fiddaman 					job_unstop(job_bypid(pw->p_pid));
1161*b30d1939SAndy Fiddaman 					if(sig)
1162*b30d1939SAndy Fiddaman 						killpg(-pid,SIGCONT);
1163*b30d1939SAndy Fiddaman 				}
1164*b30d1939SAndy Fiddaman 			}
1165*b30d1939SAndy Fiddaman 		}
1166*b30d1939SAndy Fiddaman #else
1167*b30d1939SAndy Fiddaman 		if(pid>=0)
1168*b30d1939SAndy Fiddaman 			r = kill(pid,sig);
1169*b30d1939SAndy Fiddaman 		else
1170*b30d1939SAndy Fiddaman 			r = killpg(-pid,sig);
1171*b30d1939SAndy Fiddaman #endif	/* SIGTSTP */
1172*b30d1939SAndy Fiddaman 	}
1173*b30d1939SAndy Fiddaman 	else
1174*b30d1939SAndy Fiddaman 	{
1175*b30d1939SAndy Fiddaman 		if(pid = pw->p_pgrp)
1176*b30d1939SAndy Fiddaman 		{
1177*b30d1939SAndy Fiddaman 			r = killpg(pid,sig);
1178*b30d1939SAndy Fiddaman #ifdef SIGTSTP
1179*b30d1939SAndy Fiddaman 			if(r>=0 && (sig==SIGHUP||sig==SIGTERM || sig==SIGCONT))
1180*b30d1939SAndy Fiddaman 				job_unstop(pw);
1181*b30d1939SAndy Fiddaman #endif	/* SIGTSTP */
1182*b30d1939SAndy Fiddaman 			if(r>=0)
1183*b30d1939SAndy Fiddaman 				sh_delay(.05);
1184*b30d1939SAndy Fiddaman 		}
1185*b30d1939SAndy Fiddaman 		while(pw && pw->p_pgrp==0 && (r=kill(pw->p_pid,sig))>=0)
1186*b30d1939SAndy Fiddaman 		{
1187*b30d1939SAndy Fiddaman #ifdef SIGTSTP
1188*b30d1939SAndy Fiddaman 			if(sig==SIGHUP || sig==SIGTERM)
1189*b30d1939SAndy Fiddaman 				kill(pw->p_pid,SIGCONT);
1190*b30d1939SAndy Fiddaman #endif	/* SIGTSTP */
1191*b30d1939SAndy Fiddaman 			pw = pw->p_nxtproc;
1192*b30d1939SAndy Fiddaman 		}
1193*b30d1939SAndy Fiddaman 	}
1194*b30d1939SAndy Fiddaman 	if(r<0 && job_string)
1195*b30d1939SAndy Fiddaman 	{
1196*b30d1939SAndy Fiddaman 	error:
1197*b30d1939SAndy Fiddaman 		if(pw && by_number)
1198*b30d1939SAndy Fiddaman 			msg = sh_translate(e_no_proc);
1199*b30d1939SAndy Fiddaman 		else
1200*b30d1939SAndy Fiddaman 			msg = sh_translate(e_no_job);
1201*b30d1939SAndy Fiddaman 		if(errno == EPERM)
1202*b30d1939SAndy Fiddaman 			msg = sh_translate(e_access);
1203*b30d1939SAndy Fiddaman 		sfprintf(sfstderr,"kill: %s: %s\n",job_string, msg);
1204*b30d1939SAndy Fiddaman 		r = 2;
1205*b30d1939SAndy Fiddaman 	}
1206*b30d1939SAndy Fiddaman 	sh_delay(.001);
1207*b30d1939SAndy Fiddaman 	job_unlock();
1208*b30d1939SAndy Fiddaman 	return(r);
1209*b30d1939SAndy Fiddaman }
1210*b30d1939SAndy Fiddaman 
1211*b30d1939SAndy Fiddaman /*
1212*b30d1939SAndy Fiddaman  * Similar to job_kill, but dedicated to SIGHUP handling when session is
1213*b30d1939SAndy Fiddaman  * being disconnected.
1214*b30d1939SAndy Fiddaman  */
1215*b30d1939SAndy Fiddaman int
job_hup(struct process * pw,int sig)1216*b30d1939SAndy Fiddaman job_hup(struct process *pw, int sig)
1217*b30d1939SAndy Fiddaman {
1218*b30d1939SAndy Fiddaman 	struct process	*px;
1219*b30d1939SAndy Fiddaman 	pid_t	pid;
1220*b30d1939SAndy Fiddaman 	int	r;
1221*b30d1939SAndy Fiddaman 
1222*b30d1939SAndy Fiddaman 	if (pw->p_pgrp == 0 || (pw->p_flag & P_DISOWN))
1223*b30d1939SAndy Fiddaman 		return (0);
1224*b30d1939SAndy Fiddaman 
1225*b30d1939SAndy Fiddaman #if SHOPT_COSHELL
1226*b30d1939SAndy Fiddaman 	if(pw->p_cojob) {
1227*b30d1939SAndy Fiddaman 		job_lock();
1228*b30d1939SAndy Fiddaman 		r = cokill(pw->p_cojob->coshell,pw->p_cojob,sig);
1229*b30d1939SAndy Fiddaman 		job_unlock();
1230*b30d1939SAndy Fiddaman 		return (r);
1231*b30d1939SAndy Fiddaman 	}
1232*b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
1233*b30d1939SAndy Fiddaman 
1234*b30d1939SAndy Fiddaman 	job_lock();
1235*b30d1939SAndy Fiddaman 	if (pw->p_pgrp != 0) {
1236*b30d1939SAndy Fiddaman 		int	palive = 0;
1237*b30d1939SAndy Fiddaman 
1238*b30d1939SAndy Fiddaman 		for (px = pw; px != NULL; px = px->p_nxtproc) {
1239*b30d1939SAndy Fiddaman 			if ((px->p_flag & P_DONE) == 0) {
1240*b30d1939SAndy Fiddaman 				palive = 1;
1241*b30d1939SAndy Fiddaman 				break;
1242*b30d1939SAndy Fiddaman 			}
1243*b30d1939SAndy Fiddaman 		}
1244*b30d1939SAndy Fiddaman 		/*
1245*b30d1939SAndy Fiddaman 		 * If all the processes have been dead, there is no guarantee
1246*b30d1939SAndy Fiddaman 		 * that the p_pgrp is still the valid process group that we
1247*b30d1939SAndy Fiddaman 		 * made, ie pid may have been recycled and same p_pgrp may
1248*b30d1939SAndy Fiddaman 		 * have been assigned to unrelated processes.
1249*b30d1939SAndy Fiddaman 		 */
1250*b30d1939SAndy Fiddaman 		if (palive) {
1251*b30d1939SAndy Fiddaman 			if (killpg(pw->p_pgrp, SIGHUP) >= 0)
1252*b30d1939SAndy Fiddaman 				job_unstop(pw);
1253*b30d1939SAndy Fiddaman 		}
1254*b30d1939SAndy Fiddaman 	}
1255*b30d1939SAndy Fiddaman 	for (; pw != NULL && pw->p_pgrp == 0; pw = pw->p_nxtproc) {
1256*b30d1939SAndy Fiddaman 		if (pw->p_flag & P_DONE)
1257*b30d1939SAndy Fiddaman 			continue;
1258*b30d1939SAndy Fiddaman 		if (kill(pw->p_pid, SIGHUP) >= 0)
1259*b30d1939SAndy Fiddaman 			(void) kill(pw->p_pid, SIGCONT);
1260*b30d1939SAndy Fiddaman 		pw = pw->p_nxtproc;
1261*b30d1939SAndy Fiddaman 	}
1262*b30d1939SAndy Fiddaman 	job_unlock();
1263*b30d1939SAndy Fiddaman 	return(0);
1264*b30d1939SAndy Fiddaman }
1265*b30d1939SAndy Fiddaman 
1266*b30d1939SAndy Fiddaman /*
1267*b30d1939SAndy Fiddaman  * Get process structure from first letters of jobname
1268*b30d1939SAndy Fiddaman  *
1269*b30d1939SAndy Fiddaman  */
1270*b30d1939SAndy Fiddaman 
job_byname(char * name)1271*b30d1939SAndy Fiddaman static struct process *job_byname(char *name)
1272*b30d1939SAndy Fiddaman {
1273*b30d1939SAndy Fiddaman 	register struct process *pw = job.pwlist;
1274*b30d1939SAndy Fiddaman 	register struct process *pz = 0;
1275*b30d1939SAndy Fiddaman 	register int *flag = 0;
1276*b30d1939SAndy Fiddaman 	register char *cp = name;
1277*b30d1939SAndy Fiddaman 	int offset;
1278*b30d1939SAndy Fiddaman 	if(!shgd->hist_ptr)
1279*b30d1939SAndy Fiddaman 		return(NIL(struct process*));
1280*b30d1939SAndy Fiddaman 	if(*cp=='?')
1281*b30d1939SAndy Fiddaman 		cp++,flag= &offset;
1282*b30d1939SAndy Fiddaman 	for(;pw;pw=pw->p_nxtjob)
1283*b30d1939SAndy Fiddaman 	{
1284*b30d1939SAndy Fiddaman 		if(hist_match(shgd->hist_ptr,pw->p_name,cp,flag)>=0)
1285*b30d1939SAndy Fiddaman 		{
1286*b30d1939SAndy Fiddaman 			if(pz)
1287*b30d1939SAndy Fiddaman 				errormsg(SH_DICT,ERROR_exit(1),e_jobusage,name-1);
1288*b30d1939SAndy Fiddaman 			pz = pw;
1289*b30d1939SAndy Fiddaman 		}
1290*b30d1939SAndy Fiddaman 	}
1291*b30d1939SAndy Fiddaman 	return(pz);
1292*b30d1939SAndy Fiddaman }
1293*b30d1939SAndy Fiddaman 
1294*b30d1939SAndy Fiddaman #else
1295*b30d1939SAndy Fiddaman #   define job_set(x)
1296*b30d1939SAndy Fiddaman #   define job_reset(x)
1297*b30d1939SAndy Fiddaman #endif /* JOBS */
1298*b30d1939SAndy Fiddaman 
1299*b30d1939SAndy Fiddaman 
1300*b30d1939SAndy Fiddaman 
1301*b30d1939SAndy Fiddaman /*
1302*b30d1939SAndy Fiddaman  * Initialize the process posting array
1303*b30d1939SAndy Fiddaman  */
1304*b30d1939SAndy Fiddaman 
job_clear(void)1305*b30d1939SAndy Fiddaman void	job_clear(void)
1306*b30d1939SAndy Fiddaman {
1307*b30d1939SAndy Fiddaman 	Shell_t	*shp = sh_getinterp();
1308*b30d1939SAndy Fiddaman 	register struct process *pw, *px;
1309*b30d1939SAndy Fiddaman 	register struct process *pwnext;
1310*b30d1939SAndy Fiddaman 	register int j = BYTE(shp->gd->lim.child_max);
1311*b30d1939SAndy Fiddaman 	register struct jobsave *jp,*jpnext;
1312*b30d1939SAndy Fiddaman 	job_lock();
1313*b30d1939SAndy Fiddaman 	for(pw=job.pwlist; pw; pw=pwnext)
1314*b30d1939SAndy Fiddaman 	{
1315*b30d1939SAndy Fiddaman 		pwnext = pw->p_nxtjob;
1316*b30d1939SAndy Fiddaman 		while(px=pw)
1317*b30d1939SAndy Fiddaman 		{
1318*b30d1939SAndy Fiddaman 			pw = pw->p_nxtproc;
1319*b30d1939SAndy Fiddaman 			free((void*)px);
1320*b30d1939SAndy Fiddaman 		}
1321*b30d1939SAndy Fiddaman 	}
1322*b30d1939SAndy Fiddaman 	for(jp=bck.list; jp;jp=jpnext)
1323*b30d1939SAndy Fiddaman 	{
1324*b30d1939SAndy Fiddaman 		jpnext = jp->next;
1325*b30d1939SAndy Fiddaman 		free((void*)jp);
1326*b30d1939SAndy Fiddaman 	}
1327*b30d1939SAndy Fiddaman 	bck.list = 0;
1328*b30d1939SAndy Fiddaman 	if(njob_savelist < NJOB_SAVELIST)
1329*b30d1939SAndy Fiddaman 		init_savelist();
1330*b30d1939SAndy Fiddaman 	job.pwlist = NIL(struct process*);
1331*b30d1939SAndy Fiddaman 	job.numpost=0;
1332*b30d1939SAndy Fiddaman #ifdef SHOPT_BGX
1333*b30d1939SAndy Fiddaman 	job.numbjob = 0;
1334*b30d1939SAndy Fiddaman #endif /* SHOPT_BGX */
1335*b30d1939SAndy Fiddaman 	job.waitall = 0;
1336*b30d1939SAndy Fiddaman 	job.curpgid = 0;
1337*b30d1939SAndy Fiddaman 	job.toclear = 0;
1338*b30d1939SAndy Fiddaman 	if(!job.freejobs)
1339*b30d1939SAndy Fiddaman 		job.freejobs = (unsigned char*)malloc((unsigned)(j+1));
1340*b30d1939SAndy Fiddaman 	while(j >=0)
1341*b30d1939SAndy Fiddaman 		job.freejobs[j--]  = 0;
1342*b30d1939SAndy Fiddaman 	job_unlock();
1343*b30d1939SAndy Fiddaman }
1344*b30d1939SAndy Fiddaman 
1345*b30d1939SAndy Fiddaman /*
1346*b30d1939SAndy Fiddaman  * put the process <pid> on the process list and return the job number
1347*b30d1939SAndy Fiddaman  * if non-zero, <join> is the process id of the job to join
1348*b30d1939SAndy Fiddaman  */
1349*b30d1939SAndy Fiddaman 
job_post(Shell_t * shp,pid_t pid,pid_t join)1350*b30d1939SAndy Fiddaman int job_post(Shell_t *shp,pid_t pid, pid_t join)
1351*b30d1939SAndy Fiddaman {
1352*b30d1939SAndy Fiddaman 	register struct process *pw;
1353*b30d1939SAndy Fiddaman 	register History_t *hp = shp->gd->hist_ptr;
1354*b30d1939SAndy Fiddaman #ifdef SHOPT_BGX
1355*b30d1939SAndy Fiddaman 	int val,bg=0;
1356*b30d1939SAndy Fiddaman #else
1357*b30d1939SAndy Fiddaman 	int val;
1358*b30d1939SAndy Fiddaman #endif
1359*b30d1939SAndy Fiddaman 	shp->jobenv = shp->curenv;
1360*b30d1939SAndy Fiddaman 	if(job.toclear)
1361*b30d1939SAndy Fiddaman 	{
1362*b30d1939SAndy Fiddaman 		job_clear();
1363*b30d1939SAndy Fiddaman 		return(0);
1364*b30d1939SAndy Fiddaman 	}
1365*b30d1939SAndy Fiddaman 	job_lock();
1366*b30d1939SAndy Fiddaman #ifdef SHOPT_BGX
1367*b30d1939SAndy Fiddaman 	if(join==1)
1368*b30d1939SAndy Fiddaman 	{
1369*b30d1939SAndy Fiddaman 		join = 0;
1370*b30d1939SAndy Fiddaman 		bg = P_BG;
1371*b30d1939SAndy Fiddaman 		job.numbjob++;
1372*b30d1939SAndy Fiddaman 	}
1373*b30d1939SAndy Fiddaman #endif /* SHOPT_BGX */
1374*b30d1939SAndy Fiddaman 	if(njob_savelist < NJOB_SAVELIST)
1375*b30d1939SAndy Fiddaman 		init_savelist();
1376*b30d1939SAndy Fiddaman 	if(pw = job_bypid(pid))
1377*b30d1939SAndy Fiddaman 		job_unpost(pw,0);
1378*b30d1939SAndy Fiddaman 	if(join)
1379*b30d1939SAndy Fiddaman 	{
1380*b30d1939SAndy Fiddaman 		if(pw=job_bypid(join))
1381*b30d1939SAndy Fiddaman 			val = pw->p_job;
1382*b30d1939SAndy Fiddaman 		else
1383*b30d1939SAndy Fiddaman 			val = job.curjobid;
1384*b30d1939SAndy Fiddaman 		/* if job to join is not first move it to front */
1385*b30d1939SAndy Fiddaman 		if(val && (pw=job_byjid(val)) != job.pwlist)
1386*b30d1939SAndy Fiddaman 		{
1387*b30d1939SAndy Fiddaman 			job_unlink(pw);
1388*b30d1939SAndy Fiddaman 			pw->p_nxtjob = job.pwlist;
1389*b30d1939SAndy Fiddaman 			job.pwlist = pw;
1390*b30d1939SAndy Fiddaman 		}
1391*b30d1939SAndy Fiddaman 	}
1392*b30d1939SAndy Fiddaman 	if(pw=freelist)
1393*b30d1939SAndy Fiddaman 		freelist = pw->p_nxtjob;
1394*b30d1939SAndy Fiddaman 	else
1395*b30d1939SAndy Fiddaman 		pw = new_of(struct process,0);
1396*b30d1939SAndy Fiddaman 	pw->p_flag = 0;
1397*b30d1939SAndy Fiddaman 	job.numpost++;
1398*b30d1939SAndy Fiddaman 	if(join && job.pwlist)
1399*b30d1939SAndy Fiddaman 	{
1400*b30d1939SAndy Fiddaman 		/* join existing current job */
1401*b30d1939SAndy Fiddaman 		pw->p_nxtjob = job.pwlist->p_nxtjob;
1402*b30d1939SAndy Fiddaman 		pw->p_nxtproc = job.pwlist;
1403*b30d1939SAndy Fiddaman 		pw->p_job = job.pwlist->p_job;
1404*b30d1939SAndy Fiddaman 	}
1405*b30d1939SAndy Fiddaman 	else
1406*b30d1939SAndy Fiddaman 	{
1407*b30d1939SAndy Fiddaman 		/* create a new job */
1408*b30d1939SAndy Fiddaman 		while((pw->p_job = job_alloc()) < 0)
1409*b30d1939SAndy Fiddaman 			job_wait((pid_t)1);
1410*b30d1939SAndy Fiddaman 		pw->p_nxtjob = job.pwlist;
1411*b30d1939SAndy Fiddaman 		pw->p_nxtproc = 0;
1412*b30d1939SAndy Fiddaman 	}
1413*b30d1939SAndy Fiddaman 	pw->p_exitval = job.exitval;
1414*b30d1939SAndy Fiddaman #if SHOPT_COSHELL
1415*b30d1939SAndy Fiddaman 	pw->p_cojob = 0;
1416*b30d1939SAndy Fiddaman 	if(shp->coshell && (pid&COPID_BIT))
1417*b30d1939SAndy Fiddaman 	{
1418*b30d1939SAndy Fiddaman 		pw->p_cojob = ((struct cosh*)shp->coshell)->cojob;
1419*b30d1939SAndy Fiddaman 		job.curpgid = sh_isstate(SH_MONITOR)?pid:0;
1420*b30d1939SAndy Fiddaman 	}
1421*b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
1422*b30d1939SAndy Fiddaman 	job.pwlist = pw;
1423*b30d1939SAndy Fiddaman 	pw->p_shp = shp;
1424*b30d1939SAndy Fiddaman 	pw->p_env = shp->curenv;
1425*b30d1939SAndy Fiddaman 	pw->p_pid = pid;
1426*b30d1939SAndy Fiddaman 	if(!shp->outpipe || shp->cpid==pid)
1427*b30d1939SAndy Fiddaman 		pw->p_flag = P_EXITSAVE;
1428*b30d1939SAndy Fiddaman 	pw->p_exitmin = shp->xargexit;
1429*b30d1939SAndy Fiddaman 	pw->p_exit = 0;
1430*b30d1939SAndy Fiddaman 	if(sh_isstate(SH_MONITOR))
1431*b30d1939SAndy Fiddaman 	{
1432*b30d1939SAndy Fiddaman 		if(killpg(job.curpgid,0)<0 && errno==ESRCH)
1433*b30d1939SAndy Fiddaman 			job.curpgid = pid;
1434*b30d1939SAndy Fiddaman 		pw->p_fgrp = job.curpgid;
1435*b30d1939SAndy Fiddaman 	}
1436*b30d1939SAndy Fiddaman 	else
1437*b30d1939SAndy Fiddaman 		pw->p_fgrp = 0;
1438*b30d1939SAndy Fiddaman 	pw->p_pgrp = pw->p_fgrp;
1439*b30d1939SAndy Fiddaman #ifdef DEBUG
1440*b30d1939SAndy Fiddaman 	sfprintf(sfstderr,"ksh: job line %4d: post pid=%d critical=%d job=%d pid=%d pgid=%d savesig=%d join=%d\n",__LINE__,getpid(),job.in_critical,pw->p_job,
1441*b30d1939SAndy Fiddaman 		pw->p_pid,pw->p_pgrp,job.savesig,join);
1442*b30d1939SAndy Fiddaman 	sfsync(sfstderr);
1443*b30d1939SAndy Fiddaman #endif /* DEBUG */
1444*b30d1939SAndy Fiddaman #ifdef JOBS
1445*b30d1939SAndy Fiddaman 	if(hp && !sh_isstate(SH_PROFILE))
1446*b30d1939SAndy Fiddaman 		pw->p_name=hist_tell(shgd->hist_ptr,(int)hp->histind-1);
1447*b30d1939SAndy Fiddaman 	else
1448*b30d1939SAndy Fiddaman 		pw->p_name = -1;
1449*b30d1939SAndy Fiddaman #endif /* JOBS */
1450*b30d1939SAndy Fiddaman 	if ((val = job_chksave(pid,pw->p_env))>=0 && !jobfork)
1451*b30d1939SAndy Fiddaman 	{
1452*b30d1939SAndy Fiddaman 		pw->p_exit = val;
1453*b30d1939SAndy Fiddaman 		if(pw->p_exit==SH_STOPSIG)
1454*b30d1939SAndy Fiddaman 		{
1455*b30d1939SAndy Fiddaman 			pw->p_flag |= (P_SIGNALLED|P_STOPPED);
1456*b30d1939SAndy Fiddaman 			pw->p_exit = 0;
1457*b30d1939SAndy Fiddaman 		}
1458*b30d1939SAndy Fiddaman 		else if(pw->p_exit >= SH_EXITSIG)
1459*b30d1939SAndy Fiddaman 		{
1460*b30d1939SAndy Fiddaman 			pw->p_flag |= P_DONE|P_SIGNALLED;
1461*b30d1939SAndy Fiddaman 			pw->p_exit &= SH_EXITMASK;
1462*b30d1939SAndy Fiddaman 		}
1463*b30d1939SAndy Fiddaman 		else
1464*b30d1939SAndy Fiddaman 			pw->p_flag |= (P_DONE|P_NOTIFY);
1465*b30d1939SAndy Fiddaman 	}
1466*b30d1939SAndy Fiddaman #ifdef SHOPT_BGX
1467*b30d1939SAndy Fiddaman 	if(bg)
1468*b30d1939SAndy Fiddaman 	{
1469*b30d1939SAndy Fiddaman 		if(pw->p_flag&P_DONE)
1470*b30d1939SAndy Fiddaman 			job.numbjob--;
1471*b30d1939SAndy Fiddaman 		else
1472*b30d1939SAndy Fiddaman 			pw->p_flag |= P_BG;
1473*b30d1939SAndy Fiddaman 	}
1474*b30d1939SAndy Fiddaman #endif /* SHOPT_BGX */
1475*b30d1939SAndy Fiddaman 	lastpid = 0;
1476*b30d1939SAndy Fiddaman 	job_unlock();
1477*b30d1939SAndy Fiddaman 	return(pw->p_job);
1478*b30d1939SAndy Fiddaman }
1479*b30d1939SAndy Fiddaman 
1480*b30d1939SAndy Fiddaman /*
1481*b30d1939SAndy Fiddaman  * Returns a process structure give a process id
1482*b30d1939SAndy Fiddaman  */
1483*b30d1939SAndy Fiddaman 
job_bypid(pid_t pid)1484*b30d1939SAndy Fiddaman static struct process *job_bypid(pid_t pid)
1485*b30d1939SAndy Fiddaman {
1486*b30d1939SAndy Fiddaman 	register struct process  *pw, *px;
1487*b30d1939SAndy Fiddaman 	for(pw=job.pwlist; pw; pw=pw->p_nxtjob)
1488*b30d1939SAndy Fiddaman 		for(px=pw; px; px=px->p_nxtproc)
1489*b30d1939SAndy Fiddaman 		{
1490*b30d1939SAndy Fiddaman 			if(px->p_pid==pid)
1491*b30d1939SAndy Fiddaman 				return(px);
1492*b30d1939SAndy Fiddaman 		}
1493*b30d1939SAndy Fiddaman 	return(NIL(struct process*));
1494*b30d1939SAndy Fiddaman }
1495*b30d1939SAndy Fiddaman 
1496*b30d1939SAndy Fiddaman /*
1497*b30d1939SAndy Fiddaman  * return a pointer to a job given the job id
1498*b30d1939SAndy Fiddaman  */
1499*b30d1939SAndy Fiddaman 
job_byjid(int jobid)1500*b30d1939SAndy Fiddaman static struct process *job_byjid(int jobid)
1501*b30d1939SAndy Fiddaman {
1502*b30d1939SAndy Fiddaman 	register struct process *pw;
1503*b30d1939SAndy Fiddaman 	for(pw=job.pwlist;pw; pw = pw->p_nxtjob)
1504*b30d1939SAndy Fiddaman 	{
1505*b30d1939SAndy Fiddaman 		if(pw->p_job==jobid)
1506*b30d1939SAndy Fiddaman 			break;
1507*b30d1939SAndy Fiddaman 	}
1508*b30d1939SAndy Fiddaman 	return(pw);
1509*b30d1939SAndy Fiddaman }
1510*b30d1939SAndy Fiddaman 
1511*b30d1939SAndy Fiddaman /*
1512*b30d1939SAndy Fiddaman  * print a signal message
1513*b30d1939SAndy Fiddaman  */
job_prmsg(register struct process * pw)1514*b30d1939SAndy Fiddaman static void job_prmsg(register struct process *pw)
1515*b30d1939SAndy Fiddaman {
1516*b30d1939SAndy Fiddaman 	if(pw->p_exit!=SIGINT && pw->p_exit!=SIGPIPE)
1517*b30d1939SAndy Fiddaman 	{
1518*b30d1939SAndy Fiddaman 		register const char *msg, *dump;
1519*b30d1939SAndy Fiddaman 		msg = job_sigmsg((int)(pw->p_exit));
1520*b30d1939SAndy Fiddaman 		msg = sh_translate(msg);
1521*b30d1939SAndy Fiddaman 		if(pw->p_flag&P_COREDUMP)
1522*b30d1939SAndy Fiddaman 			dump =  sh_translate(e_coredump);
1523*b30d1939SAndy Fiddaman 		else
1524*b30d1939SAndy Fiddaman 			dump = "";
1525*b30d1939SAndy Fiddaman 		if(sh_isstate(SH_INTERACTIVE))
1526*b30d1939SAndy Fiddaman 			sfprintf(sfstderr,"%s%s\n",msg,dump);
1527*b30d1939SAndy Fiddaman 		else
1528*b30d1939SAndy Fiddaman 			errormsg(SH_DICT,2,"%d: %s%s",pw->p_pid,msg,dump);
1529*b30d1939SAndy Fiddaman 	}
1530*b30d1939SAndy Fiddaman }
1531*b30d1939SAndy Fiddaman 
1532*b30d1939SAndy Fiddaman /*
1533*b30d1939SAndy Fiddaman  * Wait for process pid to complete
1534*b30d1939SAndy Fiddaman  * If pid < -1, then wait can be interrupted, -pid is waited for (wait builtin)
1535*b30d1939SAndy Fiddaman  * pid=0 to unpost all done processes
1536*b30d1939SAndy Fiddaman  * pid=1 to wait for at least one process to complete
1537*b30d1939SAndy Fiddaman  * pid=-1 to wait for all runing processes
1538*b30d1939SAndy Fiddaman  */
1539*b30d1939SAndy Fiddaman 
job_wait(register pid_t pid)1540*b30d1939SAndy Fiddaman int	job_wait(register pid_t pid)
1541*b30d1939SAndy Fiddaman {
1542*b30d1939SAndy Fiddaman 	Shell_t		*shp = sh_getinterp();
1543*b30d1939SAndy Fiddaman 	register struct process *pw=0,*px;
1544*b30d1939SAndy Fiddaman 	register int	jobid = 0;
1545*b30d1939SAndy Fiddaman 	int		nochild = 1;
1546*b30d1939SAndy Fiddaman 	char		intr = 0;
1547*b30d1939SAndy Fiddaman 	if(pid < 0)
1548*b30d1939SAndy Fiddaman 	{
1549*b30d1939SAndy Fiddaman 		pid = -pid;
1550*b30d1939SAndy Fiddaman 		intr = 1;
1551*b30d1939SAndy Fiddaman 	}
1552*b30d1939SAndy Fiddaman 	job_lock();
1553*b30d1939SAndy Fiddaman 	if(pid==0)
1554*b30d1939SAndy Fiddaman 	{
1555*b30d1939SAndy Fiddaman 		if(!job.waitall || !job.curjobid || !(pw = job_byjid(job.curjobid)))
1556*b30d1939SAndy Fiddaman 		{
1557*b30d1939SAndy Fiddaman 			job_unlock();
1558*b30d1939SAndy Fiddaman 			goto done;
1559*b30d1939SAndy Fiddaman 		}
1560*b30d1939SAndy Fiddaman 		jobid = pw->p_job;
1561*b30d1939SAndy Fiddaman 		job.curjobid = 0;
1562*b30d1939SAndy Fiddaman 		if(!(pw->p_flag&(P_DONE|P_STOPPED)))
1563*b30d1939SAndy Fiddaman 			job_reap(job.savesig);
1564*b30d1939SAndy Fiddaman 	}
1565*b30d1939SAndy Fiddaman 	if(pid > 1)
1566*b30d1939SAndy Fiddaman 	{
1567*b30d1939SAndy Fiddaman 		if(pid==shp->spid)
1568*b30d1939SAndy Fiddaman 			shp->spid = 0;
1569*b30d1939SAndy Fiddaman 		if(!(pw=job_bypid(pid)))
1570*b30d1939SAndy Fiddaman 		{
1571*b30d1939SAndy Fiddaman 			/* check to see whether job status has been saved */
1572*b30d1939SAndy Fiddaman 			if((shp->exitval = job_chksave(pid,shp->curenv)) < 0)
1573*b30d1939SAndy Fiddaman 				shp->exitval = ERROR_NOENT;
1574*b30d1939SAndy Fiddaman 			exitset();
1575*b30d1939SAndy Fiddaman 			job_unlock();
1576*b30d1939SAndy Fiddaman 			return(nochild);
1577*b30d1939SAndy Fiddaman 		}
1578*b30d1939SAndy Fiddaman 		else if(intr && pw->p_env!=shp->curenv)
1579*b30d1939SAndy Fiddaman 		{
1580*b30d1939SAndy Fiddaman 			shp->exitval = ERROR_NOENT;
1581*b30d1939SAndy Fiddaman 			job_unlock();
1582*b30d1939SAndy Fiddaman 			return(nochild);
1583*b30d1939SAndy Fiddaman 		}
1584*b30d1939SAndy Fiddaman 		jobid = pw->p_job;
1585*b30d1939SAndy Fiddaman 		if(!intr)
1586*b30d1939SAndy Fiddaman 			pw->p_flag &= ~P_EXITSAVE;
1587*b30d1939SAndy Fiddaman 		if(pw->p_pgrp && job.parent!= (pid_t)-1)
1588*b30d1939SAndy Fiddaman 			job_set(job_byjid(jobid));
1589*b30d1939SAndy Fiddaman 	}
1590*b30d1939SAndy Fiddaman 	pwfg = pw;
1591*b30d1939SAndy Fiddaman #ifdef DEBUG
1592*b30d1939SAndy Fiddaman 	sfprintf(sfstderr,"ksh: job line %4d: wait pid=%d critical=%d job=%d pid=%d\n",__LINE__,getpid(),job.in_critical,jobid,pid);
1593*b30d1939SAndy Fiddaman 	if(pw)
1594*b30d1939SAndy Fiddaman 		sfprintf(sfstderr,"ksh: job line %4d: wait pid=%d critical=%d flags=%o\n",__LINE__,getpid(),job.in_critical,pw->p_flag);
1595*b30d1939SAndy Fiddaman #endif /* DEBUG*/
1596*b30d1939SAndy Fiddaman 	errno = 0;
1597*b30d1939SAndy Fiddaman 	if(shp->coutpipe>=0 && lastpid && shp->cpid==lastpid)
1598*b30d1939SAndy Fiddaman 	{
1599*b30d1939SAndy Fiddaman 		sh_close(shp->coutpipe);
1600*b30d1939SAndy Fiddaman 		sh_close(shp->cpipe[1]);
1601*b30d1939SAndy Fiddaman 		shp->cpipe[1] = shp->coutpipe = -1;
1602*b30d1939SAndy Fiddaman 	}
1603*b30d1939SAndy Fiddaman 	while(1)
1604*b30d1939SAndy Fiddaman 	{
1605*b30d1939SAndy Fiddaman 		if(job.waitsafe)
1606*b30d1939SAndy Fiddaman 		{
1607*b30d1939SAndy Fiddaman 			for(px=job.pwlist;px; px = px->p_nxtjob)
1608*b30d1939SAndy Fiddaman 			{
1609*b30d1939SAndy Fiddaman 				if(px!=pw && (px->p_flag&P_NOTIFY))
1610*b30d1939SAndy Fiddaman 				{
1611*b30d1939SAndy Fiddaman 					if(sh_isoption(SH_NOTIFY))
1612*b30d1939SAndy Fiddaman 					{
1613*b30d1939SAndy Fiddaman 						outfile = sfstderr;
1614*b30d1939SAndy Fiddaman 						job_list(px,JOB_NFLAG|JOB_NLFLAG);
1615*b30d1939SAndy Fiddaman 						sfsync(sfstderr);
1616*b30d1939SAndy Fiddaman 					}
1617*b30d1939SAndy Fiddaman 					else if(!sh_isoption(SH_INTERACTIVE) && (px->p_flag&P_SIGNALLED))
1618*b30d1939SAndy Fiddaman 					{
1619*b30d1939SAndy Fiddaman 						job_prmsg(px);
1620*b30d1939SAndy Fiddaman 						px->p_flag &= ~P_NOTIFY;
1621*b30d1939SAndy Fiddaman 					}
1622*b30d1939SAndy Fiddaman 				}
1623*b30d1939SAndy Fiddaman 			}
1624*b30d1939SAndy Fiddaman 		}
1625*b30d1939SAndy Fiddaman 		if(pw && (pw->p_flag&(P_DONE|P_STOPPED)))
1626*b30d1939SAndy Fiddaman 		{
1627*b30d1939SAndy Fiddaman #ifdef SIGTSTP
1628*b30d1939SAndy Fiddaman 			if(pw->p_flag&P_STOPPED)
1629*b30d1939SAndy Fiddaman 			{
1630*b30d1939SAndy Fiddaman 				pw->p_flag |= P_EXITSAVE;
1631*b30d1939SAndy Fiddaman 				if(sh_isoption(SH_INTERACTIVE) && !sh_isstate(SH_FORKED))
1632*b30d1939SAndy Fiddaman 				{
1633*b30d1939SAndy Fiddaman 					if( pw->p_exit!=SIGTTIN && pw->p_exit!=SIGTTOU)
1634*b30d1939SAndy Fiddaman 						break;
1635*b30d1939SAndy Fiddaman 
1636*b30d1939SAndy Fiddaman 					killpg(pw->p_pgrp,SIGCONT);
1637*b30d1939SAndy Fiddaman 				}
1638*b30d1939SAndy Fiddaman 				else /* ignore stop when non-interactive */
1639*b30d1939SAndy Fiddaman 					pw->p_flag &= ~(P_NOTIFY|P_SIGNALLED|P_STOPPED|P_EXITSAVE);
1640*b30d1939SAndy Fiddaman 			}
1641*b30d1939SAndy Fiddaman 			else
1642*b30d1939SAndy Fiddaman #endif /* SIGTSTP */
1643*b30d1939SAndy Fiddaman 			{
1644*b30d1939SAndy Fiddaman 				if(pw->p_flag&P_SIGNALLED)
1645*b30d1939SAndy Fiddaman 				{
1646*b30d1939SAndy Fiddaman 					pw->p_flag &= ~P_NOTIFY;
1647*b30d1939SAndy Fiddaman 					job_prmsg(pw);
1648*b30d1939SAndy Fiddaman 				}
1649*b30d1939SAndy Fiddaman 				else if(pw->p_flag&P_DONE)
1650*b30d1939SAndy Fiddaman 					pw->p_flag &= ~P_NOTIFY;
1651*b30d1939SAndy Fiddaman 				if(pw->p_job==jobid)
1652*b30d1939SAndy Fiddaman 				{
1653*b30d1939SAndy Fiddaman 					px = job_byjid(jobid);
1654*b30d1939SAndy Fiddaman 					/* last process in job */
1655*b30d1939SAndy Fiddaman 					if(px!=pw)
1656*b30d1939SAndy Fiddaman 						px = 0;
1657*b30d1939SAndy Fiddaman 					if(px)
1658*b30d1939SAndy Fiddaman 					{
1659*b30d1939SAndy Fiddaman 						shp->exitval=px->p_exit;
1660*b30d1939SAndy Fiddaman 						if(px->p_flag&P_SIGNALLED)
1661*b30d1939SAndy Fiddaman 							shp->exitval |= SH_EXITSIG;
1662*b30d1939SAndy Fiddaman 						if(intr)
1663*b30d1939SAndy Fiddaman 							px->p_flag &= ~P_EXITSAVE;
1664*b30d1939SAndy Fiddaman 					}
1665*b30d1939SAndy Fiddaman 				}
1666*b30d1939SAndy Fiddaman 				px = job_unpost(pw,1);
1667*b30d1939SAndy Fiddaman 				if(!px || !job.waitall)
1668*b30d1939SAndy Fiddaman 					break;
1669*b30d1939SAndy Fiddaman 				pw = px;
1670*b30d1939SAndy Fiddaman 				continue;
1671*b30d1939SAndy Fiddaman 			}
1672*b30d1939SAndy Fiddaman 		}
1673*b30d1939SAndy Fiddaman 		sfsync(sfstderr);
1674*b30d1939SAndy Fiddaman 		job.waitsafe = 0;
1675*b30d1939SAndy Fiddaman 		nochild = job_reap(job.savesig);
1676*b30d1939SAndy Fiddaman 		if(job.waitsafe)
1677*b30d1939SAndy Fiddaman 			continue;
1678*b30d1939SAndy Fiddaman 		if(nochild)
1679*b30d1939SAndy Fiddaman 			break;
1680*b30d1939SAndy Fiddaman 		if(shp->sigflag[SIGALRM]&SH_SIGTRAP)
1681*b30d1939SAndy Fiddaman 			sh_timetraps(shp);
1682*b30d1939SAndy Fiddaman 		if((intr && shp->trapnote) || (pid==1 && !intr))
1683*b30d1939SAndy Fiddaman 			break;
1684*b30d1939SAndy Fiddaman 	}
1685*b30d1939SAndy Fiddaman 	if(intr && shp->trapnote)
1686*b30d1939SAndy Fiddaman 		shp->exitval = 1;
1687*b30d1939SAndy Fiddaman 	pwfg = 0;
1688*b30d1939SAndy Fiddaman 	job_unlock();
1689*b30d1939SAndy Fiddaman 	if(pid==1)
1690*b30d1939SAndy Fiddaman 		return(nochild);
1691*b30d1939SAndy Fiddaman 	exitset();
1692*b30d1939SAndy Fiddaman 	if(pid==0)
1693*b30d1939SAndy Fiddaman 		goto done;
1694*b30d1939SAndy Fiddaman 	if(pw->p_pgrp)
1695*b30d1939SAndy Fiddaman 	{
1696*b30d1939SAndy Fiddaman 		job_reset(pw);
1697*b30d1939SAndy Fiddaman 		/* propogate keyboard interrupts to parent */
1698*b30d1939SAndy Fiddaman 		if((pw->p_flag&P_SIGNALLED) && pw->p_exit==SIGINT && !(shp->sigflag[SIGINT]&SH_SIGOFF))
1699*b30d1939SAndy Fiddaman 			kill(getpid(),SIGINT);
1700*b30d1939SAndy Fiddaman #ifdef SIGTSTP
1701*b30d1939SAndy Fiddaman 		else if((pw->p_flag&P_STOPPED) && pw->p_exit==SIGTSTP)
1702*b30d1939SAndy Fiddaman 		{
1703*b30d1939SAndy Fiddaman 			job.parent = 0;
1704*b30d1939SAndy Fiddaman 			kill(getpid(),SIGTSTP);
1705*b30d1939SAndy Fiddaman 		}
1706*b30d1939SAndy Fiddaman #endif /* SIGTSTP */
1707*b30d1939SAndy Fiddaman 	}
1708*b30d1939SAndy Fiddaman 	else
1709*b30d1939SAndy Fiddaman 	{
1710*b30d1939SAndy Fiddaman 		if(pw->p_pid == tcgetpgrp(JOBTTY))
1711*b30d1939SAndy Fiddaman 		{
1712*b30d1939SAndy Fiddaman 			if(pw->p_pgrp==0)
1713*b30d1939SAndy Fiddaman 				pw->p_pgrp = pw->p_pid;
1714*b30d1939SAndy Fiddaman 			job_reset(pw);
1715*b30d1939SAndy Fiddaman 		}
1716*b30d1939SAndy Fiddaman 		tty_set(-1, 0, NIL(struct termios*));
1717*b30d1939SAndy Fiddaman 	}
1718*b30d1939SAndy Fiddaman done:
1719*b30d1939SAndy Fiddaman 	if(!job.waitall && sh_isoption(SH_PIPEFAIL))
1720*b30d1939SAndy Fiddaman 		return(nochild);
1721*b30d1939SAndy Fiddaman 	if(!shp->intrap)
1722*b30d1939SAndy Fiddaman 	{
1723*b30d1939SAndy Fiddaman 		job_lock();
1724*b30d1939SAndy Fiddaman 		for(pw=job.pwlist; pw; pw=px)
1725*b30d1939SAndy Fiddaman 		{
1726*b30d1939SAndy Fiddaman 			px = pw->p_nxtjob;
1727*b30d1939SAndy Fiddaman 			job_unpost(pw,0);
1728*b30d1939SAndy Fiddaman 		}
1729*b30d1939SAndy Fiddaman 		job_unlock();
1730*b30d1939SAndy Fiddaman 	}
1731*b30d1939SAndy Fiddaman 	return(nochild);
1732*b30d1939SAndy Fiddaman }
1733*b30d1939SAndy Fiddaman 
1734*b30d1939SAndy Fiddaman /*
1735*b30d1939SAndy Fiddaman  * move job to foreground if bgflag == 'f'
1736*b30d1939SAndy Fiddaman  * move job to background if bgflag == 'b'
1737*b30d1939SAndy Fiddaman  * disown job if bgflag == 'd'
1738*b30d1939SAndy Fiddaman  */
1739*b30d1939SAndy Fiddaman 
job_switch(register struct process * pw,int bgflag)1740*b30d1939SAndy Fiddaman int job_switch(register struct process *pw,int bgflag)
1741*b30d1939SAndy Fiddaman {
1742*b30d1939SAndy Fiddaman 	register const char *msg;
1743*b30d1939SAndy Fiddaman 	job_lock();
1744*b30d1939SAndy Fiddaman 	if(!pw || !(pw=job_byjid((int)pw->p_job)))
1745*b30d1939SAndy Fiddaman 	{
1746*b30d1939SAndy Fiddaman 		job_unlock();
1747*b30d1939SAndy Fiddaman 		return(1);
1748*b30d1939SAndy Fiddaman 	}
1749*b30d1939SAndy Fiddaman 	if(bgflag=='d')
1750*b30d1939SAndy Fiddaman 	{
1751*b30d1939SAndy Fiddaman 		for(; pw; pw=pw->p_nxtproc)
1752*b30d1939SAndy Fiddaman 			pw->p_flag |= P_DISOWN;
1753*b30d1939SAndy Fiddaman 		job_unlock();
1754*b30d1939SAndy Fiddaman 		return(0);
1755*b30d1939SAndy Fiddaman 	}
1756*b30d1939SAndy Fiddaman #ifdef SIGTSTP
1757*b30d1939SAndy Fiddaman 	if(bgflag=='b')
1758*b30d1939SAndy Fiddaman 	{
1759*b30d1939SAndy Fiddaman 		sfprintf(outfile,"[%d]\t",(int)pw->p_job);
1760*b30d1939SAndy Fiddaman 		sh.bckpid = pw->p_pid;
1761*b30d1939SAndy Fiddaman #ifdef SHOPT_BGX
1762*b30d1939SAndy Fiddaman 		pw->p_flag |= P_BG;
1763*b30d1939SAndy Fiddaman #endif
1764*b30d1939SAndy Fiddaman 		msg = "&";
1765*b30d1939SAndy Fiddaman 	}
1766*b30d1939SAndy Fiddaman 	else
1767*b30d1939SAndy Fiddaman 	{
1768*b30d1939SAndy Fiddaman 		job_unlink(pw);
1769*b30d1939SAndy Fiddaman 		pw->p_nxtjob = job.pwlist;
1770*b30d1939SAndy Fiddaman 		job.pwlist = pw;
1771*b30d1939SAndy Fiddaman 		msg = "";
1772*b30d1939SAndy Fiddaman 	}
1773*b30d1939SAndy Fiddaman 	hist_list(shgd->hist_ptr,outfile,pw->p_name,'&',";");
1774*b30d1939SAndy Fiddaman 	sfputr(outfile,msg,'\n');
1775*b30d1939SAndy Fiddaman 	sfsync(outfile);
1776*b30d1939SAndy Fiddaman 	if(bgflag=='f')
1777*b30d1939SAndy Fiddaman 	{
1778*b30d1939SAndy Fiddaman 		if(!(pw=job_unpost(pw,1)))
1779*b30d1939SAndy Fiddaman 		{
1780*b30d1939SAndy Fiddaman 			job_unlock();
1781*b30d1939SAndy Fiddaman 			return(1);
1782*b30d1939SAndy Fiddaman 		}
1783*b30d1939SAndy Fiddaman 		job.waitall = 1;
1784*b30d1939SAndy Fiddaman 		pw->p_flag |= P_FG;
1785*b30d1939SAndy Fiddaman #ifdef SHOPT_BGX
1786*b30d1939SAndy Fiddaman 		pw->p_flag &= ~P_BG;
1787*b30d1939SAndy Fiddaman #endif
1788*b30d1939SAndy Fiddaman 		job_wait(pw->p_pid);
1789*b30d1939SAndy Fiddaman 		job.waitall = 0;
1790*b30d1939SAndy Fiddaman 	}
1791*b30d1939SAndy Fiddaman 	else if(pw->p_flag&P_STOPPED)
1792*b30d1939SAndy Fiddaman 		job_unstop(pw);
1793*b30d1939SAndy Fiddaman #endif /* SIGTSTP */
1794*b30d1939SAndy Fiddaman 	job_unlock();
1795*b30d1939SAndy Fiddaman 	return(0);
1796*b30d1939SAndy Fiddaman }
1797*b30d1939SAndy Fiddaman 
1798*b30d1939SAndy Fiddaman 
1799*b30d1939SAndy Fiddaman #ifdef SIGTSTP
1800*b30d1939SAndy Fiddaman /*
1801*b30d1939SAndy Fiddaman  * Set the foreground group associated with a job
1802*b30d1939SAndy Fiddaman  */
1803*b30d1939SAndy Fiddaman 
job_fgrp(register struct process * pw,int newgrp)1804*b30d1939SAndy Fiddaman static void job_fgrp(register struct process *pw, int newgrp)
1805*b30d1939SAndy Fiddaman {
1806*b30d1939SAndy Fiddaman 	for(; pw; pw=pw->p_nxtproc)
1807*b30d1939SAndy Fiddaman 		pw->p_fgrp = newgrp;
1808*b30d1939SAndy Fiddaman }
1809*b30d1939SAndy Fiddaman 
1810*b30d1939SAndy Fiddaman /*
1811*b30d1939SAndy Fiddaman  * turn off STOP state of a process group and send CONT signals
1812*b30d1939SAndy Fiddaman  */
1813*b30d1939SAndy Fiddaman 
job_unstop(register struct process * px)1814*b30d1939SAndy Fiddaman static void job_unstop(register struct process *px)
1815*b30d1939SAndy Fiddaman {
1816*b30d1939SAndy Fiddaman 	register struct process *pw;
1817*b30d1939SAndy Fiddaman 	register int num = 0;
1818*b30d1939SAndy Fiddaman 	for(pw=px ;pw ;pw=pw->p_nxtproc)
1819*b30d1939SAndy Fiddaman 	{
1820*b30d1939SAndy Fiddaman 		if(pw->p_flag&P_STOPPED)
1821*b30d1939SAndy Fiddaman 		{
1822*b30d1939SAndy Fiddaman 			num++;
1823*b30d1939SAndy Fiddaman 			pw->p_flag &= ~(P_STOPPED|P_SIGNALLED|P_NOTIFY);
1824*b30d1939SAndy Fiddaman 		}
1825*b30d1939SAndy Fiddaman 	}
1826*b30d1939SAndy Fiddaman 	if(num!=0)
1827*b30d1939SAndy Fiddaman 	{
1828*b30d1939SAndy Fiddaman 		if(px->p_fgrp != px->p_pgrp)
1829*b30d1939SAndy Fiddaman 			killpg(px->p_fgrp,SIGCONT);
1830*b30d1939SAndy Fiddaman 		killpg(px->p_pgrp,SIGCONT);
1831*b30d1939SAndy Fiddaman 	}
1832*b30d1939SAndy Fiddaman }
1833*b30d1939SAndy Fiddaman #endif	/* SIGTSTP */
1834*b30d1939SAndy Fiddaman 
1835*b30d1939SAndy Fiddaman /*
1836*b30d1939SAndy Fiddaman  * remove a job from table
1837*b30d1939SAndy Fiddaman  * If all the processes have not completed, unpost first non-completed  process
1838*b30d1939SAndy Fiddaman  * Otherwise the job is removed and job_unpost returns NULL.
1839*b30d1939SAndy Fiddaman  * pwlist is reset if the first job is removed
1840*b30d1939SAndy Fiddaman  * if <notify> is non-zero, then jobs with pending notifications are unposted
1841*b30d1939SAndy Fiddaman  */
1842*b30d1939SAndy Fiddaman 
job_unpost(register struct process * pwtop,int notify)1843*b30d1939SAndy Fiddaman static struct process *job_unpost(register struct process *pwtop,int notify)
1844*b30d1939SAndy Fiddaman {
1845*b30d1939SAndy Fiddaman 	register struct process *pw;
1846*b30d1939SAndy Fiddaman 	/* make sure all processes are done */
1847*b30d1939SAndy Fiddaman #ifdef DEBUG
1848*b30d1939SAndy Fiddaman 	sfprintf(sfstderr,"ksh: job line %4d: drop pid=%d critical=%d pid=%d env=%d\n",__LINE__,getpid(),job.in_critical,pwtop->p_pid,pwtop->p_env);
1849*b30d1939SAndy Fiddaman 	sfsync(sfstderr);
1850*b30d1939SAndy Fiddaman #endif /* DEBUG */
1851*b30d1939SAndy Fiddaman 	pwtop = pw = job_byjid((int)pwtop->p_job);
1852*b30d1939SAndy Fiddaman #ifdef SHOPT_BGX
1853*b30d1939SAndy Fiddaman 	if(pw->p_flag&P_BG)
1854*b30d1939SAndy Fiddaman 		return(pw);
1855*b30d1939SAndy Fiddaman #endif /* SHOPT_BGX */
1856*b30d1939SAndy Fiddaman 	for(; pw && (pw->p_flag&P_DONE)&&(notify||!(pw->p_flag&P_NOTIFY)||pw->p_env); pw=pw->p_nxtproc);
1857*b30d1939SAndy Fiddaman 	if(pw)
1858*b30d1939SAndy Fiddaman 		return(pw);
1859*b30d1939SAndy Fiddaman 	if(pwtop->p_job == job.curjobid)
1860*b30d1939SAndy Fiddaman 		return(0);
1861*b30d1939SAndy Fiddaman 	/* all processes complete, unpost job */
1862*b30d1939SAndy Fiddaman 	job_unlink(pwtop);
1863*b30d1939SAndy Fiddaman 	for(pw=pwtop; pw; pw=pw->p_nxtproc)
1864*b30d1939SAndy Fiddaman 	{
1865*b30d1939SAndy Fiddaman 		if(pw && pw->p_exitval)
1866*b30d1939SAndy Fiddaman 			*pw->p_exitval = pw->p_exit;
1867*b30d1939SAndy Fiddaman 		/* save the exit status for background jobs */
1868*b30d1939SAndy Fiddaman 		if((pw->p_flag&P_EXITSAVE) ||  pw->p_pid==sh.spid)
1869*b30d1939SAndy Fiddaman 		{
1870*b30d1939SAndy Fiddaman 			struct jobsave *jp;
1871*b30d1939SAndy Fiddaman 			/* save status for future wait */
1872*b30d1939SAndy Fiddaman 			if(jp = jobsave_create(pw->p_pid))
1873*b30d1939SAndy Fiddaman 			{
1874*b30d1939SAndy Fiddaman 				jp->exitval = pw->p_exit;
1875*b30d1939SAndy Fiddaman 				if(pw->p_flag&P_SIGNALLED)
1876*b30d1939SAndy Fiddaman 					jp->exitval |= SH_EXITSIG;
1877*b30d1939SAndy Fiddaman 			}
1878*b30d1939SAndy Fiddaman 			pw->p_flag &= ~P_EXITSAVE;
1879*b30d1939SAndy Fiddaman 		}
1880*b30d1939SAndy Fiddaman 		pw->p_flag &= ~P_DONE;
1881*b30d1939SAndy Fiddaman 		job.numpost--;
1882*b30d1939SAndy Fiddaman 		pw->p_nxtjob = freelist;
1883*b30d1939SAndy Fiddaman 		freelist = pw;
1884*b30d1939SAndy Fiddaman 	}
1885*b30d1939SAndy Fiddaman 	pwtop->p_pid = 0;
1886*b30d1939SAndy Fiddaman #ifdef DEBUG
1887*b30d1939SAndy Fiddaman 	sfprintf(sfstderr,"ksh: job line %4d: free pid=%d critical=%d job=%d\n",__LINE__,getpid(),job.in_critical,pwtop->p_job);
1888*b30d1939SAndy Fiddaman 	sfsync(sfstderr);
1889*b30d1939SAndy Fiddaman #endif /* DEBUG */
1890*b30d1939SAndy Fiddaman 	job_free((int)pwtop->p_job);
1891*b30d1939SAndy Fiddaman 	return((struct process*)0);
1892*b30d1939SAndy Fiddaman }
1893*b30d1939SAndy Fiddaman 
1894*b30d1939SAndy Fiddaman /*
1895*b30d1939SAndy Fiddaman  * unlink a job form the job list
1896*b30d1939SAndy Fiddaman  */
job_unlink(register struct process * pw)1897*b30d1939SAndy Fiddaman static void job_unlink(register struct process *pw)
1898*b30d1939SAndy Fiddaman {
1899*b30d1939SAndy Fiddaman 	register struct process *px;
1900*b30d1939SAndy Fiddaman 	if(pw==job.pwlist)
1901*b30d1939SAndy Fiddaman 	{
1902*b30d1939SAndy Fiddaman 		job.pwlist = pw->p_nxtjob;
1903*b30d1939SAndy Fiddaman 		job.curpgid = 0;
1904*b30d1939SAndy Fiddaman 		return;
1905*b30d1939SAndy Fiddaman 	}
1906*b30d1939SAndy Fiddaman 	for(px=job.pwlist;px;px=px->p_nxtjob)
1907*b30d1939SAndy Fiddaman 		if(px->p_nxtjob == pw)
1908*b30d1939SAndy Fiddaman 		{
1909*b30d1939SAndy Fiddaman 			px->p_nxtjob = pw->p_nxtjob;
1910*b30d1939SAndy Fiddaman 			return;
1911*b30d1939SAndy Fiddaman 		}
1912*b30d1939SAndy Fiddaman }
1913*b30d1939SAndy Fiddaman 
1914*b30d1939SAndy Fiddaman /*
1915*b30d1939SAndy Fiddaman  * get an unused job number
1916*b30d1939SAndy Fiddaman  * freejobs is a bit vector, 0 is unused
1917*b30d1939SAndy Fiddaman  */
1918*b30d1939SAndy Fiddaman 
job_alloc(void)1919*b30d1939SAndy Fiddaman static int job_alloc(void)
1920*b30d1939SAndy Fiddaman {
1921*b30d1939SAndy Fiddaman 	register int j=0;
1922*b30d1939SAndy Fiddaman 	register unsigned mask = 1;
1923*b30d1939SAndy Fiddaman 	register unsigned char *freeword;
1924*b30d1939SAndy Fiddaman 	register int jmax = BYTE(shgd->lim.child_max);
1925*b30d1939SAndy Fiddaman 	/* skip to first word with a free slot */
1926*b30d1939SAndy Fiddaman 	for(j=0;job.freejobs[j] == UCHAR_MAX; j++);
1927*b30d1939SAndy Fiddaman 	if(j >= jmax)
1928*b30d1939SAndy Fiddaman 	{
1929*b30d1939SAndy Fiddaman 		register struct process *pw;
1930*b30d1939SAndy Fiddaman 		for(j=1; j < shgd->lim.child_max; j++)
1931*b30d1939SAndy Fiddaman 		{
1932*b30d1939SAndy Fiddaman 			if((pw=job_byjid(j))&& !job_unpost(pw,0))
1933*b30d1939SAndy Fiddaman 				break;
1934*b30d1939SAndy Fiddaman 		}
1935*b30d1939SAndy Fiddaman 		j /= CHAR_BIT;
1936*b30d1939SAndy Fiddaman 		if(j >= jmax)
1937*b30d1939SAndy Fiddaman 			return(-1);
1938*b30d1939SAndy Fiddaman 	}
1939*b30d1939SAndy Fiddaman 	freeword = &job.freejobs[j];
1940*b30d1939SAndy Fiddaman 	j *= CHAR_BIT;
1941*b30d1939SAndy Fiddaman 	for(j++;mask&(*freeword);j++,mask <<=1);
1942*b30d1939SAndy Fiddaman 	*freeword  |= mask;
1943*b30d1939SAndy Fiddaman 	return(j);
1944*b30d1939SAndy Fiddaman }
1945*b30d1939SAndy Fiddaman 
1946*b30d1939SAndy Fiddaman /*
1947*b30d1939SAndy Fiddaman  * return a job number
1948*b30d1939SAndy Fiddaman  */
1949*b30d1939SAndy Fiddaman 
job_free(register int n)1950*b30d1939SAndy Fiddaman static void job_free(register int n)
1951*b30d1939SAndy Fiddaman {
1952*b30d1939SAndy Fiddaman 	register int j = (--n)/CHAR_BIT;
1953*b30d1939SAndy Fiddaman 	register unsigned mask;
1954*b30d1939SAndy Fiddaman 	n -= j*CHAR_BIT;
1955*b30d1939SAndy Fiddaman 	mask = 1 << n;
1956*b30d1939SAndy Fiddaman 	job.freejobs[j]  &= ~mask;
1957*b30d1939SAndy Fiddaman }
1958*b30d1939SAndy Fiddaman 
job_sigmsg(int sig)1959*b30d1939SAndy Fiddaman static char *job_sigmsg(int sig)
1960*b30d1939SAndy Fiddaman {
1961*b30d1939SAndy Fiddaman 	static char signo[40];
1962*b30d1939SAndy Fiddaman #ifdef apollo
1963*b30d1939SAndy Fiddaman 	/*
1964*b30d1939SAndy Fiddaman 	 * This code handles the formatting for the apollo specific signal
1965*b30d1939SAndy Fiddaman 	 * SIGAPOLLO.
1966*b30d1939SAndy Fiddaman 	 */
1967*b30d1939SAndy Fiddaman 	extern char *apollo_error(void);
1968*b30d1939SAndy Fiddaman 
1969*b30d1939SAndy Fiddaman 	if ( sig == SIGAPOLLO )
1970*b30d1939SAndy Fiddaman 		return( apollo_error() );
1971*b30d1939SAndy Fiddaman #endif /* apollo */
1972*b30d1939SAndy Fiddaman 	if(sig<=shgd->sigmax && shgd->sigmsg[sig])
1973*b30d1939SAndy Fiddaman 		return(shgd->sigmsg[sig]);
1974*b30d1939SAndy Fiddaman #if defined(SIGRTMIN) && defined(SIGRTMAX)
1975*b30d1939SAndy Fiddaman 	if(sig>=sh.gd->sigruntime[SH_SIGRTMIN] && sig<=sh.gd->sigruntime[SH_SIGRTMAX])
1976*b30d1939SAndy Fiddaman 	{
1977*b30d1939SAndy Fiddaman 		static char sigrt[20];
1978*b30d1939SAndy Fiddaman 		if(sig>sh.gd->sigruntime[SH_SIGRTMIN]+(sh.gd->sigruntime[SH_SIGRTMAX]-sig<=sh.gd->sigruntime[SH_SIGRTMIN])/2)
1979*b30d1939SAndy Fiddaman 			sfsprintf(sigrt,sizeof(sigrt),"SIGRTMAX-%d",sh.gd->sigruntime[SH_SIGRTMAX]-sig);
1980*b30d1939SAndy Fiddaman 		else
1981*b30d1939SAndy Fiddaman 			sfsprintf(sigrt,sizeof(sigrt),"SIGRTMIN+%d",sig-sh.gd->sigruntime[SH_SIGRTMIN]);
1982*b30d1939SAndy Fiddaman 		return(sigrt);
1983*b30d1939SAndy Fiddaman 	}
1984*b30d1939SAndy Fiddaman #endif
1985*b30d1939SAndy Fiddaman 	sfsprintf(signo,sizeof(signo),sh_translate(e_signo),sig);
1986*b30d1939SAndy Fiddaman 	return(signo);
1987*b30d1939SAndy Fiddaman }
1988*b30d1939SAndy Fiddaman 
1989*b30d1939SAndy Fiddaman /*
1990*b30d1939SAndy Fiddaman  * see whether exit status has been saved and delete it
1991*b30d1939SAndy Fiddaman  * if pid==0, then oldest saved process is deleted
1992*b30d1939SAndy Fiddaman  * If pid is not found a -1 is returned.
1993*b30d1939SAndy Fiddaman  */
job_chksave(register pid_t pid,long env)1994*b30d1939SAndy Fiddaman static int job_chksave(register pid_t pid, long env)
1995*b30d1939SAndy Fiddaman {
1996*b30d1939SAndy Fiddaman 	register struct jobsave *jp = bck.list, *jpold=0;
1997*b30d1939SAndy Fiddaman 	register int r= -1;
1998*b30d1939SAndy Fiddaman 	register int count=bck.count;
1999*b30d1939SAndy Fiddaman 	struct back_save *bp= &bck;
2000*b30d1939SAndy Fiddaman again:
2001*b30d1939SAndy Fiddaman 	while(jp && count-->0)
2002*b30d1939SAndy Fiddaman 	{
2003*b30d1939SAndy Fiddaman 		if(jp->pid==pid)
2004*b30d1939SAndy Fiddaman 			break;
2005*b30d1939SAndy Fiddaman 		if(pid==0 && !jp->next)
2006*b30d1939SAndy Fiddaman 			break;
2007*b30d1939SAndy Fiddaman 		jpold = jp;
2008*b30d1939SAndy Fiddaman 		jp = jp->next;
2009*b30d1939SAndy Fiddaman 	}
2010*b30d1939SAndy Fiddaman 	if(!jp && pid && (bp=bp->prev))
2011*b30d1939SAndy Fiddaman 	{
2012*b30d1939SAndy Fiddaman 		count = bp->count;
2013*b30d1939SAndy Fiddaman 		jp = bp->list;
2014*b30d1939SAndy Fiddaman 		jpold = 0;
2015*b30d1939SAndy Fiddaman 		goto again;
2016*b30d1939SAndy Fiddaman 	}
2017*b30d1939SAndy Fiddaman 	if(jp && (env<0 || jp->env==env))
2018*b30d1939SAndy Fiddaman 	{
2019*b30d1939SAndy Fiddaman 		r = 0;
2020*b30d1939SAndy Fiddaman 		if(pid)
2021*b30d1939SAndy Fiddaman 			r = jp->exitval;
2022*b30d1939SAndy Fiddaman 		if(jpold)
2023*b30d1939SAndy Fiddaman 			jpold->next = jp->next;
2024*b30d1939SAndy Fiddaman 		else
2025*b30d1939SAndy Fiddaman 			bp->list = jp->next;
2026*b30d1939SAndy Fiddaman 		bp->count--;
2027*b30d1939SAndy Fiddaman 		if(njob_savelist < NJOB_SAVELIST)
2028*b30d1939SAndy Fiddaman 		{
2029*b30d1939SAndy Fiddaman 			njob_savelist++;
2030*b30d1939SAndy Fiddaman 			jp->next = job_savelist;
2031*b30d1939SAndy Fiddaman 			job_savelist = jp;
2032*b30d1939SAndy Fiddaman 		}
2033*b30d1939SAndy Fiddaman 		else
2034*b30d1939SAndy Fiddaman 			free((void*)jp);
2035*b30d1939SAndy Fiddaman 	}
2036*b30d1939SAndy Fiddaman 	return(r);
2037*b30d1939SAndy Fiddaman }
2038*b30d1939SAndy Fiddaman 
job_subsave(void)2039*b30d1939SAndy Fiddaman void *job_subsave(void)
2040*b30d1939SAndy Fiddaman {
2041*b30d1939SAndy Fiddaman 	struct back_save *bp = new_of(struct back_save,0);
2042*b30d1939SAndy Fiddaman 	job_lock();
2043*b30d1939SAndy Fiddaman 	*bp = bck;
2044*b30d1939SAndy Fiddaman 	bp->prev = bck.prev;
2045*b30d1939SAndy Fiddaman 	bck.count = 0;
2046*b30d1939SAndy Fiddaman 	bck.list = 0;
2047*b30d1939SAndy Fiddaman 	bck.prev = bp;
2048*b30d1939SAndy Fiddaman 	job_unlock();
2049*b30d1939SAndy Fiddaman 	return((void*)bp);
2050*b30d1939SAndy Fiddaman }
2051*b30d1939SAndy Fiddaman 
job_subrestore(void * ptr)2052*b30d1939SAndy Fiddaman void job_subrestore(void* ptr)
2053*b30d1939SAndy Fiddaman {
2054*b30d1939SAndy Fiddaman 	register struct jobsave *jp,*jpnext;
2055*b30d1939SAndy Fiddaman 	register struct back_save *bp = (struct back_save*)ptr;
2056*b30d1939SAndy Fiddaman 	register struct process *pw, *px, *pwnext;
2057*b30d1939SAndy Fiddaman 	struct jobsave *end=NULL;
2058*b30d1939SAndy Fiddaman 	int i=0;
2059*b30d1939SAndy Fiddaman 	job_lock();
2060*b30d1939SAndy Fiddaman 	for(jp=bck.list; jp; jp=jpnext,i++)
2061*b30d1939SAndy Fiddaman 	{
2062*b30d1939SAndy Fiddaman 		if (!(jpnext=jp->next) || jp==jpnext)
2063*b30d1939SAndy Fiddaman 			end = jp;
2064*b30d1939SAndy Fiddaman 		if(i>=shgd->lim.child_max)
2065*b30d1939SAndy Fiddaman 			break;
2066*b30d1939SAndy Fiddaman 	}
2067*b30d1939SAndy Fiddaman 	if(end)
2068*b30d1939SAndy Fiddaman 		end->next = bp->list;
2069*b30d1939SAndy Fiddaman 	else
2070*b30d1939SAndy Fiddaman 		bck.list = bp->list;
2071*b30d1939SAndy Fiddaman 	bck.count += bp->count;
2072*b30d1939SAndy Fiddaman 	bck.prev = bp->prev;
2073*b30d1939SAndy Fiddaman 	while(bck.count > shgd->lim.child_max)
2074*b30d1939SAndy Fiddaman 		job_chksave(0,-1);
2075*b30d1939SAndy Fiddaman 	for(pw=job.pwlist; pw; pw=pwnext)
2076*b30d1939SAndy Fiddaman 	{
2077*b30d1939SAndy Fiddaman 		pwnext = pw->p_nxtjob;
2078*b30d1939SAndy Fiddaman 		if(pw->p_env != sh.curenv || pw->p_pid==sh.pipepid)
2079*b30d1939SAndy Fiddaman 			continue;
2080*b30d1939SAndy Fiddaman 		for(px=pw; px; px=px->p_nxtproc)
2081*b30d1939SAndy Fiddaman 			px->p_flag |= P_DONE;
2082*b30d1939SAndy Fiddaman 		job_unpost(pw,0);
2083*b30d1939SAndy Fiddaman 	}
2084*b30d1939SAndy Fiddaman 
2085*b30d1939SAndy Fiddaman 	free((void*)bp);
2086*b30d1939SAndy Fiddaman 	job_unlock();
2087*b30d1939SAndy Fiddaman }
2088*b30d1939SAndy Fiddaman 
sh_waitsafe(void)2089*b30d1939SAndy Fiddaman int sh_waitsafe(void)
2090*b30d1939SAndy Fiddaman {
2091*b30d1939SAndy Fiddaman 	return(job.waitsafe);
2092*b30d1939SAndy Fiddaman }
2093*b30d1939SAndy Fiddaman 
job_fork(pid_t parent)2094*b30d1939SAndy Fiddaman void job_fork(pid_t parent)
2095*b30d1939SAndy Fiddaman {
2096*b30d1939SAndy Fiddaman #ifdef DEBUG
2097*b30d1939SAndy Fiddaman 	sfprintf(sfstderr,"ksh: job line %4d: fork pid=%d critical=%d parent=%d\n",__LINE__,getpid(),job.in_critical,parent);
2098*b30d1939SAndy Fiddaman #endif /* DEBUG */
2099*b30d1939SAndy Fiddaman 	switch (parent)
2100*b30d1939SAndy Fiddaman 	{
2101*b30d1939SAndy Fiddaman 	case -1:
2102*b30d1939SAndy Fiddaman 		job_lock();
2103*b30d1939SAndy Fiddaman 		jobfork++;
2104*b30d1939SAndy Fiddaman 		break;
2105*b30d1939SAndy Fiddaman 	case 0:
2106*b30d1939SAndy Fiddaman 		jobfork=0;
2107*b30d1939SAndy Fiddaman 		job_unlock();
2108*b30d1939SAndy Fiddaman 		job.waitsafe = 0;
2109*b30d1939SAndy Fiddaman 		job.in_critical = 0;
2110*b30d1939SAndy Fiddaman 		break;
2111*b30d1939SAndy Fiddaman 	default:
2112*b30d1939SAndy Fiddaman 		job_chksave(parent,-1);
2113*b30d1939SAndy Fiddaman 		jobfork=0;
2114*b30d1939SAndy Fiddaman 		job_unlock();
2115*b30d1939SAndy Fiddaman 		break;
2116*b30d1939SAndy Fiddaman 	}
2117*b30d1939SAndy Fiddaman }
2118*b30d1939SAndy Fiddaman 
2119