1
0
Fork 0
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:
Peter Stephenson 2009-01-13 12:09:26 +00:00
parent e763f79b3f
commit e7c9e03c58
4 changed files with 46 additions and 21 deletions

View file

@ -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 $
*****************************************************

View file

@ -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.

View file

@ -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 = {

View file

@ -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
}