[comp.unix.questions] Keyboard Input

eap@bucsb.bu.edu.UUCP (Eric Pearce) (07/13/87)

I would like to write a routine that performs a repeated sequence of statements
(i.e. a loop) that would check for input from the keyboard and do something
according to what was typed in.  Also, it would be able to continue doing the
loop regardless of whether or not anything was typed in from the keyboard.

like this:

    Begin Loop
      check for keyboard input
      if a key was pressed 
                     case
                         1) do something
                         2) do something else
                         ...
                     esac 
      fi
      do some more stuff
    End Loop

I used to be able to do this easily on my Apple ][.  You could check a memory
location to see if a key had been pressed and which one it was, without having
the program wait for user input.   (good for games)

Is there a way to do this in C?  Or maybe a different approach to the problem?
(this is intended for a program on a mainframe)

                                              ANY ideas welcome!

                                                           -Eric
-------------------------------------------------------------------------------
Several people asked what machine I would be running this on:
    Encore MULTIMAX 4.3 BSD UNIX
    and a  VAX 11/750 running the same...
-------------------------------------------------------------------------------
-- 
*******************************************************************************
* UUCP   : ..!harvard!bu-cs!bucsb!eap |-+-+ +-+-+-+-+-+-+-+\ /-+-+-+-+-+-+-+-+*
* ARPANET: eap@bucsb.bu.edu           |    > :   :   :    - @ -  |       g    *
* CSNET  : eap%bucsb@bu-cs            |-+-+-+-+-+-+-+-+-+-+/ \ +-+-+ +-+-+ +-+*
* BITNET : cscc8vc@bostonu            | |  Blasted by ZAXXON   |  ;  |        *
*******************************************************************************

edw@ius2.cs.cmu.edu (Eddie Wyatt) (07/13/87)

In article <1043@bucsb.bu.edu.UUCP>, eap@bucsb.bu.edu.UUCP (Eric Pearce) writes:
> 
> 
> 
> I would like to write a routine that performs a repeated sequence of statements
> (i.e. a loop) that would check for input from the keyboard and do something
> according to what was typed in.  Also, it would be able to continue doing the
> loop regardless of whether or not anything was typed in from the keyboard.
> 


   This seems to be a common question in Unix. To follow, one
procedure that reads one character without waiting for a return
and one procedure that determines if a port is ready to read from.
Modify them to fit your needs if you want.  Do a man stty and ioctl
to find out what the proper include files are.




/**************************************************************************
 *                                                                        *
 *                              w_read_char                               *
 *                                                                        *
 **************************************************************************

   Purpose :  This function reads a single character from input without
	    waiting for a return to be typed.

   Programmer : Eddie Wyatt
 
   Date : July 1987

   Input : None

   Output : returns the current character from standard input

   Locals : 
	ch - the character read
	omode - the old tty mode (used in restoring mode after the character
	        is read)
	mode - use to change the tty mode so a single character can
	       be read without waiting for a return

   Globals : 
	stdin - not modified

 ************************************************************************/

int w_read_char()
    {
    struct sgttyb omode, mode;
    int ch;

    gtty(fileno(stdin),&mode);
    bcopy((char *) &mode, (char *) &omode,sizeof(struct sgttyb));
    mode.sg_flags |= CBREAK;

    stty(fileno(stdin),&mode);
    ch = getchar();
    stty(fileno(stdin),&omode);

    return(ch);
    }




/**************************************************************************
 *                                                                        *
 *                             ready_to_read                              *
 *                                                                        *
 **************************************************************************

   Purpose :  This function returns TRUE if the port (fd) is ready to
	    read from.

   Programmer : Eddie Wyatt
 
   Date : January 1987

   Input : 
   fd - a port

   Output :  returns TRUE if the port is ready to read

   Locals : 
    num - the number of bytes ready to read

   Globals : None

 ************************************************************************/

int ready_to_read(fd)
    int fd;
    {
    int num;

    ioctl(fd,FIONREAD,(char *)&num);
    return(num > 0);
    }


-- 
					Eddie Wyatt

e-mail: edw@ius2.cs.cmu.edu

terrorist, cryptography, DES, drugs, cipher, secret, decode, NSA, CIA, NRO.

rwhite@nu3b2.UUCP (Robert C. White Jr.) (07/14/87)

In article <1043@bucsb.bu.edu.UUCP>, eap@bucsb.bu.edu.UUCP (Eric Pearce) writes:
> 
> I used to be able to do this easily on my Apple ][.  You could check a memory
> location to see if a key had been pressed and which one it was, without having
> the program wait for user input.   (good for games)
> 
> Is there a way to do this in C?  Or maybe a different approach to the problem?
> (this is intended for a program on a mainframe)

It would apear that an apple ][ isnt a mainframe after all ;-)

SERIOUSLY: use the function ioctl to set O_NDELAY on standard input,
use read to read your character. if there are no characters waiting, and you
are not at an EOF condition read will return -1 and errno will be set to
EAGAIN.

This is how it is on our machine, check read(2) in your programmers
refrence [or wherever] for details. AND REMEMBER TO ALWAS CLEAN UP
YOUR ioctl BEFORE BRANCHING/EXITING FROM THE LOOP OR GO UP IN FLAMES!


Robert.

Disclaimer:  My mind is so fragmented by random excursions into a
	wilderness of abstractions and incipient ideas that the
	practical purposes of the moment are often submerged in
	my consciousness and I don't know what I'm doing.
		[my employers certainly have no idea]

john@bby-bc.UUCP (john) (07/17/87)

> SERIOUSLY: use the function ioctl to set O_NDELAY on standard input,
> use read to read your character. if there are no characters waiting, and you
> are not at an EOF condition read will return -1 and errno will be set to
> EAGAIN.
> 
> This is how it is on our machine, check read(2) in your programmers
> refrence [or wherever] for details. AND REMEMBER TO ALWAS CLEAN UP
> YOUR ioctl BEFORE BRANCHING/EXITING FROM THE LOOP OR GO UP IN FLAMES!


Isn't it supposed to return 0  if there are no characters read.  Also
isn't there an ioctl() settable value that specifies the minimum number
of characters which must be in the buffer before a request is satisfied,
along with a time period after which this many characters don't need to
be there?


john

guy%gorodish@Sun.COM (Guy Harris) (07/18/87)

> > SERIOUSLY: use the function ioctl to set O_NDELAY on standard input,
> > use read to read your character. if there are no characters waiting, and you
> > are not at an EOF condition read will return -1 and errno will be set to
> > EAGAIN.

> Isn't it supposed to return 0  if there are no characters read.

It's like this:

In systems that implement 4.[23]BSD-style no-delay I/O, if there are
no characters waiting, "read" will return -1 and "errno" will be set
to EWOULDBLOCK.

In systems that implement System V-style no-delay I/O:

	if the descriptor doesn't refer to a stream, "read" will
	return 0;

	if the descriptor does refer to a stream, "read" will return
	-1 and "errno" will be set to EAGAIN.

S5 prior to R3 didn't have streams.

(Note that some systems may implement both styles of no-delay I/O.)

In POSIX-style non-blocking I/O (selected with O_NONBLOCK, not
O_NDELAY), "read" will return -1 and "errno" will be set to EAGAIN.
I don't know if any systems implement this yet.  (If your system
doesn't define O_NONBLOCK, it doesn't implement it.)

> Also isn't there an ioctl() settable value that specifies the minimum number
> of characters which must be in the buffer before a request is satisfied,
> along with a time period after which this many characters don't need to
> be there?

There is, but not under 4.[23]BSD; the person in question is running
systems based on 4.[23]BSD.  In those systems, there is an "ioctl"
call FIONREAD that will tell you how many characters are waiting to
be read; with this, you don't have to go into no-delay mode (and thus
don't have to leave it, either).  This is arguably more convenient.
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com

