Solved

kbhit(), ioctl() and all those nasty things.

Posted on 1998-02-20
7
386 Views
Last Modified: 2013-12-26
(Sorry for the long drawn out question...)
Does anyone know the best way to create an equivilant for the kbhit() function? (in the good ol' conio.h under DOS)
I am using BSDI3.1 with the latest vers of GCC and G++.

I have looked through all the previous questions under this topic and have found around 5 or 6 questions that are all relatively similar to what I need, and the answer given is always either to use curses and getch(), or use the esoteric ioctl function, etc...
Well, "curses" is just what I did when I tried to use curses... (and besides, I think it still WAITS for some kind of input, and Ive got some wacky things to do while its waiting for input...)
As far as the ioctl stuff goes, someone had answered with this little function for one of the questions:

>>#include <stdio.h>
>>#include <sys/types.h>
>>#include <sys/stat.h>
>>#include <sys/ioctl.h>
>>#include <unistd.h>
>>#include <fcntl.h>
>>
>>int getch()
>>{
>>struct sgttyb tty, tty_org;
>>char key;
>>int retval= EOF;
>>
>>ioctl(fileno(stdin), TIOCGETP, &tty_org);
>>tty = tty_org;
>>tty.sg_flags |= CRMOD;
>>tty.sg_flags &= ~ECHO;
>>tty.sg_flags &= ~XTABS;
>>
>>tty.sg_flags |= RAW;
>>ioctl(0, TIOCSETP, &tty);
>>fcntl(0, F_SETFL, O_NDELAY);
>>
>>if ((retval= read(0, &key, 1)) == 1)
>> retval= key;
>>
>>ioctl(fileno(stdin), TIOCSETP, &tty_org);
>>fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0)&~O_NDELAY);
>>
>>return retval;
>>}

Now, this may work with the Flinstone's compiler, but all of the include files that I have indicate that this code is outdated.
Now I HAVE actually tried to convert it (using termios instead of sgttyb, etc.) and this is what I came up with:
(Directly cut/pasted)

#include<stdio.h>
#include<sys/ioctl.h>
#include<termios.h>
#include<unistd.h>
#include<fcntl.h>

void main(void)
        {
        struct termios New, Old;
        int Value;
        char Key;

        ioctl(STDIN_FILENO, TIOCGETA, &Old);
        New = Old;
        New.c_cc[VMIN] = 0;
        New.c_cc[VTIME] = 0;
        ioctl(STDIN_FILENO, TIOCSETA, New);
        fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);

        while ((Value = read(STDIN_FILENO, &Key, 1)) < 1)
                {
                /* Do some wacky stuff here. */
                }

        printf("[%c]\n", Key);
        ioctl(STDIN_FILENO, TIOCSETA, Old);
        fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL, 0) & ~O_NONBLOCK);

        printf("\n\n");
        }

Now this ALMOST works... It actually gets a char while doing some wacky stuff, but when the program finishes, my terminal is completely hosed (As if I didnt reset the old flags,etc. properly). It doesnt recognize any characters I type in at all. I have to disconnect completely and reconnect to the server...
I know Im just being an idiot, but if anyone can provide any clues at all, I will kiss the ground you walk on for the rest of my life! Thanks, in advance, and sorry for the long question.
0
Comment
Question by:starlink
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 3
7 Comments
 
LVL 84

Expert Comment

by:ozo
ID: 1296022
Don't you mean
 ioctl(STDIN_FILENO, TIOCSETA, &Old);
?
0
 
LVL 32

Accepted Solution

by:
jhance earned 100 total points
ID: 1296023
Here is the simplest way I know how to do it.  It uses the stty command so if it not in /bin, you should change the path.  If you want to do some other processing while waiting for the character, fork this routine off and set a flag when the character comes in:


#include <stdio.h>
#include <stdlib.h>

main()      
{
        int c;
        printf("Hit any character to continue\n");            
        system("/bin/stty cbreak");
        c = getchar();            
        system("/bin/stty -cbreak");
        printf("Thank you for typing %c.\n", c);
        exit(0);
}
0
 

Author Comment

by:starlink
ID: 1296024
I knew it! Thank you, ozo... I KNEW I was just being an idiot... That was the problem the whole time. Sheesh, I tried everything else BUT that. I guess now I know why I dont program for a living... ;)
I also had to add the line (For anyone else who is interested):

New.c_lflag &= ~ICANON;

after setting the VTIME and VMIN stuff. Now it works perfectly! Thank you very much ozo!
And thank you, too, jhance, but to be honest, I always thought system calls were a little sloppy. =P
But thanks for the quick response!
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 32

Expert Comment

by:jhance
ID: 1296025
I guess it depends on your definition of "best".
0
 

Author Comment

by:starlink
ID: 1296026
Well, that may be an _easier_ way to do it, but I dont want to have to rely on another program at all. And if my program is run on many different systems, I'd have to make sure that everyone knew what directory it had to be in, etc.... I dont know about you but I cant STAND when I get a program that is supposed to do a certain thing, and it tells me it needs 20 other different programs or other third party files, and those programs need a few other files each and on and on and on (I know stty is standard, but Im not using that as an example). I suppose I should stop complaining and just be glad it's all free! Hehe. ;>
0
 
LVL 32

Expert Comment

by:jhance
ID: 1296027
BTW, did you really mean to give ME the points for this question?  Based on your comments, ozo seems to have found the problem with your code as posted.
0
 

Author Comment

by:starlink
ID: 1296028
Actually, I wasnt too sure how to do that... Well, I'll definately have other questions... ;)
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In this article, I'll describe -- and show pictures of -- some of the significant additions that have been made available to programmers in the MFC Feature Pack for Visual C++ 2008.  These same feature are in the MFC libraries that come with Visual …
This is to be the first in a series of articles demonstrating the development of a complete windows based application using the MFC classes.  I’ll try to keep each article focused on one (or a couple) of the tasks that one may meet.   Introductio…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Come and listen to Percona CEO Peter Zaitsev discuss what’s new in Percona open source software, including Percona Server for MySQL (https://www.percona.com/software/mysql-database/percona-server) and MongoDB (https://www.percona.com/software/mongo-…

695 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question