xref: /csrg-svn/local/toolchest/ksh/sh/jobs.c (revision 35148)
1*35148Smarc /*
2*35148Smarc 
3*35148Smarc  *      Copyright (c) 1984, 1985, 1986 AT&T
4*35148Smarc  *      All Rights Reserved
5*35148Smarc 
6*35148Smarc  *      THIS IS UNPUBLISHED PROPRIETARY SOURCE
7*35148Smarc  *      CODE OF AT&T.
8*35148Smarc  *      The copyright notice above does not
9*35148Smarc  *      evidence any actual or intended
10*35148Smarc  *      publication of such source code.
11*35148Smarc 
12*35148Smarc  */
13*35148Smarc /* @(#)jobs.c	1.1 */
14*35148Smarc 
15*35148Smarc /*
16*35148Smarc  *  Job control for UNIX Shell
17*35148Smarc  *
18*35148Smarc  *   David Korn
19*35148Smarc  *   AT&T Bell Laboratories
20*35148Smarc  *   Room 5D-112
21*35148Smarc  *   Murray Hill, N. J. 07974
22*35148Smarc  *   Tel. x7975
23*35148Smarc  *
24*35148Smarc  *  Written October, 1982
25*35148Smarc  */
26*35148Smarc 
27*35148Smarc 
28*35148Smarc #include	<errno.h>
29*35148Smarc 
30*35148Smarc #ifdef BSD
31*35148Smarc # ifdef BSD_4_2
32*35148Smarc #include	<sys/wait.h>
33*35148Smarc # else
34*35148Smarc #include	<wait.h>
35*35148Smarc # endif /* BSD_4_2 */
36*35148Smarc #endif	/* BSD */
37*35148Smarc 
38*35148Smarc #ifdef SXT
39*35148Smarc #define		SIGSTOP	20
40*35148Smarc #define		SIGSTIN	21
41*35148Smarc #include	<sys/types.h>
42*35148Smarc #include	<sys/tty.h>
43*35148Smarc #include	<sys/sxt.h>
44*35148Smarc #include	<sys/stat.h>
45*35148Smarc #endif	/* SXT */
46*35148Smarc 
47*35148Smarc #include	"defs.h"
48*35148Smarc #include	"flags.h"
49*35148Smarc #include	"shtype.h"
50*35148Smarc #include	"jobs.h"
51*35148Smarc #include	"brkincr.h"
52*35148Smarc #include	"io.h"
53*35148Smarc #include	"history.h"
54*35148Smarc 
55*35148Smarc #ifdef SXT
56*35148Smarc #undef input
57*35148Smarc static status_update();
58*35148Smarc static int open_chan();
59*35148Smarc static int fd_chan = -1;
60*35148Smarc static char tinybuf;
61*35148Smarc #endif	/* SXT */
62*35148Smarc 
63*35148Smarc #define LOBYTE	0377
64*35148Smarc #define MAXMSG	25
65*35148Smarc 
66*35148Smarc void	await();
67*35148Smarc void	postclr();
68*35148Smarc 
69*35148Smarc extern void	fault();
70*35148Smarc extern long	hist_list();
71*35148Smarc extern long	hist_position();
72*35148Smarc extern char	*itos();
73*35148Smarc extern char	*malloc();
74*35148Smarc extern void	failed();
75*35148Smarc extern void	free();
76*35148Smarc extern void	p_str();
77*35148Smarc extern void	p_prp();
78*35148Smarc extern void	p_num();
79*35148Smarc extern void	p_sub();
80*35148Smarc extern void	p_nchr();
81*35148Smarc extern void	p_flush();
82*35148Smarc extern void	p_setout();
83*35148Smarc 
84*35148Smarc static int	set_ttygrp();
85*35148Smarc static int	set_job();
86*35148Smarc static int	reset_ttygrp();
87*35148Smarc static struct process *next_proc();
88*35148Smarc static struct process *jobbyname();
89*35148Smarc static struct process *job_bynum();
90*35148Smarc static struct process *job_bypid();
91*35148Smarc static struct process *job_post();
92*35148Smarc static struct process *unpost();
93*35148Smarc static struct process *pgrp_jobs();
94*35148Smarc static int get_job();
95*35148Smarc static int match_jobname();
96*35148Smarc static int unstop();
97*35148Smarc static void free_job();
98*35148Smarc static void pw_unlink();
99*35148Smarc static struct process *freelist;
100*35148Smarc #define	numrun	jobstat.p_numrun	/* number of running jobs */
101*35148Smarc #define	numpost	jobstat.p_numpost	/* number of posted jobs */
102*35148Smarc #define	pwlist	jobstat.p_pwlist
103*35148Smarc #define freejobs jobstat.p_freejobs	/* free job numbers */
104*35148Smarc static long pr_jobname();
105*35148Smarc 
106*35148Smarc #ifdef FIOLOOKLD
107*35148Smarc #define version8	1
108*35148Smarc extern int tty_ld, ntty_ld;
109*35148Smarc #define OTTYDISC	tty_ld
110*35148Smarc #define NTTYDISC	ntty_ld
111*35148Smarc #endif	/* FIOLOOKLD */
112*35148Smarc 
113*35148Smarc 
114*35148Smarc static int savepgrp;
115*35148Smarc static int savetgrp;
116*35148Smarc static BOOL old_driver;
117*35148Smarc static BOOL beenhere;
118*35148Smarc 
119*35148Smarc #ifdef BSD
120*35148Smarc static struct sgttyb my_stty;		/* terminal state for shell */
121*35148Smarc #else
122*35148Smarc static struct termio my_stty;		/* terminal state for shell */
123*35148Smarc #endif	/* BSD */
124*35148Smarc 
125*35148Smarc #ifdef BSD
126*35148Smarc /*
127*35148Smarc  * initialize job control
128*35148Smarc  * if lflag is set the switching driver message will not print
129*35148Smarc  */
130*35148Smarc 
init_jobs(lflag)131*35148Smarc int init_jobs(lflag)
132*35148Smarc {
133*35148Smarc 	int ldisc;
134*35148Smarc 	register int ntry = 0;
135*35148Smarc 	register int pid;
136*35148Smarc 	jobstat.mypid = pid = getpid();
137*35148Smarc 	savepgrp = getpgrp(pid);
138*35148Smarc # ifdef version8
139*35148Smarc 	if((ldisc = ioctl (2, FIOLOOKLD, 0)) <0)
140*35148Smarc # else
141*35148Smarc 	if(ioctl(2,TIOCGETD,&ldisc) !=0)
142*35148Smarc # endif /* version8 */
143*35148Smarc 		return(-1);
144*35148Smarc 	if(ldisc!=NTTYDISC && ldisc!=OTTYDISC)
145*35148Smarc 	{
146*35148Smarc 		/* no job control when running with MPX */
147*35148Smarc # ifdef VSH
148*35148Smarc 		on_option(VIRAW);
149*35148Smarc # endif /* VSH */
150*35148Smarc 		return(-1);
151*35148Smarc 	}
152*35148Smarc retry:
153*35148Smarc 	signal(SIGTTOU,SIG_IGN);
154*35148Smarc 	if(ioctl(2,TIOCGPGRP,&savetgrp) !=0)
155*35148Smarc 	{
156*35148Smarc 		fputs(j_not_tty,output);
157*35148Smarc 		return(-1);
158*35148Smarc 	}
159*35148Smarc 	/* This shell must be in foreground to change state */
160*35148Smarc 	if(savetgrp != savepgrp)
161*35148Smarc 	{
162*35148Smarc 		signal(SIGTTOU,SIG_DFL);
163*35148Smarc 		kill(pid,SIGTTOU);
164*35148Smarc 		/* wait for continue and try again */
165*35148Smarc 		if(ntry++ > 100)
166*35148Smarc 		{
167*35148Smarc 			fputs(j_no_start,output);
168*35148Smarc 			return(-1);
169*35148Smarc 		}
170*35148Smarc 		goto retry;
171*35148Smarc 	}
172*35148Smarc 	if(ldisc == OTTYDISC)
173*35148Smarc 	{
174*35148Smarc 		ldisc = NTTYDISC;
175*35148Smarc # ifdef version8
176*35148Smarc 		ioctl(2,TIOCGETP,&my_stty);
177*35148Smarc 		if (ioctl(2, FIOPOPLD, 0) < 0)
178*35148Smarc 			return(-1);
179*35148Smarc 		if (ioctl(2, FIOPUSHLD, &ldisc, 0) < 0)
180*35148Smarc 		{
181*35148Smarc 			ldisc = OTTYDISC;
182*35148Smarc 			 ioctl(2, FIOPUSHLD, &ldisc, 0);
183*35148Smarc 			return(-1);
184*35148Smarc 		}
185*35148Smarc 		ioctl(2,TIOCSETN,&my_stty);
186*35148Smarc # else
187*35148Smarc 		if(ioctl(2,TIOCSETD,&ldisc) !=0)
188*35148Smarc 			return(-1);
189*35148Smarc # endif /* version8 */
190*35148Smarc 		if(lflag==0)
191*35148Smarc 		{
192*35148Smarc 			fputs(j_newtty,output);
193*35148Smarc 			old_driver++;
194*35148Smarc 		}
195*35148Smarc 	}
196*35148Smarc 	on_option(MONITOR);
197*35148Smarc 	signal(SIGCHLD,fault);
198*35148Smarc 	signal(SIGTSTP,SIG_IGN);
199*35148Smarc 	signal(SIGTTIN,SIG_IGN);
200*35148Smarc 	setpgrp(pid,pid);
201*35148Smarc 	set_ttygrp(pid);
202*35148Smarc 	return(0);
203*35148Smarc }
204*35148Smarc 
205*35148Smarc 
206*35148Smarc /*
207*35148Smarc  * see if there are any stopped jobs
208*35148Smarc  * restore tty driver and pgrp
209*35148Smarc  */
210*35148Smarc 
close_jobs()211*35148Smarc int close_jobs()
212*35148Smarc {
213*35148Smarc 	register struct process *pw = pwlist;
214*35148Smarc 	register int count = 0;
215*35148Smarc 	int ldisc;
216*35148Smarc 	if((states&MONITOR)==0)
217*35148Smarc 		return(0);
218*35148Smarc 	for(;pw;pw=pw->p_next)
219*35148Smarc 	{
220*35148Smarc 		if((pw->p_flag&P_STOPPED)==0)
221*35148Smarc 			continue;
222*35148Smarc 		if(beenhere)
223*35148Smarc 			killpg(pw->p_pgrp,SIGTERM);
224*35148Smarc 		count++;
225*35148Smarc 	}
226*35148Smarc 	if(beenhere++ == 0 && pwlist)
227*35148Smarc 	{
228*35148Smarc 		if(count)
229*35148Smarc 		{
230*35148Smarc 			fputs(j_terminate,output);
231*35148Smarc 			return(-1);
232*35148Smarc 		}
233*35148Smarc 		else if(login_sh)
234*35148Smarc 		{
235*35148Smarc 			fputs(j_running,output);
236*35148Smarc 			return(-1);
237*35148Smarc 		}
238*35148Smarc 	}
239*35148Smarc 	set_ttygrp(savepgrp);
240*35148Smarc 	if(old_driver)
241*35148Smarc 	{
242*35148Smarc 		/* restore old line discipline */
243*35148Smarc 		ldisc = OTTYDISC;
244*35148Smarc # ifdef version8
245*35148Smarc 		ioctl(2,TIOCGETP,&my_stty);
246*35148Smarc 		if (ioctl(2, FIOPOPLD, 0) < 0)
247*35148Smarc 			return(0);
248*35148Smarc 		if (ioctl(2, FIOPUSHLD, &ldisc, 0) < 0)
249*35148Smarc 		{
250*35148Smarc 			ldisc = NTTYDISC;
251*35148Smarc 			ioctl(2, FIOPUSHLD, &ldisc, 0);
252*35148Smarc 			return(0);
253*35148Smarc 		}
254*35148Smarc 		ioctl(2,TIOCSETN,&my_stty);
255*35148Smarc # else
256*35148Smarc 		if(ioctl(2,TIOCSETD,&ldisc) !=0)
257*35148Smarc 			return(0);
258*35148Smarc # endif /* version8 */
259*35148Smarc 		fputs(j_oldtty,output);
260*35148Smarc 	}
261*35148Smarc 	return(0);
262*35148Smarc }
263*35148Smarc 
264*35148Smarc /*
265*35148Smarc  * Set the ttygroup id to pid
266*35148Smarc  */
267*35148Smarc 
set_ttygrp(pid)268*35148Smarc static int set_ttygrp(pid)
269*35148Smarc {
270*35148Smarc 	if(ioctl(2,TIOCSPGRP,&pid) !=0)
271*35148Smarc 		return(-1);
272*35148Smarc 	return(0);
273*35148Smarc }
274*35148Smarc 
275*35148Smarc /*
276*35148Smarc  * Set the ttygroup id to a previously running job
277*35148Smarc  */
278*35148Smarc #else
279*35148Smarc # ifdef SXT
280*35148Smarc static char sxt[] = "/dev/sxt/000";
281*35148Smarc static struct sxtblock status1,status2;
282*35148Smarc 
init_jobs(lflag)283*35148Smarc int init_jobs(lflag)
284*35148Smarc {
285*35148Smarc 	register int pid;
286*35148Smarc 	register int dev;
287*35148Smarc 	struct stat statbuf;
288*35148Smarc 	jobstat.mypid = pid = getpid();
289*35148Smarc 	savepgrp = getpgrp(pid);
290*35148Smarc 	if(ioctl(2,SXTIOCSTAT,&status2) < 0)
291*35148Smarc 		return(-1);
292*35148Smarc 	if(ioctl(2,TCGETA,&my_stty) < 0)
293*35148Smarc 		return(-1);
294*35148Smarc 	if(fstat(2,&statbuf) < 0)
295*35148Smarc 		return(-1);
296*35148Smarc 	dev = statbuf.st_rdev&0xff;
297*35148Smarc 	/* must be channel 0 */
298*35148Smarc 	if(dev&07)
299*35148Smarc 		return(-1);
300*35148Smarc 	dev >>= 3;
301*35148Smarc 	sxt[10] = '0' + (dev%10);
302*35148Smarc 	sxt[9] = '0' + dev/10;
303*35148Smarc 	my_stty.c_cc[VSWTCH] = CSWTCH;
304*35148Smarc 	if(ioctl(2,TCSETAF,&my_stty) < 0)
305*35148Smarc 		return(-1);
306*35148Smarc 	setpgrp(pid,pid);
307*35148Smarc 	jobstat.maxjob = MAXPCHAN;
308*35148Smarc 	on_option(MONITOR);
309*35148Smarc 	return(0);
310*35148Smarc }
311*35148Smarc #endif	/* SXT */
312*35148Smarc 
close_jobs()313*35148Smarc int close_jobs()
314*35148Smarc {
315*35148Smarc 	register struct process *pw = pwlist;
316*35148Smarc 	register int count = 0;
317*35148Smarc 	if((states&MONITOR)==0)
318*35148Smarc 		return(0);
319*35148Smarc # ifdef SXT
320*35148Smarc 	for(;pw;pw=pw->p_next)
321*35148Smarc 	{
322*35148Smarc 		if((pw->p_flag&P_STOPPED)==0)
323*35148Smarc 			continue;
324*35148Smarc 		if(beenhere)
325*35148Smarc 			kill(-pw->p_pgrp,SIGTERM);
326*35148Smarc 		count++;
327*35148Smarc 	}
328*35148Smarc # endif /* SXT */
329*35148Smarc 	if(beenhere++ == 0 && pwlist && login_sh)
330*35148Smarc # ifdef SXT
331*35148Smarc 	{
332*35148Smarc 		if(count)
333*35148Smarc 		{
334*35148Smarc 			fputs(j_terminate,output);
335*35148Smarc 			return(-1);
336*35148Smarc 		}
337*35148Smarc 		if(login_sh || jobstat.maxjob)
338*35148Smarc # endif /* SXT */
339*35148Smarc 		{
340*35148Smarc 			fputs(j_running,output);
341*35148Smarc 			return(-1);
342*35148Smarc 		}
343*35148Smarc # ifdef SXT
344*35148Smarc 	}
345*35148Smarc 	if(jobstat.maxjob)
346*35148Smarc 		kill_all();
347*35148Smarc # endif /* SXT */
348*35148Smarc 	return(0);
349*35148Smarc }
350*35148Smarc 
351*35148Smarc #endif	/* BSD */
352*35148Smarc 
set_job(pw)353*35148Smarc static int set_job(pw)
354*35148Smarc register struct process *pw;
355*35148Smarc {
356*35148Smarc 	/* save current terminal state */
357*35148Smarc #ifdef BSD
358*35148Smarc 	ioctl(2,TIOCGETP,&my_stty);
359*35148Smarc #else
360*35148Smarc 	ioctl(2,TCGETA,&my_stty);
361*35148Smarc #endif	/* BSD */
362*35148Smarc #ifdef SXT
363*35148Smarc 	/* make sure child has opened channel */
364*35148Smarc 	if(jobstat.pipe[0] > 0)
365*35148Smarc 	{
366*35148Smarc 		read(jobstat.pipe[0],&tinybuf,1);
367*35148Smarc 		close(jobstat.pipe[0]);
368*35148Smarc 		jobstat.pipe[0] = 0;
369*35148Smarc 	}
370*35148Smarc 	if(pw->p_job < jobstat.maxjob)
371*35148Smarc 		if(ioctl(2,SXTIOCSWTCH,pw->p_job)!=0)
372*35148Smarc 		{
373*35148Smarc 			return(-1);
374*35148Smarc 		}
375*35148Smarc #endif	/* SXT */
376*35148Smarc 	if(pw->p_flag&P_STTY)
377*35148Smarc 	{
378*35148Smarc 		/* restore terminal state for job */
379*35148Smarc #ifdef BSD
380*35148Smarc 		ioctl(2,TIOCSETN,&pw->p_stty);
381*35148Smarc #else
382*35148Smarc 		ioctl(2,TCSETAF,&pw->p_stty);
383*35148Smarc #endif	/* BSD */
384*35148Smarc 	}
385*35148Smarc #ifdef BSD
386*35148Smarc 	if(ioctl(2,TIOCSPGRP,&pw->p_pgrp) !=0)
387*35148Smarc 		return(-1);
388*35148Smarc #endif	/* BSD */
389*35148Smarc 	return(0);
390*35148Smarc }
391*35148Smarc 
reset_ttygrp(pw,flag)392*35148Smarc static int	reset_ttygrp(pw,flag)
393*35148Smarc register struct process *pw;
394*35148Smarc {
395*35148Smarc 	/* save the terminal state for current job */
396*35148Smarc #ifdef BSD
397*35148Smarc 	if(ioctl(2,TIOCSPGRP,&jobstat.mypid) !=0)
398*35148Smarc 	{
399*35148Smarc 		return(-1);
400*35148Smarc 	}
401*35148Smarc #endif	/* BSD */
402*35148Smarc #ifdef SXT
403*35148Smarc 	if(pw && pw->p_job < jobstat.maxjob)
404*35148Smarc 	{
405*35148Smarc 		/* save the state of terminated process */
406*35148Smarc 		if(flag==0 && fd_chan>=0)
407*35148Smarc 		{
408*35148Smarc 			if(ioctl(fd_chan,TCGETA,&pw->p_stty)==0)
409*35148Smarc 			{
410*35148Smarc 				my_stty = pw->p_stty;
411*35148Smarc 				/* for timing problem */
412*35148Smarc 				ioctl(fd_chan,TCSETAW,&my_stty);
413*35148Smarc 			}
414*35148Smarc 		}
415*35148Smarc 		close(fd_chan);
416*35148Smarc 		fd_chan = -1;
417*35148Smarc 		/* grab control in channel 0 */
418*35148Smarc 		ioctl(2,TCSETAW,&my_stty);
419*35148Smarc 		if(ioctl(2,SXTIOCSWTCH,0)!=0)
420*35148Smarc 		{
421*35148Smarc 			return(-1);
422*35148Smarc 		}
423*35148Smarc 		if(flag==0)
424*35148Smarc 			ioctl(2,TCSETAW,&my_stty);
425*35148Smarc 		beenhere = 0;
426*35148Smarc 		return(0);
427*35148Smarc 	}
428*35148Smarc #endif	/* SXT */
429*35148Smarc 	if(pw && flag)
430*35148Smarc 	{
431*35148Smarc #ifdef BSD
432*35148Smarc 		if(ioctl(2,TIOCGETP,&pw->p_stty) == 0)
433*35148Smarc #else
434*35148Smarc 		if(ioctl(2,TCGETA,&pw->p_stty) == 0)
435*35148Smarc #endif	/* BSD */
436*35148Smarc 			pw->p_flag |= P_STTY;
437*35148Smarc 		/* restore terminal state for job */
438*35148Smarc #ifdef BSD
439*35148Smarc 		ioctl(2,TIOCSETN,&my_stty);
440*35148Smarc #else
441*35148Smarc 		ioctl(2,TCSETAF,&my_stty);
442*35148Smarc #endif	/* BSD */
443*35148Smarc 	}
444*35148Smarc 	beenhere = 0;
445*35148Smarc 	return(0);
446*35148Smarc }
447*35148Smarc 
448*35148Smarc #if BSD || SXT
449*35148Smarc 
450*35148Smarc /*
451*35148Smarc  * move job to foreground if bgflag == 0
452*35148Smarc  * move job to background if bgflag != 0
453*35148Smarc  */
454*35148Smarc 
switch_jobs(ajob,bgflag)455*35148Smarc switch_jobs(ajob,bgflag)
456*35148Smarc register char *ajob;
457*35148Smarc {
458*35148Smarc 	register struct process *pw=NULL;
459*35148Smarc 	register int pgrp;
460*35148Smarc # ifdef SXT
461*35148Smarc 	if(jobstat.maxjob==0)
462*35148Smarc 		return(NULL);
463*35148Smarc # endif /* SXT */
464*35148Smarc 	if(*ajob)
465*35148Smarc 		pw = pgrp_jobs(ajob);
466*35148Smarc 	else if(pwlist)
467*35148Smarc 		pw = job_bynum((int)pwlist->p_job);
468*35148Smarc 	if(pw)
469*35148Smarc 	{
470*35148Smarc 		if(bgflag)
471*35148Smarc 		{
472*35148Smarc 			pgrp = pw->p_pgrp;
473*35148Smarc 			if(pw->p_flag&P_STOPPED)
474*35148Smarc 			{
475*35148Smarc 				p_sub((int)pw->p_job,'\t');
476*35148Smarc 				pr_jobname(pw,'&',0L);
477*35148Smarc 				fputs(j_amp,output);
478*35148Smarc 				unstop(pgrp);
479*35148Smarc 			}
480*35148Smarc 		}
481*35148Smarc 		else
482*35148Smarc 		{
483*35148Smarc 			pw_unlink(pw);
484*35148Smarc 			pw->p_next = pwlist;
485*35148Smarc 			pwlist = pw;
486*35148Smarc 			pr_jobname(pw,'&',0L);
487*35148Smarc 			newline();
488*35148Smarc 			await(pw->p_pid,3);
489*35148Smarc 		}
490*35148Smarc 	}
491*35148Smarc 	return(pw!=NULL);
492*35148Smarc }
493*35148Smarc 
494*35148Smarc /*
495*35148Smarc  * list the current jobs
496*35148Smarc  * flag L_FLAG for long listing
497*35148Smarc  * flag N_FLAG for list only jobs marked for notification
498*35148Smarc  */
499*35148Smarc #endif	/* BSD */
500*35148Smarc 
list_jobs(flag)501*35148Smarc list_jobs(flag)
502*35148Smarc int flag;
503*35148Smarc {
504*35148Smarc 	register struct process *pw;
505*35148Smarc 	register struct process *px;
506*35148Smarc 	register int m;
507*35148Smarc 	register struct process *py;
508*35148Smarc 	int  n;
509*35148Smarc 	long offset;
510*35148Smarc 	int jobm = 0;
511*35148Smarc 	register char *msg;
512*35148Smarc 	int msize;
513*35148Smarc 	if(pwlist==NULL)
514*35148Smarc 		return;
515*35148Smarc 	await(0,2);
516*35148Smarc 	p_setout(standout);
517*35148Smarc 	/* get job number corresponding to '-' */
518*35148Smarc 	if(pw=pgrp_jobs("%-"))
519*35148Smarc 		jobm = pw->p_job;
520*35148Smarc 	for(pw=pwlist;pw;pw=py)
521*35148Smarc 	{
522*35148Smarc 		py = pw->p_next;
523*35148Smarc 		if(pw->p_flag&P_PIPEJOB)
524*35148Smarc 			continue;
525*35148Smarc 		if((flag&N_FLAG) && (pw->p_flag&P_NOTIFY)==0)
526*35148Smarc 			continue;
527*35148Smarc 		n = pw->p_job;
528*35148Smarc 		p_sub(n,' ');
529*35148Smarc 		m = ' ';
530*35148Smarc 		if(pw->p_job==pwlist->p_job)
531*35148Smarc 			m = '+';
532*35148Smarc 		else if(pw->p_job==jobm)
533*35148Smarc 		{
534*35148Smarc 			m = '-';
535*35148Smarc 			jobm = 0;
536*35148Smarc 		}
537*35148Smarc 		putc(m,output);
538*35148Smarc 		putc(' ',output);
539*35148Smarc 		offset = 0;
540*35148Smarc 		if(flag&L_FLAG)
541*35148Smarc 			px = next_proc(pwlist,(int)pw->p_job);
542*35148Smarc 		else
543*35148Smarc 			px = pw;
544*35148Smarc 		do
545*35148Smarc 		{
546*35148Smarc 			unsigned xitval = 0;
547*35148Smarc 			if(flag&L_FLAG)
548*35148Smarc 				p_num(px->p_pid,'\t');
549*35148Smarc 			if(px->p_sig&0177)
550*35148Smarc 				msg = sysmsg[px->p_sig&0177];
551*35148Smarc 			else if(px->p_flag&P_NOTIFY)
552*35148Smarc 			{
553*35148Smarc 				msg = j_Done;
554*35148Smarc 				xitval = px->p_sig>>8;
555*35148Smarc 			}
556*35148Smarc 			else
557*35148Smarc 				msg = j_Running;
558*35148Smarc 			fputs(msg,output);
559*35148Smarc 			msize = strlen(msg);
560*35148Smarc 			if(xitval)
561*35148Smarc 			{
562*35148Smarc 				putc('(',output);
563*35148Smarc 				p_num((int)xitval,')');
564*35148Smarc 				msize += (3+(xitval>10)+(xitval>100));
565*35148Smarc 			}
566*35148Smarc 			if(px->p_flag&P_COREDUMP)
567*35148Smarc 			{
568*35148Smarc 				fputs(j_coredump,output);
569*35148Smarc 				msize += strlen(j_coredump);
570*35148Smarc 			}
571*35148Smarc 			p_nchr(SP,MAXMSG-msize);
572*35148Smarc 			if(flag&L_FLAG)
573*35148Smarc 				px = next_proc(px->p_next,(int)pw->p_job);
574*35148Smarc 			else
575*35148Smarc 				px = NULL;
576*35148Smarc 			offset = pr_jobname(pw,(px?'|':0),offset);
577*35148Smarc 			if(flag&L_FLAG)
578*35148Smarc 			{
579*35148Smarc 				if(px)
580*35148Smarc 					fputs(j_space,output);
581*35148Smarc 				else if(pw->p_pid == cpid)
582*35148Smarc 					fputs(j_cpid,output);
583*35148Smarc 			}
584*35148Smarc 		}
585*35148Smarc 		while(px);
586*35148Smarc 		if(pw->p_flag&P_STOPPED)
587*35148Smarc 			pw->p_flag &= ~P_NOTIFY;
588*35148Smarc 		else if(pw->p_flag&P_NOTIFY)
589*35148Smarc 		{
590*35148Smarc 			unpost(pw);
591*35148Smarc 			if(jobm && (px=pgrp_jobs("%-")))
592*35148Smarc 				jobm = px->p_job;
593*35148Smarc 		}
594*35148Smarc 	}
595*35148Smarc }
596*35148Smarc 
597*35148Smarc /*
598*35148Smarc  * return the pointer of next process with given job number after slot px
599*35148Smarc  */
600*35148Smarc 
next_proc(pw,job)601*35148Smarc static struct process * next_proc(pw,job)
602*35148Smarc register struct process *pw;
603*35148Smarc register int job;
604*35148Smarc {
605*35148Smarc 	for(;pw;pw=pw->p_next)
606*35148Smarc 	{
607*35148Smarc 		if(pw->p_job == job)
608*35148Smarc 			return(pw);
609*35148Smarc 	}
610*35148Smarc 	return(NULL);
611*35148Smarc }
612*35148Smarc 
613*35148Smarc /*
614*35148Smarc  * print the command
615*35148Smarc  * Stop the output if character <ch> encountered
616*35148Smarc  */
617*35148Smarc 
pr_jobname(pw,ch,offset)618*35148Smarc static long pr_jobname(pw,ch,offset)
619*35148Smarc register struct process *pw;
620*35148Smarc register long offset;
621*35148Smarc int ch;
622*35148Smarc {
623*35148Smarc 	if(fc_fix)
624*35148Smarc 	{
625*35148Smarc 		offset = hist_list(pw->p_name+offset,ch,";");
626*35148Smarc 		offset -= pw->p_name;
627*35148Smarc 	}
628*35148Smarc 	return(++offset);
629*35148Smarc }
630*35148Smarc 
631*35148Smarc /*
632*35148Smarc  * get the process group given the job number
633*35148Smarc  * This routine returns the process group number or -1
634*35148Smarc  */
635*35148Smarc 
pgrp_jobs(ajob)636*35148Smarc static struct process *pgrp_jobs(ajob)
637*35148Smarc register char *ajob;
638*35148Smarc {
639*35148Smarc 	register struct process *pw;
640*35148Smarc 	register int c;
641*35148Smarc 	if(*ajob++ != '%' || pwlist==NULL)
642*35148Smarc 		return(NULL);
643*35148Smarc 	c = *ajob;
644*35148Smarc 	if(isdigit(c))
645*35148Smarc 		pw = job_bynum(atoi(ajob));
646*35148Smarc 	else if(c=='+' || c=='%')
647*35148Smarc 		pw = job_bynum((int)pwlist->p_job);
648*35148Smarc 	else if(c=='-')
649*35148Smarc 	{
650*35148Smarc 		/* find the second jobnumber on the list */
651*35148Smarc 		for(pw=pwlist->p_next;pw && pw->p_job==pwlist->p_job;pw=pw->p_next);
652*35148Smarc 		if(pw==NULL)
653*35148Smarc 			return(pw);
654*35148Smarc 		pw = job_bynum((int)pw->p_job);
655*35148Smarc 	}
656*35148Smarc 	else
657*35148Smarc 		pw = jobbyname(ajob);
658*35148Smarc 	if(pw && pw->p_flag)
659*35148Smarc 		return(pw);
660*35148Smarc 	return(NULL);
661*35148Smarc }
662*35148Smarc 
663*35148Smarc /*
664*35148Smarc  * send a hang-up signal to each of the jobs
665*35148Smarc  */
kill_all()666*35148Smarc int kill_all()
667*35148Smarc {
668*35148Smarc 	register struct process *pw = pwlist;
669*35148Smarc 	for(;pw;pw=pw->p_next)
670*35148Smarc 	{
671*35148Smarc 		if(pw->p_pgrp == pw->p_pid)
672*35148Smarc 		{
673*35148Smarc #ifdef BSD
674*35148Smarc 			unstop(pw->p_pgrp);
675*35148Smarc 			killpg(pw->p_pgrp,SIGHUP);
676*35148Smarc #else
677*35148Smarc 			kill(-pw->p_pgrp,SIGHUP);
678*35148Smarc #endif	/* BSD */
679*35148Smarc 		}
680*35148Smarc 	}
681*35148Smarc }
682*35148Smarc 
683*35148Smarc /*
684*35148Smarc  * Kill a job or process
685*35148Smarc  */
686*35148Smarc 
job_kill(job,sig)687*35148Smarc int job_kill(job,sig)
688*35148Smarc register char *job;
689*35148Smarc int sig;
690*35148Smarc {
691*35148Smarc 	register char *rjob = job;
692*35148Smarc 	register struct process *pw;
693*35148Smarc 	register int pid;
694*35148Smarc 	register int r;
695*35148Smarc 	char *msg;
696*35148Smarc 	if(*rjob == '%')
697*35148Smarc 	{
698*35148Smarc 		if(pw=pgrp_jobs(rjob))
699*35148Smarc 		{
700*35148Smarc #ifdef BSD
701*35148Smarc 			r = unstop(pw->p_pgrp);
702*35148Smarc 			if(sig!=SIGCONT || r < 0)
703*35148Smarc 				r = killpg(pw->p_pgrp,sig);
704*35148Smarc #else
705*35148Smarc 			pid = pw->p_pgrp;
706*35148Smarc 			if(states&MONITOR)
707*35148Smarc 				pid = -pid;
708*35148Smarc 			r = kill(pid,sig);
709*35148Smarc #endif	/* BSD */
710*35148Smarc 		}
711*35148Smarc 		else
712*35148Smarc 		{
713*35148Smarc 			r = -1;
714*35148Smarc 			errno = ESRCH;
715*35148Smarc 		}
716*35148Smarc 	}
717*35148Smarc 	else
718*35148Smarc 	{
719*35148Smarc 		pid = atoi(rjob);
720*35148Smarc 		if(pid==0 && *rjob != '0')
721*35148Smarc 			failed(bkill,kill_usage);
722*35148Smarc #ifdef BSD
723*35148Smarc 		if(sig==SIGSTOP && pid==jobstat.mypid && ppid==1)
724*35148Smarc 		{
725*35148Smarc 		/* can't stop login shell */
726*35148Smarc 			errno = EPERM;
727*35148Smarc 			r = -1;
728*35148Smarc 		}
729*35148Smarc 		else
730*35148Smarc 		{
731*35148Smarc 			if((pw=job_bypid(pid)) && (pw->p_flag&P_STOPPED))
732*35148Smarc 			{
733*35148Smarc 				pw->p_flag &= ~P_STOPPED;
734*35148Smarc 				numrun++;
735*35148Smarc 				kill(pid,SIGCONT);
736*35148Smarc 			}
737*35148Smarc 			r = kill(pid,sig);
738*35148Smarc 		}
739*35148Smarc #else
740*35148Smarc 		r = kill(pid,sig);
741*35148Smarc #endif	/* BSD */
742*35148Smarc 	}
743*35148Smarc 	if(r<0)
744*35148Smarc 	{
745*35148Smarc 		p_setout(stderr);
746*35148Smarc 		fputs(j_kill,output);
747*35148Smarc 		if(*rjob == '%')
748*35148Smarc 			msg = j_no_job;
749*35148Smarc 		else
750*35148Smarc 			msg = j_no_proc;
751*35148Smarc 		p_str(rjob,':');
752*35148Smarc 		if(errno == EPERM)
753*35148Smarc 			msg = j_perm;
754*35148Smarc 		p_str(msg,NL);
755*35148Smarc 		r = 1;
756*35148Smarc 	}
757*35148Smarc 	return(r);
758*35148Smarc }
759*35148Smarc 
760*35148Smarc /*
761*35148Smarc  * Get process structure from job number
762*35148Smarc  */
763*35148Smarc 
job_bynum(num)764*35148Smarc static struct process *job_bynum(num)
765*35148Smarc register int num;
766*35148Smarc {
767*35148Smarc 	register struct process *pw = pwlist;
768*35148Smarc 	for(;pw;pw=pw->p_next)
769*35148Smarc 	{
770*35148Smarc 		if((pw->p_flag&(P_PIPEJOB|P_WAITED)) == P_PIPEJOB)
771*35148Smarc 			continue;
772*35148Smarc 		if(pw->p_job == num)
773*35148Smarc 			return(pw);
774*35148Smarc 	}
775*35148Smarc 	return(NULL);
776*35148Smarc }
777*35148Smarc 
778*35148Smarc /*
779*35148Smarc  * Get process structure from first letters of jobname
780*35148Smarc  *
781*35148Smarc  */
782*35148Smarc 
jobbyname(name)783*35148Smarc static struct process *jobbyname(name)
784*35148Smarc char *name;
785*35148Smarc {
786*35148Smarc 	register struct process *pw = pwlist;
787*35148Smarc 	register struct fixcmd *fp = fc_fix;
788*35148Smarc 	if(fp==NULL)
789*35148Smarc 		return(NULL);
790*35148Smarc 	for(;pw;pw=pw->p_next)
791*35148Smarc 	{
792*35148Smarc 		if((pw->p_flag&(P_PIPEJOB|P_WAITED)) == P_PIPEJOB)
793*35148Smarc 			continue;
794*35148Smarc 		if(match_jobname(fp->fixfd,pw,name))
795*35148Smarc 			goto retrn;
796*35148Smarc 	}
797*35148Smarc 	pw = NULL;
798*35148Smarc retrn:
799*35148Smarc 	return(pw);
800*35148Smarc }
801*35148Smarc 
802*35148Smarc 
803*35148Smarc /*
804*35148Smarc  * match the name to the command starting with given name
805*35148Smarc  */
806*35148Smarc 
match_jobname(fdi,pw,name)807*35148Smarc static int	match_jobname(fdi,pw,name)
808*35148Smarc FILE *fdi;
809*35148Smarc register struct process *pw;
810*35148Smarc char *name;
811*35148Smarc {
812*35148Smarc 	register int c;
813*35148Smarc 	register char *sp;
814*35148Smarc 	if(fdi && pw->p_name>0)
815*35148Smarc 	{
816*35148Smarc 		fseek(fdi,pw->p_name,0);
817*35148Smarc 		for(sp=name;*sp;sp++)
818*35148Smarc 		{
819*35148Smarc 			c = getc(fdi);
820*35148Smarc 			if(c != *sp)
821*35148Smarc 				return(0);
822*35148Smarc 		}
823*35148Smarc 		return(1);
824*35148Smarc 	}
825*35148Smarc 	return(0);
826*35148Smarc }
827*35148Smarc 
828*35148Smarc 
829*35148Smarc 
830*35148Smarc /*
831*35148Smarc  * Initialize the process posting array
832*35148Smarc  */
833*35148Smarc 
postclr()834*35148Smarc void	postclr()
835*35148Smarc {
836*35148Smarc 	register struct process *pw = pwlist;
837*35148Smarc 	register struct process *px;
838*35148Smarc 	register int j = JBYTES;
839*35148Smarc 	for(;pw;pw=px)
840*35148Smarc 	{
841*35148Smarc 		px = pw->p_next;
842*35148Smarc 		free((char*)pw);
843*35148Smarc 	}
844*35148Smarc 	pwlist = NULL;
845*35148Smarc 	numpost=0;
846*35148Smarc 	numrun = 0;
847*35148Smarc 	while(--j >=0)
848*35148Smarc 		freejobs[j]  = 0;
849*35148Smarc }
850*35148Smarc 
851*35148Smarc /*
852*35148Smarc  * put the process <pcsid> on the process list and return the job number
853*35148Smarc  * turn on the specified flag bits.
854*35148Smarc  */
855*35148Smarc 
post(pid,flag)856*35148Smarc int post(pid,flag)
857*35148Smarc int pid;
858*35148Smarc {
859*35148Smarc 	register struct process *pw;
860*35148Smarc 	if(pw=job_post(pid))
861*35148Smarc 	{
862*35148Smarc 		pw->p_flag |= flag;
863*35148Smarc 		return(pw->p_job);
864*35148Smarc 	}
865*35148Smarc 	return(-1);
866*35148Smarc }
867*35148Smarc 
868*35148Smarc /*
869*35148Smarc  * internal version of post, this routine returns a process structure
870*35148Smarc  */
871*35148Smarc 
job_post(pcsid)872*35148Smarc static struct process *job_post(pcsid)
873*35148Smarc int 	pcsid;
874*35148Smarc {
875*35148Smarc 	register struct process  *pw = pwlist;
876*35148Smarc 	register struct process  *px=NULL;
877*35148Smarc 	register struct fixcmd *fp = fc_fix;
878*35148Smarc 	if(pcsid)
879*35148Smarc 	{
880*35148Smarc 		for(;pw;pw=pw->p_next)
881*35148Smarc 		{
882*35148Smarc 			if(pw->p_pid==pcsid)
883*35148Smarc 				return(pw);
884*35148Smarc 			if(pw->p_pgrp == jobstat.cur_pgrp)
885*35148Smarc 				px = pw;
886*35148Smarc 		}
887*35148Smarc 		if(pw=freelist)
888*35148Smarc 			freelist = pw->p_next;
889*35148Smarc 		else if((pw=(struct process*)malloc(sizeof(struct process)))==NULL)
890*35148Smarc 			error(nospace);
891*35148Smarc 		numrun++;
892*35148Smarc 		numpost++;
893*35148Smarc 		if(px)
894*35148Smarc 		{
895*35148Smarc 			pw->p_next = px->p_next;
896*35148Smarc 			px->p_next = pw;
897*35148Smarc 			pw->p_job = px->p_job;
898*35148Smarc 		}
899*35148Smarc 		else
900*35148Smarc 		{
901*35148Smarc 			/* put at front of list */
902*35148Smarc 			pw->p_next = pwlist;
903*35148Smarc 			pw->p_job = get_job();
904*35148Smarc 			pwlist = pw;
905*35148Smarc 		}
906*35148Smarc 		pw->p_pid = pcsid;
907*35148Smarc 		pw->p_flag = P_RUNNING;
908*35148Smarc 		pw->p_pgrp = jobstat.cur_pgrp;
909*35148Smarc 		if(fp!=NULL)
910*35148Smarc 			pw->p_name=hist_position(fp->fixind-1);
911*35148Smarc 		else
912*35148Smarc 			pw->p_name = -1;
913*35148Smarc 		pw->p_sig = 0;
914*35148Smarc 		if(numpost >= MAXJ-1)
915*35148Smarc 			await(0,0);
916*35148Smarc 		return(pw);
917*35148Smarc 	}
918*35148Smarc 	return(NULL);
919*35148Smarc }
920*35148Smarc 
921*35148Smarc /*
922*35148Smarc  * get job number given the process id
923*35148Smarc  */
924*35148Smarc 
job_bypid(pid)925*35148Smarc static struct process *job_bypid(pid)
926*35148Smarc register int pid;
927*35148Smarc {
928*35148Smarc 	register struct process *pw;
929*35148Smarc 	if(pid==0)
930*35148Smarc 		return(NULL);
931*35148Smarc 	for(pw=pwlist;pw;pw=pw->p_next)
932*35148Smarc 	if(pw->p_pid == pid)
933*35148Smarc 			break;
934*35148Smarc 	return(pw);
935*35148Smarc }
936*35148Smarc 
937*35148Smarc /*
938*35148Smarc  * Wait for process i to complete
939*35148Smarc  * flag=1 when wait builtin invoked so that it can be interrupted
940*35148Smarc  * flag=2 to check for waiting processes and return
941*35148Smarc  * flag=3 to resume job in foreground
942*35148Smarc  * i=0 to wait for any process
943*35148Smarc  * i=-1 to wait for all runing processes
944*35148Smarc  */
945*35148Smarc 
await(i,flag)946*35148Smarc void	await(i, flag)
947*35148Smarc register int 	i;
948*35148Smarc int 	flag;
949*35148Smarc {
950*35148Smarc 	int 	rc=0;
951*35148Smarc 	int 	w;
952*35148Smarc 	int my_job = -1;
953*35148Smarc #ifdef BSD
954*35148Smarc 	union wait wstat;
955*35148Smarc #endif	/* BSD */
956*35148Smarc 	register struct process *pw = NULL;
957*35148Smarc 	struct process *px;
958*35148Smarc 	if(i!= -1 && i)
959*35148Smarc 	{
960*35148Smarc 		if(flag)
961*35148Smarc 		{
962*35148Smarc 			pw = job_bypid(i);
963*35148Smarc 			if(flag==3 && pw)
964*35148Smarc 				flag = 0;
965*35148Smarc 		}
966*35148Smarc 		else
967*35148Smarc 			pw = job_post(i);
968*35148Smarc 		if(flag)
969*35148Smarc 		{
970*35148Smarc 			if(pw==0 || (pw->p_flag&P_STOPPED))
971*35148Smarc 			return;
972*35148Smarc 		}
973*35148Smarc 		my_job = pw->p_job;
974*35148Smarc 	}
975*35148Smarc 	if(flag==0 && (states&MONITOR) && pw)
976*35148Smarc 	{
977*35148Smarc 		set_job(pw);
978*35148Smarc 		/* if job is stopped, resume it in the background */
979*35148Smarc #if BSD || SXT
980*35148Smarc 		if(pw->p_flag&P_STOPPED)
981*35148Smarc 			unstop(pw->p_pgrp);
982*35148Smarc # ifdef SXT
983*35148Smarc 		if(pw->p_job < jobstat.maxjob)
984*35148Smarc 			open_chan(pw->p_job);
985*35148Smarc # endif /* SXT */
986*35148Smarc #endif	/* BSD */
987*35148Smarc 	}
988*35148Smarc 	p_flush();
989*35148Smarc 	while(numrun>0)
990*35148Smarc 	{
991*35148Smarc 		register int 	p;
992*35148Smarc 		register int 	sig;
993*35148Smarc 		register int 	w_hi;
994*35148Smarc #ifdef BSD
995*35148Smarc 		if(is_option(MONITOR) || flag==2)
996*35148Smarc 		{
997*35148Smarc 		retry:
998*35148Smarc 			errno = 0;
999*35148Smarc 			sig = sighold(SIGCHLD);
1000*35148Smarc 			trapnote &= ~SIGJOBS;
1001*35148Smarc 			p=wait3(&wstat,WNOHANG|WUNTRACED,0);
1002*35148Smarc 			errno = 0;
1003*35148Smarc 			if(p==0 && flag!=2)
1004*35148Smarc 			{
1005*35148Smarc # ifdef BSD_4_2
1006*35148Smarc 				sigpause(sig&~(1<<(SIGCHLD-1)));
1007*35148Smarc # else
1008*35148Smarc 				sigpause(SIGCHLD);
1009*35148Smarc # endif /* BSD_4_2 */
1010*35148Smarc 				if(errno==EINTR && flag==1 && (trapnote&SIGJOBS)==0)
1011*35148Smarc 					break;
1012*35148Smarc 				goto retry;
1013*35148Smarc 			}
1014*35148Smarc 			trapnote &= ~SIGJOBS;
1015*35148Smarc 			sigrelse(SIGCHLD);
1016*35148Smarc 			if(p==0 || p== -1)
1017*35148Smarc 				return;
1018*35148Smarc 			w = wstat.w_status;
1019*35148Smarc 			pw = job_bypid(p);
1020*35148Smarc 			if(pw->p_job == my_job && (states&MONITOR))
1021*35148Smarc 			{
1022*35148Smarc 				register int ssig = wstat.w_S.w_Stopsig;
1023*35148Smarc 				if(WIFSTOPPED(wstat) && (ssig==SIGTTIN||ssig==SIGTTOU))
1024*35148Smarc 				{
1025*35148Smarc 					/* job stopped before it got terminal */
1026*35148Smarc 					killpg(pw->p_pgrp,SIGCONT);
1027*35148Smarc 					continue;
1028*35148Smarc 				}
1029*35148Smarc 				if(p==i)
1030*35148Smarc 					reset_ttygrp(pw,w&LOBYTE);
1031*35148Smarc 			}
1032*35148Smarc 		}
1033*35148Smarc 		else
1034*35148Smarc #endif	/* BSD */
1035*35148Smarc 		{
1036*35148Smarc #ifndef BSD
1037*35148Smarc # ifdef SXT
1038*35148Smarc 			if(jobstat.maxjob >0)
1039*35148Smarc 			{
1040*35148Smarc 				/* check for job status change */
1041*35148Smarc 				status1 = status2;
1042*35148Smarc 				status2.input = status2.output = 0;
1043*35148Smarc 				if(ioctl(2,SXTIOCSTAT,&status2)!=0)
1044*35148Smarc 				{
1045*35148Smarc 					jobstat.maxjob = 0;
1046*35148Smarc 				}
1047*35148Smarc 				else if(status1.input != status2.input)
1048*35148Smarc 				{
1049*35148Smarc 					status_update(status2.input,status1.input,SIGSTIN);
1050*35148Smarc 				}
1051*35148Smarc 				else if(status1.output != status2.output)
1052*35148Smarc 				{
1053*35148Smarc 					status_update(status2.output,status1.output,SIGSTOP);
1054*35148Smarc 				}
1055*35148Smarc 			}
1056*35148Smarc # endif /* SXT */
1057*35148Smarc 			/* enable fault handler to see if there are any pending jobs */
1058*35148Smarc 			if((trapnote&SIGJOBS)==0)
1059*35148Smarc 				signal(SIGCLD,fault);
1060*35148Smarc 			if(flag==2 && (trapnote&SIGJOBS)==0)
1061*35148Smarc 				return;
1062*35148Smarc # ifdef SXT
1063*35148Smarc 			if(my_job>=0 && (trapnote&SIGJOBS)==0 && jobstat.maxjob)
1064*35148Smarc 			{
1065*35148Smarc 				errno = 0;
1066*35148Smarc 		        	p = ioctl(2, SXTIOCWF, 0);
1067*35148Smarc 				if(p==0)
1068*35148Smarc 					/* job stopped */
1069*35148Smarc 				{
1070*35148Smarc        		         		ioctl(2, SXTIOCBLK, my_job);
1071*35148Smarc 					if(fd_chan>=0)
1072*35148Smarc 					{
1073*35148Smarc 						if(ioctl(fd_chan,TCFLSH,2)!=0)
1074*35148Smarc 						{
1075*35148Smarc 							;
1076*35148Smarc 						}
1077*35148Smarc 					}
1078*35148Smarc 					pw->p_flag |= (P_NOTIFY|P_STOPPED);
1079*35148Smarc 					pw->p_sig = SIGSTOP;
1080*35148Smarc 					reset_ttygrp(pw,1);
1081*35148Smarc 					break;
1082*35148Smarc 				}
1083*35148Smarc 			}
1084*35148Smarc # endif /* SXT */
1085*35148Smarc #endif	/* BSD */
1086*35148Smarc 			trapnote &= ~ SIGJOBS;
1087*35148Smarc 			p=wait(&w);
1088*35148Smarc 			if(p== -1)
1089*35148Smarc 			{
1090*35148Smarc 				if(errno==ECHILD)
1091*35148Smarc 				{
1092*35148Smarc 					postclr();
1093*35148Smarc 					return;
1094*35148Smarc 				}
1095*35148Smarc 				else if(errno==EINTR)
1096*35148Smarc 				{
1097*35148Smarc 					if(trapnote&SIGJOBS)
1098*35148Smarc 						continue;
1099*35148Smarc 					if(flag)
1100*35148Smarc 						break;
1101*35148Smarc 				}
1102*35148Smarc 				continue;
1103*35148Smarc 			}
1104*35148Smarc 			trapnote &= ~ SIGJOBS;
1105*35148Smarc 			pw = job_bypid(p);
1106*35148Smarc #ifdef SXT
1107*35148Smarc 			pw->p_flag &= ~P_STOPPED;
1108*35148Smarc #endif	/* SXT */
1109*35148Smarc 			/* restore original tty state if jobs aborted */
1110*35148Smarc 			if(p == i && (states&MONITOR))
1111*35148Smarc 				reset_ttygrp(pw,w&LOBYTE);
1112*35148Smarc 		}
1113*35148Smarc 		if(pw)
1114*35148Smarc 		{
1115*35148Smarc 			numrun--;
1116*35148Smarc 			pw->p_flag |= P_NOTIFY;
1117*35148Smarc #ifdef BSD
1118*35148Smarc 			if((states&MONITOR) && WIFSTOPPED(wstat))
1119*35148Smarc 				pw->p_flag |= P_STOPPED;
1120*35148Smarc 			else
1121*35148Smarc #endif	/* BSD */
1122*35148Smarc 			{
1123*35148Smarc 				if(p==cpid)
1124*35148Smarc 				{
1125*35148Smarc 					cpid = 0;
1126*35148Smarc 					cpipe[1] = NULL;
1127*35148Smarc 				}
1128*35148Smarc 				if(p==i || (states&MONITOR)==0)
1129*35148Smarc 				{
1130*35148Smarc 					if(px=unpost(pw))
1131*35148Smarc 					{
1132*35148Smarc 						if(i)
1133*35148Smarc 						{
1134*35148Smarc 							if(p==i && (states&MONITOR))
1135*35148Smarc 								set_job(px);
1136*35148Smarc 							i = px->p_pid;
1137*35148Smarc 						}
1138*35148Smarc 						continue;
1139*35148Smarc 					}
1140*35148Smarc 				}
1141*35148Smarc 			}
1142*35148Smarc 		}
1143*35148Smarc 		sig = w&0177;
1144*35148Smarc 		if(states&MONITOR)
1145*35148Smarc 		{
1146*35148Smarc #ifdef BSD
1147*35148Smarc 			if(WIFSTOPPED(wstat))
1148*35148Smarc 			{
1149*35148Smarc 				if(pw)
1150*35148Smarc 					pw->p_sig = wstat.w_S.w_Stopsig;
1151*35148Smarc 				if(p == i)
1152*35148Smarc 					break;
1153*35148Smarc 				continue;
1154*35148Smarc 			}
1155*35148Smarc 			else if(p!=i)
1156*35148Smarc #else
1157*35148Smarc 			if(p!=i)
1158*35148Smarc #endif	/* BSD */
1159*35148Smarc 			{
1160*35148Smarc 				if(pw)
1161*35148Smarc 					pw->p_sig = w;
1162*35148Smarc 				if(w&HIGHBIT)
1163*35148Smarc 					pw->p_flag |= P_COREDUMP;
1164*35148Smarc 				continue;
1165*35148Smarc 			}
1166*35148Smarc 			/* this is needed since child not in same process group */
1167*35148Smarc 			else if(sig==SIGINT || sig==SIGQUIT || sig==SIGHUP)
1168*35148Smarc 				fault(sig);
1169*35148Smarc 		}
1170*35148Smarc 		w_hi = (w>>8)&LOBYTE;
1171*35148Smarc 		if(sig)
1172*35148Smarc 		{
1173*35148Smarc 			if(sig == 0177	/* ptrace! return */)
1174*35148Smarc 			{
1175*35148Smarc 				fputs(ptrace,output);
1176*35148Smarc 				sig = w_hi;
1177*35148Smarc 			}
1178*35148Smarc 			if(sig!=SIGINT && sig!=SIGPIPE)
1179*35148Smarc 			{
1180*35148Smarc 				if(i!=p || (states&PROMPT)==0)
1181*35148Smarc 					p_prp(itos(p),SP);
1182*35148Smarc 				fputs(sysmsg[sig],output);
1183*35148Smarc 				if(w&HIGHBIT)
1184*35148Smarc 					fputs(coredump,output);
1185*35148Smarc 			}
1186*35148Smarc 			newline();
1187*35148Smarc 		}
1188*35148Smarc 		if(p == i)
1189*35148Smarc 		{
1190*35148Smarc 			rc = (sig ? sig|SIGFAIL : w_hi);
1191*35148Smarc 			break;
1192*35148Smarc 		}
1193*35148Smarc 		if(i == 0)
1194*35148Smarc 			break;
1195*35148Smarc 	}
1196*35148Smarc 	if(flag>=2)
1197*35148Smarc 		return;
1198*35148Smarc 	exitval=rc;
1199*35148Smarc 	exitset();
1200*35148Smarc }
1201*35148Smarc 
1202*35148Smarc #if BSD || SXT
1203*35148Smarc /*
1204*35148Smarc  * turn off STOP state of a process group
1205*35148Smarc  */
1206*35148Smarc 
unstop(grp)1207*35148Smarc static int unstop(grp)
1208*35148Smarc register int grp;
1209*35148Smarc {
1210*35148Smarc 	register struct process *pw;
1211*35148Smarc 	register int num = numrun;
1212*35148Smarc 	for(pw=pwlist;pw;pw=pw->p_next)
1213*35148Smarc 	{
1214*35148Smarc 		if(pw->p_pgrp != grp)
1215*35148Smarc 			continue;
1216*35148Smarc 		if(pw->p_flag&P_STOPPED)
1217*35148Smarc 		{
1218*35148Smarc 			num++;
1219*35148Smarc 			pw->p_flag &= ~P_STOPPED;
1220*35148Smarc 			pw->p_sig = 0;
1221*35148Smarc # ifdef SXT
1222*35148Smarc 			break;
1223*35148Smarc # endif /* SXT */
1224*35148Smarc 		}
1225*35148Smarc 	}
1226*35148Smarc 	if(num!=numrun)
1227*35148Smarc 	{
1228*35148Smarc 		p_flush();
1229*35148Smarc #ifdef BSD
1230*35148Smarc 		numrun = num;
1231*35148Smarc 		return(killpg(grp,SIGCONT));
1232*35148Smarc #endif
1233*35148Smarc 	}
1234*35148Smarc 	return(-1);
1235*35148Smarc }
1236*35148Smarc #endif	/* BSD */
1237*35148Smarc 
1238*35148Smarc /*
1239*35148Smarc  * remove a process group from table
1240*35148Smarc  * If all the processes have not completed then unpost returns
1241*35148Smarc  * the structure pointer  of an unfinished process.
1242*35148Smarc  * Otherwise NULL is returned.
1243*35148Smarc  */
1244*35148Smarc 
unpost(pwtop)1245*35148Smarc static struct process *unpost(pwtop)
1246*35148Smarc struct process *pwtop;
1247*35148Smarc {
1248*35148Smarc 	register struct process *pw;
1249*35148Smarc 	register struct process *px=NULL;
1250*35148Smarc 	register int job = pwtop->p_job;
1251*35148Smarc 	register struct process *py;
1252*35148Smarc 	/* look for unfinished processes */
1253*35148Smarc 	for(pw=pwlist;pw;pw=pw->p_next)
1254*35148Smarc 	{
1255*35148Smarc 		if(pw->p_job != job)
1256*35148Smarc 			continue;
1257*35148Smarc 		if((pw->p_flag&P_NOTIFY)==0)
1258*35148Smarc 			px = pw;
1259*35148Smarc 	}
1260*35148Smarc 	if(px)
1261*35148Smarc 	{
1262*35148Smarc 		px->p_flag &= ~P_PIPEJOB;
1263*35148Smarc 		px->p_flag |= P_WAITED;
1264*35148Smarc 		return(px);
1265*35148Smarc 	}
1266*35148Smarc 	/* all processes complete, unpost job */
1267*35148Smarc 	for(pw=pwlist;pw;pw=py)
1268*35148Smarc 	{
1269*35148Smarc 		py = pw->p_next;
1270*35148Smarc 		if(pw->p_job != job)
1271*35148Smarc 		{
1272*35148Smarc 			px = pw;
1273*35148Smarc 			continue;
1274*35148Smarc 		}
1275*35148Smarc 		numpost--;
1276*35148Smarc 		if(px==NULL)
1277*35148Smarc 			pwlist = py;
1278*35148Smarc 		else
1279*35148Smarc 			px->p_next = py;
1280*35148Smarc 		pw->p_next = freelist;
1281*35148Smarc 		freelist = pw;
1282*35148Smarc 	}
1283*35148Smarc 	free_job((int)pwtop->p_job);
1284*35148Smarc 	return(NULL);
1285*35148Smarc }
1286*35148Smarc 
1287*35148Smarc /*
1288*35148Smarc  * unlink a process form the process list
1289*35148Smarc  */
1290*35148Smarc 
pw_unlink(pw)1291*35148Smarc static void pw_unlink(pw)
1292*35148Smarc register struct process *pw;
1293*35148Smarc {
1294*35148Smarc 	register struct process *px;
1295*35148Smarc 	if(pw==pwlist)
1296*35148Smarc 	{
1297*35148Smarc 		pwlist = pw->p_next;
1298*35148Smarc 		return;
1299*35148Smarc 	}
1300*35148Smarc 	for(px=pwlist;px;px=px->p_next)
1301*35148Smarc 		if(px->p_next == pw)
1302*35148Smarc 		{
1303*35148Smarc 			px->p_next = pw->p_next;
1304*35148Smarc 			return;
1305*35148Smarc 		}
1306*35148Smarc }
1307*35148Smarc 
1308*35148Smarc /*
1309*35148Smarc  * get an unused job number
1310*35148Smarc  * freejobs is a bit vector, 0 is unused
1311*35148Smarc  */
1312*35148Smarc 
get_job()1313*35148Smarc static int get_job()
1314*35148Smarc {
1315*35148Smarc 	register int j=0;
1316*35148Smarc 	register unsigned mask = 1;
1317*35148Smarc 	register unsigned char *freeword;
1318*35148Smarc 	/* skip to first word with a free slot */
1319*35148Smarc 	while(freejobs[j] == 0xff)
1320*35148Smarc 		j++;
1321*35148Smarc 	freeword = &freejobs[j];
1322*35148Smarc 	j *= 8;
1323*35148Smarc 	for(j++;mask&(*freeword);j++,mask <<=1);
1324*35148Smarc 	*freeword  |=mask;
1325*35148Smarc 	return(j);
1326*35148Smarc }
1327*35148Smarc 
1328*35148Smarc /*
1329*35148Smarc  * return a job number
1330*35148Smarc  */
1331*35148Smarc 
free_job(n)1332*35148Smarc static void free_job(n)
1333*35148Smarc register int n;
1334*35148Smarc {
1335*35148Smarc 	register int j = (--n)/8;
1336*35148Smarc 	register unsigned mask;
1337*35148Smarc 	n -= j*8;
1338*35148Smarc 	mask = 1 << n;
1339*35148Smarc 	freejobs[j]  &= ~mask;
1340*35148Smarc }
1341*35148Smarc 
1342*35148Smarc #ifdef SXT
1343*35148Smarc /*
1344*35148Smarc  * open up the input streams for a new channel
1345*35148Smarc  */
1346*35148Smarc 
1347*35148Smarc static char *open_mode[3] = {"r","w","w+"};
j_new_chan()1348*35148Smarc j_new_chan()
1349*35148Smarc {
1350*35148Smarc 	register FILE* fd;
1351*35148Smarc 	register int i;
1352*35148Smarc 	sxt[11] = '0' + jobstat.cur_job;
1353*35148Smarc 	close(jobstat.pipe[0]);
1354*35148Smarc 	fd = fopen(sxt,"r+");
1355*35148Smarc 	if(ioctl(fileno(fd),TCSETA,&my_stty)<0 || fd==NULL)
1356*35148Smarc 	{
1357*35148Smarc 		close(jobstat.pipe[1]);
1358*35148Smarc 		return(0);
1359*35148Smarc 	}
1360*35148Smarc 	for(i=0;i<3;i++)
1361*35148Smarc 	{
1362*35148Smarc 		if(isatty(i))
1363*35148Smarc 		{
1364*35148Smarc 			fclose(file_fd(i));
1365*35148Smarc 			fdopen(dup(fileno(fd)),open_mode[i]);
1366*35148Smarc 		}
1367*35148Smarc 	}
1368*35148Smarc 	fclose(fd);
1369*35148Smarc 	write(jobstat.pipe[1],nullstr,1);
1370*35148Smarc 	close(jobstat.pipe[1]);
1371*35148Smarc 	return(1);
1372*35148Smarc }
1373*35148Smarc 
next_job()1374*35148Smarc int next_job()
1375*35148Smarc {
1376*35148Smarc 	register int i = get_job();
1377*35148Smarc 	free_job(i);
1378*35148Smarc 	return(i);
1379*35148Smarc }
1380*35148Smarc 
status_update(mask2,mask1,sigval)1381*35148Smarc static status_update(mask2,mask1,sigval)
1382*35148Smarc {
1383*35148Smarc 	register int i,j;
1384*35148Smarc 	register struct process *pw;
1385*35148Smarc 	for(i = 1; i < MAXPCHAN; i++)
1386*35148Smarc 	{
1387*35148Smarc 		j = 1<<i;
1388*35148Smarc 		if((mask1&j)==0 && (mask2&j))
1389*35148Smarc 		{
1390*35148Smarc 			if(pw = job_bynum(i))
1391*35148Smarc 				pw->p_sig = sigval;
1392*35148Smarc 		}
1393*35148Smarc 		else if((mask2&j)==0 && (mask1&j))
1394*35148Smarc 		{
1395*35148Smarc 			if(pw = job_bynum(i))
1396*35148Smarc 				pw->p_sig = 0;
1397*35148Smarc 		}
1398*35148Smarc 	}
1399*35148Smarc }
1400*35148Smarc 
open_chan(j)1401*35148Smarc static int open_chan(j)
1402*35148Smarc {
1403*35148Smarc 	sxt[11] = '0' + j;
1404*35148Smarc 	if(fd_chan>=0)
1405*35148Smarc 	{
1406*35148Smarc 		return;
1407*35148Smarc 	}
1408*35148Smarc 	fd_chan = open(sxt,2);
1409*35148Smarc }
1410*35148Smarc #endif	/* SXT */
1411*35148Smarc 
1412