mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-09-18 15:21:16 +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>
|
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.
|
* 26300: Src/zsh.mdd: don't use "echo -n" for $ZSH_PATCHLEVEL.
|
||||||
|
|
||||||
2009-01-09 Peter Stephenson <p.w.stephenson@ntlworld.com>
|
2009-01-09 Peter Stephenson <p.w.stephenson@ntlworld.com>
|
||||||
|
@ -10893,5 +10897,5 @@
|
||||||
|
|
||||||
*****************************************************
|
*****************************************************
|
||||||
* This is used by the shell to define $ZSH_PATCHLEVEL
|
* 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
|
were typed, so beware when sending special tty driver characters such as
|
||||||
word-erase, line-kill, and end-of-file.
|
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).
|
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
|
With only a var(name) argument, the output read is copied to the standard
|
||||||
output. Unless the pseudo-terminal is non-blocking, copying continues
|
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
|
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
|
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
|
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
|
has exited but at least one character could still be read. If the option
|
||||||
writing, a maximum of one megabyte of output can be consumed this way; if
|
tt(-m) is present, the return status is zero only if the pattern matches.
|
||||||
a full megabyte is read without matching the pattern, the return status is
|
As of this writing, a maximum of one megabyte of output can be consumed
|
||||||
non-zero.
|
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
|
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.
|
is tt(2) if this is because the command has finished.
|
||||||
|
|
|
@ -485,9 +485,9 @@ checkptycmd(Ptycmd cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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;
|
char *buf;
|
||||||
Patprog prog = NULL;
|
Patprog prog = NULL;
|
||||||
|
|
||||||
|
@ -589,10 +589,24 @@ ptyread(char *nam, Ptycmd cmd, char **args, int noblock)
|
||||||
}
|
}
|
||||||
buf[used] = '\0';
|
buf[used] = '\0';
|
||||||
|
|
||||||
if (!prog && (ret <= 0 || (*args && buf[used - 1] == '\n')))
|
if (!prog) {
|
||||||
break;
|
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) &&
|
} 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 &&
|
if (prog && ret < 0 &&
|
||||||
#ifdef EWOULDBLOCK
|
#ifdef EWOULDBLOCK
|
||||||
|
@ -613,7 +627,9 @@ ptyread(char *nam, Ptycmd cmd, char **args, int noblock)
|
||||||
else if (used)
|
else if (used)
|
||||||
write(1, buf, used);
|
write(1, buf, used);
|
||||||
|
|
||||||
return (seen ? 0 : cmd->fin + 1);
|
if (seen && (!prog || matchok || !mustmatch))
|
||||||
|
return 0;
|
||||||
|
return cmd->fin + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -679,16 +695,19 @@ static int
|
||||||
bin_zpty(char *nam, char **args, Options ops, UNUSED(int func))
|
bin_zpty(char *nam, char **args, Options ops, UNUSED(int func))
|
||||||
{
|
{
|
||||||
if ((OPT_ISSET(ops,'r') && OPT_ISSET(ops,'w')) ||
|
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,'d') || OPT_ISSET(ops,'e') ||
|
||||||
OPT_ISSET(ops,'b') || OPT_ISSET(ops,'L'))) ||
|
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,'n') && (OPT_ISSET(ops,'b') || OPT_ISSET(ops,'e') ||
|
||||||
OPT_ISSET(ops,'r') || OPT_ISSET(ops,'t') ||
|
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,'d') && (OPT_ISSET(ops,'b') || OPT_ISSET(ops,'e') ||
|
||||||
OPT_ISSET(ops,'L') || OPT_ISSET(ops,'t'))) ||
|
OPT_ISSET(ops,'L') || OPT_ISSET(ops,'t') ||
|
||||||
(OPT_ISSET(ops,'L') && (OPT_ISSET(ops,'b') || OPT_ISSET(ops,'e')))) {
|
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");
|
zwarnnam(nam, "illegal option combination");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -706,7 +725,8 @@ bin_zpty(char *nam, char **args, Options ops, UNUSED(int func))
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
return (OPT_ISSET(ops,'r') ?
|
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')));
|
ptywrite(p, args + 1, OPT_ISSET(ops,'n')));
|
||||||
} else if (OPT_ISSET(ops,'d')) {
|
} else if (OPT_ISSET(ops,'d')) {
|
||||||
Ptycmd p;
|
Ptycmd p;
|
||||||
|
@ -780,7 +800,7 @@ ptyhook(UNUSED(Hookdef d), UNUSED(void *dummy))
|
||||||
|
|
||||||
|
|
||||||
static struct builtin bintab[] = {
|
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 = {
|
static struct features module_features = {
|
||||||
|
|
|
@ -80,7 +80,7 @@ comptesteval () {
|
||||||
|
|
||||||
print -lr - "$@" > $tmp
|
print -lr - "$@" > $tmp
|
||||||
zpty -w zsh ". $tmp"
|
zpty -w zsh ". $tmp"
|
||||||
zpty -r zsh log_eval "*<PROMPT>*" || {
|
zpty -r -m zsh log_eval "*<PROMPT>*" || {
|
||||||
print "prompt hasn't appeared."
|
print "prompt hasn't appeared."
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@ comptesteval () {
|
||||||
comptest () {
|
comptest () {
|
||||||
input="$*"
|
input="$*"
|
||||||
zpty -n -w zsh "$input"$'\C-Z'
|
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."
|
print "failed to invoke finish widget."
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue