[comp.unix.questions] termio under SysV

jdc@naucse.UUCP (John Campbell) (03/01/89)

I'm trying to implement some getch(), getche(), and kbdhit() type
routines under SysV (on a 3b1 actually).  I've done the following
kind of thing:

snippet for getch():

      if (ioctl (fileno(keyboard), TCGETA, &term_s) < 0) Fail;
      term_s.c_lflag &= ~ICANON;
      term_s.c_cc[VEOF] = 1;  /* One character reads */
      term_s.c_cc[VEOL] = 0x7f;  /* 12.7 seconds (best?) */
      if (ioctl (fileno(keyboard), TCSETA, &term_s) < 0) Fail;
      term_state = 2;  /* getche state */
   }
   i = getc(keyboard);
which works well enough, except I would like the time limit (MIN)
stored in .c_cc[VEOL] to really be infinite.

Question 1: Does 0 or -1 work as a "special" infinite value here?


As for kbdhit() (returns 1 if there is anything in the typeahead
buffer):

      if (ioctl (fileno(keyboard), TCGETA, &term_s) < 0) Fail;
      term_s.c_lflag &= ~ICANON;
      term_s.c_cc[VEOF] = 1;  /* One character reads */
      term_s.c_cc[VEOL] = 1;  /* .1 second read */
      if (ioctl (fileno(keyboard), TCSETA, &term_s) < 0) Fail;
      term_state = 3;  /* getche state */
   }
/* Well, all I can think to do is read, and push back... */
   i = getc(keyboard); 
   ungetc(i,keyboard);
   if (i > 0)  {   /* Assume EOF is < 0... */

all I could think of doing was read with a .1 second time limit and see
if anything came in (and, of course, push it back if nothing did). 

Question 2: Can anyone think of a better (more direct way) of finding out
            if anything is in the typeahead under SysV unix?


	John Campbell               ...!arizona!naucse!jdc
                                    CAMPBELL@NAUVAX.bitnet
	unix?  Sure send me a dozen, all different colors.
-- 
	John Campbell               ...!arizona!naucse!jdc
                                    CAMPBELL@NAUVAX.bitnet
	unix?  Sure send me a dozen, all different colors.

jdc@naucse.UUCP (John Campbell) (03/02/89)

In a previous article, I wrote:
: 
: I'm trying to implement getch(), getche(), and kbdhit() 
: 
: snippet for getch():
:       term_s.c_lflag &= ~ICANON;
:       term_s.c_cc[VEOF] = 1;  /* One character reads */
:       term_s.c_cc[VEOL] = 0x7f;  /* 12.7 seconds (best?) */
:       if (ioctl (fileno(keyboard), TCSETA, &term_s) < 0) Fail;
: 
: Question 1: Does 0 or -1 work as a "special" infinite value here?

It turns out I misread the documentation.  Unlike another (to remain
unamed) operating system I use, the MIN time is not the timeout value
of the read, but rather the required number of 1/10 seconds the read
must take!  Anyone want to tell me how useful this is?  The other
interpretation I've made use of (under the mystery operating system)
to implement automatic paging, etc.  Anyway, Question 1 is no longer
an issue--the reads always block, regardless of the MIN value.
 
: As for kbdhit() (returns 1 if there is anything in the typeahead
: buffer):
:       term_s.c_cc[VEOL] = 1;  /* .1 second read */
:       if (ioctl (fileno(keyboard), TCSETA, &term_s) < 0) Fail;
: all I could think of doing was read with a .1 second time limit and see
: if anything came in (and, of course, push it back if nothing did). 
: 
: Question 2: Can anyone think of a better (more direct way) of finding out
:             if anything is in the typeahead under SysV unix?

And the bad news is that I no longer have a valid plan for implementing
a peek into the typeahead buffer at all!  Anyone know if this can be done
under SysV?  (And, of course, how it is done?)

Thanks to all, patience requested of some, for who knows who else might be
as confused as I appear to be?
-- 
	John Campbell               ...!arizona!naucse!jdc
                                    CAMPBELL@NAUVAX.bitnet
	unix?  Sure send me a dozen, all different colors.

guy@auspex.UUCP (Guy Harris) (03/02/89)

>Question 1: Does 0 or -1 work as a "special" infinite value here?

(The time limit is TIME, not MIN.)  Yes, 0 does indicate that no timeout
should occur.

>Question 2: Can anyone think of a better (more direct way) of finding out
>            if anything is in the typeahead under SysV unix?

Without reading the character in question?  No, not in general.  If
you're willing to put up with having to read the character (and possibly
stuffing it into some "pushback" buffer for "getch" or something like
that), you can either 1) put the file descriptor into no-delay mode with
"fcntl" or 2) set both MIN *and* TIME to 0; either of these causes a
"read" to return what characters are there, or if there's nothing there
return 0 rather than blocking.

les@chinet.chi.il.us (Leslie Mikesell) (03/03/89)

In article <1182@naucse.UUCP> jdc@naucse.UUCP (John Campbell) writes:
>And the bad news is that I no longer have a valid plan for implementing
>a peek into the typeahead buffer at all!  Anyone know if this can be done
>under SysV?  (And, of course, how it is done?)

What you have to do is read the characters into your own buffer and then
you can peek all you like.

The point you are missing is that VMIN is the minimum number of characters
to be returned unless VTIME expires between characters.  That is, if
VMIN is greater than zero a read will block forever waiting for the
first character, then return when VMIN characters have come in or VTIME
tenths of seconds elapses between characters, whichever comes first.
If VMIN is 0, then the read will return immediately if no characters
are available.  You can also use fcntl() to set O_NDELAY for this effect
but you have to turn it back off before writing to the device.  However,
keep in mind that it is expensive to loop doing non-blocking reads. It
might be better to fork off a process that could block waiting for
input, or if you are really just watching for an indication to quit
doing whetever else you are doing in the loop you can use one of the
tty-generated signals and forget the read() entirely.

Les Mikesell