mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-09-17 02:51:01 +02:00
26301: make zpty -r exit more cleanly on bad reads
add option -m to make zpty -r return status 1 if pattern failed to match use this option in comptest
This commit is contained in:
parent
e763f79b3f
commit
e7c9e03c58
4 changed files with 46 additions and 21 deletions
|
@ -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 $
|
||||
*****************************************************
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
@ -682,13 +698,16 @@ bin_zpty(char *nam, char **args, Options ops, UNUSED(int func))
|
|||
((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 = {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue