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