greg@ncrcan.UUCP (Greg Foisy) (07/24/87)

In article <23758@sun.uucp> guy%gorodish@Sun.COM (Guy Harris) writes:
>> Also isn't there an ioctl() settable value that specifies the minimum number
>> of characters which must be in the buffer before a request is satisfied,
>> along with a time period after which this many characters don't need to
>> be there?

>There is, but not under 4.[23]BSD; the person in question is running
>systems based on 4.[23]BSD.  In those systems, there is an "ioctl"
>call FIONREAD that will tell you how many characters are waiting to
>be read; with this, you don't have to go into no-delay mode (and thus
>don't have to leave it, either).  This is arguably more convenient.

Under system V if you wish to set the number of characters needed to satisfy
a read request you can disable cononical processing and set VMIN and VTIME to
values which represent the minimum number of characters needed to satisfy a
read request and the minimum amount of time respectively.

You do this through an ioctl, setting the lflags to disable cononical 
processing.  VMIN and VTIME are set in c_cc at VMIN and VTIME.
(termio.c_cc[VMIN] and termio.c_cc[VTIME]).

This may have the undesired effect of disabling the erase and kill edit
functions. 

greg foisy.

mouse@mcgill-vision.UUCP (der Mouse) (07/24/87)

In article <805@nu3b2.UUCP>, rwhite@nu3b2.UUCP (Robert C. White Jr.) writes:
> In article <1043@bucsb.bu.edu.UUCP>, eap@bucsb.bu.edu.UUCP (Eric Pearce) writes:
>> I used to be able to do this [check for keyboard input without
>> waiting] easily on my Apple ][.
>> Is there a way to do this in C?

This is a system-dependent area; presumably you are talking about C
under UNIX.  C per se does not address this sort of question - all
operating system interface issues are handled through library routines.

Unfortunately, there is enough variation across different versions of
UNIX to make it impossible to give a blanket answer.

> [U]se the function ioctl to set O_NDELAY on standard input,

Please specify what flavor of UNIX!  Under 4.3 BSD, for example,
O_NDELAY is a flag to open(), not something one uses with ioctl() (the
ioctl() is called FIONBIO, also usable with fcntl()).

> [if no input and not EOF], read will return -1 and errno will be set
> to EAGAIN.

Another difference.  Under 4.3, errno is set to EWOULDBLOCK.  Please
qualify such statements with what flavor of operating system your
question or answer is for!  (Yes rwhite, I know you said "on our
system", but that doesn't help eap decide whether it applies to his
system.)

So, to sum up: it depends on your system.  Under most (all?) current
variants of UNIX, it is possible, but the details of how depend on the
particular system.  (I can provide detail for 4.3BSD UNIX, and general
ideas for 4.2BSD, but please send mail rather than cluttering the net!)

					der Mouse

				(mouse@mcgill-vision.uucp)

hitchens@godzilla.cs.utexas.edu (Ron Hitchens, Sun Wiz) (07/27/87)

In article <1043@bucsb.bu.edu.UUCP> eap@bucsb.UUCP (Eric Pearce) writes:
>I would like to write a routine that performs a repeated sequence of statements
>(i.e. a loop) that would check for input from the keyboard and do something
>according to what was typed in.  Also, it would be able to continue doing the
>loop regardless of whether or not anything was typed in from the keyboard.
>
>like this:
>
>    Begin Loop
>      check for keyboard input
>      if a key was pressed 
>                     case
>                         1) do something
>                         2) do something else
>                         ...
>                     esac 
>      fi
>      do some more stuff
>    End Loop
>
>Is there a way to do this in C?  Or maybe a different approach to the problem?
>(this is intended for a program on a mainframe)
>                                              ANY ideas welcome!
>                                                           -Eric
>-------------------------------------------------------------------------------
>Several people asked what machine I would be running this on:
>    Encore MULTIMAX 4.3 BSD UNIX
>    and a  VAX 11/750 running the same...
>*******************************************************************************
>* UUCP   : ..!harvard!bu-cs!bucsb!eap |-+-+ +-+-+-+-+-+-+-+\ /-+-+-+-+-+-+-+-+*
>* ARPANET: eap@bucsb.bu.edu           |    > :   :   :    - @ -  |       g    *
>* CSNET  : eap%bucsb@bu-cs            |-+-+-+-+-+-+-+-+-+-+/ \ +-+-+ +-+-+ +-+*
>* BITNET : cscc8vc@bostonu            | |  Blasted by ZAXXON   |  ;  |        *
>*******************************************************************************

   This article is almost two weeks old, I resisted answering until I got
