#!/usr/pkg/bin/perl
#
# $Header: /home/vikas/src/nocol/perlnocol/RCS/rcisco,v 2.3 1999/11/05 21:59:13 vikas Exp $
#
###
### Telnet to a remote Cisco router and execute a command.
###
# This is a rewrite of the original script by Christopher Sedore and
# John Wobus (jmwobus@mailbox.syr.edu) written in 1993.
#
# This script has been rewritten to avoid any copyright restrictions.
#
# 	Copyright 1997 Netplex Technologies Inc, info@netplex-tech.com
#	(See file COPYRIGHT for details)
#
# Usage:
#	rcisco <router-name or ip> <passwd> <command>
#
#  You can put a default router password in this file and then supply a
#  blank field as the password on the command line.
#	rcisco cisco-gw.abc.com  ''   'show hardware'
###
###


local ($rhost, $rpasswd, $rcmd) = @ARGV;

$rhost = "cisco-gw.my.com" unless $rhost;
$rpasswd = "default-cisco-passwd" unless $rpasswd;
$rcmd = "show hardware" unless $rcmd;

local ($rport) = 23;	# default telnet port

sub Inet_aton {
    local ($hname) = @_;
    local ($haddr, $junk);

    if ($hname =~ /^\d/) {
	local ( @n ) = split(/\./, $hname);
	$haddr = pack('C4', @n);
    }
    else { ($junk,$junk,$junk,$junk, $haddr) = gethostbyname($hname); }
    return ($haddr);
}

##
# Create a connected socket to the remote host.
#	newSocket ("cisco-gw.abc.com", 23, 'tcp')
# Dies on failure.
sub newSocket {
    local ($host, $port, $sproto) = @_ ;
    local ($type, $proto);

    $sproto = 'tcp' unless $sproto;

    `uname -s -r -m` ;

    # Depending on version of perl, call 'use Socket' or 'require socket.ph'
    # From Netnews posting by jrd@cc.usu.edu (Joe Doupnik)
    local ($AF_INET, $SOCK_STREAM, $SOCK_DGRAM) = (2, 1, 2); # default values
    if ( $] =~ /^5\.\d+$/ ) {        # perl v5
	# print STDERR "debug: Check for perl5 passed...\n";
	eval "use Socket";
	$AF_INET = &Socket'PF_INET;
        $SOCK_STREAM = &Socket'SOCK_STREAM;
        $SOCK_DGRAM  = &Socket'SOCK_DGRAM;  #'
    }
    else {  # perl v4
	eval {require "socket.ph"} || eval {require "sys/socket.ph"} ;
	if ( defined (&main'PF_INET) ) {
	    # print STDERR "debug: found sys/socket.ph\n";
	    $AF_INET = &main'PF_INET;
            $SOCK_STREAM = &main'SOCK_STREAM;
            $SOCK_DGRAM = &main'SOCK_DGRAM;
        }
        elsif (`uname -s -r -m` =~ /SunOS\s+5/) {  # Solaris, need to run h2ph
            require "sys/socket.ph";        # Gives error and exits
            die 'Did you forget to run h2ph ??';
        }
    }

    if ($port =~ /\D/) { $port = getservbyname($port, $sproto); }
    if ($sproto =~ /tcp/) { $type = $SOCK_STREAM;}
    else { $type = $SOCK_DGRAM };

    $haddr = Inet_aton($host) || die "Unknown host (no address)- $host";
    unless ($ostype) { $ostype= `uname -s -r -m` ; chop ($ostype); }
    if ($ostype =~ /BSD\/OS\s+4/) {   # bsdi 4.0 changed socket struct
      $paddr = pack ('x C n a4 x8', $AF_INET, $port, $haddr);
    }
    else { $paddr = pack ('S n a4 x8', $AF_INET, $port, $haddr); }
    ($junk, $junk, $proto) = getprotobyname($sproto);
    socket(SOCK, $AF_INET, $type, $proto) || die "socket: $!";
    connect(SOCK, $paddr) || die "connect: $!";

    return (SOCK);
}

sub cleanup {
    kill (9, $child) if $child;
}

###
### main
###

$SIG{'INT'} = 'cleanup';
local ($sock) = &newSocket($rhost, $rport, 'tcp');
select($sock); $| = 1;	# make socket unbuffered
select(STDOUT);		# set back to standard file handle.

# Now we fork and the child sends commands to the Cisco while the
# parent reads and prints from the stdout.
if ($child = fork) {
    select $sock;
    print "$rpasswd\n";
    sleep 1;
    print "terminal length 0\n";
    print "$rcmd\n";
    print "quit\n";
    sleep 2;
    exit 0;	# this will wait in zombie mode until parent exits.
}
# in the parent
while (<$sock>) { print; }
exit 0;

