rs@uunet.UU.NET (Rich Salz) (06/24/87)
Submitted by: Simon Brown <simon@its63b.ed.ac.uk>
Archive-name: sxt-sh-jobs/Part01
Mod.sources: Volume 10, Number 18
This is a set of context-diffs to implement job-control in the
System-V Bourne Shell using sxt (layer) devices.
It includes the additional files
proc.c
job.h
README
Makefile
sxtalloc.c
sxtalloc.8
See README for installation details.
To apply the diffs, its easiest to use Larry Wall's "patch" program,
if you have it; otherwise its pretty hard work.
Simon Brown
Department of Computer Science
University of Edinburgh
Scotland, UK.
UUCP: seismo!mcvax!ukc!its63b!simon
(or seismo!mcvax!ukc!cstvax!simon)
ARPA: simon@its63b.ed.ac.uk
(or simon@cstvax.ed.ac.uk)
JANET: simon@uk.ac.ed.its63b
(or simon@uk.ac.ed.cstvax)
------------- cut here -------------- cut here ---------------- cut here ------
#!/bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
# README
# Makefile
# args.c.Diff
# cmd.c.Diff
# defs.c.Diff
# defs.h.Diff
# error.c.Diff
# fault.c.Diff
# io.c.Diff
# job.h
# macro.c.Diff
# main.c.Diff
# msg.c.Diff
# name.c.Diff
# This archive created: Fri Feb 20 17:42:58 1987
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'README'" '(4879 characters)'
if test -f 'README'
then
echo shar: "will not over-write existing file 'README'"
else
cat << \SHAR_EOF > 'README'
System V Bourne Shell with additional sxt job-control features:
There are several pre-processor flags that you can set at the top of "defs.h".
These are:
JOB If you have this defined, then the shell will use
clever job-oriented data-structures. It doesn't produce
code that manipulates them - but it means that the
commands that look at job-stuff will work better -
things like "jobs" or "kill %job", etc...
JOBSXT If you have this defined, in addition to JOB, then
you have access to sxt drivers to manipulate job
control.
JOBSXT_HUP If this is defined, then the shell will do lots
of cleaning up if it should ever receive a SIGHUP
signal. This is sometimes necessary because the
kernel can get very confused about what processes
belong to what groups.
SXT_SUSPEND If this is defined, then the shell will leave the
file-descriptor to the controlling sxt device open
in its children, so they can do "suspend()" calls
to suspend themselves - this is the only way that
programs that use RAW (ie, ~ICANON) mode can be
subject to job-control. The environment variable
"SXT_CONTROL" will contain the numeric value of
this descriptor. To suspend yourself, just do
fd = atoi(getenv("SXT_CONTROL"));
ioctl(fd,SXTIOCSWTCH,0);
(see <sys/sxt.h> for details).
ERCC_SIGCONT Usually it is not possible for programs to know
if they have been suspended (unless they did it
to themselves). If ERCC_SIGCONT is defined, then
the shell will send SIGCONT to jobs whenever they
are resumed. This assumes that you have SIGCONT
defined in <signal.h> (SIGUSR2 is quite good for
this). It will set SIGCONT to be ignored by
children unless they explicitly trap it, so any
programs that use SIGCONT for any other purpose
will stop working if you have this.
BLK_BOTTOM This causes the cursor to be moved to the bottom
of your screen whenever a foreground process becomes
suspended. In fact, it uses termcap/terminfo in my
full-modifications version of the shell, but that's
not available here, so it does it in a stupid way.
You might well not want this.
SSHLIBRARY This should be the directory-name for the place
where the "sxtalloc" program is to be kept. Since
these modifications to the shell are just a subset
of a larger set of modifications forming the "ssh"
shell, the directory "/usr/lib/ssh" is normal.
Note that this must be given with unmatched quotes -
one at the start but NOT at the end; ie,
"/usr/lib/ssh
sysV You will almost certainly have this already
pre-defined by cpp, but define it if you don't. This
is pretty important.
Sxtalloc:
In order to guarentee availability (and security) of sxt terminals,
a setuid-root allocator is provided - "sxtalloc". This should be
placed in the SSHLIBRARY directory. This is used for two purposes:
1. to chown groups of sxt terminals so that they can be used
solely by the intended user and not hijacked midway by
someone else, and
2. to stamp a new entry into /etc/utmp to reflect the fact
that the user's controlling terminal has changed into an sxt.
The old terminal is put back again when the shell has finished
with the sxt.
On allocation, it returns the real tty-name on the standard output, and
this is stored in the shell-parameter $REALTTY, which is automatically
exported if set in this way. Subshells check to see if it is set and
don't bother trying to inititate job-control if it is. It is then
passed back to sxtalloc when the shell de-allocates the sxt.
See the manual entry for details.
DISCLAIMER:
I am fully aware that most of the code to implement this is
incredibly badly written. This reflects the fact that it consists
of little pieces hacked out of a larger shell in a very simple-minded
way (the larger shell also not being exactly the most beautifully-
written program ever). But it seems to work, sort-of'ish ....
If you find any important bugs, please send a summary (and a bug-fix
would be nice) to me at
ARPA: simon@its63b.ed.ac.uk
ARPA: simon@cstvax.ed.ac.uk (alternative address)
UUCP: seismo!mcvax!ukc!{its63b,cstvax}!simon
JANET: simno@uk.ac.ed.{its63b,cstvax}
Finally, I'd better copyright this so some bastard doesn't sell it
for thousands of dollars :-) so:
These modifications are Copyright (c) Simon Brown,
February 1987.
You may use or change them for personal use as much as you
like, but don't try to sell them or pretend that they're
yours ('cos that's not too impressive).
FURTHER DISCLAIMER:
This has only been tested on a GEC 63/40 super-mini, running UX63.
It is *not* guarenteed to work properly on anything else (though it'd
be quite nice if it did).
AUTHOR:
Simon Brown
Department of Computer Science
University of Edinburgh,
Scotland,
UK.
SHAR_EOF
fi
echo shar: "extracting 'Makefile'" '(521 characters)'
if test -f 'Makefile'
then
echo shar: "will not over-write existing file 'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
# Makefile 4.5 83/07/01
#
CFLAGS = -O
all: sh
cp: sh
cp sh /bin/sh
rm sh *.o
cmp: sh
cmp sh /bin/sh
rm sh *.o
sh: setbrk.o
sh: blok.o stak.o defs.o
sh: cmd.o fault.o main.o proc.o
sh: word.o string.o name.o args.o
sh: xec.o service.o error.o io.o
sh: print.o macro.o expand.o
sh: ctype.o msg.o
sh: hash.o hashserv.o profile.o echo.o test.o
sh: pwd.o func.o
blok.o: brkincr.h
fault.o: brkincr.h
main.o: brkincr.h
stak.o: brkincr.h
sh:
cc -o sh *.o
install:
install -s sh $(DESTDIR)/bin
clean:
rm -f sh *.o
SHAR_EOF
fi
echo shar: "extracting 'args.c.Diff'" '(715 characters)'
if test -f 'args.c.Diff'
then
echo shar: "will not over-write existing file 'args.c.Diff'"
else
cat << \SHAR_EOF > 'args.c.Diff'
*** args.c Mon Nov 24 17:49:17 1986
--- /cs/simon/c/shdiff-sources/args.c Thu Feb 19 19:16:31 1987
***************
*** 276,281
clearup()
{
/*
* force `for' $* lists to go away
*/
--- 276,285 -----
clearup()
{
+ #ifdef JOB
+ extern int fgjobs;
+ #endif JOB
+
/*
* force `for' $* lists to go away
*/
***************
*** 292,297
*/
while (poptemp())
;
}
struct dolnod *
--- 296,312 -----
*/
while (poptemp())
;
+
+ #ifdef JOB
+ /* reset job */
+ # ifdef JOBSXT
+ restore_sxt();
+ # endif
+ setjob(0);
+ fgjobs = 0; /* so the next `await()' won't hang */
+ iflags =0; /* they're all temporary states */
+ #endif JOB
+
}
struct dolnod *
SHAR_EOF
fi
echo shar: "extracting 'cmd.c.Diff'" '(747 characters)'
if test -f 'cmd.c.Diff'
then
echo shar: "will not over-write existing file 'cmd.c.Diff'"
else
cat << \SHAR_EOF > 'cmd.c.Diff'
*** cmd.c Mon Nov 24 17:49:19 1986
--- /cs/simon/c/shdiff-sources/cmd.c Wed Feb 18 14:06:30 1987
***************
*** 102,107
switch (wdval)
{
case '&':
if (i)
i = makefork(FINT | FPRS | FAMP, i);
else
--- 102,119 -----
switch (wdval)
{
case '&':
+ #ifdef JOB
+ /* prepend "bg" to convert "%x &" to "bg %x" */
+ if (i && i->tretyp==TCOM && ((struct comnod *)i)->comarg->argval[0]=='%'){
+ register struct comnod *ip;
+ register struct argnod *ap;
+ ip = (struct comnod *)i;
+ ap = (struct argnod *)getstor(sizeof(struct argnod)+3);
+ movstr("bg",ap->argval);
+ ap->argnxt = ip->comarg;
+ ip->comarg = ap;
+ } else
+ #endif JOB
if (i)
i = makefork(FINT | FPRS | FAMP, i);
else
SHAR_EOF
fi
echo shar: "extracting 'defs.c.Diff'" '(425 characters)'
if test -f 'defs.c.Diff'
then
echo shar: "will not over-write existing file 'defs.c.Diff'"
else
cat << \SHAR_EOF > 'defs.c.Diff'
*** defs.c Mon Nov 24 17:49:19 1986
--- /cs/simon/c/shdiff-sources/defs.c Wed Feb 18 19:00:28 1987
***************
*** 47,52
long flags;
int rwait; /* flags read waiting */
/* error exits from various parts of shell */
jmp_buf subshell;
--- 47,53 -----
long flags;
int rwait; /* flags read waiting */
+ long iflags;
/* error exits from various parts of shell */
jmp_buf subshell;
SHAR_EOF
fi
echo shar: "extracting 'defs.h.Diff'" '(3844 characters)'
if test -f 'defs.h.Diff'
then
echo shar: "will not over-write existing file 'defs.h.Diff'"
else
cat << \SHAR_EOF > 'defs.h.Diff'
*** defs.h Mon Nov 24 17:49:35 1986
--- /cs/simon/c/shdiff-sources/defs.h Thu Feb 19 19:01:28 1987
***************
*** 3,8
* UNIX shell
*/
/* error exits from various parts of shell */
#define ERROR 1
--- 3,15 -----
* UNIX shell
*/
+ #define JOB /* use job-control data structures */
+ #define JOBSXT /* ... and use sxt's to implement it */
+ #define SSHLIBRARY "/usr/lib/ssh
+ #define JOBSXT_HUP /* clever cleaning-up if it goes wrong */
+ #define SXT_SUSPEND /* export the file-descriptor for job stuff */
+ /*#define ERCC_SIGCONT*/ /* use SIGUSR2 to simulate SIGCONT */
+ /*#define BLK_BOTTOM*/ /* move cursor to bottom of screen if blocked */
/* error exits from various parts of shell */
#define ERROR 1
***************
*** 74,79
#define SYSMEM 27
#define SYSTYPE 28
/* used for input and output of shell */
#define INIO 19
--- 81,99 -----
#define SYSMEM 27
#define SYSTYPE 28
+ #ifdef JOB
+ #define SYSJOBS 29
+ #define SYSFG 30
+ #define SYSBG 31
+ #define SYSKILL 32
+ #define SYSSTOP 33
+ #define SYSNOTIFY 34
+ # ifdef JOBSXT
+ # define SYSSXT1 35
+ # endif
+ #endif JOB
+
+
/* used for input and output of shell */
#define INIO 19
***************
*** 131,137
extern char **setenv();
extern long time();
! #define attrib(n,f) (n->namflg |= f)
#define round(a,b) (((int)(((char *)(a)+b)-1))&~((b)-1))
#define closepipe(x) (close(x[INPIPE]), close(x[OTPIPE]))
#define eq(a,b) (cf(a,b)==0)
--- 151,158 -----
extern char **setenv();
extern long time();
! #define attrib(n,f) ((n)->namflg |= (f))
! #define nattrib(n,f) ((n)->namflg &= ~(f))
#define round(a,b) (((int)(((char *)(a)+b)-1))&~((b)-1))
#define closepipe(x) (close(x[INPIPE]), close(x[OTPIPE]))
#define eq(a,b) (cf(a,b)==0)
***************
*** 199,204
extern struct namnod mchknod;
extern struct namnod acctnod;
extern struct namnod mailpnod;
/* special names */
extern char flagadr[];
--- 220,227 -----
extern struct namnod mchknod;
extern struct namnod acctnod;
extern struct namnod mailpnod;
+ extern struct namnod ntfynod;
+ extern struct namnod TTYnod;
/* special names */
extern char flagadr[];
***************
*** 219,224
extern char mchkname[];
extern char acctname[];
extern char mailpname[];
/* transput */
extern char tmpout[];
--- 242,249 -----
extern char mchkname[];
extern char acctname[];
extern char mailpname[];
+ extern char ntfyname[];
+ extern char TTYname[];
/* transput */
extern char tmpout[];
***************
*** 261,266
extern long flags;
extern int rwait; /* flags read waiting */
/* error exits from various parts of shell */
#include <setjmp.h>
extern jmp_buf subshell;
--- 286,297 -----
extern long flags;
extern int rwait; /* flags read waiting */
+ #ifdef JOB
+ extern long iflags;
+ #define jobflg 01
+ #define sxtwaiting 02
+ #endif JOB
+
/* error exits from various parts of shell */
#include <setjmp.h>
extern jmp_buf subshell;
***************
*** 277,282
#define SIGSET 4
#define SIGMOD 8
#define SIGCAUGHT 16
extern int fault();
extern BOOL trapnote;
--- 308,314 -----
#define SIGSET 4
#define SIGMOD 8
#define SIGCAUGHT 16
+ #define DEVINTERRUPT 32
extern int fault();
extern BOOL trapnote;
***************
*** 362,364
exitsh(exitval ? exitval : SIGFAIL)
#define exitset() retval = exitval
--- 394,408 -----
exitsh(exitval ? exitval : SIGFAIL)
#define exitset() retval = exitval
+
+
+ #ifdef JOB
+ # ifdef sysV
+ # define TTYNOD struct termio
+ # include <termio.h>
+ # else
+ # define TTYNOD struct sgttyb
+ # include <sgtty.h>
+ # endif
+ #endif
+
SHAR_EOF
fi
echo shar: "extracting 'error.c.Diff'" '(378 characters)'
if test -f 'error.c.Diff'
then
echo shar: "will not over-write existing file 'error.c.Diff'"
else
cat << \SHAR_EOF > 'error.c.Diff'
*** error.c Mon Nov 24 17:49:20 1986
--- /cs/simon/c/shdiff-sources/error.c Wed Feb 18 14:07:55 1987
***************
*** 75,80
#ifdef ACCT
doacct();
#endif
exit(exitval);
}
--- 75,89 -----
#ifdef ACCT
doacct();
#endif
+
+ #ifdef JOB
+ zapjobs();
+ setjob(0);
+ # ifdef JOBSXT
+ sxtrelease(1);
+ # endif
+ #endif JOB
+
exit(exitval);
}
SHAR_EOF
fi
echo shar: "extracting 'fault.c.Diff'" '(3967 characters)'
if test -f 'fault.c.Diff'
then
echo shar: "will not over-write existing file 'fault.c.Diff'"
else
cat << \SHAR_EOF > 'fault.c.Diff'
*** fault.c Mon Nov 24 17:49:21 1986
--- /cs/simon/c/shdiff-sources/fault.c Thu Feb 19 18:21:00 1987
***************
*** 38,43
int (*(sigval[]))() =
{
0,
done,
fault,
fault,
--- 38,46 -----
int (*(sigval[]))() =
{
0,
+ #ifdef JOBSXT_HUP
+ fault,
+ #else
done,
#endif
fault,
***************
*** 39,44
{
0,
done,
fault,
fault,
done,
--- 42,48 -----
fault,
#else
done,
+ #endif
fault,
fault,
done,
***************
*** 54,59
fault,
fault,
done,
done,
done,
done
--- 58,67 -----
fault,
fault,
done,
+ #ifdef JOB
+ # ifdef ERCC_SIGCONT
+ fault, /* SIGUSR2 == SIGCONT? */
+ # else
done,
# endif
fault, /* SIGCLD */
***************
*** 55,60
fault,
done,
done,
done,
done
};
--- 63,71 -----
fault, /* SIGUSR2 == SIGCONT? */
# else
done,
+ # endif
+ fault, /* SIGCLD */
+ #else !JOB
done,
done,
#endif
***************
*** 56,61
done,
done,
done,
done
};
--- 67,74 -----
fault, /* SIGCLD */
#else !JOB
done,
+ done,
+ #endif
done
};
***************
*** 67,73
{
register int flag;
! signal(sig, fault);
if (sig == SIGSEGV)
{
if (setbrk(brkincr) == -1)
--- 80,90 -----
{
register int flag;
! #ifdef JOB
! if (sig!=SIGCLD)
! #endif JOB
! signal(sig,fault);
!
if (sig == SIGSEGV)
{
if (setbrk(brkincr) == -1)
***************
*** 78,83
if (flags & waiting)
done();
}
else
{
flag = (trapcom[sig] ? TRAPSET : SIGSET);
--- 95,119 -----
if (flags & waiting)
done();
}
+ #ifdef JOB
+ else if (sig==SIGCLD){
+ job_fault();
+ trapnote |= DEVINTERRUPT;
+ signal(SIGCLD,fault); /* do this AFTER waiting */
+ }
+ # ifdef JOBSXT_HUP
+ else if (sig==SIGHUP){
+ if (flags&ttyflg) hupmail();
+ done();
+ }
+ # endif JOBSXT_HUP
+ # ifdef ERCC_SIGCONT
+ else if (sig==SIGCONT){
+ trapnote |= DEVINTERRUPT;
+ }
+ # endif ERCC_SIGCONT
+ #endif JOB
+
else
{
flag = (trapcom[sig] ? TRAPSET : SIGSET);
***************
*** 106,111
setsig(SIGTERM);
setsig(SIGUSR1);
setsig(SIGUSR2);
}
ignsig(n)
--- 142,150 -----
setsig(SIGTERM);
setsig(SIGUSR1);
setsig(SIGUSR2);
+ #ifdef JOB
+ setsig(SIGCLD);
+ #endif JOB
}
#ifdef JOB
***************
*** 108,113
setsig(SIGUSR2);
}
ignsig(n)
{
register int s, i;
--- 147,171 -----
#endif JOB
}
+ #ifdef JOB
+ /*
+ * mask of signals that MUST be caught
+ */
+ #define X_CHILD 0
+ #define X_CONT 0
+ #define X_SEG (1L<<SIGSEGV)
+ #define X_ALRM (1L<<SIGALRM)
+ #ifdef JOB
+ # undef X_CHILD
+ # define X_CHILD (1L<<SIGCLD)
+ #endif JOB
+ #if defined(JOBSXT) && defined(ERCC_SIGCONT)
+ # undef X_CONT
+ # define X_CONT (1L<<SIGCONT)
+ #endif (JOBSXT and ERCC_SIGCONT)
+ long realsigs = X_CHILD | X_SEG | X_CONT | X_ALRM;
+
+
ignsig(n)
{
register int i;
***************
*** 110,115
ignsig(n)
{
register int s, i;
if ((i = n) == SIGSEGV)
--- 168,188 -----
ignsig(n)
{
+ register int i;
+
+ if (signal(i=n,SIG_IGN) != SIG_IGN){
+ trapflg[i] |= SIGMOD;
+ return(0);
+ } else if (realsigs&(1L<<n)){
+ trapflg[i] |= SIGMOD;
+ return(0);
+ } else return(1);
+ }
+
+ #else !JOB
+
+ ignsig(n)
+ {
register int s, i;
if ((i = n) == SIGSEGV)
***************
*** 123,128
}
return(s);
}
getsig(n)
{
--- 196,202 -----
}
return(s);
}
+ #endif JOB
getsig(n)
{
***************
*** 194,196
}
}
}
--- 268,290 -----
}
}
}
+
+
+
+ #ifdef JOB
+ /*
+ * fix up signals in child.
+ * this is pretty kludgy, I suppose.
+ */
+ fixsigs()
+ {
+ signal(SIGTERM,SIG_DFL);
+ signal(SIGQUIT,SIG_DFL);
+ #ifdef ERCC_SIGCONT
+ signal(SIGCONT, SIG_IGN); /* in case kid is stupid */
+ #endif ERCC_SIGCONT
+ trapflg[SIGTERM] &= ~SIGMOD;
+ trapflg[SIGQUIT] &= ~SIGMOD;
+ trapflg[SIGCONT] &= ~SIGMOD;
+ }
+ #endif JOB
SHAR_EOF
fi
echo shar: "extracting 'io.c.Diff'" '(4489 characters)'
if test -f 'io.c.Diff'
then
echo shar: "will not over-write existing file 'io.c.Diff'"
else
cat << \SHAR_EOF > 'io.c.Diff'
*** io.c Mon Nov 24 17:49:24 1986
--- /cs/simon/c/shdiff-sources/io.c Fri Feb 20 12:51:13 1987
***************
*** 313,315
}
topfd = last;
}
--- 313,529 -----
}
topfd = last;
}
+
+
+
+ #ifdef JOB
+
+ /*
+ * fetch current tty characteristics.
+ */
+ terminal(tp)
+ TTYNOD *tp;
+ {
+ # ifdef sysV
+ return(ioctl(0,TCGETA,tp));
+ # else
+ return(ioctl(0,TIOCGETP,tp));
+ # endif sysV
+ }
+
+
+ #ifdef JOBSXT
+ /*
+ * sxt virtual-terminal stuff for SystemV Job-Control (layers)
+ */
+ #undef input
+ #include "job.h"
+ #include <sys/types.h>
+ #include <sys/tty.h>
+ #include <sys/sxt.h>
+ #include <errno.h>
+
+ #define SXTIO 13
+ #define CONSTTYIO 14
+
+ /* this is a bit naughty: still... its only declared for sgtty, not termio! */
+ #define TIOCEXCL (('t'<<8)|13)
+
+ static char sxt[] = "/dev/sxt/000";
+ static char no_jobs[] = "; thus no job-control\n";
+ #define SXT_CHAN 11
+ extern int sxtchan;
+ extern int savsxtchan;
+ extern struct jobnod *jobs[];
+
+
+
+ /*
+ * open a new channel
+ */
+ sxtopen(chan)
+ {
+ int rc;
+ struct termio tb;
+
+ if (chan>SXTMAX) return(-1);
+ sxt[SXT_CHAN] = chan+'0';
+ if ((rc=open(sxt,2)) < 0){
+ failed(sxt,errno);
+ /*NOTREACHED*/
+ }
+ tb = realtty;
+ if (chan>1){
+ tb.c_cc[VSWTCH] = '\032'; /* sorry! - only ^Z allowed */
+ tb.c_cflag |= LOBLK; /* blocking allowed */
+ } else {
+ tb.c_cflag &= ~LOBLK; /* shell is immune to blocking */
+ }
+ ioctl(rc,TCSETA,&tb);
+ return(rc);
+ }
+
+ char *sxtstr[] = { SSHLIBRARY/sxtalloc`", 0 };
+
+
+ /*
+ * initialize sxt
+ */
+ sxtinit()
+ {
+ int fd;
+ #ifdef SXT_SUSPEND
+ struct namnod *np;
+ #endif
+
+ iflags &= ~jobflg;
+ if (TTYnod.namval) goto nomesg; /* its a subshell! */
+ if (setjmp(errshell)) goto bad;
+ execexp("REALTTY=`", sxtstr);
+ attrib(&TTYnod, (N_RDONLY|N_EXPORT));
+ sxtchan = 0;
+ if (exitval) goto bad;
+
+ while ((fd=open(sxt,O_RDWR)) == -1)
+ switch(errno){
+ case ENOENT:
+ prs_buff("No sxt channels available");
+ prs_buff(no_jobs);
+ flushb();
+ sxtchan = -1;
+ return;
+ case EBUSY:
+ case EACCES:
+ sxtchan++;
+ if (sxtchan>9)
+ sxt[SXT_CHAN-2] = (sxtchan/10)+'0';
+ sxt[SXT_CHAN-1] = (sxtchan%10)+'0';
+ break;
+ default:
+ prs_buff("sxt error\n");
+ flushb();
+ exit(1);
+ }
+ if (ioctl(fd,SXTIOCLINK,MAXPCHAN) != 0){
+ if (errno==ENOTTY || errno==EBUSY){
+ prs_buff("Controlling terminal not a real device");
+ prs_buff(no_jobs);
+ flushb();
+ sxtchan = -1;
+ close(fd);
+ return;
+ } else {
+ prs_buff("sxt ioctl error\n");
+ flushb();
+ exit(1);
+ }
+ }
+ ioctl(fd,SXTIOCUBLK,0); /* controller mustn't block on output */
+ ioctl(fd,TIOCEXCL,0);
+ ioctl(fd,TCSETA,&realtty);
+ #ifdef SXT_SUSPEND
+ rename(fd,sxt_fd=SXTIO); /* so subprocesses can "suspend..." */
+ itos(SXTIO);
+ np=lookup("SXT_CONTROL");
+ assign(np,numbuf);
+ attrib(np,N_EXPORT);
+ #else
+ Ldup(fd,sxt_fd=SXTIO);
+ #endif SXT_SUSPEND
+ if (getppid() == 1){ /* kernel bug; so just use sxt 0 */
+ Ldup(dup(0),CONSTTYIO);
+ #ifdef notdef
+ sxtkludge = 0;
+ fd = sxt_fd;
+ #else
+ fd = sxtopen(1);
+ #endif notdef
+ } else {
+ setpgrp(); /* setpgrp will work */
+ fd = sxtopen(1); /* BETTER work! */
+ }
+ close(0);
+ close(1); close(2); /* forget real tty */
+ dup(fd); /* input is channel 0 or 1 */
+ dup(0); dup(0); /* stdout/stderr channel 0 or 1 too*/
+ close(fd);
+ iflags |= jobflg;
+ return;
+
+ bad:
+ prs_buff("cannot initialize sxt");
+ prs_buff(no_jobs);
+ flushb();
+ nomesg:
+ sxtchan = -1;
+ iflags &= ~jobflg;
+ return;
+ }
+
+
+ /*
+ * release sxt
+ */
+ sxtrelease(suicide)
+ {
+ if (sxtchan != -1){
+ exitset();
+ if (suicide)
+ flags &= ~rshflg; /* late enough now */
+ sxtchan = -1; /* no more! */
+ close(sxt_fd); /* really! */
+ execexp(SSHLIBRARY/sxtalloc \"$REALTTY\" $?",(char * *)0);
+ if (suicide) done();
+ close(0); close(1); close(2);
+ dup(CONSTTYIO); dup(0); dup(1); /* restore old tty */
+ }
+ }
+
+
+ /* temporarily forget about sxt's */
+ hide_sxt()
+ {
+ if (sxtchan!=-1){
+ savsxtchan = sxtchan;
+ sxtchan = -1;
+ iflags &= ~jobflg;
+ return(1);
+ } else return(0);
+ }
+
+
+ /* ... and remember them again */
+ restore_sxt()
+ {
+ if (sxtchan==-1){
+ sxtchan = savsxtchan;
+ savsxtchan = -1;
+ iflags |= jobflg;
+ }
+ }
+
+ #endif JOBSXT
+
+ #endif JOB
+
+
SHAR_EOF
fi
echo shar: "extracting 'job.h'" '(1981 characters)'
if test -f 'job.h'
then
echo shar: "will not over-write existing file 'job.h'"
else
cat << \SHAR_EOF > 'job.h'
#
/*
* SSH job-control structure (one for each job).
* Copyright (c) S. Brown, 1987
*/
#ifdef JOB
/* Because of the algorithm used for parsing, only the first and last
processes of a pipeline are posted to the job-table, so set PPERJ=2. */
#define JOB_MAX 30 /* maximum number of jobs allowed */
#define PPERJ 2 /* processes known per job */
#define EXTRAPROCS JOB_MAX /* size of "extra proc" table */
struct jobnod {
union {
struct {
unsigned run : 1; /* running */
unsigned stop : 1; /* stopped */
unsigned back : 1; /* background */
unsigned notify : 1; /* to be notified of termination */
unsigned deaths : PPERJ;/* processes which have died */
unsigned lifes : PPERJ; /* processes associated with job */
unsigned knowtty : 1; /* have fetched tty status for this job */
unsigned stopstate : 2; /* stop states */
} singlebits; /* for referencing single bits */
short totalbits;/* for making global assignments */
} jb_flags; /* is this not perhaps a bit unpleasant altogether? */
char *jb_dir; /* current directory of job */
int jb_pgrp; /* process group (useful only for BSD) */
char *jb_cmd; /* name of command */
int jb_pri; /* priority (stack for %+ and %-) */
struct {
int proc_pid; /* process id */
int proc_status; /* exit status */
short proc_flags; /* flags? not used, anyway */
} jb_proc[PPERJ]; /* processes associated with job */
#ifdef JOBSXT
int jb_sxtfg; /* file descriptor for job's sxt */
#endif JOBSXT
};
#define SS_STOP 0
#define SS_TSTP 1
#define SS_TTIN 2
#define SS_TTOU 3
#ifdef PROCESS_DOT_C
struct extrawait {
int pid;
int status;
};
#endif PROCESS_DOT_C
#ifdef JOBSXT
#define SXTMAX (MAXPCHAN-1)
#define SXT(n) ((n)?(n)+1:sxtkludge)
extern int sxtchan;
extern int sxtkludge;
extern int sxt_fd;
extern TTYNOD realtty;
#endif JOBSXT
#define WAIT_FG 1
#define WAIT_BG 2
#define WAIT_NOPAUSE 4
#define WAIT_JOB 8
extern struct jobnod *jobs[];
extern int currentjob;
#endif JOB
SHAR_EOF
fi
echo shar: "extracting 'macro.c.Diff'" '(1965 characters)'
if test -f 'macro.c.Diff'
then
echo shar: "will not over-write existing file 'macro.c.Diff'"
else
cat << \SHAR_EOF > 'macro.c.Diff'
*** macro.c Mon Nov 24 17:49:25 1986
--- /cs/simon/c/shdiff-sources/macro.c Wed Feb 18 18:13:05 1987
***************
*** 253,258
return(fixstak());
}
static
comsubst()
{
--- 253,262 -----
return(fixstak());
}
+ #ifdef JOB
+ #include "job.h"
+ #endif
+
static
comsubst()
{
***************
*** 262,267
struct fileblk cb;
register char d;
register char *savptr = fixstak();
usestak();
while ((d = readc()) != SQUOTE && d)
--- 266,274 -----
struct fileblk cb;
register char d;
register char *savptr = fixstak();
+ #ifdef JOBSXT
+ BOOL chsxt = FALSE;
+ #endif JOBSXT
usestak();
while ((d = readc()) != SQUOTE && d)
***************
*** 283,288
*/
chkpipe(pv);
initf(pv[INPIPE]);
execute(t, 0, (int)(flags & errflg), 0, pv);
close(pv[OTPIPE]);
}
--- 290,298 -----
*/
chkpipe(pv);
initf(pv[INPIPE]);
+ #ifdef JOBSXT
+ chsxt = hide_sxt();
+ #endif JOBSXT
execute(t, 0, (int)(flags & errflg), 0, pv);
close(pv[OTPIPE]);
}
***************
*** 290,295
staktop = movstr(savptr, stakbot);
while (d = readc())
pushstak(d | quote);
await(0, 0);
while (stakbot != staktop)
{
--- 300,312 -----
staktop = movstr(savptr, stakbot);
while (d = readc())
pushstak(d | quote);
+ #ifdef JOB
+ await(0,WAIT_FG); /* a process, in the forground */
+ # ifdef JOBSXT
+ if (chsxt)
+ restore_sxt();
+ # endif JOBSXT
+ #else !JOB
await(0, 0);
#endif JOB
while (stakbot != staktop)
***************
*** 291,296
while (d = readc())
pushstak(d | quote);
await(0, 0);
while (stakbot != staktop)
{
if ((*--staktop & STRIP) != NL)
--- 308,314 -----
# endif JOBSXT
#else !JOB
await(0, 0);
+ #endif JOB
while (stakbot != staktop)
{
if ((*--staktop & STRIP) != NL)
***************
*** 301,306
}
pop();
}
#define CPYSIZ 512
--- 319,325 -----
}
pop();
}
+
#define CPYSIZ 512
SHAR_EOF
fi
echo shar: "extracting 'main.c.Diff'" '(2410 characters)'
if test -f 'main.c.Diff'
then
echo shar: "will not over-write existing file 'main.c.Diff'"
else
cat << \SHAR_EOF > 'main.c.Diff'
*** main.c Mon Nov 24 17:49:25 1986
--- /cs/simon/c/shdiff-sources/main.c Fri Feb 20 12:48:19 1987
***************
*** 147,152
dfault(&mchknod, MAILCHECK);
mailchk = stoi(mchknod.namval);
if ((beenhere++) == FALSE) /* ? profile */
{
if (*(simple(cmdadr)) == '-')
--- 147,156 -----
dfault(&mchknod, MAILCHECK);
mailchk = stoi(mchknod.namval);
+ #ifdef JOB
+ initjobs();
+ #endif JOB
+
if ((beenhere++) == FALSE) /* ? profile */
{
if (*(simple(cmdadr)) == '-')
***************
*** 186,191
comdiv--;
}
}
#ifdef pdp11
else
*execargs = (char *)dolv; /* for `ps' cmd */
--- 190,200 -----
comdiv--;
}
}
+ else {
+ #ifdef JOBSXT
+ extern int sxtchan;
+ sxtchan = -1;
+ #endif JOBSXT
#ifdef pdp11
*execargs = (char *)dolv; /* for `ps' cmd */
#endif
***************
*** 187,193
}
}
#ifdef pdp11
- else
*execargs = (char *)dolv; /* for `ps' cmd */
#endif
--- 196,201 -----
sxtchan = -1;
#endif JOBSXT
#ifdef pdp11
*execargs = (char *)dolv; /* for `ps' cmd */
#endif
}
***************
*** 190,195
else
*execargs = (char *)dolv; /* for `ps' cmd */
#endif
exfile(0);
done();
--- 198,204 -----
#ifdef pdp11
*execargs = (char *)dolv; /* for `ps' cmd */
#endif
+ }
exfile(0);
done();
***************
*** 262,267
if (input >= 0)
initf(input);
/*
* command loop
*/
--- 271,281 -----
if (input >= 0)
initf(input);
+
+ #ifdef JOB
+ if (flags&ttyflg) setjob(0);
+ #endif
+
/*
* command loop
*/
***************
*** 265,270
/*
* command loop
*/
for (;;)
{
tdystak(0);
--- 279,285 -----
/*
* command loop
*/
+
for (;;)
{
tdystak(0);
***************
*** 304,310
trapnote = 0;
peekc = readc();
! if (eof)
return;
#ifdef TIME_OUT
--- 319,337 -----
trapnote = 0;
peekc = readc();
! if (eof){
! #ifdef JOBSXT
! if ((flags&ttyflg) && stpjobs()){
! int fd;
! prs("\nThere are blocked jobs\n");
! fd = sxtopen(1);
! if (fd>=0){
! initf(fd);
! continue;
! }
! }
!
! #endif JOBSXT
return;
}
***************
*** 306,311
peekc = readc();
if (eof)
return;
#ifdef TIME_OUT
alarm(0);
--- 333,339 -----
#endif JOBSXT
return;
+ }
#ifdef TIME_OUT
alarm(0);
SHAR_EOF
fi
echo shar: "extracting 'msg.c.Diff'" '(3167 characters)'
if test -f 'msg.c.Diff'
then
echo shar: "will not over-write existing file 'msg.c.Diff'"
else
cat << \SHAR_EOF > 'msg.c.Diff'
*** msg.c Mon Nov 24 17:49:26 1986
--- /cs/simon/c/shdiff-sources/msg.c Wed Feb 18 20:30:56 1987
***************
*** 66,71
char mchkname[] = "MAILCHECK";
char acctname[] = "SHACCT";
char mailpname[] = "MAILPATH";
/*
* string constants
--- 66,73 -----
char mchkname[] = "MAILCHECK";
char acctname[] = "SHACCT";
char mailpname[] = "MAILPATH";
+ char ntfyname[] = "NOTIFY";
+ char TTYname[] = "REALTTY";
/*
* string constants
***************
*** 149,154
{ "[", SYSTST },
#endif
{ "break", SYSBREAK },
{ "cd", SYSCD },
{ "continue", SYSCONT },
--- 151,159 -----
{ "[", SYSTST },
#endif
+ #ifdef JOB
+ { "bg", SYSBG },
+ #endif JOB
{ "break", SYSBREAK },
{ "cd", SYSCD },
{ "continue", SYSCONT },
***************
*** 157,162
{ "exec", SYSEXEC },
{ "exit", SYSEXIT },
{ "export", SYSXPORT },
{ "hash", SYSHASH },
#ifdef RES
--- 162,170 -----
{ "exec", SYSEXEC },
{ "exit", SYSEXIT },
{ "export", SYSXPORT },
+ #ifdef JOB
+ { "fg", SYSFG },
+ #endif JOB
{ "hash", SYSHASH },
#ifdef JOB
***************
*** 159,164
{ "export", SYSXPORT },
{ "hash", SYSHASH },
#ifdef RES
{ "login", SYSLOGIN },
{ "newgrp", SYSLOGIN },
--- 167,177 -----
#endif JOB
{ "hash", SYSHASH },
+ #ifdef JOB
+ { "jobs", SYSJOBS },
+ { "kill", SYSKILL },
+ #endif JOB
+
#ifdef RES
{ "login", SYSLOGIN },
{ "newgrp", SYSLOGIN },
***************
*** 166,171
{ "newgrp", SYSNEWGRP },
#endif
{ "pwd", SYSPWD },
{ "read", SYSREAD },
{ "readonly", SYSRDONLY },
--- 179,188 -----
{ "newgrp", SYSNEWGRP },
#endif
+ #ifdef JOB
+ { "notify", SYSNOTIFY },
+ #endif JOB
+
{ "pwd", SYSPWD },
{ "read", SYSREAD },
{ "readonly", SYSRDONLY },
***************
*** 172,177
{ "return", SYSRETURN },
{ "set", SYSSET },
{ "shift", SYSSHFT },
{ "test", SYSTST },
{ "times", SYSTIMES },
{ "trap", SYSTRAP },
--- 189,200 -----
{ "return", SYSRETURN },
{ "set", SYSSET },
{ "shift", SYSSHFT },
+ #ifdef JOB
+ { "stop", SYSSTOP },
+ # ifdef JOBSXT
+ { "sxt1", SYSSXT1 },
+ # endif JOBSXT
+ #endif JOB
{ "test", SYSTST },
{ "times", SYSTIMES },
{ "trap", SYSTRAP },
***************
*** 188,193
};
#ifdef RES
int no_commands = 26;
#else
int no_commands = 27;
--- 211,219 -----
};
#ifdef RES
+ # ifdef JOB
+ int no_commands = 33;
+ # else
int no_commands = 26;
# endif
#else
***************
*** 189,194
#ifdef RES
int no_commands = 26;
#else
int no_commands = 27;
#endif
--- 215,221 -----
int no_commands = 33;
# else
int no_commands = 26;
+ # endif
#else
# ifdef JOB
int no_commands = 34;
***************
*** 190,194
#ifdef RES
int no_commands = 26;
#else
int no_commands = 27;
#endif
--- 217,225 -----
int no_commands = 26;
# endif
#else
+ # ifdef JOB
+ int no_commands = 34;
+ # else
int no_commands = 27;
# endif
#endif
***************
*** 191,194
int no_commands = 26;
#else
int no_commands = 27;
#endif
--- 221,225 -----
int no_commands = 34;
# else
int no_commands = 27;
+ # endif
#endif
SHAR_EOF
fi
echo shar: "extracting 'name.c.Diff'" '(1211 characters)'
if test -f 'name.c.Diff'
then
echo shar: "will not over-write existing file 'name.c.Diff'"
else
cat << \SHAR_EOF > 'name.c.Diff'
*** name.c Mon Nov 24 17:49:26 1986
--- /cs/simon/c/shdiff-sources/name.c Wed Feb 18 18:23:31 1987
***************
*** 54,59
(struct namnod *)NIL,
mailname
};
struct namnod mchknod =
{
&ifsnod,
--- 54,65 -----
(struct namnod *)NIL,
mailname
};
+ struct namnod ntfynod =
+ {
+ (struct namnod *)NIL,
+ &ps1nod,
+ ntfyname
+ };
struct namnod mchknod =
{
&ifsnod,
***************
*** 57,63
struct namnod mchknod =
{
&ifsnod,
! &ps1nod,
mchkname
};
struct namnod acctnod =
--- 63,69 -----
struct namnod mchknod =
{
&ifsnod,
! &ntfynod,
mchkname
};
struct namnod TTYnod =
***************
*** 60,66
&ps1nod,
mchkname
};
! struct namnod acctnod =
{
(struct namnod *)NIL,
(struct namnod *)NIL,
--- 66,72 -----
&ntfynod,
mchkname
};
! struct namnod TTYnod =
{
(struct namnod *)NIL,
(struct namnod *)NIL,
***************
*** 63,68
struct namnod acctnod =
{
(struct namnod *)NIL,
(struct namnod *)NIL,
acctname
};
--- 69,80 -----
struct namnod TTYnod =
{
(struct namnod *)NIL,
+ (struct namnod *)NIL,
+ TTYname
+ };
+ struct namnod acctnod =
+ {
+ &TTYnod,
(struct namnod *)NIL,
acctname
};
SHAR_EOF
fi
exit 0
# End of shell archive