caught up on comp.unix.questions.  A couple of people answered it with 
solutions using non-blocking reads and ioctl()s, but this is a job for
select().  If select() is available, and it is on Eric's BSD systems listed
above, it's much better than using ioctl()s.

   Below is some code which does just what Eric describes, using select().
This code is from a program which displays rwho information on the screen
using curses(), and updates its display every 20 seconds.  This loop does
the "every time" stuff at the top of the loop, and the only keyboard input
it looks for is a refresh command, anything else means to quit.  For an
application like this, select is definitely better, since the process is
asleep in a system call until either input is ready or the timer runs out.
With non-blocking I/O and ioctl()s, your process must run around in a
busy loop polling the keyboard.  A select() polling loop can still be
done by providing the address of a timer set to zero.  See the select() man
page for details.

Ron Hitchens		hitchens@ut-sally.uucp
			hitchens@godzilla.cs.utexas.edu
---------------

loop ()
{
	static	struct	timeval	timer = {REFRESH_DEFAULT, 0};
	char	c;
	int inmask, nfds;

	timer.tv_sec = refresh_time;		/* settable on cmd line */
	while (1) {
		show_stat ();			/* do it */
		inmask = 1;			/* gotta set the mask always */
		if ((nfds = select (32, &inmask, 0, 0, &timer)) < 0) {
			printf ("Error doing select, I'm gettin' outta here\n");
			return;
		}
		if (nfds == 0)
			continue;		/* timer expired */
		read (0, &c, 1);		/* the sucker hit a key */
		switch (c) {
		case 'r':
		case 'R':
		case 0x12:   /* ^R */
		case 'l':
		case 'L':
		case 0x0C:   /* ^L */
			(void) wclear (stdscr);	 /* clear the physical screen */
			(void) wrefresh (stdscr);/* for reassuring feedback */
			break;
		default:
			return;
		}
	}
}

   The above code puts the tty into CBREAK mode before calling loop().
You'll want to do this if you want to get each char as it becomes available.
If you leave it in cooked mode, select() will not indicate data is avaliable
until an entire line has been entered and a newline typed (or some other "break"
character, such as ^C or ESC).  The tty driver will also do backspace
handling transparently to you, if you use CBREAK, you'll have to do it
yourself (if appropriate).

   There is a gotcha to watch out for if you mix select() and stdio.  Select()
works on file descriptors, stdio implements a buffering system between your
code and the raw file descriptor.  This means that the data returned to you
by getchar(), gets(), etc, were probably read earlier and are being returned
from a buffer.  Doing a select() on an fd being used by stdio will only
be indicative of new data available on the fd, it won't know about any data
previously read and buffered by the stdio routines.  In general, it's not
a good idea to mix stdio and fd operations.
---------

emc@unicus.UUCP (Eric M. Carroll) (07/27/87)

greg@ncrcan.UUCP writes:
> Under system V if you wish to set the number of characters needed to satisfy
> a read request you can disable cononical processing and set VMIN and VTIME to
> values which represent the minimum number of characters needed to satisfy a
> read request and the minimum amount of time respectively.
> 
> You do this through an ioctl, setting the lflags to disable cononical 
> processing.  VMIN and VTIME are set in c_cc at VMIN and VTIME.
> (termio.c_cc[VMIN] and termio.c_cc[VTIME]).

