diff --git a/ttynvt.c b/ttynvt.c index 6594b5f..5530e8b 100644 --- a/ttynvt.c +++ b/ttynvt.c @@ -559,6 +559,11 @@ static const char *_ioctl_name(int cmd) } } +#define CHECK_BUF_IN(sz) \ + if (in_bufsz < sz) do { in_bufsz = sz; goto retry_in; } while(0) +#define CHECK_BUF_OUT(sz) \ + if (out_bufsz < sz) do { out_bufsz = sz; goto retry_out; } while(0) + static void ttynvt_ioctl(fuse_req_t req, int cmd, void *arg, struct fuse_file_info *info, unsigned int flags, @@ -581,12 +586,7 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg, case TCSETSF: case TCSETSW: case TCSETS: - if (!in_bufsz) - { - struct iovec iov = { arg, sizeof(struct termios) }; - fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0); - } - else + CHECK_BUF_IN(sizeof(struct termios)); { speed_t speed; int csize, par, sb; @@ -650,45 +650,20 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg, } break; case TCGETS: - if (out_bufsz) - { - fuse_reply_ioctl(req, 0, &tio, sizeof(struct termio)); - } - else - { - struct iovec iov = { arg, sizeof(struct termio) }; - fuse_reply_ioctl_retry(req, NULL, 0, &iov, 1); - } + CHECK_BUF_OUT(sizeof(struct termios)); + fuse_reply_ioctl(req, 0, &tio, sizeof(struct termios)); break; - case TIOCINQ: /* Get the number of bytes in the input * buffer */ - if (out_bufsz) - { - size_t rx_size = _read_avail(tty); - - fuse_reply_ioctl(req, 0, &rx_size, sizeof(size_t)); - } - else - { - struct iovec iov = { arg, sizeof(size_t) }; - fuse_reply_ioctl_retry(req, NULL, 0, &iov, 1); - } - + CHECK_BUF_OUT(sizeof(int)); + val = _read_avail(tty); + fuse_reply_ioctl(req, 0, &val, sizeof(int)); break; case TIOCOUTQ: /* Get the number of bytes in the output * buffer */ - if (out_bufsz) - { - size_t tx_size = _write_avail(tty); - - fuse_reply_ioctl(req, 0, &tx_size, sizeof(size_t)); - } - else - { - struct iovec iov = { arg, sizeof(size_t) }; - fuse_reply_ioctl_retry(req, NULL, 0, &iov, 1); - } + CHECK_BUF_OUT(sizeof(int)); + val = _write_avail(tty); + fuse_reply_ioctl(req, 0, &val, sizeof(int)); break; case TCFLSH: if (arg == TCIFLUSH) @@ -711,7 +686,6 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg, pthread_mutex_lock(&tty->tty_lock); tty->blen = 0; pthread_mutex_unlock(&tty->tty_lock); - fuse_reply_ioctl(req, 0, 0, 0); break; case TCOFLUSH: @@ -725,27 +699,13 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg, fuse_reply_ioctl(req, 0, 0, 0); break; case TIOCMGET: - if (out_bufsz) - { - fuse_reply_ioctl(req, 0, &mcr, sizeof(unsigned int)); - } - else - { - struct iovec iov = { arg, sizeof(unsigned int) }; - fuse_reply_ioctl_retry(req, NULL, 0, &iov, 1); - } + CHECK_BUF_OUT(sizeof(int)); + fuse_reply_ioctl(req, 0, &mcr, sizeof(int)); break; case TIOCMBIS: - if (!in_bufsz) - { - struct iovec iov = { arg, sizeof(unsigned int) }; - fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0); - } - else - { - tiocm = *(unsigned int *)in_buf; - fuse_reply_ioctl(req, 0, 0, 0); - } + CHECK_BUF_IN(sizeof(int)); + tiocm = *(unsigned int *)in_buf; + fuse_reply_ioctl(req, 0, 0, 0); if (tiocm & TIOCM_RTS) { mcr |= TIOCM_RTS; @@ -758,16 +718,9 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg, } break; case TIOCMBIC: - if (!in_bufsz) - { - struct iovec iov = { arg, sizeof(unsigned int) }; - fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0); - } - else - { - tiocm = *(unsigned int *)in_buf; - fuse_reply_ioctl(req, 0, 0, 0); - } + CHECK_BUF_IN(sizeof(int)); + tiocm = *(unsigned int *)in_buf; + fuse_reply_ioctl(req, 0, 0, 0); if (tiocm & TIOCM_RTS) { mcr &= ~TIOCM_RTS; @@ -780,45 +733,48 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg, } break; case TIOCMSET: - if (!in_bufsz) - { - struct iovec iov = { arg, sizeof(unsigned int) }; - fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0); - } - else - { - tiocm = *(unsigned int *)in_buf; - fuse_reply_ioctl(req, 0, 0, 0); + CHECK_BUF_IN(sizeof(int)); + tiocm = *(unsigned int *)in_buf; + fuse_reply_ioctl(req, 0, 0, 0); - DBG("CFG ioctl: DTR=%c RTS=%c\n", - tiocm & TIOCM_DTR ? '1' : '0', tiocm & TIOCM_RTS ? '1' : '0'); + DBG("CFG ioctl: DTR=%c RTS=%c\n", + tiocm & TIOCM_DTR ? '1' : '0', tiocm & TIOCM_RTS ? '1' : '0'); - mcr &= ~(TIOCM_RTS | TIOCM_DTR); - mcr |= tiocm & (TIOCM_RTS | TIOCM_DTR); - telnet_rfc2217_ctl(tty->tn, (tiocm & TIOCM_DTR) ? - TNS_CTL_DTR_ON : TNS_CTL_DTR_OFF); - telnet_rfc2217_ctl(tty->tn, (tiocm & TIOCM_RTS) ? - TNS_CTL_RTS_ON : TNS_CTL_RTS_OFF); - } + mcr &= ~(TIOCM_RTS | TIOCM_DTR); + mcr |= tiocm & (TIOCM_RTS | TIOCM_DTR); + telnet_rfc2217_ctl(tty->tn, (tiocm & TIOCM_DTR) ? + TNS_CTL_DTR_ON : TNS_CTL_DTR_OFF); + telnet_rfc2217_ctl(tty->tn, (tiocm & TIOCM_RTS) ? + TNS_CTL_RTS_ON : TNS_CTL_RTS_OFF); break; case TCSBRK: fuse_reply_ioctl(req, 0, 0, 0); break; case TIOCGWINSZ: - if (out_bufsz) + CHECK_BUF_OUT(sizeof(struct winsize)); { struct winsize ws = {.ws_row = 25,.ws_col = 80 }; fuse_reply_ioctl(req, 0, &ws, sizeof(struct winsize)); } - else + break; + + default: + fuse_reply_err(req, ENOSYS); + break; + + retry_in: { - struct iovec iov = { arg, sizeof(struct winsize) }; + struct iovec iov = { arg, in_bufsz }; + fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0); + } + break; + + retry_out: + { + struct iovec iov = { arg, out_bufsz }; fuse_reply_ioctl_retry(req, NULL, 0, &iov, 1); } break; - default: - fuse_reply_err(req, ENOSYS); - return; } }