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