It should be noted here that VTIME takes affect *AFTER* the first character is
received. ie the timeout is only for BETWEEN characters; the 0th to 1st
character transition is not covered in this timeout. Thus trying to check if 
there is anything in the queue by using VTIME and attempting to read one
character will fail. 
-- 
	Eric Carroll 			Unicus Corporation, Toronto Ont.
	Eric.M.Carroll@Unicus.COM				  (Internet)
	{seismo!mnetor, utzoo!utgpu!utcsri}!unicus!Eric.M.Carroll (dumb UUCP)
	mnetor!unicus!Eric.M.Carroll@seismo.css.GOV		  (dumb ARPA)

edw@ius1.cs.cmu.edu (Eddie Wyatt) (07/27/87)

In article <8569@ut-sally.UUCP>, hitchens@godzilla.cs.utexas.edu (Ron Hitchens, Sun Wiz) writes:
> 
>    This article is almost two weeks old, I resisted answering until I got
> caught up on comp.unix.questions.  A couple of people answered it with 
> solutions using non-blocking reads and ioctl()s, but this is a job for
> select().  If select() is available, and it is on Eric's BSD systems listed
> above, it's much better than using ioctl()s.

   If your talking about my posting of "ready_to_read" for determining
if a characters are ready to read, there is a reason why it doesn't used
"select". Plain in simple, select is a dog of a system call.  When I measure
the time it takes to call both select and ioctl on a fd associated with a
socket, I found ioctl FNREAD to be about 3 times as fast. 

  To the orignal poster,  you want to run both read_to_read or select with
CBREAKs on.

   BTW select is only better than ioctl for determining if a SINGLE port
has characters on it to read from, in that you can specify a time out value if
needed.  May I also sugguest you read the man page entry for "select".  The
synopsis specificly says the call is intended  for multiplexing.  Polling a
single line doesn't constitute multiplexing, through the system call  "select"
can obviously be used for such operations.

> 
> loop ()
> {
> 	static	struct	timeval	timer = {REFRESH_DEFAULT, 0};
> 	char	c;
> 	int inmask, nfds;
> 
> 	timer.tv_sec = refresh_time;		/* settable on cmd line */
> 	while (1) {
> 		show_stat ();			/* do it */
> 		inmask = 1;			/* gotta set the mask always */
		^^^^^^^^^^^^^^^^^^^^

		A mood point here.  If you are using BSD 4.2 this should be:

		inmask = (1<<(fileno(stdout)));

		In BSD 4.3 this should be :

		{
		fd_set inmask;
		.....

		FD_SET(fileno(stdout),&inmask);
		.........
		}
		
> 		if ((nfds = select (32, &inmask, 0, 0, &timer)) < 0) {
> 			printf ("Error doing select, I'm gettin' outta here\n");
> 			return;
> 		}
> 		if (nfds == 0)
> 			continue;		/* timer expired */
> 		read (0, &c, 1);		/* the sucker hit a key */
		     ^^^^^^^^^^
			Another mood point.  this should be -

		read(fileno(stdout),&c,sizeof(char));

			And if you are overly cautious

		if ((readval = read(fileno(stdout),&c,sizeof(char))) == -1)
			perror("read failed");
		else if (readval == 0)
			fprintf(stderr,"EOF encounter\n");

> 		switch (c) {
> 		case 'r':
> 		case 'R':
> 		case 0x12:   /* ^R */
> 		case 'l':
> 		case 'L':
> 		case 0x0C:   /* ^L */
> 			(void) wclear (stdscr);	 /* clear the physical screen */
> 			(void) wrefresh (stdscr);/* for reassuring feedback */
> 			break;
> 		default:
> 			return;
> 		}
> 	}
> }
-- 

					Eddie Wyatt

