1#!/usr/local/bin/perl 2## 3## @PACKAGE@ @VERSION@ 4@copyright@ 5# 6# RANCID - Really Awesome New Cisco confIg Differ 7# 8# rancid - generalized rancid module; command schedule is derived from the 9# rancid.types.{base,conf} configurations. 10# 11# usage: rancid [-dhltCV] -t device_type [-f filename | hostname] 12# 13use 5.010; 14use strict 'vars'; 15use warnings; 16no warnings 'uninitialized'; 17use Exporter; 18use Getopt::Std; 19our($opt_d, $opt_f, $opt_h, $opt_l, $opt_t, $opt_C, $opt_V); 20getopts('dfhlt:CV'); 21BEGIN { 22 push(@INC, "@pkglibdir@"); 23} 24use rancid; 25our @ISA = qw(Exporter rancid); 26 27sub usage() 28{ 29 print STDERR "rancid [-dhlCV] -t device_type [-f filename | hostname]\n"; 30 exit 64; 31} 32 33if ($opt_h) { 34 usage(); 35} 36 37# basic initialization 38rancidinit(); 39 40# load device type spec, build @commandtable and load modules 41if (loadtype($devtype)) { 42 die "Couldn't load device type spec for $rancid::devtype\n"; 43} 44if (! defined($lscript)) { 45 die "login script not defined for device type $rancid::devtype\n"; 46} 47# if the first word of $script is not us (this script), exec the given 48# script. 49my(@script) = split(/\s+/, $script); 50if (which($script[0]) ne which($0)) { 51 # -[hCV] are not handled; they will have already been handled earlier. 52 push(@script, "-d") if $opt_d; 53 push(@script, "-l") if $opt_l; 54 push(@script, "-f") if $opt_f; 55 push(@script, $host); 56 if ($debug) { 57 print(STDERR "device script ($script[0]) does not appear to be me ($0)". 58 ": exec(". join(" ", @script) .")\n"); 59 } 60 # there is no way to prevent an error msg from exec such that the die error 61 # is the only one displayed, without also leaving the child without a 62 # working STDERR. 63 exec(join(" ", @script)) || die "exec($script[0]) failed: $!\n"; 64} 65 66# check that inloop, the input/main loop, is defined 67if (!defined($inloop) || length($inloop) < 1) { 68 die "inloop is not configured for device type $devtype"; 69} 70 71# open the temporary file for the digested output 72open(OUTPUT,">$host.new") || die "Can't open $host.new for writing: $!\n"; 73select(OUTPUT); 74if (length($#modules)) { 75 my($module); 76 77 foreach $module (@modules) { 78 (my $file = $module) =~ s/::/\//g; 79 my($err) = 0; 80 81 # call module->init(); we expect 0 as success, as god intended it 82 eval "\$err = ". $module ."::init();"; 83 if ($@) { 84 printf(STDERR "loadtype: initializing $module failed: %s\n", $@); 85 exit 1; 86 } elsif ($err) { 87 printf(STDERR "loadtype: %s::init() returned failure\n", $module); 88 exit 1; 89 } 90 } 91} 92 93# open the input; a pre-collected file or start a login for a login stream or 94# temporary file 95if ($file) { 96 print(STDERR "opening file $host\n") if ($debug || $log); 97 open(INPUT,"<$host") || die "open failed for $host: $!\n"; 98} else { 99 my $cstr = $commandstr; 100 $cstr =~ s/\"/\\\"/g; 101 print(STDERR "executing $lscript -t $timeo -c\"$cstr\" $host\n") if ($debug || $log); 102 system "$lscript -t $timeo -c \"$cstr\" $host </dev/null > $host.raw 2>&1" || die "clogin failed for $host: $!\n"; 103 open(INPUT, "< $host.raw") || die "clogin failed for $host: $!\n"; 104} 105 106# loop over the input using the provided input/main loop 107eval($inloop ."(*INPUT, *OUTPUT);") && die "${inloop} failed: $@\n"; 108 109print STDOUT "Done $lscript: $_\n" if ($log); 110# Flush History 111ProcessHistory("","","",""); 112# Cleanup 113close(INPUT); 114close(OUTPUT); 115 116unlink("$host.raw") if (! $debug); 117 118# check for completeness 119if (scalar(%commands) || !$clean_run || !$found_end) { 120 if (scalar(keys %commands) eq $commandcnt) { 121 printf(STDERR "$host: missed cmd(s): all commands\n"); 122 } elsif (scalar(%commands)) { 123 my($count, $i) = 0; 124 for ($i = 0; $i < $#commands; $i++) { 125 if ($commands{$commands[$i]}) { 126 if (!$count) { 127 printf(STDERR "$host: missed cmd(s): %s", $commands[$i]); 128 } else { 129 printf(STDERR ", %s", $commands[$i]); 130 } 131 $count++; 132 } 133 } 134 if ($count) { 135 printf(STDERR "\n"); 136 } 137 } 138 if (!$clean_run || !$found_end) { 139 print(STDERR "$host: End of run not found\n"); 140 if ($debug) { 141 print(STDERR "$host: clean_run is false\n") if (!$clean_run); 142 print(STDERR "$host: found_end is false\n") if (!$found_end); 143 } 144 system("/usr/bin/tail -1 $host.new"); 145 } 146 unlink "$host.new" if (! $debug); 147} 148