TTY Keystroke Injection using Perl


TTY Keystroke Injection using Perl


One of my current projects deals with a program that gathers input from a mag strip reader, which emulates a USB attached keyboard. As a result, the program needs to run inside an active shell on the machine. Know, I know there are other possible methods such as capturing the keyboard input by way of custom drivers for the device, but that's a challenge for another day. I needed to occasionally shutdown the program and start it back up in the original tty session. Of course you cant simply stop and start it via restart script scheduled in cron because when it starts back up, the process will be headless and not capture any keystrokes sent to the active tty. What I needed is a way to send keystrokes to the active tty session.

My solution, TTY Keystroke Injection.

Here is a perl one liner to send one character. I found this online.

$ sudo perl -e '$TIOCSTI = 0x5412; $tty = "/dev/pts/3"; $char = "A"; open($fh, ">", $tty); ioctl($fh, $TIOCSTI, $char)'

The downside of the above command is it only sends a single character at a time (in the example, the A will get sent to /dev/pts/3). So… I wrote a simple perl script allowing me to conduct keystroke injection, passing in a full command, into a different session.

# tty keystroke injection
# version 1.2
# Richard

use Getopt::Long;
my $tty; # The tty session we are about to send keys to
my $command; # The command we are about to send to the target tty

GetOptions ("help|?" => sub{usage(0);}
	       ,"tty=s"  => \$tty
	       ,"cmd=s"  => \$command) or usage (1);

if($tty eq ''){
	print 'ERROR: You must specify a target tty session' . "\n";
if($command eq ''){
	print 'ERROR: You must specify a command' . "\n";
# Questions on how to get the correct value for $TIOCSTI
# is discussed here :
my $TIOCSTI = 0x5412;
# Open a connection to the TTY
open(TTY,">$tty") or die "ERROR: Cannot open $tty\n";
# Split the command into single characters
my @command = split("",$command . "\n");
# Sleep a second to make sure the key gets sent
# Loop the arry and send the key to the target TTY
foreach $arr(@command){
print "Command: $command\nSent to $tty\n";

sub usage{
  my $err = shift and select STDERR;
  print < -cmd 
    -tty   -> The dev path to the targeted tty session
                                  To get a list of active tty session you can use the "w" command
                                  or use the command "tty" to see what your current tty session is
    -cmd      -> This is the command to pass to the target tty session
  exit $err;
To execute the program simply pass the target tty device and the command you want to execute.
$ sudo perl ./ -tty /dev/pts/2 -cmd 'ls -al'

You might also like

Squeaky Steel Case Jersey Chair... Fixed!


Our offices recently underwent a major renovation. Part of the change was the arrival of new Steel Case Jersey chairs for our work areas. The chairs themselves are adjustable in several areas and quite comfortable. However, by the time the newness wore off the squeaking started. The slightest movement such as leaning back or forward caused an ear piercing squeak to emit from the underside of the chair. As time progressed, you could hear squeaking throughout the entire floor. At times it was quite comical; however, most of the time it simply annoying. The fix: To stop the squeak find


Building a Word Clock


I was recently asked if I could build a Word Clock. Of course, not wanting to back down from a challenge (and a bit of research) I said "yes". One of the objectives of this build, aside from producing a quality product for our client was to document the build and share with the community. After a bit work, I present to you, the Javelin Word Clock. Check out this video a co-worker put together. I think he did a great job. Javelin's Word Clock Want one? You too can build this same clock by following my Instructables