summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--Doc/Zsh/mod_zpty.yo5
-rw-r--r--Functions/Misc/nslookup2
-rw-r--r--Src/Modules/zpty.c55
-rw-r--r--Src/utils.c2
-rw-r--r--Test/comptest2
6 files changed, 55 insertions, 17 deletions
diff --git a/ChangeLog b/ChangeLog
index 4c3c49966..a8bf8c92a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2000-10-19  Sven Wischnowsky  <wischnow@zsh.org>
+
+	* 13035: Doc/Zsh/mod_zpty.yo, Functions/Misc/nslookup, Src/utils.c,
+ 	Src/Modules/zpty.c, Test/comptest: make non-blocking IO on ptys
+ 	work again; add -t option to test if command is still alive
+	
 2000-10-19  Wayne Davison  <wayned@users.sourceforge.net>
 
 	* 13034: Src/hist.c: Don't call histreduceblanks() if the line
diff --git a/Doc/Zsh/mod_zpty.yo b/Doc/Zsh/mod_zpty.yo
index 0c1558056..664e2fabd 100644
--- a/Doc/Zsh/mod_zpty.yo
+++ b/Doc/Zsh/mod_zpty.yo
@@ -9,6 +9,7 @@ xitem(tt(zpty) [ tt(-e) ] [ tt(-b) ] var(name) var(command) [ var(args ...) ])
 xitem(tt(zpty) tt(-d) [ var(names) ... ])
 xitem(tt(zpty) tt(-w) [ tt(-n) ] var(name) var(strings ...))
 xitem(tt(zpty) tt(-r) var(name) [ var(param) [ var(pattern) ] ])
+xitem(tt(zpty) tt(-t) var(name))
 item(tt(zpty) [ tt(-L) ])(
 In the first form, the var(command) is started with the var(args) as
 arguments.  The command runs under a newly assigned pseudo-terminal; this
@@ -35,6 +36,10 @@ read will be put in the parameter named var(param).  If the
 var(pattern) is also given, output will be read until the whole string 
 read matches the var(pattern).
 
+The tt(-t) option can be used to test whether the command var(name) is 
+still running.  It returns a zero value if the command is running and
+a non-zero value otherwise.
+
 The last form without any arguments is used to list the commands
 currently defined.  If the tt(-L) option is given, this is done in the
 form of calls to the tt(zpty) builtin.
diff --git a/Functions/Misc/nslookup b/Functions/Misc/nslookup
index d4f7e96b9..1751ef68a 100644
--- a/Functions/Misc/nslookup
+++ b/Functions/Misc/nslookup
@@ -24,7 +24,7 @@ zstyle -s ':nslookup' pager tmp &&
     [[ -z "$pager" ]] && pager="${opager:-more}"
 (( $#pmpt )) || pmpt=(-p '> ')
 
-zpty nslookup nslookup "$@"
+zpty -b nslookup nslookup "$@"
 
 zpty -r nslookup line '*
 > '
diff --git a/Src/Modules/zpty.c b/Src/Modules/zpty.c
index b469feb72..18f838ed4 100644
--- a/Src/Modules/zpty.c
+++ b/Src/Modules/zpty.c
@@ -48,6 +48,7 @@ struct ptycmd {
     int echo;
     int block;
     int fin;
+    int read;
 };
 
 static Ptycmd ptycmds;
@@ -381,6 +382,7 @@ newptycmd(char *nam, char *pname, char **args, int echo, int block)
     p->echo = echo;
     p->block = block;
     p->fin = 0;
+    p->read = -1;
 
     p->next = ptycmds;
     ptycmds = p;
@@ -434,7 +436,9 @@ deleteallptycmds(void)
 static void
 checkptycmd(Ptycmd cmd)
 {
-    if (kill(cmd->pid, 0) < 0) {
+    if (cmd->read != -1)
+	return;
+    if (!read_poll(cmd->fd, &cmd->read, 1) && kill(cmd->pid, 0) < 0) {
 	cmd->fin = 1;
 	zclose(cmd->fd);
     }
@@ -444,7 +448,7 @@ static int
 ptyread(char *nam, Ptycmd cmd, char **args)
 {
     int blen = 256, used = 0, ret = 1;
-    char *buf = (char *) zhalloc(blen + 1);
+    char *buf = (char *) zhalloc((blen = 256) + 1);
     Patprog prog = NULL;
 
     if (*args && args[1]) {
@@ -462,6 +466,12 @@ ptyread(char *nam, Ptycmd cmd, char **args)
 	    return 1;
 	}
     }
+    if (cmd->read != -1) {
+	buf[0] = (char) cmd->read;
+	buf[1] = '\0';
+	used = 1;
+	cmd->read = -1;
+    }
     do {
 	if (!ret) {
 	    checkptycmd(cmd);
@@ -476,11 +486,10 @@ ptyread(char *nam, Ptycmd cmd, char **args)
 	}
 	buf[used] = '\0';
 
-	/**** Hm. If we leave the loop when ret < 0 the user would have
-	 *    to make sure that `zpty -r' is tried more than once if
-	 *    there will be some output and we only got the ret == -1
-	 *    because the output is not yet available.
-	 *    The same for the `write' below. */
+#if 0
+	/* This once used the following test, to make sure to return
+	 * non-zero if there are no characters to read.  That looks
+	 * like a thinko now, because it disables non-blocking ptys. */
 
 	if (ret < 0 && (cmd->block
 #ifdef EWOULDBLOCK
@@ -492,8 +501,9 @@ ptyread(char *nam, Ptycmd cmd, char **args)
 #endif
 			))
 	    break;
+#endif
 
-	if (!prog && !ret)
+	if (!prog && ret <= 0)
 	    break;
     } while (!errflag && !breaks && !retflag && !contflag &&
 	     (prog ? (used < READ_MAX && (!ret || !pattry(prog, buf))) :
@@ -514,7 +524,10 @@ ptywritestr(Ptycmd cmd, char *s, int len)
     int written;
 
     for (; len; len -= written, s += written) {
-	if ((written = write(cmd->fd, s, len)) < 0 &&
+	if ((written = write(cmd->fd, s, len)) < 0
+#if 0
+	    /* Same as above. */
+	    &&
 	    (cmd->block
 #ifdef EWOULDBLOCK
 			|| errno != EWOULDBLOCK
@@ -523,7 +536,9 @@ ptywritestr(Ptycmd cmd, char *s, int len)
 			|| errno != EAGAIN
 #endif
 #endif
-	     ))
+	     )
+#endif
+	    )
 	    return 1;
 	if (written < 0) {
 	    checkptycmd(cmd);
@@ -567,11 +582,11 @@ static int
 bin_zpty(char *nam, char **args, char *ops, int func)
 {
     if ((ops['r'] && ops['w']) ||
-	((ops['r'] || ops['w']) && (ops['d'] || ops['e'] ||
+	((ops['r'] || ops['w']) && (ops['d'] || ops['e'] || ops['t'] ||
 				    ops['b'] || ops['L'])) ||
-	(ops['n'] && (ops['b'] || ops['e'] || ops['r'] ||
+	(ops['n'] && (ops['b'] || ops['e'] || ops['r'] || ops['t'] ||
 		      ops['d'] || ops['L'])) ||
-	(ops['d'] && (ops['b'] || ops['e'] || ops['L'])) ||
+	(ops['d'] && (ops['b'] || ops['e'] || ops['L'] || ops['t'])) ||
 	(ops['L'] && (ops['b'] || ops['e']))) {
 	zwarnnam(nam, "illegal option combination", NULL, 0);
 	return 1;
@@ -607,6 +622,18 @@ bin_zpty(char *nam, char **args, char *ops, int func)
 	    deleteallptycmds();
 
 	return ret;
+    } else if (ops['t']) {
+	Ptycmd p;
+
+	if (!*args) {
+	    zwarnnam(nam, "missing pty command name", NULL, 0);
+	    return 1;
+	} else if (!(p = getptycmd(*args))) {
+	    zwarnnam(nam, "no such pty command: %s", *args, 0);
+	    return 1;
+	}
+	checkptycmd(p);
+	return p->fin;
     } else if (*args) {
 	if (!args[1]) {
 	    zwarnnam(nam, "missing command", NULL, 0);
@@ -649,7 +676,7 @@ ptyhook(Hookdef d, void *dummy)
 }
 
 static struct builtin bintab[] = {
-    BUILTIN("zpty", 0, bin_zpty, 0, -1, 0, "ebdrwLn", NULL),
+    BUILTIN("zpty", 0, bin_zpty, 0, -1, 0, "ebdrwLnt", NULL),
 };
 
 /**/
diff --git a/Src/utils.c b/Src/utils.c
index 4e5da893b..05865cf67 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -1312,7 +1312,7 @@ setblock_stdin(void)
  */
 
 /**/
-int
+mod_export int
 read_poll(int fd, int *readchar, int polltty)
 {
     int ret = 0;
diff --git a/Test/comptest b/Test/comptest
index cb0e06f57..0f57e7d70 100644
--- a/Test/comptest
+++ b/Test/comptest
@@ -16,7 +16,7 @@ comptestinit () {
   (( OPTIND > 1 )) && shift $(( OPTIND - 1 ))
 
   export PS1="<PROMPT>"
-  zpty zsh "$comptest_zsh" -f
+  zpty -b zsh "$comptest_zsh" -f
 
   zpty -r zsh log1 "*<PROMPT>*" || { 
     print "first prompt hasn't appeared."