Path: utzoo!utgpu!water!watmath!clyde!att!osu-cis!tut.cis.ohio-state.edu!rutgers!ucsd!ucbvax!decwrl!sun!pitstop!sundc!seismo!uunet!mcvax!hp4nl!philmds!leo From: leo@philmds.UUCP (Leo de Wit) Newsgroups: comp.unix.wizards Subject: Re: How to write keypressed()? Message-ID: <828@philmds.UUCP> Date: 2 Oct 88 19:11:34 GMT References: <315@telesoft.UUCP> Reply-To: leo@philmds.UUCP (Leo de Wit) Organization: Philips I&E DTS Eindhoven Lines: 66 In article <315@telesoft.UUCP> jjh@telesoft.UUCP (Jim Hayes @dance) writes: [introduction omitted]... |/*===========================================================================*/ |short keypressed() { |/* Returns 1 if a character is available for reading from stdin; 0 otherwise */ | | char a_char; | int old_flags; | int result; | int retry; | | if ( isatty( fileno(stdin) ) == 1 ) { | old_flags = fcntl(fileno(stdin), F_GETFL, 0); | if (old_flags < 0) { | return (0); | } | if ( fcntl(fileno(stdin), F_SETFL, old_flags | FNDELAY) < 0 ) { | return (0); | } | for (retry = 1; retry <= 10; ++retry) { | usleep(2000); | result = read(fileno(stdin), &a_char, 1); | if (result >= 0) { | ungetc(a_char, stdin); ^^^^^^^^^^^^^^^^^^^^^^ There's your problem: you can't ungetc a character you never read (inspecting the return value of ungetc would indicate an error). Although you read the character, you didn't do it using stdio, so ungetc will rightly fail. The use of both buffered and 'raw' I/O on the same file descriptor should be discouraged (unless you're very sure about what you're doing) since stdio has generally spoken no means to keep track of your reads/writes etc. Suggestion for keypressed() (this one returns the number of characters actually available, but you're free to use it as you like of course): /* Returns # of characters available for reading from stdin, or a (negative) * error indication */ int keypressed() { int nchars, retval; retval = ioctl(fileno(stdin),FIONREAD,&nchars); return (retval < 0) ? retval : nchars; } This one doesn't have your retry enhancements, but I'm sure you can merge that in. If you want to do asynchronous I/O (I don't know if this applies to your application), you can also consider doing something like: fcntl(fileno(stdin),F_SETFL,FASYNC); /* perhaps also F_SETOWN ? */ and trapping the SIGIO signal, perhaps if (signal(SIGIO,SIG_IGN) != SIG_IGN) { signal(SIGIO,your_handler); } Hope this helps - Leo.