more ksh fixes
Charles Hedrick
hedrick at athos.rutgers.edu
Sun Jun 26 14:16:08 AEST 1988
This is a new edition my diffs to ksh to make job control work in System V.
Someone reported a problem that I've also seen. I was unable to get mail
back to him. Since others may have seen the same thing, I'm just posting
the result. The enclosed diffs fix several major problems with job control,
and one with Emacs completion. They are with respect to the most recent
version of ksh-i from the ATT Toolchest. Changes since the last posting are
that the interrupt character now works properly, and that it is safe
to ^Z a shell script. Here are the things fixed:
with job control in effect, commands involving a pipeline (i.e. '|')
gave odd effects. They would not complete properly, would
display the wrong job number, etc.
with job control in effect, it was impossible to pipe builtin
commands, e.g. "history | more". Output would not come
out or would be interspersed with other things. (This bug
was not in the original, but was actually caused by an
incorrect attempt to fix the first one.)
with job control in effect, if you tried to suspend a shell
script with ^Z (or whatever), the current program would be
suspended and the shell script would continue. This is
presumably some sort of messup with process groups, but
I couldn't find it. So I resorted to making the shell
exec a new copy of itself under situations where it would
normally longjmp back to the beginning. The situations
where this happens are limited enough that it shouldn't
cause performance problems.
with job control in effect, the interrupt character (^C or whatever)
would not work for commands that didn't fork. That is, you
couldn't abort a partially-typed command with the interrupt,
nor could you interrupt "while" or "for" loops typed to the
shell. Scripts would work fine, as would loops typed
within (). The problem was that /dev/sxt000, or whatever
the controlling sxt turned out to be, wasn't the controlling
terminal. The code did a setpgrp, but didn't reopen the
device so as to establish the proper controlling terminal.
(Maybe jsh should be doing this, but I was not able to
make it do so.) I tried to make it do that, but found
that I couldn't open /dev/sxt000. jsh was opening it
exclusive, but even removing that I couldn't open
/dev/sxt000. I finally ended up using the highest numbered
subchannel for the shell itself, typically /dev/sxt007.
There's got to be a better way, but I spent two days trying
to find it and failed.
in emacs mode, ESC ESC should ring the bell if there is more than
one possible completion. ESC * still does as before. (This
behavior is consistent with newer versions of ksh, and presumably
will show up in the toolkit version at some point.)
other minor emacs fixes, e.g. letting it work correctly when
the erase char is something other than ^H
Here are known problems that are *not* fixed by these edits:
the problem with the interrupt character noted above will
continue to happen if ksh is run directly as a top-level
process. My conjecture is that getty does a setpgrp,
and once it has been done for a given process, further
ones are ignored. This means that we have no way to
reset the controlling terminal to /dev/sxt007.
Currently, my .profile ends with
jsh
exit
It used to end with
exec /usr/bin/jsh
This results is using an extra process, but it's fairly
easy to show that this is unlikely to cause any trouble,
even in terms of memory and swap space usage.
when job control is in effect, attempts to run more than 6
jobs at once will hang the shell. This is obviously
just a coding blunder, but I don't have time to fix
it at the moment. I'll try to do so eventually.
typeahead may not behave as expected when job control is in
effect. This is a basic problem with the kernel
support for sxt's, and can't be fixed in the shell.
you can't suspend a builtin command, unless it is in (). This
is a reasonable restriction.
It appears that I am currently the maintainer of this stuff. I talked to
David Korn. While he is sympathetic with my desire to have job control, he
regards the System V sxt mechanism as unacceptably buggy, and is now
supporting only Berkeley-style job control. I am unwilling to wait for
System V release 4. It appears that even the current sxt support
will be removed from future releases of ksh.
*** edit.c.ORIG Fri Jun 3 20:34:18 1988
--- edit.c Fri Jun 3 04:43:37 1988
***************
*** 628,634
* file name generation for edit modes
* non-zero exit for error, <0 ring bell
* don't search back past <start> character of the buffer
! * mode is '*' for inline expansion, otherwise files are listed in select format
*/
q_expand(outbuff,cur,eol,start,mode)
--- 628,636 -----
* file name generation for edit modes
* non-zero exit for error, <0 ring bell
* don't search back past <start> character of the buffer
! * mode is '*' for inline expansion,
! * '?' for listing all files in select format
! * otherwise unique completion
*/
q_expand(outbuff,cur,eol,start,mode)
***************
*** 716,722
endstak(ptr);
last = ptr-1;
}
! if(mode!='*')
on_option(MARKDIR);
{
register char **com;
--- 718,724 -----
endstak(ptr);
last = ptr-1;
}
! if(mode=='?')
on_option(MARKDIR);
{
register char **com;
***************
*** 736,742
goto done;
}
}
! if(mode!='*')
{
if (strip)
{
--- 738,744 -----
goto done;
}
}
! if(mode=='?')
{
if (strip)
{
***************
*** 751,756
p_flush();
goto done;
}
/* see if there is enough room */
size = *eol - (out-begin);
size += narg;
--- 753,777 -----
p_flush();
goto done;
}
+ /* if normal completion, and not unique, beep and make it unique */
+ if(mode!='*' && narg > 1) {
+ char **nextcom = com+1;
+ char *firstcom;
+ char *thiscom;
+
+ e_ringbell();
+ while (*nextcom) {
+ thiscom = *nextcom;
+ firstcom = *com;
+ while (*thiscom++ == *firstcom)
+ firstcom++;
+ *firstcom = 0;
+ nextcom++;
+ }
+ narg = 1;
+ com[1] = 0;
+ }
+
/* see if there is enough room */
size = *eol - (out-begin);
size += narg;
*** emacs.c.ORIG Fri Jun 3 20:32:06 1988
--- emacs.c Tue Jun 7 11:23:47 1988
***************
*** 360,366
continue;
}
adjust = i - mark;
! ungetchar('\b');
continue;
case cntl(D) :
mark = i;
--- 368,374 -----
continue;
}
adjust = i - mark;
! ungetchar(usrerase);
continue;
case cntl(D) :
mark = i;
***************
*** 626,631
case 'l': /* M-l == lower-case */
case 'd':
case 'c':
case 'f':
{
--- 634,640 -----
case 'l': /* M-l == lower-case */
case 'd':
+ case 'u':
case 'c':
case 'f':
{
***************
*** 664,670
draw(UPDATE);
return(-1);
}
! else if(ch=='c')
{
ungetchar(cntl(C));
return(i-cur);
--- 673,679 -----
draw(UPDATE);
return(-1);
}
! else if(ch=='c' || ch=='u')
{
ungetchar(cntl(C));
return(i-cur);
***************
*** 751,760
}
/* file name expansion */
! case cntl([) : /* easier to type */
! i = '*';
! case '*':
! case '=': /* escape = - list all matching file names */
mark = cur;
if(q_expand(out,&cur,&eol,plen,i) < 0)
beep();
--- 760,770 -----
}
/* file name expansion */
! case '=': i = '?'; /* ? and = are list */
! case '?':
! case cntl([) : /* unique completion */
! case '*': /* complete all */
!
mark = cur;
if(q_expand(out,&cur,&eol,plen,i) < 0)
beep();
***************
*** 758,764
mark = cur;
if(q_expand(out,&cur,&eol,plen,i) < 0)
beep();
! else if(i=='*')
draw(UPDATE);
else
draw(REFRESH);
--- 768,774 -----
mark = cur;
if(q_expand(out,&cur,&eol,plen,i) < 0)
beep();
! else if(i!='?')
draw(UPDATE);
else
draw(REFRESH);
*** jobs.c.ORIG Sat Jun 25 20:25:38 1988
--- jobs.c Sat Jun 25 22:50:42 1988
***************
*** 279,284
#ifdef SXT
static char sxt[] = "/dev/sxt/000";
static struct sxtblock status1,status2;
int init_jobs(lflag)
{
--- 279,287 -----
#ifdef SXT
static char sxt[] = "/dev/sxt/000";
static struct sxtblock status1,status2;
+ static char *open_mode[3] = {"r","w","w+"};
+ static int ctlchn = 2;
+ #define MAIN_CHAN MAXPCHAN - 1
int init_jobs(lflag)
{
***************
*** 302,311
sxt[10] = '0' + (dev%10);
sxt[9] = '0' + dev/10;
my_stty.c_cc[VSWTCH] = CSWTCH;
! if(ioctl(2,TCSETAF,&my_stty) < 0)
! return(-1);
! setpgrp(pid,pid);
! jobstat.maxjob = MAXPCHAN;
on_option(MONITOR);
return(0);
}
--- 305,336 -----
sxt[10] = '0' + (dev%10);
sxt[9] = '0' + dev/10;
my_stty.c_cc[VSWTCH] = CSWTCH;
! {
! register int fd;
! register int i;
! sxt[11] = '0' + MAIN_CHAN;
! ctlchn = dup(2);
! setpgrp();
! fd = open(sxt,2);
! if(ioctl(fd,TCSETA,&my_stty)<0 || fd < 0)
! {
! return(0);
! }
! for(i=0;i<3;i++)
! {
! if(isatty(i))
! {
! close(i);
! dup(fd);
! }
! }
! close(fd);
! if(ioctl(ctlchn,SXTIOCSWTCH,MAIN_CHAN)!=0)
! {
! return(-1);
! }
! }
! jobstat.maxjob = MAXPCHAN - 1;
on_option(MONITOR);
return(0);
}
***************
*** 369,375
jobstat.pipe[0] = 0;
}
if(pw->p_job < jobstat.maxjob)
! if(ioctl(2,SXTIOCSWTCH,pw->p_job)!=0)
{
return(-1);
}
--- 394,400 -----
jobstat.pipe[0] = 0;
}
if(pw->p_job < jobstat.maxjob)
! if(ioctl(ctlchn,SXTIOCSWTCH,pw->p_job)!=0)
{
return(-1);
}
***************
*** 417,423
fd_chan = -1;
/* grab control in channel 0 */
ioctl(2,TCSETAW,&my_stty);
! if(ioctl(2,SXTIOCSWTCH,0)!=0)
{
return(-1);
}
--- 442,448 -----
fd_chan = -1;
/* grab control in channel 0 */
ioctl(2,TCSETAW,&my_stty);
! if(ioctl(ctlchn,SXTIOCSWTCH,MAIN_CHAN)!=0)
{
return(-1);
}
***************
*** 1345,1351
* open up the input streams for a new channel
*/
- static char *open_mode[3] = {"r","w","w+"};
j_new_chan()
{
register FILE* fd;
--- 1370,1375 -----
* open up the input streams for a new channel
*/
j_new_chan()
{
register FILE* fd;
*** makesh.ORIG Fri Jun 3 22:38:30 1988
--- makesh Mon Jun 13 03:26:08 1988
***************
*** 1,3
CMD=${CMD-/bin/make}
ARK=${ARK-lib.a}
#
--- 1,4 -----
CMD=${CMD-/bin/make}
ARK=${ARK-lib.a}
#
***************
*** 82,87
#if test -d /dev/sxt # sxt driver available
#then Options="$Options SXT=-DSXT"
#fi
if test -f /vmunix -o "$SYSTYPE" = bsd4.1 -o "$SYSTYPE" = bsd4.2 # true for BSD unix
then JOBLIB=-ljobs Options="$Options DBSD=-DBSD" JOBS=jobs.o LFLAGS=-z
if test -f /etc/networks #BSD 4.2
--- 83,89 -----
#if test -d /dev/sxt # sxt driver available
#then Options="$Options SXT=-DSXT"
#fi
+ Options="$Options SXT=-DSXT"
if test -f /vmunix -o "$SYSTYPE" = bsd4.1 -o "$SYSTYPE" = bsd4.2 # true for BSD unix
then JOBLIB=-ljobs Options="$Options DBSD=-DBSD" JOBS=jobs.o LFLAGS=-z
if test -f /etc/networks #BSD 4.2
*** service.c.ORIG Mon Jun 13 13:48:46 1988
--- service.c Tue Jun 14 00:44:06 1988
***************
*** 460,465
if(ex_xenix(p))
#endif /* XENIX */
execve(p, &t[0] ,xecenv);
switch(errno)
{
case ENOEXEC:
--- 460,475 -----
if(ex_xenix(p))
#endif /* XENIX */
execve(p, &t[0] ,xecenv);
+ if (errno == ENOEXEC && (is_option(MONITOR))) {
+ char *localarg[256]; int i;
+
+ for (i = 0; t[i]; i++)
+ localarg[i+1] = t[i];
+ localarg[i+1] = 0;
+ localarg[0] = t[0];
+ localarg[1] = p;
+ execve("/bin/sh", &localarg[0], xecenv);
+ }
switch(errno)
{
case ENOEXEC:
*** xec.c.ORIG Fri Jun 3 22:15:12 1988
--- xec.c Mon Jun 13 14:15:14 1988
***************
*** 138,143
type = t->tretyp;
oldexit=exitval;
exitval=0;
switch(type&COMMSK)
{
case TCOM:
--- 138,152 -----
type = t->tretyp;
oldexit=exitval;
exitval=0;
+
+ #ifdef clh
+ p_num(getpid(),' ');
+ p_num(execflg,' ');
+ if (states&MONITOR) p_str("monitor",' ');
+ p_num(t->tretyp,'\n');
+ p_flush();
+ #endif
+
switch(type&COMMSK)
{
case TCOM:
***************
*** 256,261
int no_fork;
sync_io();
#ifdef SXT
/* find job number and create synchronization pipe */
if((jobstat.cur_job = next_job()) < jobstat.maxjob)
if(pipe(jobstat.pipe)<0)
--- 265,272 -----
int no_fork;
sync_io();
#ifdef SXT
+ if(jobstat.j_flag==0)
+ jobstat.cur_job = next_job();
/* find job number and create synchronization pipe */
if(jobstat.cur_job < jobstat.maxjob)
if(pipe(jobstat.pipe)<0)
***************
*** 257,263
sync_io();
#ifdef SXT
/* find job number and create synchronization pipe */
! if((jobstat.cur_job = next_job()) < jobstat.maxjob)
if(pipe(jobstat.pipe)<0)
jobstat.maxjob = 0;
#endif /* SXT */
--- 268,274 -----
if(jobstat.j_flag==0)
jobstat.cur_job = next_job();
/* find job number and create synchronization pipe */
! if(jobstat.cur_job < jobstat.maxjob)
if(pipe(jobstat.pipe)<0)
jobstat.maxjob = 0;
#endif /* SXT */
***************
*** 290,295
vfork_save();
while((parent=(v_fork?vfork():fork())) == -1)
#else
while((parent=fork()) == -1)
#endif /* VFORK */
{
--- 301,312 -----
vfork_save();
while((parent=(v_fork?vfork():fork())) == -1)
#else
+ #ifdef clh
+ if (states&MONITOR) {
+ p_str("fork",'\n');
+ p_flush();
+ }
+ #endif
while((parent=fork()) == -1)
#endif /* VFORK */
{
More information about the Comp.unix.microport
mailing list