xref: /csrg-svn/local/toolchest/ksh.2/sh/jobs.c (revision 64055)
147938Smarc #define USE_OLD_TTY
247938Smarc /*
347938Smarc 
447938Smarc  *      Copyright (c) 1984, 1985, 1986 AT&T
547938Smarc  *      All Rights Reserved
647938Smarc 
747938Smarc  *      THIS IS UNPUBLISHED PROPRIETARY SOURCE
847938Smarc  *      CODE OF AT&T.
947938Smarc  *      The copyright notice above does not
1047938Smarc  *      evidence any actual or intended
1147938Smarc  *      publication of such source code.
1247938Smarc 
1347938Smarc  */
1447938Smarc /* @(#)jobs.c	1.1 */
1547938Smarc 
1647938Smarc /*
1747938Smarc  *  Job control for UNIX Shell
1847938Smarc  *
1947938Smarc  *   David Korn
2047938Smarc  *   AT&T Bell Laboratories
2147938Smarc  *   Room 5D-112
2247938Smarc  *   Murray Hill, N. J. 07974
2347938Smarc  *   Tel. x7975
2447938Smarc  *
2547938Smarc  *  Written October, 1982
2647938Smarc  */
2747938Smarc 
2847938Smarc 
2947938Smarc #include	<errno.h>
3047938Smarc 
3147938Smarc #ifdef BSD
3247938Smarc # ifdef BSD_4_2
3347938Smarc #include	<sys/wait.h>
3447938Smarc # else
3547938Smarc #include	<wait.h>
3647938Smarc # endif /* BSD_4_2 */
3747938Smarc #endif	/* BSD */
3847938Smarc 
3947938Smarc #ifdef SXT
4047938Smarc #define		SIGSTOP	20
4147938Smarc #define		SIGSTIN	21
4247938Smarc #include	<sys/types.h>
4347938Smarc #include	<sys/tty.h>
4447938Smarc #include	<sys/sxt.h>
4547938Smarc #include	<sys/stat.h>
4647938Smarc #endif	/* SXT */
4747938Smarc 
4847938Smarc #include	"defs.h"
4947938Smarc #include	"flags.h"
5047938Smarc #include	"shtype.h"
5147938Smarc #include	"jobs.h"
5247938Smarc #include	"brkincr.h"
5347938Smarc #include	"io.h"
5447938Smarc #include	"history.h"
5547938Smarc 
5647938Smarc #ifdef SXT
5747938Smarc #undef input
5847938Smarc static status_update();
5947938Smarc static int open_chan();
6047938Smarc static int fd_chan = -1;
6147938Smarc static char tinybuf;
6247938Smarc #endif	/* SXT */
6347938Smarc 
6447938Smarc #define LOBYTE	0377
6547938Smarc #define MAXMSG	25
6647938Smarc 
6747938Smarc void	await();
6847938Smarc void	postclr();
6947938Smarc 
7047938Smarc extern void	fault();
7147938Smarc extern long	hist_list();
7247938Smarc extern long	hist_position();
7347938Smarc extern char	*itos();
7447938Smarc extern char	*malloc();
7547938Smarc extern void	failed();
7647938Smarc extern void	free();
7747938Smarc extern void	p_str();
7847938Smarc extern void	p_prp();
7947938Smarc extern void	p_num();
8047938Smarc extern void	p_sub();
8147938Smarc extern void	p_nchr();
8247938Smarc extern void	p_flush();
8347938Smarc extern void	p_setout();
8447938Smarc 
8547938Smarc static int	set_ttygrp();
8647938Smarc static int	set_job();
8747938Smarc static int	reset_ttygrp();
8847938Smarc static struct process *next_proc();
8947938Smarc static struct process *jobbyname();
9047938Smarc static struct process *job_bynum();
9147938Smarc static struct process *job_bypid();
9247938Smarc static struct process *job_post();
9347938Smarc static struct process *unpost();
9447938Smarc static struct process *pgrp_jobs();
9547938Smarc static int get_job();
9647938Smarc static int match_jobname();
9747938Smarc static int unstop();
9847938Smarc static void free_job();
9947938Smarc static void pw_unlink();
10047938Smarc static struct process *freelist;
10147938Smarc #define	numrun	jobstat.p_numrun	/* number of running jobs */
10247938Smarc #define	numpost	jobstat.p_numpost	/* number of posted jobs */
10347938Smarc #define	pwlist	jobstat.p_pwlist
10447938Smarc #define freejobs jobstat.p_freejobs	/* free job numbers */
10547938Smarc static long pr_jobname();
10647938Smarc 
10747938Smarc #ifdef FIOLOOKLD
10847938Smarc #define version8	1
10947938Smarc extern int tty_ld, ntty_ld;
11047938Smarc #define OTTYDISC	tty_ld
11147938Smarc #define NTTYDISC	ntty_ld
11247938Smarc #endif	/* FIOLOOKLD */
11347938Smarc 
11447938Smarc 
11547938Smarc static int savepgrp;
11647938Smarc static int savetgrp;
11747938Smarc static BOOL old_driver;
11847938Smarc static BOOL beenhere;
11947938Smarc static int saveldisc;
12047938Smarc 
12147938Smarc #ifdef POSIX
12247938Smarc static struct termios my_stty;		/* terminal state for shell */
12347938Smarc #else
12447938Smarc # ifdef BSD
12547938Smarc static struct sgttyb my_stty;		/* terminal state for shell */
12647938Smarc # else
12747938Smarc static struct termio my_stty;		/* terminal state for shell */
12847938Smarc # endif	/* BSD */
12947938Smarc #endif /* !POSIX */
13047938Smarc 
13147938Smarc #ifdef BSD
13247938Smarc /*
13347938Smarc  * initialize job control
13447938Smarc  * if lflag is set the switching driver message will not print
13547938Smarc  */
13647938Smarc 
init_jobs(lflag)13747938Smarc int init_jobs(lflag)
13847938Smarc {
13947938Smarc 	int ldisc;
14047938Smarc 	register int ntry = 0;
14147938Smarc 	register int pid;
14247938Smarc 	jobstat.mypid = pid = getpid();
14347938Smarc 	savepgrp = getpgrp(pid);
14447938Smarc # ifdef version8
14547938Smarc 	if((ldisc = ioctl (2, FIOLOOKLD, 0)) <0)
14647938Smarc # else
14747938Smarc 	if(ioctl(2,TIOCGETD,&ldisc) !=0)
14847938Smarc # endif /* version8 */
14947938Smarc 		return(-1);
15047938Smarc 	if(ldisc!=NTTYDISC
15147938Smarc #ifdef notdef /*POSIX*/
15247938Smarc 	   && ldisc!=POSXDISC
15347938Smarc #endif
15447938Smarc 	   && ldisc!=OTTYDISC)
15547938Smarc 	{
15647938Smarc 		/* no job control when running with MPX */
15747938Smarc # ifdef VSH
15847938Smarc 		on_option(VIRAW);
15947938Smarc # endif /* VSH */
16047938Smarc 		return(-1);
16147938Smarc 	}
16247938Smarc retry:
16347938Smarc 	signal(SIGTTOU,SIG_IGN);
16447938Smarc 	if(ioctl(2,TIOCGPGRP,&savetgrp) !=0)
16547938Smarc 	{
16647938Smarc 		fputs(j_not_tty,output);
16747938Smarc 		return(-1);
16847938Smarc 	}
16947938Smarc 	/* This shell must be in foreground to change state */
17047938Smarc 	if(savetgrp != savepgrp)
17147938Smarc 	{
17247938Smarc 		signal(SIGTTOU,SIG_DFL);
17347938Smarc 		kill(pid,SIGTTOU);
17447938Smarc 		/* wait for continue and try again */
17547938Smarc 		if(ntry++ > 100)
17647938Smarc 		{
17747938Smarc 			fputs(j_no_start,output);
17847938Smarc 			return(-1);
17947938Smarc 		}
18047938Smarc 		goto retry;
18147938Smarc 	}
18247938Smarc #ifdef notdef /*POSIX*/
18347938Smarc 	if(ldisc != POSXDISC)
18447938Smarc 	{
18547938Smarc 		saveldisc = ldisc;
18647938Smarc 		ldisc = POSXDISC;
18747938Smarc #else
18847938Smarc 	if(ldisc == OTTYDISC)
18947938Smarc 	{
19047938Smarc 		ldisc = NTTYDISC;
19147938Smarc #endif
19247938Smarc # ifdef version8
19347938Smarc 		ioctl(2,TIOCGETP,&my_stty);
19447938Smarc 		if (ioctl(2, FIOPOPLD, 0) < 0)
19547938Smarc 			return(-1);
19647938Smarc 		if (ioctl(2, FIOPUSHLD, &ldisc, 0) < 0)
19747938Smarc 		{
19847938Smarc 			ldisc = OTTYDISC;
19947938Smarc 			 ioctl(2, FIOPUSHLD, &ldisc, 0);
20047938Smarc 			return(-1);
20147938Smarc 		}
20247938Smarc 		ioctl(2,TIOCSETN,&my_stty);
20347938Smarc # else
20447938Smarc 		if(ioctl(2,TIOCSETD,&ldisc) !=0)
20547938Smarc 			return(-1);
20647938Smarc # endif /* version8 */
20747938Smarc 		if(lflag==0)
20847938Smarc 		{
20947938Smarc 			fputs(j_newtty,output);
21047938Smarc 			old_driver++;
21147938Smarc 		}
21247938Smarc 	}
21347938Smarc 	on_option(MONITOR);
21447938Smarc 	signal(SIGCHLD,fault);
21547938Smarc 	signal(SIGTSTP,SIG_IGN);
21647938Smarc 	signal(SIGTTIN,SIG_IGN);
217*64055Smarc 	if (setpgrp(pid,pid) == -1) {
218*64055Smarc 		fputs(j_no_start,output);
219*64055Smarc 		return(-1);
220*64055Smarc 	}
221*64055Smarc 	if (set_ttygrp(pid) == -1) {
222*64055Smarc 		setpgrp(pid, savepgrp);	/* screwed if this fails */
223*64055Smarc 		fputs(j_no_start,output);
224*64055Smarc 		return(-1);
225*64055Smarc 	}
226*64055Smarc 
22747938Smarc 	return(0);
22847938Smarc }
22947938Smarc 
23047938Smarc 
23147938Smarc /*
23247938Smarc  * see if there are any stopped jobs
23347938Smarc  * restore tty driver and pgrp
23447938Smarc  */
23547938Smarc 
23647938Smarc int close_jobs()
23747938Smarc {
23847938Smarc 	register struct process *pw = pwlist;
23947938Smarc 	register int count = 0;
24047938Smarc 	int ldisc;
24147938Smarc 	if((states&MONITOR)==0)
24247938Smarc 		return(0);
24347938Smarc 	for(;pw;pw=pw->p_next)
24447938Smarc 	{
24547938Smarc 		if((pw->p_flag&P_STOPPED)==0)
24647938Smarc 			continue;
24747938Smarc 		if(beenhere)
24847938Smarc 			killpg(pw->p_pgrp,SIGTERM);
24947938Smarc 		count++;
25047938Smarc 	}
25147938Smarc 	if(beenhere++ == 0 && pwlist)
25247938Smarc 	{
25347938Smarc 		if(count)
25447938Smarc 		{
25547938Smarc 			fputs(j_terminate,output);
25647938Smarc 			return(-1);
25747938Smarc 		}
25847938Smarc 		else if(login_sh)
25947938Smarc 		{
26047938Smarc 			fputs(j_running,output);
26147938Smarc 			return(-1);
26247938Smarc 		}
26347938Smarc 	}
26447938Smarc 	set_ttygrp(savepgrp);
26547938Smarc 	if(old_driver)
26647938Smarc 	{
26747938Smarc 		/* restore old line discipline */
26847938Smarc #ifdef POSIX
26947938Smarc 		ldisc = saveldisc;
27047938Smarc #else
27147938Smarc 		ldisc = OTTYDISC;
27247938Smarc #endif
27347938Smarc # ifdef version8
27447938Smarc 		ioctl(2,TIOCGETP,&my_stty);
27547938Smarc 		if (ioctl(2, FIOPOPLD, 0) < 0)
27647938Smarc 			return(0);
27747938Smarc 		if (ioctl(2, FIOPUSHLD, &ldisc, 0) < 0)
27847938Smarc 		{
27947938Smarc 			ldisc = NTTYDISC;
28047938Smarc 			ioctl(2, FIOPUSHLD, &ldisc, 0);
28147938Smarc 			return(0);
28247938Smarc 		}
28347938Smarc 		ioctl(2,TIOCSETN,&my_stty);
28447938Smarc # else
28547938Smarc 		if(ioctl(2,TIOCSETD,&ldisc) !=0)
28647938Smarc 			return(0);
28747938Smarc # endif /* version8 */
28847938Smarc 		fputs(j_oldtty,output);
28947938Smarc 	}
29047938Smarc 	return(0);
29147938Smarc }
29247938Smarc 
29347938Smarc /*
29447938Smarc  * Set the ttygroup id to pid
29547938Smarc  */
29647938Smarc 
29747938Smarc static int set_ttygrp(pid)
29847938Smarc {
29947938Smarc 	if(ioctl(2,TIOCSPGRP,&pid) !=0)
30047938Smarc 		return(-1);
30147938Smarc 	return(0);
30247938Smarc }
30347938Smarc 
30447938Smarc /*
30547938Smarc  * Set the ttygroup id to a previously running job
30647938Smarc  */
30747938Smarc #else	/* !BSD */
30847938Smarc # ifdef SXT
30947938Smarc static char sxt[] = "/dev/sxt/000";
31047938Smarc static struct sxtblock status1,status2;
31147938Smarc 
31247938Smarc int init_jobs(lflag)
31347938Smarc {
31447938Smarc 	register int pid;
31547938Smarc 	register int dev;
31647938Smarc 	struct stat statbuf;
31747938Smarc 	jobstat.mypid = pid = getpid();
31847938Smarc 	savepgrp = getpgrp(pid);
31947938Smarc 	if(ioctl(2,SXTIOCSTAT,&status2) < 0)
32047938Smarc 		return(-1);
32147938Smarc 	if(ioctl(2,TCGETA,&my_stty) < 0)
32247938Smarc 		return(-1);
32347938Smarc 	if(fstat(2,&statbuf) < 0)
32447938Smarc 		return(-1);
32547938Smarc 	dev = statbuf.st_rdev&0xff;
32647938Smarc 	/* must be channel 0 */
32747938Smarc 	if(dev&07)
32847938Smarc 		return(-1);
32947938Smarc 	dev >>= 3;
33047938Smarc 	sxt[10] = '0' + (dev%10);
33147938Smarc 	sxt[9] = '0' + dev/10;
33247938Smarc 	my_stty.c_cc[VSWTCH] = CSWTCH;
33347938Smarc 	if(ioctl(2,TCSETAF,&my_stty) < 0)
33447938Smarc 		return(-1);
33547938Smarc 	setpgrp(pid,pid);
33647938Smarc 	jobstat.maxjob = MAXPCHAN;
33747938Smarc 	on_option(MONITOR);
33847938Smarc 	return(0);
33947938Smarc }
34047938Smarc #endif	/* SXT */
34147938Smarc 
34247938Smarc int close_jobs()
34347938Smarc {
34447938Smarc 	register struct process *pw = pwlist;
34547938Smarc 	register int count = 0;
34647938Smarc 	if((states&MONITOR)==0)
34747938Smarc 		return(0);
34847938Smarc # ifdef SXT
34947938Smarc 	for(;pw;pw=pw->p_next)
35047938Smarc 	{
35147938Smarc 		if((pw->p_flag&P_STOPPED)==0)
35247938Smarc 			continue;
35347938Smarc 		if(beenhere)
35447938Smarc 			kill(-pw->p_pgrp,SIGTERM);
35547938Smarc 		count++;
35647938Smarc 	}
35747938Smarc # endif /* SXT */
35847938Smarc 	if(beenhere++ == 0 && pwlist && login_sh)
35947938Smarc # ifdef SXT
36047938Smarc 	{
36147938Smarc 		if(count)
36247938Smarc 		{
36347938Smarc 			fputs(j_terminate,output);
36447938Smarc 			return(-1);
36547938Smarc 		}
36647938Smarc 		if(login_sh || jobstat.maxjob)
36747938Smarc # endif /* SXT */
36847938Smarc 		{
36947938Smarc 			fputs(j_running,output);
37047938Smarc 			return(-1);
37147938Smarc 		}
37247938Smarc # ifdef SXT
37347938Smarc 	}
37447938Smarc 	if(jobstat.maxjob)
37547938Smarc 		kill_all();
37647938Smarc # endif /* SXT */
37747938Smarc 	return(0);
37847938Smarc }
37947938Smarc 
38047938Smarc #endif	/* !BSD */
38147938Smarc 
38247938Smarc static int set_job(pw)
38347938Smarc register struct process *pw;
38447938Smarc {
38547938Smarc 	/* save current terminal state */
38647938Smarc #if defined(BSD) && !defined(POSIX)
38747938Smarc 	ioctl(2,TIOCGETP,&my_stty);
38847938Smarc #else
38947938Smarc 	ioctl(2,TCGETA,&my_stty);
39047938Smarc #endif	/* BSD */
39147938Smarc #ifdef SXT
39247938Smarc 	/* make sure child has opened channel */
39347938Smarc 	if(jobstat.pipe[0] > 0)
39447938Smarc 	{
39547938Smarc 		read(jobstat.pipe[0],&tinybuf,1);
39647938Smarc 		close(jobstat.pipe[0]);
39747938Smarc 		jobstat.pipe[0] = 0;
39847938Smarc 	}
39947938Smarc 	if(pw->p_job < jobstat.maxjob)
40047938Smarc 		if(ioctl(2,SXTIOCSWTCH,pw->p_job)!=0)
40147938Smarc 		{
40247938Smarc 			return(-1);
40347938Smarc 		}
40447938Smarc #endif	/* SXT */
40547938Smarc 	if(pw->p_flag&P_STTY)
40647938Smarc 	{
40747938Smarc 		/* restore terminal state for job */
40847938Smarc #if defined(BSD) && !defined(POSIX)
40947938Smarc 		ioctl(2,TIOCSETN,&pw->p_stty);
41047938Smarc #else
41147938Smarc 		ioctl(2,TCSETAF,&pw->p_stty);
41247938Smarc #endif	/* BSD */
41347938Smarc 	}
41447938Smarc #ifdef BSD
41547938Smarc 	if(ioctl(2,TIOCSPGRP,&pw->p_pgrp) !=0)
41647938Smarc 		return(-1);
41747938Smarc #endif	/* BSD */
41847938Smarc 	return(0);
41947938Smarc }
42047938Smarc 
42147938Smarc static int	reset_ttygrp(pw,flag)
42247938Smarc register struct process *pw;
42347938Smarc {
42447938Smarc 	/* save the terminal state for current job */
42547938Smarc #ifdef BSD
42647938Smarc 	if(ioctl(2,TIOCSPGRP,&jobstat.mypid) !=0)
42747938Smarc 	{
42847938Smarc 		return(-1);
42947938Smarc 	}
43047938Smarc #endif	/* BSD */
43147938Smarc #ifdef SXT
43247938Smarc 	if(pw && pw->p_job < jobstat.maxjob)
43347938Smarc 	{
43447938Smarc 		/* save the state of terminated process */
43547938Smarc 		if(flag==0 && fd_chan>=0)
43647938Smarc 		{
43747938Smarc 			if(ioctl(fd_chan,TCGETA,&pw->p_stty)==0)
43847938Smarc 			{
43947938Smarc 				my_stty = pw->p_stty;
44047938Smarc 				/* for timing problem */
44147938Smarc 				ioctl(fd_chan,TCSETAW,&my_stty);
44247938Smarc 			}
44347938Smarc 		}
44447938Smarc 		close(fd_chan);
44547938Smarc 		fd_chan = -1;
44647938Smarc 		/* grab control in channel 0 */
44747938Smarc 		ioctl(2,TCSETAW,&my_stty);
44847938Smarc 		if(ioctl(2,SXTIOCSWTCH,0)!=0)
44947938Smarc 		{
45047938Smarc 			return(-1);
45147938Smarc 		}
45247938Smarc 		if(flag==0)
45347938Smarc 			ioctl(2,TCSETAW,&my_stty);
45447938Smarc 		beenhere = 0;
45547938Smarc 		return(0);
45647938Smarc 	}
45747938Smarc #endif	/* SXT */
45847938Smarc 	if(pw && flag)
45947938Smarc 	{
46047938Smarc #if defined(BSD) && !defined(POSIX)
46147938Smarc 		if(ioctl(2,TIOCGETP,&pw->p_stty) == 0)
46247938Smarc #else
46347938Smarc 		if(ioctl(2,TCGETA,&pw->p_stty) == 0)
46447938Smarc #endif	/* BSD */
46547938Smarc 			pw->p_flag |= P_STTY;
46647938Smarc 		/* restore terminal state for job */
46747938Smarc #if defined(BSD) && !defined(POSIX)
46847938Smarc 		ioctl(2,TIOCSETN,&my_stty);
46947938Smarc #else
47047938Smarc 		ioctl(2,TCSETAF,&my_stty);
47147938Smarc #endif	/* BSD */
47247938Smarc 	}
47347938Smarc 	beenhere = 0;
47447938Smarc 	return(0);
47547938Smarc }
47647938Smarc 
47747938Smarc #if BSD || SXT
47847938Smarc 
47947938Smarc /*
48047938Smarc  * move job to foreground if bgflag == 0
48147938Smarc  * move job to background if bgflag != 0
48247938Smarc  */
48347938Smarc 
48447938Smarc switch_jobs(ajob,bgflag)
48547938Smarc register char *ajob;
48647938Smarc {
48747938Smarc 	register struct process *pw=NULL;
48847938Smarc 	register int pgrp;
48947938Smarc # ifdef SXT
49047938Smarc 	if(jobstat.maxjob==0)
49147938Smarc 		return(NULL);
49247938Smarc # endif /* SXT */
49347938Smarc 	if(*ajob)
49447938Smarc 		pw = pgrp_jobs(ajob);
49547938Smarc 	else if(pwlist)
49647938Smarc 		pw = job_bynum((int)pwlist->p_job);
49747938Smarc 	if(pw)
49847938Smarc 	{
49947938Smarc 		if(bgflag)
50047938Smarc 		{
50147938Smarc 			pgrp = pw->p_pgrp;
50247938Smarc 			if(pw->p_flag&P_STOPPED)
50347938Smarc 			{
50447938Smarc 				p_sub((int)pw->p_job,'\t');
50547938Smarc 				pr_jobname(pw,'&',0L);
50647938Smarc 				fputs(j_amp,output);
50747938Smarc 				unstop(pgrp);
50847938Smarc 			}
50947938Smarc 		}
51047938Smarc 		else
51147938Smarc 		{
51247938Smarc 			pw_unlink(pw);
51347938Smarc 			pw->p_next = pwlist;
51447938Smarc 			pwlist = pw;
51547938Smarc 			pr_jobname(pw,'&',0L);
51647938Smarc 			newline();
51747938Smarc 			await(pw->p_pid,3);
51847938Smarc 		}
51947938Smarc 	}
52047938Smarc 	return(pw!=NULL);
52147938Smarc }
52247938Smarc 
52347938Smarc /*
52447938Smarc  * list the current jobs
52547938Smarc  * flag L_FLAG for long listing
52647938Smarc  * flag N_FLAG for list only jobs marked for notification
52747938Smarc  */
52847938Smarc #endif	/* BSD */
52947938Smarc 
53047938Smarc list_jobs(flag)
53147938Smarc int flag;
53247938Smarc {
53347938Smarc 	register struct process *pw;
53447938Smarc 	register struct process *px;
53547938Smarc 	register int m;
53647938Smarc 	register struct process *py;
53747938Smarc 	int  n;
53847938Smarc 	long offset;
53947938Smarc 	int jobm = 0;
54047938Smarc 	register char *msg;
54147938Smarc 	int msize;
54247938Smarc 	if(pwlist==NULL)
54347938Smarc 		return;
54447938Smarc 	await(0,2);
54547938Smarc 	p_setout(standout);
54647938Smarc 	/* get job number corresponding to '-' */
54747938Smarc 	if(pw=pgrp_jobs("%-"))
54847938Smarc 		jobm = pw->p_job;
54947938Smarc 	for(pw=pwlist;pw;pw=py)
55047938Smarc 	{
55147938Smarc 		py = pw->p_next;
55247938Smarc 		if(pw->p_flag&P_PIPEJOB)
55347938Smarc 			continue;
55447938Smarc 		if((flag&N_FLAG) && (pw->p_flag&P_NOTIFY)==0)
55547938Smarc 			continue;
55647938Smarc 		n = pw->p_job;
55747938Smarc 		p_sub(n,' ');
55847938Smarc 		m = ' ';
55947938Smarc 		if(pw->p_job==pwlist->p_job)
56047938Smarc 			m = '+';
56147938Smarc 		else if(pw->p_job==jobm)
56247938Smarc 		{
56347938Smarc 			m = '-';
56447938Smarc 			jobm = 0;
56547938Smarc 		}
56647938Smarc 		putc(m,output);
56747938Smarc 		putc(' ',output);
56847938Smarc 		offset = 0;
56947938Smarc 		if(flag&L_FLAG)
57047938Smarc 			px = next_proc(pwlist,(int)pw->p_job);
57147938Smarc 		else
57247938Smarc 			px = pw;
57347938Smarc 		do
57447938Smarc 		{
57547938Smarc 			unsigned xitval = 0;
57647938Smarc 			if(flag&L_FLAG)
57747938Smarc 				p_num(px->p_pid,'\t');
57847938Smarc 			if(px->p_sig&0177)
57947938Smarc 				msg = sysmsg[px->p_sig&0177];
58047938Smarc 			else if(px->p_flag&P_NOTIFY)
58147938Smarc 			{
58247938Smarc 				msg = j_Done;
58347938Smarc 				xitval = px->p_sig>>8;
58447938Smarc 			}
58547938Smarc 			else
58647938Smarc 				msg = j_Running;
58747938Smarc 			fputs(msg,output);
58847938Smarc 			msize = strlen(msg);
58947938Smarc 			if(xitval)
59047938Smarc 			{
59147938Smarc 				putc('(',output);
59247938Smarc 				p_num((int)xitval,')');
59347938Smarc 				msize += (3+(xitval>10)+(xitval>100));
59447938Smarc 			}
59547938Smarc 			if(px->p_flag&P_COREDUMP)
59647938Smarc 			{
59747938Smarc 				fputs(j_coredump,output);
59847938Smarc 				msize += strlen(j_coredump);
59947938Smarc 			}
60047938Smarc 			p_nchr(SP,MAXMSG-msize);
60147938Smarc 			if(flag&L_FLAG)
60247938Smarc 				px = next_proc(px->p_next,(int)pw->p_job);
60347938Smarc 			else
60447938Smarc 				px = NULL;
60547938Smarc 			offset = pr_jobname(pw,(px?'|':0),offset);
60647938Smarc 			if(flag&L_FLAG)
60747938Smarc 			{
60847938Smarc 				if(px)
60947938Smarc 					fputs(j_space,output);
61047938Smarc 				else if(pw->p_pid == cpid)
61147938Smarc 					fputs(j_cpid,output);
61247938Smarc 			}
61347938Smarc 		}
61447938Smarc 		while(px);
61547938Smarc 		if(pw->p_flag&P_STOPPED)
61647938Smarc 			pw->p_flag &= ~P_NOTIFY;
61747938Smarc 		else if(pw->p_flag&P_NOTIFY)
61847938Smarc 		{
61947938Smarc 			unpost(pw);
62047938Smarc 			if(jobm && (px=pgrp_jobs("%-")))
62147938Smarc 				jobm = px->p_job;
62247938Smarc 		}
62347938Smarc 	}
62447938Smarc }
62547938Smarc 
62647938Smarc /*
62747938Smarc  * return the pointer of next process with given job number after slot px
62847938Smarc  */
62947938Smarc 
63047938Smarc static struct process * next_proc(pw,job)
63147938Smarc register struct process *pw;
63247938Smarc register int job;
63347938Smarc {
63447938Smarc 	for(;pw;pw=pw->p_next)
63547938Smarc 	{
63647938Smarc 		if(pw->p_job == job)
63747938Smarc 			return(pw);
63847938Smarc 	}
63947938Smarc 	return(NULL);
64047938Smarc }
64147938Smarc 
64247938Smarc /*
64347938Smarc  * print the command
64447938Smarc  * Stop the output if character <ch> encountered
64547938Smarc  */
64647938Smarc 
64747938Smarc static long pr_jobname(pw,ch,offset)
64847938Smarc register struct process *pw;
64947938Smarc register long offset;
65047938Smarc int ch;
65147938Smarc {
65247938Smarc 	if(fc_fix)
65347938Smarc 	{
65447938Smarc 		offset = hist_list(pw->p_name+offset,ch,";");
65547938Smarc 		offset -= pw->p_name;
65647938Smarc 	}
65747938Smarc 	return(++offset);
65847938Smarc }
65947938Smarc 
66047938Smarc /*
66147938Smarc  * get the process group given the job number
66247938Smarc  * This routine returns the process group number or -1
66347938Smarc  */
66447938Smarc 
66547938Smarc static struct process *pgrp_jobs(ajob)
66647938Smarc register char *ajob;
66747938Smarc {
66847938Smarc 	register struct process *pw;
66947938Smarc 	register int c;
67047938Smarc 	if(*ajob++ != '%' || pwlist==NULL)
67147938Smarc 		return(NULL);
67247938Smarc 	c = *ajob;
67347938Smarc 	if(isdigit(c))
67447938Smarc 		pw = job_bynum(atoi(ajob));
67547938Smarc 	else if(c=='+' || c=='%')
67647938Smarc 		pw = job_bynum((int)pwlist->p_job);
67747938Smarc 	else if(c=='-')
67847938Smarc 	{
67947938Smarc 		/* find the second jobnumber on the list */
68047938Smarc 		for(pw=pwlist->p_next;pw && pw->p_job==pwlist->p_job;pw=pw->p_next);
68147938Smarc 		if(pw==NULL)
68247938Smarc 			return(pw);
68347938Smarc 		pw = job_bynum((int)pw->p_job);
68447938Smarc 	}
68547938Smarc 	else
68647938Smarc 		pw = jobbyname(ajob);
68747938Smarc 	if(pw && pw->p_flag)
68847938Smarc 		return(pw);
68947938Smarc 	return(NULL);
69047938Smarc }
69147938Smarc 
69247938Smarc /*
69347938Smarc  * send a hang-up signal to each of the jobs
69447938Smarc  */
69547938Smarc int kill_all()
69647938Smarc {
69747938Smarc 	register struct process *pw = pwlist;
69847938Smarc 	for(;pw;pw=pw->p_next)
69947938Smarc 	{
70047938Smarc 		if(pw->p_pgrp == pw->p_pid)
70147938Smarc 		{
70247938Smarc #ifdef BSD
70347938Smarc 			unstop(pw->p_pgrp);
70447938Smarc 			killpg(pw->p_pgrp,SIGHUP);
70547938Smarc #else
70647938Smarc 			kill(-pw->p_pgrp,SIGHUP);
70747938Smarc #endif	/* BSD */
70847938Smarc 		}
70947938Smarc 	}
71047938Smarc }
71147938Smarc 
71247938Smarc /*
71347938Smarc  * Kill a job or process
71447938Smarc  */
71547938Smarc 
71647938Smarc int job_kill(job,sig)
71747938Smarc register char *job;
71847938Smarc int sig;
71947938Smarc {
72047938Smarc 	register char *rjob = job;
72147938Smarc 	register struct process *pw;
72247938Smarc 	register int pid;
72347938Smarc 	register int r;
72447938Smarc 	char *msg;
72547938Smarc 	if(*rjob == '%')
72647938Smarc 	{
72747938Smarc 		if(pw=pgrp_jobs(rjob))
72847938Smarc 		{
72947938Smarc #ifdef BSD
73047938Smarc 			r = unstop(pw->p_pgrp);
73147938Smarc 			if(sig!=SIGCONT || r < 0)
73247938Smarc 				r = killpg(pw->p_pgrp,sig);
73347938Smarc #else
73447938Smarc 			pid = pw->p_pgrp;
73547938Smarc 			if(states&MONITOR)
73647938Smarc 				pid = -pid;
73747938Smarc 			r = kill(pid,sig);
73847938Smarc #endif	/* BSD */
73947938Smarc 		}
74047938Smarc 		else
74147938Smarc 		{
74247938Smarc 			r = -1;
74347938Smarc 			errno = ESRCH;
74447938Smarc 		}
74547938Smarc 	}
74647938Smarc 	else
74747938Smarc 	{
74847938Smarc 		pid = atoi(rjob);
74947938Smarc 		if(pid==0 && *rjob != '0')
75047938Smarc 			failed(bkill,kill_usage);
75147938Smarc #ifdef BSD
75247938Smarc 		if(sig==SIGSTOP && pid==jobstat.mypid && (login_sh || ppid==1))
75347938Smarc 		{
75447938Smarc 		/* can't stop login shell */
75547938Smarc 			errno = EPERM;
75647938Smarc 			r = -1;
75747938Smarc 		}
75847938Smarc 		else
75947938Smarc 		{
76047938Smarc 			if((pw=job_bypid(pid)) && (pw->p_flag&P_STOPPED))
76147938Smarc 			{
76247938Smarc 				pw->p_flag &= ~P_STOPPED;
76347938Smarc 				numrun++;
76447938Smarc 				kill(pid,SIGCONT);
76547938Smarc 			}
76647938Smarc 			r = kill(pid,sig);
76747938Smarc 		}
76847938Smarc #else
76947938Smarc 		r = kill(pid,sig);
77047938Smarc #endif	/* BSD */
77147938Smarc 	}
77247938Smarc 	if(r<0)
77347938Smarc 	{
77447938Smarc 		p_setout(stderr);
77547938Smarc 		fputs(j_kill,output);
77647938Smarc 		if(*rjob == '%')
77747938Smarc 			msg = j_no_job;
77847938Smarc 		else
77947938Smarc 			msg = j_no_proc;
78047938Smarc 		p_str(rjob,':');
78147938Smarc 		if(errno == EPERM)
78247938Smarc 			msg = j_perm;
78347938Smarc 		p_str(msg,NL);
78447938Smarc 		r = 1;
78547938Smarc 	}
78647938Smarc 	return(r);
78747938Smarc }
78847938Smarc 
78947938Smarc /*
79047938Smarc  * Get process structure from job number
79147938Smarc  */
79247938Smarc 
79347938Smarc static struct process *job_bynum(num)
79447938Smarc register int num;
79547938Smarc {
79647938Smarc 	register struct process *pw = pwlist;
79747938Smarc 	for(;pw;pw=pw->p_next)
79847938Smarc 	{
79947938Smarc 		if((pw->p_flag&(P_PIPEJOB|P_WAITED)) == P_PIPEJOB)
80047938Smarc 			continue;
80147938Smarc 		if(pw->p_job == num)
80247938Smarc 			return(pw);
80347938Smarc 	}
80447938Smarc 	return(NULL);
80547938Smarc }
80647938Smarc 
80747938Smarc /*
80847938Smarc  * Get process structure from first letters of jobname
80947938Smarc  *
81047938Smarc  */
81147938Smarc 
81247938Smarc static struct process *jobbyname(name)
81347938Smarc char *name;
81447938Smarc {
81547938Smarc 	register struct process *pw = pwlist;
81647938Smarc 	register struct fixcmd *fp = fc_fix;
81747938Smarc 	if(fp==NULL)
81847938Smarc 		return(NULL);
81947938Smarc 	for(;pw;pw=pw->p_next)
82047938Smarc 	{
82147938Smarc 		if((pw->p_flag&(P_PIPEJOB|P_WAITED)) == P_PIPEJOB)
82247938Smarc 			continue;
82347938Smarc 		if(match_jobname(fp->fixfd,pw,name))
82447938Smarc 			goto retrn;
82547938Smarc 	}
82647938Smarc 	pw = NULL;
82747938Smarc retrn:
82847938Smarc 	return(pw);
82947938Smarc }
83047938Smarc 
83147938Smarc 
83247938Smarc /*
83347938Smarc  * match the name to the command starting with given name
83447938Smarc  */
83547938Smarc 
83647938Smarc static int	match_jobname(fdi,pw,name)
83747938Smarc FILE *fdi;
83847938Smarc register struct process *pw;
83947938Smarc char *name;
84047938Smarc {
84147938Smarc 	register int c;
84247938Smarc 	register char *sp;
84347938Smarc 	if(fdi && pw->p_name>0)
84447938Smarc 	{
84547938Smarc 		fseek(fdi,pw->p_name,0);
84647938Smarc 		for(sp=name;*sp;sp++)
84747938Smarc 		{
84847938Smarc 			c = getc(fdi);
84947938Smarc 			if(c != *sp)
85047938Smarc 				return(0);
85147938Smarc 		}
85247938Smarc 		return(1);
85347938Smarc 	}
85447938Smarc 	return(0);
85547938Smarc }
85647938Smarc 
85747938Smarc 
85847938Smarc 
85947938Smarc /*
86047938Smarc  * Initialize the process posting array
86147938Smarc  */
86247938Smarc 
86347938Smarc void	postclr()
86447938Smarc {
86547938Smarc 	register struct process *pw = pwlist;
86647938Smarc 	register struct process *px;
86747938Smarc 	register int j = JBYTES;
86847938Smarc 	for(;pw;pw=px)
86947938Smarc 	{
87047938Smarc 		px = pw->p_next;
87147938Smarc 		free((char*)pw);
87247938Smarc 	}
87347938Smarc 	pwlist = NULL;
87447938Smarc 	numpost=0;
87547938Smarc 	numrun = 0;
87647938Smarc 	while(--j >=0)
87747938Smarc 		freejobs[j]  = 0;
87847938Smarc }
87947938Smarc 
88047938Smarc /*
88147938Smarc  * put the process <pcsid> on the process list and return the job number
88247938Smarc  * turn on the specified flag bits.
88347938Smarc  */
88447938Smarc 
88547938Smarc int post(pid,flag)
88647938Smarc int pid;
88747938Smarc {
88847938Smarc 	register struct process *pw;
88947938Smarc 	if(pw=job_post(pid))
89047938Smarc 	{
89147938Smarc 		pw->p_flag |= flag;
89247938Smarc 		return(pw->p_job);
89347938Smarc 	}
89447938Smarc 	return(-1);
89547938Smarc }
89647938Smarc 
89747938Smarc /*
89847938Smarc  * internal version of post, this routine returns a process structure
89947938Smarc  */
90047938Smarc 
90147938Smarc static struct process *job_post(pcsid)
90247938Smarc int 	pcsid;
90347938Smarc {
90447938Smarc 	register struct process  *pw = pwlist;
90547938Smarc 	register struct process  *px=NULL;
90647938Smarc 	register struct fixcmd *fp = fc_fix;
90747938Smarc 	if(pcsid)
90847938Smarc 	{
90947938Smarc 		for(;pw;pw=pw->p_next)
91047938Smarc 		{
91147938Smarc 			if(pw->p_pid==pcsid)
91247938Smarc 				return(pw);
91347938Smarc 			if(pw->p_pgrp == jobstat.cur_pgrp)
91447938Smarc 				px = pw;
91547938Smarc 		}
91647938Smarc 		if(pw=freelist)
91747938Smarc 			freelist = pw->p_next;
91847938Smarc 		else if((pw=(struct process*)malloc(sizeof(struct process)))==NULL)
91947938Smarc 			error(nospace);
92047938Smarc 		numrun++;
92147938Smarc 		numpost++;
92247938Smarc 		if(px)
92347938Smarc 		{
92447938Smarc 			pw->p_next = px->p_next;
92547938Smarc 			px->p_next = pw;
92647938Smarc 			pw->p_job = px->p_job;
92747938Smarc 		}
92847938Smarc 		else
92947938Smarc 		{
93047938Smarc 			/* put at front of list */
93147938Smarc 			pw->p_next = pwlist;
93247938Smarc 			pw->p_job = get_job();
93347938Smarc 			pwlist = pw;
93447938Smarc 		}
93547938Smarc 		pw->p_pid = pcsid;
93647938Smarc 		pw->p_flag = P_RUNNING;
93747938Smarc 		pw->p_pgrp = jobstat.cur_pgrp;
93847938Smarc 		if(fp!=NULL)
93947938Smarc 			pw->p_name=hist_position(fp->fixind-1);
94047938Smarc 		else
94147938Smarc 			pw->p_name = -1;
94247938Smarc 		pw->p_sig = 0;
94347938Smarc 		if(numpost >= MAXJ-1)
94447938Smarc 			await(0,0);
94547938Smarc 		return(pw);
94647938Smarc 	}
94747938Smarc 	return(NULL);
94847938Smarc }
94947938Smarc 
95047938Smarc /*
95147938Smarc  * get job number given the process id
95247938Smarc  */
95347938Smarc 
95447938Smarc static struct process *job_bypid(pid)
95547938Smarc register int pid;
95647938Smarc {
95747938Smarc 	register struct process *pw;
95847938Smarc 	if(pid==0)
95947938Smarc 		return(NULL);
96047938Smarc 	for(pw=pwlist;pw;pw=pw->p_next)
96147938Smarc 	if(pw->p_pid == pid)
96247938Smarc 			break;
96347938Smarc 	return(pw);
96447938Smarc }
96547938Smarc 
96647938Smarc /*
96747938Smarc  * Wait for process i to complete
96847938Smarc  * flag=1 when wait builtin invoked so that it can be interrupted
96947938Smarc  * flag=2 to check for waiting processes and return
97047938Smarc  * flag=3 to resume job in foreground
97147938Smarc  * i=0 to wait for any process
97247938Smarc  * i=-1 to wait for all runing processes
97347938Smarc  */
97447938Smarc 
97547938Smarc void	await(i, flag)
97647938Smarc register int 	i;
97747938Smarc int 	flag;
97847938Smarc {
97947938Smarc 	int 	rc=0;
98047938Smarc 	int 	w;
98147938Smarc 	int my_job = -1;
98247938Smarc #ifdef BSD
98347938Smarc 	union wait wstat;
98447938Smarc #endif	/* BSD */
98547938Smarc 	register struct process *pw = NULL;
98647938Smarc 	struct process *px;
98747938Smarc 	if(i!= -1 && i)
98847938Smarc 	{
98947938Smarc 		if(flag)
99047938Smarc 		{
99147938Smarc 			pw = job_bypid(i);
99247938Smarc 			if(flag==3 && pw)
99347938Smarc 				flag = 0;
99447938Smarc 		}
99547938Smarc 		else
99647938Smarc 			pw = job_post(i);
99747938Smarc 		if(flag)
99847938Smarc 		{
99947938Smarc 			if(pw==0 || (pw->p_flag&P_STOPPED))
100047938Smarc 			return;
100147938Smarc 		}
100247938Smarc 		my_job = pw->p_job;
100347938Smarc 	}
100447938Smarc 	if(flag==0 && (states&MONITOR) && pw)
100547938Smarc 	{
100647938Smarc 		set_job(pw);
100747938Smarc 		/* if job is stopped, resume it in the background */
100847938Smarc #if BSD || SXT
100947938Smarc 		if(pw->p_flag&P_STOPPED)
101047938Smarc 			unstop(pw->p_pgrp);
101147938Smarc # ifdef SXT
101247938Smarc 		if(pw->p_job < jobstat.maxjob)
101347938Smarc 			open_chan(pw->p_job);
101447938Smarc # endif /* SXT */
101547938Smarc #endif	/* BSD */
101647938Smarc 	}
101747938Smarc 	p_flush();
101847938Smarc 	while(numrun>0)
101947938Smarc 	{
102047938Smarc 		register int 	p;
102147938Smarc 		register int 	sig;
102247938Smarc 		register int 	w_hi;
102347938Smarc #ifdef BSD
102447938Smarc 		if(is_option(MONITOR) || flag==2)
102547938Smarc 		{
102647938Smarc 		retry:
102747938Smarc 			errno = 0;
102847938Smarc 			sig = sighold(SIGCHLD);
102947938Smarc 			trapnote &= ~SIGJOBS;
103047938Smarc 			p=wait3(&wstat,WNOHANG|WUNTRACED,0);
103147938Smarc 			errno = 0;
103247938Smarc 			if(p==0 && flag!=2)
103347938Smarc 			{
103447938Smarc # ifdef BSD_4_2
103547938Smarc 				sigpause(sig&~(1<<(SIGCHLD-1)));
103647938Smarc # else
103747938Smarc 				sigpause(SIGCHLD);
103847938Smarc # endif /* BSD_4_2 */
103947938Smarc 				if(errno==EINTR && flag==1 && (trapnote&SIGJOBS)==0)
104047938Smarc 					break;
104147938Smarc 				goto retry;
104247938Smarc 			}
104347938Smarc 			trapnote &= ~SIGJOBS;
104447938Smarc 			sigrelse(SIGCHLD);
104547938Smarc 			if(p==0 || p== -1)
104647938Smarc 				return;
104747938Smarc 			w = wstat.w_status;
104847938Smarc 			pw = job_bypid(p);
104947938Smarc 			if(pw->p_job == my_job && (states&MONITOR))
105047938Smarc 			{
105147938Smarc 				register int ssig = wstat.w_S.w_Stopsig;
105247938Smarc 				if(WIFSTOPPED(wstat) && (ssig==SIGTTIN||ssig==SIGTTOU))
105347938Smarc 				{
105447938Smarc 					/* job stopped before it got terminal */
105547938Smarc 					killpg(pw->p_pgrp,SIGCONT);
105647938Smarc 					continue;
105747938Smarc 				}
105847938Smarc 				if(p==i)
105947938Smarc 					reset_ttygrp(pw,w&LOBYTE);
106047938Smarc 			}
106147938Smarc 		}
106247938Smarc 		else
106347938Smarc #endif	/* BSD */
106447938Smarc 		{
106547938Smarc #ifndef BSD
106647938Smarc # ifdef SXT
106747938Smarc 			if(jobstat.maxjob >0)
106847938Smarc 			{
106947938Smarc 				/* check for job status change */
107047938Smarc 				status1 = status2;
107147938Smarc 				status2.input = status2.output = 0;
107247938Smarc 				if(ioctl(2,SXTIOCSTAT,&status2)!=0)
107347938Smarc 				{
107447938Smarc 					jobstat.maxjob = 0;
107547938Smarc 				}
107647938Smarc 				else if(status1.input != status2.input)
107747938Smarc 				{
107847938Smarc 					status_update(status2.input,status1.input,SIGSTIN);
107947938Smarc 				}
108047938Smarc 				else if(status1.output != status2.output)
108147938Smarc 				{
108247938Smarc 					status_update(status2.output,status1.output,SIGSTOP);
108347938Smarc 				}
108447938Smarc 			}
108547938Smarc # endif /* SXT */
108647938Smarc 			/* enable fault handler to see if there are any pending jobs */
108747938Smarc 			if((trapnote&SIGJOBS)==0)
108847938Smarc 				signal(SIGCLD,fault);
108947938Smarc 			if(flag==2 && (trapnote&SIGJOBS)==0)
109047938Smarc 				return;
109147938Smarc # ifdef SXT
109247938Smarc 			if(my_job>=0 && (trapnote&SIGJOBS)==0 && jobstat.maxjob)
109347938Smarc 			{
109447938Smarc 				errno = 0;
109547938Smarc 		        	p = ioctl(2, SXTIOCWF, 0);
109647938Smarc 				if(p==0)
109747938Smarc 					/* job stopped */
109847938Smarc 				{
109947938Smarc        		         		ioctl(2, SXTIOCBLK, my_job);
110047938Smarc 					if(fd_chan>=0)
110147938Smarc 					{
110247938Smarc 						if(ioctl(fd_chan,TCFLSH,2)!=0)
110347938Smarc 						{
110447938Smarc 							;
110547938Smarc 						}
110647938Smarc 					}
110747938Smarc 					pw->p_flag |= (P_NOTIFY|P_STOPPED);
110847938Smarc 					pw->p_sig = SIGSTOP;
110947938Smarc 					reset_ttygrp(pw,1);
111047938Smarc 					break;
111147938Smarc 				}
111247938Smarc 			}
111347938Smarc # endif /* SXT */
111447938Smarc #endif	/* BSD */
111547938Smarc 			trapnote &= ~ SIGJOBS;
111647938Smarc 			p=wait(&w);
111747938Smarc 			if(p== -1)
111847938Smarc 			{
111947938Smarc 				if(errno==ECHILD)
112047938Smarc 				{
112147938Smarc 					postclr();
112247938Smarc 					return;
112347938Smarc 				}
112447938Smarc 				else if(errno==EINTR)
112547938Smarc 				{
112647938Smarc 					if(trapnote&SIGJOBS)
112747938Smarc 						continue;
112847938Smarc 					if(flag)
112947938Smarc 						break;
113047938Smarc 				}
113147938Smarc 				continue;
113247938Smarc 			}
113347938Smarc 			trapnote &= ~ SIGJOBS;
113447938Smarc 			pw = job_bypid(p);
113547938Smarc #ifdef SXT
113647938Smarc 			pw->p_flag &= ~P_STOPPED;
113747938Smarc #endif	/* SXT */
113847938Smarc 			/* restore original tty state if jobs aborted */
113947938Smarc 			if(p == i && (states&MONITOR))
114047938Smarc 				reset_ttygrp(pw,w&LOBYTE);
114147938Smarc 		}
114247938Smarc 		if(pw)
114347938Smarc 		{
114447938Smarc 			numrun--;
114547938Smarc 			pw->p_flag |= P_NOTIFY;
114647938Smarc #ifdef BSD
114747938Smarc 			if((states&MONITOR) && WIFSTOPPED(wstat))
114847938Smarc 				pw->p_flag |= P_STOPPED;
114947938Smarc 			else
115047938Smarc #endif	/* BSD */
115147938Smarc 			{
115247938Smarc 				if(p==cpid)
115347938Smarc 				{
115447938Smarc 					cpid = 0;
115547938Smarc 					cpipe[1] = NULL;
115647938Smarc 				}
115747938Smarc 				if(p==i || (states&MONITOR)==0)
115847938Smarc 				{
115947938Smarc 					if(px=unpost(pw))
116047938Smarc 					{
116147938Smarc 						if(i)
116247938Smarc 						{
116347938Smarc 							if(p==i && (states&MONITOR))
116447938Smarc 								set_job(px);
116547938Smarc 							i = px->p_pid;
116647938Smarc 						}
116747938Smarc 						continue;
116847938Smarc 					}
116947938Smarc 				}
117047938Smarc 			}
117147938Smarc 		}
117247938Smarc 		sig = w&0177;
117347938Smarc 		if(states&MONITOR)
117447938Smarc 		{
117547938Smarc #ifdef BSD
117647938Smarc 			if(WIFSTOPPED(wstat))
117747938Smarc 			{
117847938Smarc 				if(pw)
117947938Smarc 					pw->p_sig = wstat.w_S.w_Stopsig;
118047938Smarc 				if(p == i)
118147938Smarc 					break;
118247938Smarc 				continue;
118347938Smarc 			}
118447938Smarc 			else if(p!=i)
118547938Smarc #else
118647938Smarc 			if(p!=i)
118747938Smarc #endif	/* BSD */
118847938Smarc 			{
118947938Smarc 				if(pw)
119047938Smarc 					pw->p_sig = w;
119147938Smarc 				if(w&HIGHBIT)
119247938Smarc 					pw->p_flag |= P_COREDUMP;
119347938Smarc 				continue;
119447938Smarc 			}
119547938Smarc 			/* this is needed since child not in same process group */
119647938Smarc 			else if(sig==SIGINT || sig==SIGQUIT || sig==SIGHUP)
119747938Smarc 				fault(sig);
119847938Smarc 		}
119947938Smarc 		w_hi = (w>>8)&LOBYTE;
120047938Smarc 		if(sig)
120147938Smarc 		{
120247938Smarc 			if(sig == 0177	/* ptrace! return */)
120347938Smarc 			{
120447938Smarc 				fputs(ptrace,output);
120547938Smarc 				sig = w_hi;
120647938Smarc 			}
120747938Smarc 			if(sig!=SIGINT && sig!=SIGPIPE)
120847938Smarc 			{
120947938Smarc 				if(i!=p || (states&PROMPT)==0)
121047938Smarc 					p_prp(itos(p),SP);
121147938Smarc 				fputs(sysmsg[sig],output);
121247938Smarc 				if(w&HIGHBIT)
121347938Smarc 					fputs(coredump,output);
121447938Smarc 			}
121547938Smarc 			newline();
121647938Smarc 		}
121747938Smarc 		if(p == i)
121847938Smarc 		{
121947938Smarc 			rc = (sig ? sig|SIGFAIL : w_hi);
122047938Smarc 			break;
122147938Smarc 		}
122247938Smarc 		if(i == 0)
122347938Smarc 			break;
122447938Smarc 	}
122547938Smarc 	if(flag>=2)
122647938Smarc 		return;
122747938Smarc 	exitval=rc;
122847938Smarc 	exitset();
122947938Smarc }
123047938Smarc 
123147938Smarc #if BSD || SXT
123247938Smarc /*
123347938Smarc  * turn off STOP state of a process group
123447938Smarc  */
123547938Smarc 
123647938Smarc static int unstop(grp)
123747938Smarc register int grp;
123847938Smarc {
123947938Smarc 	register struct process *pw;
124047938Smarc 	register int num = numrun;
124147938Smarc 	for(pw=pwlist;pw;pw=pw->p_next)
124247938Smarc 	{
124347938Smarc 		if(pw->p_pgrp != grp)
124447938Smarc 			continue;
124547938Smarc 		if(pw->p_flag&P_STOPPED)
124647938Smarc 		{
124747938Smarc 			num++;
124847938Smarc 			pw->p_flag &= ~P_STOPPED;
124947938Smarc 			pw->p_sig = 0;
125047938Smarc # ifdef SXT
125147938Smarc 			break;
125247938Smarc # endif /* SXT */
125347938Smarc 		}
125447938Smarc 	}
125547938Smarc 	if(num!=numrun)
125647938Smarc 	{
125747938Smarc 		p_flush();
125847938Smarc #ifdef BSD
125947938Smarc 		numrun = num;
126047938Smarc 		return(killpg(grp,SIGCONT));
126147938Smarc #endif
126247938Smarc 	}
126347938Smarc 	return(-1);
126447938Smarc }
126547938Smarc #endif	/* BSD */
126647938Smarc 
126747938Smarc /*
126847938Smarc  * remove a process group from table
126947938Smarc  * If all the processes have not completed then unpost returns
127047938Smarc  * the structure pointer  of an unfinished process.
127147938Smarc  * Otherwise NULL is returned.
127247938Smarc  */
127347938Smarc 
127447938Smarc static struct process *unpost(pwtop)
127547938Smarc struct process *pwtop;
127647938Smarc {
127747938Smarc 	register struct process *pw;
127847938Smarc 	register struct process *px=NULL;
127947938Smarc 	register int job = pwtop->p_job;
128047938Smarc 	register struct process *py;
128147938Smarc 	/* look for unfinished processes */
128247938Smarc 	for(pw=pwlist;pw;pw=pw->p_next)
128347938Smarc 	{
128447938Smarc 		if(pw->p_job != job)
128547938Smarc 			continue;
128647938Smarc 		if((pw->p_flag&P_NOTIFY)==0)
128747938Smarc 			px = pw;
128847938Smarc 	}
128947938Smarc 	if(px)
129047938Smarc 	{
129147938Smarc 		px->p_flag &= ~P_PIPEJOB;
129247938Smarc 		px->p_flag |= P_WAITED;
129347938Smarc 		return(px);
129447938Smarc 	}
129547938Smarc 	/* all processes complete, unpost job */
129647938Smarc 	for(pw=pwlist;pw;pw=py)
129747938Smarc 	{
129847938Smarc 		py = pw->p_next;
129947938Smarc 		if(pw->p_job != job)
130047938Smarc 		{
130147938Smarc 			px = pw;
130247938Smarc 			continue;
130347938Smarc 		}
130447938Smarc 		numpost--;
130547938Smarc 		if(px==NULL)
130647938Smarc 			pwlist = py;
130747938Smarc 		else
130847938Smarc 			px->p_next = py;
130947938Smarc 		pw->p_next = freelist;
131047938Smarc 		freelist = pw;
131147938Smarc 	}
131247938Smarc 	free_job((int)pwtop->p_job);
131347938Smarc 	return(NULL);
131447938Smarc }
131547938Smarc 
131647938Smarc /*
131747938Smarc  * unlink a process form the process list
131847938Smarc  */
131947938Smarc 
132047938Smarc static void pw_unlink(pw)
132147938Smarc register struct process *pw;
132247938Smarc {
132347938Smarc 	register struct process *px;
132447938Smarc 	if(pw==pwlist)
132547938Smarc 	{
132647938Smarc 		pwlist = pw->p_next;
132747938Smarc 		return;
132847938Smarc 	}
132947938Smarc 	for(px=pwlist;px;px=px->p_next)
133047938Smarc 		if(px->p_next == pw)
133147938Smarc 		{
133247938Smarc 			px->p_next = pw->p_next;
133347938Smarc 			return;
133447938Smarc 		}
133547938Smarc }
133647938Smarc 
133747938Smarc /*
133847938Smarc  * get an unused job number
133947938Smarc  * freejobs is a bit vector, 0 is unused
134047938Smarc  */
134147938Smarc 
134247938Smarc static int get_job()
134347938Smarc {
134447938Smarc 	register int j=0;
134547938Smarc 	register unsigned mask = 1;
134647938Smarc 	register unsigned char *freeword;
134747938Smarc 	/* skip to first word with a free slot */
134847938Smarc 	while(freejobs[j] == 0xff)
134947938Smarc 		j++;
135047938Smarc 	freeword = &freejobs[j];
135147938Smarc 	j *= 8;
135247938Smarc 	for(j++;mask&(*freeword);j++,mask <<=1);
135347938Smarc 	*freeword  |=mask;
135447938Smarc 	return(j);
135547938Smarc }
135647938Smarc 
135747938Smarc /*
135847938Smarc  * return a job number
135947938Smarc  */
136047938Smarc 
136147938Smarc static void free_job(n)
136247938Smarc register int n;
136347938Smarc {
136447938Smarc 	register int j = (--n)/8;
136547938Smarc 	register unsigned mask;
136647938Smarc 	n -= j*8;
136747938Smarc 	mask = 1 << n;
136847938Smarc 	freejobs[j]  &= ~mask;
136947938Smarc }
137047938Smarc 
137147938Smarc #ifdef SXT
137247938Smarc /*
137347938Smarc  * open up the input streams for a new channel
137447938Smarc  */
137547938Smarc 
137647938Smarc static char *open_mode[3] = {"r","w","w+"};
137747938Smarc j_new_chan()
137847938Smarc {
137947938Smarc 	register FILE* fd;
138047938Smarc 	register int i;
138147938Smarc 	sxt[11] = '0' + jobstat.cur_job;
138247938Smarc 	close(jobstat.pipe[0]);
138347938Smarc 	fd = fopen(sxt,"r+");
138447938Smarc 	if(ioctl(fileno(fd),TCSETA,&my_stty)<0 || fd==NULL)
138547938Smarc 	{
138647938Smarc 		close(jobstat.pipe[1]);
138747938Smarc 		return(0);
138847938Smarc 	}
138947938Smarc 	for(i=0;i<3;i++)
139047938Smarc 	{
139147938Smarc 		if(isatty(i))
139247938Smarc 		{
139347938Smarc 			fclose(file_fd(i));
139447938Smarc 			fdopen(dup(fileno(fd)),open_mode[i]);
139547938Smarc 		}
139647938Smarc 	}
139747938Smarc 	fclose(fd);
139847938Smarc 	write(jobstat.pipe[1],nullstr,1);
139947938Smarc 	close(jobstat.pipe[1]);
140047938Smarc 	return(1);
140147938Smarc }
140247938Smarc 
140347938Smarc int next_job()
140447938Smarc {
140547938Smarc 	register int i = get_job();
140647938Smarc 	free_job(i);
140747938Smarc 	return(i);
140847938Smarc }
140947938Smarc 
141047938Smarc static status_update(mask2,mask1,sigval)
141147938Smarc {
141247938Smarc 	register int i,j;
141347938Smarc 	register struct process *pw;
141447938Smarc 	for(i = 1; i < MAXPCHAN; i++)
141547938Smarc 	{
141647938Smarc 		j = 1<<i;
141747938Smarc 		if((mask1&j)==0 && (mask2&j))
141847938Smarc 		{
141947938Smarc 			if(pw = job_bynum(i))
142047938Smarc 				pw->p_sig = sigval;
142147938Smarc 		}
142247938Smarc 		else if((mask2&j)==0 && (mask1&j))
142347938Smarc 		{
142447938Smarc 			if(pw = job_bynum(i))
142547938Smarc 				pw->p_sig = 0;
142647938Smarc 		}
142747938Smarc 	}
142847938Smarc }
142947938Smarc 
143047938Smarc static int open_chan(j)
143147938Smarc {
143247938Smarc 	sxt[11] = '0' + j;
143347938Smarc 	if(fd_chan>=0)
143447938Smarc 	{
143547938Smarc 		return;
143647938Smarc 	}
143747938Smarc 	fd_chan = open(sxt,2);
143847938Smarc }
143947938Smarc #endif	/* SXT */
144047938Smarc 
144147938Smarc /* XXX */
144247938Smarc #ifdef POSIX
144347938Smarc cfgetospeed(t)
144447938Smarc 	struct termios *t;
144547938Smarc {
144647938Smarc 	return(t->c_ospeed);
144747938Smarc }
144847938Smarc #endif
1449