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