Solved

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

Posted on 1998-02-20
7
379 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
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 
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

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
repeatEnd java challenge 42 83
Folder Comparison 12 52
viewing source code from eclipse 13 74
scoreUp challenge 14 48
Introduction: Dynamic window placements and drawing on a form, simple usage of windows registry as a storage place for information. Continuing from the first article about sudoku.  There we have designed the application and put a lot of user int…
If you use Adobe Reader X it is possible you can't open OLE PDF documents in the standard. The reason is the 'save box mode' in adobe reader X. Many people think the protected Mode of adobe reader x is only to stop the write access. But this fe…
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 demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

758 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

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now