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