This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

"read" bug in Cygwin 1.5.16?


Hi all,

I tried to forward this message to the main cygwin
list yesterday, but had a little trouble getting it
there, probably because I mentioned "xterm" in the
subject.  I'm trying again in case this is NOT an "X"
problem but a base cygwin problem.

I have attached the test program xtermbug.c instead 
of pasting it inline.  I hope that is OK for this
list.

If there is anything I can do to help debug the reason
I am seeing this problem, please just tell me what to
do.

BTW, thanks to all the developers for an awesome
product.

Regards,

Peter Farley

--- Peter Farley <pjfarley3@yahoo.com> wrote:

> Hi all,
> 
> The following program demonstrates what looks to me
> like a bug in the "read" function in an xterm (as
> opposed to a Cygwin console window).  To run the
> test, compile with:
> 
> gcc -g -o xtermbug.exe xtermbug.c
> 
> When you run it in a console window, you can enter
> normal keyboard characters, then a return to see
> "cmdline=<what you typed>".  Press the Esc key to
> exit the program.
> 
> When run in an xterm window, the first keypress
> causes this behavior:
> 
> 1. Select returns with rc = 0 and readset set to
> indicate that a key was received
> 2. "read" returns with kblen = 1 and kbbuf[0] = '\0'
> 3. (1) and (2) repeat forever.
> 
> I put in a "maxdbg" parameter and terminate the
> program after 5 occurrences of this loop.
> 
> This problem was first detected trying to run a copy
> of the hercules IBM mainframe emulator in a Cygwin
> xterm window.  The code below is extracted and
> minimalized as much as possible from the hercules
> keyboard input routine.
> 
> Peter Farley


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 
/*-------------------------------------------------------------------*/
/* This is a test program to show a cygwin xterm bug, possibly       */
/* in the read function.                                             */
/*-------------------------------------------------------------------*/

/*-------------------------------------------------------------------*/
/* Definitions for keyboard input sequences                          */
/*-------------------------------------------------------------------*/
#define KBD_DELETE              "\x1B[3~"

#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <string.h>
#include <errno.h>
#include <termios.h>

#define MSG_SIZE                80      /* Size of one message       */
#define CMD_SIZE             32767      /* Length of command line    */

#define BYTE unsigned char

int	ttyreset = 0;
struct	termios kbattr;                 /* Terminal I/O structure    */

/*-------------------------------------------------------------------*/
/* xterm display subroutine                                          */
/*-------------------------------------------------------------------*/

