Blame perl/AnyData_SNMP/netsh

Packit Service b38f0b
#!/usr/bin/perl
Packit Service b38f0b
Packit Service b38f0b
use Getopt::Std;
Packit Service b38f0b
Packit Service b38f0b
use DBI;
Packit Service b38f0b
use Term::ReadLine;
Packit Service b38f0b
use SNMP;
Packit Service b38f0b
use AutoLoader;
Packit Service b38f0b
use IO::File;
Packit Service b38f0b
Packit Service b38f0b
BEGIN {
Packit Service b38f0b
    $opts{'t'} = ! eval { require Text::FormatTable; };
Packit Service b38f0b
    $ansicolor = eval { require Term::ANSIColor; };
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
# override some of the functions to force our colorized semantics.
Packit Service b38f0b
# This is really ugly, but if you pass colorized strings directly to
Packit Service b38f0b
# Text::FormatTable then it calculates the string lengths incorrectly.
Packit Service b38f0b
# Children: don't try this at home.  We're trained professionals.
Packit Service b38f0b
if ($colorize) {
Packit Service b38f0b
   eval {
Packit Service b38f0b
        #
Packit Service b38f0b
	# colorized strings.
Packit Service b38f0b
	#
Packit Service b38f0b
	package color_string;
Packit Service b38f0b
Packit Service b38f0b
	require Term::ANSIColor;
Packit Service b38f0b
Packit Service b38f0b
	use overload
Packit Service b38f0b
	    '""' => \&string_it
Packit Service b38f0b
	;
Packit Service b38f0b
Packit Service b38f0b
	sub string_it {
Packit Service b38f0b
	    if ($_[0][3]) {
Packit Service b38f0b
		if ($_[0][3] == 1) {
Packit Service b38f0b
		    return color_it();
Packit Service b38f0b
		} else {
Packit Service b38f0b
		    $_[0][3] -= 1;
Packit Service b38f0b
		    return $_[0][1];
Packit Service b38f0b
		}
Packit Service b38f0b
	    }
Packit Service b38f0b
	    return $_[0][1];
Packit Service b38f0b
	}
Packit Service b38f0b
Packit Service b38f0b
        sub colorize_next {
Packit Service b38f0b
	    $_[0][3] = 2;
Packit Service b38f0b
	}
Packit Service b38f0b
Packit Service b38f0b
	sub color_it {
Packit Service b38f0b
	    my $str = $_[1] || $_[0][1];
Packit Service b38f0b
	    return $_[0][0] . $str . $_[0][2];
Packit Service b38f0b
	}
Packit Service b38f0b
Packit Service b38f0b
	sub new {
Packit Service b38f0b
	    my $this = [Term::ANSIColor::color($_[2]), $_[1],
Packit Service b38f0b
		      Term::ANSIColor::color('reset')];
Packit Service b38f0b
	    return bless($this, $_[0]);
Packit Service b38f0b
	}
Packit Service b38f0b
    }
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
if ($opts{'t'} == 0 && $colorize) {
Packit Service b38f0b
    eval {
Packit Service b38f0b
	package Text::FormatTable;
Packit Service b38f0b
Packit Service b38f0b
	sub _l_box($$)
Packit Service b38f0b
	{
Packit Service b38f0b
	    my ($width, $text) = @_;
Packit Service b38f0b
	    my $lines = _wrap($width, $text);
Packit Service b38f0b
	    map { 
Packit Service b38f0b
		if (ref($text) eq "color_string") {
Packit Service b38f0b
		    $_ .= $text->color_it($_) . ' 'x($width-length($_));
Packit Service b38f0b
		} else {
Packit Service b38f0b
		    $_ .= ' 'x($width-length($_));
Packit Service b38f0b
		} 
Packit Service b38f0b
	    } @$lines;
Packit Service b38f0b
	    return $lines;
Packit Service b38f0b
	}
Packit Service b38f0b
Packit Service b38f0b
	sub _r_box($$)
Packit Service b38f0b
	{
Packit Service b38f0b
	    my ($width, $text) = @_;
Packit Service b38f0b
	    my $lines = _wrap($width, $text);
Packit Service b38f0b
	    map { 
Packit Service b38f0b
		if (ref($text) eq "color_string") {
Packit Service b38f0b
		    $_ = ' 'x($width-length($_)) . $text->color_it($_);
Packit Service b38f0b
		} else {
Packit Service b38f0b
		    $_ = ' 'x($width-length($_)) . $_;
Packit Service b38f0b
		} 
Packit Service b38f0b
	    } @$lines;
Packit Service b38f0b
	    return $lines;
Packit Service b38f0b
	}
Packit Service b38f0b
Packit Service b38f0b
    }
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
if (!$ansicolor) {
Packit Service b38f0b
    $begin = $end = "*";
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
$SNMP::use_enums=1;
Packit Service b38f0b
Packit Service b38f0b
Packit Service b38f0b
#defaults
Packit Service b38f0b
$opts{'d'} = "\t";
Packit Service b38f0b
$opts{'v'} = 1;
Packit Service b38f0b
$opts{'l'} = 'authNoPriv';
Packit Service b38f0b
$params = "";
Packit Service b38f0b
Packit Service b38f0b
getopts('hd:tR:u:l:v:a:A:x:X:p:c:t:r:',\%opts);
Packit Service b38f0b
Packit Service b38f0b
usage() if ($#ARGV == -1 || $opts{'h'});
Packit Service b38f0b
Packit Service b38f0b
my %parammap = {
Packit Service b38f0b
    'v' => 'Version',
Packit Service b38f0b
    'u' => 'SecName',
Packit Service b38f0b
    'a' => 'AuthProto',
Packit Service b38f0b
    'A' => 'AuthPass',
Packit Service b38f0b
    'x' => 'PrivProto',
Packit Service b38f0b
    'X' => 'PrivPass',
Packit Service b38f0b
    'p' => 'RemotePort',
Packit Service b38f0b
    't' => 'Timeout',
Packit Service b38f0b
    'r' => 'Retries',
Packit Service b38f0b
    'c' => 'Community',
Packit Service b38f0b
    'l' => 'SecLevel'
Packit Service b38f0b
    };
Packit Service b38f0b
Packit Service b38f0b
foreach my $x (keys(%opts)) {
Packit Service b38f0b
    if ($parammap{$x}) {
Packit Service b38f0b
	$params .= ";ad_SNMP_$parammap{$x}=$x";
Packit Service b38f0b
    }
Packit Service b38f0b
    push @sessparams,$parammap{$x},$x;
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
my $host = shift @ARGV;
Packit Service b38f0b
$params .= ";ad_SNMP_DestHost=" . $host;
Packit Service b38f0b
push @sessparms,'DestHost', $host;
Packit Service b38f0b
Packit Service b38f0b
# connect to the DBI interface
Packit Service b38f0b
$AnyData::Storage::SNMP::debugre = $opts{'R'} if ($opts{'R'});
Packit Service b38f0b
($dbh = DBI->connect("dbi:AnyData:ad_default=SNMP$params"))
Packit Service b38f0b
    || die "\tConnection problem: $DBI::errstr\n";
Packit Service b38f0b
$AnyData::Storage::SNMP::debugre = $opts{'R'} if ($opts{'R'});
Packit Service b38f0b
Packit Service b38f0b
$prompt = "netsh> ";
Packit Service b38f0b
Packit Service b38f0b
load_rcs();
Packit Service b38f0b
Packit Service b38f0b
# setup terminal prompter
Packit Service b38f0b
$ENV{'PERL_RL'}='o=0' if (!exists($ENV{'PERL_RL'}));
Packit Service b38f0b
# the ornaments are too ugly
Packit Service b38f0b
$term = new Term::ReadLine 'netsh';
Packit Service b38f0b
Packit Service b38f0b
if ($#ARGV >= 0) {
Packit Service b38f0b
    # command line command
Packit Service b38f0b
    netsh(join(" ",@ARGV));
Packit Service b38f0b
} else {
Packit Service b38f0b
    # interactive shell
Packit Service b38f0b
    while($cmd = $term->readline($prompt)) {
Packit Service b38f0b
	last if ($cmd eq "exit" || $cmd eq "quit" || $cmd eq "q");
Packit Service b38f0b
	netsh($cmd, \%conf);
Packit Service b38f0b
    }
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
# load all configuration files we can find.
Packit Service b38f0b
sub load_rcs {
Packit Service b38f0b
    if (-f "$ENV{'HOME'}/.snmp/netshrc") {
Packit Service b38f0b
	source_file("$ENV{'HOME'}/.snmp/netshrc");
Packit Service b38f0b
    }
Packit Service b38f0b
    if (-d "$ENV{'HOME'}/.snmp/netsh") {
Packit Service b38f0b
	foreach my $i (glob("$ENV{'HOME'}/.snmp/netsh/*")) {
Packit Service b38f0b
	    if (-f "$i" && "$i" !~ /.*(~|.bak)$/) {
Packit Service b38f0b
		source_file("$i");
Packit Service b38f0b
	    }
Packit Service b38f0b
	}
Packit Service b38f0b
    }
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
# command definition for sourcing a particular file
Packit Service b38f0b
sub source_file {
Packit Service b38f0b
    my $fh = new IO::File;
Packit Service b38f0b
    if ($fh->open("<$_[0]")) {
Packit Service b38f0b
	while(<$fh>) {
Packit Service b38f0b
	    if (s/<<\s*(\w+)$//) {
Packit Service b38f0b
		my $stopat = $1;
Packit Service b38f0b
		my $lines = $_;
Packit Service b38f0b
		while(<$fh>) {
Packit Service b38f0b
		    last if (/$stopat/);
Packit Service b38f0b
		    $lines .= $_;
Packit Service b38f0b
		}
Packit Service b38f0b
		$_ = $lines;
Packit Service b38f0b
	    }
Packit Service b38f0b
	    netsh($_);
Packit Service b38f0b
	}
Packit Service b38f0b
    } else {
Packit Service b38f0b
	print STDERR "no such file: $_[0]\n";
Packit Service b38f0b
    }
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
# export data into an external file
Packit Service b38f0b
sub my_export {
Packit Service b38f0b
    shift;
Packit Service b38f0b
    if (!$insh) {
Packit Service b38f0b
	my $cmd = "create table exporttable (" . join (" varchar(255), ",@{$sth->{NAME}}) . " varchar(255))";
Packit Service b38f0b
	$exporth->do($cmd);
Packit Service b38f0b
	$cmd = "insert into exporttable values(" . ('?, ' x ($#_)) . "?)";
Packit Service b38f0b
	$insh = $exporth->prepare($cmd);
Packit Service b38f0b
    }
Packit Service b38f0b
    $insh->execute(@_);
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
# the main processing function.
Packit Service b38f0b
sub netsh {
Packit Service b38f0b
    my $stmt = shift;
Packit Service b38f0b
    chomp($stmt);      # remove trailing white space
Packit Service b38f0b
    $stmt =~ s/^\s+//; # remove leading white space
Packit Service b38f0b
    $stmt =~ s/;*$//;  # get rid of trailing semicolons
Packit Service b38f0b
    return if ($stmt =~ /^\s*$/);
Packit Service b38f0b
    return if ($stmt =~ /^\s*\#/);
Packit Service b38f0b
    my ($name, $args) = ($stmt =~ /^(\w+)\s*(.*)$/);
Packit Service b38f0b
Packit Service b38f0b
    #define alias
Packit Service b38f0b
#    print "doing [$multi_alias]: $stmt\n";
Packit Service b38f0b
    if ($name eq "alias" || $multi_alias) {
Packit Service b38f0b
	if ($multi_alias) {
Packit Service b38f0b
	    if ($stmt =~ /^prompt\s+(\d+)\s+[\"\'](.+)[\"\']/) {
Packit Service b38f0b
		$aliases{$current_alias}{'prompts'}[$1] = $2;
Packit Service b38f0b
		return;
Packit Service b38f0b
	    } elsif ($stmt =~ /^prompt\s+(\d+)\s+(.+)/) {
Packit Service b38f0b
		my $x = $2;
Packit Service b38f0b
		my $spot = $1;
Packit Service b38f0b
		$x =~ s/\s+$//;
Packit Service b38f0b
		$aliases{$current_alias}{'prompts'}[$spot] = "$x ";
Packit Service b38f0b
		return;
Packit Service b38f0b
	    } elsif ($stmt =~ /^\s*\}\s*$/) {
Packit Service b38f0b
		$prompt = $oprompt;
Packit Service b38f0b
		$multi_alias = 0;
Packit Service b38f0b
		return;
Packit Service b38f0b
	    }
Packit Service b38f0b
	    push @{$aliases{$current_alias}{'definition'}},$stmt;
Packit Service b38f0b
	    return;
Packit Service b38f0b
	}
Packit Service b38f0b
	$stmt =~ s/^alias\s+//;
Packit Service b38f0b
	if ($args eq "") {
Packit Service b38f0b
	    foreach $i (sort keys(%aliases)) {
Packit Service b38f0b
		display_alias($i);
Packit Service b38f0b
	    }
Packit Service b38f0b
	    return;
Packit Service b38f0b
	}
Packit Service b38f0b
	($name, $args) = ($stmt =~ /^(\w+)\s*(.*)$/);
Packit Service b38f0b
	if ($args eq "") {
Packit Service b38f0b
	    display_alias($name);
Packit Service b38f0b
	    return;
Packit Service b38f0b
	}
Packit Service b38f0b
#	print "alias: $name $args\n";
Packit Service b38f0b
	if ($args eq "{") {
Packit Service b38f0b
	    $oprompt = $prompt;
Packit Service b38f0b
	    $prompt = "define $name> ";
Packit Service b38f0b
	    $current_alias = $name;
Packit Service b38f0b
	    $multi_alias = 1;
Packit Service b38f0b
	    $aliases{$name}{'definition'} = [];
Packit Service b38f0b
	    return;
Packit Service b38f0b
	}
Packit Service b38f0b
	$aliases{$name}{'definition'} = $args;
Packit Service b38f0b
	return;
Packit Service b38f0b
    }
Packit Service b38f0b
Packit Service b38f0b
    #eval
Packit Service b38f0b
    if ($name eq "eval") {
Packit Service b38f0b
	eval $args;
Packit Service b38f0b
	return;
Packit Service b38f0b
    }
Packit Service b38f0b
Packit Service b38f0b
    #eval just vars
Packit Service b38f0b
    if ($name eq "evalvars") {
Packit Service b38f0b
#	print "args1:",$args,"\n";
Packit Service b38f0b
	$args =~ s/\$(\w+)/$$1/eg;
Packit Service b38f0b
#	print "args2:",$args,"\n";
Packit Service b38f0b
	netsh($args);
Packit Service b38f0b
	return;
Packit Service b38f0b
    }
Packit Service b38f0b
Packit Service b38f0b
    #eval aliases
Packit Service b38f0b
    while (exists $aliases{$name}) {
Packit Service b38f0b
#	print "modified: $stmt -> ";
Packit Service b38f0b
	my @ARGS = split(/\s+/,$args);
Packit Service b38f0b
	my $statements;
Packit Service b38f0b
	if (ref($aliases{$name}{'definition'}) eq "ARRAY") {
Packit Service b38f0b
	    $statements = $aliases{$name}{'definition'};
Packit Service b38f0b
Packit Service b38f0b
	    # maybe prompt for values
Packit Service b38f0b
	    if ($#{$aliases{$name}{'prompts'}} > -1) {
Packit Service b38f0b
		my $i;
Packit Service b38f0b
		for($i = 1; $i <= $#{$aliases{$name}{'prompts'}}; $i++) {
Packit Service b38f0b
		    if (!$ARGS[$i-1] && $term) {
Packit Service b38f0b
			$ARGS[$i-1] = 
Packit Service b38f0b
			    $term->readline($aliases{$name}{'prompts'}[$i]);
Packit Service b38f0b
		    }
Packit Service b38f0b
		}
Packit Service b38f0b
	    }
Packit Service b38f0b
	} else {
Packit Service b38f0b
	    $statements = [$aliases{$name}{'definition'}];
Packit Service b38f0b
	}
Packit Service b38f0b
	foreach my $stmt (@$statements) {
Packit Service b38f0b
	    #print "$stmt -> ";
Packit Service b38f0b
	    $stmt =~ s/\\(\d+)/$ARGS[$1-1]/g;
Packit Service b38f0b
#	    print "running $stmt\n";
Packit Service b38f0b
	    ($name, $args) = ($stmt =~ /^(\w+)\s*(.*)$/);
Packit Service b38f0b
	    netsh($stmt);
Packit Service b38f0b
	}
Packit Service b38f0b
	return;
Packit Service b38f0b
    }
Packit Service b38f0b
Packit Service b38f0b
    if ($stmt =~ /^rehash$/) {
Packit Service b38f0b
	load_rcs();
Packit Service b38f0b
	return;
Packit Service b38f0b
    }
Packit Service b38f0b
Packit Service b38f0b
    my $subfn;
Packit Service b38f0b
Packit Service b38f0b
    if ($stmt =~ /^eval (.*)/) {
Packit Service b38f0b
	eval $1;
Packit Service b38f0b
    }
Packit Service b38f0b
Packit Service b38f0b
    if ($stmt =~ s/^printf\s+(\".*\")\s*(.*)/$2/) {
Packit Service b38f0b
	if ($2 eq "") {
Packit Service b38f0b
	    print eval $1;
Packit Service b38f0b
	    return;
Packit Service b38f0b
	}
Packit Service b38f0b
	$subfn = \&my_printf;
Packit Service b38f0b
	$stmt = $2;
Packit Service b38f0b
	$printfmt = $1;
Packit Service b38f0b
    }
Packit Service b38f0b
Packit Service b38f0b
    # special show columns statement
Packit Service b38f0b
    if ($stmt =~ /^show columns from (\w+)$/) {
Packit Service b38f0b
	my $mibnode = $SNMP::MIB{$1};
Packit Service b38f0b
	my $entrynode = $mibnode->{children}[0];
Packit Service b38f0b
	if (!defined($mibnode) || !defined($entrynode)) {
Packit Service b38f0b
	    print STDERR "no such table: $1\n";
Packit Service b38f0b
	    return;
Packit Service b38f0b
	}
Packit Service b38f0b
	if ($opts{'t'}) {
Packit Service b38f0b
	    map { print $_->{label},"\n"; } sort { $a->{subID} <=> $b->{subID}} @{$entrynode->{children}};
Packit Service b38f0b
	} else {
Packit Service b38f0b
	    $table = Text::FormatTable->new('|r|');
Packit Service b38f0b
	    $table->rule('-');
Packit Service b38f0b
	    $table->head('Column');
Packit Service b38f0b
	    $table->rule('-');
Packit Service b38f0b
	    map { $table->row($_->{label}); } sort { $a->{subID} <=> $b->{subID}} @{$entrynode->{children}};
Packit Service b38f0b
	    $table->rule('-');
Packit Service b38f0b
	    print $table->render();
Packit Service b38f0b
	}
Packit Service b38f0b
	return;
Packit Service b38f0b
    }
Packit Service b38f0b
Packit Service b38f0b
    if ($stmt =~ /^source\s+(.*)/) {
Packit Service b38f0b
	source_file($1);
Packit Service b38f0b
	return;
Packit Service b38f0b
    }
Packit Service b38f0b
Packit Service b38f0b
    if ($stmt =~ s/^export\s+(\S+)\s+(.*)/$2/) {
Packit Service b38f0b
	$insh = undef;
Packit Service b38f0b
	unlink($1);
Packit Service b38f0b
	$exporth = DBI->connect('dbi:AnyData:');
Packit Service b38f0b
	$exporth->func('exporttable','CSV',$1,'ad_catalog');
Packit Service b38f0b
	$subfn = \&my_export;
Packit Service b38f0b
    }
Packit Service b38f0b
Packit Service b38f0b
    if ($stmt =~ /^import\s+(\S+)/) {
Packit Service b38f0b
	my $exporth = DBI->connect('dbi:AnyData:');
Packit Service b38f0b
	$exporth->func('exporttable','CSV',$1,'ad_catalog');
Packit Service b38f0b
	my $selh = $exporth->prepare("select * from exporttable");
Packit Service b38f0b
	$selh->execute();
Packit Service b38f0b
	$old_data = [];
Packit Service b38f0b
	while(my $row = $selh->fetchrow_arrayref) {
Packit Service b38f0b
	    push @$old_data, @$row;
Packit Service b38f0b
	}
Packit Service b38f0b
	$selh->finish();
Packit Service b38f0b
	$exporth->disconnect();
Packit Service b38f0b
	return;
Packit Service b38f0b
    }
Packit Service b38f0b
    
Packit Service b38f0b
    if ($stmt =~ /^diff\s+(.*)/) {
Packit Service b38f0b
	$running_watch = 2;
Packit Service b38f0b
	netsh($1);
Packit Service b38f0b
	$running_watch = 0;
Packit Service b38f0b
	return;
Packit Service b38f0b
    }
Packit Service b38f0b
Packit Service b38f0b
    if ($stmt =~ /^watch\s+(.*)/) {
Packit Service b38f0b
	$running_watch = 1;
Packit Service b38f0b
	my $cmd = $1;
Packit Service b38f0b
	my $delay = 1;
Packit Service b38f0b
	my $clear = `clear`;
Packit Service b38f0b
	if ($cmd =~ s/^(\d+)\s+(.*)/$2/) {
Packit Service b38f0b
	    $delay = $1;
Packit Service b38f0b
	    $cmd = $2;
Packit Service b38f0b
	}
Packit Service b38f0b
	$SIG{'TERM'} = sub { $running_watch = 0; };
Packit Service b38f0b
	$SIG{'INT'} = sub { $running_watch = 0; };
Packit Service b38f0b
	while($running_watch) {
Packit Service b38f0b
	    print $clear;
Packit Service b38f0b
	    netsh($cmd);
Packit Service b38f0b
	    sleep($delay);
Packit Service b38f0b
	}
Packit Service b38f0b
	$SIG{'TERM'} = \&exit;
Packit Service b38f0b
	$SIG{'INT'} = \&exit;
Packit Service b38f0b
	return;
Packit Service b38f0b
    }
Packit Service b38f0b
Packit Service b38f0b
    # we have an SQL statement.  process it.
Packit Service b38f0b
    if ($stmt =~ /^(select|insert|update|delete)/) {
Packit Service b38f0b
	$sth = $dbh->prepare($stmt);
Packit Service b38f0b
	$sth->execute();
Packit Service b38f0b
	if ($stmt =~ /^select/) {
Packit Service b38f0b
	    my $table;
Packit Service b38f0b
	    my $older_data = $old_data;
Packit Service b38f0b
	    if ($running_watch == 1) {
Packit Service b38f0b
		$old_data = [];
Packit Service b38f0b
	    }
Packit Service b38f0b
	    my $oldcount = 0;
Packit Service b38f0b
	    while($row = $sth->fetchrow_arrayref) {
Packit Service b38f0b
		
Packit Service b38f0b
		if ($running_watch) {
Packit Service b38f0b
		    $newrow=[];
Packit Service b38f0b
		    my $count;
Packit Service b38f0b
		    for($count = 0; $count <= $#$row; $count++) {
Packit Service b38f0b
			if ($older_data &&
Packit Service b38f0b
			    $row->[$count] ne
Packit Service b38f0b
			    $older_data->[$oldcount][$count]) {
Packit Service b38f0b
			    if ($ansicolor) {
Packit Service b38f0b
				push @$newrow, new color_string($row->[$count],'red');
Packit Service b38f0b
			    } else {
Packit Service b38f0b
				push @$newrow,"$begin$row->[$count]$end";
Packit Service b38f0b
			    }
Packit Service b38f0b
			} else {
Packit Service b38f0b
			    push @$newrow,$row->[$count];
Packit Service b38f0b
			}
Packit Service b38f0b
			if ($running_watch == 1) {
Packit Service b38f0b
			    $old_data->[$oldcount][$count] = $row->[$count];
Packit Service b38f0b
			}
Packit Service b38f0b
		    }
Packit Service b38f0b
		    $oldcount++;
Packit Service b38f0b
		    $row = $newrow;
Packit Service b38f0b
 		}
Packit Service b38f0b
Packit Service b38f0b
		# self printing;
Packit Service b38f0b
		if (ref($subfn) eq "CODE") {
Packit Service b38f0b
		    &$subfn($printfmt,@$row);
Packit Service b38f0b
		    next;
Packit Service b38f0b
		}
Packit Service b38f0b
Packit Service b38f0b
		if ($opts{'t'}) {
Packit Service b38f0b
		    if ($opts{'d'} eq 'xml') {
Packit Service b38f0b
			print "  <row>\n";
Packit Service b38f0b
			for(my $xx = 0; $xx < $#{$sth->{NAME}}; $xx++) {
Packit Service b38f0b
			    print "    <$sth->{NAME}[$xx]>$row->[$xx]</$sth->{NAME}[$xx]>\n";
Packit Service b38f0b
			}
Packit Service b38f0b
			print "  </row>\n";
Packit Service b38f0b
		    } elsif ($opts{'d'} eq 'xmlshort') {
Packit Service b38f0b
			print "  
Packit Service b38f0b
			for(my $xx = 0; $xx < $#{$sth->{NAME}}; $xx++) {
Packit Service b38f0b
			    print " $sth->{NAME}[$xx]=\"$row->[$xx]\"";
Packit Service b38f0b
			}
Packit Service b38f0b
			print "/>\n";
Packit Service b38f0b
		    } else {
Packit Service b38f0b
			print join($opts{'d'},@$row),"\n";
Packit Service b38f0b
		    }
Packit Service b38f0b
		} elsif (!$table) {
Packit Service b38f0b
		    $table = Text::FormatTable->new('|r' x ($#$row+1) . "|");
Packit Service b38f0b
		    $table->rule('-');
Packit Service b38f0b
		    $table->head(@{$sth->{NAME}});
Packit Service b38f0b
		    $table->rule('-');
Packit Service b38f0b
		    $table->row(@$row);
Packit Service b38f0b
		} else {
Packit Service b38f0b
		    $table->row(@$row);
Packit Service b38f0b
		}
Packit Service b38f0b
	    }
Packit Service b38f0b
	    if ($table) {
Packit Service b38f0b
		$table->rule('-');
Packit Service b38f0b
		print $table->render();
Packit Service b38f0b
	    }
Packit Service b38f0b
	}
Packit Service b38f0b
	$sth->finish();
Packit Service b38f0b
	return;
Packit Service b38f0b
    }
Packit Service b38f0b
Packit Service b38f0b
    # retrieve just one variable and display it
Packit Service b38f0b
    if ($stmt =~ /^(get|)\s*([^\s]+)\s*[^=]/) {
Packit Service b38f0b
	my $sess = make_session();
Packit Service b38f0b
	if ($sess) {
Packit Service b38f0b
	    my @results = split(/[,\s]+/,$stmt);
Packit Service b38f0b
	    my $resultsv = new SNMP::VarList();
Packit Service b38f0b
	    # expression stolen from the main perl SNMP module
Packit Service b38f0b
	    map {  my ($tag, $iid) = 
Packit Service b38f0b
		       (/^((?:\.\d+)+|(?:\w+(?:\-*\w+)+))\.?(.*)$/);
Packit Service b38f0b
		   push @$resultsv, [$tag, $iid] } @results;
Packit Service b38f0b
	    $sess->get($resultsv)  || 
Packit Service b38f0b
		print STDERR "Error: $sess->{ErrorNum} $sess->{ErrString}\n";
Packit Service b38f0b
  	    @results = ();
Packit Service b38f0b
	    map { push @results, $_->[2] } @$resultsv;
Packit Service b38f0b
	    if (ref($subfn) eq "CODE") {
Packit Service b38f0b
		&$subfn($printfmt,@results);
Packit Service b38f0b
	    } else {
Packit Service b38f0b
		print join(" ", @results),"\n";
Packit Service b38f0b
	    }
Packit Service b38f0b
	} else {
Packit Service b38f0b
	    print STDERR "could not establish a SNMP session to $host\n";
Packit Service b38f0b
	}
Packit Service b38f0b
	return;
Packit Service b38f0b
    }
Packit Service b38f0b
Packit Service b38f0b
    # set something
Packit Service b38f0b
    if ($stmt =~ /^(set|)\s*([^\s]+)\s=\s(.*)$/) {
Packit Service b38f0b
	my $sess = make_session();
Packit Service b38f0b
	if ($sess) {
Packit Service b38f0b
	    $sess->set([$2,undef,$1]) || 
Packit Service b38f0b
		print STDERR "opps: $sess->{ErrorNum} $sess->{ErrString}\n";
Packit Service b38f0b
	} else {
Packit Service b38f0b
	    print STDERR "could not establish a SNMP session to $host\n";
Packit Service b38f0b
	}
Packit Service b38f0b
	return;
Packit Service b38f0b
    }
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
sub auto_snmp {
Packit Service b38f0b
    my $node = $SNMP::MIB{$_[0]};
Packit Service b38f0b
#    print STDERR "netsh::fetch_snmp $_[0] $node->{label}\n";
Packit Service b38f0b
    my $indexes = $node->{parent}{indexes};
Packit Service b38f0b
    if ($#$indexes > -1) {
Packit Service b38f0b
#	print STDERR "column\n";
Packit Service b38f0b
	# table 
Packit Service b38f0b
    } else {
Packit Service b38f0b
	# scalar
Packit Service b38f0b
	if (exists($_[1])) {
Packit Service b38f0b
	    my $sess = make_session();
Packit Service b38f0b
	    my $val = $sess->set([$_[0],0,$_[1]]) || return;
Packit Service b38f0b
#	    print STDERR "scalar set: $val\n";
Packit Service b38f0b
	    return $val;
Packit Service b38f0b
	} else {
Packit Service b38f0b
	    my $sess = make_session();
Packit Service b38f0b
	    my $val = $sess->get([$_[0],0]);
Packit Service b38f0b
#	    print STDERR "scalar get: $val\n";
Packit Service b38f0b
	    return $val;
Packit Service b38f0b
	}
Packit Service b38f0b
    }
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
sub AUTOLOAD {
Packit Service b38f0b
    my $nodename = $AUTOLOAD;
Packit Service b38f0b
    $nodename =~ s/.*:://;
Packit Service b38f0b
    print STDERR "netsh::AUTOLOAD $AUTOLOAD $nodename\n";
Packit Service b38f0b
    if ($SNMP::MIB{$nodename}) {
Packit Service b38f0b
	eval << "END";
Packit Service b38f0b
        sub $AUTOLOAD {
Packit Service b38f0b
	    auto_snmp($nodename, \@_);
Packit Service b38f0b
	}
Packit Service b38f0b
END
Packit Service b38f0b
	goto &$AUTOLOAD;
Packit Service b38f0b
    }
Packit Service b38f0b
    print STDERR join(",",@_),"\n";
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
sub my_printf {
Packit Service b38f0b
    # drop quotes
Packit Service b38f0b
    my $fmt = shift;
Packit Service b38f0b
    $fmt = eval $fmt;
Packit Service b38f0b
    map { if (ref($_) eq "color_string") { $_->colorize_next(); } } @_;
Packit Service b38f0b
    printf($fmt, @_);
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
sub display_alias {
Packit Service b38f0b
    my $name = shift;
Packit Service b38f0b
    if (exists $aliases{$name}{'definition'}) {
Packit Service b38f0b
	if (ref($aliases{$name}{'definition'}) eq "ARRAY") {
Packit Service b38f0b
	    print "alias $name {\n";
Packit Service b38f0b
	    map { print "  $_\n"; } @{$aliases{$name}{'definition'}};
Packit Service b38f0b
	    print "}\n";
Packit Service b38f0b
	} else {
Packit Service b38f0b
	    print "alias $name $aliases{$name}{'definition'}\n";
Packit Service b38f0b
	}
Packit Service b38f0b
    } else {
Packit Service b38f0b
	print "no alias defined for \"$name\"\n";
Packit Service b38f0b
    }
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
sub make_session {
Packit Service b38f0b
    if (!$sess) {
Packit Service b38f0b
	$sess = new SNMP::Session(@sessparms);
Packit Service b38f0b
    }
Packit Service b38f0b
    return $sess;
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
Packit Service b38f0b
sub usage {
Packit Service b38f0b
    print STDERR "
Packit Service b38f0b
$0 [ARGUMENTS] HOSTNAME [SQL_COMMAND] 
Packit Service b38f0b
Packit Service b38f0b
  $0 implements a simple SQL shell which maps onto SNMP.  All
Packit Service b38f0b
  statements issued within the shell are converted to SNMP requests and
Packit Service b38f0b
  sent to HOSTNAME and the results displayed in a nice table output
Packit Service b38f0b
  format if the Text::FormatTable module is available.  If SQL_COMMAND
Packit Service b38f0b
  is given on the command line, then it's interpreted and control is
Packit Service b38f0b
  returned to the caller.  If not, an interactive prompt is given where
Packit Service b38f0b
  multiple commands can be issued.
Packit Service b38f0b
Packit Service b38f0b
ARGUMENTS may include:
Packit Service b38f0b
Packit Service b38f0b
  -t         delimiter separated output, don't print pretty tables.
Packit Service b38f0b
  -d DELIM   use DELIM as the delimiter.  A tab is the default delimiter.
Packit Service b38f0b
             'xml' is a special delimiter to produce xml output.
Packit Service b38f0b
Packit Service b38f0b
ARGUMENTS also may include the following.  See the net-snmp snmpcmd
Packit Service b38f0b
manual page for details on what they mean:
Packit Service b38f0b
Packit Service b38f0b
  -v VERSION        (default: 1)
Packit Service b38f0b
  -t TIMEOUT
Packit Service b38f0b
  -r RETRIES
Packit Service b38f0b
  -p PORT
Packit Service b38f0b
  -c COMMUNITY
Packit Service b38f0b
  -a AUTHPROTOCOL   (default: MD5)
Packit Service b38f0b
  -x PRIVPROTOCOL   (default: DES)
Packit Service b38f0b
  -A AUTHPASS
Packit Service b38f0b
  -X PRIVPASS
Packit Service b38f0b
  -l SECURITY_LEVEL (default: authNoPriv)
Packit Service b38f0b
  
Packit Service b38f0b
";
Packit Service b38f0b
    exit;
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
__END__
Packit Service b38f0b
Packit Service b38f0b
=head1 NAME
Packit Service b38f0b
Packit Service b38f0b
netsh - A shell environment for interacting with networking devices
Packit Service b38f0b
Packit Service b38f0b
=head1 SYNOPSIS
Packit Service b38f0b
Packit Service b38f0b
netsh [(subset of) snmpcmd arguments] hostname[,hostname...] [command]
Packit Service b38f0b
Packit Service b38f0b
=head1 OPTIONAL PERL MODULES
Packit Service b38f0b
Packit Service b38f0b
There are some optional perl modules which make using the shell nicer
Packit Service b38f0b
in general.  These modules are:
Packit Service b38f0b
Packit Service b38f0b
  Text::FormatTable
Packit Service b38f0b
  Term::ReadLine::Gnu or Term::ReadLine::Perl
Packit Service b38f0b
  Term::ANSIColor
Packit Service b38f0b
Packit Service b38f0b
You can install these by running [as root]:
Packit Service b38f0b
Packit Service b38f0b
  perl -MCPAN -e shell
Packit Service b38f0b
  cpan> install Text::FormatTable
Packit Service b38f0b
  ...
Packit Service b38f0b
Packit Service b38f0b
It is B<strongly> recommend you at least install the Text::FormatTable
Packit Service b38f0b
module, and if you like command line editing one of the two extra
Packit Service b38f0b
Term::ReadLine modules (Gnu being the better of the two).
Packit Service b38f0b
Packit Service b38f0b
=head1 DESCRIPTION
Packit Service b38f0b
Packit Service b38f0b
The netsh script provides an interactive, console-like environment
Packit Service b38f0b
suitable for monitoring and manipulating data within networking
Packit Service b38f0b
devices.  The environment is highly extensible through command
Packit Service b38f0b
aliases and easy-to-use SQL-like queries.
Packit Service b38f0b
Packit Service b38f0b
It is implemented on top of the SNMP protocol using the net-snmp
Packit Service b38f0b
package and perl.  See the snmpcmd and snmp.conf manual pages for
Packit Service b38f0b
details on configuring net-snmp for authentication information for
Packit Service b38f0b
the networking devices you wish to access.
Packit Service b38f0b
Packit Service b38f0b
=head1 ABOUT THE EXAMLPES IN THIS DOCUMENT
Packit Service b38f0b
Packit Service b38f0b
All the examples in this document are exact cut-n-pastes from the
Packit Service b38f0b
inside of the netsh shell.  This includes the "netsh> " prompt and
Packit Service b38f0b
possibly other prompts as well.
Packit Service b38f0b
Packit Service b38f0b
=head1 COMMANDS
Packit Service b38f0b
Packit Service b38f0b
The following is a list of the basic core commands supported by
Packit Service b38f0b
netsh.  Many default aliases are also supplied, some of which are
Packit Service b38f0b
listed in the next section.  At the command prompt type "alias" for
Packit Service b38f0b
a full list of all the aliases and their definitions.
Packit Service b38f0b
Packit Service b38f0b
=over
Packit Service b38f0b
Packit Service b38f0b
=item show columns from TABLE
Packit Service b38f0b
Packit Service b38f0b
=item select ... 
Packit Service b38f0b
Packit Service b38f0b
=item update ...
Packit Service b38f0b
Packit Service b38f0b
=item insert ...
Packit Service b38f0b
Packit Service b38f0b
=item delete ...
Packit Service b38f0b
Packit Service b38f0b
netsh supports the standard sql-like language queries of snmp tables.
Packit Service b38f0b
These are implemented via the SQL::Statement parser, so any form of
Packit Service b38f0b
expression it accepts netsh will accept as well.
Packit Service b38f0b
Packit Service b38f0b
Examples:
Packit Service b38f0b
Packit Service b38f0b
  netsh> show columns from ifTable
Packit Service b38f0b
  +-----------------+
Packit Service b38f0b
  |           Column|
Packit Service b38f0b
  +-----------------+
Packit Service b38f0b
  |          ifIndex|
Packit Service b38f0b
  ...
Packit Service b38f0b
  netsh> select * from ifTable
Packit Service b38f0b
  ... [output not shown]
Packit Service b38f0b
  netsh> select tcpConnState, tcpConnRemotelAddress from tcpConnTable where tcpConnState = established
Packit Service b38f0b
  ... [output not shown]
Packit Service b38f0b
  netsh> update ifTable set ifAdminStatus = up where ifOperStatus = down
Packit Service b38f0b
  ... [output not shown]
Packit Service b38f0b
Packit Service b38f0b
=item SNMPOBJECT
Packit Service b38f0b
Packit Service b38f0b
Simple lists of objects may be given which will directly request or
Packit Service b38f0b
operate on those objects.  See printf below for controlling the
Packit Service b38f0b
formatting of results
Packit Service b38f0b
Packit Service b38f0b
Examples:
Packit Service b38f0b
Packit Service b38f0b
  netsh> sysContact.0, sysLocation.0
Packit Service b38f0b
  hardaker@somewhere.net my location
Packit Service b38f0b
  netsh> sysContact.0 = my new contact information
Packit Service b38f0b
Packit Service b38f0b
=item alias my_command some other command
Packit Service b38f0b
Packit Service b38f0b
or
Packit Service b38f0b
Packit Service b38f0b
=back
Packit Service b38f0b
Packit Service b38f0b
alias my_many_commands {
Packit Service b38f0b
  command1
Packit Service b38f0b
  command2
Packit Service b38f0b
  prompt NUMBER question
Packit Service b38f0b
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
=over
Packit Service b38f0b
Packit Service b38f0b
=item
Packit Service b38f0b
Packit Service b38f0b
You can create aliases of your frequently used commands by aliasing
Packit Service b38f0b
them to an easy to remember name.  \N parameters in the defined
Packit Service b38f0b
command will be replaced by the positional argument of options passed
Packit Service b38f0b
to the alias name.
Packit Service b38f0b
Packit Service b38f0b
For multi-line defined aliases, optional prompts may be given to
Packit Service b38f0b
request information from the user when the NUMBERth argument is not
Packit Service b38f0b
given to the alias.  If it is not given, the prompt will be printed
Packit Service b38f0b
and the user will be asked to input a value for it.  This allows the
Packit Service b38f0b
easy definition of interactive commands.  The value will be inserted
Packit Service b38f0b
in alias parts containing \N substitution requests.
Packit Service b38f0b
Packit Service b38f0b
  netsh> alias interfaces select ifDescr from ifTable
Packit Service b38f0b
  netsh> interfaces
Packit Service b38f0b
  +-------+
Packit Service b38f0b
  |ifDescr|
Packit Service b38f0b
  +-------+
Packit Service b38f0b
  |     lo|
Packit Service b38f0b
  |   eth0|
Packit Service b38f0b
  +-------+
Packit Service b38f0b
  netsh> alias interface select ifDescr, ifSpeed from ifTable where ifDescr = '\1'
Packit Service b38f0b
  netsh> interface eth0
Packit Service b38f0b
  +-------+--------+
Packit Service b38f0b
  |ifDescr| ifSpeed|
Packit Service b38f0b
  +-------+--------+
Packit Service b38f0b
  |   eth0|10000000|
Packit Service b38f0b
  +-------+--------+
Packit Service b38f0b
Packit Service b38f0b
=item printf FORMATSTRING COMMAND
Packit Service b38f0b
Packit Service b38f0b
Allows B<careful> formatting of results returned by the commands.
Packit Service b38f0b
Packit Service b38f0b
Example:
Packit Service b38f0b
Packit Service b38f0b
  netsh> alias interface {
Packit Service b38f0b
  define interface> printf "interface %s is running at %d Mb/s\n" select ifDescr, ifSpeed from ifTable where ifDescr = '\1'
Packit Service b38f0b
  define interface> prompt 1 Enter the interface to describe:
Packit Service b38f0b
  define interface> }
Packit Service b38f0b
  netsh> interface
Packit Service b38f0b
  Enter the interface to describe: eth0
Packit Service b38f0b
  interface eth0 is running at 10000000 Mb/s
Packit Service b38f0b
Packit Service b38f0b
To list the definition of an already defined command, simply exclude
Packit Service b38f0b
the definition and netsh will report the definition to you:
Packit Service b38f0b
Packit Service b38f0b
  netsh> alias interface
Packit Service b38f0b
  alias interface {
Packit Service b38f0b
    printf "interface %s is running at %d Mb/s\n" select ifDescr, ifSpeed from ifTable where ifDescr = '\1'
Packit Service b38f0b
    prompt 1 Enter the interface to describe:
Packit Service b38f0b
  }
Packit Service b38f0b
Packit Service b38f0b
To list all the aliases defined in the system, just type "alias" by itself.
Packit Service b38f0b
Packit Service b38f0b
=item watch [TIME] COMMAND
Packit Service b38f0b
Packit Service b38f0b
Continually watches the results of the COMMAND being run, which is run
Packit Service b38f0b
every TIME seconds.  For select statements, it will attempt to mark
Packit Service b38f0b
the changing values from one screen to the next by surrounding them
Packit Service b38f0b
with "*"s or color (assuming you have the Term::ANSIColor perl module
Packit Service b38f0b
installed) for easy picking out on the screen.
Packit Service b38f0b
Packit Service b38f0b
=item rehash
Packit Service b38f0b
Packit Service b38f0b
Re-load the alias definitions files in the common directory, as
Packit Service b38f0b
well as those files found in $HOME/.snmp/netsh.
Packit Service b38f0b
Packit Service b38f0b
=item source FILE
Packit Service b38f0b
Packit Service b38f0b
loads definitons and commands from FILE into the running environment.
Packit Service b38f0b
Packit Service b38f0b
=back
Packit Service b38f0b
Packit Service b38f0b
=head1 FILES
Packit Service b38f0b
Packit Service b38f0b
By default, netsh will source all the definition files it can find.
Packit Service b38f0b
It does this by first reading everything in
Packit Service b38f0b
/usr/local/share/snmp/netsh/* and then reading everything in
Packit Service b38f0b
$HOME/.snmp/netsh/*.  Everything contained in these files are
Packit Service b38f0b
commands, but most frequently they entirely consist of aliases
Packit Service b38f0b
definitions.
Packit Service b38f0b
Packit Service b38f0b
=head1 AUTHOR
Packit Service b38f0b
Packit Service b38f0b
bugs, comments, questions to net-snmp-users@lists.sourceforge.net
Packit Service b38f0b
Packit Service b38f0b
=head1 Copyright
Packit Service b38f0b
Packit Service b38f0b
     Copyright (c) 2002 Networks Associates Technology, Inc. All
Packit Service b38f0b
     rights reserved.  This program is free software; you can
Packit Service b38f0b
     redistribute it and/or modify it under the same terms as Perl
Packit Service b38f0b
     itself.
Packit Service b38f0b
Packit Service b38f0b
=cut