package App::Termcast;
use Moose;
use IO::Pty::Easy;
use IO::Socket::INET;
use Term::ReadKey;
with 'MooseX::Getopt';
=head1 NAME
App::Termcast - broadcast your terminal sessions for remote viewing
=head1 SYNOPSIS
termcast [options] [command]
=head1 DESCRIPTION
App::Termcast is a client for the L service, which allows
broadcasting of a terminal session for remote viewing. It will either run a
command given on the command line, or a shell.
=cut
has host => (
is => 'rw',
isa => 'Str',
default => 'noway.ratry.ru',
documentation => 'Hostname of the termcast server to connect to',
);
has port => (
is => 'rw',
isa => 'Int',
default => 31337,
documentation => 'Port to connect to on the termcast server',
);
has user => (
is => 'rw',
isa => 'Str',
default => sub { $ENV{USER} },
documentation => 'Username for the termcast server',
);
has password => (
is => 'rw',
isa => 'Str',
default => 'asdf', # really unimportant
documentation => 'Password for the termcast server (mostly unimportant)',
);
sub run {
my $self = shift;
my @argv = @{ $self->extra_argv };
push @argv, ($ENV{SHELL} || '/bin/sh') if !@argv;
my $socket = IO::Socket::INET->new(PeerAddr => $self->host,
PeerPort => $self->port);
$socket->write('hello '.$self->user.' '.$self->password."\n");
my $sockfd = fileno($socket);
my $pty = IO::Pty::Easy->new(raw => 0);
$pty->spawn(@argv);
my $ptyfd = fileno($pty);
my ($rin, $rout) = '';
vec($rin, fileno(STDIN) ,1) = 1;
vec($rin, $ptyfd, 1) = 1;
vec($rin, $sockfd, 1) = 1;
ReadMode 5;
while (1) {
my $ready = select($rout = $rin, undef, undef, undef);
if (vec($rout, fileno(STDIN), 1)) {
my $buf;
sysread STDIN, $buf, 4096;
if (!defined $buf || length $buf == 0) {
warn "Error reading from stdin: $!" unless defined $buf;
last;
}
$pty->write($buf);
}
if (vec($rout, $ptyfd, 1)) {
my $buf = $pty->read(0);
if (!defined $buf || length $buf == 0) {
warn "Error reading from pty: $!" unless defined $buf;
last;
}
syswrite STDOUT, $buf;
$socket->write($buf);
}
if (vec($rout, $sockfd, 1)) {
my $buf;
$socket->recv($buf, 4096);
if (!defined $buf || length $buf == 0) {
warn "Error reading from socket: $!" unless defined $buf;
last;
}
# XXX: do something with this? (watcher notification, etc)
}
}
ReadMode 0;
}
__PACKAGE__->meta->make_immutable;
no Moose;
=head1 TODO
Factor some stuff out so applications can call this standalone?
Use L to make configuration easier.
Do something about the watcher notifications that the termcast server sends.
=head1 BUGS
No known bugs.
Please report any bugs through RT: email
C, or browse to
L.
=head1 SEE ALSO
L
=head1 SUPPORT
You can find this documentation for this module with the perldoc command.
perldoc App::Termcast
You can also look for information at:
=over 4
=item * AnnoCPAN: Annotated CPAN documentation
L
=item * CPAN Ratings
L
=item * RT: CPAN's request tracker
L
=item * Search CPAN
L
=back
=head1 AUTHOR
Jesse Luehrs
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2009 by Jesse Luehrs.
This is free software; you can redistribute it and/or modify it under
the same terms as perl itself.
=cut
1;