#!/bin/sh -- # A comment mentioning perl
eval 'exec perl -S $0 ${1+"$@"}'
        if 0;
#
# vcinject.pl: simple hack to inject keystrokes into Linux VC tty.
# See LinuxVNC.c for a more careful treatment using C and public API.
#
# Usage:  vcinject.pl <N>   (or /dev/ttyN)
#
# This is an example x11vnc -pipeinput program  E.g.: 
#
#   x11vnc -rawfb map:/dev/fb0@1024x768x16 -pipeinput "vcinject.pl /dev/tty3" 
#
# (see fbset(8) for obtaining fb info).
#
# It reads lines like this from STDIN:
#
# Keysym <id> <down> <n> <Keysym> ...
#
# <id> is ignored, it uses the rest to deduce the keystrokes to send
# to the console.
#

$tty = shift;
$tty = "/dev/tty$tty" if $tty =~ /^\d+$/;

warn "strange tty device: $tty\n" if $tty !~ m,^/dev/tty\d+$,;

open(TTY, ">$tty") || die "open $tty: $!\n";
$fd = fileno(TTY);

$linux_ioctl_syscall = 54;	# common knowledge, eh? :-)
$TIOCSTI = 0x5412;

%Map = qw(
	Escape		27
	Tab 		 9
	Return		13
	BackSpace	 8
	Home		 1
	End		 5
	Up		16
	Down		14
	Right		 6
	Left		 2
	Next		 6
	Prior		 2
);
# the latter few above seem to be vi specials. (since they are normally
# escape sequences, e.g. ESC [ 5 ~)

sub lookup {
	my($down, $key, $name) = @_;

	my $n = -1; 
	$name =~ s/^KP_//;

	# algorithm borrowed from LinuxVNC.c:
	if (! $down) {
		if ($name =~ /^Control/) {
			$control--;
		}
		return $n;
	} 

	if ($name =~ /^Control/) {
		$control++;
	} else {
		if (exists($Map{$name})) {
			$n = $Map{$name};
		}
		if ($control && $name =~ /^[A-z]$/) {
			$n = ord($name);
			# shift down to the Control zone:
			if ($name =~ /[a-z]/) {
				$n -= (ord("a") - 1);
			} else {
				$n -= (ord("A") - 1);
			}
		}
		if ($n < 0 && $key < 256) {
			$n = $key;
		}
	}
	return $n;
}

$control = 0;
$debug = 0;

while (<>) {
	chomp;
	if (/^\w+$/) {
		# for debugging, you type the keysym in manually.
		$_ = "Keysym 1 0 999 $_ None";
	}
	next unless /^Keysym/;

	my ($j, $id, $down, $k, $keysym, $rest) = split(' ', $_);

	$n = lookup($down, $k, $keysym);
	if ($n < 0 || $n > 255) {
		print STDERR "skip: '$keysym' -> $n\n" if $down && $debug;
		next;
	}

	$n_p = pack("c", $n);
	$ret = syscall($linux_ioctl_syscall, $fd, $TIOCSTI, $n_p);

	print STDERR "ctrl=$control $keysym/$k syscall(" .
		"$linux_ioctl_syscall, $fd, $TIOCSTI, $n) = $ret\n" if $debug;

}