e-mail: edw@ius1.cs.cmu.edu

rsh27@chemabs.UUCP (Robert S. Hall) (07/27/87)

In article <1043@bucsb.bu.edu.UUCP> eap@bucsb.UUCP (Eric Pearce) writes:
>I would like to write a routine that performs a repeated sequence of statements
>(i.e. a loop) that would check for input from the keyboard and do something
>according to what was typed in.  Also, it would be able to continue doing the
>loop regardless of whether or not anything was typed in from the keyboard.

        On a System V version of Unix you could open stdin using O_NDELAY 
(By the way on our Ultrix 1.2 system, in System V emulation mode, a program 
that uses O_NODELAY mode on the keyboard will cause a user to be logged off 
when it terminates.) On 4.[2,3] Berkley Unix you could use 
"ioctl(0,FIONREAD,&lngintvar);" this will return the number of characters 
that are ready to be returned by a read call in a long int variable named 
"lngintvar".  See the "tty(4)" documentation for more information.  6

hitchens@ut-sally.UUCP (Ron Hitchens, TP Repairman) (07/28/87)

In article <1021@ius1.cs.cmu.edu> edw@ius1.cs.cmu.edu (Eddie Wyatt) writes:
}In article <8569@ut-sally.UUCP>, hitchens@godzilla.cs.utexas.edu (Ron Hitchens, Sun Wiz) writes:
}> ...this is a job for select()...
 
}   If your talking about my posting of "ready_to_read" for determining
}if a characters are ready to read, there is a reason why it doesn't used
}"select". Plain in simple, select is a dog of a system call.  When I measure
}the time it takes to call both select and ioctl on a fd associated with a
}socket, I found ioctl FNREAD to be about 3 times as fast. 

   Ya gotta point, Eddie.  Select does indeed incur quite a bit more overhead
than an ioctl does.  Though in fairness select is more flexible and works
at a higher level than an ioctl does.  In looking at this again, I think I
made an assumption that the code would want to do periodic processing, while
also watching the keyboard for input.  This may not be the case, if you
want to spend as much time as possible computing, but also notice that
a key has been pressed, using a FIONREAD ioctl is quicker and less 
expensive.

   But if you want to go to sleep until either something is ready to read
or a time interval expires, select is clearly better.  This is in fact
multiplexing, multiplexing a timer and an fd.  This is a big win over 
polling loops for that sort of thing.
 
}  To the orignal poster,  you want to run both read_to_read or select with
}CBREAKs on.

   Yeah, and remember to reset the tty modes before you exit.  You may also
want to catch INT and QUIT signals so that you can reset the modes if
you're interrupted.
   
}   BTW select is only better than ioctl for determining if a SINGLE port
}has characters on it to read from, in that you can specify a time out value if
}needed.  May I also sugguest you read the man page entry for "select".  The
}synopsis specificly says the call is intended  for multiplexing.  Polling a
}single line doesn't constitute multiplexing, through the system call  "select"
}can obviously be used for such operations.

   Agreed.  Polling an fd with a timeout is what I had in mind.  This is
not always what is desired, but is a good coding practice for interactive
applications.  It allows you to surrender control to the kernel, so that
other processes can run, and have it wake you up when one of two (or more)
conditions is met.  Again, I agree that select is not a good choice for doing
a straight poll on a single fd, though it can be done.  A direct ioctl is
less expensive for that.

}> loop ()
}> {
}> 	static	struct	timeval	timer = {REFRESH_DEFAULT, 0};
}> 	char	c;
}> 	int inmask, nfds;
}> 
}> 	timer.tv_sec = refresh_time;		/* settable on cmd line */
}> 	while (1) {
}> 		show_stat ();			/* do it */
}> 		inmask = 1;			/* gotta set the mask always */
}		^^^^^^^^^^^^^^^^^^^^
 
}		A mood point here.  If you are using BSD 4.2 this should be:
}		inmask = (1<<(fileno(stdout)));
}
}		In BSD 4.3 this should be :
}		{
}		fd_set inmask;
}		.....
}
}		FD_SET(fileno(stdout),&inmask);
}		.........
}		}

  Right, except that I'm using stdin, not stdout.  The hardcoded 1 (shame
