home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.unix.wizards
- Path: sparky!uunet!gumby!destroyer!mudos!mju
- From: mju@mudos.ann-arbor.mi.us (Marc Unangst)
- Subject: Re: Keyboard hit in C programs
- Message-ID: <BxHq3n.2G8@mudos.ann-arbor.mi.us>
- Date: Tue, 10 Nov 1992 07:57:22 GMT
- References: <1dms9iINNa6m@agate.berkeley.edu>
- Organization: The Programmer's Pit Stop, Ann Arbor MI
- Keywords: Keyboard hit, C programs, UNIX
- Lines: 80
-
- In article <1dms9iINNa6m@agate.berkeley.edu> bernt@valois (Bernt Skottun) writes:
- >intervals will not do). In the DOS environment
- >I have been able to do this with the "kbhit()" function.
- >My question is: what is the equivalent function in the UNIX
- >environment? or how does one go about creating such a function?
-
- Your question is answered in Part 4 of the comp.unix.questions FAQ
- list. In the future, please check to see if your question is answered
- in one of the FAQ postings before posting it to the net.
-
- 4.1) How do I read characters from a terminal without requiring the user
- to hit RETURN?
-
- Check out cbreak mode in BSD, ~ICANON mode in SysV.
-
- If you don't want to tackle setting the terminal parameters
- yourself (using the "ioctl(2)" system call) you can let the stty
- program do the work - but this is slow and inefficient, and you
- should change the code to do it right some time:
-
- #include <stdio.h>
- main()
- {
- int c;
-
- printf("Hit any character to continue\n");
- /*
- * ioctl() would be better here; only lazy
- * programmers do it this way:
- */
- system("/bin/stty cbreak"); /* or "stty raw" */
- c = getchar();
- system("/bin/stty -cbreak");
- printf("Thank you for typing %c.\n", c);
-
- exit(0);
- }
-
- You might like to check out the documentation for the "curses"
- library of portable screen functions. Often if you're interested
- in single-character I/O like this, you're also interested in
- doing some sort of screen display control, and the curses library
- provides various portable routines for both functions.
-
- 4.2) How do I check to see if there are characters to be read without
- actually reading?
-
- Certain versions of UNIX provide ways to check whether characters
- are currently available to be read from a file descriptor. In
- BSD, you can use select(2). You can also use the FIONREAD ioctl
- (see tty(4)), which returns the number of characters waiting to
- be read, but only works on terminals, pipes and sockets. In
- System V Release 3, you can use poll(2), but that only works on
- streams. In Xenix - and therefore Unix SysV r3.2 and later - the
- rdchk() system call reports whether a read() call on a given file
- descriptor will block.
-
- There is no way to check whether characters are available to be
- read from a FILE pointer. (You could poke around inside stdio
- data structures to see if the input buffer is nonempty, but that
- wouldn't work since you'd have no way of knowing what will happen
- the next time you try to fill the buffer.)
-
- Sometimes people ask this question with the intention of writing
- if (characters available from fd)
- read(fd, buf, sizeof buf);
- in order to get the effect of a nonblocking read. This is not
- the best way to do this, because it is possible that characters
- will be available when you test for availability, but will no
- longer be available when you call read. Instead, set the
- O_NDELAY flag (which is also called FNDELAY under BSD) using the
- F_SETFL option of fcntl(2). Older systems (Version 7, 4.1 BSD)
- don't have O_NDELAY; on these systems the closest you can get to
- a nonblocking read is to use alarm(2) to time out the read.
-
- --
- Marc Unangst, N8VRH | "There are two ways to solve this problem:
- mju@mudos.ann-arbor.mi.us | the hard way, and the easy way. Let's start
- | with the hard way."
- | - W. Scheider, from a Physics lecture
-