[comp.sys.sgi] How to do non-blocking keyboard input

taylorr@glycine.cs.unc.edu (Russell Taylor) (06/14/90)

	I want to do non-blocking keyboard I/O in a program.  Basically, the
routine will read a character from the keyboard if there is one and return
NULL if there is not.  This is done in a tight loop with reads and writes
to other devices.  How to I get a character from the keyboard if there is
one and a NULL if there is not?

	Thanks,
	Russell Taylor
	taylorr@cs.unc.edu

archer@elysium.esd.sgi.com (Archer Sully) (06/14/90)

In article <14670@thorin.cs.unc.edu> taylorr@glycine.cs.unc.edu (Russell Taylor) writes:


>	I want to do non-blocking keyboard I/O in a program.  Basically, the
>routine will read a character from the keyboard if there is one and return
>NULL if there is not.  This is done in a tight loop with reads and writes
>to other devices.  How to I get a character from the keyboard if there is
>one and a NULL if there is not?

Check out 'Advanced UNIX(tm) Programming' by Marc Rochkind.  It contains 
more answers to this (and all of the other questions that you will inevitably
have) than I would care to post.

--
Archer Sully 	      |  Ask not what you can do for you country,
(archer@esd.sgi.com)  |  But what your country's been doing to you.
                      |                    -- The Avengers

mike@BRL.MIL (Mike Muuss) (06/14/90)

The best way to do it is to use the select() system call.

Here is a portable subroutine that will show you how to do it.
	Best,
	 -Mike

-------
/*
 *			B S D S E L E C T
 *
 *  Ordinarily, a stub for select() could have been implemented here,
 *  but the IRIS defines a graphics library routine select().
 *  On non-BSD systems, select() is a name likely to have been reused,
 *  so this special interface has been created.  This also has the slight
 *  advantage of centralizing the struct timeval stuff.
 */

#if defined(BSD)
#	include <sys/types.h>	/* for fd_set macros */
#endif
#if defined(BSD) || defined(CRAY)
#	include <sys/time.h>	/* for struct timeval.  Includes <time.h> */
#else
#	include <time.h>
#endif
#if defined(sgi)
#	if !defined(mips) || defined(SGI4D_Rel2)
		/* 3D systems, and Rel2 4D systems. */
#		include <bsd/sys/types.h>
#		include <bsd/sys/time.h>
#	else
		/* Rel3 4D systems got it right */
#		include <sys/types.h>
#		include <sys/time.h>
#	endif
#endif
#ifdef stellar
#	include <sys/timeval.h>
#endif

#ifdef FD_SET
/* The 4.3 BSD version */
bsdselect( readfds, sec, us )
long readfds;
{
	fd_set	fdset;
	int	width;
	struct	timeval tv;
	int	ret;

	tv.tv_sec = sec;
	tv.tv_usec = us;

	if( (width = getdtablesize()) <= 0 )
		width = 32;
	FD_ZERO( &fdset );
	fdset.fds_bits[0] = readfds;	/* peek inside! */

	if( (ret = select( width, &fdset, (fd_set *)0, (fd_set *)0, &tv )) <= 0 )  {
		if( ret < 0 )  perror("bsdselect/select");
		return(0);		/* no bits ready */
	}

	readfds = fdset.fds_bits[0];
	return( readfds );
}
#else

/* The old version */
bsdselect( readfds, sec, us )
long readfds;
{
#if defined(BSD) || defined(sgi) || defined(stellar) || defined(CRAY)
	struct timeval tv;
	int	ret;
	long	mask;

	tv.tv_sec = sec;
	tv.tv_usec = us;
	mask = readfds;
	if( (ret = select( 32, &mask, 0L, 0L, &tv )) <= 0 )  {
		if( ret < 0 )  perror("bsdselect/select");
		return(0);	/* No bits ready */
	}
	return( mask );
#else
	return(32-1);	/* SYSV always has lots of input */
#endif
}
#endif /* FD_SET */

msc@ramoth.esd.sgi.com (Mark Callow) (06/15/90)

In article <9006140143.aa19050@WOLF.BRL.MIL>, mike@BRL.MIL (Mike Muuss) writes:
|> The best way to do it is to use the select() system call.
|> 
|> Here is a portable subroutine that will show you how to do it.
|> 	Best,
|> 	 -Mike
|> 
|> -------
|> /*
|>  *			B S D S E L E C T
|>  *
|>  *  Ordinarily, a stub for select() could have been implemented here,
|>  *  but the IRIS defines a graphics library routine select().
|>  *  On non-BSD systems, select() is a name likely to have been reused,

The GL routine "select" was renamed gselect in release 3.0 more than 2 years
ago.

--
From the TARDIS of Mark Callow
msc@ramoth.sgi.com, ...{ames,decwrl}!sgi!msc
"There is much virtue in a window.  It is to a human being as a frame is to
a painting, as a proscenium to a play.  It strongly defines its content."

root@sgzh.uucp (Bruno Pape) (06/15/90)

In article <14670@thorin.cs.unc.edu> taylorr@glycine.cs.unc.edu (Russell Taylor) writes:
>
>	I want to do non-blocking keyboard I/O in a program.  Basically, the
>routine will read a character from the keyboard if there is one and return
>NULL if there is not.  This is done in a tight loop with reads and writes
>to other devices.  How to I get a character from the keyboard if there is
>one and a NULL if there is not?
>
>	Thanks,
>	Russell Taylor
>	taylorr@cs.unc.edu

This will do what you want.  It is short and simple, but maybe not so portable.

I know there are others that prefer select over ioctl, and we know who each
other are, but you can choose the method best suited to your own needs.

Have Fun,

Bruno

----------------------- begin program --------------------------------------
#include <sys/termio.h>

main()
{
	struct	termio	kbd, kbd_save;
	char	buff;

	if ( ioctl( 0, TCGETA, &kbd_save ) < 0 ) perror( "ioctl" );

	if ( ioctl( 0, TCGETA, &kbd ) < 0 ) perror( "ioctl" );

	kbd.c_lflag = kbd.c_cc[VTIME] = kbd.c_cc[VMIN] = 0;

	if ( ioctl( 0, TCSETA, &kbd ) < 0 ) perror( "ioctl" );

	while ( read ( 0, &buff, 1 ) == 0 ) printf( "looping\n" );

	printf("received %c\n", buff );

	if ( ioctl( 0, TCSETA, &kbd_save ) < 0 ) perror( "ioctl" );
}
------------------------ end program ---------------------------------------