Linux - Discard keyboard input - c++

First, a bit of background: I'm running the latest stable build of Crunchbang Linux inside a VirtualBox VM. I'm designing a custom text-based user interface to run on top of bash. This is being done with a combination of C++ and bash scripts.
I need to, at times, completely and totally remove the ability for the user to provide the system with any sort of standard keyboard input. This is because, when I run a part of the system, the user is forced to wait for certain amounts of time.
Unfortunately, the user can still type while this is going on, and whatever they type is put on the screen. This happens when I'm running a C++ program as well as a bash script. The reason this is a problem is that there is text on the screen which the user is to read, and if they can type, it displaces the text. There will be other uses for this later, as well, like making the system seem like it has frozen up.
So, the question - How do I
disable the keyboard, or
prevent anything pressed on the keyboard from showing up on the screen?

Turn off echo mode with stty -echo or the equivalent C code (which would use tcgetattr and tcsetattr). When you are ready to accept input again, turn it back on. You may also wish to discard the input that arrived while you weren't expecting it. That would be done with tcflush but be aware that some users (like me) would consider that an annoyance. Typeahead is a feature, not a bug!

To see how user input to a certain process or tty can be intercepted, the man page and source code of interceptty may be enlightening. (have no experience with it)
However, you can hardly (totally) prevent user input. The user is probably always able to switch to a different virtual terminal (if any) or at least to reboot the system with Alt+Print+B (Magic SysRq_key) if not disabled. It is two different things to ignore input on a given tty and disabling keyboard input altogether.

Related

How to detect whether tying is enabled in the currently selected/active interface in C++

In Windows 7(I am not sure about other OS) when you are on a webpage, pressing the space-bar scrolls a few pixels down the page. But when you are in an interface where typing can be done(like an input element, textarea, word editor, code editor, search bar, etc), pressing the space-bar obviously types a space.
Similarly, when all the open windows or menus are minimized, and you are viewing the desktop, and you press a letter key, instead of the letter being typed somewhere, a beep sound is produced.
This shows that the availability of a typing functionality can be "detected". And if it can be detected, it can most likely be done so using C++.
I don't know what to call this. I tried to find out using google but everything I got seemed unrelated to this. I was probably not using the correct keywords.
Whatever this is, I am creating a C++ program where I need to be able to detect it(in an if condition). Something like this
if (/*typing can be done*/) {
//Do something..........
}
Or this
if (/*typing can NOT be done*/) {
if( GetKeyState(VK_SPACE) & 0x8000 ) {
//Do something..........
}
}
And I need to be able to do so natively. Not specific to a particular console window or UI.
If you can help me in any way in figuring this out than please do so. And please feel free to make or suggest relevant edits to improve this question and make it less vague and more detailed and to-the-point.
The functionality you describe belongs to the program running the window with focus, not to the operating system (although the operating system will, at least in part, ultimately power that functionality). It shouldn't come as a surprise that programs can detect keystrokes, because otherwise you wouldn't be able to use your keyboard to input any characters into your computer.
However, you cannot just "detect" a random event with an if statement. "if" is not "when". Your computer will not repeatedly check all if statements in your program and jump to that location in the code whenever one matches. Imagine the chaos!
A program sufficiently complex to have a graphical interface almost certainly has an "event loop", be this in its own code or buried within an API call (as in the case of native Windows applications); such an event loop typically polls for keys being sent to the window(s) managed by the program. If you do not have an event loop (and if your operating system cannot generate a "signal" when a keystroke otherwise goes unhandled), you will have to make one.
Exact specifics are beyond the scope of a Stack Overflow answer, but by pointing you in the direction of a textbook about how to create graphical programs, I am enabling you to discover how input and output is handled in those cases.

How to detect XOFF and XON in Linux terminal application

Certain control sequences have special effects in Linux, such as CTRL-C which sends SIGINT. I can handle signals easily enough, but it appears CTRL-S (XOFF) and CTRL-Q (XON) are special snowflakes. I know their effect (to pause input) can be disabled in the console with stty -ixon, and I could use some trickery to run that command, but that feels like a cheap workaround.
Is there a proper way to rid these sequences of their special effect and get their actual ASCII values (^S, ^Q) using system calls? I know it is doable because the text editor Nano does it, but for the life of me I can't find where it's being handled. I already tried searching the repo for "XOFF".
https://github.com/dtrebbien/nano/tree/master/src
Use the tcgetattr() and tcsetattr() system calls to turn off the IXON flag on standard input, as explained in this manual page.

