From dbc0aebcd44a028ed5c5c392fa2b354a1b562955 Mon Sep 17 00:00:00 2001 From: Bart Schaefer Date: Sun, 5 Nov 2000 09:27:08 +0000 Subject: Assorted read_poll() and zpty cleanup. --- Src/Modules/zpty.c | 91 ++++++++++++++++++++++++++++++++++++++---------------- Src/utils.c | 34 +++++++++----------- 2 files changed, 79 insertions(+), 46 deletions(-) (limited to 'Src') diff --git a/Src/Modules/zpty.c b/Src/Modules/zpty.c index b854fe8e3..463fbdf75 100644 --- a/Src/Modules/zpty.c +++ b/Src/Modules/zpty.c @@ -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 diff --git a/Src/utils.c b/Src/utils.c index 05865cf67..1190347f7 100644 --- a/Src/utils.c +++ b/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); } /**/ -- cgit 1.4.1