Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

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

Posted on 1998-02-20
7
Medium Priority
?
391 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
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
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

[Webinar] Lessons on Recovering from Petya

Skyport is working hard to help customers recover from recent attacks, like the Petya worm. This work has brought to light some important lessons. New malware attacks like this can take down your entire environment. Learn from others mistakes on how to prevent Petya like worms.

Question has a verified solution.

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

Here is how to use MFC's automatic Radio Button handling in your dialog boxes and forms.  Beginner programmers usually start with a OnClick handler for each radio button and that's just not the right way to go.  MFC has a very cool system for handli…
Introduction: Dialogs (2) modeless dialog and a worker thread.  Handling data shared between threads.  Recursive functions. Continuing from the tenth article about sudoku.   Last article we worked with a modal dialog to help maintain informat…
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.
This lesson discusses how to use a Mainform + Subforms in Microsoft Access to find and enter data for payments on orders. The sample data comes from a custom shop that builds and sells movable storage structures that are delivered to your property. …
Suggested Courses

604 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