iFix ttywrite() - st - Simple Terminal Err gopher.r-36.net 70 i Err gopher.r-36.net 70 1Log /scm/st//log.gph gopher.r-36.net 70 1Files /scm/st//files.gph gopher.r-36.net 70 1Refs /scm/st//refs.gph gopher.r-36.net 70 1README /scm/st//file/README.gph gopher.r-36.net 70 1LICENSE /scm/st//file/LICENSE.gph gopher.r-36.net 70 i--- Err gopher.r-36.net 70 1commit 9f6d8845df3f81e2bc86f593a2f93e098422b2fa /scm/st//commit/9f6d8845df3f81e2bc86f593a2f93e098422b2fa.gph gopher.r-36.net 70 1parent f0398db4d172e838ef4b4ae55db3fb6a6fee6717 /scm/st//commit/f0398db4d172e838ef4b4ae55db3fb6a6fee6717.gph gopher.r-36.net 70 hAuthor: Roberto E. Vargas Caballero URL:mailto:k0ga@shike2.com gopher.r-36.net 70 iDate: Fri, 6 Nov 2015 20:01:00 +0100 Err gopher.r-36.net 70 i Err gopher.r-36.net 70 iFix ttywrite() Err gopher.r-36.net 70 i Err gopher.r-36.net 70 ittywrite was assuming that if it could not write then it could Err gopher.r-36.net 70 iread, but this is not necessarily true, there are some situations Err gopher.r-36.net 70 iwhere you cannot read or write. The correct behaviour is to detect Err gopher.r-36.net 70 iif you can read or/and write. Err gopher.r-36.net 70 i Err gopher.r-36.net 70 iDiffstat: Err gopher.r-36.net 70 i st.c | 38 ++++++++++++++++--------------- Err gopher.r-36.net 70 i Err gopher.r-36.net 70 i1 file changed, 20 insertions(+), 18 deletions(-) Err gopher.r-36.net 70 i--- Err gopher.r-36.net 70 1diff --git a/st.c b/st.c /scm/st//file/st.c.gph gopher.r-36.net 70 i@@ -415,7 +415,7 @@ static int32_t tdefcolor(int *, int *, int); Err gopher.r-36.net 70 i static void tdeftran(char); Err gopher.r-36.net 70 i static inline int match(uint, uint); Err gopher.r-36.net 70 i static void ttynew(void); Err gopher.r-36.net 70 i-static void ttyread(void); Err gopher.r-36.net 70 i+static size_t ttyread(void); Err gopher.r-36.net 70 i static void ttyresize(void); Err gopher.r-36.net 70 i static void ttysend(char *, size_t); Err gopher.r-36.net 70 i static void ttywrite(const char *, size_t); Err gopher.r-36.net 70 i@@ -1464,7 +1464,7 @@ ttynew(void) Err gopher.r-36.net 70 i } Err gopher.r-36.net 70 i } Err gopher.r-36.net 70 i Err gopher.r-36.net 70 i-void Err gopher.r-36.net 70 i+size_t Err gopher.r-36.net 70 i tttyread(void) Err gopher.r-36.net 70 i { Err gopher.r-36.net 70 i static char buf[BUFSIZ]; Err gopher.r-36.net 70 i@@ -1489,14 +1489,16 @@ ttyread(void) Err gopher.r-36.net 70 i Err gopher.r-36.net 70 i /* keep any uncomplete utf8 char for the next call */ Err gopher.r-36.net 70 i memmove(buf, ptr, buflen); Err gopher.r-36.net 70 i+ Err gopher.r-36.net 70 i+ return ret; Err gopher.r-36.net 70 i } Err gopher.r-36.net 70 i Err gopher.r-36.net 70 i void Err gopher.r-36.net 70 i tttywrite(const char *s, size_t n) Err gopher.r-36.net 70 i { Err gopher.r-36.net 70 i- fd_set wfd; Err gopher.r-36.net 70 i- struct timespec tv; Err gopher.r-36.net 70 i+ fd_set wfd, rfd; Err gopher.r-36.net 70 i ssize_t r; Err gopher.r-36.net 70 i+ size_t lim = 256; Err gopher.r-36.net 70 i Err gopher.r-36.net 70 i /* Err gopher.r-36.net 70 i * Remember that we are using a pty, which might be a modem line. Err gopher.r-36.net 70 i@@ -1506,38 +1508,34 @@ ttywrite(const char *s, size_t n) Err gopher.r-36.net 70 i */ Err gopher.r-36.net 70 i while (n > 0) { Err gopher.r-36.net 70 i FD_ZERO(&wfd); Err gopher.r-36.net 70 i+ FD_ZERO(&rfd); Err gopher.r-36.net 70 i FD_SET(cmdfd, &wfd); Err gopher.r-36.net 70 i- tv.tv_sec = 0; Err gopher.r-36.net 70 i- tv.tv_nsec = 0; Err gopher.r-36.net 70 i+ FD_SET(cmdfd, &rfd); Err gopher.r-36.net 70 i Err gopher.r-36.net 70 i /* Check if we can write. */ Err gopher.r-36.net 70 i- if (pselect(cmdfd+1, NULL, &wfd, NULL, &tv, NULL) < 0) { Err gopher.r-36.net 70 i+ if (pselect(cmdfd+1, &rfd, &wfd, NULL, NULL, NULL) < 0) { Err gopher.r-36.net 70 i if (errno == EINTR) Err gopher.r-36.net 70 i continue; Err gopher.r-36.net 70 i die("select failed: %s\n", strerror(errno)); Err gopher.r-36.net 70 i } Err gopher.r-36.net 70 i- if(!FD_ISSET(cmdfd, &wfd)) { Err gopher.r-36.net 70 i- /* No, then free some buffer space. */ Err gopher.r-36.net 70 i- ttyread(); Err gopher.r-36.net 70 i- } else { Err gopher.r-36.net 70 i+ if (FD_ISSET(cmdfd, &rfd)) Err gopher.r-36.net 70 i+ lim = ttyread(); Err gopher.r-36.net 70 i+ if (FD_ISSET(cmdfd, &wfd)) { Err gopher.r-36.net 70 i /* Err gopher.r-36.net 70 i * Only write 256 bytes at maximum. This seems to be a Err gopher.r-36.net 70 i * reasonable value for a serial line. Bigger values Err gopher.r-36.net 70 i * might clog the I/O. Err gopher.r-36.net 70 i */ Err gopher.r-36.net 70 i- r = write(cmdfd, s, (n < 256)? n : 256); Err gopher.r-36.net 70 i- if (r < 0) { Err gopher.r-36.net 70 i- die("write error on tty: %s\n", Err gopher.r-36.net 70 i- strerror(errno)); Err gopher.r-36.net 70 i- } Err gopher.r-36.net 70 i+ if ((r = write(cmdfd, s, (n < 256)? n : 256)) < 0) Err gopher.r-36.net 70 i+ goto write_error; Err gopher.r-36.net 70 i if (r < n) { Err gopher.r-36.net 70 i /* Err gopher.r-36.net 70 i * We weren't able to write out everything. Err gopher.r-36.net 70 i * This means the buffer is getting full Err gopher.r-36.net 70 i * again. Empty it. Err gopher.r-36.net 70 i */ Err gopher.r-36.net 70 i- if (n < 256) Err gopher.r-36.net 70 i- ttyread(); Err gopher.r-36.net 70 i+ if (n < lim) Err gopher.r-36.net 70 i+ lim = ttyread(); Err gopher.r-36.net 70 i n -= r; Err gopher.r-36.net 70 i s += r; Err gopher.r-36.net 70 i } else { Err gopher.r-36.net 70 i@@ -1546,6 +1544,10 @@ ttywrite(const char *s, size_t n) Err gopher.r-36.net 70 i } Err gopher.r-36.net 70 i } Err gopher.r-36.net 70 i } Err gopher.r-36.net 70 i+ return; Err gopher.r-36.net 70 i+ Err gopher.r-36.net 70 i+write_error: Err gopher.r-36.net 70 i+ die("write error on tty: %s\n", strerror(errno)); Err gopher.r-36.net 70 i } Err gopher.r-36.net 70 i Err gopher.r-36.net 70 i void Err gopher.r-36.net 70 .