Implement chunked write to the cmdfd. - st - simple terminal HTML git clone https://git.parazyd.org/st DIR Log DIR Files DIR Refs DIR README DIR LICENSE --- DIR commit 261ea4b7e0b8d979c0c91ec75251c6970caf39e2 DIR parent f8c6e7d0419d10c1425cb2c7123c5798ffb3b942 HTML Author: Christoph Lohmann <20h@r-36.net> Date: Fri, 10 Jul 2015 14:15:39 +0200 Implement chunked write to the cmdfd. This is needed so big input like a paste of several megabyte does not clog our I/O. Diffstat: M st.c | 53 +++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) --- DIR diff --git a/st.c b/st.c @@ -1478,8 +1478,57 @@ ttyread(void) void ttywrite(const char *s, size_t n) { - if (xwrite(cmdfd, s, n) == -1) - die("write error on tty: %s\n", strerror(errno)); + fd_set wfd; + struct timespec tv; + ssize_t r; + + /* + * Remember that we are using a pty, which might be a modem line. + * Writing too much will clog the line. That's why we are doing this + * dance. + * FIXME: Migrate the world to Plan 9. + */ + while (n > 0) { + FD_ZERO(&wfd); + FD_SET(cmdfd, &wfd); + tv.tv_sec = 0; + tv.tv_nsec = 0; + + /* Check if we can write. */ + if (pselect(cmdfd+1, NULL, &wfd, NULL, &tv, NULL) < 0) { + if (errno == EINTR) + continue; + die("select failed: %s\n", strerror(errno)); + } + if(!FD_ISSET(cmdfd, &wfd)) { + /* No, then free some buffer space. */ + ttyread(); + } else { + /* + * Only write 256 bytes at maximum. This seems to be a + * reasonable value for a serial line. Bigger values + * might clog the I/O. + */ + r = write(cmdfd, s, (n < 256)? n : 256); + if (r < 0) { + die("write error on tty: %s\n", + strerror(errno)); + } + if (r < n) { + /* + * We weren't able to write out everything. + * This means the buffer is getting full + * again. Empty it. + */ + ttyread(); + n -= r; + s += r; + } else { + /* All bytes have been written. */ + break; + } + } + } } void