[comp.unix.aux] select question

MATLEVAN@EKU (Jerry LeVan) (12/03/90)

Hello,

I have been playing with Doug Tody's nifty cu replacement program
"modem.c" and have run into a small problem.

The program does a "select" on the modem line and the tty (with
a small timeout value). When the returned read mask indicates that
I/O is possible a one character read is posted to the tty to pick
up a keystroke for processing and transmission to the modem line.

The program works well except when I talk to a nearby VMS system
and am using the eve editor. I am using the command shell that has
the vt100 keypad.

It appears that when I strike a key that sends an escape sequence
that only the <esc> character is initially sent and the other characters
are buffered until another keypress.

The terminal settings are set as:
        tty = o_tty; /* the old settings */
        tty.c_iflag &= ~(INLCR|ICRNL|ISTRIP|BRKINT);
        tty.c_oflag &= ~OPOST;
        tty.c_lflag &= ~(ICANON|ISIG|ECHO)
        tty.c_cc[4]=0;
        tty.c_cc[5]=0;

Question:
        Wait: select(...)
              if (rflag) read one character; process character
              goto wait
If I am at Wait: and place <esc>Or into the system,(down arrow).
the select fires once the <esc> is processed. When the code returns
to the Wait: select(...) the read flag is *not* set again even though
the "O and "r" are available.

What do I not understand about select or the terminal driver?

Jerry
-----------------------------------------------------------------------------
| Jerry LeVan                           | Phone:(606)-622-1931              |
| Department of Computer Science        |                                   |
| Eastern Kentucky University           | Email:matlevan@eku.bitnet         |
| Richmond Ky 40475                     |                                   |
|---------------------------------------------------------------------------|
|      "The series converges so slowly that it actually diverges."          |
-----------------------------------------------------------------------------

liam@cs.qmw.ac.uk (William Roberts) (12/04/90)

In <AUXPOST%90120217553536@PUCC.BITNET> MATLEVAN@EKU (Jerry LeVan) writes:

>It appears that when I strike a key that sends an escape sequence
>that only the <esc> character is initially sent and the other characters
>are buffered until another keypress.

>The terminal settings are set as:
>        tty = o_tty; /* the old settings */
>        tty.c_iflag &= ~(INLCR|ICRNL|ISTRIP|BRKINT);
>        tty.c_oflag &= ~OPOST;
>        tty.c_lflag &= ~(ICANON|ISIG|ECHO)
>        tty.c_cc[4]=0;
>        tty.c_cc[5]=0;

>Question:
>        Wait: select(...)
>              if (rflag) read one character; process character
>              goto wait
>If I am at Wait: and place <esc>Or into the system,(down arrow).
>the select fires once the <esc> is processed. When the code returns
>to the Wait: select(...) the read flag is *not* set again even though
>the "O and "r" are available.

This is a bug - it doesn't happen with psuedo terminals (i.e through a telnet 
or rlogin connection), on the A/UX console, or under SunOS 4.1. You can work
round the problem by reading more than 1 character at a time (try 3 character 
reads).

A little demo program follows: I will send a more detailed bug report to Apple 
through the proper channels.
-------------------------------------
#include <sys/time.h>
#include <termio.h>

struct termio tty, o_tty;

main(argc, argv)
int argc;
char *argv[];
{
        int n, ttyfd, nbits, nchars;
        unsigned long rmask, maskmaster;
        unsigned char buffer[20];
        unsigned char *cp;
        struct timeval timeout, now;

        if (argc > 1) {
            nchars = atoi(argv[1]);
        } else {
            nchars = 1;
        }
        if (nchars >= 20) {
            nchars = 20;
        }

        ttyfd = 2;      /* stderr */

        n = ioctl(ttyfd, TCGETA, &o_tty);
        if (n < 0) {
            perror("ioctl TCGETA failed");
            exit(1);
        }
        tty = o_tty; /* the old settings */
        tty.c_iflag &= ~(INLCR|ICRNL|ISTRIP|BRKINT);
        tty.c_oflag &= ~OPOST;
        tty.c_lflag &= ~(ICANON|ISIG|ECHO);
        tty.c_cc[4]=0;
        tty.c_cc[5]=0;
        n = ioctl(ttyfd, TCSETA, &tty);
        if (n < 0) {
            perror("ioctl TCSETA failed");
            exit(1);
        }

        maskmaster = (1<<ttyfd);
        timeout.tv_sec = 4;
        timeout.tv_usec = 0;
        nbits = 32;

Wait:
        rmask = maskmaster;
        n = select(nbits, &rmask, 0, 0, &timeout);
        gettimeofday(&now, 0);

        if (n == 0) {
            printf("%d,%d: timeout\n\r", now.tv_sec, now.tv_usec);
            goto Wait;
        }
        if (rmask) {
            n = read(ttyfd, buffer, nchars);    /* read one character */
            printf("%d,%d: got %d chars: ", now.tv_sec, now.tv_usec, n);
            for (cp=buffer; n>0; n--,cp++) {
                printf(" 0x%x", *cp);
            }
            printf("\r\n");
            if (buffer[0] == 'q') {
                ioctl(ttyfd, TCSETA, &o_tty);
                exit(0);
            }
            goto Wait;
        }

        perror("select failed");
}
-------------------------------------

--

William Roberts                 ARPA: liam@cs.qmw.ac.uk
Queen Mary & Westfield College  UUCP: liam@qmw-cs.UUCP
Mile End Road                   AppleLink: UK0087
LONDON, E1 4NS, UK              Tel:  071-975 5250 (Fax: 081-980 6533)