From 1651adc35224e149715bd85af4ba108c5ee184bc Mon Sep 17 00:00:00 2001 From: Tar Committer Date: Sun, 19 Nov 2000 22:01:05 +0000 Subject: Imported from rancid-2.0.tar.gz. --- CHANGES | 33 +- Makefile.am | 24 + Makefile.in | 352 +++++++++ README | 102 +-- acinclude.m4 | 1 + aclocal.m4 | 139 ++++ bin/Makefile.in | 37 + bin/cat5rancid | 1043 -------------------------- bin/cat5rancid.in | 1079 +++++++++++++++++++++++++++ bin/clogin | 560 -------------- bin/clogin.in | 587 +++++++++++++++ bin/configure | 1239 ++++++++++++++++++++++++++++++ bin/configure.in | 49 ++ bin/control_rancid | 259 ------- bin/control_rancid.in | 259 +++++++ bin/create_cvs | 89 --- bin/create_cvs.in | 89 +++ bin/do-diffs | 60 -- bin/do-diffs.in | 60 ++ bin/elogin | 449 ----------- bin/elogin.in | 449 +++++++++++ bin/env | 41 - bin/env.in | 42 ++ bin/erancid | 296 -------- bin/erancid.in | 296 ++++++++ bin/flogin | 530 ------------- bin/flogin.in | 530 +++++++++++++ bin/francid | 384 ---------- bin/francid.in | 384 ++++++++++ bin/jlogin | 456 ----------- bin/jlogin.in | 470 ++++++++++++ bin/jrancid | 498 ------------- bin/jrancid.in | 506 +++++++++++++ bin/par | 128 ---- bin/par.in | 128 ++++ bin/rancid | 1048 -------------------------- bin/rancid-fe | 43 -- bin/rancid-fe.in | 43 ++ bin/rancid.in | 1113 +++++++++++++++++++++++++++ bin/rename | 113 --- bin/rename.in | 113 +++ bin/rrancid | 347 --------- bin/rrancid.in | 347 +++++++++ cloginrc.sample | 19 +- configure | 1990 +++++++++++++++++++++++++++++++++++++++++++++++++ configure.in | 121 +++ install-sh | 238 ++++++ missing | 190 +++++ mkinstalldirs | 40 + util/Makefile.in | 30 + util/configure | 885 ++++++++++++++++++++++ util/configure.in | 21 + util/rtrfilter | 145 ---- util/rtrfilter.README | 2 +- util/rtrfilter.in | 145 ++++ 55 files changed, 12099 insertions(+), 6542 deletions(-) create mode 100644 Makefile.am create mode 100644 Makefile.in create mode 100644 acinclude.m4 create mode 100644 aclocal.m4 create mode 100644 bin/Makefile.in delete mode 100755 bin/cat5rancid create mode 100755 bin/cat5rancid.in delete mode 100755 bin/clogin create mode 100755 bin/clogin.in create mode 100755 bin/configure create mode 100644 bin/configure.in delete mode 100755 bin/control_rancid create mode 100755 bin/control_rancid.in delete mode 100755 bin/create_cvs create mode 100755 bin/create_cvs.in delete mode 100755 bin/do-diffs create mode 100755 bin/do-diffs.in delete mode 100755 bin/elogin create mode 100755 bin/elogin.in delete mode 100644 bin/env create mode 100644 bin/env.in delete mode 100755 bin/erancid create mode 100755 bin/erancid.in delete mode 100755 bin/flogin create mode 100755 bin/flogin.in delete mode 100755 bin/francid create mode 100755 bin/francid.in delete mode 100755 bin/jlogin create mode 100755 bin/jlogin.in delete mode 100755 bin/jrancid create mode 100755 bin/jrancid.in delete mode 100755 bin/par create mode 100755 bin/par.in delete mode 100755 bin/rancid delete mode 100755 bin/rancid-fe create mode 100755 bin/rancid-fe.in create mode 100755 bin/rancid.in delete mode 100755 bin/rename create mode 100755 bin/rename.in delete mode 100755 bin/rrancid create mode 100755 bin/rrancid.in create mode 100755 configure create mode 100644 configure.in create mode 100755 install-sh create mode 100755 missing create mode 100755 mkinstalldirs create mode 100644 util/Makefile.in create mode 100755 util/configure create mode 100644 util/configure.in delete mode 100755 util/rtrfilter create mode 100755 util/rtrfilter.in diff --git a/CHANGES b/CHANGES index 677a161..762f07b 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,29 @@ -1.7 +2.0 + Better formatting for cisco catalyst [non-ios] switches. + + Better support the cisco 3500 switches. + + Get some info out of "show version" for the cat5ks. + cat5k "show boot" does variables, not bootflash. + Skip more goo from 'write term' on some cat5ks. + + Collect 'show module' for 6500-ios. + + Revamp *login's use of .cloginrc's method directive. see + cloginrc.sample. + + Add bits for Cisco PIX. Thanks to joe rizzo@EA for access to a PIX. + + Sort usernames on ciscos. + Get more info out of "show diag" on the GSR. + + Add "show chassis sfm detail" for the M160. + + Leave router type in place when telling about changes to + router.db. + + Add autoconf (configure) and makefile bits to automate install + and perl/expect replacement 1.6 Add "dir nvram:" to rancid. @@ -15,9 +40,9 @@ 1.5 sync command-line option between clogin / jlogin. jlogin modified: - -x passphrase -> -r passphrase - -> -x command-file - -e encrypt type -> -y ssh_chyper_type + -x passphrase -> -r passphrase + -> -x command-file + -e encrypt type -> -y ssh_chyper_type add .cloginrc noenable directive to set the cmd-line -noenable option. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..efcd8b0 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,24 @@ +## Process this file with automake to produce Makefile.in + +AUTOMAKE_OPTIONS=foreign no-dependencies + +@SET_MAKE@ + +EXTRA_DIST = CHANGES README Todo cloginrc.sample configure install-sh \ + mkinstalldirs Makefile.in Todo +#DIST_COMMON = + +# '.' is here (and at the beginnging of the macro) so that distclean-recursive +# will run make distclean in . after the other dirs (preserving Makefile.inc) +SUBDIRS = . bin util + +all: + +install-exec-local: + $(mkinstalldirs) $(prefix) $(prefix)/bin $(prefix)/util + +install: + for file in CHANGES README cloginrc.sample ; do \ + $(INSTALL_DATA) $$file $(prefix); \ + done + diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..35ba7ee --- /dev/null +++ b/Makefile.in @@ -0,0 +1,352 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = . + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +AUTOMAKE = @AUTOMAKE@ +COMM = @COMM@ +CVS = @CVS@ +DIFF = @DIFF@ +DIRNAME = @DIRNAME@ +EXPECT_PATH = @EXPECT_PATH@ +INST_PROGS = @INST_PROGS@ +MAINT = @MAINT@ +MAKE = @MAKE@ +MAKEINFO = @MAKEINFO@ +MKDIR = @MKDIR@ +PACKAGE = @PACKAGE@ +PERLV_PATH = @PERLV_PATH@ +RD_BIN_DATAS = @RD_BIN_DATAS@ +RD_BIN_PROGS = @RD_BIN_PROGS@ +RD_UTIL_PROGS = @RD_UTIL_PROGS@ +SENDMAIL = @SENDMAIL@ +SORT = @SORT@ +TAR = @TAR@ +TOUCH = @TOUCH@ +UCBMAIL = @UCBMAIL@ +VERSION = @VERSION@ + +AUTOMAKE_OPTIONS = foreign no-dependencies + +EXTRA_DIST = CHANGES README Todo cloginrc.sample configure install-sh mkinstalldirs Makefile.in Todo + +#DIST_COMMON = + +# '.' is here (and at the beginnging of the macro) so that distclean-recursive +# will run make distclean in . after the other dirs (preserving Makefile.inc) +SUBDIRS = . bin util +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_CLEAN_FILES = +DIST_COMMON = README Makefile.am Makefile.in acinclude.m4 aclocal.m4 \ +configure configure.in install-sh missing mkinstalldirs + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +GZIP_ENV = --best +all: all-redirect +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status + +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ configure.in acinclude.m4 + cd $(srcdir) && $(ACLOCAL) + +config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck +$(srcdir)/configure: @MAINTAINER_MODE_TRUE@$(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) + cd $(srcdir) && $(AUTOCONF) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. + +@SET_MAKE@ + +all-recursive install-data-recursive install-exec-recursive \ +installdirs-recursive install-recursive uninstall-recursive \ +check-recursive installcheck-recursive info-recursive dvi-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \ + rev="$$subdir $$rev"; \ + test "$$subdir" = "." && dot_seen=yes; \ + done; \ + test "$$dot_seen" = "no" && rev=". $$rev"; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + -rm -rf $(distdir) + GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz + mkdir $(distdir)/=build + mkdir $(distdir)/=inst + dc_install_base=`cd $(distdir)/=inst && pwd`; \ + cd $(distdir)/=build \ + && ../configure --srcdir=.. --prefix=$$dc_install_base \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) dist + -rm -rf $(distdir) + @banner="$(distdir).tar.gz is ready for distribution"; \ + dashes=`echo "$$banner" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + echo "$$dashes" +dist: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +dist-all: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +distdir: $(DISTFILES) + -rm -rf $(distdir) + mkdir $(distdir) + -chmod 777 $(distdir) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + for subdir in $(SUBDIRS); do \ + if test "$$subdir" = .; then :; else \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + chmod 777 $(distdir)/$$subdir; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(distdir) distdir=../$(distdir)/$$subdir distdir) \ + || exit 1; \ + fi; \ + done +info-am: +info: info-recursive +dvi-am: +dvi: dvi-recursive +check-am: all-am +check: check-recursive +installcheck-am: +installcheck: installcheck-recursive +install-exec-am: install-exec-local +install-exec: install-exec-recursive + +install-data-am: +install-data: install-data-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-recursive +uninstall-am: +uninstall: uninstall-recursive +all-am: Makefile +all-redirect: all-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: installdirs-recursive +installdirs-am: + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-tags mostlyclean-generic + +mostlyclean: mostlyclean-recursive + +clean-am: clean-tags clean-generic mostlyclean-am + +clean: clean-recursive + +distclean-am: distclean-tags distclean-generic clean-am + +distclean: distclean-recursive + -rm -f config.status + +maintainer-clean-am: maintainer-clean-tags maintainer-clean-generic \ + distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-recursive + -rm -f config.status + +.PHONY: install-data-recursive uninstall-data-recursive \ +install-exec-recursive uninstall-exec-recursive installdirs-recursive \ +uninstalldirs-recursive all-recursive check-recursive \ +installcheck-recursive info-recursive dvi-recursive \ +mostlyclean-recursive distclean-recursive clean-recursive \ +maintainer-clean-recursive tags tags-recursive mostlyclean-tags \ +distclean-tags clean-tags maintainer-clean-tags distdir info-am info \ +dvi-am dvi check check-am installcheck-am installcheck \ +install-exec-local install-exec-am install-exec install-data-am \ +install-data install-am install uninstall-am uninstall all-redirect \ +all-am all installdirs-am installdirs mostlyclean-generic \ +distclean-generic clean-generic maintainer-clean-generic clean \ +mostlyclean distclean maintainer-clean + + +@SET_MAKE@ + +all: + +install-exec-local: + $(mkinstalldirs) $(prefix) $(prefix)/bin $(prefix)/util + +install: + for file in CHANGES README cloginrc.sample ; do \ + $(INSTALL_DATA) $$file $(prefix); \ + done + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/README b/README index 5125ebe..fd1ac82 100644 --- a/README +++ b/README @@ -1,37 +1,45 @@ Rancid is a "Really Awesome New Cisco confIg Differ" developed to maintain CVS controlled copies of router configs. -The following is the packing list for Rancid: +The following is the packing list for Rancid. .in is stripped from +the files below by configure with substitutions completed: README - This file. CHANGES - List of changes to Rancid. Todo - partial Todo list of what needs to be done. -env - Enviromental settings needed. -do-diffs - Script designed to be run from cron calling control_rancid. -control_rancid - Builds router list, calls rancid on each router and +env.in - Enviromental settings needed. +do-diffs.in - Script designed to be run from cron calling control_rancid. +control_rancid.in - Builds router list, calls rancid on each router and handles cvs routines. -rancid-fe - chooses between rancid/francid/jrancid/rrancid/cat5rancid. -rancid - Runs commands on cisco routers and processes the output - the meat. -erancid - Runs commands on ADC EZ-T3 muxes and processes the output. -francid - Runs commands on foundry switches and processes the output. -jrancid - Runs commands on juniper routers and processes the output. -rrancid - Runs commands on redback routers and processes the output. -cat5rancid -Runs commands on cisco cat5 switches and processes the output. -clogin - Expect script that logs into routers either interactively, - runs a set of commands or runs another expect script. -elogin - Expect script that logs into ADC EZ-T3 muxes either interactively, - runs a set of commands or runs another expect script. -flogin - Expect script that logs into foundry switches. once foundry +rancid-fe.in - chooses between rancid/[efjr]rancid/cat5rancid. +rancid.in - Runs commands on cisco routers and processes the output - the meat. +erancid.in - Runs commands on ADC EZ-T3 muxes and processes the output. +francid.in - Runs commands on foundry switches and processes the output. +jrancid.in - Runs commands on juniper routers and processes the output. +rrancid.in - Runs commands on redback routers and processes the output. +cat5rancid.in -Runs commands on cisco cat5 switches and processes the output. +clogin.in - Expect script that logs into routers either interactively, + runs a set of commands, or runs another expect script. +elogin.in - Expect script that logs into ADC EZ-T3 muxes either interactively, + runs a set of commands, or runs another expect script. +flogin.in - Expect script that logs into foundry switches. Once foundry cleans up their bloody UI, clogin should do the job. -jlogin - Expect script that logs into juniper routers similarly to - clogin. it is not terribly robust, but mainly used for it's +jlogin.in - Expect script that logs into juniper routers similarly to + clogin. It is not terribly robust, but mainly used for it's -c and -s options. .cloginrc - TCL commands to set passwords, usernames etc. used by clogin and jlogin. -par - Parallel processing of commands - any commands. -rename - Perl script to rename files. -create_cvs -Creates all of the CVS and config directories. -util - utilities / contribs +par.in - Parallel processing of commands - any commands. +rename.in - Perl script to rename files. +create_cvs.in - Creates all of the CVS and config directories. +util/ - utilities / contribs + +The following are included as part of the installation tools: + +Makefile.in - processed by configure to produce Makefiles +configure - gnu autoconf script +install-sh - shell script to simulate BSD style install +mkinstalldirs - shell script to make installation directories rancid will also need to have the following packages: cvs - code revision system available from prep.ai.mit.edu:/pub/gnu @@ -51,32 +59,29 @@ not included, but can be found here: Quick Installation Guide (an example): -1) mkdir - All rancid crud will be under this directory. we chose /home/rancid. - -2) mkdir /bin - -3) Put the contents of rancid/bin in /bin. +1) ./configure [--prefix=] + By default, All rancid crud will be installed under /usr/local/rancid. + This can be overridden with the --prefix option. E.g.: + ./configure --prefix=/home/rancid + The user who will run rancid must have write permission in this + directory. - Modify the location of perl and expect in each of cat5rancid, - clogin, elogin, erancid, flogin, francid, jlogin, jrancid, par, - rancid, rancid-fe, rename, and rrancid if necessary. There are - also 3 calls to perl in control_rancid and one in do-diffs. +2) make install - Make sure that you are using perl version 5 and not perl version 4. +3) Modify /bin/env. The variable LIST_OF_GROUPS is a + space delimited list of router "groups". E.g.: + LIST_OF_GROUPS="backbone aggregation switches" -4) Modify /bin/env. +4) Put .cloginrc in the home directory of the user who will run rancid. -5) Put .cloginrc in your home directory. - -6) Modify .cloginrc. +5) Modify .cloginrc. Test to make sure that you can log into every router. Note: the juniper user you use *must* log into a cli shell (which is the default on a juniper). -7) Modify /etc/aliases +6) Modify /etc/aliases Rancid sends the diffs and other controlling emails to rancid- and problems to rancid-admin-, where is the "GROUP" of routers. This way you can seperate your backbone routers from your @@ -93,11 +98,11 @@ Quick Installation Guide (an example): The Precedence header set to bulk or junk *hopefully* avoids replies from auto-responders and vacation type mail filters. -8) Run create_cvs. +7) Run create_cvs. This creates all of the CVS necessary directories and all of the config directories. -9) For each "group", modify the router.db file in the group directory. +8) For each "group", modify the router.db file in the group directory. The file is of the form "router:mfg:state" where "router" is the name (we use FQDN) of the router, mfg is the manufacturer from the set of (cisco|ezt3|foundry|juniper|redback|cat5), and "state" @@ -112,14 +117,21 @@ Quick Installation Guide (an example): juniper-router.domain.com:juniper:up redback-dsl-router.domain.com:redback:down -10) Put do-diffs in cron to be called however often you want it to run - for each group (do-diffs []). eg: - +9) Put do-diffs in cron to be called however often you want it to + run for each group (do-diffs []). If you run it less + often than once/hour, check the setting of OLDTIME in bin/env. + E.g.: # run config differ hourly 1 * * * * /bin/do-diffs - # clean out hourly differ logs + # clean out config differ logs 50 23 * * * /usr/bin/find /logs -mtime +2 -exec rm {} \; -11) Send any bugs, suggestions or updates to rancid@shrubbery.net. +10) Send any bugs, suggestions or updates to rancid@shrubbery.net. + See the web page at http://www.shrubbery.net/rancid. We have + created the standard mailing lists for those interested; + rancid-announce@shrubbery.net and rancid-discuss@shrubbery.net. + Subscribe by sending an email whose body contains "subscribe + rancid-" to majordomo@shrubbery.net. + -Hank diff --git a/acinclude.m4 b/acinclude.m4 new file mode 100644 index 0000000..4787366 --- /dev/null +++ b/acinclude.m4 @@ -0,0 +1 @@ +AUTOMAKE_OPTIONS=no-dependencies foreign diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 0000000..4483bca --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,139 @@ +dnl aclocal.m4 generated automatically by aclocal 1.4 + +dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without +dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A +dnl PARTICULAR PURPOSE. + +AUTOMAKE_OPTIONS=no-dependencies foreign + +# Do all the work for Automake. This macro actually does too much -- +# some checks are only needed if your package does certain things. +# But this isn't really a big deal. + +# serial 1 + +dnl Usage: +dnl AM_INIT_AUTOMAKE(package,version, [no-define]) + +AC_DEFUN(AM_INIT_AUTOMAKE, +[AC_REQUIRE([AC_PROG_INSTALL]) +PACKAGE=[$1] +AC_SUBST(PACKAGE) +VERSION=[$2] +AC_SUBST(VERSION) +dnl test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) +fi +ifelse([$3],, +AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) +AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])) +AC_REQUIRE([AM_SANITY_CHECK]) +AC_REQUIRE([AC_ARG_PROGRAM]) +dnl FIXME This is truly gross. +missing_dir=`cd $ac_aux_dir && pwd` +AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir) +AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) +AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir) +AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) +AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) +AC_REQUIRE([AC_PROG_MAKE_SET])]) + +# +# Check to make sure that the build environment is sane. +# + +AC_DEFUN(AM_SANITY_CHECK, +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftestfile +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` + if test "[$]*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftestfile` + fi + if test "[$]*" != "X $srcdir/configure conftestfile" \ + && test "[$]*" != "X conftestfile $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "[$]2" = conftestfile + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +rm -f conftest* +AC_MSG_RESULT(yes)]) + +dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY) +dnl The program must properly implement --version. +AC_DEFUN(AM_MISSING_PROG, +[AC_MSG_CHECKING(for working $2) +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if ($2 --version) < /dev/null > /dev/null 2>&1; then + $1=$2 + AC_MSG_RESULT(found) +else + $1="$3/missing $2" + AC_MSG_RESULT(missing) +fi +AC_SUBST($1)]) + +# Add --enable-maintainer-mode option to configure. +# From Jim Meyering + +# serial 1 + +AC_DEFUN(AM_MAINTAINER_MODE, +[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) + dnl maintainer-mode is disabled by default + AC_ARG_ENABLE(maintainer-mode, +[ --enable-maintainer-mode enable make rules and dependencies not useful + (and sometimes confusing) to the casual installer], + USE_MAINTAINER_MODE=$enableval, + USE_MAINTAINER_MODE=no) + AC_MSG_RESULT($USE_MAINTAINER_MODE) + AM_CONDITIONAL(MAINTAINER_MODE, test $USE_MAINTAINER_MODE = yes) + MAINT=$MAINTAINER_MODE_TRUE + AC_SUBST(MAINT)dnl +] +) + +# Define a conditional. + +AC_DEFUN(AM_CONDITIONAL, +[AC_SUBST($1_TRUE) +AC_SUBST($1_FALSE) +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi]) + diff --git a/bin/Makefile.in b/bin/Makefile.in new file mode 100644 index 0000000..ca5616b --- /dev/null +++ b/bin/Makefile.in @@ -0,0 +1,37 @@ +PREFIX = @prefix@ + +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ + +BIN_PROGS = @RD_BIN_PROGS@ +BIN_DATAS = @RD_BIN_DATAS@ + +all: + +install: all + for prog in $(BIN_PROGS) ; do \ + $(INSTALL) $$prog $(PREFIX)/bin; \ + done; \ + if test -f $(PREFIX)/bin/env ; then \ + echo "WARNING: *** $(PREFIX)/bin/env exists: not installing."; \ + else \ + $(INSTALL_DATA) env $(PREFIX)/bin; \ + fi +# BIN_DATAS are empty at the moment. +# for prog in $(BIN_DATAS) ; do \ +# $(INSTALL_DATA) $$prog $(PREFIX)/bin; \ +# done; \ + +clean: + rm -f Makefile env $(BIN_DATAS) $(BIN_PROGS) + +distclean: clean + rm -f config.log config.status + +distdir: + for file in Makefile.in configure.in env.in $(BIN_DATAS:=.in) ; do \ + $(INSTALL_DATA) $$file $(distdir); \ + done + for file in configure $(BIN_PROGS:=.in) ; do \ + $(INSTALL) $$file $(distdir); \ + done diff --git a/bin/cat5rancid b/bin/cat5rancid deleted file mode 100755 index 8073448..0000000 --- a/bin/cat5rancid +++ /dev/null @@ -1,1043 +0,0 @@ -#!/usr/local/bin/perl -## -## -## Copyright (C) 1997 by Henry Kilmer. -## All rights reserved. -## -## This software may be freely copied, modified and redistributed without -## fee for non-commerical purposes provided that this copyright notice is -## preserved intact on all copies and modified copies. -## -## There is no warranty or other guarantee of fitness of this software. -## It is provided solely "as is". The author(s) disclaim(s) all -## responsibility and liability with respect to this software's usage -## or its effect upon hardware, computer systems, other software, or -## anything else. -## -## -# -# RANCID - Really Awesome New Cisco confIg Differ -# -# usage: rancid [-d] [-l] [-f filename | $host] -# -use Getopt::Std; -getopts('dflm'); -$log = $opt_l; -$debug = $opt_d; -$file = $opt_f; -$host = $ARGV[0]; -$clean_run = 0; -$found_end = 0; -$timeo = 90; # clogin timeout in seconds - -# This routine is used to print out the router configuration -sub ProcessHistory { - my($new_hist_tag,$new_command,$command_string,@string)=(@_); - if((($new_hist_tag ne $hist_tag) || ($new_command ne $command)) - && defined %history) { - print eval "$command \%history"; - undef %history; - } - if (($new_hist_tag) && ($new_command) && ($command_string)) { - if ($history{$command_string}) { - $history{$command_string} = "$history{$command_string}@string"; - } else { - $history{$command_string} = "@string"; - } - } elsif (($new_hist_tag) && ($new_command)) { - $history{++$#history} = "@string"; - } else { - print "@string"; - } - $hist_tag = $new_hist_tag; - $command = $new_command; - 1; -} - -sub numerically { $a <=> $b; } - -# This is a sort routing that will sort numerically on the -# keys of a hash as if it were a normal array. -sub keynsort { - local(%lines)=@_; - local($i) = 0; - local(@sorted_lines); - foreach $key (sort numerically keys(%lines)) { - $sorted_lines[$i] = $lines{$key}; - $i++; - } - @sorted_lines; -} - -# This is a sort routing that will sort on the -# keys of a hash as if it were a normal array. -sub keysort { - local(%lines)=@_; - local($i) = 0; - local(@sorted_lines); - foreach $key (sort keys(%lines)) { - $sorted_lines[$i] = $lines{$key}; - $i++; - } - @sorted_lines; -} - -# This is a sort routing that will sort on the -# values of a hash as if it were a normal array. -sub valsort{ - local(%lines)=@_; - local($i) = 0; - local(@sorted_lines); - foreach $key (sort values %lines) { - $sorted_lines[$i] = $key; - $i++; - } - @sorted_lines; -} - -# This is a numerical sort routing (ascending). -sub numsort { - local(%lines)=@_; - local($i) = 0; - local(@sorted_lines); - foreach $num (sort {$a <=> $b} keys %lines) { - $sorted_lines[$i] = $lines{$num}; - $i++; - } - @sorted_lines; -} - -# This is a sort routine that will sort on the -# ip address when the ip address is anywhere in -# the strings. -sub ipsort { - local(%lines)=@_; - local($i) = 0; - local(@sorted_lines); - foreach $addr (sort sortbyipaddr keys %lines) { - $sorted_lines[$i] = $lines{$addr}; - $i++; - } - @sorted_lines; -} - -# These two routines will sort based upon IP addresses -sub ipaddrval { - my(@a) = ($_[0] =~ m#^(\d+)\.(\d+)\.(\d+)\.(\d+)$#); - $a[3]+256*($a[2]+256*($a[1]+256*$a[0])); -} -sub sortbyipaddr { - &ipaddrval($a) <=> &ipaddrval($b); -} - -# This routine parses "show version" -sub ShowVersion { - print STDERR " In ShowVersion: $_" if ($debug); - - while () { - tr/\015//d; - last if(/^$prompt/); - next if(/^(\s*|\s*$cmd\s*)$/); - if (/^Slave in slot (\d+) is running/) { - $slave = " Slave:"; - next; - } - /^IOS .* Software \(([A-Za-z-0-9]*)\), .*Version\s+(.*)$/ && - ProcessHistory("COMMENTS","keysort","F1", - "!Image:$slave Software: $1, $2\n") && next; - /^([A-Za-z-0-9_]*) Synced to mainline version: (.*)$/ && - ProcessHistory("COMMENTS","keysort","F2", - "!Image:$slave $1 Synced to mainline version: $2\n") && next; - /^Compiled (.*)$/ && - ProcessHistory("COMMENTS","keysort","F3", - "!Image:$slave Compiled: $1\n") && next; - /^ROM: (System )?Bootstrap.*(Version.*)$/ && - ProcessHistory("COMMENTS","keysort","G1", - "!ROM Bootstrap: $2\n") && next; - /^ROM: \d+ Bootstrap .*(Version.*)$/ && - ProcessHistory("COMMENTS","keysort","G2", - "!ROM Image: Bootstrap $1\n!\n") && next; - /^ROM: .*(Version.*)$/ && - ProcessHistory("COMMENTS","keysort","G3","!ROM Image: $1\n") && next; - /^BOOTFLASH: .*(Version.*)$/ && - ProcessHistory("COMMENTS","keysort","G4","!BOOTFLASH: $1\n") && next; - /^System image file is "([^\"]*)", booted via (\S*)/ && -# removed the booted source due to -# CSCdk28131: cycling info in 'sh ver' -# ProcessHistory("COMMENTS","keysort","F4","!Image: booted via $2, $1\n") && - ProcessHistory("COMMENTS","keysort","F4","!Image: booted $1\n") && - next; - /^System image file is "([^\"]*)"$/ && - ProcessHistory("COMMENTS","keysort","F5","!Image: $1\n") && next; - if (/(\S+)\s+\((\S+)\)\s+processor.*with (\S+K) bytes/) { - my($proc) = $1; - my($cpu) = $2; - my($mem) = $3; - if ( $1 eq "CSC") { - $type = "AGS"; - } elsif ( $1 eq "CSC4") { - $type = "AGS+"; - } elsif ( $1 eq "2511" || $1 eq "2524" || $1 eq "AS2511-RJ") { - $type = "2500"; - } elsif ( $1 eq "3620" || $1 eq "3640") { - $type = "3600"; - } elsif ( $1 eq "RSP7000") { - $type = "7500"; - } elsif ( $1 =~ /RSP\d/) { - $type = "7500"; - } elsif ( $1 eq "RP1") { - $type = "7000"; - } elsif ( $1 eq "RP") { - $type = "7000"; - } elsif ( $1 =~ /720[246]/) { - $type = "7200"; - } elsif ($1 =~ /1200[48]\/GRP/ || $1 =~ /1201[26]\/GRP/) { - $type = "12000"; - } else { - $type = $1; - } - print STDERR "TYPE = $type\n" if ($debug); - ProcessHistory("COMMENTS","keysort","A1", - "!Chassis type:$slave $proc - a $type router\n"); - ProcessHistory("COMMENTS","keysort","B1", - "!Memory:$slave main $mem\n"); - ProcessHistory("COMMENTS","keysort","A3","!CPU:$slave $cpu\n"); - next; - } - if (/(\S+) Silicon\s*Switch Processor/) { - if (!defined($C0)) { - $C0=1; ProcessHistory("COMMENTS","keysort","C0","!\n"); - } - ProcessHistory("COMMENTS","keysort","C2","!SSP: $1\n"); - $ssp = 1; - $sspmem = $1; - next; - } - /^(\d+K) bytes of multibus/ && - ProcessHistory("COMMENTS","keysort","B2", - "!Memory: multibus $1\n") && next; - /^(\d+K) bytes of non-volatile/ && - ProcessHistory("COMMENTS","keysort","B3", - "!Memory: nvram $1\n") && next; - /^(\d+K) bytes of flash memory/ && - ProcessHistory("COMMENTS","keysort","B5","!Memory: flash $1\n") && - next; - /^(\d+K) bytes of .*flash partition/ && - ProcessHistory("COMMENTS","keysort","B6", - "!Memory: flash partition $1\n") && next; - /^(\d+K) bytes of Flash internal/ && - ProcessHistory("COMMENTS","keysort","B4", - "!Memory: bootflash $1\n") && next; - if(/^(\d+K) bytes of (Flash|ATA)?.*PCMCIA .*slot ?(\d)/i) { - ProcessHistory("COMMENTS","keysort","B7", - "!Memory: pcmcia $2 slot$3 $1\n"); - next; - } - if(/^WARNING/) { - if (!defined($I0)) { - $I0=1; - ProcessHistory("COMMENTS","keysort","I0","!\n"); - } - ProcessHistory("COMMENTS","keysort","I1","! $_"); - # The line after the WARNING is what to do about it. - $_ = ; tr/\015//d; - ProcessHistory("COMMENTS","keysort","I1","! $_"); - } - if (/^Configuration register is (.*)$/) { - $config_register=$1; - next; - } - } - return(0); -} - -# This routine parses "show install active" -sub ShowInstallActive { - print STDERR " In ShowInstallActive: $_" if ($debug); - - while () { - tr/\015//d; - last if (/^$prompt/); - next if (/^(\s*|\s*$cmd\s*)$/); - return(1) if /^\s*\^\s*$/; - return(1) if /Invalid input detected/; - return(1) if /Unknown command/; - ProcessHistory("COMMENTS","keysort","F5","!Image: $_") && next; - } - return(0); -} - -# This routine parses "show env all" -sub ShowEnv { - # Skip if this is not a 7500, 7200, or 7000. - print STDERR " In ShowEnv: $_" if ($debug); - - while () { - tr/\015//d; - last if (/^$prompt/); - next if (/^(\s*|\s*$cmd\s*)$/); - return(1) if ($type !~ /^7/); - if (!defined($E0)) { - $E0=1; - ProcessHistory("COMMENTS","keysort","E0","!\n"); - } - if (/^Arbiter type (\d), backplane type (\S+)/) { - if (!defined($C0)) { - $C0=1; ProcessHistory("COMMENTS","keysort","C0","!\n"); - } - ProcessHistory("COMMENTS","keysort","C1", - "!Enviromental Arbiter Type: $1\n"); - ProcessHistory("COMMENTS","keysort","A2", - "!Chassis type: $2 backplane\n"); - next; - } - /^\s*(Power .*)/ && - ProcessHistory("COMMENTS","keysort","E1","!Power: $1\n") && next; - /^\s*(Lower Power .*)/i && - ProcessHistory("COMMENTS","keysort","E2","!Power: $1\n") && next; - } - ProcessHistory("COMMENTS","","","!\n"); - return(0); -} - -# This routine parses "show gsr chassis-info" for the gsr -# This will create arrarys for hw info. -sub ShowGSR { - # Skip if this is not a 1200n. - print STDERR " In ShowGSR: $_" if ($debug); - - while () { - tr/\015//d; - last if (/^$prompt/); - next if (/^(\s*|\s*$cmd\s*)$/); - return(1) if ($type !~ /^120/); - /^$/ && next; - /^\s+Chassis: type (\S+) Fab Ver: (\S+)/ && - ProcessHistory("COMMENTS","keysort","D0","!\n") && - ProcessHistory("COMMENTS","keysort","D1", - "!GSR Chassis type: $1 Fab Ver: $2\n") && - next; - /^\s+Chassis S\/N: (.*)$/ && - ProcessHistory("COMMENTS","keysort","D2", - "!GSR Chassis S/N: $1\n") && - next; - /^\s+PCA: (\S+)\s*rev: (\S+)\s*dev: \S+\s*HW ver: (\S+)$/ && - ProcessHistory("COMMENTS","keysort","D3", - "!GSR Backplane PCA: $1, rev $2, ver $3\n") && - next; - /^\s+Backplane S\/N: (\S+)$/ && - ProcessHistory("COMMENTS","keysort","D4", - "!GSR Backplane S/N: $1\n") && - next; - } - ProcessHistory("COMMENTS","","","!\n"); - return(0); -} - -# This routine parses "show boot" -sub ShowBoot { - # Pick up boot variables if 7000/7200/7500/12000; - # otherwise pick up bootflash. - print STDERR " In ShowBoot: $_" if ($debug); - - while () { - tr/\015//d; - last if (/^$prompt/); - next if (/^(\s*|\s*$cmd\s*)$/); - return(1) if /^\s*\^\s*$/; - return(1) if /Ambiguous command/i; - return(1) if /Invalid input detected/; - return(1) if /Unknown command/; - return(1) if /(Open device \S+ failed|Error opening \S+:)/; - next if /CONFGEN variable/; - if (!defined($H0)) { - $H0=1; ProcessHistory("COMMENTS","keysort","H0","!\n"); - } - if ($type !~ /^(120|7)/) { - ProcessHistory("COMMENTS","keysort","H2","!BootFlash: $_"); - } elsif (/variable/) { - ProcessHistory("COMMENTS","keysort","H1","!Variable: $_"); - } - } - ProcessHistory("COMMENTS","","","!\n"); - return(0); -} - -# This routine parses "show flash" -sub ShowFlash { - # skip if this is 7000, 7200, 7500, or 12000. - print STDERR " In ShowFlash: $_" if ($debug); - - while () { - tr/\015//d; - last if (/^$prompt/); - next if (/^(\s*|\s*$cmd\s*)$/); - return(1) if ($type =~ /^(120|7)/); - return(1) if /^\s*\^\s*$/; - return(1) if /Invalid input detected/; - ProcessHistory("FLASH","","","!Flash: $_"); - } - ProcessHistory("","","","!\n"); - return; -} - -# This routine parses "dir /all ((disk|slot)N|bootflash):" -sub DirSlotN { - # Skip if this is not a 3600, 7000, 7200, 7500, or 12000. - print STDERR " In DirSlotN: $_" if ($debug); - - my($dev) = (/\s([^\s]+):/); - - while () { - tr/\015//d; - last if (/^$prompt/); - next if (/^(\s*|\s*$cmd\s*)$/); - return(1) if ($type !~ /^(120|7|36)/); - return(1) if /^\s*\^\s*$/; - return(1) if /Invalid input detected/; - return(1) if /\%Error: No such file or directory/; - return(1) if /No space information available/; - return(-1) if /\%Error calling/; - return(-1) if /: device being squeezed/; # Flash is busy - return(1) if /(Open device \S+ failed|Error opening \S+:)/; - ProcessHistory("FLASH","","","!Flash: $dev: $_"); - } - ProcessHistory("","","","!\n"); - return(0); -} - -# This routine parses "show controllers" -sub ShowContAll { - # Skip if this is a 70[01]0, 7500, or 12000. - print STDERR " In ShowContAll: $_" if ($debug); - - while () { - tr/\015//d; - last if (/^$prompt/); - next if (/^(\s*|\s*$cmd\s*)$/); - return(1) if ($type =~ /^(120|7[05])/); - if (/^Interface ([^ \n(]*)/) { $INT = "$1, "; next; } - /^(BRI unit \d)/ && - ProcessHistory("INT","","","!Interface: $1\n") && next; - /^LANCE unit \d, NIM/ && - ProcessHistory("INT","","","!Interface: $_") && next; - /^(LANCE unit \d)/ && - ProcessHistory("INT","","","!Interface: $1\n") && next; - /(Media Type is \S+),/ && - ProcessHistory("INT","","","!\t$1\n"); - if (/(M\dT:) show controller:$/) { - my($ctlr) = $1; - $_ = ; tr/\015//d; s/ subunit \d,//; - ProcessHistory("INT","","","!Interface: $ctlr $_"); - } - if (/^(\S+) : show controller:$/) { - my($ctlr) = $1; - $_ = ; tr/\015//d; s/ subunit \d,//; - ProcessHistory("INT","","","!Interface: $ctlr: $_"); - } - /^(HD unit \d), idb/ && - ProcessHistory("INT","","","!Interface: $1\n") && next; - /^HD unit \d, NIM/ && - ProcessHistory("INT","","","!Interface: $_") && next; - /^buffer size \d+ HD unit \d, (.*)/ && - ProcessHistory("INT","","","!\t$1\n") && next; - /^AM79970 / && ProcessHistory("INT","","","!Interface: $_") && next; - /^buffer size \d+ (Universal Serial: .*)/ && - ProcessHistory("INT","","","!\t$1\n") && next; - /^Hardware is (.*)/ && - ProcessHistory("INT","","","!Interface: $INT$1\n") && next; - /^(QUICC Serial unit \d),/ && - ProcessHistory("INT","","","!$1\n") && next; - /^QUICC Ethernet .*/ && - ProcessHistory("INT","","","!$_") && next; - /^DTE .*\.$/ && - ProcessHistory("INT","","","!\t$_") && next; - /^(cable type :.*),/ && - ProcessHistory("INT","","","!\t$1\n") && next; - /^(.* cable.*), received clockrate \d+$/ && - ProcessHistory("INT","","","!\t$1\n") && next; - /^.* cable.*$/ && - ProcessHistory("INT","","","!\t$_") && next; - } - return(0); -} - -# This routine parses "show controllers cbus" -# Some of this is printed out in ShowDiagbus. -sub ShowContCbus { - # Skip if this is not a 7000 or 7500. - print STDERR " In ShowContCbus: $_" if ($debug); - - while () { - tr/\015//d; - last if (/^$prompt/); - next if (/^(\s*|\s*$cmd\s*)$/); - return(1) if ($type !~ /^7[05]0/); - if (/^\s*slot(\d+): ([^,]+), hw (\S+), sw (\S+), ccb/) { - $slot = $1; - $board{$slot} = $2; - $hwver{$slot} = $3; - $hwucode{$slot} = $4; - } elsif (/^\s*(\S+) (\d+), hardware version (\S+), microcode version (\S+)/) { - $slot = $2; - $board{$slot} = $1; - $hwver{$slot} = $3; - $hwucode{$slot} = $4; - } elsif (/(Microcode .*)/) { - $ucode{$slot} = $1; - } elsif (/(software loaded .*)/) { - $ucode{$slot} = $1; - } elsif (/(\d+) Kbytes of main memory, (\d+) Kbytes cache memory/) { - $hwmemd{$slot} = $1; - $hwmemc{$slot} = $2; - } elsif (/byte buffers/) { - chop; - s/^\s*//; - $hwbuf{$slot} = $_; - } elsif (/Interface (\d+) - (\S+ \S+),/) { - $interface = $1; - ProcessHistory("HW","","", - "!\n!Int $interface: in slot $slot, named $2\n"); next; - } elsif (/(\d+) buffer RX queue threshold, (\d+) buffer TX queue limit, buffer size (\d+)/) { - ProcessHistory("HW","","","!Int $interface: rxq $1, txq $2, bufsize $3\n"); - next; - } - } - return(0); -} - -# This routine parses "show diagbus" -# This will create arrarys for hw info. -sub ShowDiagbus { - # Skip if this is not a 7000, 70[01]0, or 7500. - print STDERR " In ShowDiagbus: $_" if ($debug); - - while () { - tr/\015//d; - last if (/^$prompt/); - next if (/^(\s*|\s*$cmd\s*)$/); - return(1) if ($type !~ /^7[05]/); - if (/^\s*Slot (\d+):/i) { - $slot = $1; - next; - } elsif (/^\s*Slot (\d+) \(virtual\):/i) { - $slot = $1; - next; - } elsif (/^\s*(.*Processor.*|.*controller|.*Chassis Interface), HW rev (\S+), board revision (\S+)/i) { - $board = $1; - $hwver = $2; - $boardrev = $3; - if ($board =~ /Processor/) { - if ($board =~ /7000 Route\/Switch/) { - $board = "RSP7000"; - } elsif ($board =~ /Route\/Switch Processor (\d)/) { - $board = "RSP$1"; - } elsif ($board =~ /Route/) { - $board = "RP"; - } elsif ($board =~ /Silicon Switch/) { - $board = "SSP"; - } elsif ($board =~ /Switch/) { - $board = "SP"; - $board = "SSP $sspmem" if $ssp; - } elsif ($board =~ /ATM/) { - $board = "AIP"; - } - } elsif ($board =~ /(.*) controller/i) { - $board = $1; - } - # hwucode{$slot} defined in ShowContCbus - if (defined $hwucode{$slot}) { - ProcessHistory("SLOT","","","!\n!Slot $slot/$board: hvers $hwver rev $boardrev ucode $hwucode{$slot}\n"); - } else { - ProcessHistory("SLOT","","","!\n!Slot $slot/$board: hvers $hwver rev $boardrev\n"); - } - # These are also from the ShowContCbus - ProcessHistory("SLOT","","","!Slot $slot/$board: $ucode{$slot}\n") if (defined $ucode{$slot}); - ProcessHistory("SLOT","","","!Slot $slot/$board: memd $hwmemd{$slot}, cache $hwmemc{$slot}\n") - if ((defined $hwmemd{$slot}) && (defined $hwmemc{$slot})); - ProcessHistory("SLOT","","","!Slot $slot/$board: $hwbuf{$slot}\n") if (defined $hwbuf{$slot}); - next; - } - /Serial number: (\S+)\s*Part number: (\S+)/ && - ProcessHistory("SLOT","","", - "!Slot $slot/$board: part $2, serial $1\n") && - next; - /^\s*Controller Memory Size: (.*)$/ && - ProcessHistory("SLOT","","","!Slot $slot/$board: $1\n") && - next; - if (/PA Bay (\d) Information/) { - $pano = $1; - if ("PA" =~ /$board/) { - ($s,$c) = split(/\//,$board); - $board = "$s/$c/PA $pano"; - } else { - $board =~ s/\/PA \d//; - $board = "$board/PA $pano"; - } - next; - } - /\s+(.*) PA, (\d) ports?, (\S+)/ && - ProcessHistory("SLOT","","","!Slot $slot/$board: type $3, $2 ports\n") && - next; - /\s+(.*) PA( \(\S+\))?, (\d) ports?/ && - ProcessHistory("SLOT","","","!Slot $slot/$board: type $1$2, $3 ports\n") && - next; - /^\s*HW rev (\S+), Board revision (\S+)/ && - ProcessHistory("SLOT","","","!Slot $slot/$board: hvers $1 rev $2\n") && - next; - /Serial number: (\S+)\s*Part number: (\S+)/ && - ProcessHistory("SLOT","","","!Slot $slot/$board: part $2, serial $1\n") && next; - } - return(0); -} - -# This routine parses "show diag" for the gsr, 7200, 3600, 2600. -# This will create arrarys for hw info. -sub ShowDiag { - # Skip if this is not a 12000. - print STDERR " In ShowDiag: $_" if ($debug); - - while () { - tr/\015//d; - last if (/^$prompt/); - next if (/^(\s*|\s*$cmd\s*)$/); - return(1) if ($type !~ /^(120|720|36|26)/); - /^$/ && next; - if (!defined($showdiags)) {$showdiags=1; ProcessHistory("SLOT","","","!\n");} - s/Port Packet Over SONET/POS/; - if (/^\s*SLOT (\d+)\s+\(.*\): (.*)/) { - $slot = $1; - ProcessHistory("SLOT","","","!Slot $slot: $2\n"); - $board = "RP" if (/Route Processor/); - $board = "CLK" if (/Clock Scheduler Card/); - next; - } - if (/^\s+PCA:\s+(.*)/){ - local($part) = $1; - $_ = ; - /^\s+HW version (\S+)\s+S\/N (\S+)/ && - ProcessHistory("SLOT","","","!Slot $slot/PCA: part $part, serial $2\n") && - ProcessHistory("SLOT","","","!Slot $slot/PCA: hvers $1\n"); - next; - } - - if (/^\s+MBUS: .*\)\s+(.*)/) { - local($tmp) = "!Slot $slot/MBUS: part $1"; - $_ = ; - /^\s+HW version (\S+)\s+S\/N (\S+)/ && - ProcessHistory("SLOT","","","$tmp, serial $2\n") && - ProcessHistory("SLOT","","","!Slot $slot/MBUS: hvers $1\n"); - next; - } - if (/^\s+MBUS Agent Software version (.*)/) { - local($sw) = $1; - local($tail) = "!\n" if ($board =~ /(CLK|RP)/); - ProcessHistory("SLOT","","","!Slot $slot/MBUS: software $sw\n$tail"); - next; - } - if (/^\s+DRAM size: (\d+)/) { - local($dram) = $1 / 1048576; - $_ = ; - /^\s+FrFab SDRAM size: (\d+)/ && - ProcessHistory("SLOT","","","!Slot $slot/MBUS: $dram Mbytes DRAM, " - . $1 / 1024 . " Kbytes SDRAM\n!\n"); - next; - } - # 7200 and 3600 stuff - if (/^(Slot)\s+(\d+):/ || /^\s+(WIC|VIC) Slot (\d):/) { - if ($1 eq "WIC") { - $WIC = "/$2"; - } elsif ($1 eq "VIC") { - $WIC = "/$2"; - } else { - $slot = $2; - undef($WIC); - } - $_ = ; tr/\015//d; - - # clean up hideous 7200 format to look more like 7500 output - s/Fast-ethernet on C7200 I\/O card/FE-IO/; - s/ with MII or RJ45/-TX/; - s/Fast-ethernet /100Base/; s/[)(]//g; - - /\s+(.*) port adapter,?\s+(\d+)\s+/i && - ProcessHistory("SLOT","","","!Slot $slot: type $1, $2 ports\n"); - # I/O controller with no interfaces - /\s+(.*)\s+port adapter\s*$/i && - ProcessHistory("SLOT","","","!Slot $slot: type $1, 0 ports\n"); - /\s+(.*)\s+daughter card(.*)$/ && - ProcessHistory("SLOT","","","!Slot $slot$WIC: type $1$2\n"); - /\s+(FT1)$/ && - ProcessHistory("SLOT","","","!Slot $slot$WIC: type $1\n"); - next; - } - /revision\s+(\S+).*revision\s+(\S+)/ && - ProcessHistory("SLOT","","","!Slot $slot$WIC: hvers $1 rev $2\n") && - next; - /number\s+(\S+)\s+Part number\s+(\S+)/ && - ProcessHistory("SLOT","","","!Slot $slot$WIC: part $2, serial $1\n!\n") && - next; -} - return(0); -} - -# This routine parses "show module" -sub ShowModule { - print STDERR " In ShowModule: $_" if ($debug); - -# # eat the header lines -# $junk = ; -# $junk = ; - - while () { - tr/\015//d; - last if(/^$prompt/); -# last if(/^$/); -# $junk = $_; -# $slot = substr($junk, 0, 2) + 0; -# $port = substr($junk, 24, 3) + 0; -# $plu = ""; -# $plu = "s" if $port > 1; -# $type = substr($junk, 30, 21); -# $type =~ s/^\s+//; -# $type =~ s/\s+$//; -# $board = substr($junk, 52, 9); -# $board =~ s/ //; -# $serial = substr($junk, 62,9) + 0; -# ProcessHistory("SLOT","","","!Slot $slot/$board: $type, $port port$plu, serial $serial\n"); - ProcessHistory("SLOT","","","! $_"); - } - # The "write term" code gives us one of these, so skip it here - # ProcessHistory("SLOT","","","!\n"); -} - -# This routine parses "show c7200" for the 7200 -# This will create arrarys for hw info. -sub ShowC7200 { - # Skip if this is not a 7200. - print STDERR " In ShowC7200: $_" if ($debug); - - while () { - tr/\015//d; - last if (/^$prompt/); - next if (/^(\s*|\s*$cmd\s*)$/); - return(1) if ($type !~ /^72/); - /^$/ && next; - if (/C7200 Midplane EEPROM:/) { - $_ = ; - /revision\s+(\S+).*revision\s+(\S+)/; - ProcessHistory("SLOT","","","!Slot Midplane: hvers $1 rev $2\n"); - $_ = ; - /number\s+(\S+)\s+Part number\s+(\S+)/; - ProcessHistory("SLOT","","","!Slot Midplane: part $2, serial $1\n!\n"); - next; - } - if (/C720\d(VXR)? CPU EEPROM:/) { - $_ = ; - /revision\s+(\S+).*revision\s+(\S+)/ && - ProcessHistory("SLOT","","","!Slot CPU: hvers $1 rev $2\n"); - $_ = ; - /number\s+(\S+)\s+Part number\s+(\S+)/ && - ProcessHistory("SLOT","","","!Slot CPU: part $2, serial $1\n!\n"); - next; - } - } - return(0); -} - -# This routine processes a "write term" -sub WriteTerm { - print STDERR " In WriteTerm: $_" if ($debug); - - while () { - tr/\015//d; - last if (/^$prompt/); -#heas next if (/^\.+$/); - /Non-Volatile memory is in use/ && return(-1); # NvRAM is locked - # skip the crap - if (/^(\.\.+$|##+$|Building configuration...)/i) { - while () { - tr/\015//d; - next if (/^Current configuration:/i); - next if (/^(\.+|[%!].*|\s*)$/); - next if (/^ip add.*ipv4:/); # band-aid for 3620 12.0S - last; - } - ProcessHistory("","","","!\n"); - tr/\015//d; - } - # some versions have other crap mixed in with the bits in the - # block above - /^! (Last configuration|NVRAM config last)/ && next; - - # Dog gone Cool matches to process the rest of the config - /^#time: / && next; # kill time: - /^tftp-server flash / && next; # kill any tftp remains - /^ntp clock-period / && next; # kill ntp clock-period - /^ length / && next; # kill length on serial lines - /^ width / && next; # kill width on serial lines - /^enable password / && - ProcessHistory("ENABLE","","","!enable password \n") && - next; - /^(username .*) password /&& - ProcessHistory("USER","","","!$1 password \n") && next; - /^\s*password / && - ProcessHistory("LINE-PASS","","","! password \n") && next; - /^\s*neighbor (\S*) password / && - ProcessHistory("","","","! neighbor $1 password \n") && - next; - /^(ip ftp password) / && - ProcessHistory("","","","!$1 \n") && next; - /^( ip ospf authentication-key) / && - ProcessHistory("","","","!$1 \n") && next; - /^( ip ospf message-digest-key \d+ md5) / && - ProcessHistory("","","","!$1 \n") && next; - /fair-queue individual-limit/ && next; - # sort ip explicit-paths. - if (/^ip explicit-path name (\S+)/) { - my($key) = $1; - my($expath) = $_; - while () { - tr/\015//d; - last if (/^$prompt/); - last if (/^$prompt/ || ! /^(ip explicit-path name |[ !])/); - if (/^ip explicit-path name (\S+)/) { - ProcessHistory("EXPATH","keysort","$key","$expath"); - $key = $1; - $expath = $_; - } else { - $expath .= $_; - } - } - ProcessHistory("EXPATH","keysort","$key","$expath"); - } - # sort route-maps - if (/^route-map (\S+)/) { - my($key) = $1; - my($routemap) = $_; - while () { - tr/\015//d; - last if (/^$prompt/ || ! /^(route-map |[ !])/); - if (/^route-map (\S+)/) { - ProcessHistory("ROUTEMAP","keysort","$key","$routemap"); - $key = $1; - $routemap = $_; - } else { - $routemap .= $_; - } - } - ProcessHistory("ROUTEMAP","keysort","$key","$routemap"); - } - # filter out any RCS/CVS tags to avoid confusing local CVS storage - s/\$(Revision|Id):/ $1:/; - # order access-lists - /^access-list\s+(\d\d?)\s+(\S+)\s+(\S+)/ && - ProcessHistory("ACL $1 $2","ipsort","$3","$_") && next; - # order extended access-lists - /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+host\s+(\S+)/ && - ProcessHistory("EACL $1 $2","ipsort","$3","$_") && next; - /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+(\d\S+)/ && - ProcessHistory("EACL $1 $2","ipsort","$3","$_") && next; - /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+any/ && - ProcessHistory("EACL $1 $2","ipsort","0.0.0.0","$_") && next; - # order arp lists - /^set arp\s+(\d+\.\d+\.\d+\.\d+)\s+/ && - ProcessHistory("ARP","ipsort","$1","$_") && next; - /^ip prefix-list\s+(\S+)\s+seq\s+(\d+)\s+(permit|deny)\s+(\d\S+)(\/.*)$/ && - ProcessHistory("PACL $1 $3","ipsort","$4","ip prefix-list $1 $3 $4$5\n") - && next; - # order logging statements - /^set logging server (\d+\.\d+\.\d+\.\d+)/ && - ProcessHistory("LOGGING","ipsort","$1","$_") && next; - # order name-server statements - /^set ip dns server (\d+\.\d+\.\d+\.\d+)/ && - ProcessHistory("NAMESERVER","ipsort","$1","$_") && next; - # order/prune snmp-server host statements - # we only prune lines of the form - # snmp-server host a.b.c.d - if (/^set snmp trap (\d+\.\d+\.\d+\.\d+) /) { - if (defined($ENV{'NOCOMMSTR'})) { - ProcessHistory("SNMPSERVERHOST","ipsort","$1","# set snmp trap $1 \n"); - } else { - ProcessHistory("SNMPSERVERHOST","ipsort","$1","$_"); - } - next; - } - if (/^(set snmp community) (\S+) (\S+)/) { - if (defined($ENV{'NOCOMMSTR'})) { - ProcessHistory("SNMPSERVERCOMM","keysort","$_","#$1 $2 \n"); - } else { - ProcessHistory("SNMPSERVERCOMM","keysort","$_","$_") - } - next; - } - # order tacacs server statements - /^set (tacacs) key / && - ProcessHistory("","","","! set $1 key \n") && next; - /^set tacacs server (\d+\.\d+\.\d+\.\d+)/ && - ProcessHistory("TAC","ipsort","$1","$_") && next; - # order clns host statements - /^clns host \S+ (\S+)/ && - ProcessHistory("CLNS","keysort","$1","$_") && next; - # order alias statements - /^alias / && ProcessHistory("ALIAS","keysort","$_","$_") && next; - # delete ntp auth password - /^(ntp authentication-key \d+ md5) / && - ProcessHistory("","","","!$1 \n") && next; - # order ntp peers/servers - if (/^ntp (server|peer) (\d+)\.(\d+)\.(\d+)\.(\d+)/) { - $sortkey = sprintf("$1 %03d%03d%03d%03d",$2,$3,$4,$5); - ProcessHistory("NTP","keysort",$sortkey,"$_"); - next; - } - # order ip host line statements - /^ip host line(\d+)/ && - ProcessHistory("IPHOST","numsort","$1","$_") && next; - # order ip nat source static statements - /^ip nat (\S+) source static (\S+)/ && - ProcessHistory("IP NAT $1","ipsort","$2","$_") && next; - # order atm map-list statements - /^\s+ip\s+(\d+\.\d+\.\d+\.\d+)\s+atm-vc/ && - ProcessHistory("ATM map-list","ipsort","$1","$_") && next; - # order ip rcmd lines - /^ip rcmd/ && ProcessHistory("RCMD","keysort","$_","$_") && next; - - ProcessHistory("","","","$_"); - # end of config - if (/^end$/) { - $found_end = 1; - return(1); - } - } - return(0); -} - -# dummy function -sub DoNothing {print STDOUT;} - -# Main -%commands=( - 'show version' => "ShowVersion", -# 'show install active' => "ShowInstallActive", -# 'show env all' => "ShowEnv", -# 'show gsr chassis' => "ShowGSR", - 'show boot' => "ShowBoot", -# 'show bootvar' => "ShowBoot", - 'show flash' => "ShowFlash", - 'dir bootflash:' => "DirSlotN", - 'dir slot0:' => "DirSlotN", -# 'dir /all disk0:' => "DirSlotN", - 'dir slot1:' => "DirSlotN", -# 'dir /all disk1:' => "DirSlotN", -# 'show controllers' => "ShowContAll", -# 'show controllers cbus' => "ShowContCbus", -# 'show diagbus' => "ShowDiagbus", -# 'show diag' => "ShowDiag", - 'show module' => "ShowModule", -# 'show c7200' => "ShowC7200", - 'write term' => "WriteTerm" -); -# keys() doesnt return things in the order entered and the order of the -# cmds is important (show version first and write term last). pita -@commands=( - "show version", -# "show install active", -# "show env all", -# "show gsr chassis", - "show boot", -# "show bootvar", - "show flash", - "dir bootflash:", - "dir slot0:", -# "dir /all disk0:", - "dir slot1:", -# "dir /all disk1:", -# "show controllers", -# "show controllers cbus", -# "show diagbus", -# "show diag", - "show module", -# "show c7200", - "write term" -); -$cisco_cmds=join(";",@commands); -$cmds_regexp=join("|",@commands); - -open(OUTPUT,">$host.new") || die "Can't open $host.new for writing: $!\n"; -select(OUTPUT); -# make OUTPUT unbuffered if debugging -if ($debug) { $| = 1; } - -if ($file) { - print STDERR "opening file $host\n" if ($debug); - print STDOUT "opening file $host\n" if ($log); - open(INPUT,"<$host") || die "open failed for $host: $!\n"; -} else { - print STDERR "executing clogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($debug); - print STDOUT "executing clogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($log); - if (defined($ENV{NOPIPE})) { - system "clogin -t $timeo -c \"$cisco_cmds\" $host $host.raw 2>&1" || die "clogin failed for $host: $!\n"; - open(INPUT, "< $host.raw") || die "clogin failed for $host: $!\n"; - } else { - open(INPUT,"clogin -t $timeo -c \"$cisco_cmds\" $host ) { - tr/\015//d; - if (/> \(enable\) exit$/) { - $clean_run=1; - last; - } - if (/Error:/) { - s/^.*Error:/Error:/; - print STDOUT ("$host clogin error: $_"); - print STDERR ("$host clogin error: $_") if ($debug); - $clean_run=0; - last; - } - while (/> \(enable\)\s*($cmds_regexp)\s*$/) { - $cmd = $1; -# if (!defined($prompt)) {$prompt = ($_ =~ /^([^>]+> .enable.)/)[0]; } - if (!defined($prompt)) {$prompt = ($_ =~ /^([^>]+>)/)[0]; } - print STDERR ("HIT COMMAND:$_") if ($debug); - if (! defined($commands{$cmd})) { - print STDERR "found unexpected command - \"$cmd\"\n"; - $clean_run = 0; - last TOP; - } - $rval = &{$commands{$cmd}}; - delete($commands{$cmd}); - if ($rval == -1) { - $clean_run = 0; - last TOP; - } - } -} -print STDOUT "Done $logincmd: $_\n" if ($log); -# Flush History -ProcessHistory("","","",""); -# Cleanup -close(INPUT); -close(OUTPUT); - -if (defined($ENV{NOPIPE})) { - unlink("$host.raw") if (! $debug); -} - -# check for completeness -if (scalar(%commands) || !$clean_run || !$found_end) { - if (scalar(%commands)) { - printf(STDOUT "missed cmd(s): %s\n", join(',', keys(%commands))); - printf(STDERR "missed cmd(s): %s\n", join(',', keys(%commands))) if ($debug); - } - if (!$clean_run || !$found_end) { - print STDOUT "End of run not found\n"; - print STDERR "End of run not found\n" if ($debug); - system("/usr/bin/tail -1 $host.new"); - } - unlink "$host.new" if (! $debug); -} diff --git a/bin/cat5rancid.in b/bin/cat5rancid.in new file mode 100755 index 0000000..8eb529b --- /dev/null +++ b/bin/cat5rancid.in @@ -0,0 +1,1079 @@ +#!@PERLV_PATH@ +## +## +## Copyright (C) 1997 by Henry Kilmer. +## All rights reserved. +## +## This software may be freely copied, modified and redistributed without +## fee for non-commerical purposes provided that this copyright notice is +## preserved intact on all copies and modified copies. +## +## There is no warranty or other guarantee of fitness of this software. +## It is provided solely "as is". The author(s) disclaim(s) all +## responsibility and liability with respect to this software's usage +## or its effect upon hardware, computer systems, other software, or +## anything else. +## +## +# +# RANCID - Really Awesome New Cisco confIg Differ +# +# usage: rancid [-d] [-l] [-f filename | $host] +# +use Getopt::Std; +getopts('dflm'); +$log = $opt_l; +$debug = $opt_d; +$file = $opt_f; +$host = $ARGV[0]; +$clean_run = 0; +$found_end = 0; +$timeo = 90; # clogin timeout in seconds + +my(%modules); # module info (part from sh ver, part from sh module) + +# This routine is used to print out the router configuration +sub ProcessHistory { + my($new_hist_tag,$new_command,$command_string,@string)=(@_); + if((($new_hist_tag ne $hist_tag) || ($new_command ne $command)) + && defined %history) { + print eval "$command \%history"; + undef %history; + } + if (($new_hist_tag) && ($new_command) && ($command_string)) { + if ($history{$command_string}) { + $history{$command_string} = "$history{$command_string}@string"; + } else { + $history{$command_string} = "@string"; + } + } elsif (($new_hist_tag) && ($new_command)) { + $history{++$#history} = "@string"; + } else { + print "@string"; + } + $hist_tag = $new_hist_tag; + $command = $new_command; + 1; +} + +sub numerically { $a <=> $b; } + +# This is a sort routing that will sort numerically on the +# keys of a hash as if it were a normal array. +sub keynsort { + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $key (sort numerically keys(%lines)) { + $sorted_lines[$i] = $lines{$key}; + $i++; + } + @sorted_lines; +} + +# This is a sort routing that will sort on the +# keys of a hash as if it were a normal array. +sub keysort { + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $key (sort keys(%lines)) { + $sorted_lines[$i] = $lines{$key}; + $i++; + } + @sorted_lines; +} + +# This is a sort routing that will sort on the +# values of a hash as if it were a normal array. +sub valsort{ + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $key (sort values %lines) { + $sorted_lines[$i] = $key; + $i++; + } + @sorted_lines; +} + +# This is a numerical sort routing (ascending). +sub numsort { + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $num (sort {$a <=> $b} keys %lines) { + $sorted_lines[$i] = $lines{$num}; + $i++; + } + @sorted_lines; +} + +# This is a sort routine that will sort on the +# ip address when the ip address is anywhere in +# the strings. +sub ipsort { + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $addr (sort sortbyipaddr keys %lines) { + $sorted_lines[$i] = $lines{$addr}; + $i++; + } + @sorted_lines; +} + +# These two routines will sort based upon IP addresses +sub ipaddrval { + my(@a) = ($_[0] =~ m#^(\d+)\.(\d+)\.(\d+)\.(\d+)$#); + $a[3]+256*($a[2]+256*($a[1]+256*$a[0])); +} +sub sortbyipaddr { + &ipaddrval($a) <=> &ipaddrval($b); +} + +# This routine parses "show version" +sub ShowVersion { + print STDERR " In ShowVersion: $_" if ($debug); + + while () { + tr/\015//d; + last if(/^$prompt/); + next if(/^(\s*|\s*$cmd\s*)$/); + /^(\S+) Software, Version\s+(.*)$/ && + ProcessHistory("COMMENTS","keysort","F1", + "!Image: Software: $2\n") && next; + /^(\S+) S\/W compiled on (.*)$/ && + ProcessHistory("COMMENTS","keysort","F3", + "!Image: Compiled: $1 on $2\n") && next; + /^System Bootstrap (Version.*)$/ && + ProcessHistory("COMMENTS","keysort","G1", + "!Bootstrap: $1\n") && next; + if (/^Hardware Version: (\S+) Model: (\S+) Serial #: (\S+)/) { + my($proc) = $2; + # Really should figure out types of switches here. + $type = $2; + ProcessHistory("COMMENTS","keysort","A1", + "!Chassis type: $proc - a $type switch\n"); + ProcessHistory("COMMENTS","keysort","C1", "!Serial Number: $3\n"); + ProcessHistory("COMMENTS","keysort","C2", "!Hardware Version: $1\n"); + next; + } + # stuff module h/w, s/w, ports, etc into %module + if (/^Mod\s+Port\s+Model/) { + ; + my($slot); + while () { + tr/\015//d; + last if (/^\s*$/); + if (/^(\d+)\s+(\d+)\s+(\S+)\s+(\S+)\s+(\S+)\s?:\s+(\S+)/) { + $slot = $1; + $modules{$slot}->{ports} = $2; + $modules{$slot}->{model} = $3; + $modules{$slot}->{serial} = $4; + $modules{$slot}->{$5} = $6; # revision info + } + /^\s+(\S+)\s?:\s+(\S+)/ && + ($modules{$slot}->{$1} = $2); + } + next; + } + # stuff module h/w, s/w, ports, etc into %module - yet another format + if (/^Module\s+Ports\s+Model/) { + ; + my($slot); + while () { + tr/\015//d; + last if (/^\s*$/); + if (/^(\d+)\s+(\d+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+\s+)?(\S+)\s*$/) { + $slot = $1; + $modules{$slot}->{ports} = $2; + $modules{$slot}->{model} = $3; + $modules{$slot}->{serial} = $4; + $modules{$slot}->{Hw} = $5; + $modules{$slot}->{Fw} = $6; + $modules{$slot}->{Sw} = $8; + $modules{$slot}->{Fw1} = $7; + $modules{$slot}->{Fw1} =~ s/\s*$//; + if ($modules{$slot}->{Fw1} =~ /^$/) {delete($modules{$slot}->{Fw1});} + } + } + next; + } + if (/^ DRAM/) { + # Eat 2 lines & then get the total dram, flash, & nvram. + $_ = ; $_ = ; + $_ = ; tr/\015//d; + /\S+\s+(\S+)\s+\S+\s+\S+\s+(\S+)\s+\S+\s+\S+\s+(\S+)/ && + ProcessHistory("COMMENTS","keysort","B1", + "!Memory: dram $1\n") && + ProcessHistory("COMMENTS","keysort","B5", + "!Memory: flash $2\n") && + ProcessHistory("COMMENTS","keysort","B2", + "!Memory: nvram $3\n"); + next; + } + if (/^Module DRAM/) { + # Eat a line & then get the total dram, flash, & nvram. + $_ = ; + $_ = ; tr/\015//d; + /\S+\s+(\S+)\s+(\S+)\s+(\S+)/ && + ProcessHistory("COMMENTS","keysort","B1", + "!Memory: dram $1\n") && + ProcessHistory("COMMENTS","keysort","B5", + "!Memory: flash $2\n") && + ProcessHistory("COMMENTS","keysort","B2", + "!Memory: nvram $3\n"); + next; + } + } + return(0); +} + +# This routine parses "show install active" +sub ShowInstallActive { + print STDERR " In ShowInstallActive: $_" if ($debug); + + while () { + tr/\015//d; + last if (/^$prompt/); + next if (/^(\s*|\s*$cmd\s*)$/); + return(1) if /^\s*\^\s*$/; + return(1) if /Invalid input detected/; + return(1) if /Unknown command/; + ProcessHistory("COMMENTS","keysort","F5","!Image: $_") && next; + } + return(0); +} + +# This routine parses "show env all" +sub ShowEnv { + # Skip if this is not a 7500, 7200, or 7000. + print STDERR " In ShowEnv: $_" if ($debug); + + while () { + tr/\015//d; + last if (/^$prompt/); + next if (/^(\s*|\s*$cmd\s*)$/); + return(1) if ($type !~ /^7/); + if (!defined($E0)) { + $E0=1; + ProcessHistory("COMMENTS","keysort","E0","!\n"); + } + if (/^Arbiter type (\d), backplane type (\S+)/) { + if (!defined($C0)) { + $C0=1; ProcessHistory("COMMENTS","keysort","C0","!\n"); + } + ProcessHistory("COMMENTS","keysort","C1", + "!Enviromental Arbiter Type: $1\n"); + ProcessHistory("COMMENTS","keysort","A2", + "!Chassis type: $2 backplane\n"); + next; + } + /^\s*(Power .*)/ && + ProcessHistory("COMMENTS","keysort","E1","!Power: $1\n") && next; + /^\s*(Lower Power .*)/i && + ProcessHistory("COMMENTS","keysort","E2","!Power: $1\n") && next; + } + ProcessHistory("COMMENTS","","","!\n"); + return(0); +} + +# This routine parses "show gsr chassis-info" for the gsr +# This will create arrarys for hw info. +sub ShowGSR { + # Skip if this is not a 1200n. + print STDERR " In ShowGSR: $_" if ($debug); + + while () { + tr/\015//d; + last if (/^$prompt/); + next if (/^(\s*|\s*$cmd\s*)$/); + return(1) if ($type !~ /^120/); + /^$/ && next; + /^\s+Chassis: type (\S+) Fab Ver: (\S+)/ && + ProcessHistory("COMMENTS","keysort","D0","!\n") && + ProcessHistory("COMMENTS","keysort","D1", + "!GSR Chassis type: $1 Fab Ver: $2\n") && + next; + /^\s+Chassis S\/N: (.*)$/ && + ProcessHistory("COMMENTS","keysort","D2", + "!GSR Chassis S/N: $1\n") && + next; + /^\s+PCA: (\S+)\s*rev: (\S+)\s*dev: \S+\s*HW ver: (\S+)$/ && + ProcessHistory("COMMENTS","keysort","D3", + "!GSR Backplane PCA: $1, rev $2, ver $3\n") && + next; + /^\s+Backplane S\/N: (\S+)$/ && + ProcessHistory("COMMENTS","keysort","D4", + "!GSR Backplane S/N: $1\n") && + next; + } + ProcessHistory("COMMENTS","","","!\n"); + return(0); +} + +# This routine parses "show boot" +sub ShowBoot { + print STDERR " In ShowBoot: $_" if ($debug); + + while () { + tr/\015//d; + last if (/^$prompt/); + next if (/^(\s*|\s*$cmd\s*)$/); + return(1) if /^\s*\^\s*$/; + return(1) if /Ambiguous command/i; + return(1) if /Invalid input detected/; + return(1) if /Unknown command/; + return(1) if /(Open device \S+ failed|Error opening \S+:)/; + next if /CONFGEN variable/; + if (!defined($H0)) { + $H0=1; ProcessHistory("COMMENTS","keysort","H0","!\n"); + } + /^(\S+) variable (.*)$/ && + ProcessHistory("COMMENTS","keysort","H1","!Variable: $1 $2\n") && + next; + if (/^Configuration register is (.*)$/) { + $config_register=$1; + next; + } + } + ProcessHistory("COMMENTS","","","!\n"); + return(0); +} + +# This routine parses "show flash" +sub ShowFlash { + # skip if this is 7000, 7200, 7500, or 12000. + print STDERR " In ShowFlash: $_" if ($debug); + + while () { + tr/\015//d; + last if (/^$prompt/); + next if (/^(\s*|\s*$cmd\s*)$/); + return(1) if ($type =~ /^(120|7)/); + return(1) if /^\s*\^\s*$/; + return(1) if /Invalid input detected/; + ProcessHistory("FLASH","","","!Flash: $_"); + } + ProcessHistory("","","","!\n"); + return; +} + +# This routine parses "dir /all ((disk|slot)N|bootflash):" +sub DirSlotN { + # Skip if this is not a 3600, 7000, 7200, 7500, or 12000. + print STDERR " In DirSlotN: $_" if ($debug); + + my($dev) = (/\s([^\s]+):/); + + while () { + tr/\015//d; + last if (/^$prompt/); + next if (/^(\s*|\s*$cmd\s*)$/); + return(1) if ($type !~ /^(120|7|36)/); + return(1) if /^\s*\^\s*$/; + return(1) if /Invalid input detected/; + return(1) if /\%Error: No such file or directory/; + return(1) if /No space information available/; + return(-1) if /\%Error calling/; + return(-1) if /: device being squeezed/; # Flash is busy + return(1) if /(Open device \S+ failed|Error opening \S+:)/; + ProcessHistory("FLASH","","","!Flash: $dev: $_"); + } + ProcessHistory("","","","!\n"); + return(0); +} + +# This routine parses "show controllers" +sub ShowContAll { + # Skip if this is a 70[01]0, 7500, or 12000. + print STDERR " In ShowContAll: $_" if ($debug); + + while () { + tr/\015//d; + last if (/^$prompt/); + next if (/^(\s*|\s*$cmd\s*)$/); + return(1) if ($type =~ /^(120|7[05])/); + if (/^Interface ([^ \n(]*)/) { $INT = "$1, "; next; } + /^(BRI unit \d)/ && + ProcessHistory("INT","","","!Interface: $1\n") && next; + /^LANCE unit \d, NIM/ && + ProcessHistory("INT","","","!Interface: $_") && next; + /^(LANCE unit \d)/ && + ProcessHistory("INT","","","!Interface: $1\n") && next; + /(Media Type is \S+),/ && + ProcessHistory("INT","","","!\t$1\n"); + if (/(M\dT:) show controller:$/) { + my($ctlr) = $1; + $_ = ; tr/\015//d; s/ subunit \d,//; + ProcessHistory("INT","","","!Interface: $ctlr $_"); + } + if (/^(\S+) : show controller:$/) { + my($ctlr) = $1; + $_ = ; tr/\015//d; s/ subunit \d,//; + ProcessHistory("INT","","","!Interface: $ctlr: $_"); + } + /^(HD unit \d), idb/ && + ProcessHistory("INT","","","!Interface: $1\n") && next; + /^HD unit \d, NIM/ && + ProcessHistory("INT","","","!Interface: $_") && next; + /^buffer size \d+ HD unit \d, (.*)/ && + ProcessHistory("INT","","","!\t$1\n") && next; + /^AM79970 / && ProcessHistory("INT","","","!Interface: $_") && next; + /^buffer size \d+ (Universal Serial: .*)/ && + ProcessHistory("INT","","","!\t$1\n") && next; + /^Hardware is (.*)/ && + ProcessHistory("INT","","","!Interface: $INT$1\n") && next; + /^(QUICC Serial unit \d),/ && + ProcessHistory("INT","","","!$1\n") && next; + /^QUICC Ethernet .*/ && + ProcessHistory("INT","","","!$_") && next; + /^DTE .*\.$/ && + ProcessHistory("INT","","","!\t$_") && next; + /^(cable type :.*),/ && + ProcessHistory("INT","","","!\t$1\n") && next; + /^(.* cable.*), received clockrate \d+$/ && + ProcessHistory("INT","","","!\t$1\n") && next; + /^.* cable.*$/ && + ProcessHistory("INT","","","!\t$_") && next; + } + return(0); +} + +# This routine parses "show controllers cbus" +# Some of this is printed out in ShowDiagbus. +sub ShowContCbus { + # Skip if this is not a 7000 or 7500. + print STDERR " In ShowContCbus: $_" if ($debug); + + while () { + tr/\015//d; + last if (/^$prompt/); + next if (/^(\s*|\s*$cmd\s*)$/); + return(1) if ($type !~ /^7[05]0/); + if (/^\s*slot(\d+): ([^,]+), hw (\S+), sw (\S+), ccb/) { + $slot = $1; + $board{$slot} = $2; + $hwver{$slot} = $3; + $hwucode{$slot} = $4; + } elsif (/^\s*(\S+) (\d+), hardware version (\S+), microcode version (\S+)/) { + $slot = $2; + $board{$slot} = $1; + $hwver{$slot} = $3; + $hwucode{$slot} = $4; + } elsif (/(Microcode .*)/) { + $ucode{$slot} = $1; + } elsif (/(software loaded .*)/) { + $ucode{$slot} = $1; + } elsif (/(\d+) Kbytes of main memory, (\d+) Kbytes cache memory/) { + $hwmemd{$slot} = $1; + $hwmemc{$slot} = $2; + } elsif (/byte buffers/) { + chop; + s/^\s*//; + $hwbuf{$slot} = $_; + } elsif (/Interface (\d+) - (\S+ \S+),/) { + $interface = $1; + ProcessHistory("HW","","", + "!\n!Int $interface: in slot $slot, named $2\n"); next; + } elsif (/(\d+) buffer RX queue threshold, (\d+) buffer TX queue limit, buffer size (\d+)/) { + ProcessHistory("HW","","","!Int $interface: rxq $1, txq $2, bufsize $3\n"); + next; + } + } + return(0); +} + +# This routine parses "show diagbus" +# This will create arrarys for hw info. +sub ShowDiagbus { + # Skip if this is not a 7000, 70[01]0, or 7500. + print STDERR " In ShowDiagbus: $_" if ($debug); + + while () { + tr/\015//d; + last if (/^$prompt/); + next if (/^(\s*|\s*$cmd\s*)$/); + return(1) if ($type !~ /^7[05]/); + if (/^\s*Slot (\d+):/i) { + $slot = $1; + next; + } elsif (/^\s*Slot (\d+) \(virtual\):/i) { + $slot = $1; + next; + } elsif (/^\s*(.*Processor.*|.*controller|.*Chassis Interface), HW rev (\S+), board revision (\S+)/i) { + $board = $1; + $hwver = $2; + $boardrev = $3; + if ($board =~ /Processor/) { + if ($board =~ /7000 Route\/Switch/) { + $board = "RSP7000"; + } elsif ($board =~ /Route\/Switch Processor (\d)/) { + $board = "RSP$1"; + } elsif ($board =~ /Route/) { + $board = "RP"; + } elsif ($board =~ /Silicon Switch/) { + $board = "SSP"; + } elsif ($board =~ /Switch/) { + $board = "SP"; + $board = "SSP $sspmem" if $ssp; + } elsif ($board =~ /ATM/) { + $board = "AIP"; + } + } elsif ($board =~ /(.*) controller/i) { + $board = $1; + } + # hwucode{$slot} defined in ShowContCbus + if (defined $hwucode{$slot}) { + ProcessHistory("SLOT","","","!\n!Slot $slot/$board: hvers $hwver rev $boardrev ucode $hwucode{$slot}\n"); + } else { + ProcessHistory("SLOT","","","!\n!Slot $slot/$board: hvers $hwver rev $boardrev\n"); + } + # These are also from the ShowContCbus + ProcessHistory("SLOT","","","!Slot $slot/$board: $ucode{$slot}\n") if (defined $ucode{$slot}); + ProcessHistory("SLOT","","","!Slot $slot/$board: memd $hwmemd{$slot}, cache $hwmemc{$slot}\n") + if ((defined $hwmemd{$slot}) && (defined $hwmemc{$slot})); + ProcessHistory("SLOT","","","!Slot $slot/$board: $hwbuf{$slot}\n") if (defined $hwbuf{$slot}); + next; + } + /Serial number: (\S+)\s*Part number: (\S+)/ && + ProcessHistory("SLOT","","", + "!Slot $slot/$board: part $2, serial $1\n") && + next; + /^\s*Controller Memory Size: (.*)$/ && + ProcessHistory("SLOT","","","!Slot $slot/$board: $1\n") && + next; + if (/PA Bay (\d) Information/) { + $pano = $1; + if ("PA" =~ /$board/) { + ($s,$c) = split(/\//,$board); + $board = "$s/$c/PA $pano"; + } else { + $board =~ s/\/PA \d//; + $board = "$board/PA $pano"; + } + next; + } + /\s+(.*) PA, (\d) ports?, (\S+)/ && + ProcessHistory("SLOT","","","!Slot $slot/$board: type $3, $2 ports\n") && + next; + /\s+(.*) PA( \(\S+\))?, (\d) ports?/ && + ProcessHistory("SLOT","","","!Slot $slot/$board: type $1$2, $3 ports\n") && + next; + /^\s*HW rev (\S+), Board revision (\S+)/ && + ProcessHistory("SLOT","","","!Slot $slot/$board: hvers $1 rev $2\n") && + next; + /Serial number: (\S+)\s*Part number: (\S+)/ && + ProcessHistory("SLOT","","","!Slot $slot/$board: part $2, serial $1\n") && next; + } + return(0); +} + +# This routine parses "show diag" for the gsr, 7200, 3600, 2600. +# This will create arrarys for hw info. +sub ShowDiag { + # Skip if this is not a 12000. + print STDERR " In ShowDiag: $_" if ($debug); + + while () { + tr/\015//d; + last if (/^$prompt/); + next if (/^(\s*|\s*$cmd\s*)$/); + return(1) if ($type !~ /^(120|720|36|26)/); + /^$/ && next; + if (!defined($showdiags)) {$showdiags=1; ProcessHistory("SLOT","","","!\n");} + s/Port Packet Over SONET/POS/; + if (/^\s*SLOT (\d+)\s+\(.*\): (.*)/) { + $slot = $1; + ProcessHistory("SLOT","","","!Slot $slot: $2\n"); + $board = "RP" if (/Route Processor/); + $board = "CLK" if (/Clock Scheduler Card/); + next; + } + if (/^\s+PCA:\s+(.*)/){ + local($part) = $1; + $_ = ; + /^\s+HW version (\S+)\s+S\/N (\S+)/ && + ProcessHistory("SLOT","","","!Slot $slot/PCA: part $part, serial $2\n") && + ProcessHistory("SLOT","","","!Slot $slot/PCA: hvers $1\n"); + next; + } + + if (/^\s+MBUS: .*\)\s+(.*)/) { + local($tmp) = "!Slot $slot/MBUS: part $1"; + $_ = ; + /^\s+HW version (\S+)\s+S\/N (\S+)/ && + ProcessHistory("SLOT","","","$tmp, serial $2\n") && + ProcessHistory("SLOT","","","!Slot $slot/MBUS: hvers $1\n"); + next; + } + if (/^\s+MBUS Agent Software version (.*)/) { + local($sw) = $1; + local($tail) = "!\n" if ($board =~ /(CLK|RP)/); + ProcessHistory("SLOT","","","!Slot $slot/MBUS: software $sw\n$tail"); + next; + } + if (/^\s+DRAM size: (\d+)/) { + local($dram) = $1 / 1048576; + $_ = ; + /^\s+FrFab SDRAM size: (\d+)/ && + ProcessHistory("SLOT","","","!Slot $slot/MBUS: $dram Mbytes DRAM, " + . $1 / 1024 . " Kbytes SDRAM\n!\n"); + next; + } + # 7200 and 3600 stuff + if (/^(Slot)\s+(\d+):/ || /^\s+(WIC|VIC) Slot (\d):/) { + if ($1 eq "WIC") { + $WIC = "/$2"; + } elsif ($1 eq "VIC") { + $WIC = "/$2"; + } else { + $slot = $2; + undef($WIC); + } + $_ = ; tr/\015//d; + + # clean up hideous 7200 format to look more like 7500 output + s/Fast-ethernet on C7200 I\/O card/FE-IO/; + s/ with MII or RJ45/-TX/; + s/Fast-ethernet /100Base/; s/[)(]//g; + + /\s+(.*) port adapter,?\s+(\d+)\s+/i && + ProcessHistory("SLOT","","","!Slot $slot: type $1, $2 ports\n"); + # I/O controller with no interfaces + /\s+(.*)\s+port adapter\s*$/i && + ProcessHistory("SLOT","","","!Slot $slot: type $1, 0 ports\n"); + /\s+(.*)\s+daughter card(.*)$/ && + ProcessHistory("SLOT","","","!Slot $slot$WIC: type $1$2\n"); + /\s+(FT1)$/ && + ProcessHistory("SLOT","","","!Slot $slot$WIC: type $1\n"); + next; + } + /revision\s+(\S+).*revision\s+(\S+)/ && + ProcessHistory("SLOT","","","!Slot $slot$WIC: hvers $1 rev $2\n") && + next; + /number\s+(\S+)\s+Part number\s+(\S+)/ && + ProcessHistory("SLOT","","","!Slot $slot$WIC: part $2, serial $1\n!\n") && + next; +} + return(0); +} + +# This routine parses "show module" +sub ShowModule { + my($slot); + print STDERR " In ShowModule: $_" if ($debug); + +OUTER:while () { + tr/\015//d; + last if(/^$prompt/); + # stuff module type into %module + if (/^Mod\s+Slot\s+Ports/) { + ; + while () { + tr/\015//d; + last if (/^\s*$/); + last OUTER if (/^$prompt/); + if (/^Module .*mismatch/) { + ProcessHistory("MODWARN","","","!\n! WARNING: $_"); + while () { + tr/\015//d; + last OUTER if (/^\s*$/); + last if (/^\d/); + ProcessHistory("MODWARN","","","! $_"); + } + } + if (/^(\d+)\s+\d+\s+\d+\s+(.*)\s+\S+\s+\S+\s*$/) { + $modules{$1}->{type} = $2; + $modules{$1}->{type} =~ s/\s{2,}.*$//; + } + } + next; + } + # one does it one way... pita + if (/^Mod\s+Module-Name\s+Ports/) { + ; + #my($slot); + while () { + tr/\015//d; + last if (/^\s*$/); + last OUTER if (/^$prompt/); + if (/^(\d+)\s+(\S+\s+)?\d+\s+(.*)\s+\S+\s+(\S+)\s+\S+\s*$/) { + $modules{$1}->{serial} = $4; + $modules{$1}->{type} = $3; + #$modules{$1}->{type} =~ s/\s{2,}.*$//; + $modules{$1}->{type} =~ s/\s*$//; + } + } + next; + } + # daughter boards + if (/^Mod\s+Sub-Type/) { + ; + my($slot, $board); + while () { + tr/\015//d; + last if (/^\s*$/); + last OUTER if (/^$prompt/); + if (/^(\d+)\s+(\S+.*\s+)?(\S+)\s+(\S+)\s+(\S+)\s*$/) { + $board = 0 if ($slot != $1); + $slot = $1; + $modules{$1}->{daughter}->{$board}->{model} = $3; + $modules{$1}->{daughter}->{$board}->{serial} = $4; + $modules{$1}->{daughter}->{$board}->{Hw} = $5; + $modules{$1}->{daughter}->{$board}->{type} = $2; + $modules{$1}->{daughter}->{$board}->{type} =~ s/\s*$//; + $board++; + } + } + next; + } + } + + # dump the module info + foreach $slot (sort numerically keys(%modules)) { + my($dboards); + ProcessHistory("MODS","","","!\n"); + ProcessHistory("MODS","","",sprintf("!Slot $slot: type %s, %d ports\n", $modules{$slot}->{type}, $modules{$slot}->{ports})); + delete($modules{$slot}->{ports}); + delete($modules{$slot}->{type}); + my($model) = sprintf("!Slot $slot: part %s, serial %s\n", $modules{$slot}->{model}, $modules{$slot}->{serial}); + delete($modules{$slot}->{model}); + delete($modules{$slot}->{serial}); + # deal with daughter boards before slot versions + if (defined($modules{$slot}->{daughter})) { + my($board); + foreach $board (sort numerically keys(%{$modules{$slot}->{daughter}})) { + $dboards .= sprintf("!Slot $slot/$board: type %s\n", $modules{$slot}->{daughter}->{$board}->{type}); + $dboards .= sprintf("!Slot $slot/$board: hvers %s\n", $modules{$slot}->{daughter}->{$board}->{Hw}); + $dboards .= sprintf("!Slot $slot/$board: part %s, serial %s\n", $modules{$slot}->{daughter}->{$board}->{model}, $modules{$slot}->{daughter}->{$board}->{serial}); + } + delete($modules{$slot}->{daughter}); + } + my($ver); my($i) = 0; + ProcessHistory("MODS","","","!Slot $slot:"); + foreach $ver (sort keys(%{$modules{$slot}})) { + if ($i) {ProcessHistory("MODS","","",",");} + ProcessHistory("MODS","","",sprintf(" %s: %s", $ver, $modules{$slot}->{$ver})); + $i++; + } + ProcessHistory("MODS","","","\n"); + ProcessHistory("MODS","","",$model); + if ($dboards) {ProcessHistory("MODS","","",$dboards);} + } +} + +# This routine parses "show c7200" for the 7200 +# This will create arrarys for hw info. +sub ShowC7200 { + # Skip if this is not a 7200. + print STDERR " In ShowC7200: $_" if ($debug); + + while () { + tr/\015//d; + last if (/^$prompt/); + next if (/^(\s*|\s*$cmd\s*)$/); + return(1) if ($type !~ /^72/); + /^$/ && next; + if (/C7200 Midplane EEPROM:/) { + $_ = ; + /revision\s+(\S+).*revision\s+(\S+)/; + ProcessHistory("SLOT","","","!Slot Midplane: hvers $1 rev $2\n"); + $_ = ; + /number\s+(\S+)\s+Part number\s+(\S+)/; + ProcessHistory("SLOT","","","!Slot Midplane: part $2, serial $1\n!\n"); + next; + } + if (/C720\d(VXR)? CPU EEPROM:/) { + $_ = ; + /revision\s+(\S+).*revision\s+(\S+)/ && + ProcessHistory("SLOT","","","!Slot CPU: hvers $1 rev $2\n"); + $_ = ; + /number\s+(\S+)\s+Part number\s+(\S+)/ && + ProcessHistory("SLOT","","","!Slot CPU: part $2, serial $1\n!\n"); + next; + } + } + return(0); +} + +# This routine processes a "write term" +sub WriteTerm { + print STDERR " In WriteTerm: $_" if ($debug); + + ProcessHistory("","","","!\n"); + while () { + tr/\015//d; + last if (/^$prompt/); + next if (/^\.+$/ | /^$/); + /Non-Volatile memory is in use/ && return(-1); # NvRAM is locked + # skip the crap + next if (/^This command shows non-default configurations only./i); + next if (/^Use 'write terminal all' to show both default and non/i); + if (/^(\.\.+$|##+$|Building configuration...)/i) { + while () { + tr/\015//d; + next if (/^Current configuration:/i); + next if (/^(\.+|[%!].*|\s*)$/); + next if (/^ip add.*ipv4:/); # band-aid for 3620 12.0S + last; + } + ProcessHistory("","","","!\n"); + if (defined($config_register)) { + ProcessHistory("","","","config-register $config_register\n"); + } + tr/\015//d; + } + # some versions have other crap mixed in with the bits in the + # block above + /^! (Last configuration|NVRAM config last)/ && next; + + # Dog gone Cool matches to process the rest of the config + /^#time: / && next; # kill time: + /^tftp-server flash / && next; # kill any tftp remains + /^ntp clock-period / && next; # kill ntp clock-period + /^ length / && next; # kill length on serial lines + /^ width / && next; # kill width on serial lines + /^enable password / && + ProcessHistory("ENABLE","","","!enable password \n") && + next; + /^(username .*) password /&& + ProcessHistory("USER","","","!$1 password \n") && next; + /^\s*password / && + ProcessHistory("LINE-PASS","","","! password \n") && next; + /^\s*neighbor (\S*) password / && + ProcessHistory("","","","! neighbor $1 password \n") && + next; + /^(ip ftp password) / && + ProcessHistory("","","","!$1 \n") && next; + /^( ip ospf authentication-key) / && + ProcessHistory("","","","!$1 \n") && next; + /^( ip ospf message-digest-key \d+ md5) / && + ProcessHistory("","","","!$1 \n") && next; + /fair-queue individual-limit/ && next; + # sort ip explicit-paths. + if (/^ip explicit-path name (\S+)/) { + my($key) = $1; + my($expath) = $_; + while () { + tr/\015//d; + last if (/^$prompt/); + last if (/^$prompt/ || ! /^(ip explicit-path name |[ !])/); + if (/^ip explicit-path name (\S+)/) { + ProcessHistory("EXPATH","keysort","$key","$expath"); + $key = $1; + $expath = $_; + } else { + $expath .= $_; + } + } + ProcessHistory("EXPATH","keysort","$key","$expath"); + } + # sort route-maps + if (/^route-map (\S+)/) { + my($key) = $1; + my($routemap) = $_; + while () { + tr/\015//d; + last if (/^$prompt/ || ! /^(route-map |[ !])/); + if (/^route-map (\S+)/) { + ProcessHistory("ROUTEMAP","keysort","$key","$routemap"); + $key = $1; + $routemap = $_; + } else { + $routemap .= $_; + } + } + ProcessHistory("ROUTEMAP","keysort","$key","$routemap"); + } + # filter out any RCS/CVS tags to avoid confusing local CVS storage + s/\$(Revision|Id):/ $1:/; + # order access-lists + /^access-list\s+(\d\d?)\s+(\S+)\s+(\S+)/ && + ProcessHistory("ACL $1 $2","ipsort","$3","$_") && next; + # order extended access-lists + /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+host\s+(\S+)/ && + ProcessHistory("EACL $1 $2","ipsort","$3","$_") && next; + /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+(\d\S+)/ && + ProcessHistory("EACL $1 $2","ipsort","$3","$_") && next; + /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+any/ && + ProcessHistory("EACL $1 $2","ipsort","0.0.0.0","$_") && next; + # order arp lists + /^set arp\s+(\d+\.\d+\.\d+\.\d+)\s+/ && + ProcessHistory("ARP","ipsort","$1","$_") && next; + /^ip prefix-list\s+(\S+)\s+seq\s+(\d+)\s+(permit|deny)\s+(\d\S+)(\/.*)$/ && + ProcessHistory("PACL $1 $3","ipsort","$4","ip prefix-list $1 $3 $4$5\n") + && next; + # order logging statements + /^set logging server (\d+\.\d+\.\d+\.\d+)/ && + ProcessHistory("LOGGING","ipsort","$1","$_") && next; + # order name-server statements + /^set ip dns server (\d+\.\d+\.\d+\.\d+)/ && + ProcessHistory("NAMESERVER","ipsort","$1","$_") && next; + # order/prune snmp-server host statements + # we only prune lines of the form + # snmp-server host a.b.c.d + if (/^set snmp trap (\d+\.\d+\.\d+\.\d+) /) { + if (defined($ENV{'NOCOMMSTR'})) { + ProcessHistory("SNMPSERVERHOST","ipsort","$1","!set snmp trap $1 \n"); + } else { + ProcessHistory("SNMPSERVERHOST","ipsort","$1","$_"); + } + next; + } + if (/^(set snmp community) (\S+) (\S+)/) { + if (defined($ENV{'NOCOMMSTR'})) { + ProcessHistory("SNMPSERVERCOMM","keysort","$_","!$1 $2 \n"); + } else { + ProcessHistory("SNMPSERVERCOMM","keysort","$_","$_") + } + next; + } + # order tacacs server statements + /^set (tacacs) key / && + ProcessHistory("","","","!set $1 key \n") && next; + /^set tacacs server (\d+\.\d+\.\d+\.\d+)/ && + ProcessHistory("TAC","ipsort","$1","$_") && next; + # order clns host statements + /^clns host \S+ (\S+)/ && + ProcessHistory("CLNS","keysort","$1","$_") && next; + # order alias statements + /^alias / && ProcessHistory("ALIAS","keysort","$_","$_") && next; + # delete ntp auth password + /^(ntp authentication-key \d+ md5) / && + ProcessHistory("","","","!$1 \n") && next; + # order ntp peers/servers + if (/^ntp (server|peer) (\d+)\.(\d+)\.(\d+)\.(\d+)/) { + $sortkey = sprintf("$1 %03d%03d%03d%03d",$2,$3,$4,$5); + ProcessHistory("NTP","keysort",$sortkey,"$_"); + next; + } + # order ip host line statements + /^ip host line(\d+)/ && + ProcessHistory("IPHOST","numsort","$1","$_") && next; + # order ip nat source static statements + /^ip nat (\S+) source static (\S+)/ && + ProcessHistory("IP NAT $1","ipsort","$2","$_") && next; + # order atm map-list statements + /^\s+ip\s+(\d+\.\d+\.\d+\.\d+)\s+atm-vc/ && + ProcessHistory("ATM map-list","ipsort","$1","$_") && next; + # order ip rcmd lines + /^ip rcmd/ && ProcessHistory("RCMD","keysort","$_","$_") && next; + + ProcessHistory("","","","$_"); + # end of config + if (/^end$/) { + $found_end = 1; + return(1); + } + } + return(0); +} + +# dummy function +sub DoNothing {print STDOUT;} + +# Main +%commands=( + 'show version' => "ShowVersion", + 'show boot' => "ShowBoot", + 'show flash' => "ShowFlash", + 'dir bootflash:' => "DirSlotN", + 'dir slot0:' => "DirSlotN", + 'dir slot1:' => "DirSlotN", + 'show module' => "ShowModule", + 'write term' => "WriteTerm" +); +# keys() doesnt return things in the order entered and the order of the +# cmds is important (show version first and write term last). pita +@commands=( + "show version", + "show boot", + "show flash", + "dir bootflash:", + "dir slot0:", + "dir slot1:", + "show module", + "write term" +); +$cisco_cmds=join(";",@commands); +$cmds_regexp=join("|",@commands); + +open(OUTPUT,">$host.new") || die "Can't open $host.new for writing: $!\n"; +select(OUTPUT); +# make OUTPUT unbuffered if debugging +if ($debug) { $| = 1; } + +if ($file) { + print STDERR "opening file $host\n" if ($debug); + print STDOUT "opening file $host\n" if ($log); + open(INPUT,"<$host") || die "open failed for $host: $!\n"; +} else { + print STDERR "executing clogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($debug); + print STDOUT "executing clogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($log); + if (defined($ENV{NOPIPE})) { + system "clogin -t $timeo -c \"$cisco_cmds\" $host $host.raw 2>&1" || die "clogin failed for $host: $!\n"; + open(INPUT, "< $host.raw") || die "clogin failed for $host: $!\n"; + } else { + open(INPUT,"clogin -t $timeo -c \"$cisco_cmds\" $host ) { + tr/\015//d; + if (/> \(enable\) exit$/) { + $clean_run=1; + last; + } + if (/Error:/) { + s/^.*Error:/Error:/; + print STDOUT ("$host clogin error: $_"); + print STDERR ("$host clogin error: $_") if ($debug); + $clean_run=0; + last; + } + while (/> \(enable\)\s*($cmds_regexp)\s*$/) { + $cmd = $1; + if (!defined($prompt)) {$prompt = ($_ =~ /^([^>]+>)/)[0]; } + print STDERR ("HIT COMMAND:$_") if ($debug); + if (! defined($commands{$cmd})) { + print STDERR "found unexpected command - \"$cmd\"\n"; + $clean_run = 0; + last TOP; + } + $rval = &{$commands{$cmd}}; + delete($commands{$cmd}); + if ($rval == -1) { + $clean_run = 0; + last TOP; + } + } +} +print STDOUT "Done $logincmd: $_\n" if ($log); +# Flush History +ProcessHistory("","","",""); +# Cleanup +close(INPUT); +close(OUTPUT); + +if (defined($ENV{NOPIPE})) { + unlink("$host.raw") if (! $debug); +} + +# check for completeness +if (scalar(%commands) || !$clean_run || !$found_end) { + if (scalar(%commands)) { + printf(STDOUT "missed cmd(s): %s\n", join(',', keys(%commands))); + printf(STDERR "missed cmd(s): %s\n", join(',', keys(%commands))) if ($debug); + } + if (!$clean_run || !$found_end) { + print STDOUT "End of run not found\n"; + print STDERR "End of run not found\n" if ($debug); + system("/usr/bin/tail -1 $host.new"); + } + unlink "$host.new" if (! $debug); +} diff --git a/bin/clogin b/bin/clogin deleted file mode 100755 index 1b345be..0000000 --- a/bin/clogin +++ /dev/null @@ -1,560 +0,0 @@ -#!/usr/local/bin/expect -- -## -## -## Copyright (C) 1997 by Henry Kilmer, Erik Sherk and Pete Whiting. -## All rights reserved. -## -## This software may be freely copied, modified and redistributed without -## fee for non-commerical purposes provided that this copyright notice is -## preserved intact on all copies and modified copies. -## -## There is no warranty or other guarantee of fitness of this software. -## It is provided solely "as is". The author(s) disclaim(s) all -## responsibility and liability with respect to this software's usage -## or its effect upon hardware, computer systems, other software, or -## anything else. -## -## -# -# clogin - Cisco login -# -# Most options are intuitive for logging into a Cisco router. -# The default is to enable (thus -noenable). Some folks have -# setup tacacs to have a user login at priv-lvl = 15 (enabled) -# so the -autoenable flag was added for this case (don't go through -# the process of enabling and the prompt will be the "#" prompt. -# The default username password is the same as the vty password. -# - -# Usage line -set usage "Usage: $argv0 \[-autoenable\] \[-noenable\] \[-c command\] \ -\[-e enable-password\] \[-f cloginrc-file\] \[-p user-password\] \ -\[-s script-file\] \[-t timeout\] \[-u username\] \ -\[-v vty-password\] \[-w enable-username\] \[-x command-file\] \ -\[-y ssh_cypher_type\] router \[router...\]\n" - -# env(CLOGIN) may contain: -# x == do not set xterm banner or name - -# Password file -set password_file $env(HOME)/.cloginrc -# Default is to login to the router -set do_command 0 -set do_script 0 -# The default is to automatically enable -set enable 1 -# The default is that you login non-enabled (tacacs can have you login already enabled) -set autoenable 0 -# The default is to look in the password file to find the passwords. This -# tracks if we receive them on the command line. -set do_passwd 1 -set do_enapasswd 1 - -# Find the user in the ENV, or use the unix userid. -if {[ info exists env(CISCO_USER) ] } { - set default_user $env(CISCO_USER) -} else { - # This uses "id" which I think is portable. At least it has existed - # (without options) on all machines/OSes I've been on recently - - # unlike whoami or id -nu. - regexp {\(([^)]*)} [exec id] junk default_user -} - -# Sometimes routers take awhile to answer (the default is 10 sec) -set timeout 45 - -# Process the command line -for {set i 0} {$i < $argc} {incr i} { - set arg [lindex $argv $i] - - switch -glob -- $arg { - # Username - -u* - - -U* { - if {! [ regexp .\[uU\](.+) $arg ignore user]} { - incr i - set username [ lindex $argv $i ] - } - # VTY Password - } -p* - - -P* { - if {! [ regexp .\[pP\](.+) $arg ignore userpasswd]} { - incr i - set userpasswd [ lindex $argv $i ] - } - set do_passwd 0 - # VTY Password - } -v* - - -v* { - if {! [ regexp .\[vV\](.+) $arg ignore passwd]} { - incr i - set passwd [ lindex $argv $i ] - } - set do_passwd 0 - # Enable Username - } -w* - - -W* { - if {! [ regexp .\[wW\](.+) $arg ignore enauser]} { - incr i - set enausername [ lindex $argv $i ] - } - # Enable Password - } -e* - - -E* { - if {! [ regexp .\[eE\](.+) $arg ignore enapasswd]} { - incr i - set enapasswd [ lindex $argv $i ] - } - set do_enapasswd 0 - # Command to run. - } -c* - - -C* { - if {! [ regexp .\[cC\](.+) $arg ignore command]} { - incr i - set command [ lindex $argv $i ] - } - set do_command 1 - # Expect script to run. - } -s* - - -S* { - if {! [ regexp .\[sS\](.+) $arg ignore sfile]} { - incr i - set sfile [ lindex $argv $i ] - } - if { ! [ file readable $sfile ] } { - send_user "Error: Can't read $sfile\n" - exit 1 - } - set do_script 1 - # 'ssh -c' cypher type - } -y* - - -Y* { - if {! [ regexp .\[eE\](.+) $arg ignore cypher]} { - incr i - set cypher [ lindex $argv $i ] - } - # alternate cloginrc file - } -f* - - -F* { - if {! [ regexp .\[fF\](.+) $arg ignore password_file]} { - incr i - set password_file [ lindex $argv $i ] - } - # Timeout - } -t* - - -T* { - if {! [ regexp .\[tT\](.+) $arg ignore timeout]} { - incr i - set timeout [ lindex $argv $i ] - } - # Command file - } -x* - - -X { - if {! [ regexp .\[xX\](.+) $arg ignore cmd_file]} { - incr i - set cmd_file [ lindex $argv $i ] - } - set cmd_fd [open $cmd_file r] - set cmd_text [read $cmd_fd] - close $cmd_fd - set command [join [split $cmd_text \n] \;] - set do_command 1 - # Do we enable? - } -noenable { - set enable 0 - # Does tacacs automatically enable us? - } -autoenable { - set autoenable 1 - set enable 0 - } -* { - send_user "Error: Unknown argument! $arg\n" - send_user $usage - exit 1 - } default { - break - } - } -} -# Process routers...no routers listed is an error. -if { $i == $argc } { - send_user "Error: $usage" -} - -# Only be quiet if we are running a script (it can log its output -# on its own) -if { $do_script } { - log_user 0 -} else { - log_user 1 -} - -# -# Done configuration/variable setting. Now run with it... -# - -# Sets Xterm title if interactive...if its an xterm and the user cares -proc label { host } { - global env - # if CLOGIN has an 'x' in it, don't set the xterm name/banner - if [info exists env(CLOGIN)] { - if {[string first "x" $env(CLOGIN)] != -1} { return } - } - # take host from ENV(TERM) - if [info exists env(TERM)] { - if [regexp \^(xterm|vs) $env(TERM) ignore ] { - send_user "\033]1;[lindex [split $host "."] 0]\a" - send_user "\033]2;$host\a" - } - } -} - -# This is a helper function to make the password file easier to -# maintain. Using this the password file has the form: -# add password sl* pete cow -# add password at* steve -# add password * hanky-pie -proc add {var args} { global $var ;lappend $var $args} -proc find {var router} { - source_password_file - upvar $var list - if { [info exists list] } { - foreach line $list { - if { [string match [lindex $line 0] $router ] } { - return [lrange $line 1 end] - } - } - } - return {} -} - -# Loads the password file. Note that as this file is tcl, and that -# it is sourced, the user better know what to put in there, as it -# could install more than just password info... I will assume however, -# that a "bad guy" could just as easy put such code in the clogin -# script, so I will leave .cloginrc as just an extention of that script -proc source_password_file { } { - global env password_file read_password_file - if { [info exists read_password_file] } { return } - if { [info exists password_file] == 0 } { - set password_file $env(HOME)/.cloginrc - } - if { ! [file exists $password_file] } { - send_user "Error: password file ($password_file) does not exist\n" - exit 1 - } - set read_password_file 1 - file stat $password_file fileinfo - if { [expr ($fileinfo(mode) & 007)] != 0000 } { - send_user "Error: $password_file must not be world readable/writable\n" - exit 1 - } - source $password_file -} - -# Log into the router. -proc login { router user userpswd passwd enapasswd prompt cyphertype } { - global spawn_id in_proc do_command do_script - global u_prompt p_prompt e_prompt - set in_proc 1 - set tryssh 1 - - # Telnet to the router & try to login. - if [ catch {spawn telnet $router} reason ] { - send_user "Error: failed to telnet: $reason\n" - exit 1 - } - sleep 0.3 - - # This helps cleanup each expect clause. - expect_after { - timeout { - send_user "\nError: TIMEOUT reached\n" - catch {close}; wait - if { $in_proc} { - return 1 - } else { - continue - } - } eof { - send_user "\nError: EOF received\n" - catch {close}; wait - if { $in_proc} { - return 1 - } else { - continue - } - } - } - - # Here we get a little tricky. There are several possibilities: - # the router can ask for a username and passwd and then - # talk to the TACACS server to authenticate you, or if the - # TACACS server is not working, then it will use the enable - # passwd. Or, the router might not have TACACS turned on, - # then it will just send the passwd. - # if telnet fails with connection refused, try ssh - expect { - "Connection refused" { - close; wait - if { $tryssh } { - if [ catch {spawn ssh -c $cyphertype -x -l $user $router} reason ] { - send_user "Error: failed to ssh: $reason\n" - exit 1 - } - set tryssh 0 - sleep 0.3 - exp_continue - } else { - expect eof - send_user "Error: Connection Refused\n"; wait; return 1 - } - } eof { send_user "Error: Couldn't login\n"; wait; return 1 - } "Unknown host\r\n" { - expect eof - send_user "Error: Unknown host\n"; wait; return 1 - } "Host is unreachable" { - expect eof - send_user "Error: Host Unreachable!\n"; wait; return 1 - } "No address associated with name" { - expect eof - send_user "Error: Unknown host\n"; wait; return 1 - } - -re "Host key not found .* \(yes\/no\)\?" { - send "yes\r" - send_user "Host $router added to the list of known hosts.\n" - exp_continue } - -re "HOST IDENTIFICATION HAS CHANGED.* \(yes\/no\)\?" { - send "no\r" - send_user "Error: The host key for $router has changed. update the known_hosts file accordingly.\n" - return 1 } - -re "$u_prompt" { send "$user\r" - expect { - eof { send_user "Error: Couldn't login\n"; wait; return 1 } - -re "$p_prompt" { send "$userpswd\r" } - "$prompt" { set in_proc 0; return 0 } - } - exp_continue - } - -re "$p_prompt" { send "$passwd\r" - expect { - eof { send_user "Error: Couldn't login\n"; wait; return 1 } - -re "$e_prompt" { send "$enapasswd\r" } - "$prompt" { set in_proc 0; return 0 } - } - exp_continue - } - "$prompt" { } - denied { send_user "Error: Check your passwd for $router\n" - if { $do_command || $do_script } { - send "exit\r" - wait - return 1 - } else { - return 1 - } - } - "% Bad passwords" {send_user "Error: Check your passwd for $router\n"; return 1 } - } - set in_proc 0 - return 0 -} - -# Enable -proc do_enable { enauser enapasswd } { - global prompt in_proc - global u_prompt e_prompt - set in_proc 1 - - send "enable\r" - expect { - -re "$u_prompt" { send "$enauser\r"; exp_continue} - -re "$e_prompt" { send "$enapasswd\r"; exp_continue} - "#" { set prompt "#" } - "(enable)" { set prompt "> (enable) " } - denied { send_user "Error: Check your Enable passwd\n"; return 1} - "% Bad passwords" { send_user "Error: Check your Enable passwd\n" - return 1 - } - } - # We set the prompt variable (above) so script files don't need - # to know what it is. - set in_proc 0 - return 0 -} - -# Run commands given on the command line. -proc run_commands { prompt command } { - global in_proc - set in_proc 1 - - # If the prompt is (enable), then we are on a switch and the - # command is "set length 0"; otherwise its "term length 0". - if [ string compare "> (enable) " "$prompt" ] { - send "term length 0\r" - } else { - send "set length 0\r" - } - - expect $prompt {} - - regsub -all "\[)(]" $prompt {\\&} reprompt - - # Is this a multi-command? - if [ string match "*\;*" "$command" ] { - set commands [split $command \;] - set num_commands [llength $commands] - - for {set i 0} {$i < $num_commands} { incr i} { - send "[subst -nocommands [lindex $commands $i]]\r" - expect { - -re "^\[^\n\r]*$reprompt." { exp_continue } - -re "^\[^\n\r *]*$reprompt" {} - -re "\[\n\r]" { exp_continue } - } - } - } else { - send "[subst -nocommands $command]\r" - expect { - -re "^\[^\n\r]*$reprompt." { exp_continue } - -re "^\[^\n\r *]*$reprompt" {} - -re "\[\n\r]" { exp_continue } - } - } - send "exit\r" - expect { - "\n" { exp_continue } - timeout { return 0 } - eof { return 0 } - } - set in_proc 0 -} - -# -# For each router... (this is main loop) -# -set in_proc 0 -foreach router [lrange $argv $i end] { - set router [string tolower $router] - send_user "$router\n" - - # Figure out prompt. - # Since autoenable is off by default, if we have it defined, it - # was done on the command line. If it is not specifically set on the - # command line, check the password file. - if $autoenable { - set prompt "#" - } else { - set ae [find autoenable $router] - if { "$ae" == "1" } { - set autoenable 1 - set enable 0 - set prompt "#" - } else { - set autoenable 0 - set prompt ">" - } - } - - # look for noenable option in .cloginrc - if { [find noenable $router] != "" } { - set enable 0 - } - - # Figure out passwords - if { $do_passwd || $do_enapasswd } { - set pswd [find password $router] - if { [llength $pswd] == 0 } { - send_user "Error - no password for $router in $password_file.\n" - continue - } - if { $do_enapasswd && $autoenable == 0 && [llength $pswd] < 2 } { - send_user "Error - no enable password for $router in $password_file.\n" - continue - } - set passwd [lindex $pswd 0] - set enapasswd [lindex $pswd 1] - } - - # Figure out username - if {[info exists username]} { - # command line username - set ruser $username - } else { - set ruser [find user $router] - if { "$ruser" == "" } { set ruser $default_user } - } - - # Figure out username's password (if different from the vty password) - if {[info exists userpasswd]} { - # command line username - set userpswd $userpasswd - } else { - set userpswd [find userpassword $router] - if { "$userpswd" == "" } { set userpswd $passwd } - } - - # Figure out enable username - if {[info exists enausername]} { - # command line enausername - set enauser $enausername - } else { - set enauser [find enauser $router] - if { "$enauser" == "" } { set enauser $ruser } - } - - # Figure out prompts - set u_prompt [find userprompt $router] - if { "$u_prompt" == "" } { set u_prompt "(Username|login):" } - set p_prompt [find passprompt $router] - if { "$p_prompt" == "" } { set p_prompt "\[Pp]assword:" } - set e_prompt [find enableprompt $router] - if { "$e_prompt" == "" } { set e_prompt "\[Pp]assword:" } - - # Figure out cypher type - if {[info exists cypher]} { - # command line cypher type - set cyphertype $cypher - } else { - set cyphertype [find cyphertype $router] - if { "$cyphertype" == "" } { set cyphertype "3des" } - } - - # Login to the router - if {[login $router $ruser $userpswd $passwd $enapasswd $prompt $cyphertype]} { - continue - } - if { $enable } { - if {[do_enable $enauser $enapasswd]} { - if { $do_command || $do_script } { - close; wait - continue - } - } - } - - if { $do_command } { - if {[run_commands $prompt $command]} { - continue - } - } elseif { $do_script } { - # If the prompt is (enable), then we are on a switch and the - # command is "set length 0"; otherwise its "term length 0". - if [ string compare "> (enable) " "$prompt" ] { - send "term length 0\r" - } else { - send "set length 0\r" - } - expect $prompt {} - source $sfile - close - } else { - label $router - log_user 1 - interact - } - - # End of for each router - wait - sleep 0.3 -} -exit 0 diff --git a/bin/clogin.in b/bin/clogin.in new file mode 100755 index 0000000..bfe3ae1 --- /dev/null +++ b/bin/clogin.in @@ -0,0 +1,587 @@ +#!@EXPECT_PATH@ -- +## +## +## Copyright (C) 1997 by Henry Kilmer, Erik Sherk and Pete Whiting. +## All rights reserved. +## +## This software may be freely copied, modified and redistributed without +## fee for non-commerical purposes provided that this copyright notice is +## preserved intact on all copies and modified copies. +## +## There is no warranty or other guarantee of fitness of this software. +## It is provided solely "as is". The author(s) disclaim(s) all +## responsibility and liability with respect to this software's usage +## or its effect upon hardware, computer systems, other software, or +## anything else. +## +## +# +# clogin - Cisco login +# +# Most options are intuitive for logging into a Cisco router. +# The default is to enable (thus -noenable). Some folks have +# setup tacacs to have a user login at priv-lvl = 15 (enabled) +# so the -autoenable flag was added for this case (don't go through +# the process of enabling and the prompt will be the "#" prompt. +# The default username password is the same as the vty password. +# + +# Usage line +set usage "Usage: $argv0 \[-autoenable\] \[-noenable\] \[-c command\] \ +\[-e enable-password\] \[-f cloginrc-file\] \[-p user-password\] \ +\[-s script-file\] \[-t timeout\] \[-u username\] \ +\[-v vty-password\] \[-w enable-username\] \[-x command-file\] \ +\[-y ssh_cypher_type\] router \[router...\]\n" + +# env(CLOGIN) may contain: +# x == do not set xterm banner or name + +# Password file +set password_file $env(HOME)/.cloginrc +# Default is to login to the router +set do_command 0 +set do_script 0 +# The default is to automatically enable +set enable 1 +# The default is that you login non-enabled (tacacs can have you login already enabled) +set autoenable 0 +# The default is to look in the password file to find the passwords. This +# tracks if we receive them on the command line. +set do_passwd 1 +set do_enapasswd 1 + +# Find the user in the ENV, or use the unix userid. +if {[ info exists env(CISCO_USER) ] } { + set default_user $env(CISCO_USER) +} else { + # This uses "id" which I think is portable. At least it has existed + # (without options) on all machines/OSes I've been on recently - + # unlike whoami or id -nu. + regexp {\(([^)]*)} [exec id] junk default_user +} + +# Sometimes routers take awhile to answer (the default is 10 sec) +set timeout 45 + +# Process the command line +for {set i 0} {$i < $argc} {incr i} { + set arg [lindex $argv $i] + + switch -glob -- $arg { + # Username + -u* - + -U* { + if {! [ regexp .\[uU\](.+) $arg ignore user]} { + incr i + set username [ lindex $argv $i ] + } + # VTY Password + } -p* - + -P* { + if {! [ regexp .\[pP\](.+) $arg ignore userpasswd]} { + incr i + set userpasswd [ lindex $argv $i ] + } + set do_passwd 0 + # VTY Password + } -v* - + -v* { + if {! [ regexp .\[vV\](.+) $arg ignore passwd]} { + incr i + set passwd [ lindex $argv $i ] + } + set do_passwd 0 + # Enable Username + } -w* - + -W* { + if {! [ regexp .\[wW\](.+) $arg ignore enauser]} { + incr i + set enausername [ lindex $argv $i ] + } + # Enable Password + } -e* - + -E* { + if {! [ regexp .\[eE\](.+) $arg ignore enapasswd]} { + incr i + set enapasswd [ lindex $argv $i ] + } + set do_enapasswd 0 + # Command to run. + } -c* - + -C* { + if {! [ regexp .\[cC\](.+) $arg ignore command]} { + incr i + set command [ lindex $argv $i ] + } + set do_command 1 + # Expect script to run. + } -s* - + -S* { + if {! [ regexp .\[sS\](.+) $arg ignore sfile]} { + incr i + set sfile [ lindex $argv $i ] + } + if { ! [ file readable $sfile ] } { + send_user "Error: Can't read $sfile\n" + exit 1 + } + set do_script 1 + # 'ssh -c' cypher type + } -y* - + -Y* { + if {! [ regexp .\[eE\](.+) $arg ignore cypher]} { + incr i + set cypher [ lindex $argv $i ] + } + # alternate cloginrc file + } -f* - + -F* { + if {! [ regexp .\[fF\](.+) $arg ignore password_file]} { + incr i + set password_file [ lindex $argv $i ] + } + # Timeout + } -t* - + -T* { + if {! [ regexp .\[tT\](.+) $arg ignore timeout]} { + incr i + set timeout [ lindex $argv $i ] + } + # Command file + } -x* - + -X { + if {! [ regexp .\[xX\](.+) $arg ignore cmd_file]} { + incr i + set cmd_file [ lindex $argv $i ] + } + set cmd_fd [open $cmd_file r] + set cmd_text [read $cmd_fd] + close $cmd_fd + set command [join [split $cmd_text \n] \;] + set do_command 1 + # Do we enable? + } -noenable { + set enable 0 + # Does tacacs automatically enable us? + } -autoenable { + set autoenable 1 + set enable 0 + } -* { + send_user "Error: Unknown argument! $arg\n" + send_user $usage + exit 1 + } default { + break + } + } +} +# Process routers...no routers listed is an error. +if { $i == $argc } { + send_user "Error: $usage" +} + +# Only be quiet if we are running a script (it can log its output +# on its own) +if { $do_script } { + log_user 0 +} else { + log_user 1 +} + +# +# Done configuration/variable setting. Now run with it... +# + +# Sets Xterm title if interactive...if its an xterm and the user cares +proc label { host } { + global env + # if CLOGIN has an 'x' in it, don't set the xterm name/banner + if [info exists env(CLOGIN)] { + if {[string first "x" $env(CLOGIN)] != -1} { return } + } + # take host from ENV(TERM) + if [info exists env(TERM)] { + if [regexp \^(xterm|vs) $env(TERM) ignore ] { + send_user "\033]1;[lindex [split $host "."] 0]\a" + send_user "\033]2;$host\a" + } + } +} + +# This is a helper function to make the password file easier to +# maintain. Using this the password file has the form: +# add password sl* pete cow +# add password at* steve +# add password * hanky-pie +proc add {var args} { global $var ;lappend $var $args} +proc find {var router} { + source_password_file + upvar $var list + if { [info exists list] } { + foreach line $list { + if { [string match [lindex $line 0] $router ] } { + return [lrange $line 1 end] + } + } + } + return {} +} + +# Loads the password file. Note that as this file is tcl, and that +# it is sourced, the user better know what to put in there, as it +# could install more than just password info... I will assume however, +# that a "bad guy" could just as easy put such code in the clogin +# script, so I will leave .cloginrc as just an extention of that script +proc source_password_file { } { + global env password_file read_password_file + if { [info exists read_password_file] } { return } + if { [info exists password_file] == 0 } { + set password_file $env(HOME)/.cloginrc + } + if { ! [file exists $password_file] } { + send_user "Error: password file ($password_file) does not exist\n" + exit 1 + } + set read_password_file 1 + file stat $password_file fileinfo + if { [expr ($fileinfo(mode) & 007)] != 0000 } { + send_user "Error: $password_file must not be world readable/writable\n" + exit 1 + } + source $password_file +} + +# Log into the router. +proc login { router user userpswd passwd enapasswd prompt cmethod cyphertype } { + global spawn_id in_proc do_command do_script + global u_prompt p_prompt e_prompt + set in_proc 1 + + # try each of the connection methods in $cmethod until one is successful + set progs [llength $cmethod] + foreach prog [lrange $cmethod 0 end] { + if ![string compare $prog "telnet"] { + if [ catch {spawn telnet $router} reason ] { + send_user "Error: telnet failed: $reason\n" + exit 1 + } + } elseif ![string compare $prog "ssh"] { + if [ catch {spawn ssh -c $cyphertype -x -l $user $router} reason ] { + send_user "Error: ssh failed: $reason\n" + exit 1 + } + } elseif ![string compare $prog "rsh"] { + if [ catch {spawn rsh -l $user $router} reason ] { + send_user "Error: rsh failed: $reason\n" + exit 1 + } + } else { + puts "ERROR: unknown connection method: $prog" + return 1 + } + incr progs -1 + sleep 0.3 + + # This helps cleanup each expect clause. + expect_after { + timeout { + send_user "\nError: TIMEOUT reached\n" + catch {close}; wait + if { $in_proc} { + return 1 + } else { + continue + } + } eof { + send_user "\nError: EOF received\n" + catch {close}; wait + if { $in_proc} { + return 1 + } else { + continue + } + } + } + + # Here we get a little tricky. There are several possibilities: + # the router can ask for a username and passwd and then + # talk to the TACACS server to authenticate you, or if the + # TACACS server is not working, then it will use the enable + # passwd. Or, the router might not have TACACS turned on, + # then it will just send the passwd. + # if telnet fails with connection refused, try ssh + expect { + -re "(Connection refused|Secure connection \[^\n\r]+ refused|Connection closed by)" { + catch {close}; wait + if !$progs { + send_user "\nError: Connection Refused ($prog)\n"; return 1 + } + } eof { send_user "Error: Couldn't login\n"; wait; return 1 + } -nocase "unknown host\r" { + catch {close}; + send_user "Error: Unknown host\n"; wait; return 1 + } "Host is unreachable" { + catch {close}; + send_user "Error: Host Unreachable!\n"; wait; return 1 + } "No address associated with name" { + catch {close}; + send_user "Error: Unknown host\n"; wait; return 1 + } + -re "Host key not found .* \(yes\/no\)\?" { + send "yes\r" + send_user "Host $router added to the list of known hosts.\n" + exp_continue } + -re "HOST IDENTIFICATION HAS CHANGED.* \(yes\/no\)\?" { + send "no\r" + send_user "Error: The host key for $router has changed. update the known_hosts file accordingly.\n" + return 1 } + -re "$u_prompt" { send "$user\r" + expect { + eof { send_user "Error: Couldn't login\n"; wait; return 1 } + "Login invalid" { send_user "Error: Invalid login\n"; vatch {close}; wait; return 1 } + -re "$p_prompt" { send "$userpswd\r" } + "$prompt" { set in_proc 0; return 0 } + } + exp_continue + } + -re "$p_prompt" { + if ![string compare $prog "ssh"] { + send "$userpswd\r" + } else { + send "$passwd\r" + } + expect { + eof { send_user "Error: Couldn't login\n"; wait; return 1 } + -re "$e_prompt" { send "$enapasswd\r" } + "$prompt" { set in_proc 0; return 0 } + } + exp_continue + } + "$prompt" { break; } + denied { send_user "Error: Check your passwd for $router\n" + if { $do_command || $do_script } { + send "exit\r" + wait + return 1 + } else { + return 1 + } + } + "% Bad passwords" {send_user "Error: Check your passwd for $router\n"; return 1 } + } +} + set in_proc 0 + return 0 +} + +# Enable +proc do_enable { enauser enapasswd } { + global prompt in_proc + global u_prompt e_prompt + set in_proc 1 + + send "enable\r" + expect { + -re "$u_prompt" { send "$enauser\r"; exp_continue} + -re "$e_prompt" { send "$enapasswd\r"; exp_continue} + "#" { set prompt "#" } + "(enable)" { set prompt "> (enable) " } + denied { send_user "Error: Check your Enable passwd\n"; return 1} + "% Bad passwords" { send_user "Error: Check your Enable passwd\n" + return 1 + } + } + # We set the prompt variable (above) so script files don't need + # to know what it is. + set in_proc 0 + return 0 +} + +# Run commands given on the command line. +proc run_commands { prompt command } { + global in_proc + set in_proc 1 + + # If the prompt is (enable), then we are on a switch and the + # command is "set length 0"; otherwise its "term length 0". + if [ string compare "> (enable) " "$prompt" ] { + send "term length 0\r" + } else { + send "set length 0\r" + } + + expect $prompt {} + + regsub -all "\[)(]" $prompt {\\&} reprompt + + # Is this a multi-command? + if [ string match "*\;*" "$command" ] { + set commands [split $command \;] + set num_commands [llength $commands] + + # the pager can not be turned off on the PIX, so we have to look + # for the "More" prompt + for {set i 0} {$i < $num_commands} { incr i} { + send "[subst -nocommands [lindex $commands $i]]\r" + expect { + -re "^\[^\n\r *]*$reprompt" {} + -re "^\[^\n\r]*$reprompt." { exp_continue } + -re "^<--- More --->" { send " " + exp_continue } + -re "\[\n\r]" { exp_continue } + } + } + } else { + # the pager can not be turned off on the PIX, so we have to look + # for the "More" prompt + send "[subst -nocommands $command]\r" + expect { + -re "^\[^\n\r *]*$reprompt" {} + -re "^\[^\n\r]*$reprompt." { exp_continue } + -re "^<--- More --->" { send " " + exp_continue } + -re "\[\n\r]" { exp_continue } + } + } + send "exit\r" + expect { + "\n" { exp_continue } + timeout { return 0 } + eof { return 0 } + } + set in_proc 0 +} + +# +# For each router... (this is main loop) +# +set in_proc 0 +foreach router [lrange $argv $i end] { + set router [string tolower $router] + send_user "$router\n" + + # Figure out prompt. + # Since autoenable is off by default, if we have it defined, it + # was done on the command line. If it is not specifically set on the + # command line, check the password file. + if $autoenable { + set prompt "#" + } else { + set ae [find autoenable $router] + if { "$ae" == "1" } { + set autoenable 1 + set enable 0 + set prompt "#" + } else { + set autoenable 0 + set prompt ">" + } + } + + # look for noenable option in .cloginrc + if { [find noenable $router] != "" } { + set enable 0 + } + + # Figure out passwords + if { $do_passwd || $do_enapasswd } { + set pswd [find password $router] + if { [llength $pswd] == 0 } { + send_user "Error - no password for $router in $password_file.\n" + continue + } + if { $do_enapasswd && $autoenable == 0 && [llength $pswd] < 2 } { + send_user "Error - no enable password for $router in $password_file.\n" + continue + } + set passwd [lindex $pswd 0] + set enapasswd [lindex $pswd 1] + } + + # Figure out username + if {[info exists username]} { + # command line username + set ruser $username + } else { + set ruser [find user $router] + if { "$ruser" == "" } { set ruser $default_user } + } + + # Figure out username's password (if different from the vty password) + if {[info exists userpasswd]} { + # command line username + set userpswd $userpasswd + } else { + set userpswd [find userpassword $router] + if { "$userpswd" == "" } { set userpswd $passwd } + } + + # Figure out enable username + if {[info exists enausername]} { + # command line enausername + set enauser $enausername + } else { + set enauser [find enauser $router] + if { "$enauser" == "" } { set enauser $ruser } + } + + # Figure out prompts + set u_prompt [find userprompt $router] + if { "$u_prompt" == "" } { set u_prompt "(Username|login):" } + set p_prompt [find passprompt $router] + if { "$p_prompt" == "" } { set p_prompt "(\[Pp]assword|passwd):" } + set e_prompt [find enableprompt $router] + if { "$e_prompt" == "" } { set e_prompt "\[Pp]assword:" } + + # Figure out cypher type + if {[info exists cypher]} { + # command line cypher type + set cyphertype $cypher + } else { + set cyphertype [find cyphertype $router] + if { "$cyphertype" == "" } { set cyphertype "3des" } + } + + # Figure out connection method + set cmethod [find method $router] + if { "$cmethod" == "" } { set cmethod {{telnet} {ssh}} } + + # Login to the router + if {[login $router $ruser $userpswd $passwd $enapasswd $prompt $cmethod $cyphertype]} { + continue + } + if { $enable } { + if {[do_enable $enauser $enapasswd]} { + if { $do_command || $do_script } { + close; wait + continue + } + } + } + + if { $do_command } { + if {[run_commands $prompt $command]} { + continue + } + } elseif { $do_script } { + # If the prompt is (enable), then we are on a switch and the + # command is "set length 0"; otherwise its "term length 0". + if [ string compare "> (enable) " "$prompt" ] { + send "term length 0\r" + } else { + send "set length 0\r" + } + expect $prompt {} + source $sfile + close + } else { + label $router + log_user 1 + interact + } + + # End of for each router + wait + sleep 0.3 +} +exit 0 diff --git a/bin/configure b/bin/configure new file mode 100755 index 0000000..b586b8d --- /dev/null +++ b/bin/configure @@ -0,0 +1,1239 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.13 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_default_prefix=/usr/local/rancid + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.13" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file= + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + + + +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:560: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + + +RD_BIN_DATAS=$rd_cv_rd_bin_datas + +RD_BIN_PROGS=$rd_cv_rd_bin_progs + + +PERLV_PATH=$ac_cv_path_PERLV_PATH + +EXPECT_PATH=$ac_cv_path_EXPECT_PATH + + +# locate tools to build $PATH for env. order is significant. want to be +# sure that we pick up the the proper diff and ucbmail in bin/env. +unset ENV_PATH +# Extract the first word of "diff", so it can be a program name with args. +set dummy diff; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:629: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_DIFF'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$DIFF" in + /*) + ac_cv_path_DIFF="$DIFF" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_DIFF="$DIFF" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_DIFF="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_DIFF" && ac_cv_path_DIFF="no" + ;; +esac +fi +DIFF="$ac_cv_path_DIFF" +if test -n "$DIFF"; then + echo "$ac_t""$DIFF" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +ENV_PATH=`dirname $ac_cv_path_DIFF` +# Extract the first word of "Mail", so it can be a program name with args. +set dummy Mail; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:666: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_UCBMAIL'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$UCBMAIL" in + /*) + ac_cv_path_UCBMAIL="$UCBMAIL" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_UCBMAIL="$UCBMAIL" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_UCBMAIL="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_UCBMAIL" && ac_cv_path_UCBMAIL="no" + ;; +esac +fi +UCBMAIL="$ac_cv_path_UCBMAIL" +if test -n "$UCBMAIL"; then + echo "$ac_t""$UCBMAIL" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +ENV_PATH="$ENV_PATH:`dirname $ac_cv_path_UCBMAIL`" +# Extract the first word of "cvs", so it can be a program name with args. +set dummy cvs; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:703: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_CVS'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$CVS" in + /*) + ac_cv_path_CVS="$CVS" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_CVS="$CVS" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_CVS="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_CVS" && ac_cv_path_CVS="no" + ;; +esac +fi +CVS="$ac_cv_path_CVS" +if test -n "$CVS"; then + echo "$ac_t""$CVS" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +ENV_PATH="$ENV_PATH:`dirname $ac_cv_path_CVS`" +# Extract the first word of "comm", so it can be a program name with args. +set dummy comm; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:740: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_COMM'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$COMM" in + /*) + ac_cv_path_COMM="$COMM" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_COMM="$COMM" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_COMM="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_COMM" && ac_cv_path_COMM="no" + ;; +esac +fi +COMM="$ac_cv_path_COMM" +if test -n "$COMM"; then + echo "$ac_t""$COMM" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +ENV_PATH="$ENV_PATH:`dirname $ac_cv_path_COMM`" +# Extract the first word of "mkdir", so it can be a program name with args. +set dummy mkdir; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:777: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_MKDIR'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$MKDIR" in + /*) + ac_cv_path_MKDIR="$MKDIR" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_MKDIR="$MKDIR" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_MKDIR="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_MKDIR" && ac_cv_path_MKDIR="no" + ;; +esac +fi +MKDIR="$ac_cv_path_MKDIR" +if test -n "$MKDIR"; then + echo "$ac_t""$MKDIR" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +ENV_PATH="$ENV_PATH:`dirname $ac_cv_path_MKDIR`" +# Extract the first word of "dirname", so it can be a program name with args. +set dummy dirname; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:814: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_DIRNAME'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$DIRNAME" in + /*) + ac_cv_path_DIRNAME="$DIRNAME" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_DIRNAME="$DIRNAME" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_DIRNAME="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_DIRNAME" && ac_cv_path_DIRNAME="no" + ;; +esac +fi +DIRNAME="$ac_cv_path_DIRNAME" +if test -n "$DIRNAME"; then + echo "$ac_t""$DIRNAME" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +ENV_PATH="$ENV_PATH:`dirname $ac_cv_path_DIRNAME`" +# Extract the first word of "touch", so it can be a program name with args. +set dummy touch; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:851: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_TOUCH'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$TOUCH" in + /*) + ac_cv_path_TOUCH="$TOUCH" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_TOUCH="$TOUCH" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_TOUCH="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_TOUCH" && ac_cv_path_TOUCH="no" + ;; +esac +fi +TOUCH="$ac_cv_path_TOUCH" +if test -n "$TOUCH"; then + echo "$ac_t""$TOUCH" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +ENV_PATH="$ENV_PATH:`dirname $ac_cv_path_TOUCH`" +# Extract the first word of "sendmail", so it can be a program name with args. +set dummy sendmail; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:888: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_SENDMAIL'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$SENDMAIL" in + /*) + ac_cv_path_SENDMAIL="$SENDMAIL" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_SENDMAIL="$SENDMAIL" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_SENDMAIL="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_SENDMAIL" && ac_cv_path_SENDMAIL="no" + ;; +esac +fi +SENDMAIL="$ac_cv_path_SENDMAIL" +if test -n "$SENDMAIL"; then + echo "$ac_t""$SENDMAIL" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +ENV_PATH="$ENV_PATH:`dirname $ac_cv_path_SENDMAIL`" +# Extract the first word of "sort", so it can be a program name with args. +set dummy sort; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:925: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_SORT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$SORT" in + /*) + ac_cv_path_SORT="$SORT" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_SORT="$SORT" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_SORT="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_SORT" && ac_cv_path_SORT="no" + ;; +esac +fi +SORT="$ac_cv_path_SORT" +if test -n "$SORT"; then + echo "$ac_t""$SORT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +ENV_PATH="$ENV_PATH:`dirname $ac_cv_path_SORT`" +ENV_PATH="$ENV_PATH:/usr/local/bin:/usr/bin" + +ENV_PATH=`echo $ENV_PATH | $PERLV_PATH -e 'foreach $x(split(":",<>)){next unless (length($x));push(@F, $x),$seen{$x}=1 unless (defined $seen{$x});}print join(":",@F);'` + + +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +cat > conftest.defs <<\EOF +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g +s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g +s%\[%\\&%g +s%\]%\\&%g +s%\$%$$%g +EOF +DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '` +rm -f conftest.defs + + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.13" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "Makefile env $RD_BIN_DATAS $RD_BIN_PROGS" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@FFLAGS@%$FFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@RD_BIN_DATAS@%$RD_BIN_DATAS%g +s%@RD_BIN_PROGS@%$RD_BIN_PROGS%g +s%@PERLV_PATH@%$PERLV_PATH%g +s%@EXPECT_PATH@%$EXPECT_PATH%g +s%@DIFF@%$DIFF%g +s%@UCBMAIL@%$UCBMAIL%g +s%@CVS@%$CVS%g +s%@COMM@%$COMM%g +s%@MKDIR@%$MKDIR%g +s%@DIRNAME@%$DIRNAME%g +s%@TOUCH@%$TOUCH%g +s%@SENDMAIL@%$SENDMAIL%g +s%@SORT@%$SORT%g +s%@ENV_PATH@%$ENV_PATH%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + + +# fix permissions on scripts. +for file in $RD_BIN_PROGS; do chmod a+x $file; done diff --git a/bin/configure.in b/bin/configure.in new file mode 100644 index 0000000..cdade86 --- /dev/null +++ b/bin/configure.in @@ -0,0 +1,49 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT() + +dnl default install location +AC_PREFIX_DEFAULT(/usr/local/rancid) + +dnl install program(s) +AC_PROG_INSTALL + +RD_BIN_DATAS=$rd_cv_rd_bin_datas +AC_SUBST(RD_BIN_DATAS) +RD_BIN_PROGS=$rd_cv_rd_bin_progs +AC_SUBST(RD_BIN_PROGS) + +PERLV_PATH=$ac_cv_path_PERLV_PATH +AC_SUBST(PERLV_PATH) +EXPECT_PATH=$ac_cv_path_EXPECT_PATH +AC_SUBST(EXPECT_PATH) + +# locate tools to build $PATH for env. order is significant. want to be +# sure that we pick up the the proper diff and ucbmail in bin/env. +unset ENV_PATH +AC_PATH_PROG(DIFF,diff,no) +ENV_PATH=`dirname $ac_cv_path_DIFF` +AC_PATH_PROG(UCBMAIL,Mail,no) +ENV_PATH="$ENV_PATH:`dirname $ac_cv_path_UCBMAIL`" +AC_PATH_PROG(CVS,cvs,no) +ENV_PATH="$ENV_PATH:`dirname $ac_cv_path_CVS`" +AC_PATH_PROG(COMM,comm,no) +ENV_PATH="$ENV_PATH:`dirname $ac_cv_path_COMM`" +AC_PATH_PROG(MKDIR,mkdir,no) +ENV_PATH="$ENV_PATH:`dirname $ac_cv_path_MKDIR`" +AC_PATH_PROG(DIRNAME,dirname,no) +ENV_PATH="$ENV_PATH:`dirname $ac_cv_path_DIRNAME`" +AC_PATH_PROG(TOUCH,touch,no) +ENV_PATH="$ENV_PATH:`dirname $ac_cv_path_TOUCH`" +AC_PATH_PROG(SENDMAIL,sendmail,no) +ENV_PATH="$ENV_PATH:`dirname $ac_cv_path_SENDMAIL`" +AC_PATH_PROG(SORT,sort,no) +ENV_PATH="$ENV_PATH:`dirname $ac_cv_path_SORT`" +ENV_PATH="$ENV_PATH:/usr/local/bin:/usr/bin" + +ENV_PATH=`echo $ENV_PATH | $PERLV_PATH -e 'foreach $x(split(":",<>)){next unless (length($x));push(@F, $x),$seen{$x}=1 unless (defined $seen{$x});}print join(":",@F);'` +AC_SUBST(ENV_PATH) + +AC_OUTPUT(Makefile env $RD_BIN_DATAS $RD_BIN_PROGS) + +# fix permissions on scripts. +for file in $RD_BIN_PROGS; do chmod a+x $file; done diff --git a/bin/control_rancid b/bin/control_rancid deleted file mode 100755 index 2c367d6..0000000 --- a/bin/control_rancid +++ /dev/null @@ -1,259 +0,0 @@ -#!/bin/sh -## -## -## Copyright (C) 1996 by Henry Kilmer. -## All rights reserved. -## -## This software may be freely copied, modified and redistributed without -## fee for non-commerical purposes provided that this copyright notice is -## preserved intact on all copies and modified copies. -## -## There is no warranty or other guarantee of fitness of this software. -## It is provided solely "as is". The author(s) disclaim(s) all -## responsibility and liability with respect to this software's usage -## or its effect upon hardware, computer systems, other software, or -## anything else. -## -## -# -# control_rancid $GROUP -# - -# Number of things par should run in parallel. -PAR_COUNT=5 - -# Must specify a group to run rancid -if [ $# -lt 1 ]; then - echo 'must specify group'; exit 1 -else - GROUP=$1 -fi -TMP=/var/tmp/rancid.$GROUP.$$ -DIR=$BASEDIR/$GROUP - -# Bail if we do not have the necessary info to run -if [ ! -d $DIR ] -then - ( - echo "$DIR does not exist." - ) | Mail -s "no $GROUP directory" rancid-admin-$GROUP - exit 1 -fi -if [ ! -f $DIR/router.db ] -then - ( - echo "$DIR/router.db does not exist." - ) | Mail -s "no $GROUP/router.db file" rancid-admin-$GROUP - exit 1; -elif [ ! -s $DIR/router.db ] -then - exit -fi - -# generate the list of routers we should try to fetch -cd $DIR -grep -v '^#' router.db > routers.db -cut -d: -f1,2 routers.db | sort -u > routers.all.new -diff routers.all routers.all.new > /dev/null 2>&1; RALL=$? -perl -F: -ane '{($F[0] =~ tr@A-Z@a-z@,print "$F[0]:$F[1]\n") - if ($F[2] =~ /^down$/i);}' routers.db | sort -u > routers.down.new -diff routers.down routers.down.new > /dev/null 2>&1; RDOWN=$? -perl -F: -ane '{($F[0] =~ tr@A-Z@a-z@,print "$F[0]:$F[1]\n") - if ($F[2] =~ /^up$/i);}' routers.db | sort -u > routers.up.new -diff routers.up routers.up.new > /dev/null 2>&1; RUP=$? - -if [ $RALL -ne 0 -o $RDOWN -ne 0 -o $RUP -ne 0 ] -then - ( - if [ $RUP -ne 0 ] ; then - if [ $RUP -eq 1 ] ; then - echo Routers changed to up: - comm -13 routers.up routers.up.new | sed -e 's/^/ /' -e 's/:.*$//' - echo - elif [ -s routers.up.new ] ; then - echo Routers changed to up: - sed -e 's/^/ /' -e 's/:.*$//' routers.up.new - echo - fi - fi - if [ $RDOWN -ne 0 ] ; then - if [ $RDOWN -eq 1 ] ; then - echo Routers changed to down: - comm -13 routers.down routers.down.new | sed -e 's/^/ /' -e 's/:.*$//' - echo - elif [ -s routers.down.new ] ; then - echo Routers changed to down: - sed -e 's/^/ /' -e 's/:.*$//' routers.down.new - echo - fi - fi - WC=`wc -l routers.all | sed -e 's/^ *\([^ ]*\) .*$/\1/'` - WCNEW=`wc -l routers.all.new | sed -e 's/^ *\([^ ]*\) .*$/\1/'` - if [ $RALL -eq 1 -a $WC -gt $WCNEW ] ; then - echo Deleted routers: - comm -23 routers.all routers.all.new | sed -e 's/^/ /' -e 's/:.*$//' - fi - ) > routers.mail - - if [ -s routers.mail ] ; then - Mail -s "changes in $GROUP routers" rancid-admin-$GROUP < routers.mail - fi - rm -f routers.mail - - cd $DIR/configs - - # Add new routers to the CVS structure. - for router in `comm -13 $DIR/routers.up $DIR/routers.up.new` - do - OFS=$IFS - IFS=: - set $router - IFS=$OFS - router=$1 - - touch $router - cvs add -ko $router - cvs commit -m 'new router' $router - echo "Added $router" - done - echo - cd $DIR - -fi -mv routers.all.new routers.all -mv routers.down.new routers.down -mv routers.up.new routers.up -rm -f routers.db - -# cvs delete configs for routers not listed in routers.up. -cd $DIR/configs -for router in `find . \( -name \*.new -prune -o -name CVS -prune \) -o -type f -print | sed -e 's/^.\///'` ; do - grep "^$router:" ../router.db > /dev/null 2>&1 - if [ $? -eq 1 ]; then - rm -f $router - cvs delete $router - cvs commit -m 'deleted router' $router - echo "Deleted $router" - fi -done -cd $DIR - -# no routers, empty list or all 'down' -if [ ! -s routers.up ] -then - # commit router.db - cvs commit -m updates router.db > /dev/null - exit; -fi - -# Now we can actually try to get the configs -cd $DIR/configs - -# The number of processes running at any given time can be -# tailored to the specific installation. -echo "Trying to get all of the configs." -par -q -n $PAR_COUNT -c "rancid-fe \{}" $DIR/routers.up - -# This section will generate a list of missed routers -# and try to grab them again. It will run through -# $pass times. -pass=4 -round=1 -if [ -f $DIR/routers.up.missed ]; then - rm -f $DIR/routers.up.missed -fi -while [ $round -le $pass ] -do - for router in `cat $DIR/routers.up` - do - OFS=$IFS - IFS=':' - set $router - IFS=$OFS - router=$1; mfg=$2 - - if [ ! -s $router.new ] - then - echo "$router:$mfg" >> $DIR/routers.up.missed - rm -f $router.new - fi - done - - if [ -f $DIR/routers.up.missed ]; then - echo "=====================================" - echo "Getting missed routers: round $round." - par -q -n $PAR_COUNT -c "rancid-fe \{}" $DIR/routers.up.missed - rm -f $DIR/routers.up.missed - round=`expr $round + 1` - else - echo "All routers sucessfully completed." - round=`expr $pass + 1` - fi -done -echo - -# Make sure that all of the new configs are not empty. -for config in *.new -do - if [ ! -s $config ] - then - rm -f $config - fi -done - -# Now that we have the new configs, rename them to their proper -# name. -rename 's/.new$//' *.new - -# This has been different for different machines... -# Diff the directory and then checkin. -cd $DIR -#cvs diff -c3 >$TMP.diff -#cvs diff -C 3 >$TMP.diff -# Change the output of a unified diff to make it a bit more readable. -cat > $TMP.sedf << EOF -/^RCS file: /d -#/^retrieving revision /d -/^--- /d -/^+++ /d -s/^\([-+ ]\)/\1 / -EOF -cvs -f diff -u -4 | sed -f $TMP.sedf >$TMP.diff -rm -f $TMP.sedf - -cvs commit -m updates - -# Mail out the diffs (if there are any). -if [ -s $TMP.diff ]; then - sendmail -t <= $OLDTIME*60*60);}" $DIR/routers.up | sort -u > $DIR/routers.failed -if [ -s $DIR/routers.failed ] -then - ( - cat < routers.db +cut -d: -f1,2 routers.db | sort -u > routers.all.new +diff routers.all routers.all.new > /dev/null 2>&1; RALL=$? +@PERLV_PATH@ -F: -ane '{($F[0] =~ tr@A-Z@a-z@,print "$F[0]:$F[1]\n") + if ($F[2] =~ /^down$/i);}' routers.db | sort -u > routers.down.new +diff routers.down routers.down.new > /dev/null 2>&1; RDOWN=$? +@PERLV_PATH@ -F: -ane '{($F[0] =~ tr@A-Z@a-z@,print "$F[0]:$F[1]\n") + if ($F[2] =~ /^up$/i);}' routers.db | sort -u > routers.up.new +diff routers.up routers.up.new > /dev/null 2>&1; RUP=$? + +if [ $RALL -ne 0 -o $RDOWN -ne 0 -o $RUP -ne 0 ] +then + ( + if [ $RUP -ne 0 ] ; then + if [ $RUP -eq 1 ] ; then + echo Routers changed to up: + comm -13 routers.up routers.up.new | sed -e 's/^/ /' + echo + elif [ -s routers.up.new ] ; then + echo Routers changed to up: + sed -e 's/^/ /' routers.up.new + echo + fi + fi + if [ $RDOWN -ne 0 ] ; then + if [ $RDOWN -eq 1 ] ; then + echo Routers changed to down: + comm -13 routers.down routers.down.new | sed -e 's/^/ /' + echo + elif [ -s routers.down.new ] ; then + echo Routers changed to down: + sed -e 's/^/ /' routers.down.new + echo + fi + fi + WC=`wc -l routers.all | sed -e 's/^ *\([^ ]*\) .*$/\1/'` + WCNEW=`wc -l routers.all.new | sed -e 's/^ *\([^ ]*\) .*$/\1/'` + if [ $RALL -eq 1 -a $WC -gt $WCNEW ] ; then + echo Deleted routers: + comm -23 routers.all routers.all.new | sed -e 's/^/ /' + fi + ) > routers.mail + + if [ -s routers.mail ] ; then + Mail -s "changes in $GROUP routers" rancid-admin-$GROUP < routers.mail + fi + rm -f routers.mail + + cd $DIR/configs + + # Add new routers to the CVS structure. + for router in `comm -13 $DIR/routers.up $DIR/routers.up.new` + do + OFS=$IFS + IFS=: + set $router + IFS=$OFS + router=$1 + + touch $router + cvs add -ko $router + cvs commit -m 'new router' $router + echo "Added $router" + done + echo + cd $DIR + +fi +mv routers.all.new routers.all +mv routers.down.new routers.down +mv routers.up.new routers.up +rm -f routers.db + +# cvs delete configs for routers not listed in routers.up. +cd $DIR/configs +for router in `find . \( -name \*.new -prune -o -name CVS -prune \) -o -type f -print | sed -e 's/^.\///'` ; do + grep "^$router:" ../router.db > /dev/null 2>&1 + if [ $? -eq 1 ]; then + rm -f $router + cvs delete $router + cvs commit -m 'deleted router' $router + echo "Deleted $router" + fi +done +cd $DIR + +# no routers, empty list or all 'down' +if [ ! -s routers.up ] +then + # commit router.db + cvs commit -m updates router.db > /dev/null + exit; +fi + +# Now we can actually try to get the configs +cd $DIR/configs + +# The number of processes running at any given time can be +# tailored to the specific installation. +echo "Trying to get all of the configs." +par -q -n $PAR_COUNT -c "rancid-fe \{}" $DIR/routers.up + +# This section will generate a list of missed routers +# and try to grab them again. It will run through +# $pass times. +pass=4 +round=1 +if [ -f $DIR/routers.up.missed ]; then + rm -f $DIR/routers.up.missed +fi +while [ $round -le $pass ] +do + for router in `cat $DIR/routers.up` + do + OFS=$IFS + IFS=':' + set $router + IFS=$OFS + router=$1; mfg=$2 + + if [ ! -s $router.new ] + then + echo "$router:$mfg" >> $DIR/routers.up.missed + rm -f $router.new + fi + done + + if [ -f $DIR/routers.up.missed ]; then + echo "=====================================" + echo "Getting missed routers: round $round." + par -q -n $PAR_COUNT -c "rancid-fe \{}" $DIR/routers.up.missed + rm -f $DIR/routers.up.missed + round=`expr $round + 1` + else + echo "All routers sucessfully completed." + round=`expr $pass + 1` + fi +done +echo + +# Make sure that all of the new configs are not empty. +for config in *.new +do + if [ ! -s $config ] + then + rm -f $config + fi +done + +# Now that we have the new configs, rename them to their proper +# name. +rename 's/.new$//' *.new + +# This has been different for different machines... +# Diff the directory and then checkin. +cd $DIR +#cvs diff -c3 >$TMP.diff +#cvs diff -C 3 >$TMP.diff +# Change the output of a unified diff to make it a bit more readable. +cat > $TMP.sedf << EOF +/^RCS file: /d +#/^retrieving revision /d +/^--- /d +/^+++ /d +s/^\([-+ ]\)/\1 / +EOF +cvs -f diff -u -4 | sed -f $TMP.sedf >$TMP.diff +rm -f $TMP.sedf + +cvs commit -m updates + +# Mail out the diffs (if there are any). +if [ -s $TMP.diff ]; then + sendmail -t <= $OLDTIME*60*60);}" $DIR/routers.up | sort -u > $DIR/routers.failed +if [ -s $DIR/routers.failed ] +then + ( + cat </bin/env -## - -ENVFILE="`dirname $0`/env" - -. $ENVFILE - -if [ $# -ge 1 ] ; then - LIST_OF_GROUPS="$*"; export LIST_OF_GROUPS -elif [ "$LIST_OF_GROUPS" = "" ] ; then - echo "LIST_OF_GROUPS is empty in $ENVFILE" - exit 1 -fi - -if [ ! -d $BASEDIR/logs ] ; then - mkdir $BASEDIR/logs -fi - -for GROUP in $LIST_OF_GROUPS -do - - LOCKFILE=$TMPDIR/.$GROUP.run.lock - - ( - echo starting: `date` - echo - - if [ -f $LOCKFILE ] - then - echo hourly config diffs failed: $LOCKFILE exists - /bin/ls -l $LOCKFILE - - # Send email if the lock file is old. - if [ "X$LOCKTIME" = "X" ] ; then - LOCKTIME=4 - fi - perl -e "\$t = (stat(\"$LOCKFILE\"))[9]; print \"OLD\\n\" if (time() - \$t >= $LOCKTIME*60*60);" > $TMPDIR/.$GROUP.old - if [ -s $TMPDIR/.$GROUP.old ] - then - ( - cat <$BASEDIR/logs/$GROUP.`date +%Y%m%d.%H%M%S` 2>&1 -done diff --git a/bin/do-diffs.in b/bin/do-diffs.in new file mode 100755 index 0000000..4a310ef --- /dev/null +++ b/bin/do-diffs.in @@ -0,0 +1,60 @@ +#!/bin/sh +## +# do diffs for each of the diff groups ($LIST_OF_GROUPS) from /bin/env +## + +ENVFILE="`dirname $0`/env" + +. $ENVFILE + +if [ $# -ge 1 ] ; then + LIST_OF_GROUPS="$*"; export LIST_OF_GROUPS +elif [ "$LIST_OF_GROUPS" = "" ] ; then + echo "LIST_OF_GROUPS is empty in $ENVFILE" + exit 1 +fi + +if [ ! -d $BASEDIR/logs ] ; then + mkdir $BASEDIR/logs +fi + +for GROUP in $LIST_OF_GROUPS +do + + LOCKFILE=$TMPDIR/.$GROUP.run.lock + + ( + echo starting: `date` + echo + + if [ -f $LOCKFILE ] + then + echo hourly config diffs failed: $LOCKFILE exists + /bin/ls -l $LOCKFILE + + # Send email if the lock file is old. + if [ "X$LOCKTIME" = "X" ] ; then + LOCKTIME=4 + fi + @PERLV_PATH@ -e "\$t = (stat(\"$LOCKFILE\"))[9]; print \"OLD\\n\" if (time() - \$t >= $LOCKTIME*60*60);" > $TMPDIR/.$GROUP.old + if [ -s $TMPDIR/.$GROUP.old ] + then + ( + cat <$BASEDIR/logs/$GROUP.`date +%Y%m%d.%H%M%S` 2>&1 +done diff --git a/bin/elogin b/bin/elogin deleted file mode 100755 index ebf126e..0000000 --- a/bin/elogin +++ /dev/null @@ -1,449 +0,0 @@ -#!/usr/local/bin/expect -- -## -## -## Copyright (C) 1997 by Henry Kilmer, Erik Sherk and Pete Whiting. -## All rights reserved. -## -## This software may be freely copied, modified and redistributed without -## fee for non-commerical purposes provided that this copyright notice is -## preserved intact on all copies and modified copies. -## -## There is no warranty or other guarantee of fitness of this software. -## It is provided solely "as is". The author(s) disclaim(s) all -## responsibility and liability with respect to this software's usage -## or its effect upon hardware, computer systems, other software, or -## anything else. -## -## -# -# elogin - ADC EZT3 login -# -# Most options are intuitive for logging into an ADC EZT3 mux. -# - -# Usage line -set usage "Usage: $argv0 \[-noenable\] \[-c command\] \ -\[-f cloginrc-file\] \[-p user-password\] \ -\[-s script-file\] \[-t timeout\] \[-u username\] \ -\[-v vty-password\] \[-w enable-username\] \[-x command-file\] \ -\[-y ssh_cypher_type\] router \[router...\]\n" - -# env(CLOGIN) may contain: -# x == do not set xterm banner or name - -# Password file -set password_file $env(HOME)/.cloginrc -# Default is to login to the router -set do_command 0 -set do_script 0 -# The default is to automatically enable -set enable 1 -# The default is that you login non-enabled (tacacs can have you login already enabled) -set autoenable 0 -# The default is to look in the password file to find the passwords. This -# tracks if we receive them on the command line. -set do_passwd 1 - -# Find the user in the ENV, or use the unix userid. -if {[ info exists env(CISCO_USER) ] } { - set default_user $env(CISCO_USER) -} else { - # This uses "id" which I think is portable. At least it has existed - # (without options) on all machines/OSes I've been on recently - - # unlike whoami or id -nu. - regexp {\(([^)]*)} [exec id] junk default_user -} - -# Sometimes routers take awhile to answer (the default is 10 sec) -set timeout 45 - -# Process the command line -for {set i 0} {$i < $argc} {incr i} { - set arg [lindex $argv $i] - - switch -glob -- $arg { - # Username - -u* - - -U* { - if {! [ regexp .\[uU\](.+) $arg ignore user]} { - incr i - set username [ lindex $argv $i ] - } - # VTY Password - } -p* - - -P* { - if {! [ regexp .\[pP\](.+) $arg ignore userpasswd]} { - incr i - set userpasswd [ lindex $argv $i ] - } - set do_passwd 0 - # VTY Password - } -v* - - -v* { - if {! [ regexp .\[vV\](.+) $arg ignore passwd]} { - incr i - set passwd [ lindex $argv $i ] - } - set do_passwd 0 - # Enable Username - } -w* - - -W* { - # ignore -w - # Enable Password - } -e* - - -E* { - # ignore -e - # Command to run. - } -c* - - -C* { - if {! [ regexp .\[cC\](.+) $arg ignore command]} { - incr i - set command [ lindex $argv $i ] - } - set do_command 1 - # Expect script to run. - } -s* - - -S* { - if {! [ regexp .\[sS\](.+) $arg ignore sfile]} { - incr i - set sfile [ lindex $argv $i ] - } - if { ! [ file readable $sfile ] } { - send_user "Error: Can't read $sfile\n" - exit 1 - } - set do_script 1 - # 'ssh -c' cypher type - } -y* - - -Y* { - if {! [ regexp .\[eE\](.+) $arg ignore cypher]} { - incr i - set cypher [ lindex $argv $i ] - } - # alternate cloginrc file - } -f* - - -F* { - if {! [ regexp .\[fF\](.+) $arg ignore password_file]} { - incr i - set password_file [ lindex $argv $i ] - } - # Timeout - } -t* - - -T* { - if {! [ regexp .\[tT\](.+) $arg ignore timeout]} { - incr i - set timeout [ lindex $argv $i ] - } - # Command file - } -x* - - -X { - if {! [ regexp .\[xX\](.+) $arg ignore cmd_file]} { - incr i - set cmd_file [ lindex $argv $i ] - } - set cmd_fd [open $cmd_file r] - set cmd_text [read $cmd_fd] - close $cmd_fd - set command [join [split $cmd_text \n] \;] - set do_command 1 - # Do we enable? - } -noenable { - # ignore -noenable - # Does tacacs automatically enable us? - } -autoenable { - # ignore -autoenable - } -* { - send_user "Error: Unknown argument! $arg\n" - send_user $usage - exit 1 - } default { - break - } - } -} -# Process routers...no routers listed is an error. -if { $i == $argc } { - send_user "Error: $usage" -} - -# Only be quiet if we are running a script (it can log its output -# on its own) -if { $do_script } { - log_user 0 -} else { - log_user 1 -} - -# -# Done configuration/variable setting. Now run with it... -# - -# Sets Xterm title if interactive...if its an xterm and the user cares -proc label { host } { - global env - # if CLOGIN has an 'x' in it, don't set the xterm name/banner - if [info exists env(CLOGIN)] { - if {[string first "x" $env(CLOGIN)] != -1} { return } - } - # take host from ENV(TERM) - if [info exists env(TERM)] { - if [regexp \^(xterm|vs) $env(TERM) ignore ] { - send_user "\033]1;[lindex [split $host "."] 0]\a" - send_user "\033]2;$host\a" - } - } -} - -# This is a helper function to make the password file easier to -# maintain. Using this the password file has the form: -# add password sl* pete cow -# add password at* steve -# add password * hanky-pie -proc add {var args} { global $var ;lappend $var $args} -proc find {var router} { - source_password_file - upvar $var list - if { [info exists list] } { - foreach line $list { - if { [string match [lindex $line 0] $router ] } { - return [lrange $line 1 end] - } - } - } - return {} -} - -# Loads the password file. Note that as this file is tcl, and that -# it is sourced, the user better know what to put in there, as it -# could install more than just password info... I will assume however, -# that a "bad guy" could just as easy put such code in the clogin -# script, so I will leave .cloginrc as just an extention of that script -proc source_password_file { } { - global env password_file read_password_file - if { [info exists read_password_file] } { return } - if { [info exists password_file] == 0 } { - set password_file $env(HOME)/.cloginrc - } - if { ! [file exists $password_file] } { - send_user "Error: password file ($password_file) does not exist\n" - exit 1 - } - set read_password_file 1 - file stat $password_file fileinfo - if { [expr ($fileinfo(mode) & 007)] != 0000 } { - send_user "Error: $password_file must not be world readable/writable\n" - exit 1 - } - source $password_file -} - -# Log into the router. -proc login { router user userpswd passwd prompt cyphertype } { - global spawn_id in_proc do_command do_script - global u_prompt p_prompt - set in_proc 1 - set tryssh 1 - - # Telnet to the router & try to login. - if [ catch {spawn telnet $router} reason ] { - send_user "Error: failed to telnet: $reason\n" - exit 1 - } - sleep 0.3 - - # This helps cleanup each expect clause. - expect_after { - timeout { - send_user "\nError: TIMEOUT reached\n" - catch {close}; wait - if { $in_proc} { - return 1 - } else { - continue - } - } eof { - send_user "\nError: EOF received\n" - catch {close}; wait - if { $in_proc} { - return 1 - } else { - continue - } - } - } - - expect { - "Connection refused" { - close; wait - sleep 0.3 - expect eof - send_user "Error: Connection Refused\n"; wait; return 1 - } eof { send_user "Error: Couldn't login\n"; wait; return 1 - } "Unknown host\r\n" { - expect eof - send_user "Error: Unknown host\n"; wait; return 1 - } "Host is unreachable" { - expect eof - send_user "Error: Host Unreachable!\n"; wait; return 1 - } "No address associated with name" { - expect eof - send_user "Error: Unknown host\n"; wait; return 1 - } - -re "$u_prompt" { send "$user\r" - expect { - "Login incorrect" { send_user "Error: Couldn't login\n"; - catch {close}; wait; return 1 } - eof { send_user "Error: Couldn't login\n"; wait; return 1 } - -re "$p_prompt" { send "$userpswd\r" } - "$prompt" { set in_proc 0; return 0 } - } - exp_continue - } - -re "$p_prompt" { send "$passwd\r" - expect { - "Password incorrect" { send_user "Error: Couldn't login\n"; - catch {close}; wait; return 1 } - eof { send_user "Error: Couldn't login\n"; wait; return 1 } - "$prompt" { set in_proc 0; return 0 } - } - exp_continue - } - "Password incorrect" { send_user "Error: Check your password for $router\n"; - catch {close}; wait; return 1 } - "$prompt" { } - denied { send_user "Error: Check your passwd for $router\n" - if { $do_command || $do_script } { - send "exit\r" - wait - return 1 - } else { - return 1 - } - } - "\r\n" { exp_continue; } - } - set in_proc 0 - return 0 -} - -# Run commands given on the command line. -proc run_commands { prompt command } { - global in_proc - set in_proc 1 - - send "screen 0\r" - expect $prompt {} - - regsub -all "\[)(]" $prompt {\\&} reprompt - - # Is this a multi-command? - if [ string match "*\;*" "$command" ] { - set commands [split $command \;] - set num_commands [llength $commands] - - for {set i 0} {$i < $num_commands} { incr i} { - send "[subst -nocommands [lindex $commands $i]]\r" - expect { - -re "^\[^\n\r]*$reprompt." { exp_continue } - -re "^\[^\n\r *]*$reprompt" {} - -re "\[\n\r]" { exp_continue } - } - } - } else { - send "[subst -nocommands $command]\r" - expect { - -re "^\[^\n\r]*$reprompt." { exp_continue } - -re "^\[^\n\r *]*$reprompt" {} - -re "\[\n\r]" { exp_continue } - } - } - send "exit\r" - expect { - "\n" { exp_continue } - timeout { return 0 } - eof { return 0 } - } - set in_proc 0 -} - -# -# For each router... (this is main loop) -# -set in_proc 0 -foreach router [lrange $argv $i end] { - set router [string tolower $router] - send_user "$router\n" - - # Figure out prompt. - set prompt "Active) > " - set autoenable 1 - set enable 0 - - # Figure out passwords - if { $do_passwd } { - set pswd [find password $router] - if { [llength $pswd] == 0 } { - send_user "Error - no password for $router in $password_file.\n" - continue - } - set passwd [lindex $pswd 0] - } - - # Figure out username - if {[info exists username]} { - # command line username - set ruser $username - } else { - set ruser [find user $router] - if { "$ruser" == "" } { set ruser $default_user } - } - - # Figure out username's password (if different from the vty password) - if {[info exists userpasswd]} { - # command line username - set userpswd $userpasswd - } else { - set userpswd [find userpassword $router] - if { "$userpswd" == "" } { set userpswd $passwd } - } - - # Figure out prompts - set u_prompt [find userprompt $router] - if { "$u_prompt" == "" } { set u_prompt "(Username|login| Login):" } - set p_prompt [find passprompt $router] - if { "$p_prompt" == "" } { set p_prompt "\[Pp]assword:" } - - # Figure out cypher type - if {[info exists cypher]} { - # command line cypher type - set cyphertype $cypher - } else { - set cyphertype [find cyphertype $router] - if { "$cyphertype" == "" } { set cyphertype "3des" } - } - - # Login to the router - if {[login $router $ruser $userpswd $passwd $prompt $cyphertype]} { - continue - } - - if { $do_command } { - if {[run_commands $prompt $command]} { - continue - } - } elseif { $do_script } { - send "screen 0\r" - expect $prompt {} - source $sfile - close - } else { - label $router - log_user 1 - interact - } - - # End of for each router - wait - sleep 0.3 -} -exit 0 diff --git a/bin/elogin.in b/bin/elogin.in new file mode 100755 index 0000000..e75efed --- /dev/null +++ b/bin/elogin.in @@ -0,0 +1,449 @@ +#!@EXPECT_PATH@ -- +## +## +## Copyright (C) 1997 by Henry Kilmer, Erik Sherk and Pete Whiting. +## All rights reserved. +## +## This software may be freely copied, modified and redistributed without +## fee for non-commerical purposes provided that this copyright notice is +## preserved intact on all copies and modified copies. +## +## There is no warranty or other guarantee of fitness of this software. +## It is provided solely "as is". The author(s) disclaim(s) all +## responsibility and liability with respect to this software's usage +## or its effect upon hardware, computer systems, other software, or +## anything else. +## +## +# +# elogin - ADC EZT3 login +# +# Most options are intuitive for logging into an ADC EZT3 mux. +# + +# Usage line +set usage "Usage: $argv0 \[-noenable\] \[-c command\] \ +\[-f cloginrc-file\] \[-p user-password\] \ +\[-s script-file\] \[-t timeout\] \[-u username\] \ +\[-v vty-password\] \[-w enable-username\] \[-x command-file\] \ +\[-y ssh_cypher_type\] router \[router...\]\n" + +# env(CLOGIN) may contain: +# x == do not set xterm banner or name + +# Password file +set password_file $env(HOME)/.cloginrc +# Default is to login to the router +set do_command 0 +set do_script 0 +# The default is to automatically enable +set enable 1 +# The default is that you login non-enabled (tacacs can have you login already enabled) +set autoenable 0 +# The default is to look in the password file to find the passwords. This +# tracks if we receive them on the command line. +set do_passwd 1 + +# Find the user in the ENV, or use the unix userid. +if {[ info exists env(CISCO_USER) ] } { + set default_user $env(CISCO_USER) +} else { + # This uses "id" which I think is portable. At least it has existed + # (without options) on all machines/OSes I've been on recently - + # unlike whoami or id -nu. + regexp {\(([^)]*)} [exec id] junk default_user +} + +# Sometimes routers take awhile to answer (the default is 10 sec) +set timeout 45 + +# Process the command line +for {set i 0} {$i < $argc} {incr i} { + set arg [lindex $argv $i] + + switch -glob -- $arg { + # Username + -u* - + -U* { + if {! [ regexp .\[uU\](.+) $arg ignore user]} { + incr i + set username [ lindex $argv $i ] + } + # VTY Password + } -p* - + -P* { + if {! [ regexp .\[pP\](.+) $arg ignore userpasswd]} { + incr i + set userpasswd [ lindex $argv $i ] + } + set do_passwd 0 + # VTY Password + } -v* - + -v* { + if {! [ regexp .\[vV\](.+) $arg ignore passwd]} { + incr i + set passwd [ lindex $argv $i ] + } + set do_passwd 0 + # Enable Username + } -w* - + -W* { + # ignore -w + # Enable Password + } -e* - + -E* { + # ignore -e + # Command to run. + } -c* - + -C* { + if {! [ regexp .\[cC\](.+) $arg ignore command]} { + incr i + set command [ lindex $argv $i ] + } + set do_command 1 + # Expect script to run. + } -s* - + -S* { + if {! [ regexp .\[sS\](.+) $arg ignore sfile]} { + incr i + set sfile [ lindex $argv $i ] + } + if { ! [ file readable $sfile ] } { + send_user "Error: Can't read $sfile\n" + exit 1 + } + set do_script 1 + # 'ssh -c' cypher type + } -y* - + -Y* { + if {! [ regexp .\[eE\](.+) $arg ignore cypher]} { + incr i + set cypher [ lindex $argv $i ] + } + # alternate cloginrc file + } -f* - + -F* { + if {! [ regexp .\[fF\](.+) $arg ignore password_file]} { + incr i + set password_file [ lindex $argv $i ] + } + # Timeout + } -t* - + -T* { + if {! [ regexp .\[tT\](.+) $arg ignore timeout]} { + incr i + set timeout [ lindex $argv $i ] + } + # Command file + } -x* - + -X { + if {! [ regexp .\[xX\](.+) $arg ignore cmd_file]} { + incr i + set cmd_file [ lindex $argv $i ] + } + set cmd_fd [open $cmd_file r] + set cmd_text [read $cmd_fd] + close $cmd_fd + set command [join [split $cmd_text \n] \;] + set do_command 1 + # Do we enable? + } -noenable { + # ignore -noenable + # Does tacacs automatically enable us? + } -autoenable { + # ignore -autoenable + } -* { + send_user "Error: Unknown argument! $arg\n" + send_user $usage + exit 1 + } default { + break + } + } +} +# Process routers...no routers listed is an error. +if { $i == $argc } { + send_user "Error: $usage" +} + +# Only be quiet if we are running a script (it can log its output +# on its own) +if { $do_script } { + log_user 0 +} else { + log_user 1 +} + +# +# Done configuration/variable setting. Now run with it... +# + +# Sets Xterm title if interactive...if its an xterm and the user cares +proc label { host } { + global env + # if CLOGIN has an 'x' in it, don't set the xterm name/banner + if [info exists env(CLOGIN)] { + if {[string first "x" $env(CLOGIN)] != -1} { return } + } + # take host from ENV(TERM) + if [info exists env(TERM)] { + if [regexp \^(xterm|vs) $env(TERM) ignore ] { + send_user "\033]1;[lindex [split $host "."] 0]\a" + send_user "\033]2;$host\a" + } + } +} + +# This is a helper function to make the password file easier to +# maintain. Using this the password file has the form: +# add password sl* pete cow +# add password at* steve +# add password * hanky-pie +proc add {var args} { global $var ;lappend $var $args} +proc find {var router} { + source_password_file + upvar $var list + if { [info exists list] } { + foreach line $list { + if { [string match [lindex $line 0] $router ] } { + return [lrange $line 1 end] + } + } + } + return {} +} + +# Loads the password file. Note that as this file is tcl, and that +# it is sourced, the user better know what to put in there, as it +# could install more than just password info... I will assume however, +# that a "bad guy" could just as easy put such code in the clogin +# script, so I will leave .cloginrc as just an extention of that script +proc source_password_file { } { + global env password_file read_password_file + if { [info exists read_password_file] } { return } + if { [info exists password_file] == 0 } { + set password_file $env(HOME)/.cloginrc + } + if { ! [file exists $password_file] } { + send_user "Error: password file ($password_file) does not exist\n" + exit 1 + } + set read_password_file 1 + file stat $password_file fileinfo + if { [expr ($fileinfo(mode) & 007)] != 0000 } { + send_user "Error: $password_file must not be world readable/writable\n" + exit 1 + } + source $password_file +} + +# Log into the router. +proc login { router user userpswd passwd prompt cyphertype } { + global spawn_id in_proc do_command do_script + global u_prompt p_prompt + set in_proc 1 + set tryssh 1 + + # Telnet to the router & try to login. + if [ catch {spawn telnet $router} reason ] { + send_user "Error: failed to telnet: $reason\n" + exit 1 + } + sleep 0.3 + + # This helps cleanup each expect clause. + expect_after { + timeout { + send_user "\nError: TIMEOUT reached\n" + catch {close}; wait + if { $in_proc} { + return 1 + } else { + continue + } + } eof { + send_user "\nError: EOF received\n" + catch {close}; wait + if { $in_proc} { + return 1 + } else { + continue + } + } + } + + expect { + "Connection refused" { + close; wait + sleep 0.3 + expect eof + send_user "Error: Connection Refused\n"; wait; return 1 + } eof { send_user "Error: Couldn't login\n"; wait; return 1 + } "Unknown host\r\n" { + expect eof + send_user "Error: Unknown host\n"; wait; return 1 + } "Host is unreachable" { + expect eof + send_user "Error: Host Unreachable!\n"; wait; return 1 + } "No address associated with name" { + expect eof + send_user "Error: Unknown host\n"; wait; return 1 + } + -re "$u_prompt" { send "$user\r" + expect { + "Login incorrect" { send_user "Error: Couldn't login\n"; + catch {close}; wait; return 1 } + eof { send_user "Error: Couldn't login\n"; wait; return 1 } + -re "$p_prompt" { send "$userpswd\r" } + "$prompt" { set in_proc 0; return 0 } + } + exp_continue + } + -re "$p_prompt" { send "$passwd\r" + expect { + "Password incorrect" { send_user "Error: Couldn't login\n"; + catch {close}; wait; return 1 } + eof { send_user "Error: Couldn't login\n"; wait; return 1 } + "$prompt" { set in_proc 0; return 0 } + } + exp_continue + } + "Password incorrect" { send_user "Error: Check your password for $router\n"; + catch {close}; wait; return 1 } + "$prompt" { } + denied { send_user "Error: Check your passwd for $router\n" + if { $do_command || $do_script } { + send "exit\r" + wait + return 1 + } else { + return 1 + } + } + "\r\n" { exp_continue; } + } + set in_proc 0 + return 0 +} + +# Run commands given on the command line. +proc run_commands { prompt command } { + global in_proc + set in_proc 1 + + send "screen 0\r" + expect $prompt {} + + regsub -all "\[)(]" $prompt {\\&} reprompt + + # Is this a multi-command? + if [ string match "*\;*" "$command" ] { + set commands [split $command \;] + set num_commands [llength $commands] + + for {set i 0} {$i < $num_commands} { incr i} { + send "[subst -nocommands [lindex $commands $i]]\r" + expect { + -re "^\[^\n\r]*$reprompt." { exp_continue } + -re "^\[^\n\r *]*$reprompt" {} + -re "\[\n\r]" { exp_continue } + } + } + } else { + send "[subst -nocommands $command]\r" + expect { + -re "^\[^\n\r]*$reprompt." { exp_continue } + -re "^\[^\n\r *]*$reprompt" {} + -re "\[\n\r]" { exp_continue } + } + } + send "exit\r" + expect { + "\n" { exp_continue } + timeout { return 0 } + eof { return 0 } + } + set in_proc 0 +} + +# +# For each router... (this is main loop) +# +set in_proc 0 +foreach router [lrange $argv $i end] { + set router [string tolower $router] + send_user "$router\n" + + # Figure out prompt. + set prompt "Active) > " + set autoenable 1 + set enable 0 + + # Figure out passwords + if { $do_passwd } { + set pswd [find password $router] + if { [llength $pswd] == 0 } { + send_user "Error - no password for $router in $password_file.\n" + continue + } + set passwd [lindex $pswd 0] + } + + # Figure out username + if {[info exists username]} { + # command line username + set ruser $username + } else { + set ruser [find user $router] + if { "$ruser" == "" } { set ruser $default_user } + } + + # Figure out username's password (if different from the vty password) + if {[info exists userpasswd]} { + # command line username + set userpswd $userpasswd + } else { + set userpswd [find userpassword $router] + if { "$userpswd" == "" } { set userpswd $passwd } + } + + # Figure out prompts + set u_prompt [find userprompt $router] + if { "$u_prompt" == "" } { set u_prompt "(Username|login| Login):" } + set p_prompt [find passprompt $router] + if { "$p_prompt" == "" } { set p_prompt "\[Pp]assword:" } + + # Figure out cypher type + if {[info exists cypher]} { + # command line cypher type + set cyphertype $cypher + } else { + set cyphertype [find cyphertype $router] + if { "$cyphertype" == "" } { set cyphertype "3des" } + } + + # Login to the router + if {[login $router $ruser $userpswd $passwd $prompt $cyphertype]} { + continue + } + + if { $do_command } { + if {[run_commands $prompt $command]} { + continue + } + } elseif { $do_script } { + send "screen 0\r" + expect $prompt {} + source $sfile + close + } else { + label $router + log_user 1 + interact + } + + # End of for each router + wait + sleep 0.3 +} +exit 0 diff --git a/bin/env b/bin/env deleted file mode 100644 index 7a18204..0000000 --- a/bin/env +++ /dev/null @@ -1,41 +0,0 @@ -# -# This file setups up the environment used for rancid -# -# This will be site specific -# -TERM=network;export TERM -# -# Under $BASEDIR, there will be a bin directory for the rancid programs, -# a log directory for the logs from rancid and a directory for each group -# of routers. In addition to these directories, there will be the CVS -# repositories as well. -# use a full path (no sym-links) for BASEDIR. some versions of CVS seemingly -# don't take kindly to sym-links. -# -TMPDIR=/tmp; export TMPDIR -BASEDIR=$HOME/rancid; export BASEDIR -PATH=$BASEDIR/bin:/usr/local/bin:/usr/ucb:/usr/bin:/bin:/usr/lib:/usr/sbin;export PATH -CVSROOT=$BASEDIR/CVS; export CVSROOT -# -# if NOPIPE is set, temp files will be used instead of a cmd pipe during -# collection from the router(s). -#NOPIPE=YES; export NOPIPE -# -# if NOCOMMSTR is set, snmp community strings will be stripped from the configs -#NOCOMMSTR=YES; export NOCOMMSTR -# -# How many hours to go by before complaining about routers that -# can not be reached. -OLDTIME=4; export OLDTIME -# -LIST_OF_GROUPS="sl joebobisp" -# -# For each group, define a list of people to receive the diffs. -# in a .mailrc file in the following format: -# alias rancid-$GROUP hank@rem.com pwhiting@sprint.net -# or sendmail's /etc/aliases. -# rancid-group: joe,moe@foo -# rancid-group-admin: hostmaster -# be sure to read ../README regarding aliases. -# -umask 007 diff --git a/bin/env.in b/bin/env.in new file mode 100644 index 0000000..37e9a8b --- /dev/null +++ b/bin/env.in @@ -0,0 +1,42 @@ +# +# This file setups up the environment used for rancid +# +# This will be site specific +# +TERM=network;export TERM +# +# Under $BASEDIR, there will be a bin directory for the rancid programs, +# a log directory for the logs from rancid and a directory for each group +# of routers. In addition to these directories, there will be the CVS +# repositories as well. +# use a full path (no sym-links) for BASEDIR. some versions of CVS seemingly +# don't take kindly to sym-links. +# +TMPDIR=/tmp; export TMPDIR +BASEDIR=@prefix@; export BASEDIR +PATH=$BASEDIR/bin:@ENV_PATH@; export PATH +#PATH=$BASEDIR/bin:/usr/local/bin:/usr/ucb:/usr/bin:/bin:/usr/lib:/usr/sbin;export PATH +CVSROOT=$BASEDIR/CVS; export CVSROOT +# +# if NOPIPE is set, temp files will be used instead of a cmd pipe during +# collection from the router(s). +#NOPIPE=YES; export NOPIPE +# +# if NOCOMMSTR is set, snmp community strings will be stripped from the configs +#NOCOMMSTR=YES; export NOCOMMSTR +# +# How many hours to go by before complaining about routers that +# can not be reached. +OLDTIME=4; export OLDTIME +# +LIST_OF_GROUPS="sl joebobisp" +# +# For each group, define a list of people to receive the diffs. +# in a .mailrc file in the following format: +# alias rancid-$GROUP hank@rem.com pwhiting@sprint.net +# or sendmail's /etc/aliases. +# rancid-group: joe,moe@foo +# rancid-group-admin: hostmaster +# be sure to read ../README regarding aliases. +# +umask 007 diff --git a/bin/erancid b/bin/erancid deleted file mode 100755 index 2adba78..0000000 --- a/bin/erancid +++ /dev/null @@ -1,296 +0,0 @@ -#!/usr/local/bin/perl -## -## Hacked version of rancid for ADC EZT3 series muxes. Only tested -## with switch software 1.50 so far - terry@tmk.com -## -## -## Copyright (C) 1997 by Henry Kilmer. -## All rights reserved. -## -## This software may be freely copied, modified and redistributed without -## fee for non-commerical purposes provided that this copyright notice is -## preserved intact on all copies and modified copies. -## -## There is no warranty or other guarantee of fitness of this software. -## It is provided solely "as is". The author(s) disclaim(s) all -## responsibility and liability with respect to this software's usage -## or its effect upon hardware, computer systems, other software, or -## anything else. -## -## -# -# RANCID - Really Awesome New Cisco confIg Differ -# -# usage: rancid [-d] [-l] [-f filename | $host] -# -use Getopt::Std; -getopts('dflm'); -$log = $opt_l; -$debug = $opt_d; -$file = $opt_f; -$host = $ARGV[0]; -$clean_run = 0; -$found_end = 0; -$timeo = 90; # clogin timeout in seconds - -# This routine is used to print out the router configuration -sub ProcessHistory { - my($new_hist_tag,$new_command,$command_string,@string)=(@_); - if((($new_hist_tag ne $hist_tag) || ($new_command ne $command)) - && defined %history) { - print eval "$command \%history"; - undef %history; - } - if (($new_hist_tag) && ($new_command) && ($command_string)) { - if ($history{$command_string}) { - $history{$command_string} = "$history{$command_string}@string"; - } else { - $history{$command_string} = "@string"; - } - } elsif (($new_hist_tag) && ($new_command)) { - $history{++$#history} = "@string"; - } else { - print "@string"; - } - $hist_tag = $new_hist_tag; - $command = $new_command; - 1; -} - -sub numerically { $a <=> $b; } - -# This is a sort routing that will sort numerically on the -# keys of a hash as if it were a normal array. -sub keynsort { - local(%lines)=@_; - local($i) = 0; - local(@sorted_lines); - foreach $key (sort numerically keys(%lines)) { - $sorted_lines[$i] = $lines{$key}; - $i++; - } - @sorted_lines; -} - -# This is a sort routing that will sort on the -# keys of a hash as if it were a normal array. -sub keysort { - local(%lines)=@_; - local($i) = 0; - local(@sorted_lines); - foreach $key (sort keys(%lines)) { - $sorted_lines[$i] = $lines{$key}; - $i++; - } - @sorted_lines; -} - -# This is a sort routing that will sort on the -# values of a hash as if it were a normal array. -sub valsort{ - local(%lines)=@_; - local($i) = 0; - local(@sorted_lines); - foreach $key (sort values %lines) { - $sorted_lines[$i] = $key; - $i++; - } - @sorted_lines; -} - -# This is a numerical sort routing (ascending). -sub numsort { - local(%lines)=@_; - local($i) = 0; - local(@sorted_lines); - foreach $num (sort {$a <=> $b} keys %lines) { - $sorted_lines[$i] = $lines{$num}; - $i++; - } - @sorted_lines; -} - -# This is a sort routine that will sort on the -# ip address when the ip address is anywhere in -# the strings. -sub ipsort { - local(%lines)=@_; - local($i) = 0; - local(@sorted_lines); - foreach $addr (sort sortbyipaddr keys %lines) { - $sorted_lines[$i] = $lines{$addr}; - $i++; - } - @sorted_lines; -} - -# These two routines will sort based upon IP addresses -sub ipaddrval { - my(@a) = ($_[0] =~ m#^(\d+)\.(\d+)\.(\d+)\.(\d+)$#); - $a[3]+256*($a[2]+256*($a[1]+256*$a[0])); -} -sub sortbyipaddr { - &ipaddrval($a) <=> &ipaddrval($b); -} - -# This routine parses "show version" -sub ShowVersion { - print STDERR " In ShowVersion: $_" if ($debug); - - ProcessHistory("COMMENTS","keysort","A1", - "- Chassis type:EZT3 - an ADC EZT3 M13 multiplexor\n"); - - while () { - tr/\015//d; - last if(/Active\) >/); - next if(/^(\s*|\s*$cmd\s*)$/); - - /Boot Version (\S*)/ && - ProcessHistory("COMMENTS","keysort","G1", - "- ROM Bootstrap: $1\n") && next; - /Software Version (\S*)/ && - ProcessHistory("COMMENTS","keysort","F1", - "- Software: $1\n") && next; - } - return(0); -} - -# This routine parses "show module" -sub ShowModule { - print STDERR " In ShowModule: $_" if ($debug); - - # eat the header line - $junk = ; - - ProcessHistory("SLOT","","","-\n"); - - # now just copy it verbatim to the history file - while () { - tr/\015//d; - last if(/Active\) >/); - last if(/^$/); - chop; - ProcessHistory("SLOT","","","-$_\n"); - } - ProcessHistory("SLOT","","","-\n"); -} - -# This routine processes a "write term" -sub WriteTerm { - print STDERR " In WriteTerm: $_" if ($debug); - - # eat the header line - $junk = ; - - # now just copy it verbatim to the history file - while () { - tr/\015//d; - last if(/Active\) >/); - chop; - if (/^\s*snmp/ && defined($ENV{'NOCOMMSTR'})) { - /snmp (getcomm|setcomm|trapcomm)(\s+)(\S*)/ && - ProcessHistory("","","","- snmp $1$2\"\"\n") && next; - } - # believe it or not, "-" is the "whole line is comment" command - ProcessHistory("","","","$_\n"); - } - $found_end = 1; - return(1); -} - -# dummy function -sub DoNothing {print STDOUT;} - -# Main -%commands=( - 'version' => "ShowVersion", - 'equipment' => "ShowModule", - 'config' => "WriteTerm", -); -# keys() doesnt return things in the order entered and the order of the -# cmds is important (show version first and write term last). pita -@commands=( - "version", - "equipment", - "config", -); -$cisco_cmds=join(";",@commands); -$cmds_regexp=join("|",@commands); - -open(OUTPUT,">$host.new") || die "Can't open $host.new for writing: $!\n"; -select(OUTPUT); -# make OUTPUT unbuffered if debugging -if ($debug) { $| = 1; } - -if ($file) { - print STDERR "opening file $host\n" if ($debug); - print STDOUT "opening file $host\n" if ($log); - open(INPUT,"<$host") || die "open failed for $host: $!\n"; -} else { - print STDERR "executing elogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($debug); - print STDOUT "executing elogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($log); - if (defined($ENV{NOPIPE})) { - system "elogin -t $timeo -c \"$cisco_cmds\" $host $host.raw 2>&1" || die "elogin failed for $host: $!\n"; - open(INPUT, "< $host.raw") || die "elogin failed for $host: $!\n"; - } else { - open(INPUT,"elogin -t $timeo -c \"$cisco_cmds\" $host ) { - tr/\015//d; - if (/Logging out$/) { - $clean_run=1; - last; - } - if (/Error:/) { - s/^.*Error:/Error:/; - print STDOUT ("$host elogin error: $_"); - print STDERR ("$host elogin error: $_") if ($debug); - $clean_run=0; - last; - } - while (/Active\) >\s*($cmds_regexp)\s*$/) { - $cmd = $1; - if (!defined($prompt)) {$prompt = ($_ =~ /^([^#]+#)/)[0]; } - print STDERR ("HIT COMMAND:$_") if ($debug); - if (! defined($commands{$cmd})) { - print STDERR "found unexpected command - \"$cmd\"\n"; - $clean_run = 0; - last; - } - $rval = &{$commands{$cmd}}; - delete($commands{$cmd}); - if ($rval == -1) { - $clean_run = 0; - last; - } - } -} -print STDOUT "Done $logincmd: $_\n" if ($log); -# Flush History -ProcessHistory("","","",""); -# Cleanup -close(INPUT); -close(OUTPUT); - -if (defined($ENV{NOPIPE})) { - unlink("$host.raw") if (! $debug); -} - -# check for completeness -if (scalar(%commands) || !$clean_run || !$found_end) { - if (scalar(%commands)) { - printf(STDOUT "missed cmd(s): %s\n", join(',', keys(%commands))); - printf(STDERR "missed cmd(s): %s\n", join(',', keys(%commands))) if ($debug); - } - if (!$clean_run || !$found_end) { - print STDOUT "End of run not found\n"; - print STDERR "End of run not found\n" if ($debug); - system("/usr/bin/tail -1 $host.new"); - } - unlink "$host.new" if (! $debug); -} diff --git a/bin/erancid.in b/bin/erancid.in new file mode 100755 index 0000000..185a634 --- /dev/null +++ b/bin/erancid.in @@ -0,0 +1,296 @@ +#!@PERLV_PATH@ +## +## Hacked version of rancid for ADC EZT3 series muxes. Only tested +## with switch software 1.50 so far - terry@tmk.com +## +## +## Copyright (C) 1997 by Henry Kilmer. +## All rights reserved. +## +## This software may be freely copied, modified and redistributed without +## fee for non-commerical purposes provided that this copyright notice is +## preserved intact on all copies and modified copies. +## +## There is no warranty or other guarantee of fitness of this software. +## It is provided solely "as is". The author(s) disclaim(s) all +## responsibility and liability with respect to this software's usage +## or its effect upon hardware, computer systems, other software, or +## anything else. +## +## +# +# RANCID - Really Awesome New Cisco confIg Differ +# +# usage: rancid [-d] [-l] [-f filename | $host] +# +use Getopt::Std; +getopts('dflm'); +$log = $opt_l; +$debug = $opt_d; +$file = $opt_f; +$host = $ARGV[0]; +$clean_run = 0; +$found_end = 0; +$timeo = 90; # clogin timeout in seconds + +# This routine is used to print out the router configuration +sub ProcessHistory { + my($new_hist_tag,$new_command,$command_string,@string)=(@_); + if((($new_hist_tag ne $hist_tag) || ($new_command ne $command)) + && defined %history) { + print eval "$command \%history"; + undef %history; + } + if (($new_hist_tag) && ($new_command) && ($command_string)) { + if ($history{$command_string}) { + $history{$command_string} = "$history{$command_string}@string"; + } else { + $history{$command_string} = "@string"; + } + } elsif (($new_hist_tag) && ($new_command)) { + $history{++$#history} = "@string"; + } else { + print "@string"; + } + $hist_tag = $new_hist_tag; + $command = $new_command; + 1; +} + +sub numerically { $a <=> $b; } + +# This is a sort routing that will sort numerically on the +# keys of a hash as if it were a normal array. +sub keynsort { + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $key (sort numerically keys(%lines)) { + $sorted_lines[$i] = $lines{$key}; + $i++; + } + @sorted_lines; +} + +# This is a sort routing that will sort on the +# keys of a hash as if it were a normal array. +sub keysort { + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $key (sort keys(%lines)) { + $sorted_lines[$i] = $lines{$key}; + $i++; + } + @sorted_lines; +} + +# This is a sort routing that will sort on the +# values of a hash as if it were a normal array. +sub valsort{ + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $key (sort values %lines) { + $sorted_lines[$i] = $key; + $i++; + } + @sorted_lines; +} + +# This is a numerical sort routing (ascending). +sub numsort { + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $num (sort {$a <=> $b} keys %lines) { + $sorted_lines[$i] = $lines{$num}; + $i++; + } + @sorted_lines; +} + +# This is a sort routine that will sort on the +# ip address when the ip address is anywhere in +# the strings. +sub ipsort { + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $addr (sort sortbyipaddr keys %lines) { + $sorted_lines[$i] = $lines{$addr}; + $i++; + } + @sorted_lines; +} + +# These two routines will sort based upon IP addresses +sub ipaddrval { + my(@a) = ($_[0] =~ m#^(\d+)\.(\d+)\.(\d+)\.(\d+)$#); + $a[3]+256*($a[2]+256*($a[1]+256*$a[0])); +} +sub sortbyipaddr { + &ipaddrval($a) <=> &ipaddrval($b); +} + +# This routine parses "show version" +sub ShowVersion { + print STDERR " In ShowVersion: $_" if ($debug); + + ProcessHistory("COMMENTS","keysort","A1", + "- Chassis type:EZT3 - an ADC EZT3 M13 multiplexor\n"); + + while () { + tr/\015//d; + last if(/Active\) >/); + next if(/^(\s*|\s*$cmd\s*)$/); + + /Boot Version (\S*)/ && + ProcessHistory("COMMENTS","keysort","G1", + "- ROM Bootstrap: $1\n") && next; + /Software Version (\S*)/ && + ProcessHistory("COMMENTS","keysort","F1", + "- Software: $1\n") && next; + } + return(0); +} + +# This routine parses "show module" +sub ShowModule { + print STDERR " In ShowModule: $_" if ($debug); + + # eat the header line + $junk = ; + + ProcessHistory("SLOT","","","-\n"); + + # now just copy it verbatim to the history file + while () { + tr/\015//d; + last if(/Active\) >/); + last if(/^$/); + chop; + ProcessHistory("SLOT","","","-$_\n"); + } + ProcessHistory("SLOT","","","-\n"); +} + +# This routine processes a "write term" +sub WriteTerm { + print STDERR " In WriteTerm: $_" if ($debug); + + # eat the header line + $junk = ; + + # now just copy it verbatim to the history file + while () { + tr/\015//d; + last if(/Active\) >/); + chop; + if (/^\s*snmp/ && defined($ENV{'NOCOMMSTR'})) { + /snmp (getcomm|setcomm|trapcomm)(\s+)(\S*)/ && + ProcessHistory("","","","- snmp $1$2\"\"\n") && next; + } + # believe it or not, "-" is the "whole line is comment" command + ProcessHistory("","","","$_\n"); + } + $found_end = 1; + return(1); +} + +# dummy function +sub DoNothing {print STDOUT;} + +# Main +%commands=( + 'version' => "ShowVersion", + 'equipment' => "ShowModule", + 'config' => "WriteTerm", +); +# keys() doesnt return things in the order entered and the order of the +# cmds is important (show version first and write term last). pita +@commands=( + "version", + "equipment", + "config", +); +$cisco_cmds=join(";",@commands); +$cmds_regexp=join("|",@commands); + +open(OUTPUT,">$host.new") || die "Can't open $host.new for writing: $!\n"; +select(OUTPUT); +# make OUTPUT unbuffered if debugging +if ($debug) { $| = 1; } + +if ($file) { + print STDERR "opening file $host\n" if ($debug); + print STDOUT "opening file $host\n" if ($log); + open(INPUT,"<$host") || die "open failed for $host: $!\n"; +} else { + print STDERR "executing elogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($debug); + print STDOUT "executing elogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($log); + if (defined($ENV{NOPIPE})) { + system "elogin -t $timeo -c \"$cisco_cmds\" $host $host.raw 2>&1" || die "elogin failed for $host: $!\n"; + open(INPUT, "< $host.raw") || die "elogin failed for $host: $!\n"; + } else { + open(INPUT,"elogin -t $timeo -c \"$cisco_cmds\" $host ) { + tr/\015//d; + if (/Logging out$/) { + $clean_run=1; + last; + } + if (/Error:/) { + s/^.*Error:/Error:/; + print STDOUT ("$host elogin error: $_"); + print STDERR ("$host elogin error: $_") if ($debug); + $clean_run=0; + last; + } + while (/Active\) >\s*($cmds_regexp)\s*$/) { + $cmd = $1; + if (!defined($prompt)) {$prompt = ($_ =~ /^([^#]+#)/)[0]; } + print STDERR ("HIT COMMAND:$_") if ($debug); + if (! defined($commands{$cmd})) { + print STDERR "found unexpected command - \"$cmd\"\n"; + $clean_run = 0; + last; + } + $rval = &{$commands{$cmd}}; + delete($commands{$cmd}); + if ($rval == -1) { + $clean_run = 0; + last; + } + } +} +print STDOUT "Done $logincmd: $_\n" if ($log); +# Flush History +ProcessHistory("","","",""); +# Cleanup +close(INPUT); +close(OUTPUT); + +if (defined($ENV{NOPIPE})) { + unlink("$host.raw") if (! $debug); +} + +# check for completeness +if (scalar(%commands) || !$clean_run || !$found_end) { + if (scalar(%commands)) { + printf(STDOUT "missed cmd(s): %s\n", join(',', keys(%commands))); + printf(STDERR "missed cmd(s): %s\n", join(',', keys(%commands))) if ($debug); + } + if (!$clean_run || !$found_end) { + print STDOUT "End of run not found\n"; + print STDERR "End of run not found\n" if ($debug); + system("/usr/bin/tail -1 $host.new"); + } + unlink "$host.new" if (! $debug); +} diff --git a/bin/flogin b/bin/flogin deleted file mode 100755 index 652e38a..0000000 --- a/bin/flogin +++ /dev/null @@ -1,530 +0,0 @@ -#!/usr/local/bin/expect -- -## -## -## Copyright (C) 1997 by Henry Kilmer, Erik Sherk and Pete Whiting. -## All rights reserved. -## -## This software may be freely copied, modified and redistributed without -## fee for non-commerical purposes provided that this copyright notice is -## preserved intact on all copies and modified copies. -## -## There is no warranty or other guarantee of fitness of this software. -## It is provided solely "as is". The author(s) disclaim(s) all -## responsibility and liability with respect to this software's usage -## or its effect upon hardware, computer systems, other software, or -## anything else. -## -## -# -# flogin - foundry login -# -# Most options are intuitive for logging into a foundry switch. -# this should be the clogin, but foundry can't seem to dislodge -# their heads and make the UI consistent. i think the UI -# development has been outsourced to Fisher Price. -# The default is to enable (thus -noenable). Some folks have -# setup tacacs to have a user login at priv-lvl = 15 (enabled) -# so the -autoenable flag was added for this case (don't go through -# the process of enabling and the prompt will be the "#" prompt. -# The default username password is the same as the vty password. -# - -# Usage line -set usage "Usage: $argv0 \[-u user\] \[-p user-password\] \[-v vty-password\] \ -\[-w enable-username\] \[-e enable-password\] \[-noenable\] \ -\[-f cloginrc-file\] \[-y ssh_cypher_type\] \[-c command\] \[-s script-file\] \ -\[-autoenable\] \[-t timeout\] router \[router...\]\n" - -# env(CLOGIN) may contain: -# x == do not set xterm banner or name - -# Password file -set password_file $env(HOME)/.cloginrc -# Default is to login to the router -set do_command 0 -set do_script 0 -# The default is to automatically enable -set enable 1 -# The default is that you login non-enabled (tacacs can have you login already enabled) -set autoenable 0 -# The default is to look in the password file to find the passwords. This -# tracks if we receive them on the command line. -set do_passwd 1 -set do_enapasswd 1 - -# Find the user in the ENV, or use the unix userid. -if {[ info exists env(CISCO_USER) ] } { - set default_user $env(CISCO_USER) -} else { - # This uses "id" which I think is portable. At least it has existed - # (without options) on all machines/OSes I've been on recently - - # unlike whoami or id -nu. - regexp {\(([^)]*)} [exec id] junk default_user -} - -# Sometimes routers take awhile to answer (the default is 10 sec) -set timeout 45 - -# Process the command line -for {set i 0} {$i < $argc} {incr i} { - set arg [lindex $argv $i] - - switch -glob -- $arg { - # Username - -u* - - -U* { - if {! [ regexp .\[uU\](.+) $arg ignore user]} { - incr i - set username [ lindex $argv $i ] - } - # VTY Password - } -p* - - -P* { - if {! [ regexp .\[pP\](.+) $arg ignore userpasswd]} { - incr i - set userpasswd [ lindex $argv $i ] - } - set do_passwd 0 - # VTY Password - } -v* - - -v* { - if {! [ regexp .\[vV\](.+) $arg ignore passwd]} { - incr i - set passwd [ lindex $argv $i ] - } - set do_passwd 0 - # Enable Username - } -w* - - -W* { - if {! [ regexp .\[wW\](.+) $arg ignore enauser]} { - incr i - set enausername [ lindex $argv $i ] - } - # Enable Password - } -e* - - -E* { - if {! [ regexp .\[eE\](.+) $arg ignore enapasswd]} { - incr i - set enapasswd [ lindex $argv $i ] - } - set do_enapasswd 0 - # Command to run. - } -c* - - -C* { - if {! [ regexp .\[cC\](.+) $arg ignore command]} { - incr i - set command [ lindex $argv $i ] - } - set do_command 1 - # Expect script to run. - } -s* - - -S* { - if {! [ regexp .\[sS\](.+) $arg ignore sfile]} { - incr i - set sfile [ lindex $argv $i ] - } - if { ! [ file readable $sfile ] } { - send_user "Error: Can't read $sfile\n" - exit 1 - } - set do_script 1 - # cypher type - } -y* - - -Y* { - if {! [ regexp .\[eE\](.+) $arg ignore cypher]} { - incr i - set cypher [ lindex $argv $i ] - } - # alternate cloginrc file - } -f* - - -F* { - if {! [ regexp .\[fF\](.+) $arg ignore password_file]} { - incr i - set password_file [ lindex $argv $i ] - } - } -t* - - -T* { - incr i - set timeout [ lindex $argv $i ] - } -x* - - -X { - if {! [ regexp .\[xX\](.+) $arg ignore cmd_file]} { - incr i - set cmd_file [ lindex $argv $i ] - } - set cmd_fd [open $cmd_file r] - set cmd_text [read $cmd_fd] - close $cmd_fd - set command [join [split $cmd_text \n] \;] - set do_command 1 - # Do we enable? - } -noenable { - set enable 0 - # Does tacacs automatically enable us? - } -autoenable { - set autoenable 1 - set enable 0 - } -* { - send_user "Error: Unknown argument! $arg\n" - send_user $usage - exit 1 - } default { - break - } - } -} -# Process routers...no routers listed is an error. -if { $i == $argc } { - send_user "Error: $usage" -} - -# Only be quiet if we are running a script (it can log its output -# on its own) -if { $do_script } { - log_user 0 -} else { - log_user 1 -} - -# -# Done configuration/variable setting. Now run with it... -# - -# Sets Xterm title if interactive...if its an xterm and the user cares -proc label { host } { - global env - # if CLOGIN has an 'x' in it, don't set the xterm name/banner - if [info exists env(CLOGIN)] { - if {[string first "x" $env(CLOGIN)] != -1} { return } - } - # take host from ENV(TERM) - if [info exists env(TERM)] { - if [regexp \^(xterm|vs) $env(TERM) ignore ] { - send_user "\033]1;[lindex [split $host "."] 0]\a" - send_user "\033]2;$host\a" - } - } -} - -# This is a helper function to make the password file easier to -# maintain. Using this the password file has the form: -# add password sl* pete cow -# add password at* steve -# add password * hanky-pie -proc add {var args} { global $var ;lappend $var $args} -proc find {var router} { - source_password_file - upvar $var list - if { [info exists list] } { - foreach line $list { - if { [string match [lindex $line 0] $router ] } { - return [lrange $line 1 end] - } - } - } - return {} -} - -# Loads the password file. Note that as this file is tcl, and that -# it is sourced, the user better know what to put in there, as it -# could install more than just password info... I will assume however, -# that a "bad guy" could just as easy put such code in the clogin -# script, so I will leave .cloginrc as just an extention of that script -proc source_password_file { } { - global env password_file read_password_file - if { [info exists read_password_file] } { return } - if { [info exists password_file] == 0 } { - set password_file $env(HOME)/.cloginrc - } - set read_password_file 1 - file stat $password_file fileinfo - if { [expr ($fileinfo(mode) & 007)] != 0000 } { - send_user "Error: $password_file must not be world readable/writable\n" - exit 1 - } - source $password_file -} - -# Log into the router. -proc login { router user userpswd passwd enapasswd prompt cyphertype } { - global spawn_id in_proc do_command do_script - set in_proc 1 - set tryssh 1 - - # Telnet to the router & try to login. - if [ catch {spawn telnet $router} reason ] { - send_user "Error: failed to telnet: $reason\n" - exit 1 - } - sleep 0.3 - - # This helps cleanup each expect clause. - expect_after { - timeout { - send_user "\nError: TIMEOUT reached\n" - catch {close}; wait - if { $in_proc} { - return 1 - } else { - continue - } - } eof { - send_user "\nError: EOF received\n" - catch {close}; wait - if { $in_proc} { - return 1 - } else { - continue - } - } - } - - # Here we get a little tricky. There are several possibilities: - # the router can ask for a username and passwd and then - # talk to the TACACS server to authenticate you, or if the - # TACACS server is not working, then it will use the enable - # passwd. Or, the router might not have TACACS turned on, - # then it will just send the passwd. - # if telnet fails with connection refused, try ssh - expect { - "Connection refused" { - close; wait - if { $tryssh } { - if [ catch {spawn ssh -c $cyphertype -x -l $user $router} reason ] { - send_user "Error: failed to ssh: $reason\n" - exit 1 - } - set tryssh 0 - sleep 0.3 - exp_continue - } else { - expect eof - send_user "Error: Connection Refused\n"; wait; return 1 - } - } eof { send_user "Error: Couldn't login\n"; wait; return 1 - } "Unknown host\r\n" { - expect eof - send_user "Error: Unknown host\n"; wait; return 1 - } "Host is unreachable" { - expect eof - send_user "Error: Host Unreachable!\n"; wait; return 1 - } "No address associated with name" { - expect eof - send_user "Error: Unknown host\n"; wait; return 1 - } - -re "Host key not found .* \(yes\/no\)\?" { - send "yes\r" - send_user "Host $router added to the list of known hosts.\n" - exp_continue } - -re "HOST IDENTIFICATION HAS CHANGED.* \(yes\/no\)\?" { - send "no\r" - send_user "Error: The host key for $router has changed. update the known_hosts file accordingly.\n" - return 1 } - -re "(Username:|login:|Name :)" { - sleep 1; - send "$user\r" - expect { - eof { send_user "Error: Couldn't login\n"; wait; return 1 } - -re "\[Pp]assword:" { send "$userpswd\r" } - "$prompt" { set in_proc 0; return 0 } - } - exp_continue - } - "\[Pp]assword:" { send "$passwd\r" - expect { - eof { send_user "Error: Couldn't login\n"; wait; return 1 } - "Password:" { send "$enapasswd\r" } - "$prompt" { set in_proc 0; return 0 } - } - exp_continue - } - "$prompt" { } - denied { send_user "Error: Check your passwd for $router\n" - if { $do_command || $do_script } { - send "quit" - wait - return 1 - } else { - return 1 - } - } - "% Bad passwords" {send_user "Error: Check your passwd for $router\n"; return 1 } - } - set in_proc 0 - return 0 -} - -# Enable -proc do_enable { enauser enapasswd } { - global prompt in_proc - set in_proc 1 - - sleep 1; # dont go too fast for it now... - send "enable\r" - expect { - -re "(Username|User Name):" { send "$enauser\r"; exp_continue} - "Password:" { send "$enapasswd\r"; exp_continue} - "#" { } - denied { send_user "Error: Check your Enable passwd\n"; return 1} - "% Bad passwords" { send_user "Error: Check your Enable passwd\n" - return 1 - } - } - # Set the prompt variable so script files don't need to know what it is. - set prompt "#" - set in_proc 0 - return 0 -} - -# Run commands given on the command line. -proc run_commands { prompt command } { - global in_proc - set in_proc 1 - - send "skip-page-display\r" - expect $prompt {} - - # Is this a multi-command? - if [ string match "*\;*" "$command" ] { - set commands [split $command \;] - set num_commands [llength $commands] - - for {set i 0} {$i < $num_commands} { incr i} { - send "[subst [lindex $commands $i]]\r" - expect { - -re "^\[^\n\r]*$prompt." { exp_continue } - -re "^\[^\n\r *]*$prompt" {} - -re "\[\n\r]" { exp_continue } - } - } - } else { - send "[subst $command]\r" - expect { - -re "^\[^\n\r]*$prompt." { exp_continue } - -re "^\[^\n\r *]*$prompt" {} - -re "\[\n\r]" { exp_continue } - } - } - send "exit\r" - expect { - "\n" { exp_continue } - -re "^\[^ ]+>" { - send "exit\r" - exp_continue } - timeout { return 0 } - eof { return 0 } - } - set in_proc 0 -} - -# -# For each router... (this is main loop) -# -set in_proc 0 -foreach router [lrange $argv $i end] { - set router [string tolower $router] - send_user "$router\n" - - # Figure out prompt. - # Since autoenable is off by default, if we have it defined, it - # was done on the command line. If it is not specifically set on the - # command line, check the password file. - if $autoenable { - set prompt "#" - } else { - set ae [find autoenable $router] - if { "$ae" == "1" } { - set autoenable 1 - set enable 0 - set prompt "#" - } else { - set autoenable 0 - set prompt ">" - } - } - - # Figure out passwords - if { $do_passwd || $do_enapasswd } { - set pswd [find password $router] - if { [llength $pswd] == 0 } { - send_user "Error - no password for $router in $password_file.\n" - continue - } - if { $do_enapasswd && $autoenable == 0 && [llength $pswd] < 2 } { - send_user "Error - no enable password for $router in $password_file.\n" - continue - } - set passwd [lindex $pswd 0] - set enapasswd [lindex $pswd 1] - } - - # Figure out username - if {[info exists username]} { - # command line username - set ruser $username - } else { - set ruser [find user $router] - if { "$ruser" == "" } { set ruser $default_user } - } - - # Figure out username's password (if different from the vty password) - if {[info exists userpasswd]} { - # command line username - set userpswd $userpasswd - } else { - set userpswd [find userpassword $router] - if { "$userpswd" == "" } { set userpswd $passwd } - } - - # Figure out enable username - if {[info exists enausername]} { - # command line enausername - set enauser $enausername - } else { - set enauser [find enauser $router] - if { "$enauser" == "" } { set enauser $ruser } - } - - # Figure out cypher tpye - if {[info exists cypher]} { - # command line cypher type - set cyphertype $cypher - } else { - set cyphertype [find cyphertype $router] - if { "$cyphertype" == "" } { set cyphertype "3des" } - } - - # Login to the router - if {[login $router $ruser $userpswd $passwd $enapasswd $prompt $cyphertype]} { - continue - } - if { $enable } { - if {[do_enable $enauser $enapasswd]} { - if { $do_command || $do_script } { - close; wait - continue - } - } - } - - if { $do_command } { - if {[run_commands $prompt $command]} { - continue - } - } elseif { $do_script } { - # fucking foundry - send "skip-page-display\r" - expect $prompt {} - source $sfile - close - } else { - label $router - log_user 1 - interact - } - - # End of for each router - wait - sleep 0.3 -} -exit 0 diff --git a/bin/flogin.in b/bin/flogin.in new file mode 100755 index 0000000..0419bb6 --- /dev/null +++ b/bin/flogin.in @@ -0,0 +1,530 @@ +#!@EXPECT_PATH@ -- +## +## +## Copyright (C) 1997 by Henry Kilmer, Erik Sherk and Pete Whiting. +## All rights reserved. +## +## This software may be freely copied, modified and redistributed without +## fee for non-commerical purposes provided that this copyright notice is +## preserved intact on all copies and modified copies. +## +## There is no warranty or other guarantee of fitness of this software. +## It is provided solely "as is". The author(s) disclaim(s) all +## responsibility and liability with respect to this software's usage +## or its effect upon hardware, computer systems, other software, or +## anything else. +## +## +# +# flogin - foundry login +# +# Most options are intuitive for logging into a foundry switch. +# this should be the clogin, but foundry can't seem to dislodge +# their heads and make the UI consistent. i think the UI +# development has been outsourced to Fisher Price. +# The default is to enable (thus -noenable). Some folks have +# setup tacacs to have a user login at priv-lvl = 15 (enabled) +# so the -autoenable flag was added for this case (don't go through +# the process of enabling and the prompt will be the "#" prompt. +# The default username password is the same as the vty password. +# + +# Usage line +set usage "Usage: $argv0 \[-u user\] \[-p user-password\] \[-v vty-password\] \ +\[-w enable-username\] \[-e enable-password\] \[-noenable\] \ +\[-f cloginrc-file\] \[-y ssh_cypher_type\] \[-c command\] \[-s script-file\] \ +\[-autoenable\] \[-t timeout\] router \[router...\]\n" + +# env(CLOGIN) may contain: +# x == do not set xterm banner or name + +# Password file +set password_file $env(HOME)/.cloginrc +# Default is to login to the router +set do_command 0 +set do_script 0 +# The default is to automatically enable +set enable 1 +# The default is that you login non-enabled (tacacs can have you login already enabled) +set autoenable 0 +# The default is to look in the password file to find the passwords. This +# tracks if we receive them on the command line. +set do_passwd 1 +set do_enapasswd 1 + +# Find the user in the ENV, or use the unix userid. +if {[ info exists env(CISCO_USER) ] } { + set default_user $env(CISCO_USER) +} else { + # This uses "id" which I think is portable. At least it has existed + # (without options) on all machines/OSes I've been on recently - + # unlike whoami or id -nu. + regexp {\(([^)]*)} [exec id] junk default_user +} + +# Sometimes routers take awhile to answer (the default is 10 sec) +set timeout 45 + +# Process the command line +for {set i 0} {$i < $argc} {incr i} { + set arg [lindex $argv $i] + + switch -glob -- $arg { + # Username + -u* - + -U* { + if {! [ regexp .\[uU\](.+) $arg ignore user]} { + incr i + set username [ lindex $argv $i ] + } + # VTY Password + } -p* - + -P* { + if {! [ regexp .\[pP\](.+) $arg ignore userpasswd]} { + incr i + set userpasswd [ lindex $argv $i ] + } + set do_passwd 0 + # VTY Password + } -v* - + -v* { + if {! [ regexp .\[vV\](.+) $arg ignore passwd]} { + incr i + set passwd [ lindex $argv $i ] + } + set do_passwd 0 + # Enable Username + } -w* - + -W* { + if {! [ regexp .\[wW\](.+) $arg ignore enauser]} { + incr i + set enausername [ lindex $argv $i ] + } + # Enable Password + } -e* - + -E* { + if {! [ regexp .\[eE\](.+) $arg ignore enapasswd]} { + incr i + set enapasswd [ lindex $argv $i ] + } + set do_enapasswd 0 + # Command to run. + } -c* - + -C* { + if {! [ regexp .\[cC\](.+) $arg ignore command]} { + incr i + set command [ lindex $argv $i ] + } + set do_command 1 + # Expect script to run. + } -s* - + -S* { + if {! [ regexp .\[sS\](.+) $arg ignore sfile]} { + incr i + set sfile [ lindex $argv $i ] + } + if { ! [ file readable $sfile ] } { + send_user "Error: Can't read $sfile\n" + exit 1 + } + set do_script 1 + # cypher type + } -y* - + -Y* { + if {! [ regexp .\[eE\](.+) $arg ignore cypher]} { + incr i + set cypher [ lindex $argv $i ] + } + # alternate cloginrc file + } -f* - + -F* { + if {! [ regexp .\[fF\](.+) $arg ignore password_file]} { + incr i + set password_file [ lindex $argv $i ] + } + } -t* - + -T* { + incr i + set timeout [ lindex $argv $i ] + } -x* - + -X { + if {! [ regexp .\[xX\](.+) $arg ignore cmd_file]} { + incr i + set cmd_file [ lindex $argv $i ] + } + set cmd_fd [open $cmd_file r] + set cmd_text [read $cmd_fd] + close $cmd_fd + set command [join [split $cmd_text \n] \;] + set do_command 1 + # Do we enable? + } -noenable { + set enable 0 + # Does tacacs automatically enable us? + } -autoenable { + set autoenable 1 + set enable 0 + } -* { + send_user "Error: Unknown argument! $arg\n" + send_user $usage + exit 1 + } default { + break + } + } +} +# Process routers...no routers listed is an error. +if { $i == $argc } { + send_user "Error: $usage" +} + +# Only be quiet if we are running a script (it can log its output +# on its own) +if { $do_script } { + log_user 0 +} else { + log_user 1 +} + +# +# Done configuration/variable setting. Now run with it... +# + +# Sets Xterm title if interactive...if its an xterm and the user cares +proc label { host } { + global env + # if CLOGIN has an 'x' in it, don't set the xterm name/banner + if [info exists env(CLOGIN)] { + if {[string first "x" $env(CLOGIN)] != -1} { return } + } + # take host from ENV(TERM) + if [info exists env(TERM)] { + if [regexp \^(xterm|vs) $env(TERM) ignore ] { + send_user "\033]1;[lindex [split $host "."] 0]\a" + send_user "\033]2;$host\a" + } + } +} + +# This is a helper function to make the password file easier to +# maintain. Using this the password file has the form: +# add password sl* pete cow +# add password at* steve +# add password * hanky-pie +proc add {var args} { global $var ;lappend $var $args} +proc find {var router} { + source_password_file + upvar $var list + if { [info exists list] } { + foreach line $list { + if { [string match [lindex $line 0] $router ] } { + return [lrange $line 1 end] + } + } + } + return {} +} + +# Loads the password file. Note that as this file is tcl, and that +# it is sourced, the user better know what to put in there, as it +# could install more than just password info... I will assume however, +# that a "bad guy" could just as easy put such code in the clogin +# script, so I will leave .cloginrc as just an extention of that script +proc source_password_file { } { + global env password_file read_password_file + if { [info exists read_password_file] } { return } + if { [info exists password_file] == 0 } { + set password_file $env(HOME)/.cloginrc + } + set read_password_file 1 + file stat $password_file fileinfo + if { [expr ($fileinfo(mode) & 007)] != 0000 } { + send_user "Error: $password_file must not be world readable/writable\n" + exit 1 + } + source $password_file +} + +# Log into the router. +proc login { router user userpswd passwd enapasswd prompt cyphertype } { + global spawn_id in_proc do_command do_script + set in_proc 1 + set tryssh 1 + + # Telnet to the router & try to login. + if [ catch {spawn telnet $router} reason ] { + send_user "Error: failed to telnet: $reason\n" + exit 1 + } + sleep 0.3 + + # This helps cleanup each expect clause. + expect_after { + timeout { + send_user "\nError: TIMEOUT reached\n" + catch {close}; wait + if { $in_proc} { + return 1 + } else { + continue + } + } eof { + send_user "\nError: EOF received\n" + catch {close}; wait + if { $in_proc} { + return 1 + } else { + continue + } + } + } + + # Here we get a little tricky. There are several possibilities: + # the router can ask for a username and passwd and then + # talk to the TACACS server to authenticate you, or if the + # TACACS server is not working, then it will use the enable + # passwd. Or, the router might not have TACACS turned on, + # then it will just send the passwd. + # if telnet fails with connection refused, try ssh + expect { + "Connection refused" { + close; wait + if { $tryssh } { + if [ catch {spawn ssh -c $cyphertype -x -l $user $router} reason ] { + send_user "Error: failed to ssh: $reason\n" + exit 1 + } + set tryssh 0 + sleep 0.3 + exp_continue + } else { + expect eof + send_user "Error: Connection Refused\n"; wait; return 1 + } + } eof { send_user "Error: Couldn't login\n"; wait; return 1 + } "Unknown host\r\n" { + expect eof + send_user "Error: Unknown host\n"; wait; return 1 + } "Host is unreachable" { + expect eof + send_user "Error: Host Unreachable!\n"; wait; return 1 + } "No address associated with name" { + expect eof + send_user "Error: Unknown host\n"; wait; return 1 + } + -re "Host key not found .* \(yes\/no\)\?" { + send "yes\r" + send_user "Host $router added to the list of known hosts.\n" + exp_continue } + -re "HOST IDENTIFICATION HAS CHANGED.* \(yes\/no\)\?" { + send "no\r" + send_user "Error: The host key for $router has changed. update the known_hosts file accordingly.\n" + return 1 } + -re "(Username:|login:|Name :)" { + sleep 1; + send "$user\r" + expect { + eof { send_user "Error: Couldn't login\n"; wait; return 1 } + -re "\[Pp]assword:" { send "$userpswd\r" } + "$prompt" { set in_proc 0; return 0 } + } + exp_continue + } + "\[Pp]assword:" { send "$passwd\r" + expect { + eof { send_user "Error: Couldn't login\n"; wait; return 1 } + "Password:" { send "$enapasswd\r" } + "$prompt" { set in_proc 0; return 0 } + } + exp_continue + } + "$prompt" { } + denied { send_user "Error: Check your passwd for $router\n" + if { $do_command || $do_script } { + send "quit" + wait + return 1 + } else { + return 1 + } + } + "% Bad passwords" {send_user "Error: Check your passwd for $router\n"; return 1 } + } + set in_proc 0 + return 0 +} + +# Enable +proc do_enable { enauser enapasswd } { + global prompt in_proc + set in_proc 1 + + sleep 1; # dont go too fast for it now... + send "enable\r" + expect { + -re "(Username|User Name):" { send "$enauser\r"; exp_continue} + "Password:" { send "$enapasswd\r"; exp_continue} + "#" { } + denied { send_user "Error: Check your Enable passwd\n"; return 1} + "% Bad passwords" { send_user "Error: Check your Enable passwd\n" + return 1 + } + } + # Set the prompt variable so script files don't need to know what it is. + set prompt "#" + set in_proc 0 + return 0 +} + +# Run commands given on the command line. +proc run_commands { prompt command } { + global in_proc + set in_proc 1 + + send "skip-page-display\r" + expect $prompt {} + + # Is this a multi-command? + if [ string match "*\;*" "$command" ] { + set commands [split $command \;] + set num_commands [llength $commands] + + for {set i 0} {$i < $num_commands} { incr i} { + send "[subst [lindex $commands $i]]\r" + expect { + -re "^\[^\n\r]*$prompt." { exp_continue } + -re "^\[^\n\r *]*$prompt" {} + -re "\[\n\r]" { exp_continue } + } + } + } else { + send "[subst $command]\r" + expect { + -re "^\[^\n\r]*$prompt." { exp_continue } + -re "^\[^\n\r *]*$prompt" {} + -re "\[\n\r]" { exp_continue } + } + } + send "exit\r" + expect { + "\n" { exp_continue } + -re "^\[^ ]+>" { + send "exit\r" + exp_continue } + timeout { return 0 } + eof { return 0 } + } + set in_proc 0 +} + +# +# For each router... (this is main loop) +# +set in_proc 0 +foreach router [lrange $argv $i end] { + set router [string tolower $router] + send_user "$router\n" + + # Figure out prompt. + # Since autoenable is off by default, if we have it defined, it + # was done on the command line. If it is not specifically set on the + # command line, check the password file. + if $autoenable { + set prompt "#" + } else { + set ae [find autoenable $router] + if { "$ae" == "1" } { + set autoenable 1 + set enable 0 + set prompt "#" + } else { + set autoenable 0 + set prompt ">" + } + } + + # Figure out passwords + if { $do_passwd || $do_enapasswd } { + set pswd [find password $router] + if { [llength $pswd] == 0 } { + send_user "Error - no password for $router in $password_file.\n" + continue + } + if { $do_enapasswd && $autoenable == 0 && [llength $pswd] < 2 } { + send_user "Error - no enable password for $router in $password_file.\n" + continue + } + set passwd [lindex $pswd 0] + set enapasswd [lindex $pswd 1] + } + + # Figure out username + if {[info exists username]} { + # command line username + set ruser $username + } else { + set ruser [find user $router] + if { "$ruser" == "" } { set ruser $default_user } + } + + # Figure out username's password (if different from the vty password) + if {[info exists userpasswd]} { + # command line username + set userpswd $userpasswd + } else { + set userpswd [find userpassword $router] + if { "$userpswd" == "" } { set userpswd $passwd } + } + + # Figure out enable username + if {[info exists enausername]} { + # command line enausername + set enauser $enausername + } else { + set enauser [find enauser $router] + if { "$enauser" == "" } { set enauser $ruser } + } + + # Figure out cypher tpye + if {[info exists cypher]} { + # command line cypher type + set cyphertype $cypher + } else { + set cyphertype [find cyphertype $router] + if { "$cyphertype" == "" } { set cyphertype "3des" } + } + + # Login to the router + if {[login $router $ruser $userpswd $passwd $enapasswd $prompt $cyphertype]} { + continue + } + if { $enable } { + if {[do_enable $enauser $enapasswd]} { + if { $do_command || $do_script } { + close; wait + continue + } + } + } + + if { $do_command } { + if {[run_commands $prompt $command]} { + continue + } + } elseif { $do_script } { + # fucking foundry + send "skip-page-display\r" + expect $prompt {} + source $sfile + close + } else { + label $router + log_user 1 + interact + } + + # End of for each router + wait + sleep 0.3 +} +exit 0 diff --git a/bin/francid b/bin/francid deleted file mode 100755 index 54aae8d..0000000 --- a/bin/francid +++ /dev/null @@ -1,384 +0,0 @@ -#!/usr/local/bin/perl -## -## Amazingly hacked version of Hank's rancid - this one tries to -## deal with foundrys. -## -## Copyright (C) 1997 by Henry Kilmer. -## All rights reserved. -## -## This software may be freely copied, modified and redistributed without -## fee for non-commerical purposes provided that this copyright notice is -## preserved intact on all copies and modified copies. -## -## There is no warranty or other guarantee of fitness of this software. -## It is provided solely "as is". The author(s) disclaim(s) all -## responsibility and liability with respect to this software's usage -## or its effect upon hardware, computer systems, other software, or -## anything else. -## -## -# -# RANCID - Really Awesome New Cisco confIg Differ -# -# usage: rancid [-d] [-l] [-f filename | $host] -# -use Getopt::Std; -getopts('dflm'); -$log = $opt_l; -$debug = $opt_d; -$file = $opt_f; -$host = $ARGV[0]; -$clean_run = 0; -$found_end = 0; -$timeo = 90; # flogin timeout in seconds - -# This routine is used to print out the router configuration -sub ProcessHistory { - my($new_hist_tag,$new_command,$command_string,@string)=(@_); - if((($new_hist_tag ne $hist_tag) || ($new_command ne $command)) - && defined %history) { - print eval "$command \%history"; - undef %history; - } - if (($new_hist_tag) && ($new_command) && ($command_string)) { - if ($history{$command_string}) { - $history{$command_string} = "$history{$command_string}@string"; - } else { - $history{$command_string} = "@string"; - } - } elsif (($new_hist_tag) && ($new_command)) { - $history{++$#history} = "@string"; - } else { - print "@string"; - } - $hist_tag = $new_hist_tag; - $command = $new_command; - 1; -} - -sub numerically { $a <=> $b; } - -# This is a sort routing that will sort numerically on the -# keys of a hash as if it were a normal array. -sub keynsort { - local(%lines)=@_; - local($i) = 0; - local(@sorted_lines); - foreach $key (sort numerically keys(%lines)) { - $sorted_lines[$i] = $lines{$key}; - $i++; - } - @sorted_lines; -} - -# This is a sort routing that will sort on the -# keys of a hash as if it were a normal array. -sub keysort { - local(%lines)=@_; - local($i) = 0; - local(@sorted_lines); - foreach $key (sort keys(%lines)) { - $sorted_lines[$i] = $lines{$key}; - $i++; - } - @sorted_lines; -} - -# This is a sort routing that will sort on the -# values of a hash as if it were a normal array. -sub valsort{ - local(%lines)=@_; - local($i) = 0; - local(@sorted_lines); - foreach $key (sort values %lines) { - $sorted_lines[$i] = $key; - $i++; - } - @sorted_lines; -} - -# This is a numerical sort routing (ascending). -sub numsort { - local(%lines)=@_; - local($i) = 0; - local(@sorted_lines); - foreach $num (sort {$a <=> $b} keys %lines) { - $sorted_lines[$i] = $lines{$num}; - $i++; - } - @sorted_lines; -} - -# This is a sort routine that will sort on the -# ip address when the ip address is anywhere in -# the strings. -sub ipsort { - local(%lines)=@_; - local($i) = 0; - local(@sorted_lines); - foreach $addr (sort sortbyipaddr keys %lines) { - $sorted_lines[$i] = $lines{$addr}; - $i++; - } - @sorted_lines; -} - -# These two routines will sort based upon IP addresses -sub ipaddrval { - my(@a) = ($_[0] =~ m#^(\d+)\.(\d+)\.(\d+)\.(\d+)$#); - $a[3]+256*($a[2]+256*($a[1]+256*$a[0])); -} -sub sortbyipaddr { - &ipaddrval($a) <=> &ipaddrval($b); -} - -# This routine parses "show version" -sub ShowVersion { - my($slot); - - print STDERR " In ShowVersion: $_" if ($debug); - - while () { - tr/\015//d; - next if /^\s*$/; - last if(/^$prompt/); - - next if (/^The system /); - - s/^\s*(HW|SW)/$1/; - s/^\s*(Compiled on)/SW: $1/; - #s/^(HW.*)/$1\n/; - if (/^SL (\d)/) { - $slot = "Slot $1"; - s/^SL \d+/$slot/; - } - if (/MHz .* processor/) { - $slot = "MGMT"; - } - s/^(\s*\d+ )/$slot:$1/; - s/^===*//; - - ProcessHistory("VERSION","","","!$_"); - } - ProcessHistory("VERSION","","","!\n"); - return(0); -} - -# This routine parses "show chassis" -sub ShowChassis { - print STDERR " In ShowChassis: $_" if ($debug); - - while () { - tr/\015//d; - last if (/^$prompt/); - next if (/ from /); - next if (/current temperature/i); - ProcessHistory("CHASSIS","","","! $_"); - } - ProcessHistory("CHASSIS","","","!\n"); - return(0); -} - -# This routine parses "show flash" -sub ShowFlash { - print STDERR " In ShowFlash: $_" if ($debug); - - while () { - tr/\015//d; - last if(/^$prompt/); - next if /^\s*$/; - ProcessHistory("FLASH","","","!Flash: $_"); - } - ProcessHistory("","","","!\n"); - return; -} - -# This routine parses "show module" -sub ShowModule { - print STDERR " In ShowModule: $_" if ($debug); - - while () { - tr/\015//d; - last if(/^$prompt/); - next if /^\s*$/; - next if /:\s*$/; - ProcessHistory("MODULE","","","!Module: $_"); - } - ProcessHistory("","","","!\n"); - return(0); -} - -# This routine processes a "write term" -sub WriteTerm { - print STDERR " In WriteTerm: $_" if ($debug); - - while () { - tr/\015//d; - last if(/^$prompt/); - - /Current configuration:/i && next; - /^ver \d+\.\d+/ && next; - /^module \d+ / && next; - - /^ntp clock-period / && next; # kill ntp clock-period - /^ length / && next; # kill length on serial lines - /^ width / && next; # kill width on serial lines - # filter out any RCS/CVS tags to avoid confusing local CVS storage - s/\$(Revision|Id):/ $1:/; - # order access-lists - /^access-list\s+(\d+)\s+(perm|deny)\s+(\d\S+)(\/\d+)\s*$/ && - ProcessHistory("PACL $1 $2","ipsort","$3","$_") - && next; - /^access-list\s+(\d\d?)\s+(\S+)\s+(\S+)/ && - ProcessHistory("ACL $1 $2","ipsort","$3","$_") && next; - # order extended access-lists - /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+host\s+(\S+)/ && - ProcessHistory("EACL $1 $2","ipsort","$3","$_") && next; - /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+(\d\S+)/ && - ProcessHistory("EACL $1 $2","ipsort","$3","$_") && next; - /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+any/ && - ProcessHistory("EACL $1 $2","ipsort","0.0.0.0","$_") && next; - # order arp lists - /^arp\s+(\d+\.\d+\.\d+\.\d+)\s+/ && - ProcessHistory("ARP","ipsort","$1","$_") && next; - # order logging statements - /^logging (\d+\.\d+\.\d+\.\d+)/ && - ProcessHistory("LOGGING","ipsort","$1","$_") && next; - # order name-server statements - /^ip name-server (\d+\.\d+\.\d+\.\d+)/ && - ProcessHistory("NAMESERVER","ipsort","$1","$_") && next; - # order snmp-server host statements - /^snmp-server host (\d+\.\d+\.\d+\.\d+)/ && - ProcessHistory("SNMPSERVERHOST","ipsort","$1","$_") && next; - /^snmp-server community / && - ProcessHistory("SNMPSERVERCOMM","keysort","$_","$_") && next; - - # order tacacs server statements - /^(tacacs-server key )/ && - ProcessHistory("","","","! $1\n") && next; - /^tacacs-server host (\d+\.\d+\.\d+\.\d+)/ && - ProcessHistory("TAC","ipsort","$1","$_") && next; - - # delete ntp auth password - /^(ntp authentication-key \d+ md5) / && - ProcessHistory("","","","!$1 \n") && next; - # order ntp peers/servers - if (/^ntp (server|peer) (\d+)\.(\d+)\.(\d+)\.(\d+)/) { - $sortkey = sprintf("$1 %03d%03d%03d%03d",$2,$3,$4,$5); - ProcessHistory("NTP","keysort",$sortkey,"$_"); - next; - } - # order ip host line statements - /^ip host line(\d+)/ && - ProcessHistory("IPHOST","numsort","$1","$_") && next; - # order ip nat source static statements - /^ip nat (\S+) source static (\S+)/ && - ProcessHistory("IP NAT $1","ipsort","$2","$_") && next; - - ProcessHistory("","","","$_"); - # end of config - if (/^end$/) { - $found_end = 1; - return(1); - } - } - return(0); -} - -# dummy function -sub DoNothing {print STDOUT;} - -# Main -%commands=( - 'show version' => "ShowVersion", - 'show chassis' => "ShowChassis", - 'show module' => "ShowModule", - 'show flash' => "ShowFlash", - 'write term' => "WriteTerm" -); -# keys() doesnt return things in the order entered and the order of the -# cmds is important. pita -@commands=( - "show version", - "show chassis", - "show module", - "show flash", - "write term" -); -$cisco_cmds=join(";",@commands); -$cmds_regexp=join("|",@commands); - -open(OUTPUT,">$host.new") || die "Can't open $host.new for writing: $!\n"; -select(OUTPUT); -# make OUTPUT unbuffered if debugging -if ($debug) { $| = 1; } - -if ($file) { - print STDERR "opening file $host\n" if ($debug); - print STDOUT "opening file $host\n" if ($log); - open(INPUT,"<$host") || die "open failed for $host: $!\n"; -} else { - print STDERR "executing flogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($debug); - print STDOUT "executing flogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($log); - if (defined($ENV{NOPIPE})) { - system "flogin -t $timeo -c \"$cisco_cmds\" $host $host.raw 2>&1" || die "flogin failed for $host: $!\n"; - open(INPUT, "< $host.raw") || die "flogin failed for $host: $!\n"; - } else { - open(INPUT,"flogin -t $timeo -c \"$cisco_cmds\" $host ) { - tr/\015//d; - if (/\#exit$/) { - $clean_run=1; - last; - } - if (/Error:/) { - s/^.*Error:/Error:/; - print STDOUT ("$host flogin error: $_"); - print STDERR ("$host flogin error: $_") if ($debug); - $clean_run=0; - last; - } - while (/#\s*($cmds_regexp)\s*$/) { - $cmd = $1; - if (!defined($prompt)) {$prompt = ($_ =~ /^([^#]+#)/)[0]; } - print STDERR ("HIT COMMAND:$_") if ($debug); - if (! defined($commands{$cmd})) { - print STDERR "found unexpected command - \"$cmd\"\n"; - $clean_run = 0; - last TOP; - } - $rval = &{$commands{$cmd}}; - delete($commands{$cmd}); - if ($rval == -1) { - $clean_run = 0; - last TOP; - } - } -} -print STDOUT "Done $logincmd: $_\n" if ($log); -# Flush History -ProcessHistory("","","",""); -# Cleanup -close(INPUT); -close(OUTPUT); - -if (defined($ENV{NOPIPE})) { - unlink("$host.raw") if (! $debug); -} - -# check for completeness -if (scalar(%commands) || !$clean_run || !$found_end) { - if (scalar(%commands)) { - printf(STDOUT "missed cmd(s): %s\n", join(',', keys(%commands))); - printf(STDERR "missed cmd(s): %s\n", join(',', keys(%commands))) if ($debug); - } - if (!$clean_run || !$found_end) { - print STDOUT "End of run not found\n"; - print STDERR "End of run not found\n" if ($debug); - system("/usr/bin/tail -1 $host.new"); - } - unlink "$host.new" if (! $debug); -} diff --git a/bin/francid.in b/bin/francid.in new file mode 100755 index 0000000..6f0c2b7 --- /dev/null +++ b/bin/francid.in @@ -0,0 +1,384 @@ +#!@PERLV_PATH@ +## +## Amazingly hacked version of Hank's rancid - this one tries to +## deal with foundrys. +## +## Copyright (C) 1997 by Henry Kilmer. +## All rights reserved. +## +## This software may be freely copied, modified and redistributed without +## fee for non-commerical purposes provided that this copyright notice is +## preserved intact on all copies and modified copies. +## +## There is no warranty or other guarantee of fitness of this software. +## It is provided solely "as is". The author(s) disclaim(s) all +## responsibility and liability with respect to this software's usage +## or its effect upon hardware, computer systems, other software, or +## anything else. +## +## +# +# RANCID - Really Awesome New Cisco confIg Differ +# +# usage: rancid [-d] [-l] [-f filename | $host] +# +use Getopt::Std; +getopts('dflm'); +$log = $opt_l; +$debug = $opt_d; +$file = $opt_f; +$host = $ARGV[0]; +$clean_run = 0; +$found_end = 0; +$timeo = 90; # flogin timeout in seconds + +# This routine is used to print out the router configuration +sub ProcessHistory { + my($new_hist_tag,$new_command,$command_string,@string)=(@_); + if((($new_hist_tag ne $hist_tag) || ($new_command ne $command)) + && defined %history) { + print eval "$command \%history"; + undef %history; + } + if (($new_hist_tag) && ($new_command) && ($command_string)) { + if ($history{$command_string}) { + $history{$command_string} = "$history{$command_string}@string"; + } else { + $history{$command_string} = "@string"; + } + } elsif (($new_hist_tag) && ($new_command)) { + $history{++$#history} = "@string"; + } else { + print "@string"; + } + $hist_tag = $new_hist_tag; + $command = $new_command; + 1; +} + +sub numerically { $a <=> $b; } + +# This is a sort routing that will sort numerically on the +# keys of a hash as if it were a normal array. +sub keynsort { + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $key (sort numerically keys(%lines)) { + $sorted_lines[$i] = $lines{$key}; + $i++; + } + @sorted_lines; +} + +# This is a sort routing that will sort on the +# keys of a hash as if it were a normal array. +sub keysort { + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $key (sort keys(%lines)) { + $sorted_lines[$i] = $lines{$key}; + $i++; + } + @sorted_lines; +} + +# This is a sort routing that will sort on the +# values of a hash as if it were a normal array. +sub valsort{ + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $key (sort values %lines) { + $sorted_lines[$i] = $key; + $i++; + } + @sorted_lines; +} + +# This is a numerical sort routing (ascending). +sub numsort { + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $num (sort {$a <=> $b} keys %lines) { + $sorted_lines[$i] = $lines{$num}; + $i++; + } + @sorted_lines; +} + +# This is a sort routine that will sort on the +# ip address when the ip address is anywhere in +# the strings. +sub ipsort { + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $addr (sort sortbyipaddr keys %lines) { + $sorted_lines[$i] = $lines{$addr}; + $i++; + } + @sorted_lines; +} + +# These two routines will sort based upon IP addresses +sub ipaddrval { + my(@a) = ($_[0] =~ m#^(\d+)\.(\d+)\.(\d+)\.(\d+)$#); + $a[3]+256*($a[2]+256*($a[1]+256*$a[0])); +} +sub sortbyipaddr { + &ipaddrval($a) <=> &ipaddrval($b); +} + +# This routine parses "show version" +sub ShowVersion { + my($slot); + + print STDERR " In ShowVersion: $_" if ($debug); + + while () { + tr/\015//d; + next if /^\s*$/; + last if(/^$prompt/); + + next if (/^The system /); + + s/^\s*(HW|SW)/$1/; + s/^\s*(Compiled on)/SW: $1/; + #s/^(HW.*)/$1\n/; + if (/^SL (\d)/) { + $slot = "Slot $1"; + s/^SL \d+/$slot/; + } + if (/MHz .* processor/) { + $slot = "MGMT"; + } + s/^(\s*\d+ )/$slot:$1/; + s/^===*//; + + ProcessHistory("VERSION","","","!$_"); + } + ProcessHistory("VERSION","","","!\n"); + return(0); +} + +# This routine parses "show chassis" +sub ShowChassis { + print STDERR " In ShowChassis: $_" if ($debug); + + while () { + tr/\015//d; + last if (/^$prompt/); + next if (/ from /); + next if (/current temperature/i); + ProcessHistory("CHASSIS","","","! $_"); + } + ProcessHistory("CHASSIS","","","!\n"); + return(0); +} + +# This routine parses "show flash" +sub ShowFlash { + print STDERR " In ShowFlash: $_" if ($debug); + + while () { + tr/\015//d; + last if(/^$prompt/); + next if /^\s*$/; + ProcessHistory("FLASH","","","!Flash: $_"); + } + ProcessHistory("","","","!\n"); + return; +} + +# This routine parses "show module" +sub ShowModule { + print STDERR " In ShowModule: $_" if ($debug); + + while () { + tr/\015//d; + last if(/^$prompt/); + next if /^\s*$/; + next if /:\s*$/; + ProcessHistory("MODULE","","","!Module: $_"); + } + ProcessHistory("","","","!\n"); + return(0); +} + +# This routine processes a "write term" +sub WriteTerm { + print STDERR " In WriteTerm: $_" if ($debug); + + while () { + tr/\015//d; + last if(/^$prompt/); + + /Current configuration:/i && next; + /^ver \d+\.\d+/ && next; + /^module \d+ / && next; + + /^ntp clock-period / && next; # kill ntp clock-period + /^ length / && next; # kill length on serial lines + /^ width / && next; # kill width on serial lines + # filter out any RCS/CVS tags to avoid confusing local CVS storage + s/\$(Revision|Id):/ $1:/; + # order access-lists + /^access-list\s+(\d+)\s+(perm|deny)\s+(\d\S+)(\/\d+)\s*$/ && + ProcessHistory("PACL $1 $2","ipsort","$3","$_") + && next; + /^access-list\s+(\d\d?)\s+(\S+)\s+(\S+)/ && + ProcessHistory("ACL $1 $2","ipsort","$3","$_") && next; + # order extended access-lists + /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+host\s+(\S+)/ && + ProcessHistory("EACL $1 $2","ipsort","$3","$_") && next; + /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+(\d\S+)/ && + ProcessHistory("EACL $1 $2","ipsort","$3","$_") && next; + /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+any/ && + ProcessHistory("EACL $1 $2","ipsort","0.0.0.0","$_") && next; + # order arp lists + /^arp\s+(\d+\.\d+\.\d+\.\d+)\s+/ && + ProcessHistory("ARP","ipsort","$1","$_") && next; + # order logging statements + /^logging (\d+\.\d+\.\d+\.\d+)/ && + ProcessHistory("LOGGING","ipsort","$1","$_") && next; + # order name-server statements + /^ip name-server (\d+\.\d+\.\d+\.\d+)/ && + ProcessHistory("NAMESERVER","ipsort","$1","$_") && next; + # order snmp-server host statements + /^snmp-server host (\d+\.\d+\.\d+\.\d+)/ && + ProcessHistory("SNMPSERVERHOST","ipsort","$1","$_") && next; + /^snmp-server community / && + ProcessHistory("SNMPSERVERCOMM","keysort","$_","$_") && next; + + # order tacacs server statements + /^(tacacs-server key )/ && + ProcessHistory("","","","! $1\n") && next; + /^tacacs-server host (\d+\.\d+\.\d+\.\d+)/ && + ProcessHistory("TAC","ipsort","$1","$_") && next; + + # delete ntp auth password + /^(ntp authentication-key \d+ md5) / && + ProcessHistory("","","","!$1 \n") && next; + # order ntp peers/servers + if (/^ntp (server|peer) (\d+)\.(\d+)\.(\d+)\.(\d+)/) { + $sortkey = sprintf("$1 %03d%03d%03d%03d",$2,$3,$4,$5); + ProcessHistory("NTP","keysort",$sortkey,"$_"); + next; + } + # order ip host line statements + /^ip host line(\d+)/ && + ProcessHistory("IPHOST","numsort","$1","$_") && next; + # order ip nat source static statements + /^ip nat (\S+) source static (\S+)/ && + ProcessHistory("IP NAT $1","ipsort","$2","$_") && next; + + ProcessHistory("","","","$_"); + # end of config + if (/^end$/) { + $found_end = 1; + return(1); + } + } + return(0); +} + +# dummy function +sub DoNothing {print STDOUT;} + +# Main +%commands=( + 'show version' => "ShowVersion", + 'show chassis' => "ShowChassis", + 'show module' => "ShowModule", + 'show flash' => "ShowFlash", + 'write term' => "WriteTerm" +); +# keys() doesnt return things in the order entered and the order of the +# cmds is important. pita +@commands=( + "show version", + "show chassis", + "show module", + "show flash", + "write term" +); +$cisco_cmds=join(";",@commands); +$cmds_regexp=join("|",@commands); + +open(OUTPUT,">$host.new") || die "Can't open $host.new for writing: $!\n"; +select(OUTPUT); +# make OUTPUT unbuffered if debugging +if ($debug) { $| = 1; } + +if ($file) { + print STDERR "opening file $host\n" if ($debug); + print STDOUT "opening file $host\n" if ($log); + open(INPUT,"<$host") || die "open failed for $host: $!\n"; +} else { + print STDERR "executing flogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($debug); + print STDOUT "executing flogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($log); + if (defined($ENV{NOPIPE})) { + system "flogin -t $timeo -c \"$cisco_cmds\" $host $host.raw 2>&1" || die "flogin failed for $host: $!\n"; + open(INPUT, "< $host.raw") || die "flogin failed for $host: $!\n"; + } else { + open(INPUT,"flogin -t $timeo -c \"$cisco_cmds\" $host ) { + tr/\015//d; + if (/\#exit$/) { + $clean_run=1; + last; + } + if (/Error:/) { + s/^.*Error:/Error:/; + print STDOUT ("$host flogin error: $_"); + print STDERR ("$host flogin error: $_") if ($debug); + $clean_run=0; + last; + } + while (/#\s*($cmds_regexp)\s*$/) { + $cmd = $1; + if (!defined($prompt)) {$prompt = ($_ =~ /^([^#]+#)/)[0]; } + print STDERR ("HIT COMMAND:$_") if ($debug); + if (! defined($commands{$cmd})) { + print STDERR "found unexpected command - \"$cmd\"\n"; + $clean_run = 0; + last TOP; + } + $rval = &{$commands{$cmd}}; + delete($commands{$cmd}); + if ($rval == -1) { + $clean_run = 0; + last TOP; + } + } +} +print STDOUT "Done $logincmd: $_\n" if ($log); +# Flush History +ProcessHistory("","","",""); +# Cleanup +close(INPUT); +close(OUTPUT); + +if (defined($ENV{NOPIPE})) { + unlink("$host.raw") if (! $debug); +} + +# check for completeness +if (scalar(%commands) || !$clean_run || !$found_end) { + if (scalar(%commands)) { + printf(STDOUT "missed cmd(s): %s\n", join(',', keys(%commands))); + printf(STDERR "missed cmd(s): %s\n", join(',', keys(%commands))) if ($debug); + } + if (!$clean_run || !$found_end) { + print STDOUT "End of run not found\n"; + print STDERR "End of run not found\n" if ($debug); + system("/usr/bin/tail -1 $host.new"); + } + unlink "$host.new" if (! $debug); +} diff --git a/bin/jlogin b/bin/jlogin deleted file mode 100755 index a21188c..0000000 --- a/bin/jlogin +++ /dev/null @@ -1,456 +0,0 @@ -#!/usr/local/bin/expect -- -## -## -## Copyright (C) 1997 by Henry Kilmer, Erik Sherk and Pete Whiting. -## All rights reserved. -## -## This software may be freely copied, modified and redistributed without -## fee for non-commerical purposes provided that this copyright notice is -## preserved intact on all copies and modified copies. -## -## There is no warranty or other guarantee of fitness of this software. -## It is provided solely "as is". The author(s) disclaim(s) all -## responsibility and liability with respect to this software's usage -## or its effect upon hardware, computer systems, other software, or -## anything else. -## -## -# -# jlogin - juniper ssh login -# -## Most options are intuitive for logging into a Cisco router. -## The default username password is the same as the vty password. -# - -# Usage line -set usage "Usage: $argv0 \[-c command\] \[-f cloginrc-file\] \ -\[-p user-password\] \[-r passphrase\] \[-s script-file\] \ -\[-u username\] \[-t timeout\] \[-x command-file\] \[-y ssh_cypher_type\] \ -router \[router...\]\n" - -# env(CLOGIN) may contain the following chars: -# x == do not set xterm banner or name - -# Password file -set password_file $env(HOME)/.cloginrc -# Default is to login to the router -set do_command 0 -set do_script 0 -# The default is to automatically enable -set enable 1 -# The default is to look in the password file to find the passwords. This -# tracks if we receive them on the command line. -set do_passwd 1 -# No passphrase by default -set passphrase "" - -# Find the user in the ENV, or use the unix userid. -if {[ info exists env(CISCO_USER) ] } { - set default_user $env(CISCO_USER) -} else { - # This uses "id" which I think is portable. At least it has existed - # (without options) on all machines/OSes I've been on recently - - # unlike whoami or id -nu. - regexp {\(([^)]*)} [exec id] junk default_user -} - -# Sometimes routers take awhile to answer (the default is 10 sec) -set timeout 120 - -# Process the command line -for {set i 0} {$i < $argc} {incr i} { - set arg [lindex $argv $i] - - switch -glob -- $arg { - # Command to run. - -c* - - -C* { - if {! [ regexp .\[cC\](.+) $arg ignore command]} { - incr i - set command [ lindex $argv $i ] - } - set do_command 1 - # alternate cloginrc file - } -f* - - -F* { - if {! [ regexp .\[fF\](.+) $arg ignore password_file]} { - incr i - set password_file [ lindex $argv $i ] - } - # user Password - } -p* - - -P* { - if {! [ regexp .\[pP\](.+) $arg ignore userpswd]} { - incr i - set userpswd [ lindex $argv $i ] - } - set do_passwd 0 - # passphrase - } -r* - - -R* { - if {! [ regexp .\[rR\](.+) $arg ignore passphrase]} { - incr i - set passphrase [ lindex $argv $i ] - } - # Expect script to run. - } -s* - - -S* { - if {! [ regexp .\[sS\](.+) $arg ignore sfile]} { - incr i - set sfile [ lindex $argv $i ] - } - if { ! [ file readable $sfile ] } { - send_user "Error: Can't read $sfile\n" - exit 1 - } - set do_script 1 - # Timeout - } -t* - - -T* { - if {! [ regexp .\[tT\](.+) $arg ignore timeout]} { - incr i - set timeout [ lindex $argv $i ] - } - # Username - } -u* - - -U* { - if {! [ regexp .\[uU\](.+) $arg ignore user]} { - incr i - set username [ lindex $argv $i ] - } - # command file - } -x* - - -X* { - if {! [ regexp .\[xX\](.+) $arg ignore cmd_file]} { - incr i - set cmd_file [ lindex $argv $i ] - } - set cmd_fd [open $cmd_file r] - set cmd_text [read $cmd_fd] - close $cmd_fd - set command [join [split $cmd_text \n] \;] - set do_command 1 - # 'ssh -c' cypher type - } -y* - - -Y* { - if {! [ regexp .\[yY\](.+) $arg ignore cypher]} { - incr i - set cypher [ lindex $argv $i ] - } - } -* { - send_user "Error: Unknown argument! $arg\n" - send_user $usage - exit 1 - } default { - break - } - } -} -# Process routers...no routers listed is an error. -if { $i == $argc } { - send_user "Error: $usage" -} - -# Only be quiet if we are running a script (it can log its output -# on its own) -if { $do_script } { - log_user 0 -} else { - log_user 1 -} - -# -# Done configuration/variable setting. Now run with it... -# - -# Sets Xterm title if interactive...if its an xterm and the user cares -proc label { host } { - global env - # if CLOGIN has an 'x' in it, don't set the xterm name/banner - if [info exists env(CLOGIN)] { - if {[string first "x" $env(CLOGIN)] != -1} { return } - } - # take host from ENV(TERM) - if [info exists env(TERM)] { - if [regexp \^(xterm|vs) $env(TERM) ignore ] { - send_user "\033]1;[lindex [split $host "."] 0]\a" - send_user "\033]2;$host\a" - } - } -} - -# This is a helper function to make the password file easier to -# maintain. Using this the password file has the form: -# add password sl* pete cow -# add password at* steve -# add password * hanky-pie -proc add {var args} { global $var ;lappend $var $args } - -proc find {var router} { - source_password_file - upvar $var list - if { [info exists list] } { - foreach line $list { - if { [string match [lindex $line 0] $router ] } { - return [lrange $line 1 end] - } - } - } - return {} -} - -# Loads the password file. Note that as this file is tcl, and that -# it is sourced, the user better know what to put in there, as it -# could install more than just password info... I will assume however, -# that a "bad guy" could just as easy put such code in the clogin -# script, so I will leave .cloginrc as just an extention of that script -proc source_password_file { } { - global env password_file read_password_file - if { [info exists read_password_file] } { return } - if { [info exists password_file] == 0 } { - set password_file $env(HOME)/.cloginrc - } - if { ! [file exists $password_file] } { - send_user "Error: password file ($password_file) does not exist\n" - exit 1 - } - - set read_password_file 1 - file stat $password_file fileinfo - if { [expr ($fileinfo(mode) & 007)] != 0000 } { - send_user "Error: $password_file must not be world readable/writable\n" - exit 1 - } - source $password_file -} - -# Log into the router. -proc login { router user passwd prompt cyphertype identfile} { - global spawn_id in_proc do_command do_script passphrase - set in_proc 1 - - # ssh to the router & try to login with or without an identfile. - # We use two calls to spawn since spawn does not seem to parse - # spaces correctly. - if {$identfile != ""} { - if [ catch {spawn ssh -c $cyphertype -x -l $user -i $identfile $router} reason ] { - send_user "Error: failed to ssh: $reason\n" - exit 1 - } - } else { - if [ catch {spawn ssh -c $cyphertype -x -l $user $router} reason ] { - send_user "Error: failed to ssh: $reason\n" - exit 1 - } - } - sleep 0.3 - - # This helps cleanup each expect clause. - expect_after { - timeout { - send_user "\nError: TIMEOUT reached\n" - catch {close}; wait - if { $in_proc} { - return 1 - } else { - continue - } - } eof { - send_user "\nError: EOF received\n" - catch {close}; wait - if { $in_proc} { - return 1 - } else { - continue - } - } - } - - # Here we get a little tricky. There are several possibilities: - # the router can ask for a username and passwd and then - # talk to the TACACS server to authenticate you, or if the - # TACACS server is not working, then it will use the enable - # passwd. Or, the router might not have TACACS turned on, - # then it will just send the passwd. - expect { - eof { send_user "Error: Couldn't login\n"; wait; return 1 } - "Connection refused" { - expect eof - send_user "Error: Connection Refused\n"; wait; return 1 - } "Unknown host\r\n" { - expect eof - send_user "Error: Unknown host\n"; wait; return 1 - } "Host is unreachable" { - expect eof - send_user "Error: Host Unreachable!\n"; wait; return 1 - } "No address associated with name" { - expect eof - send_user "Error: Unknown host\n"; wait; return 1 - } - -re "Enter passphrase for RSA key '\[^'\]*': " { - send_user "\nKey has passphrase!\n" - send "$passphrase\r" - exp_continue } - -re "Host key not found .* \(yes\/no\)\?" { - send "yes\r" - send_user "Host $router added to the list of known hosts.\n" - exp_continue } - -re "HOST IDENTIFICATION HAS CHANGED.* \(yes\/no\)\?" { - send "no\r" - send_user "Error: The host key for $router has changed. update the known_hosts file accordingly.\n" - return 1 } - -re "(Username|^login):" { send "$user\r" - expect { - eof { send_user "Error: Couldn't login\n"; wait; return 1 } - -re "\[Pp]assword:" { send "$passwd\r" } - "$prompt" { set in_proc 0; return 0 } - } - exp_continue - } - "\[Pp]assword:" { send "$passwd\r" - expect { - eof { send_user "Error: Couldn't login\n"; wait; return 1 } - "$prompt" { set in_proc 0; return 0 } - } - exp_continue - } - "$prompt" { } - denied { send_user "Error: Check your passwd for $router\n" - if { $do_command || $do_script } { - send "quit" - wait - return 1 - } else { - return 1 - } - } - "% Bad passwords" {send_user "Error: Check your passwd for $router\n"; return 1 } - } - set in_proc 0 - return 0 -} - -# Run commands given on the command line. -proc run_commands { prompt command } { - global in_proc - set in_proc 1 - - send "set cli complete-on-space off\r" - expect $prompt {} - send "set cli screen-length 0\r" - expect $prompt {} - - # Is this a multi-command? - if [ string match "*\;*" "$command" ] { - set commands [split $command \;] - set num_commands [llength $commands] - - for {set i 0} {$i < $num_commands} { incr i} { - send "[lindex $commands $i]\r" - expect { - -re "^\[^\n\r *]*$prompt $" {} - -re "^\[^\n\r]*$prompt." { exp_continue } - -re "(\r\n|\n)" { exp_continue } - } - } - } else { - send "$command\r" - expect { - -re "^\[^\n\r *]*$prompt $" {} - -re "^\[^\n\r]*$prompt." { exp_continue } - -re "(\r\n|\n)" { exp_continue } - } - } - send "quit\r" - expect { - "\n" { exp_continue } - timeout { return 0 } - eof { return 0 } - } - set in_proc 0 -} - -# -# For each router... (this is main loop) -# -set in_proc 0 -foreach router [lrange $argv $i end] { - set router [string tolower $router] - send_user "$router\n" - - set prompt ">" - - # Figure out passwords -# if { $do_passwd } { -# set pswd [find password $router] -# if { [llength $pswd] == 0 } { -# send_user "Error - no password for $router in $password_file.\n" -# continue -# } -# if { $do_enapasswd && !$autoenable && [llength $pswd] < 2 } { -# send_user "Error - no enable password for $router in $password_file." -# continue -# } -# set passwd [lindex $pswd 0] -# } - - # Figure out username - if {[info exists username]} { - # command line username - set loginname $username - } else { - set loginname [find user $router] - if { "$loginname" == "" } { set loginname $default_user } - } - - # Figure out loginname's password (if different from the vty password) - if {[info exists userpswd]} { - # command line passwd - set passwd $userpswd - } else { - set passwd [lindex [find password $loginname@$router] 0] - if { "$passwd" == "" } { set passwd [lindex [find password $router] 0] } - } - - # figure out identity file to use - set identfile "" - if {[info exists identity]} { - set identfile [lindex [find identity $router] 0] - } - - # Figure out ssh cypher type - if {[info exists cypher]} { - # command line ssh cypher type - set cyphertype $cypher - } else { - set cyphertype [find cyphertype $router] - if { "$cyphertype" == "" } { set cyphertype "3des" } - } - - # Login to the router - if {[login $router $loginname $passwd $prompt $cyphertype $identfile]} { - continue - } - - if { $do_command } { - if {[run_commands $prompt $command]} { - continue - } - } elseif { $do_script } { - send "set cli complete-on-space off\r" - expect $prompt {} - send "set cli screen-length 0\r" - expect $prompt {} - source $sfile - close - } else { - label $router - log_user 1 - interact - } - - # End of for each router - wait - sleep 0.3 -} -exit 0 diff --git a/bin/jlogin.in b/bin/jlogin.in new file mode 100755 index 0000000..0718321 --- /dev/null +++ b/bin/jlogin.in @@ -0,0 +1,470 @@ +#!@EXPECT_PATH@ -- +## +## +## Copyright (C) 1997 by Henry Kilmer, Erik Sherk and Pete Whiting. +## All rights reserved. +## +## This software may be freely copied, modified and redistributed without +## fee for non-commerical purposes provided that this copyright notice is +## preserved intact on all copies and modified copies. +## +## There is no warranty or other guarantee of fitness of this software. +## It is provided solely "as is". The author(s) disclaim(s) all +## responsibility and liability with respect to this software's usage +## or its effect upon hardware, computer systems, other software, or +## anything else. +## +## +# +# jlogin - juniper ssh login +# +## Most options are intuitive for logging into a Cisco router. +## The default username password is the same as the vty password. +# + +# Usage line +set usage "Usage: $argv0 \[-c command\] \[-f cloginrc-file\] \ +\[-p user-password\] \[-r passphrase\] \[-s script-file\] \ +\[-u username\] \[-t timeout\] \[-x command-file\] \[-y ssh_cypher_type\] \ +router \[router...\]\n" + +# env(CLOGIN) may contain the following chars: +# x == do not set xterm banner or name + +# Password file +set password_file $env(HOME)/.cloginrc +# Default is to login to the router +set do_command 0 +set do_script 0 +# The default is to automatically enable +set enable 1 +# The default is to look in the password file to find the passwords. This +# tracks if we receive them on the command line. +set do_passwd 1 +# No passphrase by default +set passphrase "" + +# Find the user in the ENV, or use the unix userid. +if {[ info exists env(CISCO_USER) ] } { + set default_user $env(CISCO_USER) +} else { + # This uses "id" which I think is portable. At least it has existed + # (without options) on all machines/OSes I've been on recently - + # unlike whoami or id -nu. + regexp {\(([^)]*)} [exec id] junk default_user +} + +# Sometimes routers take awhile to answer (the default is 10 sec) +set timeout 120 + +# Process the command line +for {set i 0} {$i < $argc} {incr i} { + set arg [lindex $argv $i] + + switch -glob -- $arg { + # Command to run. + -c* - + -C* { + if {! [ regexp .\[cC\](.+) $arg ignore command]} { + incr i + set command [ lindex $argv $i ] + } + set do_command 1 + # alternate cloginrc file + } -f* - + -F* { + if {! [ regexp .\[fF\](.+) $arg ignore password_file]} { + incr i + set password_file [ lindex $argv $i ] + } + # user Password + } -p* - + -P* { + if {! [ regexp .\[pP\](.+) $arg ignore userpswd]} { + incr i + set userpswd [ lindex $argv $i ] + } + set do_passwd 0 + # passphrase + } -r* - + -R* { + if {! [ regexp .\[rR\](.+) $arg ignore passphrase]} { + incr i + set passphrase [ lindex $argv $i ] + } + # Expect script to run. + } -s* - + -S* { + if {! [ regexp .\[sS\](.+) $arg ignore sfile]} { + incr i + set sfile [ lindex $argv $i ] + } + if { ! [ file readable $sfile ] } { + send_user "Error: Can't read $sfile\n" + exit 1 + } + set do_script 1 + # Timeout + } -t* - + -T* { + if {! [ regexp .\[tT\](.+) $arg ignore timeout]} { + incr i + set timeout [ lindex $argv $i ] + } + # Username + } -u* - + -U* { + if {! [ regexp .\[uU\](.+) $arg ignore user]} { + incr i + set username [ lindex $argv $i ] + } + # command file + } -x* - + -X* { + if {! [ regexp .\[xX\](.+) $arg ignore cmd_file]} { + incr i + set cmd_file [ lindex $argv $i ] + } + set cmd_fd [open $cmd_file r] + set cmd_text [read $cmd_fd] + close $cmd_fd + set command [join [split $cmd_text \n] \;] + set do_command 1 + # 'ssh -c' cypher type + } -y* - + -Y* { + if {! [ regexp .\[yY\](.+) $arg ignore cypher]} { + incr i + set cypher [ lindex $argv $i ] + } + } -* { + send_user "Error: Unknown argument! $arg\n" + send_user $usage + exit 1 + } default { + break + } + } +} +# Process routers...no routers listed is an error. +if { $i == $argc } { + send_user "Error: $usage" +} + +# Only be quiet if we are running a script (it can log its output +# on its own) +if { $do_script } { + log_user 0 +} else { + log_user 1 +} + +# +# Done configuration/variable setting. Now run with it... +# + +# Sets Xterm title if interactive...if its an xterm and the user cares +proc label { host } { + global env + # if CLOGIN has an 'x' in it, don't set the xterm name/banner + if [info exists env(CLOGIN)] { + if {[string first "x" $env(CLOGIN)] != -1} { return } + } + # take host from ENV(TERM) + if [info exists env(TERM)] { + if [regexp \^(xterm|vs) $env(TERM) ignore ] { + send_user "\033]1;[lindex [split $host "."] 0]\a" + send_user "\033]2;$host\a" + } + } +} + +# This is a helper function to make the password file easier to +# maintain. Using this the password file has the form: +# add password sl* pete cow +# add password at* steve +# add password * hanky-pie +proc add {var args} { global $var ;lappend $var $args } + +proc find {var router} { + source_password_file + upvar $var list + if { [info exists list] } { + foreach line $list { + if { [string match [lindex $line 0] $router ] } { + return [lrange $line 1 end] + } + } + } + return {} +} + +# Loads the password file. Note that as this file is tcl, and that +# it is sourced, the user better know what to put in there, as it +# could install more than just password info... I will assume however, +# that a "bad guy" could just as easy put such code in the clogin +# script, so I will leave .cloginrc as just an extention of that script +proc source_password_file { } { + global env password_file read_password_file + if { [info exists read_password_file] } { return } + if { [info exists password_file] == 0 } { + set password_file $env(HOME)/.cloginrc + } + if { ! [file exists $password_file] } { + send_user "Error: password file ($password_file) does not exist\n" + exit 1 + } + + set read_password_file 1 + file stat $password_file fileinfo + if { [expr ($fileinfo(mode) & 007)] != 0000 } { + send_user "Error: $password_file must not be world readable/writable\n" + exit 1 + } + source $password_file +} + +# Log into the router. +proc login { router user passwd prompt cmethod cyphertype identfile} { + global spawn_id in_proc do_command do_script passphrase + set in_proc 1 + + # try each of the connection methods in $cmethod until one is successful + set progs [llength $cmethod] + foreach prog [lrange $cmethod 0 end] { + if ![string compare $prog "telnet"] { + if [ catch {spawn telnet $router} reason ] { + send_user "Error: telnet failed: $reason\n" + exit 1 + } + } elseif ![string compare $prog "ssh"] { + # ssh to the router & try to login with or without an identfile. + # We use two calls to spawn since spawn does not seem to parse + # spaces correctly. + if {$identfile != ""} { + if [ catch {spawn ssh -c $cyphertype -x -l $user -i $identfile $router} reason ] { + send_user "Error: failed to ssh: $reason\n" + exit 1 + } + } else { + if [ catch {spawn ssh -c $cyphertype -x -l $user $router} reason ] { + send_user "Error: failed to ssh: $reason\n" + exit 1 + } + } + } elseif ![string compare $prog "rsh"] { + if [ catch {spawn rsh -l $user $router} reason ] { + send_user "Error: rsh failed: $reason\n" + exit 1 + } + } else { + puts "ERROR: unknown connection method: $prog" + return 1 + } + incr progs -1 + sleep 0.3 + + # This helps cleanup each expect clause. + expect_after { + timeout { + send_user "\nError: TIMEOUT reached\n" + catch {close}; wait + if { $in_proc} { + return 1 + } else { + continue + } + } eof { + send_user "\nError: EOF received\n" + catch {close}; wait + if { $in_proc} { + return 1 + } else { + continue + } + } + } + + # Here we get a little tricky. There are several possibilities: + # the router can ask for a username and passwd and then + # talk to the TACACS server to authenticate you, or if the + # TACACS server is not working, then it will use the enable + # passwd. Or, the router might not have TACACS turned on, + # then it will just send the passwd. + expect { + -re "(Connection refused|Secure connection \[^\n\r]+ refused|Connectionclosed by)" { + catch {close}; wait + if !$progs { + send_user "\nError: Connection Refused ($prog)\n"; return 1 + } + } + eof { send_user "Error: Couldn't login\n"; wait; return 1 + } -nocase "unknown host\r\n" { + catch {close}; + send_user "Error: Unknown host\n"; wait; return 1 + } "Host is unreachable" { + catch {close}; + send_user "Error: Host Unreachable!\n"; wait; return 1 + } "No address associated with name" { + catch {close}; + send_user "Error: Unknown host\n"; wait; return 1 + } + -re "Enter passphrase for RSA key '\[^'\]*': " { + send_user "\nKey has passphrase!\n" + send "$passphrase\r" + exp_continue } + -re "Host key not found .* \(yes\/no\)\?" { + send "yes\r" + send_user "Host $router added to the list of known hosts.\n" + exp_continue } + -re "HOST IDENTIFICATION HAS CHANGED.* \(yes\/no\)\?" { + send "no\r" + send_user "Error: The host key for $router has changed. update the known_hosts file accordingly.\n" + return 1 } + -re "(Username|\[\r\n]login):" { send "$user\r" + expect { + eof { send_user "Error: Couldn't login\n"; + wait; return 1 } + -re "\[Pp]assword:" { send "$passwd\r" } + "$prompt" { set in_proc 0; return 0 } + } + exp_continue + } + "\[Pp]assword:" { send "$passwd\r" + expect { + eof { send_user "Error: Couldn't login\n"; wait; return 1 } + "$prompt" { set in_proc 0; return 0 } + } + exp_continue + } + "$prompt" { break; } + denied { send_user "Error: Check your passwd for $router\n" + if { $do_command || $do_script } { + send "quit" + wait + return 1 + } else { + return 1 + } + } + "% Bad passwords" {send_user "Error: Check your passwd for $router\n"; return 1 } + } + } + set in_proc 0 + return 0 +} + +# Run commands given on the command line. +proc run_commands { prompt command } { + global in_proc + set in_proc 1 + + send "set cli complete-on-space off\r" + expect $prompt {} + send "set cli screen-length 0\r" + expect $prompt {} + + # Is this a multi-command? + if [ string match "*\;*" "$command" ] { + set commands [split $command \;] + set num_commands [llength $commands] + + for {set i 0} {$i < $num_commands} { incr i} { + send "[lindex $commands $i]\r" + expect { + -re "^\[^\n\r *]*$prompt $" {} + -re "^\[^\n\r]*$prompt." { exp_continue } + -re "(\r\n|\n)" { exp_continue } + } + } + } else { + send "$command\r" + expect { + -re "^\[^\n\r *]*$prompt $" {} + -re "^\[^\n\r]*$prompt." { exp_continue } + -re "(\r\n|\n)" { exp_continue } + } + } + send "quit\r" + expect { + "\n" { exp_continue } + timeout { return 0 } + eof { return 0 } + } + set in_proc 0 +} + +# +# For each router... (this is main loop) +# +set in_proc 0 +foreach router [lrange $argv $i end] { + set router [string tolower $router] + send_user "$router\n" + + set prompt ">" + + # Figure out username + if {[info exists username]} { + # command line username + set loginname $username + } else { + set loginname [find user $router] + if { "$loginname" == "" } { set loginname $default_user } + } + + # Figure out loginname's password (if different from the vty password) + if {[info exists userpswd]} { + # command line passwd + set passwd $userpswd + } else { + set passwd [lindex [find password $loginname@$router] 0] + if { "$passwd" == "" } { set passwd [lindex [find password $router] 0] } + } + + # figure out identity file to use + set identfile "" + if {[info exists identity]} { + set identfile [lindex [find identity $router] 0] + } + + # Figure out ssh cypher type + if {[info exists cypher]} { + # command line ssh cypher type + set cyphertype $cypher + } else { + set cyphertype [find cyphertype $router] + if { "$cyphertype" == "" } { set cyphertype "3des" } + } + + # Figure out connection method + set cmethod [find method $router] + if { "$cmethod" == "" } { set cmethod {{telnet} {ssh}} } + + # Login to the router + if {[login $router $loginname $passwd $prompt $cmethod $cyphertype $identfile]} { + continue + } + + if { $do_command } { + if {[run_commands $prompt $command]} { + continue + } + } elseif { $do_script } { + send "set cli complete-on-space off\r" + expect $prompt {} + send "set cli screen-length 0\r" + expect $prompt {} + source $sfile + close + } else { + label $router + log_user 1 + interact + } + + # End of for each router + wait + sleep 0.3 +} +exit 0 diff --git a/bin/jrancid b/bin/jrancid deleted file mode 100755 index ea158bf..0000000 --- a/bin/jrancid +++ /dev/null @@ -1,498 +0,0 @@ -#!/usr/local/bin/perl -## -## Amazingly hacked version of Hank's rancid - this one tries to -## deal with Junipers. -## -## Original Rancid: Copyright (C) 1997 by Henry Kilmer. -## All rights reserved. -## -## This software may be freely copied, modified and redistributed without -## fee for non-commerical purposes provided that this copyright notice is -## preserved intact on all copies and modified copies. -## -## There is no warranty or other guarantee of fitness of this software. -## It is provided solely "as is". The author(s) disclaim(s) all -## responsibility and liability with respect to this software's usage -## or its effect upon hardware, computer systems, other software, or -## anything else. -## -## -# -# RANCID - Really Awesome New Cisco confIg Differ -# -# usage: jrancid [-d] [-l] [-f filename | $host] -# -use Getopt::Std; -getopts('dfl'); -$debug = $opt_d; -$log = $opt_l; -$file = $opt_f; -$host = $ARGV[0]; - -$clean_run = 0; - -# This routine is used to print out the router configuration -sub ProcessHistory { - my($new_hist_tag,$new_command,$command_string,@string)=(@_); - if((($new_hist_tag ne $hist_tag) || ($new_command ne $command)) - && defined %history) { - print eval "$command \%history"; - undef %history; - } - if (($new_hist_tag) && ($new_command) && ($command_string)) { - if ($history{$command_string}) { - $history{$command_string} = "$history{$command_string}@string"; - } else { - $history{$command_string} = "@string"; - } - } elsif (($new_hist_tag) && ($new_command)) { - $history{++$#history} = "@string"; - } else { - print "@string"; - } - $hist_tag = $new_hist_tag; - $command = $new_command; - 1; -} - -sub numerically { $a <=> $b; } - -# This is a sort routing that will sort numerically on the -# keys of a hash as if it were a normal array. -sub keynsort { - local(%lines)=@_; - local($i) = 0; - local(@sorted_lines); - foreach $key (sort numerically keys(%lines)) { - $sorted_lines[$i] = $lines{$key}; - $i++; - } - @sorted_lines; -} - -# This is a sort routing that will sort on the -# keys of a hash as if it were a normal array. -sub keysort { - local(%lines)=@_; - local($i) = 0; - local(@sorted_lines); - foreach $key (sort keys(%lines)) { - $sorted_lines[$i] = $lines{$key}; - $i++; - } - @sorted_lines; -} - -# This is a sort routing that will sort on the -# values of a hash as if it were a normal array. -sub valsort{ - local(%lines)=@_; - local($i) = 0; - local(@sorted_lines); - foreach $key (sort values %lines) { - $sorted_lines[$i] = $key; - $i++; - } - @sorted_lines; -} - -# This is a numerical sort routing (ascending). -sub numsort { - local(%lines)=@_; - local($i) = 0; - local(@sorted_lines); - foreach $num (sort {$a <=> $b} keys %lines) { - $sorted_lines[$i] = $lines{$num}; - $i++; - } - @sorted_lines; -} - -# This is a sort routine that will sort on the -# ip address when the ip address is anywhere in -# the strings. -sub ipsort { - local(%lines)=@_; - local($i) = 0; - local(@sorted_lines); - foreach $addr (sort sortbyipaddr keys %lines) { - $sorted_lines[$i] = $lines{$addr}; - $i++; - } - @sorted_lines; -} - -# These two routines will sort based upon IP addresses -sub ipaddrval { - my(@a) = ($_[0] =~ m#^(\d+)\.(\d+)\.(\d+)\.(\d+)$#); - $a[3]+256*($a[2]+256*($a[1]+256*$a[0])); -} -sub sortbyipaddr { - &ipaddrval($a) <=> &ipaddrval($b); -} - -### -### Start of real work -### - -# This routine parses "show chassis clocks" -sub ShowChassisClocks { - print STDERR " In ShowChassisClocks: $_" if ($debug); - - s/^[a-z]+@//; - ProcessHistory("","","","# $_"); - while () { - tr/\015//d; - last if(/^$prompt/); - - /error: the chassis subsystem is not running/ && return; - /Couldn\'t initiate connection/ && return; - /Unrecognized command/ && return; - /command is not valid/ && return; - /^\s+\^/ && return; - /syntax error/ && return; - ProcessHistory("","","","# $_"); - } - return; -} - -# This routine parses "show chassis environment" -sub ShowChassisEnvironment { - print STDERR " In ShowChassisEnvironment: $_" if ($debug); - - s/^[a-z]+@//; - ProcessHistory("","","","# $_"); - while () { - tr/\015//d; - last if(/^$prompt/); - - /error: the chassis subsystem is not running/ && return; - /Couldn\'t initiate connection/ && return; - /Unrecognized command/ && return; - /command is not valid/ && return; - /^\s+\^/ && return; - /syntax error/ && return; - / backplane temperature/ && next; - /(\s*Power supply.*), temperature/ && - ProcessHistory("","","","# $1\n") && next; - /(\s*.+) +\d+ degrees C.*$/ && - ProcessHistory("","","","# $1\n") && next; - /(^.*\S)\s+ Spinning at .*$/ && - ProcessHistory("","","","# $1\n") && next; - ProcessHistory("","","","# $_"); - } - return; -} - -# This routine parses "show chassis firmware" -sub ShowChassisFirmware { - print STDERR " In ShowChassisFirmware: $_" if ($debug); - - s/^[a-z]+@//; - ProcessHistory("","","","# $_"); - while () { - tr/\015//d; - last if(/^$prompt/); - - /error: the chassis subsystem is not running/ && return; - /Couldn\'t initiate connection/ && return; - /Unrecognized command/ && return; - /command is not valid/ && return; - /^\s+\^/ && return; - /syntax error/ && return; - ProcessHistory("","","","# $_"); - } - return; -} - -# This routine parses "show chassis fpc detail" -sub ShowChassisFpcDetail { - print STDERR " In ShowChassisFpcDetail: $_" if ($debug); - - s/^[a-z]+@//; - ProcessHistory("","","","# $_"); - while () { - tr/\015//d; - last if(/^$prompt/); - - /error: the chassis subsystem is not running/ && return; - /Couldn\'t initiate connection/ && return; - /Unrecognized command/ && return; - /command is not valid/ && return; - /^\s+\^/ && return; - /syntax error/ && return; - / Temperature/ && next; - / Start time/ && next; - / Uptime/ && next; - ProcessHistory("","","","# $_"); - } - return; -} - -# This routine parses "show chassis hardware" -sub ShowChassisHardware { - print STDERR " In ShowChassisHardware: $_" if ($debug); - - s/^[a-z]+@//; - ProcessHistory("","","","# $_"); - while () { - tr/\015//d; - last if(/^$prompt/); - - /error: the chassis subsystem is not running/ && return; - /Couldn\'t initiate connection/ && return; - /Unrecognized command/ && return; - /command is not valid/ && return; - /^\s+\^/ && return; - /syntax error/ && return; - ProcessHistory("","","","# $_"); - } - return; -} - -# This routine parses "show chassis routing-engine" -# Most output is ignored. -sub ShowChassisRoutingEngine { - print STDERR " In ShowChassisRoutingEngine: $_" if ($debug); - - s/^[a-z]+@//; - ProcessHistory("","","","# $_"); - while () { - tr/\015//d; - last if(/^$prompt/); - - /error: the chassis subsystem is not running/ && return; - /Couldn\'t initiate connection/ && return; - /Unrecognized command/ && return; - /command is not valid/ && return; - /^\s+\^/ && return; - /syntax error/ && return; - /^Routing Engine status:/ && ProcessHistory("","","","# $_") && next; - / Slot / && ProcessHistory("","","","# $_") && next; - / Current state/ && ProcessHistory("","","","# $_") && next; - / Election priority/ && ProcessHistory("","","","# $_") && next; - / DRAM/ && ProcessHistory("","","","# $_") && next; - / Serial ID/ && ProcessHistory("","","","# $_") && next; - /^\s*$/ && ProcessHistory("","","","# $_") && next; - } - return; -} - -# This routine parses "show chassis scb", "show chassis ssb", and -# "show chassis feb". -# Only do this routine once. -sub ShowChassisSCB { - print STDERR " In ShowChassisSCB: $_" if ($debug); - - s/^[a-z]+@//; - ProcessHistory("","","","# $_"); - while () { - tr/\015//d; - last if(/^$prompt/); - - return if ($ShowChassisSCB); - /error: the chassis subsystem is not running/ && return; - /Couldn\'t initiate connection/ && return; - /Unrecognized command/ && return; - /command is not valid/ && return; - /^\s+\^/ && return; - /syntax error/ && return; - / Temperature/ && next; - / utilization/ && next; - / Start time/ && next; - / Uptime/ && next; - / (IP|MLPS) routes:/ && next; - / used:/ && next; - ProcessHistory("","","","# $_"); - } - $ShowChassisSCB = 1; - return; -} - -# This routine parses "show system boot-messages" -sub ShowSystemBootMessages { - print STDERR " In ShowSystemBootMessages: $_" if ($debug); - - s/^[a-z]+@//; - ProcessHistory("","","","# $_"); - while () { - tr/\015//d; - last if(/^$prompt/); - - /Unrecognized command/ && return; - /^\s+\^/ && return; - /syntax error/ && return; - /^JUNOS / && && next; - /^real memory / && next; - /^avail memory / && next; - /^\/dev\// && next; - ProcessHistory("","","","# $_"); - } - return; -} - -# This routine parses "show version" -sub ShowVersion { - print STDERR " In ShowVersion: $_" if ($debug); - - s/^[a-z]+@//; - ProcessHistory("","","","# $_"); - while () { - tr/\015//d; - last if(/^$prompt/); - - /^Juniper Networks is:/ && ProcessHistory("","","","# \n# $_") && next; - ProcessHistory("","","","# $_"); - } - return; -} - -# This routine parses "show configuration" -sub ShowConfiguration { - print STDERR " In ShowConfiguration: $_" if ($debug); - - s/^[a-z]+@//; - ProcessHistory("","","","# $_"); - while () { - tr/\015//d; - last if(/^$prompt/); - next if (/^\s*$/); - - /^database header mismatch: / && return(-1); - /^version .*;\d+$/ && return(-1); - if (/^(\s*)(community |trap-group )[^ ;]+(\s?[;{])$/) { - if (defined($ENV{'NOCOMMSTR'})) { - $_ = "$1$2\"\"$3\n"; - } - } - s/(\s*authentication-key ).*$/#$1;/; - s/^(.*\ssecret \")\$9\$.*(\".*)$/#$1$2/; - s/ # SECRET-DATA$//; - ProcessHistory("","","","$_"); - } - return; -} - -### -### End of real work -### - -# dummy function -sub DoNothing {print STDOUT;} - -# Main -%commands=( - "show chassis clocks" => "ShowChassisClocks", - "show chassis environment" => "ShowChassisEnvironment", - "show chassis firmware" => "ShowChassisFirmware", - "show chassis fpc detail" => "ShowChassisFpcDetail", - "show chassis hardware" => "ShowChassisHardware", - "show chassis routing-engine" => "ShowChassisRoutingEngine", - "show chassis scb" => "ShowChassisSCB", - "show chassis ssb" => "ShowChassisSCB", - "show chassis feb" => "ShowChassisSCB", - "show system boot-messages" => "ShowSystemBootMessages", - "show version" => "ShowVersion", - "show configuration" => "ShowConfiguration" -); -@commands=( - "show chassis clocks", - "show chassis environment", - "show chassis firmware", - "show chassis fpc detail", - "show chassis hardware", - "show chassis routing-engine", - "show chassis scb", - "show chassis ssb", - "show chassis feb", - "show system boot-messages", - "show version", - "show configuration" -); - -$jnx_commands=join(";",@commands); -$cmds_regexp=join("|",@commands); - -open(OUTPUT,">$host.new") || die "Can't open $host.new for writing: $!\n"; -select(OUTPUT); -# make OUTPUT unbuffered -if ($debug) { $| = 1; } - -if ($file) { - print STDERR "opening file $host\n" if ($debug); - print STDOUT "opening file $host\n" if ($log); - open(INPUT,"< $host") || die "open failed for $host: $!\n"; -} else { - print(STDERR "executing echo jlogin -c\"$jnx_commands\" $host\n") if ($debug); - print(STDOUT "executing echo jlogin -c\"$jnx_commands\" $host\n") if ($debug); - - if (defined($ENV{NOPIPE})) { - system "jlogin -c \"$jnx_commands\" $host $host.raw" || die "jlogin failed for $host: $!\n"; - open(INPUT, "< $host.raw") || die "jlogin failed for $host: $!\n"; - } else { - open(INPUT,"jlogin -c \"$jnx_commands\" $host ) { - tr/\015//d; - if (/^Error:/) { - s/^.*Error:/Error:/; - print STDOUT ("$host jlogin error: $_"); - print STDERR ("$host jlogin error: $_") if ($debug); - $clean_run=0; - last; - } - if (/System shutdown message/) { - print STDOUT ("$host shutdown msg: $_"); - print STDERR ("$host shutdown msg: $_") if ($debug); - $clean_run = 0; - last; - } - while (/>\s*($cmds_regexp)\s*$/) { - $cmd = $1; - if (!defined($prompt)) {$prompt = ($_ =~ /^([^>]+>)/)[0]; } - print STDERR ("HIT COMMAND:$_") if ($debug); - if (! defined($commands{$cmd})) { - print STDERR "found unexpected command - \"$cmd\"\n"; - $clean_run = 0; - last TOP; - } - $rval = &{$commands{$cmd}}; - delete($commands{$cmd}); - if ($rval == -1) { - $clean_run = 0; - last TOP; - } - } - if (/>\s*quit/) { - $clean_run=1; - last; - } -} -print STDOUT "Done jlogin: $_\n" if ($log); -# Flush History -ProcessHistory("","","",""); -# Cleanup -close(INPUT); -close(OUTPUT); - -if (defined($ENV{NOPIPE})) { - unlink("$host.raw") if (! $debug); -} - -# check for completeness -$commands = join(", ", keys(%commands)); -if (scalar(%commands) || !$clean_run) { - if (scalar(%commands)) { - printf(STDOUT "missed cmd(s): %s\n", join(',', keys(%commands))); - printf(STDERR "missed cmd(s): %s\n", join(',', keys(%commands))) if ($debug); - } - if (!$clean_run) { - print STDOUT "End of run not found\n"; - print STDERR "End of run not found\n" if ($debug); - system("/usr/bin/tail -1 $host.new"); - } - unlink "$host.new" if (! $debug); -} diff --git a/bin/jrancid.in b/bin/jrancid.in new file mode 100755 index 0000000..633d844 --- /dev/null +++ b/bin/jrancid.in @@ -0,0 +1,506 @@ +#!@PERLV_PATH@ +## +## Amazingly hacked version of Hank's rancid - this one tries to +## deal with Junipers. +## +## Original Rancid: Copyright (C) 1997 by Henry Kilmer. +## All rights reserved. +## +## This software may be freely copied, modified and redistributed without +## fee for non-commerical purposes provided that this copyright notice is +## preserved intact on all copies and modified copies. +## +## There is no warranty or other guarantee of fitness of this software. +## It is provided solely "as is". The author(s) disclaim(s) all +## responsibility and liability with respect to this software's usage +## or its effect upon hardware, computer systems, other software, or +## anything else. +## +## +# +# RANCID - Really Awesome New Cisco confIg Differ +# +# usage: jrancid [-d] [-l] [-f filename | $host] +# +use Getopt::Std; +getopts('dfl'); +$debug = $opt_d; +$log = $opt_l; +$file = $opt_f; +$host = $ARGV[0]; + +$clean_run = 0; +$found_end = 0; + +# This routine is used to print out the router configuration +sub ProcessHistory { + my($new_hist_tag,$new_command,$command_string,@string)=(@_); + if((($new_hist_tag ne $hist_tag) || ($new_command ne $command)) + && defined %history) { + print eval "$command \%history"; + undef %history; + } + if (($new_hist_tag) && ($new_command) && ($command_string)) { + if ($history{$command_string}) { + $history{$command_string} = "$history{$command_string}@string"; + } else { + $history{$command_string} = "@string"; + } + } elsif (($new_hist_tag) && ($new_command)) { + $history{++$#history} = "@string"; + } else { + print "@string"; + } + $hist_tag = $new_hist_tag; + $command = $new_command; + 1; +} + +sub numerically { $a <=> $b; } + +# This is a sort routing that will sort numerically on the +# keys of a hash as if it were a normal array. +sub keynsort { + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $key (sort numerically keys(%lines)) { + $sorted_lines[$i] = $lines{$key}; + $i++; + } + @sorted_lines; +} + +# This is a sort routing that will sort on the +# keys of a hash as if it were a normal array. +sub keysort { + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $key (sort keys(%lines)) { + $sorted_lines[$i] = $lines{$key}; + $i++; + } + @sorted_lines; +} + +# This is a sort routing that will sort on the +# values of a hash as if it were a normal array. +sub valsort{ + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $key (sort values %lines) { + $sorted_lines[$i] = $key; + $i++; + } + @sorted_lines; +} + +# This is a numerical sort routing (ascending). +sub numsort { + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $num (sort {$a <=> $b} keys %lines) { + $sorted_lines[$i] = $lines{$num}; + $i++; + } + @sorted_lines; +} + +# This is a sort routine that will sort on the +# ip address when the ip address is anywhere in +# the strings. +sub ipsort { + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $addr (sort sortbyipaddr keys %lines) { + $sorted_lines[$i] = $lines{$addr}; + $i++; + } + @sorted_lines; +} + +# These two routines will sort based upon IP addresses +sub ipaddrval { + my(@a) = ($_[0] =~ m#^(\d+)\.(\d+)\.(\d+)\.(\d+)$#); + $a[3]+256*($a[2]+256*($a[1]+256*$a[0])); +} +sub sortbyipaddr { + &ipaddrval($a) <=> &ipaddrval($b); +} + +### +### Start of real work +### + +# This routine parses "show chassis clocks" +sub ShowChassisClocks { + print STDERR " In ShowChassisClocks: $_" if ($debug); + + s/^[a-z]+@//; + ProcessHistory("","","","# $_"); + while () { + tr/\015//d; + last if(/^$prompt/); + + /error: the chassis subsystem is not running/ && return; + /Couldn\'t initiate connection/ && return; + /Unrecognized command/ && return; + /command is not valid/ && return; + /^\s+\^/ && return; + /syntax error/ && return; + ProcessHistory("","","","# $_"); + } + return; +} + +# This routine parses "show chassis environment" +sub ShowChassisEnvironment { + print STDERR " In ShowChassisEnvironment: $_" if ($debug); + + s/^[a-z]+@//; + ProcessHistory("","","","# $_"); + while () { + tr/\015//d; + last if(/^$prompt/); + + /error: the chassis subsystem is not running/ && return; + /Couldn\'t initiate connection/ && return; + /Unrecognized command/ && return; + /command is not valid/ && return; + /^\s+\^/ && return; + /syntax error/ && return; + / backplane temperature/ && next; + /(\s*Power supply.*), temperature/ && + ProcessHistory("","","","# $1\n") && next; + /(\s*.+) +\d+ degrees C.*$/ && + ProcessHistory("","","","# $1\n") && next; + /(^.*\S)\s+ Spinning at .*$/ && + ProcessHistory("","","","# $1\n") && next; + ProcessHistory("","","","# $_"); + } + return; +} + +# This routine parses "show chassis firmware" +sub ShowChassisFirmware { + print STDERR " In ShowChassisFirmware: $_" if ($debug); + + s/^[a-z]+@//; + ProcessHistory("","","","# $_"); + while () { + tr/\015//d; + last if(/^$prompt/); + + /error: the chassis subsystem is not running/ && return; + /Couldn\'t initiate connection/ && return; + /Unrecognized command/ && return; + /command is not valid/ && return; + /^\s+\^/ && return; + /syntax error/ && return; + ProcessHistory("","","","# $_"); + } + return; +} + +# This routine parses "show chassis fpc detail" +sub ShowChassisFpcDetail { + print STDERR " In ShowChassisFpcDetail: $_" if ($debug); + + s/^[a-z]+@//; + ProcessHistory("","","","# $_"); + while () { + tr/\015//d; + last if(/^$prompt/); + + /error: the chassis subsystem is not running/ && return; + /Couldn\'t initiate connection/ && return; + /Unrecognized command/ && return; + /command is not valid/ && return; + /^\s+\^/ && return; + /syntax error/ && return; + / Temperature/ && next; + / Start time/ && next; + / Uptime/ && next; + ProcessHistory("","","","# $_"); + } + return; +} + +# This routine parses "show chassis hardware" +sub ShowChassisHardware { + print STDERR " In ShowChassisHardware: $_" if ($debug); + + s/^[a-z]+@//; + ProcessHistory("","","","# $_"); + while () { + tr/\015//d; + last if(/^$prompt/); + + /error: the chassis subsystem is not running/ && return; + /Couldn\'t initiate connection/ && return; + /Unrecognized command/ && return; + /command is not valid/ && return; + /^\s+\^/ && return; + /syntax error/ && return; + ProcessHistory("","","","# $_"); + } + return; +} + +# This routine parses "show chassis routing-engine" +# Most output is ignored. +sub ShowChassisRoutingEngine { + print STDERR " In ShowChassisRoutingEngine: $_" if ($debug); + + s/^[a-z]+@//; + ProcessHistory("","","","# $_"); + while () { + tr/\015//d; + last if(/^$prompt/); + + /error: the chassis subsystem is not running/ && return; + /Couldn\'t initiate connection/ && return; + /Unrecognized command/ && return; + /command is not valid/ && return; + /^\s+\^/ && return; + /syntax error/ && return; + /^Routing Engine status:/ && ProcessHistory("","","","# $_") && next; + / Slot / && ProcessHistory("","","","# $_") && next; + / Current state/ && ProcessHistory("","","","# $_") && next; + / Election priority/ && ProcessHistory("","","","# $_") && next; + / DRAM/ && ProcessHistory("","","","# $_") && next; + / Serial ID/ && ProcessHistory("","","","# $_") && next; + /^\s*$/ && ProcessHistory("","","","# $_") && next; + } + return; +} + +# This routine parses "show chassis feb" "show chassis scb", "show +# chassis sfm detail", and "show chassis ssb". +# Only do this routine once. +sub ShowChassisSCB { + print STDERR " In ShowChassisSCB: $_" if ($debug); + + s/^[a-z]+@//; + ProcessHistory("","","","# $_"); + while () { + tr/\015//d; + last if(/^$prompt/); + + return if ($ShowChassisSCB); + /error: the chassis subsystem is not running/ && return; + /Couldn\'t initiate connection/ && return; + /Unrecognized command/ && return; + /command is not valid/ && return; + /^\s+\^/ && return; + /syntax error/ && return; + / Temperature/ && next; + / utilization/ && next; + / Start time/ && next; + / Uptime/ && next; + / (IP|MLPS) routes:/ && next; + / used:/ && next; + ProcessHistory("","","","# $_"); + } + $ShowChassisSCB = 1; + return; +} + +# This routine parses "show system boot-messages" +sub ShowSystemBootMessages { + print STDERR " In ShowSystemBootMessages: $_" if ($debug); + + s/^[a-z]+@//; + ProcessHistory("","","","# $_"); + while () { + tr/\015//d; + last if(/^$prompt/); + + /Unrecognized command/ && return; + /^\s+\^/ && return; + /syntax error/ && return; + /^JUNOS / && && next; + /^real memory / && next; + /^avail memory / && next; + /^\/dev\// && next; + ProcessHistory("","","","# $_"); + } + return; +} + +# This routine parses "show version" +sub ShowVersion { + print STDERR " In ShowVersion: $_" if ($debug); + + s/^[a-z]+@//; + ProcessHistory("","","","# $_"); + while () { + tr/\015//d; + last if(/^$prompt/); + + /^Juniper Networks is:/ && ProcessHistory("","","","# \n# $_") && next; + ProcessHistory("","","","# $_"); + } + return; +} + +# This routine parses "show configuration" +sub ShowConfiguration { + print STDERR " In ShowConfiguration: $_" if ($debug); + + s/^[a-z]+@//; + ProcessHistory("","","","# $_"); + while () { + tr/\015//d; + next if (/^\s*$/); + # end of config - hopefully. juniper does not have a reliable + # end-of-config tag. appears to end with "\nPROMPT>", but not sure. + if(/^$prompt/) { + $found_end++; + last; + } + + /^database header mismatch: / && return(-1); + /^version .*;\d+$/ && return(-1); + if (/^(\s*)(community |trap-group )[^ ;]+(\s?[;{])$/) { + if (defined($ENV{'NOCOMMSTR'})) { + $_ = "$1$2\"\"$3\n"; + } + } + s/(\s*authentication-key ).*$/#$1;/; + s/^(.*\ssecret \")\$9\$.*(\".*)$/#$1$2/; + s/ # SECRET-DATA$//; + ProcessHistory("","","","$_"); + } + return; +} + +### +### End of real work +### + +# dummy function +sub DoNothing {print STDOUT;} + +# Main +%commands=( + "show chassis clocks" => "ShowChassisClocks", + "show chassis environment" => "ShowChassisEnvironment", + "show chassis firmware" => "ShowChassisFirmware", + "show chassis fpc detail" => "ShowChassisFpcDetail", + "show chassis hardware" => "ShowChassisHardware", + "show chassis routing-engine" => "ShowChassisRoutingEngine", + "show chassis scb" => "ShowChassisSCB", + "show chassis sfm detail" => "ShowChassisSCB", + "show chassis ssb" => "ShowChassisSCB", + "show chassis feb" => "ShowChassisSCB", + "show system boot-messages" => "ShowSystemBootMessages", + "show version" => "ShowVersion", + "show configuration" => "ShowConfiguration" +); +@commands=( + "show chassis clocks", + "show chassis environment", + "show chassis firmware", + "show chassis fpc detail", + "show chassis hardware", + "show chassis routing-engine", + "show chassis scb", + "show chassis sfm detail", + "show chassis ssb", + "show chassis feb", + "show system boot-messages", + "show version", + "show configuration" +); + +$jnx_commands=join(";",@commands); +$cmds_regexp=join("|",@commands); + +open(OUTPUT,">$host.new") || die "Can't open $host.new for writing: $!\n"; +select(OUTPUT); +# make OUTPUT unbuffered +if ($debug) { $| = 1; } + +if ($file) { + print STDERR "opening file $host\n" if ($debug); + print STDOUT "opening file $host\n" if ($log); + open(INPUT,"< $host") || die "open failed for $host: $!\n"; +} else { + print(STDERR "executing echo jlogin -c\"$jnx_commands\" $host\n") if ($debug); + print(STDOUT "executing echo jlogin -c\"$jnx_commands\" $host\n") if ($debug); + + if (defined($ENV{NOPIPE})) { + system "jlogin -c \"$jnx_commands\" $host $host.raw" || die "jlogin failed for $host: $!\n"; + open(INPUT, "< $host.raw") || die "jlogin failed for $host: $!\n"; + } else { + open(INPUT,"jlogin -c \"$jnx_commands\" $host ) { + tr/\015//d; + if (/^Error:/) { + s/^.*Error:/Error:/; + print STDOUT ("$host jlogin error: $_"); + print STDERR ("$host jlogin error: $_") if ($debug); + $clean_run=0; + last; + } + if (/System shutdown message/) { + print STDOUT ("$host shutdown msg: $_"); + print STDERR ("$host shutdown msg: $_") if ($debug); + $clean_run = 0; + last; + } + while (/>\s*($cmds_regexp)\s*$/) { + $cmd = $1; + if (!defined($prompt)) {$prompt = ($_ =~ /^([^>]+>)/)[0]; } + print STDERR ("HIT COMMAND:$_") if ($debug); + if (! defined($commands{$cmd})) { + print STDERR "found unexpected command - \"$cmd\"\n"; + $clean_run = 0; + last TOP; + } + $rval = &{$commands{$cmd}}; + delete($commands{$cmd}); + if ($rval == -1) { + $clean_run = 0; + last TOP; + } + } + if (/>\s*quit/) { + $clean_run=1; + last; + } +} +print STDOUT "Done jlogin: $_\n" if ($log); +# Flush History +ProcessHistory("","","",""); +# Cleanup +close(INPUT); +close(OUTPUT); + +if (defined($ENV{NOPIPE})) { + unlink("$host.raw") if (! $debug); +} + +# check for completeness +$commands = join(", ", keys(%commands)); +if (scalar(%commands) || !$clean_run || !$found_end) { + if (scalar(%commands)) { + printf(STDOUT "missed cmd(s): %s\n", join(',', keys(%commands))); + printf(STDERR "missed cmd(s): %s\n", join(',', keys(%commands))) if ($debug); + } + if (!$clean_run || !$found_end) { + print STDOUT "End of run not found\n"; + print STDERR "End of run not found\n" if ($debug); + system("/usr/bin/tail -1 $host.new"); + } + unlink "$host.new" if (! $debug); +} diff --git a/bin/par b/bin/par deleted file mode 100755 index a0138d8..0000000 --- a/bin/par +++ /dev/null @@ -1,128 +0,0 @@ -#!/usr/local/bin/perl -## -## -## Copyright (C) 1997 by Henry Kilmer and Peter Whiting. -## All rights reserved. -## -## This software may be freely copied, modified and redistributed without -## fee for non-commerical purposes provided that this copyright notice is -## preserved intact on all copies and modified copies. -## -## There is no warranty or other guarantee of fitness of this software. -## It is provided solely "as is". The author(s) disclaim(s) all -## responsibility and liability with respect to this software's usage -## or its effect upon hardware, computer systems, other software, or -## anything else. -## -## -# -# PAR - parallel processing of command -# -# par -q -n # -l logfile -c command -x -d -# -q = quiet mode (don't log anything to the logfiles) -# -n # = number of processes to run at once (default = 3) -# -l logfile = logfile to store par logging into (.0-.n) -# -c command = command to run (can also be in the list -# of routers begining with a : -# -x = view par logs as they run through xterms -# -i = run commands through interactive xterms -# -d = print debugging to stderr -# -# par takes a list of items to run a command on. If the list entry begins -# with a ":" the remainder of the line is the command to run ("{}" will be -# replaced with each subsequent item in the list. If the list entry begins -# with a "#", the entry is ignored. If a command is defined (either with -# the -c or with a : line) any entry thereafter will be applied to the -# command by replacing the {} brackets. In no cammand is defined, then each -# line is assumed to be a command to be run. -# -use Getopt::Std; -getopts('n:l:c:xidq'); -$procs=$opt_n; $procs=3 if(!$procs); -$command=$opt_c;$command="{}" if(!$command); -$parlog=$opt_l; $parlog="par.log.".time if(!$parlog); -$debug=$opt_d; - -if ($opt_q && ($opt_x || $opt_l)) { - print STDERR "-q nullifies -x and -l\n"; - exit 1; -} - -$signalled=0; - -sub handler { - $signalled++; - print STDERR "Received signal - ending run ($signalled).\n"; - if($signalled>1) { - printf STDERR "Ok - killing $id!\n"; - kill 9, 0; - exit(1); - } -} - -$SIG{'INT'} = 'handler'; -$SIG{'TERM'} = 'handler'; -$SIG{'QUIT'} = 'handler'; - -sub start { - local($cmd,$logfile)=@_; - unless ($id=fork) { - if (!$opt_q) { - local($date)=scalar localtime; - open(LOG,">>$logfile"); - print(LOG "!!!!!!!\n!$date: $cmd\n!!!!!!!\n"); - close(LOG); - exec "($cmd) >>$logfile"; - } else { - exec "($cmd)"; - } - exit 0; - } - print STDERR "Starting $cmd: process id=$id logfile=$logfile\n" if ($debug); - $id; -} - -sub finish { - if(($id=wait)>0){ - $logfile=$log{$id}; - print STDERR "$id finished (logfile $logfile)\n" if($logfile && $debug); - $logfile; - } -} - -sub watchf { - local($log)=@_; - unless(fork) { exec "xterm -e tail -f $log" ; exit 1; } -} - -for($i=0;<>;$i++) { - chop; - if (/^\#/){$i--;next;} - if(/^:(.*)$/){$command=$1;$i--;next;} - if ($i<$procs) { - $logfile="running.$i"; $logfile="$parlog.$i" if (!$opt_q); - watchf($logfile) if($opt_x); - } else { $logfile=finish; } - last if $signalled; - if ($logfile) { - $cmd = $command; - $cmd =~ s/\{\}/$_/g; - $cmd = "xterm -e $cmd" if ($opt_i); - $id=start($cmd,$logfile); - $log{$id}=$logfile; - } - print STDERR "$i/$procs: $_: id=$id, log=$log{$id}\n" if ($debug); -} - -if($signalled && !eof) { - $i--; - print STDERR "Signalled - not running these:\n$_\n"; - while(<>){print STDERR;} -} else { - print STDERR "All work assigned. Waiting for remaining processes.\n" if ($debug); -} -$procs=$i if ($i<$procs); -while($procs) { - $procs-- if(finish); -} -print STDERR "Complete\n" if ($debug); diff --git a/bin/par.in b/bin/par.in new file mode 100755 index 0000000..d8b628b --- /dev/null +++ b/bin/par.in @@ -0,0 +1,128 @@ +#!@PERLV_PATH@ +## +## +## Copyright (C) 1997 by Henry Kilmer and Peter Whiting. +## All rights reserved. +## +## This software may be freely copied, modified and redistributed without +## fee for non-commerical purposes provided that this copyright notice is +## preserved intact on all copies and modified copies. +## +## There is no warranty or other guarantee of fitness of this software. +## It is provided solely "as is". The author(s) disclaim(s) all +## responsibility and liability with respect to this software's usage +## or its effect upon hardware, computer systems, other software, or +## anything else. +## +## +# +# PAR - parallel processing of command +# +# par -q -n # -l logfile -c command -x -d +# -q = quiet mode (don't log anything to the logfiles) +# -n # = number of processes to run at once (default = 3) +# -l logfile = logfile to store par logging into (.0-.n) +# -c command = command to run (can also be in the list +# of routers begining with a : +# -x = view par logs as they run through xterms +# -i = run commands through interactive xterms +# -d = print debugging to stderr +# +# par takes a list of items to run a command on. If the list entry begins +# with a ":" the remainder of the line is the command to run ("{}" will be +# replaced with each subsequent item in the list. If the list entry begins +# with a "#", the entry is ignored. If a command is defined (either with +# the -c or with a : line) any entry thereafter will be applied to the +# command by replacing the {} brackets. In no cammand is defined, then each +# line is assumed to be a command to be run. +# +use Getopt::Std; +getopts('n:l:c:xidq'); +$procs=$opt_n; $procs=3 if(!$procs); +$command=$opt_c;$command="{}" if(!$command); +$parlog=$opt_l; $parlog="par.log.".time if(!$parlog); +$debug=$opt_d; + +if ($opt_q && ($opt_x || $opt_l)) { + print STDERR "-q nullifies -x and -l\n"; + exit 1; +} + +$signalled=0; + +sub handler { + $signalled++; + print STDERR "Received signal - ending run ($signalled).\n"; + if($signalled>1) { + printf STDERR "Ok - killing $id!\n"; + kill 9, 0; + exit(1); + } +} + +$SIG{'INT'} = 'handler'; +$SIG{'TERM'} = 'handler'; +$SIG{'QUIT'} = 'handler'; + +sub start { + local($cmd,$logfile)=@_; + unless ($id=fork) { + if (!$opt_q) { + local($date)=scalar localtime; + open(LOG,">>$logfile"); + print(LOG "!!!!!!!\n!$date: $cmd\n!!!!!!!\n"); + close(LOG); + exec "($cmd) >>$logfile"; + } else { + exec "($cmd)"; + } + exit 0; + } + print STDERR "Starting $cmd: process id=$id logfile=$logfile\n" if ($debug); + $id; +} + +sub finish { + if(($id=wait)>0){ + $logfile=$log{$id}; + print STDERR "$id finished (logfile $logfile)\n" if($logfile && $debug); + $logfile; + } +} + +sub watchf { + local($log)=@_; + unless(fork) { exec "xterm -e tail -f $log" ; exit 1; } +} + +for($i=0;<>;$i++) { + chop; + if (/^\#/){$i--;next;} + if(/^:(.*)$/){$command=$1;$i--;next;} + if ($i<$procs) { + $logfile="running.$i"; $logfile="$parlog.$i" if (!$opt_q); + watchf($logfile) if($opt_x); + } else { $logfile=finish; } + last if $signalled; + if ($logfile) { + $cmd = $command; + $cmd =~ s/\{\}/$_/g; + $cmd = "xterm -e $cmd" if ($opt_i); + $id=start($cmd,$logfile); + $log{$id}=$logfile; + } + print STDERR "$i/$procs: $_: id=$id, log=$log{$id}\n" if ($debug); +} + +if($signalled && !eof) { + $i--; + print STDERR "Signalled - not running these:\n$_\n"; + while(<>){print STDERR;} +} else { + print STDERR "All work assigned. Waiting for remaining processes.\n" if ($debug); +} +$procs=$i if ($i<$procs); +while($procs) { + $procs-- if(finish); +} +print STDERR "Complete\n" if ($debug); diff --git a/bin/rancid b/bin/rancid deleted file mode 100755 index 4bdde6c..0000000 --- a/bin/rancid +++ /dev/null @@ -1,1048 +0,0 @@ -#!/usr/local/bin/perl -## -## -## Copyright (C) 1997 by Henry Kilmer. -## All rights reserved. -## -## This software may be freely copied, modified and redistributed without -## fee for non-commerical purposes provided that this copyright notice is -## preserved intact on all copies and modified copies. -## -## There is no warranty or other guarantee of fitness of this software. -## It is provided solely "as is". The author(s) disclaim(s) all -## responsibility and liability with respect to this software's usage -## or its effect upon hardware, computer systems, other software, or -## anything else. -## -## -# -# RANCID - Really Awesome New Cisco confIg Differ -# -# usage: rancid [-d] [-l] [-f filename | $host] -# -use Getopt::Std; -getopts('dflm'); -$log = $opt_l; -$debug = $opt_d; -$file = $opt_f; -$host = $ARGV[0]; -$clean_run = 0; -$found_end = 0; -$timeo = 90; # clogin timeout in seconds - -# This routine is used to print out the router configuration -sub ProcessHistory { - my($new_hist_tag,$new_command,$command_string,@string)=(@_); - if((($new_hist_tag ne $hist_tag) || ($new_command ne $command)) - && defined %history) { - print eval "$command \%history"; - undef %history; - } - if (($new_hist_tag) && ($new_command) && ($command_string)) { - if ($history{$command_string}) { - $history{$command_string} = "$history{$command_string}@string"; - } else { - $history{$command_string} = "@string"; - } - } elsif (($new_hist_tag) && ($new_command)) { - $history{++$#history} = "@string"; - } else { - print "@string"; - } - $hist_tag = $new_hist_tag; - $command = $new_command; - 1; -} - -sub numerically { $a <=> $b; } - -# This is a sort routing that will sort numerically on the -# keys of a hash as if it were a normal array. -sub keynsort { - local(%lines)=@_; - local($i) = 0; - local(@sorted_lines); - foreach $key (sort numerically keys(%lines)) { - $sorted_lines[$i] = $lines{$key}; - $i++; - } - @sorted_lines; -} - -# This is a sort routing that will sort on the -# keys of a hash as if it were a normal array. -sub keysort { - local(%lines)=@_; - local($i) = 0; - local(@sorted_lines); - foreach $key (sort keys(%lines)) { - $sorted_lines[$i] = $lines{$key}; - $i++; - } - @sorted_lines; -} - -# This is a sort routing that will sort on the -# values of a hash as if it were a normal array. -sub valsort{ - local(%lines)=@_; - local($i) = 0; - local(@sorted_lines); - foreach $key (sort values %lines) { - $sorted_lines[$i] = $key; - $i++; - } - @sorted_lines; -} - -# This is a numerical sort routing (ascending). -sub numsort { - local(%lines)=@_; - local($i) = 0; - local(@sorted_lines); - foreach $num (sort {$a <=> $b} keys %lines) { - $sorted_lines[$i] = $lines{$num}; - $i++; - } - @sorted_lines; -} - -# This is a sort routine that will sort on the -# ip address when the ip address is anywhere in -# the strings. -sub ipsort { - local(%lines)=@_; - local($i) = 0; - local(@sorted_lines); - foreach $addr (sort sortbyipaddr keys %lines) { - $sorted_lines[$i] = $lines{$addr}; - $i++; - } - @sorted_lines; -} - -# These two routines will sort based upon IP addresses -sub ipaddrval { - my(@a) = ($_[0] =~ m#^(\d+)\.(\d+)\.(\d+)\.(\d+)$#); - $a[3]+256*($a[2]+256*($a[1]+256*$a[0])); -} -sub sortbyipaddr { - &ipaddrval($a) <=> &ipaddrval($b); -} - -# This routine parses "show version" -sub ShowVersion { - print STDERR " In ShowVersion: $_" if ($debug); - - while () { - tr/\015//d; - last if(/^$prompt/); - next if(/^(\s*|\s*$cmd\s*)$/); - if (/^Slave in slot (\d+) is running/) { - $slave = " Slave:"; - next; - } - /^IOS .* Software \(([A-Za-z-0-9]*)\), .*Version\s+(.*)$/ && - ProcessHistory("COMMENTS","keysort","F1", - "!Image:$slave Software: $1, $2\n") && next; - /^([A-Za-z-0-9_]*) Synced to mainline version: (.*)$/ && - ProcessHistory("COMMENTS","keysort","F2", - "!Image:$slave $1 Synced to mainline version: $2\n") && next; - /^Compiled (.*)$/ && - ProcessHistory("COMMENTS","keysort","F3", - "!Image:$slave Compiled: $1\n") && next; - /^ROM: (System )?Bootstrap.*(Version.*)$/ && - ProcessHistory("COMMENTS","keysort","G1", - "!ROM Bootstrap: $2\n") && next; - /^ROM: \d+ Bootstrap .*(Version.*)$/ && - ProcessHistory("COMMENTS","keysort","G2", - "!ROM Image: Bootstrap $1\n!\n") && next; - /^ROM: .*(Version.*)$/ && - ProcessHistory("COMMENTS","keysort","G3","!ROM Image: $1\n") && next; - /^BOOTFLASH: .*(Version.*)$/ && - ProcessHistory("COMMENTS","keysort","G4","!BOOTFLASH: $1\n") && next; - /^System image file is "([^\"]*)", booted via (\S*)/ && -# removed the booted source due to -# CSCdk28131: cycling info in 'sh ver' -# ProcessHistory("COMMENTS","keysort","F4","!Image: booted via $2, $1\n") && - ProcessHistory("COMMENTS","keysort","F4","!Image: booted $1\n") && - next; - /^System image file is "([^\"]*)"$/ && - ProcessHistory("COMMENTS","keysort","F5","!Image: $1\n") && next; - if (/(\S+)\s+\((\S+)\)\s+processor.*with (\S+K) bytes/) { - my($proc) = $1; - my($cpu) = $2; - my($mem) = $3; - my($deivce) = "router"; - if ( $1 eq "CSC") { - $type = "AGS"; - } elsif ( $1 eq "CSC4") { - $type = "AGS+"; - } elsif ( $1 eq "2511" || $1 eq "2524" || $1 eq "AS2511-RJ") { - $type = "2500"; - } elsif ( $1 eq "3620" || $1 eq "3640") { - $type = "3600"; - } elsif ( $1 eq "RSP7000") { - $type = "7500"; - } elsif ( $1 =~ /RSP\d/) { - $type = "7500"; - } elsif ( $1 eq "RP1") { - $type = "7000"; - } elsif ( $1 eq "RP") { - $type = "7000"; - } elsif ( $1 =~ /720[246]/) { - $type = "7200"; - } elsif ( $1 =~ /1200[48]\/GRP/ || $1 =~ /1201[26]\/GRP/) { - $type = "12000"; - } elsif ( $1 =~ /WS-C29/) { - $type = "2900XL"; - $device = "switch"; - } else { - $type = $1; - } - print STDERR "TYPE = $type\n" if ($debug); - ProcessHistory("COMMENTS","keysort","A1", - "!Chassis type:$slave $proc - a $type $device\n"); - ProcessHistory("COMMENTS","keysort","B1", - "!Memory:$slave main $mem\n"); - ProcessHistory("COMMENTS","keysort","A3","!CPU:$slave $cpu\n"); - next; - } - if (/(\S+) Silicon\s*Switch Processor/) { - if (!defined($C0)) { - $C0=1; ProcessHistory("COMMENTS","keysort","C0","!\n"); - } - ProcessHistory("COMMENTS","keysort","C2","!SSP: $1\n"); - $ssp = 1; - $sspmem = $1; - next; - } - /^(\d+K) bytes of multibus/ && - ProcessHistory("COMMENTS","keysort","B2", - "!Memory: multibus $1\n") && next; - /^(\d+K) bytes of non-volatile/ && - ProcessHistory("COMMENTS","keysort","B3", - "!Memory: nvram $1\n") && next; - /^(\d+K) bytes of flash memory/ && - ProcessHistory("COMMENTS","keysort","B5","!Memory: flash $1\n") && - next; - /^(\d+K) bytes of .*flash partition/ && - ProcessHistory("COMMENTS","keysort","B6", - "!Memory: flash partition $1\n") && next; - /^(\d+K) bytes of Flash internal/ && - ProcessHistory("COMMENTS","keysort","B4", - "!Memory: bootflash $1\n") && next; - if(/^(\d+K) bytes of (Flash|ATA)?.*PCMCIA .*slot ?(\d)/i) { - ProcessHistory("COMMENTS","keysort","B7", - "!Memory: pcmcia $2 slot$3 $1\n"); - next; - } - if(/^WARNING/) { - if (!defined($I0)) { - $I0=1; - ProcessHistory("COMMENTS","keysort","I0","!\n"); - } - ProcessHistory("COMMENTS","keysort","I1","! $_"); - # The line after the WARNING is what to do about it. - $_ = ; tr/\015//d; - ProcessHistory("COMMENTS","keysort","I1","! $_"); - } - if (/^Configuration register is (.*)$/) { - $config_register=$1; - next; - } - } - return(0); -} - -# This routine parses "show install active" -sub ShowInstallActive { - print STDERR " In ShowInstallActive: $_" if ($debug); - - while () { - tr/\015//d; - last if (/^$prompt/); - next if (/^(\s*|\s*$cmd\s*)$/); - return(1) if /^\s*\^\s*$/; - return(1) if /Invalid input detected/; - ProcessHistory("COMMENTS","keysort","F5","!Image: $_") && next; - } - return(0); -} - -# This routine parses "show env all" -sub ShowEnv { - # Skip if this is not a 7500, 7200, or 7000. - print STDERR " In ShowEnv: $_" if ($debug); - - while () { - tr/\015//d; - last if (/^$prompt/); - next if (/^(\s*|\s*$cmd\s*)$/); - return(1) if ($type !~ /^7/); - if (!defined($E0)) { - $E0=1; - ProcessHistory("COMMENTS","keysort","E0","!\n"); - } - if (/^Arbiter type (\d), backplane type (\S+)/) { - if (!defined($C0)) { - $C0=1; ProcessHistory("COMMENTS","keysort","C0","!\n"); - } - ProcessHistory("COMMENTS","keysort","C1", - "!Enviromental Arbiter Type: $1\n"); - ProcessHistory("COMMENTS","keysort","A2", - "!Chassis type: $2 backplane\n"); - next; - } - /^\s*(Power .*)/ && - ProcessHistory("COMMENTS","keysort","E1","!Power: $1\n") && next; - /^\s*(Lower Power .*)/i && - ProcessHistory("COMMENTS","keysort","E2","!Power: $1\n") && next; - } - ProcessHistory("COMMENTS","","","!\n"); - return(0); -} - -# This routine parses "show gsr chassis-info" for the gsr -# This will create arrarys for hw info. -sub ShowGSR { - # Skip if this is not a 1200n. - print STDERR " In ShowGSR: $_" if ($debug); - - while () { - tr/\015//d; - last if (/^$prompt/); - next if (/^(\s*|\s*$cmd\s*)$/); - return(1) if ($type !~ /^120/); - /^$/ && next; - /^\s+Chassis: type (\S+) Fab Ver: (\S+)/ && - ProcessHistory("COMMENTS","keysort","D0","!\n") && - ProcessHistory("COMMENTS","keysort","D1", - "!GSR Chassis type: $1 Fab Ver: $2\n") && - next; - /^\s+Chassis S\/N: (.*)$/ && - ProcessHistory("COMMENTS","keysort","D2", - "!GSR Chassis S/N: $1\n") && - next; - /^\s+PCA: (\S+)\s*rev: (\S+)\s*dev: \S+\s*HW ver: (\S+)$/ && - ProcessHistory("COMMENTS","keysort","D3", - "!GSR Backplane PCA: $1, rev $2, ver $3\n") && - next; - /^\s+Backplane S\/N: (\S+)$/ && - ProcessHistory("COMMENTS","keysort","D4", - "!GSR Backplane S/N: $1\n") && - next; - } - ProcessHistory("COMMENTS","","","!\n"); - return(0); -} - -# This routine parses "show boot" -sub ShowBoot { - # Pick up boot variables if 7000/7200/7500/12000; - # otherwise pick up bootflash. - print STDERR " In ShowBoot: $_" if ($debug); - - while () { - tr/\015//d; - last if (/^$prompt/); - next if (/^(\s*|\s*$cmd\s*)$/); - return(1) if /^\s*\^\s*$/; - return(1) if /Ambiguous command/i; - return(1) if /Invalid input detected/; - return(1) if /(Open device \S+ failed|Error opening \S+:)/; - next if /CONFGEN variable/; - if (!defined($H0)) { - $H0=1; ProcessHistory("COMMENTS","keysort","H0","!\n"); - } - if ($type !~ /^(120|7)/) { - ProcessHistory("COMMENTS","keysort","H2","!BootFlash: $_"); - } elsif (/variable/) { - ProcessHistory("COMMENTS","keysort","H1","!Variable: $_"); - } - } - ProcessHistory("COMMENTS","","","!\n"); - return(0); -} - -# This routine parses "show flash" -sub ShowFlash { - # skip if this is 7000, 7200, 7500, or 12000. - print STDERR " In ShowFlash: $_" if ($debug); - - while () { - tr/\015//d; - last if (/^$prompt/); - next if (/^(\s*|\s*$cmd\s*)$/); - return(1) if ($type =~ /^(120|7)/); - return(1) if /^\s*\^\s*$/; - return(1) if /Invalid input detected/; - ProcessHistory("FLASH","","","!Flash: $_"); - } - ProcessHistory("","","","!\n"); - return; -} - -# This routine parses "dir /all ((disk|slot)N|bootflash|nvram):" -sub DirSlotN { - # Skip if this is not a 3600, 7000, 7200, 7500, or 12000. - print STDERR " In DirSlotN: $_" if ($debug); - - my($dev) = (/\s([^\s]+):/); - - while () { - tr/\015//d; - last if (/^$prompt/); - next if (/^(\s*|\s*$cmd\s*)$/); - return(1) if ($type !~ /^(120|7|36)/); - return(1) if /^\s*\^\s*$/; - return(1) if /Invalid input detected/; - return(1) if /\%Error: No such file or directory/; - return(1) if /No space information available/; - return(-1) if /\%Error calling/; - return(-1) if /: device being squeezed/; # Flash is busy - return(1) if /(Open device \S+ failed|Error opening \S+:)/; - ProcessHistory("FLASH","","","!Flash: $dev: $_"); - } - ProcessHistory("","","","!\n"); - return(0); -} - -# This routine parses "show controllers" -sub ShowContAll { - # Skip if this is a 70[01]0, 7500, or 12000. - print STDERR " In ShowContAll: $_" if ($debug); - - while () { - tr/\015//d; - last if (/^$prompt/); - next if (/^(\s*|\s*$cmd\s*)$/); - return(1) if ($type =~ /^(120|7[05])/); - if (/^Interface ([^ \n(]*)/) { $INT = "$1, "; next; } - /^(BRI unit \d)/ && - ProcessHistory("INT","","","!Interface: $1\n") && next; - /^LANCE unit \d, NIM/ && - ProcessHistory("INT","","","!Interface: $_") && next; - /^(LANCE unit \d)/ && - ProcessHistory("INT","","","!Interface: $1\n") && next; - /(Media Type is \S+),/ && - ProcessHistory("INT","","","!\t$1\n"); - if (/(M\dT:) show controller:$/) { - my($ctlr) = $1; - $_ = ; tr/\015//d; s/ subunit \d,//; - ProcessHistory("INT","","","!Interface: $ctlr $_"); - } - if (/^(\S+) : show controller:$/) { - my($ctlr) = $1; - $_ = ; tr/\015//d; s/ subunit \d,//; - ProcessHistory("INT","","","!Interface: $ctlr: $_"); - } - /^(HD unit \d), idb/ && - ProcessHistory("INT","","","!Interface: $1\n") && next; - /^HD unit \d, NIM/ && - ProcessHistory("INT","","","!Interface: $_") && next; - /^buffer size \d+ HD unit \d, (.*)/ && - ProcessHistory("INT","","","!\t$1\n") && next; - /^AM79970 / && ProcessHistory("INT","","","!Interface: $_") && next; - /^buffer size \d+ (Universal Serial: .*)/ && - ProcessHistory("INT","","","!\t$1\n") && next; - /^Hardware is (.*)/ && - ProcessHistory("INT","","","!Interface: $INT$1\n") && next; - /^(QUICC Serial unit \d),/ && - ProcessHistory("INT","","","!$1\n") && next; - /^QUICC Ethernet .*/ && - ProcessHistory("INT","","","!$_") && next; - /^DTE .*\.$/ && - ProcessHistory("INT","","","!\t$_") && next; - /^(cable type :.*),/ && - ProcessHistory("INT","","","!\t$1\n") && next; - /^(.* cable.*), received clockrate \d+$/ && - ProcessHistory("INT","","","!\t$1\n") && next; - /^.* cable.*$/ && - ProcessHistory("INT","","","!\t$_") && next; - } - return(0); -} - -# This routine parses "show controllers cbus" -# Some of this is printed out in ShowDiagbus. -sub ShowContCbus { - # Skip if this is not a 7000 or 7500. - print STDERR " In ShowContCbus: $_" if ($debug); - - while () { - tr/\015//d; - last if (/^$prompt/); - next if (/^(\s*|\s*$cmd\s*)$/); - return(1) if ($type !~ /^7[05]0/); - if (/^\s*slot(\d+): ([^,]+), hw (\S+), sw (\S+), ccb/) { - $slot = $1; - $board{$slot} = $2; - $hwver{$slot} = $3; - $hwucode{$slot} = $4; - } elsif (/^\s*(\S+) (\d+), hardware version (\S+), microcode version (\S+)/) { - $slot = $2; - $board{$slot} = $1; - $hwver{$slot} = $3; - $hwucode{$slot} = $4; - } elsif (/(Microcode .*)/) { - $ucode{$slot} = $1; - } elsif (/(software loaded .*)/) { - $ucode{$slot} = $1; - } elsif (/(\d+) Kbytes of main memory, (\d+) Kbytes cache memory/) { - $hwmemd{$slot} = $1; - $hwmemc{$slot} = $2; - } elsif (/byte buffers/) { - chop; - s/^\s*//; - $hwbuf{$slot} = $_; - } elsif (/Interface (\d+) - (\S+ \S+),/) { - $interface = $1; - ProcessHistory("HW","","", - "!\n!Int $interface: in slot $slot, named $2\n"); next; - } elsif (/(\d+) buffer RX queue threshold, (\d+) buffer TX queue limit, buffer size (\d+)/) { - ProcessHistory("HW","","","!Int $interface: rxq $1, txq $2, bufsize $3\n"); - next; - } - } - return(0); -} - -# This routine parses "show diagbus" -# This will create arrarys for hw info. -sub ShowDiagbus { - # Skip if this is not a 7000, 70[01]0, or 7500. - print STDERR " In ShowDiagbus: $_" if ($debug); - - while () { - tr/\015//d; - last if (/^$prompt/); - next if (/^(\s*|\s*$cmd\s*)$/); - return(1) if ($type !~ /^7[05]/); - if (/^\s*Slot (\d+):/i) { - $slot = $1; - next; - } elsif (/^\s*Slot (\d+) \(virtual\):/i) { - $slot = $1; - next; - } elsif (/^\s*(.*Processor.*|.*controller|.*Chassis Interface), HW rev (\S+), board revision (\S+)/i) { - $board = $1; - $hwver = $2; - $boardrev = $3; - if ($board =~ /Processor/) { - if ($board =~ /7000 Route\/Switch/) { - $board = "RSP7000"; - } elsif ($board =~ /Route\/Switch Processor (\d)/) { - $board = "RSP$1"; - } elsif ($board =~ /Route/) { - $board = "RP"; - } elsif ($board =~ /Silicon Switch/) { - $board = "SSP"; - } elsif ($board =~ /Switch/) { - $board = "SP"; - $board = "SSP $sspmem" if $ssp; - } elsif ($board =~ /ATM/) { - $board = "AIP"; - } - } elsif ($board =~ /(.*) controller/i) { - $board = $1; - } - # hwucode{$slot} defined in ShowContCbus - if (defined $hwucode{$slot}) { - ProcessHistory("SLOT","","","!\n!Slot $slot/$board: hvers $hwver rev $boardrev ucode $hwucode{$slot}\n"); - } else { - ProcessHistory("SLOT","","","!\n!Slot $slot/$board: hvers $hwver rev $boardrev\n"); - } - # These are also from the ShowContCbus - ProcessHistory("SLOT","","","!Slot $slot/$board: $ucode{$slot}\n") if (defined $ucode{$slot}); - ProcessHistory("SLOT","","","!Slot $slot/$board: memd $hwmemd{$slot}, cache $hwmemc{$slot}\n") - if ((defined $hwmemd{$slot}) && (defined $hwmemc{$slot})); - ProcessHistory("SLOT","","","!Slot $slot/$board: $hwbuf{$slot}\n") if (defined $hwbuf{$slot}); - next; - } - /Serial number: (\S+)\s*Part number: (\S+)/ && - ProcessHistory("SLOT","","", - "!Slot $slot/$board: part $2, serial $1\n") && - next; - /^\s*Controller Memory Size: (.*)$/ && - ProcessHistory("SLOT","","","!Slot $slot/$board: $1\n") && - next; - if (/PA Bay (\d) Information/) { - $pano = $1; - if ("PA" =~ /$board/) { - ($s,$c) = split(/\//,$board); - $board = "$s/$c/PA $pano"; - } else { - $board =~ s/\/PA \d//; - $board = "$board/PA $pano"; - } - next; - } - /\s+(.*) PA, (\d) ports?, (\S+)/ && - ProcessHistory("SLOT","","","!Slot $slot/$board: type $3, $2 ports\n") && - next; - /\s+(.*) PA( \(\S+\))?, (\d) ports?/ && - ProcessHistory("SLOT","","","!Slot $slot/$board: type $1$2, $3 ports\n") && - next; - /^\s*HW rev (\S+), Board revision (\S+)/ && - ProcessHistory("SLOT","","","!Slot $slot/$board: hvers $1 rev $2\n") && - next; - /Serial number: (\S+)\s*Part number: (\S+)/ && - ProcessHistory("SLOT","","","!Slot $slot/$board: part $2, serial $1\n") && next; - } - return(0); -} - -# This routine parses "show diag" for the gsr, 7200, 3600, 2600. -# This will create arrarys for hw info. -sub ShowDiag { - # Skip if this is not a 12000. - print STDERR " In ShowDiag: $_" if ($debug); - - while () { - tr/\015//d; - last if (/^$prompt/); - next if (/^(\s*|\s*$cmd\s*)$/); - return(1) if ($type !~ /^(120|720|36|26)/); - /^$/ && next; - if (!defined($showdiags)) {$showdiags=1; ProcessHistory("SLOT","","","!\n");} - s/Port Packet Over SONET/POS/; - if (/^\s*SLOT (\d+)\s+\(.*\): (.*)/) { - $slot = $1; - ProcessHistory("SLOT","","","!Slot $slot: $2\n"); - $board = "RP" if (/Route Processor/); - $board = "CLK" if (/Clock Scheduler Card/); - next; - } - if (/^\s+PCA:\s+(.*)/){ - local($part) = $1; - $_ = ; - /^\s+HW version (\S+)\s+S\/N (\S+)/ && - ProcessHistory("SLOT","","","!Slot $slot/PCA: part $part, serial $2\n") && - ProcessHistory("SLOT","","","!Slot $slot/PCA: hvers $1\n"); - next; - } - - if (/^\s+MBUS: .*\)\s+(.*)/) { - local($tmp) = "!Slot $slot/MBUS: part $1"; - $_ = ; - /^\s+HW version (\S+)\s+S\/N (\S+)/ && - ProcessHistory("SLOT","","","$tmp, serial $2\n") && - ProcessHistory("SLOT","","","!Slot $slot/MBUS: hvers $1\n"); - next; - } - if (/^\s+MBUS Agent Software version (.*)/) { - local($sw) = $1; - local($tail) = "!\n" if ($board =~ /(CLK|RP)/); - ProcessHistory("SLOT","","","!Slot $slot/MBUS: software $sw\n$tail"); - next; - } - if (/^\s+DRAM size: (\d+)/) { - local($dram) = $1 / 1048576; - $_ = ; - /^\s+FrFab SDRAM size: (\d+)/ && - ProcessHistory("SLOT","","","!Slot $slot/MBUS: $dram Mbytes DRAM, " - . $1 / 1024 . " Kbytes SDRAM\n!\n"); - next; - } - # 7200 and 3600 stuff - if (/^(Slot)\s+(\d+):/ || /^\s+(WIC|VIC) Slot (\d):/) { - if ($1 eq "WIC") { - $WIC = "/$2"; - } elsif ($1 eq "VIC") { - $WIC = "/$2"; - } else { - $slot = $2; - undef($WIC); - } - $_ = ; tr/\015//d; - - # clean up hideous 7200 format to look more like 7500 output - s/Fast-ethernet on C7200 I\/O card/FE-IO/; - s/ with MII or RJ45/-TX/; - s/Fast-ethernet /100Base/; s/[)(]//g; - - /\s+(.*) port adapter,?\s+(\d+)\s+/i && - ProcessHistory("SLOT","","","!Slot $slot: type $1, $2 ports\n"); - # I/O controller with no interfaces - /\s+(.*)\s+port adapter\s*$/i && - ProcessHistory("SLOT","","","!Slot $slot: type $1, 0 ports\n"); - /\s+(.*)\s+daughter card(.*)$/ && - ProcessHistory("SLOT","","","!Slot $slot$WIC: type $1$2\n"); - /\s+(FT1)$/ && - ProcessHistory("SLOT","","","!Slot $slot$WIC: type $1\n"); - next; - } - /revision\s+(\S+).*revision\s+(\S+)/ && - ProcessHistory("SLOT","","","!Slot $slot$WIC: hvers $1 rev $2\n") && - next; - /number\s+(\S+)\s+Part number\s+(\S+)/ && - ProcessHistory("SLOT","","","!Slot $slot$WIC: part $2, serial $1\n!\n") && - next; -} - return(0); -} - -# This routine parses "show c7200" for the 7200 -# This will create arrarys for hw info. -sub ShowC7200 { - # Skip if this is not a 7200. - print STDERR " In ShowC7200: $_" if ($debug); - - while () { - tr/\015//d; - last if (/^$prompt/); - next if (/^(\s*|\s*$cmd\s*)$/); - return(1) if ($type !~ /^72/); - /^$/ && next; - if (/C7200 Midplane EEPROM:/) { - $_ = ; - /revision\s+(\S+).*revision\s+(\S+)/; - ProcessHistory("SLOT","","","!Slot Midplane: hvers $1 rev $2\n"); - $_ = ; - /number\s+(\S+)\s+Part number\s+(\S+)/; - ProcessHistory("SLOT","","","!Slot Midplane: part $2, serial $1\n!\n"); - next; - } - if (/C720\d(VXR)? CPU EEPROM:/) { - $_ = ; - /revision\s+(\S+).*revision\s+(\S+)/ && - ProcessHistory("SLOT","","","!Slot CPU: hvers $1 rev $2\n"); - $_ = ; - /number\s+(\S+)\s+Part number\s+(\S+)/ && - ProcessHistory("SLOT","","","!Slot CPU: part $2, serial $1\n!\n"); - next; - } - } - return(0); -} - -# This routine parses "show vtp status" -sub ShowVTP { - print STDERR " In ShowVTP: $_" if ($debug); - - while () { - tr/\015//d; - last if (/^$prompt/); - next if (/^(\s*|\s*$cmd\s*)$/); - return(1) if ($type !~ /^2900XL$/); - ProcessHistory("COMMENTS","keysort","I0","!VTP: $_"); - } - ProcessHistory("COMMENTS","keysort","I0","!\n"); -} - -# This routine processes a "write term" -sub WriteTerm { - print STDERR " In WriteTerm: $_" if ($debug); - - while () { - tr/\015//d; - last if(/^$prompt/); - /Non-Volatile memory is in use/ && return(-1); # NvRAM is locked - # skip the crap - if (/^(##+$|Building configuration...)/i) { - while () { - next if (/^Current configuration:/i); - next if (/^([%!].*|\s*)$/); - next if (/^ip add.*ipv4:/); # band-aid for 3620 12.0S - last; - } - ProcessHistory("","","","!\nconfig-register $config_register\n"); - tr/\015//d; - } - # some versions have other crap mixed in with the bits in the - # block above - /^! (Last configuration|NVRAM config last)/ && next; - - # Dog gone Cool matches to process the rest of the config - /^tftp-server flash / && next; # kill any tftp remains - /^ntp clock-period / && next; # kill ntp clock-period - /^ length / && next; # kill length on serial lines - /^ width / && next; # kill width on serial lines - /^ clockrate / && next; # kill clockrate on serial interfaces - /^enable password / && - ProcessHistory("ENABLE","","","! enable password \n") && - next; - /^username (\S+) password /&& - ProcessHistory("USER","keysort","$1","! username $1 password \n") && next; - /^\s*password / && - ProcessHistory("LINE-PASS","","","! password \n") && next; - /^\s*neighbor (\S*) password / && - ProcessHistory("","","","! neighbor $1 password \n") && - next; - /^(ip ftp password) / && - ProcessHistory("","","","! $1 \n") && next; - /^( ip ospf authentication-key) / && - ProcessHistory("","","","!$1 \n") && next; - /^( ip ospf message-digest-key \d+ md5) / && - ProcessHistory("","","","!$1 \n") && next; - /fair-queue individual-limit/ && next; - # sort ip explicit-paths. - if (/^ip explicit-path name (\S+)/) { - my($key) = $1; - my($expath) = $_; - while () { - tr/\015//d; - last if (/^$prompt/); - last if (/^$prompt/ || ! /^(ip explicit-path name |[ !])/); - if (/^ip explicit-path name (\S+)/) { - ProcessHistory("EXPATH","keysort","$key","$expath"); - $key = $1; - $expath = $_; - } else { - $expath .= $_; - } - } - ProcessHistory("EXPATH","keysort","$key","$expath"); - } - # sort route-maps - if (/^route-map (\S+)/) { - my($key) = $1; - my($routemap) = $_; - while () { - tr/\015//d; - last if (/^$prompt/ || ! /^(route-map |[ !])/); - if (/^route-map (\S+)/) { - ProcessHistory("ROUTEMAP","keysort","$key","$routemap"); - $key = $1; - $routemap = $_; - } else { - $routemap .= $_; - } - } - ProcessHistory("ROUTEMAP","keysort","$key","$routemap"); - } - # filter out any RCS/CVS tags to avoid confusing local CVS storage - s/\$(Revision|Id):/ $1:/; - # order access-lists - /^access-list\s+(\d\d?)\s+(\S+)\s+(\S+)/ && - ProcessHistory("ACL $1 $2","ipsort","$3","$_") && next; - # order extended access-lists - /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+host\s+(\S+)/ && - ProcessHistory("EACL $1 $2","ipsort","$3","$_") && next; - /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+(\d\S+)/ && - ProcessHistory("EACL $1 $2","ipsort","$3","$_") && next; - /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+any/ && - ProcessHistory("EACL $1 $2","ipsort","0.0.0.0","$_") && next; - # order arp lists - /^arp\s+(\d+\.\d+\.\d+\.\d+)\s+/ && - ProcessHistory("ARP","ipsort","$1","$_") && next; - /^ip prefix-list\s+(\S+)\s+seq\s+(\d+)\s+(permit|deny)\s+(\d\S+)(\/.*)$/ && - ProcessHistory("PACL $1 $3","ipsort","$4","ip prefix-list $1 $3 $4$5\n") - && next; - # order logging statements - /^logging (\d+\.\d+\.\d+\.\d+)/ && - ProcessHistory("LOGGING","ipsort","$1","$_") && next; - # order name-server statements - /^ip name-server (\d+\.\d+\.\d+\.\d+)/ && - ProcessHistory("NAMESERVER","ipsort","$1","$_") && next; - # order/prune snmp-server host statements - # we only prune lines of the form - # snmp-server host a.b.c.d - if (/^snmp-server host (\d+\.\d+\.\d+\.\d+) /) { - if (defined($ENV{'NOCOMMSTR'})) { - my($ip) = $1; - my($line) = "snmp-server host $ip"; - my(@tokens) = split(' ', $'); - my($token); - while ($token = shift(@tokens)) { - if ($token eq 'version') { - $line .= " " . join(' ', ($token, shift(@tokens))); - } elsif ($token =~ /^(informs?|traps?|(no)?auth)$/) { - $line .= " " . $token; - } else { - $line = "! $line " . join(' ', ("", join(' ',@tokens))); - last; - } - } - ProcessHistory("SNMPSERVERHOST","ipsort","$ip","$line\n"); - } else { - ProcessHistory("SNMPSERVERHOST","ipsort","$1","$_"); - } - next; - } - if (/^(snmp-server community) (\S+)/) { - if (defined($ENV{'NOCOMMSTR'})) { - ProcessHistory("SNMPSERVERCOMM","keysort","$_","! $1 $'") && next; - } else { - ProcessHistory("SNMPSERVERCOMM","keysort","$_","$_") && next; - } - } - # order/prune tacacs/radius server statements - /^(tacacs-server|radius-server) key / && - ProcessHistory("","","","! $1 key \n") && next; - # order clns host statements - /^clns host \S+ (\S+)/ && - ProcessHistory("CLNS","keysort","$1","$_") && next; - # order alias statements - /^alias / && ProcessHistory("ALIAS","keysort","$_","$_") && next; - # delete ntp auth password - /^(ntp authentication-key \d+ md5) / && - ProcessHistory("","","","! $1 \n") && next; - # order ntp peers/servers - if (/^ntp (server|peer) (\d+)\.(\d+)\.(\d+)\.(\d+)/) { - $sortkey = sprintf("$1 %03d%03d%03d%03d",$2,$3,$4,$5); - ProcessHistory("NTP","keysort",$sortkey,"$_"); - next; - } - # order ip host line statements - /^ip host line(\d+)/ && - ProcessHistory("IPHOST","numsort","$1","$_") && next; - # order ip nat source static statements - /^ip nat (\S+) source static (\S+)/ && - ProcessHistory("IP NAT $1","ipsort","$2","$_") && next; - # order atm map-list statements - /^\s+ip\s+(\d+\.\d+\.\d+\.\d+)\s+atm-vc/ && - ProcessHistory("ATM map-list","ipsort","$1","$_") && next; - # order ip rcmd lines - /^ip rcmd/ && ProcessHistory("RCMD","keysort","$_","$_") && next; - - # system controller - /^syscon address (\S*) (\S*)/ && - ProcessHistory("","","","! syscon address $1 \n") && - next; - /^syscon password (\S*)/ && - ProcessHistory("","","","! syscon password \n") && - next; - - # catch anything that wasnt match above. - ProcessHistory("","","","$_"); - # end of config - if (/^end$/) { - $found_end = 1; - return(1); - } - } - return(0); -} - -# dummy function -sub DoNothing {print STDOUT;} - -# Main -%commands=( - 'show version' => "ShowVersion", - 'show install active' => "ShowInstallActive", - 'show env all' => "ShowEnv", - 'show gsr chassis' => "ShowGSR", - 'show boot' => "ShowBoot", - 'show bootvar' => "ShowBoot", - 'show flash' => "ShowFlash", - 'dir /all nvram:' => "DirSlotN", - 'dir /all bootflash:' => "DirSlotN", - 'dir /all slot0:' => "DirSlotN", - 'dir /all disk0:' => "DirSlotN", - 'dir /all slot1:' => "DirSlotN", - 'dir /all disk1:' => "DirSlotN", - 'show controllers' => "ShowContAll", - 'show controllers cbus' => "ShowContCbus", - 'show diagbus' => "ShowDiagbus", - 'show diag' => "ShowDiag", - 'show c7200' => "ShowC7200", - 'show vtp status' => "ShowVTP", - 'write term' => "WriteTerm" -); -# keys() doesnt return things in the order entered and the order of the -# cmds is important (show version first and write term last). pita -@commands=( - "show version", - "show install active", - "show env all", - "show gsr chassis", - "show boot", - "show bootvar", - "show flash", - "dir /all nvram:", - "dir /all bootflash:", - "dir /all slot0:", - "dir /all disk0:", - "dir /all slot1:", - "dir /all disk1:", - "show controllers", - "show controllers cbus", - "show diagbus", - "show diag", - "show c7200", - "show vtp status", - "write term" -); -$cisco_cmds=join(";",@commands); -$cmds_regexp=join("|",@commands); - -open(OUTPUT,">$host.new") || die "Can't open $host.new for writing: $!\n"; -select(OUTPUT); -# make OUTPUT unbuffered if debugging -if ($debug) { $| = 1; } - -if ($file) { - print STDERR "opening file $host\n" if ($debug); - print STDOUT "opening file $host\n" if ($log); - open(INPUT,"<$host") || die "open failed for $host: $!\n"; -} else { - print STDERR "executing clogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($debug); - print STDOUT "executing clogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($log); - if (defined($ENV{NOPIPE})) { - system "clogin -t $timeo -c \"$cisco_cmds\" $host $host.raw 2>&1" || die "clogin failed for $host: $!\n"; - open(INPUT, "< $host.raw") || die "clogin failed for $host: $!\n"; - } else { - open(INPUT,"clogin -t $timeo -c \"$cisco_cmds\" $host ) { - tr/\015//d; - if (/\#exit$/) { - $clean_run=1; - last; - } - if (/Error:/) { - s/^.*Error:/Error:/; - print STDOUT ("$host clogin error: $_"); - print STDERR ("$host clogin error: $_") if ($debug); - $clean_run=0; - last; - } - while (/#\s*($cmds_regexp)\s*$/) { - $cmd = $1; - if (!defined($prompt)) {$prompt = ($_ =~ /^([^#]+#)/)[0]; } - print STDERR ("HIT COMMAND:$_") if ($debug); - if (! defined($commands{$cmd})) { - print STDERR "found unexpected command - \"$cmd\"\n"; - $clean_run = 0; - last TOP; - } - $rval = &{$commands{$cmd}}; - delete($commands{$cmd}); - if ($rval == -1) { - $clean_run = 0; - last TOP; - } - } -} -print STDOUT "Done $logincmd: $_\n" if ($log); -# Flush History -ProcessHistory("","","",""); -# Cleanup -close(INPUT); -close(OUTPUT); - -if (defined($ENV{NOPIPE})) { - unlink("$host.raw") if (! $debug); -} - -# check for completeness -if (scalar(%commands) || !$clean_run || !$found_end) { - if (scalar(%commands)) { - printf(STDOUT "missed cmd(s): %s\n", join(',', keys(%commands))); - printf(STDERR "missed cmd(s): %s\n", join(',', keys(%commands))) if ($debug); - } - if (!$clean_run || !$found_end) { - print STDOUT "End of run not found\n"; - print STDERR "End of run not found\n" if ($debug); - system("/usr/bin/tail -1 $host.new"); - } - unlink "$host.new" if (! $debug); -} diff --git a/bin/rancid-fe b/bin/rancid-fe deleted file mode 100755 index e3fa735..0000000 --- a/bin/rancid-fe +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/local/bin/perl -## -## -## Copyright (C) 1997 by Henry Kilmer. -## All rights reserved. -## -## This software may be freely copied, modified and redistributed without -## fee for non-commerical purposes provided that this copyright notice is -## preserved intact on all copies and modified copies. -## -## There is no warranty or other guarantee of fitness of this software. -## It is provided solely "as is". The author(s) disclaim(s) all -## responsibility and liability with respect to this software's usage -## or its effect upon hardware, computer systems, other software, or -## anything else. -## -## -# -# rancid-FE - front-end to rancid/jrancid for use with par. -# -# usage: rancid-fe : -# - -require 5; - -($router, $vendor) = split('\:', $ARGV[0]); - -if ($vendor =~ /^cisco$/i) { - exec('rancid', $router); -} elsif ($vendor =~ /^cat5$/i) { - exec('cat5rancid', $router); -} elsif ($vendor =~ /^ezt3$/i) { - exec('erancid', $router); -} elsif ($vendor =~ /^juniper$/i) { - exec('jrancid', $router); -} elsif ($vendor =~ /^foundry$/i) { - exec('francid', $router); -} elsif ($vendor =~ /^redback$/i) { - exec('rrancid', $router); -} - -printf(STDERR "unknown router manufacturer for $router: $vendor\n"); -exit(-1); diff --git a/bin/rancid-fe.in b/bin/rancid-fe.in new file mode 100755 index 0000000..8e5d333 --- /dev/null +++ b/bin/rancid-fe.in @@ -0,0 +1,43 @@ +#!@PERLV_PATH@ +## +## +## Copyright (C) 1997 by Henry Kilmer. +## All rights reserved. +## +## This software may be freely copied, modified and redistributed without +## fee for non-commerical purposes provided that this copyright notice is +## preserved intact on all copies and modified copies. +## +## There is no warranty or other guarantee of fitness of this software. +## It is provided solely "as is". The author(s) disclaim(s) all +## responsibility and liability with respect to this software's usage +## or its effect upon hardware, computer systems, other software, or +## anything else. +## +## +# +# rancid-FE - front-end to rancid/jrancid for use with par. +# +# usage: rancid-fe : +# + +require 5; + +($router, $vendor) = split('\:', $ARGV[0]); + +if ($vendor =~ /^cisco$/i) { + exec('rancid', $router); +} elsif ($vendor =~ /^cat5$/i) { + exec('cat5rancid', $router); +} elsif ($vendor =~ /^ezt3$/i) { + exec('erancid', $router); +} elsif ($vendor =~ /^juniper$/i) { + exec('jrancid', $router); +} elsif ($vendor =~ /^foundry$/i) { + exec('francid', $router); +} elsif ($vendor =~ /^redback$/i) { + exec('rrancid', $router); +} + +printf(STDERR "unknown router manufacturer for $router: $vendor\n"); +exit(-1); diff --git a/bin/rancid.in b/bin/rancid.in new file mode 100755 index 0000000..d7b5fbf --- /dev/null +++ b/bin/rancid.in @@ -0,0 +1,1113 @@ +#!@PERLV_PATH@ +## +## +## Copyright (C) 1997 by Henry Kilmer. +## All rights reserved. +## +## This software may be freely copied, modified and redistributed without +## fee for non-commerical purposes provided that this copyright notice is +## preserved intact on all copies and modified copies. +## +## There is no warranty or other guarantee of fitness of this software. +## It is provided solely "as is". The author(s) disclaim(s) all +## responsibility and liability with respect to this software's usage +## or its effect upon hardware, computer systems, other software, or +## anything else. +## +## +# +# RANCID - Really Awesome New Cisco confIg Differ +# +# usage: rancid [-d] [-l] [-f filename | $host] +# +use Getopt::Std; +getopts('dflm'); +$log = $opt_l; +$debug = $opt_d; +$file = $opt_f; +$host = $ARGV[0]; +$clean_run = 0; +$found_end = 0; +$timeo = 90; # clogin timeout in seconds + +# This routine is used to print out the router configuration +sub ProcessHistory { + my($new_hist_tag,$new_command,$command_string,@string)=(@_); + if((($new_hist_tag ne $hist_tag) || ($new_command ne $command)) + && defined %history) { + print eval "$command \%history"; + undef %history; + } + if (($new_hist_tag) && ($new_command) && ($command_string)) { + if ($history{$command_string}) { + $history{$command_string} = "$history{$command_string}@string"; + } else { + $history{$command_string} = "@string"; + } + } elsif (($new_hist_tag) && ($new_command)) { + $history{++$#history} = "@string"; + } else { + print "@string"; + } + $hist_tag = $new_hist_tag; + $command = $new_command; + 1; +} + +sub numerically { $a <=> $b; } + +# This is a sort routing that will sort numerically on the +# keys of a hash as if it were a normal array. +sub keynsort { + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $key (sort numerically keys(%lines)) { + $sorted_lines[$i] = $lines{$key}; + $i++; + } + @sorted_lines; +} + +# This is a sort routing that will sort on the +# keys of a hash as if it were a normal array. +sub keysort { + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $key (sort keys(%lines)) { + $sorted_lines[$i] = $lines{$key}; + $i++; + } + @sorted_lines; +} + +# This is a sort routing that will sort on the +# values of a hash as if it were a normal array. +sub valsort{ + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $key (sort values %lines) { + $sorted_lines[$i] = $key; + $i++; + } + @sorted_lines; +} + +# This is a numerical sort routing (ascending). +sub numsort { + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $num (sort {$a <=> $b} keys %lines) { + $sorted_lines[$i] = $lines{$num}; + $i++; + } + @sorted_lines; +} + +# This is a sort routine that will sort on the +# ip address when the ip address is anywhere in +# the strings. +sub ipsort { + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $addr (sort sortbyipaddr keys %lines) { + $sorted_lines[$i] = $lines{$addr}; + $i++; + } + @sorted_lines; +} + +# These two routines will sort based upon IP addresses +sub ipaddrval { + my(@a) = ($_[0] =~ m#^(\d+)\.(\d+)\.(\d+)\.(\d+)$#); + $a[3]+256*($a[2]+256*($a[1]+256*$a[0])); +} +sub sortbyipaddr { + &ipaddrval($a) <=> &ipaddrval($b); +} + +# This routine parses "show version" +sub ShowVersion { + print STDERR " In ShowVersion: $_" if ($debug); + + while () { + tr/\015//d; + last if(/^$prompt/); + next if(/^(\s*|\s*$cmd\s*)$/); + if (/^Slave in slot (\d+) is running/) { + $slave = " Slave:"; + next; + } + /^Cisco Secure PIX /i && + ProcessHistory("COMMENTS","keysort","F1", "!Image: $_") && next; + /^IOS .* Software \(([A-Za-z-0-9]*)\), .*Version\s+(.*)$/ && + ProcessHistory("COMMENTS","keysort","F1", + "!Image:$slave Software: $1, $2\n") && next; + /^([A-Za-z-0-9_]*) Synced to mainline version: (.*)$/ && + ProcessHistory("COMMENTS","keysort","F2", + "!Image:$slave $1 Synced to mainline version: $2\n") && next; + /^Compiled (.*)$/ && + ProcessHistory("COMMENTS","keysort","F3", + "!Image:$slave Compiled: $1\n") && next; + /^ROM: (System )?Bootstrap.*(Version.*)$/ && + ProcessHistory("COMMENTS","keysort","G1", + "!ROM Bootstrap: $2\n") && next; + if (/^Hardware:\s+(.*), (.* RAM), CPU (.*)$/) { + ProcessHistory("COMMENTS","keysort","A1", + "!Chassis type: $1 - a PIX\n"); + ProcessHistory("COMMENTS","keysort","A2", + "!CPU: $3\n"); + ProcessHistory("COMMENTS","keysort","B1", "!Memory: $2\n"); + } + /^Serial Number:\s+(.*)$/ && + ProcessHistory("COMMENTS","keysort","C1", "!$_") && next; + /^Activation Key:\s+(.*)$/ && + ProcessHistory("COMMENTS","keysort","C2", "!$_") && next; + /^ROM: \d+ Bootstrap .*(Version.*)$/ && + ProcessHistory("COMMENTS","keysort","G2", + "!ROM Image: Bootstrap $1\n!\n") && next; + /^ROM: .*(Version.*)$/ && + ProcessHistory("COMMENTS","keysort","G3","!ROM Image: $1\n") && next; + /^BOOTFLASH: .*(Version.*)$/ && + ProcessHistory("COMMENTS","keysort","G4","!BOOTFLASH: $1\n") && next; + /^System image file is "([^\"]*)", booted via (\S*)/ && +# removed the booted source due to +# CSCdk28131: cycling info in 'sh ver' +# ProcessHistory("COMMENTS","keysort","F4","!Image: booted via $2, $1\n") && + ProcessHistory("COMMENTS","keysort","F4","!Image: booted $1\n") && + next; + /^System image file is "([^\"]*)"$/ && + ProcessHistory("COMMENTS","keysort","F5","!Image: $1\n") && next; + if (/(\S+)\s+\((\S+)\)\s+processor.*with (\S+K) bytes/) { + my($proc) = $1; + my($cpu) = $2; + my($mem) = $3; + my($device) = "router"; + if ( $1 eq "CSC") { + $type = "AGS"; + } elsif ( $1 eq "CSC4") { + $type = "AGS+"; + } elsif ( $1 eq "2511" || $1 eq "2524" || $1 eq "AS2511-RJ") { + $type = "2500"; + } elsif ( $1 eq "3620" || $1 eq "3640") { + $type = "3600"; + } elsif ( $1 eq "RSP7000") { + $type = "7500"; + } elsif ( $1 =~ /RSP\d/) { + $type = "7500"; + } elsif ( $1 eq "RP1") { + $type = "7000"; + } elsif ( $1 eq "RP") { + $type = "7000"; + } elsif ( $1 =~ /720[246]/) { + $type = "7200"; + } elsif ( $1 =~ /1200[48]\/GRP/ || $1 =~ /1201[26]\/GRP/) { + $type = "12000"; + } elsif ( $1 =~ /WS-C29/) { + $type = "2900XL"; + $device = "switch"; + } else { + $type = $1; + } + print STDERR "TYPE = $type\n" if ($debug); + ProcessHistory("COMMENTS","keysort","A1", + "!Chassis type:$slave $proc - a $type $device\n"); + ProcessHistory("COMMENTS","keysort","B1", + "!Memory:$slave main $mem\n"); + ProcessHistory("COMMENTS","keysort","A3","!CPU:$slave $cpu\n"); + next; + } + if (/(\S+) Silicon\s*Switch Processor/) { + if (!defined($C0)) { + $C0=1; ProcessHistory("COMMENTS","keysort","C0","!\n"); + } + ProcessHistory("COMMENTS","keysort","C2","!SSP: $1\n"); + $ssp = 1; + $sspmem = $1; + next; + } + /^(\d+K) bytes of multibus/ && + ProcessHistory("COMMENTS","keysort","B2", + "!Memory: multibus $1\n") && next; + /^(\d+K) bytes of non-volatile/ && + ProcessHistory("COMMENTS","keysort","B3", + "!Memory: nvram $1\n") && next; + /^(\d+K) bytes of flash memory/ && + ProcessHistory("COMMENTS","keysort","B5","!Memory: flash $1\n") && + next; + /^(\d+K) bytes of .*flash partition/ && + ProcessHistory("COMMENTS","keysort","B6", + "!Memory: flash partition $1\n") && next; + /^(\d+K) bytes of Flash internal/ && + ProcessHistory("COMMENTS","keysort","B4", + "!Memory: bootflash $1\n") && next; + if(/^(\d+K) bytes of (Flash|ATA)?.*PCMCIA .*slot ?(\d)/i) { + ProcessHistory("COMMENTS","keysort","B7", + "!Memory: pcmcia $2 slot$3 $1\n"); + next; + } + if(/^WARNING/) { + if (!defined($I0)) { + $I0=1; + ProcessHistory("COMMENTS","keysort","I0","!\n"); + } + ProcessHistory("COMMENTS","keysort","I1","! $_"); + # The line after the WARNING is what to do about it. + $_ = ; tr/\015//d; + ProcessHistory("COMMENTS","keysort","I1","! $_"); + } + if (/^Configuration register is (.*)$/) { + $config_register=$1; + next; + } + } + return(0); +} + +# This routine parses "show install active" +sub ShowInstallActive { + print STDERR " In ShowInstallActive: $_" if ($debug); + + while () { + tr/\015//d; + last if (/^$prompt/); + next if (/^(\s*|\s*$cmd\s*)$/); + return(1) if /^\s*\^\s*$/; + return(1) if /(Invalid input detected|Type help or )/; + ProcessHistory("COMMENTS","keysort","F5","!Image: $_") && next; + } + return(0); +} + +# This routine parses "show env all" +sub ShowEnv { + # Skip if this is not a 7500, 7200, or 7000. + print STDERR " In ShowEnv: $_" if ($debug); + + while () { + tr/\015//d; + last if (/^$prompt/); + next if (/^(\s*|\s*$cmd\s*)$/); + return(1) if ($type !~ /^7/); + if (!defined($E0)) { + $E0=1; + ProcessHistory("COMMENTS","keysort","E0","!\n"); + } + if (/^Arbiter type (\d), backplane type (\S+)/) { + if (!defined($C0)) { + $C0=1; ProcessHistory("COMMENTS","keysort","C0","!\n"); + } + ProcessHistory("COMMENTS","keysort","C1", + "!Enviromental Arbiter Type: $1\n"); + ProcessHistory("COMMENTS","keysort","A2", + "!Chassis type: $2 backplane\n"); + next; + } + /^\s*(Power .*)/ && + ProcessHistory("COMMENTS","keysort","E1","!Power: $1\n") && next; + /^\s*(Lower Power .*)/i && + ProcessHistory("COMMENTS","keysort","E2","!Power: $1\n") && next; + } + ProcessHistory("COMMENTS","","","!\n"); + return(0); +} + +# This routine parses "show gsr chassis-info" for the gsr +# This will create arrarys for hw info. +sub ShowGSR { + # Skip if this is not a 1200n. + print STDERR " In ShowGSR: $_" if ($debug); + + while () { + tr/\015//d; + last if (/^$prompt/); + next if (/^(\s*|\s*$cmd\s*)$/); + return(1) if ($type !~ /^120/); + /^$/ && next; + /^\s+Chassis: type (\S+) Fab Ver: (\S+)/ && + ProcessHistory("COMMENTS","keysort","D0","!\n") && + ProcessHistory("COMMENTS","keysort","D1", + "!GSR Chassis type: $1 Fab Ver: $2\n") && + next; + /^\s+Chassis S\/N: (.*)$/ && + ProcessHistory("COMMENTS","keysort","D2", + "!GSR Chassis S/N: $1\n") && + next; + /^\s+PCA: (\S+)\s*rev: (\S+)\s*dev: \S+\s*HW ver: (\S+)$/ && + ProcessHistory("COMMENTS","keysort","D3", + "!GSR Backplane PCA: $1, rev $2, ver $3\n") && + next; + /^\s+Backplane S\/N: (\S+)$/ && + ProcessHistory("COMMENTS","keysort","D4", + "!GSR Backplane S/N: $1\n") && + next; + } + ProcessHistory("COMMENTS","","","!\n"); + return(0); +} + +# This routine parses "show boot" +sub ShowBoot { + # Pick up boot variables if 7000/7200/7500/12000/2900; + # otherwise pick up bootflash. + print STDERR " In ShowBoot: $_" if ($debug); + + while () { + tr/\015//d; + last if (/^$prompt/); + next if (/^(\s*|\s*$cmd\s*)$/); + return(1) if /^\s*\^\s*$/; + return(1) if /Ambiguous command/i; + return(1) if /(Invalid input detected|Type help or )/; + return(1) if /(Open device \S+ failed|Error opening \S+:)/; + next if /CONFGEN variable/; + if (!defined($H0)) { + $H0=1; ProcessHistory("COMMENTS","keysort","H0","!\n"); + } + if ($type !~ /^(120|7)/) { + if ($type !~ /^2900/) { + ProcessHistory("COMMENTS","keysort","H2","!BootFlash: $_"); + } else { + ProcessHistory("COMMENTS","keysort","H1","!Variable: $_"); + } + } elsif (/variable/) { + ProcessHistory("COMMENTS","keysort","H1","!Variable: $_"); + } + } + ProcessHistory("COMMENTS","","","!\n"); + return(0); +} + +# This routine parses "show flash" +sub ShowFlash { + # skip if this is 7000, 7200, 7500, or 12000. + print STDERR " In ShowFlash: $_" if ($debug); + + while () { + tr/\015//d; + last if (/^$prompt/); + next if (/^(\s*|\s*$cmd\s*)$/); + return(1) if ($type =~ /^(120|7)/); + return(1) if /^\s*\^\s*$/; + return(1) if /(Invalid input detected|Type help or )/; + ProcessHistory("FLASH","","","!Flash: $_"); + } + ProcessHistory("","","","!\n"); + return; +} + +# This routine parses "dir /all ((disk|slot)N|bootflash|nvram):" +sub DirSlotN { + # Skip if this is not a 3600, 7000, 7200, 7500, or 12000. + print STDERR " In DirSlotN: $_" if ($debug); + + my($dev) = (/\s([^\s]+):/); + + while () { + tr/\015//d; + last if (/^$prompt/); + next if (/^(\s*|\s*$cmd\s*)$/); + return(1) if ($type !~ /^(120|7|36)/); + return(1) if /^\s*\^\s*$/; + return(1) if /(Invalid input detected|Type help or )/; + return(1) if /\%Error: No such file or directory/; + return(1) if /No space information available/; + return(-1) if /\%Error calling/; + return(-1) if /: device being squeezed/; # Flash is busy + return(1) if /(Open device \S+ failed|Error opening \S+:)/; + ProcessHistory("FLASH","","","!Flash: $dev: $_"); + } + ProcessHistory("","","","!\n"); + return(0); +} + +# This routine parses "show controllers" +sub ShowContAll { + # Skip if this is a 70[01]0, 7500, or 12000. + print STDERR " In ShowContAll: $_" if ($debug); + + while () { + tr/\015//d; + last if (/^$prompt/); + next if (/^(\s*|\s*$cmd\s*)$/); + return(1) if ($type =~ /^(120|7[05])/); + if (/^Interface ([^ \n(]*)/) { $INT = "$1, "; next; } + /^(BRI unit \d)/ && + ProcessHistory("INT","","","!Interface: $1\n") && next; + /^LANCE unit \d, NIM/ && + ProcessHistory("INT","","","!Interface: $_") && next; + /^(LANCE unit \d)/ && + ProcessHistory("INT","","","!Interface: $1\n") && next; + /(Media Type is \S+),/ && + ProcessHistory("INT","","","!\t$1\n"); + if (/(M\dT:) show controller:$/) { + my($ctlr) = $1; + $_ = ; tr/\015//d; s/ subunit \d,//; + ProcessHistory("INT","","","!Interface: $ctlr $_"); + } + if (/^(\S+) : show controller:$/) { + my($ctlr) = $1; + $_ = ; tr/\015//d; s/ subunit \d,//; + ProcessHistory("INT","","","!Interface: $ctlr: $_"); + } + /^(HD unit \d), idb/ && + ProcessHistory("INT","","","!Interface: $1\n") && next; + /^HD unit \d, NIM/ && + ProcessHistory("INT","","","!Interface: $_") && next; + /^buffer size \d+ HD unit \d, (.*)/ && + ProcessHistory("INT","","","!\t$1\n") && next; + /^AM79970 / && ProcessHistory("INT","","","!Interface: $_") && next; + /^buffer size \d+ (Universal Serial: .*)/ && + ProcessHistory("INT","","","!\t$1\n") && next; + /^Hardware is (.*)/ && + ProcessHistory("INT","","","!Interface: $INT$1\n") && next; + /^(QUICC Serial unit \d),/ && + ProcessHistory("INT","","","!$1\n") && next; + /^QUICC Ethernet .*/ && + ProcessHistory("INT","","","!$_") && next; + /^DTE .*\.$/ && + ProcessHistory("INT","","","!\t$_") && next; + /^(cable type :.*),/ && + ProcessHistory("INT","","","!\t$1\n") && next; + /^(.* cable.*), received clockrate \d+$/ && + ProcessHistory("INT","","","!\t$1\n") && next; + /^.* cable.*$/ && + ProcessHistory("INT","","","!\t$_") && next; + } + return(0); +} + +# This routine parses "show controllers cbus" +# Some of this is printed out in ShowDiagbus. +sub ShowContCbus { + # Skip if this is not a 7000 or 7500. + print STDERR " In ShowContCbus: $_" if ($debug); + + while () { + tr/\015//d; + last if (/^$prompt/); + next if (/^(\s*|\s*$cmd\s*)$/); + return(1) if ($type !~ /^7[05]0/); + if (/^\s*slot(\d+): ([^,]+), hw (\S+), sw (\S+), ccb/) { + $slot = $1; + $board{$slot} = $2; + $hwver{$slot} = $3; + $hwucode{$slot} = $4; + } elsif (/^\s*(\S+) (\d+), hardware version (\S+), microcode version (\S+)/) { + $slot = $2; + $board{$slot} = $1; + $hwver{$slot} = $3; + $hwucode{$slot} = $4; + } elsif (/(Microcode .*)/) { + $ucode{$slot} = $1; + } elsif (/(software loaded .*)/) { + $ucode{$slot} = $1; + } elsif (/(\d+) Kbytes of main memory, (\d+) Kbytes cache memory/) { + $hwmemd{$slot} = $1; + $hwmemc{$slot} = $2; + } elsif (/byte buffers/) { + chop; + s/^\s*//; + $hwbuf{$slot} = $_; + } elsif (/Interface (\d+) - (\S+ \S+),/) { + $interface = $1; + ProcessHistory("HW","","", + "!\n!Int $interface: in slot $slot, named $2\n"); next; + } elsif (/(\d+) buffer RX queue threshold, (\d+) buffer TX queue limit, buffer size (\d+)/) { + ProcessHistory("HW","","","!Int $interface: rxq $1, txq $2, bufsize $3\n"); + next; + } + } + return(0); +} + +# This routine parses "show diagbus" +# This will create arrarys for hw info. +sub ShowDiagbus { + # Skip if this is not a 7000, 70[01]0, or 7500. + print STDERR " In ShowDiagbus: $_" if ($debug); + + while () { + tr/\015//d; + last if (/^$prompt/); + next if (/^(\s*|\s*$cmd\s*)$/); + return(1) if ($type !~ /^7[05]/); + if (/^\s*Slot (\d+):/i) { + $slot = $1; + next; + } elsif (/^\s*Slot (\d+) \(virtual\):/i) { + $slot = $1; + next; + } elsif (/^\s*(.*Processor.*|.*controller|.*Chassis Interface), HW rev (\S+), board revision (\S+)/i) { + $board = $1; + $hwver = $2; + $boardrev = $3; + if ($board =~ /Processor/) { + if ($board =~ /7000 Route\/Switch/) { + $board = "RSP7000"; + } elsif ($board =~ /Route\/Switch Processor (\d)/) { + $board = "RSP$1"; + } elsif ($board =~ /Route/) { + $board = "RP"; + } elsif ($board =~ /Silicon Switch/) { + $board = "SSP"; + } elsif ($board =~ /Switch/) { + $board = "SP"; + $board = "SSP $sspmem" if $ssp; + } elsif ($board =~ /ATM/) { + $board = "AIP"; + } + } elsif ($board =~ /(.*) controller/i) { + $board = $1; + } + # hwucode{$slot} defined in ShowContCbus + if (defined $hwucode{$slot}) { + ProcessHistory("SLOT","","","!\n!Slot $slot/$board: hvers $hwver rev $boardrev ucode $hwucode{$slot}\n"); + } else { + ProcessHistory("SLOT","","","!\n!Slot $slot/$board: hvers $hwver rev $boardrev\n"); + } + # These are also from the ShowContCbus + ProcessHistory("SLOT","","","!Slot $slot/$board: $ucode{$slot}\n") if (defined $ucode{$slot}); + ProcessHistory("SLOT","","","!Slot $slot/$board: memd $hwmemd{$slot}, cache $hwmemc{$slot}\n") + if ((defined $hwmemd{$slot}) && (defined $hwmemc{$slot})); + ProcessHistory("SLOT","","","!Slot $slot/$board: $hwbuf{$slot}\n") if (defined $hwbuf{$slot}); + next; + } + /Serial number: (\S+)\s*Part number: (\S+)/ && + ProcessHistory("SLOT","","", + "!Slot $slot/$board: part $2, serial $1\n") && + next; + /^\s*Controller Memory Size: (.*)$/ && + ProcessHistory("SLOT","","","!Slot $slot/$board: $1\n") && + next; + if (/PA Bay (\d) Information/) { + $pano = $1; + if ("PA" =~ /$board/) { + ($s,$c) = split(/\//,$board); + $board = "$s/$c/PA $pano"; + } else { + $board =~ s/\/PA \d//; + $board = "$board/PA $pano"; + } + next; + } + /\s+(.*) PA, (\d) ports?, (\S+)/ && + ProcessHistory("SLOT","","","!Slot $slot/$board: type $3, $2 ports\n") && + next; + /\s+(.*) PA( \(\S+\))?, (\d) ports?/ && + ProcessHistory("SLOT","","","!Slot $slot/$board: type $1$2, $3 ports\n") && + next; + /^\s*HW rev (\S+), Board revision (\S+)/ && + ProcessHistory("SLOT","","","!Slot $slot/$board: hvers $1 rev $2\n") && + next; + /Serial number: (\S+)\s*Part number: (\S+)/ && + ProcessHistory("SLOT","","","!Slot $slot/$board: part $2, serial $1\n") && next; + } + return(0); +} + +# This routine parses "show diag" for the gsr, 7200, 3600, 2600. +# This will create arrarys for hw info. +sub ShowDiag { + # Skip if this is not a 12000. + print STDERR " In ShowDiag: $_" if ($debug); + + while () { + tr/\015//d; + last if (/^$prompt/); + next if (/^(\s*|\s*$cmd\s*)$/); + return(1) if ($type !~ /^(120|720|36|26)/); + /^$/ && next; + if (!defined($showdiags)) {$showdiags=1; ProcessHistory("SLOT","","","!\n");} + s/Port Packet Over SONET/POS/; + if (/^\s*SLOT\s+(\d+)\s+\((.*)\): (.*)/) { + $slot = $1; + ProcessHistory("SLOT","","","!Slot $slot: $3\n"); + # Here we look for boards that don't have DRAM. + $board = "Other"; + $board = "RP" if (/Route Processor/); + $board = "CLK" if (/Clock Scheduler Card/); + $board = "SFC" if (/Switch Fabric Card/); + next; + } + if (/^\s+MAIN:\s+ type \d+,\s+(.*)/) { + ProcessHistory("SLOT","","","!Slot $slot/MAIN: part $1\n") && next; + } + if (/^\s+PCA:\s+(.*)/) { + local($part) = $1; + $_ = ; + /^\s+HW version (\S+)\s+S\/N (\S+)/ && + ProcessHistory("SLOT","","","!Slot $slot/PCA: part $part, serial $2\n") && + ProcessHistory("SLOT","","","!Slot $slot/PCA: hvers $1\n"); + next; + } + if (/^\s+MBUS: .*\)\s+(.*)/) { + local($tmp) = "!Slot $slot/MBUS: part $1"; + $_ = ; + /^\s+HW version (\S+)\s+S\/N (\S+)/ && + ProcessHistory("SLOT","","","$tmp, serial $2\n") && + ProcessHistory("SLOT","","","!Slot $slot/MBUS: hvers $1\n"); + next; + } + if (/^\s+MBUS Agent Software version (.*)/) { + local($sw) = $1; + local($tail) = "!\n" if ($board ne "Other"); + ProcessHistory("SLOT","","","!Slot $slot/MBUS: software $sw\n$tail"); + next; + } + if (/^\s+DRAM size: (\d+)/) { + local($dram) = $1 / 1048576; + $_ = ; + /^\s+FrFab SDRAM size: (\d+)/ && + ProcessHistory("SLOT","","","!Slot $slot/MBUS: $dram Mbytes DRAM, " + . $1 / 1024 . " Kbytes SDRAM\n!\n"); + next; + } + # 7200 and 3600 stuff + if (/^(Slot)\s+(\d+(\/\d+)?):/ || /^\s+(WIC|VIC) Slot (\d):/) { + if ($1 eq "WIC") { + $WIC = "/$2"; + } elsif ($1 eq "VIC") { + $WIC = "/$2"; + } else { + $slot = $2; + undef($WIC); + } + $_ = ; tr/\015//d; + + # clean up hideous 7200 format to look more like 7500 output + s/Fast-ethernet on C7200 I\/O card/FE-IO/; + s/ with MII or RJ45/-TX/; + s/Fast-ethernet /100Base/; s/[)(]//g; + + /\s+(.*) port adapter,?\s+(\d+)\s+/i && + ProcessHistory("SLOT","","","!Slot $slot: type $1, $2 ports\n"); + # I/O controller with no interfaces + /\s+(.*)\s+port adapter\s*$/i && + ProcessHistory("SLOT","","","!Slot $slot: type $1, 0 ports\n"); + /\s+(.*)\s+daughter card(.*)$/ && + ProcessHistory("SLOT","","","!Slot $slot$WIC: type $1$2\n"); + /\s+(FT1)$/ && + ProcessHistory("SLOT","","","!Slot $slot$WIC: type $1\n"); + next; + } + /revision\s+(\S+).*revision\s+(\S+)/ && + ProcessHistory("SLOT","","","!Slot $slot$WIC: hvers $1 rev $2\n") && + next; + /number\s+(\S+)\s+Part number\s+(\S+)/ && + ProcessHistory("SLOT","","","!Slot $slot$WIC: part $2, serial $1\n!\n") && + next; + } + return(0); +} + +# This routine parses "show module". +sub ShowModule { + print STDERR " In ShowModule: $_" if ($debug); + + my(@lines); + my($slot); + + while () { + tr/\015//d; + return if (/^\s*\^$/); + last if (/^$prompt/); + next if (/^(\s*|\s*$cmd\s*)$/); + + # match slot info line, slot info then the rev info (the two are split) + if (/^ ?(\d+)\s+(\d+)\s+(.*)\s+(\S+)\s+(\S+)\s*$/) { + $lines[$1] .= "!Slot $1: type $3, $2 ports\n!Slot $1: part $4, serial $5\n"; + $lines[$1] =~ s/\s+,/,/g; + } + if (/^ ?(\d+)\s+\S+\s+to\s+\S+\s+(\S+)\s+(.*)\s+(\S+)\s*$/) { + $lines[$1] .= "!Slot $1: hvers $2, firmware $3, sw $4\n"; + $lines[$1] =~ s/\s+,/,/g; + } + } + foreach $slot (@lines) { + next if ($slot =~ /^\s*$/); + ProcessHistory("Module","","","$slot!\n"); + } + + return(0); +} + +# This routine parses "show c7200" for the 7200 +# This will create arrays for hw info. +sub ShowC7200 { + # Skip if this is not a 7200. + print STDERR " In ShowC7200: $_" if ($debug); + + while () { + tr/\015//d; + last if (/^$prompt/); + next if (/^(\s*|\s*$cmd\s*)$/); + return(1) if ($type !~ /^72/); + /^$/ && next; + if (/C7200 Midplane EEPROM:/) { + $_ = ; + /revision\s+(\S+).*revision\s+(\S+)/; + ProcessHistory("SLOT","","","!Slot Midplane: hvers $1 rev $2\n"); + $_ = ; + /number\s+(\S+)\s+Part number\s+(\S+)/; + ProcessHistory("SLOT","","","!Slot Midplane: part $2, serial $1\n!\n"); + next; + } + if (/C720\d(VXR)? CPU EEPROM:/) { + $_ = ; + /revision\s+(\S+).*revision\s+(\S+)/ && + ProcessHistory("SLOT","","","!Slot CPU: hvers $1 rev $2\n"); + $_ = ; + /number\s+(\S+)\s+Part number\s+(\S+)/ && + ProcessHistory("SLOT","","","!Slot CPU: part $2, serial $1\n!\n"); + next; + } + } + return(0); +} + +# This routine parses "show vtp status" +sub ShowVTP { + print STDERR " In ShowVTP: $_" if ($debug); + + while () { + tr/\015//d; + last if (/^$prompt/); + next if (/^(\s*|\s*$cmd\s*)$/); + return(1) if /^\s*\^\s*$/; + return(1) if /(Invalid input detected|Type help or )/; + return(1) if ($type !~ /^2900XL$/); + next if (/^Configuration last modified by/); + ProcessHistory("COMMENTS","keysort","I0","!VTP: $_"); + } + ProcessHistory("COMMENTS","keysort","I0","!\n"); + return(0); +} + +# This routine processes a "write term" +sub WriteTerm { + print STDERR " In WriteTerm: $_" if ($debug); + + while () { + tr/\015//d; + last if(/^$prompt/); + # the pager can not be disabled per-session on the PIX + s/^<-+ More -+>\s*//; + /Non-Volatile memory is in use/ && return(-1); # NvRAM is locked + # skip the crap + if (/^(##+$|Building configuration...)/i) { + while () { + next if (/^Current configuration\s*:/i); + next if (/^:/); + next if (/^([%!].*|\s*)$/); + next if (/^ip add.*ipv4:/); # band-aid for 3620 12.0S + last; + } + if (defined($config_register)) { + ProcessHistory("","","","!\nconfig-register $config_register\n"); + } + tr/\015//d; + } + # some versions have other crap mixed in with the bits in the + # block above + /^! (Last configuration|NVRAM config last)/ && next; + + # Dog gone Cool matches to process the rest of the config + /^tftp-server flash / && next; # kill any tftp remains + /^ntp clock-period / && next; # kill ntp clock-period + /^ length / && next; # kill length on serial lines + /^ width / && next; # kill width on serial lines + /^ clockrate / && next; # kill clockrate on serial interfaces + /^(enable )?(password|passwd) / && + ProcessHistory("ENABLE","","","!$1$2 \n") && + next; + /^username (\S+) password /&& + ProcessHistory("USER","keysort","$1","!username $1 password \n") && next; + /^\s*password / && + ProcessHistory("LINE-PASS","","","! password \n") && next; + /^\s*neighbor (\S*) password / && + ProcessHistory("","","","! neighbor $1 password \n") && + next; + /^(ip ftp password) / && + ProcessHistory("","","","!$1 \n") && next; + /^( ip ospf authentication-key) / && + ProcessHistory("","","","!$1 \n") && next; + /^( ip ospf message-digest-key \d+ md5) / && + ProcessHistory("","","","!$1 \n") && next; + /fair-queue individual-limit/ && next; + # sort ip explicit-paths. + if (/^ip explicit-path name (\S+)/) { + my($key) = $1; + my($expath) = $_; + while () { + tr/\015//d; + last if (/^$prompt/); + last if (/^$prompt/ || ! /^(ip explicit-path name |[ !])/); + if (/^ip explicit-path name (\S+)/) { + ProcessHistory("EXPATH","keysort","$key","$expath"); + $key = $1; + $expath = $_; + } else { + $expath .= $_; + } + } + ProcessHistory("EXPATH","keysort","$key","$expath"); + } + # sort route-maps + if (/^route-map (\S+)/) { + my($key) = $1; + my($routemap) = $_; + while () { + tr/\015//d; + last if (/^$prompt/ || ! /^(route-map |[ !])/); + if (/^route-map (\S+)/) { + ProcessHistory("ROUTEMAP","keysort","$key","$routemap"); + $key = $1; + $routemap = $_; + } else { + $routemap .= $_; + } + } + ProcessHistory("ROUTEMAP","keysort","$key","$routemap"); + } + # filter out any RCS/CVS tags to avoid confusing local CVS storage + s/\$(Revision|Id):/ $1:/; + # order access-lists + /^access-list\s+(\d\d?)\s+(\S+)\s+(\S+)/ && + ProcessHistory("ACL $1 $2","ipsort","$3","$_") && next; + # order extended access-lists + /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+host\s+(\S+)/ && + ProcessHistory("EACL $1 $2","ipsort","$3","$_") && next; + /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+(\d\S+)/ && + ProcessHistory("EACL $1 $2","ipsort","$3","$_") && next; + /^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+any/ && + ProcessHistory("EACL $1 $2","ipsort","0.0.0.0","$_") && next; + # order arp lists + /^arp\s+(\d+\.\d+\.\d+\.\d+)\s+/ && + ProcessHistory("ARP","ipsort","$1","$_") && next; + /^ip prefix-list\s+(\S+)\s+seq\s+(\d+)\s+(permit|deny)\s+(\d\S+)(\/.*)$/ && + ProcessHistory("PACL $1 $3","ipsort","$4","ip prefix-list $1 $3 $4$5\n") + && next; + # order logging statements + /^logging (\d+\.\d+\.\d+\.\d+)/ && + ProcessHistory("LOGGING","ipsort","$1","$_") && next; + # order name-server statements + /^ip name-server (\d+\.\d+\.\d+\.\d+)/ && + ProcessHistory("NAMESERVER","ipsort","$1","$_") && next; + # order/prune snmp-server host statements + # we only prune lines of the form + # snmp-server host a.b.c.d + if (/^snmp-server host (\d+\.\d+\.\d+\.\d+) /) { + if (defined($ENV{'NOCOMMSTR'})) { + my($ip) = $1; + my($line) = "snmp-server host $ip"; + my(@tokens) = split(' ', $'); + my($token); + while ($token = shift(@tokens)) { + if ($token eq 'version') { + $line .= " " . join(' ', ($token, shift(@tokens))); + } elsif ($token =~ /^(informs?|traps?|(no)?auth)$/) { + $line .= " " . $token; + } else { + $line = "!$line " . join(' ', ("", join(' ',@tokens))); + last; + } + } + ProcessHistory("SNMPSERVERHOST","ipsort","$ip","$line\n"); + } else { + ProcessHistory("SNMPSERVERHOST","ipsort","$1","$_"); + } + next; + } + if (/^(snmp-server community) (\S+)/) { + if (defined($ENV{'NOCOMMSTR'})) { + ProcessHistory("SNMPSERVERCOMM","keysort","$_","!$1 $'") && next; + } else { + ProcessHistory("SNMPSERVERCOMM","keysort","$_","$_") && next; + } + } + # order/prune tacacs/radius server statements + /^(tacacs-server|radius-server) key / && + ProcessHistory("","","","!$1 key \n") && next; + # order clns host statements + /^clns host \S+ (\S+)/ && + ProcessHistory("CLNS","keysort","$1","$_") && next; + # order alias statements + /^alias / && ProcessHistory("ALIAS","keysort","$_","$_") && next; + # delete ntp auth password + /^(ntp authentication-key \d+ md5) / && + ProcessHistory("","","","!$1 \n") && next; + # order ntp peers/servers + if (/^ntp (server|peer) (\d+)\.(\d+)\.(\d+)\.(\d+)/) { + $sortkey = sprintf("$1 %03d%03d%03d%03d",$2,$3,$4,$5); + ProcessHistory("NTP","keysort",$sortkey,"$_"); + next; + } + # order ip host line statements + /^ip host line(\d+)/ && + ProcessHistory("IPHOST","numsort","$1","$_") && next; + # order ip nat source static statements + /^ip nat (\S+) source static (\S+)/ && + ProcessHistory("IP NAT $1","ipsort","$2","$_") && next; + # order atm map-list statements + /^\s+ip\s+(\d+\.\d+\.\d+\.\d+)\s+atm-vc/ && + ProcessHistory("ATM map-list","ipsort","$1","$_") && next; + # order ip rcmd lines + /^ip rcmd/ && ProcessHistory("RCMD","keysort","$_","$_") && next; + + # system controller + /^syscon address (\S*) (\S*)/ && + ProcessHistory("","","","!syscon address $1 \n") && + next; + /^syscon password (\S*)/ && + ProcessHistory("","","","!syscon password \n") && + next; + + # catch anything that wasnt match above. + ProcessHistory("","","","$_"); + # end of config + #if (/^end(\n\[OK])?$/) { + if (/^(: )?end$/) { + $found_end = 1; + return(1); + } + } + return(0); +} + +# dummy function +sub DoNothing {print STDOUT;} + +# Main +%commands=( + 'show version' => "ShowVersion", + 'show install active' => "ShowInstallActive", + 'show env all' => "ShowEnv", + 'show gsr chassis' => "ShowGSR", + 'show boot' => "ShowBoot", + 'show bootvar' => "ShowBoot", + 'show flash' => "ShowFlash", + 'dir /all nvram:' => "DirSlotN", + 'dir /all bootflash:' => "DirSlotN", + 'dir /all slot0:' => "DirSlotN", + 'dir /all disk0:' => "DirSlotN", + 'dir /all slot1:' => "DirSlotN", + 'dir /all disk1:' => "DirSlotN", + 'show controllers' => "ShowContAll", + 'show controllers cbus' => "ShowContCbus", + 'show diagbus' => "ShowDiagbus", + 'show diag' => "ShowDiag", + 'show module' => "ShowModule", # cat 6500-ios + 'show c7200' => "ShowC7200", + 'show vtp status' => "ShowVTP", + 'write term' => "WriteTerm" +); +# keys() doesnt return things in the order entered and the order of the +# cmds is important (show version first and write term last). pita +@commands=( + "show version", + "show install active", + "show env all", + "show gsr chassis", + "show boot", + "show bootvar", + "show flash", + "dir /all nvram:", + "dir /all bootflash:", + "dir /all slot0:", + "dir /all disk0:", + "dir /all slot1:", + "dir /all disk1:", + "show controllers", + "show controllers cbus", + "show diagbus", + "show diag", + "show module", + "show c7200", + "show vtp status", + "write term" +); +$cisco_cmds=join(";",@commands); +$cmds_regexp=join("|",@commands); + +open(OUTPUT,">$host.new") || die "Can't open $host.new for writing: $!\n"; +select(OUTPUT); +# make OUTPUT unbuffered if debugging +if ($debug) { $| = 1; } + +if ($file) { + print STDERR "opening file $host\n" if ($debug); + print STDOUT "opening file $host\n" if ($log); + open(INPUT,"<$host") || die "open failed for $host: $!\n"; +} else { + print STDERR "executing clogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($debug); + print STDOUT "executing clogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($log); + if (defined($ENV{NOPIPE})) { + system "clogin -t $timeo -c \"$cisco_cmds\" $host $host.raw 2>&1" || die "clogin failed for $host: $!\n"; + open(INPUT, "< $host.raw") || die "clogin failed for $host: $!\n"; + } else { + open(INPUT,"clogin -t $timeo -c \"$cisco_cmds\" $host ) { + tr/\015//d; + if (/\#\s?exit$/) { + $clean_run=1; + last; + } + if (/Error:/) { + s/^.*Error:/Error:/; + print STDOUT ("$host clogin error: $_"); + print STDERR ("$host clogin error: $_") if ($debug); + $clean_run=0; + last; + } + while (/#\s*($cmds_regexp)\s*$/) { + $cmd = $1; + if (!defined($prompt)) {$prompt = ($_ =~ /^([^#]+#)/)[0]; } + print STDERR ("HIT COMMAND:$_") if ($debug); + if (! defined($commands{$cmd})) { + print STDERR "found unexpected command - \"$cmd\"\n"; + $clean_run = 0; + last TOP; + } + $rval = &{$commands{$cmd}}; + delete($commands{$cmd}); + if ($rval == -1) { + $clean_run = 0; + last TOP; + } + } +} +print STDOUT "Done $logincmd: $_\n" if ($log); +# Flush History +ProcessHistory("","","",""); +# Cleanup +close(INPUT); +close(OUTPUT); + +if (defined($ENV{NOPIPE})) { + unlink("$host.raw") if (! $debug); +} + +# check for completeness +if (scalar(%commands) || !$clean_run || !$found_end) { + if (scalar(%commands)) { + printf(STDOUT "missed cmd(s): %s\n", join(',', keys(%commands))); + printf(STDERR "missed cmd(s): %s\n", join(',', keys(%commands))) if ($debug); + } + if (!$clean_run || !$found_end) { + print STDOUT "End of run not found\n"; + print STDERR "End of run not found\n" if ($debug); + system("/usr/bin/tail -1 $host.new"); + } + unlink "$host.new" if (! $debug); +} diff --git a/bin/rename b/bin/rename deleted file mode 100755 index 8883355..0000000 --- a/bin/rename +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/local/bin/perl -'di'; -'ig00'; -# -# Revision 3.0.1.2 90/08/09 03:17:57 lwall -# patch19: added man page for relink and rename -# - -if ($ARGV[0] eq '-i') { - shift; - if (open(TTYIN, "/dev/tty")) { - $inspect++; - select((select(TTYOUT),$|=1)[0]); - } -} -($op = shift) || die "Usage: rename [-i] perlexpr [filenames]\n"; -if (!@ARGV) { - @ARGV = ; - chop(@ARGV); -} -for (@ARGV) { - unless (-e) { - print STDERR "$0: $_: $!\n"; - $status = 1; - next; - } - $was = $_; - eval $op; - die $@ if $@; - if ($was ne $_) { - if ($inspect && -e) { - print TTYOUT "remove $_? "; - next unless =~ /^y/i; - } - unless (rename($was, $_)) { - print STDERR "$0: can't rename $was to $_: $!\n"; - $status = 1; - } - } -} -exit $status; -############################################################################## -__END__ - # These next few lines are legal in both Perl and nroff. - -.00; # finish .ig - -'di \" finish diversion--previous line must be blank -.nr nl 0-1 \" fake up transition to first page again -.nr % 0 \" start at page 1 -';<<'.ex'; #__END__ ############# From here on it's a standard manual page ############ -.TH RENAME 1 "July 30, 1990" -.AT 3 -.SH NAME -rename \- renames multiple files -.SH SYNOPSIS -.B rename [-i] perlexpr [files] -.SH DESCRIPTION -.I Rename -renames the filenames supplied according to the rule specified as the -first argument. -The argument is a Perl expression which is expected to modify the $_ -string in Perl for at least some of the filenames specified. -If a given filename is not modified by the expression, it will not be -renamed. -If no filenames are given on the command line, filenames will be read -via standard input. -.PP -The -.B \-i -flag will prompt to remove the old file first if it exists. This -flag will be ignored if there is no tty. -.PP -For example, to rename all files matching *.bak to strip the extension, -you might say -.nf - - rename 's/\e.bak$//' *.bak - -.fi -To translate uppercase names to lower, you'd use -.nf - - rename 'y/A-Z/a-z/' * - -.fi -To do the same thing but leave Makefiles unharmed: -.nf - - rename 'y/A-Z/a-z/ unless /^Make/' * - -.fi -To rename all the *.f files to *.BAD, you'd use -.nf - - rename 's/\e.f$/.BAD/' *.f - -.SH ENVIRONMENT -.fi -No environment variables are used. -.SH FILES -.SH AUTHOR -Larry Wall -.SH "SEE ALSO" -mv(1) -.br -perl(1) -.SH DIAGNOSTICS -If you give an invalid Perl expression you'll get a syntax error. -.SH BUGS -.I Rename -does not check for the existence of target filenames, so use with care. -.ex diff --git a/bin/rename.in b/bin/rename.in new file mode 100755 index 0000000..8c3a111 --- /dev/null +++ b/bin/rename.in @@ -0,0 +1,113 @@ +#!@PERLV_PATH@ +'di'; +'ig00'; +# +# Revision 3.0.1.2 90/08/09 03:17:57 lwall +# patch19: added man page for relink and rename +# + +if ($ARGV[0] eq '-i') { + shift; + if (open(TTYIN, "/dev/tty")) { + $inspect++; + select((select(TTYOUT),$|=1)[0]); + } +} +($op = shift) || die "Usage: rename [-i] perlexpr [filenames]\n"; +if (!@ARGV) { + @ARGV = ; + chop(@ARGV); +} +for (@ARGV) { + unless (-e) { + print STDERR "$0: $_: $!\n"; + $status = 1; + next; + } + $was = $_; + eval $op; + die $@ if $@; + if ($was ne $_) { + if ($inspect && -e) { + print TTYOUT "remove $_? "; + next unless =~ /^y/i; + } + unless (rename($was, $_)) { + print STDERR "$0: can't rename $was to $_: $!\n"; + $status = 1; + } + } +} +exit $status; +############################################################################## +__END__ + # These next few lines are legal in both Perl and nroff. + +.00; # finish .ig + +'di \" finish diversion--previous line must be blank +.nr nl 0-1 \" fake up transition to first page again +.nr % 0 \" start at page 1 +';<<'.ex'; #__END__ ############# From here on it's a standard manual page ############ +.TH RENAME 1 "July 30, 1990" +.AT 3 +.SH NAME +rename \- renames multiple files +.SH SYNOPSIS +.B rename [-i] perlexpr [files] +.SH DESCRIPTION +.I Rename +renames the filenames supplied according to the rule specified as the +first argument. +The argument is a Perl expression which is expected to modify the $_ +string in Perl for at least some of the filenames specified. +If a given filename is not modified by the expression, it will not be +renamed. +If no filenames are given on the command line, filenames will be read +via standard input. +.PP +The +.B \-i +flag will prompt to remove the old file first if it exists. This +flag will be ignored if there is no tty. +.PP +For example, to rename all files matching *.bak to strip the extension, +you might say +.nf + + rename 's/\e.bak$//' *.bak + +.fi +To translate uppercase names to lower, you'd use +.nf + + rename 'y/A-Z/a-z/' * + +.fi +To do the same thing but leave Makefiles unharmed: +.nf + + rename 'y/A-Z/a-z/ unless /^Make/' * + +.fi +To rename all the *.f files to *.BAD, you'd use +.nf + + rename 's/\e.f$/.BAD/' *.f + +.SH ENVIRONMENT +.fi +No environment variables are used. +.SH FILES +.SH AUTHOR +Larry Wall +.SH "SEE ALSO" +mv(1) +.br +perl(1) +.SH DIAGNOSTICS +If you give an invalid Perl expression you'll get a syntax error. +.SH BUGS +.I Rename +does not check for the existence of target filenames, so use with care. +.ex diff --git a/bin/rrancid b/bin/rrancid deleted file mode 100755 index 40113aa..0000000 --- a/bin/rrancid +++ /dev/null @@ -1,347 +0,0 @@ -#!/usr/local/bin/perl -## -## hacked version of Hank's rancid - this one tries to deal with redbacks. -## -## Copyright (C) 1997 by Henry Kilmer. -## All rights reserved. -## -## This software may be freely copied, modified and redistributed without -## fee for non-commerical purposes provided that this copyright notice is -## preserved intact on all copies and modified copies. -## -## There is no warranty or other guarantee of fitness of this software. -## It is provided solely "as is". The author(s) disclaim(s) all -## responsibility and liability with respect to this software's usage -## or its effect upon hardware, computer systems, other software, or -## anything else. -## -## -# -# RANCID - Really Awesome New Cisco confIg Differ -# -# usage: rancid [-d] [-l] [-f filename | $host] -# -use Getopt::Std; -getopts('dflm'); -$log = $opt_l; -$debug = $opt_d; -$file = $opt_f; -$host = $ARGV[0]; -$clean_run = 0; -$found_end = 0; -$timeo = 90; # clogin timeout in seconds - -# This routine is used to print out the router configuration -sub ProcessHistory { - my($new_hist_tag,$new_command,$command_string,@string)=(@_); - if((($new_hist_tag ne $hist_tag) || ($new_command ne $command)) - && defined %history) { - print eval "$command \%history"; - undef %history; - } - if (($new_hist_tag) && ($new_command) && ($command_string)) { - if ($history{$command_string}) { - $history{$command_string} = "$history{$command_string}@string"; - } else { - $history{$command_string} = "@string"; - } - } elsif (($new_hist_tag) && ($new_command)) { - $history{++$#history} = "@string"; - } else { - print "@string"; - } - $hist_tag = $new_hist_tag; - $command = $new_command; - 1; -} - -sub numerically { $a <=> $b; } - -# This is a sort routing that will sort numerically on the -# keys of a hash as if it were a normal array. -sub keynsort { - local(%lines)=@_; - local($i) = 0; - local(@sorted_lines); - foreach $key (sort numerically keys(%lines)) { - $sorted_lines[$i] = $lines{$key}; - $i++; - } - @sorted_lines; -} - -# This is a sort routing that will sort on the -# keys of a hash as if it were a normal array. -sub keysort { - local(%lines)=@_; - local($i) = 0; - local(@sorted_lines); - foreach $key (sort keys(%lines)) { - $sorted_lines[$i] = $lines{$key}; - $i++; - } - @sorted_lines; -} - -# This is a sort routing that will sort on the -# values of a hash as if it were a normal array. -sub valsort{ - local(%lines)=@_; - local($i) = 0; - local(@sorted_lines); - foreach $key (sort values %lines) { - $sorted_lines[$i] = $key; - $i++; - } - @sorted_lines; -} - -# This is a numerical sort routing (ascending). -sub numsort { - local(%lines)=@_; - local($i) = 0; - local(@sorted_lines); - foreach $num (sort {$a <=> $b} keys %lines) { - $sorted_lines[$i] = $lines{$num}; - $i++; - } - @sorted_lines; -} - -# This is a sort routine that will sort on the -# ip address when the ip address is anywhere in -# the strings. -sub ipsort { - local(%lines)=@_; - local($i) = 0; - local(@sorted_lines); - foreach $addr (sort sortbyipaddr keys %lines) { - $sorted_lines[$i] = $lines{$addr}; - $i++; - } - @sorted_lines; -} - -# These two routines will sort based upon IP addresses -sub ipaddrval { - my(@a) = ($_[0] =~ m#^(\d+)\.(\d+)\.(\d+)\.(\d+)$#); - $a[3]+256*($a[2]+256*($a[1]+256*$a[0])); -} -sub sortbyipaddr { - &ipaddrval($a) <=> &ipaddrval($b); -} - -# This routine parses "dir /" -sub DirFlash { - print STDERR " In DirFlash: $_" if ($debug); - - my($dev) = (/\/(.*)$/); - while () { - tr/\015//d; - last if(/^$prompt/); - /^\s*$/ && next; - - /(Can\'t open|No such device)/ && return; - ProcessHistory("FLASH","keysort",$dev,"!Flash: $dev: $_"); - } - ProcessHistory("FLASH","keysort",$dev,"!\n"); - return; -} - -# This routine parses "show hardware" -sub ShowHardware { - print STDERR " In ShowHardware: $_" if ($debug); - - while () { - tr/\015//d; - last if(/^$prompt/); - s/\s*$/\n/; - - #ProcessHistory("","","","!Chassis: $_") && next; - ProcessHistory("COMMENTS","keysort","B1","!Chassis: $_"); - } - ProcessHistory("COMMENTS","keysort","B1","!\n"); - return; -} - -# This routine parses "show version" -sub ShowVersion { - print STDERR " In ShowVersion: $_" if ($debug); - - while () { - tr/\015//d; - last if(/^$prompt/); - - /(uptime|restarted|^\s*$)/ && next; - ProcessHistory("COMMENTS","keysort","A1","!Image: $_"); - } - return; -} - -# This routine parses "show slot table" -sub ShowSlotTable { - print STDERR " In ShowSlotTable: $_" if ($debug); - - while () { - tr/\015//d; - last if(/^$prompt/); - - /(Slot Table|^$)/ && next; - s/^\s*//; - ProcessHistory("COMMENTS","keysort","D1","!Slot Table: $_"); - } - ProcessHistory("COMMENTS","keysort","D1","!\n"); - return; -} - -# This routine processes a "write term" -sub WriteTerm { - print STDERR " In WriteTerm: $_" if ($debug); - - while () { - tr/\015//d; - last if(/^$prompt/); - -# /Non-Volatile memory is in use/ && return(-1); # NvRAM is locked - # Dog gone Cool matches to process the rest of the config - /^! last updated: .*$/ && next; # kill last updated line - /^ length / && next; # kill length on serial lines - /^ width / && next; # kill width on serial lines - # filter out any RCS/CVS tags to avoid confusing local CVS storage - s/\$(Revision|Id):/ $1:/; - # order access-lists - /^access-list\s+(\d\d?)\s+(\S+)\s+(\S+)/ && - ProcessHistory("ACL $1 $2","ipsort","$3","$_") && next; - ProcessHistory("","","","$_"); - # end of config - if (/^end$/) { - $found_end = 1; - last; - } - } - return; -} - -# dummy function -sub DoNothing {print STDOUT;} - -# Main subroutine that splits up the work -# All Subs return the name of the next function to use. -# If the sub returns a new funtion name, that name will be used -# else the main loop keeps using the current function -sub FlailHelplessly { - print STDERR "Flailing: $_" if ($debug); - print STDOUT "Flailing: $_" if ($log); - /#(show hardware)$/ && delete($commands{$1}) && return("ShowHardware"); - /#(show version)$/ && delete($commands{$1}) && return("ShowVersion"); - /#(show slot table)$/ && delete($commands{$1}) && return("ShowSlotTable"); - /#(show config)$/ && delete($commands{$1}) && return("WriteTerm"); - return "FlailHelplessly"; -} - -# Main -%commands=( - 'show version' => "ShowVersion", - "dir /flash" => "DirFlash", - "dir /pcmcia0" => "DirFlash", - "dir /pcmcia1" => "DirFlash", - 'show hardware' => "ShowHardware", - 'show slot table' => "ShowSlotTable", - 'show config' => "WriteTerm" -); -@commands=( - "show version", - "dir /flash", - "dir /pcmcia0", - "dir /pcmcia1", - "show hardware", - "show slot table", - "show config" -); -# dir /flash -# dir /pcmcia0 -# dir /pcmcia1 - -$redback_cmds=join(";",@commands); -$cmds_regexp=join("|",@commands); - -open(OUTPUT,">$host.new") || die "Can't open $host.new for writing: $!\n"; -select(OUTPUT); -# make OUTPUT unbuffered -if ($debug) { $| = 1; } - -if ($file) { - print STDERR "opening file $host\n" if ($debug); - print STDOUT "opening file $host\n" if ($log); - open(INPUT,"<$host") || die "open failed for $host: $!\n"; -} else { - print STDERR "executing clogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($debug); - print STDOUT "executing clogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($log); - - if (defined($ENV{NOPIPE})) { - system "clogin -t $timeo -c \"$redback_cmds\" $host $host.raw" || die "clogin failed for $host: $!\n"; - open(INPUT, "< $host.raw") || die "clogin failed for $host: $!\n"; - } else { - open(INPUT,"clogin -t $timeo -c \"$redback_cmds\" $host ) { - tr/\015//d; - if (/\#exit$/) { - $clean_run=1; - last; - } - if (/^Error:/) { - print STDOUT ("$host clogin error: $_"); - print STDERR ("$host clogin error: $_") if ($debug); - $clean_run=0; - last; - } - while (/#\s*($cmds_regexp)\s*$/) { - $cmd = $1; - if (!defined($prompt)) { - $prompt = ($_ =~ /^([^#]*#)/)[0]; - $prompt =~ s/([][])/\\$1/g; # quote the damn []'s - } - print STDERR ("HIT COMMAND:$_") if ($debug); - if (! defined($commands{$cmd})) { - print STDERR "found unexpected command - \"$cmd\"\n"; - $clean_run = 0; - last; - } - $rval = &{$commands{$cmd}}; - delete($commands{$cmd}); - if ($rval == -1) { - $clean_run = 0; - last; - } - } -} -print STDOUT "Done $logincmd: $_\n" if ($log); -# Flush History -ProcessHistory("","","",""); -# Cleanup -close(INPUT); -close(OUTPUT); - -if (defined($ENV{NOPIPE})) { - unlink("$host.raw") if (! $debug); -} - -# check for completeness -if (scalar(%commands) || !$clean_run || !$found_end) { - if (scalar(%commands)) { - printf(STDOUT "missed cmd(s): %s\n", join(',', keys(%commands))); - printf(STDERR "missed cmd(s): %s\n", join(',', keys(%commands))) if ($debug); - } - if (!$clean_run || !$found_end) { - print STDOUT "End of run not found\n"; - print STDERR "End of run not found\n" if ($debug); - system("/usr/bin/tail -1 $host.new"); - } - unlink "$host.new" if (! $debug); -} diff --git a/bin/rrancid.in b/bin/rrancid.in new file mode 100755 index 0000000..9d9b84f --- /dev/null +++ b/bin/rrancid.in @@ -0,0 +1,347 @@ +#!@PERLV_PATH@ +## +## hacked version of Hank's rancid - this one tries to deal with redbacks. +## +## Copyright (C) 1997 by Henry Kilmer. +## All rights reserved. +## +## This software may be freely copied, modified and redistributed without +## fee for non-commerical purposes provided that this copyright notice is +## preserved intact on all copies and modified copies. +## +## There is no warranty or other guarantee of fitness of this software. +## It is provided solely "as is". The author(s) disclaim(s) all +## responsibility and liability with respect to this software's usage +## or its effect upon hardware, computer systems, other software, or +## anything else. +## +## +# +# RANCID - Really Awesome New Cisco confIg Differ +# +# usage: rancid [-d] [-l] [-f filename | $host] +# +use Getopt::Std; +getopts('dflm'); +$log = $opt_l; +$debug = $opt_d; +$file = $opt_f; +$host = $ARGV[0]; +$clean_run = 0; +$found_end = 0; +$timeo = 90; # clogin timeout in seconds + +# This routine is used to print out the router configuration +sub ProcessHistory { + my($new_hist_tag,$new_command,$command_string,@string)=(@_); + if((($new_hist_tag ne $hist_tag) || ($new_command ne $command)) + && defined %history) { + print eval "$command \%history"; + undef %history; + } + if (($new_hist_tag) && ($new_command) && ($command_string)) { + if ($history{$command_string}) { + $history{$command_string} = "$history{$command_string}@string"; + } else { + $history{$command_string} = "@string"; + } + } elsif (($new_hist_tag) && ($new_command)) { + $history{++$#history} = "@string"; + } else { + print "@string"; + } + $hist_tag = $new_hist_tag; + $command = $new_command; + 1; +} + +sub numerically { $a <=> $b; } + +# This is a sort routing that will sort numerically on the +# keys of a hash as if it were a normal array. +sub keynsort { + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $key (sort numerically keys(%lines)) { + $sorted_lines[$i] = $lines{$key}; + $i++; + } + @sorted_lines; +} + +# This is a sort routing that will sort on the +# keys of a hash as if it were a normal array. +sub keysort { + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $key (sort keys(%lines)) { + $sorted_lines[$i] = $lines{$key}; + $i++; + } + @sorted_lines; +} + +# This is a sort routing that will sort on the +# values of a hash as if it were a normal array. +sub valsort{ + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $key (sort values %lines) { + $sorted_lines[$i] = $key; + $i++; + } + @sorted_lines; +} + +# This is a numerical sort routing (ascending). +sub numsort { + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $num (sort {$a <=> $b} keys %lines) { + $sorted_lines[$i] = $lines{$num}; + $i++; + } + @sorted_lines; +} + +# This is a sort routine that will sort on the +# ip address when the ip address is anywhere in +# the strings. +sub ipsort { + local(%lines)=@_; + local($i) = 0; + local(@sorted_lines); + foreach $addr (sort sortbyipaddr keys %lines) { + $sorted_lines[$i] = $lines{$addr}; + $i++; + } + @sorted_lines; +} + +# These two routines will sort based upon IP addresses +sub ipaddrval { + my(@a) = ($_[0] =~ m#^(\d+)\.(\d+)\.(\d+)\.(\d+)$#); + $a[3]+256*($a[2]+256*($a[1]+256*$a[0])); +} +sub sortbyipaddr { + &ipaddrval($a) <=> &ipaddrval($b); +} + +# This routine parses "dir /" +sub DirFlash { + print STDERR " In DirFlash: $_" if ($debug); + + my($dev) = (/\/(.*)$/); + while () { + tr/\015//d; + last if(/^$prompt/); + /^\s*$/ && next; + + /(Can\'t open|No such device)/ && return; + ProcessHistory("FLASH","keysort",$dev,"!Flash: $dev: $_"); + } + ProcessHistory("FLASH","keysort",$dev,"!\n"); + return; +} + +# This routine parses "show hardware" +sub ShowHardware { + print STDERR " In ShowHardware: $_" if ($debug); + + while () { + tr/\015//d; + last if(/^$prompt/); + s/\s*$/\n/; + + #ProcessHistory("","","","!Chassis: $_") && next; + ProcessHistory("COMMENTS","keysort","B1","!Chassis: $_"); + } + ProcessHistory("COMMENTS","keysort","B1","!\n"); + return; +} + +# This routine parses "show version" +sub ShowVersion { + print STDERR " In ShowVersion: $_" if ($debug); + + while () { + tr/\015//d; + last if(/^$prompt/); + + /(uptime|restarted|^\s*$)/ && next; + ProcessHistory("COMMENTS","keysort","A1","!Image: $_"); + } + return; +} + +# This routine parses "show slot table" +sub ShowSlotTable { + print STDERR " In ShowSlotTable: $_" if ($debug); + + while () { + tr/\015//d; + last if(/^$prompt/); + + /(Slot Table|^$)/ && next; + s/^\s*//; + ProcessHistory("COMMENTS","keysort","D1","!Slot Table: $_"); + } + ProcessHistory("COMMENTS","keysort","D1","!\n"); + return; +} + +# This routine processes a "write term" +sub WriteTerm { + print STDERR " In WriteTerm: $_" if ($debug); + + while () { + tr/\015//d; + last if(/^$prompt/); + +# /Non-Volatile memory is in use/ && return(-1); # NvRAM is locked + # Dog gone Cool matches to process the rest of the config + /^! last updated: .*$/ && next; # kill last updated line + /^ length / && next; # kill length on serial lines + /^ width / && next; # kill width on serial lines + # filter out any RCS/CVS tags to avoid confusing local CVS storage + s/\$(Revision|Id):/ $1:/; + # order access-lists + /^access-list\s+(\d\d?)\s+(\S+)\s+(\S+)/ && + ProcessHistory("ACL $1 $2","ipsort","$3","$_") && next; + ProcessHistory("","","","$_"); + # end of config + if (/^end$/) { + $found_end = 1; + last; + } + } + return; +} + +# dummy function +sub DoNothing {print STDOUT;} + +# Main subroutine that splits up the work +# All Subs return the name of the next function to use. +# If the sub returns a new funtion name, that name will be used +# else the main loop keeps using the current function +sub FlailHelplessly { + print STDERR "Flailing: $_" if ($debug); + print STDOUT "Flailing: $_" if ($log); + /#(show hardware)$/ && delete($commands{$1}) && return("ShowHardware"); + /#(show version)$/ && delete($commands{$1}) && return("ShowVersion"); + /#(show slot table)$/ && delete($commands{$1}) && return("ShowSlotTable"); + /#(show config)$/ && delete($commands{$1}) && return("WriteTerm"); + return "FlailHelplessly"; +} + +# Main +%commands=( + 'show version' => "ShowVersion", + "dir /flash" => "DirFlash", + "dir /pcmcia0" => "DirFlash", + "dir /pcmcia1" => "DirFlash", + 'show hardware' => "ShowHardware", + 'show slot table' => "ShowSlotTable", + 'show config' => "WriteTerm" +); +@commands=( + "show version", + "dir /flash", + "dir /pcmcia0", + "dir /pcmcia1", + "show hardware", + "show slot table", + "show config" +); +# dir /flash +# dir /pcmcia0 +# dir /pcmcia1 + +$redback_cmds=join(";",@commands); +$cmds_regexp=join("|",@commands); + +open(OUTPUT,">$host.new") || die "Can't open $host.new for writing: $!\n"; +select(OUTPUT); +# make OUTPUT unbuffered +if ($debug) { $| = 1; } + +if ($file) { + print STDERR "opening file $host\n" if ($debug); + print STDOUT "opening file $host\n" if ($log); + open(INPUT,"<$host") || die "open failed for $host: $!\n"; +} else { + print STDERR "executing clogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($debug); + print STDOUT "executing clogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($log); + + if (defined($ENV{NOPIPE})) { + system "clogin -t $timeo -c \"$redback_cmds\" $host $host.raw" || die "clogin failed for $host: $!\n"; + open(INPUT, "< $host.raw") || die "clogin failed for $host: $!\n"; + } else { + open(INPUT,"clogin -t $timeo -c \"$redback_cmds\" $host ) { + tr/\015//d; + if (/\#exit$/) { + $clean_run=1; + last; + } + if (/^Error:/) { + print STDOUT ("$host clogin error: $_"); + print STDERR ("$host clogin error: $_") if ($debug); + $clean_run=0; + last; + } + while (/#\s*($cmds_regexp)\s*$/) { + $cmd = $1; + if (!defined($prompt)) { + $prompt = ($_ =~ /^([^#]*#)/)[0]; + $prompt =~ s/([][])/\\$1/g; # quote the damn []'s + } + print STDERR ("HIT COMMAND:$_") if ($debug); + if (! defined($commands{$cmd})) { + print STDERR "found unexpected command - \"$cmd\"\n"; + $clean_run = 0; + last; + } + $rval = &{$commands{$cmd}}; + delete($commands{$cmd}); + if ($rval == -1) { + $clean_run = 0; + last; + } + } +} +print STDOUT "Done $logincmd: $_\n" if ($log); +# Flush History +ProcessHistory("","","",""); +# Cleanup +close(INPUT); +close(OUTPUT); + +if (defined($ENV{NOPIPE})) { + unlink("$host.raw") if (! $debug); +} + +# check for completeness +if (scalar(%commands) || !$clean_run || !$found_end) { + if (scalar(%commands)) { + printf(STDOUT "missed cmd(s): %s\n", join(',', keys(%commands))); + printf(STDERR "missed cmd(s): %s\n", join(',', keys(%commands))) if ($debug); + } + if (!$clean_run || !$found_end) { + print STDOUT "End of run not found\n"; + print STDERR "End of run not found\n" if ($debug); + system("/usr/bin/tail -1 $host.new"); + } + unlink "$host.new" if (! $debug); +} diff --git a/cloginrc.sample b/cloginrc.sample index b8368a2..2e17025 100644 --- a/cloginrc.sample +++ b/cloginrc.sample @@ -5,6 +5,7 @@ # userprompt # userpassword # passprompt +# method # noenable # enauser # enableprompt @@ -31,6 +32,14 @@ # What the router prints to prompt for the password. # Default: "\[Pp]assword:" # +# add method {ssh} [...] +# Defines, in order, which connection method(s) to use for a device +# from the set {ssh,telnet,rsh}. eg: add method * {ssh} {telnet} {rsh} +# will attempt ssh connection first. if ssh fails with connection +# refused (ie: not due to authentication failure), then try telnet, +# then rsh. +# Default: {telnet} {ssh} +# # add noenable # equivalent of -noenable on the cmd line to not enable at login. # @@ -63,7 +72,7 @@ #add password * anything # #add user sl-gw*-dc twit -#add user sdn* sdn_auto +#add user sdn* sdn_auto #add user sdn-bb* ops_eng #add user * $env(USER) @@ -76,13 +85,17 @@ add autoenable *.custx.net 1 # customer y # this is the normal cisco login. a password followed by and enable password. +# try ssh first, then rlogin. add password *.custy.net {vector} {victor} +add method *.custy.net ssh rlogin -# customer z +# customer z; they use ssh only. add user *.custz.net shirley add password *.custz.net {jive} {surely} +add method *.custz.net ssh -# the route-server's do provide enable access. cmdline -noenable equivalent. +# the route-server's do not provide enable access. cmdline -noenable +# equivalent. add noenable route-server* 1 # all our routers, ie: everything else diff --git a/configure b/configure new file mode 100755 index 0000000..be66c88 --- /dev/null +++ b/configure @@ -0,0 +1,1990 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.13 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_default_prefix=/usr/local/rancid +ac_help="$ac_help + --enable-maintainer-mode enable make rules and dependencies not useful + (and sometimes confusing) to the casual installer" +ac_help="$ac_help + --with-ucbmail=[FQPN] path to UCB mail" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.13" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file= + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:563: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6 +echo "configure:616: checking whether build environment is sane" >&5 +# Just in case +sleep 1 +echo timestamp > conftestfile +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftestfile` + fi + if test "$*" != "X $srcdir/configure conftestfile" \ + && test "$*" != "X conftestfile $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + { echo "configure: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" 1>&2; exit 1; } + fi + + test "$2" = conftestfile + ) +then + # Ok. + : +else + { echo "configure: error: newly created file is older than distributed files! +Check your system clock" 1>&2; exit 1; } +fi +rm -f conftest* +echo "$ac_t""yes" 1>&6 +if test "$program_transform_name" = s,x,x,; then + program_transform_name= +else + # Double any \ or $. echo might interpret backslashes. + cat <<\EOF_SED > conftestsed +s,\\,\\\\,g; s,\$,$$,g +EOF_SED + program_transform_name="`echo $program_transform_name|sed -f conftestsed`" + rm -f conftestsed +fi +test "$program_prefix" != NONE && + program_transform_name="s,^,${program_prefix},; $program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" + +# sed with no file args requires a program. +test "$program_transform_name" = "" && program_transform_name="s,x,x," + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:673: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + + +PACKAGE=PACKAGE + +VERSION=VERSION + +if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then + { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; } +fi +cat >> confdefs.h <> confdefs.h <&6 +echo "configure:719: checking for working aclocal" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (aclocal --version) < /dev/null > /dev/null 2>&1; then + ACLOCAL=aclocal + echo "$ac_t""found" 1>&6 +else + ACLOCAL="$missing_dir/missing aclocal" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working autoconf""... $ac_c" 1>&6 +echo "configure:732: checking for working autoconf" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (autoconf --version) < /dev/null > /dev/null 2>&1; then + AUTOCONF=autoconf + echo "$ac_t""found" 1>&6 +else + AUTOCONF="$missing_dir/missing autoconf" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working automake""... $ac_c" 1>&6 +echo "configure:745: checking for working automake" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (automake --version) < /dev/null > /dev/null 2>&1; then + AUTOMAKE=automake + echo "$ac_t""found" 1>&6 +else + AUTOMAKE="$missing_dir/missing automake" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working autoheader""... $ac_c" 1>&6 +echo "configure:758: checking for working autoheader" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (autoheader --version) < /dev/null > /dev/null 2>&1; then + AUTOHEADER=autoheader + echo "$ac_t""found" 1>&6 +else + AUTOHEADER="$missing_dir/missing autoheader" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6 +echo "configure:771: checking for working makeinfo" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (makeinfo --version) < /dev/null > /dev/null 2>&1; then + MAKEINFO=makeinfo + echo "$ac_t""found" 1>&6 +else + MAKEINFO="$missing_dir/missing makeinfo" + echo "$ac_t""missing" 1>&6 +fi + + + +subdirs="bin util" + + + + + +PACKAGE=rancid + +# VERSION needs to be updated such that 'make dist' uses the correct +# filename for the direcotyr name and tarball. + +VERSION=2.0 + +echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6 +echo "configure:799: checking whether to enable maintainer-specific portions of Makefiles" >&5 + # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then + enableval="$enable_maintainer_mode" + USE_MAINTAINER_MODE=$enableval +else + USE_MAINTAINER_MODE=no +fi + + echo "$ac_t""$USE_MAINTAINER_MODE" 1>&6 + + +if test $USE_MAINTAINER_MODE = yes; then + MAINTAINER_MODE_TRUE= + MAINTAINER_MODE_FALSE='#' +else + MAINTAINER_MODE_TRUE='#' + MAINTAINER_MODE_FALSE= +fi + MAINT=$MAINTAINER_MODE_TRUE + + + +# Extract the first word of "cvs", so it can be a program name with args. +set dummy cvs; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:825: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_CVS'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$CVS" in + /*) + ac_cv_path_CVS="$CVS" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_CVS="$CVS" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_CVS="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_CVS" && ac_cv_path_CVS="no" + ;; +esac +fi +CVS="$ac_cv_path_CVS" +if test -n "$CVS"; then + echo "$ac_t""$CVS" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +# Extract the first word of "comm", so it can be a program name with args. +set dummy comm; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:861: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_COMM'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$COMM" in + /*) + ac_cv_path_COMM="$COMM" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_COMM="$COMM" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_COMM="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_COMM" && ac_cv_path_COMM="no" + ;; +esac +fi +COMM="$ac_cv_path_COMM" +if test -n "$COMM"; then + echo "$ac_t""$COMM" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +# Extract the first word of "mkdir", so it can be a program name with args. +set dummy mkdir; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:897: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_MKDIR'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$MKDIR" in + /*) + ac_cv_path_MKDIR="$MKDIR" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_MKDIR="$MKDIR" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_MKDIR="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_MKDIR" && ac_cv_path_MKDIR="no" + ;; +esac +fi +MKDIR="$ac_cv_path_MKDIR" +if test -n "$MKDIR"; then + echo "$ac_t""$MKDIR" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +# Extract the first word of "dirname", so it can be a program name with args. +set dummy dirname; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:933: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_DIRNAME'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$DIRNAME" in + /*) + ac_cv_path_DIRNAME="$DIRNAME" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_DIRNAME="$DIRNAME" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_DIRNAME="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_DIRNAME" && ac_cv_path_DIRNAME="no" + ;; +esac +fi +DIRNAME="$ac_cv_path_DIRNAME" +if test -n "$DIRNAME"; then + echo "$ac_t""$DIRNAME" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +# locate GNU diff (-u option) +# Extract the first word of "diff", so it can be a program name with args. +set dummy diff; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:970: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_DIFF'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$DIFF" in + /*) + ac_cv_path_DIFF="$DIFF" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_DIFF="$DIFF" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="/usr/local/bin:/usr/gnu/bin:/usr/bin:/usr/contrib/bin" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_DIFF="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_DIFF" && ac_cv_path_DIFF="no" + ;; +esac +fi +DIFF="$ac_cv_path_DIFF" +if test -n "$DIFF"; then + echo "$ac_t""$DIFF" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test $DIFF = no; then + unset ac_cv_path_DIFF + { echo "configure: error: can't locate a GNU diff." 1>&2; exit 1; } +else + $DIFF -u /dev/null /dev/null > /dev/null 2>&1 + if test $? -ne 0; then + { echo "configure: error: can't locate a GNU diff (one which accepts the -u option)." 1>&2; exit 1; } + exit 1 + fi +fi +# Extract the first word of "touch", so it can be a program name with args. +set dummy touch; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1016: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_TOUCH'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$TOUCH" in + /*) + ac_cv_path_TOUCH="$TOUCH" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_TOUCH="$TOUCH" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_TOUCH="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_TOUCH" && ac_cv_path_TOUCH="no" + ;; +esac +fi +TOUCH="$ac_cv_path_TOUCH" +if test -n "$TOUCH"; then + echo "$ac_t""$TOUCH" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +# Extract the first word of "sendmail", so it can be a program name with args. +set dummy sendmail; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1052: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_SENDMAIL'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$SENDMAIL" in + /*) + ac_cv_path_SENDMAIL="$SENDMAIL" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_SENDMAIL="$SENDMAIL" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="/usr/sbin:/usr/bin:/usr/lib" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_SENDMAIL="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_SENDMAIL" && ac_cv_path_SENDMAIL="no" + ;; +esac +fi +SENDMAIL="$ac_cv_path_SENDMAIL" +if test -n "$SENDMAIL"; then + echo "$ac_t""$SENDMAIL" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +# find UCB mail. +# Check whether --with-ucbmail or --without-ucbmail was given. +if test "${with_ucbmail+set}" = set; then + withval="$with_ucbmail" + UCBMAIL=$withval; unset ac_cv_path_UCBMAIL +fi + +# Extract the first word of "Mail", so it can be a program name with args. +set dummy Mail; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1095: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_UCBMAIL'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$UCBMAIL" in + /*) + ac_cv_path_UCBMAIL="$UCBMAIL" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_UCBMAIL="$UCBMAIL" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_UCBMAIL="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_UCBMAIL" && ac_cv_path_UCBMAIL="no" + ;; +esac +fi +UCBMAIL="$ac_cv_path_UCBMAIL" +if test -n "$UCBMAIL"; then + echo "$ac_t""$UCBMAIL" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test $UCBMAIL = no; then + unset ac_cv_path_UCBMAIL + # Extract the first word of "mailx", so it can be a program name with args. +set dummy mailx; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1133: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_UCBMAIL'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$UCBMAIL" in + /*) + ac_cv_path_UCBMAIL="$UCBMAIL" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_UCBMAIL="$UCBMAIL" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_UCBMAIL="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_UCBMAIL" && ac_cv_path_UCBMAIL="no" + ;; +esac +fi +UCBMAIL="$ac_cv_path_UCBMAIL" +if test -n "$UCBMAIL"; then + echo "$ac_t""$UCBMAIL" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test $UCBMAIL = no; then + { echo "configure: error: can't locate a UCB Mail (one which accepts the -s option for subject)." 1>&2; exit 1; } + { echo "configure: error: UCB mail is normally Mail or mailx. use --with-ucbmail to specify the path." 1>&2; exit 1; } + exit 1 + fi +fi +# Extract the first word of "sort", so it can be a program name with args. +set dummy sort; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1175: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_SORT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$SORT" in + /*) + ac_cv_path_SORT="$SORT" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_SORT="$SORT" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_SORT="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_SORT" && ac_cv_path_SORT="no" + ;; +esac +fi +SORT="$ac_cv_path_SORT" +if test -n "$SORT"; then + echo "$ac_t""$SORT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + +# Extract the first word of "gmake", so it can be a program name with args. +set dummy gmake; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1212: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_MAKE'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$MAKE" in + /*) + ac_cv_path_MAKE="$MAKE" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_MAKE="$MAKE" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_MAKE="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_MAKE" && ac_cv_path_MAKE="no" + ;; +esac +fi +MAKE="$ac_cv_path_MAKE" +if test -n "$MAKE"; then + echo "$ac_t""$MAKE" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test $MAKE = no; then + unset ac_cv_path_MAKE + # Extract the first word of "make", so it can be a program name with args. +set dummy make; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1250: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_MAKE'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$MAKE" in + /*) + ac_cv_path_MAKE="$MAKE" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_MAKE="$MAKE" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_MAKE="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_MAKE" && ac_cv_path_MAKE="no" + ;; +esac +fi +MAKE="$ac_cv_path_MAKE" +if test -n "$MAKE"; then + echo "$ac_t""$MAKE" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test $MAKE = no; then + { echo "configure: error: can't locate a make." 1>&2; exit 1; } + exit 1 + fi +fi +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:1289: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + + +# Find an appropriate tar for use in "dist" targets. A "best guess" +# is good enough -- if we can't find GNU tar, we don't really care. +for ac_prog in gnutar gtar tar +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1323: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_TAR'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$TAR"; then + ac_cv_prog_TAR="$TAR" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_TAR="$ac_prog" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +TAR="$ac_cv_prog_TAR" +if test -n "$TAR"; then + echo "$ac_t""$TAR" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$TAR" && break +done + + +for ac_prog in automake +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1358: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_AUTOMAKE'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$AUTOMAKE"; then + ac_cv_prog_AUTOMAKE="$AUTOMAKE" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_AUTOMAKE="$ac_prog" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +AUTOMAKE="$ac_cv_prog_AUTOMAKE" +if test -n "$AUTOMAKE"; then + echo "$ac_t""$AUTOMAKE" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$AUTOMAKE" && break +done + + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:1400: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +# Extract the first word of "perl5", so it can be a program name with args. +set dummy perl5; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1455: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_PERLV_PATH'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$PERLV_PATH" in + /*) + ac_cv_path_PERLV_PATH="$PERLV_PATH" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_PERLV_PATH="$PERLV_PATH" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_PERLV_PATH="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_PERLV_PATH" && ac_cv_path_PERLV_PATH="no" + ;; +esac +fi +PERLV_PATH="$ac_cv_path_PERLV_PATH" +if test -n "$PERLV_PATH"; then + echo "$ac_t""$PERLV_PATH" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test $PERLV_PATH = no; then + unset ac_cv_path_PERLV_PATH + # Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1493: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_PERLV_PATH'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$PERLV_PATH" in + /*) + ac_cv_path_PERLV_PATH="$PERLV_PATH" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_PERLV_PATH="$PERLV_PATH" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_PERLV_PATH="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_PERLV_PATH" && ac_cv_path_PERLV_PATH="no" + ;; +esac +fi +PERLV_PATH="$ac_cv_path_PERLV_PATH" +if test -n "$PERLV_PATH"; then + echo "$ac_t""$PERLV_PATH" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test $PERLV_PATH = no; then + { echo "configure: error: can't locate a suitable perl5." 1>&2; exit 1; } + exit 1 + else + $PERLV_PATH -e 'require 5;' + if test $? -ne 0 ; then + { echo "configure: error: can't locate a suitable perl5." 1>&2; exit 1; } + exit 1 + fi + fi +fi + + +# Extract the first word of "expect", so it can be a program name with args. +set dummy expect; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1542: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_EXPECT_PATH'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$EXPECT_PATH" in + /*) + ac_cv_path_EXPECT_PATH="$EXPECT_PATH" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_EXPECT_PATH="$EXPECT_PATH" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_EXPECT_PATH="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_EXPECT_PATH" && ac_cv_path_EXPECT_PATH="no" + ;; +esac +fi +EXPECT_PATH="$ac_cv_path_EXPECT_PATH" +if test -n "$EXPECT_PATH"; then + echo "$ac_t""$EXPECT_PATH" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test $EXPECT_PATH = no; then + { echo "configure: error: can't locate expect." 1>&2; exit 1; } +fi + + +# RD_BIN_DATAS are bin/ .in's that need to be installed without execute +# perms. +RD_BIN_DATAS="" + +rd_cv_rd_bin_datas=$RD_BIN_DATAS + +# RD_BIN_PROGS are bin/ .in's that need to be installed with execute perms. +RD_BIN_PROGS="cat5rancid control_rancid \ +clogin create_cvs do-diffs elogin erancid \ +flogin francid jlogin jrancid par rancid-fe \ +rancid rename rrancid" + +rd_cv_rd_bin_progs=$RD_BIN_PROGS + +# RD_BIN_PROGS are util/ .in's that need to be installed with execute perms. +RD_UTIL_PROGS="rtrfilter" + +rd_cv_rd_util_progs=$RD_UTIL_PROGS + + +INST_PROGS=$progs + + +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +cat > conftest.defs <<\EOF +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g +s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g +s%\[%\\&%g +s%\]%\\&%g +s%\$%$$%g +EOF +DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '` +rm -f conftest.defs + + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.13" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@FFLAGS@%$FFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@PACKAGE@%$PACKAGE%g +s%@VERSION@%$VERSION%g +s%@ACLOCAL@%$ACLOCAL%g +s%@AUTOCONF@%$AUTOCONF%g +s%@AUTOMAKE@%$AUTOMAKE%g +s%@AUTOHEADER@%$AUTOHEADER%g +s%@MAKEINFO@%$MAKEINFO%g +s%@SET_MAKE@%$SET_MAKE%g +s%@subdirs@%$subdirs%g +s%@MAINTAINER_MODE_TRUE@%$MAINTAINER_MODE_TRUE%g +s%@MAINTAINER_MODE_FALSE@%$MAINTAINER_MODE_FALSE%g +s%@MAINT@%$MAINT%g +s%@CVS@%$CVS%g +s%@COMM@%$COMM%g +s%@MKDIR@%$MKDIR%g +s%@DIRNAME@%$DIRNAME%g +s%@DIFF@%$DIFF%g +s%@TOUCH@%$TOUCH%g +s%@SENDMAIL@%$SENDMAIL%g +s%@UCBMAIL@%$UCBMAIL%g +s%@SORT@%$SORT%g +s%@MAKE@%$MAKE%g +s%@TAR@%$TAR%g +s%@PERLV_PATH@%$PERLV_PATH%g +s%@EXPECT_PATH@%$EXPECT_PATH%g +s%@RD_BIN_DATAS@%$RD_BIN_DATAS%g +s%@RD_BIN_PROGS@%$RD_BIN_PROGS%g +s%@RD_UTIL_PROGS@%$RD_UTIL_PROGS%g +s%@INST_PROGS@%$INST_PROGS%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + +if test "$no_recursion" != yes; then + + # Remove --cache-file and --srcdir arguments so they do not pile up. + ac_sub_configure_args= + ac_prev= + for ac_arg in $ac_configure_args; do + if test -n "$ac_prev"; then + ac_prev= + continue + fi + case "$ac_arg" in + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + ;; + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + ;; + *) ac_sub_configure_args="$ac_sub_configure_args $ac_arg" ;; + esac + done + + for ac_config_dir in bin util; do + + # Do not complain, so a configure script can configure whichever + # parts of a large source tree are present. + if test ! -d $srcdir/$ac_config_dir; then + continue + fi + + echo configuring in $ac_config_dir + + case "$srcdir" in + .) ;; + *) + if test -d ./$ac_config_dir || mkdir ./$ac_config_dir; then :; + else + { echo "configure: error: can not create `pwd`/$ac_config_dir" 1>&2; exit 1; } + fi + ;; + esac + + ac_popdir=`pwd` + cd $ac_config_dir + + # A "../" for each directory in /$ac_config_dir. + ac_dots=`echo $ac_config_dir|sed -e 's%^\./%%' -e 's%[^/]$%&/%' -e 's%[^/]*/%../%g'` + + case "$srcdir" in + .) # No --srcdir option. We are building in place. + ac_sub_srcdir=$srcdir ;; + /*) # Absolute path. + ac_sub_srcdir=$srcdir/$ac_config_dir ;; + *) # Relative path. + ac_sub_srcdir=$ac_dots$srcdir/$ac_config_dir ;; + esac + + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_sub_srcdir/configure; then + ac_sub_configure=$ac_sub_srcdir/configure + elif test -f $ac_sub_srcdir/configure.in; then + ac_sub_configure=$ac_configure + else + echo "configure: warning: no configuration information is in $ac_config_dir" 1>&2 + ac_sub_configure= + fi + + # The recursion is here. + if test -n "$ac_sub_configure"; then + + # Make the cache file name correct relative to the subdirectory. + case "$cache_file" in + /*) ac_sub_cache_file=$cache_file ;; + *) # Relative path. + ac_sub_cache_file="$ac_dots$cache_file" ;; + esac + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo "running ${CONFIG_SHELL-/bin/sh} $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_sub_srcdir" + # The eval makes quoting arguments work. + if eval ${CONFIG_SHELL-/bin/sh} $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_sub_srcdir + then : + else + { echo "configure: error: $ac_sub_configure failed for $ac_config_dir" 1>&2; exit 1; } + fi + fi + + cd $ac_popdir + done +fi + + +# fix permissions on scripts. +for file in $progs; do chmod a+x $file; done diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..fde93cd --- /dev/null +++ b/configure.in @@ -0,0 +1,121 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT() + +AM_INIT_AUTOMAKE(PACKAGE, VERSION) + +AC_CONFIG_SUBDIRS(bin util) + +dnl default install location +AC_PREFIX_DEFAULT(/usr/local/rancid) + +AC_SUBST(PACKAGE) +PACKAGE=rancid + +# VERSION needs to be updated such that 'make dist' uses the correct +# filename for the directory name and tarball. +AC_SUBST(VERSION) +VERSION=2.0 + +AM_MAINTAINER_MODE() + +AC_PATH_PROG(CVS,cvs,no) +AC_PATH_PROG(COMM,comm,no) +AC_PATH_PROG(MKDIR,mkdir,no) +AC_PATH_PROG(DIRNAME,dirname,no) +# locate GNU diff (-u option) +AC_PATH_PROG(DIFF,diff,no, /usr/local/bin:/usr/gnu/bin:/usr/bin:/usr/contrib/bin) +if test $DIFF = no; then + unset ac_cv_path_DIFF + AC_MSG_ERROR([can't locate a GNU diff.]) +else + $DIFF -u /dev/null /dev/null > /dev/null 2>&1 + if test $? -ne 0; then + AC_MSG_ERROR([can't locate a GNU diff (one which accepts the -u option).]) + exit 1 + fi +fi +AC_PATH_PROG(TOUCH,touch,no) +AC_PATH_PROG(SENDMAIL,sendmail,no, /usr/sbin:/usr/bin:/usr/lib) +# find UCB mail. +AC_ARG_WITH(ucbmail, [ --with-ucbmail=[FQPN] path to UCB mail], UCBMAIL=$withval; unset ac_cv_path_UCBMAIL) +AC_PATH_PROG(UCBMAIL,Mail,no) +if test $UCBMAIL = no; then + unset ac_cv_path_UCBMAIL + AC_PATH_PROG(UCBMAIL,mailx,no) + if test $UCBMAIL = no; then + AC_MSG_ERROR([can't locate a UCB Mail (one which accepts the -s option for subject).]) + AC_MSG_ERROR([UCB mail is normally Mail or mailx. use --with-ucbmail to specify the path.]) + exit 1 + fi +fi +AC_PATH_PROG(SORT,sort,no) + +AC_PATH_PROG(MAKE,gmake,no) +if test $MAKE = no; then + unset ac_cv_path_MAKE + AC_PATH_PROG(MAKE,make,no) + if test $MAKE = no; then + AC_MSG_ERROR([can't locate a make.]) + exit 1 + fi +fi +AC_PROG_MAKE_SET() + +# Find an appropriate tar for use in "dist" targets. A "best guess" +# is good enough -- if we can't find GNU tar, we don't really care. +AC_CHECK_PROGS(TAR, gnutar gtar tar) + +AC_CHECK_PROGS(AUTOMAKE, automake) + +dnl locate perl 5 and expect. +AC_PROG_INSTALL +AC_PATH_PROG(PERLV_PATH,perl5,no) +if test $PERLV_PATH = no; then + unset ac_cv_path_PERLV_PATH + AC_PATH_PROG(PERLV_PATH,perl,no) + if test $PERLV_PATH = no; then + AC_MSG_ERROR([can't locate a suitable perl5.]) + exit 1 + else + $PERLV_PATH -e 'require 5;' + if test $? -ne 0 ; then + AC_MSG_ERROR([can't locate a suitable perl5.]) + exit 1 + fi + fi +fi +AC_SUBST(PERLV_PATH) + +AC_PATH_PROG(EXPECT_PATH,expect,no) +if test $EXPECT_PATH = no; then + AC_MSG_ERROR([can't locate expect.]) +fi +AC_SUBST(EXPECT_PATH) + +# RD_BIN_DATAS are bin/ .in's that need to be installed without execute +# perms. +RD_BIN_DATAS="" +AC_SUBST(RD_BIN_DATAS) +rd_cv_rd_bin_datas=$RD_BIN_DATAS + +# RD_BIN_PROGS are bin/ .in's that need to be installed with execute perms. +RD_BIN_PROGS="cat5rancid control_rancid \ +clogin create_cvs do-diffs elogin erancid \ +flogin francid jlogin jrancid par rancid-fe \ +rancid rename rrancid" +AC_SUBST(RD_BIN_PROGS) +rd_cv_rd_bin_progs=$RD_BIN_PROGS + +# RD_BIN_PROGS are util/ .in's that need to be installed with execute perms. +RD_UTIL_PROGS="rtrfilter" +AC_SUBST(RD_UTIL_PROGS) +rd_cv_rd_util_progs=$RD_UTIL_PROGS + +AC_SUBST(INST_PROGS) +INST_PROGS=$progs + + +AC_OUTPUT(Makefile) + +# fix permissions on scripts. +for file in $progs; do chmod a+x $file; done diff --git a/install-sh b/install-sh new file mode 100755 index 0000000..89fc9b0 --- /dev/null +++ b/install-sh @@ -0,0 +1,238 @@ +#! /bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. +# + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +tranformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/missing b/missing new file mode 100755 index 0000000..7789652 --- /dev/null +++ b/missing @@ -0,0 +1,190 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. +# Copyright (C) 1996, 1997 Free Software Foundation, Inc. +# Franc,ois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +case "$1" in + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + yacc create \`y.tab.[ch]', if possible, from existing .[ch]" + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing - GNU libit 0.0" + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + + aclocal) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acinclude.m4' or \`configure.in'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`configure.in'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acconfig.h' or \`configure.in'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' configure.in` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case "$f" in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if [ ! -f y.tab.h ]; then + echo >y.tab.h + fi + if [ ! -f y.tab.c ]; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if [ ! -f lex.yy.c ]; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + makeinfo) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` + fi + touch $file + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and you do not seem to have it handy on your + system. You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequirements for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 diff --git a/mkinstalldirs b/mkinstalldirs new file mode 100755 index 0000000..78724ba --- /dev/null +++ b/mkinstalldirs @@ -0,0 +1,40 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman +# Created: 1993-05-16 +# Public domain + +# $Id: mkinstalldirs,v 1.1 2000/10/03 03:52:43 heas Exp $ + +errstatus=0 + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case "$pathcomp" in + -* ) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# mkinstalldirs ends here diff --git a/util/Makefile.in b/util/Makefile.in new file mode 100644 index 0000000..bf41c54 --- /dev/null +++ b/util/Makefile.in @@ -0,0 +1,30 @@ +PREFIX = @prefix@ + +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ + +UTIL_PROGS = @RD_UTIL_PROGS@ + +all: + +install: all + for file in $(UTIL_PROGS) ; do \ + $(INSTALL) $$file $(PREFIX)/util; \ + done; \ + for file in *README* ; do \ + $(INSTALL_DATA) $$file $(PREFIX)/util; \ + done + +clean: + rm -f Makefile $(UTIL_PROGS) + +distclean: clean + rm -f config.log config.status + +distdir: + for file in Makefile.in configure.in *README* ; do \ + $(INSTALL_DATA) $$file $(distdir); \ + done; \ + for file in configure $(UTIL_PROGS:=.in) ; do \ + $(INSTALL) $$file $(distdir); \ + done diff --git a/util/configure b/util/configure new file mode 100755 index 0000000..598f74f --- /dev/null +++ b/util/configure @@ -0,0 +1,885 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.13 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_default_prefix=/usr/local/rancid + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.13" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file= + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + + + +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:560: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + + +RD_UTIL_PROGS=$rd_cv_rd_util_progs + + +PERLV_PATH=$ac_cv_path_PERLV_PATH + +EXPECT_PATH=$ac_cv_path_EXPECT_PATH + + +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +cat > conftest.defs <<\EOF +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g +s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g +s%\[%\\&%g +s%\]%\\&%g +s%\$%$$%g +EOF +DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '` +rm -f conftest.defs + + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.13" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "Makefile $RD_UTIL_PROGS" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@FFLAGS@%$FFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@RD_UTIL_PROGS@%$RD_UTIL_PROGS%g +s%@PERLV_PATH@%$PERLV_PATH%g +s%@EXPECT_PATH@%$EXPECT_PATH%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + + +# fix permissions on scripts. +for file in $RD_UTIL_PROGS; do chmod a+x $file; done diff --git a/util/configure.in b/util/configure.in new file mode 100644 index 0000000..4861771 --- /dev/null +++ b/util/configure.in @@ -0,0 +1,21 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT() + +dnl default install location +AC_PREFIX_DEFAULT(/usr/local/rancid) + +dnl install program(s) +AC_PROG_INSTALL + +RD_UTIL_PROGS=$rd_cv_rd_util_progs +AC_SUBST(RD_UTIL_PROGS) + +PERLV_PATH=$ac_cv_path_PERLV_PATH +AC_SUBST(PERLV_PATH) +EXPECT_PATH=$ac_cv_path_EXPECT_PATH +AC_SUBST(EXPECT_PATH) + +AC_OUTPUT(Makefile $RD_UTIL_PROGS) + +# fix permissions on scripts. +for file in $RD_UTIL_PROGS; do chmod a+x $file; done diff --git a/util/rtrfilter b/util/rtrfilter deleted file mode 100755 index d57f565..0000000 --- a/util/rtrfilter +++ /dev/null @@ -1,145 +0,0 @@ -#!/usr/local/bin/perl -## -# rtrtfilter - "| rtrfilter -x -i -f \ -# -u -s " -# expects to read an email message on stdin containing a diff from -# rancid and emails a filtered copy to with the subject of the -# original msg or the contents of -s . the perl regex(es) specified -# via -x or -i (exclusive and inclusive, respectively) are applied to the -# router names (ie: files) from the "Index:" of the diff o/p. alternatively, -# the regex's may be specified in -f in the form: -# # comment -# x -# # comment -# i -# do not include /'s in the regex's. -# eg: -# #i inc1 -# i a0[12]\. -# i a0[34]\. -# # comment -# x router\.db -# x ^r0[0-9] -# #i foo -# -# exclusion takes precedence and defaults to nothing. inclusion defaults to -# everything. -# -# this program require the Mail::Mailer module which can be found on CPAN. -## -BEGIN { -$me = $0; -$me =~ s/.*\/(\S+)$/$1/; -} - -require 'newgetopt.pl'; -use Mail::Mailer; - -# process command line options -$newgetopt'ignorecase=0; -$newgetopt'autoabbrev=1; -$result = &NGetOpt('h','x=s@','i=s@','f=s','s=s'); -&usage($result) if (defined($opt_h) || $result == 0); - -if ($#ARGV < 0) { - usage; -} -my($rcpts) = join(',', @ARGV); - -# if specified, read the regex file and append to @opt_i / @opt_x -if (defined($opt_f)) { - open(FILE, "< $opt_f") || die "Cant open the regex file $opt_f: $!"; - - while () { - next if (! /^(i|x)\s+(.*$)/); - #/(i|x)\s+(.*)$/; - if ($1 eq "i" ) { - push(@opt_i, $2); - } else { - push(@opt_x, $2); - } - } - close(FILE); -} - -# read the header, grok the subject line -my($subject, $from); -while () { - last if (/^$/); - if (s/^from: //i) { - chomp; - $from = $_; - } - if (s/^subject: //i) { - chomp; - $subject = $_; - } -} -if (defined($opt_s)) { $subject = $opt_s;} -if (defined($opt_u)) { $from = $opt_u;} - -# filter the remainder of the mail. save mail in memory to avoid empty msgs -my(@mail); -my($skip) = 1; -while () { - # look for /^Index: ", the filtering key - if (/^Index: (.*)$/) { - # strip the directory before passing to filter() - my($line) = ($1 =~ /.*\/([^\/\s]*)$/); - $skip = filter($line); - } - - next if ($skip); - - push(@mail, $_); -} - -# send mail, if any -if ($#mail < 0) { exit; } -$mailer = new Mail::Mailer 'sendmail', ('-t'); -$headers{From} = $from; -$headers{"Reply-To"} = $from; -$headers{"Errors-To"} = $from; -$headers{Subject} = $subject; -$headers{To} = $rcpts; -$headers{Precedence} = "bulk"; - -$mailer->open(\%headers); -print $mailer @mail; -$mailer->close; - -exit; - -# filter $line inclusive/exclusive (0 / 1) -sub filter { - my($line) = shift; - - # exclusion - if (defined(@opt_x)) { - foreach $regex (@opt_x) { - if ($line =~ /$regex/) { return(1); } - } - } - - # inclusion / default inclusion - if (! @opt_i) { return(0); } - foreach $regex (@opt_i) { - if ($line =~ /$regex/) { return(0); } - } - - # inclusion regex specified, but fall through - return(1); -} - -sub usage { - print STDERR <] [-x ] [-f ] [-u [-s ] [ ...] - -h prints this message - -f file containing perl regex matching router names (mind the cwd()) - -i perl regex matching router names (inclusive) - -u From: address - -s mail subject - -x perl regex matching router names (exclusive) -USAGE - exit $_; -} diff --git a/util/rtrfilter.README b/util/rtrfilter.README index 51ca6e9..bc98c4e 100644 --- a/util/rtrfilter.README +++ b/util/rtrfilter.README @@ -1,4 +1,4 @@ -rtrfilter can be user to filter rancid diffs to avoid sending unwanted +rtrfilter can be used to filter rancid diffs to avoid sending unwanted diffs to certain recipient(s) or diffs which those recipient(s) should not see without the need to create a separate group(s). diff --git a/util/rtrfilter.in b/util/rtrfilter.in new file mode 100755 index 0000000..d1fa45f --- /dev/null +++ b/util/rtrfilter.in @@ -0,0 +1,145 @@ +#!@PERLV_PATH@ +## +# rtrtfilter - "| rtrfilter -x -i -f \ +# -u -s " +# expects to read an email message on stdin containing a diff from +# rancid and emails a filtered copy to with the subject of the +# original msg or the contents of -s . the perl regex(es) specified +# via -x or -i (exclusive and inclusive, respectively) are applied to the +# router names (ie: files) from the "Index:" of the diff o/p. alternatively, +# the regex's may be specified in -f in the form: +# # comment +# x +# # comment +# i +# do not include /'s in the regex's. +# eg: +# #i inc1 +# i a0[12]\. +# i a0[34]\. +# # comment +# x router\.db +# x ^r0[0-9] +# #i foo +# +# exclusion takes precedence and defaults to nothing. inclusion defaults to +# everything. +# +# this program require the Mail::Mailer module which can be found on CPAN. +## +BEGIN { +$me = $0; +$me =~ s/.*\/(\S+)$/$1/; +} + +require 'newgetopt.pl'; +use Mail::Mailer; + +# process command line options +$newgetopt'ignorecase=0; +$newgetopt'autoabbrev=1; +$result = &NGetOpt('h','x=s@','i=s@','f=s','s=s'); +&usage($result) if (defined($opt_h) || $result == 0); + +if ($#ARGV < 0) { + usage; +} +my($rcpts) = join(',', @ARGV); + +# if specified, read the regex file and append to @opt_i / @opt_x +if (defined($opt_f)) { + open(FILE, "< $opt_f") || die "Cant open the regex file $opt_f: $!"; + + while () { + next if (! /^(i|x)\s+(.*$)/); + #/(i|x)\s+(.*)$/; + if ($1 eq "i" ) { + push(@opt_i, $2); + } else { + push(@opt_x, $2); + } + } + close(FILE); +} + +# read the header, grok the subject line +my($subject, $from); +while () { + last if (/^$/); + if (s/^from: //i) { + chomp; + $from = $_; + } + if (s/^subject: //i) { + chomp; + $subject = $_; + } +} +if (defined($opt_s)) { $subject = $opt_s;} +if (defined($opt_u)) { $from = $opt_u;} + +# filter the remainder of the mail. save mail in memory to avoid empty msgs +my(@mail); +my($skip) = 1; +while () { + # look for /^Index: ", the filtering key + if (/^Index: (.*)$/) { + # strip the directory before passing to filter() + my($line) = ($1 =~ /.*\/([^\/\s]*)$/); + $skip = filter($line); + } + + next if ($skip); + + push(@mail, $_); +} + +# send mail, if any +if ($#mail < 0) { exit; } +$mailer = new Mail::Mailer 'sendmail', ('-t'); +$headers{From} = $from; +$headers{"Reply-To"} = $from; +$headers{"Errors-To"} = $from; +$headers{Subject} = $subject; +$headers{To} = $rcpts; +$headers{Precedence} = "bulk"; + +$mailer->open(\%headers); +print $mailer @mail; +$mailer->close; + +exit; + +# filter $line inclusive/exclusive (0 / 1) +sub filter { + my($line) = shift; + + # exclusion + if (defined(@opt_x)) { + foreach $regex (@opt_x) { + if ($line =~ /$regex/) { return(1); } + } + } + + # inclusion / default inclusion + if (! @opt_i) { return(0); } + foreach $regex (@opt_i) { + if ($line =~ /$regex/) { return(0); } + } + + # inclusion regex specified, but fall through + return(1); +} + +sub usage { + print STDERR <] [-x ] [-f ] [-u [-s ] [ ...] + -h prints this message + -f file containing perl regex matching router names (mind the cwd()) + -i perl regex matching router names (inclusive) + -u From: address + -s mail subject + -x perl regex matching router names (exclusive) +USAGE + exit $_; +} -- cgit