guy@auspex.auspex.com (Guy Harris) (04/09/91)
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.