I have tried using pipes and redirections to have (C program or scripts) output end up on the input buffer, the way printf "33[6n" does, but no positive results.
Does anyone know how this is possible as:
- a command line
- in a shell script
- C code
Piping output _cmd_ > /dev/stdin and C code fprintf(stdin, "blahn"); have no measurable effect.
Note: I don’t want to “pipe” the input out to another command, I want to “inject” characters into the “keyboard buffer” (as it were).
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
Edit: The short answer was /dev/uinput, now its TIOCSTI (see end of post)
This is the answer so far, and to address the comments:
man ioctl_tty I dont have, but a lookup of TIOCSTI on the kernel source (via FreeElectrons ) will show tiocsti “fake input character”, which uses a tty_struct context.
The application in question is running all the time, interactively, so pipes and redirects cant be used. It can shell out for scripting, however, unlike a lot of other similar apps, it does not, nor allows for, capture the results, only allowing stdin & stdout to do their thing as per normal.
For the foreseeable future there is no chance of changing this, its not my application. However I was able to cut the results of "33[6n", which have been injected into the keyboard buffer by the kernel through tty_insert_flip_char & tty_schedule_flip in src/drivers/tty/tty_buffer.c, which uses a tty_port context.
If memory serves, before the FD file structure was changed, when there was only 4 file descriptors, it may have been possible to achieve this. Nowadays although you can write to /dev/stdin or /proc/self/fd/0, they are connected to /dev/tty# and anything written to to a TTY device will end up on the screen (/dev/stdout). The kernel seems to bypass the file descriptor route when using TTY’s, notice the flip functions refer to it as a port.
Any userland app does not have access to either of those kernel functions. Under X-Windows it is possible to use xvkbd and xdotool or xte, but this app is being used on the linux (VT) console.
The (Almost) Real Answer:
Although /dev/uinput does not have user privileges (on most systems), sudo a script that printf all arguments will work.
Alternatively, the keyboard event will also work, as all users have access to it, but it changes per boot and per system (mine is normally /dev/input/event0, but not always).
After further research, neither of these approaches is practical, especially for scripting. The thing we need to understand about what needs to be done, is that we just want to present text on the input buffer, not “simulate a keypress” (which is how the above devices work).
The (Most Practical) Real Answer:
An offsite question referred back to an answer on stackexchange, from 2011 (here). It uses TIOCSTI. After reviewing the the Perl example again, it may also be practical for scripting, where an application is not supplied.
perl -le 'require "sys/ioctl.ph";
ioctl(STDIN, &TIOCSTI, $_) for split "", join " ", @ARGV
' `_cmds_`
However it does echo it to the screen as well. After many hours of further research and experimentation the following is practical in a script or on the command line:
stty -echo; perl -le 'require "sys/ioctl.ph"; ioctl(STDIN, &TIOCSTI, $_) for split "", join " ", @ARGV ' `_cmds_` ;stty echo
Note: although TIOCSTI has currently been revoked in BSD (Nov 2017), apparently the Linux Kernel developers are of the opposite mind, categorically refusing to revoke it
Method 2
writevt /dev/tty# text, at least on Linux, maybe BSD and Unix, its currently party of the console-tools package. The user must have write privileges for the VT. Specifically, the full and correct answer to the OP is:
writevt `tty` "`_cmds_`"
This question shows the lack of depth of knowledge about base operating systems by the StackExchange community as a whole. writevt is very old, it is a base command installed on 99% (of Linux) systems. Up until June 2002 there was no man page or maintainer for it in Debian, which may account for why a lot of people don’t know about it, even though that was 15 years ago. However, even on Kali Linux (which has everything) it is most often not listed under available commands, even though it has been there since the start.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0