Return to BSD News archive
Received: by minnie.vk1xwt.ampr.org with NNTP id AA6426 ; Sat, 09 Jan 93 11:02:38 EST Xref: sserve comp.unix.bsd:9805 comp.lang.c:37809 Newsgroups: comp.unix.bsd,comp.lang.c Path: sserve!manuel.anu.edu.au!munnari.oz.au!spool.mu.edu!howland.reston.ans.net!usc!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 -------------------------------------------------------------------------------