Solved

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

Posted on 1998-02-20
7
382 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
  • 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
What is SQL Server and how does it work?

The purpose of this paper is to provide you background on SQL Server. It’s your self-study guide for learning fundamentals. It includes both the history of SQL and its technical basics. Concepts and definitions will form the solid foundation of your future DBA expertise.

 
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

VMware Disaster Recovery and Data Protection

In this expert guide, you’ll learn about the components of a Modern Data Center. You will use cases for the value-added capabilities of Veeam®, including combining backup and replication for VMware disaster recovery and using replication for data center migration.

Question has a verified solution.

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

Suggested Solutions

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…
Introduction: Displaying information on the statusbar.   Continuing from the third article about sudoku.   Open the project in visual studio. Status bar – let’s display the timestamp there.  We need to get the timestamp from the document s…
This Micro Tutorial will teach you how to censor certain areas of your screen. The example in this video will show a little boy's face being blurred. This will be demonstrated using Adobe Premiere Pro CS6.
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.

777 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