From: hawkeye AT tcp DOT com (Hawkeye) Subject: bugs in noncanonnical termios mode 12 Apr 1997 15:16:30 -0700 Approved: cygnus DOT gnu-win32 AT cygnus DOT com Distribution: cygnus Message-ID: <199704121041.DAA03823.cygnus.gnu-win32@tcp.com> Content-Type: text Original-To: gnu-win32 AT cygnus DOT com X-Mailer: ELM [version 2.4 PL23] Original-Sender: owner-gnu-win32 AT cygnus DOT com In gnu-win32/cygwin32 b17.1 for Win95, termios noncannonical mode blocks when it shouldn't, doesn't block when it should, and gets confused by shift, ctrl, and capslock. (only ~ICANON seemed to cause the problem; the other flags in the example program are only there because those are what I use in the real program I was trying to port). The example program below takes 4 command line parameters: 1. the maximum number of characters to read() 2. a flag to enable or disable select() before reading 3. termios VMIN 4. termios VTIME With max>=1 and selectflag==0, the read() always blocked until max chars were typed, completely ignoring VMIN and VTIME. Since termios ECHO is on, it appears likely that the cygwin code is blocked in a windows call, since not even it echoes until max chars are typed. With max>=1 and selectflag==1, it got even weirder: for single-keystroke characters, the read() immediately returned 1 character (even if VMIN>1); but if SHIFT or CTRL was held, or CAPS LOCK was on, when a key was pressed, the read() would then block until max chars were typed. --- cut here --- #include #include #include #include struct termios tty, old_tty; void set_tty(int vmin, int vtime); void reset_tty(void); int main(int argc, char *argv[]) { char buf[1024]; int max, selectflag, vmin, vtime; int len, count; fd_set readers; if (argc != 5) exit(1); max = atoi(argv[1]); selectflag = atoi(argv[2]); vmin = atoi(argv[3]); vtime = atoi(argv[4]); FD_ZERO(&readers); set_tty(vmin, vtime); while (1) { if (selectflag) { FD_SET(STDIN_FILENO, &readers); count = select(STDIN_FILENO+1, &readers, NULL, NULL, NULL); if (count < 0) { perror("select"); break; } } len = read(STDIN_FILENO, buf, max); if (len < 0) { perror("read"); break; } write(STDOUT_FILENO, buf, len); if (buf[0] == 'x') break; } reset_tty(); } void set_tty(int vmin, int vtime) { if (tcgetattr(STDIN_FILENO, &tty) < 0) { perror("getattr"); exit(1); } old_tty = tty; tty.c_lflag &= ~ICANON; tty.c_lflag |= ISIG; tty.c_iflag |= IGNBRK | IGNPAR; tty.c_iflag &= ~(ICRNL | INLCR | ISTRIP | IGNCR); tty.c_cc[VMIN] = vmin; tty.c_cc[VTIME] = vtime; if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &tty) < 0) { perror("setattr"); exit(1); } } void reset_tty(void) { if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &old_tty) < 0) perror("reset"); } --- end cut --- =========================================================================== Ken Keys hawkeye AT tcp DOT com http://tf.tcp.com/~hawkeye/ --------------------------------------------------------------------------- TinyFugue info: http://tf.tcp.com/~hawkeye/tf/ TF version 3.5 beta 4 for UNIX and OS/2 is available at: ftp://tf.tcp.com/pub/tinyfugue/ and ftp://ftp.tcp.com/pub/mud/Clients/tf/ TF mailing list: mail to majordomo AT tcp DOT com, with body "subscribe tinyfugue" =========================================================================== - For help on using this list (especially unsubscribing), send a message to "gnu-win32-request AT cygnus DOT com" with one line of text: "help".