Subject: Possible bug in non blocking read from /dev/tty
From: "Ehud Karni" <[email-masked]>
To: "Unix on M$Win" <[email-masked]>
Date: Wed, 20 Nov 2002 18:45:14 +0200

I'm converting from a program linux to Cygwin. This program uses non
blocking read from the terminal by setting the VMIN and VTIME in the
`termios' structure and doing a non CANON read, like this:

   ttyarg.c_cc [VMIN] = 0 ;
   ttyarg.c_cc [VTIME] = 1 ;
   ttyarg.c_lflag = 0 ;

The read does BLOCK (wait for a character to be typed) and does not
return after 1/10 second as it supposed (It works OK on linux).

I added a call to `stty -a' before and after I change the terminal
attributes. here is the output:

Before:
speed 38400 baud; rows 49; columns 105; line = 0;
intr = ^C; quit = ^\; erase = ^H; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; start = ^Q;
stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 2;
-parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk brkint ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany imaxbel
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -tostop echoctl echoke

After:
speed 38400 baud; rows 49; columns 105; line = 0;
intr = ^C; quit = ^\; erase = ^H; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; start = ^Q;
stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 0; time = 1;
-parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts
ignbrk -brkint ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl -ixon -ixoff -iuclc -ixany imaxbel
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
-isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -tostop -echoctl -echoke

As you can see the VMIN & VTIME values were set, and the icanon was
changed to -icanon.

My system is P4, 1.7GH, running M$Windows XP. Output of uname -a :
CYGWIN_NT-5.1 P4-1700-XP 1.3.15(0.63/3/2) 2002-11-07 13:57 i686 unknown

Setting the CYGWIN environment variable to tty/notty have no effect.
A full test program with debug messages is below.

Ehud.

//  test_read_term.c  program

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <termios.h>

int main ( int argc, char *argv[] )

{
FILE *devttyr = NULL ;                     /* stream for terminal I/O */
struct termios ttyarg, intrm ;             /* arguments for termios */
char buf [ 50 ] , *lni ;
int ftty, n , rdn , length ;               /* devtty file number, temp n, rdn */

   length = atoi ( argv [ 1 ] ) ;          /* real length to read */

   lni = buf ;                             /* pointer to input */

   if ( ( devttyr = fopen ( "/dev/tty" , "r+" ) ) == NULL )    /* open (terminal ?) for read */
   {
       fprintf ( stderr , "Could not open /dev/tty" ) ;
       exit ( 1 ) ;
   }

   ftty = fileno ( devttyr ) ;             /* file number of devtty */
   tcgetattr( ftty , &intrm ) ;            /* get stdin arguments (SAVE) */
   ttyarg = intrm ;                        /* saved original configuration */

   ttyarg.c_cc [VMIN] = 0 ;                /* min of 0 chars */
   ttyarg.c_cc [VTIME] = 1 ;               /* wait max vtime_val/10 sec (def 15/10) */
   ttyarg.c_iflag = IGNBRK | IGNPAR | ICRNL | IMAXBEL ;    /* set these modes only on input */
   ttyarg.c_lflag = 0 ;                    /* clear lflag of all processing */

   system ( "stty -a" ) ;
   n = tcsetattr( ftty , TCSANOW , &ttyarg ) ; /* set changed tty arguments */
   fprintf ( stderr , "result of tcsetattr is %d\n" , n ) ;
   system ( "stty -a" ) ;

   lni [ length + 1 ] = 0 ;                /* last pos must be Z byte */
   while ( length > 0 )                    /* read until buffer full */
   {
       fprintf ( stderr , "before read ----------\n" ) ;
       rdn = length ;                      /* min (length, MAX_BEL) */
       n = read ( ftty , lni , rdn ) ;     /* read devtty, max n chars, up to 1/2 sec wait */
       fprintf ( stderr , "AFTER  read n=%d -----\n" , n ) ;
       switch ( n )                        /* read devtty, max n chars, up to 1/2 sec wait */
       {
           case -1:                        /* error */
                   fprintf ( stderr , "Error occurred \n" ) ;
                   length = 0 ;            /* exit while loop */

           case  0:                        /* no input (do nothing) */
                   break;                  /* all ok */

           default:                        /* input read, check for terminating NL */
                   lni += n ;              /* next address */
                   *lni = 0 ;              /* must (we may stop reading) */
                   length -= n ;           /* length left to read */
                   if ( *(lni-1) == '\n' ) /* if last char is NL */
                       length = 0 ;        /* dont read any more */

       }
   }

   tcsetattr( ftty , TCSANOW , & intrm ) ; /* reset devtty to saved value */
   return ( 0 ) ;
}
/*=============== end of test_read_term.c =================

--
 Ehud Karni           Tel: +972-3-7966-561  /"\
 Mivtach - Simon      Fax: +972-3-7966-667  \ /  ASCII Ribbon Campaign
 Insurance agencies   (USA) voice mail and   X   Against   HTML   Mail
 http://www.mvs.co.il  FAX:  1-815-5509341  / \
 mailto:[email-masked]                  Better  Safe  Than  Sorry

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Bug reporting:         http://cygwin.com/bugs.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/