diff options
author | phk <phk@FreeBSD.org> | 2004-06-26 08:44:04 +0000 |
---|---|---|
committer | phk <phk@FreeBSD.org> | 2004-06-26 08:44:04 +0000 |
commit | 1aa6c5a754b178a4700e8508f2e7a2f5136fd9b6 (patch) | |
tree | 04c3b44b676c0a500305ae7636bab0655dde9123 /sys/kern/tty.c | |
parent | 772718717b358bd1045f527cb6842b45a4838f18 (diff) | |
download | FreeBSD-src-1aa6c5a754b178a4700e8508f2e7a2f5136fd9b6.zip FreeBSD-src-1aa6c5a754b178a4700e8508f2e7a2f5136fd9b6.tar.gz |
Fix line discipline switching issues: If opening a new ldisc fails,
we have to revert to TTYDISC which we know will successfully open
rather than try the previous ldisc which might also fail to open.
Do not let ldisc implementations muck about with ->t_line, and remove
code which checks for reopens, it should never happen.
Move ldisc->l_hotchar to tty->t_hotchar and have ldisc implementation
initialize it in their open routines. Reset to zero when we enter
TTYDISC. ("no" should really be -1 since zero could be a valid
hotchar for certain old european mainframe protocols.)
Diffstat (limited to 'sys/kern/tty.c')
-rw-r--r-- | sys/kern/tty.c | 33 |
1 files changed, 21 insertions, 12 deletions
diff --git a/sys/kern/tty.c b/sys/kern/tty.c index fced5d7..5520b82 100644 --- a/sys/kern/tty.c +++ b/sys/kern/tty.c @@ -236,6 +236,7 @@ ttyopen(struct cdev *device, struct tty *tp) s = spltty(); tp->t_dev = device; + tp->t_hotchar = 0; if (!ISSET(tp->t_state, TS_ISOPEN)) { ttyref(tp); SET(tp->t_state, TS_ISOPEN); @@ -276,6 +277,7 @@ ttyclose(struct tty *tp) tp->t_gen++; tp->t_line = TTYDISC; + tp->t_hotchar = 0; tp->t_pgrp = NULL; tp->t_session = NULL; tp->t_state = 0; @@ -1072,18 +1074,25 @@ ttioctl(struct tty *tp, u_long cmd, void *data, int flag) if ((u_int)t >= nlinesw) return (ENXIO); - if (t != tp->t_line) { - s = spltty(); - ttyld_close(tp, flag); - error = (*linesw[t]->l_open)(device, tp); - if (error) { - (void)ttyld_open(tp, device); - splx(s); - return (error); - } - tp->t_line = t; - splx(s); + if (t == tp->t_line) + return (0); + s = spltty(); + ttyld_close(tp, flag); + tp->t_line = t; + error = ttyld_open(tp, device); + if (error) { + /* + * If we fail to switch line discipline we cannot + * fall back to the previous, because we can not + * trust that ldisc to open successfully either. + * Fall back to the default ldisc which we know + * will allways succeed. + */ + tp->t_line = TTYDISC; + (void)ttyld_open(tp, device); } + splx(s); + return (error); break; } case TIOCSTART: /* start output, like ^Q */ @@ -2905,7 +2914,7 @@ ttyldoptim(struct tty *tp) tp->t_state |= TS_CAN_BYPASS_L_RINT; else tp->t_state &= ~TS_CAN_BYPASS_L_RINT; - return (linesw[tp->t_line]->l_hotchar); + return (tp->t_hotchar); } |