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