Bug in S5R4 handling of VLNEXT when ICANON not set
Guy Harris
guy at auspex.auspex.com
Tue Apr 9 08:36:42 AEST 1991
The SunOS 4.x "ldterm" streams module - and, according to a person I
asked at Sun, the S5R4 version, derived from the SunOS version - doesn't
correctly handle the "literal-next" character when ICANON isn't set; it
does cause the character typed after it to be treated as ordinary input
(rather than, say, an interrupt/quit/suspend character), but the VLNEXT
character itself appears as input.
The fix is to the routine "do_noncanon_input()", or the moral equivalent
in the S5R4 "ldterm"; here's a patch to the SunOS 4.1 version - S5R4's
mileage may differ. The bug has been reported to AT&T, but if you want
to fix it before they do....
*** /home/unix_src/sunos/sunos.4.1/src/sys/os/tty_ldterm.c Sun Nov 25 13:37:31 1990
--- ./tty_ldterm.c Wed Mar 27 18:21:14 1991
***************
*** 1860,1913 ****
{
queue_t *wrq = WR(q);
int ebsize;
! register mblk_t *bp, *prevbp;
! mblk_t *savebp;
! register unsigned char *rptr;
for (bp = mp, prevbp = NULL; bp != NULL;
! prevbp = bp, bp = bp->b_cont) {
! while (bp->b_rptr == bp->b_wptr) {
/*
! * Zero-length block. Throw it away.
*/
! if (prevbp == NULL)
! mp = bp->b_cont;
! else
! prevbp->b_cont = bp->b_cont;
! savebp = bp;
! bp = bp->b_cont;
! savebp->b_cont = NULL;
! freeb(savebp);
! if (bp == NULL)
! return; /* entire message gone */
! }
! if (tp->t_modes.c_lflag & (ECHO|ECHONL)) {
! /*
! * Echo the data in this message.
! */
! if (tp->t_modes.c_lflag & ECHO) {
! ebsize = bp->b_wptr - bp->b_rptr;
! if (ebsize > EBSIZE)
! ebsize = EBSIZE;
! rptr = bp->b_rptr;
! while (rptr < bp->b_wptr)
! (void) echo_char(*rptr++, wrq,
! ebsize, tp);
! } else {
/*
! * Echo NL, even though ECHO is not
! * set.
*/
! rptr = bp->b_rptr;
! while (rptr < bp->b_wptr) {
! if (*rptr++ == '\n')
output_echo_char('\n',
wrq, 1, tp);
}
}
}
}
! putnext(q, mp);
/*
* Send whatever we echoed downstream.
--- 1860,1956 ----
{
queue_t *wrq = WR(q);
int ebsize;
! register mblk_t *bp, *prevbp, *nextbp;
! register unsigned char *rptr, *wptr;
! register unsigned char c;
for (bp = mp, prevbp = NULL; bp != NULL;
! prevbp = bp, bp = nextbp) {
! if (tp->t_modes.c_lflag & (ECHO|ECHONL|IEXTEN)) {
/*
! * Either we must echo the characters, or we must
! * echo NL, or we must check for VLNEXT.
! * Process characters one at a time.
*/
! ebsize = bp->b_wptr - bp->b_rptr;
! if (ebsize > EBSIZE)
! ebsize = EBSIZE;
! rptr = bp->b_rptr;
! wptr = bp->b_rptr;
! while (rptr < bp->b_wptr) {
! c = *rptr++;
/*
! * If this character is the literal next
! * character, echo it as '^' and backspace
! * over it if echoing is enabled, indicate
! * that the next character is to be treated
! * literally, and remove the LNEXT from the
! * input stream.
! *
! * If the *previous* character was the
! * literal next character, don't check
! * whether this is a literal next or not.
*/
! if ((tp->t_modes.c_lflag & IEXTEN)
! && !(tp->t_state & TS_SLNCH)
! && c != VDISABLE
! && c == tp->t_modes.c_cc[VLNEXT]) {
! if (tp->t_modes.c_lflag & ECHO)
! output_echo_string(
! (unsigned char *)"^\b",
! 2, wrq, ebsize, tp);
! tp->t_state |= TS_SLNCH;
! continue; /* and ignore it */
! }
!
! /*
! * Not a "literal next" character, so
! * it should show up as input.
! * If it was literal-nexted, turn off the
! * literal-next flag.
! */
! tp->t_state &= ~TS_SLNCH;
! *wptr++ = c;
! if (tp->t_modes.c_lflag & ECHO) {
! /*
! * Echo the character.
! */
! (void) echo_char(c, wrq, ebsize, tp);
! } else if (tp->t_modes.c_lflag & ECHONL) {
! /*
! * Echo NL, even though ECHO is not
! * set.
! */
! if (c == '\n')
output_echo_char('\n',
wrq, 1, tp);
}
}
+ bp->b_wptr = wptr;
+ } else {
+ /*
+ * If there are any characters in this buffer,
+ * and the first of them was literal-nexted,
+ * turn off the literal-next flag.
+ */
+ if (bp->b_rptr != bp->b_wptr)
+ tp->t_state &= ~TS_SLNCH;
}
+ nextbp = bp->b_cont; /* next block */
+ if (bp->b_rptr == bp->b_wptr) {
+ /*
+ * Zero-length block. Throw it away.
+ */
+ if (prevbp == NULL)
+ mp = nextbp;
+ else
+ prevbp->b_cont = nextbp;
+ bp->b_cont = NULL;
+ freeb(bp);
+ }
}
! if (mp != NULL)
! putnext(q, mp);
/*
* Send whatever we echoed downstream.
More information about the Comp.bugs.sys5
mailing list