Path: utzoo!utgpu!water!watmath!clyde!att!osu-cis!tut.cis.ohio-state.edu!bloom-beacon!mcgill-vision!mouse From: mouse@mcgill-vision.UUCP (der Mouse) Newsgroups: comp.unix.wizards Subject: Re: How can I read keyboard without stopping Keywords: curses keyboard Message-ID: <1246@mcgill-vision.UUCP> Date: 15 Aug 88 08:09:47 GMT References: <813@ms3.UUCP> Organization: McGill University, Montreal Lines: 82 In article <813@ms3.UUCP>, isns02@ms3.UUCP (Harris Reavin) writes: > I would like to know if it is possible to get input data from the > keyboard while my program is constantly looping and displaying output > to the screen. The input comes from a call to "popen()". Now wait a minute! If you used popen(), your input is coming from another program, and only indirectly (if at all) from the keyboard. > I am using C, curses, and BSD4.2 on a VAX-780. I have only been able > to enter input if the display stops for "getch()". This is not > acceptable because I want the display to be continuous unless I am > going to change one of the parameters. It sounds as though you really want to read from the keyboard, so I'll ignore the bit about popen(). I know of at least four ways to do this (read without jamming the whole process), of varying degrees of portability and functionality. 1) Signals. Set up an alarm signal (eg, with alarm()) before doing the read and disable it afterwards. Have the signal handler either longjmp out or, depending on how signals interact with read on the system in question, simply do nothing. Good: - works nearly everywhere. Bad: - program blocks for a while. - if alarm() is used (as it must for portability), the granularity of this timeout is one second. 2) Non-blocking I/O. BSD systems, and I believe recent SV systems, support the notion of "non-blocking" reads. What this amounts to is you make a call to turn this mode on, and then any read for which no characters are available will return an error indication instead of blocking. Good: - no temporary blockage. - reasonably widely available (I think). Bad: - may not interact well with curses. Many programs (and library packages) are not prepared to handle "would block" errors. - specifics vary from system to system. - generally, non-blocking mode *must* be turned off or the shell will die - so you must trap SIGBUS, SIGSEGV, SIGINT, etc. - requires constant polling. 3) FIONREAD. BSD systems have an ioctl you can apply to a terminal line to get the number of characters queued available for a read(). SV may have something similar; I don't know. Good: - no temporary blockage. - indicates not only *whether* input is available but also *how much* input is available. Bad: - BSD only (as far as I know). - requires constant polling. 4) select(). BSD systems, and some "SV with BSD extensions" systems (I know of at least one) have the select() syscall. This allows you to block until something is available from any one of several sources you specify, or a timeout expires. (It is possible to wait for other conditions as well, but I'm not trying to write a manpage for the thing.) This is the most flexible method of the four. Good: - full control over blockage, from a zero timeout (polling) to infinite (blocking). Bad: - BSD-specific, though your system may have it even if it's primarily SV. Pick the one you think best suits your needs. Since you're on a BSD system, all four are available. If you aren't interested in porting to non-BSD systems, I recommend select(). (Actually, I recommend that you use select(), with preprocessor #if lines to select some other method if you have to compile somewhere select() is unavailable.) der Mouse old: mcgill-vision!mouse new: mouse@larry.mcrcim.mcgill.edu