Tuesday, 25 August 2009

Interact with other local Linux terminal sessions

If you're interested in trying to control/inject/view other terminal sessions (e.g. with ssh or telnet on a tty or pts) that you/someone is logged into on that machine then read on. Handy for zapping that vi session you left running at work, or playing havoc with something random ;)

It seems that watch does the trick for FreeBSD, but for Linux there's only things like ttysnoop (for linux-2.6) but that requires you modify your /etc/inittab files which is a bore. There's also conspy but that only works with physical terminal devices not ptys, as far as the docs say...

However you can do it without altering anything:
  • See what's being typed (and subsequent output) in another terminal session by using peekfd - you just need to supply the UID of the shell running on that other terminal (find it using ps). Watch out as the output may well contain some 8-bits chars which can confuse your current terminal - though you can get it back to normal using a terminal reset. (e.g. sudo peekfd /dev/pts/27)
  • Inject characters into a terminal by using the TIOCSTI ioctl() with this neat Perl script (copied below). Find the tty of the process you're interested in (e.g. ps axg | grep vi) and use that as the argument to the perl script e.g. echo 'ZZ' | sudo ./catvt.pl /dev/pts/27
  • #!/usr/bin/perl -w
    use strict;
    use Fcntl;
    use constant TIOCSTI => 0x5412;
    
    unless (@ARGV >= 1) {
    print "usage: $0 [vt] <input>\n";
    exit; }
    my $vt = shift @ARGV;
    my $buf = join '', <>;
    &writevt ($vt, $buf) || die "can't write to $vt: $!\n";
    exit;
    
    sub writevt {
    my ($vt, $buf) = @_;
    sysopen (VT, $vt, O_RDONLY) || return 0;
    for (my $i = 0; $i < length $buf; $i++) {
    ioctl (VT, TIOCSTI, substr ($buf, $i, 1)) || return 0; }
    close (VT) || return 0;
    return 1; } 
[updated 6jan10]

No comments:

Post a Comment