mirror of
git://git.code.sf.net/p/zsh/code
synced 2024-11-18 21:14:11 +01:00
Assorted read_poll() and zpty cleanup.
This commit is contained in:
parent
ab99c6d8b6
commit
dbc0aebcd4
@ -1,3 +1,12 @@
|
||||
2000-11-05 Bart Schaefer <schaefer@zsh.org>
|
||||
|
||||
* 13120: Doc/Zsh/mod_zpty.yo, Functions/Misc/nslookup,
|
||||
Src/utils.c, Src/Modules/zpty.c: Merge Sven's uncommitted patch
|
||||
from 13061 with 13116. WARNING: This reverses the meaning of
|
||||
`zpty -b'; the default is now blocking, -b selects non-blocking.
|
||||
Fix nslookup accordingly. Clean up read_poll() somewhat.
|
||||
Document that `zpty -w' and `zpty -r' can stream to/from the pty.
|
||||
|
||||
2000-11-04 Bart Schaefer <schaefer@zsh.org>
|
||||
|
||||
* 13118: Completion/Core/compinit: Add `bareglobqual' to the
|
||||
|
@ -5,42 +5,73 @@ The tt(zsh/zpty) module offers one builtin:
|
||||
|
||||
startitem()
|
||||
findex(zpty)
|
||||
xitem(tt(zpty) [ tt(-e) ] [ tt(-b) ] var(name) var(command) [ var(args ...) ])
|
||||
xitem(tt(zpty) tt(-d) [ var(names) ... ])
|
||||
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(-t) var(name))
|
||||
item(tt(zpty) [ tt(-L) ])(
|
||||
item(tt(zpty) [ tt(-e) ] [ tt(-b) ] var(name) var(command) [ var(args ...) ])(
|
||||
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
|
||||
is useful for running commands non-interactively which expect an
|
||||
interactive environment. The var(name) given is used to refer to this
|
||||
command in later calls to tt(pty). With the tt(-e) option given, the
|
||||
pseudo-terminal will be set up so that input characters are echoed and
|
||||
with the tt(-b) option given, input and output from and to the
|
||||
pseudo-terminal will be blocking.
|
||||
interactive environment. The var(name) is used to refer to this command
|
||||
in later calls to tt(zpty).
|
||||
|
||||
The second form with the tt(-d) option is used to delete commands
|
||||
previously started by supplying a list of their var(name)s. If no
|
||||
With the tt(-e) option, the pseudo-terminal is set up so that input
|
||||
characters are echoed.
|
||||
|
||||
With the tt(-b) option, input to and output from the pseudo-terminal are
|
||||
made non-blocking.
|
||||
)
|
||||
item(tt(zpty) tt(-d) [ var(names) ... ])(
|
||||
The second form, with the tt(-d) option, is used to delete commands
|
||||
previously started, by supplying a list of their var(name)s. If no
|
||||
var(names) are given, all commands are deleted. Deleting a command causes
|
||||
the HUP signal to be sent to the corresponding process.
|
||||
|
||||
The tt(-w) option can be used to send the command var(name) the given
|
||||
)
|
||||
item(tt(zpty) tt(-w) [ tt(-n) ] var(name) [ var(strings ...) ])(
|
||||
The tt(-w) option can be used to send the to command var(name) the given
|
||||
var(strings) as input (separated by spaces). If the tt(-n) option is
|
||||
not given, a newline will be added at the end.
|
||||
em(not) given, a newline is added at the end.
|
||||
|
||||
The tt(-r) option can be used to read the output of the command
|
||||
var(name). Without a var(param) argument, the string read will be
|
||||
printed to standard output. With a var(param) argument, the string
|
||||
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
|
||||
read matches the var(pattern).
|
||||
If no var(strings) are provided, the standard input is copied to the
|
||||
pseudo-terminal; this may stop before copying the full input if the
|
||||
pseudo-terminal is non-blocking.
|
||||
|
||||
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.
|
||||
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) ] ])(
|
||||
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
|
||||
until the command under the pseudo-terminal exits; when non-blocking, only
|
||||
as much output as is immediately available is copied. The return value is
|
||||
zero if any output is copied.
|
||||
|
||||
The last form without any arguments is used to list the commands
|
||||
When also given a var(param) argument, at most one line is read and stored
|
||||
in the parameter named var(param). Less than a full line may be read if
|
||||
the pseudo-terminal is non-blocking. The return value is zero if at least
|
||||
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
|
||||
value 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 value is
|
||||
non-zero.
|
||||
|
||||
In all cases, the return value is non-zero if nothing could be read, and
|
||||
is tt(2) if this is because the command has finished.
|
||||
|
||||
If the tt(-r) option is combined with the tt(-t) option, tt(zpty) tests
|
||||
whether output is available before trying to read. If no output is
|
||||
available, tt(zpty) immediately returns the value tt(1).
|
||||
)
|
||||
item(tt(zpty) tt(-t) var(name))(
|
||||
The tt(-t) option without the tt(-r) 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.
|
||||
)
|
||||
item(tt(zpty) [ tt(-L) ])(
|
||||
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
|
||||
form of calls to the tt(zpty) builtin.
|
||||
)
|
||||
|
@ -24,7 +24,7 @@ zstyle -s ':nslookup' pager tmp &&
|
||||
[[ -z "$pager" ]] && pager="${opager:-more}"
|
||||
(( $#pmpt )) || pmpt=(-p '> ')
|
||||
|
||||
zpty -b nslookup nslookup "$@"
|
||||
zpty nslookup nslookup "$@"
|
||||
|
||||
zpty -r nslookup line '*
|
||||
> '
|
||||
|
@ -34,7 +34,6 @@
|
||||
* upper bound on the number of bytes we read (even if we are give a
|
||||
* pattern). */
|
||||
|
||||
#define READ_LEN 1024
|
||||
#define READ_MAX (1024 * 1024)
|
||||
|
||||
typedef struct ptycmd *Ptycmd;
|
||||
@ -46,9 +45,10 @@ struct ptycmd {
|
||||
int fd;
|
||||
int pid;
|
||||
int echo;
|
||||
int block;
|
||||
int nblock;
|
||||
int fin;
|
||||
int read;
|
||||
char *old;
|
||||
};
|
||||
|
||||
static Ptycmd ptycmds;
|
||||
@ -264,7 +264,7 @@ get_pty(int master, int *retfd)
|
||||
#endif /* __SVR4 */
|
||||
|
||||
static int
|
||||
newptycmd(char *nam, char *pname, char **args, int echo, int block)
|
||||
newptycmd(char *nam, char *pname, char **args, int echo, int nblock)
|
||||
{
|
||||
Ptycmd p;
|
||||
int master, slave, pid;
|
||||
@ -380,14 +380,15 @@ newptycmd(char *nam, char *pname, char **args, int echo, int block)
|
||||
p->fd = master;
|
||||
p->pid = pid;
|
||||
p->echo = echo;
|
||||
p->block = block;
|
||||
p->nblock = nblock;
|
||||
p->fin = 0;
|
||||
p->read = -1;
|
||||
p->old = NULL;
|
||||
|
||||
p->next = ptycmds;
|
||||
ptycmds = p;
|
||||
|
||||
if (!block)
|
||||
if (nblock)
|
||||
ptynonblock(master);
|
||||
|
||||
return 0;
|
||||
@ -411,12 +412,12 @@ deleteptycmd(Ptycmd cmd)
|
||||
zsfree(p->name);
|
||||
freearray(p->args);
|
||||
|
||||
zclose(cmd->fd);
|
||||
|
||||
/* We kill the process group the command put itself in. */
|
||||
|
||||
kill(-(p->pid), SIGHUP);
|
||||
|
||||
zclose(cmd->fd);
|
||||
|
||||
zfree(p, sizeof(*p));
|
||||
}
|
||||
|
||||
@ -438,7 +439,7 @@ checkptycmd(Ptycmd cmd)
|
||||
{
|
||||
if (cmd->read != -1)
|
||||
return;
|
||||
if (!read_poll(cmd->fd, &cmd->read, !cmd->block) &&
|
||||
if (!read_poll(cmd->fd, &cmd->read, 0) &&
|
||||
kill(cmd->pid, 0) < 0) {
|
||||
cmd->fin = 1;
|
||||
zclose(cmd->fd);
|
||||
@ -448,8 +449,8 @@ checkptycmd(Ptycmd cmd)
|
||||
static int
|
||||
ptyread(char *nam, Ptycmd cmd, char **args)
|
||||
{
|
||||
int blen = 256, used = 0, seen = 0, ret = 1;
|
||||
char *buf = (char *) zhalloc((blen = 256) + 1);
|
||||
int blen, used, seen = 0, ret = 0;
|
||||
char *buf;
|
||||
Patprog prog = NULL;
|
||||
|
||||
if (*args && args[1]) {
|
||||
@ -469,10 +470,20 @@ ptyread(char *nam, Ptycmd cmd, char **args)
|
||||
} else
|
||||
fflush(stdout);
|
||||
|
||||
if (cmd->old) {
|
||||
used = strlen(cmd->old);
|
||||
buf = (char *) zhalloc((blen = 256 + used) + 1);
|
||||
strcpy(buf, cmd->old);
|
||||
zsfree(cmd->old);
|
||||
cmd->old = NULL;
|
||||
} else {
|
||||
used = 0;
|
||||
buf = (char *) zhalloc((blen = 256) + 1);
|
||||
}
|
||||
if (cmd->read != -1) {
|
||||
buf[0] = (char) cmd->read;
|
||||
buf[1] = '\0';
|
||||
used = 1;
|
||||
buf[used] = (char) cmd->read;
|
||||
buf[used + 1] = '\0';
|
||||
seen = used = 1;
|
||||
cmd->read = -1;
|
||||
}
|
||||
do {
|
||||
@ -495,36 +506,60 @@ ptyread(char *nam, Ptycmd cmd, char **args)
|
||||
}
|
||||
buf[used] = '\0';
|
||||
|
||||
if (!prog && ret <= 0)
|
||||
if (!prog && (ret <= 0 || (*args && buf[used - 1] == '\n')))
|
||||
break;
|
||||
} while (!errflag && !breaks && !retflag && !contflag &&
|
||||
(prog ? (used < READ_MAX && (!ret || !pattry(prog, buf))) :
|
||||
(used < READ_LEN)));
|
||||
} while (!(errflag || breaks || retflag || contflag) &&
|
||||
used < READ_MAX && !(prog && ret && pattry(prog, buf)));
|
||||
|
||||
if (prog && ret < 0 &&
|
||||
#ifdef EWOULDBLOCK
|
||||
errno == EWOULDBLOCK
|
||||
#else
|
||||
#ifdef EAGAIN
|
||||
errno == EAGAIN
|
||||
#endif
|
||||
#endif
|
||||
) {
|
||||
cmd->old = ztrdup(buf);
|
||||
used = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
if (*args)
|
||||
setsparam(*args, ztrdup(metafy(buf, used, META_HREALLOC)));
|
||||
else
|
||||
else if (used)
|
||||
write(1, buf, used);
|
||||
|
||||
return !seen;
|
||||
return (seen ? 0 : cmd->fin + 1);
|
||||
}
|
||||
|
||||
static int
|
||||
ptywritestr(Ptycmd cmd, char *s, int len)
|
||||
{
|
||||
int written;
|
||||
int written, all = 0;
|
||||
|
||||
for (; len; len -= written, s += written) {
|
||||
if ((written = write(cmd->fd, s, len)) < 0)
|
||||
return 1;
|
||||
for (; !errflag && !breaks && !retflag && !contflag && len;
|
||||
len -= written, s += written) {
|
||||
if ((written = write(cmd->fd, s, len)) < 0 && cmd->nblock &&
|
||||
#ifdef EWOULDBLOCK
|
||||
errno == EWOULDBLOCK
|
||||
#else
|
||||
#ifdef EAGAIN
|
||||
errno == EAGAIN
|
||||
#endif
|
||||
#endif
|
||||
)
|
||||
return !all;
|
||||
if (written < 0) {
|
||||
checkptycmd(cmd);
|
||||
if (cmd->fin)
|
||||
break;
|
||||
written = 0;
|
||||
}
|
||||
if (written > 0)
|
||||
all += written;
|
||||
}
|
||||
return 0;
|
||||
return (all ? 0 : cmd->fin + 1);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -559,8 +594,9 @@ static int
|
||||
bin_zpty(char *nam, char **args, char *ops, int func)
|
||||
{
|
||||
if ((ops['r'] && ops['w']) ||
|
||||
((ops['r'] || ops['w']) && (ops['d'] || ops['e'] || ops['t'] ||
|
||||
((ops['r'] || ops['w']) && (ops['d'] || ops['e'] ||
|
||||
ops['b'] || ops['L'])) ||
|
||||
(ops['w'] && ops['t']) ||
|
||||
(ops['n'] && (ops['b'] || ops['e'] || ops['r'] || ops['t'] ||
|
||||
ops['d'] || ops['L'])) ||
|
||||
(ops['d'] && (ops['b'] || ops['e'] || ops['L'] || ops['t'])) ||
|
||||
@ -579,7 +615,10 @@ bin_zpty(char *nam, char **args, char *ops, int func)
|
||||
return 1;
|
||||
}
|
||||
if (p->fin)
|
||||
return 2;
|
||||
if (ops['t'] && p->read == -1 && !read_poll(p->fd, &p->read, 0))
|
||||
return 1;
|
||||
|
||||
return (ops['r'] ?
|
||||
ptyread(nam, p, args + 1) :
|
||||
ptywrite(p, args + 1, ops['n']));
|
||||
@ -629,7 +668,7 @@ bin_zpty(char *nam, char **args, char *ops, int func)
|
||||
checkptycmd(p);
|
||||
if (ops['L'])
|
||||
printf("%s %s%s%s ", nam, (p->echo ? "-e " : ""),
|
||||
(p->block ? "-b " : ""), p->name);
|
||||
(p->nblock ? "-b " : ""), p->name);
|
||||
else if (p->fin)
|
||||
printf("(finished) %s: ", p->name);
|
||||
else
|
||||
|
34
Src/utils.c
34
Src/utils.c
@ -1315,7 +1315,7 @@ setblock_stdin(void)
|
||||
mod_export int
|
||||
read_poll(int fd, int *readchar, int polltty)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret = -1;
|
||||
long mode = -1;
|
||||
char c;
|
||||
#ifdef HAVE_SELECT
|
||||
@ -1353,38 +1353,32 @@ read_poll(int fd, int *readchar, int polltty)
|
||||
*/
|
||||
if (polltty) {
|
||||
gettyinfo(&ti);
|
||||
ti.tio.c_cc[VMIN] = 0;
|
||||
settyinfo(&ti);
|
||||
if ((polltty = ti.tio.c_cc[VMIN])) {
|
||||
ti.tio.c_cc[VMIN] = 0;
|
||||
settyinfo(&ti);
|
||||
}
|
||||
}
|
||||
#else
|
||||
polltty = 0;
|
||||
#endif
|
||||
#ifdef HAVE_SELECT
|
||||
if (!ret) {
|
||||
expire_tv.tv_sec = expire_tv.tv_usec = 0;
|
||||
FD_ZERO(&foofd);
|
||||
FD_SET(fd, &foofd);
|
||||
if (select(fd+1, (SELECT_ARG_2_T) &foofd, NULL, NULL, &expire_tv)
|
||||
> 1)
|
||||
ret = 1;
|
||||
}
|
||||
expire_tv.tv_sec = expire_tv.tv_usec = 0;
|
||||
FD_ZERO(&foofd);
|
||||
FD_SET(fd, &foofd);
|
||||
ret = select(fd+1, (SELECT_ARG_2_T) &foofd, NULL, NULL, &expire_tv);
|
||||
#else
|
||||
#ifdef FIONREAD
|
||||
if (!ret) {
|
||||
ioctl(fd, FIONREAD, (char *)&val);
|
||||
if (val)
|
||||
ret = 1;
|
||||
}
|
||||
if (ioctl(fd, FIONREAD, (char *) &val) == 0)
|
||||
ret = (val > 0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (!ret) {
|
||||
if (ret <= 0) {
|
||||
/*
|
||||
* Final attempt: set non-blocking read and try to read a character.
|
||||
* Praise Bill, this works under Cygwin (nothing else seems to).
|
||||
*/
|
||||
if ((polltty || setblock_fd(0, fd, &mode))
|
||||
&& read(fd, &c, 1) > 0) {
|
||||
if ((polltty || setblock_fd(0, fd, &mode)) && read(fd, &c, 1) > 0) {
|
||||
*readchar = STOUC(c);
|
||||
ret = 1;
|
||||
}
|
||||
@ -1397,7 +1391,7 @@ read_poll(int fd, int *readchar, int polltty)
|
||||
settyinfo(&ti);
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
return (ret > 0);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
Loading…
Reference in New Issue
Block a user