mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-09-01 09:41:44 +02:00
make non-blocking IO on ptys work again; add -t option to test if command is still alive (13035)
This commit is contained in:
parent
f718ed6b52
commit
16d7e31ae8
6 changed files with 55 additions and 17 deletions
|
@ -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>
|
2000-10-19 Wayne Davison <wayned@users.sourceforge.net>
|
||||||
|
|
||||||
* 13034: Src/hist.c: Don't call histreduceblanks() if the line
|
* 13034: Src/hist.c: Don't call histreduceblanks() if the line
|
||||||
|
|
|
@ -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(-d) [ var(names) ... ])
|
||||||
xitem(tt(zpty) tt(-w) [ tt(-n) ] var(name) var(strings ...))
|
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(-r) var(name) [ var(param) [ var(pattern) ] ])
|
||||||
|
xitem(tt(zpty) tt(-t) var(name))
|
||||||
item(tt(zpty) [ tt(-L) ])(
|
item(tt(zpty) [ tt(-L) ])(
|
||||||
In the first form, the var(command) is started with the var(args) as
|
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
|
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
|
var(pattern) is also given, output will be read until the whole string
|
||||||
read matches the var(pattern).
|
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
|
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
|
currently defined. If the tt(-L) option is given, this is done in the
|
||||||
form of calls to the tt(zpty) builtin.
|
form of calls to the tt(zpty) builtin.
|
||||||
|
|
|
@ -24,7 +24,7 @@ zstyle -s ':nslookup' pager tmp &&
|
||||||
[[ -z "$pager" ]] && pager="${opager:-more}"
|
[[ -z "$pager" ]] && pager="${opager:-more}"
|
||||||
(( $#pmpt )) || pmpt=(-p '> ')
|
(( $#pmpt )) || pmpt=(-p '> ')
|
||||||
|
|
||||||
zpty nslookup nslookup "$@"
|
zpty -b nslookup nslookup "$@"
|
||||||
|
|
||||||
zpty -r nslookup line '*
|
zpty -r nslookup line '*
|
||||||
> '
|
> '
|
||||||
|
|
|
@ -48,6 +48,7 @@ struct ptycmd {
|
||||||
int echo;
|
int echo;
|
||||||
int block;
|
int block;
|
||||||
int fin;
|
int fin;
|
||||||
|
int read;
|
||||||
};
|
};
|
||||||
|
|
||||||
static Ptycmd ptycmds;
|
static Ptycmd ptycmds;
|
||||||
|
@ -381,6 +382,7 @@ newptycmd(char *nam, char *pname, char **args, int echo, int block)
|
||||||
p->echo = echo;
|
p->echo = echo;
|
||||||
p->block = block;
|
p->block = block;
|
||||||
p->fin = 0;
|
p->fin = 0;
|
||||||
|
p->read = -1;
|
||||||
|
|
||||||
p->next = ptycmds;
|
p->next = ptycmds;
|
||||||
ptycmds = p;
|
ptycmds = p;
|
||||||
|
@ -434,7 +436,9 @@ deleteallptycmds(void)
|
||||||
static void
|
static void
|
||||||
checkptycmd(Ptycmd cmd)
|
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;
|
cmd->fin = 1;
|
||||||
zclose(cmd->fd);
|
zclose(cmd->fd);
|
||||||
}
|
}
|
||||||
|
@ -444,7 +448,7 @@ static int
|
||||||
ptyread(char *nam, Ptycmd cmd, char **args)
|
ptyread(char *nam, Ptycmd cmd, char **args)
|
||||||
{
|
{
|
||||||
int blen = 256, used = 0, ret = 1;
|
int blen = 256, used = 0, ret = 1;
|
||||||
char *buf = (char *) zhalloc(blen + 1);
|
char *buf = (char *) zhalloc((blen = 256) + 1);
|
||||||
Patprog prog = NULL;
|
Patprog prog = NULL;
|
||||||
|
|
||||||
if (*args && args[1]) {
|
if (*args && args[1]) {
|
||||||
|
@ -462,6 +466,12 @@ ptyread(char *nam, Ptycmd cmd, char **args)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (cmd->read != -1) {
|
||||||
|
buf[0] = (char) cmd->read;
|
||||||
|
buf[1] = '\0';
|
||||||
|
used = 1;
|
||||||
|
cmd->read = -1;
|
||||||
|
}
|
||||||
do {
|
do {
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
checkptycmd(cmd);
|
checkptycmd(cmd);
|
||||||
|
@ -476,11 +486,10 @@ ptyread(char *nam, Ptycmd cmd, char **args)
|
||||||
}
|
}
|
||||||
buf[used] = '\0';
|
buf[used] = '\0';
|
||||||
|
|
||||||
/**** Hm. If we leave the loop when ret < 0 the user would have
|
#if 0
|
||||||
* to make sure that `zpty -r' is tried more than once if
|
/* This once used the following test, to make sure to return
|
||||||
* there will be some output and we only got the ret == -1
|
* non-zero if there are no characters to read. That looks
|
||||||
* because the output is not yet available.
|
* like a thinko now, because it disables non-blocking ptys. */
|
||||||
* The same for the `write' below. */
|
|
||||||
|
|
||||||
if (ret < 0 && (cmd->block
|
if (ret < 0 && (cmd->block
|
||||||
#ifdef EWOULDBLOCK
|
#ifdef EWOULDBLOCK
|
||||||
|
@ -492,8 +501,9 @@ ptyread(char *nam, Ptycmd cmd, char **args)
|
||||||
#endif
|
#endif
|
||||||
))
|
))
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!prog && !ret)
|
if (!prog && ret <= 0)
|
||||||
break;
|
break;
|
||||||
} while (!errflag && !breaks && !retflag && !contflag &&
|
} while (!errflag && !breaks && !retflag && !contflag &&
|
||||||
(prog ? (used < READ_MAX && (!ret || !pattry(prog, buf))) :
|
(prog ? (used < READ_MAX && (!ret || !pattry(prog, buf))) :
|
||||||
|
@ -514,7 +524,10 @@ ptywritestr(Ptycmd cmd, char *s, int len)
|
||||||
int written;
|
int written;
|
||||||
|
|
||||||
for (; len; len -= written, s += 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
|
(cmd->block
|
||||||
#ifdef EWOULDBLOCK
|
#ifdef EWOULDBLOCK
|
||||||
|| errno != EWOULDBLOCK
|
|| errno != EWOULDBLOCK
|
||||||
|
@ -523,7 +536,9 @@ ptywritestr(Ptycmd cmd, char *s, int len)
|
||||||
|| errno != EAGAIN
|
|| errno != EAGAIN
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
))
|
)
|
||||||
|
#endif
|
||||||
|
)
|
||||||
return 1;
|
return 1;
|
||||||
if (written < 0) {
|
if (written < 0) {
|
||||||
checkptycmd(cmd);
|
checkptycmd(cmd);
|
||||||
|
@ -567,11 +582,11 @@ static int
|
||||||
bin_zpty(char *nam, char **args, char *ops, int func)
|
bin_zpty(char *nam, char **args, char *ops, int func)
|
||||||
{
|
{
|
||||||
if ((ops['r'] && ops['w']) ||
|
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['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['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']))) {
|
(ops['L'] && (ops['b'] || ops['e']))) {
|
||||||
zwarnnam(nam, "illegal option combination", NULL, 0);
|
zwarnnam(nam, "illegal option combination", NULL, 0);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -607,6 +622,18 @@ bin_zpty(char *nam, char **args, char *ops, int func)
|
||||||
deleteallptycmds();
|
deleteallptycmds();
|
||||||
|
|
||||||
return ret;
|
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) {
|
} else if (*args) {
|
||||||
if (!args[1]) {
|
if (!args[1]) {
|
||||||
zwarnnam(nam, "missing command", NULL, 0);
|
zwarnnam(nam, "missing command", NULL, 0);
|
||||||
|
@ -649,7 +676,7 @@ ptyhook(Hookdef d, void *dummy)
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct builtin bintab[] = {
|
static struct builtin bintab[] = {
|
||||||
BUILTIN("zpty", 0, bin_zpty, 0, -1, 0, "ebdrwLn", NULL),
|
BUILTIN("zpty", 0, bin_zpty, 0, -1, 0, "ebdrwLnt", NULL),
|
||||||
};
|
};
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
|
|
|
@ -1312,7 +1312,7 @@ setblock_stdin(void)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
int
|
mod_export int
|
||||||
read_poll(int fd, int *readchar, int polltty)
|
read_poll(int fd, int *readchar, int polltty)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
|
@ -16,7 +16,7 @@ comptestinit () {
|
||||||
(( OPTIND > 1 )) && shift $(( OPTIND - 1 ))
|
(( OPTIND > 1 )) && shift $(( OPTIND - 1 ))
|
||||||
|
|
||||||
export PS1="<PROMPT>"
|
export PS1="<PROMPT>"
|
||||||
zpty zsh "$comptest_zsh" -f
|
zpty -b zsh "$comptest_zsh" -f
|
||||||
|
|
||||||
zpty -r zsh log1 "*<PROMPT>*" || {
|
zpty -r zsh log1 "*<PROMPT>*" || {
|
||||||
print "first prompt hasn't appeared."
|
print "first prompt hasn't appeared."
|
||||||
|
|
Loading…
Reference in a new issue