diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | Doc/Zsh/mod_zpty.yo | 11 | ||||
-rw-r--r-- | Src/Modules/zpty.c | 46 | ||||
-rw-r--r-- | Test/comptest | 4 |
4 files changed, 46 insertions, 21 deletions
diff --git a/ChangeLog b/ChangeLog index 50e9bdc09..2ee34773b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2009-01-13 Peter Stephenson <pws@csr.com> + * Doc/Zsh/mod_zpty.yo, Src/Modules/zpty.c, Test/comptest: + make "zpty -r" exit more cleanly on read failures and add and + use option to ensure a pattern has been matched. + * 26300: Src/zsh.mdd: don't use "echo -n" for $ZSH_PATCHLEVEL. 2009-01-09 Peter Stephenson <p.w.stephenson@ntlworld.com> @@ -10893,5 +10897,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.4504 $ +* $Revision: 1.4505 $ ***************************************************** diff --git a/Doc/Zsh/mod_zpty.yo b/Doc/Zsh/mod_zpty.yo index 5a5459179..de471153e 100644 --- a/Doc/Zsh/mod_zpty.yo +++ b/Doc/Zsh/mod_zpty.yo @@ -38,7 +38,7 @@ Note that the command under the pseudo-terminal sees this input as if it were typed, so beware when sending special tty driver characters such as word-erase, line-kill, and end-of-file. ) -item(tt(zpty) tt(-r) [ tt(-t) ] var(name) [ var(param) [ var(pattern) ] ])( +item(tt(zpty) tt(-r) [ tt(-mt) ] var(name) [ var(param) [ var(pattern) ] ])( The tt(-r) option can be used to read the output of the command var(name). With only a var(name) argument, the output read is copied to the standard output. Unless the pseudo-terminal is non-blocking, copying continues @@ -54,10 +54,11 @@ one character is stored in var(param). If a var(pattern) is given as well, output is read until the whole string read matches the var(pattern), even in the non-blocking case. The return status is zero if the string read matches the pattern, or if the command -has exited but at least one character could still be read. As of this -writing, a maximum of one megabyte of output can be consumed this way; if -a full megabyte is read without matching the pattern, the return status is -non-zero. +has exited but at least one character could still be read. If the option +tt(-m) is present, the return status is zero only if the pattern matches. +As of this writing, a maximum of one megabyte of output can be consumed +this way; if a full megabyte is read without matching the pattern, the +return status is non-zero. In all cases, the return status is non-zero if nothing could be read, and is tt(2) if this is because the command has finished. diff --git a/Src/Modules/zpty.c b/Src/Modules/zpty.c index d115afcef..4899f8e2e 100644 --- a/Src/Modules/zpty.c +++ b/Src/Modules/zpty.c @@ -485,9 +485,9 @@ checkptycmd(Ptycmd cmd) } static int -ptyread(char *nam, Ptycmd cmd, char **args, int noblock) +ptyread(char *nam, Ptycmd cmd, char **args, int noblock, int mustmatch) { - int blen, used, seen = 0, ret = 0; + int blen, used, seen = 0, ret = 0, matchok = 0; char *buf; Patprog prog = NULL; @@ -589,10 +589,24 @@ ptyread(char *nam, Ptycmd cmd, char **args, int noblock) } buf[used] = '\0'; - if (!prog && (ret <= 0 || (*args && buf[used - 1] == '\n'))) - break; + if (!prog) { + if (ret <= 0 || (*args && buf[used - 1] == '\n')) + break; + } else { + if (ret < 0 +#ifdef EWOULDBLOCK + && errno != EWOULDBLOCK +#else +#ifdef EAGAIN + && errno != EAGAIN +#endif +#endif + ) + break; + } } while (!(errflag || breaks || retflag || contflag) && - used < READ_MAX && !(prog && ret && pattry(prog, buf))); + used < READ_MAX && + !(prog && ret && (matchok = pattry(prog, buf)))); if (prog && ret < 0 && #ifdef EWOULDBLOCK @@ -613,7 +627,9 @@ ptyread(char *nam, Ptycmd cmd, char **args, int noblock) else if (used) write(1, buf, used); - return (seen ? 0 : cmd->fin + 1); + if (seen && (!prog || matchok || !mustmatch)) + return 0; + return cmd->fin + 1; } static int @@ -679,16 +695,19 @@ static int bin_zpty(char *nam, char **args, Options ops, UNUSED(int func)) { if ((OPT_ISSET(ops,'r') && OPT_ISSET(ops,'w')) || - ((OPT_ISSET(ops,'r') || OPT_ISSET(ops,'w')) && + ((OPT_ISSET(ops,'r') || OPT_ISSET(ops,'w')) && (OPT_ISSET(ops,'d') || OPT_ISSET(ops,'e') || OPT_ISSET(ops,'b') || OPT_ISSET(ops,'L'))) || - (OPT_ISSET(ops,'w') && OPT_ISSET(ops,'t')) || + (OPT_ISSET(ops,'w') && (OPT_ISSET(ops,'t') || OPT_ISSET(ops,'m'))) || (OPT_ISSET(ops,'n') && (OPT_ISSET(ops,'b') || OPT_ISSET(ops,'e') || OPT_ISSET(ops,'r') || OPT_ISSET(ops,'t') || - OPT_ISSET(ops,'d') || OPT_ISSET(ops,'L'))) || + OPT_ISSET(ops,'d') || OPT_ISSET(ops,'L') || + OPT_ISSET(ops,'m'))) || (OPT_ISSET(ops,'d') && (OPT_ISSET(ops,'b') || OPT_ISSET(ops,'e') || - OPT_ISSET(ops,'L') || OPT_ISSET(ops,'t'))) || - (OPT_ISSET(ops,'L') && (OPT_ISSET(ops,'b') || OPT_ISSET(ops,'e')))) { + OPT_ISSET(ops,'L') || OPT_ISSET(ops,'t') || + OPT_ISSET(ops,'m'))) || + (OPT_ISSET(ops,'L') && (OPT_ISSET(ops,'b') || OPT_ISSET(ops,'e') || + OPT_ISSET(ops,'m')))) { zwarnnam(nam, "illegal option combination"); return 1; } @@ -706,7 +725,8 @@ bin_zpty(char *nam, char **args, Options ops, UNUSED(int func)) return 2; return (OPT_ISSET(ops,'r') ? - ptyread(nam, p, args + 1, OPT_ISSET(ops,'t')) : + ptyread(nam, p, args + 1, OPT_ISSET(ops,'t'), + OPT_ISSET(ops, 'm')) : ptywrite(p, args + 1, OPT_ISSET(ops,'n'))); } else if (OPT_ISSET(ops,'d')) { Ptycmd p; @@ -780,7 +800,7 @@ ptyhook(UNUSED(Hookdef d), UNUSED(void *dummy)) static struct builtin bintab[] = { - BUILTIN("zpty", 0, bin_zpty, 0, -1, 0, "ebdrwLnt", NULL), + BUILTIN("zpty", 0, bin_zpty, 0, -1, 0, "ebdmrwLnt", NULL), }; static struct features module_features = { diff --git a/Test/comptest b/Test/comptest index 8a3900f5e..14938a7cd 100644 --- a/Test/comptest +++ b/Test/comptest @@ -80,7 +80,7 @@ comptesteval () { print -lr - "$@" > $tmp zpty -w zsh ". $tmp" - zpty -r zsh log_eval "*<PROMPT>*" || { + zpty -r -m zsh log_eval "*<PROMPT>*" || { print "prompt hasn't appeared." return 1 } @@ -90,7 +90,7 @@ comptesteval () { comptest () { input="$*" zpty -n -w zsh "$input"$'\C-Z' - zpty -r zsh log "*<WIDGET><finish>*<PROMPT>*" || { + zpty -r -m zsh log "*<WIDGET><finish>*<PROMPT>*" || { print "failed to invoke finish widget." return 1 } |