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

Simple Bash Script To Email Server Status


I didn't want to constantly have to log into my servers in order to check on key performance indicators so I decided to write a simple script that would do the checking for me. After collecting results, the script emails them to me. There are a few tools called within the script you might need to install. I also convert any tabs into spaces in order to make sure things line up nicely inside my email. #!/bin/bash SERVER="myserver001" TOEMAIL="" FROMEMAIL="myserver001@myserverscom" # Who is logged in and what are they up to WHO=`w` #



How to fix: “PageHandlerFactory-Integrated” has a bad module when setting up ASP.NET


I was recently setting up IIS 7.5 on Windows 2008 R2 for an ASP.NET site and came across the following 500 error: Handler "PageHandlerFactory-Integrated" has a bad module "ManagedPipelineHandler" in its module list. After a bit of searching, it turns out ASP.NET was not completely installed with IIS even though I checked that box in the "Add Feature" dialog. I found a number of suggestions but found this command. It fixed my issues and got rid of the error. %windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -i For a 32 bit system, use the