[net.lang.c] C Input Question?

sah9577@ritcv.UUCP (Scott Hossler) (02/25/85)

I am working an a very simple game using graphics text with a
GiGi terminal.  I am having a big problem with the input.  When
I get to a read, or any input statment, in C, everything stops
and waits for the input.

I want to be able to have the program check for keyboard input, and 
if it is there to act upon it, otherwise to continue processing.
Is there an easy way to do this in C.  I am doing this on a VAX
runnung 4.2 if that makes a difference.  

I have played around with the low leval input described in a V7
manual, but couldn't get any where.  My next thought is to fork
off a process for the background and one for the user's charactor
and then use a semaphore to allow access to the graphics cursor.
Is this nessassary, and if it is, any hints on what to watch out
for?

Thanks to all.

scott hossler
rochester!ritcv!sah9577

jlup@cci-bdc.UUCP (John Lupien ) (02/27/85)

> I am working an a very simple game using graphics text with a
> GiGi terminal.  I am having a big problem with the input.  When
> I get to a read, or any input statment, in C, everything stops
> and waits for the input.
> 
[text cut for brevity. Scott wants non-blocking I/O, that is "read if
data, but don't wait for data.]
>
> Is there an easy way to do this in C.  
> I am doing this on a VAX running 4.2 if that makes a difference.  
>
> scott hossler
> rochester!ritcv!sah9577

Scott, your big problem lies in the use of a V7 manual.
Read the 4.2 manual on tty(4) and fcntl(2) for the right way read
without blocking. In brief;

	stty cbreak		/* use ioctl, stty(2), whatever */
	
#include <sys/types.h>
#include <sys/uio.h>
#include <fcntl.h>

	res = fcntl (stdin, F_SETFL, FNDELAY);
	
	if (res == -1)
	{
		printf("Can't set up terminal. Goodbye\n");
		exit(1);
	}
	
	if (read (stdin, buf, bytes) == -1)
	{
		if (errno != EWOULDBLOCK)
		{
		printf ("Screwy I/O error: errno = %d. Bombing...\n", 
						errno);
			exit(1);
		}
		noread = TRUE;
	} else
	{
		noread = FALSE;
	}
	
	if (noread)
	{
		/* do processing for *no input* condition */
	} else
	{
		/* process input in buf. */
	}
	
  Although the above is not in any sense a legal program, this is the 
  kind of thing you need to do on 4.2 to get the functionality you 
  describe. I hope I understood your needs, but this should be of
  general interest to BSD users anyway.

		-John Lupien
		CCI Boston Development Center
		222 Third St.
		Cambridge,MA 02142

<imaginary data>

mroddy@enmasse.UUCP (Mark Roddy) (02/28/85)

[ bug me not ]

	{ use nodelay mode to solve reading from empty terminal input file }

	But if you don't have 4.2, V3(5):

		alarm(x);
		read(0,buf,1);
		alarm(0);
		/* and set up a signal routine for SIGALARM */

		x is the number of seconds your read will time out in.
	There is a problem here, if you lose the cpu at alarm(x), 
	you may get alarmed before read. You could lock yourself in
	before the alarm call, but that's rather rude.

	I was reading Creative Computing when I saw the most bogus
	C programming example.
	The author was comparing C to Basic-

	Basic: if A=1 and B=1 goto 104950393040 [:->

	C: if (A==1 & B==1) foobar();

	Which works, of course, but it was clear from the context that the
	author thought that '&' and logical AND were identical!!!!

	Boy is he in for a surprise.

	Don't they have editors at that mag?

-- 
						Mark Roddy
						Net working,
						Just reading the news.

					(harvard!talcott!panda!enmasse!mroddy)

ndiamond@watdaisy.UUCP (Norman Diamond) (03/04/85)

> I was reading Creative Computing when I saw the most bogus C programming
> example.  The author was comparing C to Basic-
> 	Basic: if A=1 and B=1 goto 104950393040 [:->
> 	C: if (A==1 & B==1) foobar();
> Which works, of course, but it was clear from the context that the author
> thought that '&' and logical AND were identical!!!!  -- Mark Roddy

It doesn't work if A == 1 and B == 3.  It calls foobar when it shouldn't.

-- 

   Norman Diamond

UUCP:  {decvax|utzoo|ihnp4|allegra}!watmath!watdaisy!ndiamond
CSNET: ndiamond%watdaisy@waterloo.csnet
ARPA:  ndiamond%watdaisy%waterloo.csnet@csnet-relay.arpa

"Opinions are those of the keyboard, and do not reflect on me or higher-ups."

meister@faron.UUCP (Philip W. Servita) (03/04/85)

>> I am working an a very simple game using graphics text with a
>> GiGi terminal.  I am having a big problem with the input.  When
>> I get to a read, or any input statment, in C, everything stops
>> and waits for the input.
>> 
>[text cut for brevity. Scott wants non-blocking I/O, that is "read if
>data, but don't wait for data.]
>>
>> Is there an easy way to do this in C.  
>> I am doing this on a VAX running 4.2 if that makes a difference.  
>>
>> scott hossler
>> rochester!ritcv!sah9577


i did this once i a game program also. try the following:

#include <sgtty.h>

...

char 
inkey()

{

   long charwaiting;
   char getchar();

   ioctl(0,FIONREAD,&charwaiting);

   if(charwaiting) return(getchar());   
 
   return((char) 0);

}

returns the next character on the stdin stream if there is one, 0 otherwise.
this will only work in cbreak or raw mode. look up tty(4) for details.

                                        -the venn buddhist
-- 
---------------------------------------------------------------------
         is anything really trash before you throw it away?
---------------------------------------------------------------------

tim@callan.UUCP (Tim Smith) (03/09/85)

In article <7026@watdaisy.UUCP> ndiamond@watdaisy.UUCP (Norman Diamond) writes:
>> I was reading Creative Computing when I saw the most bogus C programming
>> example.  The author was comparing C to Basic-
>> 	Basic: if A=1 and B=1 goto 104950393040 [:->
>> 	C: if (A==1 & B==1) foobar();
>> Which works, of course, but it was clear from the context that the author
>> thought that '&' and logical AND were identical!!!!  -- Mark Roddy
>
>It doesn't work if A == 1 and B == 3.  It calls foobar when it shouldn't.

Mr. Roddy is correct.  I think Mr. Diamond is forgetting that the range
of the '==' operator is {0,1}.
-- 
Duty Now for the Future
					Tim Smith
			ihnp4!wlbr!callan!tim or ihnp4!cithep!tim

dave@lsuc.UUCP (David Sherman) (03/19/85)

In article <247@faron.UUCP> meister@faron.UUCP (Philip W. Servita) writes:
||>[text cut for brevity. Scott wants non-blocking I/O, that is "read if
||>data, but don't wait for data.]
||
||   ioctl(0,FIONREAD,&charwaiting);

That's fine for BSD (which was the system the questioner wanted it for).
Anyone have an easy way of doing this for v7? I'm willing to do a
limited amount of kernel hacking.

Dave Sherman
The Law Society of Upper Canada
-- 
{utzoo pesnta nrcaero utcs hcr}!lsuc!dave
{allegra decvax ihnp4 linus}!utcsri!lsuc!dave

sjoerd@tjalk.UUCP (Sjoerd Mullender) (03/21/85)

In article <522@lsuc.UUCP> dave@lsuc.UUCP (David Sherman) writes:
>In article <247@faron.UUCP> meister@faron.UUCP (Philip W. Servita) writes:
>||>[text cut for brevity. Scott wants non-blocking I/O, that is "read if
>||>data, but don't wait for data.]
>||
>||   ioctl(0,FIONREAD,&charwaiting);
>
>That's fine for BSD (which was the system the questioner wanted it for).
>Anyone have an easy way of doing this for v7? I'm willing to do a
>limited amount of kernel hacking.

Here is a C routine that returns non-zero if there was any input pending.
This is for a V7 PDP 11 system.  The only requirement is that /dev/kmem
is readable (which it should NOT be for security).

#include <sys/param.h>
#include <sys/dir.h>
#include <sys/user.h>

inputpending()
{
	static int fd = -2;
	unsigned c;

	if (fd == -2)	/* uninitialized */
		if ((fd = open("/dev/kmem", 0)) >= 0) {
			/* If the open fails, fd will be -1, so we won't
			 * try again.
			 * Close the file descriptor on exec.
			 */
			ioctl(fd, FIOCLEX, (struct sgttyb *) 0);
			/* 0140000 is the beginning of the u area
			 * u_ttyp is the pointer to the tty struct
			 */
			lseek(fd, (long) &((struct user *) 0140000)->u_ttyp, 0);
			read(fd, &c, sizeof c);
			/* seek to the beginning of the tty struct */
			lseek(fd, (long) c, 0);
		}
	if (fd < 0)
		return 0;
	/* the first 2 byte of the tty struct is a pointer to the clist */
	if (read(fd, &c, sizeof c) < sizeof c)
		return 0;
	lseek(fd, - (long) sizeof c, 1);
	/* there is input when the pointer to the clist is != 0 */
	return c != 0;
}
-- 
			Sjoerd Mullender
			...!{decvax,philabs,seismo}!mcvax!vu44!sjoerd

alexis@reed.UUCP (Alexis Dimitriadis) (03/24/85)

In article <522@lsuc.UUCP> dave@lsuc.UUCP (David Sherman) writes:

>||>[text cut for brevity. Scott wants non-blocking I/O, that is "read if
>||>data, but don't wait for data.]
>||
>||   ioctl(0,FIONREAD,&charwaiting);
>
>That's fine for BSD (which was the system the questioner wanted it for).
>Anyone have an easy way of doing this for v7? I'm willing to do a
>limited amount of kernel hacking.

  I have gotten the same effect without using non-blocking I/O at all.
I used it to write a real-time "game", so the following is in that context.

If you have the equivalent of setitimer(), which arranges for a signal to
be sent to your process after a specified amount of time, then you can
set the signal handler to be the routine that makes things happen with
time. (e.g., advances the killer ships)  The same routine should also 
reset the timer if it cannot automatically be set to repeat.
(And the handler, if it gets reset!)

  Then the main thread of your program can block waiting for input to
process, and things will happen in `real time' by repeated calls to the
handler.  You have to be careful not to confuse the main thread by altering
things while it is processing input, (e.g. by ignoring the alarm for a
while), and to make sure alarms do not come so 
often that the input never gets read at all, as will be the case if the 
handler takes a while. (You can discard pending alarms or whatever).

  It is fairly straightforward, but may be difficult to debug, since the
control flow is strange.  The safest course is probably to block alarms
while processing input, and unblock them just before a read.  The approach
needs a fairly sophisticated interrupt handler, but can be used where non-
blocking I/O is not implemented. 

	Alexis Dimitriadis 
-- 
_______________________________________________
	  alexis @ reed
	...ihnp4!{harvard|tektronix}!reed
	...decvax!tektronix!reed
	...teneron!reed