home *** CD-ROM | disk | FTP | other *** search
- Xref: sparky comp.unix.bsd:11131 comp.lang.c:19551
- Newsgroups: comp.unix.bsd,comp.lang.c
- Path: sparky!uunet!cs.utexas.edu!hellgate.utah.edu!fcom.cc.utah.edu!cs.weber.edu!terry
- From: terry@cs.weber.edu (A Wizard of Earth C)
- Subject: Re: a unix terminal question
- Message-ID: <1993Jan11.215312.2080@fcom.cc.utah.edu>
- Sender: news@fcom.cc.utah.edu
- Organization: Weber State University (Ogden, UT)
- References: <1iql6kINNisk@ub.d.umn.edu>
- Date: Mon, 11 Jan 93 21:53:12 GMT
- Lines: 77
-
- In article <1iql6kINNisk@ub.d.umn.edu> cbusch@ub.d.umn.edu (Chris) writes:
- >
- > How does one read in a character from standard input without having
- >the program wait for the key. Basically, I want to do something like:
- > if(kbhit()) c=getch();
- >Except that is not standard, and I want it to work on all platforms.
-
- This is a bad thing to do, unless you have processing to do when characters
- aren't present, and you do your checks relatively infrequently compared to
- the procesing itself; otherwise, you will be in a buzz-loop and suck your
- CPU through the floor. This is common practice under DOS where there is
- nothing else running, but is a generally bad thing to do.
-
- The CORRECT way to do this: use the select() or poll() system call to
- wait for an interval or a character to be present. Resoloution is
- generally 1/1000th of a second; you can effect a poll by having a
- zero-valued timeval struct (as opposed to passing (struct timeval *)NULL).
- This will cause the behaviour you have asked for. When the select()
- returns that there are characters available, do a read() on the descriptor
- (otherwise, return as if the read() has returned 0 characters). It
- should be noted that some systems are sensitive to select/read pairing,
- and if you do this, you should have a select() call prior to every read()
- call, regardless of whther or not you use the select information aro simply
- read anyway.
-
- Another method would be to put the terminal in raw mode, and set the vmin
- to 0 and the vtime based on whether you wanted to screw everyone on your
- system every time your program is run (set it to 0 to poll and screw
- everyone). Normal reads will return 0 characters read.
-
- An older mechanism for BSD systems which is no longer in common use is
- the rdchk() library routine, which ioctl'ed with a FIONREAD to count
- the number of characters pending input (this is still used in SCO Xenix).
- If the number was larger than 0, then you do the read.
-
- In general, these mechanisms are not usable with stdio routines. This is
- because the stdio routines operate on user-space buffering. If I am using
- "getchar()" to read characters, and I typ the string "fred", if I type
- it fast enough, it will be read into the stdin buffer in its entirety.
- When I check the number of characters pending input on the fd, the answer
- will be 0, even though there are still 3 characters pending input on the
- stdin file pointer. You can either check that the number of characters
- in the stdin buffer is not 0 (extremely system dependant), then check to
- see if there are no characters on the fd, and only then skip your getchar.
- For portability, you should use raw I/O (read/write/select) rather than
- character counting the stdio buffer contents.
-
- If the reason you are doing this is a game, you are probably SOL: you
- will eat the machine when you run it. Even then, using a timeout on
- select for the background processing will allow you to adjust the
- speed of the background tasks relative to the player's movement,
- and will not eat the machine in the majority case. This also makes
- your game timing dependent on your players use/nonuse of the control
- entry window rather than on whther or not the player is doing something
- (ie: it's bad if by entering commands I cause the game to become "jerky"
- in it's movements).
-
- If the reason you need to do this is to read from two file descriptors
- at once, then select() or poll() is your best bet (there are other
- methods to do this as well, but select/poll are more efficient in terms
- of system call overhead). You may want to do this if you are writing a
- terminal emulation or chat program.
-
- Good luck.
-
-
- Terry Lambert
- terry@icarus.weber.edu
- terry_lambert@novell.com
- ---
- Any opinions in this posting are my own and not those of my present
- or previous employers.
- --
- -------------------------------------------------------------------------------
- "I have an 8 user poetic license" - me
- Get the 386bsd FAQ from agate.berkeley.edu:/pub/386BSD/386bsd-0.1/unofficial
- -------------------------------------------------------------------------------
-