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