$NetBSD: patch-ac,v 1.4 2023/09/06 18:34:24 bouyer Exp $ Make this compile on Solaris. Fix a bug where rtty would loop forever if its parent process (such as a shell) were to die and close rtty's standard input. Fix a bug where rtty would exit with messages like serv_input: read@3 need 468 got 396 when a read on the unix socket returns a partial read. --- rtty.c.orig 2023-09-06 18:23:56.430905709 +0200 +++ rtty.c 2023-09-06 18:24:21.275470294 +0200 @@ -34,6 +34,11 @@ #include #include #include +#include + +#if (defined(__sun__) && defined(__svr4__)) +#include +#endif #include "rtty.h" #ifdef NEED_BITYPES_H @@ -266,13 +271,16 @@ static void tty_input(fd) { static enum {base, need_cr, tilde} state = base; + ssize_t cnt; + int readone = 0; u_char buf[1]; #if 0 fcntl(Tty, F_SETFL, fcntl(Tty, F_GETFL, 0)|O_NONBLOCK); #endif - while (1 == read(fd, buf, 1)) { + while (1 == (cnt = read(fd, buf, 1))) { u_char ch = buf[0]; + readone = 1; switch (state) { case base: @@ -346,6 +354,14 @@ write(Log, buf, 1); } } + + if (readone == 0 && cnt == 0) { + /* + * True EOF -- get out now rather than loop forever. + */ + quit(0); + } + #if 0 fcntl(Tty, F_SETFL, fcntl(Tty, F_GETFL, 0)&~O_NONBLOCK); #endif @@ -502,6 +518,33 @@ } } +static ssize_t +read_exact(int fd, void *buf, size_t nbytes) +{ + struct pollfd pfd; + ssize_t ret = 0, r; + + while (nbytes > 0) { + pfd.fd = fd; + pfd.events = POLLRDNORM; + pfd.revents = 0; + + switch (poll(&pfd, 1, 1000)) { + case -1: + return -1; + case 0: + return ret; + default: + r = read(fd, buf, nbytes); + if (r < 0) + return r; + ret += r; + nbytes -= r; + break; + } + } +} + static void serv_input(fd) { char passwd[TP_MAXVAR], s[3], *c, *crypt(); @@ -521,7 +564,7 @@ switch (t) { case TP_DATA: /* FALLTHROUGH */ case TP_NOTICE: - if (i != (nchars = read(fd, T.c, i))) { + if (i != (nchars = read_exact(fd, T.c, i))) { fprintf(stderr, "serv_input: read@%d need %d got %d\n", fd, i, nchars); server_died(); @@ -563,7 +606,7 @@ break; case TP_PARITY: if (o & TP_QUERY) { - if (i != (nchars = read(fd, T.c, i))) { + if (i != (nchars = read_exact(fd, T.c, i))) { server_died(); } T.c[i] = '\0';