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