1
0
Fork 0
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:
Sven Wischnowsky 2000-10-19 08:46:54 +00:00
parent f718ed6b52
commit 16d7e31ae8
6 changed files with 55 additions and 17 deletions

View file

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

View file

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

View file

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

View file

@ -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),
}; };
/**/ /**/

View file

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

View file

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