Linux keyboard scancode issues: For example, UP ARROW gives ^[[A

We've been struggling for a while now to understand the keyboard scancode behavior in Linux.
When we open a normal bash shell, the arrow keys works as expected: UP shows the previous item in the history etc. However when you spawn a process, arrows does not work as expected anymore. For example, UP prints ^[[A instead of the previous command.
To demonstrate this, do something like:
bash$ ping www.google.com
Now, press UP or DOWN etc. and you will see the wrongly mapped key codes while the process is running. However, when you terminate the process the arrow keys will work again.
We've tested it on CentOs, Ubuntu, Mac and even in different shells (bash, sh, zsh) and the same happens everywhere. I've also tried different keyboard modes using kbd_mode where we tested with RAW and XLATE modes.
The closest thing I could see while searching for answers were IPython users have experienced the same behavior when IPython was not build against readline. However, this is not related to our case as far as I can see.
We are developing a C++ Tcl based console application which uses cin and cout to communicate with, and get input from the user. We are having issues with the arrow keys when we try to access the history of previously entered commands. This is a major issue for us as 99% of people expects the arrow characters to just work.
Any ideas on how we could overcome this would be much appreciated.
You must set the terminal into raw mode to get the scan codes and handle them (that is: disable ICANON, you want the non-canonical mode). You probably also want to disable ECHO (so that it doesn't print your input on the terminal).
That is what readline or linenoise are doing. See here for some code. Esp. see the function linenoiseEnableRawMode. Some other simple sample Python code is here where I have written a simple console media player which checks for the keypresses left ("\x1b[D") and right ("\x1b[C").
The relevant calls are to tcgetattr (to get the current terminal state and modify that state struct to get into raw mode and enable some other useful behavior stuff) and tcsetattr (to set the state).
readline, libedit or linenoise are some libraries which do all that work for you and provide you with history, autocompletion, etc.
At the end, you must restore back the old state, otherwise you get the behavior you are describing in your shell.

Echo characters in istream to an unusual "device"

I want to make a version of cin that works in a graphics display window (it's SDL, but I don't think that matters here): that is, when you type, the characters echo into that window rather than the console window. The solution should be cross-platform.
I have this page to tell me how to get characters NOT to echo to the console window: Reading a password from std::cin
...but what I don't know how to do is to make the characters echo on the new graphics display window.
One thing I could do is intercept keyboard events, and if one happens, print the character. But this wouldn't perfectly echo the actual behavior of the istream buffer, because of repeating keys, backspace, enter, tab, and also the real behavior of cin in that if you are typing before C++ gets to the cin, it will put that stuff you typed on the screen at that point.
I think this echoing is done inside the call to _read (read in the Unix world), and that I'm not sure how to access.
TIA.
The behaviors you're talking about are not done by cin nor read() syscall; buffering and processing of special character is done by the terminal emulator and the shell.
You do need to intercept key events and implement these yourself. Alternatively, some terminal emulators (e.g. VTE widget in Gnome) were designed so they can be embedded into another program. You might want to look at that option.
Considering your application is running in a window you shouldn't read input from the console . It's probably possible but you'll have to switch to the terminal window from where you started the window each time you want to input text. If you take this route you need to disable tty echo: http://man7.org/tlpi/code/online/dist/tty/no_echo.c.html (for Linux). Check out http://www.cplusplus.com/forum/general/12256/ for some solutions for Windows too. I don't think there is a solution that works for both so you'll need to bury some #ifdef's in some utility functions.
Since you're using SDL you should probably use SDL's input functions.
Check out http://www.libsdl.org/docs/html/guideinputkeyboard.html
And, more specific to your needs: http://wiki.libsdl.org/moin.fcg/Tutorials/TextInput

Async Console Output

I have a problem with my application win32 console.
The console is used to give commands to my application. However, at the same time it is used to output log messages which mostly comes from asynchronous threads. This becomes a problem when the user tries to write some input and simultaneously an async log message is printed, thus thrashing the display of the users input.
I would like to have some advice in regards to how to handle such a situtation?
Is it possible for example to dedicate the last line in the console to input, similarly to how it looks in the in-game consoles for some games?
You can use SetConsoleMode to disable input echo and line editing mode. You can then echo back input whenever your program is ready to do so. Note that this means you will need to implement things like backspace manually. And don't forget to reset the mode back when you're done with the console!
This is possible using the Console API, but it involves quite a bit of work and all the threads that use the console will have to cooperate by calling your output method rather than directly calling the Console API functions or the runtime library output functions.
The basic idea is to have your common output function write to the console screen buffer, and scroll the buffer in code rather than letting the text flow onto the last line and scroll automatically. As I recall, you'll have to parse the output for newlines and other control characters, and handle them correctly.
You might be able to get away with using "cooked" console input on the last line, although in doing so you risk problems if the user enters more text than will fit on a single line. Also, the user hitting Enter at the end of the line might cause it to scroll up. Probably best in this situation to use raw console input.
You'll want to become very familiar with Windows consoles.
Any time you have asyncronous threads trying to update the same device at once, you are going to have issues like this unless something synchronizes them.
If you have access to everyone's source code, the thing to do would probably be to create some kind of sync object that every task must use to access the console (semaphore, etc).