about summary refs log tree commit diff
path: root/Src/Modules/zpty.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Modules/zpty.c')
-rw-r--r--Src/Modules/zpty.c46
1 files changed, 41 insertions, 5 deletions
diff --git a/Src/Modules/zpty.c b/Src/Modules/zpty.c
index 7e140102e..9bd14985e 100644
--- a/Src/Modules/zpty.c
+++ b/Src/Modules/zpty.c
@@ -468,7 +468,7 @@ checkptycmd(Ptycmd cmd)
 }
 
 static int
-ptyread(char *nam, Ptycmd cmd, char **args)
+ptyread(char *nam, Ptycmd cmd, char **args, int noblock)
 {
     int blen, used, seen = 0, ret = 0;
     char *buf;
@@ -509,6 +509,45 @@ ptyread(char *nam, Ptycmd cmd, char **args)
 	cmd->read = -1;
     }
     do {
+	if (noblock && cmd->read == -1) {
+	    int pollret;
+	    /*
+	     * Check there is data available.  Borrowed from
+	     * poll_read() in utils.c and simplified.
+	     */
+#ifdef HAVE_SELECT
+	    fd_set foofd;
+	    struct timeval expire_tv;
+	    expire_tv.tv_sec = 0;
+	    expire_tv.tv_usec = 0;
+	    FD_ZERO(&foofd);
+	    FD_SET(cmd->fd, &foofd);
+	    pollret = select(cmd->fd+1,
+			 (SELECT_ARG_2_T) &foofd, NULL, NULL, &expire_tv);
+#else
+#ifdef FIONREAD
+	    if (ioctl(cmd->fd, FIONREAD, (char *) &val) == 0)
+		pollret = (val > 0);
+#endif
+#endif
+
+	    if (pollret < 0) {
+		/*
+		 * See read_poll() for this.
+		 * Last despairing effort to poll: attempt to
+		 * set nonblocking I/O and actually read the
+		 * character.  cmd->read stores the character read.
+		 */
+		long mode;
+
+		if (setblock_fd(0, cmd->fd, &mode))
+		    pollret = read(cmd->fd, &cmd->read, 1);
+		if (mode != -1)
+		    fcntl(cmd->fd, F_SETFL, mode);
+	    }
+	    if (pollret == 0)
+		break;
+	}
 	if (!ret) {
 	    checkptycmd(cmd);
 	    if (cmd->fin)
@@ -648,12 +687,9 @@ bin_zpty(char *nam, char **args, Options ops, UNUSED(int func))
 	}
 	if (p->fin)
 	    return 2;
-	if (OPT_ISSET(ops,'t') && p->read == -1 &&
-	    !read_poll(p->fd, &p->read, 0, 0))
-	    return 1;
 
 	return (OPT_ISSET(ops,'r') ?
-		ptyread(nam, p, args + 1) :
+		ptyread(nam, p, args + 1, OPT_ISSET(ops,'t')) :
 		ptywrite(p, args + 1, OPT_ISSET(ops,'n')));
     } else if (OPT_ISSET(ops,'d')) {
 	Ptycmd p;