void xterm_display (void)
{
int     rc;                             /* Return code               */
int     i;                              /* Array subscripts          */
char    cmdline[CMD_SIZE+1];            /* Command line buffer       */
int     cmdoff = 0;                     /* Cursor position in cmdline*/
int     cmdlen = 0;                     /* Number of bytes in cmdline*/
//BYTE    c;                              /* Character work area       */
FILE   *confp;                          /* Console file pointer      */
size_t  kbbufsize = CMD_SIZE;           /* Size of keyboard buffer   */
char   *kbbuf = NULL;                   /* Keyboard input buffer     */
int     kblen;                          /* Number of chars in kbbuf  */
int     keybfd;                         /* Keyboard file descriptor  */
int     maxfd;                          /* Highest file descriptor   */
fd_set  readset;                        /* Select file descriptors   */
struct  timeval tv;                     /* Select timeout structure  */
int	maxdbg = 0;

    /* Set up the input file descriptors */
    confp = stdout;
    keybfd = STDIN_FILENO;
    
    fprintf(confp, "start kbbuf=%8.8X,&kbbuf=%8.8X\n", 
	kbbuf, &kbbuf);

    /* Obtain storage for the keyboard buffer */
    if (!(kbbuf = (char *)malloc (kbbufsize)))
    {
        fprintf(stderr, "HHCPN002S Cannot obtain keyboard buffer: %s\n",
                strerror(errno));
        return;
    }

    fprintf(confp, "start kbbuf=%8.8X,&kbbuf=%8.8X,*kbbuf=%8.8X\n", 
	kbbuf, &kbbuf, *kbbuf);

    /* Set screen output stream to fully buffered */
    setvbuf (confp, NULL, _IOFBF, 0);

    /* Put the terminal into cbreak mode */
    tcgetattr (keybfd, &kbattr);
    kbattr.c_lflag &= ~(ECHO | ICANON);
    kbattr.c_cc[VMIN] = 0;
    kbattr.c_cc[VTIME] = 0;
    tcsetattr (keybfd, TCSANOW, &kbattr);
    ttyreset = 1;

    fprintf(confp, "Starting while(1) loop.\n");
    fflush(confp);

    /* Process messages and commands */
    while (1)
    {
        /* Set the file descriptors for select */
        FD_ZERO (&readset);
        FD_SET (keybfd, &readset);
        maxfd = keybfd;

        /* Wait for a key to be pressed,
           or the inactivity interval to expire */
        tv.tv_sec = 1;
        tv.tv_usec = 1 % 1000000;
        rc = select (maxfd + 1, &readset, NULL, NULL, &tv);
        if (rc < 0 )
        {
            if (errno == EINTR) continue;
            fprintf (stderr,
                    "HHCPN004E select: %s\n",
                    strerror(errno));
            break;
        }

	fprintf(confp, "rc=%d,readset={%8.8X,%8.8X}\n", rc,
	    readset.fds_bits[0], readset.fds_bits[1]);
	fflush(confp);

        /* If keyboard input has arrived then process it */

        if (FD_ISSET(keybfd, &readset))
        {
            /* Read character(s) from the keyboard */
            kblen = read (keybfd, kbbuf, kbbufsize-1);
	    
	    fprintf(confp, "kblen=%d\n", kblen);

            if (kblen < 0)
            {
                fprintf (stderr,
                        "HHCPN005E keyboard read: %s\n",
                        strerror(errno));
                break;
            }

            kbbuf[kblen] = '\0';

    	    fprintf(confp, "kbbuf[0-%d]=", kblen); 
	    for (i = 0; i <= kblen; i++)
	    {
	        fprintf(confp, "%2.2X", kbbuf[i]);
		if (i < kblen) fprintf(confp, ",");
	    }
	    fprintf(confp, "\n");

            /* Process characters in the keyboard buffer */
            for (i = 0; i < kblen; )
            {
                /* Process backspace character  */
                if (kbbuf[i] == '\b' || kbbuf[i] == '\x7F')
                {
                    if (cmdoff > 0) {
                        int j;
                        for (j = cmdoff-1; j<cmdlen; j++)
                            cmdline[j] = cmdline[j+1];
                        cmdoff--;
                        cmdlen--;
                    }
                    i++;
                    break;
                }
                /* Process DEL character              */
                if (strcmp(kbbuf+i, KBD_DELETE) == 0) {
                    if (cmdoff < cmdlen) {
                        int j;
                        for (j = cmdoff; j<cmdlen; j++)
                            cmdline[j] = cmdline[j+1];
                        cmdlen--;
                    }
                    i++;
                    break;
                }

                /* Process escape key */
                if (kbbuf[i] == '\x1B')
                {
        	    cmdline[0] = '\0';
        	    cmdoff = 0;
        	    cmdlen = 0;
		    
		    /* Restore the terminal mode */
		    tcgetattr (STDIN_FILENO, &kbattr);
		    kbattr.c_lflag |= (ECHO | ICANON);
		    tcsetattr (STDIN_FILENO, TCSANOW, &kbattr);
		    ttyreset = 0;
		    
        	    fprintf(confp, "\n\nTerminating xtermbug test!\n");
		    fflush(confp);
		    return;
                }

                /* Process the command if newline was read */
                if (kbbuf[i] == '\n')
                {
		    fprintf (confp, "\ncmdline=%s\n", cmdline);
                    break;
                }

                /* Ignore non-printable characters */
                if (!isprint(kbbuf[i]))
                {
                    fprintf(stderr, "Unprintable:%8.8X\n", 
			*(kbbuf+i));
                    i++;
		    if (++maxdbg > 5) { return; }
                    break;
                }

                /* Append the character to the command buffer */
                if (cmdoff < CMD_SIZE-1) {
                    if (cmdoff < cmdlen) {
                        int j;
                        for (j=cmdlen-1; j>=cmdoff; j--)
                            cmdline[j+1] = cmdline[j];
                        cmdline[cmdoff++] = kbbuf[i];
                    }
                    else
                        cmdline[cmdoff++] = kbbuf[i];
                    cmdlen++;
                }
                i++;
            } /* end for(i) */
        }

    } /* end while */

    return;

} /* end function xterm_display */

int main(int argc, char *argv[]) {
    xterm_display();
    if (ttyreset)
    {
	/* Restore the terminal mode */
	tcgetattr (STDIN_FILENO, &kbattr);
	kbattr.c_lflag |= (ECHO | ICANON);
	tcsetattr (STDIN_FILENO, TCSANOW, &kbattr);
    }
    return(0);
}

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]