diff options
author | Peter Stephenson <pws@users.sourceforge.net> | 2000-06-26 21:27:07 +0000 |
---|---|---|
committer | Peter Stephenson <pws@users.sourceforge.net> | 2000-06-26 21:27:07 +0000 |
commit | 756a2aba9c94fdd7976bf30d0420e5565be7a190 (patch) | |
tree | 72b1966724fbfc1090056db91135733dfe055a58 /Src/utils.c | |
parent | 29030cc13b4df6a6078b08432d3feaabd3e4a6b7 (diff) | |
download | zsh-756a2aba9c94fdd7976bf30d0420e5565be7a190.tar.gz zsh-756a2aba9c94fdd7976bf30d0420e5565be7a190.tar.xz zsh-756a2aba9c94fdd7976bf30d0420e5565be7a190.zip |
unposted: move poll_read
Diffstat (limited to 'Src/utils.c')
-rw-r--r-- | Src/utils.c | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/Src/utils.c b/Src/utils.c index f423795ab..f5242bbaa 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -1298,6 +1298,105 @@ setblock_stdin(void) return setblock_fd(1, 0, &mode); } +/* + * Check for pending input on fd. If polltty is set, we may need to + * use termio to look for input. As a final resort, go to non-blocking + * input and try to read a character, which in this case will be + * returned in *readchar. + * + * Note that apart from setting (and restoring) non-blocking input, + * this function does not change the input mode. The calling function + * should have set cbreak mode if necessary. + */ + +/**/ +int +read_poll(int fd, int *readchar, int polltty) +{ + int ret = 0; + long mode = -1; + char c; +#ifdef FIONREAD + int val; +#endif +#ifdef HAVE_SELECT + fd_set foofd; + struct timeval expire_tv; +#endif +#ifdef HAS_TIO + struct ttyinfo ti; +#endif + + +#if defined(HAS_TIO) && !defined(__CYGWIN__) + /* + * Under Solaris, at least, reading from the terminal in non-canonical + * mode requires that we use the VMIN mechanism to poll. Any attempt + * to check any other way, or to set the terminal to non-blocking mode + * and poll that way, fails; it will just for canonical mode input. + * We should probably use this mechanism if the user has set non-canonical + * mode, in which case testing here for isatty() and ~ICANON would be + * better than testing whether bin_read() set it, but for now we've got + * enough problems. + * + * Under Cygwin, you won't be surprised to here, this mechanism, + * although present, doesn't work, and we *have* to use ordinary + * non-blocking reads to find out if there is a character present + * in non-canonical mode. + * + * I am assuming Solaris is nearer the UNIX norm. This is not necessarily + * as plausible as it sounds, but it seems the right way to guess. + * pws 2000/06/26 + */ + if (polltty) { + gettyinfo(&ti); + 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; + } +#else +#ifdef FIONREAD + if (!ret) { + ioctl(fd, FIONREAD, (char *)&val); + if (val) + ret = 1; + } +#endif +#endif + + if (!ret) { + /* + * 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) { + *readchar = STOUC(c); + ret = 1; + } + if (mode != -1) + fcntl(fd, F_SETFL, mode); + } +#ifdef HAS_TIO + if (polltty) { + ti.tio.c_cc[VMIN] = 1; + settyinfo(&ti); + } +#endif + return ret; +} + /**/ int checkrmall(char *s) |