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