on me!) is the bit for fd 0 which is (usually) stdin.  Sorry about that, this
is ancient code and I should know better.

}> 		if ((nfds = select (32, &inmask, 0, 0, &timer)) < 0) {
}> 			printf ("Error doing select, I'm gettin' outta here\n");
}> 			return;
}> 		}
}> 		if (nfds == 0)
}> 			continue;		/* timer expired */
}> 		read (0, &c, 1);		/* the sucker hit a key */
}		     ^^^^^^^^^^
}			Another mood point.  this should be -
}		read(fileno(stdout),&c,sizeof(char));

   Right again.  I really do code more portably now (honest).  This code is
from a program which is necessarily BSD specific (it looks at rwhod packets,
which is a hack only Berkeley could love), so I went ahead and harcoded those
fd values, a habit I've mostly broken now.  I could argue about sizeof(char),
in that I want to only read one byte, even if sizeof(char) wasn't 1, but it's
not worth it.

}			And if you are overly cautious
}
}		if ((readval = read(fileno(stdout),&c,sizeof(char))) == -1)
}			perror("read failed");
}		else if (readval == 0)
}			fprintf(stderr,"EOF encounter\n");

  I wasn't overcautious, I wanted to quit on the slightest excuse and leave.
If there was a read error or EOF, I'd exit through the switch statement,
though I should have cleared the character before reading.

}> 		switch (c) {
}> 		case 'r':
}> 		case 'R':
}> 		case 0x12:   /* ^R */
}> 		case 'l':
}> 		case 'L':
}> 		case 0x0C:   /* ^L */
}> 			(void) wclear (stdscr);	 /* clear the physical screen */
}> 			(void) wrefresh (stdscr);/* for reassuring feedback */
}> 			break;
}> 		default:
}> 			return;
}> 		}
}> 	}
}> }
}					Eddie Wyatt
}e-mail: edw@ius1.cs.cmu.edu

   I'm a little embarrassed by the number of nits to be picked in my sample
code, I should have cleaned it up before posting.  But anyway, I'm still
a fan of select, when used appropriately it can greatly simplify your life,
and achieving the same functionality without it is a major pain.


Ron Hitchens		hitchens@ut-sally.uucp
			hitchens@godzilla.cs.utexas.edu

gwyn@brl-smoke.ARPA (Doug Gwyn ) (07/28/87)

In article <196@chemabs.UUCP> rsh27@UNIX14.UUCP (PUT YOUR NAME HERE) writes:
>(By the way on our Ultrix 1.2 system, in System V emulation mode, a program 
>that uses O_NODELAY mode on the keyboard will cause a user to be logged off 
>when it terminates.)

That's inherent in O_NDELAY.  If you don't reset it, when the shell tries
to read from the terminal it gets back what it interprets as EOF and exits.

guy%gorodish@Sun.COM (Guy Harris) (07/29/87)

> It should be noted here that VTIME takes affect *AFTER* the first character
> is received.

Unless VMIN is zero, in which case (under System V, but not under System
III), the timer is started when the "read" is done, and the "read" is
satisfied as soon as a single character arrives.  If VTIME is also
zero, the effect is the same as if you'd turned no-delay mode on; the
"read" is immediately satisfied regardless of whether there are any
characters present or not.

Of course, the person who asked the original question was using
machines that, most likely, have a 4BSD terminal driver, so none
of this is pertinent.  Furthermore, all they wanted to do was know
whether there was any input present; FIONREAD, which *is* available
under 4BSD, does this job better than either no-delay I/O or
VMIN/VTIME.
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com