mrtg-2.17.10/THANKS0000644000175300017510000000103113057016060012552 0ustar oetikeroepMRTG as it is distributed contains several perl modules created by other people. The Plain Perl SNMP Code from Simon Leinen SNMP_Session.pm BER.pm --> http://www.switch.ch/misc/leinen/snmp/perl/ The SNMP Utilities module from Mike Mitchell SNMP_util.pm --> this is distributed together with SNMP_Session.pm The PodParser Module from Brad Appleton Pod/*.pm --> CPAN/modules/by-module/Pod/BRADAPP/ (Included with perl 5.6) Thanks very much tobi mrtg-2.17.10/CHANGES0000644000175300017510000034004614171763260012657 0ustar oetikeroepChanges 2.17.10, 2022-01-19 --------------------------- From: tobi * add missing mrtglib.3 to release archive Changes 2.17.9, 2022-01-18 -------------------------- From: tobi * add pid to lockfile and check if the pid is still running when trying to lock remove the stale lockfile otherwhise ... * add bootstrap * github/CODEOWNERS * add new author in manpage for rateup * cleanup manifest, drop makefile, improve bootstrap From: David Bristel * add contrib/mrtg-ipacc From: gpancot * add mikrotik vendor to cfgmaker From: Andrey Tarasov * add Huawei and Eltex vendors to cfgmaker From: youpong * remove unused variables from rateup.c * stop ignoring return value of function fgets * fix signedness of time_t * fix left shift of negative value From: Hilko Bengen * avoid to include global options by default From: Joao Eriberto Mota Filho * add absent mrtg-startup-script and remove extra blank spaces from contrib/00INDEX * add example of systemd and init scripts from Debian (contrib/debian-systemd/) * add examples for WorkDir in Linux in cfgmaker * add a trivial CI test for GitHub * add manpage for rateup * create directories /run/mrtg/, /var/lib/mrtg/, /var/lock/mrtg/ and /var/log/mrtg/ automatically if they not exist when using --fhs option * fix a warning about datarootdir in Makefile.in * fix some spelling errors in manuals and executables * fix some uncommented lines breaking contrib/accesslistmon/examplescript * fix translation files for some languages (Brazilian, Catalan, French, German, Portuguese and Spanish) * fix whatis in manpage mrtg-squid.pod * modernize configure.in, removing warnings * remove an orphan symlink (mrtg-mailer.pod) * remove files generated by the build process and forgotten when cleaning * remove non-free files in contrib/ (nt-service and cisco_tftp) * remove some extra blank spaces in EOL in changelog * rename mrtglib.1 to mrtglib.3 * update GPL-2 text in src/contrib/TTrafic to break very long lines and fix a wrong address for FSF * update src/bin/mrtg and its manpage to use FHS version 3.0 in --fhs option From: Leo Iannacone * make ifref default to name to cfgmaker From: Michael-John Turner * fix wrong line break that stop the execution in contrib/iptables-accounting From: Ray Smith * add new contrib: exim-stats From: Ryan Murray * fix a comment error causing doesn't chdir to workdir in src/contrib/mrtgindex.cgi/mrtgindx.cgi From: Theodore Alexandrov * use gawk because mawk doesn't have strftime Changes 2.17.8, 2021-08-05 -------------------------- From: Martin Sechny, shenk.sk * add missing optional textcolor property in mrtg.cfg * automatic value for textcolor (if null) with good contrast for every Background property value (default black text on white background) From: renatocfrancisco * update README.md From: vcrhonek * fix mrtg-traffic-sum incorrectly ignores '--man' option From: leoreginin * add support for Alcatel and Datacom to cfgmaker From: cheese1 * small typo Changes 2.17.7, 2018-07-12 -------------------------- From: Martin Sechny, shenk.sk * update to HTML 5 template in bin/mrtg, checked by HTML+CSS W3C validator * corrected style in HTML template: color with background-color (workaround for missing text color property in mrtg.cfg) Changes 2.17.6, 2014-12-02 -------------------------- From: tobi * add --descr=ifname option to indexmaker * fix parsing of global option in cfgmaker * add dcn id to cfgmaker (baed on input from Pawel Golaszeswski) From: Steve Alligood * make sure threshval does not get clobberd Changes 2.17.5, 2012-04-26 -------------------------- From: Pavel Gulchouck * fix for kmg option coredump Changes 2.17.4, 2012-01-12 -------------------------- From: tobi * some address fixes to contrib * fixed duplicate install-sh entry in archive Changes 2.17.3, 2011-12-01 -------------------------- From: tobi * set oid-mib-cache file for New_SNMP_util as well #106 From: rihad * prevent spurious warnings about unknonwn values of inlast outlast in mrtg From: tobi * add the process id tmp file extensions, to guard against multiple rateup instances messing things up for each other. (attempt to fix #115) * quell warning in CnTWaLK mode #111 From: morph@debian.org * spelling fixes From: tobi * make threshold checking more robust against incomplete information in the config file #113 From: trac * support ifAlias for Vyatta gear From: Dannys * CnTWaLK should add the count and not max index From: Tobi * abort indexmaker if there is no data to be found From: Ryan * fix for big5 translation From: Tobi * in cfgmaker use ifdesc=alias only if there is actualy alias info From: Vitezslav Crhonek vcrhonek redhat.com * fix of a file pointer leak found by coverity scan * fix for kMG support in rateup From: Adrian Minta * add support for zyxel ifAlias From: #110 * add support for Matrix N7 Diamond From: Tobi * enable warnings in cfgmaker and fix issues ... * explicitly import SOCK_DGRAM and AF_UNSPEC to make ipv6 support work From: Mike Mitchell * Updated Net_SNMP_util.pm and SNMP_util.pm to latest versions Changes 2.17.2, 2011-02-20 -------------------------- From: Tobi * can not replace a file by renaming another to its name under WIN32 fix in rateup #104 From: Tobi Changes 2.17.1, 2011-02-18 -------------------------- From: Tobi * Fix scaling when noo and noi options are used. fix for #95 * Stop staticly linking rateup. fix for #97 * Only set LD_RUN_PATH if it is actually necessary. patch from #98 * Net::SNMP only support aes128, des and 3des ... fix for cfgmaker from #99 * Understand desc and descr in ifdesc option of cfgmaker * only set $args{'-maxrepetitions'} if $Net_SNMP_util::MaxRepetitions > 0 * do not load Net_SNMP_util unless snmpv3 is requested ... fix for #75 * be more agressive about updating the confcache. If a key is missing, go looking for it again and complain. fix for #74 * only apply 32bit counter wrap compensation when the wrap is within 32bit range. fix for #70 * implement pngdate as TimeStrPos[x]: RU instead of separately. for for #68 * add missing

tag arount 'last updated ... ' in html output. fix for #63 * remove rececondition when writing new trafic graph files by writing to a temp file and moving it later. fix for #51 * make snmpopt_current available in cfgmaker templates. fix for #48 * explicitly import Socket6 routines in SNMP_Session. fix for #45 * default ThreshHyst to 0.1 only if ThreshDir is define. fix for #42 * point out when there is an unknown interface found. fix for #41. * allow for $speed to return 0 and still use SNMPv2 ... some Cisco Gear seems todo that. Fix for #33 * add dlink support for ifAlias OIDs to cfgmaker from #50 * add WWP (Ciena) support for ifAlias OIDs to cfgmaker from #66 From: Chris Chiappa * Updated squid docu #80 From: redrat at mail.ru * Fix russian translation bug #92 Changes 2.17.0, 2010-12-15 -------------------------- From: Steve Shipway s.shipway auckland.ac.nz * added rrdcached support - new keyword: RRDCached: which overrides anything set in the RRDCACHED_ADDRESS environment variable and sets MRTG to work in RRDCached mode. This verifies that you're using a unix-domain socket and the socket is writeable. - Check for environment variable RRDCACHED_ADDRESS and use this if no explicit address was set in the cfg file, making the same config validity checks. - Make warning if using rrdcached to the effect that the thresholding checks will no longer work. - If in rrdcached-mode, and using RRDTool 1.4, then force use of update rather than updatev (as rrdcached does not yet support updatev) and consequently bypass the thresholding checks. - Changes to validity check error messages to also report the file containing the error (as well as the line). * Added support for glob patterns in include * Make daemon reload cfg automatically when it changes From: john.belshaw cggveritas.com * added support for Arista to cfgmaker From: duncan_j_ferguson at yahoo.co.uk * fix cfgmaker to work in mixed v1/2/3 snmp environment From: Stuart Henderson stu spacehopper.org * do not strigify arguments to conversion function let eval take care of this * untaint inlast and outlast to make perl taint mode happy * teach cfgmaker about openbsd Changes 2.16.4, 2010-05-17 -------------------------- From: Tobi * fix "P_DETACH" and Pod::Usage issues with perl 5.12 From: James Golovich * relax cfgmaker option parsing when figuring whether to test for highspeed counters or not. From: Stephen Satchell * fix sorting of numbered interface names index maker From: Hleb Valoshka * belarusian translation for mrtg 2.16 Changes 2.16.3, 2010-01-20 -------------------------- From: chris.merrett melbourne.co.uk * three new config options to compliment the existing RRDRowCount option to explicitly set the size of all RRAs From: Leonardo Reginin leonardo procergs.rs.gov.br * allow to rename target in the clonedirectory option * add import to the require File::Copy Steve Shipway s.shipway auckland.ac.nz * support multiple options in ifdesc and ifref setting for cfgmaker Carlos Fuentes Bermejo carlos.fuentes rediris.es * teach cfgmaker about nortel switches Pavel Gulchouck gul gul.kiev.ua * make sure rates over 4G work too From: Oliver Lehmann oliver FreeBSD.org * allow group and user option to be set to root Changes 2.16.2, 2008-05-16 -------------------------- From: Steven Bakker steven.bakker ams-ix.net * globally disable __DIE__ handler in eval using $^S check * updated to SNMP_Session 1.12 From: Tobi * make SNMP_Session.pm work on windows even when a __DIE__ handler ist installed. Changes 2.16.1, 2008-02-17 -------------------------- From: Tobi * fix RouterUptime config with non unique targets Changes 2.16.0, 2008-02-06 -------------------------- From: Fernando Nieto fnieto satec.es * Makesure mrtg repopulates its cache only once even in fork mode From: Tobi * Added support for RRDtool based Holt-Winters aberrant behaviour detection. Threshold based alerts have been enhanced to be able to fire based on the FAILURES RRA. Note that Holt-Winters aberrant behaviour detection can only be enabled on newly created RRAs. From: Sergio Chiesa sergio.chiesa eutelia.it * when thresholds were UNboraken, the threshprogok did not run necessarily From: Mike Mitchell Mike.Mitchell sas.com * MIB parser rewritten for better compatibility From: Norman Rasmussen norman rasmussen.co.za * allow RouterUptime to contain an explicit OID for queriing the uptime. From Ajit Mallick ajitmallick gmail com * support for nortel passport 8600 in cfgmaker From Dan.McDonald * Added Documentation for GeTNEXT prefix * Added New Prefix for Counterd SNMP Walk -> CnTWaLK (see docs) From: Simon Leinen * Upgrade to SNMP Session 1.10 From: Mike Mitchel * Updates for Net_SNMP_util.pm and SNMP_util.pm From: Tobi * Fix if_is_ciscovlan condition in cfgmaker * Updated port syntax in documentation (based on trac entry) Changes 2.15.2, 2007-04-29 -------------------------- From: Tobi * Improve parsing reliability of indexmaker * Fixed deadhost detection in mrtg From: Dan.McDonald austinenergy.com * added config option noHC for boxes that don't have HC counters but run SNMPv2/v3 From: Mike Mitchell Mike.Mitchell sas.com * Updated Net_SNMP_util module (error messages) From: G�nter Knauf * Updated Makefiles for Win32 and Netware * New Netware version of rateup.nlm Changes 2.15.1, 2007-02-01 -------------------------- From: Gosselin, Gerry GGosselin onecommunications.com * make cfgmaker detect broken snmpv1 counters more reliably From: Mike Mitchell * latest Net_SNMP_util.pm with many small fixes From: Dan.McDonald austinenergy.com * more cfgmaker smarts and documentation for snmpv3 From: Tobi * be happy even if no threshmail sending is configured * add install target for traffic-summer * fix mrtg-traffic-sum default catch expression to be in sync with docs Changes 2.15.0, 2006-12-05 -------------------------- From: Stefan.Schnitter t-systems.com * Free positioning of a generated ifIndex in the OID string using the magic IndexPOS keyword From: Tobi * When doing threshold checking with rrdtool, there was a very expensive 'getting the data back with rrdinfo and rrdfetch' cycle after each rrdupdate. with rrdtool 1.2 and the updatev function this is not necessary anymore the new code speeds up mrtg cycle time by a factor of 3 to 10 depending on your platform. * Threshold Un-Borken Messages will only be generated when the value is 10% away from the threshold. Configurable via ThreshHyst * New function thresholdmail lets you send an email when a threshold is broken. This feature talks directly to the mailserver and does not require any external programs. * New template writers helper function in cfgmaker - oid_pick. It tests if a device is willing to supply information regarding a particular oid. This makes template writing much more pleasant. http://oss.oetiker.ch/mrtg-trac/browser/trunk/templates/cisco/host-cisco.tmpl * added new tool mrtg-traffic-sum to build traffic stats based on the content of your mrtg log (not rrd) files. * mrtg running with rrdtool can now do sub-minute resolution if the interval is specified like that: 0:30 ... note that you can not change the resolution of an existing rrd file. So this will only have the desired effect on new rrds. Also note that the graphing frontend may need changes too to be able to deal with the new interval type. Internally interval is now a float! * new debug option 'prof' to see how long rrdtool spends on its writes ... From: Daniel J McDonald dan.mcdonald austinenergy.com * fixed snmpv3 support in cfgmaker Changes 2.14.7, 2006-09-06 -------------------------- From: Tobi * removed extra spaces from Makefile.in Changes 2.14.6, 2006-09-06 -------------------------- From: Tobi * timestamps in log files to be YYYY-MM-DD HH:MM:SS * fixed rateup to propely support kMG option * fixed problem with conversioncode option throwing an exception. * fixed config parsing problem for libadd lines terminated by a \ * added 'eval' debug target * updated local $SIG{__DIE__} locations to work as intended From: Akihiro Sagawa sagawa sohgoh.net * fix ifspeed for foundry switches in cfgmaker From: Russ Price gpg fubegra.net * Added expscale option (opposite of logscale) to emphasize the top end of the scale; this improves display of line voltages that don't change a whole lot From: Stefan stefan sf-net.com * added sample startup script for mrtg Changes 2.14.5, 2006-07-14 -------------------------- From: Tobi * allow - in oid name * make sure __DIE__ does not get triggered in eval sections Changes 2.14.4, 2006-07-04 -------------------------- From: Pierfrancesco Caci p.caci seabone.net * cfgmaker should know that IOS-XR version 3.x is newer that IOS 11.x From: Tobi * make install should build rateup ... * indexmaker with --prehost should act sensible even with targets that have no host * remove extra \n from cfgmaker output in pagetop section * cfgmaker, escape " in SetEnv MRTG_INT_DESCR output * allow ifalias for 3com gear Changes 2.14.3, 2006-05-05 -------------------------- From: Tobi * fix regression in indexmaker due to --check fix Changes 2.14.2, 2006-05-03 -------------------------- From: Mike Mitchell * updated SNMP_util.pm and Net_SNMP_util.pm From: Tobi * do not create directories in --check mode Changes 2.14.1, 2006-05-03 -------------------------- From: Peter W. Osel pwo qimonda.com * remove superfluous ^M from rateup.c Changes 2.14.0, 2006-05-02 -------------------------- From: tobi * only enable snmpv3 in cfgmaker if it is explicitly specified on the cli. * we live in a new home now ... oss.oetiker.ch/mrtg * fix makefile to work for the install target again * remove remaining html references From: jpturchi at mageos dot com * timestamp all error and warning messages of mrtg From: Pawe? Go?aszewski * teach cfgmaker about unrouted vlans From: Leonardo Reginin * new: clonedirectory function From: Miloslav Trmac * explicit cast in char conversion (minus one warning) for rateup.c From: Simon Leinen * Updated SNMP_Session to 1.08 From: Guenter Knauf * Small fixes for libgd in Makefile.Win32 and Makefile.Netware Changes 2.13.2, 2006-02-03 -------------------------- From: Tobi * cfgmaker and if-templates should work again Changes 2.13.1, 2006-01-24 -------------------------- From: Tobi * fix routeruptime config paramter * fix spelling and presentation in the documentation * added rateup.nlm back to the distribution Changes 2.13.0, 2006-01-23 -------------------------- From: Tobi * make sure rateup properly handles unscaled graphs even when the bits option is active ... * place if-filter later in the cfgmaker code so that it can see ALL the template variables. * New magic OID prefix WaLK and GeTNEXT to cause mrtg to use snmpwalk for certain variables and keep the first value it finds. (sponsored by srg.com.bs) * use short image paths in if images and HTML are in the same directory. * fix threshold checking with rrdtool for logging From: Michel * allow kMG to be set to '' From: Juergen Obermann * improved german translation From: Jerzy Sobczyk * make indexmaker work properly in rrdtool mode with images turned off From: Yusaku Nakajima * remove unconditional warning from windows code From: "Dean, Mike" * have some sensibility in return codes from mrtg ... From: NormW * point to favicon from indexmaker From: Fuminori Uematsu * improved japanese translation From: NormW * look for rateup.nlm if running on netware From: Mike Tkatchouk * --log-only option for mrtg script to not update the graphics. From: Daniel J McDonald (with help from Mike Mitchell) * SNMP v3 support added Net::SNMP library required for this From: Guenter Knauf * Updates for NEtWare and Win32 Makefiles From: Mike Tkatchouk * new option --update-only will not produce graphs or crete webpages ... From: Karl M. Ramberg * fix regexmatches in indexmaker From: Stefan Loidl * teach cfgmaker about hp gear * make 10Gig interface detection work Changes 2.12.2, 2005-06-19 -------------------------- From: Fabian Uebersax * fix portname math in indexmaker From: Andrej Ota * accept extreme networks switches for ifAlias in cfgmaker From: Jeff Woolsey * set unknown values to 0 for threshold checking if unknonwnaszero is set From: NormW * updated NetWare integration Changes 2.12.1, 2005-05-16 -------------------------- From: tobi * max maxbytes work again (rateup.c) From: Jeremy Chadwick * css fix ... do not specify the graph size this is flexible From: Peter W. Osel * fix background color setting in new css code Changes 2.12.0, 2005-05-15 -------------------------- From: Benjamin Gufler * make mrtg produce propper xhtml output From: tobi * do not maintain separate confcache entries for different timeout settings * make mrtg work with rrdtool 1.2 (note that this does not mean that you graphing frontend will necesarily work with rrdtool 1.2.x too) * Fix location of maxbytes line in log scale mode * do not die when encountering a bad rrd ... only warn * stop mrtg from popping up windows whenever rateup runs by using the Win32::SetChildShowWindow(0); From: Erek Dyskant * give derive precendence when when setting the update mode. From: Miloslav Trmac * call tzset when running on unix after setting TZ to cater for multithreaded perl From: "Bruijn de, Pascal" * added make CatOS if names available in cfgmaker ifdesc From: Jeremy J. Smith * DOCTYPE must be before any comment ... From: Steve Bonds <388rzvl02 alpha sneakemail.com> * added --zero-speed option to cfgmaker to deal with broken snmp From: "Poetzel, Christopher J." * Force10 ifAlias support for cfgmaker From: Nick Ellson * teach cfgmaker about Cisco PIX Firewall Switch Modules From: NormW * updated NetWare integration Changes 2.11.1, 2005-01-05 -------------------------- From: Artyom Adjemov * new Windows docu ... running mrtg as an nt service with srvany. From: Joe Pruett * fixed snmp options parsing in MRTG_lib.pm to allow for ! From: Tobi * fixed secondmean and logscale to actually issue the propper options for rateup. * fixed compilation of rateup.exe for windows to get the new strftime function to be actually used ... Changes 2.11.00, 2004-12-08 --------------------------- From: Al Payne * integrated support for dellLan in cfgmaker * reindented cfgmaker From: Mike Nealon and Larry Fahnoe * fix cfgmaker handling of 'lowspeed' highSpeed interfaces From: Tobi Oetiker * reindent rateup.c * remove @ signs from mail addresses in change log * added if_MTU variable to cfgmaker * make windows users happy. rateup.exe now uses a special strftime.c that knows about %V and will thus provided propper ISO week numbers for windows as well. Changed the default week format to V. From: zurkabsd location yahoo.com.cn * new chinese translation From: Jaime Damiao Anjos Cadete * put -lm into LIBS to make sure it comes last From: Ian Duplisse * remove the flattening of peaks from the code in rateup.c this does not reflect what actually happens From: John Van Essen * fix handling of unknonwn (-1) data in rateup ... From: Benjamin Despres * Logscale and Secondmean logarithmic scaling for rateup From: alex * contributed mrtg message dll. Added note about it to mrtg-reference.pod From: Mateusz * support option derive is using rrdtool logging From: Ulf H�rnhammar * prevent potential buffer overflow in ratup due to 'strange' input files Changes 2.10.15, 2004-08-08 --------------------------- From: NormW * patches for netware support From: Tobi * the optional Conversion function wants to have the original data pulled in via snmp to work with, mapping \n and \r to nothing and stripping spaces must happen later. * better error message for missing library * Updated to snmp_session 1.05 From: Fuminori -Tany- Tanizaki * fix for cuin and cout values saved in html comments From: Tom Pala * fix for polish translation From: Georgi Georgiev * nodetach option for running mrtg under daemontools From: Jozsef Szilagyi * fixed indexmaker. added missing last for --section=portname code From: Bartosz Kwitniewski * fixed scaling bug in rateup (unsigned long) should have been long long From: Mike Mitchell * fix indexmaker when used with 14all Changes 2.10.14 --------------- From: Michael P. Soulier * new option subtitle for indexmaker From: Lech Szychowski * added new options for printing date inside the graph: TimeStrPos[] and TimeStrFmt[] From: Joshua Nichols * teach Makefile about DESTDIR From: Tobi * do not try to populate the confcache off a dead hosts ... From: Norm * make mrtg work on netware From: Fuminori Uematsu * updated japanese translation From: Ladislav Mihok * fixed encoding for slovak translation From: Hal Dell * added 3com RMON VLAN detection to cfgmaker From: Michael_Soulier location Mitel.com * added --headeradd option to indexmaker From: Simon Leinen * updated SMNP_Session to 1.03 From: Quentin Dunchue * added host anchor in indexmaker * fixed $default filter in cfgmaker to not include everything From: ���F�� * updates for chinese big5 translation From: Klaus Schmidinger * fix for ytics with small values in rateup From: "Peter Wirdemo (MO/EMW)" * enhance cfgmaker for extremenetworks From: Tobi and Bernd Drefs * fix hairy issue with description matching in indexmaker (add quoting) From: Kenji * make thresholds work when maxbytes1 and maxbytes2 are in use ... Changes 2.10.13 --------------- From: Pedro Marcolino * fixed undef data problem with forks * add --icondir option to indexmaker From: Tobi * faild rrdtune should not kill mrtg complaining is enough. * fixed manpages first lines to include mrtg as well Changes 2.10.12 --------------- From: Nico Kadel-Garcia * Makefile should not complain when running clean on a clean setup * It's community not comunity. From: Luc Pauwels and Simon Leinen * 16-Bit SNMP Session ID support for cfgmaker and SNMP_Session From: Tobi * renamed all doc pages to mrtg-* except the manpages for cfgmaker and indexmaker * added MaxAge option setting which will prevent mrtg from touching old logfiles, potentially caused by setting the clock to a wrong date. * fixed a number of && vs and and || vs or problems in the mrtg script and library Changes 2.10.11 --------------- From: Tobi * put out color allocation back into rateup.c what was I thinking Changes 2.10.10 --------------- From: Tobi * config.h.in was out of sync * removed eout checking after select as the output seems unreliable Changes 2.10.9 -------------- From: Tobi * with forks, do not try to look at filehandles which have been closed From: Albert Chin-A-Young * improved long long check for configure.in Changes 2.10.8 -------------- From: Marc Baudoin * cfgmaker has to know about Foundry virtual Ethernet interfaces From: Tobi * %lf was bad ... go back to %f this should portable Changes 2.10.7 -------------- From: Don Russell * fixed READPID in MRTG_lib.pm * added commandline as meta tag in indexmaker output From: Tobi * for running on old perls ... we need %Lf not %lf for sprintf. Changes 2.10.6 -------------- From: Dave Plonka * modified fork code to use select to determine if data is ready to be read From: Philipp Capoy * teach cfgmaker about Nokia IPSO From: Richard Bullington-McGuire * pseudo entry for his contributions which somehow got lost from the changes file. Early in 2.0 history (1996) Richard contributed. * Perl code strictification (it now runs with "use strict;") * Makefile for rateup * rateup debugging * Perl code cleanup Sorry for that. From: Klaus Schmidinger * fix rounding error with YTicsFactor in ratuep (nmax_q is double) From: Mike Mitchell * fix for generation of non negative request ids in SNMP_Session.pm From: Alex Samorukov * updated OS/2 portability ...RunAsDaemon works now From: Stephen Heise * fix for lockfile management when two instances run in parallel From: Rafael Martinez Torres * updated docs and snmp_session to be comaptible with INET6-2.00 From: Tobi * fix command line option description in reference and mrtg * Updated to SNMP Session 0.99 * fixed handling of dead host for cases where ip matching is involved * Fixed table structure generated by indexmaker * Change Doctype to HTML 4.01 Transitional, so that font face becomes legal * fix pngtitle alignement for growright option. * Restart after HUP, but terminate for INT and TERM * fix handling of ' ' in community names * make rounding work even without BigFloat * allow BigFloat only in perl 5.8 and later * added new oid hacks ... PseudoOne and PseudoZero ... they return the respective number. * make threshold handling deal gracefuly with missing thershold descript * fixed portability to hpux (setsid) * make sure snmpoptions are passed everywhere * run rateup with unknown values ... as we used to in the good old days. unknown as zero would not make much sense otherwhise Changes 2.10.5 -------------- From: Dmitry Sivachenko * Improved configure to work on *bsd as well Changes 2.10.4 -------------- From: Tobi * More BigFloat portability fixes Changes 2.10.3 -------------- From: Tobi * Can only use BigFloat in perl > 5.6.1 Changes 2.10.2 -------------- From: Tobi * Updated to SNMP_Session 0.98 Changes 2.10.1 -------------- From: Tobi * make snmp_session work with old perls Changes 2.10.0 -------------- From: Simon Leinen * New Version of SNMP Library (0.97) From: Martin Opitz * allow sci notation numbers Changes 2.10.0pre9 ------------------ From: Jon Barber * new configurables: printrouter and pngdate ... check the docs From: Jessica Blackburn * indexmaker: improve handling of multiple cfg file situation with rrdtool logging From: Tobi * allow user and group to be set even when not running as a daemon. From: "Spain, Jeffry A." * use Math::BigFloat objects with 40 digits of precision so that we can handle floats for rrdtool if needs be * detect if a target is a simple target for simplified handling of uptime and router name * propperly handle \& in targets Changes 2.10.0pre8 ------------------ From: Tobi * handle dead hosts propperly by returning 'empty data' and not just the same as in the previous round. fixes the stray update error with rrdtool. From: Eric Einhorn * there are snmp devices which emit bizzar output when their tables get walked in the wrong order. Use a fix walking order now. No more hanging cfgmaker instances. Changes 2.10.0pre7 ------------------ From: Tobi * Oops configure was broken ... Changes 2.10.0pre6 ------------------ From: Tobi * attempt to restart when hitting a die in daemon mode. From: "Spain, Jeffry A." * revamped target parser to weed out duplicat polls * added new 'per target' conversion filter capability Changes 2.10.0pre5 ------------------ From: Tobi * fixed goof in rateup where the wrong long long printf string crept back in Changes 2.10.0pre4 ------------------ From: Alex Samorukov * OS/2 port From: Tobi * Detect 3com VLAN ids * mrtg should not gethostbyname on numberic ipv4 addresses * allow empty variables to be set in SetEnv * make diff routine more conservative in rateup ... * snmpv2 did not poll HC counters anymore ... fixed From: Lorenzo Colitti , * updated docs on ipv6 * portability fixes for perl 5.00502 From: Brian Lube * use $if_snmp_name if $if_title_desc is empty in cfgmaker From: Dmitry Sivachenko * fix to rateup where sizeof(time_t) != sizeof(long) Changes 2.10.0pre3 ------------------ From: Andrew A. Vasilyev * fix for freebsd ... its %qd and not %lld there From: Simon Leinen and Lorenzo Colitti * updates to SNMP_Session From: Gleydson Mazioli da Silva * fixes for brazilian translation Changes 2.10.0pre2 ------------------ From: bill shamam * contributed a favicon From: Lorenzo Colitti , From: Valerio Bontempi , Roma Tre Computer Networks research group * fix for IPv6 support (work with out option settings) * fix IPv6 module detection From: Daniel J McDonald * allow $if_vlan_id in cfgmaker filters From: imacat * make --bindir, --libdir, --mandir, etc work From: Paul Slootman * removes a couple of silly typo's and the capitalization for weekday and month names * fix indexmaker to propperly parse description tags which do not have a white space at the end of the line. Changes 2.10.0pre1 ------------------ From: Lorenzo Colitti , Valerio Bontempi , Roma Tre Computer Networks research group * IPv6 for mrtg From: Ryan Finnie * get router name from a dirfferent oid with Routerneme configurable From: Tobi * cfgmaker now complains about hosts it can not get info from, but does not die. * force all counters to be BigInt * make configure escape to scanf if long long is missing (inspired by marc.elsen location imec.be) From: Clas Mayer * improved swedish translation Changes 2.9.29 -------------- From: Tobi * allow external scripts to return UNKNOWN * fixed SnmpOptions setting * improved skipping of dead hosts (do not confused with 'dead' interfaces) Changes 2.9.28 -------------- From: jackie * fix charset in gb2312 From: Jan Kasprzak * small fix for BER.pm. Sent upstream to Simon too. From: Andreas Plesner Jacobsen * make sure ifdescr does not display doubly exscaped descriptions From: Colin Horsington * foundry ATM subinterfaces always report 0 speed, make it 155Mbps instead. From: Tobi * skip hosts which do not resolve to an IP address * removed --descint option form cfgmaker this did only exist in the docs * added support for config.h and test for __strtoll which will make reatup work on HPUX * make maxbytes2 line reappear * update compile instructions * fix ifref escaping in cfgmaker From: Fernando Nieto * make cfgmaker handle highspeed interface speed better Changes 2.9.27 -------------- From: Gordon Tetlow * allow unsetting of Unscaled, WithPeak, and Suppress From: Barry Rountree * updated compile instructions for new gdlib * various documentation fixes From: David Corlette * a whole set of new mrtg commandline options: "--fhs", --daemon", "--pid-file", "--confcachefile" ... this makes From: MASUDA Takashi * fix for propperly handling 'one unknown' value ... From: Markus Schlup * --check option for mrtg From: Christian Birchinger * --pid-file option for mrtg From: Willem Jaap Zwart * --perhost option for indexmaker From: Dave Habben * fix UTF-8 warning ... From: Moose God * cfgmaker now treats old pre-XL Catalyst 2900 the same as any other non-CiscoIOS Catalyst switch From: Tobi * revisit default_avoid_negative_request_ids now it should be ok * --debug option for mrtg * deal more gracefully with space and other od chars in targets ... * do not die on unknown data returned from external scripts skip router instead * fixed win32 with long long ... MS libc does not understand %lld it need %I64d instead * generate missing mrtg logo images automatically * add check for correct operation of long long %lld and strtoll * fixed daemon code From: Ambrose Li * treat script output ##UNDEF## as this ... From: Norbert Klasen * strings for sys* are too long in cfgmaker use snmpwalk Changes 2.9.26 -------------- From: Andr� Silveira * with thresholds ... have two decimals in % mode * give threshdesc and value as ar 4 and 5 of called threshprog From: Pietro Falessi * propperly ignore signal 127 on UNIX From: Leon Chang * make cfgmaker foundry aware From: "Jones, Derek C." * ds3 (30) and sonet (39) are wan interface types too added them to the $if_is_wan group in cfgmaker From: Tobi * don't give up too quickly if a confcache setup entry does not match ... * make rateup.c (64bit) work on macos x * debug 64bit rateup ... From: Michael C. Haller * drop special MacOS X includes they are harmful on 10.2. Use bsd approach From: Emilio Mena (emilio location satec.es) * use long long in log files to enable logging of FAST links long long = 64 bit integers From: Fernando Nieto * make cfgmaker support ifHighSpeed propperly and teach it about Juniper From: "Davids, Ronald" * make output of cfgmaker such that indexmaker will sort propperly Changes 2.9.25 -------------- * die gracefully when LANG is set to UTF-8 and give advice (RedHat 8) * updated squid monitoring example Changes 2.9.24 -------------- From: Tobi * Fixed indexmaker which got truncated during the last release process Changes 2.9.23 -------------- From: John Papandriopoulos * cosmetic tweaks for layout From: Tobi * Use Snmp Session 0.93 with option avoid_negative_request_ids enabled * Supress Posix Locales in the locale module ... people who have LANG set to UTF-8 report very strange errors otherwhise. * skip all queries to a host for one round when 1 query has returned undef. * skip all trailing space in keys when matching interface by Name, Description, Anything From: Francois Wolmarans * remove
before


near pagetop From: Jeremy Hinton * make Includes search in directory of main config files as well as in current directory From: Quip * addhead option for indexmaker From: hw * fix for uptime for squid and other non standard devices From: Norbert.Klasen location avinci.de * indexmaker: improve handling of urls given with --rrdviewer From: webmaster location kingisme.com * improved chinese translation Changes 2.9.22 -------------- From: Nick Hilliard * fixed pid file handling under unix From: Tobi * removed VERSION for ISA arry in MRTG_lib.pm ... it has no reason to be there, and perl 5.8 complains From: James Overbeck * fixed cfgmaker directory_name for template accessibility From: John Caruso * fix for rateup rounding problems ... Changes 2.9.21 -------------- From: Tobi * finally fixed rrdtool thershold checking ... Changes 2.9.20 -------------- From: Tobi * Only complain about missing data for thresholds if someone actually wanted to check thresholds there ... Changes 2.9.19 -------------- From: Szabo Balazs Zsolt * fix for dynamic graph label ... From: Andrea Rossi * updated italian translation From: Tobi * allow for empty names * when reading cfg files make sure to quit when $_ comes back undef * fix for jpeg+freetype+png compiles * icons get now installed in $(prefix)/share/mrtg2/icons * fixed row count in newly created rrd files for cases where people use other intervals than 5 minutes * allow configuration of hires data store size in rrds with RRDRowCount configuration keyword * make cleanurl function in indexmaker more robust * make pagetop non mandatory * compensate for broken SNMP counters which go negative, by adding 2**31; * log2rrd on NT must use "|command" syntax Changes 2.9.18 -------------- From: Tobi * make router_connect work with host_templates too Changes 2.9.18pre12 ------------------- From: Herold Heiko * --sectionhost option for indexmaker From: Tobi * some more casts in rateup.c to make things work right when printing time values ... * make warnings for targets realy work * handle faild snmp queries more gracefully. Changes 2.9.18pre11 ------------------- From: Tobi * make sure inlast and outlast never go negative if rateup is used From: Herold Heiko * feature update for indexmaker From: Peter K * kill warnings in rateup :-) Changes 2.9.18pre10 ------------------ From: Tobi * Fixing documentation on SetEnv * deal the mrtg-rrd returning nan for last update * complain if workdir has spaces in path on windows From: "Jones, Derek C." * cfgmaker new if-filter ... if_is_wan From: CHOI Junho * fixes for korean translation Changes 2.9.18pre9 ------------------ From: Tobi * properly test for thresholds with % at the end * detect failing rateup * make cfgmaker really work with snmpv2 and test properly if snmpv2 is supported or not using ifHighSpeed * make translation system simpler ... by using eval * try to be even smarter about spaces and odd characters in rateup calling sequence under NT .. Changes 2.9.18pre8 ------------------ From: Tobi * fix cfgmaker tests for snmp v2 counters ... make sure they work before using them in the cfg file * make mrtg work if it installed in c:/program files From: Jussi Siponen * finish translation From: Tobi * make sure failing external commands do not produce warnings in the code except where I want them. Changes 2.9.18pre7 ------------------ From: Tobi * fixed up various warnings which occurred throughout the code because of the introduction of -w Changes 2.9.18pre6 ------------------ From: Tobi * fixed up various warnings which occurred throughout the code because of the introduction of -w Changes 2.9.18pre5 ------------------ From: Ian Duplisse * using kilo is not sensible everywhere in rateup as long as there are still pow and log10 instances there. From: Tobi * if inlast or outlast are undefined, skip update unless rrdtool is used * added -w to perl line in mrtg ... this should give us warnings about potential problems in the code ... everybody will now start complaining. fixed the most obvious issues already. As a side effect the code should work with perl 5.003 again. From: Delev Zoran * translation to macedionan Changes 2.9.18pre4 ------------------ From: Tobi * rateup: if last counter value is 0, this is no problem ... backout of the change from pre2 * data cleanup ... if a value is unknown, then it is set to 'undef' * more robust 'error' handling for strange target return values From: Adrian Senn * drop . from the end of hostnames in cfgmaker From: Sergiy Guminilovych * improved Ukrainian translation From: Systems Administrator * we also are using squid if the OID matches enterprises.3495 Changes 2.9.18pre3 ------------------ From: yoshimoto * Patch for YTics Factor Problem in rateup ... YTics Should work properly now ... From: David Lee * allow ../configure to work ... From: Klemens Kasemaa * estonian translation From: dima location Chg.RU * Updated Russian translation From: Amir Guindehi * added missing prefix to flastmod in indexmaker Changes 2.9.18pre2 ------------------ From: Tobi * rateup: if last counter value is 0 then something must be wrong ... do not calc then * mrtg: add warning to lockit code when mrtg thinks that the user is running mrtg from two cron entries simultaneously on the same config file. * rateup: force rateup to compile static ... try realy hard :-) From: Olexander Kunytsa * updated ukranian translation From: Simon Leinen and Mike Mitchell * update to SNMP_Session 0.92 Changes 2.9.18pre1 ------------------ From: "MORI, Takahiro" * yticsfactor was not considered when building ylab in rateup.c atted *yticsf to line 668 of the code From: Tobi * When reading back the html file only looked at the first 40 lines and thus ignored 5 values off the statistics on the last graph * Updated unix install instr to latest library versions * allow handling of rrd conversion for 'strange' filenames ... * added avgpeak option ... for ISPs who like this for billing ... (paid for by Advances.Com, Inc.) * cfgmaker should not comment out DS3 interfaces on non Cisco Gear From: "Leitch, Roger (CRTLDN)" * fix for withzeros option ... this did not work before From: Roman Festchook * translation file for mrtg to ukrainian language Changes 2.9.17 -------------- From: Tobi * mrtg_lib had broken scanning for Ip tables in populateconfcache this caused reference by IP to break Changes 2.9.16 -------------- From: Tobi * Removed win32::console from daemon mode mrtg * updated docu to get nt mrtg started with wperl instead of perl ... Changes 2.9.15 -------------- From: Tobi * new rateup.exe which creates pngs ... created using a mingw32 gcc running as a crosscompiler on SPARC Solaris. The rateup.exe is not linked as a console application, so no more popping cmd windows ... mrtg should run quietly now ... * updated instructions for running mrtg on windows in daemon mode * new option for mrtg --logging replaces $main::debugfile from 2.9.13. It can be set to a file which will take all mrtg output. On Win32 it can also be set to 'eventlog' which will make all mrtg output go to the eventlog. Changes 2.9.14 -------------- From: Martin.Frys location newtonit.cz * fix for configure ... -lfreetrype will not work :-) From: Tobi * propper caching for new gd lib variant tests in configure.in Changes 2.9.13 -------------- From: Damien * contrib mrtg_php_portal From: HERITIER Herv� * contrib iptables_acc_snmp From: Pascal Eeftinck * snmpv2 regexp did not match in cfgmaker From: Alexander V Redyuk * russian translation to windows-1251 russian charset. From: Klaus_Klein location mckinsey.com * contrib apc_ups monitor From: Ratko Bucic * serbian language translation updated From: O'Shaughnessy Evans * fix for indexmakers extension feature From: Dinko Korunic * croatian translation From: Graziano * updated cfgmaker_dlci contrib with work with win32 From: Jamaludin Ahmad * Indonesian and Malaysian translations From: "Newman, Daniel" * contrib document monitoring Cisco BPX and MGX switches with MRTG From: Tobi * improved mrtg logfile format description * require perl 5.005 for mrtg_lib * populateconfcache steps across non existing tables gracefully * in mrtg, handle bigint more carefully and remove excess + from results as some perls seem to crash on them ... * check if gd was linked with jpeg and even freetype ... * if $main::debugfile is set to a writeable filename, all output form mrtg will go there (Firedeamon Suggenstion) * SNMP_Session 0.86 added ... lenient_source_port_matching replaces the add hock only_ip_address_matching from mrtg 2.9.11 ... AS/400 folks beware * added --section=portname to indexmaker * try to fix IsCounterBroken test in cfgmaker ... just cant find any broken coutners to test this :-( From: Jakob Ilves * configuration templates for cfgmaker ... read the docs * fix for broken --dns-domain in cfgmaker Changes 2.9.12a --------------- From: Tobi * the windows binary rateup.exe creates gif file ... fixed mrtg accordingly ... * no changes to unix mrtg Changes 2.9.12 -------------- From: Tobi & Jeff Frost * fix for broken RouterUptime[] configurable Changes 2.9.11 -------------- From: Mike Mitchell * fix for broken snmp with returns negative numbers for counters ... * integrated my SNMP_utils changes into the real thing. From: Tobi * make sure cfgmaker puts now raw < or > into the PageTop tag From: Chad Mynhier * properly integrated ytics support in rateup From: Diogo Gomes * Portuguese translation for mrtg From: Thomas Abthorpe - Tby. * * The period "." was missing in front of $$rcfg{extension}{$item}. in indexmaker From: James Overbeck * properly deal with target math resulting in non integer data even when logging to rateup which can not deal with floats. From: Simon Butcher * cleanup of rateup.c and some new options -b -a -o -i * new options for mrtg noborder, noarrow, noi, noo, nobanner and nolegend check reference.pod for docs. * generator meta tag to html pages From: Gerry Van Steerteghem * add hyperlinks to 14all compatible indexmaker pages From: David Boyer * contrib mrtg.php produces live index From: David A. P�rez * contrib TTrafic a *.log analyzer in asp From: Ratko Bucic * serbian language translation From: "Gill, Vern" * contrib iptables-accounting From: Dan Lukes * allow configure to work even if you have a gdlib which supports BOTH gif and png From: GOMEZ Henri * add 'only_ip_address_matching' feature to SNMP_Session. We are more libaral when accepting snmp responses now. From: Tobi * be more tolerant with external scripts input * added feature to SNMP_utils: If first snmp var name is a HASH pointer, the hash contents is used to set snmp options on the connection * handle descriptions with & in cfgmaker * added SnmpOptions: command to mrtg.cfg lanuage ... It allows to set Snmp Options as available in SNMP_Session. Check the reference.txt file. * test for availability of ifHCInOctets when running cfgmaker for v2 targets suggested by Pascal Eeftinck * fixed indexmake image path for situations with Directories * added option --prefix to indexmaker for people keeping thier index somewhere else than default. * honor background option in cfg file for indexmaker pages * fixed warning in indexmaker (Use of uninitialized value in concatenation <.> at indexmaker line 174) * when the integer option was specified, there was still a .x printed in the sumary area ... * updated url in ircstats2 README * mrtg will now timestamp any warning and error message it emits suggested by SUZUKI Yasuhiro From: Juha Laine * fixed threshold processing ... IT REALY WORKS NOW! ... **** Incompatible CHANGE **************** ThreshProgOK now gets the same commandline arguments as the normal ThreshProg ... **** Incompatible CHANGE **************** From: Alexey Milevsky * configurable confcache (.ok) file location From: Anthony Howe * add to html files as this seems to be more understandable than "Pragma" content="no-cache" Changes 2.9.10 -------------- From: Tobi * reintroduced new cfgmaker ... somehow it got replaced by an older version in 2.9.8 and 2.9.9 Changes 2.9.9 ------------- From: Tobi * accept numbers starting with + comming from snmp * changed library version to 2.090009 Changes 2.9.8 ----------------- From: Tobi * indexmaker does now also honor ImageDir and problems in connection with the directory option. The result should be fewer broken links in index files. * better documentation on how to suppress images in indexmaker * remove potential newlines and padding from snmp response * added new global config: SingleRequest to force single variable snmp requests. * switch group before user if --group is used when starting mrtg * added special legends for perminute and perhour * new option for indexmaker --pagetop * if threshdir is defined, run thresholdprog* only when a boudery has been crossed. * better documentation of threshold programming * only run threshprogs if there are threshold bounderies defined * make threshold checking work better ... only run the threshold programs when a threshold boundery has been crossed ... * threshold stuff should be realy working now From: Fernando Braghetto - Webmaster Hiway * total control modem config From: Sune Kirkeby * configurable lockfile locations From: Tim Cimarusti * update for ciscoindex contrib From: Michael Bussmann * update mrtgindx.cgi to work with .png files From: Steven Shipway * Steven has a MRTG&RRDTOOL website now. Replaced references and contribs with links to http://www.cheshire.demon.co.uk/pub/ From: Gianmarco Armellin * index.html?.meta code was not working From: Us * slovenian translation From: Andres Kroonmaa * add commandline to generated output of indexmaker as a commet From: Andrew Ivanov * snmpoptions were disregadrded in the table population area of the script From: Simon Lyall * more tolerant matching for Description in indexmaker From: Anthony Fabian * fixed threshold feature: threshprog was not getting the right parameters when called Changes 2.9.7 ------------- From: Tobi * improved scanning of results from external scripts ... * in cfgmaker remove excess \ in Titles From: Wolfgang Hoffmann * new mrtglog programm in contrib From: Tobi and Daniel Elvin * added --show-op-down parameter to cfgmaker From: Jakob Ilves * massive enhancement to cfgmaker ... the beast has become much more configurable. Hold on to your hats, there is more to come. From: Simon * Upgrade to snmp_session.pm ... the beast was not reacting to udp packets coming from another interface of the router. Changes 2.9.6 ------------- From: Tobi * downgraded rateup code ... 2.9.5 was completely broken * fixed .pid fiel code ... now it should work, and double starts of mrtg will get prevented as well ... Changes 2.9.5 ------------- From: Jakob Ilves * rewrote --ifdesc in cfgmaker ... there are many more options now From: O'Shaughnessy Evans * fixes for cfgmaker (--help, --noreversedns and version param) * fixes for indexmaker (--help, --version, added man info on section=descr) From: Do Jong Gwan * rules for activating threshold checking were not ideal ... (often it did not get activated when it should) From: Tobi * removed extra space in hrefs in indexmaker pages * make configure catch missing gd.h * make sure no two mrtg daemons run on the same cfg file in parallel. * proper exit values for cfgmaker and indexmaker * rewrote threshold checking to be more perlish * thresholds can now be specified in % of maxbytes to activate this, they must end in '%' From: Tobi & Luiz Encarnacao * All translations had bad formating in the credit line (extra font and td tags) From: Justin Schoonover * Make Rateup honour the yticsf properly From: Tobi * Removed 14all.cgi from the contrib section and replaced by a pointer to Rainers website. This ensures that people get the current version and not some outdated code from my contrib archive. From: Curtis Doty * add refresh and expiery to indexmaker pages * fix rateup.c to honor weekformat when drawing grid lines "Format U" From: Tobi & Mac Daddy * New BodyTag configurable lets you customize the webpages tag From: Alex and Tobi * fix for external data sources sending "" as response breaking the logfile problem From: Hubert Figuiere * Support for MAC OS X From: Simon Leinen * Update to SNMP Session 0.81 From: Bernard Martinet * Fix for parsing of 'by name' matchin target parser ... From: Miroslaw.Maczka location bze.com.pl * update to nt-service From: Tobi Changes 2.9.4 ------------- From: Curtis Doty * excess whitespace after cfgmaker ECHO line was wrecking havoc Changes 2.9.3 ------------- From: Andrew Farrior + teach cfgmaker about catalyst port names From: O'Shaughnessy Evans + cfgmaker will now add a SetEnv line to each router config block * improved cfgmaker docu spelling + indexmaker change --section=descr so that it doesn't include the basic interface description unless it doesn't have a Cisco description to use; adds/docs a new option, --show=none, which disables inclusion of any graph in the index page From: Kevin Benton + contrib gentcucci From: Matija Grabnar + teach log2rrd to honour perhour and perminute options From: Dan Harkless + made cfgmakers --subdirs option way more flexible From: Yo + tranlation into galician From: Dimitrios Stergiou + contrib procmem ... cisco cpu monitoring From: Jeff Liebermann * fixed location dddd[] structures in gb2312.pmd From: John Begley * CEF subinterfaces are not 'graphable' (cfgmaker) From: Tobi * forking code revisited again ... missed closing a handle which was wrecking havoc on log files on certain OSes. No idea how this could happen but it did ... * fix for complex target parser in conection with escaped characters * updated the reference doc description of absolute and gauge to be more concise * check is RunAsDeamon is set to yes + cfgmaker option --noreversedns + add options --user and --group to mrtg script to allow setting user and group when starting mrtg as a daemon from init.d (idea from Dan Harkless ) From: Francis VIVAT * add start command line to runasdaemon section of nt-guide From: Chris Pepper * about 1000 spell fixes for the mrtg docu From: Dan Harkless * spell fix for MRTG_lib.pm again ... Changes 2.9.2 ------------- From: Tobi * revisited and fixed forking code. mrtg was not stable when run as daemon with forking enabled. Aftermath of the confcache problems in 2.9.0 * cfgmaker was not working properly when multiple routers were specified on the commandline From: Dan Harkless * cfgmaker fixes: spelling, quote arguments with space, make --subdirs work * MRTG_lib.pm include file error message had misspelling and output wrong file. From: donlong * updated big5 translation Changes 2.9.1 ------------- From: Rainer Bawidamann * problem with confcache update marker From: Dan Harkless * Various documentation spelling and version number fixes. * Change whatis.* doc files to mrtg.* to not conflict with system whatis.1. From: Lars Christiansen * get subif description on cisco hssi interfaces in cfgmaker Changes 2.9.0 ------------- * The rrdtool integration allows for massively increased logging performance. * Routers which change their interface numbers are no problem any more. MRTG can now reliably address interfaces by IP, MAC, Description, Name and Type. The cfgmaker tool has been rewritten from scratch and allows to generate configurations with any of the above mentioned interface addressing methods. * Indexmaker has be rewritten from scratch, it is now much more flexible and fully documented. * All the MRTG documentation has been reviewed and ported to perls "Plain Old Documentation (POD)" format. This allows to provide all documentation in text, HTML and man format. It is now all available on the MRTG web-site. * Config file parsing has been optimized. This makes reading configuration files much faster. Especially large configuration files are faster by factors * Under UNIX, mrtg can fork into several instances while querying routers. This improves data acquisition performance dramatically, especially with slow networks. * Graphs and webpages can be generated on the fly is mrtg is used with rrdtool logging. Several tools in the mrtg contrib section are available for this purpose. * And there is more: MRTG has been translated into 29 languages, OS detection has been automated, did I mention performance, many of the contributed tools have been dated and a slew of new ones has been added, The config file reading code is now available in a documented library which simplifies the creation of other tools which need access to the mrtg cfg file. Details: From: Rainer Bawidamann - new version of 14all.cgi ----pre33------------- From: Justin Shore - End MRTG Block comment was going to STDOUT ... ----pre32------------- From: Tobi - do not threshold check if cuin or cuout is undef - join continuation lines with newline - moved End MRTG Block coment to the right place - allow forks: 1 but ignore it ... ----pre31------------- From: Tobi - indexmaker with no sorting was broken in pre30 ... From: Curtis Doty - improved sorting for repeated titles in indexmaker ----pre30------------- From: Tobi - removed exess close from forking code ... it seems that perl hates it when I try to close a FH of a dead pipe From: Gereon Ruetten - contrib: script for using mrtg with iptables From: Dimitar Pashev - mrtg can now also run as daemon ... check reference.txt From: Curtis Doty - added --descint option to cfgmake describe interface instead of just 'Traffic Analysis for' From: Tobi & Alex - added query test to cfgmaker (it now does a test query to see if the interface does acctually have traffic counters) From: Peter - gb2312 translation From: Jonathan Cohn - better equipment identification for cfgmaker ... cisco and nokia got mixed up du to a missing . From: Patrik Andersin - mrtg was not accepting withzeroes option (typo in cfg checker) From: "Starkweather, Mike (CNS)" - NT does know -x ... repaced it with -e in threshprog* From: O'Shaughnessy Evans - allow capitals in SetEnv - cfgmeker added option --subdirs ... give subdir to each router From: Tobi - kill and \r in cfg files created on DOS and used on unix ----pre29------------- From: tobi - fixed cfgmaker ... problem with confcache content ... - cfgmaker .. autoquote commandline in cfgfile - cfgmaker ignore agregate interfaces (53) on cisco ----pre28------------- From: Rainer Bawidamann - upgraded to 14all.cgi 1.1.p5 From: O'Shaughnessy Evans - allow to use Description for sectioning in indexmaker From: Adrian Turcu - contributed mrtgrq ... quota monitoring script - contributed net-hosts for monitoring a set of hosts using fping From: Robert Boyle - updated version of PMLines which works with Portmaster 2 to 4 From: tobi - added query by ifType (I know this is sick) - when using forking the confcache updates were not propagated back to the calling process - properly detect situations where the Interface number can not be determined ----pre27------------- From: John Lange - update for ipchains script From: Tobi - fix for indexmaker ... $$item problem ----pre26------------- From: Brian Mudge - fixed showstoppers in mrtg and cfgmaker ----pre25------------- From: Tobi - added xff parameter for log2rrd function in accordance with rrdtool 1.0.27 From: Michele Michelotto - removed excess from locales From: blube location floridadigital.net - make cfgmaker comment out DS3 controlers ... they do not count their traffic From: Rainer Bawidamann - made PID file name generation robust to cfg files without extenssion From: Mattias Lilliesk�ld - make cfgmaker recognize options[^]: bits From: Thomas Abthorpe - Tby. * - go for threshold checking if threshdir is defined ----pre24------------ From: Robert Boyle - Contrib PM4lines, the Lucent Portmaster 4 monitor From: Lucas Nussbaum - create a pid file when mrtg gets executed in daemon mode From: Thomas Abthorpe - Tby. * - fix for configurable file extension in indexmaker From: Juergen Baier and Jacques Supcik - fix for 'target by Ip' name matching code From: Tobi - fixed router uptime ... was not asking on the right target ... From: Steven.Shipway location adsweu.com - updated contrib/routers to version 1.0 - contributed contrib/servers.cgi From: Rainer Bawidamann - fixes for 14all.cgi ... - more debbugging information in log mode about what happens when rrdtool and rateup run ----pre23------------ From: Rainer Bawidamann - fixed threshold support for rrdtool mode - -w fixes for MRTG_lib.pm - relax check for going into threshold mode From: Tobi - pre22 optimisation in target parser broke it ... fixed now complex targets get parsed properly - fixed indexmaker in connection with the directory option ----pre22------------ From: Rainer Bawidamann - updated version of 14all.cgi - identify threshold checking configs properly - fixed snmp level 2 identification for simple targets - add default values for background and backgc From: Benoit Artuso - fix for confcache regeneration From: Bjorn Nordbo - fixes for forker (trgnum was wrong ...) - fixes for missing 'directory' support in log2rrd From: Tobi - use OS installer if one is available - lost a line from cfg file reads ... fixed - added OS detection to MRTG_lib so no more main:: stuff is necessary. - test for existence of work/log/html/image dir, try to reate if missing - Used SmallProf on cfgparser found a grep which was bogging everything down ... together with some other small optimizations this brought the config file reading in my test case (900 simple targets) down from 30 seconds to 7 seconds ... SmallProf rules (or if you look at the total runtime (I am using fork 10) this went down from 43 to 21 seconds ----pre21------------ From: Lucas Nussbaum - contrib: ircstats2.pl a script used to monitor the user load on IRC networks. Contrary to ircstats by Matt Ramsey, it remains connected to the server. From: Tobi - add mask to mkdir call it seems some perls can't deal with the simple form ... - fixed forking code ... I think I got the typeglob magic right now. note, when experimenting with the number of forked collectors, more is not always better. Eg, If you shoot two collectors at a single router in parallel this may prove to be slower than having one collector at work. As a rule of thumb you might want to try a fork equivalent to the number of routers you are monitoring ... (my record with forking, RunAsDaemon and RRDtool is 800 interfaces in 13 seconds ... - added the Include: keyword to the config parser as discussed on the ML ----pre20------------ From: Matthew Schumacher - upate to cpu info From: Tobi - fixed start time for newly created rrds ... this must be $time-2 not $now - fixed quick check rules for maxbytes1 and maxbytes2 - missing directory[xxx] entries will get autocreated - modified quickcheck rules ... instead of strings we use anonymous subs now ... this has the advantage of perl actually compiling the stuff and thus finding errors in the checks even when they are not exercised ... - ***EXPERIMENTAL*** added forking function. If you run mrtg on a system that can fork (UNIX for example) you can try the new 'Forks:' option in the config file. The result of this is that mrtg will fork into several instances prior to going out to ask the routers for snmp data. For situations with high latency as well as mrtg.cfgs with many different devices this will speed things up considerably. It will not make things faster if you query a single switch sitting around next door. As fahr as I know NT can not fork so I have disabled this for NT. If you measure some performance data with this approach please let me know how much faster you went ... ----pre19------------ From: Roy-Magne Mo - binaries must be installed with 755 From: Tobi - when eval fails in target we die - relaxed target parser to cope with oid names which have no dots at all and oids starting with a dot. ----pre18------------ From: Tobi - cfgmaker will disable cisco interfaces with description VLAN.. From: Ferenc Toth - MRTG_lib.pm target parser for complex targets (&) was broken in pre16 .. (off by one error) ----pre17------------ From: Tobi - fixed directory option to generate proper img paths under NT (untested) - made cfgmaker output more useful looking - fixed sorting order in cfgmaker - added --no-down swith to cfgmaker for querying downed interfaces all the same - fixed operstatus tests in cfgmaker - fixed problem in indexmaker. it did not work properly with multiple files. SRC path was wrong - fixed potential problem with ensureSL where a final / was added to an empty string ... - added new interface reference type ifName introduced in mrtg and cfgmaker ifname references are introduced by the # character. Check the reference and the cfgmaker man pages - improved mrtg performance by not asking for uptime and sysname with every target when doing logformat rrdtool - fixed lost uptime and sys name querying for rateup logformat From: Steven.Shipway location adsweu.com - updated contrib/routers to version 0.11 ----pre16------------ Thomas Abthorpe - Tby. * - fixed broken header introduced in pre15 :-) From: Rainer Bawidamann - reenabled threshold checking which got inadvertedly disabled in pre15 - cosmetic fixes for MRTG_lib.pm From: Tobi - we die always if we get errors from RRDs - moved read/write confcache functions into MRTG_lib ----pre15------------ From: Tobi - fixed problem with confcache where mrtg did not see that the confcache was already populated and thus repopulated it on every target ... this means that for all Descr / Ip and Eth targets we get a performance improvement of 1000% - fixed problem with calculation targets (adding results from two interfaces and such) this did not get detected properly ... - integrated automatic log to rrd convertor ... if you have configured logformat: rrdtool and and are running for the first time, your old .log file will be converted to the new rrd format of rrdtool. the .log files will not get removed. So that you can compare the old with the new graphs. Note that this is a VERY NEW feature and it may well not yet work exactly as planned ... - replaced the UseRRDtool cfg parameter with logformat: rrdtool. Check the doc/mrtg-rrd.txt file for details. (NOTE: 14all.cgi has not yet been modified to work with this new convention, but Rainer said he will do it in a few adays after his exames) - added -w switch to mrtg, cfgmaker and indexmaker ... found&fixed many little problems in the process - fixed problem with missing space in per and posttargers - Rearanged directory layout to follow more traditional lines. Binaries are in bin/ libraries in lib/mrtg2 - adepted Makfile to also install in these directories - adapted documentation - fixed some issues with cfg reading introduced when splitting mrtg into MRTG_lib.pm - fixed error handling with RRDtool From: William P. McGonigle - if writeexpire has been defined, create one for the index.html file as well From: Kit-pui Wong - fixed alignement of indexmaker graph titles ... From: Miroslaw.Maczka location bze.com.pl - a rateup for NT which produces pngs so finally no mode gifs for NT as well From: Rainer Bawidamann - Documentation for MRTG_lib and some better argument checking for MRTG_lib From: Curtis Doty & Tobi - use FindBin to determine location of modules. Revamped all the library finding code in mrtg - indexmaker fix for filter regexp and some output fixes ----pre14------------ From: Rainer Bawidamann - more flexible config parsing functionality added to MRTG_lib.pm in preparation for a better configurable 14all.cgi due out soon. From: Tobi - fixed NT path issues ... backslash is a bitch in re ... needed to put some \Q and \E in to fix things ... (I am amazed it did run at all befor this hmmm. From: Curtis Doty - fixes some install errors in Makefile.in From: Thomas Brian Granier - NT verion wanted to create "zip" instead for "gif" fixed ----pre13------------ From: Tobi - reworked directory[x]: and general path issues with mrtg ... maybe it works now ... - default graph format for NT is gif (until someone submits a rateup.exe which is compiled with a recent gd) - fixed bug in confcache code which prevented proper matching of non ifnum targets - modified parsing rules for EXEC targets, COMMUNITY and DESCRIPTION ... EXEC backticks can be used inside when escaped like this: \` COMMUNITY space and @ can be used like this \ location and "\ " DESCRIPTION space and : can be used with "\ " and "\:" in all other combinations the \ has no special significance ----pre12------------ From: Tobi - made SNMPv2c queriing work ... the target parser did not properly see :::::2 ----pre11------------ From: Tobi - fixed target nameing in cfgmaker - fixed 'no workdir' error in mrtg - fixed populateconfcache for setups with communities other than 'public' ----pre10------------ From: Tobi - fixed cfgmaker man page to use " for --global delimiters as NT seems to have no clue on '. - added hint on escaping ! to the indexmaker manual - added mrtg version to documentation pages ----pre9------------ From: Tobi - fixed RunAsDaemon Code ... target array should not get deleted between runs. - fixed mrtg target parser for If number 0 case ... ----pre8------------ From: Curtis Doty - fixes for Makefile install routine From: Simon Barnes - fix to test for validty of results from data returned by 'external' targets.It was inverted. From: Tobi - added missing semi colon to indexmaker - added requirement for perl 5.005 to indexmaker and cfgmaker - added part of the PodParser module so that things work with perl 5.005 From: Alex - spell fixes for unix-guide.pod, forum.pod, contrib.pod ----pre7------------ From: Rainer Bawidamann - contrib / version 1.0p16 of 14all.cgi From: Benoit Artuso - images did not get generated in the correct place with the 'directory' option From: Tobi - converted all documentation to pod format and added several new chapters ... - created new mrtg homepage which links all available documentation online - created new installation guides for unix and nt - complete overhaul of the target parser (NOTE: it is NOT a horrible Hack any more ... look at the code (tobi is proud) - along with the target parser I also replaced all the snmpget logic. - calling Interfaces by ifNumber, Ethernet Address, IP Number or Description are all neatly integrated in the code. No more Horrible Hacks. Along with data polling, the Interface nubmers get double checked. If a reconfiguration occures, mrtg automatically gets the new configuration from the router. - MRTG does *NOT* notice config changes on Interface Numbers anymore. This means if you have devices which change interface numbering do not call the interfaces into the mrtg.cfg by number but rather by Description or by Ip. - added new debug facility to mrtg. Different debug levels can now be called by name. Check the beginning of the script. - when using rrdtool, mrtg now also deals with *UNKNOWN* and non integer values. - extracted some functionality of mrtg into an external module called MRTG_lib.pm. This module is now used by cfgmaker and indexmaker. For indexmaker this means that it uses the same cfg parsing engine as mrtg proper. - over all about 30% of mrtg got replaced by brand new and rather clean code. - complete rewrite of cfgmaker ... try cfgmaker --help for instructions cfgmaker can now produce config files with interface identification by Number, Ip, Description and Ethernet Address - complete rewrite of indexmaker ... the old code was broken beyond reason. options are different in the new indexmaker. Use indexmaker --help for help. - added RRDs detection to configure script (--with-RRDs can be used to set a path explicitly ----pre6------------ From: Tobi - added automatic OS detection ... no more editing mrtg - better isolation of graphics format ... ${main::GRAPHFMT} - made imagedir logdir and htmldir work - fixed infinite loop for workdir configs - added $! to most open calls for better error reporting - reviewed and updated install instructions in README From: Ilja Pavkovic - update fuer deutsches locale ----pre5------------ From: Tobi - removed debug output from mrtg ----pre4------------ From: Yovko Lambrev - fixed bulgarian translation From: Rainer and Tobi - added docu for PageFoot to config.pod From: Tobi - extension config did not work ... now it does From: ve location hardcore.lt - update to lithuanian locale From: Tobi - made new options imagedir logdir and htmldir work From: Simon Leinen - some SNMPv2c additions to SNMP_util.pm From: Tobi - added SetEnv[xyz]: option to mrtg.cfg for passing information on to external scripts. From: John Dunning/NS/WSC - added -d option to indexmaker wich makes index.html files go into the directory with the data files for a target From: Matija Grabnar - added RRDtool / 14all.cgi awareness to indexmaker From: CmdrData - contrib nt_n_cisco some tools for running mrtg with ms-sql and cisco gear From: Graziano Sommariva - contrib cfgmaker_dlci From: Rainer Bawidamann - made theshold configs working in connections with UseRRDtool: yes - updated 14all.cgi in contrib to 1.0p13 From: John Lange - contrib: ipchains accounting script with mrtg From: Justin Shore - added comments into generated webpage for easier parsing From: Hui Zhang - added chinese locale gb From: Thomas Lehnig - add new config option 'factor' for scaling the values printed below the graph From: Colin Morey - allow to split images, logfiles, webpages into different directories introduces HtmlDir ImageDir LogDir . From: Chris Knipe - contrib: monitor -- NT/Access/ASP based network monitoring system using mrtg technology. From: Oleg Krotoff - contrib: mrtg-archiver-script From: Ladislav Mihok - slovak translation for mrtg From: Martin R�sjorde - improved norwegian translation From: Michael Med - make complex TZ settings work with rateup in solaris. By copying the localtime data to private memory. From: Walery Kokarev - Added withzeroes option for people who want zero sample considered in their average transfer rate. From: ٤��� - simplified chinese locale From: Patrick Koppen - make -r work in indexmaker From: Nick Hilliard - fix for title case in indexmaker (this should take care of the pagetop problem) From: Tobi and Albert Chin-A-Young - added install target to Makefile default prefix is /usr/local/mrtg-2 From: Jodok Sutterluety - added extension option for people who want their pages end in something else than .html From: Zaphod Beeblebrox - bulgarian locale From: "John H. Robinson, IV" - made cfgmaker print interface speed with apropriate units if we think in bits From: Miroslaw.Maczka location bze.com.pl - contrib nt-service: make mrtg a service under NT From: Nathan Wiger - make sure no name gets used twice - all errors from cfgmaker should go to STDERR From: x - contrib snmpping.pl see if a device speaks snmp From: Johannes Demel - fixed minimal hearbeat to be in sync with Interval parameter when using RRDtool From: Simon Leinen - new version of SNMP Session which can do SNMPv2c this allows to poll the ifHC??Octets counters (64Bit) if your router supports them ... No more wrapping in this life or half life anyway. If you specify y:public location router1:::::2 this will poll the HC counters. This will only work if your router supports it ... From: Richard Kwong - fix for ytics in rateup From: Tobi and "Purvis, William" - added nomib2 option to supress 'sysUptime', 'sysName' queriing .... some devices do not support this. From: Matthew Schumacher - update for contrib/cpuinfo From: Rainer Bawidamann - improved rrdtool integration ... From: Tobi - added default for interval in case it does not get set From: Anton Voronin - additional syntax for Target: Target[ezwf]: \My-Interface2:public location wellfleet-fddi.ethz.ch use the interface description From: Jozsef Szilagyi - improved romainan translation From: Alon Goldberg - bugfixes for contrib/diskmon/getdisk.pl From: Steven.Shipway location adsweu.com - contrib routers: CGI frontend to mrtg/RRDtool check example on http://ukpavu99.adsweu.com/cgi-bin/routers.cgi From: ve - pmd file for Lithuanian language From: Miroslaw.Maczka location bze.com.pl - contrib Informix Performance monitoring From: Roddy Strachan - contrib Access-list Monitoring via MRTG From: Clas Mayer - swedish translation From: Simos Xenitellis - improved greek translation From: Christian Rost - spell fixes for german.pmd From: seweryn location anatema.torun.pdi.net - spell fixes for polish translation From: Tobi - shame on me ... all these nice translations and I forgot to update the MANIFEST ... now they are all in ... Changes 2.8.12 -------------- From: Tobi + Hoorelbeke Rik - make -M and -r work in indexmaker From: Levente Nagy - hungarian translation From: Peter Gervai - NoSpaceChar option. Supresses SPACE normally inserted between local value and PRE or APPEND value. From: Francois Wolmarans - new features for cfgmaker --iponly, --options, --workdir From: Tobi Oetiker - make RunAsDaemon work ... - Daemon mode now forks into background after cfgcheck - Remove locks after sig INT and TERM - make indexmaker ignore default values - added ThreshDesc config option. Its value is assigned to the env variable THRESH_DESC before and of the Thresh-Action scripts are called. From: "[big5] ���F��" and Tate - bugfix for big5 locale From: knut.groneng location merkantildata.no - bugfix for norwegian.pmd Changes 2.8.11 (2000/01/17) -------------- From: Lucas - it is RunAsDaemon and not RunAsDeamon Changes 2.8.10 (2000/01/16) -------------- From: Rainer.Bawidamann location informatik.uni-ulm.de - update for rrdtool integration 14all.cgi to 0.16 From: Morten S. Nielsen - updated danish translation From: Francois Wolmarans - have cfgmaker put specific comments into the mrtg.cfg file regarding the reason for droping a certain interface .. From: Krister Karlsson - Added RunAsDeamon mode. Start mrtg only once. No Cron necessary. From: Ronald Florence - linux ip-filter integration in contrib From: Iulian Radu - version 2.2 of mrtgmk in contrib From: LLu�s Gras - catalan locales From: John Line - rateup.c fix for kMG override bug From: John Line - allow to set ShortLegend to '' From: Tobi - better parsing of PageTop with intexmakers -P option From: Ruben Cheng - fix for spanish translation (uptime had some probmlems) From: Markley P. Dykeman - contrib: switchmaker produces mrtg cfg files for Cisco Catylst 5XXX From: Tobi - made sure -lm comes last when linking ... From: Tobi + Ben - converted remaining gifs to png From: Tobi + Mike Lawrie - make sure AbsMax is not smaller than MaxBytes From: Halldor.Hognason location islandssimi.is - translation to icelandic From: Fuminori Uematsu - added japanese translations for ISO-2022-JP and EUC-JP From: ozgurcd location koc.net - added turkish translation Changes 2.8.9 ------------- From: Rainer.Bawidamann location informatik.uni-ulm.de - update for rrdtool integration 14all.cgi From: Morten S. Nielsen - Added more modular translation system From: Ilja Pavkovic - Added German Translation From: "Tate <����>" - Chinese Translation From: John-Mark Gurney - cfgmaker_ip ... keep first address and not last .. From: Assakhof Bin Ab. Satar - Malayan translation From: Tobi - restored mibhelp to its old glory .. From: Jon Rifkin - added ability to index interfaces by physical address analog to the existing IP stuff ... there is now also a cfgmaker_phys From: Lukasz Jokiel - polish translation From: Hideyuki Suzuki - graphing fix for rateup ... From: Matthew Schumacher - cpuinfo contrib From: Paul E. Erkkila - contrib cisco config tftp From: Iulian Radu - updates and bugfixes for mrtgmk v2.0 From: David Boone - fix for -F/-f in indexmaker - fix for view type in indexmaker From: Matthias Cramer - cisco accounting contrib From: Karl Friesen - added -lm to LIBS in configure.in From: Morten S. Nielsen - patching system for languages ... check translate directory From: "Kloberg Mac (LAM)" - NSI (Network Status Imager for MRTG) contrib From: Rawlin Blake - updates for mrtg-archiver Changes 2.8.8 ------------- From: Tobi - fixed problems with RRDs integration ... Changes 2.8.7 ------------- From: Rainer Bawidamann - contrib: RRDtool integration -> contrib/14all From: Xenitellis S - greek locales From: Andrea Rossi - italian locales From: Martin Goebel - better html for indexmaker ... From: "Stieers, Ken" - added a new switch to indexmaker ( [-v d|w|m|y] ) which allows you to select which graphs you get. From: Daniel Haun - indexmaker can now take - as a filename to allow input from stdin - cfgmaker_ip works with IOS 10.0 now (CRLF <=> LF in sysDescr) From: Tobi - allow targets with name of Option entries ... From: Marcelo Roccasalva - contributed spanish locale From: Tobi - added LD_RUN_PATH to make file and configure in support ofr shared libraries ... From: Luiz Felipe R E - fixed gifpath for NT - added brazilian portuguese locales From: Barry van Dijk - added Dutch locales From: calle olsen - updated stat.pl in contrib From: tobi - added -lm do default LDFLAGS From: Daisuke Aoyama - fixes for generated HTML From: Dmitry S. Sivachenko - added russian translation Changes 2.8.6 ------------- From: Philippe.Simonet location swisscom.com - contributed rateup.exe for NT users Changes 2.8.5 ------------- From: Tobi - even better config script Changes 2.8.4 ------------- From: Iulian Radu - new version of mrtgmk contributed (2.1) From: Tobi - fixed indexmaker - udated configure to better check for gd presence ... - added Option unknaszero which turns logging of *unknown* data to logging zero instead of repeating the last value seen. Log unknown data as zero instead of the default behaviour of repeating the last value seen. Be careful with this, often a flat line in the graph is much more obvious than a line at 0. From: Fabrice Prigent & St�phane Marzloff - french locales Changes 2.8.3 ------------- From: Tobi - fixed MIB reading integration Changes 2.8.2 ------------- From: Philippe.Simonet location swisscom.com - added updated rateup.exe for NT ... - fixed NT *.zip distro ... Changes 2.8.1 ------------- From: Tobi - fixed URL for GD library in documentation .. Changes 2.8.0 ------------- From: Tobi - fixed autoconf system to work with new gd version From: Miguel Vitorino - added -o filename option to indexmaker From: Antonio Querubin - fixed indexmaker to work with -m and -P option in parallel From: Rodrigue Assard - added ytics and yticsfactor options to mrtg/rateup From: Iulian Radu - contributed mrtgmk, a mrtg.cfg file generator ... From: Yozo Toda and and Bernard Quatermass and Tobi - support for gd-1.6.1 ... Depending on the available version of libgd mrtg will be configured for generation png or gif images From: Mike Mitchell - MIB Parsing for mrtg ... the mrtg.cfg file can now countain something like this: LoadMIBs: /usr/lib/mib/cool.mib,/etc/snmp/BOX.mib MIB-II and FrameRelay MIB are preloaded ... For improved efficiency a OID cache is maintained in the WorkDir oid-mib-cache.txt From: Morten Nielsen - Support for different locales in mrtg added ... At the moment the only supported Languages are English and Danish if you want to translate things to your language, edit the locales_mrtg file apropriately. In the mrtg.cfg file you can select your language with the global Language: option From: Cristian Caramida - Contributed mrtg-ipacc script for using Linux IP accounting kernel rules to feed mrtg Changes 2.7.6 ------------- From: Henry Steinhauer - contrib cfgmaker for ATM Bay MIB From: Fred Korz - fixed some typos in config.pod and manual.html Changes 2.7.5 ------------- From: Kari.Hiitola location sonera.fi - make maxbytes = 0 work ... From: Iulian Radu - contrib mrtgmk From: Tomas Pospisek - update for get-multiserial contrib From: "Gellatly, Laurie (x8864)" - contrib: hp openview integration From: Jef Considine - fixed the relative percent y-coordinates in rateup when using bits From: Tim Cimarusti - ciscoindex contribution From: "J. Nick Koston" - allow @ in community names ... From: Steven Micallef - addded diskmon contrib From: Tobi - fixed multiline sysdescr handling in indexmaker - added nt-guide back into the archive ... - fixed the Signal 127 with Exit Value 16777215 problem From: Justin McCann - moved a last malloc to calloc in rateup .. From: Butch Kemper - updated PM3Lines.pl From: Calle Olsen - added stat.pl (DNS monitor) Changes 2.7.4 ------------- From: Alexandre Steinberg - rateup.c made to compile with VC++ 6.0 - new rateup.exe which has no timezone problems added to zip archive. From: Thomas Muggli - NSM - added threshold monitoring functionality Changes 2.7.3 ------------- From: Dima Sivachenko - more squid OIDs for SNMP_util.pm From: Vlado Potisk - reproducable evaluation order by sorting targets ... From: Morten S. Nielsen - fixes for Squid OIDs in SNMP_utils.pm From: "Tony-Farr (Canberra)" - contributed Whodo, a set of Perl scripts to analyse IP accounting data from a cisco. to be found in the contrib direcotry. From: Andreas Papst - fix for y legend in scaling mode with dorelpercent enabled Changes 2.7.2 ------------- From: Brad - Fix for malloc.h warning when compiling on *BSD From: Tobi - Ignore \n at the end of ifDescrs. This was fatal for Reconfig checking From: Ken Stieers - Added -G and -g as arguments to indexmaker Changes 2.7.1 ------------- From: Kevin Sartorelli - SNMP_util.pm cacheCurrentSwapSize should end in 14 From: Andres Kroonmaa - added option transparent to make the background of generated gifs transparent ... - more updates to indexmaker - massive enhancement to cfgmaker to go with ipget patch for mrtg this is experimental code. it is called cfgmaker_ip. - ipget integrated into mrtg. you can now specify an ip address instead of an port number ... From: Horak Daniel - updated ip-get patch From: "Mark D. Nagel" - icondir awarenes for indexmaker From: Alexandre BAUMEISTER - fixed -s /-S options in indexmaker From: Ralf Weber - fixed compatibility problem with SNMP_Session ... undef != -1 !!! Changes 2.7.0 ------------- From: Steve Pierce, Director of Fun @ HDL - new nt install guide ... From: Simon Leinen abd Mike Mitchell - Update to SNMP_Session 0.69 - ability to use @ in community string ... From: Eric Murat little error in subst code fixed ... From: Rory Clancy From: andre location ml.ee Thu Feb 25 21:13:01 1999 * NEW indexmaker ... - accepts multiple config files, (also wildcards) - options allowed per config-file (options between filenames) - now handles global Directory[^] tag - optional 2-column layout - unsorted target sequencing, optionally numbered - option to specify bacground color - option to specify overview graphs sizes - few options to increase/decrease bells an whistles From: Anri Kopystyansky * correct squid OIDs for cacheHttpInKb cacheHttpOutKb cacheICPpktsSent cacheICPpktsRecv From: Simon Leinen * new version of SNMP_Session and friends ... Changes 2.6.5 ------------- From: Norman Aronsen * added space after #! in perl scripts this is more portable From: "riocat(^..^)~" * Japanese translation of mrtg docu added ... From: Robert Allmeroth * relaxed SNMP_Session.pm s requirements for SNMP response consistancy so that error-index gets disregarded when error-status is 0 From: "Tony-Farr (Canberra)" * contributed script that extracts summary figures from the MRTG log files. Because it uses Excel, it is only useful on Windows. From: Eric Billeter * contrubuted some scripts he modified to monitor the modem utilization of my USR Total control racks. From: Alberto Pasquale * optional handling of two different MaxBytes settings: MaxBytes1/MaxBytes2 Changes 2.6.4 ------------- From: Dimitar Kazakov * Updated mrtg-ipget patch for SNMP_util.pm compatibility From: Tobi * readhist now uses unsigned longint when reading in the log file this might speed up things slightly ... * added warning, that dorelpercent requires 5 colours ... Changes 2.6.3 ------------- From: Tobi added joey millers contribs (jm) to contrib tree made website more mirror friendly updated nt-guide thanks to Steve Price fixed squid OIDs in SNMP_util.pm ... thanks Michael Riedel properly integrated rateup binary for NT ... just get the mrtg zip archive ... improved cfgmaker thanks to Joerg Schumacher ... fixed mapping problems ... Changes 2.6.2 ------------- From: Tobi fixed quotes in indexmaker fixed configure.in --with-gd-*= was not working ... fixed version number fixer for distribution im Makefile.in From: Blair Zajac fixed html im indexmaker and mrtg Changes 2.6.1 ------------- From: Tobi fixed stupid bug in connection with bits option ... the numbers below the graph were not calculated correctly .. Changes 2.6.0 ------------- From: Tobi cleaned up distribution added configure script changed cfgmaker to use ipaddress as name for targets From: Simon Leinen integration of the SNMP_util and the latest SNMP_session interestingly enough this can make things much faster on occasion ... new version of cfgmaker which uses gettable ... From: oliver.haid location tilak.or.at mrtg-conf.pod fixes, #a0a0a0 and integer option rateup.c added better scanning of legend argument From: Andreas Papst dorelpercent kMG kilo improvements for perminute perhour some OIDs for SQUID 2.0.RELEASE From: Matija Grabnar I implemented a patch that displays the per-hour rate instead of the per-second rate. It is triggered by including "hourly" in the options line. The patch has worked satisfactorily on our site (used when measuring cache access and news server article counts) I find it better than simply multiplying the sample values, because it takes into account the actual time that passed between the samples. Changes 2.5.4c -------------- removed <> in the end function for perl 5.005 compatibility Changes 2.5.4b -------------- Documentation Update ... all the info about simons changes for 2.5.4 were missing ... Changes 2.5.4a -------------- fixed fatal comma in cfgmaker .. Changes 2.5.4 ------------- From: Russell Carleton almost 100 new interface types for cfgmaker ... From: "Tony-Farr (Canberra)" better matching for cisco version number in cfgmaker From: Ricardo Bravo improved matching of regexp indexmaker From: yours truely made external commands driver cut whitespace from the the front and back of external commands output fixed longstanding bug in diff function ... 0 - 10 did not work From: Henning P . Schmiedehausen Correct behaviour if the child process has already terminated before mrtg goes to wait for it ... From: Daniel Trinkle Error message if the cfg file can not be opened ... >From Simon Leinen better configurability of SNMP timeouts ... >From Jean-Luc RICHIER (Jean-Luc.Richier location Imag.Fr richier location imag.fr) 1/ If there is a ' in an external target description (within `), mrtg dies with eval problems. (I needed ' to protect spaces). This comes from a substitution in the target, which tries to convert the target in a perl string, quoted with '. Therefore a ' in the target causes a badly quoted string. 2/ The second problem is a lock problem : if mrtg fails (for example due to the ' problem above), the two lock files CFG_l et CFG_l_$$ are kept, which forbid to restart mrtg. I think that at least the lock file CFG_l_$$ should always be destroyed. If this is done, the second lock will only have 1 link, so it is discarded. Changes 2.5.3 ------------- * more consistant handling of pre and postfix settings in cfg files and lots of fixes to the manual ... thanks to Mark Martinec * correct handling of ifDescrs which contain an = sign ... * better sanitizing of calculated target values * fixed overflow bug with maxx in rateup * BER.pm up to 0.57 SNMP_Session.pm up to 0.58 * fixed writeexpires ... Changes 2.5.2 -------------- * removed NT cron from readme.html ... just too many problems with it ... * make sure no two mrtgs are running at the same time. Locking code for UNIX by Dave Rand, for NT by Tobi (I don't know about NT ...:-) ) testing for the NT version was done by Henry Steinhauer thanks ! * updated to SNMP_Session and BER.pm to their latest versions. * updated get-active contrib From: Wee-Meng LEE * cpumon contrib by Matthew Ramsey * cfgmaker patch from Mike Diehn mdiehn location mindspring.net to make it get Cisco PVC descriptions * Updated mrtg-dynip to 0.41b * mrtg.cfg-dist is now mrtg-conf.html thanks to Matija Grabnar * typo in error messages when external gatherer returns invalid data. Changes 2.5.1 ------------- * Percentages in HTML pages was 8 time to high with the bits option Changes 2.5 ----------- * we want perl 5.003 now. older versions have problems with large numbers ... * better cisco scanning added to cfgmaker ... Carlos Canau * actually remove whitespace at the end of the line ... * BER.pm and SNMPSession.pm with version numbers ... * rewrite of the mailstats script from Petter Reinholdtsen * do only draw the maxbytes line if it is within the actual graph. * NT portability fixes for rateup.c * contrib from Emanuele Leonardi: Script to archive the daily stat-gifs to a separate directory every night ... * fix for Timezone handling ... * another attempt to fix overflows ... and strange behavior of sprintf ... * fixed handling of SNMP errors * Updated SNMP_Session.pm to 0.51 (Better Error Reporting) * made cfgmaker ignore cisco E1 controllers, as their if-descriptions seems not to be reported properly by IOS .... patch from Josh Bailey (mailto:joshb location xtra.co.nz) * Added README.logfile-format by Butch Kemper * update mrtg-pingprobe thanks peter * added atmmaker by Mark Trettin to the contrib section. this is a cfgmaker variant which generates cfgs for the FORE ASX * its suppress and not suppress. Changed this and added backward compatibility. * From: Niels : added Option[] Integer which suppresses the decimal part the summary line below the graphs ... * added --vendor switch to cfgmaker. This enables and disables the vendor specific queries ... * added contrib from Carlos Canau It allows one to make a graph of analog/ISDN lines on a Livingston Portmaster 3. (PMLines) * fixed a longstanding bug where rateup was skewing at log entries not aligned with the normal sampling interval. This happened when ever the NEXT macro was going from one sampling interval onto another one ... thanks to Lane Patterson of GlobalCenter ISI , Erwin Authried and Ari Lewitter * further improved the accuracy for large installations. Mrtg does now get a timestamp down with every reading taken from a router. If we are running a simple target, this timestamp is passed along to rateup with the t option * ircstats contrib by Matt Ramsey added ... * fixed 'current time' passing from mrtg to rateup ... * much improved handling of 'first run' * output for cfgmaker is now sorted alphabeticaly .. (Andres Kroonmaa) * added mrtg-dynip contrib from John Heenan, providing support for environments with dynamic IP addersses ... * Added Contrib to mibhelp.txt * check the output of external gatherers. Are we really being fed a number? * Added PageFoot[] configurable ... Changes 2.4.1 ------------- * fixed external command bug Changes 2.4 ----------- * fixed IconDir ... Carlos Canau * mrtg.cfg-dist debugged and rewritten ... Paul FIscher * mod_expire tip from Stephane Bortzmeyer added to mrtg.cfg-dist * mrtg: large values are not handled by int any more but rather by sprintf "%.0f" * mailstat fixes by Petter Reinholdtsen * added nopercent option as suggested by Frank van Wensveen * added contrib by Philippe.Simonet location SWISSTELECOM.com a c-program to create gifs showing the traffic distribution over time real neat ... Thanks ... * changed chops in mrtg to chomp calls just in case ... * fixed 'external' command parsing in target lines ... Changes 2.3 ----------- Added IconDir configurable, for people who want to keep the mrtg logo in a central location. As suggested by James FitzGibbon Made the period var a double in rateup.c as suggested by Dave Added patch from Paul to cfgmaker now it will try to figure the speed of an interface .... Stooped mrtg from aborting on non existing HOST names Warn on Duplicate CFG entries. Customizable week number thingy from Simon Leinen rateup fix for FreeBSD: FreeBSD does not need malloc.h included. From: Ulf Zimmermann Fix for time chitter by Dave ... new pingprobe from Peter W. Osel relaxed parsing of keywords. ther can be a space before the colon .... as sugested by Samath >From mcm location unx.sas.com Tue Jun 3 07:43:38 1997 Cheanged rateup.c so that it will start scaling the graphs when the datarate is higher than MaxBytes, if the AbsMax value is set. Even when it is operation in unscaled mode ... I also changed 'indexmaker' to allow me to pass in a title, and to support the 'Directory' option in the configuration file. From: Jay Soffian Wed, 04 Jun 1997 15:34:01 -0400 Added new configurables XScale[], YScale[] to really enlarge the graphs and not just make their pixels larger ... Added configurable Step[] to allow for shorter base periods different from 5 Minutes ... But beware, this is NOT supported ... and its likely that you will run into problems ... Updated to latest version of SNMP_Session.pm This will work fine with perl5.002 and above. BUT not with perl 5.001 !!! so if you are still using an old version of perl, use SNMP_Session.pm-for-perl5.001 2.2 --- Added Contribution from Anthony Rumble. For gathering stats for apache webservers and squid proxies From: T. Pospisek SHELL scripts to get active tty(-dial-in modem-) lines localy and remotely. I'm using them with a cyclades board but they can be adapted at wish to different tasks. made graphs in indexmaker generated pages clickable ... leewm location sgp.hp.com added contributet script for gatherig portmaster stats added mrtg-blast contrib from Balthasar T. Indermuehle made mrtg observe order of routers in cfg file .... as suggested by Mick Ghazey Added GetSNMPLinesUP to contrib ... from Carlos Canau this is for monitoring Modembanks ... Added timezone configurable to set a timezone per router. Details in mrtg.cfg-dist as suggested by Jun (John) Wu Added MaxBytes check .... Fixed portability problem of Makefile under IRIX Added sendmail stats contrib from Rachel Polanskis 2.1 --- Added 100BaseVG iftyp to cfgmaker Fixed rounding Bug in rateup.c which caused it to scale graphs with small values incorrectly ... Added rdlog2 by Phillip Simonet. This tool transforms a xfig network map into a clickable gif with colorcoded representation of the current load of your network links. The information for the colorcoding is taken from the mrtg log files. From: "Peter W. Osel" A perl script to get roundtrip delays to hosts by sending a ping to them. Added to contrib. Allowed any character except @ and \s to be used in a community string ... Fixed two instances where variables were declared twice (my($var)) within the same scope. Late perl5.003 versions do not like that ... and it was wrong anyway. This happens both in SNMP_Session.pm and mrtg When using the Directory option in connection with [^] a stray space gets added to the path. This is now removed with s/\s//g ... spaces in path names are stupid anyway. 2.0.1 ----- Fixed ascendget script mrtg-2.17.10/COPYING0000644000175300017510000004307013057016060012703 0ustar oetikeroep GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy 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 of the License, 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., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. mrtg-2.17.10/COPYRIGHT0000644000175300017510000000153713057016060013145 0ustar oetikeroep MRTG - The Multi Router Traffic Grapher. A tool to visualise network traffic via a WebPage. Copyright (c) 1996-2001 Tobias Oetiker and all the Contributers to MRTG All rights reserved. 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 of the License, 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., 675 Mass Ave, Cambridge, MA 02139, USA. mrtg-2.17.10/README0000644000175300017510000000103213057016060012520 0ustar oetikeroepWelcome to MRTG ================================================================== I bet you are eager to get going with the program. All documentation is stored in the doc sub directory. For installing on UNIX, follow the instructions in doc/mrtg-unix-guide.txt If you want to setup MRTG on NT, read doc/mrtg-nt-guide.txt There are many more documents in the doc directory. Look at the doc/mrtg.txt file for an overview. ------------------------------------------------------------------ Tobias Oetiker mrtg-2.17.10/MANIFEST0000644000175300017510000000315014171763062013005 0ustar oetikeroepTHANKS CHANGES COPYING COPYRIGHT README MANIFEST Makefile.in Makefile.Win32 Makefile.NetWare get_ver.awk configure config.h.in mkinstalldirs configure.ac install-sh images/ lib/mrtg2/BER.pm lib/mrtg2/SNMP_Session.pm lib/mrtg2/SNMP_util.pm lib/mrtg2/MRTG_lib.pm lib/mrtg2/Net_SNMP_util.pm lib/mrtg2/locales_mrtg.pm bin/cfgmaker bin/indexmaker bin/mrtg bin/mrtg-traffic-sum lib/mrtg2/Pod/InputObjects.pm lib/mrtg2/Pod/Parser.pm lib/mrtg2/Pod/PlainText.pm lib/mrtg2/Pod/Select.pm lib/mrtg2/Pod/Usage.pm src/rateup.c src/strftime.c src/strftime.h translate/ contrib/ doc/cfgmaker.pod doc/indexmaker.pod doc/mrtg-contrib.pod doc/mrtg-faq.pod doc/mrtg-forum.pod doc/mrtg-ipv6.pod doc/mrtglib.pod doc/mrtg-logfile.pod doc/mrtg-mibhelp.pod doc/mrtg-nt-guide.pod doc/mrtg-nw-guide.pod doc/mrtg.pod doc/mrtg-reference.pod doc/mrtg-rrd.pod doc/mrtg-squid.pod doc/mrtg-traffic-sum.pod doc/mrtg-unix-guide.pod doc/mrtg-webserver.pod doc/rateup.pod doc/cfgmaker.1 doc/indexmaker.1 doc/mrtg-contrib.1 doc/mrtg-faq.1 doc/mrtg-forum.1 doc/mrtg-ipv6.1 doc/mrtglib.3 doc/mrtg-logfile.1 doc/mrtg-mibhelp.1 doc/mrtg-nt-guide.1 doc/mrtg-nw-guide.1 doc/mrtg.1 doc/mrtg-reference.1 doc/mrtg-rrd.1 doc/mrtg-squid.1 doc/mrtg-traffic-sum.1 doc/mrtg-unix-guide.1 doc/mrtg-webserver.1 doc/rateup.1 doc/cfgmaker.txt doc/indexmaker.txt doc/mrtg-contrib.txt doc/mrtg-faq.txt doc/mrtg-forum.txt doc/mrtg-ipv6.txt doc/mrtglib.txt doc/mrtg-logfile.txt doc/mrtg-mibhelp.txt doc/mrtg-nt-guide.txt doc/mrtg-nw-guide.txt doc/mrtg.txt doc/mrtg-reference.txt doc/mrtg-rrd.txt doc/mrtg-squid.txt doc/mrtg-traffic-sum.txt doc/mrtg-unix-guide.txt doc/mrtg-webserver.txt doc/rateup.txtmrtg-2.17.10/Makefile.in0000644000175300017510000001364014171763337013733 0ustar oetikeroep# things that the GNU standards document suggests all makefiles # should have. SHELL=/bin/sh VER=2.17.10 .SUFFIXES: .SUFFIXES: .c .o .pl .pm .pod .man .1 .3 .txt prefix = @prefix@ datarootdir = @datarootdir@ exec_prefix = @exec_prefix@ bindir = @bindir@ libdir = @libdir@ mandir = @mandir@ datadir = @datadir@ top_srcdir = @top_srcdir@ # Where is perl 5 on this machine PERL = @PERL@ CC = @CC@ CFLAGS = @CFLAGS@ @DEFS@ CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ GDFORM_EXT = @GDFORM_EXT@ SET_LD_RUN_PATH = @SET_LD_RUN_PATH@ LIBS = @LIBS@ INSTALL = @INSTALL@ MKINSTALLDIRS = $(SHELL) $(top_srcdir)/mkinstalldirs all: configure bin/rateup subst bin/rateup: bin/rateup.o $(SET_LD_RUN_PATH) $(CC) bin/rateup.o -o bin/rateup $(LDFLAGS) $(LIBS) bin/rateup.o: $(top_srcdir)/src/rateup.c $(CC) $(CPPFLAGS) $(CFLAGS) -c $(top_srcdir)/src/rateup.c -o bin/rateup.o subst: $(PERL) -0777 -p -i~ -e "s'^#!\s*/\S*perl'#! $(PERL)'" $(top_srcdir)/bin/cfgmaker $(top_srcdir)/bin/indexmaker $(top_srcdir)/bin/mrtg $(PERL) -0777 -p -i~ -e 's@GRAPHFMT="...";@GRAPHFMT="$(GDFORM_EXT)";@' $(top_srcdir)/bin/mrtg $(top_srcdir)/bin/indexmaker configure: configure.ac autoreconf --make clean: -rm -f bin/rateup -rm -f bin/rateup.o -rm -f config.cache -rm -f config.h -rm -f config.log -rm -f config.status -rm -f Makefile install: all $(MKINSTALLDIRS) $(DESTDIR)$(bindir) for x in $(top_srcdir)/bin/mrtg $(top_srcdir)/bin/cfgmaker $(top_srcdir)/bin/indexmaker $(top_srcdir)/bin/mrtg-traffic-sum; do \ $(INSTALL) -m 755 $$x $(DESTDIR)$(bindir); done for x in bin/rateup; do \ $(INSTALL) -m 755 $$x $(DESTDIR)$(bindir); done $(MKINSTALLDIRS) $(DESTDIR)$(libdir)/mrtg2/Pod for x in $(top_srcdir)/lib/mrtg2/*.pm; do \ $(INSTALL) -m 644 $$x $(DESTDIR)$(libdir)/mrtg2; done for x in $(top_srcdir)/lib/mrtg2/Pod/*.pm; do \ $(INSTALL) -m 644 $$x $(DESTDIR)$(libdir)/mrtg2/Pod; done $(MKINSTALLDIRS) $(DESTDIR)$(datadir)/mrtg2/icons for x in $(top_srcdir)/images/*.gif $(top_srcdir)/images/*.png; do \ $(INSTALL) -m 644 $$x $(DESTDIR)$(datadir)/mrtg2/icons; done $(MKINSTALLDIRS) $(DESTDIR)$(datadir)/doc/mrtg2 (cd $(top_srcdir); for x in COPYING COPYRIGHT README CHANGES THANKS doc/*; do \ $(INSTALL) -m 644 $$x $(DESTDIR)$(datadir)/doc/mrtg2; done) $(MKINSTALLDIRS) $(DESTDIR)$(mandir)/man1 for x in $(top_srcdir)/doc/*.1; do \ $(INSTALL) -m 644 $$x $(DESTDIR)$(mandir)/man1; done $(MKINSTALLDIRS) $(DESTDIR)$(mandir)/man3 for x in $(top_srcdir)/doc/*.3; do \ $(INSTALL) -m 644 $$x $(DESTDIR)$(mandir)/man3; done ########### Distribution Tools ### ### Things you might NOT want to play with ... ### ARCHIVE = mrtg-$(VER) DIRNAME = mrtg-$(VER) POD1 = doc/mrtg-faq.pod doc/mrtg-logfile.pod doc/mrtg-nt-guide.pod doc/mrtg-nw-guide.pod \ doc/mrtg-unix-guide.pod \ doc/mrtg-forum.pod doc/mrtg-mibhelp.pod doc/mrtg-reference.pod doc/mrtg-webserver.pod \ doc/mrtg-rrd.pod doc/mrtg-squid.pod doc/mrtg.pod doc/mrtg-contrib.pod \ doc/cfgmaker.pod doc/indexmaker.pod doc/mrtg-ipv6.pod doc/mrtg-traffic-sum.pod \ doc/rateup.pod POD3 = doc/mrtglib.pod MAN1 = $(POD1:.pod=.1) MAN3 = $(POD3:.pod=.3) TXT = $(POD1:.pod=.txt) $(POD3:.pod=.txt) getpod: -rm $(MAN1) $(MAN3) $(TXT) -for x in cfgmaker indexmaker mrtg-mailer mrtg-traffic-sum; do \ rm doc/$$x.pod; ln -s ../bin/$$x doc/$$x.pod; done -rm doc/mrtglib.pod;ln -s ../lib/mrtg2/MRTG_lib.pm doc/mrtglib.pod .pod.1: pod2man --release=$(VER) --center=mrtg $< > $@ .pod.3: pod2man --release=$(VER) --center=mrtg --section=3 $< > $@ .1.txt: @NROFF@ -man -Tascii $< > $@ .3.txt: @NROFF@ -man -Tascii $< > $@ man: $(MAN1) $(MAN3) txt: $(TXT) versync: $(PERL) -i -p -e 's|VERSION\s*=\s*"\d+\.\d+\.\d+([a-z0-9]+)?"|VERSION = "$(VER)"|gi; s|mrtg-\d+\.\d+\.\d+([a-z0-9]+)?|mrtg-$(VER)|gi; s|MRTG\s\d+\.\d+\.\d+([a-z0-9]+)?|MRTG $(VER)|gi' bin/mrtg bin/cfgmaker bin/indexmaker lib/mrtg2/*.pm src/*.c `find doc/ -name \*.pod -type f` cd translate && $(PERL) mergelocale.pl skeleton.pm0 *.pmd && cp locales_mrtg.pm ../lib/mrtg2 doc: getpod versync man txt rateupexe: i686-w64-mingw32-gcc -Wall -Wno-format -Wpointer-arith -Wcast-align -Wmissing-declarations -Wnested-externs -O3 -mwindows -Ilibs-i386-mingw32msvc/zlib -Ilibs-i386-mingw32msvc/libpng -Ilibs-i386-mingw32msvc/gd -c src/strftime.c -o src/strftime.o i686-w64-mingw32-gcc -Wall -Wno-format -Wpointer-arith -Wcast-align -Wmissing-declarations -Wnested-externs -O3 -mwindows -Ilibs-i386-mingw32msvc/zlib -Ilibs-i386-mingw32msvc/libpng -Ilibs-i386-mingw32msvc/gd -c src/rateup.c -o src/rateup.o -Dstrftime=strftime_ i686-w64-mingw32-gcc -Llibs-i386-mingw32msvc/zlib -Llibs-i386-mingw32msvc/libpng -Llibs-i386-mingw32msvc/gd src/rateup.o src/strftime.o -o bin/rateup.exe -lgd -lpng -lz i686-w64-mingw32-strip bin/rateup.exe tar: doc rateupexe autoconf chmod -R u=rwX,go=rX . (cd .. ; ln -s src $(DIRNAME)) (cd .. ; sed -e "s/^/$(DIRNAME)\//" $(DIRNAME)/MANIFEST | tar --exclude='*~' --exclude="*.rej" --exclude="*.orig" --exclude=".svn" -czv --files-from=- -f $(DIRNAME)/$(ARCHIVE).tar.gz) $(PERL) -0777 -pi -e 's@GRAPHFMT="...";@GRAPHFMT="png";@' bin/mrtg bin/indexmaker # build rateup for windows ... (cd .. ; touch $(DIRNAME)/contrib/a~;sed -e "s/^/$(DIRNAME)\//" $(DIRNAME)/MANIFEST | xargs zip -r $(DIRNAME)/$(ARCHIVE).zip; zip $(DIRNAME)/$(ARCHIVE).zip $(DIRNAME)/bin/rateup.exe $(DIRNAME)/bin/rateup.nlm $(DIRNAME)/bin/rateup.nlm; zip -d $(DIRNAME)/$(ARCHIVE).zip '*~' '*.svn*') -rm ../$(DIRNAME) dist: tar git commit -m 'released version $(VER)' -a git tag v$(VER) git push --tags md5sum $(ARCHIVE).tar.gz >$(ARCHIVE).tar.gz.md5 # gpg -s $(ARCHIVE).tar.gz.md5 # chmod 644 $(ARCHIVE).tar.gz.md5* scp CHANGES $(ARCHIVE).* oposs@freddie:public_html/mrtg/pub/ ssh oposs@freddie "cd public_html/mrtg/pub; rm mrtg.tar.gz;ln -s $(ARCHIVE).tar.gz mrtg.tar.gz" betadist: tar mv $(ARCHIVE).* ${HOME}/public_html/webtools/mrtg/pub/beta cp CHANGES ${HOME}/public_html/webtools/mrtg/pub/beta mrtg-2.17.10/Makefile.Win320000644000175300017510000002014713057016060014211 0ustar oetikeroep# GNU Makefile for Win32 rateup.exe target * 17-Feb-2007 # for use with MingW32 gcc or Metrowerks CodeWarrior compiler # use with: make -f Makefile.Win32 [all|clean|dist|distclean|help] TARGET = rateup DESCR = MRTG Rateup Command Utility $(RATEUP_VERSION_STR) COPYR = Distributed under the GNU General Public License WWWURL = http://www.mrtg.org/ # If you want to link with an icon you can specify here... LNKICON = images/favicon.ico # Edit the path below to point to your install destination (for 'install' option.) ifndef INSTDIR INSTDIR = c:/mrtg/run endif # All library code is statically linked to avoid problems with other lib NLMs. # Base for the lib sources ifndef LIBBASE LIBBASE = .. endif # All library code is statically linked to avoid problems with other lib DLLs. # Edit the path below to point to your libgd sources or set environment var. ifndef LIBGD LIBGD = $(LIBBASE)/gd-2.0.34 endif # Edit the path below to point to your libpng sources or set environment var. ifndef LIBPNG LIBPNG = $(LIBBASE)/libpng-1.2.16 endif # Edit the path below to point to your zlib sources or set environment var. ifndef ZLIBSDK ZLIBSDK = $(LIBBASE)/zlib-1.2.3 endif # The following line defines your compiler. ifdef METROWERKS CC = mwcc else CC = gcc endif AWK = awk # RM = rm -f CP = cp -fav # MV = mv -f ZIP = zip -qzR9 ARCHIVE = rateup-$(RATEUP_VERSION_STR)-w32.zip # must be equal to DEBUG or NDEBUG DB = NDEBUG # DB = DEBUG # Optimization: -O or debugging: -g ifeq ($(DB),NDEBUG) OPT = -O2 OBJDIR = release else OPT = -g OBJDIR = debug endif # Include the version info retrieved from source. -include $(OBJDIR)/version.inc # Global flags for all compilers CFLAGS = $(OPT) -D$(DB) -DHAVE_LIBPNG -DNONDLL ifeq ($(CC),mwcc) LD = mwld CFLAGS += -nostdinc -gccinc -msgstyle gcc -inline off -opt nointrinsics -proc 586 CFLAGS += -relax_pointers #CFLAGS += -w on,nounused,nounusedexpr #CFLAGS += -ansi strict CFLAGS += -ir "$(METROWERKS)/MSL" -ir "$(METROWERKS)/Win32-x86 Support" LD = mwld RC = mwwinrc LDFLAGS = -nostdlib LIBPATH += -lr "$(METROWERKS)/MSL" -lr "$(METROWERKS)/Win32-x86 Support" LDLIBS += -lkernel32.lib -luser32.lib LDLIBS += -lMSL_Runtime_x86.lib -lMSL_C_x86.lib -lMSL_Extras_x86.lib RCFLAGS = else LD = gcc RC = windres LDFLAGS = -s RCFLAGS = -O coff -i CFLAGS += -fno-strict-aliasing CFLAGS += -Wall -Wno-format # -Wno-unused # -pedantic endif ifeq ($(findstring msys,$(OSTYPE)),msys) DL = ' DS = / else DS = \\ endif ifndef COPYR COPYR = Copyright (c) 2007 The Open Source Community. endif ifndef DESCR DESCR = $(TARGET) Command Extension endif DESCR += - $(CC) build INCLUDES += -I$(LIBGD) -I$(LIBPNG) -I$(ZLIBSDK) CFLAGS += $(INCLUDES) vpath %.c src $(LIBGD) $(LIBPNG) $(ZLIBSDK) GDOBJS = \ $(OBJDIR)/gd.o \ $(OBJDIR)/gd_io.o \ $(OBJDIR)/gd_io_dp.o \ $(OBJDIR)/gd_io_file.o \ $(OBJDIR)/gd_io_ss.o \ $(OBJDIR)/gd_png.o \ $(OBJDIR)/gd_ss.o \ $(OBJDIR)/gdcache.o \ $(OBJDIR)/gdfonts.o \ $(OBJDIR)/gdhelpers.o \ $(OBJDIR)/gdtables.o \ $(EOLIST) ifeq "$(wildcard $(LIBGD)/gd_security.c)" "$(LIBGD)/gd_security.c" GDOBJS += \ $(OBJDIR)/gd_security.o \ $(EOLIST) endif PNGOBJS = \ $(OBJDIR)/png.o \ $(OBJDIR)/pngerror.o \ $(OBJDIR)/pnggccrd.o \ $(OBJDIR)/pngget.o \ $(OBJDIR)/pngmem.o \ $(OBJDIR)/pngpread.o \ $(OBJDIR)/pngread.o \ $(OBJDIR)/pngrio.o \ $(OBJDIR)/pngrtran.o \ $(OBJDIR)/pngrutil.o \ $(OBJDIR)/pngset.o \ $(OBJDIR)/pngtrans.o \ $(OBJDIR)/pngvcrd.o \ $(OBJDIR)/pngwio.o \ $(OBJDIR)/pngwrite.o \ $(OBJDIR)/pngwtran.o \ $(OBJDIR)/pngwutil.o \ $(EOLIST) ZLIBOBJS = \ $(OBJDIR)/adler32.o \ $(OBJDIR)/compress.o \ $(OBJDIR)/crc32.o \ $(OBJDIR)/deflate.o \ $(OBJDIR)/inflate.o \ $(OBJDIR)/inffast.o \ $(OBJDIR)/inftrees.o \ $(OBJDIR)/trees.o \ $(OBJDIR)/zutil.o \ $(EOLIST) ifeq "$(wildcard $(ZLIBSDK)/infblock.c)" "$(ZLIBSDK)/infblock.c" ZLIBOBJS += \ $(OBJDIR)/infblock.o \ $(OBJDIR)/infcodes.o \ $(OBJDIR)/infutil.o \ $(EOLIST) endif OBJS = $(GDOBJS) $(PNGOBJS) $(ZLIBOBJS) $(OBJDIR)/$(TARGET).o ifndef NO_OWN_STRFTIME OBJS += $(OBJDIR)/strftime.o DEFS = -Dstrftime=strftime_ endif all: $(OBJDIR) $(OBJDIR)/$(TARGET).exe dist: all $(OBJDIR)/readme.txt -$(RM) $(OBJDIR)/*.o $(OBJDIR)/$(TARGET).map $(OBJDIR)/$(TARGET).ncv -$(RM) $(OBJDIR)/$(TARGET).def $(OBJDIR)/$(TARGET).res $(OBJDIR)/$(TARGET).rc -$(RM) $(OBJDIR)/version.inc @-$(CP) -a COPYRIGHT $(OBJDIR) @echo Creating $(ARCHIVE) @$(ZIP) $(ARCHIVE) $(OBJDIR)/* < $(OBJDIR)/readme.txt install: all @[ -d $(INSTDIR) ] || mkdir $(INSTDIR) @$(CP) $(TARGET).exe $(INSTDIR) clean: -$(RM) -r $(OBJDIR) distclean: clean -$(RM) $(ARCHIVE) $(OBJDIR): @mkdir $@ $(OBJDIR)/version.inc: $(TARGET).c $(OBJDIR) @echo Creating $@ @$(AWK) -f get_ver.awk $< > $@ $(OBJDIR)/$(TARGET).o: $(TARGET).c @echo Compiling $< @$(CC) $(CFLAGS) $(DEFS) -c $< -o $@ $(OBJDIR)/%.o: %.c @echo Compiling $< @$(CC) $(CFLAGS) -c $< -o $@ $(OBJDIR)/$(TARGET).exe: $(OBJS) $(OBJDIR)/$(TARGET).res @echo Linking $@ @-$(RM) $@ @$(LD) $(LDFLAGS) $^ -o $@ $(LIBPATH) $(LDLIBS) $(OBJDIR)/%.res: $(OBJDIR)/%.rc @echo Creating $@ @$(RC) $(RCFLAGS) $< -o $@ $(OBJDIR)/%.rc: Makefile.Win32 $(OBJDIR)/version.inc @echo $(DL)1 VERSIONINFO$(DL) > $@ @echo $(DL) FILEVERSION $(RATEUP_VERSION),0$(DL) >> $@ @echo $(DL) PRODUCTVERSION $(RATEUP_VERSION),0$(DL) >> $@ @echo $(DL) FILEFLAGSMASK 0x3fL$(DL) >> $@ @echo $(DL) FILEOS 0x40004L$(DL) >> $@ @echo $(DL) FILEFLAGS 0x0L$(DL) >> $@ @echo $(DL) FILETYPE 0x1L$(DL) >> $@ @echo $(DL) FILESUBTYPE 0x0L$(DL) >> $@ @echo $(DL)BEGIN$(DL) >> $@ @echo $(DL) BLOCK "StringFileInfo"$(DL) >> $@ @echo $(DL) BEGIN$(DL) >> $@ @echo $(DL) BLOCK "040904E4"$(DL) >> $@ @echo $(DL) BEGIN$(DL) >> $@ @echo $(DL) VALUE "LegalCopyright","$(COPYR)\0"$(DL) >> $@ ifdef COMPANY @echo $(DL) VALUE "CompanyName","$(COMPANY)\0"$(DL) >> $@ endif @echo $(DL) VALUE "ProductName","$(notdir $(@:.rc=.exe))\0"$(DL) >> $@ @echo $(DL) VALUE "ProductVersion","$(RATEUP_VERSION_STR)\0"$(DL) >> $@ @echo $(DL) VALUE "License","Released under GPL.\0"$(DL) >> $@ @echo $(DL) VALUE "FileDescription","$(DESCR)\0"$(DL) >> $@ @echo $(DL) VALUE "FileVersion","$(RATEUP_VERSION_STR)\0"$(DL) >> $@ @echo $(DL) VALUE "InternalName","$(notdir $(@:.rc=))\0"$(DL) >> $@ @echo $(DL) VALUE "OriginalFilename","$(notdir $(@:.rc=.exe))\0"$(DL) >> $@ ifdef WWWURL @echo $(DL) VALUE "WWW","$(WWWURL)\0"$(DL) >> $@ endif @echo $(DL) END$(DL) >> $@ @echo $(DL) END$(DL) >> $@ @echo $(DL) BLOCK "VarFileInfo"$(DL) >> $@ @echo $(DL) BEGIN$(DL) >> $@ @echo $(DL) VALUE "Translation", 0x409, 1252$(DL) >> $@ @echo $(DL) END$(DL) >> $@ @echo $(DL)END$(DL) >> $@ ifdef LNKICON @echo $(DL)10 ICON DISCARDABLE "$(LNKICON)"$(DL) >> $@ endif $(OBJDIR)/readme.txt: Makefile.Win32 $(OBJDIR)/version.inc @echo Creating $@ @echo $(DL)This is a binary distribution for Win32 platform.$(DL) > $@ @echo $(DL)MRTG rateup version $(RATEUP_VERSION_STR)$(DL) >> $@ @echo $(DL)This binary was built with these libs:$(DL) >> $@ @echo $(DL)libpng Version : $(notdir $(LIBPNG))$(DL) >> $@ @echo $(DL)libGD Version : $(notdir $(LIBGD))$(DL) >> $@ @echo $(DL)Zlib Version : $(notdir $(ZLIBSDK))$(DL) >> $@ @echo $(DL)Please download the complete MRTG package for$(DL) >> $@ @echo $(DL)any further documentation:$(DL) >> $@ @echo $(DL)http://www.mrtg.org/$(DL) >> $@ help: $(OBJDIR)/version.inc @echo $(DL)===========================================================$(DL) @echo $(DL)libpng Source = $(LIBPNG)$(DL) @echo $(DL)libGD Source = $(LIBGD)$(DL) @echo $(DL)Zlib SDK = $(ZLIBSDK)$(DL) @echo $(DL)===========================================================$(DL) @echo $(DL)RRDTool $(RATEUP_VERSION_STR) - available targets are:$(DL) @echo $(DL)$(MAKE) all$(DL) @echo $(DL)$(MAKE) clean$(DL) @echo $(DL)$(MAKE) dist$(DL) @echo $(DL)$(MAKE) distclean$(DL) @echo $(DL)===========================================================$(DL) mrtg-2.17.10/Makefile.NetWare0000644000175300017510000002237413057016060014660 0ustar oetikeroep# Gnu Makefile for NetWare rateup.nlm target * 17-Feb-2007 # for use with gcc/nlmconv or Metrowerks CodeWarrior compiler # use with: make -f Makefile.NetWare [all|clean|dist|distclean|help] TARGET = rateup DESCR = MRTG Rateup Command Utility $(RATEUP_VERSION_STR) COPYR = Distributed under the GNU General Public License WWWURL = http://www.mrtg.org/ MTSAFE = YES #SCREEN = NONE STACK = 65536 # Comment the line below if you dont want to load protected automatically. #LDRING = 3 # Edit the path below to point to your Novell NDK. ifndef NDKBASE NDKBASE = c:/novell endif # Edit the path below to point to your install destination. ifndef INSTDIR INSTDIR = s:/mrtg/run endif # All library code is statically linked to avoid problems with other lib NLMs. # Base for the lib sources ifndef LIBBASE LIBBASE = .. endif # All library code is statically linked to avoid problems with other lib NLMs. # Edit the path below to point to your libgd sources or set environment var. ifndef LIBGD LIBGD = $(LIBBASE)/gd-2.0.34 endif # Edit the path below to point to your libpng sources or set environment var. ifndef LIBPNG LIBPNG = $(LIBBASE)/libpng-1.2.16 endif # Edit the path below to point to your zlib sources or set environment var. ifndef ZLIBSDK ZLIBSDK = $(LIBBASE)/zlib-1.2.3 endif # Edit the var below to point to your library architecture. ifndef LIBARCH # LIBARCH = CLIB LIBARCH = LIBC endif # The following defines your compiler. ifdef METROWERKS CC = mwccnlm else CC = gcc endif AWK = awk #RM = rm -f CP = cp -afv MV = mv -f ZIP = zip -qzR9 ARCHIVE = rateup-$(RATEUP_VERSION_STR)-nw.zip # If you want to mark the target as MTSAFE you will need a tool for # generating the xdc data for the linker; here's a minimal tool: # http://www.gknw.de/development/prgtools/mkxdc.zip MPKXDC = mkxdc # Must be equal to DEBUG or NDEBUG DB = NDEBUG #DB = DEBUG # Optimization: -O or debugging: -g ifeq ($(DB),NDEBUG) OPT = -O2 OBJDIR = release else OPT = -g OBJDIR = debug endif # Include the version info retrieved from source. -include $(OBJDIR)/version.inc # Global flags for all compilers CFLAGS = $(OPT) -D$(DB) -nostdinc -DNETWARE -DN_PLAT_NLM -DHAVE_LIBPNG ifeq ($(CC),mwccnlm) LD = mwldnlm LDFLAGS = -nostdlib $(PRELUDE) $(OBJDIR)/*.o -o $@ -commandfile CFLAGS += -gccinc -msgstyle gcc -inline off -opt nointrinsics -proc 586 CFLAGS += -relax_pointers #CFLAGS += -w on,nounused,nounusedexpr #CFLAGS += -ansi strict ifeq ($(LIBARCH),LIBC) PRELUDE = $(SDK_LIBC)/imports/libcpre.o CFLAGS += -align 4 else PRELUDE = "$(METROWERKS)/Novell Support/libraries/runtime/prelude.obj" CFLAGS += -include "$(METROWERKS)/Novell Support/headers/nlm_prefix.h" CFLAGS += -align 1 endif else LD = nlmconv LDFLAGS = -T CFLAGS += -fno-builtin -fpcc-struct-return -fno-strict-aliasing CFLAGS += -Wall # -Wno-unused # -pedantic ifeq ($(LIBARCH),LIBC) PRELUDE = $(SDK_LIBC)/imports/libcpre.gcc.o else PRELUDE = $(NDK_ROOT)/pre/prelude.o CFLAGS += -include $(NDKBASE)/nlmconv/genlm.h endif endif ifeq ($(findstring linux,$(OSTYPE)),linux) DL = ' DS = / else DS = \\ endif ifeq ($(MTSAFE),YES) XDCOPT = -n endif ifeq ($(MTSAFE),NO) XDCOPT = -u endif ifdef XDCOPT XDCDATA = $(OBJDIR)/$(TARGET).xdc endif ifndef COPYR COPYR = Copyright (c) 2007 The Open Source Community. endif ifndef DESCR DESCR = $(TARGET) Command Extension endif DESCR += ($(LIBARCH)) - $(CC) build NDK_ROOT = $(NDKBASE)/ndk SDK_CLIB = $(NDK_ROOT)/nwsdk SDK_LIBC = $(NDK_ROOT)/libc ifeq ($(LIBARCH),LIBC) INCLUDES = -I$(SDK_LIBC)/include -I$(SDK_LIBC)/include/nks else INCLUDES = -I$(SDK_CLIB)/include/nlm -I$(SDK_CLIB)/include endif INCLUDES += -I$(LIBGD) -I$(LIBPNG) -I$(ZLIBSDK) CFLAGS += $(INCLUDES) vpath %.c src $(LIBGD) $(LIBPNG) $(ZLIBSDK) GDOBJS = \ $(OBJDIR)/gd.o \ $(OBJDIR)/gd_io.o \ $(OBJDIR)/gd_io_dp.o \ $(OBJDIR)/gd_io_file.o \ $(OBJDIR)/gd_io_ss.o \ $(OBJDIR)/gd_png.o \ $(OBJDIR)/gd_ss.o \ $(OBJDIR)/gdcache.o \ $(OBJDIR)/gdfonts.o \ $(OBJDIR)/gdhelpers.o \ $(OBJDIR)/gdtables.o \ $(EOLIST) ifeq "$(wildcard $(LIBGD)/gd_security.c)" "$(LIBGD)/gd_security.c" GDOBJS += \ $(OBJDIR)/gd_security.o \ $(EOLIST) endif PNGOBJS = \ $(OBJDIR)/png.o \ $(OBJDIR)/pngerror.o \ $(OBJDIR)/pnggccrd.o \ $(OBJDIR)/pngget.o \ $(OBJDIR)/pngmem.o \ $(OBJDIR)/pngpread.o \ $(OBJDIR)/pngread.o \ $(OBJDIR)/pngrio.o \ $(OBJDIR)/pngrtran.o \ $(OBJDIR)/pngrutil.o \ $(OBJDIR)/pngset.o \ $(OBJDIR)/pngtrans.o \ $(OBJDIR)/pngvcrd.o \ $(OBJDIR)/pngwio.o \ $(OBJDIR)/pngwrite.o \ $(OBJDIR)/pngwtran.o \ $(OBJDIR)/pngwutil.o \ $(EOLIST) ZLIBOBJS = \ $(OBJDIR)/adler32.o \ $(OBJDIR)/compress.o \ $(OBJDIR)/crc32.o \ $(OBJDIR)/deflate.o \ $(OBJDIR)/inflate.o \ $(OBJDIR)/inffast.o \ $(OBJDIR)/inftrees.o \ $(OBJDIR)/trees.o \ $(OBJDIR)/zutil.o \ $(EOLIST) ifeq "$(wildcard $(ZLIBSDK)/infblock.c)" "$(ZLIBSDK)/infblock.c" ZLIBOBJS += \ $(OBJDIR)/infblock.o \ $(OBJDIR)/infcodes.o \ $(OBJDIR)/infutil.o \ $(EOLIST) endif OBJS = $(GDOBJS) $(PNGOBJS) $(ZLIBOBJS) $(OBJDIR)/$(TARGET).o all: $(OBJDIR) $(OBJDIR)/$(TARGET).nlm dist: all $(OBJDIR)/readme.txt -$(RM) $(OBJDIR)/*.o $(OBJDIR)/$(TARGET).map $(OBJDIR)/$(TARGET).ncv -$(RM) $(OBJDIR)/$(TARGET).def $(XDCDATA) -$(RM) $(OBJDIR)/version.inc @-$(CP) -a COPYRIGHT $(OBJDIR) @echo Creating $(ARCHIVE) @$(ZIP) $(ARCHIVE) $(OBJDIR)/* < $(OBJDIR)/readme.txt install: all @[ -d $(INSTDIR) ] || mkdir $(INSTDIR) @$(CP) $(TARGET).nlm $(INSTDIR) clean: -$(RM) -r $(OBJDIR) distclean: clean -$(RM) $(ARCHIVE) $(OBJDIR): @mkdir $@ $(OBJDIR)/version.inc: $(TARGET).c $(OBJDIR) get_ver.awk @echo Creating $@ @$(AWK) -f get_ver.awk $< > $@ $(OBJDIR)/%.o: %.c @echo Compiling $< @$(CC) $(CFLAGS) -c $< -o $@ $(OBJDIR)/$(TARGET).nlm: $(OBJDIR) $(OBJS) $(OBJDIR)/$(TARGET).def $(XDCDATA) @echo Linking $@ @-$(RM) $@ @$(LD) $(LDFLAGS) $(OBJDIR)/$(TARGET).def ifeq ($(LD),nlmconv) @$(MV) $(TARGET).nlm $(OBJDIR) endif $(OBJDIR)/%.xdc: Makefile.NetWare @echo Creating $@ @$(MPKXDC) $(XDCOPT) $@ $(OBJDIR)/%.def: Makefile.NetWare $(OBJDIR)/version.inc @echo $(DL)# DEF Linker File for use with gcc and nlmconv$(DL) > $@ @echo $(DL)# or with Codewarrior command line compiler.$(DL) >> $@ @echo $(DL)# Do not edit this file - it is created by make!$(DL) >> $@ @echo $(DL)# All your changes will be lost!!$(DL) >> $@ @echo $(DL)#$(DL) >> $@ @echo $(DL)copyright "$(COPYR)"$(DL) >> $@ @echo $(DL)description "$(DESCR)"$(DL) >> $@ @echo $(DL)version $(RATEUP_VERSION)$(DL) >> $@ ifdef NLMTYPE @echo $(DL)type $(NLMTYPE)$(DL) >> $@ else @echo $(DL)type 0$(DL) >> $@ endif ifdef STACK @echo $(DL)stack $(STACK)$(DL) >> $@ endif @echo $(DL)threadname "$(TARGET)"$(DL) >> $@ ifdef SCREEN @echo $(DL)screenname "$(SCREEN)"$(DL) >> $@ else @echo $(DL)screenname "DEFAULT"$(DL) >> $@ endif ifeq ($(DB),DEBUG) @echo $(DL)debug$(DL) >> $@ endif ifeq ($(LIBARCH),CLIB) @echo $(DL)start _Prelude$(DL) >> $@ @echo $(DL)exit _Stop$(DL) >> $@ @echo $(DL)import @$(NDK_ROOT)/nwsdk/imports/clib.imp$(DL) >> $@ @echo $(DL)import @$(NDK_ROOT)/nwsdk/imports/threads.imp$(DL) >> $@ @echo $(DL)import @$(NDK_ROOT)/nwsdk/imports/nlmlib.imp$(DL) >> $@ @echo $(DL)module clib$(DL) >> $@ else @echo $(DL)start _LibCPrelude$(DL) >> $@ @echo $(DL)exit _LibCPostlude$(DL) >> $@ @echo $(DL)check _LibCCheckUnload$(DL) >> $@ @echo $(DL)import @$(NDK_ROOT)/libc/imports/libc.imp$(DL) >> $@ @echo $(DL)import @$(NDK_ROOT)/libc/imports/netware.imp$(DL) >> $@ @echo $(DL)module libc$(DL) >> $@ @echo $(DL)pseudopreemption$(DL) >> $@ @echo $(DL)flag_on 64$(DL) >> $@ endif ifeq ($(LDRING),0) @echo $(DL)flag_on 16$(DL) >> $@ endif ifeq ($(LDRING),3) @echo $(DL)flag_on 512$(DL) >> $@ endif ifdef XDCDATA @echo $(DL)xdcdata $(XDCDATA)$(DL) >> $@ endif ifeq ($(LD),nlmconv) @echo $(DL)input $(OBJS)$(DL) >> $@ @echo $(DL)input $(PRELUDE)$(DL) >> $@ @echo $(DL)output $(TARGET).nlm$(DL) >> $@ endif $(OBJDIR)/readme.txt: Makefile.NetWare $(OBJDIR)/version.inc @echo Creating $@ @echo $(DL)This is a binary distribution for NetWare platform.$(DL) > $@ @echo $(DL)MRTG rateup version $(RATEUP_VERSION_STR)$(DL) >> $@ @echo $(DL)This binary was built with these libs:$(DL) >> $@ @echo $(DL)libpng Version : $(notdir $(LIBPNG))$(DL) >> $@ @echo $(DL)libGD Version : $(notdir $(LIBGD))$(DL) >> $@ @echo $(DL)Zlib Version : $(notdir $(ZLIBSDK))$(DL) >> $@ @echo $(DL)Please download the complete MRTG package for$(DL) >> $@ @echo $(DL)any further documentation:$(DL) >> $@ @echo $(DL)http://www.mrtg.org/$(DL) >> $@ help: $(OBJDIR)/version.inc @echo $(DL)===========================================================$(DL) @echo $(DL)libpng Source = $(LIBPNG)$(DL) @echo $(DL)libGD Source = $(LIBGD)$(DL) @echo $(DL)Zlib SDK = $(ZLIBSDK)$(DL) @echo $(DL)===========================================================$(DL) @echo $(DL)RRDTool $(RATEUP_VERSION_STR) - available targets are:$(DL) @echo $(DL)$(MAKE) all$(DL) @echo $(DL)$(MAKE) clean$(DL) @echo $(DL)$(MAKE) dist$(DL) @echo $(DL)$(MAKE) distclean$(DL) @echo $(DL)===========================================================$(DL) mrtg-2.17.10/get_ver.awk0000644000175300017510000000067613057016062014016 0ustar oetikeroep# fetch rateup version number from input file and write them to STDOUT BEGIN { while ((getline < ARGV[1]) > 0) { if (match ($0, /VERSION = "[^"]+"/)) { rateup_ver_str = substr($4, 2, length($4) - 3); split(rateup_ver_str, v, "."); gsub("[^0-9].*$", "", v[3]); rateup_ver = v[1] "," v[2] "," v[3]; } } print "RATEUP_VERSION = " rateup_ver ""; print "RATEUP_VERSION_STR = " rateup_ver_str ""; } mrtg-2.17.10/configure0000755000175300017510000046323214171763343013600 0ustar oetikeroep#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME= PACKAGE_TARNAME= PACKAGE_VERSION= PACKAGE_STRING= PACKAGE_BUGREPORT= PACKAGE_URL= ac_unique_file="src/rateup.c" ac_default_prefix=/opt/mrtg-2 # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='LTLIBOBJS LIBOBJS SET_LD_RUN_PATH GDFORM_EXT RRD_PERL EGREP GREP NROFF PERL INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM SET_MAKE CPP OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir runstatedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking with_gd with_gd_lib with_gd_inc with_z with_z_lib with_z_inc with_png with_png_lib with_png_inc ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= 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=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -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_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$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 ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$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 | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$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 ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) 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 | -n) 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 ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -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_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=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 ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # 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 the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` 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 test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # 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 <<_ACEOF \`configure' configures this package to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then cat <<\_ACEOF Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-gd=DIR location of the gd lib/inc --with-gd-lib=DIR location of the gd library --with-gd-inc=DIR location of the gd include files --with-z=DIR location of zlib lib/inc --with-z-lib=DIR location of zlib library --with-z-inc=DIR location of the zlib include files --with-png=DIR location of png lib/inc --with-png-lib=DIR location of png library --with-png-inc=DIR location of the libpng include files Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF configure generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" 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 elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # 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 # AmigaOS /C/install, which installs bootblocks on floppy discs # 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" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /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 for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir 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. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&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}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' # Extract the first word of "perl", so it can be a program name with args. set dummy perl; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PERL+:} false; then : $as_echo_n "(cached) " >&6 else case $PERL in [\\/]* | ?:[\\/]*) ac_cv_path_PERL="$PERL" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="$PATH:/usr/bin:/usr/local/bin" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PERL="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_PERL" && ac_cv_path_PERL="no" ;; esac fi PERL=$ac_cv_path_PERL if test -n "$PERL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5 $as_echo "$PERL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test $PERL = no; then echo echo "** No Perl found in the PATH. A recent copy of Perl" echo " is required for mrtg to work. Check www.perl.com" echo exit 1 fi for ac_prog in groff nroff do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_NROFF+:} false; then : $as_echo_n "(cached) " >&6 else case $NROFF in [\\/]* | ?:[\\/]*) ac_cv_path_NROFF="$NROFF" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_NROFF="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi NROFF=$ac_cv_path_NROFF if test -n "$NROFF"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NROFF" >&5 $as_echo "$NROFF" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$NROFF" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in inttypes.h do : ac_fn_c_check_header_mongrel "$LINENO" "inttypes.h" "ac_cv_header_inttypes_h" "$ac_includes_default" if test "x$ac_cv_header_inttypes_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_INTTYPES_H 1 _ACEOF fi done ac_fn_c_check_type "$LINENO" "unsigned long long" "ac_cv_type_unsigned_long_long" "$ac_includes_default" if test "x$ac_cv_type_unsigned_long_long" = xyes; then : fi ac_fn_c_check_type "$LINENO" "long long" "ac_cv_type_long_long" "$ac_includes_default" if test "x$ac_cv_type_long_long" = xyes; then : fi for ac_func in strtoll do : ac_fn_c_check_func "$LINENO" "strtoll" "ac_cv_func_strtoll" if test "x$ac_cv_func_strtoll" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRTOLL 1 _ACEOF fi done # Taken from libIDL-0.8.2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for printf long long format specifier" >&5 $as_echo_n "checking for printf long long format specifier... " >&6; } if ${mr_cv_long_long_format_specifier+:} false; then : $as_echo_n "(cached) " >&6 else for format in ll l q I64; do if test "$cross_compiling" = yes; then : { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run test program while cross compiling See \`config.log' for more details" "$LINENO" 5; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main() { long long b, a = -0x3AFAFAFAFAFAFAFALL; char buffer[1000]; sprintf (buffer, "%${format}u", a); sscanf (buffer, "%${format}u", &b); exit (b!=a); } _ACEOF if ac_fn_c_try_run "$LINENO"; then : mr_cv_long_long_format_specifier="%${format}d" mr_cv_long_long_format="${format}d" break fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $mr_cv_long_long_format_specifier" >&5 $as_echo "$mr_cv_long_long_format_specifier" >&6; } cat >>confdefs.h <<_ACEOF #define LLD "$mr_cv_long_long_format_specifier" _ACEOF cat >>confdefs.h <<_ACEOF #define LLD_FORMAT "$mr_cv_long_long_format" _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pow in -lm" >&5 $as_echo_n "checking for pow in -lm... " >&6; } if ${ac_cv_lib_m_pow+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pow (); int main () { return pow (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_m_pow=yes else ac_cv_lib_m_pow=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_pow" >&5 $as_echo "$ac_cv_lib_m_pow" >&6; } if test "x$ac_cv_lib_m_pow" = xyes; then : MATHLIBS="-lm" fi # Check whether --with-gd was given. if test "${with_gd+set}" = set; then : withval=$with_gd; LDFLAGS="${LDFLAGS} -L${withval}" CPPFLAGS="${CPPFLAGS} -I${withval}" LD_RUN_PATH="${withval}${LD_RUN_PATH:+:}${LD_RUN_PATH}" fi # Check whether --with-gd-lib was given. if test "${with_gd_lib+set}" = set; then : withval=$with_gd_lib; LDFLAGS="${LDFLAGS} -L${withval}" LD_RUN_PATH="${withval}${LD_RUN_PATH:+:}${LD_RUN_PATH}" fi # Check whether --with-gd-inc was given. if test "${with_gd_inc+set}" = set; then : withval=$with_gd_inc; CPPFLAGS="${CPPFLAGS} -I${withval}" fi # Check whether --with-z was given. if test "${with_z+set}" = set; then : withval=$with_z; LDFLAGS="${LDFLAGS} -L${withval}" CPPFLAGS="${CPPFLAGS} -I${withval}" LD_RUN_PATH="${withval}${LD_RUN_PATH:+:}${LD_RUN_PATH}" fi # Check whether --with-z-lib was given. if test "${with_z_lib+set}" = set; then : withval=$with_z_lib; LDFLAGS="${LDFLAGS} -L${withval}" LD_RUN_PATH="${withval}${LD_RUN_PATH:+:}${LD_RUN_PATH}" fi # Check whether --with-z-inc was given. if test "${with_z_inc+set}" = set; then : withval=$with_z_inc; CPPFLAGS="${CPPFLAGS} -I${withval}" fi # Check whether --with-png was given. if test "${with_png+set}" = set; then : withval=$with_png; LDFLAGS="${LDFLAGS} -L${withval}" CPPFLAGS="${CPPFLAGS} -I${withval}" LD_RUN_PATH="${withval}${LD_RUN_PATH:+:}${LD_RUN_PATH}" fi # Check whether --with-png-lib was given. if test "${with_png_lib+set}" = set; then : withval=$with_png_lib; LDFLAGS="${LDFLAGS} -L${withval}" LD_RUN_PATH="${withval}${LD_RUN_PATH:+:}${LD_RUN_PATH}" fi # Check whether --with-png-inc was given. if test "${with_png_inc+set}" = set; then : withval=$with_png_inc; CPPFLAGS="${CPPFLAGS} -I${withval}" fi LIBS="${LIBS} ${MATHLIBS}" GDEXTRALIB="" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gdImageGif in -lgd" >&5 $as_echo_n "checking for gdImageGif in -lgd... " >&6; } if ${ac_cv_lib_gd_gdImageGif+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgd -lgd ${MATHLIBS} $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gdImageGif (); int main () { return gdImageGif (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_gd_gdImageGif=yes else ac_cv_lib_gd_gdImageGif=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gd_gdImageGif" >&5 $as_echo "$ac_cv_lib_gd_gdImageGif" >&6; } if test "x$ac_cv_lib_gd_gdImageGif" = xyes; then : GDFORM_EXT=gif GLIBS="-lgd" else : fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gdImagePng in -lgd" >&5 $as_echo_n "checking for gdImagePng in -lgd... " >&6; } if ${ac_cv_lib_gd_gdImagePng+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgd -lgd -lpng -lz ${MATHLIBS} $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gdImagePng (); int main () { return gdImagePng (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_gd_gdImagePng=yes else ac_cv_lib_gd_gdImagePng=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gd_gdImagePng" >&5 $as_echo "$ac_cv_lib_gd_gdImagePng" >&6; } if test "x$ac_cv_lib_gd_gdImagePng" = xyes; then : GDFORM_EXT=png GLIBS="-lgd -lpng -lz" else : fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gdImagePng_jpg in -lgd" >&5 $as_echo_n "checking for gdImagePng_jpg in -lgd... " >&6; } if ${ac_cv_lib_gd_gdImagePng_jpg+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgd -lgd -lpng -lz -ljpeg ${MATHLIBS} $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gdImagePng_jpg (); int main () { return gdImagePng_jpg (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_gd_gdImagePng_jpg=yes else ac_cv_lib_gd_gdImagePng_jpg=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gd_gdImagePng_jpg" >&5 $as_echo "$ac_cv_lib_gd_gdImagePng_jpg" >&6; } if test "x$ac_cv_lib_gd_gdImagePng_jpg" = xyes; then : GDFORM_EXT=png GLIBS="-lgd -lpng -lz -ljpeg" else : fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gdImagePng_jpg_ft in -lgd" >&5 $as_echo_n "checking for gdImagePng_jpg_ft in -lgd... " >&6; } if ${ac_cv_lib_gd_gdImagePng_jpg_ft+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgd -lgd -lpng -lz -ljpeg -lfreetype ${MATHLIBS} $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gdImagePng_jpg_ft (); int main () { return gdImagePng_jpg_ft (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_gd_gdImagePng_jpg_ft=yes else ac_cv_lib_gd_gdImagePng_jpg_ft=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gd_gdImagePng_jpg_ft" >&5 $as_echo "$ac_cv_lib_gd_gdImagePng_jpg_ft" >&6; } if test "x$ac_cv_lib_gd_gdImagePng_jpg_ft" = xyes; then : GDFORM_EXT=png GLIBS="-lgd -lpng -lz -ljpeg -lfreetype" else : fi if test x$GDFORM_EXT = xgif; then CPPFLAGS="$CPPFLAGS -DGFORM_GD=gdImageGif" fi LIBS="${GLIBS} ${LIBS}" if test x$LD_RUN_PATH != x; then SET_LD_RUN_PATH="LD_RUN_PATH=${LD_RUN_PATH}" fi ac_fn_c_check_header_mongrel "$LINENO" "gd.h" "ac_cv_header_gd_h" "$ac_includes_default" if test "x$ac_cv_header_gd_h" = xyes; then : : else GDFORM_EXT="" fi if test x$GDFORM_EXT = x; then echo echo "** Ooops, one of many bad things happened:" echo "" echo " a) You don't have the GD library installed." echo " Get it from http://www.boutell.com, compile it and" echo " use either --with-gd-lib=DIR and --with-gd-inc=DIR to specify" echo " its location. You might also have to use --with-z-inc," echo " --with-z-lib and --with-png-inc, --with-png-lib for gd" echo " versions 1.6 and higher. Check config.log for more" echo " information on the problem." echo "" echo " b) You have the GD library installed, but not the gd.h" echo " header file. Download the source (see above) and use" echo " --with-gd-inc=DIR to specify where the file can be found." echo "" echo " c) You have the library and the header file installed, but" echo " you also have a shared GD library in the same directory. " echo " Remove the shared library files and/or links (e.g. " echo " libgd.so.2.0.0, libgd.so and libgd.so.2). This is especially" echo " likely if you're using a recent (post 1.8.4) version of GD" echo " and didn't configure it with --disable-shared." echo "" echo " d) You have gd library installed and also it's headers, but you are" echo " missing libpng (and headers) or freetype (and headers)" echo " (mrtg does not use freetype, but if your copy of gd is precompiled" echo " against it, you have to install it ... " echo "" echo " Consider following the instructions in doc/mrtg-unix-guide.txt" exit 1 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking the weather" >&5 $as_echo_n "checking the weather... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: (cached) it's fine" >&5 $as_echo "(cached) it's fine" >&6; } if test "x$GCC" = "xyes"; then oCFLAGS=$CFLAGS CFLAGS="$CFLAGS -Wall -Wpointer-arith -Wcast-align -Wmissing-declarations -Wnested-externs -Winline -W" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can use GCC-specific compiler options" >&5 $as_echo_n "checking if we can use GCC-specific compiler options... " >&6; } if ${rd_cv_gcc_opt+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return 0 ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : rd_cv_gcc_opt=yes else rd_cv_gcc_opt=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $rd_cv_gcc_opt" >&5 $as_echo "$rd_cv_gcc_opt" >&6; } if test $rd_cv_gcc_opt = no; then CFLAGS=$oCFLAGS fi fi ac_config_headers="$ac_config_headers config.h" ac_config_files="$ac_config_files Makefile" cat >confcache <<\_ACEOF # 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, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # 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. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by $as_me, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ config.status configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi echo $ECHO_N "ordering CD from http://tobi.oetiker.ch/wish $ECHO_C" 1>&6 sleep 1 echo $ECHO_N ".$ECHO_C" 1>&6 sleep 1 echo $ECHO_N ".$ECHO_C" 1>&6 sleep 1 echo $ECHO_N ".$ECHO_C" 1>&6 sleep 1 echo $ECHO_N ".$ECHO_C" 1>&6 sleep 1 { $as_echo "$as_me:${as_lineno-$LINENO}: result: just kidding ;-)" >&5 $as_echo " just kidding ;-)" >&6; } sleep 2 echo echo "----------------------------------------------------------------" echo "Config is DONE!" echo echo "Type 'make' to compile the software" echo echo " ... that wishlist mentioned above does really exist. So if" echo "you feel like showing your appreciation for MRTG, this is the" echo "place to go. I just love CDs and DVDs" echo echo " -- Tobi Oetiker " echo "----------------------------------------------------------------" mrtg-2.17.10/config.h.in0000644000175300017510000000325314171763343013705 0ustar oetikeroep/* config.h.in. Generated from configure.ac by autoheader. */ /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `strtoll' function. */ #undef HAVE_STRTOLL /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* How to print a long long */ #undef LLD /* long long format without % specifier */ #undef LLD_FORMAT /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS #ifndef HAVE_STRTOLL long long int strtoll(const char *str, char **ptr, int base) { long long int ll; sscanf(str, LLD, &ll); return ll; } #endif mrtg-2.17.10/mkinstalldirs0000755000175300017510000000133113057016062014452 0ustar oetikeroep#! /bin/sh # mkinstalldirs --- make directory hierarchy # Author: Noah Friedman # Created: 1993-05-16 # Public domain # $Id: mkinstalldirs,v 1.1.1.1 2002/02/26 10:15:49 oetiker 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 mrtg-2.17.10/configure.ac0000644000175300017510000001612114130554613014137 0ustar oetikeroepAC_INIT AC_CONFIG_SRCDIR([src/rateup.c]) AC_PREREQ([2.69]) dnl Check for programs. AC_PROG_CC AC_PREFIX_DEFAULT( /opt/mrtg-2 ) AC_PROG_CPP AC_PROG_MAKE_SET AC_PROG_INSTALL AC_PATH_PROG(PERL, perl, no, $PATH:/usr/bin:/usr/local/bin) if test $PERL = no; then echo echo "** No Perl found in the PATH. A recent copy of Perl" echo " is required for mrtg to work. Check www.perl.com" echo exit 1 fi AC_PATH_PROGS(NROFF, groff nroff) dnl Check for long long type (64 bit rateup) AC_CHECK_HEADERS(inttypes.h) AC_CHECK_TYPE(unsigned long long) AC_CHECK_TYPE(long long) AC_CHECK_FUNCS(strtoll) # Taken from libIDL-0.8.2 AC_MSG_CHECKING([for printf long long format specifier]) AC_CACHE_VAL(mr_cv_long_long_format_specifier,[ for format in ll l q I64; do AC_RUN_IFELSE([AC_LANG_SOURCE([[#include int main() { long long b, a = -0x3AFAFAFAFAFAFAFALL; char buffer[1000]; sprintf (buffer, "%${format}u", a); sscanf (buffer, "%${format}u", &b); exit (b!=a); } ]])],[mr_cv_long_long_format_specifier="%${format}d" mr_cv_long_long_format="${format}d" break],[],[]) done]) AC_MSG_RESULT($mr_cv_long_long_format_specifier) AC_DEFINE_UNQUOTED(LLD, "$mr_cv_long_long_format_specifier", [How to print a long long]) AC_DEFINE_UNQUOTED(LLD_FORMAT, "$mr_cv_long_long_format", [long long format without % specifier]) AH_BOTTOM( #ifndef HAVE_STRTOLL long long int strtoll(const char *str, char **ptr, int base) { long long int ll; sscanf(str, LLD, &ll); return ll; } #endif ) dnl Checks for libraries. AC_CHECK_LIB(m, pow, [ MATHLIBS="-lm" ]) AC_ARG_WITH(gd,[ --with-gd=DIR location of the gd lib/inc], [LDFLAGS="${LDFLAGS} -L${withval}" CPPFLAGS="${CPPFLAGS} -I${withval}" LD_RUN_PATH="${withval}${LD_RUN_PATH:+:}${LD_RUN_PATH}"]) AC_ARG_WITH(gd-lib,[ --with-gd-lib=DIR location of the gd library], [LDFLAGS="${LDFLAGS} -L${withval}" LD_RUN_PATH="${withval}${LD_RUN_PATH:+:}${LD_RUN_PATH}"]) AC_ARG_WITH(gd-inc,[ --with-gd-inc=DIR location of the gd include files], [CPPFLAGS="${CPPFLAGS} -I${withval}"]) AC_ARG_WITH(z,[ --with-z=DIR location of zlib lib/inc], [LDFLAGS="${LDFLAGS} -L${withval}" CPPFLAGS="${CPPFLAGS} -I${withval}" LD_RUN_PATH="${withval}${LD_RUN_PATH:+:}${LD_RUN_PATH}"]) AC_ARG_WITH(z-lib,[ --with-z-lib=DIR location of zlib library], [LDFLAGS="${LDFLAGS} -L${withval}" LD_RUN_PATH="${withval}${LD_RUN_PATH:+:}${LD_RUN_PATH}"]) AC_ARG_WITH(z-inc,[ --with-z-inc=DIR location of the zlib include files], [CPPFLAGS="${CPPFLAGS} -I${withval}"]) AC_ARG_WITH(png,[ --with-png=DIR location of png lib/inc], [LDFLAGS="${LDFLAGS} -L${withval}" CPPFLAGS="${CPPFLAGS} -I${withval}" LD_RUN_PATH="${withval}${LD_RUN_PATH:+:}${LD_RUN_PATH}"]) AC_ARG_WITH(png-lib,[ --with-png-lib=DIR location of png library], [LDFLAGS="${LDFLAGS} -L${withval}" LD_RUN_PATH="${withval}${LD_RUN_PATH:+:}${LD_RUN_PATH}"]) AC_ARG_WITH(png-inc,[ --with-png-inc=DIR location of the libpng include files], [CPPFLAGS="${CPPFLAGS} -I${withval}"]) LIBS="${LIBS} ${MATHLIBS}" GDEXTRALIB="" dnl which version of gd do we have here ? AC_CHECK_LIB(gd,gdImageGif,[ GDFORM_EXT=gif GLIBS="-lgd" ],:,[-lgd ${MATHLIBS}]) AC_CHECK_LIB(gd,gdImagePng,[ GDFORM_EXT=png GLIBS="-lgd -lpng -lz" ],:,[-lgd -lpng -lz ${MATHLIBS}]) AC_CHECK_LIB(gd,gdImagePng_jpg,[ GDFORM_EXT=png GLIBS="-lgd -lpng -lz -ljpeg" ],:,[-lgd -lpng -lz -ljpeg ${MATHLIBS}]) AC_CHECK_LIB(gd,gdImagePng_jpg_ft,[ GDFORM_EXT=png GLIBS="-lgd -lpng -lz -ljpeg -lfreetype" ],:,[-lgd -lpng -lz -ljpeg -lfreetype ${MATHLIBS}]) if test x$GDFORM_EXT = xgif; then CPPFLAGS="$CPPFLAGS -DGFORM_GD=gdImageGif" fi LIBS="${GLIBS} ${LIBS}" if test x$LD_RUN_PATH != x; then SET_LD_RUN_PATH="LD_RUN_PATH=${LD_RUN_PATH}" fi dnl Make sure the header is here AC_CHECK_HEADER( gd.h,:,[ GDFORM_EXT="" ]) if test x$GDFORM_EXT = x; then echo echo "** Ooops, one of many bad things happened:" echo "" echo " a) You don't have the GD library installed." echo " Get it from http://www.boutell.com, compile it and" echo " use either --with-gd-lib=DIR and --with-gd-inc=DIR to specify" echo " its location. You might also have to use --with-z-inc," echo " --with-z-lib and --with-png-inc, --with-png-lib for gd" echo " versions 1.6 and higher. Check config.log for more" echo " information on the problem." echo "" echo " b) You have the GD library installed, but not the gd.h" echo " header file. Download the source (see above) and use" echo " --with-gd-inc=DIR to specify where the file can be found." echo "" echo " c) You have the library and the header file installed, but" echo " you also have a shared GD library in the same directory. " echo " Remove the shared library files and/or links (e.g. " echo " libgd.so.2.0.0, libgd.so and libgd.so.2). This is especially" echo " likely if you're using a recent (post 1.8.4) version of GD" echo " and didn't configure it with --disable-shared." echo "" echo " d) You have gd library installed and also it's headers, but you are" echo " missing libpng (and headers) or freetype (and headers)" echo " (mrtg does not use freetype, but if your copy of gd is precompiled" echo " against it, you have to install it ... " echo "" echo " Consider following the instructions in doc/mrtg-unix-guide.txt" exit 1 fi AC_MSG_CHECKING(the weather) AC_MSG_RESULT((cached) it's fine) dnl Does the compiler like -Wall and if test "x$GCC" = "xyes"; then oCFLAGS=$CFLAGS CFLAGS="$CFLAGS -Wall -Wpointer-arith -Wcast-align -Wmissing-declarations -Wnested-externs -Winline -W" AC_CACHE_CHECK(if we can use GCC-specific compiler options, rd_cv_gcc_opt, [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[return 0 ]])],[rd_cv_gcc_opt=yes],[rd_cv_gcc_opt=no ]) ] ) if test $rd_cv_gcc_opt = no; then CFLAGS=$oCFLAGS fi fi AC_SUBST(PERL) AC_SUBST(RRD_PERL) AC_SUBST(GDFORM_EXT) AC_SUBST(SET_LD_RUN_PATH) AC_SUBST(LIBS) AC_SUBST(CFLAGS) AC_CONFIG_HEADERS(config.h) AC_CONFIG_FILES([Makefile]) AC_OUTPUT echo $ECHO_N "ordering CD from http://tobi.oetiker.ch/wish $ECHO_C" 1>&6 sleep 1 echo $ECHO_N ".$ECHO_C" 1>&6 sleep 1 echo $ECHO_N ".$ECHO_C" 1>&6 sleep 1 echo $ECHO_N ".$ECHO_C" 1>&6 sleep 1 echo $ECHO_N ".$ECHO_C" 1>&6 sleep 1 AC_MSG_RESULT([ just kidding ;-)]) sleep 2 echo echo "----------------------------------------------------------------" echo "Config is DONE!" echo echo "Type 'make' to compile the software" echo echo " ... that wishlist mentioned above does really exist. So if" echo "you feel like showing your appreciation for MRTG, this is the" echo "place to go. I just love CDs and DVDs" echo echo " -- Tobi Oetiker " echo "----------------------------------------------------------------" mrtg-2.17.10/install-sh0000755000175300017510000001273613057016062013663 0ustar oetikeroep#!/bin/sh # # install - install a program, script, or datafile # This comes from X11R5 (mit/util/scripts/install.sh). # # Copyright 1991 by the Massachusetts Institute of Technology # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation, and that the name of M.I.T. not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. M.I.T. makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # 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. It can only install one file at a time, a restriction # shared with many OS's install programs. # 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}" transformbasename="" 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=: chmodcmd="" 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 mrtg-2.17.10/images/0000755000175300017510000000000013057016062013113 5ustar oetikeroepmrtg-2.17.10/images/mrtg-l.gif0000644000175300017510000000052713057016062015010 0ustar oetikeroepGIF89a?}f}4]_bgymivMtTq\!,?X0I8`e:* Am mײr@UtLǖjs:(XLjem=3$đsT|GYz j<Bk#?{!`5344` D"BVX \dLFfUH cV. O ;p#-3A" !,}f}4]ZbisscvMtRr[Xܾ3DpP|h:\f i Y)BqF(!G +H4 !,}f}4]YbjrscvMtRrZXܾ3DpP1|h:\Vxi˱@+ՉL+ _p TWlE׊'> xs(4u-F ʮg(ϢkP~Y}Spq-7Y{ rJ5G'!G.- !,}f}4][bisscvMtRr[Xܾ1DpP1|h:`NUi ,S, A#ByI 8 RVXRˍm9jC%m 6-\>F '#a7C T:W1I zCP"$Wx ;mrtg-2.17.10/images/mrtg-r.png0000644000175300017510000000333713057016062015037 0ustar oetikeroepPNG  IHDRDPLTE4]ɨ` O3㌳Q!-B=MXzC9+cjc}4dA5?.gh%fC*O)4WP.9UOwD + x[d|Q{%r_bMjpe)©#ۅ~B[Sm=7{u|ޜr2;y??*zm >CtEXtSoftware@(#)ImageMagick 4.2.9 99/09/01 cristy@mystic.es.dupont.com*tEXtSignature12175e6b3183337d381f01c63cfc436e2tEXtPage388x25+0+0RiIENDB`mrtg-2.17.10/images/mrtg-ti.png0000644000175300017510000001030513057016062015203 0ustar oetikeroepPNG  IHDRPPLTE4]emuMq\its TbKGDaIDATxIv8 NW  [BV?恨$^eB}Uj*կ6{^yW+[/"˧r;wO@@UQ%]' (SU?}* w.86n[erxp8(LB'$6=ZûV*)ַ= LpW}M^$6Wˬ&cx|*yApH͖ⵋIA^[q6^%bE%6"^4S/,b8)RdziמmȫM)$CyKx\ w\\ Px+HEpY|フ(e" bg75'Vq\ϩ`waUSI|Zg> GJyb޴K]Ekԅ83t7wj4>UdjͻV]>K(m)oSYlH74y۲V} fH)/)LgkJx1@okF)/7$?3J$Uԭż}I|FgSߢqFiWfy,^Uח%5{G/6Je>[}(-,6 \6B%׹vfpm$#Ǝ?=xASx!YmPyƽZh7014A^w: 51y[ pukj/=yx0b *p XgsާB؍aqjmx|BW "#Saل74$n7whe7o"V>Cز*k 7DN:_pYm ԛ*/\+ RW%t<yqlR ʛyq^[IP3hxy{B$\*/z*+7Ch%升B$޵ mW)gh\NrZBM>W]x/?:۸­]]]Um^fVv&(m>7m]xX77A>w Sfw>o_xUȉuv#W%-gOʕv}"ŷ 2yӚ]^p~އj x̛_(A^* C&e0s>M0(/?N鿛 /[[(rxyopI*) \_ݠCY7p(:a?4 oË%tPHp~ɴŒlqՠaMoS q6O`r"6aOǕ uW @&o_ D+Fym`O"qؼkt%}b0]Ğ[#0FE+ghx|05%r')kw xpB'x-{)\NyV%vh)ң JCє?baVBBJy#^qxވܑ!^q})/,RV1^}i|7 #ЮRwťwVj 0^fzk r dE_{}9PS{kx-$)M}ռ* ^|7λyAR̄Nxw^3-ۆ/hbX#⽟Ұ-'͂s6ŁOyŒo Z I]ʛ3b9/<?qC `NxlU_@@dpɿ?H!DS.M+/n )tf(y^#7|wr ټd6^;-گZ+00UDq:7m^iA "\{Q;gY+S![ Xx4I,ޔwMozxM]`y@dҿx2[V!㘔heU(5}`[1^8vBgBNK y}B waEpbe[6 йA`*7Y# iDVBg!\΋JB4§Vnv0.~9|L8~"V>/#2gIxii\>OěV\y?w~_./o؏@5%&?dHD;kOWco拠Gv[ \:@Ǫ̾DYox0J/xG~ʱY Ce)iUpfZdY*J. vRsxߔ6*؍R1UT6 IV yvx\ɋ,)AO"=k8NiK_V3} ˯]T'ҜbZ=_%M˒1uQeג(W"xxf/fR+ջ Y4m:٨ztGSs~ q/M|*e>.xkv|+c&>;ӚVB[[Fss[X<$Лly&AVOj(; 2{r1*;:C>mޅ0{q7fVLl;Y\x=ٕD`MЖWgeY4t/9( VBs਷yߌ;+^^fiOq4w_۳ _kŗW; ^#d=DKL%5sgQ Xϣ;>;u/BO~>Uq-3M$=D ,^_2dBf g>Uցv[;Y=B4.nGq`t^k3SG8CB''Df*+fj7׬ݙ)rFQ-|\Fgh7=( 0G&3H㕌^1%Q.ZXW^;=^nQXL0ʨQxCvRǃ3ztc(;1ѫA:i:>4%W<).tgv,z T j Ϧ_yED*5t/[^je`tɖx帎6щ:M] ܙf|v_D3:;镭R _,w!yՕ2EsQnHZNlOj|Y|;MVθ=|d 7xNx-5=TWv:d#|e^gbUi7v?UP= oͻw~׬A !KAן4.֣f{枷ލhe|ilD̿P"vIJ`GW- Y+fc"EG\f'x4Y+蹲ۅVB fҥ |~d29?bQ".sYOv:M_j+4 ""]Z? 3%Tҩ_:htYۄCM="RLO_Q܈n<]4W1o>،j{QΜx5^Or5))NeԒ?bIj/m5rUWBj͜R%x㳨68KAfQ,I`Ozg++n\wa%C7u7u붹&<\ܟd;DwQ;'\oQI`WB5}jZ*.uI;s~p_R";wG2T<-\˵.Wkǐ޲CtEXtSoftware@(#)ImageMagick 4.2.9 99/09/01 cristy@mystic.es.dupont.com*tEXtSignatureb7ccc270275734d4609aed00f913eee6QFtEXtPage478x160+0+0&̀IENDB`mrtg-2.17.10/images/mrtg-ti.gif0000644000175300017510000001113013057016062015161 0ustar oetikeroepGIF89a4]emuMq\its!,(0I8ͻ`(dihlp,tmx|pH,Ȥrl:ШtJZجvzxL.ۀ8`~rquySkv& kx26Pr&uw'3źwMʵϵ!تn"/uK!$(( r ZCXBxӪ> rec Tvu[d뾺T/-.L΍vQ~eț`09PhfpO( :aK oT؅ϠC@Ufuz [Z]]as=o8k}l[ޘxm0užk|nìկ*?ubޢ|9~_]  IaY-HaS{n9H!?ه&(/i"<硗O%(O966RP=βTL?h($G!IERTt=9R䙗"AU$f{Z] g%~j"&gY\ucKU%z9lOΥ(,WVp:]ՠu1j[> whB *b VGN˪j!PkojS Z*tOl$b~0>MZ DZ$յ sôV)f1kTGRPLf ]FÚ x>ѫ36Um ᎧiYkk_'ʨ ,.+k A!Mmq/(\q9 s46B'A#L?}; 3Sئ ^300u[М-)v .:5zSFDqGAx $v_2#>@bB6|^u%!6A 2 V}ou:G/C?Bd^s+O飵ESHv azU~ݚ;L3iʃ8!?ė1 j64t GLDDF@okОBpA c@)`~7A! 1kX}!}D=*Cn ?߼|XD9I/a|,L (s!gr 9"w:eר p"|Ʀxc^tqsGabZDNuu4#'5~-.aex`F<t$הO zJPf`!8.^ Wr!2f1BI_L683!;7l9Ʒ]0j'$v)~ x#'`z7E3sJjpZڙՊ^)|ꧦ٥vܑ@șGYz\\Iࣦ؄ IʧJKb  bG‹ٌqy4~XuڔʱٕaZZjӰ>?誫ئO9'밃j菂 :ZGʴp ܺ-ʵ_I zjT`|س 6z(C :^ ~X%(myr;pVZZYrXۢyZZ{p۱@g˳9ȘۺNKj-ԙΈ˷i; ?*'ۓRꚔ{;ыa{ ^dAhjRZٽI{;0뤌 +䫲@[2+h˃뿢wH 2l<5-=6ď^YRHꏿ 2ۻ.gj]ok_% ˫bڒKkUY[Q=x\;^p&]AXu gU1D]~M-كrY~!!Ԃfdm@T|(zRI.߁vrTJ81*e_D0Q[k8.FrV]ay؅Q"@GmwZLV9AYKB2}a';7a?eeR(@%HRK&m餡b!R1J*a F5 cɪ6 }ה.YH'$5Q${  zj(V5I54iD^](c0Up>Rc!; XIŲYq`TCֳIBQ6%Ph+ x L+&9(1B8'g@&s+Iħ ̦r CfEqM"в0""U?<#BbleZ;*cjDlFXҶff8KTĢ O'{r@7 E5a؂7SdMyZAf&<2hV3H(͋J>1Laȏ8< *qYLC"C*ѢpBB@ġp N5+ZI +\p&zMbؾ6,d'KZ"H;mrtg-2.17.10/images/mrtg-l.png0000644000175300017510000000103213057016062015017 0ustar oetikeroepPNG  IHDR?tPLTE}f}4]_bgymivMtTq\RbKGDaIDATxڭo@ ũT: -NkmEU'~g[9JuC{p<;գ9݀ȓHKIπ&<Rz&聅X0/F@ߖRvkTsk*Ϣ--MT9=HF|%AdwiBb#f˘<5IK 6 >.`Fv A=It Lc8ZG\QiH GXjdCtEXtSoftware@(#)ImageMagick 4.2.9 99/09/01 cristy@mystic.es.dupont.com*tEXtSignatured227c7498a501e7fa45086c9ff44bb9c[4~tEXtPage63x25+0+0xIENDB`mrtg-2.17.10/lib/mrtg2/BER.pm0000644000175300017510000006621314171763414014435 0ustar oetikeroep### -*- mode: Perl -*- ###################################################################### ### BER (Basic Encoding Rules) encoding and decoding. ###################################################################### ### Copyright (c) 1995-2008, Simon Leinen. ### ### This program is free software; you can redistribute it under the ### "Artistic License 2.0" included in this distribution ### (file "Artistic"). ###################################################################### ### This module implements encoding and decoding of ASN.1-based data ### structures using the Basic Encoding Rules (BER). Only the subset ### necessary for SNMP is implemented. ###################################################################### ### Created by: Simon Leinen ### ### Contributions and fixes by: ### ### Andrzej Tobola : Added long String decode ### Tobias Oetiker : Added 5 Byte Integer decode ... ### Dave Rand : Added SysUpTime decode ### Philippe Simonet : Support larger subids ### Yufang HU : Support even larger subids ### Mike Mitchell : New generalized encode_int() ### Mike Diehn : encode_ip_address() ### Rik Hoorelbeke : encode_oid() fix ### Brett T Warden : pretty UInteger32 ### Bert Driehuis : Handle SNMPv2 exception codes ### Jakob Ilves (/IlvJa) : PDU decoding ### Jan Kasprzak : Fix for PDU syntax check ### Milen Pavlov : Recognize variant length for ints ###################################################################### package BER; require 5.002; use strict; use vars qw(@ISA @EXPORT $VERSION $pretty_print_timeticks %pretty_printer %default_printer $errmsg); use Exporter; $VERSION = '1.05'; @ISA = qw(Exporter); @EXPORT = qw(context_flag constructor_flag encode_int encode_int_0 encode_null encode_oid encode_sequence encode_tagged_sequence encode_string encode_ip_address encode_timeticks encode_uinteger32 encode_counter32 encode_counter64 encode_gauge32 decode_sequence decode_by_template pretty_print pretty_print_timeticks hex_string hex_string_of_type encoded_oid_prefix_p errmsg register_pretty_printer unregister_pretty_printer); ### Variables ## Bind this to zero if you want to avoid that TimeTicks are converted ## into "human readable" strings containing days, hours, minutes and ## seconds. ## ## If the variable is zero, pretty_print will simply return an ## unsigned integer representing hundredths of seconds. ## $pretty_print_timeticks = 1; ### Prototypes sub encode_header ($$); sub encode_int_0 (); sub encode_int ($); sub encode_oid (@); sub encode_null (); sub encode_sequence (@); sub encode_tagged_sequence ($@); sub encode_string ($); sub encode_ip_address ($); sub encode_timeticks ($); sub pretty_print ($); sub pretty_using_decoder ($$); sub pretty_string ($); sub pretty_intlike ($); sub pretty_unsignedlike ($); sub pretty_oid ($); sub pretty_uptime ($); sub pretty_uptime_value ($); sub pretty_ip_address ($); sub pretty_generic_sequence ($); sub register_pretty_printer ($); sub unregister_pretty_printer ($); sub hex_string ($); sub hex_string_of_type ($$); sub decode_oid ($); sub decode_by_template; sub decode_by_template_2; sub decode_sequence ($); sub decode_int ($); sub decode_intlike ($); sub decode_unsignedlike ($); sub decode_intlike_s ($$); sub decode_string ($); sub decode_length ($@); sub encoded_oid_prefix_p ($$); sub decode_subid ($$$); sub decode_generic_tlv ($); sub error (@); sub template_error ($$$); sub version () { $VERSION; } ### Flags for different types of tags sub universal_flag { 0x00 } sub application_flag { 0x40 } sub context_flag { 0x80 } sub private_flag { 0xc0 } sub primitive_flag { 0x00 } sub constructor_flag { 0x20 } ### Universal tags sub boolean_tag { 0x01 } sub int_tag { 0x02 } sub bit_string_tag { 0x03 } sub octet_string_tag { 0x04 } sub null_tag { 0x05 } sub object_id_tag { 0x06 } sub sequence_tag { 0x10 } sub set_tag { 0x11 } sub uptime_tag { 0x43 } ### Flag for length octet announcing multi-byte length field sub long_length { 0x80 } ### SNMP specific tags sub snmp_ip_address_tag { 0x00 | application_flag () } sub snmp_counter32_tag { 0x01 | application_flag () } sub snmp_gauge32_tag { 0x02 | application_flag () } sub snmp_timeticks_tag { 0x03 | application_flag () } sub snmp_opaque_tag { 0x04 | application_flag () } sub snmp_nsap_address_tag { 0x05 | application_flag () } sub snmp_counter64_tag { 0x06 | application_flag () } sub snmp_uinteger32_tag { 0x07 | application_flag () } ## Error codes (SNMPv2 and later) ## sub snmp_nosuchobject { context_flag () | 0x00 } sub snmp_nosuchinstance { context_flag () | 0x01 } sub snmp_endofmibview { context_flag () | 0x02 } ### pretty-printer initialization code. Create a hash with ### the most common types of pretty-printer routines. BEGIN { $default_printer{int_tag()} = \&pretty_intlike; $default_printer{snmp_counter32_tag()} = \&pretty_unsignedlike; $default_printer{snmp_gauge32_tag()} = \&pretty_unsignedlike; $default_printer{snmp_counter64_tag()} = \&pretty_unsignedlike; $default_printer{snmp_uinteger32_tag()} = \&pretty_unsignedlike; $default_printer{octet_string_tag()} = \&pretty_string; $default_printer{object_id_tag()} = \&pretty_oid; $default_printer{snmp_ip_address_tag()} = \&pretty_ip_address; %pretty_printer = %default_printer; } #### Encoding sub encode_header ($$) { my ($type,$length) = @_; return pack ("C C", $type, $length) if $length < 128; return pack ("C C C", $type, long_length | 1, $length) if $length < 256; return pack ("C C n", $type, long_length | 2, $length) if $length < 65536; return error ("Cannot encode length $length yet"); } sub encode_int_0 () { return pack ("C C C", 2, 1, 0); } sub encode_int ($) { return encode_intlike ($_[0], int_tag); } sub encode_uinteger32 ($) { return encode_intlike ($_[0], snmp_uinteger32_tag); } sub encode_counter32 ($) { return encode_intlike ($_[0], snmp_counter32_tag); } sub encode_counter64 ($) { return encode_intlike ($_[0], snmp_counter64_tag); } sub encode_gauge32 ($) { return encode_intlike ($_[0], snmp_gauge32_tag); } sub encode_intlike ($$) { my ($int, $tag)=@_; my ($sign, $val, @vals); $sign = ($int >= 0) ? 0 : 0xff; if (ref $int && $int->isa ("Math::BigInt")) { for(;;) { $val = $int->copy()->bmod (256); unshift(@vals, $val); return encode_header ($tag, $#vals + 1).pack ("C*", @vals) if ($int >= -128 && $int < 128); $int->bsub ($sign)->bdiv (256); } } else { for(;;) { $val = $int & 0xff; unshift(@vals, $val); return encode_header ($tag, $#vals + 1).pack ("C*", @vals) if ($int >= -128 && $int < 128); $int -= $sign, $int = int($int / 256); } } } sub encode_oid (@) { my @oid = @_; my ($result,$subid); $result = ''; ## Ignore leading empty sub-ID. The favourite reason for ## those to occur is that people cut&paste numeric OIDs from ## CMU/UCD SNMP including the leading dot. shift @oid if $oid[0] eq ''; return error ("Object ID too short: ", join('.',@oid)) if $#oid < 1; ## The first two subids in an Object ID are encoded as a single ## byte in BER, according to a funny convention. This poses ## restrictions on the ranges of those subids. In the past, I ## didn't check for those. But since so many people try to use ## OIDs in CMU/UCD SNMP's format and leave out the mib-2 or ## enterprises prefix, I introduced this check to catch those ## errors. ## return error ("first subid too big in Object ID ", join('.',@oid)) if $oid[0] > 2; $result = shift (@oid) * 40; $result += shift @oid; return error ("second subid too big in Object ID ", join('.',@oid)) if $result > 255; $result = pack ("C", $result); foreach $subid (@oid) { if ( ($subid>=0) && ($subid<128) ){ #7 bits long subid $result .= pack ("C", $subid); } elsif ( ($subid>=128) && ($subid<16384) ){ #14 bits long subid $result .= pack ("CC", 0x80 | $subid >> 7, $subid & 0x7f); } elsif ( ($subid>=16384) && ($subid<2097152) ) {#21 bits long subid $result .= pack ("CCC", 0x80 | (($subid>>14) & 0x7f), 0x80 | (($subid>>7) & 0x7f), $subid & 0x7f); } elsif ( ($subid>=2097152) && ($subid<268435456) ){ #28 bits long subid $result .= pack ("CCCC", 0x80 | (($subid>>21) & 0x7f), 0x80 | (($subid>>14) & 0x7f), 0x80 | (($subid>>7) & 0x7f), $subid & 0x7f); } elsif ( ($subid>=268435456) && ($subid<4294967296) ){ #32 bits long subid $result .= pack ("CCCCC", 0x80 | (($subid>>28) & 0x0f), #mask the bits beyond 32 0x80 | (($subid>>21) & 0x7f), 0x80 | (($subid>>14) & 0x7f), 0x80 | (($subid>>7) & 0x7f), $subid & 0x7f); } else { return error ("Cannot encode subid $subid"); } } encode_header (object_id_tag, length $result).$result; } sub encode_null () { encode_header (null_tag, 0); } sub encode_sequence (@) { encode_tagged_sequence (sequence_tag, @_); } sub encode_tagged_sequence ($@) { my ($tag,$result); $tag = shift @_; $result = join '',@_; return encode_header ($tag | constructor_flag, length $result).$result; } sub encode_string ($) { my ($string)=@_; return encode_header (octet_string_tag, length $string).$string; } sub encode_ip_address ($) { my ($addr)=@_; my @octets; if (length $addr == 4) { ## Four bytes... let's suppose that this is a binary IP address ## in network byte order. return encode_header (snmp_ip_address_tag, length $addr).$addr; } elsif (@octets = ($addr =~ /^([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)$/)) { return encode_ip_address (pack ("CCCC", @octets)); } else { return error ("IP address must be four bytes long or a dotted-quad"); } } sub encode_timeticks ($) { my ($tt) = @_; return encode_intlike ($tt, snmp_timeticks_tag); } #### Decoding sub pretty_print ($) { my ($packet) = @_; return undef unless defined $packet; my $result = ord (substr ($packet, 0, 1)); if (exists ($pretty_printer{$result})) { my $c_ref = $pretty_printer{$result}; return &$c_ref ($packet); } return ($pretty_print_timeticks ? pretty_uptime ($packet) : pretty_unsignedlike ($packet)) if $result == uptime_tag; return "(null)" if $result == null_tag; return error ("Exception code: noSuchObject") if $result == snmp_nosuchobject; return error ("Exception code: noSuchInstance") if $result == snmp_nosuchinstance; return error ("Exception code: endOfMibView") if $result == snmp_endofmibview; # IlvJa # pretty print sequences and their contents. my $ctx_cons_flags = context_flag | constructor_flag; if($result == (&constructor_flag | &sequence_tag) # sequence || $result == (0 | $ctx_cons_flags) #get_request || $result == (1 | $ctx_cons_flags) #getnext_request || $result == (2 | $ctx_cons_flags) #response || $result == (3 | $ctx_cons_flags) #set_request || $result == (4 | $ctx_cons_flags) #trap_request || $result == (5 | $ctx_cons_flags) #getbulk_request || $result == (6 | $ctx_cons_flags) #inform_request || $result == (7 | $ctx_cons_flags) #trap2_request ) { my $pretty_result = pretty_generic_sequence($packet); $pretty_result =~ s/^/ /gm; #Indent. my $seq_type_desc = { (constructor_flag | sequence_tag) => "Sequence", (0 | $ctx_cons_flags) => "GetRequest", (1 | $ctx_cons_flags) => "GetNextRequest", (2 | $ctx_cons_flags) => "Response", (3 | $ctx_cons_flags) => "SetRequest", (4 | $ctx_cons_flags) => "Trap", (5 | $ctx_cons_flags) => "GetBulkRequest", (6 | $ctx_cons_flags) => "InformRequest", (7 | $ctx_cons_flags) => "SNMPv2-Trap", (8 | $ctx_cons_flags) => "Report", }->{($result)}; return $seq_type_desc . "{\n" . $pretty_result . "\n}"; } return sprintf ("#", $result); } sub pretty_using_decoder ($$) { my ($decoder, $packet) = @_; my ($decoded,$rest); ($decoded,$rest) = &$decoder ($packet); return error ("Junk after object") unless $rest eq ''; return $decoded; } sub pretty_string ($) { pretty_using_decoder (\&decode_string, $_[0]); } sub pretty_intlike ($) { my $decoded = pretty_using_decoder (\&decode_intlike, $_[0]); $decoded; } sub pretty_unsignedlike ($) { return pretty_using_decoder (\&decode_unsignedlike, $_[0]); } sub pretty_oid ($) { my ($oid) = shift; my ($result,$subid,$next); my (@oid); $result = ord (substr ($oid, 0, 1)); return error ("Object ID expected") unless $result == object_id_tag; ($result, $oid) = decode_length ($oid, 1); return error ("inconsistent length in OID") unless $result == length $oid; @oid = (); $subid = ord (substr ($oid, 0, 1)); push @oid, int ($subid / 40); push @oid, $subid % 40; $oid = substr ($oid, 1); while ($oid ne '') { $subid = ord (substr ($oid, 0, 1)); if ($subid < 128) { $oid = substr ($oid, 1); push @oid, $subid; } else { $next = $subid; $subid = 0; while ($next >= 128) { $subid = ($subid << 7) + ($next & 0x7f); $oid = substr ($oid, 1); $next = ord (substr ($oid, 0, 1)); } $subid = ($subid << 7) + $next; $oid = substr ($oid, 1); push @oid, $subid; } } join ('.', @oid); } sub pretty_uptime ($) { my ($packet,$uptime); ($uptime,$packet) = &decode_unsignedlike (@_); pretty_uptime_value ($uptime); } sub pretty_uptime_value ($) { my ($uptime) = @_; my ($seconds,$minutes,$hours,$days,$result); ## We divide the uptime by hundred since we're not interested in ## sub-second precision. $uptime = int ($uptime / 100); $days = int ($uptime / (60 * 60 * 24)); $uptime %= (60 * 60 * 24); $hours = int ($uptime / (60 * 60)); $uptime %= (60 * 60); $minutes = int ($uptime / 60); $seconds = $uptime % 60; if ($days == 0){ $result = sprintf ("%d:%02d:%02d", $hours, $minutes, $seconds); } elsif ($days == 1) { $result = sprintf ("%d day, %d:%02d:%02d", $days, $hours, $minutes, $seconds); } else { $result = sprintf ("%d days, %d:%02d:%02d", $days, $hours, $minutes, $seconds); } return $result; } sub pretty_ip_address ($) { my $pdu = shift; my ($length, $rest); return error ("IP Address tag (".snmp_ip_address_tag.") expected") unless ord (substr ($pdu, 0, 1)) == snmp_ip_address_tag; ($length,$pdu) = decode_length ($pdu, 1); return error ("Length of IP address should be four") unless $length == 4; sprintf "%d.%d.%d.%d", unpack ("CCCC", $pdu); } # IlvJa # Returns a string with the pretty prints of all # the elements in the sequence. sub pretty_generic_sequence ($) { my ($pdu) = shift; my $rest; my $type = ord substr ($pdu, 0 ,1); my $flags = context_flag | constructor_flag; return error (sprintf ("Tag 0x%x is not a valid sequence tag",$type)) unless ($type == (&constructor_flag | &sequence_tag) # sequence || $type == (0 | $flags) #get_request || $type == (1 | $flags) #getnext_request || $type == (2 | $flags) #response || $type == (3 | $flags) #set_request || $type == (4 | $flags) #trap_request || $type == (5 | $flags) #getbulk_request || $type == (6 | $flags) #inform_request || $type == (7 | $flags) #trap2_request ); my $curelem; my $pretty_result; # Holds the pretty printed sequence. my $pretty_elem; # Holds the pretty printed current elem. my $first_elem = 'true'; # Cut away the first Tag and Length from $packet and then # init $rest with that. (undef, $rest) = decode_length ($pdu, 1); while($rest) { ($curelem,$rest) = decode_generic_tlv($rest); $pretty_elem = pretty_print($curelem); $pretty_result .= "\n" if not $first_elem; $pretty_result .= $pretty_elem; # The rest of the iterations are not related to the # first element of the sequence so.. $first_elem = '' if $first_elem; } return $pretty_result; } sub hex_string ($) { &hex_string_of_type ($_[0], octet_string_tag); } sub hex_string_of_type ($$) { my ($pdu, $wanted_type) = @_; my ($length); return error ("BER tag ".$wanted_type." expected") unless ord (substr ($pdu, 0, 1)) == $wanted_type; ($length,$pdu) = decode_length ($pdu, 1); hex_string_aux ($pdu); } sub hex_string_aux ($) { my ($binary_string) = @_; my ($c, $result); $result = ''; for $c (unpack "C*", $binary_string) { $result .= sprintf "%02x", $c; } $result; } sub decode_oid ($) { my ($pdu) = @_; my ($result,$pdu_rest); my (@result); $result = ord (substr ($pdu, 0, 1)); return error ("Object ID expected") unless $result == object_id_tag; ($result, $pdu_rest) = decode_length ($pdu, 1); return error ("Short PDU") if $result > length $pdu_rest; @result = (substr ($pdu, 0, $result + (length ($pdu) - length ($pdu_rest))), substr ($pdu_rest, $result)); @result; } # IlvJa # This takes a PDU and returns a two element list consisting of # the first element found in the PDU (whatever it is) and the # rest of the PDU sub decode_generic_tlv ($) { my ($pdu) = @_; my (@result); my ($elemlength,$pdu_rest) = decode_length ($pdu, 1); @result = (# Extract the first element. substr ($pdu, 0, $elemlength + (length ($pdu) - length ($pdu_rest) ) ), #Extract the rest of the PDU. substr ($pdu_rest, $elemlength) ); @result; } sub decode_by_template { my ($pdu) = shift; local ($_) = shift; return decode_by_template_2 ($pdu, $_, 0, 0, @_); } my $template_debug = 0; sub decode_by_template_2 { my ($pdu, $template, $pdu_index, $template_index); local ($_); $pdu = shift; $template = $_ = shift; $pdu_index = shift; $template_index = shift; my (@results); my ($length,$expected,$read,$rest); return undef unless defined $pdu; while (0 < length ($_)) { if (substr ($_, 0, 1) eq '%') { print STDERR "template $_ ", length $pdu," bytes remaining\n" if $template_debug; $_ = substr ($_,1); ++$template_index; if (($expected) = /^(\d*|\*)\{(.*)/) { ## %{ $template_index += length ($expected) + 1; print STDERR "%{\n" if $template_debug; $_ = $2; $expected = shift | constructor_flag if ($expected eq '*'); $expected = sequence_tag | constructor_flag if $expected eq ''; return template_error ("Unexpected end of PDU", $template, $template_index) if !defined $pdu or $pdu eq ''; return template_error ("Expected sequence tag $expected, got ". ord (substr ($pdu, 0, 1)), $template, $template_index) unless (ord (substr ($pdu, 0, 1)) == $expected); (($length,$pdu) = decode_length ($pdu, 1)) || return template_error ("cannot read length", $template, $template_index); return template_error ("Expected length $length, got ".length $pdu , $template, $template_index) unless length $pdu == $length; } elsif (($expected,$rest) = /^(\*|)s(.*)/) { ## %s $template_index += length ($expected) + 1; ($expected = shift) if $expected eq '*'; (($read,$pdu) = decode_string ($pdu)) || return template_error ("cannot read string", $template, $template_index); print STDERR "%s => $read\n" if $template_debug; if ($expected eq '') { push @results, $read; } else { return template_error ("Expected $expected, read $read", $template, $template_index) unless $expected eq $read; } $_ = $rest; } elsif (($rest) = /^A(.*)/) { ## %A $template_index += 1; { my ($tag, $length, $value); $tag = ord (substr ($pdu, 0, 1)); return error ("Expected IP address, got tag ".$tag) unless $tag == snmp_ip_address_tag; ($length, $pdu) = decode_length ($pdu, 1); return error ("Inconsistent length of InetAddress encoding") if $length > length $pdu; return template_error ("IP address must be four bytes long", $template, $template_index) unless $length == 4; $read = substr ($pdu, 0, $length); $pdu = substr ($pdu, $length); } print STDERR "%A => $read\n" if $template_debug; push @results, $read; $_ = $rest; } elsif (/^O(.*)/) { ## %O $template_index += 1; $_ = $1; (($read,$pdu) = decode_oid ($pdu)) || return template_error ("cannot read OID", $template, $template_index); print STDERR "%O => ".pretty_oid ($read)."\n" if $template_debug; push @results, $read; } elsif (($expected,$rest) = /^(\d*|\*|)i(.*)/) { ## %i $template_index += length ($expected) + 1; print STDERR "%i\n" if $template_debug; $_ = $rest; (($read,$pdu) = decode_int ($pdu)) || return template_error ("cannot read int", $template, $template_index); if ($expected eq '') { push @results, $read; } else { $expected = int (shift) if $expected eq '*'; return template_error (sprintf ("Expected %d (0x%x), got %d (0x%x)", $expected, $expected, $read, $read), $template, $template_index) unless ($expected == $read) } } elsif (($rest) = /^u(.*)/) { ## %u $template_index += 1; print STDERR "%u\n" if $template_debug; $_ = $rest; (($read,$pdu) = decode_unsignedlike ($pdu)) || return template_error ("cannot read uptime", $template, $template_index); push @results, $read; } elsif (/^\@(.*)/) { ## %@ $template_index += 1; print STDERR "%@\n" if $template_debug; $_ = $1; push @results, $pdu; $pdu = ''; } else { return template_error ("Unknown decoding directive in template: $_", $template, $template_index); } } else { if (substr ($_, 0, 1) ne substr ($pdu, 0, 1)) { return template_error ("Expected ".substr ($_, 0, 1).", got ".substr ($pdu, 0, 1), $template, $template_index); } $_ = substr ($_,1); $pdu = substr ($pdu,1); } } return template_error ("PDU too long", $template, $template_index) if length ($pdu) > 0; return template_error ("PDU too short", $template, $template_index) if length ($_) > 0; @results; } sub decode_sequence ($) { my ($pdu) = @_; my ($result); my (@result); $result = ord (substr ($pdu, 0, 1)); return error ("Sequence expected") unless $result == (sequence_tag | constructor_flag); ($result, $pdu) = decode_length ($pdu, 1); return error ("Short PDU") if $result > length $pdu; @result = (substr ($pdu, 0, $result), substr ($pdu, $result)); @result; } sub decode_int ($) { my ($pdu) = @_; my $tag = ord (substr ($pdu, 0, 1)); return error ("Integer expected, found tag ".$tag) unless $tag == int_tag; decode_intlike ($pdu); } sub decode_intlike ($) { decode_intlike_s ($_[0], 1); } sub decode_unsignedlike ($) { decode_intlike_s ($_[0], 0); } my $have_math_bigint_p = 0; sub decode_intlike_s ($$) { my ($pdu, $signedp) = @_; my ($length,$result); ($length,$pdu) = decode_length ($pdu, 1); my $ptr = 0; $result = unpack ($signedp ? "c" : "C", substr ($pdu, $ptr++, 1)); if ($length > 5 || ($length == 5 && $result > 0)) { require 'Math/BigInt.pm' unless $have_math_bigint_p++; $result = new Math::BigInt ($result); } while (--$length > 0) { $result *= 256; $result += unpack ("C", substr ($pdu, $ptr++, 1)); } ($result, substr ($pdu, $ptr)); } sub decode_string ($) { my ($pdu) = shift; my ($result); $result = ord (substr ($pdu, 0, 1)); return error ("Expected octet string, got tag ".$result) unless $result == octet_string_tag; ($result, $pdu) = decode_length ($pdu, 1); return error ("Short PDU") if $result > length $pdu; return (substr ($pdu, 0, $result), substr ($pdu, $result)); } sub decode_length ($@) { my ($pdu) = shift; my $index = shift || 0; my ($result); my (@result); $result = ord (substr ($pdu, $index, 1)); if ($result & long_length) { if ($result == (long_length | 1)) { @result = (ord (substr ($pdu, $index+1, 1)), substr ($pdu, $index+2)); } elsif ($result == (long_length | 2)) { @result = ((ord (substr ($pdu, $index+1, 1)) << 8) + ord (substr ($pdu, $index+2, 1)), substr ($pdu, $index+3)); } else { return error ("Unsupported length"); } } else { @result = ($result, substr ($pdu, $index+1)); } @result; } # This takes a hashref that specifies functions to call when # the specified value type is being printed. It returns the # number of functions that were registered. sub register_pretty_printer($) { my ($h_ref) = shift; my ($type, $val, $cnt); $cnt = 0; while(($type, $val) = each %$h_ref) { if (ref $val eq "CODE") { $pretty_printer{$type} = $val; $cnt++; } } return($cnt); } # This takes a hashref that specifies functions to call when # the specified value type is being printed. It removes the # functions from the list for the types specified. # It returns the number of functions that were unregistered. sub unregister_pretty_printer($) { my ($h_ref) = shift; my ($type, $val, $cnt); $cnt = 0; while(($type, $val) = each %$h_ref) { if ((exists ($pretty_printer{$type})) && ($pretty_printer{$type} == $val)) { if (exists($default_printer{$type})) { $pretty_printer{$type} = $default_printer{$type}; } else { delete $pretty_printer{$type}; } $cnt++; } } return($cnt); } #### OID prefix check ### encoded_oid_prefix_p OID1 OID2 ### ### OID1 and OID2 should be BER-encoded OIDs. ### The function returns non-zero iff OID1 is a prefix of OID2. ### This can be used in the termination condition of a loop that walks ### a table using GetNext or GetBulk. ### sub encoded_oid_prefix_p ($$) { my ($oid1, $oid2) = @_; my ($i1, $i2); my ($l1, $l2); my ($subid1, $subid2); return error ("OID tag expected") unless ord (substr ($oid1, 0, 1)) == object_id_tag; return error ("OID tag expected") unless ord (substr ($oid2, 0, 1)) == object_id_tag; ($l1,$oid1) = decode_length ($oid1, 1); ($l2,$oid2) = decode_length ($oid2, 1); for ($i1 = 0, $i2 = 0; $i1 < $l1 && $i2 < $l2; ++$i1, ++$i2) { ($subid1,$i1) = &decode_subid ($oid1, $i1, $l1); ($subid2,$i2) = &decode_subid ($oid2, $i2, $l2); return 0 unless $subid1 == $subid2; } return $i2 if $i1 == $l1; return 0; } ### decode_subid OID INDEX ### ### Decodes a subid field from a BER-encoded object ID. ### Returns two values: the field, and the index of the last byte that ### was actually decoded. ### sub decode_subid ($$$) { my ($oid, $i, $l) = @_; my $subid = 0; my $next; while (($next = ord (substr ($oid, $i, 1))) >= 128) { $subid = ($subid << 7) + ($next & 0x7f); ++$i; return error ("decoding object ID: short field") unless $i < $l; } return (($subid << 7) + $next, $i); } sub error (@) { $errmsg = join ("",@_); return undef; } sub template_error ($$$) { my ($errmsg, $template, $index) = @_; return error ($errmsg."\n ".$template."\n ".(' ' x $index)."^"); } 1; mrtg-2.17.10/lib/mrtg2/SNMP_Session.pm0000644000175300017510000010464614171763414016310 0ustar oetikeroep### -*- mode: Perl -*- ###################################################################### ### SNMP Request/Response Handling ###################################################################### ### Copyright (c) 1995-2008, Simon Leinen. ### ### This program is free software; you can redistribute it under the ### "Artistic License 2.0" included in this distribution ### (file "Artistic"). ###################################################################### ### The abstract class SNMP_Session defines objects that can be used ### to communicate with SNMP entities. It has methods to send ### requests to and receive responses from an agent. ### ### Two instantiable subclasses are defined: ### SNMPv1_Session implements SNMPv1 (RFC 1157) functionality ### SNMPv2c_Session implements community-based SNMPv2. ###################################################################### ### Created by: Simon Leinen ### ### Contributions and fixes by: ### ### Matthew Trunnell ### Tobias Oetiker ### Heine Peters ### Daniel L. Needles ### Mike Mitchell ### Clinton Wong ### Alan Nichols ### Mike McCauley ### Andrew W. Elble ### Brett T Warden : pretty UInteger32 ### Michael Deegan ### Sergio Macedo ### Jakob Ilves (/IlvJa) : PDU capture ### Valerio Bontempi : IPv6 support ### Lorenzo Colitti : IPv6 support ### Philippe Simonet : Export avoid... ### Luc Pauwels : use_16bit_request_ids ### Andrew Cornford-Matheson : inform ### Gerry Dalton : strict subs bug ### Mike Fischer : pass MSG_DONTWAIT to recv() ###################################################################### package SNMP_Session; require 5.002; use strict; use Exporter; use vars qw(@ISA $VERSION @EXPORT $errmsg $suppress_warnings $default_avoid_negative_request_ids $default_use_16bit_request_ids); use Socket; use BER '1.05'; use Carp; sub map_table ($$$ ); sub map_table_4 ($$$$); sub map_table_start_end ($$$$$$); sub index_compare ($$); sub oid_diff ($$); $VERSION = '1.12'; @ISA = qw(Exporter); @EXPORT = qw(errmsg suppress_warnings index_compare oid_diff recycle_socket ipv6available); my $default_debug = 0; ### Default initial timeout (in seconds) waiting for a response PDU ### after a request is sent. Note that when a request is retried, the ### timeout is increased by BACKOFF (see below). ### my $default_timeout = 2.0; ### Default number of attempts to get a reply for an SNMP request. If ### no response is received after TIMEOUT seconds, the request is ### resent and a new response awaited with a longer timeout (see the ### documentation on BACKOFF below). The "retries" value should be at ### least 1, because the first attempt counts, too (the name "retries" ### is confusing, sorry for that). ### my $default_retries = 5; ### Default backoff factor for SNMP_Session objects. This factor is ### used to increase the TIMEOUT every time an SNMP request is ### retried. ### my $default_backoff = 1.0; ### Default value for maxRepetitions. This specifies how many table ### rows are requested in getBulk requests. Used when walking tables ### using getBulk (only available in SNMPv2(c) and later). If this is ### too small, then a table walk will need unnecessarily many ### request/response exchanges. If it is too big, the agent may ### compute many variables after the end of the table. It is ### recommended to set this explicitly for each table walk by using ### map_table_4(). ### my $default_max_repetitions = 12; ### Default value for "avoid_negative_request_ids". ### ### Set this to non-zero if you have agents that have trouble with ### negative request IDs, and don't forget to complain to your agent ### vendor. According to the spec (RFC 1905), the request-id is an ### Integer32, i.e. its range is from -(2^31) to (2^31)-1. However, ### some agents erroneously encode the response ID as an unsigned, ### which prevents this code from matching such responses to requests. ### $SNMP_Session::default_avoid_negative_request_ids = 0; ### Default value for "use_16bit_request_ids". ### ### Set this to non-zero if you have agents that use 16bit request IDs, ### and don't forget to complain to your agent vendor. ### $SNMP_Session::default_use_16bit_request_ids = 0; ### Whether all SNMP_Session objects should share a single UDP socket. ### $SNMP_Session::recycle_socket = 0; ### IPv6 initialization code: check that IPv6 libraries are available, ### and if so load them. ### We store the length of an IPv6 socket address structure in the class ### so we can determine if a socket address is IPv4 or IPv6 just by checking ### its length. The proper way to do this would be to use sockaddr_family(), ### but this function is only available in recent versions of Socket.pm. my $ipv6_addr_len; ### Flags to be passed to recv() when non-blocking behavior is ### desired. On most POSIX-like systems this will be set to ### MSG_DONTWAIT, on other systems we leave it at zero. ### my $dont_wait_flags; BEGIN { $ipv6_addr_len = undef; $SNMP_Session::ipv6available = 0; $dont_wait_flags = 0; if (eval {local $SIG{__DIE__};require Socket6;} && eval {local $SIG{__DIE__};require IO::Socket::INET6; IO::Socket::INET6->VERSION("1.26");}) { Socket6->import(qw(pack_sockaddr_in6 inet_pton getaddrinfo)); $ipv6_addr_len = length(pack_sockaddr_in6(161, inet_pton(AF_INET6(), "::1"))); $SNMP_Session::ipv6available = 1; } eval 'local $SIG{__DIE__};local $SIG{__WARN__};$dont_wait_flags = MSG_DONTWAIT();'; } my $the_socket; $SNMP_Session::errmsg = ''; $SNMP_Session::suppress_warnings = 0; sub get_request { 0 | context_flag () }; sub getnext_request { 1 | context_flag () }; sub get_response { 2 | context_flag () }; sub set_request { 3 | context_flag () }; sub trap_request { 4 | context_flag () }; sub getbulk_request { 5 | context_flag () }; sub inform_request { 6 | context_flag () }; sub trap2_request { 7 | context_flag () }; sub standard_udp_port { 161 }; sub open { return SNMPv1_Session::open (@_); } sub timeout { $_[0]->{timeout} } sub retries { $_[0]->{retries} } sub backoff { $_[0]->{backoff} } sub set_timeout { my ($session, $timeout) = @_; croak ("timeout ($timeout) must be a positive number") unless $timeout > 0.0; $session->{'timeout'} = $timeout; } sub set_retries { my ($session, $retries) = @_; croak ("retries ($retries) must be a non-negative integer") unless $retries == int ($retries) && $retries >= 0; $session->{'retries'} = $retries; } sub set_backoff { my ($session, $backoff) = @_; croak ("backoff ($backoff) must be a number >= 1.0") unless $backoff == int ($backoff) && $backoff >= 1.0; $session->{'backoff'} = $backoff; } sub encode_request_3 ($$$@) { my($this, $reqtype, $encoded_oids_or_pairs, $i1, $i2) = @_; my($request); local($_); $this->{request_id} = ($this->{request_id} == 0x7fffffff) ? -0x80000000 : $this->{request_id}+1; $this->{request_id} += 0x80000000 if ($this->{avoid_negative_request_ids} && $this->{request_id} < 0); $this->{request_id} &= 0x0000ffff if ($this->{use_16bit_request_ids}); foreach $_ (@{$encoded_oids_or_pairs}) { if (ref ($_) eq 'ARRAY') { $_ = &encode_sequence ($_->[0], $_->[1]) || return $this->ber_error ("encoding pair"); } else { $_ = &encode_sequence ($_, encode_null()) || return $this->ber_error ("encoding value/null pair"); } } $request = encode_tagged_sequence ($reqtype, encode_int ($this->{request_id}), defined $i1 ? encode_int ($i1) : encode_int_0 (), defined $i2 ? encode_int ($i2) : encode_int_0 (), encode_sequence (@{$encoded_oids_or_pairs})) || return $this->ber_error ("encoding request PDU"); return $this->wrap_request ($request); } sub encode_get_request { my($this, @oids) = @_; return encode_request_3 ($this, get_request, \@oids); } sub encode_getnext_request { my($this, @oids) = @_; return encode_request_3 ($this, getnext_request, \@oids); } sub encode_getbulk_request { my($this, $non_repeaters, $max_repetitions, @oids) = @_; return encode_request_3 ($this, getbulk_request, \@oids, $non_repeaters, $max_repetitions); } sub encode_set_request { my($this, @encoded_pairs) = @_; return encode_request_3 ($this, set_request, \@encoded_pairs); } sub encode_trap_request ($$$$$$@) { my($this, $ent, $agent, $gen, $spec, $dt, @pairs) = @_; my($request); local($_); foreach $_ (@pairs) { if (ref ($_) eq 'ARRAY') { $_ = &encode_sequence ($_->[0], $_->[1]) || return $this->ber_error ("encoding pair"); } else { $_ = &encode_sequence ($_, encode_null()) || return $this->ber_error ("encoding value/null pair"); } } $request = encode_tagged_sequence (trap_request, $ent, $agent, $gen, $spec, $dt, encode_sequence (@pairs)) || return $this->ber_error ("encoding trap PDU"); return $this->wrap_request ($request); } sub encode_v2_trap_request ($@) { my($this, @pairs) = @_; return encode_request_3($this, trap2_request, \@pairs); } sub decode_get_response { my($this, $response) = @_; my @rest; @{$this->{'unwrapped'}}; } sub decode_trap_request ($$) { my ($this, $trap) = @_; my ($snmp_version, $community, $ent, $agent, $gen, $spec, $dt, $request_id, $error_status, $error_index, $bindings); ($snmp_version, $community, $ent, $agent, $gen, $spec, $dt, $bindings) = decode_by_template ($trap, "%{%i%s%*{%O%A%i%i%u%{%@", trap_request); if (!defined $snmp_version) { ($snmp_version, $community, $request_id, $error_status, $error_index, $bindings) = decode_by_template ($trap, "%{%i%s%*{%i%i%i%{%@", trap2_request); if (!defined $snmp_version) { ($snmp_version, $community,$request_id, $error_status, $error_index, $bindings) = decode_by_template ($trap, "%{%i%s%*{%i%i%i%{%@", inform_request); } return $this->error_return ("v2 trap/inform request contained errorStatus/errorIndex " .$error_status."/".$error_index) if defined $error_status && defined $error_index && ($error_status != 0 || $error_index != 0); } if (!defined $snmp_version) { return $this->error_return ("BER error decoding trap:\n ".$BER::errmsg); } return ($community, $ent, $agent, $gen, $spec, $dt, $bindings); } sub wait_for_response { my($this) = shift; my($timeout) = shift || 10.0; my($rin,$win,$ein) = ('','',''); my($rout,$wout,$eout); vec($rin,$this->sockfileno,1) = 1; select($rout=$rin,$wout=$win,$eout=$ein,$timeout); } sub get_request_response ($@) { my($this, @oids) = @_; return $this->request_response_5 ($this->encode_get_request (@oids), get_response, \@oids, 1); } sub set_request_response ($@) { my($this, @pairs) = @_; return $this->request_response_5 ($this->encode_set_request (@pairs), get_response, \@pairs, 1); } sub getnext_request_response ($@) { my($this,@oids) = @_; return $this->request_response_5 ($this->encode_getnext_request (@oids), get_response, \@oids, 1); } sub getbulk_request_response ($$$@) { my($this,$non_repeaters,$max_repetitions,@oids) = @_; return $this->request_response_5 ($this->encode_getbulk_request ($non_repeaters,$max_repetitions,@oids), get_response, \@oids, 1); } sub trap_request_send ($$$$$$@) { my($this, $ent, $agent, $gen, $spec, $dt, @pairs) = @_; my($req); $req = $this->encode_trap_request ($ent, $agent, $gen, $spec, $dt, @pairs); ## Encoding may have returned an error. return undef unless defined $req; $this->send_query($req) || return $this->error ("send_trap: $!"); return 1; } sub v2_trap_request_send ($$$@) { my($this, $trap_oid, $dt, @pairs) = @_; my @sysUptime_OID = ( 1,3,6,1,2,1,1,3 ); my @snmpTrapOID_OID = ( 1,3,6,1,6,3,1,1,4,1 ); my($req); unshift @pairs, [encode_oid (@snmpTrapOID_OID,0), encode_oid (@{$trap_oid})]; unshift @pairs, [encode_oid (@sysUptime_OID,0), encode_timeticks ($dt)]; $req = $this->encode_v2_trap_request (@pairs); ## Encoding may have returned an error. return undef unless defined $req; $this->send_query($req) || return $this->error ("send_trap: $!"); return 1; } sub request_response_5 ($$$$$) { my ($this, $req, $response_tag, $oids, $errorp) = @_; my $retries = $this->retries; my $timeout = $this->timeout; my ($nfound, $timeleft); ## Encoding may have returned an error. return undef unless defined $req; $timeleft = $timeout; while ($retries > 0) { $this->send_query ($req) || return $this->error ("send_query: $!"); # IlvJa # Add request pdu to capture_buffer push @{$this->{'capture_buffer'}}, $req if (defined $this->{'capture_buffer'} and ref $this->{'capture_buffer'} eq 'ARRAY'); # wait_for_response: ($nfound, $timeleft) = $this->wait_for_response($timeleft); if ($nfound > 0) { my($response_length); $response_length = $this->receive_response_3 ($response_tag, $oids, $errorp, 1); if ($response_length) { # IlvJa # Add response pdu to capture_buffer push (@{$this->{'capture_buffer'}}, substr($this->{'pdu_buffer'}, 0, $response_length) ) if (defined $this->{'capture_buffer'} and ref $this->{'capture_buffer'} eq 'ARRAY'); # return $response_length; } elsif (defined ($response_length)) { goto wait_for_response; # A response has been received, but for a different # request ID or from a different IP address. } else { return undef; } } else { ## No response received - retry --$retries; $timeout *= $this->backoff; $timeleft = $timeout; } } # IlvJa # Add empty packet to capture_buffer push @{$this->{'capture_buffer'}}, "" if (defined $this->{'capture_buffer'} and ref $this->{'capture_buffer'} eq 'ARRAY'); # $this->error ("no response received"); } sub map_table ($$$) { my ($session, $columns, $mapfn) = @_; return $session->map_table_4 ($columns, $mapfn, $session->default_max_repetitions ()); } sub map_table_4 ($$$$) { my ($session, $columns, $mapfn, $max_repetitions) = @_; return $session->map_table_start_end ($columns, $mapfn, "", undef, $max_repetitions); } sub map_table_start_end ($$$$$$) { my ($session, $columns, $mapfn, $start, $end, $max_repetitions) = @_; my @encoded_oids; my $call_counter = 0; my $base_index = $start; do { foreach (@encoded_oids = @{$columns}) { $_=encode_oid (@{$_},split '\.',$base_index) || return $session->ber_error ("encoding OID $base_index"); } if ($session->getnext_request_response (@encoded_oids)) { my $response = $session->pdu_buffer; my ($bindings) = $session->decode_get_response ($response); my $smallest_index = undef; my @collected_values = (); my @bases = @{$columns}; while ($bindings ne '') { my ($binding, $oid, $value); my $base = shift @bases; ($binding, $bindings) = decode_sequence ($bindings); ($oid, $value) = decode_by_template ($binding, "%O%@"); my $out_index; $out_index = &oid_diff ($base, $oid); my $cmp; if (!defined $smallest_index || ($cmp = index_compare ($out_index,$smallest_index)) == -1) { $smallest_index = $out_index; grep ($_=undef, @collected_values); push @collected_values, $value; } elsif ($cmp == 1) { push @collected_values, undef; } else { push @collected_values, $value; } } (++$call_counter, &$mapfn ($smallest_index, @collected_values)) if defined $smallest_index; $base_index = $smallest_index; } else { return undef; } } while (defined $base_index && (!defined $end || index_compare ($base_index, $end) < 0)); $call_counter; } sub index_compare ($$) { my ($i1, $i2) = @_; $i1 = '' unless defined $i1; $i2 = '' unless defined $i2; if ($i1 eq '') { return $i2 eq '' ? 0 : 1; } elsif ($i2 eq '') { return 1; } elsif (!$i1) { return $i2 eq '' ? 1 : !$i2 ? 0 : 1; } elsif (!$i2) { return -1; } else { my ($f1,$r1) = split('\.',$i1,2); my ($f2,$r2) = split('\.',$i2,2); if ($f1 < $f2) { return -1; } elsif ($f1 > $f2) { return 1; } else { return index_compare ($r1,$r2); } } } sub oid_diff ($$) { my($base, $full) = @_; my $base_dotnot = join ('.',@{$base}); my $full_dotnot = BER::pretty_oid ($full); return undef unless substr ($full_dotnot, 0, length $base_dotnot) eq $base_dotnot && substr ($full_dotnot, length $base_dotnot, 1) eq '.'; substr ($full_dotnot, length ($base_dotnot)+1); } # Pretty_address returns a human-readable representation of an IPv4 or IPv6 address. sub pretty_address { my($addr) = shift; my($port, $addrunpack, $addrstr); # Disable strict subs to stop old versions of perl from # complaining about AF_INET6 when Socket6 is not available if( (defined $ipv6_addr_len) && (length $addr == $ipv6_addr_len)) { ($port,$addrunpack) = Socket6::unpack_sockaddr_in6 ($addr); $addrstr = inet_ntop (AF_INET6(), $addrunpack); } else { ($port,$addrunpack) = unpack_sockaddr_in ($addr); $addrstr = inet_ntoa ($addrunpack); } return sprintf ("[%s].%d", $addrstr, $port); } sub version { $VERSION; } sub error_return ($$) { my ($this,$message) = @_; $SNMP_Session::errmsg = $message; unless ($SNMP_Session::suppress_warnings) { $message =~ s/^/ /mg; carp ("Error:\n".$message."\n"); } return undef; } sub error ($$) { my ($this,$message) = @_; my $session = $this->to_string; $SNMP_Session::errmsg = $message."\n".$session; unless ($SNMP_Session::suppress_warnings) { $session =~ s/^/ /mg; $message =~ s/^/ /mg; carp ("SNMP Error:\n".$SNMP_Session::errmsg."\n"); } return undef; } sub ber_error ($$) { my ($this,$type) = @_; my ($errmsg) = $BER::errmsg; $errmsg =~ s/^/ /mg; return $this->error ("$type:\n$errmsg"); } package SNMPv1_Session; use strict qw(vars subs); # see above use vars qw(@ISA); use SNMP_Session; use Socket; use BER; use IO::Socket; use Carp; BEGIN { if($SNMP_Session::ipv6available) { import IO::Socket::INET6; Socket6->import(qw(pack_sockaddr_in6 inet_pton getaddrinfo)); } } @ISA = qw(SNMP_Session); sub snmp_version { 0 } # Supports both IPv4 and IPv6. # Numeric IPv6 addresses must be passed between square brackets [] sub open { my($this, $remote_hostname,$community,$port, $max_pdu_len,$local_port,$max_repetitions, $local_hostname,$ipv4only) = @_; my($remote_addr,$socket,$sockfamily); $ipv4only = 1 unless defined $ipv4only; $sockfamily = AF_INET; $community = 'public' unless defined $community; $port = SNMP_Session::standard_udp_port unless defined $port; $max_pdu_len = 8000 unless defined $max_pdu_len; $max_repetitions = $default_max_repetitions unless defined $max_repetitions; if ($ipv4only || ! $SNMP_Session::ipv6available) { # IPv4-only code, uses only Socket and INET calls if (defined $remote_hostname) { $remote_addr = inet_aton ($remote_hostname) or return $this->error_return ("can't resolve \"$remote_hostname\" to IP address"); } if ($SNMP_Session::recycle_socket && defined $the_socket) { $socket = $the_socket; } else { $socket = IO::Socket::INET->new(Proto => 17, Type => SOCK_DGRAM, LocalAddr => $local_hostname, LocalPort => $local_port) || return $this->error_return ("creating socket: $!"); $the_socket = $socket if $SNMP_Session::recycle_socket; } $remote_addr = pack_sockaddr_in ($port, $remote_addr) if defined $remote_addr; } else { # IPv6-capable code. Will use IPv6 or IPv4 depending on the address. # Uses Socket6 and INET6 calls. # If it's a numeric IPv6 addresses, remove square brackets if ($remote_hostname =~ /^\[(.*)\]$/) { $remote_hostname = $1; } my (@res, $socktype_tmp, $proto_tmp, $canonname_tmp); @res = getaddrinfo($remote_hostname, $port, AF_UNSPEC, SOCK_DGRAM); ($sockfamily, $socktype_tmp, $proto_tmp, $remote_addr, $canonname_tmp) = @res; if (scalar(@res) < 5) { return $this->error_return ("can't resolve \"$remote_hostname\" to IPv6 address"); } if ($SNMP_Session::recycle_socket && defined $the_socket) { $socket = $the_socket; } elsif ($sockfamily == AF_INET) { $socket = IO::Socket::INET->new(Proto => 17, Type => SOCK_DGRAM, LocalAddr => $local_hostname, LocalPort => $local_port) || return $this->error_return ("creating socket: $!"); } else { $socket = IO::Socket::INET6->new(Proto => 17, Type => SOCK_DGRAM, LocalAddr => $local_hostname, LocalPort => $local_port) || return $this->error_return ("creating socket: $!"); $the_socket = $socket if $SNMP_Session::recycle_socket; } } bless { 'sock' => $socket, 'sockfileno' => fileno ($socket), 'community' => $community, 'remote_hostname' => $remote_hostname, 'remote_addr' => $remote_addr, 'sockfamily' => $sockfamily, 'max_pdu_len' => $max_pdu_len, 'pdu_buffer' => '\0' x $max_pdu_len, 'request_id' => (int (rand 0x10000) << 16) + int (rand 0x10000) - 0x80000000, 'timeout' => $default_timeout, 'retries' => $default_retries, 'backoff' => $default_backoff, 'debug' => $default_debug, 'error_status' => 0, 'error_index' => 0, 'default_max_repetitions' => $max_repetitions, 'use_getbulk' => 1, 'lenient_source_address_matching' => 1, 'lenient_source_port_matching' => 1, 'avoid_negative_request_ids' => $SNMP_Session::default_avoid_negative_request_ids, 'use_16bit_request_ids' => $SNMP_Session::default_use_16bit_request_ids, 'capture_buffer' => undef, }; } sub open_trap_session (@) { my ($this, $port) = @_; $port = 162 unless defined $port; return $this->open (undef, "", 161, undef, $port); } sub sock { $_[0]->{sock} } sub sockfileno { $_[0]->{sockfileno} } sub remote_addr { $_[0]->{remote_addr} } sub pdu_buffer { $_[0]->{pdu_buffer} } sub max_pdu_len { $_[0]->{max_pdu_len} } sub default_max_repetitions { defined $_[1] ? $_[0]->{default_max_repetitions} = $_[1] : $_[0]->{default_max_repetitions} } sub debug { defined $_[1] ? $_[0]->{debug} = $_[1] : $_[0]->{debug} } sub close { my($this) = shift; ## Avoid closing the socket if it may be shared with other session ## objects. if (! defined $the_socket || $this->sock ne $the_socket) { close ($this->sock) || $this->error ("close: $!"); } } sub wrap_request { my($this) = shift; my($request) = shift; encode_sequence (encode_int ($this->snmp_version), encode_string ($this->{community}), $request) || return $this->ber_error ("wrapping up request PDU"); } my @error_status_code = qw(noError tooBig noSuchName badValue readOnly genErr noAccess wrongType wrongLength wrongEncoding wrongValue noCreation inconsistentValue resourceUnavailable commitFailed undoFailed authorizationError notWritable inconsistentName); sub unwrap_response_5b { my ($this,$response,$tag,$oids,$errorp) = @_; my ($community,$request_id,@rest,$snmpver); ($snmpver,$community,$request_id, $this->{error_status}, $this->{error_index}, @rest) = decode_by_template ($response, "%{%i%s%*{%i%i%i%{%@", $tag); return $this->ber_error ("Error decoding response PDU") unless defined $snmpver; return $this->error ("Received SNMP response with unknown snmp-version field $snmpver") unless $snmpver == $this->snmp_version; if ($this->{error_status} != 0) { if ($errorp) { my ($oid, $errmsg); $errmsg = $error_status_code[$this->{error_status}] || $this->{error_status}; $oid = $oids->[$this->{error_index}-1] if $this->{error_index} > 0 && $this->{error_index}-1 <= $#{$oids}; $oid = $oid->[0] if ref($oid) eq 'ARRAY'; return ($community, $request_id, $this->error ("Received SNMP response with error code\n" ." error status: $errmsg\n" ." index ".$this->{error_index} .(defined $oid ? " (OID: ".&BER::pretty_oid($oid).")" : ""))); } else { if ($this->{error_index} == 1) { @rest[$this->{error_index}-1..$this->{error_index}] = (); } } } ($community, $request_id, @rest); } sub send_query ($$) { my ($this,$query) = @_; send ($this->sock,$query,0,$this->remote_addr); } ## Compare two sockaddr_in structures for equality. This is used when ## matching incoming responses with outstanding requests. Previous ## versions of the code simply did a bytewise comparison ("eq") of the ## two sockaddr_in structures, but this didn't work on some systems ## where sockaddr_in contains other elements than just the IP address ## and port number, notably FreeBSD. ## ## We allow for varying degrees of leniency when checking the source ## address. By default we now ignore it altogether, because there are ## agents that don't respond from UDP port 161, and there are agents ## that don't respond from the IP address the query had been sent to. ## ## The address family is stored in the session object. We could use ## sockaddr_family() to determine it from the sockaddr, but this function ## is only available in recent versions of Socket.pm. sub sa_equal_p ($$$) { my ($this, $sa1, $sa2) = @_; my ($p1,$a1,$p2,$a2); # Disable strict subs to stop old versions of perl from # complaining about AF_INET6 when Socket6 is not available if($this->{'sockfamily'} == AF_INET) { # IPv4 addresses ($p1,$a1) = unpack_sockaddr_in ($sa1); ($p2,$a2) = unpack_sockaddr_in ($sa2); } elsif($this->{'sockfamily'} == AF_INET6()) { # IPv6 addresses ($p1,$a1) = Socket6::unpack_sockaddr_in6 ($sa1); ($p2,$a2) = Socket6::unpack_sockaddr_in6 ($sa2); } else { return 0; } use strict "subs"; if (! $this->{'lenient_source_address_matching'}) { return 0 if $a1 ne $a2; } if (! $this->{'lenient_source_port_matching'}) { return 0 if $p1 != $p2; } return 1; } sub receive_response_3 { my ($this, $response_tag, $oids, $errorp, $dont_block_p) = @_; my ($remote_addr); my $flags = 0; $flags = $dont_wait_flags if defined $dont_block_p and $dont_block_p; $remote_addr = recv ($this->sock,$this->{'pdu_buffer'},$this->max_pdu_len,$flags); return $this->error ("receiving response PDU: $!") unless defined $remote_addr; return $this->error ("short (".length $this->{'pdu_buffer'} ." bytes) response PDU") unless length $this->{'pdu_buffer'} > 2; my $response = $this->{'pdu_buffer'}; ## ## Check whether the response came from the address we've sent the ## request to. If this is not the case, we should probably ignore ## it, as it may relate to another request. ## if (defined $this->{'remote_addr'}) { if (! $this->sa_equal_p ($remote_addr, $this->{'remote_addr'})) { if ($this->{'debug'} && !$SNMP_Session::recycle_socket) { carp ("Response came from ".&SNMP_Session::pretty_address($remote_addr) .", not ".&SNMP_Session::pretty_address($this->{'remote_addr'})) unless $SNMP_Session::suppress_warnings; } return 0; } } $this->{'last_sender_addr'} = $remote_addr; my ($response_community, $response_id, @unwrapped) = $this->unwrap_response_5b ($response, $response_tag, $oids, $errorp); if ($response_community ne $this->{community} || $response_id ne $this->{request_id}) { if ($this->{'debug'}) { carp ("$response_community != $this->{community}") unless $SNMP_Session::suppress_warnings || $response_community eq $this->{community}; carp ("$response_id != $this->{request_id}") unless $SNMP_Session::suppress_warnings || $response_id == $this->{request_id}; } return 0; } if (!defined $unwrapped[0]) { $this->{'unwrapped'} = undef; return undef; } $this->{'unwrapped'} = \@unwrapped; return length $this->pdu_buffer; } sub receive_trap { my ($this) = @_; my ($remote_addr, $iaddr, $port, $trap); $remote_addr = recv ($this->sock,$this->{'pdu_buffer'},$this->max_pdu_len,0); return undef unless $remote_addr; if( (defined $ipv6_addr_len) && (length $remote_addr == $ipv6_addr_len)) { ($port,$iaddr) = Socket6::unpack_sockaddr_in6($remote_addr); } else { ($port,$iaddr) = unpack_sockaddr_in($remote_addr); } $trap = $this->{'pdu_buffer'}; return ($trap, $iaddr, $port); } sub describe { my($this) = shift; print $this->to_string (),"\n"; } sub to_string { my($this) = shift; my ($class,$prefix); $class = ref($this); $prefix = ' ' x (length ($class) + 2); ($class .(defined $this->{remote_hostname} ? " (remote host: \"".$this->{remote_hostname}."\"" ." ".&SNMP_Session::pretty_address ($this->remote_addr).")" : " (no remote host specified)") ."\n" .$prefix." community: \"".$this->{'community'}."\"\n" .$prefix." request ID: ".$this->{'request_id'}."\n" .$prefix."PDU bufsize: ".$this->{'max_pdu_len'}." bytes\n" .$prefix." timeout: ".$this->{timeout}."s\n" .$prefix." retries: ".$this->{retries}."\n" .$prefix." backoff: ".$this->{backoff}.")"); ## sprintf ("SNMP_Session: %s (size %d timeout %g)", ## &SNMP_Session::pretty_address ($this->remote_addr),$this->max_pdu_len, ## $this->timeout); } ### SNMP Agent support ### contributed by Mike McCauley ### sub receive_request { my ($this) = @_; my ($remote_addr, $iaddr, $port, $request); $remote_addr = recv($this->sock, $this->{'pdu_buffer'}, $this->{'max_pdu_len'}, 0); return undef unless $remote_addr; if( (defined $ipv6_addr_len) && (length $remote_addr == $ipv6_addr_len)) { ($port,$iaddr) = Socket6::unpack_sockaddr_in6($remote_addr); } else { ($port,$iaddr) = unpack_sockaddr_in($remote_addr); } $request = $this->{'pdu_buffer'}; return ($request, $iaddr, $port); } sub decode_request { my ($this, $request) = @_; my ($snmp_version, $community, $requestid, $errorstatus, $errorindex, $bindings); ($snmp_version, $community, $requestid, $errorstatus, $errorindex, $bindings) = decode_by_template ($request, "%{%i%s%*{%i%i%i%@", SNMP_Session::get_request); if (defined $snmp_version) { # Its a valid get_request return(SNMP_Session::get_request, $requestid, $bindings, $community); } ($snmp_version, $community, $requestid, $errorstatus, $errorindex, $bindings) = decode_by_template ($request, "%{%i%s%*{%i%i%i%@", SNMP_Session::getnext_request); if (defined $snmp_version) { # Its a valid getnext_request return(SNMP_Session::getnext_request, $requestid, $bindings, $community); } ($snmp_version, $community, $requestid, $errorstatus, $errorindex, $bindings) = decode_by_template ($request, "%{%i%s%*{%i%i%i%@", SNMP_Session::set_request); if (defined $snmp_version) { # Its a valid set_request return(SNMP_Session::set_request, $requestid, $bindings, $community); } # Something wrong with this packet # Decode failed return undef; } package SNMPv2c_Session; use strict qw(vars subs); # see above use vars qw(@ISA); use SNMP_Session; use BER; use Carp; @ISA = qw(SNMPv1_Session); sub snmp_version { 1 } sub open { my $session = SNMPv1_Session::open (@_); return undef unless defined $session; return bless $session; } ## map_table_start_end using get-bulk ## sub map_table_start_end ($$$$$$) { my ($session, $columns, $mapfn, $start, $end, $max_repetitions) = @_; my @encoded_oids; my $call_counter = 0; my $base_index = $start; my $ncols = @{$columns}; my @collected_values = (); if (! $session->{'use_getbulk'}) { return SNMP_Session::map_table_start_end ($session, $columns, $mapfn, $start, $end, $max_repetitions); } $max_repetitions = $session->default_max_repetitions unless defined $max_repetitions; for (;;) { foreach (@encoded_oids = @{$columns}) { $_=encode_oid (@{$_},split '\.',$base_index) || return $session->ber_error ("encoding OID $base_index"); } if ($session->getbulk_request_response (0, $max_repetitions, @encoded_oids)) { my $response = $session->pdu_buffer; my ($bindings) = $session->decode_get_response ($response); my @colstack = (); my $k = 0; my $j; my $min_index = undef; my @bases = @{$columns}; my $n_bindings = 0; my $binding; ## Copy all bindings into the colstack. ## The colstack is a vector of vectors. ## It contains one vector for each "repeater" variable. ## while ($bindings ne '') { ($binding, $bindings) = decode_sequence ($bindings); my ($oid, $value) = decode_by_template ($binding, "%O%@"); push @{$colstack[$k]}, [$oid, $value]; ++$k; $k = 0 if $k >= $ncols; } ## Now collect rows from the column stack: ## ## Iterate through the column stacks to find the smallest ## index, collecting the values for that index in ## @collected_values. ## ## As long as a row can be assembled, the map function is ## called on it and the iteration proceeds. ## $base_index = undef; walk_rows_from_pdu: for (;;) { my $min_index = undef; for ($k = 0; $k < $ncols; ++$k) { $collected_values[$k] = undef; my $pair = $colstack[$k]->[0]; unless (defined $pair) { $min_index = undef; last walk_rows_from_pdu; } my $this_index = SNMP_Session::oid_diff ($columns->[$k], $pair->[0]); if (defined $this_index) { my $cmp = !defined $min_index ? -1 : SNMP_Session::index_compare ($this_index, $min_index); if ($cmp == -1) { for ($j = 0; $j < $k; ++$j) { unshift (@{$colstack[$j]}, [$min_index, $collected_values[$j]]); $collected_values[$j] = undef; } $min_index = $this_index; } if ($cmp <= 0) { $collected_values[$k] = $pair->[1]; shift @{$colstack[$k]}; } } } ($base_index = undef), last if !defined $min_index; last if defined $end and SNMP_Session::index_compare ($min_index, $end) >= 0; &$mapfn ($min_index, @collected_values); ++$call_counter; $base_index = $min_index; } } else { return undef; } last if !defined $base_index; last if defined $end and SNMP_Session::index_compare ($base_index, $end) >= 0; } $call_counter; } 1; mrtg-2.17.10/lib/mrtg2/SNMP_util.pm0000644000175300017510000012227614171763414015641 0ustar oetikeroep### - *- mode: Perl -*- ###################################################################### ### SNMP_util -- SNMP utilities using SNMP_Session.pm and BER.pm ###################################################################### ### Copyright (c) 1998-2010, Mike Mitchell. ### ### This program is free software; you can redistribute it under the ### "Artistic License 2.0" included in this distribution ### (file "Artistic"). ###################################################################### ### Created by: Mike Mitchell ### ### Contributions and fixes by: ### ### Tobias Oetiker : Basic layout ### Simon Leinen : SNMP_session.pm/BER.pm ### Jeff Allen : length() of undefined value ### Johannes Demel : MIB file parse problem ### Simon Leinen : more OIDs from Interface MIB ### Jacques Supcik : Specify local IP, port ### Tobias Oetiker : HASH as first OID to set SNMP options ### Simon Leinen : 'undefined port' bug ### Daniel McDonald : request for getbulk support ### Laurent Girod : code for snmpwalkhash ### Ian Duplisse : MIB parsing suggestions ### Jakob Ilves : return_array_refs for snmpwalk() ### Valerio Bontempi : IPv6 support ### Lorenzo Colitti : IPv6 support ### Joerg Kummer : TimeTicks support in snmpset() ### Christopher J. Tengi : Gauge32 support in snmpset() ### Nicolai Petri : hashref passing for snmpwalkhash() ### : parse NOTIFICATION-TYPE in MIB ### Dan Thorson : handle quotes in MIB comments better ###################################################################### package SNMP_util; require 5.004; use strict; use vars qw(@ISA @EXPORT $VERSION); use Exporter; use Carp; use BER "1.02"; use SNMP_Session "1.00"; use Socket; $VERSION = '1.15'; @ISA = qw(Exporter); @EXPORT = qw(snmpget snmpgetnext snmpwalk snmpset snmptrap snmpgetbulk snmpmaptable snmpmaptable4 snmpwalkhash snmpmapOID snmpMIB_to_OID snmpLoad_OID_Cache snmpQueue_MIB_File); # The OID numbers from RFC1213 (MIB-II) and RFC1315 (Frame Relay) # are pre-loaded below. %SNMP_util::OIDS = ( 'iso' => '1', 'org' => '1.3', 'dod' => '1.3.6', 'internet' => '1.3.6.1', 'directory' => '1.3.6.1.1', 'mgmt' => '1.3.6.1.2', 'mib-2' => '1.3.6.1.2.1', 'system' => '1.3.6.1.2.1.1', 'sysDescr' => '1.3.6.1.2.1.1.1.0', 'sysObjectID' => '1.3.6.1.2.1.1.2.0', 'sysUpTime' => '1.3.6.1.2.1.1.3.0', 'sysUptime' => '1.3.6.1.2.1.1.3.0', 'sysContact' => '1.3.6.1.2.1.1.4.0', 'sysName' => '1.3.6.1.2.1.1.5.0', 'sysLocation' => '1.3.6.1.2.1.1.6.0', 'sysServices' => '1.3.6.1.2.1.1.7.0', 'interfaces' => '1.3.6.1.2.1.2', 'ifNumber' => '1.3.6.1.2.1.2.1.0', 'ifTable' => '1.3.6.1.2.1.2.2', 'ifEntry' => '1.3.6.1.2.1.2.2.1', 'ifIndex' => '1.3.6.1.2.1.2.2.1.1', 'ifInOctets' => '1.3.6.1.2.1.2.2.1.10', 'ifInUcastPkts' => '1.3.6.1.2.1.2.2.1.11', 'ifInNUcastPkts' => '1.3.6.1.2.1.2.2.1.12', 'ifInDiscards' => '1.3.6.1.2.1.2.2.1.13', 'ifInErrors' => '1.3.6.1.2.1.2.2.1.14', 'ifInUnknownProtos' => '1.3.6.1.2.1.2.2.1.15', 'ifOutOctets' => '1.3.6.1.2.1.2.2.1.16', 'ifOutUcastPkts' => '1.3.6.1.2.1.2.2.1.17', 'ifOutNUcastPkts' => '1.3.6.1.2.1.2.2.1.18', 'ifOutDiscards' => '1.3.6.1.2.1.2.2.1.19', 'ifDescr' => '1.3.6.1.2.1.2.2.1.2', 'ifOutErrors' => '1.3.6.1.2.1.2.2.1.20', 'ifOutQLen' => '1.3.6.1.2.1.2.2.1.21', 'ifSpecific' => '1.3.6.1.2.1.2.2.1.22', 'ifType' => '1.3.6.1.2.1.2.2.1.3', 'ifMtu' => '1.3.6.1.2.1.2.2.1.4', 'ifSpeed' => '1.3.6.1.2.1.2.2.1.5', 'ifPhysAddress' => '1.3.6.1.2.1.2.2.1.6', 'ifAdminHack' => '1.3.6.1.2.1.2.2.1.7', 'ifAdminStatus' => '1.3.6.1.2.1.2.2.1.7', 'ifOperHack' => '1.3.6.1.2.1.2.2.1.8', 'ifOperStatus' => '1.3.6.1.2.1.2.2.1.8', 'ifLastChange' => '1.3.6.1.2.1.2.2.1.9', 'at' => '1.3.6.1.2.1.3', 'atTable' => '1.3.6.1.2.1.3.1', 'atEntry' => '1.3.6.1.2.1.3.1.1', 'atIfIndex' => '1.3.6.1.2.1.3.1.1.1', 'atPhysAddress' => '1.3.6.1.2.1.3.1.1.2', 'atNetAddress' => '1.3.6.1.2.1.3.1.1.3', 'ip' => '1.3.6.1.2.1.4', 'ipForwarding' => '1.3.6.1.2.1.4.1', 'ipOutRequests' => '1.3.6.1.2.1.4.10', 'ipOutDiscards' => '1.3.6.1.2.1.4.11', 'ipOutNoRoutes' => '1.3.6.1.2.1.4.12', 'ipReasmTimeout' => '1.3.6.1.2.1.4.13', 'ipReasmReqds' => '1.3.6.1.2.1.4.14', 'ipReasmOKs' => '1.3.6.1.2.1.4.15', 'ipReasmFails' => '1.3.6.1.2.1.4.16', 'ipFragOKs' => '1.3.6.1.2.1.4.17', 'ipFragFails' => '1.3.6.1.2.1.4.18', 'ipFragCreates' => '1.3.6.1.2.1.4.19', 'ipDefaultTTL' => '1.3.6.1.2.1.4.2', 'ipAddrTable' => '1.3.6.1.2.1.4.20', 'ipAddrEntry' => '1.3.6.1.2.1.4.20.1', 'ipAdEntAddr' => '1.3.6.1.2.1.4.20.1.1', 'ipAdEntIfIndex' => '1.3.6.1.2.1.4.20.1.2', 'ipAdEntNetMask' => '1.3.6.1.2.1.4.20.1.3', 'ipAdEntBcastAddr' => '1.3.6.1.2.1.4.20.1.4', 'ipAdEntReasmMaxSize' => '1.3.6.1.2.1.4.20.1.5', 'ipRouteTable' => '1.3.6.1.2.1.4.21', 'ipRouteEntry' => '1.3.6.1.2.1.4.21.1', 'ipRouteDest' => '1.3.6.1.2.1.4.21.1.1', 'ipRouteAge' => '1.3.6.1.2.1.4.21.1.10', 'ipRouteMask' => '1.3.6.1.2.1.4.21.1.11', 'ipRouteMetric5' => '1.3.6.1.2.1.4.21.1.12', 'ipRouteInfo' => '1.3.6.1.2.1.4.21.1.13', 'ipRouteIfIndex' => '1.3.6.1.2.1.4.21.1.2', 'ipRouteMetric1' => '1.3.6.1.2.1.4.21.1.3', 'ipRouteMetric2' => '1.3.6.1.2.1.4.21.1.4', 'ipRouteMetric3' => '1.3.6.1.2.1.4.21.1.5', 'ipRouteMetric4' => '1.3.6.1.2.1.4.21.1.6', 'ipRouteNextHop' => '1.3.6.1.2.1.4.21.1.7', 'ipRouteType' => '1.3.6.1.2.1.4.21.1.8', 'ipRouteProto' => '1.3.6.1.2.1.4.21.1.9', 'ipNetToMediaTable' => '1.3.6.1.2.1.4.22', 'ipNetToMediaEntry' => '1.3.6.1.2.1.4.22.1', 'ipNetToMediaIfIndex' => '1.3.6.1.2.1.4.22.1.1', 'ipNetToMediaPhysAddress' => '1.3.6.1.2.1.4.22.1.2', 'ipNetToMediaNetAddress' => '1.3.6.1.2.1.4.22.1.3', 'ipNetToMediaType' => '1.3.6.1.2.1.4.22.1.4', 'ipRoutingDiscards' => '1.3.6.1.2.1.4.23', 'ipInReceives' => '1.3.6.1.2.1.4.3', 'ipInHdrErrors' => '1.3.6.1.2.1.4.4', 'ipInAddrErrors' => '1.3.6.1.2.1.4.5', 'ipForwDatagrams' => '1.3.6.1.2.1.4.6', 'ipInUnknownProtos' => '1.3.6.1.2.1.4.7', 'ipInDiscards' => '1.3.6.1.2.1.4.8', 'ipInDelivers' => '1.3.6.1.2.1.4.9', 'icmp' => '1.3.6.1.2.1.5', 'icmpInMsgs' => '1.3.6.1.2.1.5.1', 'icmpInTimestamps' => '1.3.6.1.2.1.5.10', 'icmpInTimestampReps' => '1.3.6.1.2.1.5.11', 'icmpInAddrMasks' => '1.3.6.1.2.1.5.12', 'icmpInAddrMaskReps' => '1.3.6.1.2.1.5.13', 'icmpOutMsgs' => '1.3.6.1.2.1.5.14', 'icmpOutErrors' => '1.3.6.1.2.1.5.15', 'icmpOutDestUnreachs' => '1.3.6.1.2.1.5.16', 'icmpOutTimeExcds' => '1.3.6.1.2.1.5.17', 'icmpOutParmProbs' => '1.3.6.1.2.1.5.18', 'icmpOutSrcQuenchs' => '1.3.6.1.2.1.5.19', 'icmpInErrors' => '1.3.6.1.2.1.5.2', 'icmpOutRedirects' => '1.3.6.1.2.1.5.20', 'icmpOutEchos' => '1.3.6.1.2.1.5.21', 'icmpOutEchoReps' => '1.3.6.1.2.1.5.22', 'icmpOutTimestamps' => '1.3.6.1.2.1.5.23', 'icmpOutTimestampReps' => '1.3.6.1.2.1.5.24', 'icmpOutAddrMasks' => '1.3.6.1.2.1.5.25', 'icmpOutAddrMaskReps' => '1.3.6.1.2.1.5.26', 'icmpInDestUnreachs' => '1.3.6.1.2.1.5.3', 'icmpInTimeExcds' => '1.3.6.1.2.1.5.4', 'icmpInParmProbs' => '1.3.6.1.2.1.5.5', 'icmpInSrcQuenchs' => '1.3.6.1.2.1.5.6', 'icmpInRedirects' => '1.3.6.1.2.1.5.7', 'icmpInEchos' => '1.3.6.1.2.1.5.8', 'icmpInEchoReps' => '1.3.6.1.2.1.5.9', 'tcp' => '1.3.6.1.2.1.6', 'tcpRtoAlgorithm' => '1.3.6.1.2.1.6.1', 'tcpInSegs' => '1.3.6.1.2.1.6.10', 'tcpOutSegs' => '1.3.6.1.2.1.6.11', 'tcpRetransSegs' => '1.3.6.1.2.1.6.12', 'tcpConnTable' => '1.3.6.1.2.1.6.13', 'tcpConnEntry' => '1.3.6.1.2.1.6.13.1', 'tcpConnState' => '1.3.6.1.2.1.6.13.1.1', 'tcpConnLocalAddress' => '1.3.6.1.2.1.6.13.1.2', 'tcpConnLocalPort' => '1.3.6.1.2.1.6.13.1.3', 'tcpConnRemAddress' => '1.3.6.1.2.1.6.13.1.4', 'tcpConnRemPort' => '1.3.6.1.2.1.6.13.1.5', 'tcpInErrs' => '1.3.6.1.2.1.6.14', 'tcpOutRsts' => '1.3.6.1.2.1.6.15', 'tcpRtoMin' => '1.3.6.1.2.1.6.2', 'tcpRtoMax' => '1.3.6.1.2.1.6.3', 'tcpMaxConn' => '1.3.6.1.2.1.6.4', 'tcpActiveOpens' => '1.3.6.1.2.1.6.5', 'tcpPassiveOpens' => '1.3.6.1.2.1.6.6', 'tcpAttemptFails' => '1.3.6.1.2.1.6.7', 'tcpEstabResets' => '1.3.6.1.2.1.6.8', 'tcpCurrEstab' => '1.3.6.1.2.1.6.9', 'udp' => '1.3.6.1.2.1.7', 'udpInDatagrams' => '1.3.6.1.2.1.7.1', 'udpNoPorts' => '1.3.6.1.2.1.7.2', 'udpInErrors' => '1.3.6.1.2.1.7.3', 'udpOutDatagrams' => '1.3.6.1.2.1.7.4', 'udpTable' => '1.3.6.1.2.1.7.5', 'udpEntry' => '1.3.6.1.2.1.7.5.1', 'udpLocalAddress' => '1.3.6.1.2.1.7.5.1.1', 'udpLocalPort' => '1.3.6.1.2.1.7.5.1.2', 'egp' => '1.3.6.1.2.1.8', 'egpInMsgs' => '1.3.6.1.2.1.8.1', 'egpInErrors' => '1.3.6.1.2.1.8.2', 'egpOutMsgs' => '1.3.6.1.2.1.8.3', 'egpOutErrors' => '1.3.6.1.2.1.8.4', 'egpNeighTable' => '1.3.6.1.2.1.8.5', 'egpNeighEntry' => '1.3.6.1.2.1.8.5.1', 'egpNeighState' => '1.3.6.1.2.1.8.5.1.1', 'egpNeighStateUps' => '1.3.6.1.2.1.8.5.1.10', 'egpNeighStateDowns' => '1.3.6.1.2.1.8.5.1.11', 'egpNeighIntervalHello' => '1.3.6.1.2.1.8.5.1.12', 'egpNeighIntervalPoll' => '1.3.6.1.2.1.8.5.1.13', 'egpNeighMode' => '1.3.6.1.2.1.8.5.1.14', 'egpNeighEventTrigger' => '1.3.6.1.2.1.8.5.1.15', 'egpNeighAddr' => '1.3.6.1.2.1.8.5.1.2', 'egpNeighAs' => '1.3.6.1.2.1.8.5.1.3', 'egpNeighInMsgs' => '1.3.6.1.2.1.8.5.1.4', 'egpNeighInErrs' => '1.3.6.1.2.1.8.5.1.5', 'egpNeighOutMsgs' => '1.3.6.1.2.1.8.5.1.6', 'egpNeighOutErrs' => '1.3.6.1.2.1.8.5.1.7', 'egpNeighInErrMsgs' => '1.3.6.1.2.1.8.5.1.8', 'egpNeighOutErrMsgs' => '1.3.6.1.2.1.8.5.1.9', 'egpAs' => '1.3.6.1.2.1.8.6', 'transmission' => '1.3.6.1.2.1.10', 'frame-relay' => '1.3.6.1.2.1.10.32', 'frDlcmiTable' => '1.3.6.1.2.1.10.32.1', 'frDlcmiEntry' => '1.3.6.1.2.1.10.32.1.1', 'frDlcmiIfIndex' => '1.3.6.1.2.1.10.32.1.1.1', 'frDlcmiState' => '1.3.6.1.2.1.10.32.1.1.2', 'frDlcmiAddress' => '1.3.6.1.2.1.10.32.1.1.3', 'frDlcmiAddressLen' => '1.3.6.1.2.1.10.32.1.1.4', 'frDlcmiPollingInterval' => '1.3.6.1.2.1.10.32.1.1.5', 'frDlcmiFullEnquiryInterval' => '1.3.6.1.2.1.10.32.1.1.6', 'frDlcmiErrorThreshold' => '1.3.6.1.2.1.10.32.1.1.7', 'frDlcmiMonitoredEvents' => '1.3.6.1.2.1.10.32.1.1.8', 'frDlcmiMaxSupportedVCs' => '1.3.6.1.2.1.10.32.1.1.9', 'frDlcmiMulticast' => '1.3.6.1.2.1.10.32.1.1.10', 'frCircuitTable' => '1.3.6.1.2.1.10.32.2', 'frCircuitEntry' => '1.3.6.1.2.1.10.32.2.1', 'frCircuitIfIndex' => '1.3.6.1.2.1.10.32.2.1.1', 'frCircuitDlci' => '1.3.6.1.2.1.10.32.2.1.2', 'frCircuitState' => '1.3.6.1.2.1.10.32.2.1.3', 'frCircuitReceivedFECNs' => '1.3.6.1.2.1.10.32.2.1.4', 'frCircuitReceivedBECNs' => '1.3.6.1.2.1.10.32.2.1.5', 'frCircuitSentFrames' => '1.3.6.1.2.1.10.32.2.1.6', 'frCircuitSentOctets' => '1.3.6.1.2.1.10.32.2.1.7', 'frOutOctets' => '1.3.6.1.2.1.10.32.2.1.7', 'frCircuitReceivedFrames' => '1.3.6.1.2.1.10.32.2.1.8', 'frCircuitReceivedOctets' => '1.3.6.1.2.1.10.32.2.1.9', 'frInOctets' => '1.3.6.1.2.1.10.32.2.1.9', 'frCircuitCreationTime' => '1.3.6.1.2.1.10.32.2.1.10', 'frCircuitLastTimeChange' => '1.3.6.1.2.1.10.32.2.1.11', 'frCircuitCommittedBurst' => '1.3.6.1.2.1.10.32.2.1.12', 'frCircuitExcessBurst' => '1.3.6.1.2.1.10.32.2.1.13', 'frCircuitThroughput' => '1.3.6.1.2.1.10.32.2.1.14', 'frErrTable' => '1.3.6.1.2.1.10.32.3', 'frErrEntry' => '1.3.6.1.2.1.10.32.3.1', 'frErrIfIndex' => '1.3.6.1.2.1.10.32.3.1.1', 'frErrType' => '1.3.6.1.2.1.10.32.3.1.2', 'frErrData' => '1.3.6.1.2.1.10.32.3.1.3', 'frErrTime' => '1.3.6.1.2.1.10.32.3.1.4', 'frame-relay-globals' => '1.3.6.1.2.1.10.32.4', 'frTrapState' => '1.3.6.1.2.1.10.32.4.1', 'snmp' => '1.3.6.1.2.1.11', 'snmpInPkts' => '1.3.6.1.2.1.11.1', 'snmpInBadValues' => '1.3.6.1.2.1.11.10', 'snmpInReadOnlys' => '1.3.6.1.2.1.11.11', 'snmpInGenErrs' => '1.3.6.1.2.1.11.12', 'snmpInTotalReqVars' => '1.3.6.1.2.1.11.13', 'snmpInTotalSetVars' => '1.3.6.1.2.1.11.14', 'snmpInGetRequests' => '1.3.6.1.2.1.11.15', 'snmpInGetNexts' => '1.3.6.1.2.1.11.16', 'snmpInSetRequests' => '1.3.6.1.2.1.11.17', 'snmpInGetResponses' => '1.3.6.1.2.1.11.18', 'snmpInTraps' => '1.3.6.1.2.1.11.19', 'snmpOutPkts' => '1.3.6.1.2.1.11.2', 'snmpOutTooBigs' => '1.3.6.1.2.1.11.20', 'snmpOutNoSuchNames' => '1.3.6.1.2.1.11.21', 'snmpOutBadValues' => '1.3.6.1.2.1.11.22', 'snmpOutGenErrs' => '1.3.6.1.2.1.11.24', 'snmpOutGetRequests' => '1.3.6.1.2.1.11.25', 'snmpOutGetNexts' => '1.3.6.1.2.1.11.26', 'snmpOutSetRequests' => '1.3.6.1.2.1.11.27', 'snmpOutGetResponses' => '1.3.6.1.2.1.11.28', 'snmpOutTraps' => '1.3.6.1.2.1.11.29', 'snmpInBadVersions' => '1.3.6.1.2.1.11.3', 'snmpEnableAuthenTraps' => '1.3.6.1.2.1.11.30', 'snmpInBadCommunityNames' => '1.3.6.1.2.1.11.4', 'snmpInBadCommunityUses' => '1.3.6.1.2.1.11.5', 'snmpInASNParseErrs' => '1.3.6.1.2.1.11.6', 'snmpInTooBigs' => '1.3.6.1.2.1.11.8', 'snmpInNoSuchNames' => '1.3.6.1.2.1.11.9', 'ifName' => '1.3.6.1.2.1.31.1.1.1.1', 'ifInMulticastPkts' => '1.3.6.1.2.1.31.1.1.1.2', 'ifInBroadcastPkts' => '1.3.6.1.2.1.31.1.1.1.3', 'ifOutMulticastPkts' => '1.3.6.1.2.1.31.1.1.1.4', 'ifOutBroadcastPkts' => '1.3.6.1.2.1.31.1.1.1.5', 'ifHCInOctets' => '1.3.6.1.2.1.31.1.1.1.6', 'ifHCInUcastPkts' => '1.3.6.1.2.1.31.1.1.1.7', 'ifHCInMulticastPkts' => '1.3.6.1.2.1.31.1.1.1.8', 'ifHCInBroadcastPkts' => '1.3.6.1.2.1.31.1.1.1.9', 'ifHCOutOctets' => '1.3.6.1.2.1.31.1.1.1.10', 'ifHCOutUcastPkts' => '1.3.6.1.2.1.31.1.1.1.11', 'ifHCOutMulticastPkts' => '1.3.6.1.2.1.31.1.1.1.12', 'ifHCOutBroadcastPkts' => '1.3.6.1.2.1.31.1.1.1.13', 'ifLinkUpDownTrapEnable' => '1.3.6.1.2.1.31.1.1.1.14', 'ifHighSpeed' => '1.3.6.1.2.1.31.1.1.1.15', 'ifPromiscuousMode' => '1.3.6.1.2.1.31.1.1.1.16', 'ifConnectorPresent' => '1.3.6.1.2.1.31.1.1.1.17', 'ifAlias' => '1.3.6.1.2.1.31.1.1.1.18', 'ifCounterDiscontinuityTime' => '1.3.6.1.2.1.31.1.1.1.19', 'experimental' => '1.3.6.1.3', 'private' => '1.3.6.1.4', 'enterprises' => '1.3.6.1.4.1', ); # GIL my %revOIDS = (); # Reversed %SNMP_util::OIDS hash my $RevNeeded = 1; my $agent_start_time = time; undef $SNMP_util::Host; undef $SNMP_util::Session; undef $SNMP_util::Version; undef $SNMP_util::LHost; undef $SNMP_util::IPv4only; $SNMP_util::Debug = 0; $SNMP_util::CacheFile = "OID_cache.txt"; $SNMP_util::CacheLoaded = 0; $SNMP_util::Return_array_refs = 0; $SNMP_util::Return_hash_refs = 0; srand(time + $$); ### Prototypes sub snmpget ($@); sub snmpgetnext ($@); sub snmpopen ($$$); sub snmpwalk ($@); sub snmpwalk_flg ($$@); sub snmpset ($@); sub snmptrap ($$$$$@); sub snmpgetbulk ($$$@); sub snmpmaptable ($$@); sub snmpmaptable4 ($$$@); sub snmpwalkhash ($$@); sub toOID (@); sub snmpmapOID (@); sub snmpMIB_to_OID ($); sub encode_oid_with_errmsg ($); sub Check_OID ($); sub snmpLoad_OID_Cache ($); sub snmpQueue_MIB_File (@); sub MIB_fill_OID ($); sub version () { $VERSION; } # # Start an snmp session # sub snmpopen ($$$) { my($host, $type, $vars) = @_; my($nhost, $port, $community, $lhost, $lport, $nlhost); my($timeout, $retries, $backoff, $version); my $v4onlystr; $type = 0 if (!defined($type)); $community = "public"; $nlhost = ""; ($community, $host) = ($1, $2) if ($host =~ /^(.*)@([^@]+)$/); # We can't split on the : character because a numeric IPv6 # address contains a variable number of :'s my $opts; if( ($host =~ /^(\[.*\]):(.*)$/) or ($host =~ /^(\[.*\])$/) ) { # Numeric IPv6 address between [] ($host, $opts) = ($1, $2); } else { # Hostname or numeric IPv4 address ($host, $opts) = split(':', $host, 2); } ($port, $timeout, $retries, $backoff, $version, $v4onlystr) = split(':', $opts, 6) if(defined($opts) and (length $opts > 0) ); undef($version) if (defined($version) and length($version) <= 0); $v4onlystr = "" unless defined $v4onlystr; $version = '1' unless defined $version; if (defined($port) and ($port =~ /^([^!]*)!(.*)$/)) { ($port, $lhost) = ($1, $2); $nlhost = $lhost; ($lhost, $lport) = ($1, $2) if ($lhost =~ /^(.*)!(.*)$/); undef($lhost) if (defined($lhost) and (length($lhost) <= 0)); undef($lport) if (defined($lport) and (length($lport) <= 0)); } undef($port) if (defined($port) and length($port) <= 0); $port = 162 if ($type == 1 and !defined($port)); $nhost = "$community\@$host"; $nhost .= ":" . $port if (defined($port)); if ((!defined($SNMP_util::Session)) or ($SNMP_util::Host ne $nhost) or ($SNMP_util::Version ne $version) or ($SNMP_util::LHost ne $nlhost) or ($SNMP_util::IPv4only ne $v4onlystr)) { if (defined($SNMP_util::Session)) { $SNMP_util::Session->close(); undef $SNMP_util::Session; undef $SNMP_util::Host; undef $SNMP_util::Version; undef $SNMP_util::LHost; undef $SNMP_util::IPv4only; } $SNMP_util::Session = ($version =~ /^2c?$/i) ? SNMPv2c_Session->open($host, $community, $port, undef, $lport, undef, $lhost, ($v4onlystr eq 'v4only') ? 1:0 ) : SNMP_Session->open($host, $community, $port, undef, $lport, undef, $lhost, ($v4onlystr eq 'v4only') ? 1:0 ); ($SNMP_util::Host = $nhost, $SNMP_util::Version = $version, $SNMP_util::LHost = $nlhost, $SNMP_util::IPv4only = $v4onlystr) if defined($SNMP_util::Session); } if (defined($SNMP_util::Session)) { if (ref $vars->[0] eq 'HASH') { my $opts = shift @$vars; foreach $type (keys %$opts) { if ($type eq 'return_array_refs') { $SNMP_util::Return_array_refs = $opts->{$type}; } elsif ($type eq 'return_hash_refs') { $SNMP_util::Return_hash_refs = $opts->{$type}; } else { if (exists $SNMP_util::Session->{$type}) { if ($type eq 'timeout') { $SNMP_util::Session->set_timeout($opts->{$type}); } elsif ($type eq 'retries') { $SNMP_util::Session->set_retries($opts->{$type}); } elsif ($type eq 'backoff') { $SNMP_util::Session->set_backoff($opts->{$type}); } else { $SNMP_util::Session->{$type} = $opts->{$type}; } } else { carp "SNMPopen Unknown SNMP Option Key '$type'\n" unless ($SNMP_Session::suppress_warnings > 1); } } } } $SNMP_util::Session->set_timeout($timeout) if (defined($timeout) and (length($timeout) > 0)); $SNMP_util::Session->set_retries($retries) if (defined($retries) and (length($retries) > 0)); $SNMP_util::Session->set_backoff($backoff) if (defined($backoff) and (length($backoff) > 0)); } return $SNMP_util::Session; } # # A restricted snmpget. # sub snmpget ($@) { my($host, @vars) = @_; my(@enoid, $var, $response, $bindings, $binding, $value, $oid, @retvals); my $session; @retvals = (); $session = &snmpopen($host, 0, \@vars); if (!defined($session)) { carp "SNMPGET Problem for $host\n" unless ($SNMP_Session::suppress_warnings > 1); return wantarray ? @retvals : undef; } @enoid = &toOID(@vars); if ($#enoid < 0) { return wantarray ? @retvals : undef; } if ($session->get_request_response(@enoid)) { $response = $session->pdu_buffer; ($bindings) = $session->decode_get_response($response); while ($bindings) { ($binding, $bindings) = decode_sequence($bindings); ($oid, $value) = decode_by_template($binding, "%O%@"); my $tempo = pretty_print($value); push @retvals, $tempo; } return wantarray ? @retvals : $retvals[0]; } $var = join(' ', @vars); carp "SNMPGET Problem for $var on $host\n" unless ($SNMP_Session::suppress_warnings > 1); return wantarray ? @retvals : undef; } # # A restricted snmpgetnext. # sub snmpgetnext ($@) { my($host, @vars) = @_; my(@enoid, $var, $response, $bindings, $binding); my($value, $upoid, $oid, @retvals); my($noid); my $session; @retvals = (); $session = &snmpopen($host, 0, \@vars); if (!defined($session)) { carp "SNMPGETNEXT Problem for $host\n" unless ($SNMP_Session::suppress_warnings > 1); return wantarray ? @retvals : undef; } @enoid = &toOID(@vars); if ($#enoid < 0) { return wantarray ? @retvals : undef; } undef @vars; undef @retvals; foreach $noid (@enoid) { $upoid = pretty_print($noid); push(@vars, $upoid); } if ($session->getnext_request_response(@enoid)) { $response = $session->pdu_buffer; ($bindings) = $session->decode_get_response($response); while ($bindings) { ($binding, $bindings) = decode_sequence($bindings); ($oid, $value) = decode_by_template($binding, "%O%@"); my $tempo = pretty_print($oid); my $tempv = pretty_print($value); push @retvals, "$tempo:$tempv"; } return wantarray ? @retvals : $retvals[0]; } else { $var = join(' ', @vars); carp "SNMPGETNEXT Problem for $var on $host\n" unless ($SNMP_Session::suppress_warnings > 1); return wantarray ? @retvals : undef; } } # # A restricted snmpwalk. # sub snmpwalk ($@) { my($host, @vars) = @_; return(&snmpwalk_flg($host, undef, @vars)); } # # Walk the MIB, putting everything you find into hashes. # sub snmpwalkhash($$@) { # my($host, $hash_sub, @vars) = @_; return(&snmpwalk_flg( @_ )); } sub snmpwalk_flg ($$@) { my($host, $hash_sub, @vars) = @_; my(@enoid, $var, $response, $bindings, $binding); my($value, $upoid, $oid, @retvals, @retvaltmprefs); my($got, @nnoid, $noid, $ok, $ix, @avars); my $session; my(%soid); my(%done, %rethash, $h_ref); $h_ref = (ref $vars[$#vars] eq "HASH") ? pop(@vars) : \%rethash; $session = &snmpopen($host, 0, \@vars); if (!defined($session)) { carp "SNMPWALK Problem for $host\n" unless ($SNMP_Session::suppress_warnings > 1); if (defined($hash_sub)) { return ($h_ref) if ($SNMP_util::Return_hash_refs); return (%$h_ref); } else { @retvals = (); return (@retvals); } } @enoid = toOID(@vars); if ($#enoid < 0) { if (defined($hash_sub)) { return ($h_ref) if ($SNMP_util::Return_hash_refs); return (%$h_ref); } else { @retvals = (); return (@retvals); } } # GIL # # Create/Refresh a reversed hash with oid -> name # if (defined($hash_sub) and ($RevNeeded)) { %revOIDS = reverse %SNMP_util::OIDS; $RevNeeded = 0; } $got = 0; @nnoid = @enoid; undef @vars; foreach $noid (@enoid) { $upoid = pretty_print($noid); push(@vars, $upoid); } # @vars is the original set of walked variables. # @avars is the current set of walked variables as the # walk goes on. # @vars stays static while @avars may shrink as we reach end # of walk for individual variables during PDU exchange. @avars = @vars; # IlvJa # # Create temporary array of refs to return vals. if ($SNMP_util::Return_array_refs) { for($ix = 0;$ix < scalar @vars; $ix++) { my $tmparray = []; $retvaltmprefs[$ix] = $tmparray; $retvals[$ix] = $tmparray; } } while(($SNMP_util::Version ne '1' and $session->{'use_getbulk'}) ? $session->getbulk_request_response(0, $session->default_max_repetitions(), @nnoid) : $session->getnext_request_response(@nnoid)) { $got = 1; $response = $session->pdu_buffer; ($bindings) = $session->decode_get_response($response); $ix = 0; while ($bindings) { ($binding, $bindings) = decode_sequence($bindings); unless ($nnoid[$ix]) { # IlvJa $ix = ++$ix % (scalar @avars); next; } ($oid, $value) = decode_by_template($binding, "%O%@"); $ok = 0; my $tempo = pretty_print($oid); $noid = $avars[$ix]; # IlvJa if ($tempo =~ /^$noid\./ or $tempo eq $noid ) { $ok = 1; $upoid = $noid; } else { # IlvJa # # The walk for variable $vars[$ix] has been finished as # $nnoid[$ix] no longer is in the $avar[$ix] OID tree. # So we exclude this variable from further requests. $avars[$ix] = ""; $nnoid[$ix] = ""; $retvaltmprefs[$ix] = undef if $SNMP_util::Return_array_refs; } if ($ok) { my $tmp = encode_oid_with_errmsg ($tempo); if (!defined $tmp) { if (defined($hash_sub)) { return ($h_ref) if ($SNMP_util::Return_hash_refs); return (%$h_ref); } else { @retvals = (); return (@retvals); } } if (exists($done{$tmp})) { # GIL, Ilvja # # We've detected a loop for $nnoid[$ix], so mark it as finished. # Exclude this variable from further requests. # $avars[$ix] = ""; $nnoid[$ix] = ""; $retvaltmprefs[$ix] = undef if $SNMP_util::Return_array_refs; next; } $nnoid[$ix] = $tmp; # Keep on walking. (IlvJa) my $tempv = pretty_print($value); if (defined($hash_sub)) { # # extract name of the oid, if possible, the rest becomes the instance # my $inst = ""; my $upo = $upoid; while (!exists($revOIDS{$upo}) and length($upo)) { $upo =~ s/(\.\d+?)$//; if (defined($1) and length($1)) { $inst = $1 . $inst; } else { $upo = ""; last; } } if (length($upo) and exists($revOIDS{$upo})) { $upo = $revOIDS{$upo} . $inst; } else { $upo = $upoid; } $inst = ""; while (!exists($revOIDS{$tempo}) and length($tempo)) { $tempo =~ s/(\.\d+?)$//; if (defined($1) and length($1)) { $inst = $1 . $inst; } else { $tempo = ""; last; } } if (length($tempo) and exists($revOIDS{$tempo})) { $var = $revOIDS{$tempo}; } else { $var = pretty_print($oid); } # # call hash_sub # &$hash_sub($h_ref, $host, $var, $tempo, $inst, $tempv, $upo); } else { if ($SNMP_util::Return_array_refs) { $tempo=~s/^$upoid\.//; push @{$retvaltmprefs[$ix]}, "$tempo:$tempv"; } else { $tempo=~s/^$upoid\.// if ($#enoid <= 0); push @retvals, "$tempo:$tempv"; } } $done{$tmp} = 1; # GIL } $ix = ++$ix % (scalar @avars); } # Ok, @nnoid should contain the remaining variables for the # next request. Some or all entries in @nnoid might be the empty # string. If the nth element in @nnoid is "" that means that # the walk related to the nth variable in the last request has been # completed and we should not include that var in subsequent reqs. # Clean up both @nnoid and @avars so "" elements are removed. @nnoid = grep (($_), @nnoid); @avars = grep (($_), @avars); @retvaltmprefs = grep (($_), @retvaltmprefs); last if ($#nnoid < 0); # @nnoid empty means we are done walking. } if (!$got) { $var = join(' ', @vars); carp "SNMPWALK Problem for $var on $host\n" unless ($SNMP_Session::suppress_warnings > 1); @retvals = (); } if (defined($hash_sub)) { return ($h_ref) if ($SNMP_util::Return_hash_refs); return (%$h_ref); } else { return (@retvals); } } # # A restricted snmpset. # sub snmpset($@) { my($host, @vars) = @_; my(@enoid, $response, $bindings, $binding); my($oid, @retvals, $type, $value, $val); my $session; @retvals = (); $session = &snmpopen($host, 0, \@vars); if (!defined($session)) { carp "SNMPSET Problem for $host\n" unless ($SNMP_Session::suppress_warnings > 1); return wantarray ? @retvals : undef; } while(@vars) { ($oid) = toOID((shift @vars)); $type = shift @vars; $value = shift @vars; $type =~ tr/A-Z/a-z/; if ($type eq "int") { $val = encode_int($value); } elsif ($type eq "integer") { $val = encode_int($value); } elsif ($type eq "string") { $val = encode_string($value); } elsif ($type eq "octetstring") { $val = encode_string($value); } elsif ($type eq "octet string") { $val = encode_string($value); } elsif ($type eq "oid") { $val = encode_oid_with_errmsg($value); } elsif ($type eq "object id") { $val = encode_oid_with_errmsg($value); } elsif ($type eq "object identifier") { $val = encode_oid_with_errmsg($value); } elsif ($type eq "ipaddr") { $val = encode_ip_address($value); } elsif ($type eq "ip address") { $val = encode_ip_address($value); } elsif ($type eq "timeticks") { $val = encode_timeticks($value); } elsif ($type eq "uint") { $val = encode_uinteger32($value); } elsif ($type eq "uinteger") { $val = encode_uinteger32($value); } elsif ($type eq "uinteger32") { $val = encode_uinteger32($value); } elsif ($type eq "unsigned int") { $val = encode_uinteger32($value); } elsif ($type eq "unsigned integer") { $val = encode_uinteger32($value); } elsif ($type eq "unsigned integer32") { $val = encode_uinteger32($value); } elsif ($type eq "counter") { $val = encode_counter32($value); } elsif ($type eq "counter32") { $val = encode_counter32($value); } elsif ($type eq "counter64") { $val = encode_counter64($value); } elsif ($type eq "gauge") { $val = encode_gauge32($value); } elsif ($type eq "gauge32") { $val = encode_gauge32($value); } else { carp "unknown SNMP type: $type\n" unless ($SNMP_Session::suppress_warnings > 1); return wantarray ? @retvals : undef; } if (!defined($val)) { carp "SNMP type $type value $value didn't encode properly\n" unless ($SNMP_Session::suppress_warnings > 1); return wantarray ? @retvals : undef; } push @enoid, [$oid,$val]; } if ($#enoid < 0) { return wantarray ? @retvals : undef; } if ($session->set_request_response(@enoid)) { $response = $session->pdu_buffer; ($bindings) = $session->decode_get_response($response); while ($bindings) { ($binding, $bindings) = decode_sequence($bindings); ($oid, $value) = decode_by_template($binding, "%O%@"); my $tempo = pretty_print($value); push @retvals, $tempo; } return wantarray ? @retvals : $retvals[0]; } return wantarray ? @retvals : undef; } # # Send an SNMP trap # sub snmptrap($$$$$@) { my($host, $ent, $agent, $gen, $spec, @vars) = @_; my($oid, @retvals, $type, $value); my(@enoid); my $session; $session = &snmpopen($host, 1, \@vars); if (!defined($session)) { carp "SNMPTRAP Problem for $host\n" unless ($SNMP_Session::suppress_warnings > 1); return undef; } if ($agent =~ /^\d+\.\d+\.\d+\.\d+(.*)/ ) { $agent = pack("C*", split /\./, $agent); } else { $agent = inet_aton($agent); } push @enoid, toOID(($ent)); push @enoid, encode_ip_address($agent); push @enoid, encode_int($gen); push @enoid, encode_int($spec); push @enoid, encode_timeticks((time-$agent_start_time) * 100); while(@vars) { ($oid) = toOID((shift @vars)); $type = shift @vars; $value = shift @vars; if ($type =~ /string/i) { $value = encode_string($value); push @enoid, [$oid,$value]; } elsif ($type =~ /ipaddr/i) { $value = encode_ip_address($value); push @enoid, [$oid,$value]; } elsif ($type =~ /int/i) { $value = encode_int($value); push @enoid, [$oid,$value]; } elsif ($type =~ /oid/i) { my $tmp = encode_oid_with_errmsg($value); return undef unless defined $tmp; push @enoid, [$oid,$tmp]; } else { carp "unknown SNMP type: $type\n" unless ($SNMP_Session::suppress_warnings > 1); return undef; } } return($session->trap_request_send(@enoid)); } # # A restricted snmpgetbulk. # sub snmpgetbulk ($$$@) { my($host, $nr, $mr, @vars) = @_; my(@enoid, $var, $response, $bindings, $binding); my($value, $upoid, $oid, @retvals); my($noid); my $session; @retvals = (); $session = &snmpopen($host, 0, \@vars); if (!defined($session)) { carp "SNMPGETBULK Problem for $host\n" unless ($SNMP_Session::suppress_warnings > 1); return @retvals; } @enoid = &toOID(@vars); return @retvals if ($#enoid < 0); undef @vars; foreach $noid (@enoid) { $upoid = pretty_print($noid); push(@vars, $upoid); } if ($session->getbulk_request_response($nr, $mr, @enoid)) { $response = $session->pdu_buffer; ($bindings) = $session->decode_get_response($response); while ($bindings) { ($binding, $bindings) = decode_sequence($bindings); ($oid, $value) = decode_by_template($binding, "%O%@"); my $tempo = pretty_print($oid); my $tempv = pretty_print($value); push @retvals, "$tempo:$tempv"; } return @retvals; } else { $var = join(' ', @vars); carp "SNMPGETBULK Problem for $var on $host\n" unless ($SNMP_Session::suppress_warnings > 1); return @retvals; } } # # walk a table, calling a user-supplied function for each # column of a table. # sub snmpmaptable($$@) { my($host, $fun, @vars) = @_; return snmpmaptable4($host, $fun, 0, @vars); } sub snmpmaptable4($$$@) { my($host, $fun, $max_reps, @vars) = @_; my(@enoid, $var, $session); $session = &snmpopen($host, 0, \@vars); if (!defined($session)) { carp "SNMPMAPTABLE Problem for $host\n" unless ($SNMP_Session::suppress_warnings > 1); return undef; } foreach $var (toOID(@vars)) { push(@enoid, [split('\.', pretty_print($var))]); } $max_reps = $session->default_max_repetitions() if ($max_reps <= 0); return $session->map_table_start_end( [@enoid], sub() { my ($ind, @vals) = @_; my (@pvals, $val); foreach $val (@vals) { push(@pvals, pretty_print($val)); } &$fun($ind, @pvals); }, "", undef, $max_reps); } # # Given an OID in either ASN.1 or mixed text/ASN.1 notation, return an # encoded OID. # sub toOID(@) { my(@vars) = @_; my($oid, $var, $tmp, $tmpv, @retvar); undef @retvar; foreach $var (@vars) { ($oid, $tmp) = &Check_OID($var); if (!$oid and $SNMP_util::CacheLoaded == 0) { $tmp = $SNMP_Session::suppress_warnings; $SNMP_Session::suppress_warnings = 1000; &snmpLoad_OID_Cache($SNMP_util::CacheFile); $SNMP_util::CacheLoaded = 1; $SNMP_Session::suppress_warnings = $tmp; ($oid, $tmp) = &Check_OID($var); } while (!$oid and $#SNMP_util::MIB_Files >= 0) { $tmp = $SNMP_Session::suppress_warnings; $SNMP_Session::suppress_warnings = 1000; snmpMIB_to_OID(shift(@SNMP_util::MIB_Files)); $SNMP_Session::suppress_warnings = $tmp; ($oid, $tmp) = &Check_OID($var); if ($oid) { open(CACHE, ">>$SNMP_util::CacheFile"); print CACHE "$tmp\t$oid\n"; close(CACHE); } } if ($oid) { $var =~ s/^$tmp/$oid/; } else { carp "Unknown SNMP var $var\n" unless ($SNMP_Session::suppress_warnings > 1); next; } while ($var =~ /\"([^\"]*)\"/) { $tmp = sprintf("%d.%s", length($1), join(".", map(ord, split(//, $1)))); $var =~ s/\"$1\"/$tmp/; } print "toOID: $var\n" if $SNMP_util::Debug; $tmp = encode_oid_with_errmsg($var); if (!defined($tmp)) { my @empty = (); return @empty; } push(@retvar, $tmp); } return @retvar; } # # Add passed-in text, OID pairs to the OID mapping table. # sub snmpmapOID(@) { my(@vars) = @_; my($oid, $txt); while($#vars >= 0) { $txt = shift @vars; $oid = shift @vars; next unless($txt =~ /^[a-zA-Z][\w\-]*(\.[a-zA-Z][\w\-])*$/); next unless($oid =~ /^\d+(\.\d+)*$/); $SNMP_util::OIDS{$txt} = $oid; $RevNeeded = 1; print "snmpmapOID: $txt => $oid\n" if $SNMP_util::Debug; } return undef; } # # Open the passed-in file name and read it in to populate # the cache of text-to-OID map table. It expects lines # with two fields, the first the textual string like "ifInOctets", # and the second the OID value, like "1.3.6.1.2.1.2.2.1.10". # # blank lines and anything after a '#' or between '--' is ignored. # sub snmpLoad_OID_Cache ($) { my($arg) = @_; my($txt, $oid); if (!open(CACHE, $arg)) { carp "snmpLoad_OID_Cache: Can't open $arg: $!" unless ($SNMP_Session::suppress_warnings > 1); return -1; } while() { s/#.*//; # '#' starts a comment s/--.*?--/ /g; # comment delimited by '--', like MIBs s/--.*//; # comment started by '--' next if (/^$/); next unless (/\s/); # must have whitespace as separator chomp; ($txt, $oid) = split(' ', $_, 2); $txt = $1 if ($txt =~ /^[\'\"](.*)[\'\"]/); $oid = $1 if ($oid =~ /^[\'\"](.*)[\'\"]/); if (($txt =~ /^\.?\d+(\.\d+)*\.?$/) and ($oid !~ /^\.?\d+(\.\d+)*\.?$/)) { my($a) = $oid; $oid = $txt; $txt = $a; } $oid =~ s/^\.//; $oid =~ s/\.$//; &snmpmapOID($txt, $oid); } close(CACHE); return 0; } # # Check to see if an OID is in the text-to-OID cache. # Returns the OID and the corresponding text as two separate # elements. # sub Check_OID ($) { my($var) = @_; my($tmp, $tmpv, $oid); if ($var =~ /^[a-zA-Z][\w\-]*(\.[a-zA-Z][\w\-]*)*/) { $tmp = $&; $tmpv = $tmp; for (;;) { last if exists($SNMP_util::OIDS{$tmpv}); last if !($tmpv =~ s/^[^\.]*\.//); } $oid = $SNMP_util::OIDS{$tmpv}; if ($oid) { return ($oid, $tmp); } else { my @empty = (); return @empty; } } return ($var, $var); } # # Save the passed-in list of MIB files until an OID can't be # found in the existing table. At that time the MIB file will # be loaded, and the lookup attempted again. # sub snmpQueue_MIB_File (@) { my(@files) = @_; my($file); foreach $file (@files) { push(@SNMP_util::MIB_Files, $file); } } # # Read in the passed MIB file, parsing it # for their text-to-OID mappings # sub snmpMIB_to_OID ($) { my($arg) = @_; my($cnt, $quote, $buf, %tOIDs, $tgot); my($var, @parts, $strt, $indx, $ind, $val); if (!open(MIB, $arg)) { carp "snmpMIB_to_OID: Can't open $arg: $!" unless ($SNMP_Session::suppress_warnings > 1); return -1; } print "snmpMIB_to_OID: loading $arg\n" if $SNMP_util::Debug; $cnt = 0; $quote = 0; $tgot = 0; $buf = ''; while() { if ($quote) { next unless /"/; $quote = 0; } chomp; $buf .= ' ' . $_; $buf =~ s/"[^"]*"//g; # throw away quoted strings $buf =~ s/--.*?--/ /g; # throw away comments (-- anything --) $buf =~ s/--.*//; # throw away comments (-- anything to EOL) $buf =~ s/\s+/ /g; # clean up multiple spaces if ($buf =~ /"/) { # look for quoted string $quote = 1; next; } if ($buf =~ /DEFINITIONS *::= *BEGIN/) { $cnt += MIB_fill_OID(\%tOIDs) if ($tgot); $buf = ''; %tOIDs = (); $tgot = 0; next; } $buf =~ s/OBJECT-TYPE/OBJECT IDENTIFIER/; $buf =~ s/OBJECT-IDENTITY/OBJECT IDENTIFIER/; $buf =~ s/OBJECT-GROUP/OBJECT IDENTIFIER/; $buf =~ s/MODULE-IDENTITY/OBJECT IDENTIFIER/; $buf =~ s/NOTIFICATION-TYPE/OBJECT IDENTIFIER/; $buf =~ s/ IMPORTS .*\;//; $buf =~ s/ SEQUENCE *{.*}//; $buf =~ s/ SYNTAX .*//; $buf =~ s/ [\w\-]+ *::= *OBJECT IDENTIFIER//; $buf =~ s/ OBJECT IDENTIFIER.*::= *{/ OBJECT IDENTIFIER ::= {/; if ($buf =~ / ([\w\-]+) OBJECT IDENTIFIER *::= *{([^}]+)}/) { $var = $1; $buf = $2; $buf =~ s/ +$//; $buf =~ s/\s+\(/\(/g; # remove spacing around '(' $buf =~ s/\(\s+/\(/g; $buf =~ s/\s+\)/\)/g; # remove spacing before ')' @parts = split(' ', $buf); $strt = ''; foreach $indx (@parts) { if ($indx =~ /([\w\-]+)\((\d+)\)/) { $ind = $1; $val = $2; if (exists($tOIDs{$strt})) { $tOIDs{$ind} = $tOIDs{$strt} . '.' . $val; } elsif ($strt ne '') { $tOIDs{$ind} = "${strt}.${val}"; } else { $tOIDs{$ind} = $val; } $strt = $ind; $tgot = 1; } elsif ($indx =~ /^\d+$/) { if (exists($tOIDs{$strt})) { $tOIDs{$var} = $tOIDs{$strt} . '.' . $indx; } else { $tOIDs{$var} = "${strt}.${indx}"; } $tgot = 1; } else { $strt = $indx; } } $buf = ''; } } $cnt += MIB_fill_OID(\%tOIDs) if ($tgot); $RevNeeded = 1 if ($cnt > 0); return $cnt; } # # Fill the OIDS hash with results from the MIB parsing # sub MIB_fill_OID ($) { my($href) = @_; my($cnt, $changed, @del, $var, $val, @parts, $indx); my(%seen); $cnt = 0; do { $changed = 0; @del = (); foreach $var (keys %$href) { $val = $href->{$var}; @parts = split('\.', $val); $val = ''; foreach $indx (@parts) { if ($indx =~ /^\d+$/) { $val .= '.' . $indx; } else { if (exists($SNMP_util::OIDS{$indx})) { $val = $SNMP_util::OIDS{$indx}; } else { $val .= '.' . $indx; } } } if ($val =~ /^[\d\.]+$/) { $val =~ s/^\.+//; if (!exists($SNMP_util::OIDS{$var}) || (length($val) > length($SNMP_util::OIDS{$var}))) { $SNMP_util::OIDS{$var} = $val; print "'$var' => '$val'\n" if $SNMP_util::Debug; $changed = 1; $cnt++; } push @del, $var; } } foreach $var (@del) { delete $href->{$var}; } } while($changed); $Carp::CarpLevel++; foreach $var (sort keys %$href) { $val = $href->{$var}; $val =~ s/\..*//; next if (exists($seen{$val})); $seen{$val} = 1; $seen{$var} = 1; carp "snmpMIB_to_OID: prefix \"$val\" unknown, load the parent MIB first.\n" unless ($SNMP_Session::suppress_warnings > 1); } $Carp::CarpLevel--; return $cnt; } sub encode_oid_with_errmsg ($) { my ($oid) = @_; my $tmp = encode_oid(split(/\./, $oid)); if (! defined $tmp) { carp "cannot encode Object ID $oid: $BER::errmsg" unless ($SNMP_Session::suppress_warnings > 1); return undef; } return $tmp; } 1; mrtg-2.17.10/lib/mrtg2/MRTG_lib.pm0000644000175300017510000024253114171763414015423 0ustar oetikeroep# -*- mode: Perl -*- package MRTG_lib; ################################################################### # MRTG 2.17.10 Support library MRTG_lib.pm ################################################################### # Created by Tobias Oetiker # and Dave Rand # # For individual Contributers check the CHANGES file # ################################################################### # # Distributed under the GNU General Public License # ################################################################### require 5.005; use strict; use vars qw($OS $SL $PS @EXPORT @ISA $VERSION %timestrpospattern); my %mrtgrules; BEGIN { # Automatic OS detection ... do NOT touch if ( $^O =~ /^(?:(ms)?(dos|win(32|nt)?))/i ) { $OS = 'NT'; $SL = '\\'; $PS = ';'; } elsif ( $^O =~ /^NetWare$/i ) { $OS = 'NW'; $SL = '/'; $PS = ';'; } elsif ( $^O =~ /^VMS$/i ) { $OS = 'VMS'; $SL = '.'; $PS = ':'; } elsif ( $^O =~ /^os2$/i ) { $OS = 'OS2'; $SL = '/'; $PS = ';'; } else { $OS = 'UNIX'; $SL = '/'; $PS = ':'; } } require Exporter; @ISA = qw(Exporter); @EXPORT = qw(readcfg cfgcheck setup_loghandlers datestr expistr ensureSL timestamp create_pid demonize_me debug log2rrd storeincache readfromcache clearfromcache cleanhostkey populateconfcache readconfcache writeconfcache v4onlyifnecessary); $VERSION = 2.100016; %timestrpospattern = ( 'NO' => 0, 'LU' => 1, 'RU' => 2, 'LL' => 3, 'RL' => 4 ); %mrtgrules = ( # General CFG 'workdir' => [sub{$_[0] && (-d $_[0])}, sub{"Working directory $_[0] does not exist"}], 'htmldir' => [sub{$_[0] && (-d $_[0])}, sub{"Html directory $_[0] does not exist"}], 'imagedir' => [sub{$_[0] && (-d $_[0])}, sub{"Image directory $_[0] does not exist"}], 'logdir' => [sub{$_[0] && (-d $_[0] )}, sub{"Log directory $_[0] does not exist"}], 'forks' => [sub{$_[0] && (int($_[0]) > 0 and $MRTG_lib::OS eq 'UNIX')}, sub{"Less than 1 fork or not running on Unix/Linux"}], 'refresh' => [sub{int($_[0]) >= 300}, sub{"$_[0] should be 300 seconds or more"}], 'enablesnmpv3' => [sub{((lc($_[0])) eq 'yes' or (lc($_[0])) eq 'no')}, sub{"$_[0] must be yes or no"}], 'enableipv6' => [sub{((lc($_[0])) eq 'yes' or (lc($_[0])) eq 'no')}, sub{"$_[0] must be yes or no"}], 'interval' => [sub{$_[0] =~ /(\d+)(?::(\d+))?/ ; my $int = $1*60; $int += $2 if $2; $int >= 1 and $int <= 60*60}, sub{"$_[0] should be at least 1 Second (0:01) and no more than 60 Minutes (60)"}], 'writeexpires' => [sub{1}, sub{"Internal Error"}], 'nomib2' => [sub{1}, sub{"Internal Error"}], 'singlerequest' => [sub{1}, sub{"Internal Error"}], 'icondir' => [sub{$_[0]}, sub{"Directory argument missing"}], 'language' => [sub{1}, sub{"Mrtg not localized for $_[0] - defaulting to english"}], 'loadmibs' => [sub{$_[0]}, sub{"No MIB Files specified"}], 'userrdtool' => [sub{0}, sub{"UseRRDtool is not valid any more. Use LogFormat, PathAdd and LibAdd instead"}], 'userrdtool[]' => [sub{0}, sub{"UseRRDtool[] is not valid any more. Check the new xyz*bla[] syntax for passing parameters to tool xyz who reads the mrtg.cfg"}], 'logformat' => [sub{$_[0] =~ /^(rateup|rrdtool)$/}, sub{"Invalid Logformat '$_[0]'"}], 'pathadd' => [sub{-d $_[0]}, sub{"$_[0] is not the name of a directory"}], 'libadd' => [sub{-d $_[0]}, sub{"$_[0] is not the name of a directory"}], 'runasdaemon' => [sub{1}, sub{"Internal Error"}], 'nodetach' => [sub{1}, sub{"Internal Error"}], 'maxage' => [sub{(($_[0] =~ /^[0-9]+$/) and ($_[0] > 0)) }, sub{"$_[0] must be a Number bigger than 0"}], 'nospacechar' => [sub{length($_[0]) == 1}, sub{"$_[0] must be one character long"}], 'snmpoptions' => [sub{ debug('eval',"snmpotions $_[0]");local $SIG{__DIE__}; eval( '{'.$_[0].'}' ); return not $@}, sub{"Must have the format \"OptA => Number, OptB => 'String', ... \""}], 'conversioncode' => [sub{-r $_[0]}, sub{"Cannot read conversion code file $_[0]"}], # Check for an environment setting for RRDCACHED_ADDRESS # Steve Shipway, Sep 2010 'rrdcached' => # [sub{(($_[0] =~ /^unix:(\S+)/)and(-w $1))}, sub{"Currently, only UNIX domain sockets are supported for RRDCached, and must exist and be writable."}], [sub{1},sub{"Internal Error"}], # Get graphite server name/ip and port 'sendtographite' => [sub{$_[0] =~ /^.*,\d+$/}, sub{"Invalid Graphite Destination '$_[0]'"}], # Per Router CFG 'target[]' => [sub{1}, sub{"Internal Error"}], #will test this later 'snmpoptions[]' => [sub{ debug('eval',"snmpotions[] $_[0]");local $SIG{__DIE__}; eval('{'.$_[0].'}' ); return not $@}, sub{"Must have the format \"OptA => Number, OptB => 'String', ... \""}], 'routeruptime[]' => [sub{1}, sub{"Internal Error"}], #will test this later 'routername[]' => [sub{1}, sub{"Internal Error"}], #will test this later 'nohc[]' => [sub{((lc($_[0])) eq 'yes' or (lc($_[0])) eq 'no')}, sub{"$_[0] must be yes or no"}], 'maxbytes[]' => [sub{(($_[0] =~ /^[0-9]+$/) && ($_[0] > 0)) }, sub{"$_[0] must be a Number bigger than 0"}], 'maxbytes1[]' => [sub{(($_[0] =~ /^[0-9]+$/) && ($_[0] > 0))}, sub{"$_[0] must be numerical and larger than 0"}], 'maxbytes2[]' => [sub{(($_[0] =~ /^[0-9]+$/) && ($_[0] > 0))}, sub{"$_[0] must a number bigger than 0"}], 'ipv4only[]' => [sub{((lc($_[0])) eq 'yes' or (lc($_[0])) eq 'no')}, sub{"$_[0] must be yes or no"}], 'absmax[]' => [sub{($_[0] =~ /^[0-9]+$/)}, sub{"$_[0] must be a Number"}], 'title[]' => [sub{1}, sub{"Internal Error"}], #what ever the user chooses. 'directory[]' => [sub{1}, sub{"Internal Error"}], #what ever the user chooses. 'clonedirectory[]' => [sub{($_[0] =~ /[^,]\s*$/)}, sub{"$_[0] with comma must have the second parameter"}], 'pagetop[]' => [sub{1}, sub{"Internal Error"}], #what ever the user chooses. 'bodytag[]' => [sub{1}, sub{"Internal Error"}], #what ever the user chooses. 'pagefoot[]' => [sub{1}, sub{"Internal Error"}], #what ever the user chooses. 'addhead[]' => [sub{1}, sub{"Internal Error"}], #what ever the user chooses. 'rrdrowcount[]' => [sub{1}, sub{"Internal Error"}], #what ever the user chooses. 'rrdrowcount30m[]' => [sub{1}, sub{"Internal Error"}], #what ever the user chooses. 'rrdrowcount2h[]' => [sub{1}, sub{"Internal Error"}], #what ever the user chooses. 'rrdrowcount1d[]' => [sub{1}, sub{"Internal Error"}], #what ever the user chooses. 'rrdhwrras[]' => [sub{$_[0] =~ /^RRA:(HWPREDICT|SEASONAL|DEVPREDICT|DEVSEASONAL|FAILURES):\S+(\s+RRA:(HWPREDICT|SEASONAL|DEVPREDICT|DEVSEASONAL|FAILURES):\S+)*$/}, sub{"This does not look like rrdtool HW RRAs. Check the rrdcreate manual page for inspiration. ($_[0])"}], 'extension[]' => [sub{1}, sub{"Internal Error"}], #what ever the user chooses. 'unscaled[]' => [sub{$_[0] =~ /[ndwmy]+/i}, sub{"Must be a string of [n]one, [d]ay, [w]eek, [m]onth, [y]ear"}], 'weekformat[]' => [sub{$_[0] =~ /[UVW]/}, sub{"Must be either W, V, or U"}], 'withpeak[]' => [sub{$_[0] =~ /[ndwmy]+/i}, sub{"Must be a string of [n]one, [d]ay, [w]eek, [m]onth, [y]ear"}], 'suppress[]' => [sub{$_[0] =~ /[ndwmy]+/i}, sub{"Must be a string of [n]one, [d]ay, [w]eek, [m]onth, [y]ear"}], 'xsize[]' => [sub{((int($_[0]) >= 30) && (int($_[0]) <= 600))}, sub{"$_[0] must be between 30 and 600 pixels"}], 'ysize[]' => [sub{(int($_[0]) >= 30)}, sub{"Must be >= 30 pixels"}], 'ytics[]' => [sub{(int($_[0]) >= 1) }, sub{"Must be >= 1"}], 'yticsfactor[]' => [sub{$_[0] =~ /[-+0-9.efg]+/}, sub{"Should be a numerical value"}], 'factor[]' => [sub{$_[0] =~ /[-+0-9.efg]+/}, sub{"Should be a numerical value"}], 'step[]' => [sub{(int($_[0]) >= 0)}, sub{"$_[0] must be > 0"}], 'timezone[]' => [sub{1}, sub{"Internal Error"}], 'options[]' => [sub{1}, sub{"Internal Error"}], 'colours[]' => [sub{1}, sub{"Internal Error"}], 'background[]' => [sub{1}, sub{"Internal Error"}], 'textcolor[]' => [sub{1}, sub{"Internal Error"}], 'kilo[]' => [sub{($_[0] =~ /^[0-9]+$/)}, sub{"$_[0] must be a Integer Number"}], #define whatever k should be (1000, 1024, ???) 'kmg[]' => [sub{1}, sub{"Internal Error"}], 'pngtitle[]' => [sub{1}, sub{"Internal Error"}], 'ylegend[]' => [sub{1}, sub{"Internal Error"}], 'shortlegend[]' => [sub{1}, sub{"Internal Error"}], 'legend1[]' => [sub{1}, sub{"Internal Error"}], 'legend2[]' => [sub{1}, sub{"Internal Error"}], 'legend3[]' => [sub{1}, sub{"Internal Error"}], 'legend4[]' => [sub{1}, sub{"Internal Error"}], 'legend5[]' => [sub{1}, sub{"Internal Error"}], 'legendi[]' => [sub{1}, sub{"Internal Error"}], 'legendo[]' => [sub{1}, sub{"Internal Error"}], 'setenv[]' => [sub{$_[0] =~ /^(?:[-\w]+=\"[^"]*"(?:\s+|$))+$/}, sub{"$_[0] must be XY=\"dddd\" AASD=\"kjlkj\" ... "}], 'xzoom[]' => [sub{($_[0] =~ /^[0-9]+(?:\.[0-9]+)?$/)}, sub{"$_[0] must be a Number xxx.xxx"}], 'yzoom[]' => [sub{($_[0] =~ /^[0-9]+(?:\.[0-9]+)?$/)}, sub{"$_[0] must be a Number xxx.xxx"}], 'xscale[]' => [sub{($_[0] =~ /^[0-9]+(?:\.[0-9]+)?$/)}, sub{"$_[0] must be a Number xxx.xxx"}], 'yscale[]' => [sub{($_[0] =~ /^[0-9]+(?:\.[0-9]+)?$/)}, sub{"$_[0] must be a Number xxx.xxx"}], 'threshdir' => [sub{$_[0] && (-d $_[0])}, sub{"Threshold directory $_[0] does not exist"}], 'threshhyst' => [sub{($_[0] =~ /^[0-9]+(?:\.[0-9]+)?$/)}, sub{"$_[0] must be a Number xxx.xxx"}], 'hwthreshhyst' => [sub{($_[0] =~ /^[0-9]+(?:\.[0-9]+)?$/)}, sub{"$_[0] must be a Number xxx.xxx"}], 'threshmailserver' => [sub{$_[0] && gethostbyname($_[0])}, sub{"Unknown mailserver hostname $_[0]"}], 'threshmailsender' => [sub{$_[0] && ($_[0] =~ /\S+\@\S+/)}, sub{"ThreshMailAddress $_[0] does not look like an email address at all"}], 'threshmini[]' => [sub{1}, sub{"Internal Threshold Config Error"}], 'threshmino[]' => [sub{1}, sub{"Internal Threshold Config Error"}], 'threshmaxi[]' => [sub{1}, sub{"Internal Threshold Config Error"}], 'threshmaxo[]' => [sub{1}, sub{"Internal Threshold Config Error"}], 'threshdesc[]' => [sub{1}, sub{"Internal Threshold Config Error"}], 'threshprogi[]' => [sub{$_[0] && (-e $_[0])}, sub{"Threshold program $_[0] cannot be executed"}], 'threshprogo[]' => [sub{$_[0] && (-e $_[0])}, sub{"Threshold program $_[0] cannot be executed"}], 'threshprogoki[]' => [sub{$_[0] && (-e $_[0])}, sub{"Threshold program $_[0] cannot be executed"}], 'threshprogoko[]' => [sub{$_[0] && (-e $_[0])}, sub{"Threshold program $_[0] cannot be executed"}], 'threshmailaddress[]' => [sub{$_[0] && ($_[0] =~ /\S+\@\S+/)}, sub{"ThreshMailAddress $_[0] does not look like an email address at all"}], 'hwthreshmini[]' => [sub{1}, sub{"Internal Threshold Config Error"}], 'hwthreshmino[]' => [sub{1}, sub{"Internal Threshold Config Error"}], 'hwthreshmaxi[]' => [sub{1}, sub{"Internal Threshold Config Error"}], 'hwthreshmaxo[]' => [sub{1}, sub{"Internal Threshold Config Error"}], 'hwthreshdesc[]' => [sub{1}, sub{"Internal Threshold Config Error"}], 'hwthreshprogi[]' => [sub{$_[0] && (-e $_[0])}, sub{"Threshold program $_[0] cannot be executed"}], 'hwthreshprogo[]' => [sub{$_[0] && (-e $_[0])}, sub{"Threshold program $_[0] cannot be executed"}], 'hwthreshprogoki[]' => [sub{$_[0] && (-e $_[0])}, sub{"Threshold program $_[0] cannot be executed"}], 'hwthreshprogoko[]' => [sub{$_[0] && (-e $_[0])}, sub{"Threshold program $_[0] cannot be executed"}], 'hwthreshmailaddress[]' => [sub{$_[0] && ($_[0] =~ /\S+\@\S+/)}, sub{"ThreshMailAddress $_[0] does not look like an email address at all"}], 'timestrpos[]' => [sub{$_[0] =~ /^(no|[lr][ul])$/i}, sub{"Must be a string of NO, LU, RU, LL, RL"}], 'timestrfmt[]' => [sub{1}, sub{"Internal Error"}] #what ever the user chooses. ); # config file reading sub readcfg ($$$$;$$) { my $cfgfile = shift; my $routers = shift; my $cfg = shift; my $rcfg = shift; my $extprefix = shift || ''; my $extrules = shift; my ($first,$second,$key,$userules); my (%seen); my (%pre,%post,%deflt,%defaulted); unless ($cfgfile) { die "ERROR: readfg: no configfile specified\n"; } unless (ref($routers) eq 'ARRAY' and ref($cfg) eq 'HASH' and ref($rcfg) eq 'HASH') { die "ERROR: readcfg called with wrong arguments\n"; } if ($extprefix and ref($extrules) ne 'HASH') { die "ERROR: readcfg called with wrong args for mrtg extension\n"; } my $hand; my $file; my @filestack; local *CFG; if ($cfgfile eq '-'){$cfgfile = '<&STDIN'}; open (CFG, $cfgfile) || die "ERROR: unable to open config file: $cfgfile\n"; $hand = *CFG; my @handstack; my $nextfile = $cfgfile; my %routerhash; while (1) { if (eof $hand || not defined ($_ = <$hand>) ) { close $hand; if (scalar @handstack){ $hand = pop @handstack; $nextfile = pop @filestack; next; } else { last; } } $file=$nextfile; chomp; my $line = $.; if (/^include:\s*(.*?\S)\s*$/i){ my $newhandle; my @nextfiles; $nextfile = $1; if( $nextfile =~ /\*/ ) { @nextfiles = glob( $nextfile ); @nextfiles = glob( ($cfgfile =~ m#(.+)${MRTG_lib::SL}[^${MRTG_lib::SL}]+$#)[0] . ${MRTG_lib::SL} . $nextfile ) if(!@nextfiles); } else { $nextfile = ($cfgfile =~ m#(.+)${MRTG_lib::SL}[^${MRTG_lib::SL}]+$#)[0] . ${MRTG_lib::SL} . $nextfile if(!-r $nextfile); @nextfiles = ( $nextfile ); } foreach $nextfile ( @nextfiles ) { open my $newhandle, '<', $nextfile or die "ERROR: unable to open include file: $nextfile\n"; push @handstack, $hand; push @filestack, $file; $hand = $newhandle; $file = $nextfile; } next; } debug('cfg',"$file\[$.\]: $_"); s/\t/ /g; #replace tab by space s/\r$//; # kill dos newlines ... s/ +$//g; #remove space at the end of the line next if /^ *\#/; #ignore comment lines next if /^ *$/; #ignore empty lines # oops spelling error s/^supress/suppress/gi; # the line we got starts with white space so it is to be appended to what ever # was on the previous line. if (defined $first && /^\s+(.*\S)\s*$/) { if (defined $second) { $second eq '^' && do { $pre{$first} .= "\n".$1; next}; $second eq '$' && do { $post{$first} .= "\n".$1; next}; $second eq '_' && do { $deflt{$first} .= "\n".$1; next}; $$rcfg{$first}{$second} .= " ".$1; } else { $$cfg{$first} .= "\n".$1; } next; } if (defined $first && defined $second && defined $post{$first} && ($second !~ /^[\$^_]$/)) { if (defined $defaulted{$first}{$second}) { $$rcfg{$first}{$second} = $post{$first}; delete $defaulted{$first}{$second}; } else { $$rcfg{$first}{$second} .= ( defined $$cfg{nospacechar} and $post{$first} =~ /(.*)\Q$$cfg{nospacechar}\E$/) ? $1 : " ".$post{$first} ; } } if (defined $first and $first =~ m/^([^*]+)\*(.+)$/) { $userules = ($1 eq $extprefix ? $extrules : ''); } else { $userules = \%mrtgrules; } if ($first && defined $deflt{$first} && ($second eq '_')) { quickcheck($first,$second,$deflt{$first},$file,$line,$userules) } elsif ($first && $second && ($second !~ /^[\$^_]$/)) { quickcheck($first,$second,$$rcfg{$first}{$second},$file,$line,$userules) } elsif ($first && not $second) { quickcheck($first,0,$$cfg{$first},$file, $line,$userules) } if (/^([A-Za-z0-9*]+)\[(\S+)\]\s*:\s*(.*\S?)\s*$/) { $first = lc($1); $second = lc($2); # For us spelling-handicapped Americans. ;) # James Overbeck, grendel@gmo.jp, 2003/01/19 if ($first eq 'colors') { $first = 'colours' }; if ($second eq '^') { if ($3 ne '') { $pre{$first}=$3; } else { delete $pre{$first}; } next; } if ($second eq '$') { if ($3 ne '') { $post{$first}=$3; } else { delete $post{$first}; } next; } if ($second eq '_') { if ($3 ne '') { $deflt{$first}=$3; } else { delete $deflt{$first}; } next; } if (not defined $routerhash{$second}) { push (@{$routers}, $second); $routerhash{$second} = 1; } # make sure that default tags spring into existence upon first # call of a router foreach $key (keys %deflt) { if (! defined $$rcfg{$key}{$second}) { $$rcfg{$key}{$second} = $deflt{$key}; $defaulted{$key}{$second} = 1; } } # make sure that prefix-only tags spring into existence upon first # call of a router foreach $key (keys %pre) { if (! defined $$rcfg{$key}{$second}) { delete $defaulted{$key}{$second} if $defaulted{$key}{$second}; $$rcfg{$key}{$second} = ( defined $$cfg{nospacechar} && $pre{$key} =~ m/(.*)\Q$$cfg{nospacechar}\E$/ ) ? $1 : $pre{$key}." "; } } if ($seen{$first}{$second}) { die ("ERROR: Line $line ($_) in CFG file ($file)\n". "contains a duplicate definition for $first\[$second].\n". "First definition is on line $seen{$first}{$second}\n") } else { $seen{$first}{$second} = $line; } if ($defaulted{$first}{$second}) { $$rcfg{$first}{$second} = ''; delete $defaulted{$first}{$second}; } $$rcfg{$first}{$second} .= $3; next; } if (/^(\S+):\s*(.*\S)\s*$/) { $first = lc($1); $$cfg{$first} = $2; $second = ''; next; } die "ERROR: Line $line ($_) in CFG file ($file) does not make sense\n"; } # append $ stuff to the very last tag in cfg file if necessary if (defined $first && defined $second && defined $post{$first} && ($second !~ /^[\$^_]$/)) { if ($defaulted{$first}{$second}) { $$rcfg{$first}{$second} = $post{$first}; delete $defaulted{$first}{$second}; } else { $$rcfg{$first}{$second} .= ( defined $$cfg{'nospacechar'} && $post{$first} =~ /(.*)\Q$$cfg{nospacechar}\E$/ ) ? $1 : " ".$post{$first} ; } } #check the last input line if ($first =~ m/^([^*]+)\*(.+)$/) { $userules = ($1 eq $extprefix ? $extrules : ''); } else { $userules = \%mrtgrules; } if ($first && defined $deflt{$first} && ($second eq '_')) { quickcheck($first,$second,$deflt{$first},$file,$.,$userules) } elsif ($first && $second && ($second !~ /^[\$^_]$/)) { quickcheck($first,$second,$$rcfg{$first}{$second},$file,$.,$userules) } elsif ($first && not $second) { quickcheck($first,0,$$cfg{$first},$file,$.,$userules) } close (CFG); # Check for an environment setting for RRDCACHED_ADDRESS # Steve Shipway, Sep 2010 if( $ENV{RRDCACHED_ADDRESS} and not exists $cfg->{ rrdcached } ) { warn("WARNING: Using environment variable RRDCACHED_ADDRESS\n"); $cfg->{ rrdcached } = $ENV{RRDCACHED_ADDRESS}; quickcheck('rrdcached',0,$ENV{RRDCACHED_ADDRESS},'Environment variable RRDCACHED_ADDRESS','n/a',\%mrtgrules); } if( exists $cfg->{ rrdcached } ) { warn ("WARNING: You are running with RRDCached enabled (".$cfg->{ rrdcached }."). This will disable all Threshold checking, since RRDCached does not support updatev and an update/fetch will cancel out the caching benefits.\n"); if( $cfg->{ rrdcached } !~ /^unix:/ ) { warn("WARNING: You are running RRDCached in TCP mode. This means that it will use its own Base Directory instead of WorkDir for storing the RRD files. Also, changes to MaxBytes and DS Type will not be actioned after the RRD file has been created.\n"); } } if ($cfg->{enablesnmpv3} and $cfg->{enablesnmpv3} eq 'yes' and eval {local $SIG{__DIE__}; require Net_SNMP_util} ) { import Net_SNMP_util; } else { require SNMP_util; import SNMP_util; } } # quick checks sub quickcheck ($$$$$$) { my ($first,$second,$arg,$file,$line,$rules) = @_; return unless ref($rules) eq 'HASH'; my $braces = $second ? '[]':''; if (exists $rules->{$first.$braces}) { if (&{$rules->{$first.$braces}[0]}($arg)) { return 1; } else { if ($second) { die "ERROR: CFG Error in \"$first\[$second\]\", file $file line $line: ". &{$rules->{$first.$braces}[1]}($arg)."\n\n"; } else { die "ERROR: CFG Error in \"$first\", file $file line $line: ". &{$rules->{$first.$braces}[1]}($arg)."\n\n"; } } } die "ERROR: CFG Error Unknown Option \"$first\" in file $file on line $line or above.\n". " Check /usr/share/doc/mrtg/mrtg-reference.txt.gz for Help\n\n"; } # complex config checks sub mkdirhier ($){ my @dirs = split /\Q${MRTG_lib::SL}\E+/, shift; my $path = ""; while (@dirs){ $path .= shift @dirs; $path .= ${MRTG_lib::SL}; if (! -d $path){ warn ("WARNING: $path did not exist I will create it now\n"); mkdir $path, 0777 or die ("ERROR: mkdir $path: $!\n"); } } } sub cfgcheck ($$$$;$) { my $routers = shift; my $cfg = shift; my $rcfg = shift; my $target = shift; my $opts = shift || {}; my ($rou, $confname, $one_option); # Target index hash. Keys are "int:community@router" target definition # strings and values are indices of the @$target array. Used to avoid # duplicate entries in @$target. my $targIndex = { }; my $error="no"; my(@known_options) = qw(growright bits noinfo absolute gauge nopercent avgpeak derive integer perhour perminute transparent dorelpercent unknaszero withzeroes noborder noarrow noi noo nobanner nolegend logscale secondmean pngdate printrouter expscale); snmpmapOID('hrSystemUptime' => '1.3.6.1.2.1.25.1.1'); if (defined $$cfg{workdir}) { die ("ERROR: WorkDir must not contain spaces when running on Windows. (Yeat another reason to get Linux)\n") if ($OS eq 'NT' or $OS eq 'OS2') and $$cfg{workdir} =~ /\s/; ensureSL(\$$cfg{workdir}); $$cfg{logdir}=$$cfg{htmldir}=$$cfg{imagedir}=$$cfg{workdir}; mkdirhier "$$cfg{workdir}" unless $opts->{check}; } elsif ( not (defined $$cfg{logdir} or defined $$cfg{htmldir} or defined $$cfg{imagedir})) { die ("ERROR: \"WorkDir\" not specified in mrtg config file\n"); $error = "yes"; } else { if (! defined $$cfg{logdir}) { warn ("WARNING: \"LogDir\" not specified\n"); $error = "yes"; } else { ensureSL(\$$cfg{logdir}); mkdirhier $$cfg{logdir} unless $opts->{check}; } if (! defined $$cfg{htmldir}) { warn ("WARNING: \"HtmlDir\" not specified\n"); $error = "yes"; } else { ensureSL(\$$cfg{htmldir}); mkdirhier $$cfg{htmldir} unless $opts->{check}; } if (! defined $$cfg{imagedir}) { warn ("WARNING: \"ImageDir\" not specified\n"); $error = "yes"; } else { ensureSL(\$$cfg{imagedir}); mkdirhier $$cfg{imagedir} unless $opts->{check}; } } if ($cfg->{threshmailserver} and not $cfg->{threshmailsender}){ warn ("WARNING: If \"ThreshMailServer\" is defined, then \"ThreshMailSender\" must be defined too.\n"); $error = "yes"; } if ($cfg->{threshmailsender} and not $cfg->{threshmailserver}){ warn ("WARNING: If \"ThreshMailSender\" is defined, then \"ThreshMailServer\" must be defined too.\n"); $error = "yes"; } # default ThreshHyst to 0.1 if ThreshDir is defined if ($cfg->{threshdir}){ $cfg->{threshhyst} = 0.1 unless $cfg->{threshhyst}; } # build relativ path from htmldir to image dir. my @htmldir = split /\Q${MRTG_lib::SL}\E+/, $$cfg{htmldir}; my @imagedir = split /\Q${MRTG_lib::SL}\E+/, $$cfg{imagedir}; while (scalar @htmldir > 0 and $htmldir[0] eq $imagedir[0]) { shift @htmldir; shift @imagedir; } # this is for the webpages so we use / path separator always $$cfg{imagehtml} = ""; foreach my $dir ( @htmldir ) { $$cfg{imagehtml} .= "../" if $dir; } map {$$cfg{imagehtml} .= "$_/" } @imagedir; # relative path is built debug('dir', "imagehtml = $$cfg{imagehtml}"); $SNMP_util::CacheFile = "$$cfg{'logdir'}oid-mib-cache.txt"; $Net_SNMP_util::CacheFile = "$$cfg{'logdir'}oid-mib-cache.txt"; if (defined $$cfg{loadmibs}) { my($mibFile); foreach $mibFile (split /[,\s]+/, $$cfg{loadmibs}) { snmpQueue_MIB_File($mibFile); } } if(defined $$cfg{pathadd}){ ensureSL(\$$cfg{pathadd}); $ENV{PATH} = "$$cfg{pathadd}${MRTG_lib::PS}$ENV{PATH}"; } if(defined $$cfg{libadd}){ ensureSL(\$$cfg{libadd}); debug('eval',"libadd $$cfg{libadd}\n"); local $SIG{__DIE__}; eval "use lib qw( $$cfg{libadd} )"; my @match; foreach my $dir (@INC){ push @match, $dir if -f "$dir/RRDs.pm"; } warn "WARN: found several copies of RRDs.pm in your path: ". (join ", ", @match)." I will be using $match[0]. This could ". "be a problem if this is an old copy and you think I would be using a newer one!\n" if $#match > 0; } $$cfg{logformat} = 'rateup' unless defined $$cfg{logformat}; if($$cfg{logformat} eq 'rrdtool') { my ($name); if ($MRTG_lib::OS eq 'NT' or $MRTG_lib::OS eq 'OS2'){ $name = "rrdtool.exe"; } elsif ($MRTG_lib::OS eq 'NW'){ $name = "rrdtool.nlm"; } else { $name = "rrdtool"; } foreach my $path (split /\Q${MRTG_lib::PS}\E/, $ENV{PATH}) { ensureSL(\$path); -f "$path$name" && do { $$cfg{'rrdtool'} = "$path$name"; last;} }; die "ERROR: could not find $name. Use PathAdd: in mrtg.cfg to help mrtg find rrdtool\n" unless defined $$cfg{rrdtool}; debug ('rrd',"found rrdtool in $$cfg{rrdtool}"); my $found; foreach my $path (@INC) { ensureSL(\$path); -f "${path}RRDs.pm" && do { $found=1; last;} }; die "ERROR: could not find RRDs.pm. Use LibAdd: in mrtg.cfg to help mrtg find RRDs.pm\n" unless defined $found; } if (defined $$cfg{snmpoptions}) { debug('eval',"redef snmpotions $cfg->{snmpoptions}"); local $SIG{__DIE__}; $cfg->{snmpoptions} = eval('{'.$cfg->{snmpoptions}.'}'); } # default interval is 5 minutes if ($cfg->{interval} and $cfg->{interval} =~ /(\d+)(?::(\d+))?/){ $cfg->{interval} = $1; $cfg->{interval} += $2/60.0 if $2; } else { $cfg->{interval} = 5; } unless ($$cfg{logformat} eq 'rrdtool') { # interval has to be 5 minutes at least without userrdtool if ($$cfg{interval} < 5.0) { die "ERROR: CFG Error in \"Interval\": should be at least 5 Minutes (unless you use rrdtool)"; } } # Check for a Conversion Code file and evaluate its contents, which # should consist of one or more subroutine definitions. The code goes # into the MRTGConversion name space. if( exists $cfg->{ conversioncode } ) { open CONV, $cfg->{ conversioncode } or die "ERROR: Can't open file $cfg->{ conversioncode }\n"; my $code = "local \$SIG{__DIE__};package MRTGConversion;\n". join( '', ) . "1;\n"; close CONV; debug('eval',"covnversioncode $cfg->{ conversioncode }"); die "ERROR: File $cfg->{ conversioncode } conversion code evaluation failed\n$@\n" unless eval $code; } my $thresh_error; # sendtographite directive parsing # sanity check for , or , if ($cfg->{sendtographite}){ my @a = split ",",$cfg->{sendtographite}; # is this an IP address? unless($a[0] =~ /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/) { # maybe we were passed a DNS name? unless(gethostbyname($a[0])) { die "ERROR: cannot find graphite server name $a[0] in DNS\n"; } } # if we got this far, now check the port number range unless($a[1] > 0 and $a[1] < 65536) { die "ERROR: invalid port number $a[1] in sendtographite directive\n"; } } foreach $rou (@$routers) { # and now for the testing if (defined $rcfg->{threshmailaddress}{$rou}){ if (not defined $cfg->{threshmailserver} and not $thresh_error){ warn (qq{ERROR: ThreshMailAddress[$rou]: specified without "ThreshMailServer:"}); $error = "yes"; $thresh_error = "yes"; } # the dependency between sender and server is taken care of already } if (! defined $rcfg->{snmpoptions}{$rou}) { $rcfg->{snmpoptions}{$rou} = {%{$cfg->{snmpoptions}}} if defined $cfg->{snmpoptions}; } else { debug('eval',"redef snmpoptions[$rou] $rcfg->{snmpoptions}{$rou}"); local $SIG{__DIE__}; $rcfg->{snmpoptions}{$rou} = eval('{'.$rcfg->{snmpoptions}{$rou}.'}'); } $rcfg->{snmpoptions}{$rou}{avoid_negative_request_ids} = 1; # $rcfg->{snmpoptions}{$rou}{domain} = 'udp'; if (! defined $$rcfg{"title"}{$rou}) { warn ("WARNING: \"Title[$rou]\" not specified\n"); $error = "yes"; } if (defined $$rcfg{'directory'}{$rou} and $$rcfg{'directory'}{$rou} ne "") { # They specified a directory for this router. Append the # pathname separator to it (so that it can either be present or # absent, and the rules for including it are the same). ensureSL(\$$rcfg{'directory'}{$rou}); for my $x (qw(imagedir logdir htmldir)) { mkdirhier $$cfg{$x}.$$rcfg{directory}{$rou} unless $opts->{check}; } $$rcfg{'directory_web'}{$rou} = $$rcfg{'directory'}{$rou}; $$rcfg{'directory_web'}{$rou} =~ s/\Q${MRTG_lib::SL}\E+/\//g; debug('dir', "directory for $rou '$$rcfg{'directory_web'}{$rou}'"); } else { $$rcfg{'directory'}{$rou}=""; $$rcfg{'directory_web'}{$rou}=""; } if (defined $$rcfg{"pagetop"}{$rou}) { $$rcfg{"pagetop"}{$rou} =~ s/\\n/\n/g; } if (defined $$rcfg{"pagefoot"}{$rou}) { # allow for linebreaks $$rcfg{"pagefoot"}{$rou} =~ s/\\n/\n/g; } $$rcfg{"maxbytes1"}{$rou} = $$rcfg{"maxbytes"}{$rou} unless defined $$rcfg{"maxbytes1"}{$rou}; $$rcfg{"maxbytes2"}{$rou} = $$rcfg{"maxbytes"}{$rou} unless defined $$rcfg{"maxbytes2"}{$rou}; if ( not defined $$rcfg{"maxbytes"}{$rou} and not defined $$rcfg{"maxbytes1"}{$rou} and not defined $$rcfg{"maxbytes2"}{$rou}) { warn ("WARNING: \"MaxBytes[$rou]\" not specified\n"); $error = "yes"; } else { if (not defined $$rcfg{"maxbytes1"}{$rou}) { warn ("WARNING: \"MaxBytes1[$rou]\" not specified\n"); $error = "yes"; } if (not defined $$rcfg{"maxbytes2"}{$rou}) { warn ("WARNING: \"MaxBytes2[$rou]\" not specified\n"); $error = "yes"; } } # set default extension if (! defined $$rcfg{"extension"}{$rou}) { $$rcfg{"extension"}{$rou}="html"; } # set default size if (! defined $$rcfg{"xsize"}{$rou}) { $$rcfg{"xsize"}{$rou}=400; } if (! defined $$rcfg{"ysize"}{$rou}) { $$rcfg{"ysize"}{$rou}=100; } if (! defined $$rcfg{"ytics"}{$rou}) { $$rcfg{"ytics"}{$rou}=4; } if (! defined $$rcfg{"yticsfactor"}{$rou}) { $$rcfg{"yticsfactor"}{$rou}=1; } if (! defined $$rcfg{"factor"}{$rou}) { $$rcfg{"factor"}{$rou}=1; } if (defined $$rcfg{"options"}{$rou}) { my $opttemp = lc($$rcfg{"options"}{$rou}); delete $$rcfg{"options"}{$rou}; foreach $one_option (split /[,\s]+/, $opttemp) { if (grep {$one_option eq $_} @known_options) { $$rcfg{'options'}{$one_option}{$rou} = 1; } else { warn ("WARNING: Option[$rou]: \"$one_option\" is unknown\n"); $error="yes"; } } if ($rcfg->{'options'}{derive}{$rou} and not $cfg->{logformat} eq 'rrdtool'){ warn ("WARNING: Option[$rou]: \"derive\" works only with rrdtool logformat\n"); $error="yes"; } } # # Check out routeruptime definition # if (defined $$rcfg{"routeruptime"}{$rou}) { ($$rcfg{"community"}{$rou},$$rcfg{"router"}{$rou}) = split(/@/,$$rcfg{"routeruptime"}{$rou}); } # # Check out target definition # if (defined $$rcfg{"target"}{$rou}) { $$rcfg{targorig}{$rou} = $$rcfg{target}{$rou}; debug ('tarp',"Starting $rou -> $$rcfg{target}{$rou}"); # Decide whether to turn on IPv6 support for this target. # IPv6 support is turned on only if the EnableIPv6 global # setting is yes and the IPv4Only per-target setting is no. # If IPv6 is disabled, we set IPv4Only to true for all # targets, thus disabling all IPv6-related code. my $ipv4only = 1; if ($$cfg{enableipv6} and $$cfg{enableipv6} eq 'yes') { # IPv4Only is off by default $ipv4only = 0 unless (defined $$rcfg{ipv4only}{$rou}) && (lc($$rcfg{ipv4only}{$rou}) eq 'yes'); } # Check if nohc has been set, designating a low-speed interface # without working HC counters. Default is that high-speed # counters exist. my $nohc = 0; $nohc = 1 if (defined $$rcfg{nohc}{$rou}) && (lc($$rcfg{nohc}{$rou}) eq 'yes'); ( $$rcfg{target}{$rou}, $$rcfg{uniqueTarget}{$rou} ) = targparser( $$rcfg{target}{$rou}, $target, $targIndex, $ipv4only, $rcfg->{snmpoptions}{$rou}, $nohc ); } else { warn ("WARNING: I can't find a \"target[$rou]\" definition\n"); $error = "yes"; } # colors format: name#hexcol, if (defined $$rcfg{"colours"}{$rou}) { if ($$rcfg{'options'}{'dorelpercent'}{$rou}) { if ($$rcfg{"colours"}{$rou} =~ /^([^\#]+)(\#[0-9a-f]{6})\s*,\s* ([^\#]+)(\#[0-9a-f]{6})\s*,\s* ([^\#]+)(\#[0-9a-f]{6})\s*,\s* ([^\#]+)(\#[0-9a-f]{6})\s*,\s* ([^\#]+)(\#[0-9a-f]{6})/ix) { ($$rcfg{'col1'}{$rou}, $$rcfg{'rgb1'}{$rou}, $$rcfg{'col2'}{$rou}, $$rcfg{'rgb2'}{$rou}, $$rcfg{'col3'}{$rou}, $$rcfg{'rgb3'}{$rou}, $$rcfg{'col4'}{$rou}, $$rcfg{'rgb4'}{$rou}, $$rcfg{'col5'}{$rou}, $$rcfg{'rgb5'}{$rou}) = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10); } else { warn ("WARNING: \"colours[$rou]\" for colour definition\n". " use the format: Name#hexcolour, Name#Hexcolour,...\n", " note, that dorelpercent requires 5 colours"); $error="yes"; } } else { if ($$rcfg{"colours"}{$rou} =~ /^([^\#]+)(\#[0-9a-f]{6})\s*,\s* ([^\#]+)(\#[0-9a-f]{6})\s*,\s* ([^\#]+)(\#[0-9a-f]{6})\s*,\s* ([^\#]+)(\#[0-9a-f]{6})/ix) { ($$rcfg{'col1'}{$rou}, $$rcfg{'rgb1'}{$rou}, $$rcfg{'col2'}{$rou}, $$rcfg{'rgb2'}{$rou}, $$rcfg{'col3'}{$rou}, $$rcfg{'rgb3'}{$rou}, $$rcfg{'col4'}{$rou}, $$rcfg{'rgb4'}{$rou}) = ($1, $2, $3, $4, $5, $6, $7, $8); } else { warn "WARNING: \"colours[$rou]\" for colour definition\n". " use the format: Name#hexcolour, Name#Hexcolour,...\n"; $error="yes"; } } } else { if (defined $$rcfg{'options'}{'dorelpercent'}{$rou}) { ($$rcfg{'col1'}{$rou}, $$rcfg{'rgb1'}{$rou}, $$rcfg{'col2'}{$rou}, $$rcfg{'rgb2'}{$rou}, $$rcfg{'col3'}{$rou}, $$rcfg{'rgb3'}{$rou}, $$rcfg{'col4'}{$rou}, $$rcfg{'rgb4'}{$rou}, $$rcfg{'col5'}{$rou}, $$rcfg{'rgb5'}{$rou}) = ("GREEN","#00cc00", "BLUE","#0000ff", "DARK GREEN","#006600", "MAGENTA","#ff00ff", "AMBER","#ef9f4f"); } else { ($$rcfg{'col1'}{$rou}, $$rcfg{'rgb1'}{$rou}, $$rcfg{'col2'}{$rou}, $$rcfg{'rgb2'}{$rou}, $$rcfg{'col3'}{$rou}, $$rcfg{'rgb3'}{$rou}, $$rcfg{'col4'}{$rou}, $$rcfg{'rgb4'}{$rou}) = ("GREEN","#00cc00", "BLUE","#0000ff", "DARK GREEN","#006600", "MAGENTA","#ff00ff"); } } # Background color, format: #rrggbb if (! defined $$rcfg{'background'}{$rou}) { $$rcfg{'background'}{$rou} = "#ffffff"; } if ($$rcfg{'background'}{$rou} =~ /^(\#[0-9a-f]{6})/i) { $$rcfg{'backgc'}{$rou} = "$1"; } else { warn "WARNING: \"background[$rou]: ". "$$rcfg{'background'}{$rou}\" for colour definition\n". " use the format: #rrggbb\n"; $error="yes"; } # Text color, format: #rrggbb if (! defined $$rcfg{'textcolor'}{$rou}) { # make some textcolor if not defined # convert backg hex to decimal rgb my @rgbvalue=split('',$$rcfg{'backgc'}{$rou}); my @rgb=(hex($rgbvalue[1].$rgbvalue[2]),hex($rgbvalue[3].$rgbvalue[4]),hex($rgbvalue[5].$rgbvalue[6])); # make contrast textcolor from backg for all backg values if($rgb[0]+$rgb[1]+$rgb[2]<(256*3/2)) { $$rcfg{textcolor}{$rou}="#ffffff"; } else { $$rcfg{textcolor}{$rou}="#000000"; } } if ($$rcfg{'textcolor'}{$rou} =~ /^(\#[0-9a-f]{6})/i) { $$rcfg{'textc'}{$rou} = "$1"; } else { warn "WARNING: \"textcolor[$rou]: ". "$$rcfg{'textcolor'}{$rou}\" for colour definition\n". " use the format: #rrggbb\n"; $error="yes"; } if (! defined $$rcfg{'kilo'}{$rou}) { $$rcfg{'kilo'}{$rou} = 1000; } if (defined $$rcfg{'kmg'}{$rou}) { $$rcfg{'kmg'}{$rou} =~ s/\s+//g; } if (! defined $$rcfg{'xzoom'}{$rou}) { $$rcfg{'xzoom'}{$rou} = 1.0; } if (! defined $$rcfg{'yzoom'}{$rou}) { $$rcfg{'yzoom'}{$rou} = 1.0; } if (! defined $$rcfg{'xscale'}{$rou}) { $$rcfg{'xscale'}{$rou} = 1.0; } if (! defined $$rcfg{'yscale'}{$rou}) { $$rcfg{'yscale'}{$rou} = 1.0; } if (defined $$rcfg{'options'}{'pngdate'}{$rou}) { $$rcfg{'timestrpos'}{$rou} = 'RU'; $$rcfg{'timestrfmt'}{$rou} = $$rcfg{'timezone'}{$rou} ? "%Y-%m-%d %H:%M %Z" : "%Y-%m-%d %H:%M"; delete $$rcfg{'options'}{'pntdate'}{$rou} } if (! defined $$rcfg{'timestrpos'}{$rou}) { $$rcfg{'timestrpos'}{$rou} = 'NO'; } if (! defined $$rcfg{'timestrfmt'}{$rou}) { $$rcfg{'timestrfmt'}{$rou} = "%Y-%m-%d %H:%M"; } if ($error eq "yes") { die "ERROR: Please fix the error(s) in your config file\n"; } } } # make sure string ends with a slash. sub ensureSL($) { # return; my $ref = shift; return if not $$ref; debug('dir',"ensure path IN: '$$ref'"); if (${MRTG_lib::SL} eq '\\'){ # two slashes at the start of the string are OK $$ref =~ s/(.)\Q${MRTG_lib::SL}\E+/$1${MRTG_lib::SL}/g; } else { $$ref =~ s/\Q${MRTG_lib::SL}\E+/${MRTG_lib::SL}/g; } $$ref =~ s/\Q${MRTG_lib::SL}\E*$/${MRTG_lib::SL}/; debug('dir',"ensure path OUT: '$$ref'"); } # convert current supplied time into a nice date string sub datestr ($) { my ($time) = shift || return 0; my ($wday) = ('Sunday','Monday','Tuesday','Wednesday', 'Thursday','Friday','Saturday')[(localtime($time))[6]]; my ($month) = ('January','February' ,'March' ,'April' , 'May' , 'June' , 'July' , 'August' , 'September' , 'October' , 'November' , 'December' )[(localtime($time))[4]]; my ($mday,$year,$hour,$min) = (localtime($time))[3,5,2,1]; if ($min<10) { $min = "0$min"; } return "$wday, $mday $month ".($year+1900)." at $hour:$min"; } # create expire date for expiery in ARG Minutes sub expistr ($) { my ($time) = time+int($_[0]*60)+5; my ($wday) = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat')[(gmtime($time))[6]]; my ($month) = ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep', 'Oct','Nov','Dec')[(gmtime($time))[4]]; my ($mday,$year,$hour,$min,$sec) = (gmtime($time))[3,5,2,1,0]; if ($mday<10) { $mday = "0$mday"; } ; if ($hour<10) { $hour = "0$hour"; } ; if ($min<10) { $min = "0$min"; } if ($sec<10) { $sec = "0$sec"; } return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; } sub create_pid ($) { my $pidfile = shift; return if ($OS eq 'NT' ); return if -e $pidfile; if ( open(PIDFILE,">$pidfile")) { close PIDFILE; } else { warn "cannot write to $pidfile: $!\n"; } } sub demonize_me ($) { my $pidfile = shift; my $cfgfile = shift; print "Daemonizing MRTG ...\n"; if ( $OS eq 'NT' ) { print "Do Not close this window. Or MRTG will die\n"; # require Win32::Console; # my $CONSOLE = new Win32::Console; # detach process from Console # $CONSOLE->Flush(); # $CONSOLE->Free(); # $CONSOLE->Alloc(); # $CONSOLE->Mode() } elsif( $OS eq 'OS2') { require OS2::Process; if (my_type() eq 'VIO'){ $main::Cleanfile3 = $pidfile; print "MRTG detached. PID=".system(P_DETACH(),$^X." ".$0." ".$cfgfile); exit; } } else { # Check out if there is another mrtg running before forking if (defined $pidfile && open(READPID, "<$pidfile")){ if (not eof READPID) { chomp(my $input = ); # read process id in pidfile my ($pid) = $input =~ /^(\d+)$/; # to improve taint-safe code if ($pid && kill 0 => $pid) {# oops - the pid actually exists die "ERROR: I Quit! Another copy of mrtg seems to be running. Check $pidfile\n"; } } close READPID; } defined (my $pid = fork) or die "Can't fork: $!"; if ($pid) { exit; } else { if (defined $pidfile){ $main::Cleanfile3 = $pidfile; if (open(PIDFILE,">$pidfile")) { print PIDFILE "$$\n"; close PIDFILE; } else { warn "cannot write to $pidfile: $!\n"; } } require 'POSIX.pm'; POSIX::setsid() or die "Can't start a new session: $!"; open STDOUT,'>/dev/null' or die "ERROR: Redirecting STDOUT to /dev/null: $!"; open STDERR,'>/dev/null' or die "ERROR: Redirecting STDERR to /dev/null: $!"; open STDIN, '{ Methode } = 'SNMP'; $targ->{ Community } = $if->{ComStr}; $targ->{ Host } = ( defined $if->{HostIPv6} ) ? $if->{HostIPv6} : $if->{HostName}; $targ->{ SnmpOpt } = $if->{SnmpInfo}; $targ->{ snmpoptions} = $if->{snmpoptions}; $targ->{ Conversion } = ( defined $if->{ConvSub} ) ? $if->{ConvSub} : ''; for my $i( 0..1 ) { die 'ERROR: Malformed ', $i ? 'output ' : 'input ', "ifSpec in '$t'\n" if not defined $if->{OID}[$i] and not defined $if->{Alt}[$i]; $targ->{OID}[$i] = $if->{OID}[$i]; if( defined $if->{Alt}[$i] ) { if( defined $if->{Num}[$i] ) { $targ->{IfSel}[$i] = 'If'; $targ->{Key}[$i] = $if->{Num}[$i]; } elsif( defined $if->{IP}[$i] ) { $targ->{IfSel}[$i] = 'Ip'; $targ->{Key}[$i] = $if->{IP}[$i]; } elsif( defined $if->{Desc}[$i] ) { $targ->{IfSel}[$i] = 'Descr'; $targ->{Key}[$i] = $if->{Desc}[$i]; } elsif( defined $if->{Name}[$i] ) { $targ->{IfSel}[$i] = 'Name'; $targ->{Key}[$i] = $if->{Name}[$i]; } elsif( defined $if->{Eth}[$i] ) { $targ->{IfSel}[$i] = 'Eth'; $targ->{Key}[$i] = join( '-', map( { sprintf '%02x', hex $_ } split( /-/, $if->{Eth}[$i] ) ) ); } elsif( defined $if->{Type}[$i] ) { $targ->{IfSel}[$i] = 'Type'; $targ->{Key}[$i] = $if->{Type}[$i]; } else { die "ERROR: Internal error parsing ifSpec in '$t'\n"; } } else { $targ->{IfSel}[$i] = 'None'; $targ->{Key}[$i] = ''; } # Remove escaped characters and trailing space from Descr or Name Key $targ->{Key}[$i] =~ s/\\([\s:&@])/$1/g if $targ->{IfSel}[$i] eq 'Descr' or $targ->{IfSel}[$i] eq 'Name'; $targ->{Key}[$i] =~ s/[\0- ]+$//; } # Remove escaped characters from community $targ->{ Community } =~ s/\\([ @])/$1/g; return $targ; # Return new target closure } # ( $string, $unique ) = targparser( $string, $target, $targIndex, $ipv4only ) # Walk amd analyze the target string $string. $target is a reference to the # array of targets being built. $targIndex is a reference to a hash of targets # previously encountered indexed by target string. When $ipv4only is nonzero, # only IPv4 is in use. Returns the modified target string and the index of the # @$target array to which the target refers if that index is unique. If the # index is not unique, i.e. the target definition is a calculation involving # two or more different targets, then the value -1 is returned for $unique. # Targparser updates the target array avoiding duplicate targets. The goal is # to substitute all target definitions with strings of the form # "$t1$thisTarg$t2", where $thisTarg is the target index, and $t1 and $t2 are # as defined below. The intended result is a target string that can be eval'ed # in its entirety later on when monitoring data has been collected. This # evaluation occurs in sub getcurrent in the main mrtg script. # Note: In the regular expressions in &targparser, we have avoided m/.../i # and the variables &`, $&, and $'. Use of these makes regex processing less # efficient. See Friedl, J.E.F. Mastering Regular Expressions. O'Reilly. # p. 273 sub targparser( $$$$$$ ) { # Target string (int:community@router, etc.) my $string = shift; # Reference to target array my $target = shift; # Reference to target index hash my $targIndex = shift; # Nonzero if only IPv4 is in use my $ipv4only = shift; # options passed per target. my $snmpoptions = shift; # Highspeed Counter test my $nohc = shift; # Next available index in the @$target array my $idx = @$target; # Common match strings: pre-target, target, post-target my( $pre, $t, $post ); # Portion of string already parsed my $parsed = ''; # Initialize $unique to undefined. It will take on the $targIndex value # of the first target encountered. $otherTargCount will count the # number of other targets (targets with different values of $targIndex) # encountered during the parse. $unique will be returned as undef # unless $otherTargCount remains 0. my $unique = -1; my $otherTargCount = 0; # Components of the target expression that are substituted into the # target string each time a target is identified. The substitution # string is the interpolated value of "$t1$targIndex$t2". At present # $t1 and $t2 are set to create a new BigFloat object. # my $t1 = ' Math::BigFloat->new($target->['; # my $t2 = ']{$mode}) '; # this gives problems with perl 5.005 so bigfloat is introduces in mrtg itself my $t1 = ' $target->['; my $t2 = ']{$mode} '; # Find and substitute all external program targets while( ( $pre, $t, $post ) = $string =~ m< ^(.*?) # capture pre-target string ` # beginning of program target ((?:\\`|[^`])+) # capture target contents (\` allowed) ` # end of program target (.*)$ # capture post-target string >x ) { # Total of 3 captures my $thisTarg; if( exists $targIndex->{ $t } ) { # This program target has been encountered previously $thisTarg = $targIndex->{ $t }; debug( 'tarp', "Existing program target [$thisTarg]" ); } else { # A new program target is needed my $targ = { }; $targ->{ Methode } = 'EXEC'; $targ->{ Command } = $t; # Remove escaped backticks $targ->{ Command } =~ s/\\\`/\`/g; $target->[ $idx ] = $targ; $thisTarg = $idx++; $targIndex->{ $t } = $thisTarg; debug( 'tarp', "New program target [$thisTarg] '$t'" ); } $parsed .= "$pre$t1$thisTarg$t2"; $string = $post; if( $unique < 0 ) { $unique = $thisTarg; } else { $otherTargCount++ unless $thisTarg == $unique; } }; # Reset $string for new target type search $string = $parsed . $string; $parsed = ''; debug( 'tarp', "&targparser external done: '$string'" ); # Common interface specification regex components # Simple interface specification regex component. Matches interface # specification by IPv4 address, description, name, Ethernet address, or # type. my $ifSimple = ' (\d+)|' . # by number ($if->{Num}) ' / (\d+(?:\.\d+)+)|' . # by IPv4 address ($if->{IP}) ' \\\\ ((?:\\\\[\s:&@]|[^\s:&@])+)|' . # by description (allow \ \: \& \@) ($if->{Desc}) ' \# ((?:\\\\[\s:&@]|[^\s:&@])+)|' . # by name (allow \ \: \& \@) ($if->{Name}) ' ! ([a-fA-F0-9]+(?:-[a-fA-F0-9]+)+)|' . # by Ethernet address ($if->{Eth}) ' % (\d+)'; # by type ($if->{Type}) # Complex interface specification regex component. Note that a null string # will match. Therefore the match must be postprocessed to check that # $ifOID and $ifAlt are not both null. my $ifComplex = '((?:\.\d+)*?\.?[-a-zA-Z0-9]*(?:\.\d+)*?)' . # OID possibly starting with a MIB name ($if->{OID}) '(' . # Interface specification alternatives: ($if->{Alt}) '\.' . # separator $ifSimple . # simple alternatives (6 variables) ')?'; # maybe none of the above # Community-host interface specification regex component. my $ifComHost = '((?:\\\\[@ ]|[^\s@])+)' . # community string ('\@' and '\ ' allowed) ($if->{ComStr}) '@' . # separator '(?:(\[[a-fA-F0-9:]*\])|' . # hostname as IPv6 address ($if->{HostIPv6}) '([-\w]+(?:\.[-\w]+)*))' . # or DNS name ($if->{HostName}) '((?::[\d.!]*)*)' . # SNMP session configuration ($if->{SnmpInfo}) '(?:\|([a-zA-Z_][\w]*))?'; # numeric conversion subroutine ($if->{ConvSub}) # Match strings for simple and complex interface specifications. Entries # are of the form $if->{k1}[i], where k1 is OID, Alt, Num, IP, Desc, # Name, Eth, or Type, and i is 0 or 1 (input or output). Entries may also # have the form $if->{k1}, where k1 is Rev, ComStr, HostIPv6, HostName, # SnmpInfo, or ConvSub, with no [i] in these cases. my $if; # Find and substitute all complex OID targets while( ( $pre, $t, $if->{OID}[0], $if->{Alt}[0], $if->{Num}[0], $if->{IP}[0], $if->{Desc}[0], $if->{Name}[0], $if->{Eth}[0], $if->{Type}[0], $if->{OID}[1], $if->{Alt}[1], $if->{Num}[1], $if->{IP}[1], $if->{Desc}[1], $if->{Name}[1], $if->{Eth}[1], $if->{Type}[1], $if->{ComStr}, $if->{HostIPv6}, $if->{HostName}, $if->{SnmpInfo}, $if->{ConvSub}, $post ) = $string =~ m< ^(.*?) # capture pre-target string ( # capture entire target ${ifComplex} # input interface specification (8 captures) & # separator ${ifComplex} # output interface specification (8 captures) : # separator ${ifComHost} # community-host specification (5 captures) ) # end of entire target capture (.*)$ # capture post-target string >x ) { # Total of 24 captures my $thisTarg; # Exception: skip and try to parse later as a simple target if # $if->{Desc}[0], $if->{Name}[0], $if->{Desc}[1], or $if->{Name}[1] # ends with a backslash character if( ( defined $if->{Desc}[0] and $if->{Desc}[0] =~ m<\\$> ) or ( defined $if->{Name}[0] and $if->{Name}[0] =~ m<\\$> ) or ( defined $if->{Desc}[1] and $if->{Desc}[1] =~ m<\\$> ) or ( defined $if->{Name}[1] and $if->{Name}[1] =~ m<\\$> ) ) { $parsed .= "$pre$t"; $string = $post; next; } if( exists $targIndex->{ $t } ) { # This complex target has been encountered previously $thisTarg = $targIndex->{ $t }; debug( 'tarp', "Existing complex target [$thisTarg]" ); } else { # A new complex target is needed my $targ = newSnmpTarg( $t, $if ); $targ->{ ipv4only } = $ipv4only; $targ->{ snmpoptions } = $snmpoptions; $target->[ $idx ] = $targ; $thisTarg = $idx++; $targIndex->{ $t } = $thisTarg; debug( 'tarp', "New complex target [$thisTarg] '$t':\n" . " Comu: $targ->{Community}, Host: $targ->{Host}\n" . " Opt: $targ->{SnmpOpt}, IPv4: $targ->{ipv4only}\n" . " Conv: $targ->{Conversion}\n" . " OID: $targ->{OID}[0], $targ->{OID}[1]\n" . " IfSel: $targ->{IfSel}[0], $targ->{IfSel}[1]\n" . " Key: $targ->{Key}[0], $targ->{Key}[1]" ); } $parsed .= "$pre$t1$thisTarg$t2"; $string = $post; if( $unique < 0 ) { $unique = $thisTarg; } else { $otherTargCount++ unless $thisTarg == $unique; } } # Reset $string and $parsedfor new target type search $string = $parsed . $string; $parsed = ''; debug( 'tarp', "&targparser complex done: '$string'" ); # Find and substitute all simple targets while( ( $pre, $t, $if->{Rev}, $if->{Num}[0], $if->{IP}[0], $if->{Desc}[0], $if->{Name}[0], $if->{Eth}[0], $if->{Type}[0], $if->{ComStr}, $if->{HostIPv6}, $if->{HostName}, $if->{SnmpInfo}, $if->{ConvSub}, $post ) = $string =~ m< ^(.*?) # capture pre-target string ( # capture entire target (-)? # capture direction reversal (?: ${ifSimple} ) # simple interface specification (6 captures) : # separator ${ifComHost} # community-host specification (5 captures) ) # end of entire target capture (.*)$ # capture post-target string >x ) { # Total of 15 captures my $thisTarg; if( exists $targIndex->{ $t } ) { # This simple target has been encountered previously $thisTarg = $targIndex->{ $t }; debug( 'tarp', "Existing simple target [$thisTarg]" ); } else { # A new simple target is needed # Reverse interface directions if indicated by $if->{Rev}. # The sense of $d1 and $d2 is 0 for input and 1 for output my $d1 = ( defined $if->{Rev} and $if->{Rev} eq '-' ) ? 1 : 0; my $d2 = 1 - $d1; # Set the OIDs depending on whether SNMPv2 has been specified # and on the direction if( $if->{SnmpInfo} =~ m/(?::[^:]*){4}:[32][Cc]?/ and $nohc == 0 ) { $if->{OID}[$d1] = 'ifHCInOctets'; $if->{OID}[$d2] = 'ifHCOutOctets'; } else { $if->{OID}[$d1] = 'ifInOctets'; $if->{OID}[$d2] = 'ifOutOctets'; } # Give $if->{Alt}[i] an arbitrary defined value so that # &newSnmpTarg works correctly $if->{Alt}[0] = 1; $if->{Alt}[1] = 1; # Copy input specification to output $if->{Num}[1] = $if->{Num}[0]; $if->{IP}[1] = $if->{IP}[0]; $if->{Desc}[1] = $if->{Desc}[0]; $if->{Name}[1] = $if->{Name}[0]; $if->{Eth}[1] = $if->{Eth}[0]; $if->{Type}[1] = $if->{Type}[0]; my $targ = newSnmpTarg( $t, $if ); $targ->{ snmpoptions} = $snmpoptions; $targ->{ ipv4only } = $ipv4only; $target->[ $idx ] = $targ; $thisTarg = $idx++; $targIndex->{ $t } = $thisTarg; debug( 'tarp', "New simple target [$thisTarg] '$t':\n" . " Comu: $targ->{Community}, Host: $targ->{Host}\n" . " Opt: $targ->{SnmpOpt}, IPv4: $targ->{ipv4only}\n" . " Conv: $targ->{Conversion}\n" . " OID: $targ->{OID}[0], $targ->{OID}[1]\n" . " IfSel: $targ->{IfSel}[0], $targ->{IfSel}[1]\n" . " Key: $targ->{Key}[0], $targ->{Key}[1]" ); } $parsed .= "$pre$t1$thisTarg$t2"; $string = $post; if( $unique < 0 ) { $unique = $thisTarg; } else { $otherTargCount++ unless $thisTarg == $unique; } } # Assemble string to be returned $string = $parsed . $string; # Set $unique undefined if more than one target is referred to in the # target string $unique = -1 if $otherTargCount; debug( 'tarp', "&targparser simple done: '$string'" ); debug( 'tarp', "&targparser returning: unique = $unique" ); return ( $string, $unique ); } # Display of &targparser intermediate values for debugging purposes. Call as # showMatch( $string, $pre, $t, $post, $if ) from within &targparser. sub showMatch( $$$$$ ) { my( $string, $pre, $t, $post, $if ) = @_; warn "# Matching on string '$string'\n"; warn "# Prematch: '$pre'\n"; warn "# Target: '$t'\n"; warn "# Postmatch: '$post'\n"; warn "# Captured:\n"; foreach my $k( keys %$if ) { if( ref( $if->{$k} ) eq 'ARRAY' ) { warn "# \$if->{$k}[0,1]: '", ( defined $if->{$k}[0] ) ? $if->{$k}[0] : 'undef', "', '", ( defined $if->{$k}[1] ) ? $if->{$k}[1] : 'undef', "'\n"; } else { warn "# \$if->{$k}: '", ( defined $if->{$k} ) ? $if->{$k} : 'undef', "'\n"; } } } sub readconfcache ($) { my $cfgfile = shift; my %confcache; if (open (CFGOK,"<$cfgfile")) { while () { chomp; next unless /\t/; #ignore odd lines next if /^\S+:/; #ignore legacy lines my ($host,$method,$key,$if) = split (/\t/, $_); $key =~ s/[\0- ]+$//; # no trailing whitespace in keys really ! $key =~ s/[\0- ]/ /g; # all else becomes a normal space ... get a life $confcache{$host}{$method}{$key} = $if; } close CFGOK; } return \%confcache; } sub writeconfcache ($$) { my $confcache = shift; my $cfgfile = shift; if ($cfgfile ne '&STDOUT'){ open (CFGOK,">$cfgfile") or die "ERROR: writing $cfgfile.ok: $!"; } my @hosts; if (defined $$confcache{___updated}) { @hosts = @{$$confcache{___updated}} ; delete $$confcache{___updated}; } else { @hosts = grep !/^___/, keys %{$confcache} } foreach my $host (sort @hosts) { foreach my $method (sort keys %{$$confcache{$host}}) { foreach my $key (sort keys %{$$confcache{$host}{$method}}) { if ($cfgfile ne '&STDOUT'){ print CFGOK "$host\t$method\t$key\t". $$confcache{$host}{$method}{$key},"\n"; } else { print "$host\t$method\t$key\t". $$confcache{$host}{$method}{$key},"\n"; } } } } close CFGOK; } sub cleanhostkey ($){ my $host = shift; return undef unless defined $host; $host =~ s/(:\d*)(?:(:\d*)(?:(:\d*)(?:(:\d*)(?:(:\d*)))))$/$1$5/ or $host =~ s/(:\d*)(?:(:\d*)(?:(:\d*)(?:(:\d*)?)?)?)$/$1/; $host =~ s/:/_/g; # make sure that double invocations do not kill us return $host; } sub storeincache ($$$$$){ my($confcache,$host,$method,$key,$value) = @_; $host = cleanhostkey $host; if (not defined $value ){ $$confcache{$host}{$method}{$key} = undef; return; } $value =~ s/[\0- ]/ /g; # all else becomes a normal space ... get a life $value =~ s/ +$//; # no trailing spaces if (defined $$confcache{$host}{$method}{$key} and $$confcache{$host}{$method}{$key} ne $value) { $$confcache{$host}{$method}{$key} = "Dup"; debug('coca',"store in confcache $host $method $key --> $value (duplicate)"); } else { $$confcache{$host}{$method}{$key} = $value; debug('coca',"store in confcache $host $method $key --> $value"); } } sub readfromcache ($$$$){ my($confcache,$host,$method,$key) = @_; $host = cleanhostkey $host; return $$confcache{$host}{$method}{$key}; } sub clearfromcache ($$){ my($confcache,$host) = @_; $host = cleanhostkey $host; delete $$confcache{$host}; debug('coca',"clear confcache $host"); } sub populateconfcache ($$$$$) { my $confcache = shift; my $host = shift; my $ipv4only = shift; my $reread = shift; my $snmpoptions = shift || {}; my $hostkey = cleanhostkey $host; return if defined $$confcache{$hostkey} and not $reread; my $snmp_errlevel = $SNMP_Session::suppress_warnings; my $net_snmp_errlevel = $Net_SNMP_util::suppress_warnings; $SNMP_Session::suppress_warnings = 3; $Net_SNMP_util::suppress_warnings = 3; debug('coca',"populate confcache $host"); # clear confcache for host; delete $$confcache{$hostkey}; my @ret; my %tables = ( ifDescr => 'Descr', ifName => 'Name', ifType => 'Type', ipAdEntIfIndex => 'Ip' ); my @nodes = qw (ifName ifDescr ifType ipAdEntIfIndex); # it seems that some devices only give back sensible data if their tables # are walked in the right ordere .... foreach my $node (@nodes) { next if $confcache->{___deadhosts}{$hostkey} and time - $confcache->{___deadhosts}{$hostkey} < 300; $SNMP_Session::errmsg = undef; $Net_SNMP_util::ErrorMessage = undef; @ret = &main::snmpwalk(v4onlyifnecessary($host, $ipv4only), $snmpoptions, $node); unless ( $SNMP_Session::errmsg or $Net_SNMP_util::ErrorMessage){ foreach my $ret (@ret) { my ($oid, $desc) = split(':', $ret, 2); if ($tables{$node} eq 'Ip') { storeincache($confcache,$host,$tables{$node},$oid,$desc); } else { $desc =~ s/[\0- ]+$//; #trailing whitespace is too sick for us $desc =~ s/[\0- ]/ /g; #whitespace is just whitespace storeincache($confcache,$host,$tables{$node},$desc,$oid); } }; } else { $confcache->{___deadhosts}{$hostkey} = time if defined($SNMP_Session::errmsg) and $SNMP_Session::errmsg =~ /no response received/; $confcache->{___deadhosts}{$hostkey} = time if defined($Net_SNMP_util::ErrorMessage) and $Net_SNMP_util::ErrorMessage =~ /No response from remote/; debug('coca',"Skipping $node scanning because $host does not seem to support it"); } } if ($confcache->{___deadhosts}{$hostkey} and time - $confcache->{___deadhosts}{$hostkey} < 300){ $SNMP_Session::suppress_warnings = $snmp_errlevel; $Net_SNMP_util::suppress_warnings = $snmp_errlevel; return; } $SNMP_Session::errmsg = undef; $Net_SNMP_util::ErrorMessage = undef; @ret = &main::snmpwalk(v4onlyifnecessary($host, $ipv4only), $snmpoptions, "ifPhysAddress"); unless ( $SNMP_Session::errmsg or $Net_SNMP_util::ErrorMessage){ foreach my $ret (@ret) { my ($oid, $bin) = split(':', $ret, 2); my $eth = unpack 'H*', $bin; my @eth; while ($eth =~ s/^..//){ push @eth, $&; } my $phys=join '-', @eth; storeincache($confcache,$host,"Eth",$phys,$oid); } } else { debug('coca',"Skipping ifPhysAddress scanning because $host does not seem to support it"); } if (ref $$confcache{___updated} ne 'ARRAY') { $$confcache{___updated} = []; #init to empty array } push @{$$confcache{___updated}}, $hostkey; $SNMP_Session::suppress_warnings = $snmp_errlevel; $Net_SNMP_util::suppress_warnings = $net_snmp_errlevel; } sub log2rrd ($$$) { my $router = shift; my $cfg = shift; my $rcfg = shift; my %mark; my %incomp; my %elapsed_time; my %rate; my %store; my %first_step; my %cur; my %next; my $rrd; my @steps = qw(300 1800 7200 86400); my %sizes = ( 300 => 600, 1800 => 700, 7200 => 775, 86400 => 797); open R, "<$$cfg{logdir}$$rcfg{'directory'}{$router}$router.log" or die "ERROR: opening $$cfg{logdir}$$rcfg{'directory'}{$router}$router.log: $!"; debug('rrd',"converting $$cfg{logdir}$$rcfg{'directory'}{$router}$router.log"); my $latest_timestamp; my %latest_counter; chomp($_ = ); my $time; my $next_time; ($latest_timestamp,$latest_counter{in},$latest_counter{out}) = split /\s+/; chomp($_ = ); ($time,$cur{in},$cur{out},$cur{maxin},$cur{maxout}) = split /\s+/; foreach my $s (@steps) { $mark{$s} = $latest_timestamp - ($latest_timestamp % $s) + $s; $first_step{$s} = $latest_timestamp - ($mark{$s} - $s); $elapsed_time{$s} = $s - $first_step{$s}; $rate{in}{$s}=$cur{in}; $rate{out}{$s}=$cur{out}; $rate{maxin}{$s}=$cur{maxin}; $rate{maxout}{$s}=$cur{maxout}; } while(){ chomp; ($next_time,$next{in},$next{out},$next{maxin},$next{maxout}) = split /\s+/; foreach my $s (@steps) { # bail if we have enough entries next if ref $store{in}{$s} and scalar @{$store{in}{$s}} > $sizes{$s}; # ok we are still here. If next mark is before the next time # we take a short step, else we gobble up my $next_stop; do { if ($elapsed_time{$s} + $time - $next_time > $s) { $next_stop = $mark{$s}-$s; } else { $next_stop = $next_time; } my $time_diff = $time-$next_stop; foreach my $d (qw(in out)) { $rate{$d}{$s} = ($rate{$d}{$s} * $elapsed_time{$s} + $cur{$d} * $time_diff) / ($elapsed_time{$s} + $time_diff); } foreach my $d (qw(maxin maxout)){ $rate{$d}{$s} = $cur{$d} if $rate{$d}{$s} < $cur{$d}; } $elapsed_time{$s} += $time_diff; # print "$time $next_stop\n" if $s == 300; if ($next_stop == $mark{$s}-$s) { foreach my $t (qw(in out maxin maxout)){ $rate{$t}{$s}/=3600 if (defined $$rcfg{'options'}{'perhour'}{$router}); $rate{$t}{$s}/=60 if (defined $$rcfg{'options'}{'perminute'}{$router}); push @{$store{$t}{$s}}, $rate{$t}{$s}; } $mark{$s} -= $s; $rate{maxin}{$s} = 0; $rate{maxout}{$s} = 0; $elapsed_time{$s} = 0; } } while ($next_stop > $next_time ); } ($time,$cur{in},$cur{out},$cur{maxin},$cur{maxout}) = ($next_time,$next{in},$next{out},$next{maxin},$next{maxout}); } close R; # lets see if we have rrdtool 1.2 at our hands my $VERSION = '0001'; if ($RRDs::VERSION >= 1.2){ $VERSION = '0003'; } my $DST; my $pdprepin = (shift @{$store{in}{300}})*($first_step{300}); my $pdprepout = (shift @{$store{out}{300}})*($first_step{300}); if (defined $$rcfg{'options'}{'absolute'}{$router}) { $DST = 'ABSOLUTE' } elsif (defined $$rcfg{'options'}{'gauge'}{$router}) { $DST = 'GAUGE' } else { $DST = 'COUNTER' } my $MHB = int($$cfg{interval} * 60 * 2); my $MAX1 = $$rcfg{'absmax'}{$router} || $$rcfg{'maxbytes1'}{$router} || 'U'; my $MAX2 = $$rcfg{'absmax'}{$router} || $$rcfg{'maxbytes2'}{$router} || 'U'; $rrd = < $VERSION 300 $latest_timestamp ds0 $DST $MHB 0 $MAX1 $latest_counter{in} $pdprepin 0 ds1 $DST $MHB 0 $MAX2 $latest_counter{out} $pdprepout 0 RRD $first_step{300} = 0; # invalidate addarch(1,'AVERAGE','in','out',\%store,\%first_step,\$rrd); addarch(6,'AVERAGE','in','out',\%store,\%first_step,\$rrd); addarch(24,'AVERAGE','in','out',\%store,\%first_step,\$rrd); addarch(288,'AVERAGE','in','out',\%store,\%first_step,\$rrd); addarch(1,'MAX','maxin','maxout',\%store,\%first_step,\$rrd); addarch(6,'MAX','maxin','maxout',\%store,\%first_step,\$rrd); addarch(24,'MAX','maxin','maxout',\%store,\%first_step,\$rrd); addarch(288,'MAX','maxin','maxout',\%store,\%first_step,\$rrd); $rrd .= < RRD if ( $OS eq 'NT' or $OS eq 'OS2') { open (R, "|$$cfg{rrdtool} restore - $$cfg{logdir}$$rcfg{'directory'}{$router}$router.rrd"); } else { open (R, "|-") or exec "$$cfg{rrdtool}","restore","-","$$cfg{logdir}$$rcfg{'directory'}{$router}$router.rrd"; } print R $rrd; close R; } sub addarch($$$$$$$){ my $steps = shift; my $cons = shift; my $in = shift; my $out = shift; my $store = shift; my $first_step = shift; my $rrd = shift; my $cdpin = 'NaN'; my $cdpout = 'NaN'; my $param_start = ''; my $param_end = ''; my $extra_ds = ''; if ($RRDs::VERSION >= 1.2){ $param_start = ''; $param_end = ''; $extra_ds = ' 0.0000000000e+00 0.0000000000e+00 '; } if ($steps != 300) { $cdpin = shift @{$$store{$in}{300*$steps}}; $cdpout = shift @{$$store{$out}{300*$steps}}; }; $$rrd .= < $cons $steps $param_start 0.5 $param_end $extra_ds $cdpin 0 $extra_ds $cdpout 0 RRD while (@{$$store{$in}{$steps*300}}){ # we take zero as UNKNOWN my $inr = pop @{$$store{$in}{$steps*300}} || 'NaN'; my $outr = pop @{$$store{$out}{$steps*300}} || 'NaN'; $$rrd .= < $inr $outr RRD } $$rrd .= < RRD } # debug if the relevant debug tag is active print the debug message sub debug ($$) { return unless scalar @main::DEBUG; my $tag = shift; my $msg = shift; return unless grep {$_ eq $tag} @main::DEBUG; warn "--".$tag.": ".$msg."\n"; return; } # timestamp sub timestamp () { my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); $year += 1900; $mon += 1; return sprintf "%4d-%02d-%02d %02d:%02d:%02d", $year,$mon,$mday,$hour,$min,$sec; } # configure __DIE__ and __WARN__ sub setup_loghandlers ($){ $::global_logfile = $_[0]; for($_[0]){ /^eventlog$/i && do { require Win32::EventLog; $SIG{__WARN__} = sub { my $EventLog = Win32::EventLog->new('MRTG'); my $Type = ($_[0] =~ /warning/) ? &Win32::EventLog::EVENTLOG_WARNING_TYPE : &Win32::EventLog::EVENTLOG_INFORMATION_TYPE; my $Msg = $_[0]; $Msg =~ s/\n/\r\n/g; $Msg =~ s/[\n\r]$//g; $EventLog->Report({ EventID => 1000, Category => "WARN", EventType => $Type, Data => '', Strings => $Msg }); $EventLog->Close; }; $SIG{__DIE__} = sub { return if $^S ; # no handler in eval my $EventLog = Win32::EventLog->new('MRTG'); my $Msg = $_[0]; $Msg =~ s/\n/\r\n/g; $Msg =~ s/[\n\r]$//g; $EventLog->Report({ EventID => 1000, Category => "ERROR", EventType => &Win32::EventLog::EVENTLOG_ERROR_TYPE, Data => '', Strings => $Msg }); $EventLog->Close; exit 1; }; last; }; $SIG{__WARN__} = sub { if (open DEB, ">>$::global_logfile") { print DEB timestamp." -- $_[0]"; close DEB; } else { print STDERR timestamp." -- $_[0]" } }; $SIG{__DIE__} = sub { return if $^S ; # no handler in eval if ( open DEB, ">>$::global_logfile") { print DEB timestamp." -- $_[0]"; close DEB; } else { print STDERR timestamp." -- $_[0]" } exit 1 }; } } # Adds the v4only attribute to a target if the caller requests it. # (this includes targets specified using numeric IPv6 addresses...) sub v4onlyifnecessary ($$) { my $target = shift; my $add = shift; my ($v6addr, $temptarget); if($add) { # Catch numeric IPv6 addresses if ( $target =~ /(\[[\w:]*\])(.*)/) { ($v6addr, $temptarget) = ($1,$2); } else { $temptarget = $target; } return $target.(":" x (5 - ($temptarget =~ tr/://))).":v4only"; } else { return $target; } } __END__ =pod =head1 NAME MRTG_lib.pm - Library for MRTG and support scripts =head1 SYNOPSIS use MRTG_lib; my ($configfile, @target_names, %globalcfg, %targetcfg); readcfg($configfile, \@target_names, \%globalcfg, \%targetcfg); my (@parsed_targets); cfgcheck(\@target_names, \%globalcfg, \%targetcfg, \@parsed_targets); =head1 DESCRIPTION MRTG_lib is part of MRTG, the Multi Router Traffic Grapher. It was separated from MRTG to allow other programs to easily use the same config files. The main part of MRTG_lib is the config file parser but some other functions are there too. =over 4 =item C<$MRTG_lib::OS> Type of OS: WIN, UNIX, VMS =item C<$MRTG_lib::SL> I in the current OS. =item C<$MRTG_lib::PS> Path separator in PATH variable =item C C Reads a config file, parses it and fills some arrays and hashes. The mandatory arguments are: the name of the config file, a ref to an array which will be filled with a list of the target names, a hashref for the global configuration, a hashref for the target configuration. The configuration file syntax is: globaloption: value targetoption[targetname]: value aprefix*extglobal: value aprefix*exttarget[target2]: value E.g. workdir: /var/stat/mrtg target[router1]: 2:public@router1.local.net 14all*columns: 2 The global config hash has the structure $globalcfg{configoption} = 'value' The target config hash has the structure $targetcfg{configoption}{targetname} = 'value' See L for more information about the MRTG configuration syntax. C can take two additional arguments to extend the config file syntax. This allows programs to put their configuration into the mrtg config file. The fifth argument is the prefix of the extension, the sixth argument is a hash with the checkrules for these extension settings. E.g. if the prefix is "14all" C will check config lines that begin with "14all*", i.e. all lines like 14all*columns: 2 14all*graphsize[target3]: 500 200 against the rules in %extrules. The format of this hash is: $extrules{option} = [sub{$_[0] =~ m/^\d+$/}, sub{"Error message for $_[0]"}] i.e. $extrules{option}[0] -> a test expression $extrules{option}[1] -> error message if test fails The first part of the array is a perl expression to test the value of the option. The test can access this value in the variable "$arg". The second part of the array is an error message to display when the test fails. The failed value can be integrated by using the variable "$arg". Config settings with an different prefix than the one given in the C call are not checked but inserted into I<%globalcfg> and I<%targetcfg>. Prefixed settings keep their prefix in the config hashes: $targetcfg{'14all*graphsize'}{'target3'} = '500 200' =item C C Checks the configuration read by C. Checks the values in the config for syntactical and/or semantical errors. Sets defaults for some options. Parses the "target[...]" options and files the array @parsed_targets ready for mrtg functions. The first three arguments are the same as for C. The fourth argument is an arrayref which will be filled with the parsed target defs. C converts the values of target settings I, e.g. options[router1]: bits, growright to a hash: $targetcfg{'option'}{'bits'}{'router1'} = 1 $targetcfg{'option'}{'growright'}{'router1'} = 1 This is not done by C so if you don't use C you have to check the scalar variable I<$targetcfg{'option'}{'router1'}> (MRTG allows options to be separated by space or ','). =item C C Checks that the I does not contain double path separators and ends with a path separator. It uses $MRTG_lib::SL as path separator which will be / or \ depending on the OS. =item C C Convert log file to rrd format. Needs rrdtool. =item C C Returns the time given in the argument as a nicely formatted date string. The argument has to be in UNIX time format (seconds since 1970-1-1). =item C C Return a string representing the current time. =item C C Install signalhandlers for __DIE__ and __WARN__ making the errors go the the specified destination. If filename is 'eventlog' mrtg will log to the windows event logger. =item C C Returns the time given in the argument formatted suitable for HTTP Expire-Headers. =item C C Creates a pid file for the mrtg daemon =item C C Puts the running program into background, detaching it from the terminal. =item C C Reads the SNMP variables I, I, I, I from the I and stores the values in I<%confcache> as follows: $confcache{$host}{'Descr'}{ifDescr}{oid} = (ifDescr or 'Dup') $confcache{$host}{'IP'}{ipAdEntIfIndex}{oid} = (ipAdEntIfIndex or 'Dup') $confcache{$host}{'Eth'}{ifPhysAddress}{oid} = (ifPhysAddress or 'Dup') $confcache{$host}{'Name'}{ifName}{oid} = (ifName or 'Dup') $confcache{$host}{'Type'}{ifType}{oid} = (ifType or 'Dup') The value (at the right side of =) is 'Dup' if a value was retrieved multiple times, the retrieved value else. =item C C Preload the confcache from a file. =item C C Store the current confcache into a file. =item C C Store the current confcache into a file. =item C C =item C C =item C C =item C C Prints the I on STDERR if debugging is enabled for type I. A debug type is enabled if I is in array @main::DEBUG. =back =head1 AUTHORS Rainer Bawidamann ERainer.Bawidamann@rz.uni-ulm.deE (This Manpage) =cut mrtg-2.17.10/lib/mrtg2/Net_SNMP_util.pm0000644000175300017510000020164214171763414016442 0ustar oetikeroep### - *- mode: Perl -*- ###################################################################### ### Net_SNMP_util -- SNMP utilities using Net::SNMP ###################################################################### ### Copyright (c) 2005-2011 Mike Mitchell. ### ### This program is free software; you can redistribute it under the ### "Artistic License" included in this distribution (file "Artistic"). ###################################################################### ### Created by: Mike Mitchell ### ### Contributions and fixes by: ### ### Laszlo Herczeg ### ignore unimplemented SNMP_Session.pm options ### ### Daniel McDonald ### make sure snmpwalk_flg stops when last instance in table is fetched ### ### Alexander Kozlov ### Leave snmpwalk_flg early if no OIDs are returned ### ### ### parse NOTIFICATION-TYPE in MIB ### ### Dan Thorson ### Handle quotes in MIB comments better ### ### Daniel J McDonald ### fix getbulk_request -> get_bulk_request typo ### ### Tobias Oetiker ### fix '-privpassword' error against snmpv2 hosts ### ###################################################################### package Net_SNMP_util; =head1 NAME Net_SNMP_util - SNMP utilities based on Net::SNMP =head1 SYNOPSIS The Net_SNMP_util module implements SNMP utilities using the Net::SNMP module. It implements snmpget, snmpgetnext, snmpwalk, snmpset, snmptrap, and snmpgetbulk. The Net_SNMP_util module assumes that the user has a basic understanding of the Simple Network Management Protocol and related network management concepts. =head1 DESCRIPTION The Net_SNMP_util module simplifies SNMP queries even more than Net::SNMP alone. Easy-to-use "get", "getnext", "walk", "set", "trap", and "getbulk" routines are provided, hiding all the details of a SNMP query. =cut # ========================================================================== use strict; ## Validate the version of Perl BEGIN { die('Perl version 5.6.0 or greater is required') if ($] < 5.006); } ## Handle importing/exporting of symbols use vars qw( @ISA @EXPORT $VERSION $ErrorMessage); use Exporter; our @ISA = qw( Exporter ); our @EXPORT = qw( snmpget snmpgetnext snmpwalk snmpset snmptrap snmpgetbulk snmpmaptable snmpmaptable4 snmpwalkhash snmpmapOID snmpMIB_to_OID snmpLoad_OID_Cache snmpQueue_MIB_File ErrorMessage ); ## Version of the Net_SNMP_util module our $VERSION = v1.0.20; use Carp; use Net::SNMP v5.0; # The OID numbers from RFC1213 (MIB-II) and RFC1315 (Frame Relay) # are pre-loaded below. %Net_SNMP_util::OIDS = ( 'iso' => '1', 'org' => '1.3', 'dod' => '1.3.6', 'internet' => '1.3.6.1', 'directory' => '1.3.6.1.1', 'mgmt' => '1.3.6.1.2', 'mib-2' => '1.3.6.1.2.1', 'system' => '1.3.6.1.2.1.1', 'sysDescr' => '1.3.6.1.2.1.1.1.0', 'sysObjectID' => '1.3.6.1.2.1.1.2.0', 'sysUpTime' => '1.3.6.1.2.1.1.3.0', 'sysUptime' => '1.3.6.1.2.1.1.3.0', 'sysContact' => '1.3.6.1.2.1.1.4.0', 'sysName' => '1.3.6.1.2.1.1.5.0', 'sysLocation' => '1.3.6.1.2.1.1.6.0', 'sysServices' => '1.3.6.1.2.1.1.7.0', 'interfaces' => '1.3.6.1.2.1.2', 'ifNumber' => '1.3.6.1.2.1.2.1.0', 'ifTable' => '1.3.6.1.2.1.2.2', 'ifEntry' => '1.3.6.1.2.1.2.2.1', 'ifIndex' => '1.3.6.1.2.1.2.2.1.1', 'ifInOctets' => '1.3.6.1.2.1.2.2.1.10', 'ifInUcastPkts' => '1.3.6.1.2.1.2.2.1.11', 'ifInNUcastPkts' => '1.3.6.1.2.1.2.2.1.12', 'ifInDiscards' => '1.3.6.1.2.1.2.2.1.13', 'ifInErrors' => '1.3.6.1.2.1.2.2.1.14', 'ifInUnknownProtos' => '1.3.6.1.2.1.2.2.1.15', 'ifOutOctets' => '1.3.6.1.2.1.2.2.1.16', 'ifOutUcastPkts' => '1.3.6.1.2.1.2.2.1.17', 'ifOutNUcastPkts' => '1.3.6.1.2.1.2.2.1.18', 'ifOutDiscards' => '1.3.6.1.2.1.2.2.1.19', 'ifDescr' => '1.3.6.1.2.1.2.2.1.2', 'ifOutErrors' => '1.3.6.1.2.1.2.2.1.20', 'ifOutQLen' => '1.3.6.1.2.1.2.2.1.21', 'ifSpecific' => '1.3.6.1.2.1.2.2.1.22', 'ifType' => '1.3.6.1.2.1.2.2.1.3', 'ifMtu' => '1.3.6.1.2.1.2.2.1.4', 'ifSpeed' => '1.3.6.1.2.1.2.2.1.5', 'ifPhysAddress' => '1.3.6.1.2.1.2.2.1.6', 'ifAdminHack' => '1.3.6.1.2.1.2.2.1.7', 'ifAdminStatus' => '1.3.6.1.2.1.2.2.1.7', 'ifOperHack' => '1.3.6.1.2.1.2.2.1.8', 'ifOperStatus' => '1.3.6.1.2.1.2.2.1.8', 'ifLastChange' => '1.3.6.1.2.1.2.2.1.9', 'at' => '1.3.6.1.2.1.3', 'atTable' => '1.3.6.1.2.1.3.1', 'atEntry' => '1.3.6.1.2.1.3.1.1', 'atIfIndex' => '1.3.6.1.2.1.3.1.1.1', 'atPhysAddress' => '1.3.6.1.2.1.3.1.1.2', 'atNetAddress' => '1.3.6.1.2.1.3.1.1.3', 'ip' => '1.3.6.1.2.1.4', 'ipForwarding' => '1.3.6.1.2.1.4.1', 'ipOutRequests' => '1.3.6.1.2.1.4.10', 'ipOutDiscards' => '1.3.6.1.2.1.4.11', 'ipOutNoRoutes' => '1.3.6.1.2.1.4.12', 'ipReasmTimeout' => '1.3.6.1.2.1.4.13', 'ipReasmReqds' => '1.3.6.1.2.1.4.14', 'ipReasmOKs' => '1.3.6.1.2.1.4.15', 'ipReasmFails' => '1.3.6.1.2.1.4.16', 'ipFragOKs' => '1.3.6.1.2.1.4.17', 'ipFragFails' => '1.3.6.1.2.1.4.18', 'ipFragCreates' => '1.3.6.1.2.1.4.19', 'ipDefaultTTL' => '1.3.6.1.2.1.4.2', 'ipAddrTable' => '1.3.6.1.2.1.4.20', 'ipAddrEntry' => '1.3.6.1.2.1.4.20.1', 'ipAdEntAddr' => '1.3.6.1.2.1.4.20.1.1', 'ipAdEntIfIndex' => '1.3.6.1.2.1.4.20.1.2', 'ipAdEntNetMask' => '1.3.6.1.2.1.4.20.1.3', 'ipAdEntBcastAddr' => '1.3.6.1.2.1.4.20.1.4', 'ipAdEntReasmMaxSize' => '1.3.6.1.2.1.4.20.1.5', 'ipRouteTable' => '1.3.6.1.2.1.4.21', 'ipRouteEntry' => '1.3.6.1.2.1.4.21.1', 'ipRouteDest' => '1.3.6.1.2.1.4.21.1.1', 'ipRouteAge' => '1.3.6.1.2.1.4.21.1.10', 'ipRouteMask' => '1.3.6.1.2.1.4.21.1.11', 'ipRouteMetric5' => '1.3.6.1.2.1.4.21.1.12', 'ipRouteInfo' => '1.3.6.1.2.1.4.21.1.13', 'ipRouteIfIndex' => '1.3.6.1.2.1.4.21.1.2', 'ipRouteMetric1' => '1.3.6.1.2.1.4.21.1.3', 'ipRouteMetric2' => '1.3.6.1.2.1.4.21.1.4', 'ipRouteMetric3' => '1.3.6.1.2.1.4.21.1.5', 'ipRouteMetric4' => '1.3.6.1.2.1.4.21.1.6', 'ipRouteNextHop' => '1.3.6.1.2.1.4.21.1.7', 'ipRouteType' => '1.3.6.1.2.1.4.21.1.8', 'ipRouteProto' => '1.3.6.1.2.1.4.21.1.9', 'ipNetToMediaTable' => '1.3.6.1.2.1.4.22', 'ipNetToMediaEntry' => '1.3.6.1.2.1.4.22.1', 'ipNetToMediaIfIndex' => '1.3.6.1.2.1.4.22.1.1', 'ipNetToMediaPhysAddress' => '1.3.6.1.2.1.4.22.1.2', 'ipNetToMediaNetAddress' => '1.3.6.1.2.1.4.22.1.3', 'ipNetToMediaType' => '1.3.6.1.2.1.4.22.1.4', 'ipRoutingDiscards' => '1.3.6.1.2.1.4.23', 'ipInReceives' => '1.3.6.1.2.1.4.3', 'ipInHdrErrors' => '1.3.6.1.2.1.4.4', 'ipInAddrErrors' => '1.3.6.1.2.1.4.5', 'ipForwDatagrams' => '1.3.6.1.2.1.4.6', 'ipInUnknownProtos' => '1.3.6.1.2.1.4.7', 'ipInDiscards' => '1.3.6.1.2.1.4.8', 'ipInDelivers' => '1.3.6.1.2.1.4.9', 'icmp' => '1.3.6.1.2.1.5', 'icmpInMsgs' => '1.3.6.1.2.1.5.1', 'icmpInTimestamps' => '1.3.6.1.2.1.5.10', 'icmpInTimestampReps' => '1.3.6.1.2.1.5.11', 'icmpInAddrMasks' => '1.3.6.1.2.1.5.12', 'icmpInAddrMaskReps' => '1.3.6.1.2.1.5.13', 'icmpOutMsgs' => '1.3.6.1.2.1.5.14', 'icmpOutErrors' => '1.3.6.1.2.1.5.15', 'icmpOutDestUnreachs' => '1.3.6.1.2.1.5.16', 'icmpOutTimeExcds' => '1.3.6.1.2.1.5.17', 'icmpOutParmProbs' => '1.3.6.1.2.1.5.18', 'icmpOutSrcQuenchs' => '1.3.6.1.2.1.5.19', 'icmpInErrors' => '1.3.6.1.2.1.5.2', 'icmpOutRedirects' => '1.3.6.1.2.1.5.20', 'icmpOutEchos' => '1.3.6.1.2.1.5.21', 'icmpOutEchoReps' => '1.3.6.1.2.1.5.22', 'icmpOutTimestamps' => '1.3.6.1.2.1.5.23', 'icmpOutTimestampReps' => '1.3.6.1.2.1.5.24', 'icmpOutAddrMasks' => '1.3.6.1.2.1.5.25', 'icmpOutAddrMaskReps' => '1.3.6.1.2.1.5.26', 'icmpInDestUnreachs' => '1.3.6.1.2.1.5.3', 'icmpInTimeExcds' => '1.3.6.1.2.1.5.4', 'icmpInParmProbs' => '1.3.6.1.2.1.5.5', 'icmpInSrcQuenchs' => '1.3.6.1.2.1.5.6', 'icmpInRedirects' => '1.3.6.1.2.1.5.7', 'icmpInEchos' => '1.3.6.1.2.1.5.8', 'icmpInEchoReps' => '1.3.6.1.2.1.5.9', 'tcp' => '1.3.6.1.2.1.6', 'tcpRtoAlgorithm' => '1.3.6.1.2.1.6.1', 'tcpInSegs' => '1.3.6.1.2.1.6.10', 'tcpOutSegs' => '1.3.6.1.2.1.6.11', 'tcpRetransSegs' => '1.3.6.1.2.1.6.12', 'tcpConnTable' => '1.3.6.1.2.1.6.13', 'tcpConnEntry' => '1.3.6.1.2.1.6.13.1', 'tcpConnState' => '1.3.6.1.2.1.6.13.1.1', 'tcpConnLocalAddress' => '1.3.6.1.2.1.6.13.1.2', 'tcpConnLocalPort' => '1.3.6.1.2.1.6.13.1.3', 'tcpConnRemAddress' => '1.3.6.1.2.1.6.13.1.4', 'tcpConnRemPort' => '1.3.6.1.2.1.6.13.1.5', 'tcpInErrs' => '1.3.6.1.2.1.6.14', 'tcpOutRsts' => '1.3.6.1.2.1.6.15', 'tcpRtoMin' => '1.3.6.1.2.1.6.2', 'tcpRtoMax' => '1.3.6.1.2.1.6.3', 'tcpMaxConn' => '1.3.6.1.2.1.6.4', 'tcpActiveOpens' => '1.3.6.1.2.1.6.5', 'tcpPassiveOpens' => '1.3.6.1.2.1.6.6', 'tcpAttemptFails' => '1.3.6.1.2.1.6.7', 'tcpEstabResets' => '1.3.6.1.2.1.6.8', 'tcpCurrEstab' => '1.3.6.1.2.1.6.9', 'udp' => '1.3.6.1.2.1.7', 'udpInDatagrams' => '1.3.6.1.2.1.7.1', 'udpNoPorts' => '1.3.6.1.2.1.7.2', 'udpInErrors' => '1.3.6.1.2.1.7.3', 'udpOutDatagrams' => '1.3.6.1.2.1.7.4', 'udpTable' => '1.3.6.1.2.1.7.5', 'udpEntry' => '1.3.6.1.2.1.7.5.1', 'udpLocalAddress' => '1.3.6.1.2.1.7.5.1.1', 'udpLocalPort' => '1.3.6.1.2.1.7.5.1.2', 'egp' => '1.3.6.1.2.1.8', 'egpInMsgs' => '1.3.6.1.2.1.8.1', 'egpInErrors' => '1.3.6.1.2.1.8.2', 'egpOutMsgs' => '1.3.6.1.2.1.8.3', 'egpOutErrors' => '1.3.6.1.2.1.8.4', 'egpNeighTable' => '1.3.6.1.2.1.8.5', 'egpNeighEntry' => '1.3.6.1.2.1.8.5.1', 'egpNeighState' => '1.3.6.1.2.1.8.5.1.1', 'egpNeighStateUps' => '1.3.6.1.2.1.8.5.1.10', 'egpNeighStateDowns' => '1.3.6.1.2.1.8.5.1.11', 'egpNeighIntervalHello' => '1.3.6.1.2.1.8.5.1.12', 'egpNeighIntervalPoll' => '1.3.6.1.2.1.8.5.1.13', 'egpNeighMode' => '1.3.6.1.2.1.8.5.1.14', 'egpNeighEventTrigger' => '1.3.6.1.2.1.8.5.1.15', 'egpNeighAddr' => '1.3.6.1.2.1.8.5.1.2', 'egpNeighAs' => '1.3.6.1.2.1.8.5.1.3', 'egpNeighInMsgs' => '1.3.6.1.2.1.8.5.1.4', 'egpNeighInErrs' => '1.3.6.1.2.1.8.5.1.5', 'egpNeighOutMsgs' => '1.3.6.1.2.1.8.5.1.6', 'egpNeighOutErrs' => '1.3.6.1.2.1.8.5.1.7', 'egpNeighInErrMsgs' => '1.3.6.1.2.1.8.5.1.8', 'egpNeighOutErrMsgs' => '1.3.6.1.2.1.8.5.1.9', 'egpAs' => '1.3.6.1.2.1.8.6', 'transmission' => '1.3.6.1.2.1.10', 'frame-relay' => '1.3.6.1.2.1.10.32', 'frDlcmiTable' => '1.3.6.1.2.1.10.32.1', 'frDlcmiEntry' => '1.3.6.1.2.1.10.32.1.1', 'frDlcmiIfIndex' => '1.3.6.1.2.1.10.32.1.1.1', 'frDlcmiState' => '1.3.6.1.2.1.10.32.1.1.2', 'frDlcmiAddress' => '1.3.6.1.2.1.10.32.1.1.3', 'frDlcmiAddressLen' => '1.3.6.1.2.1.10.32.1.1.4', 'frDlcmiPollingInterval' => '1.3.6.1.2.1.10.32.1.1.5', 'frDlcmiFullEnquiryInterval' => '1.3.6.1.2.1.10.32.1.1.6', 'frDlcmiErrorThreshold' => '1.3.6.1.2.1.10.32.1.1.7', 'frDlcmiMonitoredEvents' => '1.3.6.1.2.1.10.32.1.1.8', 'frDlcmiMaxSupportedVCs' => '1.3.6.1.2.1.10.32.1.1.9', 'frDlcmiMulticast' => '1.3.6.1.2.1.10.32.1.1.10', 'frCircuitTable' => '1.3.6.1.2.1.10.32.2', 'frCircuitEntry' => '1.3.6.1.2.1.10.32.2.1', 'frCircuitIfIndex' => '1.3.6.1.2.1.10.32.2.1.1', 'frCircuitDlci' => '1.3.6.1.2.1.10.32.2.1.2', 'frCircuitState' => '1.3.6.1.2.1.10.32.2.1.3', 'frCircuitReceivedFECNs' => '1.3.6.1.2.1.10.32.2.1.4', 'frCircuitReceivedBECNs' => '1.3.6.1.2.1.10.32.2.1.5', 'frCircuitSentFrames' => '1.3.6.1.2.1.10.32.2.1.6', 'frCircuitSentOctets' => '1.3.6.1.2.1.10.32.2.1.7', 'frOutOctets' => '1.3.6.1.2.1.10.32.2.1.7', 'frCircuitReceivedFrames' => '1.3.6.1.2.1.10.32.2.1.8', 'frCircuitReceivedOctets' => '1.3.6.1.2.1.10.32.2.1.9', 'frInOctets' => '1.3.6.1.2.1.10.32.2.1.9', 'frCircuitCreationTime' => '1.3.6.1.2.1.10.32.2.1.10', 'frCircuitLastTimeChange' => '1.3.6.1.2.1.10.32.2.1.11', 'frCircuitCommittedBurst' => '1.3.6.1.2.1.10.32.2.1.12', 'frCircuitExcessBurst' => '1.3.6.1.2.1.10.32.2.1.13', 'frCircuitThroughput' => '1.3.6.1.2.1.10.32.2.1.14', 'frErrTable' => '1.3.6.1.2.1.10.32.3', 'frErrEntry' => '1.3.6.1.2.1.10.32.3.1', 'frErrIfIndex' => '1.3.6.1.2.1.10.32.3.1.1', 'frErrType' => '1.3.6.1.2.1.10.32.3.1.2', 'frErrData' => '1.3.6.1.2.1.10.32.3.1.3', 'frErrTime' => '1.3.6.1.2.1.10.32.3.1.4', 'frame-relay-globals' => '1.3.6.1.2.1.10.32.4', 'frTrapState' => '1.3.6.1.2.1.10.32.4.1', 'snmp' => '1.3.6.1.2.1.11', 'snmpInPkts' => '1.3.6.1.2.1.11.1', 'snmpInBadValues' => '1.3.6.1.2.1.11.10', 'snmpInReadOnlys' => '1.3.6.1.2.1.11.11', 'snmpInGenErrs' => '1.3.6.1.2.1.11.12', 'snmpInTotalReqVars' => '1.3.6.1.2.1.11.13', 'snmpInTotalSetVars' => '1.3.6.1.2.1.11.14', 'snmpInGetRequests' => '1.3.6.1.2.1.11.15', 'snmpInGetNexts' => '1.3.6.1.2.1.11.16', 'snmpInSetRequests' => '1.3.6.1.2.1.11.17', 'snmpInGetResponses' => '1.3.6.1.2.1.11.18', 'snmpInTraps' => '1.3.6.1.2.1.11.19', 'snmpOutPkts' => '1.3.6.1.2.1.11.2', 'snmpOutTooBigs' => '1.3.6.1.2.1.11.20', 'snmpOutNoSuchNames' => '1.3.6.1.2.1.11.21', 'snmpOutBadValues' => '1.3.6.1.2.1.11.22', 'snmpOutGenErrs' => '1.3.6.1.2.1.11.24', 'snmpOutGetRequests' => '1.3.6.1.2.1.11.25', 'snmpOutGetNexts' => '1.3.6.1.2.1.11.26', 'snmpOutSetRequests' => '1.3.6.1.2.1.11.27', 'snmpOutGetResponses' => '1.3.6.1.2.1.11.28', 'snmpOutTraps' => '1.3.6.1.2.1.11.29', 'snmpInBadVersions' => '1.3.6.1.2.1.11.3', 'snmpEnableAuthenTraps' => '1.3.6.1.2.1.11.30', 'snmpInBadCommunityNames' => '1.3.6.1.2.1.11.4', 'snmpInBadCommunityUses' => '1.3.6.1.2.1.11.5', 'snmpInASNParseErrs' => '1.3.6.1.2.1.11.6', 'snmpInTooBigs' => '1.3.6.1.2.1.11.8', 'snmpInNoSuchNames' => '1.3.6.1.2.1.11.9', 'ifName' => '1.3.6.1.2.1.31.1.1.1.1', 'ifInMulticastPkts' => '1.3.6.1.2.1.31.1.1.1.2', 'ifInBroadcastPkts' => '1.3.6.1.2.1.31.1.1.1.3', 'ifOutMulticastPkts' => '1.3.6.1.2.1.31.1.1.1.4', 'ifOutBroadcastPkts' => '1.3.6.1.2.1.31.1.1.1.5', 'ifHCInOctets' => '1.3.6.1.2.1.31.1.1.1.6', 'ifHCInUcastPkts' => '1.3.6.1.2.1.31.1.1.1.7', 'ifHCInMulticastPkts' => '1.3.6.1.2.1.31.1.1.1.8', 'ifHCInBroadcastPkts' => '1.3.6.1.2.1.31.1.1.1.9', 'ifHCOutOctets' => '1.3.6.1.2.1.31.1.1.1.10', 'ifHCOutUcastPkts' => '1.3.6.1.2.1.31.1.1.1.11', 'ifHCOutMulticastPkts' => '1.3.6.1.2.1.31.1.1.1.12', 'ifHCOutBroadcastPkts' => '1.3.6.1.2.1.31.1.1.1.13', 'ifLinkUpDownTrapEnable' => '1.3.6.1.2.1.31.1.1.1.14', 'ifHighSpeed' => '1.3.6.1.2.1.31.1.1.1.15', 'ifPromiscuousMode' => '1.3.6.1.2.1.31.1.1.1.16', 'ifConnectorPresent' => '1.3.6.1.2.1.31.1.1.1.17', 'ifAlias' => '1.3.6.1.2.1.31.1.1.1.18', 'ifCounterDiscontinuityTime' => '1.3.6.1.2.1.31.1.1.1.19', 'experimental' => '1.3.6.1.3', 'private' => '1.3.6.1.4', 'enterprises' => '1.3.6.1.4.1', ); # GIL my %revOIDS = (); # Reversed %Net_SNMP_util::OIDS hash my $RevNeeded = 1; undef $Net_SNMP_util::Host; undef $Net_SNMP_util::Session; undef $Net_SNMP_util::Version; undef $Net_SNMP_util::LHost; undef $Net_SNMP_util::IPv4only; undef $Net_SNMP_util::ContextEngineID; undef $Net_SNMP_util::ContextName; $Net_SNMP_util::Debug = 0; $Net_SNMP_util::SuppressWarnings = 0; $Net_SNMP_util::CacheFile = "OID_cache.txt"; $Net_SNMP_util::CacheLoaded = 0; $Net_SNMP_util::ReturnArrayRefs = 0; $Net_SNMP_util::ReturnHashRefs = 0; $Net_SNMP_util::MaxRepetitions = 12; ### Prototypes sub snmpget ($@); sub snmpgetnext ($@); sub snmpopen ($$$); sub snmpwalk ($@); sub snmpwalk_flg ($$@); sub snmpset ($@); sub snmptrap ($$$$$@); sub snmpgetbulk ($$$@); sub snmpwalkhash ($$@); sub toOID (@); sub snmpmapOID (@); sub snmpMIB_to_OID ($); sub Check_OID ($); sub snmpLoad_OID_Cache ($); sub snmpQueue_MIB_File (@); sub ASNtype ($); sub error_msg ($); sub MIB_fill_OID ($); sub version () { $VERSION; } =head1 Option Notes =over =item host Parameter SNMP parameters can be specified as part of the hostname/ip address passed as the first argument. The syntax is community@host:port:timeout:retries:backoff:version If the community is left off, it defaults to "public". If the port is left off, it defaults to 161 for everything but snmptrap(). The snmptrap() routine uses a default port of 162. Timeout and retries defaults to whatever Net::SNMP uses, currently 5.0 seconds and 1 retry (2 tries total). The backoff parameter is currently unimplemented. The version parameter defaults to SNMP version 1. Some SNMP values such as 64-bit counters have to be queried using SNMP version 2. Specifying "2" or "2c" as the version parameter will accomplish this. The snmpgetbulk routine is only supported in SNMP version 2 and higher. Additional security features are available under SNMP version 3. Some machines have additional security features that only allow SNMP queries to come from certain IP addresses. If the host doing the query has multiple interfaces, it may be necessary to specify the interface the query should come from. The port parameter is further broken down into remote_port!local_address!local_port Here are some examples: somehost somehost:161 somehost:161!192.168.2.4!4000 use 192.168.2.4 and port 4000 as source somehost:!192.168.2.4 use 192.168.2.4 as source somehost:!!4000 use port 4000 as source Most people will only need to use the first form ("somehost"). =item OBJECT IDENTIFIERs To further simplify SNMP queries, the query routines use a small table that maps the textual representation of OBJECT IDENTIFIERs to their dotted notation. The OBJECT IDENTIFIERs from RFC1213 (MIB-II) and RFC1315 (Frame Relay) are preloaded. This allows OBJECT IDENTIFIERs like "ifInOctets.4" to be used instead of the more cumbersome "1.3.6.1.2.1.2.2.1.10.4". Several functions are provided to manage the mapping table. Mapping entries can be added directly, SNMP MIB files can be read, and a cache file with the text-to-OBJECT-IDENTIFIER mappings are maintained. By default, the file "OID_cache.txt" is loaded, but it can by changed by setting the variable $Net_SNMP_util::CacheFile to the desired file name. The functions to manipulate the mappings are: snmpmapOID Add a textual OID mapping directly snmpMIB_to_OID Read a SNMP MIB file snmpLoad_OID_Cache Load an OID-mapping cache file snmpQueue_MIB_File Queue a SNMP MIB file for loading on demand =item Net::SNMP extensions This module is built on top of Net::SNMP. Net::SNMP has a different method of specifying SNMP parameters. To support this different method, this module will accept an optional hash reference containing the SNMP parameters. The hash may contain the following: [-port => $port,] [-localaddr => $localaddr,] [-localport => $localport,] [-version => $version,] [-domain => $domain,] [-timeout => $seconds,] [-retries => $count,] [-maxmsgsize => $octets,] [-debug => $bitmask,] [-community => $community,] # v1/v2c [-username => $username,] # v3 [-authkey => $authkey,] # v3 [-authpassword => $authpasswd,] # v3 [-authprotocol => $authproto,] # v3 [-privkey => $privkey,] # v3 [-privpassword => $privpasswd,] # v3 [-privprotocol => $privproto,] # v3 [-contextengineid => $engine_id,] # v3 [-contextname => $name,] # v3 Please see the documentation for Net::SNMP for a description of these parameters. =item SNMPv3 Arguments A SNMP context is a collection of management information accessible by a SNMP entity. An item of management information may exist in more than one context and a SNMP entity potentially has access to many contexts. The combination of a contextEngineID and a contextName unambiguously identifies a context within an administrative domain. In a SNMPv3 message, the contextEngineID and contextName are included as part of the scopedPDU. All methods that generate a SNMP message optionally take a B<-contextengineid> and B<-contextname> argument to configure these fields. =over =item Context Engine ID The B<-contextengineid> argument expects a hexadecimal string representing the desired contextEngineID. The string must be 10 to 64 characters (5 to 32 octets) long and can be prefixed with an optional "0x". Once the B<-contextengineid> is specified it stays with the object until it is changed again or reset to default by passing in the undefined value. By default, the contextEngineID is set to match the authoritativeEngineID of the authoritative SNMP engine. =item Context Name The contextName is passed as a string which must be 0 to 32 octets in length using the B<-contextname> argument. The contextName stays with the object until it is changed. The contextName defaults to an empty string which represents the "default" context. =back =back =cut # [public methods] --------------------------------------------------- =head1 Functions =head2 snmpget() - send a SNMP get-request to the remote agent @result = snmpget( [community@]host[:port[:timeout[:retries[:backoff[:version]]]]], [\%param_hash], @oids ); This function performs a SNMP get-request query to gather data from the remote agent on the host specified. The message is built using the list of OBJECT IDENTIFIERs passed as an array. Each OBJECT IDENTIFIER is placed into a single SNMP GetRequest-PDU in the same order that it held in the original list. The requested values are returned in an array in the same order as they were requested. In scalar context the first requested value is returned. =cut # # snmpget. # sub snmpget ($@) { my($host, @vars) = @_; my($session, @enoid, %args, $ret, $oid, @retvals); @retvals = (); $session = &snmpopen($host, 0, \@vars); if (!defined($session)) { carp "SNMPGET Problem for $host" unless ($Net_SNMP_util::SuppressWarnings > 1); return wantarray ? @retvals : undef; } @enoid = &toOID(@vars); if ($#enoid < 0) { return wantarray ? @retvals : undef; } $args{'-varbindlist'} = \@enoid; if ($Net_SNMP_util::Version > 2) { $args{'-contextengineid'} = $Net_SNMP_util::ContextEngineID if (defined($Net_SNMP_util::ContextEngineID)); $args{'-contextname'} = $Net_SNMP_util::ContextName if (defined($Net_SNMP_util::ContextName)); } $ret = $session->get_request(%args); if ($ret) { foreach $oid (@enoid) { push @retvals, $ret->{$oid} if (exists($ret->{$oid})); } return wantarray ? @retvals : $retvals[0]; } $ret = join(' ', @vars); error_msg("SNMPGET Problem for $ret on ${host}: " . $session->error()); return wantarray ? @retvals : undef; } =head2 snmpgetnext() - send a SNMP get-next-request to the remote agent @result = snmpgetnext( [community@]host[:port[:timeout[:retries[:backoff[:version]]]]], [\%param_hash], @oids ); This function performs a SNMP get-next-request query to gather data from the remote agent on the host specified. The message is built using the list of OBJECT IDENTIFIERs passed as an array. Each OBJECT IDENTIFIER is placed into a single SNMP GetNextRequest-PDU in the same order that it held in the original list. The requested values are returned in an array in the same order as they were requested. The OBJECT IDENTIFIER number is added as a prefix to each value using a colon as a separator, like '1.3.6.1.2.1.2.2.1.2.1:ethernet'. In scalar context the first requested value is returned. =cut # # snmpgetnext. # sub snmpgetnext ($@) { my($host, @vars) = @_; my($session, @enoid, %args, $ret, $oid, @retvals); @retvals = (); $session = &snmpopen($host, 0, \@vars); if (!defined($session)) { carp "SNMPGETNEXT Problem for $host" unless ($Net_SNMP_util::SuppressWarnings > 1); return wantarray ? @retvals : undef; } @enoid = &toOID(@vars); if ($#enoid < 0) { return wantarray ? @retvals : undef; } $args{'-varbindlist'} = \@enoid; if ($Net_SNMP_util::Version > 2) { $args{'-contextengineid'} = $Net_SNMP_util::ContextEngineID if (defined($Net_SNMP_util::ContextEngineID)); $args{'-contextname'} = $Net_SNMP_util::ContextName if (defined($Net_SNMP_util::ContextName)); } $ret = $session->get_next_request(%args); if ($ret) { foreach $oid (@enoid) { push @retvals, $oid . ':' . $ret->{$oid} if (exists($ret->{$oid})); } return wantarray ? @retvals : $retvals[0]; } $ret = join(' ', @vars); error_msg("SNMPGETNEXT Problem for $ret on ${host}: " . $session->error()); return wantarray ? @retvals : undef; } =head2 snmpgetbulk() - send a SNMP get-bulk-request to the remote agent @result = snmpgetbulk( [community@]host[:port[:timeout[:retries[:backoff[:version]]]]], $nonrepeaters, $maxrepetitions, [\%param_hash], @oids ); This function performs a SNMP get-bulk-request query to gather data from the remote agent on the host specified. =over =item * The B<$nonrepeaters> value specifies the number of variables in the @oids list for which a single successor is to be returned. If it is null or undefined, a value of 0 is used. =item * The B<$maxrepetitions> value specifies the number of successors to be returned for the remaining variables in the @oids list. If it is null or undefined, the default value of 12 is used. =item * The message is built using the list of OBJECT IDENTIFIERs passed as an array. Each OBJECT IDENTIFIER is placed into a single SNMP GetNextRequest-PDU in the same order that it held in the original list. =back The requested values are returned in an array in the same order as they were requested. B This function can only be used when the SNMP version is set to SNMPv2c or SNMPv3. =cut # # snmpgetbulk. # sub snmpgetbulk ($$$@) { my($host, $nr, $mr, @vars) = @_; my($session, %args, @enoid, $ret); my($oid, @retvals); @retvals = (); $session = &snmpopen($host, 0, \@vars); if (!defined($session)) { carp "SNMPGETBULK Problem for $host" unless ($Net_SNMP_util::SuppressWarnings > 1); return @retvals; } if ($Net_SNMP_util::Version < 2) { carp "SNMPGETBULK Problem for $host : must use SNMP version > 1" unless ($Net_SNMP_util::SuppressWarnings > 1); return @retvals; } $args{'-nonrepeaters'} = $nr if ($nr > 0); $mr = $Net_SNMP_util::MaxRepetitions if ($mr <= 0); $args{'-maxrepetitions'} = $mr; if ($Net_SNMP_util::Version > 2) { $args{'-contextengineid'} = $Net_SNMP_util::ContextEngineID if (defined($Net_SNMP_util::ContextEngineID)); $args{'-contextname'} = $Net_SNMP_util::ContextName if (defined($Net_SNMP_util::ContextName)); } @enoid = &toOID(@vars); return @retvals if ($#enoid < 0); $args{'-varbindlist'} = \@enoid; $ret = $session->get_bulk_request(%args); if ($ret) { @enoid = &Net::SNMP::oid_lex_sort(keys %$ret); foreach $oid (@enoid) { push @retvals, $oid . ":" . $ret->{$oid}; } return @retvals; } else { $ret = join(' ', @vars); error_msg("SNMPGETBULK Problem for $ret on ${host}: " . $session->error()); return @retvals; } } =head2 snmpwalk() - walk OBJECT IDENTIFIER tree(s) on the remote agent @result = snmpwalk( [community@]host[:port[:timeout[:retries[:backoff[:version]]]]], [\%param_hash], @oids ); This function performs a sequence of SNMP get-next-request or get-bulk-request (if the SNMP version is 2 or higher) queries to gather data from the remote agent on the host specified. The initial message is built using the list of OBJECT IDENTIFIERs passed as an array. Each OBJECT IDENTIFIER is placed into a single SNMP GetNextRequest-PDU in the same order that it held in the original list. Queries continue until all the returned OBJECT IDENTIFIERs are no longer a child of the base OBJECT IDENTIFIERs. The requested values are returned in an array in the same order as they were requested. The OBJECT IDENTIFIER number is added as a prefix to each value using a colon as a separator, like '1.3.6.1.2.1.2.2.1.2.1:ethernet'. If only one OBJECT IDENTIFIER is requested, just the "instance" part of the OBJECT IDENTIFIER is added as a prefix, like '1:ethernet', '2:ethernet', '3:fddi'. =cut # # snmpwalk. # sub snmpwalk ($@) { my($host, @vars) = @_; return(&snmpwalk_flg($host, undef, @vars)); } =head2 snmpset() - send a SNMP set-request to the remote agent @result = snmpset( [community@]host[:port[:timeout[:retries[:backoff[:version]]]]], [\%param_hash], $oid1, $type1, $value1, [$oid2, $type2, $value2 ...] ); This function is used to modify data on the remote agent using a SNMP set-request. The message is built using the list of values consisting of groups of an OBJECT IDENTIFIER, an object type, and the actual value to be set. The object type can be one of the following strings: integer | int string | octetstring | octet string oid | object id | object identifier ipaddr | ip addr4ess timeticks uint | uinteger | uinteger32 | unsigned int | unsigned integer | unsigned integer32 counter | counter 32 counter64 gauge | gauge32 The object type may also be an octet corresponding to the ASN.1 type. See the Net::SNMP documentation for more information. The requested values are returned in an array in the same order as they were requested. In scalar context the first requested value is returned. =cut # # snmpset. # sub snmpset($@) { my($host, @vars) = @_; my($session, @vals, %args, $ret); my($oid, $type, $value, @enoid, @retvals); @retvals = (); $session = &snmpopen($host, 0, \@vars); if (!defined($session)) { carp "SNMPSET Problem for $host" unless ($Net_SNMP_util::SuppressWarnings > 1); return wantarray ? @retvals : undef; } if ($Net_SNMP_util::Version > 2) { $args{'-contextengineid'} = $Net_SNMP_util::ContextEngineID if (defined($Net_SNMP_util::ContextEngineID)); $args{'-contextname'} = $Net_SNMP_util::ContextName if (defined($Net_SNMP_util::ContextName)); } while(@vars) { ($oid) = toOID((shift @vars)); $ret = shift @vars; $value = shift @vars; $type = ASNtype($ret); if (!defined($type)) { carp "Unknown SNMP type: $type\n" unless ($Net_SNMP_util::SuppressWarnings > 1); } push @vals, $oid, $type, $value; push @enoid, $oid; } if ($#vals < 0) { return wantarray ? @retvals : undef; } $args{'-varbindlist'} = \@vals; $ret = $session->set_request(%args); if ($ret) { foreach $oid (@enoid) { push @retvals, $ret->{$oid} if (exists($ret->{$oid})); } return wantarray ? @retvals : $retvals[0]; } $ret = join(' ', @enoid); error_msg("SNMPSET Problem for $ret on ${host}: " . $session->error()); return wantarray ? @retvals : undef; } =head2 snmptrap() - send a SNMP trap to the remote manager @result = snmptrap( [community@]host[:port[:timeout[:retries[:backoff[:version]]]]], $enterprise, $agentaddr, $generictrap, $specifictrap, [\%param_hash], $oid1, $type1, $value1, [$oid2, $type2, $value2 ...] ); This function sends a SNMP trap to the remote manager on the host specified. The message is built using the list of values consisting of groups of an OBJECT IDENTIFIER, an object type, and the actual value to be set. The object type can be one of the following strings: integer | int string | octetstring | octet string oid | object id | object identifier ipaddr | ip addr4ess timeticks uint | uinteger | uinteger32 | unsigned int | unsigned integer | unsigned integer32 counter | counter 32 counter64 gauge | gauge32 The object type may also be an octet corresponding to the ASN.1 type. See the Net::SNMP documentation for more information. A true value is returned if sending the trap is successful. The undefined value is returned when a failure has occurred. When the trap is sent as SNMPv2c, the B<$enterprise>, B<$agentaddr>, B<$generictrap>, and B<$specifictrap> arguments are ignored. Furthermore, the first two (oid, type, value) tuples should be: =over =item * sysUpTime.0 - ('1.3.6.1.2.1.1.3.0', 'timeticks', $timeticks) =item * snmpTrapOID.0 - ('1.3.6.1.6.3.1.1.4.1.0', 'oid', $oid) =back B This function can only be used when the SNMP version is set to SNMPv1 or SNMPv2c. =cut # # Send an SNMP trap # sub snmptrap($$$$$@) { my($host, $ent, $agent, $gen, $spec, @vars) = @_; my($oid, $type, $value, $ret, @enoid, @vals); my($session, %args); $session = &snmpopen($host, 1, \@vars); if (!defined($session)) { carp "SNMPTRAP Problem for $host" unless ($Net_SNMP_util::SuppressWarnings > 1); return undef; } if ($Net_SNMP_util::Version == 1) { $args{'-enterprise'} = $ent if (defined($ent) and (length($ent) > 0)); $args{'-agentaddr'} = $agent if (defined($agent) and (length($agent) > 0)); $args{'-generictrap'} = $gen if (defined($gen) and (length($gen) > 0)); $args{'-specifictrap'} = $spec if (defined($spec) and (length($spec) > 0)); } elsif ($Net_SNMP_util::Version > 2) { carp "SNMPTRAP Problem for $host : must use SNMP version 1 or 2" unless ($Net_SNMP_util::SuppressWarnings > 1); } while(@vars) { ($oid) = toOID((shift @vars)); $ret = shift @vars; $value = shift @vars; $type = ASNtype($ret); if (!defined($type)) { carp "unknown SNMP type: $type" unless ($Net_SNMP_util::SuppressWarnings > 1); } push @vals, $oid, $type, $value; push @enoid, $oid; } return undef unless defined $vals[0]; $args{'-varbindlist'} = \@vals; if ($Net_SNMP_util::Version == 1) { $ret = $session->trap_request(%args); } else { $ret = $session->snmpv2_trap(%args); } if (!$ret) { $ret = join(' ', @enoid); error_msg("SNMPTRAP Problem for $ret on ${host}: " . $session->error()); } return $ret; } =head2 snmpmaptable() - walk OBJECT IDENTIFIER tree(s) on the remote agent $result = snmpmaptable( [community@]host[:port[:timeout[:retries[:backoff[:version]]]]], \&function, [\%param_hash], @oids ); This function performs a sequence of SNMP get-next-request or get-bulk-request (if the SNMP version is 2 or higher) queries to gather data from the remote agent on the host specified. The initial message is built using the list of OBJECT IDENTIFIERs passed as an array. Each OBJECT IDENTIFIER is placed into a single SNMP GetNextRequest-PDU in the same order that it held in the original list. Queries continue until all the returned OBJECT IDENTIFIERs are no longer a child of the base OBJECT IDENTIFIERs. The OBJECT IDENTIFIERs must correspond to column entries for a conceptual row in a table. They may however be columns in different tables as long as each table is indexed the same way. =over =item * The B<\&function> argument will be called once per row of the table. It will be passed the row index as a partial OBJECT IDENTIFIER in dotted notation, e.g. "1.3" or "10.0.1.34", and the values of the requested table columns in that row. =back The number of rows in the table is returned on success. The undefined value is returned when a failure has occurred. =cut # # walk a table, calling a user-supplied function for each # column of a table. # sub snmpmaptable($$@) { my($host, $fun, @vars) = @_; return snmpmaptable4($host, $fun, 0, @vars); } =head2 snmpmaptable4() - walk OBJECT IDENTIFIER tree(s) on the remote agent $result = snmpmaptable4( [community@]host[:port[:timeout[:retries[:backoff[:version]]]]], \&function, $maxrepetitions, [\%param_hash], @oids ); This function performs a sequence of SNMP get-next-request or get-bulk-request (if the SNMP version is 2 or higher) queries to gather data from the remote agent on the host specified. The initial message is built using the list of OBJECT IDENTIFIERs passed as an array. Each OBJECT IDENTIFIER is placed into a single SNMP GetNextRequest-PDU in the same order that it held in the original list. Queries continue until all the returned OBJECT IDENTIFIERs are no longer a child of the base OBJECT IDENTIFIERs. The OBJECT IDENTIFIERs must correspond to column entries for a conceptual row in a table. They may however be columns in different tables as long as each table is indexed the same way. =over =item * The B<\&function> argument will be called once per row of the table. It will be passed the row index as a partial OBJECT IDENTIFIER in dotted notation, e.g. "1.3" or "10.0.1.34", and the values of the requested table columns in that row. =item * The B<$maxrepetitions> argument specifies the number of rows to be returned by a single get-bulk-request. If it is null or undefined, the default value of 12 is used. =back The number of rows in the table is returned on success. The undefined value is returned when a failure has occurred. =cut sub snmpmaptable4($$$@) { my($host, $fun, $max_reps, @vars) = @_; my($session, @enoid, %args, $ret); my($oid, $soid, $toid, $inst, @row, $nr); $session = &snmpopen($host, 0, \@vars); if (!defined($session)) { carp "SNMPMAPTABLE Problem for $host" unless ($Net_SNMP_util::SuppressWarnings > 1); return undef; } @enoid = toOID(@vars); return undef unless defined $enoid[0]; if ($Net_SNMP_util::Version > 1) { $max_reps = $Net_SNMP_util::MaxRepetitions if ($max_reps <= 0); $args{'-maxrepetitions'} = $max_reps; } if ($Net_SNMP_util::Version > 2) { $args{'-contextengineid'} = $Net_SNMP_util::ContextEngineID if (defined($Net_SNMP_util::ContextEngineID)); $args{'-contextname'} = $Net_SNMP_util::ContextName if (defined($Net_SNMP_util::ContextName)); } $args{'-columns'} = \@enoid; $ret = $session->get_entries(%args); if ($ret) { $soid = $enoid[0]; $nr = 0; foreach $oid (&Net::SNMP::oid_lex_sort(keys %$ret)) { if (&Net::SNMP::oid_base_match($soid, $oid)) { $inst = substr($oid, length($soid)+1); undef @row; foreach $toid (@enoid) { push @row, $ret->{$toid . "." . $inst}; } &$fun($inst, @row); $nr++; } else { return($nr) if ($nr > 0); } } return($nr); } else { $ret = join(' ', @vars); error_msg("SNMPMAPTABLE Problem for $ret on ${host}: " . $session->error()); return undef; } } =head2 snmpwalkhash() - send a SNMP get-next-request to the remote agent @result = snmpwalkhash( [community@]host[:port[:timeout[:retries[:backoff[:version]]]]], \&function(), [\%param_hash], @oids, [\%hash] ); This function performs a sequence of SNMP get-next-request or get-bulk-request (if the SNMP version is 2 or higher) queries to gather data from the remote agent on the host specified. The message is built using the list of OBJECT IDENTIFIERs passed as an array. Each OBJECT IDENTIFIER is placed into a single SNMP GetNextRequest-PDU in the same order that it held in the original list. Queries continue until all the returned OBJECT IDENTIFIERs are outside of the tree specified by the initial OBJECT IDENTIFIERs. The B<\&function> is called once for every returned value. It is passed a reference to a hash, the hostname, the textual OBJECT IDENTIFIER, the dotted-numberic OBJECT IDENTIFIER, the instance, the value and the requested textual OBJECT IDENTIFIER. That function can customize the result so the values can be extracted later by hosts, by oid_names, by oid_numbers, by instances... like these: $hash{$host}{$name}{$inst} = $value; $hash{$host}{$oid}{$inst} = $value; $hash{$name}{$inst} = $value; $hash{$oid}{$inst} = $value; $hash{$oid . '.' . $ints} = $value; $hash{$inst} = $value; ... If the last argument to B is a reference to a hash, that hash reference is passed to the passed-in function instead of a local hash reference. That way the function can look up other objects unrelated to the current invocation of B. The snmpwalkhash routine returns the hash. =cut # # Walk the MIB, putting everything you find into hashes. # sub snmpwalkhash($$@) { # my($host, $hash_sub, @vars) = @_; return(&snmpwalk_flg( @_ )); } =head2 snmpmapOID() - add texual OBJECT INDENTIFIER mapping snmpmapOID( $text1, $oid1, [ $text2, $oid2 ...] ); This routine adds entries to the table that maps textual representation of OBJECT IDENTIFIERs to their dotted notation. For example, snmpmapOID('ciscoCPU', '1.3.6.1.4.1.9.9.109.1.1.1.1.5.1'); allows the string 'ciscoCPU' to be used as an OBJECT IDENTIFIER in any SNMP query routine. This routine doesn't return anything. =cut # # Add passed-in text, OID pairs to the OID mapping table. # sub snmpmapOID(@) { my(@vars) = @_; my($oid, $txt); $Net_SNMP_util::ErrorMessage = ''; while($#vars >= 0) { $txt = shift @vars; $oid = shift @vars; next unless($txt =~ /^[a-zA-Z][\w\-]*(\.[a-zA-Z][\w\-])*$/); next unless($oid =~ /^\d+(\.\d+)*$/); $Net_SNMP_util::OIDS{$txt} = $oid; $RevNeeded = 1; print "snmpmapOID: $txt => $oid\n" if $Net_SNMP_util::Debug; } return undef; } =head2 snmpLoad_OID_Cache() - Read a file of cached OID mappings $result = snmpLoad_OID_Cache( $file ); This routine opens the file named by the B<$file> argument and reads it. The file should contain text, OBJECT IDENTIFIER pairs, one pair per line. It adds the pairs as entries to the table that maps textual representation of OBJECT IDENTIFIERs to their dotted notation. Blank lines and anything after a '#' or between '--' is ignored. This routine returns 0 on success and -1 if the B<$file> could not be opened. =cut # # Open the passed-in file name and read it in to populate # the cache of text-to-OID map table. It expects lines # with two fields, the first the textual string like "ifInOctets", # and the second the OID value, like "1.3.6.1.2.1.2.2.1.10". # # blank lines and anything after a '#' or between '--' is ignored. # sub snmpLoad_OID_Cache ($) { my($arg) = @_; my($txt, $oid); $Net_SNMP_util::ErrorMessage = ''; if (!open(CACHE, $arg)) { error_msg("snmpLoad_OID_Cache: Can't open ${arg}: $!"); return -1; } while() { s/#.*//; # '#' starts a comment s/--.*?--/ /g; # comment delimited by '--', like MIBs s/--.*//; # comment started by '--' next if (/^$/); next unless (/\s/); # must have whitespace as separator chomp; ($txt, $oid) = split(' ', $_, 2); $txt = $1 if ($txt =~ /^[\'\"](.*)[\'\"]/); $oid = $1 if ($oid =~ /^[\'\"](.*)[\'\"]/); if (($txt =~ /^\.?\d+(\.\d+)*\.?$/) and ($oid !~ /^\.?\d+(\.\d+)*\.?$/)) { my($a) = $oid; $oid = $txt; $txt = $a; } $oid =~ s/^\.//; $oid =~ s/\.$//; &snmpmapOID($txt, $oid); } close(CACHE); return 0; } =head2 snmpMIB_to_OID() - Read a MIB file for textual OID mappings $result = snmpMIB_to_OID( $file ); This routine opens the file named by the B<$file> argument and reads it. The file should be an SNMP Management Information Base (MIB) file that describes OBJECT IDENTIFIERs supported by an SNMP agent. per line. It adds the textual representation of the OBJECT IDENTIFIERs to the text-to-OID mapping table. This routine returns the number of entries added to the table or -1 if the B<$file> could not be opened. =cut # # Read in the passed MIB file, parsing it # for their text-to-OID mappings # sub snmpMIB_to_OID ($) { my($arg) = @_; my($cnt, $quote, $buf, %tOIDs, $tgot); my($var, @parts, $strt, $indx, $ind, $val); $Net_SNMP_util::ErrorMessage = ''; if (!open(MIB, $arg)) { error_msg("snmpMIB_to_OID: Can't open ${arg}: $!"); return -1; } print "snmpMIB_to_OID: loading $arg\n" if $Net_SNMP_util::Debug; $cnt = 0; $quote = 0; $tgot = 0; $buf = ''; while() { if ($quote) { next unless /"/; $quote = 0; } chomp; $buf .= ' ' . $_; $buf =~ s/"[^"]*"//g; # throw away quoted strings $buf =~ s/--.*?--/ /g; # throw away comments (-- anything --) $buf =~ s/--.*//; # throw away comments (-- anything to EOL) $buf =~ s/\s+/ /g; # clean up multiple spaces if ($buf =~ /"/) { $quote = 1; next; } if ($buf =~ /DEFINITIONS *::= *BEGIN/) { $cnt += MIB_fill_OID(\%tOIDs) if ($tgot); $buf = ''; %tOIDs = (); $tgot = 0; next; } $buf =~ s/OBJECT-TYPE/OBJECT IDENTIFIER/; $buf =~ s/OBJECT-IDENTITY/OBJECT IDENTIFIER/; $buf =~ s/OBJECT-GROUP/OBJECT IDENTIFIER/; $buf =~ s/MODULE-IDENTITY/OBJECT IDENTIFIER/; $buf =~ s/NOTIFICATION-TYPE/OBJECT IDENTIFIER/; $buf =~ s/ IMPORTS .*\;//; $buf =~ s/ SEQUENCE *{.*}//; $buf =~ s/ SYNTAX .*//; $buf =~ s/ [\w\-]+ *::= *OBJECT IDENTIFIER//; $buf =~ s/ OBJECT IDENTIFIER.*::= *{/ OBJECT IDENTIFIER ::= {/; if ($buf =~ / ([\w\-]+) OBJECT IDENTIFIER *::= *{([^}]+)}/) { $var = $1; $buf = $2; $buf =~ s/ +$//; $buf =~ s/\s+\(/\(/g; # remove spacing around '(' $buf =~ s/\(\s+/\(/g; $buf =~ s/\s+\)/\)/g; # remove spacing before ')' @parts = split(' ', $buf); $strt = ''; foreach $indx (@parts) { if ($indx =~ /([\w\-]+)\((\d+)\)/) { $ind = $1; $val = $2; if (exists($tOIDs{$strt})) { $tOIDs{$ind} = $tOIDs{$strt} . '.' . $val; } elsif ($strt ne '') { $tOIDs{$ind} = "${strt}.${val}"; } else { $tOIDs{$ind} = $val; } $strt = $ind; $tgot = 1; } elsif ($indx =~ /^\d+$/) { if (exists($tOIDs{$strt})) { $tOIDs{$var} = $tOIDs{$strt} . '.' . $indx; } else { $tOIDs{$var} = "${strt}.${indx}"; } $tgot = 1; } else { $strt = $indx; } } $buf = ''; } } $cnt += MIB_fill_OID(\%tOIDs) if ($tgot); $RevNeeded = 1 if ($cnt > 0); return $cnt; } =head2 snmpQueue_MIB_File() - queue a MIB file for reading "on demand" snmpQueue_MIB_File( $file1, [$file2, ...] ); This routine queues the list of SNMP MIB files for later processing. Whenever a text-to-OBJECT IDENTIFIER lookup fails, the list of queued MIB files is consulted. If it isn't empty, the first MIB file in the list is removed and passed to B. The lookup is attempted again, and if that still fails the next MIB file in the list is removed and passed to B. This process continues until the lookup succeeds or the list is exhausted. This routine doesn't return anything. =cut # # Save the passed-in list of MIB files until an OID can't be # found in the existing table. At that time the MIB file will # be loaded, and the lookup attempted again. # sub snmpQueue_MIB_File (@) { my(@files) = @_; my($file); $Net_SNMP_util::ErrorMessage = ''; foreach $file (@files) { push(@Net_SNMP_util::MIB_Files, $file); } } # [private methods] ------------------------------------- # # Start an snmp session # sub snmpopen ($$$) { my($host, $type, $vars) = @_; my($nhost, $port, $community, $lhost, $lport, $nlhost); my($timeout, $retries, $backoff, $version, $v4onlystr); my($opts, %args, $tmp, $sess); my($debug, $maxmsgsize); $type = 0 if (!defined($type)); $community = "public"; $nlhost = ""; ($community, $host) = ($1, $2) if ($host =~ /^(.*)@([^@]+)$/); # We can't split on the : character because a numeric IPv6 # address contains a variable number of :'s if( ($host =~ /^(\[.*\]):(.*)$/) or ($host =~ /^(\[.*\])$/) ) { # Numeric IPv6 address between [] ($host, $opts) = ($1, $2); } else { # Hostname or numeric IPv4 address ($host, $opts) = split(':', $host, 2); } ($port, $timeout, $retries, $backoff, $version, $v4onlystr) = split(':', $opts, 6) if(defined($opts) and (length $opts > 0) ); undef($timeout) if (defined($timeout) and length($timeout) <= 0); undef($retries) if (defined($retries) and length($retries) <= 0); undef($backoff) if (defined($backoff) and length($backoff) <= 0); undef($version) if (defined($version) and length($version) <= 0); $v4onlystr = "" unless defined $v4onlystr; if (defined($port) and ($port =~ /^([^!]*)!(.*)$/)) { ($port, $lhost) = ($1, $2); $nlhost = $lhost; ($lhost, $lport) = ($1, $2) if ($lhost =~ /^(.*)!(.*)$/); undef($lport) if (defined($lport) and (length($lport) <= 0)); } undef($port) if (defined($port) and length($port) <= 0); if (ref $vars->[0] eq 'HASH') { undef($debug); undef($maxmsgsize); undef $Net_SNMP_util::ContextEngineID; undef $Net_SNMP_util::ContextName; $opts = shift @$vars; foreach $type (keys %$opts) { if ($type =~ /^-?return_array_refs$/i) { $Net_SNMP_util::ReturnArrayRefs = $opts->{$type}; } elsif ($type =~ /^-?return_hash_refs$/i) { $Net_SNMP_util::ReturnHashRefs = $opts->{$type}; } elsif ($type =~ /^-?contextengineid$/i) { $Net_SNMP_util::ContextEngineID = $opts->{$type}; } elsif ($type =~ /^-?contextname$/i) { $Net_SNMP_util::ContextName = $opts->{$type}; } elsif ($type =~ /^-?maxrepetitions$/i) { $Net_SNMP_util::MaxRepetitions = $opts->{$type}; } elsif ($type =~ /^-?default_max_repetitions$/i) { $Net_SNMP_util::MaxRepetitions = $opts->{$type}; } elsif ($type =~ /^-?version$/i) { $version = $opts->{$type}; } elsif ($type =~ /^-?port$/i) { $port = $opts->{$type}; } elsif ($type =~ /^-?localaddr$/i) { $lhost = $opts->{$type}; } elsif ($type =~ /^-?community$/i) { $community = $opts->{$type}; } elsif ($type =~ /^-?timeout$/i) { $timeout = $opts->{$type}; } elsif ($type =~ /^-?retries$/i) { $retries = $opts->{$type}; } elsif ($type =~ /^-?maxmsgsize$/i) { $maxmsgsize = $opts->{$type}; } elsif ($type =~ /^-?debug$/i) { $debug = $opts->{$type}; } elsif ($type =~ /^-?backoff$/i) { next; # XXXX not implemented in Net::SNMP } elsif ($type =~ /^-?avoid_negative_request_ids$/i) { next; # XXXX not implemented in Net::SNMP } elsif ($type =~ /^-?lenient_source_/i) { next; # XXXX not implemented in Net::SNMP } elsif ($type =~ /^-?use_16bit_request_ids$/i) { next; # XXXX not implemented in Net::SNMP } elsif ($type =~ /^-?use_getbulk$/i) { next; # XXXX not implemented in Net::SNMP } else { $tmp = $type; $tmp = '-' . $tmp unless ($tmp =~ /^-/); $args{$tmp} = $opts->{$type}; } } } $port = 162 if ($type == 1 and !defined($port)); $nhost = "$community\@$host"; $nhost .= ":" . $port if (defined($port)); undef($lhost) if (defined($lhost) and (length($lhost) <= 0)); $version = '1' unless defined $version; if ($version =~ /1/) { $version = 1; } elsif ($version =~ /2/) { $version = 2; } elsif ($version =~ /3/) { $version = 3; } $Net_SNMP_util::ErrorMessage = ''; if ((!defined($Net_SNMP_util::Session)) or ($Net_SNMP_util::Host ne $nhost) or ($Net_SNMP_util::Version ne $version) or ($Net_SNMP_util::LHost ne $nlhost) or ($Net_SNMP_util::IPv4only ne $v4onlystr)) { if (defined($Net_SNMP_util::Session)) { $Net_SNMP_util::Session->close(); undef $Net_SNMP_util::Session; undef $Net_SNMP_util::Host; undef $Net_SNMP_util::Version; undef $Net_SNMP_util::LHost; undef $Net_SNMP_util::IPv4only; } $args{'-hostname'} = $host; $args{'-port'} = $port if (defined($port)); $args{'-localaddr'} = $lhost if (defined($lhost)); $args{'-localport'} = $lport if (defined($lport)); $args{'-version'} = $version; $args{'-domain'} = "udp/ipv4" if (length($v4onlystr) > 0); $args{'-timeout'} = $timeout if (defined($timeout)); $args{'-retries'} = $retries if (defined($retries)); $args{'-maxmsgsize'} = $maxmsgsize if (defined($maxmsgsize)); $args{'-debug'} = $debug if (defined($debug)); $args{'-community'} = $community unless ($community eq "public"); if ($version == 3) { delete $args{'-community'} } else { delete $args{'-username'}; delete $args{'-authkey'}; delete $args{'-authpassword'}; delete $args{'-authprotocol'}; delete $args{'-privkey'}; delete $args{'-privpassword'}; delete $args{'-privprotocol'}; } ($sess, $tmp) = Net::SNMP->session(%args); if (defined($sess)) { $Net_SNMP_util::Session = $sess; $Net_SNMP_util::Host = $nhost; $Net_SNMP_util::Version = $version; $Net_SNMP_util::LHost = $nlhost; $Net_SNMP_util::IPv4only = $v4onlystr; } else { error_msg("SNMPopen failed: $tmp\n"); return(undef); } return $Net_SNMP_util::Session; } else { $Net_SNMP_util::Session->timeout($timeout) if (defined($timeout) and (length($timeout) > 0)); $Net_SNMP_util::Session->retries($retries) if (defined($retries) and (length($retries) > 0)); $Net_SNMP_util::Session->maxmsgsize($maxmsgsize) if (defined($maxmsgsize) and (length($maxmsgsize) > 0)); $Net_SNMP_util::Session->debug($debug) if (defined($debug) and (length($debug) > 0)); $Net_SNMP_util::Session->{_context_engine_id} = undef if (!defined($Net_SNMP_util::ContextEngineID)); $Net_SNMP_util::Session->{_context_name} = undef if (!defined($Net_SNMP_util::ContextName)); } return $Net_SNMP_util::Session; } # # Given an OID in either ASN.1 or mixed text/ASN.1 notation, return an OID. # sub toOID(@) { my(@vars) = @_; my($oid, $var, $tmp, $tmpv, @retvar); @retvar = (); foreach $var (@vars) { ($oid, $tmp) = &Check_OID($var); if (!$oid and $Net_SNMP_util::CacheLoaded == 0) { $tmp = $Net_SNMP_util::SuppressWarnings; $Net_SNMP_util::SuppressWarnings = 1000; &snmpLoad_OID_Cache($Net_SNMP_util::CacheFile); $Net_SNMP_util::CacheLoaded = 1; $Net_SNMP_util::SuppressWarnings = $tmp; ($oid, $tmp) = &Check_OID($var); } while (!$oid and $#Net_SNMP_util::MIB_Files >= 0) { $tmp = $Net_SNMP_util::SuppressWarnings; $Net_SNMP_util::SuppressWarnings = 1000; snmpMIB_to_OID(shift(@Net_SNMP_util::MIB_Files)); $Net_SNMP_util::SuppressWarnings = $tmp; ($oid, $tmp) = &Check_OID($var); if ($oid) { open(CACHE, ">>$Net_SNMP_util::CacheFile"); print CACHE "$tmp\t$oid\n"; close(CACHE); } } if ($oid) { $var =~ s/^$tmp/$oid/; } else { carp("Unknown SNMP var $var\n") unless ($Net_SNMP_util::SuppressWarnings > 1); next; } while ($var =~ /\"([^\"]*)\"/) { $tmp = sprintf("%d.%s", length($1), join(".", map(ord, split(//, $1)))); $var =~ s/\"$1\"/$tmp/; } print "toOID: $var\n" if $Net_SNMP_util::Debug; push(@retvar, $var); } return @retvar; } # # Check to see if an OID is in the text-to-OID cache. # Returns the OID and the corresponding text as two separate # elements. # sub Check_OID ($) { my($var) = @_; my($tmp, $tmpv, $oid); if ($var =~ /^[a-zA-Z][\w\-]*(\.[a-zA-Z][\w\-]*)*/) { $tmp = $&; $tmpv = $tmp; for (;;) { last if exists($Net_SNMP_util::OIDS{$tmpv}); last if !($tmpv =~ s/^[^\.]*\.//); } $oid = $Net_SNMP_util::OIDS{$tmpv}; if ($oid) { return ($oid, $tmp); } else { my @empty = (); return @empty; } } return ($var, $var); } sub snmpwalk_flg ($$@) { my($host, $hash_sub, @vars) = @_; my($session, %args, @enoid, @poid, $toid, $oid, $got); my($val, $ret, %soid, %nsoid, @retvals, $tmp); my(%rethash, $h_ref, @tmprefs); my($stop); $h_ref = (ref $vars[$#vars] eq "HASH") ? pop(@vars) : \%rethash; $session = &snmpopen($host, 0, \@vars); if (!defined($session)) { carp "SNMPWALK Problem for $host" unless ($Net_SNMP_util::SuppressWarnings > 1); if (defined($hash_sub)) { return ($h_ref) if ($SNMP_util::Return_hash_refs); return (%$h_ref); } else { @retvals = (); return (@retvals); } } @enoid = toOID(@vars); if ($#enoid < 0) { if (defined($hash_sub)) { return ($h_ref) if ($SNMP_util::Return_hash_refs); return (%$h_ref); } else { @retvals = (); return (@retvals); } } # # Create/Refresh a reversed hash with oid -> name # if (defined($hash_sub) and ($RevNeeded)) { %revOIDS = reverse %Net_SNMP_util::OIDS; $RevNeeded = 0; } # # Create temporary array of refs to return values # foreach $oid (0..$#enoid) { my $tmparray = []; $tmprefs[$oid] = $tmparray; $nsoid{$oid} = $oid; } $got = 0; @poid = @enoid; if ($Net_SNMP_util::Version > 1 and $Net_SNMP_util::MaxRepetitions > 0) { $args{'-maxrepetitions'} = $Net_SNMP_util::MaxRepetitions; } if ($Net_SNMP_util::Version > 2) { $args{'-contextengineid'} = $Net_SNMP_util::ContextEngineID if (defined($Net_SNMP_util::ContextEngineID)); $args{'-contextname'} = $Net_SNMP_util::ContextName if (defined($Net_SNMP_util::ContextName)); } while($#poid >= 0) { $args{'-varbindlist'} = \@poid; if (($Net_SNMP_util::Version > 1) and ($Net_SNMP_util::MaxRepetitions > 1)) { $ret = $session->get_bulk_request(%args); } else { $ret = $session->get_next_request(%args); } last if (!defined($ret)); %soid = %nsoid; undef %nsoid; $stop = 0; foreach $oid (&Net::SNMP::oid_lex_sort(keys %$ret)) { $got = 1; $tmp = -1; foreach $toid (@enoid) { $tmp++; if (&Net::SNMP::oid_base_match($toid, $oid) and (!exists($soid{$toid}) or ($oid ne $soid{$toid}))) { $nsoid{$toid} = $oid; if (defined($hash_sub)) { # # extract name of the oid, if possible, the rest becomes the # instance # my $inst = ""; my $upo = $toid; while (!exists($revOIDS{$upo}) and length($upo)) { $upo =~ s/(\.\d+?)$//; if (defined($1) and length($1)) { $inst = $1 . $inst; } else { $upo = ""; last; } } if (length($upo) and exists($revOIDS{$upo})) { $upo = $revOIDS{$upo} . $inst; } else { $upo = $toid; } my $qoid = $oid; my $tmpo; $inst = ""; while (!exists($revOIDS{$qoid}) and length($qoid)) { $qoid =~ s/(\.\d+?)$//; if (defined($1) and length($1)) { $inst = $1 . $inst; } else { $qoid = ""; last; } } if (length($qoid) and exists($revOIDS{$qoid})) { $tmpo = $qoid; $qoid = $revOIDS{$qoid}; } else { $qoid = $oid; $tmpo = $toid; $inst = substr($oid, length($tmpo)+1); } # # call hash_sub # &$hash_sub($h_ref, $host, $qoid, $tmpo, $inst, $ret->{$oid}, $upo); } else { my $tmpo; my $tmpv = $ret->{$oid}; $tmpo = substr($oid, length($toid)+1); push @{$tmprefs[$tmp]}, "$tmpo:$tmpv"; } } else { $stop = 1 if ($#enoid == 0); } } } undef @poid; @poid = values %nsoid if (!$stop); } if ($got) { if (defined($hash_sub)) { return ($h_ref) if ($Net_SNMP_util::ReturnHashRefs); return (%$h_ref); } elsif ($Net_SNMP_util::Return_array_refs) { return (@tmprefs); } else { do { $got = 0; foreach $toid (0..$#enoid) { next if (scalar(@{$tmprefs[$toid]}) <= 0); $got = 1; $oid = shift(@{$tmprefs[$toid]}); if ($#enoid > 0) { ($oid, $val) = split(':', $oid, 2); $oid = $enoid[$toid] . '.' . $oid; push(@retvals, "$oid:$val"); } else { push(@retvals, $oid); } } } while($got); return (@retvals); } } else { $ret = join(' ', @vars); error_msg("SNMPWALK Problem for $ret on ${host}: " . $session->error()); if (defined($hash_sub)) { return ($h_ref) if ($SNMP_util::Return_hash_refs); return (%$h_ref); } else { @retvals = (); return (@retvals); } } } # # When passed a string, return the ASN.1 type that corresponds to the # string. # sub ASNtype($) { my($type) = @_; $type =~ tr/A-Z/a-z/; if ($type eq "int") { $type = 0x02; } elsif ($type eq "integer") { $type = 0x02; } elsif ($type eq "string") { $type = 0x04; } elsif ($type eq "octetstring") { $type = 0x04; } elsif ($type eq "octet string") { $type = 0x04; } elsif ($type eq "oid") { $type = 0x06; } elsif ($type eq "object id") { $type = 0x06; } elsif ($type eq "object identifier") { $type = 0x06; } elsif ($type eq "ipaddr") { $type = 0x40; } elsif ($type eq "ip address") { $type = 0x40; } elsif ($type eq "timeticks") { $type = 0x43; } elsif ($type eq "uint") { $type = 0x47; } elsif ($type eq "uinteger") { $type = 0x47; } elsif ($type eq "uinteger32") { $type = 0x47; } elsif ($type eq "unsigned int") { $type = 0x47; } elsif ($type eq "unsigned integer") { $type = 0x47; } elsif ($type eq "unsigned integer32") { $type = 0x47; } elsif ($type eq "counter") { $type = 0x41; } elsif ($type eq "counter32") { $type = 0x41; } elsif ($type eq "counter64") { $type = 0x46; } elsif ($type eq "gauge") { $type = 0x42; } elsif ($type eq "gauge32") { $type = 0x42; } elsif (($type <= 0) or ($type > 255)) { return undef; } return $type; } # # set the ErrorMessage global and print an error message # sub error_msg($) { my($msg) = @_; $Net_SNMP_util::ErrorMessage = $msg; if ($Net_SNMP_util::SuppressWarnings <= 1) { $Carp::CarpLevel++; carp($msg); $Carp::CarpLevel--; } } # # Fill the OIDS hash with results from the MIB parsing # sub MIB_fill_OID($) { my($href) = @_; my($cnt, $changed, @del, $var, $val, @parts, $indx); my(%seen); $cnt = 0; do { $changed = 0; @del = (); foreach $var (keys %$href) { $val = $href->{$var}; @parts = split('\.', $val); $val = ''; foreach $indx (@parts) { if ($indx =~ /^\d+$/) { $val .= '.' . $indx; } else { if (exists($Net_SNMP_util::OIDS{$indx})) { $val = $Net_SNMP_util::OIDS{$indx}; } else { $val .= '.' . $indx; } } } if ($val =~ /^[\d\.]+$/) { $val =~ s/^\.+//; if (!exists($Net_SNMP_util::OIDS{$var}) || (length($val) > length($Net_SNMP_util::OIDS{$var}))) { $Net_SNMP_util::OIDS{$var} = $val; print "'$var' => '$val'\n" if $Net_SNMP_util::Debug; $changed = 1; $cnt++; } push @del, $var; } } foreach $var (@del) { delete $href->{$var}; } } while($changed); $Carp::CarpLevel++; foreach $var (sort keys %$href) { $val = $href->{$var}; $val =~ s/\..*//; next if (exists($seen{$val})); $seen{$val} = 1; $seen{$var} = 1; error_msg( "snmpMIB_to_OID: prefix \"$val\" unknown, load the parent MIB first.\n" ); } $Carp::CarpLevel--; return $cnt; } # [documentation] ------------------------------------------------------------ =head1 EXPORTS The Net_SNMP_util module uses the F module to export useful constants and subroutines. These exportable symbols are defined below and follow the rules and conventions of the F module (see L). =over =item Exportable &snmpget, &snmpgetnext, &snmpgetbulk, &snmpwalk, &snmpset, &snmptrap, &snmpmaptable, &snmpmaptable4, &snmpwalkhash, &snmpmapOID, &snmpMIB_to_OID, &snmpLoad_OID_Cache, &snmpQueue_MIB_File, ErrorMessage =back =head1 EXAMPLES =head2 1. SNMPv1 get-request for sysUpTime This example gets the sysUpTime from a remote host. #! /usr/local/bin/perl use strict; use Net_SNMP_util; my ($host, $ret) $host = shift || 'localhost'; $ret = snmpget($host, 'sysUpTime'); print("sysUpTime for $host is $ret\n"); exit 0; =head2 2. SNMPv3 set-request of sysContact This example sets the sysContact information on the remote host to "Help Desk x911". The parameters passed to the snmpset function are for the demonstration of syntax only. These parameters will need to be set according to the SNMPv3 parameters of the remote host used by the script. #! /usr/local/bin/perl use strict; use Net_SNMP_util; my($host, %v3hash, $ret); $host = shift || 'localhost'; $v3hash{'-version'} = 'snmpv3'; $v3hash{'-username'} = 'myv3Username'; $v3hash{'-authkey'} = '0x05c7fbde31916f64da4d5b77156bdfa7'; $v3hash{'-authprotocol'} = 'md5'; $v3hash{'-privkey'} = '0x93725fd3a02a48ce02df4e065a1c1746'; $ret = snmpset($host, \%v3hash, 'sysContact', 'string', 'Help Desk x911'); print "sysContact on $host is now $ret\n"; exit 0; =head2 3. SNMPv2c walk for ifTable This example gets the contents of the ifTable by sending get-bulk-requests until the responses are no longer part of the ifTable. The ifTable can also be retrieved using C. #! /usr/local/bin/perl use strict; use Net_SNMP_util; my($host, @ret, $oid, $val); $host = shift || 'localhost'; @ret = snmpwalk($host . ':::::2', 'ifTable'); foreach $val (@ret) { ($oid, $val) = split(':', $val, 2); print "$oid => $val\n"; } exit 0; =head2 4. SNMPv2c maptable collecting ifDescr, ifInOctets, and ifOutOctets. This example collects a table containing the columns ifDescr, ifInOctets, and ifOutOctets. A printing function is called once per row. #! /usr/local/bin/perl use strict; use Net_SNMP_util; sub printfun($$$$) { my($inst, $desc, $in, $out) = @_; printf "%3d %-52.52s %10d %10d\n", $inst, $desc, $in, $out; } my($host, @ret); $host = shift || 'localhost'; printf "%-3s %-52s %10s %10s\n", "Int", "Description", "In", "Out"; @ret = snmpmaptable($host . ':::::2', \&printfun, 'ifDescr', 'ifInOctets', 'ifOutOctets'); exit 0; =head1 REQUIREMENTS =over =item * The Net_SNMP_util module uses syntax that is not supported in versions of Perl earlier than v5.6.0. =item * The Net_SNMP_util module uses the F module, and as such may depend on other modules. Please see the documentaion on F for more information. =back =head1 AUTHOR Mike Mitchell =head1 ACKNOWLEGEMENTS The original concept for this module was based on F written by Simon Leinen =head1 COPYRIGHT Copyright (c) 2007 Mike Mitchell. All rights reserved. This program is free software; you may redistribute it and/or modify it under the same terms as Perl itself. =cut # ====================================================================== 1; # [end Net_SNMP_util] mrtg-2.17.10/lib/mrtg2/locales_mrtg.pm0000644000175300017510000070046314171763414016502 0ustar oetikeroep# -*- mode: Perl -*- ###################################################################### ### Localization of mrtg output pages ###################################################################### # # # This is a generated perl module file. # # Please see the perl script mergelocale.pl and the language # # databasefiles skelton.pm0 and locale.*.pmd in translate/. # # If you want to contribute to mrtg change in the *.pmd files. # # If you just want to change your own mrtg: Go ahead and edit! # # # ###################################################################### ### Defines programs which handles centralized pattern matching and pattern ### replacements in order to translate the given strings ###################################################################### ### Created by: Morten Storgaard Nielsen ################################################################### # # Distributed under the GNU copyleft # ################################################################### ### Locale by: ### Belarusian/Беларуская ### => Глеб Валошка <375gnu@gmail.com> ### Chinese/c ### => Tate Chen @ ### => Ryan Huang F ### Brazil/Brazilian Portuguese ### => Luiz Felipe R E ### => Gleydson Mazoli da Silva (Atualização) ### Bulgarian/ ### => Yovko Lambrev ### catalan/Català ### => LLuís Gras ### Simplified Chinese/ ### => ƻ ### => QQ:582955 ӭFreeBSD ### => ԭĴ.°汾. ### cn/ĺ ### =>  ### => MSN:chenguang2001@hotmail.com FreeBSD Fan ### => MRTG. ### Croatian/Hrvatski ### => Dinko Korunic ### Czech/esky ### => Martin Och ### Czech/Česky ### => David Toman ### Danish/Dansk ### => Morten Storgaard Nielsen ### Dutch/Nederlands ### => Barry van Dijk ### Estonian/Eesti ### => Klemens Kasemaa ### ܸ(EUC-JP) ### => Fuminori Uematsu ### Finnish/Suomi ### => Jussi Siponen ### French/Francais ### => Fabrice Prigent ### and Stéphane Marzloff ### Galician/Galego ### => David Garabana Barro ### Chinese/庺 ### => Zhanghui Ż ### Chinese/ļ ### => Peter Wong ### German/Deutsch ### => Ilja Pavkovic ### Greek/Ellinika ### => Simos Xenitellis ### Hungarian/Magyar ### => Levente Nagy ### Icelandic/Islenska ### => Halldor Karl Hgnason ### Indonesian/Indonesia ### => Jamaludin Ahmad ### taken from malaysian translation ### by Assakhof Ab. Satar ### $BF|K\8l(B(ISO-2022-JP) ### => Fuminori Uematsu ### Italian/Italiano ### => Andrea Rossi ### Korean ### => Kensoon Hwang ### CHOI Junho ### Lithuanian/Lietuvikai ### => ve ### Macedonian/Makedonski ### => Delev Zoran ### Malaysian/Malay ### => Assakhof Ab. Satar ### Norwegian/norsk ### => Knut Grneng Lukasz Jokiel ### Portuguese/Português ### => Diogo Gomes ### Romn/Romanian ### => Jzsef Szilgyi ### Russian/ ### => ### Russian1251/1251 ### => ### Serbian/Srpski ### => Ratko Bucic ### Slovak/Slovensky ### => Ladislav Mihok ### Slovenian/Slovensko ### => Aljosa Us ### Spanish/Español ### => Marcelo Roccasalva ### Swedish/Svenska ### => Clas Mayer ### Turkish/Trke ### => zgr C. Demir ### Ukrainian/ ### => Ǧ ͦΦ ### Ukrainian/ ### => Olexander Kunytsa ### ### Contributions and fixes by: ### ### 0.05 fixed DARK GREEN entry (msn@ipt.dtu.dk) ### fixed credits for native language (msn@ipt.dtu.dk) ### 0.06 added the PATCHTAGs (msn@ipt.dtu.dk) ### fixed several small errors (msn@ipt.dtu.dk) ### 0.07 changed PATCHTAG to support ### mergelocale.pl (msn@ipt.dtu.dk) ### ###################################################################### ### package locales_mrtg; require 5.002; # make sure we do not get hit by UTF-8 here no locale; use strict; use vars qw(@ISA @EXPORT $VERSION); use Exporter; $VERSION = '0.07'; @ISA = qw(Exporter); @EXPORT = qw ( &english &belarusian &big5 &brazilian &bulgarian &catalan &chinese &cn &croatian &czech &czechutf8 &danish &dutch &estonian &eucjp &german &french &galician &gb &gb2312 &german &greek &hungarian &icelandic &indonesia &iso2022jp &italian &korean &lithuanian &macedonian &malay &norwegianh &polish &portuguese &romanian &russian &russian1251 &serbian &slovak &slovenian &spanish &swedish &turkish &ukrainian &ukrainian1251 ); %lang2tran::LOCALE= ( 'english' => \&english, 'default' => \&english, 'belarusian' => \&belarusian, 'беларуская' => \&belarusian, 'big5' => \&big5, 'c' => \&big5, 'brazil' => \&brazilian, 'brazilian' => \&brazilian, 'bulgarian' => \&bulgarian, '' => \&bulgarian, 'catalan' => \&catalan, 'catalan' => \&catalan, 'chinese' => \&chinese, '' => \&chinese, 'cn' => \&cn, 'ĺ' => \&cn, 'croatian' => \&croatian, 'hrvatski' => \&croatian, 'czech' => \&czech, 'czechutf8' => \&czechutf8, 'danish' => \&danish, 'dansk' => \&danish, 'dutch' => \&dutch, 'nederlands' => \&dutch, 'estonian' => \&estonian, 'eesti' => \&estonian, 'eucjp' => \&eucjp, 'euc-jp' => \&eucjp, 'finnish' => \&finnish, 'suomi' => \&finnish, 'french' => \&french, 'francais' => \&french, 'galician' => \&galician, 'galego' => \&galician, 'gb' => \&gb, '庺' => \&gb, 'gb2312' => \&gb2312, 'ļ' => \&gb2312, 'german' => \&german, 'german' => \&german, 'greek' => \&greek, 'ellinika' => \&greek, 'hungarian' => \&hungarian, 'magyar' => \&hungarian, 'icelandic' => \&icelandic, 'islenska' => \&icelandic, 'indonesia' => \&indonesia, 'indonesian' => \&indonesia, 'iso2022jp' => \&iso2022jp, 'iso-2022-jp' => \&iso2022jp, 'italian' => \&italian, 'italiano' => \&italian, 'korean' => \&korean, 'lithuanian' => \&lithuanian, 'lietuvikai' => \&lithuanian, 'macedonian' => \&macedonian, 'makedonski' => \&macedonian, 'malay' => \&malay, 'malaysian' => \&malay, 'norwegian' => \&norwegian, 'norsk' => \&norwegian, 'polish' => \&polish, 'polski' => \&polish, 'portuguese' => \&portuguese, 'romanian' => \&romanian, 'romn' => \&romanian, 'russian' => \&russian, '' => \&russian, 'russian1251' => \&russian1251, '1251' => \&russian1251, 'serbian' => \&serbian, 'slovak' => \&slovak, 'slovenian' => \&slovenian, 'spanish' => \&spanish, 'espanol' => \&spanish, 'swedish' => \&swedish, 'svenska' => \&swedish, 'turkish' => \&turkish, 'turkce' => \&turkish, 'ukrainian' => \&ukrainian, '' => \&ukrainian, 'ukrainian1251' => \&ukrainian1251, '1251' => \&ukrainian1251, ); %credits::LOCALE= ( # default 'default' => "Prepared for localization by Morten S. Nielsen <msn\@ipt.dtu.dk>", # Belarusian/беларуская 'belarusian' => "Беларускі пераклад: Глеб Валошка <375gnu\@gmail.com>", # Chinese/c 'big5' => "Ƨ@ Tate Chen <tate\@joy-tech.com.tw>
and F <ryan\@asplord.com>", # Brazil/brazilian 'brazilian' => "Localização efetuada por Luiz Felipe R E <luizfelipe\@encarnacao.com>
atualização por Gleydson Mazioli da Silva <gleydson\@debian.org>", # Bulgarian/ 'bulgarian' => " : <yovko\@sdf.lonestar.org>", # catalan/catalan 'catalan' => "Preparat per a localització per: Lluís Gras", # Simplified Chinese/ 'chinese' => "ȫ¼ĺ ƻ <webmaster\@kingisme.com>", # cn/ĺ 'cn' => "
MRTG  <zurkabsd\@yahoo.com.cn>", # Croatian/hrvatski 'croatian' => "Hrvatska lokalizacija - Dinko Korunic <kreator\@fly.srk.fer.hr>", # Czech/esky 'czech' => "esk peklad pipravil Martin Och <martin\@och.cz>", # Czechutf8/Česky 'czechutf8' => "Český překlad do UTF-8 připravil David Toman <david\@idkfa.cz>", # Danish/dansk 'danish' => "Forberedt for sprog samt oversat til dansk af Morten S. Nielsen <msn\@ipt.dtu.dk>", # the danish string means: "Prepared for languages and translated to danish by" # Dutch/nederlands 'dutch' => "Vertaald naar het Nederlands door Barry van Dijk <barry\@dijk.com>
; Aangepast door Paul Slootman <paul\@debian.org>", # Estonian/Eesti 'estonian' => "Tõlge eesti keelde Klemens Kasemaa <klem\@linux.ee>", # the estonian string means: "Translation to estonian by" # eucjp/euc-jp 'eucjp' => "ܸ(EUC-JP) ʸ <uematsu\@kgz.com>", # Finnish/Suomi 'finnish' => "Lokalisoinut Jussi Siponen <jussi.siponen\@online.tietokone.fi>", # the Finnish string means: "Localized by" # French/francais 'french' => "Localisation effectuée par Fabrice Prigent <fabrice.prigent\@univ-tlse1.fr>", # Galician/Galego 'galician' => "Traducido ao galego por David Garabana Barro <dgaraban\@arrakis.es>", # Chinese/庺 'gb' => "Ƨ@ Hui Zhang <zhanghui\@asiainfo.com>", # Chinese/ļ 'gb2312' => "Ļ Peter Wong &webmaster\@tcpip.com.cn>", # German/deutsch 'german' => "Vorbereitet für die Lokalisation von Ilja Pavkovic <illsen\@gumblfarz.de>", # Greek/Ellinika 'greek' => " <S.Xenitellis\@hellug.gr>", # Hungarian/magyar 'hungarian' => "Magyarosította Nagy Levente <levinet\@euroweb.hu>", # the hungarian string means: "Prepared for languages and translated to Hungarian by" # Icelandic/islenska 'icelandic' => "Þýtt yfir á íslensku af Halldór Karl Högnason <halldor.hognason\@islandssimi.is>", # Indonesian/Indonesia 'indonesia' => "Terjemahan ke bahasa Indonesia oleh: Jamaludin Ahmad <jamaludin\@jamalinux.com>", # iso2022jp/iso-2022-jp 'iso2022jp' => "\e\$BF|K\\8lLu\e(B(ISO-2022-JP)\e\$B:n\@.\e(B \e\$B?\">>\e(B \e\$BJ8FA\e(B <uematsu\@kgz.com>", # Italian/Italiano 'italian' => "Localizzazione effettuata da Andrea Rossi <rouge\@shiny.it>", # korean ,'korean' => "ѱ۸޽ : ȲǼ, ȣ", # Lithuanian/lietuvikai 'lithuanian' => "Paruo ir lietuvi kalb ivert ve <ve\@hardcore.lt>", # the lithuanian string means: "Prepared for languages and translated to lithuanian by" # Macedonian/makedonski 'macedonian' => "Makedonska lokalizacija - Delev D Zoran <delevz\@esmak.com.mk>", # the macedonian string means: "Prepared for languages and translated to macedonian by" # Malaysian/Malay 'malay' => "Terjemahan ke bahasa Malaysia/Indonesia oleh: Assakhof Ab. Satar <assakhof\@mimos.my>", # Danish/dansk 'norwegian' => "Oversatt til norsk av Knut Grneng <knut.groneng\@merkantildata.no>", # the norwegian string means: "Translated to norwegian by" # Polish/polski 'polish' => "Polska lokalizacja Lukasz Jokiel <Lukasz.Jokiel\@klonex.com.pl>", # Português/portuguese 'portuguese' => "Traduzido por Diogo Gomes <etdgomes\@ua.pt>", # Romn/romanian 'romanian' => "Tradus de Jzsef Szilgyi <jozsi\@maxiq.ro>", # Russian/ 'russian' => " : <mitya\@cavia.pp.ru>", # Russian1251/1251 'russian1251' => " ( 1251): <aredyuk\@irmcity.com>", # Serbian/Srpski 'serbian' => "Ported to Serbian by / Srpski prevod uradio: Ratko Bui <ratko\@ni.ac.yu>", # Slovak/Slovensky 'slovak' => "Slovensk preklad pripravil Ing. Ladislav Mihok <laco\@mrokh.shmu.sk>", # Slovenian/Slovensko 'slovenian' => "Slovenski prevod pripravil Ragnar Belial Us <us\@sweet-sorrow.com>", # Spanish/español 'spanish' => "Preparado para localización por Marcelo Roccasalva", # Swedish/Svenska 'swedish' => "Översatt till svenska av Clas Mayer <clas\@mayer.se>", # the Swedish string means: "Prepared for languages and translated to Swedish by" # Turkish/Trke 'turkish' => "Trkeletiren zgr C. Demir", # Ukrainian/ 'ukrainian' => " : Ǧ ͦΦ <gray\@arte-fact.net>", # Ukrainian1251/1251 'ukrainian1251' => " (cp1251): <xakep\@snark.ukma.kiev.ua>", ); $credits::LOCALE{'беларуская'}=$credits::LOCALE{'belarusian'}; $credits::LOCALE{'c'}=$credits::LOCALE{'big5'}; $credits::LOCALE{'brazil'}=$credits::LOCALE{'brazilian'}; $credits::LOCALE{''}=$credits::LOCALE{'bulgarian'}; $credits::LOCALE{'catalan'}=$credits::LOCALE{'catalan'}; $credits::LOCALE{''}=$credits::LOCALE{'Chinese'}; $credits::LOCALE{'ĺ'}=$credits::LOCALE{'cn'}; $credits::LOCALE{'hrvatski'}=$credits::LOCALE{'croatian'}; $credits::LOCALE{'czech'}=$credits::LOCALE{'czech'}; $credits::LOCALE{'czechutf8'}=$credits::LOCALE{'czechutf8'}; $credits::LOCALE{'dansk'}=$credits::LOCALE{'danish'}; $credits::LOCALE{'nederlands'}=$credits::LOCALE{'dutch'}; $credits::LOCALE{'eesti'}=$credits::LOCALE{'estonian'}; $credits::LOCALE{'euc-jp'}=$credits::LOCALE{'eucjp'}; $credits::LOCALE{'finnish'}=$credits::LOCALE{'finnish'}; $credits::LOCALE{'francais'}=$credits::LOCALE{'french'}; $credits::LOCALE{'galego'}=$credits::LOCALE{'galician'}; $credits::LOCALE{'庺'}=$credits::LOCALE{'gb'}; $credits::LOCALE{'ļ'}=$credits::LOCALE{'gb2312'}; $credits::LOCALE{'deutsch'}=$credits::LOCALE{'german'}; $credits::LOCALE{'ellinika'}=$credits::LOCALE{'greek'}; $credits::LOCALE{'magyar'}=$credits::LOCALE{'hungarian'}; $credits::LOCALE{'islenska'}=$credits::LOCALE{'icelandic'}; $credits::LOCALE{'indonesian'}=$credits::LOCALE{'indonesia'}; $credits::LOCALE{'iso-2022-jp'}=$credits::LOCALE{'iso2022jp'}; $credits::LOCALE{'italiano'}=$credits::LOCALE{'italian'}; $credits::LOCALE{'korean'}=$credits::LOCALE{'korean'}; $credits::LOCALE{'lietuvikai'}=$credits::LOCALE{'lithuanian'}; $credits::LOCALE{'macedonian'}=$credits::LOCALE{'macedonian'}; $credits::LOCALE{'malaysian'}=$credits::LOCALE{'malay'}; $credits::LOCALE{'norsk'}=$credits::LOCALE{'norwegian'}; $credits::LOCALE{'polski'}=$credits::LOCALE{'polish'}; $credits::LOCALE{'portuguese'}=$credits::LOCALE{'portuguese'}; $credits::LOCALE{'romn'}=$credits::LOCALE{'romanian'}; $credits::LOCALE{''}=$credits::LOCALE{'russian'}; $credits::LOCALE{'1251'}=$credits::LOCALE{'russian1251'}; $credits::LOCALE{'serbian'}=$credits::LOCALE{'serbian'}; $credits::LOCALE{'slovak'}=$credits::LOCALE{'slovak'}; $credits::LOCALE{'slovenian'}=$credits::LOCALE{'slovenian'}; $credits::LOCALE{'espanol'}=$credits::LOCALE{'spanish'}; $credits::LOCALE{'svenska'}=$credits::LOCALE{'swedish'}; $credits::LOCALE{'turkce'}=$credits::LOCALE{'turkish'}; $credits::LOCALE{''}=$credits::LOCALE{'ukrainian'}; $credits::LOCALE{'1251'}=$credits::LOCALE{'ukrainian1251'}; # English - default sub english { return shift; }; # Belarusian sub belarusian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=utf-8 %translations = ( 'iso-8859-1' => 'utf-8', 'Maximal 5 Minute Incoming Traffic' => 'Найбольшы ўваходны трафік за 5 хвілін', 'Maximal 5 Minute Outgoing Traffic' => 'Найбольшы выходны трафік за 5 хвілін', 'the device' => 'прылада', 'The statistics were last updated(.*)' => 'Апошні раз статыстыка абнаўлялася: $1', ' Average\)' => ')', 'Average' => 'спасярэднены', 'Max' => 'найбольшы', 'Current' => 'бягучы', 'version' => 'вэрсія', '`Daily\' Graph \((.*) Minute' => 'Графік трафіку за суткі (за $1 хвілін ', '`Weekly\' Graph \(30 Minute' => 'Графік трафіку за тыдзень (за 30 хвілін ', '`Monthly\' Graph \(2 Hour' => 'Графік трафіку за месяц (за 2 гадзіны ', '`Yearly\' Graph \(1 Day' => 'Графік трафіку за год (за 1 дзень ', 'Incoming Traffic in (\S+) per Second' => 'Уваходны трафік $1 за сэкунду', 'Outgoing Traffic in (\S+) per Second' => 'Выходны трафік $1 за сэкунду', 'Incoming Traffic in (\S+) per Minute' => 'Уваходны трафік $1 за хвіліну', 'Outgoing Traffic in (\S+) per Minute' => 'Выходны трафік $1 за хвіліну', 'Incoming Traffic in (\S+) per Hour' => 'Уваходны трафік $1 за гадзіну', 'Outgoing Traffic in (\S+) per Hour' => 'Выходны трафік $1 за гадзіну', 'at which time (.*) had been up for(.*)' => 'калі $1 працаваў $2', '(\S+) per minute' => '$1 за хвіліну', '(\S+) per hour' => '$1 за гадзіну', '(.+)/s$' => '$1/с', '(.+)/min' => '$1/хв', '(.+)/h$' => '$1/г', '([kMG]?)([bB])/s' => '$1$2/с', '([kMG]?)([bB])/min' => '$1$2/хв', '([kMG]?)([bB])/h' => '$1$2/г', 'Bits' => 'бітах', 'Bytes' => 'байтах', 'In' => 'Уваходны', 'Out' => 'Выходны', 'Percentage' => 'Адсоткі', 'Ported to OpenVMS Alpha by' => 'Перанос на OpenVMS:', 'Ported to WindowsNT by' => 'Перанос на WindowsNT:', 'and' => 'і', '^GREEN' => 'ЗЯЛЁНЫ', 'BLUE' => 'СІНІ', 'DARK GREEN' => 'ЦЁМНАЗЯЛЁНЫ', 'MAGENTA' => 'РУЖОВЫ', 'AMBER' => 'БУРШТЫНАВЫ' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Нядзеля', 'Sun' => 'Нд', 'Monday' => 'Панядзелак', 'Mon' => 'Пн', 'Tuesday' => 'Аўторак', 'Tue' => 'Аў', 'Wednesday' => 'Серада', 'Wed' => 'Ср', 'Thursday' => 'Чацьвер', 'Thu' => 'Чц', 'Friday' => 'Пятніца', 'Fri' => 'Пт', 'Saturday' => 'Субота', 'Sat' => 'Сб' ); %month = ( 'January' => 'Студзень', 'February' => 'Люты' , 'March' => 'Сакавік', 'Jan' => 'Сту', 'Feb' => 'Лют', 'Mar' => 'Сак', 'April' => 'Красавік', 'May' => 'Травень', 'June' => 'Чэрвень', 'Apr' => 'Кра', 'May' => 'Тра', 'Jun' => 'Чэр', 'July' => 'Ліпень', 'August' => 'Жнівень', 'September' => 'Верасень', 'Jul' => 'Ліп', 'Aug' => 'Жні', 'Sep' => 'Вер', 'October' => 'Кастрычнік','November' => 'Лістапад', 'December' => 'Сьнежань', 'Oct' => 'Кас', 'Nov' => 'Ліс', 'Dec' => 'Сьн' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." у ".$quux[1]; }; return "$wday{$foo[0]}, $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Chinese Big5 Code sub big5 { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'big5', 'Maximal 5 Minute Incoming Traffic' => '5̤jyJq', 'Maximal 5 Minute Outgoing Traffic' => '5̤jyXq', 'the device' => '˸m', 'The statistics were last updated(.*)' => 'Wέpsɶ: $1', ' Average\)' => ' )', 'Average' => '', 'Max$' => '̤j', 'Current' => 'ثe', 'version' => '', '`Daily\' Graph \((.*) Minute' => 'C Ϫ ($1 ', '`Weekly\' Graph \(30 Minute' => 'Cg Ϫ (30 ' , '`Monthly\' Graph \(2 Hour' => 'C Ϫ (2 p', '`Yearly\' Graph \(1 Day' => 'C~ Ϫ (1 ', 'Incoming Traffic in (\S+) per Second' => 'CyJq ( $1)', 'Outgoing Traffic in (\S+) per Second' => 'CyXq ( $1)', 'Incoming Traffic in (\S+) per Minute' => 'CyJq ( $1)', 'Outgoing Traffic in (\S+) per Minute' => 'CyXq ( $1)', 'Incoming Traffic in (\S+) per Hour' => 'CpɬyJq ( $1)', 'Outgoing Traffic in (\S+) per Hour' => 'CpɬyXq ( $1)', 'at which time (.*) had been up for(.*)' => ']ƦW $1AwB@ɶ(UPTIME): $2', '(\S+) per minute' => '$1/', '(\S+) per hour' => '$1/p', '(.+)/s$' => '$1/', '(.+)/min$' => '$1/', '(.+)/h$' => '$1/p', #'([kMG]?)([bB])/s' => '$1$2/s', #'([kMG]?)([bB])/min' => '$1$2/min', #'([kMG]?)([bB])/h' => '$1$2/std', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'yJ', 'Out$' => 'yX', 'Percentage' => 'ʤ', 'Ported to OpenVMS Alpha by' => 'Ө OpenVM Alpha @', 'Ported to WindowsNT by' => 'Ө WindowsNT @', 'and' => '', '^GREEN' => '', 'BLUE' => 'Ŧ', 'DARK GREEN' => '', 'MAGENTA' => '', 'AMBER' => '[Ħ' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'P', 'Sun' => '', 'Monday' => 'P@', 'Mon' => '@', 'Tuesday' => 'PG', 'Tue' => 'G', 'Wednesday' => 'PT', 'Wed' => 'T', 'Thursday' => 'P|', 'Thu' => '|', 'Friday' => 'P', 'Fri' => '', 'Saturday' => 'P', 'Sat' => '' ); %month = ( 'January' => '@', 'February' => 'G', 'March' => 'T', 'Jan' => '@', 'Feb' => 'G', 'Mar' => 'T', 'April' => '|', 'May' => '', 'June' => '', 'Apr' => '|', 'May' => '', 'Jun' => '', 'July' => 'C', 'August' => 'K', 'September' => 'E', 'Jul' => 'C', 'Aug' => 'K', 'Sep' => 'E', 'October' => 'Q', 'November' => 'Q@', 'December' => 'QG', 'Oct' => 'Q', 'Nov' => 'Q@', 'Dec' => 'QG' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]; $foo[4]=$quux[1]; }; return "$foo[3] ~ $month{$foo[2]} $foo[1] $wday{$foo[0]} $foo[4]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Brazilian (Portugues) sub brazilian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Tráfego Máximo de Entrada em 5 minutos', 'Maximal 5 Minute Outgoing Traffic' => 'Tráfego Máximo de Saída em 5 minutos', 'the device' => 'dispositivo', 'The statistics were last updated (.*)' => 'Última atualização das estatísticas: $1', ' Average\)' => ' - média)', 'Average' => 'Média', 'Max' => 'Máx', 'Current' => 'Atual', 'version' => 'versão', '`Daily\' Graph \((.*) Minute' => 'Gráfico `Diário\' ($1 minutos', '`Weekly\' Graph \(30 Minute' => 'Gráfico `Semanal\' (30 minutos' , '`Monthly\' Graph \(2 Hour' => 'Gráfico `Mensal\' (2 horas', '`Yearly\' Graph \(1 Day' => 'Gráfico `Anual\' (1 dia', 'Incoming Traffic in (\S+) per Second' => 'Tráfego de Entrada em $1 por segundo', 'Outgoing Traffic in (\S+) per Second' => 'Tráfego de Saída em $1 por segundo', 'at which time (.*) had been up for(.*)' => 'nesta hora $1 estava ativo por $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', # '([kMG]?)([bB])/h' => '$1$2/t', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Entr.', 'Out' => 'Saí', 'Percentage' => 'Porc.', 'Ported to OpenVMS Alpha by' => 'Adaptado para o Alpha OpenVMS por', 'Ported to WindowsNT by' => 'Adaptado para o WindowsNT por', 'and' => 'e', '^GREEN' => 'VERDE', 'BLUE' => 'AZUL', 'DARK GREEN' => 'VERDE ESCURO', 'MAGENTA' => 'LILÁS', 'AMBER' => 'AMBAR' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Domingo', 'Sun' => 'Dom', 'Monday' => 'Segunda', 'Mon' => 'Seg', 'Tuesday' => 'Terça', 'Tue' => 'Ter', 'Wednesday' => 'Quarta', 'Wed' => 'Qua', 'Thursday' => 'Quinta', 'Thu' => 'Qui', 'Friday' => 'Sexta', 'Fri' => 'Sex', 'Saturday' => 'Sábado', 'Sat' => 'Sáb' ); %month = ( 'January' => 'Janeiro', 'February' => 'Fevereiro' , 'March' => 'Março', 'Jan' => 'Jan', 'Feb' => 'Fev', 'Mar' => 'Mar', 'April' => 'Abril', 'May' => 'Maio', 'June' => 'Junho', 'Apr' => 'Abr', 'May' => 'Mai', 'Jun' => 'Jun', 'July' => 'Julho', 'August' => 'Agosto', 'September' => 'Setembro', 'Jul' => 'Jul', 'Aug' => 'Ago', 'Sep' => 'Set', 'October' => 'Outubro', 'November' => 'Novembro', 'December' => 'Dezembro', 'Oct' => 'Out', 'Nov' => 'Nov', 'Dec' => 'Dez' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." às ".$quux[1]; }; return "$wday{$foo[0]}, $foo[1] de $month{$foo[2]} de $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Bulgarian sub bulgarian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'windows-1251', 'Maximal 5 Minute Incoming Traffic' => ' 5 ', 'Maximal 5 Minute Outgoing Traffic' => ' 5 ', 'the device' => '', 'The statistics were last updated(.*)' => ' : $1', ' Average\)' => ' )', 'Average' => '', 'Max' => '.', 'Current' => '', 'version' => '', '`Daily\' Graph \((.*) Minute' => ' ( $1 ', '`Weekly\' Graph \(30 Minute' => ' ( 30 ' , '`Monthly\' Graph \(2 Hour' => ' ( 2 ', '`Yearly\' Graph \(1 Day' => ' ( 1 ', 'Incoming Traffic in (\S+) per Second' => ' $1 ', 'Outgoing Traffic in (\S+) per Second' => ' $1 ', 'at which time (.*) had been up for(.*)' => ' $1 $2', #'([kMG]?)([bB])/s' => '$1$1/', #'([kMG]?)([bB])/min' => '$1$2/', '([kMG]?)([bB])/h' => '$1$2/', 'Bits' => '', 'Bytes' => '', 'In' => '.', 'Out' => '.', 'Percentage' => '', 'Ported to OpenVMS Alpha by' => ' OpenVMS Alpha ', 'Ported to WindowsNT by' => ' WindowsNT ', 'and' => '', '^GREEN' => '', 'BLUE' => '', 'DARK GREEN' => '', 'MAGENTA' => '', 'AMBER' => '' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => ' ', 'Sun' => '', 'Monday' => ' ', 'Mon' => '', 'Tuesday' => ' ', 'Tue' => '', 'Wednesday' => ' ', 'Wed' => '', 'Thursday' => ' ', 'Thu' => '', 'Friday' => ' ', 'Fri' => '', 'Saturday' => ' ', 'Sat' => '' ); %month = ( 'January' => '', 'February' => '' , 'March' => '', 'Jan' => '', 'Feb' => '', 'Mar' => '', 'April' => '', 'May' => '', 'June' => '', 'Apr' => '', 'May' => '', 'Jun' => '', 'July' => '', 'August' => '', 'September' => '', 'Jul' => '', 'Aug' => '', 'Sep' => '', 'October' => '', 'November' => '', 'December' => '', 'Oct' => '', 'Nov' => '', 'Dec' => '' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].". ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # catalan sub catalan { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Tràfic entrant màxim en 5 minuts', 'Maximal 5 Minute Outgoing Traffic' => 'Tràfic sortint màxim en 5 minuts', 'the device' => 'el dispositiu', 'The statistics were last updated(.*)' => 'Estadístiques actualitzades el $1', ' Average\)' => ' Promig)', 'Average' => 'Promig', 'Max' => 'Màxim', 'Current' => 'Actual', 'version' => 'versió', '`Daily\' Graph \((.*) Minute' => 'Gràfic diari ($1 minuts :', '`Weekly\' Graph \(30 Minute' => 'Gràfic setmanal (30 minuts :' , '`Monthly\' Graph \(2 Hour' => 'Gràfic mensual (2 hores :', '`Yearly\' Graph \(1 Day' => 'Gràfic anual (1 dia :', 'Incoming Traffic in (\S+) per Second' => 'Tràfic entrant en $1 per segon', 'Outgoing Traffic in (\S+) per Second' => 'Tràfic sortint en $1 per segon', 'at which time (.*) had been up for(.*)' => '$1 ha estat funcionant durant $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', # '([kMG]?)([bB])/h' => '$1$2/t', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Entrant', 'Out' => 'Sortint', 'Percentage' => 'Percentatge', 'Ported to OpenVMS Alpha by' => 'Portat a OpenVMS Alpha per', 'Ported to WindowsNT by' => 'Portat a WindowsNT per', 'and' => 'i', '^GREEN' => 'VERD', 'BLUE' => 'BLAU', 'DARK GREEN' => 'VERD FOSC', 'MAGENTA' => 'MAGENTA', 'AMBER' => 'AMBAR' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Diumenge', 'Sun' => 'Dg', 'Monday' => 'Dilluns', 'Mon' => 'Dl', 'Tuesday' => 'Dimarts', 'Tue' => 'Dm', 'Wednesday' => 'Dimecres', 'Wed' => 'Dc', 'Thursday' => 'Dijous', 'Thu' => 'Dj', 'Friday' => 'Divendres', 'Fri' => 'Dv', 'Saturday' => 'Dissabte', 'Sat' => 'Ds' ); %month = ( 'January' => 'Gener', 'February' => 'Febrer' , 'March' => 'Març', 'Jan' => 'Gen', 'Feb' => 'Feb', 'Mar' => 'Mar', 'April' => 'Abril', 'May' => 'Maig', 'June' => 'Juny', 'Apr' => 'Abr', 'May' => 'Mai', 'Jun' => 'Jun', 'July' => 'Juliol', 'August' => 'Agost', 'September' => 'Setembre', 'Jul' => 'Jul', 'Aug' => 'Ago', 'Sep' => 'Set', 'October' => 'Octubre', 'November' => 'Novembre', 'December' => 'Desembre', 'Oct' => 'Oct', 'Nov' => 'Nov', 'Dec' => 'Des' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." a les ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] de $month{$foo[2]} de $foo[3]"; }; return $string; }; # Simplified Chinese sub chinese { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... %translations = ( 'iso-8859-1' => 'gb2312', 'Maximal 5 Minute Incoming Traffic' => '5', 'Maximal 5 Minute Outgoing Traffic' => '5', 'the device' => '豸', 'The statistics were last updated(.*)' => 'ͳƸʱ䣺$1', ' Average\)' => ' ƽ)', 'Average' => 'ƽ', 'Max' => '', 'Current' => 'ǰ', 'version' => '汾', '`Daily\' Graph \((.*) Minute' => 'ÿ ͼ ($1 ', '`Weekly\' Graph \(30 Minute' => 'ÿ ͼ (30 ' , '`Monthly\' Graph \(2 Hour' => 'ÿ ͼ (2 Сʱ', '`Yearly\' Graph \(1 Day' => 'ÿ ͼ (1 ', 'Incoming Traffic in (\S+) per Second' => 'ÿ (λ $1 )', 'Outgoing Traffic in (\S+) per Second' => 'ÿ (λ $1 )', 'at which time (.*) had been up for(.*)' => ' $1 ˣ $2 ', '(.+)/s$' => '$1/', '(.+)/min$' => '$1/', '(.+)/h$' => '$1/ʱ', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => '룺', 'Out' => '', 'Percentage' => 'ٷֱȣ', 'Ported to OpenVMS Alpha by' => 'ֲ OpenVMS ', 'Ported to WindowsNT by' => 'ֲ WindowsNT ', 'and' => '', '^GREEN' => 'ɫ', 'BLUE' => 'ɫ', 'DARK GREEN' => 'ī', 'MAGENTA' => 'ɫ', 'AMBER' => 'ɫ' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => '', 'Sun' => '', 'Monday' => 'һ', 'Mon' => 'һ', 'Tuesday' => 'ڶ', 'Tue' => '', 'Wednesday' => '', 'Wed' => '', 'Thursday' => '', 'Thu' => '', 'Friday' => '', 'Fri' => '', 'Saturday' => '', 'Sat' => '' ); %month = ( 'January' => ' һ ', 'February' => ' ', 'March' => ' ', 'April' => ' ', 'May' => ' ', 'June' => ' ', 'July' => ' ', 'August' => ' ', 'September' => ' ', 'October' => ' ʮ ', 'November' => 'ʮһ', 'December' => 'ʮ', 'Jan' => '', 'Feb' => '', 'Mar' => '', 'Apr' => '', 'May' => '', 'Jun' => '', 'Jul' => '', 'Aug' => '', 'Sep' => '', 'Oct' => '10', 'Nov' => '11', 'Dec' => '12' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]; $foo[4]=$quux[1]; }; return "$foo[3] $month{$foo[2]} $foo[1] $wday{$foo[0]} $foo[4]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # cn s-Chinese sub cn { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... %translations = ( 'charset=iso-8859-1' => 'charset=gb2312', 'Maximal 5 Minute Incoming Traffic' => '5', 'Maximal 5 Minute Outgoing Traffic' => '5', 'the device' => '豸', 'The statistics were last updated(.*)' => 'ͳʱ䣺$1', ' Average\)
' => ' ƽ)
', 'Average(.*)' => 'ƽ$1', 'Max(.*)' => '$1', 'Current(.*)' => 'ǰ$1', 'version' => '汾', '`Daily\' Graph \((.*) Minute' => '"ÿ" ͼ ($1 ', '`Weekly\' Graph \(30 Minute' => '"ÿ" ͼ (30 ' , '`Monthly\' Graph \(2 Hour' => '"ÿ" ͼ (2 Сʱ', '`Yearly\' Graph \(1 Day' => '"ÿ" ͼ (1 ', 'Incoming Traffic in (\S+) per Second' => 'ÿ $1 ', 'Outgoing Traffic in (\S+) per Second' => 'ÿ $1 ', 'at which time (.*) had been up for(.*)' => 'ʱ $1 ˣ $2 ', '(.+)/s$' => '$1/', '(.+)/min$' => '$1/', '(.+)/h$' => '$1/ʱ', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' ' In:' => ' 룺', ' Out:' => ' ', ' Percentage' => ' ٷֱȣ', 'Ported to OpenVMS Alpha by' => 'ֲ OpenVMS ', 'Ported to WindowsNT by' => 'ֲ WindowsNT ', 'and' => '', '^GREEN' => '', 'BLUE' => '', 'DARK GREEN' => 'ī', 'MAGENTA' => '', 'AMBER' => 'ɫ' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => '', 'Sun' => '', 'Monday' => 'һ', 'Mon' => 'һ', 'Tuesday' => 'ڶ', 'Tue' => '', 'Wednesday' => '', 'Wed' => '', 'Thursday' => '', 'Thu' => '', 'Friday' => '', 'Fri' => '', 'Saturday' => '', 'Sat' => '' ); %month = ( 'January' => ' һ ', 'February' => ' ', 'March' => ' ', 'April' => ' ', 'May' => ' ', 'June' => ' ', 'July' => ' ', 'August' => ' ', 'September' => ' ', 'October' => ' ʮ ', 'November' => 'ʮһ', 'December' => 'ʮ', 'Jan' => '', 'Feb' => '', 'Mar' => '', 'Apr' => '', 'May' => '', 'Jun' => '', 'Jul' => '', 'Aug' => '', 'Sep' => '', 'Oct' => '', 'Nov' => '', 'Dec' => '' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]; $foo[4]=$quux[1]; }; return "$foo[3] $month{$foo[2]} $foo[1] $wday{$foo[0]} $foo[4]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; sub croatian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'iso-8859-2', 'Maximal 5 Minute Incoming Traffic' => 'Maksimalni ulazni promet unutar 5 minuta', 'Maximal 5 Minute Outgoing Traffic' => 'Maksimalni izlazni promet unutar 5 minuta', 'the device' => 'ureaj', 'The statistics were last updated(.*)' => 'Statistike su zadnji puta izmijenjene $1', ' Average\)' => ' prosjena vrijednost)', 'Average' => 'Prosjeno', 'Max' => 'Maksimalno', 'Current' => 'Trenutno', 'version' => 'verzija', '`Daily\' Graph \((.*) Minute' => 'Dnevne statistike (svakih $1 minuta', '`Weekly\' Graph \(30 Minute' => 'Tjedne statistike (svakih 30 minuta' , '`Monthly\' Graph \(2 Hour' => 'Mjesene statistike (svakih 2 sata', '`Yearly\' Graph \(1 Day' => 'Godinje statistike (svaki 1 dan', 'Incoming Traffic in (\S+) per Second' => 'Ulazni promet - $1 po sekundi', 'Outgoing Traffic in (\S+) per Second' => 'Izlazni promet - $1 po sekundi', 'at which time (.*) had been up for(.*)' => 'gdje $1 je bio aktivan $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/g', 'Bits' => 'Bitova', 'Bytes' => 'Bajtova', 'In' => 'Unutra', 'Out' => 'Van', 'Percentage' => 'Postotak', 'Ported to OpenVMS Alpha by' => 'Port na OpenVMS Alpha od', 'Ported to WindowsNT by' => 'Post od WindowsNT od', 'and' => 'i', '^GREEN' => 'ZELENA', 'BLUE' => 'PLAVA', 'DARK GREEN' => 'TAMNO ZELENA', 'MAGENTA' => 'LJUBIASTA', 'AMBER' => 'AMBER' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Nedjelja', 'Sun' => 'Ned', 'Monday' => 'Ponedjeljak', 'Mon' => 'Pon', 'Tuesday' => 'Utorak', 'Tue' => 'Uto', 'Wednesday' => 'Srijeda', 'Wed' => 'Sri', 'Thursday' => 'etvrtak', 'Thu' => 'et', 'Friday' => 'Petak', 'Fri' => 'Pet', 'Saturday' => 'Subota', 'Sat' => 'Sub' ); %month = ( 'January' => 'Sijeanj', 'February' => 'Veljaa', 'March' => 'Oujak', 'Jan' => 'Sij', 'Feb' => 'Vel', 'Mar' => 'Ou', 'April' => 'Travanj', 'May' => 'Svibanj', 'June' => 'Lipanj', 'Apr' => 'Tra', 'May' => 'Svi', 'Jun' => 'Lip', 'July' => 'Srpanj', 'August' => 'Kolovoz', 'September' => 'Rujan', 'Jul' => 'Srp', 'Aug' => 'Kol', 'Sep' => 'Ruj', 'October' => 'Listopad', 'November' => 'Studeni', 'December' => 'Prosinac', 'Oct' => 'Lis', 'Nov' => 'Stu', 'Dec' => 'Pro' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." godine"." u".$quux[1]; }; return "$wday{$foo[0]} dana $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Czech sub czech { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'windows-1250', 'Maximal 5 Minute Incoming Traffic' => 'Maximln 5 minutov pchoz tok', 'Maximal 5 Minute Outgoing Traffic' => 'Maximln 5 minutov odchoz tok', 'the device' => 'zazen', 'The statistics were last updated(.*)' => 'Posledn aktualizace statistiky:$1', ' Average\)' => ' prmr)', 'Average' => 'Prm.', 'Max' => 'Max.', 'Current' => 'Akt.', 'version' => 'verze', '`Daily\' Graph \((.*) Minute' => 'Denn graf ($1 minutov', '`Weekly\' Graph \(30 Minute' => 'Tdenn graf (30 minutov' , '`Monthly\' Graph \(2 Hour' => 'Msn graf (2 hodinov', '`Yearly\' Graph \(1 Day' => 'Ron graf (1 denn', 'Incoming Traffic in (\S+) per Second' => 'Pchoz tok v $1 za sec.', 'Outgoing Traffic in (\S+) per Second' => 'Odchoz tok v $1 za sec.', 'at which time (.*) had been up for(.*)' => 'od poslednho restartu $1 ubhlo: $2', #'([kMG]?)([bB])/s' => '\$1\$2/s', #'([kMG]?)([bB])/min' => '\$1\$2/min', #'([kMG]?)([bB])/h' => '$1$2/h', 'Bits' => 'bitech', 'Bytes' => 'bajtech', #' In:' => ' In:', #' Out:' => ' Out:', 'Percentage' => 'Proc.', 'Ported to OpenVMS Alpha by' => 'Na OpenVMS portoval', 'Ported to WindowsNT by' => 'Na WindowsNT portoval', 'and' => 'a', '^GREEN' => 'Zelen', 'BLUE' => 'Modr', 'DARK GREEN' => 'Tmav zelen', 'MAGENTA' => 'Fialov', 'AMBER' => 'lut' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Nedle', 'Sun' => 'Ne', 'Monday' => 'Pondli', 'Mon' => 'Po', 'Tuesday' => 'ter', 'Tue' => 't', 'Wednesday' => 'Steda', 'Wed' => 'St', 'Thursday' => 'tvrtek', 'Thu' => 't', 'Friday' => 'Ptek', 'Fri' => 'P', 'Saturday' => 'Sobota', 'Sat' => 'So' ); %month = ( 'January' => 'Leden', 'February' => 'nor', 'March' => 'Bezen', 'Jan' => 'Leden', 'Feb' => 'nor', 'Mar' => 'Bezen', 'April' => 'Duben', 'May' => 'Kvten', 'June' => 'erven', 'Apr' => 'Duben', 'May' => 'Kvten', 'Jun' => 'erven', 'July' => 'ervenec','August' => 'Srpen', 'September' => 'Z', 'Jul' => 'ervenec','Aug' => 'Srpen', 'Sep' => 'Z', 'October' => 'jen', 'November' => 'Listopad', 'December' => 'Prosinec', 'Oct' => 'jen', 'Nov' => 'Listopad', 'Dec' => 'Prosinec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].",".$quux[1]." hod."; }; return "$wday{$foo[0]} $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; } # # Czechutf8 sub czechutf8 { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'utf-8', 'Maximal 5 Minute Incoming Traffic' => 'Maximální 5 minutový příchozí tok', 'Maximal 5 Minute Outgoing Traffic' => 'Maximální 5 minutový odchozí tok', 'the device' => 'zařízení', 'The statistics were last updated(.*)' => 'Poslední aktualizace statistiky:$1', ' Average\)' => ' průměr)', 'Average' => 'Prům.', 'Max' => 'Max.', 'Current' => 'Akt.', 'version' => 'verze', '`Daily\' Graph \((.*) Minute' => 'Denní graf ($1 minutový', '`Weekly\' Graph \(30 Minute' => 'Týdenní graf (30 minutový' , '`Monthly\' Graph \(2 Hour' => 'Měsíční graf (2 hodinový', '`Yearly\' Graph \(1 Day' => 'Roční graf (1 denní', 'Incoming Traffic in (\S+) per Second' => 'Příchozí tok v $1 za sec.', 'Outgoing Traffic in (\S+) per Second' => 'Odchozí tok v $1 za sec.', 'at which time (.*) had been up for(.*)' => 'od posledního restartu $1 uběhlo: $2', #'([kMG]?)([bB])/s' => '\$1\$2/s', #'([kMG]?)([bB])/min' => '\$1\$2/min', #'([kMG]?)([bB])/h' => '$1$2/h', 'Bits' => 'bitech', 'Bytes' => 'bajtech', #' In:' => ' In:', #' Out:' => ' Out:', 'Percentage' => 'Proc.', 'Ported to OpenVMS Alpha by' => 'Na OpenVMS portoval', 'Ported to WindowsNT by' => 'Na WindowsNT portoval', 'and' => 'a', '^GREEN' => 'Zelená', 'BLUE' => 'Modrá', 'DARK GREEN' => 'Tmavě zelená', 'MAGENTA' => 'Fialová', 'AMBER' => 'Žlutá' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Neděle', 'Sun' => 'Ne', 'Monday' => 'Pondělí', 'Mon' => 'Po', 'Tuesday' => 'Úterý', 'Tue' => 'Út', 'Wednesday' => 'Středa', 'Wed' => 'St', 'Thursday' => 'Čtvrtek', 'Thu' => 'Čt', 'Friday' => 'Pátek', 'Fri' => 'Pá', 'Saturday' => 'Sobota', 'Sat' => 'So' ); %month = ( 'January' => 'Leden', 'February' => 'Únor', 'March' => 'Březen', 'Jan' => 'Leden', 'Feb' => 'Únor', 'Mar' => 'Březen', 'April' => 'Duben', 'May' => 'Květen', 'June' => 'Červen', 'Apr' => 'Duben', 'May' => 'Květen', 'Jun' => 'Červen', 'July' => 'Červenec','August' => 'Srpen', 'September' => 'Září', 'Jul' => 'Červenec','Aug' => 'Srpen', 'Sep' => 'Září', 'October' => 'Říjen', 'November' => 'Listopad', 'December' => 'Prosinec', 'Oct' => 'Říjen', 'Nov' => 'Listopad', 'Dec' => 'Prosinec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].",".$quux[1]." hod."; }; return "$wday{$foo[0]} $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; } # # Danish sub danish { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Maksimal indgående trafik i 5 minutter', 'Maximal 5 Minute Outgoing Traffic' => 'Maksimal udgående trafik i 5 minutter', 'the device' => 'enheden', 'The statistics were last updated(.*)' => 'Statistikken blev sidst opdateret$1', ' Average\)' => ' Middel)', 'Average' => 'Middel', 'Max' => 'Max', 'Current' => 'Nu', 'version' => 'version', '`Daily\' Graph \((.*) Minute' => '`Daglig\' graf ($1 minuts', '`Weekly\' Graph \(30 Minute' => '`Ugentlig\' graf (30 minuts' , '`Monthly\' Graph \(2 Hour' => '`Månedlig\' graf (2 times', '`Yearly\' Graph \(1 Day' => '`Årlig\' graf (1 dags', 'Incoming Traffic in (\S+) per Second' => 'Indgående trafik i $1 per sekund', 'Outgoing Traffic in (\S+) per Second' => 'Udgående trafik i $1 per sekund', 'at which time (.*) had been up for(.*)' => 'hvor $1 havde været oppe i$2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/t', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Ind', 'Out' => 'Ud', 'Percentage' => 'Procent', 'Ported to OpenVMS Alpha by' => 'Port til OpenVMS af', 'Ported to WindowsNT by' => 'Port til WindowsNT af', 'and' => 'og', '^GREEN' => 'GRØN', 'BLUE' => 'BLÅ', 'DARK GREEN' => 'MØRKEGRØN', 'MAGENTA' => 'LYSLILLA', 'AMBER' => 'RAV' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Søndag', 'Sun' => 'Søn', 'Monday' => 'Mandag', 'Mon' => 'Man', 'Tuesday' => 'Tirsdag', 'Tue' => 'Tir', 'Wednesday' => 'Onsdag', 'Wed' => 'Ons', 'Thursday' => 'Torsdag', 'Thu' => 'Tor', 'Friday' => 'Fredag', 'Fri' => 'Fre', 'Saturday' => 'Lørdag', 'Sat' => 'Lør' ); %month = ( 'January' => 'Januar', 'February' => 'Februar' , 'March' => 'Marts', 'Jan' => 'Jan', 'Feb' => 'Feb', 'Mar' => 'Mar', 'April' => 'April', 'May' => 'Maj', 'June' => 'Juni', 'Apr' => 'Apr', 'May' => 'Maj', 'Jun' => 'Jun', 'July' => 'Juli', 'August' => 'August', 'September' => 'September', 'Jul' => 'Jul', 'Aug' => 'Aug', 'Sep' => 'Sep', 'October' => 'Oktober', 'November' => 'November', 'December' => 'December', 'Oct' => 'Okt', 'Nov' => 'Nov', 'Dec' => 'Dec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." kl.".$quux[1]; }; return "$wday{$foo[0]} den $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Dutch sub dutch { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Maximaal inkomend verkeer per 5 minuten', 'Maximal 5 Minute Outgoing Traffic' => 'Maximaal uitgaand verkeer per 5 minuten', 'the device' => 'het apparaat', 'The statistics were last updated(.*)' => 'Statistieken voor het laatst bijgewerkt op$1', ' Average\)' => ' gemiddeld)', 'Average' => 'Gemiddeld', 'Max' => 'Max', 'Current' => 'Actueel', 'version' => 'versie', '`Daily\' Graph \((.*) Minute' => '`Dagelijkse\' grafiek ($1 minuten', '`Weekly\' Graph \(30 Minute' => '`Wekelijkse\' grafiek (30 minuten' , '`Monthly\' Graph \(2 Hour' => '`Maandelijkse\' grafiek (2 uur', '`Yearly\' Graph \(1 Day' => '`Jaarlijkse\' grafiek (1 dag', 'Incoming Traffic in (\S+) per Second' => 'Inkomend verkeer in $1 per seconde', 'Outgoing Traffic in (\S+) per Second' => 'Uitgaand verkeer in $1 per seconde', 'at which time (.*) had been up for(.*)' => 'op het moment dat $1 reeds actief was voor$2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/u', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' # ' In:' => ' In:', 'Out' => 'Uit', 'Percentage' => 'Procent', 'Ported to OpenVMS Alpha by' => 'Ported naar OpenVMS door', 'Ported to WindowsNT by' => 'Ported naar WindowsNT door', 'and' => 'en', 'DARK GREEN' => 'DONKER GROEN', '^GREEN' => 'GROEN', 'BLUE' => 'BLAUW', 'MAGENTA' => 'LILA', 'AMBER' => 'AMBER' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'zondag', 'Sun' => 'zon', 'Monday' => 'maandag', 'Mon' => 'maa', 'Tuesday' => 'dinsdag', 'Tue' => 'din', 'Wednesday' => 'woensdag', 'Wed' => 'woe', 'Thursday' => 'donderdag', 'Thu' => 'don', 'Friday' => 'vrijdag', 'Fri' => 'vri', 'Saturday' => 'zaterdag', 'Sat' => 'zat' ); %month = ( 'January' => 'januari', 'February' => 'februari', 'March' => 'maart', 'Jan' => 'jan', 'Feb' => 'feb', 'Mar' => 'mrt', 'April' => 'april', 'May' => 'mei', 'June' => 'juni', 'Apr' => 'apr', 'May' => 'mei', 'Jun' => 'jun', 'July' => 'juli', 'August' => 'augustus', 'September' => 'september', 'Jul' => 'jul', 'Aug' => 'aug', 'Sep' => 'sep', 'October' => 'oktober', 'November' => 'november', 'December' => 'december', 'Oct' => 'okt', 'Nov' => 'nov', 'Dec' => 'dec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." om".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Estonian sub estonian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => '5 minuti maksimaalne sisenev liiklus', 'Maximal 5 Minute Outgoing Traffic' => '5 minuti maksimaalne väljuv liiklus', 'the device' => 'seade', 'The statistics were last updated(.*)' => 'Statistikat uuendati viimati$1', ' Average\)' => ' keskmine)', 'Average' => 'Keskmine', #'Max' => 'Max', 'Current' => 'Hetkel', 'version' => 'versioon', '`Daily\' Graph \((.*) Minute' => '`Päevane\' graafik ($1 minuti', '`Weekly\' Graph \(30 Minute' => '`Nädala\' graafik (30 minuti' , '`Monthly\' Graph \(2 Hour' => '`Kuu \' graafik (2 tunni', '`Yearly\' Graph \(1 Day' => '`Aasta\' graafik (1 päeva', 'Incoming Traffic in (\S+) per Second' => 'Sisenev liiklus $1 sekundi kohta', 'Outgoing Traffic in (\S+) per Second' => 'Väljuv liiklus $1 sekundi kohta', 'at which time (.*) had been up for(.*)' => 'kui $1 on katkematult töötanud$2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/t', 'Bits' => 'bitti', 'Bytes' => 'baiti', 'In' => 'sisse', 'Out' => 'välja', 'Percentage' => 'protsent', 'Ported to OpenVMS Alpha by' => 'portis OpenVMS-le:', 'Ported to WindowsNT by' => 'portis WindowsNT-le:', 'and' => 'ja', '^GREEN' => 'ROHELINE', 'BLUE' => 'SININE', 'DARK GREEN' => 'TUMEROHELINE', 'MAGENTA' => 'LILLA', 'AMBER' => 'HELEROHELINE' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'pühapäev', 'Sun' => 'P', 'Monday' => 'esmaspäev', 'Mon' => 'E', 'Tuesday' => 'teisipäev', 'Tue' => 'T', 'Wednesday' => 'kolmapäev', 'Wed' => 'K', 'Thursday' => 'neljapäev', 'Thu' => 'N', 'Friday' => 'reede', 'Fri' => 'R', 'Saturday' => 'laupäev', 'Sat' => 'L' ); %month = ( 'January' => 'jaanuar', 'February' => 'veebruar' , 'March' => 'märts', 'Jan' => 'jaan', 'Feb' => 'veebr', 'Mar' => 'märts', 'April' => 'aprill', 'May' => 'mai', 'June' => 'juuni', 'Apr' => 'aprill', 'May' => 'mai', 'Jun' => 'juuni', 'July' => 'juuli', 'August' => 'august', 'September' => 'september', 'Jul' => 'juuli', 'Aug' => 'aug', 'Sep' => 'sept', 'October' => 'oktoober', 'November' => 'november', 'December' => 'detsember', 'Oct' => 'okt', 'Nov' => 'nov', 'Dec' => 'dets' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." kl.".$quux[1]; }; return "$wday{$foo[0]}, $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # eucjp sub eucjp { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( '^iso-8859-1' => 'euc-jp', '^Maximal 5 Minute Incoming Traffic' => '5ʬ', '^Maximal 5 Minute Outgoing Traffic' => '5ʬ', '^the device' => 'ǥХ', '^The statistics were last updated (.*)' => ' $1', '^Average\)' => 'ʿ)', '^Average$' => 'ʿ', '^Max$' => '', '^Current' => 'ǿ', '^`Daily\' Graph \((.*) Minute' => '($1ʬ', '^`Weekly\' Graph \(30 Minute' => '(30ʬ', '^`Monthly\' Graph \(2 Hour' => '(2', '^`Yearly\' Graph \(1 Day' => 'ǯ(1', '^Incoming Traffic in (\S+) per Second' => 'äμ$1', '^Incoming Traffic in (\S+) per Minute' => 'ʬμ$1', '^Incoming Traffic in (\S+) per Hour' => 'μ$1', '^Outgoing Traffic in (\S+) per Second' => 'ä$1', '^Outgoing Traffic in (\S+) per Minute' => 'ʬ$1', '^Outgoing Traffic in (\S+) per Hour' => '$1', '^at which time (.*) had been up for (.*)' => '$1βƯ $2', '^Average max 5 min values for `Daily\' Graph \((.*) Minute interval\):' => 'դǤκ5ʬͤʿ($1ʬֳ):', '^Average max 5 min values for `Weekly\' Graph \(30 Minute interval\):' => 'դǤκ5ʬͤʿ(30ʬֳ):', '^Average max 5 min values for `Monthly\' Graph \(2 Hour interval\):' => 'դǤκ5ʬͤʿ(2ֳִ):', '^Average max 5 min values for `Yearly\' Graph \(1 Day interval\):' => 'ǯդǤκ5ʬͤʿ(1ֳ):', #'^([kMG]?)([bB])/s' => '$1$2/', #'^([kMG]?)([bB])/min' => '$1$2/ʬ', #'^([kMG]?)([bB])/h' => '$1$2/', '^Bits$' => 'ӥå', '^Bytes$' => 'Х', '^In$' => '', '^Out$' => '', '^Percentage' => 'Ψ', '^Ported to OpenVMS Alpha by' => 'OpenVMS Alphaؤΰܿ', '^Ported to WindowsNT by' => 'WindowsNTؤΰܿ', #'^and' => 'and', '^GREEN' => '', '^BLUE' => '', '^DARK GREEN' => '', '^MAGENTA' => 'ޥ', '^AMBER' => '' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => '()', 'Monday' => '()', 'Tuesday' => '()', 'Wednesday' => '()', 'Thursday' => '()', 'Friday' => '()', 'Saturday' => '()', ); %month = ( 'January' => '1', 'February' => '2', 'March' => '3', 'April' => '4', 'May' => '5', 'June' => '6', 'July' => '7', 'August' => '8', 'September' => '9', 'October' => '10', 'November' => '11', 'December' => '12', ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)\s+(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~/at/) { @quux=split(/\s+at\s+/,$foo[3]); } else { @quux=split(/ /,$foo[3],2); }; return "$quux[0]ǯ$month{$foo[2]}$foo[1]$wday{$foo[0]} $quux[1]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Finnish sub finnish { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Tulevan liikenteen maksimi 5 minuutin aikana', 'Maximal 5 Minute Outgoing Traffic' => 'Lähtevän liikenteen maksimi 5 minuutin aikana', 'the device' => 'laite', 'The statistics were last updated(.*)' => 'Tiedot päivitetty viimeksi $1', ' Average\)' => '', 'Average' => 'Keskimäärin', 'Max' => 'Maksimi', 'Current' => 'Tällä hetkellä', 'version' => 'versio', '`Daily\' Graph \((.*) Minute' => 'Päiväraportti (skaala $1 minuutti(a))', '`Weekly\' Graph \(30 Minute' => 'Viikkoraportti (skaala 30 minuuttia)' , '`Monthly\' Graph \(2 Hour' => 'Kuukausiraportti (skaala 2 tuntia)', '`Yearly\' Graph \(1 Day' => 'Vuosiraportti (skaala 1 vuorokausi)', 'Incoming Traffic in (\S+) per Second' => 'Tuleva liikenne $1 sekunnissa', 'Outgoing Traffic in (\S+) per Second' => 'Lähtevä liikenne $1 sekunnissa', 'Incoming Traffic in (\S+) per Minute' => 'Tuleva liikenne $1 minuutissa', 'Outgoing Traffic in (\S+) per Minute' => 'Lähtevä liikenne $1 minuutissa', 'Incoming Traffic in (\S+) per Hour' => 'Tuleva liikenne $1 tunnissa', 'Outgoing Traffic in (\S+) per Hour' => 'Lähtevä liikenne $1 tunnissa', 'at which time (.*) had been up for(.*)' => 'jolloin $1 on toiminut yhtäjaksoisesti $2', '(\S+) per minute' => '$1 minuutissa', '(\S+) per hour' => '$1 tunnissa', '(.+)/s$' => '$1/s', # '(.+)/min' => '$1/min', #'(.+)/h$' => '$1/h', #'([kMG]?)([bB])/s' => '$1$2/s', #'([kMG]?)([bB])/min' => '$1$2/min', #'([kMG]?)([bB])/h' => '$1$2/h', 'Bits' => 'bittiä', 'Bytes' => 'tavua', 'In' => 'Tuleva', 'Out' => 'Lähtevä', 'Percentage' => 'Prosenttia', 'Ported to OpenVMS Alpha by' => 'OpenVMS -järjestelmälle sovittanut', 'Ported to WindowsNT by' => 'WindowsNT -järjestelmälle sovittanut', 'and' => 'ja', '^GREEN' => 'VIHREÄ', 'BLUE' => 'SININEN', 'DARK GREEN' => 'TUMMANVIHREÄ', 'MAGENTA' => 'PINKKI', 'AMBER' => 'PUNAINEN', ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Sunnuntai', 'Sun' => 'Su', 'Monday' => 'Maanantai', 'Mon' => 'Ma', 'Tuesday' => 'Tiistai', 'Tue' => 'Ti', 'Wednesday' => 'Keskiviikko', 'Wed' => 'Ke', 'Thursday' => 'Torstai', 'Thu' => 'To', 'Friday' => 'Perjantai', 'Fri' => 'Pe', 'Saturday' => 'Lauantai', 'Sat' => 'La' ); %month = ( 'January' => 'Tammi', 'February' => 'Helmi' , 'March' => 'Maalis', 'Jan' => 'Tam', 'Feb' => 'Hel', 'Mar' => 'Maa', 'April' => 'Huhti', 'May' => 'Touko', 'June' => 'Kesä', 'Apr' => 'Huh', 'May' => 'Tou', 'Jun' => 'Kes', 'July' => 'Heinä', 'August' => 'Elo', 'September' => 'Syys', 'Jul' => 'Hei', 'Aug' => 'Elo', 'Sep' => 'Syy', 'October' => 'Loka', 'November' => 'Marras', 'December' => 'Joulu', 'Oct' => 'Lok', 'Nov' => 'Mar', 'Dec' => 'Kou' ); # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if( $wday{$foo[0]} && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." kello ".$quux[1]; }; return "$wday{$foo[0]}, $foo[1]. $month{$foo[2]} $foo[3]"; }; # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # French sub french { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Trafic maximal en entrée sur 5 minutes', 'Maximal 5 Minute Outgoing Traffic' => 'Trafic maximal en sortie sur 5 minutes', 'the device' => 'le matériel', 'The statistics were last updated(.*)' => 'Les statistiques ont été mises à jour le $1', ' Average\)' => ' Moyenne)', 'Average' => 'Moyenne', '>Max' => 'Max', 'Current' => 'Actuel', #'version' => 'version', '`Daily\' Graph \((.*) Minute' => 'Graphique quotidien (sur $1 minutes :', '`Weekly\' Graph \(30 Minute' => 'Graphique hebdomadaire (sur 30 minutes :' , '`Monthly\' Graph \(2 Hour' => 'Graphique mensuel (sur 2 heures :', '`Yearly\' Graph \(1 Day' => 'Graphique annuel (sur 1 jour :', 'Incoming Traffic in (\S+) per Second' => 'Trafic d\'entrée en $1 par seconde', 'Outgoing Traffic in (\S+) per Second' => 'Trafic de sortie en $1 par seconde', 'at which time (.*) had been up for(.*)' => '$1 était alors en marche depuis $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/t', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Entrée', 'Out' => 'Sortie', 'Percentage' => 'Pourcentage', 'Ported to OpenVMS Alpha by' => 'Porté sur OpenVMS Alpha par', 'Ported to WindowsNT by' => 'Porté sur WindowsNT par', 'and' => 'et', '^GREEN' => 'VERT', 'BLUE' => 'BLEU', 'DARK GREEN' => 'VERT SOMBRE', 'MAGENTA' => 'MAGENTA', 'AMBER' => 'AMBRE' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Dimanche', 'Sun' => 'Dim', 'Monday' => 'Lundi', 'Mon' => 'Lun', 'Tuesday' => 'Mardi', 'Tue' => 'Mar', 'Wednesday' => 'Mercredi', 'Wed' => 'Mer', 'Thursday' => 'Jeudi', 'Thu' => 'Jeu', 'Friday' => 'Vendredi', 'Fri' => 'Ven', 'Saturday' => 'Samedi', 'Sat' => 'Sam' ); %month = ( 'January' => 'Janvier', 'February' => 'Février' , 'March' => 'Mars', 'Jan' => 'Jan', 'Feb' => 'Fev', 'Mar' => 'Mar', 'April' => 'Avril', 'May' => 'Mai', 'June' => 'Juin', 'Apr' => 'Avr', 'May' => 'Mai', 'Jun' => 'Jun', 'July' => 'Juillet', 'August' => 'Août', 'September' => 'Septembre', 'Jul' => 'Jul', 'Aug' => 'Aou', 'Sep' => 'Sep', 'October' => 'Octobre', 'November' => 'Novembre', 'December' => 'Décembre', 'Oct' => 'Oct', 'Nov' => 'Nov', 'Dec' => 'Dec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." à ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." à $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Galician sub galician { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Tr&áfico entrante máximo en 5 minutos', 'Maximal 5 Minute Outgoing Traffic' => 'Tr&áfico saínte máximo en 5 minutos', 'the device' => 'o dispositivo', 'The statistics were last updated(.*)' => 'Estas estatísticas actualizáronse o $1', ' Average\)' => ' de Media)', 'Average' => 'Media', 'Max' => 'Máx', 'Current' => 'Actual', 'version' => 'versión', '`Daily\' Graph \((.*) Minute' => 'Gráfica diaria ($1 minutos', '`Weekly\' Graph \(30 Minute' => 'Gráfica semanal (30 minutos' , '`Monthly\' Graph \(2 Hour' => 'Gráfica mensual (2 horas', '`Yearly\' Graph \(1 Day' => 'Gráfica anual (1 día', 'Incoming Traffic in (\S+) per Second' => 'Tráfico entrante en $1 por segundo', 'Outgoing Traffic in (\S+) per Second' => 'Tráfico saínte en $1 por segundo', 'at which time (.*) had been up for(.*)' => 'nese intre $1 levaba prendida $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/h', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Entrante', 'Out' => 'Saínte', 'Percentage' => 'Tanto por ciento', 'Ported to OpenVMS Alpha by' => 'Portado a OpenVMS Alpha por', 'Ported to WindowsNT by' => 'Portado a Windows NT por', 'and' => 'e', '^GREEN' => 'VERDE', 'BLUE' => 'AZUL', 'DARK GREEN' => 'VERDE OSCURO', 'MAGENTA' => 'ROSA', 'AMBER' => 'AMBAR' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Domingo', 'Sun' => 'Dom', 'Monday' => 'Luns', 'Mon' => 'Lun', 'Tuesday' => 'Martes', 'Tue' => 'Mar', 'Wednesday' => 'Mércores', 'Wed' => 'mér', 'Thursday' => 'Xoves', 'Thu' => 'Xov', 'Friday' => 'Venres', 'Fri' => 'Ven', 'Saturday' => 'Sábado', 'Sat' => 'Sáb' ); %month = ( 'January' => 'Xaneiro', 'February' => 'Febreiro' , 'March' => 'Marzo', 'Jan' => 'Xan', 'Feb' => 'Feb', 'Mar' => 'Mar', 'April' => 'Abril', 'May' => 'Maio', 'June' => 'Xuño', 'Apr' => 'Abr', 'May' => 'Mai', 'Jun' => 'Xuñ', 'July' => 'Xullo', 'August' => 'Agosto', 'September' => 'Setembro', 'Jul' => 'Xul', 'Aug' => 'Ago', 'Sep' => 'Set', 'October' => 'Outubro', 'November' => 'Novembro', 'December' => 'Decembro', 'Oct' => 'Out', 'Nov' => 'Nov', 'Dec' => 'Dec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." ás ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] de $month{$foo[2]} de $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Chinese gb Code sub gb { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'gb', 'Maximal 5 Minute Incoming Traffic' => '5', 'Maximal 5 Minute Outgoing Traffic' => '5', 'the device' => 'ǰ豸', 'The statistics were last updated(.*)' => 'ͳϢ: $1', ' Average\)' => 'ƽ)', 'Average' => 'ƽ', 'Max' => '', 'Current' => 'ǰ', 'version' => '汾', '`Daily\' Graph \((.*) Minute' => 'շͼ($1', '`Weekly\' Graph \(30 Minute' => 'ܷͼ(30' , '`Monthly\' Graph \(2 Hour' => '·ͼ(2Сʱ', '`Yearly\' Graph \(1 Day' => 'ͼ(1', 'Incoming Traffic in (\S+) per Second' => 'ÿ(λ$1)', 'Outgoing Traffic in (\S+) per Second' => 'ÿ(λ$1)', 'at which time (.*) had been up for(.*)' => 'ʱ $1Ѿ(UPTIME): $2', '([kMG]?)([bB])/s' => '$1$2/s', '([kMG]?)([bB])/min' => '$1$2/m', '([kMG]?)([bB])/h' => '$1$2/h', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => '', 'Out' => '', 'Percentage' => 'ٷֱ', 'Ported to OpenVMS Alpha by' => 'OpenVMSĶ˿', 'Ported to WindowsNT by' => 'WindowsNTĶ˿', 'and' => '', '^GREEN' => 'ɫ', 'BLUE' => 'ɫ', 'DARK GREEN' => '', 'MAGENTA' => 'ɫ', 'AMBER' => 'ɫ' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => '', 'Sun' => '', 'Monday' => 'һ', 'Mon' => 'һ@', 'Tuesday' => 'ܶ', 'Tue' => 'ܶG', 'Wednesday' => '', 'Wed' => 'T', 'Thursday' => '', 'Thu' => 'ĥ|', 'Friday' => '', 'Fri' => '', 'Saturday' => '', 'Sat' => '' ); %month = ( 'January' => '1', 'February' => '2', 'March' => '3', 'Jan' => '1', 'Feb' => '2', 'Mar' => '3', 'April' => '4', 'May' => '5', 'June' => '6', 'Apr' => '4', 'May' => '5', 'Jun' => '6', 'July' => '7', 'August' => '8', 'September' => '9', 'Jul' => '7', 'Aug' => '8', 'Sep' => '9', 'October' => '10', 'November' => '11', 'December' => '12', 'Oct' => '10', 'Nov' => '11', 'Dec' => '12' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { @quux=split(/at/,$foo[3]); if($foo[3]=~(/(.*)at(.*)/)) { $foo[3]=$quux[0]; $foo[4]=$quux[1]; }; return "$foo[3] $month{$foo[2]} $foo[1], $wday{$foo[0]}, $foo[4]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Chinese gb2312 Code sub gb2312 { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'gb2312', 'Maximal 5 Minute Incoming Traffic' => '5', 'Maximal 5 Minute Outgoing Traffic' => '5', 'the device' => 'װ', 'The statistics were last updated(.*)' => 'ϴͳƸʱ: $1', ' Average\)' => ' ƽ)', 'Average' => 'ƽ', 'Max' => '', 'Current' => 'Ŀǰ', 'version' => '汾', '`Daily\' Graph \((.*) Minute' => 'ÿ ͼ ($1 ', '`Weekly\' Graph \(30 Minute' => 'ÿ ͼ (30 ' , '`Monthly\' Graph \(2 Hour' => 'ÿ ͼ (2 Сʱ', '`Yearly\' Graph \(1 Day' => 'ÿ ͼ (1 ', 'Incoming Traffic in (\S+) per Second' => 'ÿ (λ $1)', 'Outgoing Traffic in (\S+) per Second' => 'ÿ (λ $1)', 'at which time (.*) had been up for(.*)' => '豸 $1ʱ(UPTIME): $2', '([kMG]?)([bB])/s' => '\$1\$2/', '([kMG]?)([bB])/min' => '\$1\$2/', '([kMG]?)([bB])/h' => '$1$2/ʱ', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => '', 'Out' => '', 'Percentage' => 'ٷֱ', 'Ported to OpenVMS Alpha by' => 'ֲ OpenVM Alpha ', 'Ported to WindowsNT by' => 'ֲ WindowsNT ', 'and' => '', '^GREEN' => 'ɫ', 'BLUE' => 'ɫ', 'DARK GREEN' => 'īɫ', 'MAGENTA' => 'ɫ', 'AMBER' => 'ɫ' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => '', 'Sun' => '', 'Monday' => 'һ', 'Mon' => 'һ', 'Tuesday' => 'ڶ', 'Tue' => '', 'Wednesday' => '', 'Wed' => '', 'Thursday' => '', 'Thu' => '', 'Friday' => '', 'Fri' => '', 'Saturday' => '', 'Sat' => '' ); %month = ( 'January' => 'һ', 'February' => '', 'March' => '', 'Jan' => 'һ', 'Feb' => '', 'Mar' => '', 'April' => '', 'May' => '', 'June' => '', 'Apr' => '', 'May' => '', 'Jun' => '', 'July' => '', 'August' => '', 'September' => '', 'Jul' => '', 'Aug' => '', 'Sep' => '', 'October' => 'ʮ', 'November' => 'ʮһ', 'December' => 'ʮ', 'Oct' => 'ʮ', 'Nov' => 'ʮһ', 'Dec' => 'ʮ' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { @quux=split(/at/,$foo[3]); if($foo[3]=~(/(.*)at(.*)/)) { $foo[3]=$quux[0]; $foo[4]=$quux[1]; }; return "$foo[3] $month{$foo[2]} $foo[1] , $wday{$foo[0]}, $foo[4]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # German sub german { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Maximaler hereinkommender Traffic in 5 Minuten', 'Maximal 5 Minute Outgoing Traffic' => 'Maximaler hinausgehender Traffic in 5 Minuten', 'the device' => 'das Gerät', 'The statistics were last updated(.*)' => 'Die Statistiken wurden am $1 zuletzt aktualisiert', ' Average\)' => '', 'Average' => 'Mittel', 'Max' => 'Maximal', 'Current' => 'Aktuell', 'version' => 'Version', '`Daily\' Graph \((.*) Minute' => 'Tagesübersicht (Skalierung $1 Minute(n)', '`Weekly\' Graph \(30 Minute' => 'Wochenübersicht (Skalierung 30 Minuten', '`Monthly\' Graph \(2 Hour' => 'Monatsübersicht (Skalierung 2 Stunden', '`Yearly\' Graph \(1 Day' => 'Jahresübersicht (Skalierung 1 Tag', 'Incoming Traffic in (\S+) per Second' => 'Hereinkommender Traffic in $1 pro Sekunde', 'Outgoing Traffic in (\S+) per Second' => 'Hinausgehender Traffic in $1 pro Sekunde', 'Incoming Traffic in (\S+) per Minute' => 'Hereinkommender Traffic in $1 pro Minute', 'Outgoing Traffic in (\S+) per Minute' => 'Hinausgehender Traffic in $1 pro Minute', 'Incoming Traffic in (\S+) per Hour' => 'Hereinkommender Traffic in $1 pro Stunde', 'Outgoing Traffic in (\S+) per Hour' => 'Hinausgehender Traffic in $1 pro Stunde', 'at which time (.*) had been up for(.*)' => 'zu diesem Zeitpunkt lief $1 seit $2', '(\S+) per minute' => '$1 pro Minute', '(\S+) per hour' => '$1 pro Stunde', '(.+)/s$' => '$1/s', # '(.+)/min' => '$1/min', '(.+)/h$' => '$1/std', #'([kMG]?)([bB])/s' => '$1$2/s', #'([kMG]?)([bB])/min' => '$1$2/min', #'([kMG]?)([bB])/h' => '$1$2/std', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Herein', 'Out' => 'Hinaus', 'Percentage' => 'Prozent', 'Ported to OpenVMS Alpha by' => 'Portierung nach OpenVMS von', 'Ported to WindowsNT by' => 'Portierung nach WindowsNT von', 'and' => 'und', '^GREEN' => 'GRÜN', 'BLUE' => 'BLAU', 'DARK GREEN' => 'DUNKELGRÜN', # 'MAGENTA' => 'ROSA', # 'AMBER' => 'AMBER', ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Sonntag', 'Sun' => 'So', 'Monday' => 'Montag', 'Mon' => 'Mo', 'Tuesday' => 'Dienstag', 'Tue' => 'Di', 'Wednesday' => 'Mittwoch', 'Wed' => 'Mi', 'Thursday' => 'Donnerstag', 'Thu' => 'Do', 'Friday' => 'Freitag', 'Fri' => 'Fr', 'Saturday' => 'Samstag', 'Sat' => 'Sa' ); %month = ( 'January' => 'Januar', 'February' => 'Februar' , 'March' => 'März', 'Jan' => 'Jan', 'Feb' => 'Feb', 'Mar' => 'Mär', 'April' => 'April', 'May' => 'Mai', 'June' => 'Juni', 'Apr' => 'Apr', 'May' => 'Mai', 'Jun' => 'Jun', 'July' => 'Juli', 'August' => 'August', 'September' => 'September', 'Jul' => 'Jul', 'Aug' => 'Aug', 'Sep' => 'Sep', 'October' => 'Oktober', 'November' => 'November', 'December' => 'Dezember', 'Oct' => 'Okt', 'Nov' => 'Nov', 'Dec' => 'Dez' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." um ".$quux[1]; }; return "$wday{$foo[0]}, den $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Greek sub greek { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'iso-8859-7', 'Maximal 5 Minute Incoming Traffic' => ' 5 ', 'Maximal 5 Minute Outgoing Traffic' => ' 5 ', 'the device' => ' ', 'The statistics were last updated(.*)' => ' ()/ $1', ' Average\)' => ' )', 'Average' => ' ', 'Max' => '', 'Current' => '', 'version' => '', '`Daily\' Graph \((.*) Minute' => ' ( $1 :', '`Weekly\' Graph \(30 Minute' => ' ( 30 :' , '`Monthly\' Graph \(2 Hour' => ' ( 2 :', '`Yearly\' Graph \(1 Day' => ' ( 1 :', 'Incoming Traffic in (\S+) per Second' => ' $1 ', 'Outgoing Traffic in (\S+) per Second' => ' $1 ', 'at which time (.*) had been up for(.*)' => ' $1 $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/t', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => '', 'Out' => '', 'Percentage' => '', 'Ported to OpenVMS Alpha by' => ' OpenVMS Alpha ', 'Ported to WindowsNT by' => ' WindowsNT ', 'and' => '', '^GREEN' => '', 'BLUE' => '', 'DARK GREEN' => ' ', 'MAGENTA' => '', 'AMBER' => '' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => '', 'Sun' => '', 'Monday' => '', 'Mon' => '', 'Tuesday' => '', 'Tue' => '', 'Wednesday' => '', 'Wed' => '', 'Thursday' => '', 'Thu' => '', 'Friday' => '', 'Fri' => '', 'Saturday' => '', 'Sat' => '' ); %month = ( 'January' => '', 'February' => '' , 'March' => '', 'Jan' => '', 'Feb' => '', 'Mar' => '', 'April' => '', 'May' => '', 'June' => '', 'Apr' => '', 'May' => '', 'Jun' => '', 'July' => '', 'August' => '', 'September' => '', 'Jul' => '', 'Aug' => '', 'Sep' => '', 'October' => '', 'November' => '', 'December' => '', 'Oct' => '', 'Nov' => '', 'Dec' => '' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." à $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Hungarian sub hungarian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-2', 'Maximal 5 Minute Incoming Traffic' => 'Maximális bejövõ forgalom 5 perc alatt', 'Maximal 5 Minute Outgoing Traffic' => 'Maximális kimenõ forgalom 5 perc alatt', 'the device' => 'az eszköz', 'The statistics were last updated(.*)' => 'A statisztika utolsó frissítése:$1', ' Average\)' => ' átlag)', 'Average' => 'Átlagos', 'Max' => 'Maximum', 'Current' => 'Pillanatnyi', 'version' => 'verzió', '`Daily\' Graph \((.*) Minute' => '`Napi\' grafikon ($1 perces', '`Weekly\' Graph \(30 Minute' => '`Heti\' grafikon (30 perces' , '`Monthly\' Graph \(2 Hour' => '`Havi\' grafikon (2 órás', '`Yearly\' Graph \(1 Day' => '`Éves\' grafikon (1 napos', 'Incoming Traffic in (\S+) per Second' => 'Bejövõ forgalom $1 per másodpercben', 'Outgoing Traffic in (\S+) per Second' => 'Kimenõ forgalom $1 per másodpercben', 'at which time (.*) had been up for(.*)' => 'amikor a $1 üzemideje $2 volt.', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/t', 'Bits' => 'Bit', 'Bytes' => 'Byte', 'In' => 'be', 'Out' => 'ki', 'Percentage' => 'százale´k', 'Ported to OpenVMS Alpha by' => 'OpenVMS-re portolta', 'Ported to WindowsNT by' => 'WindowsNT-re portolta', 'and' => 'és', '^GREEN' => 'ZÖLD', 'BLUE' => 'KÉK', 'DARK GREEN' => 'SÖTÉT ZÖLD', 'MAGENTA' => 'BÍBOR', 'AMBER' => 'SÁRGA' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'vasárnap', 'Sun' => 'vas', 'Monday' => 'hétfõ', 'Mon' => 'hét', 'Tuesday' => 'kedd', 'Tue' => 'kedd', 'Wednesday' => 'szerda', 'Wed' => 'sze', 'Thursday' => 'csütörtök','Thu' => 'csüt', 'Friday' => 'péntek', 'Fri' => 'pén', 'Saturday' => 'szombat', 'Sat' => 'szo' ); %month = ( 'January' => 'január', 'February' => 'február' , 'March' => 'március', 'Jan' => 'jan', 'Feb' => 'feb', 'Mar' => 'marc', 'April' => 'április', 'May' => 'május', 'June' => 'június', 'Apr' => 'apr', 'May' => 'maj', 'Jun' => 'jun', 'July' => 'július', 'August' => 'augusztus', 'September' => 'szeptember', 'Jul' => 'jul', 'Aug' => 'aug', 'Sep' => 'szept', 'October' => 'október', 'November' => 'november', 'December' => 'december', 'Oct' => 'okt', 'Nov' => 'nov', 'Dec' => 'dec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." kl.".$quux[1]; }; return "$quux[0]. $month{$foo[2]} $foo[1]., $wday{$foo[0]} $quux[1]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Icelandic sub icelandic { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Hámarks 5 mínútna umferð inn', 'Maximal 5 Minute Outgoing Traffic' => 'Hámarks 5 mínútna umferð út', 'the device' => 'tkið', 'The statistics were last updated(.*)' => 'Gögnin voru síðast uppfærð$1', ' Average\)' => ' Meðaltal)', 'Average' => 'Meðaltal', 'Max' => 'Hámark', 'Current' => 'Nú', 'version' => 'útgáfa', '`Daily\' Graph \((.*) Minute' => '`Dagleg\' staða ($1 mínútur', '`Weekly\' Graph \(30 Minute' => '`Vikuleg\' staða (30 mínútur', '`Monthly\' Graph \(2 Hour' => '`Mánaðarleg\' staða (2 klst.', '`Yearly\' Graph \(1 Day' => '`&Aarleg\' staða (1 dags', 'Incoming Traffic in (\S+) per Second' => 'Umferð inn í $1 á sekúndu', 'Outgoing Traffic in (\S+) per Second' => 'Umferð út í $1 á sekúndu', 'at which time (.*) had been up for(.*)' => 'þegar $1 hafði verið uppi í$2', # '([kMG]?)([bB])/s' => '\$1\$2/sek', # '([kMG]?)([bB])/min' => '\$1\$2/mín', '([kMG]?)([bB])/h' => '$1$2/klst', # 'Bits' => 'Bitar', # 'Bytes' => 'Bæti' 'In' => 'Inn', 'Out' => 'Út', 'Percentage' => 'Prósent', 'Ported to OpenVMS Alpha by' => 'Staðfært á OpenVMS af', 'Ported to WindowsNT by' => 'Staðfært á WindowsNT af', 'and' => 'og', '^GREEN' => 'GRÆNt', 'BLUE' => 'BLÁTT', 'DARK GREEN' => 'DÖKK GRÆNN', 'MAGENTA' => 'BLÁRAUÐUR', 'AMBER' => 'GULBRÚNN' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Sunnudagur', 'Sun' => 'Sun', 'Monday' => 'Mánudagur', 'Mon' => 'Mán', 'Tuesday' => 'Þriðjudagur', 'Tue' => 'Þri', 'Wednesday' => 'Miðvikudagur', 'Wed' => 'Mið', 'Thursday' => 'Fimmtudagur', 'Thu' => 'Fim', 'Friday' => 'Föstudagur', 'Fri' => 'Fös', 'Saturday' => 'Laugardagur', 'Sat' => 'Lau' ); %month = ( 'January' => 'Janúar', 'February' => 'Febrúar' , 'March' => 'Mars', 'Jan' => 'Jan', 'Feb' => 'Feb', 'Mar' => 'Mar', 'April' => 'Apríl', 'May' => 'Maí', 'June' => 'Júní', 'Apr' => 'Apr', 'May' => 'Maí', 'Jun' => 'Jún', 'July' => 'Júlí', 'August' => 'Ágúst', 'September' => 'September', 'Jul' => 'Júl', 'Aug' => 'Ágú', 'Sep' => 'Sep', 'October' => 'Október', 'November' => 'Nóvember', 'December' => 'Desember', 'Oct' => 'Okt', 'Nov' => 'Nóv', 'Dec' => 'Des' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." kl.".$quux[1]; }; return "$wday{$foo[0]} den $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Malaysian/Indonesian/Malay sub indonesia { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Trafik Masuk Maksimum dalam 5 Menit', 'Maximal 5 Minute Outgoing Traffic' => 'Trafik Keluar Maksimum dalam 5 Menit', 'the device' => 'device', 'The statistics were last updated(.*)' => 'Statistik ini terakhir kali diupdate pada $1', ' Average\)' => ')', 'Average' => 'Rata-rata', 'Max' => 'Maksimum', 'Current' => 'Sekarang', 'version' => 'versi', '`Daily\' Graph \((.*) Minute' => 'Grafik Harian (Rata-rata per $1 menit', '`Weekly\' Graph \(30 Minute' => 'Grafik Mingguan (Rata-rata per 30 menit', '`Monthly\' Graph \(2 Hour' => 'Grafik Bulanan (Rata-rata per 2 jam', '`Yearly\' Graph \(1 Day' => 'Grafik Tahunan (Rata-rata per hari', 'Incoming Traffic in (\S+) per Second' => 'Trafik Masuk $1 per detik', 'Outgoing Traffic in (\S+) per Second' => 'Trafik Keluar $1 per detik', 'at which time (.*) had been up for(.*)' => 'Pada saat $1 telah aktif selama $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/j', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Masuk', 'Out' => 'Keluar', 'Percentage' => 'Persentase', 'Ported to OpenVMS Alpha by' => 'Porting ke OpenVMS Alpha oleh', 'Ported to WindowsNT by' => 'Porting ke WindowsNT oleh', 'and' => 'dan', '^GREEN' => 'HIJAU', 'BLUE' => 'BIRU', 'DARK GREEN' => 'HIJAU GELAP', 'MAGENTA' => 'MAGENTA', 'AMBER' => 'AMBAR' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Ahad', 'Sun' => 'Aha', 'Monday' => 'Senin', 'Mon' => 'Sen', 'Tuesday' => 'Selasa', 'Tue' => 'Sel', 'Wednesday' => 'Rabu', 'Wed' => 'Rab', 'Thursday' => 'Kamis', 'Thu' => 'Kam', 'Friday' => 'Jumat', 'Fri' => 'Jum', 'Saturday' => 'Sabtu', 'Sat' => 'Sab' ); %month = ( 'January' => 'Januari', 'February' => 'Februari' , 'March' => 'Maret', 'Jan' => 'Jan', 'Feb' => 'Feb', 'Mar' => 'Mar', 'April' => 'April', 'May' => 'Mei', 'June' => 'Juni', 'Apr' => 'Apr', 'May' => 'Mei', 'Jun' => 'Jun', 'July' => 'Juli', 'August' => 'Agustus', 'September' => 'September', 'Jul' => 'Jul', 'Aug' => 'Ags', 'Sep' => 'Sep', 'October' => 'Oktober', 'November' => 'November', 'December' => 'Desember', 'Oct' => 'Okt', 'Nov' => 'Nov', 'Dec' => 'Des' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." pada ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # iso2022jp sub iso2022jp { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( '^iso-8859-1' => 'iso-2022-jp', '^Maximal 5 Minute Incoming Traffic' => '\e\\$B:GBg\e(B5\e\\$BJ, '\e\\$B:GBg\e(B5\e\\$BJ,Aw?.NL\e(B', '^the device' => '\e\\$B%G%P%\\$%9\e(B', '^The statistics were last updated (.*)' => '\e\\$B99?7F|;~\e(B $1', '^Average\)' => '\e\\$BJ?6Q\e(B)', '^Average$' => '\e\\$BJ?6Q\e(B', '^Max$' => '\e\\$B:GBg\e(B', '^Current' => '\e\\$B:G?7\e(B', '^`Daily\' Graph \((.*) Minute' => '\e\\$BF|%0%i%U\e(B($1\e\\$BJ,4V\e(B', '^`Weekly\' Graph \(30 Minute' => '\e\\$B=5%0%i%U\e(B(30\e\\$BJ,4V\e(B', '^`Monthly\' Graph \(2 Hour' => '\e\\$B7n%0%i%U\e(B(2\e\\$B;~4V\e(B', '^`Yearly\' Graph \(1 Day' => '\e\\$BG/%0%i%U\e(B(1\e\\$BF|\e(B', '^Incoming Traffic in (\S+) per Second' => '\e\\$BKhIC\\$N '\e\\$BKhJ,\\$N '\e\\$BKh;~\\$N '\e\\$BKhIC\\$NAw?.\e(B$1\e\\$B?t\e(B', '^Outgoing Traffic in (\S+) per Minute' => '\e\\$BKhJ,\\$NAw?.\e(B$1\e\\$B?t\e(B', '^Outgoing Traffic in (\S+) per Hour' => '\e\\$BKh;~\\$NAw?.\e(B$1\e\\$B?t\e(B', '^at which time (.*) had been up for (.*)' => '$1\e\\$B\\$N2TF/;~4V\e(B $2', '^Average max 5 min values for `Daily\' Graph \((.*) Minute interval\):' => '\e\\$BF|%0%i%U\\$G\\$N:GBg\e(B5\e\\$BJ,CM\\$NJ?6Q\e(B($1\e\\$BJ,4V3V\e(B):', '^Average max 5 min values for `Weekly\' Graph \(30 Minute interval\):' => '\e\\$B=5%0%i%U\\$G\\$N:GBg\e(B5\e\\$BJ,CM\\$NJ?6Q\e(B(30\e\\$BJ,4V3V\e(B):', '^Average max 5 min values for `Monthly\' Graph \(2 Hour interval\):' => '\e\\$B7n%0%i%U\\$G\\$N:GBg\e(B5\e\\$BJ,CM\\$NJ?6Q\e(B(2\e\\$B;~4V4V3V\e(B):', '^Average max 5 min values for `Yearly\' Graph \(1 Day interval\):' => '\e\\$BG/%0%i%U\\$G\\$N:GBg\e(B5\e\\$BJ,CM\\$NJ?6Q\e(B(1\e\\$BF|4V3V\e(B):', #'^([kMG]?)([bB])/s' => '$1$2/\e\\$BIC\e(B', #'^([kMG]?)([bB])/min' => '$1$2/\e\\$BJ,\e(B', #'^([kMG]?)([bB])/h' => '$1$2/\e\\$B;~\e(B', '^Bits$' => '\e\\$B%S%C%H\e(B', '^Bytes$' => '\e\\$B%P%\\$%H\e(B', '^In$' => '\e\\$B '\e\\$BAw?.\e(B', '^Percentage' => '\e\\$BHfN(\e(B', '^Ported to OpenVMS Alpha by' => 'OpenVMS Alpha\e\\$B\\$X\\$N0\\\?"\e(B', '^Ported to WindowsNT by' => 'WindowsNT\e\\$B\\$X\\$N0\\\?"\e(B', #'^and' => 'and', '^GREEN' => '\e\\$BNP\e(B', '^BLUE' => '\e\\$B\\@D\e(B', '^DARK GREEN' => '\e\\$B? '\e\\$B%^%<%s%?\e(B', '^AMBER' => '\e\\$B`h`a\e(B' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => "(\e\$BF|\e(B)", 'Monday' => "(\e\$B7n\e(B)", 'Tuesday' => "(\e\$B2P\e(B)", 'Wednesday' => "(\e\$B?e\e(B)", 'Thursday' => "(\e\$BLZ\e(B)", 'Friday' => "(\e\$B6b\e(B)", 'Saturday' => "(\e\$BEZ\e(B)", ); %month = ( 'January' => "1\e\$B7n\e(B", 'February' => "2\e\$B7n\e(B", 'March' => "3\e\$B7n\e(B", 'April' => "4\e\$B7n\e(B", 'May' => "5\e\$B7n\e(B", 'June' => "6\e\$B7n\e(B", 'July' => "7\e\$B7n\e(B", 'August' => "8\e\$B7n\e(B", 'September' => "9\e\$B7n\e(B", 'October' => "10\e\$B7n\e(B", 'November' => "11\e\$B7n\e(B", 'December' => "12\e\$B7n\e(B", ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)\s+(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~/at/) { @quux=split(/\s+at\s+/,$foo[3]); } else { @quux=split(/ /,$foo[3],2); }; return "$quux[0]\e\$BG/\e(B$month{$foo[2]}$foo[1]\e\$BF|\e(B$wday{$foo[0]} $quux[1]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Italian sub italian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Traffico massimo in entrata su 5 minuti', 'Maximal 5 Minute Outgoing Traffic' => 'Traffico massimo in uscita su 5 minuti', 'the device' => 'Il dispositivo', 'The statistics were last updated(.*)' => 'Le statistiche l\' ultima volta sono state aggiornate $1', ' Average\)' => ' Media)', 'Average' => 'Media', 'Max' => 'Max', 'Current' => 'Attuale', 'version' => 'versione', '`Daily\' Graph \((.*) Minute' => 'Grafico giornaliero (su $1 minuti:', '`Weekly\' Graph \(30 Minute' => 'Grafico settimanale (su 30 minuti:' , '`Monthly\' Graph \(2 Hour' => 'Grafico mensile (su 2 ore:', '`Yearly\' Graph \(1 Day' => 'Grafico annuale (su 1 giorno:', 'Incoming Traffic in (\S+) per Second' => 'Traffico in ingresso in $1 per Secondo', 'Outgoing Traffic in (\S+) per Second' => 'Traffico in uscita in $1 per Secondo', 'Incoming Traffic in (\S+) per Minute' => 'Traffico in ingresso in $1 per Minuto', 'Outgoing Traffic in (\S+) per Minute' => 'Traffico in uscita $1 per Minuto', 'Incoming Traffic in (\S+) per Hour' => 'Traffico in ingresso $1 per Ora', 'Outgoing Traffic in (\S+) per Hour' => 'Traffico in uscita $1 per Ora', 'at which time (.*) had been up for(.*)' => '$1 é attivo da $2', '(\S+) per minute' => '$1 per Minuto', '(\S+) per hour' => '$1 per Ora', '(.+)/s$' => '$1/s', # '(.+)/min' => '$1/min', '(.+)/h$' => '$1/ora', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', # '([kMG]?)([bB])/h' => '$1$2/t', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Ingresso', 'Out' => 'Uscita', 'Percentage' => 'Percentuale', 'Ported to OpenVMS Alpha by' => 'Ported su OpenVMS Alpha da', 'Ported to WindowsNT by' => 'Ported su WindowsNT da', 'and' => 'e', '^GREEN' => 'VERDE', 'BLUE' => 'BLU', 'DARK GREEN' => 'VERDE SCURO', #'MAGENTA' => 'MAGENTA', #'AMBER' => 'AMBRA' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Domenica', 'Sun' => 'Dom', 'Monday' => 'Lunedi', 'Mon' => 'Lun', 'Tuesday' => 'Martedi', 'Tue' => 'Mar', 'Wednesday' => 'Mercoledi', 'Wed' => 'Mer', 'Thursday' => 'Giovedi', 'Thu' => 'Gio', 'Friday' => 'Venerdi', 'Fri' => 'Ven', 'Saturday' => 'Sabato', 'Sat' => 'Sab' ); %month = ( 'January' => 'Gennaio', 'February' => 'Febbraio' , 'March' => 'Marzo', 'Jan' => 'Gen', 'Feb' => 'Feb', 'Mar' => 'Mar', 'April' => 'Aprile', 'May' => 'Maggio', 'June' => 'Giugno', 'Apr' => 'Apr', 'May' => 'Mag', 'Jun' => 'Giu', 'July' => 'Luglio', 'August' => 'Agosto', 'September' => 'Settembre', 'Jul' => 'Lug', 'Aug' => 'Ago', 'Sep' => 'Set', 'October' => 'Ottobre', 'November' => 'Novembre', 'December' => 'Dicembre', 'Oct' => 'Ott', 'Nov' => 'Nov', 'Dec' => 'Dic' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." alle ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." à $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Korean sub korean { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'euc-kr', 'Maximal 5 Minute Incoming Traffic' => '5а ִ ', 'Maximal 5 Minute Outgoing Traffic' => '5а ִ ۽', 'the device' => 'ġ', 'The statistics were last updated(.*)' => ' Ͻ: $1', ' Average\)' => ' հ )', 'Average' => '', 'Max' => 'ִ', 'Current' => '', 'version' => '', '`Daily\' Graph \((.*) Minute' => 'ϰ ׷ ($1 ', '`Weekly\' Graph \(30 Minute' => 'ְ ׷ (30 ' , '`Monthly\' Graph \(2 Hour' => ' ׷ (2 ð ', '`Yearly\' Graph \(1 Day' => ' ׷ (1 ', 'Incoming Traffic in (\S+) per Second' => 'ʴ ŵ Ʈ ($1)', 'Outgoing Traffic in (\S+) per Second' => 'ʴ ۽ŵ Ʈ ($1)', 'at which time (.*) had been up for(.*)' => '$1 ð: $2', '([kMG]?)([bB])/s' => '$1$2/', '([kMG]?)([bB])/min' => '$1$2/', '([kMG]?)([bB])/h' => '$1$2/', 'Bits' => 'Ʈ', 'Bytes' => 'Ʈ', 'In' => '', 'Out' => '۽', 'Percentage' => 'ۼƮ', 'Ported to OpenVMS Alpha by' => 'OpenVMS Alpha ', 'Ported to WindowsNT by' => 'WindowsNT ', 'and' => '', '^GREEN' => '', 'BLUE' => 'û', 'DARK GREEN' => 'ѳ', 'MAGENTA' => 'ȫ', 'AMBER' => 'Ȳ' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Ͽ', 'Sun' => '', 'Monday' => '', 'Mon' => '', 'Tuesday' => 'ȭ', 'Tue' => 'ȭ', 'Wednesday' => '', 'Wed' => '', 'Thursday' => '', 'Thu' => '', 'Friday' => 'ݿ', 'Fri' => '', 'Saturday' => '', 'Sat' => '' ); %month = ( 'January' => '1', 'February' => '2' , 'March' => '3', 'Jan' => '1', 'Feb' => '2', 'Mar' => '3', 'April' => '4', 'May' => '5', 'June' => '6', 'Apr' => '4', 'May' => '5', 'Jun' => '6', 'July' => '7', 'August' => '8', 'September' => '9', 'Jul' => '7', 'Aug' => '8', 'Sep' => '9', 'October' => '10', 'November' => '11', 'December' => '12', 'Oct' => '10', 'Nov' => '11', 'Dec' => '12' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); # $foo[3]=$quux[0]." kl.".$quux[1]; $foo[3]=$quux[0]; $foo[4]=$quux[1]; }; return $foo[3]." $month{$foo[2]} $foo[1] $wday{$foo[0]} $foo[4]"; # return "$wday{$foo[0]} den $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Lithuanian sub lithuanian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'windows-1257', 'Maximal 5 Minute Incoming Traffic' => 'Maksimalus 5 minui einantis srautas', 'Maximal 5 Minute Outgoing Traffic' => 'Maksimalus 5 minui ieinantis srautas', 'the device' => 'renginys', 'The statistics were last updated(.*)' => 'Statistika atnaujinta$1', ' Average\)' => ' vidurkis)', 'Average' => 'vid', 'Max' => 'max', 'Current' => 'dabar', 'version' => 'versija', '`Daily\' Graph \((.*) Minute' => '\'dienos\' grafikas ($1 min.', '`Weekly\' Graph \(30 Minute' => '\'savaits\' grafikas (30 min.' , '`Monthly\' Graph \(2 Hour' => '\'mnesio\' grafikas (2 val.', '`Yearly\' Graph \(1 Day' => '\'met\' grafikas (1 d.', 'Incoming Traffic in (\S+) per Second' => 'einantis srautas, $1 per sekund', 'Outgoing Traffic in (\S+) per Second' => 'Ieinantis srautas i $1 per sekund', 'at which time (.*) had been up for(.*)' => '$1 veikia jau $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', # '([kMG]?)([bB])/h' => '$1$2/h', 'Bits' => 'bitai', 'Bytes' => 'baitai', 'In' => '', 'Out' => 'i', 'Percentage' => 'procentai', 'Ported to OpenVMS Alpha by' => 'Perkl OpenVMS Alpha:', 'Ported to WindowsNT by' => 'Perkl WindowsNT:', 'and' => 'ir', '^GREEN' => 'ALIA ', 'BLUE' => 'MLYNA ', 'DARK GREEN' => 'TAMSIAI ALIA ', 'MAGENTA' => 'RAUDONA ', 'AMBER' => 'GINTARIN ' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'sekmadien', 'Sun' => 'Sek', 'Monday' => 'pirmadien', 'Mon' => 'Pir', 'Tuesday' => 'antradien', 'Tue' => 'Ant', 'Wednesday' => 'treiadien', 'Wed' => 'Tre', 'Thursday' => 'ketvirtadien', 'Thu' => 'Ket', 'Friday' => 'penktadien', 'Fri' => 'Pen', 'Saturday' => 'etadien', 'Sat' => 'e' ); %month = ( 'January' => 'sausio', 'February' => 'vasario' , 'March' => 'kovo', 'Jan' => 'Sau', 'Feb' => 'Vas', 'Mar' => 'Kov', 'April' => 'balandio', 'May' => 'gegus', 'June' => 'birelio', 'Apr' => 'Bal', 'May' => 'Geg', 'Jun' => 'Bir', 'July' => 'liepos', 'August' => 'rugpjio', 'September' => 'rugsjo', 'Jul' => 'Lie', 'Aug' => 'Rgp', 'Sep' => 'Rgs', 'October' => 'spalio', 'November' => 'lapkriio', 'December' => 'gruodio', 'Oct' => 'Spa', 'Nov' => 'Lap', 'Dec' => 'Gru' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[1].", ".$quux[0]; }; return "$foo[3] $month{$foo[2]} $foo[1], $wday{$foo[0]}" ; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Macedonian sub macedonian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=windows-1251', 'Maximal 5 Minute Incoming Traffic' => ' 5 ', 'Maximal 5 Minute Outgoing Traffic' => ' 5 ', 'the device' => '', 'The statistics were last updated(.*)' => ' $1', ' Average\)' => ' )', 'Average' => '', 'Max' => '', 'Current' => 'o', 'version' => '', '`Daily\' Graph \((.*) Minute' => '`\' ($1 ', '`Weekly\' Graph \(30 Minute' => '`\' (30 ' , '`Monthly\' Graph \(2 Hour' => '`\' (2 ', '`Yearly\' Graph \(1 Day' => '`\' (1 ', 'Incoming Traffic in (\S+) per Second' => ' - $1 ', 'Outgoing Traffic in (\S+) per Second' => ' - $1 ', 'at which time (.*) had been up for(.*)' => ' $1 : $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/h', # 'Bits' => '', # 'Bytes' => '' 'In' => '', 'Out' => '', 'Percentage' => '', 'Ported to OpenVMS Alpha by' => ' OpenVMS ', 'Ported to WindowsNT by' => ' WindowsNT ', 'and' => '', '^GREEN' => '', 'BLUE' => '', 'DARK GREEN' => ' ', 'MAGENTA' => '', 'AMBER' => '' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => '', 'Sun' => '', 'Monday' => '', 'Mon' => '', 'Tuesday' => '', 'Tue' => '', 'Wednesday' => '', 'Wed' => '', 'Thursday' => '', 'Thu' => '', 'Friday' => '', 'Fri' => '', 'Saturday' => '', 'Sat' => '' ); %month = ( 'January' => '', 'February' => '' , 'March' => '', 'Jan' => '', 'Feb' => '', 'Mar' => '', 'April' => '', 'May' => '', 'June' => '', 'Apr' => '', 'May' => '', 'Jun' => '', 'July' => '', 'August' => '', 'September' => '', 'Jul' => '', 'Aug' => '', 'Sep' => '', 'October' => '', 'November' => '', 'December' => '', 'Oct' => '', 'Nov' => '', 'Dec' => '' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." kl.".$quux[1]; }; return "$wday{$foo[0]} $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; };# Malaysian/Malay sub malay { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Maksimum 5 Minit Trafik Masuk', 'Maximal 5 Minute Outgoing Traffic' => 'Maksimum 5 Minit Trafik Keluar', 'the device' => 'alatan', 'The statistics were last updated(.*)' => 'Statistik ini kali terakhir dikemaskini pada $1', ' Average\)' => ' secara purata)', 'Average' => 'Purata', 'Max' => 'Maksimum', 'Current' => 'Kini', 'version' => 'versi', '`Daily\' Graph \((.*) Minute' => 'Graf `Harian\' ($1 minit :', '`Weekly\' Graph \(30 Minute' => 'Graf `Mingguan\' (30 minit :' , '`Monthly\' Graph \(2 Hour' => 'Graf `Bulanan\' (2 jam :', '`Yearly\' Graph \(1 Day' => 'Graf `Tahunan\' (1 hari :', 'Incoming Traffic in (\S+) per Second' => 'Trafik Masuk $1 per saat', 'Outgoing Traffic in (\S+) per Second' => 'Traffic Keluar $1 per saat', 'at which time (.*) had been up for(.*)' => 'Sehingga waktu $1 ia telah aktif selama $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/j', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Masuk', 'Out' => 'Keluar', 'Percentage' => 'Peratus', 'Ported to OpenVMS Alpha by' => 'Pengubahsuaian ke OpenVMS Alpha oleh', 'Ported to WindowsNT by' => 'Pengubahsuaian ke WindowsNT oleh', 'and' => 'dan', '^GREEN' => 'HIJAU', 'BLUE' => 'BIRU', 'DARK GREEN' => 'HIJAU GELAP', 'MAGENTA' => 'MAGENTA', 'AMBER' => 'AMBAR' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Ahad', 'Sun' => 'Aha', 'Monday' => 'Isnin', 'Mon' => 'Isn', 'Tuesday' => 'Selasa', 'Tue' => 'Sel', 'Wednesday' => 'Rabu', 'Wed' => 'Rab', 'Thursday' => 'Khamis', 'Thu' => 'Kha', 'Friday' => 'Jumaat', 'Fri' => 'Jum', 'Saturday' => 'Sabtu', 'Sat' => 'Sab' ); %month = ( 'January' => 'Januari', 'February' => 'Februari' , 'March' => 'Mac', 'Jan' => 'Jan', 'Feb' => 'Feb', 'Mar' => 'Mac', 'April' => 'April', 'May' => 'Mei', 'June' => 'Jun', 'Apr' => 'Apr', 'May' => 'Mei', 'Jun' => 'Jun', 'July' => 'Julai', 'August' => 'Ogos', 'September' => 'September', 'Jul' => 'Jul', 'Aug' => 'Ogo', 'Sep' => 'Sep', 'October' => 'Oktober', 'November' => 'November', 'December' => 'Disember', 'Oct' => 'Okt', 'Nov' => 'Nov', 'Dec' => 'Dis' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." pada ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Norwegian sub norwegian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Maksimal inngående trafikk i 5 minutter', 'Maximal 5 Minute Outgoing Traffic' => 'Maksimal utgående trafikk i 5 minutter', 'the device' => 'enhetden', 'The statistics were last updated(.*)' => 'Statistikken ble sist oppdatert $1', ' Average\)' => ' gjennomsnitt)', 'Average' => 'Gjennomsnitt', 'Max' => 'Max', 'Current' => 'Nå', 'version' => 'versjon', '`Daily\' Graph \((.*) Minute' => '`Daglig\' graf ($1 minutts', '`Weekly\' Graph \(30 Minute' => '`Ukentlig\' graf (30 minutts' , '`Monthly\' Graph \(2 Hour' => '`Månedlig\' graf (2 times', '`Yearly\' Graph \(1 Day' => '`Årlig\' graf (1 dags', 'Incoming Traffic in (\S+) per Second' => 'Inngående trafikk i $1 per sekund', 'Outgoing Traffic in (\S+) per Second' => 'Utgående trafikk i $1 per sekund', 'at which time (.*) had been up for(.*)' => 'hvor $1 hadde vært oppe i $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/t', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Inn', 'Out' => 'Ut', 'Percentage' => 'Prosent', 'Ported to OpenVMS Alpha by' => 'Port til OpenVMS av', 'Ported to WindowsNT by' => 'Port til WindowsNT av', 'and' => 'og', '^GREEN' => 'GRØNN', 'BLUE' => 'BLÅ', 'DARK GREEN' => 'MØRKEGRØNN', 'MAGENTA' => 'MAGENTA', 'AMBER' => 'GUL' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Søndag', 'Sun' => 'Søn', 'Monday' => 'Mandag', 'Mon' => 'Man', 'Tuesday' => 'Tirsdag', 'Tue' => 'Tir', 'Wednesday' => 'Onsdag', 'Wed' => 'Ons', 'Thursday' => 'Torsdag', 'Thu' => 'Tor', 'Friday' => 'Fredag', 'Fri' => 'Fre', 'Saturday' => 'Lørdag', 'Sat' => 'Lør' ); %month = ( 'January' => 'Januar', 'February' => 'Februar' , 'March' => 'Mars', 'Jan' => 'Jan', 'Feb' => 'Feb', 'Mar' => 'Mar', 'April' => 'April', 'May' => 'Mai', 'June' => 'Juni', 'Apr' => 'Apr', 'May' => 'Mai', 'Jun' => 'Jun', 'July' => 'Juli', 'August' => 'August', 'September' => 'September', 'Jul' => 'Jul', 'Aug' => 'Aug', 'Sep' => 'Sep', 'October' => 'Oktober', 'November' => 'November', 'December' => 'Desember', 'Oct' => 'Okt', 'Nov' => 'Nov', 'Dec' => 'Des' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." kl.".$quux[1]; }; return "$wday{$foo[0]} den $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; sub polish { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'iso-8859-2', 'Maximal 5 Minute Incoming Traffic' => 'Maksymalny ruch przychodzcy w cigu 5 minut', 'Maximal 5 Minute Outgoing Traffic' => 'Maksymalny ruch wychodzcy w cigu 5 minut', 'the device' => 'urzdzenie', 'The statistics were last updated(.*)' => 'Ostatnie uaktualnienie statystyki $1', ' Average\)' => ' rednia)', 'Average' => 'rednio', 'Max' => 'Maksymalnie', 'Current' => 'Aktualnie', 'version' => 'wersja', '`Daily\' Graph \((.*) Minute' => '`Dzienny\' Graf w cigu ($1 Minut/y - ', '`Weekly\' Graph \(30 Minute' => '`Tygodniowy\' Graf w cigu (30 minut - ' , '`Monthly\' Graph \(2 Hour' => '`Miesiczny\' Graf w cigu (2 Godzin - ', '`Yearly\' Graph \(1 Day' => '`Roczny\' Graf w cigu (1 Dnia - ', 'Incoming Traffic in (\S+) per Second' => 'Ruch przychodzcy - $1 na sekund', 'Outgoing Traffic in (\S+) per Second' => 'Ruch wychodzcy - $1 na sekund', 'at which time (.*) had been up for(.*)' => 'gdy $1 by wczony przez $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/g', 'Bits' => 'Bity', 'Bytes' => 'Bajty', 'In' => 'Do', 'Out' => 'Z', 'Percentage' => 'Procent', 'Ported to OpenVMS Alpha by' => 'Port dla OpenVMS Alpha dziki', 'Ported to WindowsNT by' => 'Port dla WindowsNT dziki', 'and' => 'i', '^GREEN' => 'ZIELONY', 'BLUE' => 'NIEBIESKI', 'DARK GREEN' => 'CIEMNO ZIELONY', 'MAGENTA' => 'KARMAZYNOWY', 'AMBER' => 'BURSZTYNOWY' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Niedziela', 'Sun' => 'Nie', 'Monday' => 'Poniedziaek', 'Mon' => 'Pon', 'Tuesday' => 'Wtorek', 'Tue' => 'Wto', 'Wednesday' => 'roda', 'Wed' => 'ro', 'Thursday' => 'Czwartek', 'Thu' => 'Czw', 'Friday' => 'Pitek', 'Fri' => 'Pi', 'Saturday' => 'Sobota', 'Sat' => 'Sob' ); %month = ( 'January' => 'Stycznia', 'February' => 'Lutego', 'March' => 'Marca', 'Jan' => 'Sty', 'Feb' => 'Lut', 'Mar' => 'Mar', 'April' => 'Kwietnia', 'May' => 'Maja', 'June' => 'Czerwca', 'Apr' => 'Kwi', 'May' => 'Maj', 'Jun' => 'Cze', 'July' => 'Lipca', 'August' => 'Sierpnia', 'September' => 'Wrzenia', 'Jul' => 'Lip', 'Aug' => 'Sie', 'Sep' => 'Wrz', 'October' => 'Padziernika', 'November' => 'Listopada', 'December' => 'Grudnia', 'Oct' => 'Pa', 'Nov' => 'Lis', 'Dec' => 'Gru' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." o godzinie".$quux[1]; }; return "$wday{$foo[0]} dzie $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Português sub portuguese { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Tráfego Maximal Recebido em 5 minutos', 'Maximal 5 Minute Outgoing Traffic' => 'Tráfego Maximal Enviado em 5 minutos', 'the device' => 'o dispositivo', 'The statistics were last updated(.*)' => 'As Estatísticas foram actualizadas pela última vez na $1', ' Average\)
' => '', 'Average' => 'Média', 'Max' => 'Max.', 'Current' => 'Actual', 'version' => 'Versão', '`Daily\' Graph \((.*) Minute' => 'Gráfico Diário (em intervalos de $1 Minutos)

', '`Weekly\' Graph \(30 Minute' => 'Gráfico Semanal (em intervalos de 30 Minutos)' , '`Monthly\' Graph \(2 Hour' => 'Gráfico Mensal (em intervalos de 2 horas)', '`Yearly\' Graph \(1 Day' => 'Gráfico Anual (em intervalos de 24 horas)', 'Incoming Traffic in (\S+) per Second' => 'Tráfego recebido em $1/segundo', 'Outgoing Traffic in (\S+) per Second' => 'Tráfego enviado em $1/segundo', 'Incoming Traffic in (\S+) per Minute' => 'Tráfego recebido em $1/minuto', 'Outgoing Traffic in (\S+) per Minute' => 'Tráfego enviado em $1/minuto', 'Incoming Traffic in (\S+) per Hour' => 'Tráfego recebido em $1/hora', 'Outgoing Traffic in (\S+) per Hour' => 'Tráfego recebido em $1/hora', 'at which time (.*) had been up for(.*)' => 'quando o $1, tinha um uptime de $2', '(\S+) per minute' => '$1/minuto', '(\S+) per hour' => '$1/hora', '(.+)/s$' => '$1/s', # '(.+)/min' => '$1/min', '(.+)/h$' => '$1/h', #'([kMG]?)([bB])/s' => '$1$2/s', #'([kMG]?)([bB])/min' => '$1$2/min', #'([kMG]?)([bB])/h' => '$1$2/h', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Rec.', 'Out' => 'Env.', 'Percentage' => 'Perc.', 'Ported to OpenVMS Alpha by' => 'Portado para OpenVMS Alpha por', 'Ported to WindowsNT by' => 'Portado para WindowsNT por', 'and' => 'e', '^GREEN' => 'VERDE', 'BLUE' => 'AZUL', 'DARK GREEN' => 'VERDE ESCURO', # 'MAGENTA' => 'MAGENTA', # 'AMBER' => 'AMBAR', ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Domingo', 'Sun' => 'Dom', 'Monday' => 'Segunda-Feira', 'Mon' => 'Seg', 'Tuesday' => 'Terça-Feira', 'Tue' => 'Ter', 'Wednesday' => 'Quarta-Feira', 'Wed' => 'Qua', 'Thursday' => 'Quinta-Feira', 'Thu' => 'Qui', 'Friday' => 'Sexta-Feira', 'Fri' => 'Sex', 'Saturday' => 'Sábado', 'Sat' => 'Sab' ); %month = ( 'January' => 'Janeiro', 'February' => 'Fevereiro' , 'March' => 'Março', 'Jan' => 'Jan', 'Feb' => 'Fev', 'Mar' => 'Mar', 'April' => 'Abril', 'May' => 'Maio', 'June' => 'Junho', 'Apr' => 'Abr', 'May' => 'Mai', 'Jun' => 'Jun', 'July' => 'Julho', 'August' => 'Agosto', 'September' => 'Setembro', 'Jul' => 'Jul', 'Aug' => 'Ago', 'Sep' => 'Set', 'October' => 'Outubro', 'November' => 'Novembro', 'December' => 'Dezembro', 'Oct' => 'Out', 'Nov' => 'Nov', 'Dec' => 'Dez' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." pelas ".$quux[1]; }; return "$wday{$foo[0]}, $foo[1] de $month{$foo[2]} de $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Romanian sub romanian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-8859-2 %translations = ( 'iso-8859-1' => 'iso-8859-2', 'Maximal 5 Minute Incoming Traffic' => 'Traficul Maxim de intrare pe 5 Minute', 'Maximal 5 Minute Outgoing Traffic' => 'Traficul Maxim de iesire pe 5 Minute', 'the device' => 'echipamentul', 'The statistics were last updated(.*)' => 'Ultima actualizare :$1', ' Average\)' => '', 'Average' => 'Medie', 'Max' => 'Maxim', 'Current' => 'Curent', 'version' => 'versiunea', '`Daily\' Graph \((.*) Minute' => 'Graficul \'Zilnic\' (medie pe $1 minute)', '`Weekly\' Graph \(30 Minute' => 'Graficul \'Sptmnal\' (medie pe 30 de minute)' , '`Monthly\' Graph \(2 Hour' => 'Graficul \'Lunar\' (medie pe 2 ore)', '`Yearly\' Graph \(1 Day' => 'Graficul \'Anual\' (medie pe 1 zi)', 'Incoming Traffic in (\S+) per Second' => 'Traficul de intrare [$1/secund]', 'Outgoing Traffic in (\S+) per Second' => 'Traficul de ieire [$1/secund]', 'at which time (\S+) had been up for (\S+)' => 'cnd $1 funciona de $2', 'at which time (\S+) had been up for (\S+) day, (\S+)' => 'cnd $1 funciona de $2 zi, $3', 'at which time (\S+) had been up for (\S+) days, (\S+)' => 'cnd $1 funciona de $2 zile, $3', #'(.+)/s$' => '$1/s', #'(.+)/min' => '$1/min', '(.+)/h$' => '$1/ora', #'([kMG]?)([bB])/s' => '$1$2/s', #'([kMG]?)([bB])/min' => '$1$2/min', '([kMG]?)([bB])/h' => '$1$2/ora', 'Bits' => 'Bii', 'Bytes' => 'Octei', 'In' => 'int', 'Out' => 'ie', 'Percentage' => 'procent', 'Ported to OpenVMS Alpha by' => 'Translatat sub OpenVMS de', 'Ported to WindowsNT by' => 'Translatat sub WindowsNT de', 'and' => 'i', '^GREEN' => 'VERDE', 'BLUE' => 'ALBASTRU', 'DARK GREEN' => 'VERDE NCHIS', 'MAGENTA' => 'PURPURIU', 'AMBER' => 'GALBEN', ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'duminic', 'Sun' => 'lu', 'Monday' => 'luni', 'Mon' => 'ma', 'Tuesday' => 'mari', 'Tue' => 'mi', 'Wednesday' => 'miercuri', 'Wed' => 'jo', 'Thursday' => 'joi', 'Thu' => 'vi', 'Friday' => 'vineri', 'Fri' => 's', 'Saturday' => 'smbt', 'Sat' => 'du' ); %month = ( 'January' => 'ianuarie', 'February' => 'februarie' , 'March' => 'martie', 'Jan' => 'ian', 'Feb' => 'feb', 'Mar' => 'mar', 'April' => 'aprilie', 'May' => 'mai', 'June' => 'iunie', 'Apr' => 'apr', 'May' => 'mai', 'Jun' => 'iun', 'July' => 'iulie', 'August' => 'august', 'September' => 'septembrie', 'Jul' => 'iul', 'Aug' => 'aug', 'Sep' => 'sep', 'October' => 'octombrie', 'November' => 'noiembrie', 'December' => 'decembrie', 'Oct' => 'oct', 'Nov' => 'noi', 'Dec' => 'dec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].", ora ".$quux[1]; }; return "$wday{$foo[0]}, $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Russian sub russian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'koi8-r', 'Maximal 5 Minute Incoming Traffic' => ' 5 ', 'Maximal 5 Minute Outgoing Traffic' => ' 5 ', 'the device' => '', 'The statistics were last updated(.*)' => ' : $1', ' Average\)' => ')', 'Average' => '', 'Max' => '.', 'Current' => '', 'version' => '', '`Daily\' Graph \((.*) Minute' => ' ( $1 ', '`Weekly\' Graph \(30 Minute' => ' ( 30 ' , '`Monthly\' Graph \(2 Hour' => ' ( 2 ', '`Yearly\' Graph \(1 Day' => ' ( 1 ', 'Incoming Traffic in (\S+) per Second' => ' $1 ', 'Outgoing Traffic in (\S+) per Second' => ' $1 ', 'at which time (.*) had been up for(.*)' => ' $1 $2', #'([kMG]?)([bB])/s' => '$1$1/', #'([kMG]?)([bB])/min' => '$1$2/', '([kMG]?)([bB])/h' => '$1$2/', 'Bits' => '', 'Bytes' => '', 'In' => '', 'Out' => '', 'Percentage' => '', 'Ported to OpenVMS Alpha by' => ' OpenVMS Alpha', 'Ported to WindowsNT by' => ' WindowsNT', 'and' => '', '^GREEN' => '', 'BLUE' => '', 'DARK GREEN' => '', 'MAGENTA' => '', 'AMBER' => '' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => ' ', 'Sun' => '', 'Monday' => ' ', 'Mon' => '', 'Tuesday' => ' ', 'Tue' => '', 'Wednesday' => ' ', 'Wed' => '', 'Thursday' => ' ', 'Thu' => '', 'Friday' => ' ', 'Fri' => '', 'Saturday' => ' ', 'Sat' => '' ); %month = ( 'January' => '', 'February' => '' , 'March' => '', 'Jan' => '', 'Feb' => '', 'Mar' => '', 'April' => '', 'May' => '', 'June' => '', 'Apr' => '', 'May' => '', 'Jun' => '', 'July' => '', 'August' => '', 'September' => '', 'Jul' => '', 'Aug' => '', 'Sep' => '', 'October' => '', 'November' => '', 'December' => '', 'Oct' => '', 'Nov' => '', 'Dec' => '' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].". ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Russian1251 Code sub russian1251 { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'windows-1251', 'Maximal 5 Minute Incoming Traffic' => ' 5 ', 'Maximal 5 Minute Outgoing Traffic' => ' 5 ', 'the device' => '', 'The statistics were last updated(.*)' => ' : $1', ' Average\)' => ')', 'Average' => ' ', 'Max' => '', 'Current' => '', 'version' => '', '`Daily\' Graph \((.*) Minute' => ' ( $1 ', '`Weekly\' Graph \(30 Minute' => ' ( 30 ' , '`Monthly\' Graph \(2 Hour' => ' ( 2 ', '`Yearly\' Graph \(1 Day' => ' ( 1 ', 'Incoming Traffic in (\S+) per Second' => ' $1 ', 'Outgoing Traffic in (\S+) per Second' => ' $1 ', 'at which time (\S+) had been up for (\S+)' => ' $1: $2.', 'at which time (\S+) had been up for (\S+) day, (\S+)' => ' $1: $2 , $3.', 'at which time (\S+) had been up for (\S+) days, (\S+)' => ' $1: $2 , $3.', #'([kMG]?)([bB])/s' => '$1$1/', #'([kMG]?)([bB])/min' => '$1$2/', '([kMG]?)([bB])/h' => '$1$2/', 'Bits' => '', 'Bytes' => '', 'In' => '', 'Out' => '', 'Percentage' => '', 'Ported to OpenVMS Alpha by' => ' OpenVMS Alpha', 'Ported to WindowsNT by' => ' WindowsNT', 'and' => '', '^GREEN' => '', 'BLUE' => '', 'DARK GREEN' => '', 'MAGENTA' => '', 'AMBER' => '' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => ' ', 'Sun' => '', 'Monday' => ' ', 'Mon' => '', 'Tuesday' => ' ', 'Tue' => '', 'Wednesday' => ' ', 'Wed' => '', 'Thursday' => ' ', 'Thu' => '', 'Friday' => ' ', 'Fri' => '', 'Saturday' => ' ', 'Sat' => '' ); %month = ( 'January' => '', 'February' => '' , 'March' => '', 'Jan' => '', 'Feb' => '', 'Mar' => '', 'April' => '', 'May' => '', 'June' => '', 'Apr' => '', 'May' => '', 'Jun' => '', 'July' => '', 'August' => '', 'September' => '', 'Jul' => '', 'Aug' => '', 'Sep' => '', 'October' => '', 'November' => '', 'December' => '', 'Oct' => '', 'Nov' => '', 'Dec' => '' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].". ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Serbian sub serbian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'windows-1250', 'Maximal 5 Minute Incoming Traffic' => 'Najvei 5 minutni ulazni saobraaj', 'Maximal 5 Minute Outgoing Traffic' => 'Najvei 5 minutni izlazni saobraaj', 'the device' => 'uredjaj', 'The statistics were last updated(.*)' => 'Poslednje auriranje podataka:$1', ' Average\)' => ' prosek)', 'Average' => 'Proseni', 'Max' => 'Maksimalni', 'Current' => 'Trenutni', 'version' => 'verzija', '`Daily\' Graph \((.*) Minute' => 'Dnevni graf ($1 minutni ', '`Weekly\' Graph \(30 Minute' => 'Nedeljni graf (30 minutni ' , '`Monthly\' Graph \(2 Hour' => 'Meseni graf (2 sata ', '`Yearly\' Graph \(1 Day' => 'Godinji graf (1 dnevni ', 'Incoming Traffic in (\S+) per Second' => 'Ulazni saobraaj - $1 u sekundi.', 'Outgoing Traffic in (\S+) per Second' => 'Izlazni saobraaj - $1 u sekundi.', 'Incoming Traffic in (\S+) per Minute' => 'Ulazni saobraaj - $1 u minutu', 'Outgoing Traffic in (\S+) per Minute' => 'Izlazni saobraaj - $1 u minutu', 'Incoming Traffic in (\S+) per Hour' => 'Ulazni saobraaj - $1 na sat', 'Outgoing Traffic in (\S+) per Hour' => 'Izlazni saobraaj - $1 na sat', 'at which time (.*) had been up for(.*)' => 'Vreme neprekidnog rada sistema $1 : $2', #'([kMG]?)([bB])/s' => '\$1\$2/s', #'([kMG]?)([bB])/min' => '\$1\$2/min', #'([kMG]?)([bB])/h' => '$1$2/h', 'Bits' => 'Bita', 'Bytes' => 'Bajta', 'In' => 'Ulaz', 'Out' => 'Izlaz', 'Percentage' => 'Procenat', 'Ported to OpenVMS Alpha by' => 'Na OpenVMS portovao', 'Ported to WindowsNT by' => 'Na WindowsNT portovao', 'and' => 'i', '^GREEN' => 'Zeleno', 'BLUE' => 'Plavo', 'DARK GREEN' => 'Tamnozeleno', 'MAGENTA' => 'Ljubiasto', 'AMBER' => 'Narandasto' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Nedelja', 'Sun' => 'Ned', 'Monday' => 'Ponedeljak', 'Mon' => 'Pon', 'Tuesday' => 'Utorak', 'Tue' => 'Uto', 'Wednesday' => 'Sreda', 'Wed' => 'Sre', 'Thursday' => 'etvrtak', 'Thu' => 'et', 'Friday' => 'Petak', 'Fri' => 'Pet', 'Saturday' => 'Subota', 'Sat' => 'Sub' ); %month = ( 'January' => 'januar', 'February' => 'februar', 'March' => 'mart', 'Jan' => 'Jan', 'Feb' => 'Feb', 'Mar' => 'Mar', 'April' => 'april', 'May' => 'maj', 'June' => 'jun', 'Apr' => 'Apr', 'May' => 'Maj', 'Jun' => 'Jun', 'July' => 'jul', 'August' => 'avgust', 'September' => 'septembar', 'Jul' => 'Jul', 'Aug' => 'Avg', 'Sep' => 'Sep', 'October' => 'oktobar','November' => 'novembar','December' => 'decembar', 'Oct' => 'Okt', 'Nov' => 'Nov', 'Dec' => 'Dec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].",".$quux[1]." "; }; return "$wday{$foo[0]} $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; } # # Slovak sub slovak { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'iso-8859-2', 'Maximal 5 Minute Incoming Traffic' => 'Maximlny 5 mintov prichdzajci tok', 'Maximal 5 Minute Outgoing Traffic' => 'Maximlny 5 mintov odchdzajci tok', 'the device' => 'zariadenie', 'The statistics were last updated(.*)' => 'Posledn aktualizcia tatistk:$1', ' Average\)' => ' priemer)', 'Average' => 'Priem.', 'Max' => 'Max.', 'Current' => 'Akt.', 'version' => 'verzia', '`Daily\' Graph \((.*) Minute' => 'Denn graf ($1 mintov', '`Weekly\' Graph \(30 Minute' => 'Tdenn graf (30 mintov' , '`Monthly\' Graph \(2 Hour' => 'Mesan graf (2 hodinov', '`Yearly\' Graph \(1 Day' => 'Ron graf (1 denn', 'Incoming Traffic in (\S+) per Second' => 'Prichdzajci tok v $1 za sekundu.', 'Outgoing Traffic in (\S+) per Second' => 'Odchdzajci tok v $1 za sekundu.', 'at which time (.*) had been up for(.*)' => 'as od poslednho retartu $1 : $2', #'([kMG]?)([bB])/s' => '\$1\$2/s', #'([kMG]?)([bB])/min' => '\$1\$2/min', #'([kMG]?)([bB])/h' => '$1$2/h', 'Bits' => 'bitoch', 'Bytes' => 'bytoch', #' In:' => ' In:', #' Out:' => ' Out:', 'Percentage' => 'Perc.', 'Ported to OpenVMS Alpha by' => 'Na OpenVMS portoval', 'Ported to WindowsNT by' => 'Na WindowsNT portoval', 'and' => 'a', '^GREEN' => 'Zelen', 'BLUE' => 'Modr', 'DARK GREEN' => 'Tmavozelen', 'MAGENTA' => 'Fialov', 'AMBER' => 'lt' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Nedea', 'Sun' => 'Ne', 'Monday' => 'Pondelok', 'Mon' => 'Po', 'Tuesday' => 'Utorok', 'Tue' => 'Ut', 'Wednesday' => 'Streda', 'Wed' => 'St', 'Thursday' => 'tvrtok', 'Thu' => 't', 'Friday' => 'Piatok', 'Fri' => 'Pi', 'Saturday' => 'Sobota', 'Sat' => 'So' ); %month = ( 'January' => 'Janur', 'February' => 'Februr', 'March' => 'Marec', 'Jan' => 'Janur', 'Feb' => 'Februr', 'Mar' => 'Marec', 'April' => 'Aprl', 'May' => 'Mj', 'June' => 'Jn', 'Apr' => 'Aprl', 'May' => 'Mj', 'Jun' => 'Jn', 'July' => 'Jl', 'August' => 'August', 'September' => 'September', 'Jul' => 'Jl', 'Aug' => 'August', 'Sep' => 'September', 'October' => 'Oktber','November' => 'November','December' => 'December', 'Oct' => 'Oktber','Nov' => 'November','Dec' => 'December' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].",".$quux[1]." hod."; }; return "$wday{$foo[0]} $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; } # # Slovenian sub slovenian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'windows-1250', 'Maximal 5 Minute Incoming Traffic' => 'Najvecji petminutni vhodni promet', 'Maximal 5 Minute Outgoing Traffic' => 'Najvecji petminutni izhodni promet', 'the device' => 'naprava', 'The statistics were last updated(.*)' => 'Zadnja posodobitev podatkov:$1', ' Average\)' => ' povprecje)', 'Average' => 'Povprecje', 'Max' => 'Maksimalno', 'Current' => 'Trenutno', 'version' => 'verzija', '`Daily\' Graph \((.*) Minute' => 'Dnevni graf ($1 min.', '`Weekly\' Graph \(30 Minute' => 'Tedenski graf (30 min.' , '`Monthly\' Graph \(2 Hour' => 'Mesecni graf (2 urno', '`Yearly\' Graph \(1 Day' => 'Letni graf (1 dnevno', 'Incoming Traffic in (\S+) per Second' => 'Vhodni promet v $1 na sekundo.', 'Outgoing Traffic in (\S+) per Second' => 'Izhodni promet v $1 na sekundo.', 'at which time (.*) had been up for(.*)' => 'Cas od zadnjega restarta sistema $1 : $2', #'([kMG]?)([bB])/s' => '\$1\$2/s', #'([kMG]?)([bB])/min' => '\$1\$2/min', #'([kMG]?)([bB])/h' => '$1$2/h', 'Bits' => 'bitov', 'Bytes' => 'bytov', 'In' => 'Vhod', 'Out' => 'Izhod', 'Percentage' => 'Proc.', 'Ported to OpenVMS Alpha by' => 'Na OpenVMS portiral', 'Ported to WindowsNT by' => 'Na WindowsNT portiral', 'and' => 'in', '^GREEN' => 'Zeleno', 'BLUE' => 'Modro', 'DARK GREEN' => 'Temnozeleno', 'MAGENTA' => 'Vijolicasto', 'AMBER' => 'Oranzno' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Nedelja', 'Sun' => 'Ne', 'Monday' => 'Ponedeljek', 'Mon' => 'Po', 'Tuesday' => 'Torek', 'Tue' => 'To', 'Wednesday' => 'Sreda', 'Wed' => 'Sr', 'Thursday' => 'Cetrtek', 'Thu' => 'Ce', 'Friday' => 'Petek', 'Fri' => 'Po', 'Saturday' => 'Sobota', 'Sat' => 'So' ); %month = ( 'January' => 'Januar', 'February' => 'Februar', 'March' => 'Marec', 'Jan' => 'Jan', 'Feb' => 'Feb', 'Mar' => 'Mar', 'April' => 'April', 'May' => 'Maj', 'June' => 'Jun', 'Apr' => 'Apr', 'May' => 'Maj', 'Jun' => 'Jun', 'July' => 'Julij', 'August' => 'Avgust', 'September' => 'September', 'Jul' => 'Jul', 'Aug' => 'Avg', 'Sep' => 'Sep', 'October' => 'Oktober','November' => 'November','December' => 'December', 'Oct' => 'Okt','Nov' => 'Nov','Dec' => 'Dec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].",".$quux[1]." "; }; return "$wday{$foo[0]} $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; } # # Spanish sub spanish { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... %translations = ( #'iso-8859-1' => 'iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Tráfico entrante máximo en 5 minutos', 'Maximal 5 Minute Outgoing Traffic' => 'Tráfico saliente máximo en 5 minutos', 'the device' => 'el dispositivo', 'The statistics were last updated(.*)' => 'Estadísticas actualizadas el $1', ' Average\)' => ' Promedio)', 'Average' => 'Promedio', 'Max' => 'Máx', 'Current' => 'Actual', 'version' => 'version', '`Daily\' Graph \((.*) Minute' => 'Gráfico diario ($1 minutos :', '`Weekly\' Graph \(30 Minute' => 'Gráfico semanal (30 minutos :' , '`Monthly\' Graph \(2 Hour' => 'Gráfico mensual (2 horas :', '`Yearly\' Graph \(1 Day' => 'Gráfico anual (1 día :', 'Incoming Traffic in (\S+) per Second' => 'Tráfico entrante en $1 por segundo', 'Outgoing Traffic in (\S+) per Second' => 'Tráfico saliente en $1 por segundo', 'at which time (.*) had been up for(.*)' => '$1 ha estado funcionando durante $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', # '([kMG]?)([bB])/h' => '$1$2/t', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Entrante:', 'Out' => 'Saliente:', 'Percentage' => 'Porcentaje:', 'Ported to OpenVMS Alpha by' => 'Portado a OpenVMS Alpha por', 'Ported to WindowsNT by' => 'Portado a WindowsNT por', 'and' => 'y', '^GREEN' => 'VERDE', 'BLUE' => 'AZUL', 'DARK GREEN' => 'VERDE OSCURO', 'MAGENTA' => 'MAGENTA', 'AMBER' => 'AMBAR' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Domingo', 'Sun' => 'Dom', 'Monday' => 'Lunes', 'Mon' => 'Lun', 'Tuesday' => 'Martes', 'Tue' => 'Mar', 'Wednesday' => 'Miércoles','Wed' => 'Mié', 'Thursday' => 'Jueves', 'Thu' => 'Jue', 'Friday' => 'Viernes', 'Fri' => 'Vie', 'Saturday' => 'Sábado', 'Sat' => 'Sab' ); %month = ( 'January' => 'Enero', 'February' => 'Febrero' , 'March' => 'Marzo', 'Jan' => 'Ene', 'Feb' => 'Feb', 'Mar' => 'Mar', 'April' => 'Abril', 'May' => 'Mayo', 'June' => 'Junio', 'Apr' => 'Abr', 'May' => 'Mai', 'Jun' => 'Jun', 'July' => 'Julio', 'August' => 'Agosto', 'September' => 'Setiembre', 'Jul' => 'Jul', 'Aug' => 'Ago', 'Sep' => 'Set', 'October' => 'Octubre', 'November' => 'Noviembre', 'December' => 'Diciembre', 'Oct' => 'Oct', 'Nov' => 'Nov', 'Dec' => 'Dic' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." a las ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] de $month{$foo[2]} de $foo[3]"; }; return $string; } # Swedish sub swedish { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Maximalt inkommande trafik i 5 minuter', 'Maximal 5 Minute Outgoing Traffic' => 'Maximalt utgående trafik i 5 minuter', 'the device' => 'enheten', 'The statistics were last updated(.*)' => 'Statistiken blev senast uppdaterad$1', ' Average\)' => ')', 'Average' => 'Medel', #'Max' => 'Max', 'Current' => 'Senaste', 'version' => 'version', '`Daily\' Graph \((.*) Minute' => 'Daglig graf (samplingsintervall $1 minut(er)', '`Weekly\' Graph \(30 Minute' => 'Veckovis graf (medelvrde per 30 minuter' , '`Monthly\' Graph \(2 Hour' => 'Månatlig graf (medelvrde per 2 timmar', '`Yearly\' Graph \(1 Day' => 'Årlig graf (medelvrde per dygn', 'Incoming Traffic in (\S+) per Second' => 'Inkommande trafik i $1 per sekund', 'Outgoing Traffic in (\S+) per Second' => 'Utgende trafik i $1 per sekund', 'at which time (.*) had been up for(.*)' => 'd $1 varit igång i$2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/t', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes', #'In' => 'In', 'Out' => 'Ut', 'Percentage' => 'Procent', 'Ported to OpenVMS Alpha by' => 'Portad till OpenVMS av', 'Ported to WindowsNT by' => 'Portad till WindowsNT av', 'and' => 'och', '^GREEN' => 'GRÖN', 'BLUE' => 'BLÅ', 'DARK GREEN' => 'MÖRKGRÖN', 'MAGENTA' => 'MANGENTA', 'AMBER' => 'BRUN', ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'söndag', 'Sun' => 'sön', 'Monday' => 'måndag', 'Mon' => 'mån', 'Tuesday' => 'tisdag', 'Tue' => 'tis', 'Wednesday' => 'onsdag', 'Wed' => 'ons', 'Thursday' => 'torsdag', 'Thu' => 'tor', 'Friday' => 'fredag', 'Fri' => 'fre', 'Saturday' => 'lördag', 'Sat' => 'lör' ); %month = ( 'January' => 'januari', 'February' => 'februari', 'March' => 'mars', 'Jan' => 'jan', 'Feb' => 'feb', 'Mar' => 'mar', 'April' => 'april', 'May' => 'maj', 'June' => 'juni', 'Apr' => 'apr', 'May' => 'maj', 'Jun' => 'jun', 'July' => 'juli', 'August' => 'augusti', 'September' => 'september', 'Jul' => 'jul', 'Aug' => 'aug', 'Sep' => 'sep', 'October' => 'oktober', 'November' => 'november', 'December' => 'december', 'Oct' => 'okt', 'Nov' => 'nov', 'Dec' => 'dec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." kl.".$quux[1]; }; return "$wday{$foo[0]} den $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Turkish sub turkish { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... %translations = ( 'iso-8859-1' => 'iso-8859-9', 'Maximal 5 Minute Incoming Traffic' => '5 dakika iin en yksek giri trafii', 'Maximal 5 Minute Outgoing Traffic' => '5 dakika iin en yksek k trafii', 'the device' => 'aygt', 'The statistics were last updated(.*)' => 'statistiklerin en son gncellenmesi $1', ' Average\)' => ' Ortalama)', 'Average' => 'Ortalama', 'Max' => 'EnYksek;x', 'Current' => 'uAnki', 'version' => 'srm', '`Daily\' Graph \((.*) Minute' => 'Gnlk ($1 dakika :', '`Weekly\' Graph \(30 Minute' => 'Haftalk (30 dakika :' , '`Monthly\' Graph \(2 Hour' => 'Aylk (2 saat :', '`Yearly\' Graph \(1 Day' => 'Yllk (1 gn :', 'Incoming Traffic in (\S+) per Second' => '$1 deki saniyelik giri trafii', 'Outgoing Traffic in (\S+) per Second' => '$1 deki saniyelik k trafii', 'at which time (.*) had been up for(.*)' => '$1 Ne zamandan $2 beri ayakta', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', # '([kMG]?)([bB])/h' => '$1$2/t', # 'Bits' => 'Bit', # 'Bytes' => 'Byte' 'In' => 'Giri', 'Out' => 'k', 'Percentage' => 'Yzge', 'Ported to OpenVMS Alpha by' => 'OpenVMS Alpha ya uyarlayan', 'Ported to WindowsNT by' => 'WindowsNT ye uyarlayan', 'and' => 've', '^GREEN' => 'YEL', 'BLUE' => 'MAV', 'DARK GREEN' => 'KOYU YEL', 'MAGENTA' => 'MACENTA', 'AMBER' => 'AMBER' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Pazar', 'Pzr' => 'Dom', 'Monday' => 'Pazartesi', 'Pzt' => 'Lun', 'Tuesday' => 'Sal', 'Sal' => 'Mar', 'Wednesday' => 'aramba', 'r' => 'Mié', 'Thursday' => 'Perembe', 'Pr' => 'Jue', 'Friday' => 'Cuma', 'Cum' => 'Vie', 'Saturday' => 'Cumartesi', 'Cmr' => 'Sab' ); %month = ( 'January' => 'Ocak', 'February' => 'ubat', 'March' => 'Mart', 'Jan' => 'Ock', 'Feb' => 'ub', 'Mar' => 'Mar', 'April' => 'Nisan', 'May' => 'Mays', 'June' => 'Haziran', 'Apr' => 'Nis', 'May' => 'May', 'Jun' => 'Hzr', 'July' => 'Temmuz', 'August' => 'Agustos', 'September' => 'Eyll', 'Jul' => 'Tem', 'Aug' => 'Agu', 'Sep' => 'Eyl', 'October' => 'Ekim', 'November' => 'Kasm', 'December' => 'Aralk', 'Oct' => 'Ekm', 'Nov' => 'Kas', 'Dec' => 'Ara' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." a las ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] de $month{$foo[2]} de $foo[3]"; }; } # Ukrainian sub ukrainian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'koi8-u', 'Maximal 5 Minute Incoming Traffic' => ' Ȧ Ʀ 5 ', 'Maximal 5 Minute Outgoing Traffic' => ' Ȧ Ʀ 5 ', 'the device' => 'Ҧ', 'The statistics were last updated(.*)' => 'Τ : $1', ' Average\)' => ')', 'Average' => 'Φ', 'Max' => '.', 'Current' => '', 'version' => 'Ӧ', '`Daily\' Graph \((.*) Minute' => ' Ʀ (Τ $1 ', '`Weekly\' Graph \(30 Minute' => ' Ʀ (Τ 30 ' , '`Monthly\' Graph \(2 Hour' => ' Ʀ (Τ 2 ', '`Yearly\' Graph \(1 Day' => ' Ʀ (Τ 1 ', 'Incoming Traffic in (\S+) per Second' => 'Ȧ Ʀ $1 ', 'Outgoing Traffic in (\S+) per Second' => 'Ȧ Ʀ $1 ', 'at which time (.*) had been up for(.*)' => '$1 $2', #'([kMG]?)([bB])/s' => '$1$1/', #'([kMG]?)([bB])/min' => '$1$2/', '([kMG]?)([bB])/h' => '$1$2/', 'Bits' => '¦', 'Bytes' => '', 'In' => '', 'Out' => '', 'Percentage' => '', 'Ported to OpenVMS Alpha by' => ' OpenVMS Alpha', 'Ported to WindowsNT by' => ' WindowsNT', 'and' => '', '^GREEN' => '', 'BLUE' => '', 'DARK GREEN' => '', 'MAGENTA' => '', 'AMBER' => '' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => ' Ħ', 'Sun' => '', 'Monday' => ' Ħ', 'Mon' => '', 'Tuesday' => ' ', 'Tue' => '', 'Wednesday' => ' ', 'Wed' => '', 'Thursday' => ' ', 'Thu' => '', 'Friday' => ' \'', 'Fri' => '', 'Saturday' => ' ', 'Sat' => '' ); %month = ( 'January' => '', 'February' => '' , 'March' => '', 'Jan' => '', 'Feb' => '', 'Mar' => '', 'April' => 'צ', 'May' => '', 'June' => '', 'Apr' => 'צ', 'May' => '', 'Jun' => '', 'July' => '', 'August' => '', 'September' => '', 'Jul' => '', 'Aug' => '', 'Sep' => '', 'October' => '', 'November' => '', 'December' => '', 'Oct' => '', 'Nov' => '', 'Dec' => '' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].". ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Ukrainian1251 - windowze encoding sub ukrainian1251 { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); %translations = ( 'iso-8859-1' => 'windows-1251', 'Maximal 5 Minute Incoming Traffic' => ' 5 ', 'Maximal 5 Minute Outgoing Traffic' => ' 5 ', 'the device' => '', 'The statistics were last updated(.*)' => ' : $1', ' Average\)' => ')', 'Average' => '', 'Max' => '', 'Current' => '', 'version' => '', '`Daily\' Graph \((.*) Minute' => ' ( $1 ', '`Weekly\' Graph \(30 Minute' => ' ( 30 ' , '`Monthly\' Graph \(2 Hour' => '̳ ( i ', '`Yearly\' Graph \(1 Day' => 'г ( ', 'Incoming Traffic in (\S+) per Second' => ' $1 ', 'Outgoing Traffic in (\S+) per Second' => ' $1 ', 'at which time (.*) had been up for(.*)' => '$1 䳿: $2', '([kMG]?)([bB])/s' => '$1$1/', '([kMG]?)([bB])/min' => '$1$2/', '([kMG]?)([bB])/h' => '$1$2/', '([bB])/s' => '$1/', '([bB])/min' => '$1/', '([bB])/h' => '$1/', 'Bits' => '', 'Bytes' => '', 'In' => '', 'Out' => '', 'Percentage' => '³', 'Ported to OpenVMS Alpha by' => ' OpenVMS Alpha', 'Ported to WindowsNT by' => ' WindowsNT', 'and' => '', 'RED' => '', '^GREEN' => '', 'BLUE' => 'Ͳ', 'DARK GREEN' => '', 'MAGENTA' => 'Բ', 'AMBER' => '', ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => ' ', 'Sun' => '', 'Monday' => ' ', 'Mon' => '', 'Tuesday' => ' ³', 'Tue' => '', 'Wednesday' => ' ', 'Wed' => '', 'Thursday' => ' ', 'Thu' => '', 'Friday' => ' \'', 'Fri' => '', 'Saturday' => ' ', 'Sat' => '' ); %month = ( 'January' => 'ѳ', 'February' => '' , 'March' => '', 'Jan' => 'ѳ', 'Feb' => '', 'Mar' => '', 'April' => '', 'May' => '', 'June' => '', 'Apr' => '', 'May' => '', 'Jun' => '', 'July' => '', 'August' => '', 'September' => '', 'Jul' => '', 'Aug' => '', 'Sep' => '', 'October' => '', 'November' => '', 'December' => '', 'Oct' => '', 'Nov' => '', 'Dec' => '' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].". ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/bin/cfgmaker0000755000175300017510000033010614171763413014135 0ustar oetikeroep#! /home/oetiker/.plenv/shims/perl -w # -*- mode: Perl -*- ################################################################## # MRTG 2.17.10 -- Config file creator ################################################################## # Created by Tobias Oetiker # this produces an mrtg config file for one router or more routers # by pulling info off the router via snmp ################################################################## # Distributed under the GNU copyleft # Copyright 2000 by Tobias Oetiker ################################################################## # DEBUG TARGETS # base - basic program flow # snpo - SNMP Polling # snpd - SNMP Detail #@main::DEBUG=qw(base); @main::DEBUG=qw(base snpo snpd); require 5.005; use strict; BEGIN { # Automatic OS detection ... do NOT touch if ( $^O =~ /^(?:(ms)?(dos|win(32|nt)?))/i ) { $main::OS = 'NT'; $main::SL = '\\'; $main::PS = ';'; } elsif ( $^O =~ /^NetWare$/i ) { $main::OS = 'NW'; $main::SL = '/'; $main::PS = ';'; } elsif ( $^O =~ /^VMS$/i ) { $main::OS = 'VMS'; $main::SL = '.'; $main::PS = ':'; } else { $main::OS = 'UNIX'; $main::SL = '/'; $main::PS = ':'; } } use FindBin; use lib "${FindBin::Bin}"; use lib "${FindBin::Bin}${main::SL}..${main::SL}lib${main::SL}mrtg2"; use MRTG_lib "2.100015"; use Getopt::Long; use Pod::Usage; use Socket; sub main { # assign defaults my %opt = ( 'enable-ipv6' => 0, 'use-16bit' => 0, 'community' => 'public', 'interfaces' => 1, 'enablesnmpv3' => 0, # 'snmp-options' => ':::::2' ); my %routers; my %confcache; my $ipv4only; my %v3opt; $opt{fullcmd} = "$0 ".(join " ", map {$_ =~ /[ \[\]\*\{\}\;\>\<\&]/ ? qq{"$_"} : $_ } @ARGV); options(\%opt,\%routers); # Check for IPv6 libraries if IPv6 is enabled. # If the check fails, IPv6 is disabled. $ipv4only = 1; if ($opt{'enable-ipv6'} == 1) { if ((eval {local $SIG{__DIE__};require Socket6;}) && (eval {local $SIG{__DIE__};require IO::Socket::INET6;})) { debug ('base',"IPv6 libraries found, IPv6 enabled."); $ipv4only = 0; } else { warn "WARNING: IPv6 libraries not found, IPv6 disabled.\n"; $opt{'enable-ipv6'} = 0; } } if ($opt{'use-16bit'} == 1) { warn "WARNING: Using 16bit RequestIDs\n"; no warnings; $SNMP_Session::default_use_16bit_request_ids=1; } # Check for SNMP V3 # if (exists($opt{username}) or lc($opt{enablesnmpv3}) eq "yes" ) { if (eval {local $SIG{__DIE__};require Net_SNMP_util;}) { import Net_SNMP_util; debug('base', "SNMP V3 libraries found, SNMP V3 enabled."); $opt{enablesnmpv3} = "yes"; push @{$opt{global}}, "enablesnmpv3: yes"; } else { warn "WARNING: SNMP V3 libraries not found, SNMP V3 disabled. Falling back to V2c.\n"; require SNMP_util; import SNMP_util; $opt{enablesnmpv3} = "revert"; } } else { require SNMP_util; import SNMP_util; $opt{enablesnmpv3} = "no"; } init(); foreach my $router (sort {($routers{$a}{noofrouter}) <=> ($routers{$b}{noofrouter})} keys %routers) { my @snmpopt = split(/:/,$routers{$router}{'snmp-options'}); if ($snmpopt[5] and $snmpopt[5] == 3) { if ($opt{enablesnmpv3} eq "revert") { $snmpopt[5] = 2; warn "reverting to snmpV2c for router $router\n"; $routers{$router}{'snmp-options'} = join(":",@snmpopt); $routers{$router}{snmpopt_current} = $routers{$router}{'snmp-options'}; } else { die "SNMP V3 requires a --username parameter as part of the User Security Model for router $routers{$router}{routerkey}" if $opt{enablesnmpv3} eq "no"; $routers{$router}{enablesnmpv3} = $opt{enablesnmpv3}; %v3opt = parsev3(\%opt); } } else { debug('base',"snmpv3 available, but using v1/v2c for $routers{$router}{routerkey}") if $opt{enablesnmpv3} eq "yes"; } # pod2usage(-verbose=>1,-message=>"ERROR: Could not Parse $router\n") # unless $router =~ /.*\@.*/; debug('base',"Get Device Info on $router"); $routers{$router}{ipv4only} = $ipv4only; if ( my $devinfo = DeviceInfo($router,\%routers,\%v3opt) ) { $routers{$router}{deviceinfo} = $devinfo; } else { warn "WARNING: Skipping $router as no info could be retrieved\n\n"; sleep 5; next; } if ($opt{interfaces}) { debug('base',"Populating confcache"); populateconfcache(\%confcache,$router,$routers{$router}{ipv4only},1,\%v3opt); debug('base',"Get Interface Info"); InterfaceInfo(\%confcache,\%routers,$router,\%opt,\%v3opt); } } GenConf(\%opt,\%routers,\%confcache,\%v3opt); } # end main main; exit 0; sub InterfaceInfo($$$$$) { my $confcache = shift; my $routers = shift; my $router = shift; my $opt = shift; my $v3opt = shift; my @Variables = qw (ifIndex ifType ifAdminStatus ifOperStatus ifMtu); my $snmphost = v4onlyifnecessary($router, $routers->{$router}{ipv4only}); if ($routers->{$router}{deviceinfo}{Vendor} eq 'cisco' && $routers->{$router}{deviceinfo}{sysDescr} =~ m/Version\s+(\d+\.\d+)/) { push @Variables, ($1 > 11.0 or $1 < 10.0 ) ? "ifAlias" : "CiscolocIfDescr"; if ($1 > 11.2) {push @Variables, "vmVlan";}; if ($1 > 11.3) {push @Variables, "vlanTrunkPortDynamicStatus";}; } elsif ( $routers->{$router}{deviceinfo}{Vendor} =~ /(?:hp|juniper|dlink|wwp|foundry|dellLan|force10|3com|extremenetworks|openBSD|arista|enterasys|zyxel|vyatta|dcn|brocade|datacom|alcatel|mikrotik|huawei|eltex)/i) { push @Variables, "ifAlias"; } my $descr = $routers->{$router}{deviceinfo}{sysDescr}; if ($routers->{$router}{deviceinfo}{Vendor} eq 'cisco' && $descr =~ m/Catalyst\sOperating\sSystem|Cisco\sSystems\sWS-C2900/ ) { push @Variables, "CiscoCatalystPortName"; push @Variables, "vmVlan"; } if ($routers->{$router}{deviceinfo}{Vendor} eq 'cisco' && $descr =~ m/Catalyst/ ) { push @Variables, "vlanTrunkPortDynamicStatus"; } if ($descr =~ m/Passport-8610/ || $descr =~ m/MERS-8610/ ) { push @Variables, "ppPortName"; } foreach my $var (@Variables) { debug('base',"Walking $var"); foreach my $tuple (snmpwalk($snmphost,$v3opt, $var)){ my($if,$value) = split /:/, $tuple, 2; $value =~ s/[\0- ]+$//; # no trailing space $routers->{$router}{$if}{$var} = $value; debug('snpd'," $router -> $if -> $var = $value"); } } # interface speed var depends on snmp version my $snmp_version = (split(':', $router, 6))[5] || 1; if ( $snmp_version =~ /[23]/ ) { debug('base',"Walking ifSpeed"); my @ifSpeed = snmpwalk($snmphost, $v3opt,'ifSpeed'); debug('snpd',"\@ifSpeed = @ifSpeed\n"); debug('base',"Walking ifHighSpeed"); my @ifHighSpeed = snmpwalk($snmphost,$v3opt, 'ifHighSpeed'); for ( my $i=0; $i<=$#ifSpeed; $i++ ) { my ($if,$value) = split /:/, $ifSpeed[$i], 2; # the mib entry on ifSpeed says # "An estimate of the interface's current bandwidth in bits # per second. For interfaces which do not vary in bandwidth # or for those where no accurate estimation can be made, this # object should contain the nominal bandwidth. If the # bandwidth of the interface is greater than the maximum value # reportable by this object then this object should report its # maximum value (4,294,967,295) and ifHighSpeed must be used # to report the interface's speed. For a sub-layer which has # no concept of bandwidth, this object should be zero." if ( (not defined $value) || ($value == 2**32-1) ) { ($if, $value) = split /:/, $ifHighSpeed[$i], 2; $value = $value * 1000000; # highSpeed = contador * 10^6 debug('base',"Speed: $if - $value"); } if ( ($descr =~ m/MERS-8610/ ) && (defined $ifHighSpeed[$i]) ) { ($if, $value) = split /:/, $ifHighSpeed[$i], 2; $value = $value * 1000000; # highSpeed = contador * 10^6 debug('base',"Speed: $if - $value"); } $routers->{$router}{$if}{'ifSpeed'} = $value; } } else { debug('base',"Walking ifSpeed"); foreach my $tuple (snmpwalk($snmphost,$v3opt, 'ifSpeed')){ my($if,$value) = split /:/, $tuple, 2; $routers->{$router}{$if}{'ifSpeed'} = $value; debug('snpd'," $router -> $if -> ifSpeed = $value"); } } # magic speed determination for portmaster IFs if ($routers->{$router}{deviceinfo}{Vendor} eq 'portmaster') { # We can only approximate speeds # # so we think that ppp can do 76800 bit/s, and slip 38400. # (actually, slip is a bit faster, but usually users with newer modems # use ppp). Alternatively, you can set async speed to 115200 or # 230400 (the maximum speed supported by portmaster). # # But if the interface is ptpW (sync), max speed is 128000 # change it to your needs. On various Portmasters there are # various numbers of sync interfaces, so modify it. # # The most commonly used PM-2ER has only one sync. # # Paul Makeev (mac@redline.ru) # foreach my $if (keys %{$routers->{$router}}) { next unless $if =~ /^\d+$/; my $ift = $routers->{$router}{$if}{ifType}; my $ifd = $routers->{$router}{$if}{Descr}; if ($ift == 23) { if ($ifd eq 'ptpW1') { $routers->{$router}{$if}{ifSpeed} = 128000; } else { $routers->{$router}{$if}{ifSpeed} = 76800; } } elsif ($ift == 28) { $routers->{$router}{$if}{ifSpeed} = 38400; } elsif ($ift == 6) { $routers->{$router}{$if}{ifSpeed} = 10000000; } } } # match confcache info into tree my $cachekey = cleanhostkey $router; foreach my $method (keys %{$$confcache{$cachekey}}) { foreach my $key (keys %{$$confcache{$cachekey}{$method}}) { my $if = readfromcache($confcache,$router,$method,$key); next unless $if =~ /^\d+$/; $routers->{$router}{$if}{$method} = $key; for ($method) { #fix special chars in ifdescr # no need for this we fix if references later on # /^Descr|Name$/ && do { # $routers->{$router}{$if}{"R$method"} = $routers->{$router}{$if}{$method}; # $routers->{$router}{$if}{$method} =~ s/(:)/\\$1/g; # next; # }; #find hostname of IF !$$opt{noreversedns} && /^Ip$/ and do { my $name = gethostbyaddr( pack('C4', split(/\./, $routers->{$router}{$if}{$method})), AF_INET); $routers->{$router}{$if}{DNSName} = ($name or ""); next; }; } } } } # end InterfaceInfo sub GenConf ($$$$) { my $opt = shift; my $routers = shift; my $confcache = shift; my $v3opt = shift; my $conf = "# Created by \n# $$opt{fullcmd}\n\n"; # print global options unless (defined $$opt{'nodefaultglobal'}) { $conf .= < ($$routers{$b}{noofrouter})} keys %$routers ) { my $router_ref = $$routers{$router}; my $router_opt = $$router_ref{opt}; my $router_dev = $$router_ref{deviceinfo}; # Did any global options appear on the command line # before this router? If so, include them into the # configuration file. if (defined $$router_opt{global}) { foreach my $key (@{$$router_opt{global}}) { $conf .= "$key\n"; } } # If IPv6 is enabled, add IPv4Only target directive for targets # that do not support SNMP over IPv6. my $ipv4only_directive; my $router_ipv4only = ($$opt{'enable-ipv6'} == 1) && $$router_ref{ipv4only}; my $syscontact = $$router_dev{sysContact}; my $html_syscontact = html_escape($syscontact); my $syslocation = $$router_dev{sysLocation}; my $html_syslocation = html_escape($syslocation); my $sysname = $$router_dev{sysName}; my $sysdescr = $$router_dev{sysDescr}; my $comment_sysdescr = $sysdescr; # make sure embedded newlines do not harm us here $comment_sysdescr =~ s/[\n\r]+/\n\# /g; my $community = $$router_ref{community}; $community =~ s/([@ ])/\\$1/g; my $router_connect = "$community\@$$router_ref{routername}$$router_ref{snmpopt_current}"; my @v3options; foreach my $v3op (keys %$v3opt) { push @v3options, $v3op."=>'".$$v3opt{$v3op}."'"; } my $v3options = join(",",@v3options) if $$router_ref{'snmp-options'} =~ /(?::[^:]*){4}:3/ ; my $html_sysdescr = html_escape($sysdescr); my $router_name = ($$router_ref{routername} . (($$router_ref{'dns-domain'})?'.':'') . $$router_ref{'dns-domain'}); # James Overbeck 2001/09/20 # Moved $directory_name definition from within the interface # foreach loop to here. In its previous location, $directory_name # was not accessible to host templates. $directory_name is not # changed per-interface so it might as well be here instead of # where it was. my $directory_name = ""; if (defined $$router_opt{subdirs}) { $directory_name = $$router_opt{subdirs}; $directory_name =~ s/HOSTNAME/$router_name/g; $directory_name =~ s/SNMPNAME/$$router_dev{sysName}/g; } my $target_lines = ""; my $problem_lines = ""; my $head_lines = " ###################################################################### # System: $sysname # Description: $comment_sysdescr # Contact: $syscontact # Location: $syslocation ###################################################################### "; my $separator_lines = "\n\n"; # Host specific config lines generation code starts HERE if(defined $$router_opt{'host-template'}) { # First test if the file exists and is readable, die if not. die "File $$router_opt{'host-template'} didn't exist.\n" unless (-e $$router_opt{'host-template'} and -r $$router_opt{'host-template'}); # Open the file (or die). open IF_TEMPLATE, $$router_opt{'host-template'} or die "File $$router_opt{'host-template'} couldn't be opened.\n"; my @template_lines = readline *IF_TEMPLATE; close IF_TEMPLATE; $@ = undef; eval ('local $SIG{__DIE__};'.join("", @template_lines)); die "ERROR Evaluation of the contents in the file \n\n". "$$router_opt{'host-template'}\ngave the error \n\n\"$@\"\n\nExiting cfgmaker\n" if $@; } $conf .= ($head_lines . $problem_lines . $target_lines . $separator_lines); # Host specific config lines generation code ends HERE if ($$router_opt{'interfaces'}) { foreach my $ifindex (sort {int($a) <=> int($b)} grep /^\d+$/, keys %$router_ref) { my $i = $$router_ref{$ifindex}; # Now define a number of variables used for this interface. # Some variables are just used internally by cfgmaker to # process the interface, others are provided for usage in # host and interface templates and for interface filters. my $if_index = $ifindex; my $if_eth = $$i{Eth} || 'No Ethernet Id'; # does it make sense to look at the interface ? my @prob; my $default_ifstate = 1; # State assumed up. my $default_iftype = 1; # iftype assumed ok. my $if_ok = 1; # my $if_admin = (($$i{ifAdminStatus} || 0) == 1); my $if_oper = (($$i{ifOperStatus} || 0) == 1); my $if_type = $$i{ifType} || -1; my $if_is_ethernet = 0 < scalar(grep {$_ == $if_type;} (6,7,26,62,69,117)); my $if_is_isdn = (0 < scalar (grep {$_ == $if_type;} (20,21,63,75,76,77))); my $if_is_dialup = $if_is_isdn || (0 < scalar (grep {$_ == $if_type;} (23,81,82,108))); my $if_is_atm = (0 < scalar(grep {$_ == $if_type;} (37,49,107,105,106,114,134))); my $if_is_wan = 0 < scalar(grep {$_ == $if_type;} (22,30,32,39,44,46)); my $if_is_lan = $if_is_ethernet || (0 < scalar (grep {$_ == $if_type;} (8,9,11,15,26,55,59,60,115))); my $if_is_dsl = (0 < scalar(grep {$_ == $if_type;} (94,95,96,97))); my $if_is_loopback = $if_type == 24; my $if_is_ciscovlan = ($$router_dev{Vendor} eq 'cisco' and $$i{Descr} =~ /^(unrouted )?[- ]?VLAN[- ]?\d*$/i); my $if_ip = $$i{Ip} || 'No Ip'; my $if_snmp_descr = $$i{Descr} || 'No Description'; $if_snmp_descr =~ s/\n$//; # no you don't want to know who does this # ok ... dell 3524 $if_snmp_descr =~ s/ /-/g; my $if_type_num = $$i{ifType} || 'Unknown Type'; $$i{ifType} ||= -1; my $if_snmp_name = $$i{Name} || 'No Name'; my $if_snmp_alias = $$i{ifAlias} || ''; my $if_cisco_descr = $$i{CiscolocIfDescr} || ''; my $if_dns_name = $$i{DNSName} || 'No DNS name'; my $if_vlan_id = $$i{vmVlan} || 'No Vlan'; my $if_cisco_trunk = ($$i{vlanTrunkPortDynamicStatus} || 0 == 1); my $if_MTU = $$i{ifMtu} || 'No MTU'; # For Nokia IPSO, find non-ethernet interfaces with IP addresses # and add missing MAC address and Port Speed information to # to the LOGICAL and LOGICAL+VLAN interfaces. if ( $$router_dev{Vendor} eq 'nokiaipsofw' ) { if ($$i{ifType} ne "6" and $$router_dev{sysDescr} =~ / IPSO / && $$i{Ip} =~ /^\d+/ and (not $$i{Eth} or not $$i{ifSpeed} or $$i{ifSpeed} < 10 ) ) { my $logical_if_name = $$i{Name}; # Split the LOGICAL interface name in attempt # to match with base PHYSICAL interface detail. my ($logical_if_HEAD, $logical_if_TAIL) = $logical_if_name =~ /^(.*)(c\d+)$/; foreach my $ifindexTMP (sort {int($a) <=> int($b)} grep /^\d+$/, keys %$router_ref) { next unless $ifindexTMP =~ /^\d+$/; my $physical_if_name = $$router_ref{$ifindexTMP}; if ($$physical_if_name{ifType} == 6 && $logical_if_HEAD eq $$physical_if_name{Name} ) { $$i{Eth} ||= $$physical_if_name{Eth}; $$i{ifSpeed} = $$physical_if_name{ifSpeed} if ( not $$i{ifSpeed} or $$i{ifSpeed} < 10 ); } } } } # First investigate the state of the interface. if (not defined $$router_opt{'no-down'}) { if (($$i{ifAdminStatus} || 0 )== 2) { push @prob, "it is administratively DOWN"; $default_ifstate = 0; } elsif (($$i{ifAdminStatus} || 0 ) == 3) { push @prob, "it is in administrative TEST mode"; $default_ifstate = 0; } if (not defined $$router_opt{'show-op-down'}) { if (($$i{ifOperStatus} || 0 ) == 2) { push @prob, "it is operationally DOWN"; $default_ifstate = 0; } elsif (($$i{ifOperStatus} || 0 ) == 3) { push @prob, "it is in operational TEST mode"; $default_ifstate = 0; } } } # Investigate the type of the interface. if ($$router_dev{Vendor} eq 'cisco' && $$i{ifType} == 18) { # by fwo@obsidian.co.za push @prob, "it is a DS1 controllers"; $default_iftype = 0; } elsif ($$router_dev{Vendor} eq 'cisco' && $$i{ifType} == 19) { # by fwo@obsidian.co.za push @prob, "it is a E1 controllers"; $default_iftype = 0; } elsif ($$i{ifType} == 24) { push @prob, "it is a Software Loopback interface" ; $default_iftype = 0; } elsif ($$router_dev{Vendor} eq 'cisco' && $$i{ifType} == 30) { # by blube@floridadigital.net push @prob, "it is a DS3 controller"; $default_iftype = 0; } elsif ($$router_dev{Vendor} eq 'cisco' && $$i{ifType} == 102) { # by dan.mcdonald@austinenergy.com push @prob, "it is a Voice controller"; $default_iftype = 0; } elsif ($$router_dev{Vendor} eq 'cisco' && $$i{ifType} == 103) { # by dan.mcdonald@austinenergy.com push @prob, "it is a Voice dial peer"; $default_iftype = 0; } elsif ($$i{ifType} == 162) { push @prob, "it is a CEF Sub-interface"; # John Begley } elsif ($$router_dev{Vendor} eq 'cisco' and $$i{Descr} eq 'Null0') { push @prob, "it is a cisco Null0 interface"; $default_iftype = 0; } my $default = $default_iftype && $default_ifstate; # Do some futher investigation if the interface makes # sense to collect on # I debated whether to insert the zero-speed check before # or after the "will always be zero" sections below. # I settled on before since I'll assume the user knows # what speed the zero-speed interfaces should be better # than the simple logic below. if (not $$i{ifSpeed} and $$router_opt{'zero-speed'}) { # Set all interfaces with zero speed to the value specified # by the --zero-speed= command line option. # Be sure the value specified is a valid integer. # It seems like this could be done once when # $$router_opt is set, but I didn't see any example # of input validation in that part of cfgmaker, # so it gets done here, more times than are # really necessary. ;-) unless ($$router_opt{'zero-speed'} =~ /^\d+$/) { die "ERROR: zero-speed specified with non-integer speed: $$router_opt{'zero-speed'}"; } $$i{ifSpeed} = $$router_opt{'zero-speed'}; } if (not $$i{ifSpeed} and $$router_dev{Vendor} eq 'foundry' and $$i{ifType} and $$i{ifType} == 194) { # foundry ATM subinterfaces always report 0 speed, make it 155Mbps instead. $$i{ifSpeed} = 155000000; } elsif (not $$i{ifSpeed} and $$router_dev{Vendor} eq 'foundry' and $$i{ifType} and $$i{ifType} == 135) { # Foundry virtual Ethernet interfaces always report 0 speed, make it 1GB instead. $$i{ifSpeed} = 1000000000; } elsif (not $$i{ifSpeed} and $$router_dev{Vendor} eq 'cisco' and $$i{sysDescr} and $$i{sysDescr} =~ /FWSM-Firewall / ) { # Cisco PIX Firewall Switch Modules have effective backplane speed of 600 Megs $$i{ifSpeed} = 600000000; } elsif (not $$i{ifSpeed} and $$router_dev{Vendor} eq '3com' and $$i{Descr} and $$i{Descr} =~ /RMON VLAN (\d+)/ ) { $$i{ifSpeed} = 100000000; $if_vlan_id = $1; } elsif (not $$i{ifSpeed}) { push @prob, "has no ifSpeed property"; $$i{ifSpeed} = 0; $if_ok = 0; } my $message; my $nohc =0; if ($message = IsCounterBroken($ifindex, $router_ref,$v3opt)) { # set snmpopt_current to working snmp options if ($message eq '1') { $nohc = 1; } else { push @prob, "got '$message' from interface when trying to query"; $if_ok = 0; } } my $community = $$router_ref{community}; $community =~ s/([@ ])/\\$1/g; my $router_connect = "$community\@$$router_ref{routername}$$router_ref{snmpopt_current}"; my $v3options = join(",",@v3options) if $$router_ref{snmpopt_current} =~ /(?::[^:]*){4}:3/ ; # determine interface reference my $if_ref; if (defined $$router_opt{ifref}) { foreach (split /,/,$$router_opt{ifref}) { /^ip$/ && do { if($$i{Ip} ){ $if_ref = "/".$$i{Ip}; last;} next}; /^eth$/ && do { if($$i{Eth} ){ $if_ref = "!".$$i{Eth}; last;} next}; /^descr?$/&& do { if($$i{Descr}){ $if_ref = "\\".$$i{Descr};last;} next}; /^name$/ && do { if($$i{Name} ){ $if_ref = "#".$$i{Name}; last;} next}; /^type$/ && do { if($$i{Type} ){ $if_ref = "%".$$i{Type}; last;} next}; /^nr$/ && do { $if_ref = $ifindex; last }; die "ERROR: Invalid value for --ifref: $$router_opt{ifref} ($_)\n"; } if (not defined $if_ref) { push @prob, "--ifref=$$router_opt{ifref} is not unique for this interface"; $if_ref = $ifindex; $if_ok = 0; } } else { if ($$i{Name}) { $if_ref = "#".$$i{Name}; } else { $if_ref = $ifindex; } } # generate Target name my $trim_if_ref = $if_ref; $trim_if_ref =~ s/[\#!\/\\:\s\@%]+/_/g; $trim_if_ref =~ s/^_*(.+?)_*$/$1/; my $target_name = "${router_name}_$trim_if_ref"; my $if_title_desc = $if_ref; $if_title_desc =~ s/^[^\d]//; my $if_speed = int($$i{ifSpeed} / 8); my $if_speed_str = fmi($if_speed,$$router_ref{flags}); my $if_type_desc = IfType($$i{ifType}); my $html_if_type_desc = html_escape($if_type_desc); my $desc_prefix = 'Traffic Analysis for '; my $port_dot = $$i{Name} || 'Unknown'; $port_dot =~ s/\//./g; my $if_port_name = $$router_ref{$port_dot}{CiscoCatalystPortName}; my $if_pp_port_name = $$router_ref{$ifindex}{ppPortName}; if (defined $$router_opt{ifdesc}) { $desc_prefix = ''; foreach (split /,/,$$router_opt{ifdesc}) { /^ip$/ && do { if($$i{Ip}) { $if_title_desc = $$i{Ip}; last } next }; /^eth$/ && do { if($$i{Eth}) { $if_title_desc = $$i{Eth}; last } next }; /^descr?$/ && do { if($$i{Descr}){ $if_title_desc = $if_snmp_descr; last } next }; /^alias$/ && do { if($$i{ifAlias}){ $if_title_desc = "$if_snmp_descr $if_snmp_alias $if_cisco_descr"; last } next }; /^name$/ && do { if($$i{Name}) {$if_title_desc = "#".$$i{Name}; last } next }; /^catname$/ && do {$if_title_desc = $if_port_name; last }; /^ppname$/ && do {$if_title_desc = $if_pp_port_name; last}; /^type$/ && do { if($$i{Type}) { $if_title_desc = "%".$$i{Type}; last } next }; /^nr$/ && do {$if_title_desc = "Interface $ifindex"; last}; /^$/ && do {$if_title_desc = $if_type_desc || $if_snmp_descr; last }; die "ERROR: Invalid value for --ifdesc: '$$router_opt{ifdesc} ($_)'\n"; } } # Now setup a large number of variables needed for the # generation of the configuration lines. $if_title_desc =~ s/\\([:@\\\/\# ])/$1/g; # unescape $if_title_desc = $if_snmp_name if not $if_title_desc; my $html_if_title_desc = html_escape($if_title_desc); my $html_desc_prefix = html_escape($desc_prefix); my $html_if_snmp_descr = html_escape($if_snmp_descr); my $html_if_snmp_name = html_escape($if_snmp_name); my $html_if_snmp_alias = html_escape($if_snmp_alias); my $html_if_cisco_descr = html_escape($if_cisco_descr); my $if_description = "$if_snmp_descr $if_snmp_alias $if_cisco_descr"; my $html_if_description = html_escape($if_description); my $if_title = "$desc_prefix$if_title_desc -- $sysname"; my $html_if_title = html_escape($if_title); my $head_lines = "### Interface $ifindex >> Descr: '$if_snmp_descr' |". " Name: '$if_snmp_name' | Ip: '$if_ip' | Eth: '$if_eth' ###\n"; my $target_lines = ""; my $separator_lines = "\n\n"; # escape the if reference $if_ref =~ s/([& :])/\\$1/g; my $default_target_directive = "Target[$target_name]: $if_ref:$router_connect"; $default_target_directive .= "\nSnmpOptions[$target_name]: $v3options" if $$router_ref{snmpopt_current} =~ /(?::[^:]*){4}:3/ ; $default_target_directive .= "\nnoHC[$target_name]: yes" if $nohc == 1; my $if_snmp_descr_save = $if_snmp_descr; $if_snmp_descr_save =~ s/"/'/g; my $default_setenv_directive = "SetEnv[$target_name]: MRTG_INT_IP=\"$if_ip\" MRTG_INT_DESCR=\"$if_snmp_descr_save\""; my $default_directory_directive = ($directory_name ? "Directory[$target_name]: $directory_name" : ""); my $default_maxbytes_directive = "MaxBytes[$target_name]: $if_speed"; $ipv4only_directive = $router_ipv4only ? "IPv4Only[$target_name]: yes" : ""; my $default_title_directive = "Title[$target_name]: $html_desc_prefix$html_if_title_desc -- $sysname"; my $default_pagetop_directive = "PageTop[$target_name]:

$html_desc_prefix$html_if_title_desc -- $sysname

"; $default_pagetop_directive .= " " if defined $if_port_name; $default_pagetop_directive .= " " if defined $if_pp_port_name; $default_pagetop_directive .= " "; $default_pagetop_directive .= " " if $if_ip; $default_pagetop_directive .= "
System: $sysname in $html_syslocation
Maintainer: $html_syscontact
Description: $html_if_description
ifType: $html_if_type_desc ($if_type_num)
ifName: $html_if_snmp_name
Port Name: $if_port_name
Port Name: $if_pp_port_name
Max Speed: $if_speed_str
Ip: $if_ip ($if_dns_name)
"; my $default_target_lines = ("\n" . $default_target_directive . "\n" . $default_setenv_directive . "\n" . ($default_directory_directive ? ($default_directory_directive . "\n") : "") . $default_maxbytes_directive . "\n" . ($ipv4only_directive ? ($ipv4only_directive . "\n") : "") . $default_title_directive . "\n" . $default_pagetop_directive . "\n"); # If --if-filter is provided, evaluate that. If it # returns true, clear @prob. If it returns false, # instead add a complaint to @prob. if (defined $$router_opt{'if-filter'}) { $@ = undef; if (eval('local $SIG{__DIE__};'.$$router_opt{'if-filter'})) { @prob = (); } else { push @prob, "filter specified by --if-filter rejected the interface"; $if_ok = 0; } die "ERROR: with if-filter $$router_opt{'if-filter'}: $@" if $@; } # issue problem report my $problem_lines = ""; if (@prob) { $problem_lines .= "### The following interface is commented out because:\n"; map {$problem_lines .= "### * $_\n"} @prob; $if_ok = 0; } # The target config generation code starts HERE. if (defined $$router_opt{'if-template'}) { # First test if the file exists and is readable, # die if not. die "File $$router_opt{'if-template'} didn't exist.\n" unless (-e $$router_opt{'if-template'} and -r $$router_opt{'if-template'}); # Open the file (or die). open IF_TEMPLATE, $$router_opt{'if-template'} or die "File $$router_opt{'if-template'} couldn't be opened.\n"; my @template_lines = readline *IF_TEMPLATE; $@ = undef; eval ('local $SIG{__DIE__};'.join( "", @template_lines)); die "Evaluation of the contents in the file \n\n$$router_opt{'if-template'}\n". "gave the error \n\n\"$@\"\n\nExiting cfgmaker\n" if $@; } else { $target_lines = $default_target_lines; } if ($target_lines && not $if_ok) { # comment out the target lines if needed $target_lines =~ s/^/\# /gm; } $conf .= ($head_lines . $problem_lines . $target_lines . $separator_lines); } # Target generation code ends HERE. } } # print any global options which might have # appeared on the command line after the last # router. if (defined $$opt{global}) { foreach my $key (@{$$opt{global}}) { $conf .= "$key\n"; } } if ($$opt{output}) { debug ('base', "Writing $$opt{output}"); open X, ">$$opt{output}" or die "ERROR: creating $$opt{output}: $!\n"; print X $conf; close X; } else { print $conf; } } # end GenConf sub IsCounterBroken ($$$) { my $if = shift; my $router_ref = shift; my $v3opt = shift; my $router = $$router_ref{routerkey}; my $fallback = 0; local $SNMP_Session::suppress_warnings = 3; local $Net_SNMP_util::suppress_warnings = 3; my $ipv4only = $$router_ref{ipv4only}; my $snmphost = v4onlyifnecessary($router, $ipv4only); if ($router =~ /:[\d.]*:[\d.]*:[\d.]*:[23]/) { my $speed = (snmpget($snmphost, $v3opt, 'ifHighSpeed.'.$if))[0] || 'unknown'; debug('base',"snmpget $snmphost for ifHighSpeed.$if -> $speed Mb/s"); $SNMP_Session::errmsg = undef; $Net_SNMP_util::ErrorMessage = undef; my $counter = (snmpget($snmphost,$v3opt, 'ifHCInOctets.'.$if))[0] || 'unknown'; debug('base',"snmpget $snmphost for ifHCInOctets.$if -> $counter"); if( $speed eq 'unknown' or $counter !~ /^\d+$/ or $SNMP_Session::errmsg or $Net_SNMP_util::ErrorMessage){ $SNMP_Session::errmsg = undef; $Net_SNMP_util::ErrorMessage = undef; $fallback = 1; debug('base',"check for HighspeedCounters failed ... Dropping back to V1"); } else { return 0; } } if ( $fallback == 1 or $$router_ref{snmpopt_current} !~ /:[\d.]*:[\d.]*:[\d.]*:[23]/) { my $counter = (snmpget($snmphost, 'ifInOctets.'.$if))[0]; if (defined $SNMP_Session::errmsg) { my $error = $SNMP_Session::errmsg; $SNMP_Session::errmsg = undef; $error =~ s/\n/\n### /g; return $error; } elsif (defined $Net_SNMP_util::ErrorMessage and $Net_SNMP_util::ErrorMessage =~ /\w/) { my $error = $Net_SNMP_util::ErrorMessage; $Net_SNMP_util::ErrorMessage = undef; $error =~ s/\n/\n### /g; return $error; } elsif (not defined $counter or $counter eq '' or $counter =~ /\D/) { return "No counter exists for $if"; } } return $fallback; } # end IsCounterBroken # DeviceInfo does fallback between IPv6 and IPv4: if an IPv6 snmpwalk returns # undef values (= an error) and the target is a hostname, then it repeats the # query using IPv4 in case the target does not support SNMP over IPv6. # If DeviceInfo falls back to IPv4, it sets the ipv4only field for the target # in the routers hash. sub DeviceInfo ($$$) { my $router=shift; my $routers=shift; my $v3opt=shift; my %DevInfo; my $ipv4only = $$routers{$router}{ipv4only}; my @variables = snmpwalk(v4onlyifnecessary($router, $ipv4only),$v3opt,'1.3.6.1.2.1.1'); # walk system if (!(defined $variables[0])) { # Do we need to fall back to IPv4? my ($community, $host) = ($1, $2) if ($router =~ /^(.*)@([^@]+)$/); if ( ( ! $ipv4only ) && ( $host !~ /^\[(.*)\]/) ) { # Not using IPv4, not an IPv6 address, so a hostname debug ('base',"No response using IPv6 for $router, trying again using IPv4"); $$routers{$router}{ipv4only} = 1; @variables = snmpwalk(v4onlyifnecessary($router, 1),$v3opt, '1.3.6.1.2.1.1'); } } if ( defined $variables[0] ) { my (%DevInfo, %revOIDS); if ($$routers{$router}{enablesnmpv3} || '' eq "yes") { no warnings; %revOIDS = reverse %Net_SNMP_util::OIDS; } else { no warnings; %revOIDS = reverse %SNMP_util::OIDS; } foreach my $variable ( @variables ) { my ($oid, $value) = split ( ':', $variable, 2); if ($revOIDS{'1.3.6.1.2.1.1.'.$oid}){ $DevInfo{ $revOIDS{'1.3.6.1.2.1.1.'.$oid} } = $value; } } # vendor identification my %vendorIDs = ( # Add your vendor here # sysObjectID Vendora '1.3.6.1.4.1.11863.' => 'tplink', '1.3.6.1.4.1.43.' => '3com', '1.3.6.1.4.1.11.' => 'hp', '1.3.6.1.4.1.9.' => 'cisco', '1.3.6.1.4.1.171.' => 'dlink', '1.3.6.1.4.1.6141.' => 'wwp', '1.3.6.1.4.1.674.10895.' => 'dellLan', '1.3.6.1.4.1.1916.' => 'extremenetworks', '1.3.6.1.4.1.1991.' => 'foundry', '1.3.6.1.4.1.6027.' => 'force10', '1.3.6.1.4.1.2636.' => 'juniper', '1.3.6.1.4.1.94.' => 'nokiaipsofw', '1.3.6.1.4.1.307.' => 'portmaster', '1.3.6.1.4.1.890.' => 'zyxel', '1.3.6.1.4.1.2272.30' => 'nortel', '1.3.6.1.4.1.6339' => 'DCN', '1.3.6.1.4.1.30155.' => 'openBSD', '1.3.6.1.4.1.30065.' => 'arista', '1.3.6.1.4.1.5624.' => 'enterasys', '1.3.6.1.4.1.30803.' => 'Vyatta', '1.3.6.1.4.1.3955.' => 'LinkSys', '1.3.6.1.4.1.1588.' => 'brocade', '1.3.6.1.4.1.3709.' => 'datacom', '1.3.6.1.4.1.14988.' => 'mikrotik', '1.3.6.1.4.1.6486.' => 'alcatel', '1.3.6.1.4.1.2011.' => 'huawei', '1.3.6.1.4.1.35265.' => 'eltex' ); $DevInfo{Vendor} = 'Unknown Vendor - '.$DevInfo{sysObjectID}; foreach (keys %vendorIDs) { $DevInfo{Vendor} = $vendorIDs{$_} if ($DevInfo{sysObjectID} =~ /\Q$_\E/); } debug('base',"Vendor Id: $DevInfo{Vendor}"); return \%DevInfo; } else { # we just die because the snmp module has already complained return undef; } } # end DeviceInfo sub fmi ($$) { my $number = shift; my $flags = shift; my(@short); if ($$flags{bits}){ $number*=8; @short = ("bits/s","kbits/s","Mbits/s","Gbits/s"); } else { @short = ("Bytes/s","kBytes/s","MBytes/s","GBytes/s"); } my $digits=length("".$number); my $divm=0; while ($digits-$divm*3 > 4) { $divm++; } my $divnum = $number/10**($divm*3); return sprintf("%1.1f %s",$divnum,$short[$divm]); } # end fmi sub IfType ($) { my $id = shift; my $ift = { '1'=>'Other', '2'=>'regular1822', '3'=>'hdh1822', '4'=>'ddnX25', '5'=>'rfc877x25', '6'=>'ethernetCsmacd', '7'=>'iso88023Csmacd', '8'=>'iso88024TokenBus', '9'=>'iso88025TokenRing', '10'=>'iso88026Man', '11'=>'starLan', '12'=>'proteon10Mbit', '13'=>'proteon80Mbit', '14'=>'hyperchannel', '15'=>'fddi', '16'=>'lapb', '17'=>'sdlc', '18'=>'ds1', '19'=>'e1', '20'=>'basicISDN', '21'=>'primaryISDN', '22'=>'propPointToPointSerial', '23'=>'ppp', '24'=>'softwareLoopback', '25'=>'eon', '26'=>'ethernet-3Mbit', '27'=>'nsip', '28'=>'slip', '29'=>'ultra', '30'=>'ds3', '31'=>'sip', '32'=>'frame-relay', '33'=>'rs232', '34'=>'para', '35'=>'arcnet', '36'=>'arcnetPlus', '37'=>'atm', '38'=>'miox25', '39'=>'sonet', '40'=>'x25ple', '41'=>'iso88022llc', '42'=>'localTalk', '43'=>'smdsDxi', '44'=>'frameRelayService', '45'=>'v35', '46'=>'hssi', '47'=>'hippi', '48'=>'modem', '49'=>'aal5', '50'=>'sonetPath', '51'=>'sonetVT', '52'=>'smdsIcip', '53'=>'propVirtual', '54'=>'propMultiplexor', '55'=>'100BaseVG', '56'=>'Fibre Channel', '57'=>'HIPPI Interface', '58'=>'Obsolete for FrameRelay', '59'=>'ATM Emulation of 802.3 LAN', '60'=>'ATM Emulation of 802.5 LAN', '61'=>'ATM Emulation of a Circuit', '62'=>'FastEthernet (100BaseT)', '63'=>'ISDN & X.25', '64'=>'CCITT V.11/X.21', '65'=>'CCITT V.36', '66'=>'CCITT G703 at 64Kbps', '67'=>'Obsolete G702 see DS1-MIB', '68'=>'SNA QLLC', '69'=>'Full Duplex Fast Ethernet (100BaseFX)', '70'=>'Channel', '71'=>'Radio Spread Spectrum (802.11)', '72'=>'IBM System 360/370 OEMI Channel', '73'=>'IBM Enterprise Systems Connection', '74'=>'Data Link Switching', '75'=>'ISDN S/T Interface', '76'=>'ISDN U Interface', '77'=>'Link Access Protocol D (LAPD)', '78'=>'IP Switching Objects', '79'=>'Remote Source Route Bridging', '80'=>'ATM Logical Port', '81'=>'AT&T DS0 Point (64 Kbps)', '82'=>'AT&T Group of DS0 on a single DS1', '83'=>'BiSync Protocol (BSC)', '84'=>'Asynchronous Protocol', '85'=>'Combat Net Radio', '86'=>'ISO 802.5r DTR', '87'=>'Ext Pos Loc Report Sys', '88'=>'Apple Talk Remote Access Protocol', '89'=>'Proprietary Connectionless Protocol', '90'=>'CCITT-ITU X.29 PAD Protocol', '91'=>'CCITT-ITU X.3 PAD Facility', '92'=>'MultiProtocol Connection over Frame/Relay', '93'=>'CCITT-ITU X213', '94'=>'Asymmetric Digital Subscriber Loop (ADSL)', '95'=>'Rate-Adapt Digital Subscriber Loop (RDSL)', '96'=>'Symmetric Digital Subscriber Loop (SDSL)', '97'=>'Very High Speed Digital Subscriber Loop (HDSL)', '98'=>'ISO 802.5 CRFP', '99'=>'Myricom Myrinet', '100'=>'Voice recEive and transMit (voiceEM)', '101'=>'Voice Foreign eXchange Office (voiceFXO)', '102'=>'Voice Foreign eXchange Station (voiceFXS)', '103'=>'Voice Encapsulation', '104'=>'Voice Over IP Encapsulation', '105'=>'ATM DXI', '106'=>'ATM FUNI', '107'=>'ATM IMA', '108'=>'PPP Multilink Bundle', '109'=>'IBM IP over CDLC', '110'=>'IBM Common Link Access to Workstation', '111'=>'IBM Stack to Stack', '112'=>'IBM Virtual IP Address (VIPA)', '113'=>'IBM Multi-Protocol Channel Support', '114'=>'IBM IP over ATM', '115'=>'ISO 802.5j Fiber Token Ring', '116'=>'IBM Twinaxial Data Link Control (TDLC)', '117'=>'Gigabit Ethernet', '118'=>'Higher Data Link Control (HDLC)', '119'=>'Link Access Protocol F (LAPF)', '120'=>'CCITT V.37', '121'=>'CCITT X.25 Multi-Link Protocol', '122'=>'CCITT X.25 Hunt Group', '123'=>'Transp HDLC', '124'=>'Interleave Channel', '125'=>'Fast Channel', '126'=>'IP (for APPN HPR in IP Networks)', '127'=>'CATV MAC Layer', '128'=>'CATV Downstream Interface', '129'=>'CATV Upstream Interface', '130'=>'Avalon Parallel Processor', '131'=>'Encapsulation Interface', '132'=>'Coffee Pot', '133'=>'Circuit Emulation Service', '134'=>'ATM Sub Interface', '135'=>'Layer 2 Virtual LAN using 802.1Q', '136'=>'Layer 3 Virtual LAN using IP', '137'=>'Layer 3 Virtual LAN using IPX', '138'=>'IP Over Power Lines', '139'=>'Multi-Media Mail over IP', '140'=>'Dynamic synchronous Transfer Mode (DTM)', '141'=>'Data Communications Network', '142'=>'IP Forwarding Interface', '144'=>'IEEE1394 High Performance Serial Bus', '150'=>'MPLS Tunnel Virtual Interface', '161'=>'IEEE 802.3ad Link Aggregate', '162'=>'Cisco Express Forwarding Interface', '166'=>'MPLS', '238'=>'Asymmetric Digital Subscriber Loop', '246'=>'Pseudowire interface type', '251'=>'Very high speed digital subscriber line', }; return ($ift->{$id} || "Unknown Interface Type"); } # end IfType sub options ($$) { my $opt = shift; my $routers = shift; my $noofrouter = 0; # How many routers we've seen on cmdline. # The $flags hash stores what we've seen in Options[_], # Options[^] and Options[$] so far. # A cmdline arg like --global 'Options[_]: bits' will insert # the element $$flags{default}{bits}="set". # Similarly --global 'Options[$]:' will delete all elements # in $$flags{append} # # This was originally created to manipulate the "bits" flag # so fmi should know when to use "bits" or "bytes". It might # be overkill to use such a complex solution but it makes life # easier if cfgmaker in the future has to be extended to be # aware of other Options[] settings like gauge, growright etc. my %flags; { my $def = {}; my $pre = {}; my $app = {}; %flags = (default => $def, prepend => $pre, append => $app); } my $addrouter_ornf = addrouter($opt, $routers, \$noofrouter, \%flags); Getopt::Long::Configure("permute"); GetOptions( $opt, 'help|?', 'man', 'subdirs=s', 'no-down', 'show-op-down', 'noreversedns', 'ifref=s', 'ifdesc=s', 'if-filter=s', 'if-template=s', 'interfaces!', 'host-template=s', 'community=s', 'username=s', 'authkey=s', 'authpassword=s', 'authprotocol=s', 'contextengineid=s', 'contextname=s', 'privkey=s', 'privpassword=s', 'privprotocol=s', 'snmp-options=s', 'dns-domain=s', 'version', 'output=s', 'global=s@', 'nodefaultglobal', 'enable-ipv6', 'enablesnmpv3', 'use-16bit', 'zero-speed=s', '<>', $addrouter_ornf) or pod2usage(2); die("cfgmaker for mrtg-2.17.10\n") if $$opt{version}; pod2usage(-exitval => 0, -verbose => 2) if $$opt{man}; pod2usage(-verbose => 1) if not keys %$routers; } # end options # The callback routine used by GetOptions to process "non-option # strings" (routers) among the arguments is given only ONE argument. # However, I want it to be able to specify both the %options hash # (for read access) and the %routers hash (for modifying) as well # as the router's name. This makes for three arguments. # # The solution is to use a closure. addrouter takes a opt hash, a # routers hash, an index to the current number of routers and a flags # hash and then returns a function which "remembers" these # values (the closure) but also takes an argument (the router name). sub addrouter() { my $opt = shift; my $routers = shift; my $noofrouter = shift; my $flags = shift; return sub { my $rawname = shift; $$noofrouter++; # First increase the number of routers seen. my ($community,$routername,$routerkey,$snmpopt,$dnsdomain,$tmpname,@tmpsnmp); # Now make sure that the router is defined with the # proper community, domainname and SNMP options. # Dissect the rawname to find out what it contains. # First check for community: if ($rawname =~ /^(.+)\@([^@]+)$/) { # Community was given explicitly! $community = $1; $tmpname = $2 } else { $community = $$opt{community}; $tmpname = $rawname; } # Now separate the router name from the options. We # can't just split on the : character because a numeric # IPv6 address contains a variable number of :'s if( ($tmpname =~ /^(\[.*\]):(.*)$/) || ($tmpname =~ /^(\[.*\])$/) ){ # Numeric IPv6 address between [] ($routername, $snmpopt) = ($1, $2); } else { # Hostname or numeric IPv4 address ($routername, $snmpopt) = split(':', $tmpname, 2); } @tmpsnmp = split(':', $snmpopt || ''); $routername =~ s/\.$//; # if the hostname ends in a '.' remove it # it seems to cause trouble in some other # parts of mrtg # Now setup the SNMP options. if (not defined $$opt{'snmp-options'}) { $snmpopt = ':' . (join ':', @tmpsnmp); # No merge needed. } else { my ($t,$o,@s); my @optsnmp = split ':',$$opt{'snmp-options'}; # Trim first element as the SNMP options start # with a colon and thus the first element is a # dummy "" string not corresponding to any SNMP option # (or rather, corresponding to a router, if there had # been one...) shift @optsnmp; while ((scalar @tmpsnmp > 0) or (scalar @optsnmp > 0)) { $t = shift @tmpsnmp; $o = shift @optsnmp; if(not defined $t) {$t = "";} if(not defined $o) {$o = "";} if($t ne "") { push @s, $t; } else { push @s, $o; } } $snmpopt = ':' . (join ':', @s); } my $newopt={}; # Perhaps unnecessary initialization but... foreach my $o (keys %$opt) { my $ovalue = $$opt{$o}; $$newopt{$o} = $ovalue unless ($o =~ /^fullcmd$/ or $o =~ /^community$/ or $o =~ /^snmp-options$/ or $o =~ /^global$/ or $o =~ /^output$/ ); # Ok, copy the --globals array from $$opt so we know # that which global(s) to print out into the config. push @{$$newopt{$o}}, @{$$opt{$o}} if ($o =~ /^global$/); # Go through these --global statements one by one. # If anyone of them contains Options[] for any of the # targets [_], [^] or [_], process those statements # tenderly and populate the $$flags{}{} hashes accordingly. for my $g (@{$$opt{"global"}}) { if ($g =~ /^options\[([_^\$])\]:\s*(.*)$/i){ my ($t,$fs); $t = $1; $fs = $2; $t =~ s/_/default/; $t =~ s/\^/prepend/; $t =~ s/\$/append/; # If a line like "options[X]:" is found clear # all flags for that category and then go to next # --global 'Options[..' line if any. if ($fs =~ /^\s*$/) { $$flags{$t} = {}; next; } else { for my $f (split /\s*,\s*/,$fs) { $$flags{$t}{$f} = "set"; } } } } $$opt{$o} = [] if ($o =~ /^global$/); } # Now let this router get it's own copy of # the "currently effective" flags. # Note, Options[_] should only be considered # if Options[^] and Options[$] both are absent. my $newflags = {}; if((0 == keys %{$$flags{prepend}}) and (0== keys %{$$flags{append}})) { for my $f (keys %{$$flags{default}}) { $$newflags{$f}="set"; } } else { for my $f (keys %{$$flags{prepend}}, keys %{$$flags{append}}) { $$newflags{$f}="set"; } } if(defined $$opt{'dns-domain'}) { $dnsdomain=$$opt{'dns-domain'}; } else { $dnsdomain=""; } $routerkey = "${community}\@${routername}" . (($dnsdomain eq "")?"":".") . "${dnsdomain}${snmpopt}"; $$routers{$routerkey}= { # rawname is the unprocessed string from the # command line. rawname => $rawname, # opt is the commandline options which are # in effect for THIS particular router. opt => $newopt, # noofrouter is the unique number for the # router. The first router on the command # line is given number 1, the second number 2 # and so on. noofrouter => $$noofrouter, # flags contains which --global 'Options[^_$]: flags' # are effective for THIS particular router. flags => $newflags, # community is the SNMP community used for the router community => $community, # snmpopt is the SNMP options on the form # [port[:timeout[:retries[:backoff[:version]]]]] # The empty string simply means that no # specific SNMP options has been given. 'snmp-options' => $snmpopt, snmpopt_current => $snmpopt, # dns-domain is a domain which should be added # to the routers hostname. # e.g if dns-domain is place.xyz and host is router # the host "router.place.xyz" will be polled. # If host is "router.dept" the poll will be against # "router.dept.place.xyz". 'dns-domain' => $dnsdomain, # routername is the routers name as given on the # command line but with SNMP community (if given) # and SNMP options (if given) stripped. # # (Yes, routername COULD be on the form # "host.domain" or "host.subdomain.domain") routername => $routername, # routerkey is the same as the has key used for the # router, which is the router name with everything # taken into account: community, dns-domain and # snmp-options. This is the value used when doing # SNMP communication with the router. routerkey => $routerkey, }; } } # end addrouter sub html_escape ($) { my $s = shift || ''; $s =~ s/&/&/g; $s =~ s//>/g; $s =~ s/[\n\r]+([^\n\r])/
\n $1/g; return $s; } # end html_escape sub oid_pick ($$$;@){ my $router = shift; my $v3opt = shift; my @oids = @_; local $SNMP_Session::suppress_warnings = 3; foreach my $oid (@oids){ local $SNMP_Session::errmsg = undef; my $counter = snmpget($router,$v3opt,$oid); if (not defined $SNMP_Session::errmsg and defined $counter and $counter ne '' ) { debug('base',"oid_pick - found $oid to work for $router"); return $oid; } } debug('base',"oid_pick - none of ".(join ",",@oids)." seem to work for $router"); return undef; } sub parsev3 ($) { my $opt = shift; my %v3opt; if (!exists ($$opt{username})) { die "SMNP V3 requires a --username parameter as part of the User Security Model"; } else { $v3opt{username} = $$opt{username}; } $v3opt{contextname} = $$opt{contextname} if exists($$opt{contextname}); if (exists ($$opt{authkey})) { die "Can't use both an --authkey and --authpassword in the User Security Model" if exists($$opt{authpassword}); $v3opt{authkey} = $$opt{authkey}; } if (exists ($$opt{authpassword})) { die "Use of --authpassword requires --contextengineid" if !exists($$opt{contextengineid}); $v3opt{authpassword} = $$opt{authpassword}; } if (exists ($$opt{authprotocol})) { die "Only sha and md5 are defined for --authprotocol" if $$opt{authprotocol} !~ /^(md5|sha)$/i; die "--authprotocol can only be used with --authpassword or --authkey" if ! exists($$opt{authpassword}) and ! exists($$opt{authkey}); ($v3opt{authprotocol}) = (lc($$opt{authprotocol}) =~ /^(md5|sha)$/); } if (exists ($$opt{privkey})) { die "Can't use both an --privkey and --privpassword in the User Security Model" if exists($$opt{privpassword}); die "Can't have privacy parameters without authentication in the User security Model" if ! exists($$opt{authpassword}) and ! exists($$opt{authkey}); $v3opt{privkey} = $$opt{privkey}; } if (exists ($$opt{privpassword})) { die "Use of --privpassword requires --contextengineid" if !exists($$opt{contextengineid}); die "Can't have privacy parameters without authentication in the User security Model" if ! exists($$opt{authpassword}) and ! exists($$opt{authkey}); $v3opt{privpassword} = $$opt{privpassword}; } if (exists ($$opt{privprotocol})) { die "Only des, 3des, 3desede, aes, aes128 are defined for --privprotocol" if $$opt{privprotocol} !~ /^(?:3?des(?:ede)?|aes(?:128)?)$/; die "--privprotocol can only be used with --privpassword or --privkey" if ! exists($$opt{privpassword}) and ! exists($$opt{privkey}); $v3opt{privprotocol} = lc($$opt{privprotocol}); } return %v3opt; } sub init () { snmpmapOID('sysObjectID' => '1.3.6.1.2.1.1.2.0', 'CiscolocIfDescr' => '1.3.6.1.4.1.9.2.2.1.1.28', 'CiscoCatalystPortName' => '1.3.6.1.4.1.9.5.1.4.1.1.4', 'ppPortName' => '1.3.6.1.4.1.2272.1.4.10.1.1.35', 'vlanTrunkPortDynamicStatus'=> '1.3.6.1.4.1.9.9.46.1.6.1.1.14', 'vmVlan' => '1.3.6.1.4.1.9.9.68.1.2.2.1.2', 'ifAlias' => '1.3.6.1.2.1.31.1.1.1.18'); } # end init __END__ =pod =head1 NAME cfgmaker - Creates mrtg.cfg files (for mrtg-2.17.10) =head1 SYNOPSIS cfgmaker [options] [community@]router [[options] [community@]router ...] =head1 OPTIONS --ifref=name interface references by Interface Name (default) --ifref=ip ... by Ip Address --ifref=eth ... by Ethernet Number --ifref=descr ... by Interface Description --ifref=nr ... by Interface Number --ifref=type ... by Interface Type You may also use multiple options separated by commas, in which case the first available one is used: e.g. --ifref=ip,name,nr --ifdesc=nr interface description uses Interface Number (default) --ifdesc=ip ... uses Ip Address --ifdesc=eth ... uses Ethernet Number --ifdesc=descr ... uses Interface Description --ifdesc=name ... uses Interface Name --ifdesc=catname ... uses CatOS Interface Name --ifdesc=ppname ... uses Passport Port Name --ifdesc=alias ... uses Interface Alias --ifdesc=type ... uses Interface Type You may also use multiple options separated by commas, in which case the first available one is used: e.g. --ifdesc=catname,ppname,descr,alias,ip,name,nr --if-filter=f Test every interface against filter f to decide whether or not to include that interface into the collection. Currently f is being evaluated as a Perl expression and it's truth value is used to reject or accept the interface. (Experimental, under development, might change) --if-template=templatefile Replace the normal target entries for the interfaces with an entry as specified by the contents in the file templatefile. The file is supposed to contain Perl code to be executed to generate the lines for the target in the configuration file. (Experimental, under development, might change) --host-template=templatefile In addition to creating targets for a host's interfaces do also create targets for the host itself as specified by the contents in the file templatefile. The file is supposed to contain Perl code to be executed to generate the lines for the host related targets (such as CPU, ping response time measurements etc.) in the config- uration file. (Experimental, under development, might change) --global "x: a" add global config entries --nodefaultglobal do not include default global settings --no-down do not look at admin or opr status of interfaces --show-op-down show interfaces which are operatively down --zero-speed=spd use this speed in bits-per-second as the interface speed for all interfaces that return a speed of 0 via ifSpeed/ifHighSpeed. 100Mbps = 100000000 --subdirs=format give each router its own subdirectory, naming each per "format", in which HOSTNAME and SNMPNAME will be replaced by the values of those items -- for instance, --subdirs=HOSTNAME or --subdirs="HOSTNAME (SNMPNAME)" --noreversedns do not reverse lookup ip numbers --community=cmty Set the default community string to "cmty" instead of "public". --enable-ipv6 Enable IPv6 support, if the required libraries are present. Numeric IPv6 addresses must be enclosed in square brackets, e.g. public@[2001:760:4::1]:161 --use-16bit Use 16bit SNMP request IDs to query all routers. --snmp-options=:[][:[][:[][:[][:]]]] Specify default SNMP options to be appended to all routers following. Individual fields can be empty. Routers following might override some or all of the options given to --snmp-options. --dns-domain=domain Specifies a domain to append to the name of all routers following. --nointerfaces Don't do generate any configuration lines for interfaces, skip the step of gathering interface information and don't run any interface template code. --interfaces Generate configuration lines for interfaces (this is the default). The main purpose of this option is to negate an --nointerfaces appearing earlier on the command line. --help brief help message --man full documentation --version print the version of cfgmaker --output=file output filename default is STDOUT =head1 DESCRIPTION B creates MRTG configuration files based on information pulled from a router or another SNMP manageable device. [IB<@>]I I is the community name of the device you want to create a configuration for. If not specified, it defaults to 'B'; you might want to try this first if you do not know the community name of a device. If you are using the wrong community name you will get no response from the device. I is the DNS name or the IP number of an SNMP-manageable device. Following the name you can specify 6 further options separated by colons. The full syntax looks like this: B[:[B][:[B][:[B][:[B][:B]]]]] Of special interest may be the last parameter, B. If you set this to '2' then your device will be queried with SNMP version 2 requests. This allows you to poll the 64 bit traffic counters in the device and will thus work much better with fast interfaces (no more counter overrun). Note that the order in which the routers are specified on the command line do matter as the same order is used when the configuration file is generated. The first specified router has it's configuration lines generated first, followed by the lines belonging to the next router and so on. Note that the first line of the generated cfg file will contain all the commandline options you used for generating it. This is to allow for the easy 'regeneration' in case you want to add newhosts or make some other global change. =head2 Configuration Except for the B<--output> and B<--global> options, all options affect only the routers following them on the command line. If an option specified earlier on the command line reappears later on the command line with another value, the new value overrides the old value as far as remaining routers are concerned. This way options might be tailored for groups of routers or for individual routers. See B<--output> and B<--global> for how their behaviour is affected by where or how many times they appear on the command line. See the B below on how to set an option differently for multiple routers. =over =item B<--help> Print a brief help message and exit. =item B<--man> Prints the manual page and exits. =item B<--version> Print the version of cfgmaker. This should match the version of MRTG for which config files are being created. =item B<--ifref> B|B|B|B|B Select the interface identification method. Default is B which identifies the router interfaces by their number. Unfortunately the interface numbering scheme in an SNMP tree can change. Some routers change their numbering when new interfaces are added, others change their numbering every full moon just for fun. To work around this sad problem MRTG can identify interfaces by 4 other properties. None of these works for all interfaces, but you should be able to find one which does fine for you. Note that especially ethernet addresses can be problematic as some routers have the same ethernet address on most of their interface cards. Select B to identify the interface by its IP number. Use B to use the ethernet address for identification. Use B to use the Interface description. Or use B to use the Interface name. You can specify multiple properties if you wish, separated by commas. In this case, cfgmaker will use the first item in the list which can provide unique identification. This allows you to specify, for example, to use IP address and to use ifName if this is not defined: --ifref ip,name If your chosen method does not allow unique interface identification on the device you are querying, B will tell you about it. =item B<--ifdesc> B|B|B|B|B|B|B Select what to use as the description of the interface. The description appears in the C property for the target as well as the text header in the HTML code defined in the target's C. Default is to use B which is just the interface number which isn't always useful to the viewer of the graphs. There are 6 other properties which could be used. Use B if you want to use the interface's IP-address. Use B if you want to use the interface's ethernet address. If you want a better description, you can use either B, B or B. Exactly what each of these do varies between different equipment so you might need to experiment. For instance, for a serial interface on a Cisco router running IOS using B might result in C<"S0"> being the interface description , B might result in C<"Serial0"> and B might result in C<"Link to HQ"> (provided that is what is used as the interface's C in the router's configuration). Finally, if you want to describe the interface by it's Btype (i.e C<"ethernetCSMA">, C<"propPointtoPoint"> etc) you can use B. You can specify multiple properties if you wish, separated by commas. In this case, cfgmaker will use the first item in the list which is available for this interface. This allows you to specify, for example, to use any of the different aliases in order of preference. =item B<--if-filter> 'B' First of all, this is under some development and is experimental. Use this if you want to have better control over what interfaces gets included into the configuration. The B is evaluated as a piece of Perl code and is expected to return a truth value. If true, include the interface and if false, exclude the interface. For a further discussion on how these filters work, see the section L
below. =item B<--if-template> B First of all, this is under some development and is experimental. Use this if you want to control what the line for each target should look like in the configuration file. The contents of the file B will be evaluated as a Perl program which generates the lines using certain variables for input and output. For a further discussion on how these templates work, see the section L
below. =item B<--host-template> B First of all, this is under some development and is experimental. Use this if you want to have some extra targets related to the host itself such as CPU utilization, ping response time to the host, number of busy modems etc. The contents of the file B will be evaluated once per host as a Perl program which generates the lines using certain variables for input and output. For a further discussion on how these templates work, see the section L
below. =item B<--community> B Use this to set the community for the routers following on the command line to B. Individual routers might override this community string by using the syntax BB<@>B. =item B<--enable-ipv6> This option enables IPv6 support. It requires the appropriate perl modules; if they are not found then IPv6 is disabled (see the ipv6 documentation). cfgmaker will use IPv6 or IPv4 depending on the target. If the target is a numeric address, the protocol depends on the type of address. If the target is a hostname, cfgmaker will try to resolve the name first to an IPv6 address then to an IPv4 address. IPv6 numeric addresses must be specified between square braces. For example: cfgmaker --enable-ipv6 [2001:760:4::1]:165:::2 If the target has both an IPv6 address and an IPv4 address with the same hostname, cfgmaker first queries the target using IPv6 and falls back to IPv4 if it fails. This is useful for targets which don't support SNMP over IPv6. =item B<--use-16bit> This option forces the use of 16bit SNMP request IDs. Some broken SNMP agents do not accept 32bit request IDs. Try to avoid this option as much as possible, complain to your agent vendor instead. =item B<--snmp-options> :[B][:[B][:[B][:[B][:B]]]] Use this to set the default SNMP options for all routers following on the command line. Individual values might be omitted as well as trailing colons. Note that routers might override individual (or all) values specified by B<--snmp-options> by using the syntax B[:[B][:[B][:[B][:[B][:B]]]]] =item B<--global> B<">IB<"> Use this to add global options to the generated config file. You can call B<--global> several times to add multiple options. The line will appear in the configuration just before the config for the next router appearing on the command line. --global "workdir: /home/mrtg" If you want some default Options you might want to put --global "options[_]: growright,bits" Specifying B<--global> after the last router on the command line will create a line in the configuration file which will appear after all the routers. =item B<--noreversedns> Do not try to reverse lookup IP numbers ... a must for DNS free environments. =item B<--no-down> Normally cfgmaker will not include interfaces which are marked anything but administratively and operationally UP. With this switch you get them all. =item B<--show-op-down> Include interfaces which are operatively down. =item B<--zero-speed> I Assign this speed in bits-per-second to all interfaces which return 0 for ifSpeed and ifHighSpeed. Some switches, notably Foundry equipment, return a speed of zero for some interfaces. For example, to have all interfaces reporting zero set to 100Mbps, use --zero-speed=100000000. =item B<--subdirs> I Give each router its own subdirectory for the HTML and graphics (or .rrd) files. The directory name is the given I string with a couple of pattern replacements. The string "HOSTNAME" will be replaced by the hostname of the router (however you specified it on the B commandline -- it may be an actual hostname or just an IP address), and "SNMPNAME" will be replaced with the device's idea of its own name (the same name that appears on the right side of the "Title" lines). For instance, a call like: cfgmaker --subdirs=HOSTNAME__SNMPNAME public@10.10.0.18 would result in the generation of lines looking something like: Directory[10.10.0.18_1]: 10.10.0.18__fp2200-bothrip-1.3 =item B<--output> I Write the output from B into the file I. The default is to use C. B<--output> is expected to appear only once on the command line. If used multiple times, the file specified by the last B<--output> will be used. =item B<--nointerfaces> Don't generate configuration lines for interfaces. This makes cfgmaker skip all steps related to interfaces which means it will not do any polling of the router to retrieve interface information which speeds up the execution of cfgmaker and it will neither run any interface templates. =item B<--interfaces> This makes cfgmaker generate configuration lines for interfaces (the default behaviour). The main usage of this option is to negate an --nointerfaces appearing earlier on the command line. =back =head2 SNMP V3 Options B supports SNMP V3 using the B perl module. There are optional parameters affecting SNMP operation. =over =item --enablesnmpv3 {yes|no} The B<--enablesnmpv3> option is an optional flag to check for the presence of the B libraries. B will try to determine whether this flag is required and will set the values automatically. =back =head3 SNMPv3 Arguments A SNMP context is a collection of management information accessible by a SNMP entity. An item of management information may exist in more than one context and a SNMP entity potentially has access to many contexts. The combination of a contextEngineID and a contextName unambiguously identifies a context within an administrative domain. In a SNMPv3 message, the contextEngineID and contextName are included as part of the scopedPDU. All methods that generate a SNMP message optionally take a B<--contextengineid> and B<--contextname> argument to configure these fields. =over =item Context Engine ID The B<--contextengineid> argument expects a hexadecimal string representing the desired contextEngineID. The string must be 10 to 64 characters (5 to 32 octets) long and can be prefixed with an optional "0x". Once the B<--contextengineid> is specified it stays with the object until it is changed again or reset to default by passing in the undefined value. By default, the contextEngineID is set to match the authoritativeEngineID of the authoritative SNMP engine. =item Context Name The contextName is passed as a string which must be 0 to 32 octets in length using the B<--contextname> argument. The contextName stays with the object until it is changed. The contextName defaults to an empty string which represents the "default" context. =back =head3 User-based Security Model Arguments The User-based Security Model (USM) used by SNMPv3 requires that a securityName be specified using the B<--username> argument. The creation of a Net::SNMP object with the version set to SNMPv3 will fail if the B<--username> argument is not present. The B<--username> argument expects a string 1 to 32 octets in length. Different levels of security are allowed by the User-based Security Model which address authentication and privacy concerns. A SNMPv3 target will derive the security level (securityLevel) based on which of the following arguments are specified. By default a securityLevel of 'noAuthNoPriv' is assumed. If the B<--authkey> or B<--authpassword> arguments are specified, the securityLevel becomes 'authNoPriv'. The B<--authpassword> argument expects a string which is at least 1 octet in length. Optionally, the B<--authkey> argument can be used so that a plain text password does not have to be specified in a script. The B<--authkey> argument expects a hexadecimal string produced by localizing the password with the authoritativeEngineID for the specific destination device. The C utility included with the Net::SNMP distribution can be used to create the hexadecimal string (see L). Two different hash algorithms are defined by SNMPv3 which can be used by the Security Model for authentication. These algorithms are HMAC-MD5-96 "MD5" (RFC 1321) and HMAC-SHA-96 "SHA-1" (NIST FIPS PUB 180-1). The default algorithm used by the module is HMAC-MD5-96. This behavior can be changed by using the B<--authprotocol> argument. This argument expects either the string 'md5' or 'sha' to be passed to modify the hash algorithm. By specifying the arguments B<--privkey> or B<--privpassword> the securityLevel associated with the object becomes 'authPriv'. According to SNMPv3, privacy requires the use of authentication. Therefore, if either of these two arguments are present and the B<--authkey> or B<--authpassword> arguments are missing, the creation of the object fails. The B<--privkey> and B<--privpassword> arguments expect the same input as the B<--authkey> and B<--authpassword> arguments respectively. The User-based Security Model described in RFC 3414 defines a single encryption protocol to be used for privacy. This protocol, CBC-DES "DES" (NIST FIPS PUB 46-1), is used by default or if the string 'des' is passed to the B<--privprotocol> argument. By working with the Extended Security Options Consortium http://www.snmp.com/eso/, the module also supports additional protocols which have been defined in draft specifications. The draft http://www.snmp.com/eso/draft-reeder-snmpv3-usm-3desede-00.txt defines the support of CBC-3DES-EDE "Triple-DES" (NIST FIPS 46-3) in the User-based Security Model. This protocol can be selected using the B<--privprotocol> argument with the string '3desede'. The draft http://www.snmp.com/eso/draft-blumenthal-aes-usm-04.txt describes the use of CFB128-AES-128/192/256 "AES" (NIST FIPS PUB 197) in the USM. The three AES encryption protocols, differentiated by their key sizes, can be selected by passing 'aescfb128', 'aescfb192', or 'aescfb256' to the B<-privprotocol> argument. =head2 Details on Filters The purpose of the filters is to decide which interfaces to accept and which interfaces to reject. This decision is done for each interface by evaluating the filter expression as a piece of Perl code and investigating the result of the evaluation. If true, accept the interface otherwise reject it. When working with filters, remember that Perl has it's own idea of what truth and false is. The empty string "" and the string "0" are false, all other strings are true. This further implies that any integer value of 0 is false as well as any undef value. It also implies that all references are considered true. As the filter is evaluated as a Perl expression, several useful constructs in Perl are worth mentioning: Expressions might be grouped by using parentheses "()". Expressions might be combined using boolean operators such as the following: =over =item "B" (equivalent with "B<&&>") Boolean "and" of the two expressions, is only true if both expressions are true. Example: I B I =item "B" (equivalent with "B<||>") Boolean "or" of the two expressions, is true if either or both expressions are true. Example: I B I =item "B" (equivalent with "B") Boolean negation of a single expression. Example: B I . Yet another example: BI =back (For more details on this I recommend a book on Perl) =head3 Predefined Filter Variables To facilitate, there are a number of predefined values available to use in the filter. Note that these variables are also available when templates interfaces are evaluated (but not host templates). Caveat: All these variables' names begin with a dollar sign ($), which is a syntactic requirement for scalar variables in Perl. The danger here is that the dollar sign in many shells is an active character (often used for shell variables exactly as in Perl variables) so it is important to ensure that the Perl expression isn't evaluated by the command line shell as shell code before being passed to cfgmaker as command line arguments. In shells like Bourne shell, ksh shell or bash shell, placing the entire expression within single quotes will avoid such accidental evaluation: '--if-filter=($default_iftype && $if_admin)' =over =item B<$if_type> This is an integer specifying the interface type as per the SNMP standards and as reported by the polled device. A complete list of interface types would be impractical for this document , but there are a number predefined variables below. Normally, cfgmaker puts in the target's PageTop this iftype value within parenthesis after the name of the interface type. (e.g "propPointToPointSerial (22)"). Here's a list of some of the most common interface types by number: 6 ethernetCsmacd 7 iso88023Csmacd 9 iso88025TokenRing 15 fddi 19 E1 20 basicISDN 21 primaryISDN 22 propPointToPointSerial 23 ppp 24 softwareLoopback 30 ds3 32 frame-relay 33 rs232 37 atm 39 sonet 44 frameRelayService 46 hssi 49 aal5 53 propVirtual 62 Fast Ethernet (100BaseT) 63 ISDN & X.25 69 Full Duplex Fast Ethernet (100BaseFX) 94 Asymmetric Digital Subscriber Loop (ADSL) 117 Gigabit Ethernet 134 ATM Sub Interface =item B<$default> True if and only if cfgmaker normally should accepted the interface based on the interfaces administrative and operational state (taking the flags B<--no-down> and B<--show-op-down> into account) and it's type (and a few other things). =item B<$default_ifstate> True if and only if cfgmaker would have accepted the interface based on it's operational and administrative states (also taking into account the presence of the flags B<--no-down> and B<--show-op-down>). =item B<$default_iftype> True if and only if cfgmaker would have accepted the interface based on it's type (and a few type specific details in addition). =item B<$if_admin> True if and only if the interface is in an administrative up state. =item B<$if_oper> True if and only if the interface is in an operational up state. =back A number of variables are also predefined to easily decide if an interface belong to a certain category or not. Below is all those variables listed together with which if_type numbers each variable will be true for. Note that some variables refer to other variables as well. =over =item B<$if_is_ethernet> True for ethernet interfaces (nr 6, 7, 26, 62, 69 and 117). =item B<$if_is_isdn> True for various ISDN interface types (nr 20, 21, 63, 75, 76 and 77) =item B<$if_is_dialup> True for dial-up interfaces such as PPP as well as ISDN. (nr 23, 81, 82 and 108 in addition to the numbers of B<$if_is_isdn>). =item B<$if_is_atm> True for miscellaneous ATM related interface types (nr 37, 49, 107, 105, 106, 114 and 134). =item B<$if_is_wan> True for WAN interfaces point to point, Frame Relay and High Speed Serial ( 22,32,44,46) =item B<$if_is_lan> True for LAN interfaces (8, 9, 11, 15, 26, 55, 59, 60 and 115 in addition to the numbers of B<$if_is_ethernet>). =item B<$if_is_dsl> True for ADSL, RDSL, HDSL and SDSL (nr 94, 95, 96, 97) =item B<$if_is_loopback> True for software loopback interfaces (nr 24) =item B<$if_is_ciscovlan> True for Cisco VLAN interfaces (interfaces with the word Vlan or VLAN in their ifdescs) =item B<$if_vlan_id> Returns the vlan id associated with a specific port on Cisco Catalyst switches under both Catalyst OS and IOS, and 3Com switches. If it is not a vlan interface, will return undef. =item B<$if_cisco_trunk> Returns the trunking state of a specific port on Cisco Catalyst switches under both Catalyst OS and IOS. Returns "1" if the interface is a trunk, undef otherwise. =item B<$if_MTU> Returns the Maximum Transfer Unit associated with a specific port. =back Besides that, you can also use the variables defined for templates below. Further, all the variables available in cfgmaker is at the scripts disposal even if the use of such features is discouraged. More "shortcuts" in the form of variables and functions will be made available in the future instead. =head3 Examples on Filters The following filter will not affect which interfaces gets included or excluded, it will make cfgmaker behave as normally. '--if-filter=$default' The following filter will make cfgmaker exclude PPP (23) interfaces: '--if-filter=$default && $if_type!=23' The following filter will make cfgmaker behave as usual except that it will consider the operational state of an interface irrelevant but still reject all interfaces which are administratively down. '--if-filter=$if_admin && $default_iftype' =head2 Details on Templates The contents of the template files are evaluated as a Perl program. A number or Perl variables are available for the program to read and others are used to be written to. As quite a few of the predefined variables has values which are are supposed to be used in HTML code some of them have an "HTML-escaped" variant, e.g $html_syslocation is the HTML escaped variant of $syslocation. The HTML escaping means that the chars "<", ">" and "&" are replaced by "<", ">" and "&" and that newlines embedded in the string are prepended with "
" and appended with a space character (if a newline is last in the string it is not touched). =head3 Writable Template Variables These are the variables available to store the configuration lines in. Some of them are initialized prior to the evaluation of the template but such content normally is comments for inclusion in the final configuration file so those variables might be reset to the empty string in the template code to eliminate the comments. The other way around is also possible, the contents of these variables might be extended with further information for various reasons such as debugging etc. Once the template has been evaluated, the following happens: if the template is a interface template and the actual interface for some reason is rejected and thus needs to be commented out, all the lines in the variable B<$target_lines> are turned into comments by adding a hash mark ("#") at their beginning. Then all the variables B<$head_lines>, B<$problem_lines> , B<$target_lines> and B<$separator_lines> are concatenated together to form the lines to add to the configuration file. =over =item B<$target_lines> This variable is the placeholder for the configuration lines created by the template. B<$target_lines> is predefined to be empty when the template code is evaluated. =item B<$head_lines> This variable is intended to be the placeholder for the comment line appearing just before the target in the configuration file. It is initialized with that comment line before the evaluation of the template code and if the template doesn't modify B<$head_lines> during evaluation, the comment will look like usual in the config file. =item B<$problem_lines> This variable is intended to be the placholder for the comment lines describing any problems which might have been encountered when trying to add the target into the configuration. For host templates it's normally not used and for those it's predefined as the empty string. For interface templates B<$problem_lines> is predefined with the error description comments which cfgmaker normally would use for rejected interfaces or as the empty string for accepted interfaces. It is possible to test against B<$problem_lines> to find out if an interface will be included or rejected but this is not recommended. Test against B<$if_ok> instead. =item B<$separator_lines> This variable is the placeholder for the string to use as the separator between the code for individual targets. The contents of this variable is put after each target (so the lines will appear after the end of the last target in the config as well). =back =head3 Predefined Template Variables All the variables below are available for interface templates to use. For host templates, only those listed under L are available. For interface templates the variables listed under L are also available. =head3 Host and System Variables =over =item B<$router_name> This is the fully qualified name for the router. It is affected by the following items on the command line: the router name itself and B<--dns-domain>. =item B<$router_connect> This is the reference string for the router being polled. It is on the form community@router possibly followed by some snmp options. It is affected by the following items on the command line: the router name itself, B<--community>, B<--snmp-options> and B<--dns-domain>. (There's no HTML escaped variant available) =item B<$directory_name> This variable should contain the directory name as cfgmaker normally would use as the value for the "Directory[]" directive. The value is determined by the B<--subdirs> command line option. If B<--subdirs> isn't specified B<$directory_name> will be the empty string. (There's no HTML escaped variant available) =item B<$syscontact> This variable is the router's SNMP sysContact value. (HTML escaped variant: B<$html_syscontact>) =item B<$sysname> This variable is the router's SNMP sysName value. (No HTML escaped variant available) =item B<$syslocation> This variable is the router's SNMP sysLocation value. (HTML escaped variant: B<$html_syslocation>) =item B<$sysdescr> This variable is the router's SNMP sysDescr value. It is normally not used by cfgmaker but might be useful in a template. (HTML escaped variant: B<$html_sysdescr>) =back =head3 Interface Target Related Variables =over =item B<$target_name> This is what cfgmaker normally would use as the the name of the target. The target name is what is found within the square brackets, "[]", for target directives. (There's no HTML escaped variant available) =item B<$if_ref> This the reference string for the interface. It is expected to be used in the "Target[xyz]" directive to distinguish what interface to use. The value of this variable is affected by the B<--ifref> command line option. It is normally used together with B<$router_connect>. (There's no HTML escaped variant available) =item B<$if_ok> This variable is true if the interface is going to be included into the configuration file, otherwise false. Don't test against other variables such as B<$problem_lines> to find out if an interface will be rejected or not, use this B<$if_ok> instead. =item B<$default_target_lines> This variable contains all the target lines which cfgmaker by default outputs for this interface. It's useful if you want to have the "standard target" but want to add some extra lines to it by using a template. =back By default cfgmaker uses the following directives for each target it generates: Target[], SetEnv[], MaxBytes[], Title[], PageTop[] and if there is any directory specified also the Directory[] directive. To facilitate the creation of templates which generates target configs which are similar to the default one, each of the above mentioned directive lines have a corresponding variable containing the line as cfgmaker would have output it by default. Note that none of these have a HTML escaped variant, text in them is HTML escaped where needed. Also note that they do not have any newline at the end. =over =item B<$default_target_directive> This variable contains the default string for the Target[] directive line. =item B<$default_setenv_directive> This variable contains the default string for the SetEnv[] directive line. =item B<$default_directory_directive> This variable contains the default string for the Directory[] directive line which means it is an empty string (with no newline) if there's no directory. =item B<$default_maxbytes_directive> This variable contains the default string for the MaxBytes[] directive line. =item B<$default_title_directive> This variable contains the default string for the Title[] directive line. =item B<$default_pagetop_directive> This variable contains the default string for the PageTop[] directive lines. =back =head3 Interface Network Configuration Variables =over =item B<$if_ip> This variable should contain the IP-address of the interface, if any has been assigned to it. (There's no HTML escaped variant available) =item B<$ifindex> This variable is the SNMP ifIndex for the interface which per definition always is an integer. (There's no HTML escaped variant available) =item B<$if_index> Equivalent with B<$ifindex>. =item B<$if_eth> Contains the ethernet address of the interface, if any. (There's no HTML escaped variant available) =item B<$if_speed> This variable is the speed in bytes/second (with prefixes). (There's no HTML escaped variant available) =item B<$if_speed_str> This variable is a cooked speed description which is either in bits or bytes depending on whether or not the bits option is active and also with the proper prefix for the speed (k, M, G etc). (No HTML escaped variant available) =item B<$if_type_desc> This variable is a textual description of the interface type. (HTML escaped variant: B<$html_if_type_desc>) =item B<$if_type_num> This variable the integer value corresponding to the interface type (for a listing for the value for the more common interface types, see the section DETAILS ON FILTERS above). (No HTML escaped variant available) =item B<$if_dns_name> This is the DNS name for the interface. (No HTML escaped variant available) =back =head3 Interface Name, Description and Alias Variables It might seem confusing with both I, I and I in this context and to some extent it is. I and I are usually supported on most equipment but how they are used varies, both between manufacturers as well as between different categories of equipment from the same manufacturer. The I is at least supported by Cisco IOS, and that variable contains whatever is used in the IOS statement called "description" for the interface (not to be confused with the SNMP variables for I). For better control from the command line consider B<$if_title_desc> which contents are controlled by the B<--if-descr> command line option. =over =item B<$if_snmp_descr> This variable should contain the "raw" description of the interface as determined by the SNMP polling of the router. (HTML escaped variant: B<$html_if_snmp_descr>) =item B<$if_snmp_name> The "raw" name for the interface as provided by SNMP polling. (HTML escaped variant: B<$html_if_snmp_name>) =item B<$if_snmp_alias> The "raw" ifAlias for the interface as provided by SNMP polling. (HTML escaped variant: B<$html_if_snmp_alias>) =item B<$if_cisco_descr> The "raw" CiscolocIfDescr for the interface as provided by SNMP polling. (HTML escaped variant: B<$html_if_cisco_descr>) =item B<$if_description> This is the "cooked" description string for the interface, taking into account the SNMP values found for the interface's RDescr, ifAlias and CiscolocIfDescr. (HTML escaped variant: B<$html_if_description>) =item B<$if_title> The full string cfgmaker by default would have used for the Title[] directive in the configuration as well as the content of the topmost H1 tag in the PageTop[]. Is composed by the contents of B<$desc_prefix>, B<$if_title_desc> and B<$sysname>. As B<$if_title> depends on B<$if_title_desc>, it is possible to indirectly control B<$if_title> by using the command line option B<--if-descr>. (HTML escaped variant: B<$html_if_title>) =item B<$if_port_name> If the host is a Cisco Catalyst LAN switch, this variable is the name of that port. (No HTML escaped variant available) =item B<$if_pp_port_name> If the host is a Nortel Passport LAN switch, this variable is the name of that port. (No HTML escaped variant available) =item B<$desc_prefix> This variable is a prefix of the description of what the target is to use in the "Title[]" directive and in the H1 section of the "PageTop[]". Default is "Traffic analysis for ". (HTML escaped variant: B<$html_desc_prefix>) =item B<$if_title_desc> This is the description of the interface normally used by cfgmaker as part of the variable B<$if_title>. The latter is used as the full string in the "Title[]" directive and the H1 section in the PageTop[]. B<$if_title_desc> is controlled by the command line option B<--if-descr> which indirectly controls the contents of B<$if_title> (HTML escaped variant: B<$html_if_title_desc>) =back =head3 Help Functions for Templates The following functions exists to facilitate the writing of host and interface templates. =over =item B)> B takes a string as an argument and returns a new string where the following substitutions has been done: the chars "<", ">" and "&" are replaced by "<", ">" and "&" and that newlines embedded in the string are prepended with "
" and appended with a space character (newlines at the end of the string are not touched). =item B This function will try to poll each of the oids specified until it is successful or has run out of oids. It will return the name of the first oid that worked or undef if it is not successful =back =head3 Example Template Files =head4 Template Example 1: Eliminating Rejected Targets From Appearing This template file generates exactly the same configuration code per interface as cfgmaker does by default, with the exception that it eliminates all lines (comments as well as config code) for an interface if the interface happens to be rejected. if(not $problem_lines) { $target_lines .= <$html_desc_prefix$html_if_title_desc -- $sysname
ECHO $target_lines .= < ECHO $target_lines .= < ECHO $target_lines .= < ECHO $target_lines .= < ECHO $target_lines .= < ECHO } else { $head_lines=""; $problem_lines=""; $target_lines=""; $separator_lines=""; } =head3 Template Example 2: Simpler Version of Example 1 Example 1 was partly intended to demonstrate how to customize the generation of interface targets but also to provide a hint of how the variables are used in the "default" template which one could consider that cfgmaker normally uses. If you're only interested in the easiest way of entirely eliminating those reject interfaces, the template below would do the job as well by using B<$default_target_lines>. if($if_ok) { $target_lines = $default_target_lines; } else { $head_lines=""; $problem_lines=""; $target_lines=""; $separator_lines=""; } =head3 Template Example 3: Creating CPU Targets for Hosts Below is an example of a host template. $head_lines .= <$router_name CPU load
System: $sysname in $html_syslocation
Maintainer: $html_syscontact
Description: $html_if_description
ifType: $html_if_type_desc ($if_type_num)
ifName: $html_if_snmp_name
Port Name: $if_port_name
Port Name: $if_pp_port_name
Max Speed: $if_speed_str
Ip: $if_ip ($if_dns_name)
System: $router_name in $html_syslocation
Maintainer: $html_syscontact
Description: $html_sysdescr
Resource: CPU.
ECHO =head1 EXAMPLES The first example creates a config file for I: the router has the community name I. Interfaces get identified by their IP number. Two global options get added to the config file. The config file gets redirected to I. The '\' signs at the end of the line mean that this command should be written on a single line. cfgmaker --global "WorkDir: /home/tobi" \ --global "Options[_]: growright,bits" \ --ifref=ip \ public@router.place.xyz > mrtg.cfg Note: if cfgmaker is not in your path, but you are in the directory where cfgmaker is stored, you can start it with ./cfgmaker The next example creates a config file for four devices: I, I, I and I all with the community I. The two routers will have B<--ifref> set to B whilst the two switches will use B<--ifref> set to B. Further the routers will use B<--ifdesc> set to B and I will use B<--ifdesc> set to B whilst I use B instead. Finally, there will be two Options lines inserted in the configuration: One will be in the beginning, whilst the other will be inserted after the lines related to the two routers but before those lines related to the switches. cfgmaker --global "WorkDir: /home/tobi" \ --global "Options[_]: growright,bits" \ --ifref=descr \ --ifdesc=alias \ public@router1.place.xyz \ public@router2.place.xyz \ --global "Options[_]: growright" \ --ifref=name \ --ifdesc=descr \ public@switch1.place.xyz \ --ifdesc=name \ public@switch2.place.xyz > mrtg.cfg The next example demonstrates how to use the B<--community>, B<--snmp-options> and B<--dns-domain> to make the command line simpler. All the equipment will use the community I, except for the ppp-server which use community I. All equipment uses these SNMP options: B<1s timeout>, B<1 retry> and B (B and B is unspecified which means they use the default values). The exception again is the ppp-server which uses B. Finally, all the equipment is part of the domain I, except for the ppp-server which is part of the domain I. Note that the latter is achieved simply by specifying the name of the ppp-server to be I> . cfgmaker --global "WorkDir: /home/tobi" \ --global "Options[_]: growright,bits" \ --dns-domain=place.xyz \ --community=hidden \ --snmp-options=::1:1::2 \ router1 \ router2 \ router3 \ router4 \ router5 \ switch1 \ switch2 \ switch3 \ switch4 \ switch5 \ switch6 \ switch7 \ access@ppp-server.remote:::::1 > mrtg.cfg =head1 SEE ALSO L =head1 AUTHOR Tobias Oetiker Etobi@oetiker.chE and Jakob Ilves Ejakob.ilves@oracle.comE =head1 LICENSE GNU General Public License =head1 COPYRIGHT Cfgmaker is Copyright 2000 by Tobias Oetiker Etobi@oetiker.chE =cut mrtg-2.17.10/bin/indexmaker0000755000175300017510000006354614171763413014520 0ustar oetikeroep#! /home/oetiker/.plenv/shims/perl -w # -*- mode: Perl -*- ################################################################## # MRTG 2.17.10 --- Index Generator ################################################################## # # This reads a mrtg.cfg file form std input or cmdline argument # and it takes a regexp on the cmdline to specify which # targets to look at. # # from this info it produces a router index on stdout or # on the filename specified by the --output option # ################################################################## # Distributed under the GNU General Public License # Copyright 2000 by Tobias Oetiker ################################################################## $main::GRAPHFMT="png"; require 5.005; use strict; # DEBUG TARGETS # base - basic program flow #@main::DEBUG=qw(base); BEGIN { # Automatic OS detection ... do NOT touch if ( $^O =~ /^(?:(ms)?(dos|win(32|nt)?))/i ) { $main::OS = 'NT'; $main::SL = '\\'; $main::PS = ';'; } elsif ( $^O =~ /^NetWare$/i ) { $main::OS = 'NW'; $main::SL = '/'; $main::PS = ';'; } elsif ( $^O =~ /^VMS$/i ) { $main::OS = 'VMS'; $main::SL = '.'; $main::PS = ':'; } else { $main::OS = 'UNIX'; $main::SL = '/'; $main::PS = ':'; } } use FindBin; use lib "${FindBin::Bin}"; use lib "${FindBin::Bin}${main::SL}..${main::SL}lib${main::SL}mrtg2"; use MRTG_lib "2.100016"; use Getopt::Long; use Pod::Usage; #---------------------------------------------------------------------- sub decimal_sort($$) { my $a = $_[0]; my $b = $_[1]; $a =~ s/([0-9]+)/sprintf("%09u",${1})/ge; $b =~ s/([0-9]+)/sprintf("%09u",${1})/ge; return $a cmp $b; } #---------------------------------------------------------------------- my @argv = @ARGV; my $argz = "$0"; foreach my $ar (@argv) { if ($ar =~ /[ |()]/ ) { $ar = sprintf qq{"%s"}, $ar; } $argz .= " $ar"; } main(); exit 0; sub main { # default options my %opt = ( sort => 'original', show => 'day', section => 'h1', columns => 2, addhead => '', bodyopt => 'bgcolor="#ffffff" text="#000000" '. 'link="#000000" vlink="#000000" alink="#000000"', title => 'MRTG Index Page', headlevel => 1, pagetopend => '', pagetop => '', pageend => '', prefix => '', rrdviewer => '/cgi-bin/14all.cgi', optlog => 1, bold => 1, boldon => '', boldoff => '', div => 'DIV', imgborder => 1, cellspacing => 10, nolegend => 0, ); $opt{headon} = ""; $opt{headoff} = ""; # load real options options(\%opt); #adapt some defaults to the current options die "ERROR: --autoprefix requires --output" if ($opt{autoprefix} and !defined $opt{output}); $opt{pageend} = $opt{pagetopend} if (defined $opt{pagetopend} and not $opt{pageend}); $opt{pagetop} = $opt{pagetopend} if (defined $opt{pagetopend} and not $opt{pagetop}); $opt{boldon} = $opt{boldoff} = "" if (!$opt{bold}); $opt{picfirst} = (defined $opt{picfirst}?1:0); if ($opt{compact}) { $opt{imgborder} = 0; $opt{cellspacing} = 0; $opt{headon} = $opt{boldon}; $opt{headoff} = $opt{boldoff}; } if ($opt{sidebyside}) { $opt{div} = 'td'; } # slurp config files my %rcfg; my %cfg; my @target; my @routers; my $cfgfile; my %files; while (@ARGV) { $cfgfile = shift @ARGV; readcfg($cfgfile,\@routers,\%cfg,\%rcfg); if (($opt{sectionhost}) or ($opt{perhost})) { #We need to cache the "hostname" as appeared in cfgfile, #since it does change in cfgcheck (for ex. if multiple #overlapping cfgfiles are specified) for my $targ (@routers) { if ( !defined $rcfg{host}{$targ} and !($rcfg{target}{$targ} =~ m/(?{$targ} = $pref if (! defined $rcfg{prefixes}->{$targ}); } } } # generate index page genindex(\@routers, \%cfg, \%rcfg, \%opt, \%files); } sub cleanurl ($) { my $url = shift; $url =~ s|([^/.][^/.]*/)\.\./\1|$1|g; return $url; } #Take a path the mrtg (usually the mrtg output directory) and the overview #file, find the relative path from the overview to the directory sub subpath ($$) { my $sub = shift; my $out = shift; my @s=split /$main::SL/,$sub; my @o=split /$main::SL/,$out; pop @o; #Last is a filename; for my $i (0..$#s) { #cut common dirs if (defined $s[0] and defined $o[0] and $s[0] eq $o[0] ) { shift @s; shift @o; } } my $ret = join $main::SL,@s; for my $i (0..$#o) { $ret = "..$main::SL$ret"; # ".." == "Directory below this one" for # dos, windows, unix. What about VMS ? # Is this correct ? HEH } $ret .= $main::SL; #Possibly this should be "/" in order not #to break on platforms !unix, since it will be #used for generating urls ? #Don't degenerate in "/" when really no prefix is needed. $ret = "" if ($ret eq $main::SL); return $ret; } sub genindex ($$$$) { my $routers = shift; my $cfg = shift; my $rcfg = shift; my $opt = shift; my $cfgfile = shift; my $index; my $metaCmdLine; # ----------------------------------------------------------- # keep only the items our users want (--filter) # ----------------------------------------------------------- my @filtered; ITEM: foreach my $item (@{$routers}) { foreach my $filter (@{$$opt{filter}}) { if ($filter =~ /(.+)([=!]~)(.+)/) { my ($area,$comp,$regex) = ($1,$2,$3); my $value; for ($area) { /^title|pagetop$/ && do { $value = $$rcfg{$area}{$item}; last }; /^name$/ && do { $value = $item; last }; die "ERROR: unknown filter area $_\n"; }; for ($comp) { /^=~$/ && do { next ITEM unless $value =~ /$regex/; last }; /^!~$/ && do { next ITEM unless $value !~ /$regex/; last }; die "ERROR: unknown comparison operator $_\n"; }; } else { die "ERROR: invalid filter expression $filter\n"; } } push @filtered, $item; }; # ----------------------------------------------------------- # get items into proper order (--sort) # ----------------------------------------------------------- my @order; for ($$opt{sort}) { /^original$/ && do {@order = @filtered; last}; /^name$/ && do { @order = sort { decimal_sort($a,$b); } @filtered; last}; /^title$/ && do { @order = sort { decimal_sort($$rcfg{title}{$a}, $$rcfg{title}{$b}) || $a cmp $b } @filtered; last; }; /^descr(iption)?$/ && do { @order = sort { $$rcfg{pagetop}{$a} =~ m[Description:\s*(?:\S+\s+)?(.+?)]i; my $aval = lc $1; $$rcfg{pagetop}{$b} =~ m[Description:\s*(?:\S+\s+)?(.+?)]i; my $bval = lc $1; $aval cmp $bval; } @filtered; last; }; die "ERROR: unknown sort order '$$opt{sort}'\n"; } die "ERROR: did not find any matching data in cfg file\n" unless @order; # ----------------------------------------------------------- # issue page top # ----------------------------------------------------------- my $interval =$$cfg{'interval'} ? $$cfg{'interval'} : 5; my $expiration = &expistr($interval); my $refresh = $$cfg{'refresh'} ? $$cfg{'refresh'} : 300; for ($$opt{show}) { $refresh = /^week$/ && 1800 || /^month$/ && 7200 || /^year$/ && 86400 || $refresh ; } my $gifPath = ''; if ($$cfg{icondir} || $$opt{icondir}) { $gifPath = $$opt{icondir} || $$cfg{icondir}; #lets make sure there is a trailing path separator $gifPath =~ s|/*$|/|; } else { $gifPath = "$$cfg{imagehtml}"; } if ($$opt{optlog}) { $metaCmdLine = $argz; } else { $metaCmdLine = ""; } $metaCmdLine =~ s/&/&/g; # Must be first, otherwise it will affect the following changes $metaCmdLine =~ s/"/"/g; $metaCmdLine =~ s//>/g; my $headeradd = $$opt{headeradd} || ""; $index = < $$opt{title} $headeradd ECHO $index .= < /* commandline was: $argz */ /* sorry, no style, just abusing this to place the commandline and pass validation */ ECHO $index .= < ECHO $index .= <$$opt{subtitle}

ECHO $index .= < ECHO # ----------------------------------------------------------- # print the graph items # ----------------------------------------------------------- my $itemnr = 0; my $first = $order[0]; my $host = $$rcfg{host}{$first}; if ($host){ $index .= "$$opt{headon}Interfaces of $host $$opt{headoff}" if $$opt{perhost}; } else { $index .= "$$opt{headon}Special Items$$opt{headoff}" if $$opt{perhost}; } foreach my $item (@order) { if ($$opt{perhost}) { my $newhost = $$rcfg{host}{$item} || 'unspecified host'; if (!($host eq $newhost)) { $host = $newhost; if ($host){ $index .= "$$opt{headon}Interfaces of $host $$opt{headoff}\n"; } else { $index .= "$$opt{headon}Special Items$$opt{headoff}\n"; } $index .= "\n"; $itemnr=0; } } $$opt{prefix} = $$rcfg{prefixes}->{$item} if ($$opt{autoprefix}); $itemnr++; $index .= ""; my $dirrel = "../" x ($$rcfg{'directory_web'}{$item} =~ tr|/|/|); # --- produce graph section title --- my $section; for ($$opt{section}) { /^h1$/ && do{ if ($$rcfg{pagetop}{$item} =~ m[+]*>(.+?)Description:\s*\Q$section\E\s*([^< ][^<]+?),i and $section = $1; last; }; /^portname$/ && do{ $section = "No Portname for $item"; $$rcfg{pagetop}{$item} =~ m,Port Name:\s*(.*?),i and $section = $1; last; }; /^ifname$/ && do{ $section = "No Portname for $item"; $$rcfg{pagetop}{$item} =~ m,ifname:\s*(.*?),i and $section = $1; last; }; die "ERROR: unknown sectioning type $_\n"; }; if (defined $$rcfg{host}{$item} and !($section =~ m/\b\Q$$rcfg{host}{$item}\E\b/i)) { $section = ucfirst $$rcfg{host}{$item} . ": $section"; } # --- write the actual graph ---- die "ERROR: Unknown show type $$opt{show}\n" unless $$opt{show} =~ /^day|week|month|year|none$/; my $image = "$item-$$opt{show}.${main::GRAPHFMT}" if $$opt{show} ne 'none'; $index .= "<$$opt{div}>" if (!$$opt{sidebyside}); if (not $image) { if ($$cfg{logformat} eq 'rrdtool') { my $sep = $$opt{rrdviewer} =~ /\?/ ? '&' : '?'; $index .= "". "$$opt{boldon}". "$section$$opt{boldoff}"; } else { $index .= "$$opt{boldon}". "". "$section$$opt{boldoff}\n<$$opt{div}>"; } } else { #loop used for reversing (text,images) to (images,text) if req. for my $picfirstloop (1,0) { if ( $picfirstloop^$$opt{picfirst} ) { $index .= "$$opt{boldon}$itemnr. $$opt{boldoff}" if $$opt{enumerate}; if ($$opt{clicktext}) { $index .= "$$opt{boldon}"; $index .= $section; $index .= "$$opt{boldoff}"; } else { $index .= "$$opt{boldon}$section$$opt{boldoff}"; } $index .= "\n<$$opt{div}>" if $picfirstloop; } if ( !($picfirstloop^$$opt{picfirst}) ) { # figure show name for rrd viewer if ($$cfg{logformat} eq 'rrdtool') { my $sep = $$opt{rrdviewer} =~ /\?/ ? '&' : '?'; $index .= "". "\"$item" } else { $index .= ""; $index .= "\"$item
"; } $index .= "\n<$$opt{div}>" if $picfirstloop; } } } $index .= "" if (!$$opt{sidebyside}); $index .= "\n"; # --- new table column if necessary ---- if (($itemnr) % $$opt{columns} == 0) { $index .= "\n\n"; } } # ----------------------------------------------------------- # print page end # ----------------------------------------------------------- my $VERSION = "2.17.10"; $index .= < ECHO $index .= <
MRTG Multi Router Traffic Grapher
version $VERSION Tobias Oetiker <tobi\@oetiker.ch> and Dave Rand <dlr\@bungi.com>
ECHO $index .= < ECHO # ----------------------------------------------------------- # write out the index page # ----------------------------------------------------------- if ($$opt{output}) { debug ('base', "Writing $$opt{output}"); open X, ">$$opt{output}" or die "ERROR: creating $$opt{output}: $!\n"; print X $index; close X; } else { print $index; } } sub options ($) { my $opt = shift; my @options = ( 'help|?', 'man', 'output=s', 'filter=s@', 'addhead=s', 'title=s', 'subtitle=s', 'bodyopt=s', 'pagetopend=s', 'pagetop=s', 'pageend=s', 'columns=i', 'perhost!', 'sort=s', 'enumerate', 'width=i', 'height=i', 'show=s', 'section=s', 'version', 'prefix=s', 'headeradd=s', 'clicktext!', 'optlog!', 'compact!', 'headlevel=i', 'bold!', 'picfirst!', 'sidebyside!', 'nolegend', 'autoprefix!', 'sectionhost!', 'icondir=s', 'rrdviewer=s'); #generate --option-file from --option for ( grep /=s$/,@options ) { my $fileopt = $_; $fileopt =~ s/=s$/-file=s/; push @options, $fileopt; } GetOptions( $opt, @options ) or pod2usage(-verbose => 1); if ($$opt{prefix}){ $$opt{prefix} .= '/'; $$opt{prefix} =~ s|/+$|/|; } die ("Indexmaker for mrtg-2.17.10\n") if $$opt{version}; pod2usage(-exitval => 1, -verbose => 2) if $$opt{man}; pod2usage(-verbose => 1) if not @ARGV; #take care of --fileoption --> --option for my $fileopt ( grep /-file$/, keys %{$opt} ) { my $orgopt = $fileopt; $orgopt =~ s/-file$//; $$opt{$orgopt} = &readfile($$opt{$fileopt}); } } #return the contents of a file sub readfile($) { my $file = shift; open F,"<$file" or die "ERROR: can\'t open $file for read, $!"; my $sl = $/; $/ = undef; my $string = ; $/ = $sl; close F; return $string; } __END__ =pod =head1 NAME indexmaker - Creates index files for mrtg web sites (mrtg-2.17.10) =head1 SYNOPSIS indexmaker [options] mrtg.cfg [other.cfg ...] =head1 OPTIONS --output=filename set output filename (default: stdout) --filter title=~regexp select targets by matching regexp against titles --filter pagetop=~regexp select targets by matching regexp against pagetop --filter name=~regexp select targets by matching regexp against name --addhead=text insert this text between and --title=text set title of generated index file --subtitle=text add a subtitle to the generated index file --bodyopt=text set body tag options --headlevel=number use at top of page (default: 1) --pagetop=text insert this text between and

...

--pageend=text insert this text after the main body --pagetopend=text use this text for pagetop or pageend if undefined --nolegend do not add the Mrtg legend at the end of the page --columns=number show graphs in a table with x columns (default: 2) --perhost show graphs of the same host on a row --compact try to make a vertically more compact page --optlog log the used command line in the page (default: log) --sort=title sort graphs by title --sort=name sort graphs by their name --sort=descr sort graphs by their description --sort=original leave as is (default) --enumerate add a sequence number to the title of each graph --picfirst place pictures before text (default: text first) --width=number set width of graphs (default: not set) --height=number --sidebyside place text / pictures side by side (default: above/below) --bold use bold text (default: bold) --clicktext make the text link to the inner page (like the image) --show=day pick which graph to show in the index (default) --show=week --show=month --show=year --show=none --section=h1 h1 tag from pagetop as section heading (default) --section=title title as section headings for graphs --section=name graph name as section heading --section=descr graph description as section heading --section=ifname interface name (ifName) as section heading --section=portname port name entry in pagetop as section heading --sectionhost Try to prepend the host to the section heading if missing --rrdviewer=path path to rrdviewer (default: /cgi-bin/14all.cgi) --icondir=path path to icondir --prefix=path path from the location of the index.html to the graphs --headeradd=string add string to the html page header --autoprefix try to set prefix automatically ---file=file read string argument for option from file =head1 DESCRIPTION B can create web pages which display the status of an array of mrtg interface status pages. =over =item B<--output> I set output filename (default: stdout) =item B<--filter> (B|B<pagetop>|B<name>)(B<=~>|B<!~>)I<regexp> Several filters may get set. Each filter can match against the contents of a specific section of the mrtg config file. B<Name> refers to the bit in square brackets (option[name]: bla). Depending on the match operator chosen (B<=~> or B<!~>) the match will be positive or negative. Note that some shells consider B<!> a special character. It may be necessary to type B<\!~> instead. =item B<--title> I<text> Set title of generated index file (default: regexp) =item B<--bodyopt> I<text> The value of this argument gets appended to the E<lt>BODYE<gt> tag. This allows you to set document colors. By default this option is set to bgcolor="#ffffff" text="#000000" link="#000000" vlink="#000000" alink="#000000" =item B<--columns> I<number> Display graphs in a table with I<number> columns (default: 2) =item B<--sort> B<title>|B<name>|B<descr>|B<original> Sort the graphs in the page either by B<title>, by B<name>, by interface B<descr>iption, or leave them as is. =item B<--enumerate> Add a sequence number to the title of each graph =item B<--width> I<number> Set width of graphs =item B<--height> I<number> Set the height of the graphs =item B<--show> B<day>|B<week>|B<month>|B<year>|B<none> Select which graph to show in the index page. You can suppress images completely with B<--show=none>. =item B<--section> B<h1>|B<title>|B<name>|B<description>|B<portname> Select what to use as the title for each graph in the page. B<h1> is the H1 section from pagetop, B<title> is the graph title, B<name> is the bit in square brackets (option[name]: bla), and B<descr> or B<description> is the text from the Description field of the PageTop (the Cisco description text if it's available, otherwise just the interface description). B<portname> is the C<Port Name:> from pagetop. =item B<--sectionhost> Extract the hostname from the target line (this does not work if the target is a mathematical expression). Prepend the hostname (and a colon) to the section if not already present. =item B<--rrdviewer> I<path> If you have set the B<LogFormat: rrdtool> property in the mrtg.cfg file, the index will take this into account. The only thing you must tell it is the path to your grapher cgi. (default: /cgi-bin/14all.cgi) =item B<--prefix> I<path> By default we assume that the file generated by indexmaker is stored in I<WorkDir>. If you want to store it somewhere else, specify how to reach I<WorkDir> from the place where the Index is stored. Note that you have to use '/' as path separator as this will be used in urls. Speaking of which, you can even enter a whole url. =item B<--autoprefix> I<path> Requires --output. Try to generate the prefix automatically by comparison of the path to the output file set with --output and the Htmldir set in the configuration files. Particularly useful when multiple configuration files are specified, with different Htmldir settings. =item B<--optlog> Default is logging in the generated page the command line, suppress with --nooptlog . Useful if the commandline contains a complex --pagetop=string which could confuse simple browsers. =item B<--someoption-file> I<filename> For any someoption which takes a I<string> as parameter you can read the string from a file by adding <-file> to the option keyword. The whole content of the file will be read and used as the I<string>. The file must exist. =back =head1 AUTHOR Tobias Oetiker E<lt>tobi@oetiker.chE<gt> =head1 LICENSE GNU General Public License =head1 COPYRIGHT 2000-2001 Tobias Oetiker E<lt>tobi@oetiker.chE<gt> =cut ����������������������������������������������������������������������������������������������������������������������������������������������������������mrtg-2.17.10/bin/mrtg�������������������������������������������������������������������������������0000755�0001753�0001751�00000336762�14171763413�013345� 0����������������������������������������������������������������������������������������������������ustar �oetiker�������������������������oep��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#! /home/oetiker/.plenv/shims/perl -w # -*- mode: cperl -*- ################################################################### # MRTG 2.17.10 Multi Router Traffic Grapher ################################################################### # Created by Tobias Oetiker <tobi@oetiker.ch> # and Dave Rand <dlr@bungi.com> # # For individual Contributers check the CHANGES file # ################################################################### # # Distributed under the GNU General Public License # ################################################################### my @STARTARGS=($0,@ARGV); @main::DEBUG=qw(); # DEBUG TARGETS # cfg - watch the config file reading # dir - directory mangeling # base - basic program flow # tarp - target parser # snpo - snmp polling # snpo2 - more snmp debug # coca - confcache operations # repo - track confcache repopulation # fork - forking view # time - some timing info # log - logging of data via rateup or rrdtool # eval - trace eval expressions # prof - add timeing info some interesting bits of code $main::GRAPHFMT="png"; # There older perls tend to behave peculiar with # large integers ... require 5.005; use strict; # addon jpt BEGIN { # Automatic OS detection ... do NOT touch if ( $^O =~ /^(ms)?(dos|win(32|nt)?)/i ) { $main::OS = 'NT'; $main::SL = '\\'; $main::PS = ';'; } elsif ( $^O =~ /^NetWare$/i ) { $main::OS = 'NW'; $main::SL = '/'; $main::PS = ';'; } elsif ( $^O =~ /^VMS$/i ) { $main::OS = 'VMS'; $main::SL = '.'; $main::PS = ':'; } elsif ( $^O =~ /^os2$/i ) { $main::OS = 'OS2'; $main::SL = '/'; $main::PS = ';'; } else { $main::OS = 'UNIX'; $main::SL = '/'; $main::PS = ':'; } if ( $ENV{LANG} and $ENV{LANG} =~ /UTF.*8/i ){ my $args = join " ", map { /\s/ ? "\"$_\"" : $_ } @ARGV; $args ||= ""; print <<ERR; ----------------------------------------------------------------------- ERROR: Mrtg will most likely not work properly when the environment variable LANG is set to UTF-8. Please run mrtg in an environment where this is not the case. Try the following command to start: env LANG=C ${0} $args ----------------------------------------------------------------------- ERR exit 0; } } use FindBin; use lib "${FindBin::Bin}"; use lib "${FindBin::Bin}${main::SL}..${main::SL}lib${main::SL}mrtg2"; use Getopt::Long; use Math::BigFloat; # search for binaries in the bin and bin/../lib directory use MRTG_lib "2.100016"; my $NOW = timestamp; my $graphiteObj; # $SNMP_Session::suppress_warnings = 2; use locales_mrtg "0.07"; # Do not Flash Console Windows for the forked rateup process BEGIN { if ($^O eq 'MSWin32'){ eval {local $SIG{__DIE__};require Win32; Win32::SetChildShowWindow(0)}; warn "WARNING: $@\n" if $@; } } $main::STARTTIME = time; %main::verified_rrd = (); if ($MRTG_lib::OS eq 'OS2') { # in daemon mode we will pause 3 seconds to be sure that parent died require OS2::Process; if (OS2::Process::my_type() eq 'DETACH') {sleep(3);} } if ($MRTG_lib::OS eq 'UNIX') { $SIG{INT} = $SIG{TERM} = sub { unlink ${main::Cleanfile} if defined $main::Cleanfile; unlink ${main::Cleanfile2} if defined $main::Cleanfile2; unlink ${main::Cleanfile3} if defined $main::Cleanfile3; warn "$NOW: ERROR: Bailout after SIG $_[0]\n"; exit 1; }; $SIG{HUP} = sub { unlink ${main::Cleanfile} if defined $main::Cleanfile; unlink ${main::Cleanfile2} if defined $main::Cleanfile2; unlink ${main::Cleanfile3} if defined $main::Cleanfile3; die "$NOW: ERROR: Bailout after SIG $_[0]\n"; }; } END { local($?, $!); unlink ${main::Cleanfile} if defined $main::Cleanfile; unlink ${main::Cleanfile2} if defined $main::Cleanfile2; unlink ${main::Cleanfile3} if defined $main::Cleanfile3; } &main; exit(0); #### Functions ################################################ sub main { # read in the config file my @routers; my %cfg; my %rcfg; my %opts; my $EXITCODE = 0; GetOptions(\%opts, 'user=s', 'group=s', 'lock-file=s','confcache-file=s','logging=s', 'check', 'fhs', 'daemon', 'pid-file=s','debug=s', 'log-only') or die "Please use valid Options\n"; if (defined $opts{debug}){ @main::DEBUG = split /\s*,\s*/, $opts{debug}; if (defined $SNMP_util::Debug){ $SNMP_util::Debug = 1 if grep /^snpo2$/, @main::DEBUG; } } if (grep /^prof$/, @main::DEBUG){ require Time::HiRes; eval "sub gettimeofday() {return Time::HiRes::time()}"; # note this will crash if the module is missing # so only use the --debug=prof if you have Time::HiRes installed } else { eval "sub gettimeofday() {return time()}"; } debug 'time', "prog start ".localtime(time); my $uid = $<; my $gid = $(; if (defined $opts{group}) { $gid = getgrnam($opts{group}); die "$NOW: ERROR: Unknown Group: $opts{group})\n" if not defined $gid; } if (defined $opts{user}) { $uid = getpwnam($opts{user}); die "$NOW: ERROR: Unknown User: $opts{user})\n" if not defined $uid; } # If we've specified using FHS # (https://refspecs.linuxfoundation.org/FHS_3.0/index.html) on the command # line, use the relevant path definitions (can be overridden later): my $confcachepath; my $confcachefile; my $pidpath; my $pidfile; my $lockpath; my $lockfile; my $templock; my $logpath; my $logfile; if (defined $opts{"fhs"}) { $confcachepath = "/var/lib/mrtg"; $confcachefile = "$confcachepath/mrtg.ok"; $pidpath = "/run/mrtg"; $pidfile = "$pidpath/mrtg.pid"; $lockpath = "/var/lock/mrtg"; $lockfile = "$lockpath/mrtg.lck"; $templock = "$lockpath/mrtg.lck.$$"; $logpath = "/var/log/mrtg"; $logfile = "$logpath/mrtg.log"; } my $cfgfile = shift @ARGV; if ( !defined $cfgfile and -r "/etc/mrtg/mrtg.cfg" ) { $cfgfile = "/etc/mrtg/mrtg.cfg"; } printusage() unless defined $cfgfile; # PID file code, used later if daemonizing... if ( !defined($pidfile) ) { $pidfile = $cfgfile; $pidfile =~ s/\.[^.\/]+$//; $pidfile .= '.pid'; } $pidfile = $opts{"pid-file"} || $pidfile; # Create directories needed for --fhs if (defined $opts{"fhs"}) { unless(-e $pidpath or mkdir ($pidpath, 0755)) { die "Unable to create $pidpath\n"; } unless(-e $confcachepath or mkdir ($confcachepath, 0750)) { die "Unable to create $confcachepath\n"; } unless(-e $logpath or mkdir ($logpath, 0750)) { die "Unable to create $logpath\n"; } unless(-e $lockpath or mkdir ($lockpath, 0755)) { die "Unable to create $lockpath\n"; } chown $uid, $gid, $pidpath; chown $uid, $gid, $confcachepath; chown $uid, $gid, $logpath; chown $uid, $gid, $lockpath; } # Run as a daemon, specified on command line (required for FHS compliant daemon) if (defined $opts{"daemon"}) { # Create a pidfile, then chown it so we can use it once we change user &create_pid($pidfile); chown $uid, $gid, $pidfile; } ($(,$)) = ($gid,$gid) ; ($<,$>) = ($uid,$uid) ; die "$NOW: ERROR failed to set UID to $uid\n" unless ($< == $uid and $> == $uid); $logfile = $opts{logging} || $logfile; if (defined $logfile){ setup_loghandlers $logfile; warn "Started mrtg with config \'$cfgfile\'\n"; } # lets make sure that there are not two mrtgs running in parallel. # so we lock on the cfg file. Nothing fancy, just a lockfile $lockfile = $opts{"lock-file"} || $lockfile; if (! defined $lockfile) { $lockfile = $cfgfile."_l"; } if (! defined $templock) { $templock = $lockfile."_" . $$ ; } debug('base', "Creating Lockfiles $lockfile,$templock"); &lockit($lockfile,$templock); debug('base', "Reading Config File: $cfgfile"); my $cfgfile_age = -M $cfgfile; readcfg($cfgfile,\@routers,\%cfg,\%rcfg); imggen($cfg{icondir} || $cfg{imagedir} || $cfg{workdir}); # Enable or disable snmpv3 if(defined $cfg{enablesnmpv3}) { $cfg{enablesnmpv3} = lc($cfg{enablesnmpv3}); } else { $cfg{enablesnmpv3} = 'no'; } if ($cfg{threshmailserver}) { if (eval {local $SIG{__DIE__};require Net::SMTP;}) { import Net::SMTP; debug('base', "Loaded Net::SMTP module for ThreshMail."); } else { die "$NOW: WARNING: Can't load Net::SMTP module. This is required for ThreshMail."; } } # Check we have the necessary libraries for IPv6 support if ($cfg{enablesnmpv3} eq 'yes') { if (eval {local $SIG{__DIE__};require Net_SNMP_util;}) { import Net_SNMP_util; debug('base', "SNMP V3 libraries found, SNMP V3 enabled."); } else { warn "$NOW: WARNING: SNMP V3 libraries not found, SNMP V3 disabled.\n"; $cfg{enablesnmpv3} = 'no'; require SNMP_util; import SNMP_util; } } else { # load V1/V2 libraries require SNMP_util; import SNMP_util; } # Enable or disable IPv6 if(defined $cfg{enableipv6}) { $cfg{enableipv6} = lc($cfg{enableipv6}); } else { $cfg{enableipv6} = 'no'; } # Check we have the necessary libraries for IPv6 support if ($cfg{enableipv6} eq 'yes') { if ( eval {local $SIG{__DIE__};require Socket; require Socket6; require IO::Socket::INET6;}) { import Socket; import Socket6; debug('base', "IPv6 libraries found, IPv6 enabled."); } else { warn "$NOW: WARNING: IPv6 libraries not found, IPv6 disabled.\n"; $cfg{enableipv6} = 'no'; } } # Module invocation for sending a copy of the time series data to graphite. if(defined $cfg{sendtographite}) { require Net::Graphite; } # from our last run we kept some info about # the configuration of our devices around debug('base', "Reading Interface Config cache"); $confcachefile = $opts{"confcache-file"} || $confcachefile; if ( !defined($confcachefile) ) { $confcachefile = $cfgfile; $confcachefile =~ s/\.[^.\/]+$//; $confcachefile .= ".ok"; } my $confcache = readconfcache($confcachefile); # Check the config and create the target object debug('base', "Checking Config File"); my @target; cfgcheck(\@routers, \%cfg, \%rcfg, \@target, \%opts); # exit here if we only check the config file # in case of an error, cfgcheck() already exited if (defined $opts{check}) { debug('base', "Remove Lock Files"); close LOCK; unlink ($templock, $lockfile); debug('base', "Exit after successful config file check"); exit 0; } # postload rrdtool support if ($cfg{logformat} eq 'rrdtool'){ debug('base', "Loading RRD support"); require 'RRDs.pm'; } # set the locale my $LOC; if ( $cfg{'language'} and defined($lang2tran::LOCALE{"\L$cfg{'language'}\E"})) { debug('base', "Loading Locale for ".$cfg{'language'}); $LOC=$lang2tran::LOCALE{"\L$cfg{'language'}\E"}; } else { debug('base', "Loading default Locale"); $LOC=$lang2tran::LOCALE{'default'}; } # Daemon Code my $last_time=0; my $curent_time; my $sleep_time; if (defined $opts{"daemon"}) { $cfg{'runasdaemon'} = "yes"; } &demonize_me($pidfile,$cfgfile) if defined $cfg{'runasdaemon'} and $cfg{'runasdaemon'} =~ /y/i and $MRTG_lib::OS ne 'VMS' and not (defined $cfg{'nodetach'} and $cfg{'nodetach'} =~ /y/i); # auto restart on die if running as demon $SIG{__DIE__} = sub { warn $_[0]; warn "*** Restarting after 10 seconds in an attempt to recover from the error above\n"; sleep 10; exec @STARTARGS; } if $cfg{'runasdaemon'}; debug('base', "Starting main Loop"); do { # Do this loop once for native mode and forever in daemon mode my $router; $NOW = timestamp; # get the time debug 'time', "loop start ".localtime(time); #if we run as daemon, we sleep in between collection cycles $sleep_time= (int($cfg{interval}*60))-(time-$last_time); if ($sleep_time > 0 ) { #If greater than 0 the sleep that amount of time debug('time', "Sleep time $sleep_time seconds"); sleep ($sleep_time); } elsif ($last_time > 0) { warn "$NOW: WARNING: data collection did not complete within interval!\n"; } $last_time=time; # set meta expires if there is an index file # 2000/05/03 Bill McGonigle <bill@zettabyte.net> if (defined $cfg{'writeexpires'}) { my $exp = &expistr($cfg{'interval'}); my $fil; $fil = "$cfg{'htmldir'}index.html" if -e "$cfg{'htmldir'}index.html"; $fil = "$cfg{'htmldir'}index.htm" if -e "$cfg{'htmldir'}index.htm"; if (defined $fil) { open(META, ">$fil.meta"); print META "Expires: $exp\n"; close(META); } } # Use SNMP to populate the target object debug('base', "Populate Target object by polling SNMP and". " external Datasources"); debug 'time', "snmp read start ".localtime(time); readtargets($confcache,\@target, \%cfg); $NOW = timestamp; # get the time # collect data for each router or pseudo target (`executable`) debug 'time', "target loop start ".localtime(time); foreach $router (@routers) { debug('base', "Act on Router/Target $router"); if (defined $rcfg{'setenv'}{$router}) { my $line = $rcfg{'setenv'}{$router}; while ( $line =~ s/([^=]+)=\"([^\"]*)\"\s*// ) # " - unconfuse the highliter { $ENV{$1}=$2; } } my($savetz) = $ENV{'TZ'}; if (defined $rcfg{'timezone'}{$router}) { $ENV{'TZ'} = $rcfg{'timezone'}{$router}; if ( $main::OS eq 'UNIX' ){ require 'POSIX.pm'; POSIX::tzset(); } } my ($inlast, $outlast, $uptime, $name, $time) = getcurrent(\@target, $router, \%rcfg, \%cfg); if ( defined($inlast) and defined($outlast)) { $EXITCODE = $EXITCODE | 1; } else { $EXITCODE = $EXITCODE | 2; } debug('base', "Get Current values: in:".( defined $inlast ? $inlast : "undef").", out:". ( defined $outlast? $outlast : "undef").", up:". ( defined $uptime ? $uptime : "undef").", name:". ( defined $name ? $name : "undef").", time:". ( defined $time ? $time : "undef")); #abort, if the router is not responding. if ($cfg{'logformat'} ne 'rrdtool') { # undefined values are ok for rrdtool ! #if ( not defined $inlast or not defined $outlast){ # warn "$NOW: WARNING: Skipping Update of $router, inlast is not defined\n" # unless defined $inlast; # warn "$NOW: WARNING: Skipping Update of $router, outlast is not defined\n" # unless defined $outlast; # next; #} if (defined $inlast and $inlast < 0) { $inlast += 2**31; # this is likely to be a broken snmp counter ... lets compensate } if (defined $outlast and $outlast < 0) { $outlast += 2**31; # this is likely to be a broken snmp counter ... lets compensate } } my ($maxin, $maxout, $maxpercent, $avin, $avout, $avpercent,$avmxin, $avmxout, $cuin, $cuout, $cupercent); debug('base', "Create Graphics"); if ($rcfg{'options'}{'dorelpercent'}{$router}) { ($maxin, $maxout, $maxpercent, $avin, $avout, $avpercent, $cuin, $cuout, $cupercent, $avmxin, $avmxout) = writegraphics($router, \%cfg, \%rcfg, $inlast, $outlast, $time,$LOC, \%opts); } else { ($maxin, $maxout ,$avin, $avout, $cuin, $cuout, $avmxin, $avmxout) = writegraphics($router, \%cfg, \%rcfg, $inlast, $outlast, $time,$LOC, \%opts); } # skip this update if we did not get anything useful out of # writegraphics next if not defined $maxin; debug('base', "Check for Thresholds"); threshcheck(\%cfg,\%rcfg,$cfgfile,$router,$cuin,$cuout); if (defined $opts{'log-only'}){ debug('base', "Disable Graph and HTML generation"); } if ($cfg{logformat} eq 'rateup' and not defined $opts{'log-only'} ){ debug('base', "Check for Write HTML Pages"); writehtml($router, \%cfg, \%rcfg, $maxin, $maxout, $maxpercent, $avin, $avout, $avmxin, $avmxout, $avpercent, $cuin, $cuout, $cupercent, $uptime, $name, $LOC) } # clonedirectory($router,\%cfg, \%rcfg); # #put TZ things back in shape ... if ($savetz) { $ENV{'TZ'} = $savetz; } else { delete $ENV{'TZ'}; } if ( $main::OS eq 'UNIX' ){ require 'POSIX.pm'; POSIX::tzset(); }; } # Has the cfg file been modified since we started? if so, reload it. if ( -M $cfgfile < $cfgfile_age and $cfg{'runasdaemon'} and $cfg{'runasdaemon'} =~ /y/i ) { # reload the configuration $cfgfile_age = -M $cfgfile; debug('base', "Re-reading Config File: $cfgfile"); @routers = (); %cfg = (); %rcfg = (); readcfg($cfgfile,\@routers,\%cfg,\%rcfg); cfgcheck(\@routers, \%cfg, \%rcfg, \@target, \%opts); } debug('base', "End of main Loop"); } while ($cfg{'runasdaemon'} and $cfg{'runasdaemon'} =~ /y/i ); #In daemon mode run forever debug('base', "Exit main Loop"); # OK we are done, remove the lock files ... debug('base', "Remove Lock Files"); close LOCK; unlink ($templock, $lockfile); debug('base', "Store Interface Config Cache"); delete $$confcache{___updated} if exists $$confcache{___updated}; # make sure everything gets written out not only the updated entries writeconfcache($confcache,$confcachefile); if ( ! $cfg{'runasdaemon'} or $cfg{'runasdaemon'} !~ /y/i ) { if ( ($EXITCODE & 1) and ($EXITCODE & 2) ) { # At least one target was successful exit 91; } elsif ( not ($EXITCODE & 1) and ($EXITCODE & 2) ) { # All targets failed exit 92; } } } # ( $inlast, $outlast, $uptime, $name, $time ) = # &getcurrent( $target, $rou, $rcfg, $cfg ) # Calculate monitored data for device $rou based on information in @$target # and referring to configuration data in %$rcfg and %$cfg. In the returned # list, $inlast and $outlast are the input and output monitored data values, # $uptime is the device uptime, $name is the device name, and $time is the # current time when the calculation was performed. sub getcurrent { my( $target, $rou, $rcfg, $cfg ) = @_; # Hash indexed by $mode for conveniently saving $inlast and $outlast my %last; # Initialize uptime, device name, and data collection time to empty strings my $uptime = ''; my $name = ''; my $time = ''; # Calculate input and output monitored data foreach my $mode( qw( _IN_ _OUT_ ) ) { # Initialize monitored data, warning message, and death message # to empty strings my $data; my $warning; my $death; { # Code block used to calculate monitoring data # Localize warning and death exception handlers to capture # error message less any leading and trailing white space local $SIG{ __WARN__ } = sub { $_[0] =~ /^\s*(.+?)\s*$/; $warning = $1; }; local $SIG{ __DIE__ } = sub { $_[0] =~ /^\s*(.+?)\s*$/; $death = $1; }; # Calculate monitoring data. $rcfg->{ target }{ $rou } contains # a Perl expression for the calculation. $data = eval "$rcfg->{target}{$rou}"; } # Test for various exceptions occurring in the calculation if( $warning ) { warn "$NOW: ERROR: Target[$rou][$mode] '$$rcfg{target}{$rou}' (warn): $warning\n"; $data = undef; } elsif( $death ) { warn "$NOW: ERROR: Target[$rou][$mode] '$$rcfg{target}{$rou}' (kill): $death\n"; $data = undef; } elsif( $@ ) { warn "$NOW: ERROR: Target[$rou][$mode] '$$rcfg{target}{$rou}' (eval): $@\n"; $data = undef; } elsif( not defined $data ) { warn "$NOW: ERROR: Target[$rou][$mode] '$$rcfg{target}{$rou}' did not eval into defined data\n"; $data = undef; } elsif( $data and $data !~ /^[-+]?\d+(\.\d*)?([eE][+-]?[0-9]+)?$/ ) { warn "$NOW: ERROR: Target[$rou][$mode] '$$rcfg{target}{$rou}' evaluated to '$data' instead of a number\n"; $data = undef; } elsif( length( $data ) > 190 ) { warn "$NOW: ERROR: $mode value: '$data' is way to long ...\n"; $data = undef; } else { # At this point data is considered valid. Round to an integer # unless RRDTool is in use and this is a gauge if (not ( $cfg->{ logformat } eq 'rrdtool' and defined $rcfg->{ options }{ gauge }{ $rou })){ if (ref $data and ref $data eq 'Math::BigFloat') { $data->ffround( 0 ) } else { $data = sprintf "%.0f", $data; } } # Remove any leading plus sign $data =~ s/^\+//; } $last{ $mode } = $data; } # Set $u to the unique index of the @$target array referred to in the # monitored data calculation for the current device. $u will be set to # -1 if that index is not unique. my $u = $rcfg->{ uniqueTarget }{ $rou }; # Get the uptime, device name, and data collection time from the @$target # array if the monitored data calculation refers only to one target. # Otherwise it doesn't make sense to do this. if( $u >= 0 ) { $uptime = $target->[ $u ]{ _UPTIME_ }; $name = $target->[ $u ]{ _NAME_ }; $time = $target->[ $u ]{ _TIME_ }; if ($time =~ /^([-0-9.]+)$/) { $time = $1; } } # Set the time to the current time if it was not set above $time = time unless $time; # Cache uptime location for reading name my( $uploc ); # Get the uptime and device name from the alternate location (community@host or # (OID:community@host or OID) that may have been specified with the RouterUptime # target keyword if( defined $rcfg->{ routeruptime }{ $rou } ) { my( $noid, $nloc ) = split( /:/, $rcfg->{ routeruptime }{ $rou }, 2 ); # If only location (community@host) was specified then # move the location details into the right place if( $noid =~ /@/ ) { $nloc = $noid; $noid = undef; } # If no OID (community@host) was specified use the hardcoded default if( not $noid ) { $noid = 'sysUptime'; } # If no location (community@host) was specified use values from the # unique target referred to in the monitored data calculation if( not $nloc ){ if ($u >= 0) { my $comm = $target->[ $u ]{ Community }; my $host = $target->[ $u ]{ Host }; my $opt = $target->[ $u ]{ SnmpOpt }; $nloc = "$comm\@$host$opt"; } else { die "$NOW: ERROR: You must specify the location part of the RouterUptime oid for non unique targets! ($rou)\n"; } } $uploc = $nloc; # Get the device uptime if $noid(OID) and $nloc (community@host) have been specified # one way or the other debug('base', "Fetching sysUptime and sysName from: $noid:$nloc"); ( $uptime, $name ) = snmpget( $uploc, $rcfg->{ snmpoptions }{ $rou }, $noid, 'sysName'); } # Get the device name from the alternate location (OID or # OID:community@host) that may have been specified with the RouterName # target keyword if( defined $rcfg->{ routername }{ $rou } ) { my( $noid, $nloc ) = split( /:/, $rcfg->{ routername }{ $rou }, 2 ); # If no location (community@host) was specified use values from the # unique target referred to in the monitored data calculation if( $u >= 0 and not $nloc ) { my $comm = $target->[ $u ]{ Community }; my $host = $target->[ $u ]{ Host }; my $opt = $target->[ $u ]{ SnmpOpt }; $nloc = "$comm\@$host$opt"; } # Get the location from the RouterUptime keyword if that is defined # and $nloc has not otherwise been specified $nloc = $uploc if $uploc and not $nloc; # Get the device name if $nloc (community@host) has been specified # one way or the other debug('base', "Fetching sysName from: $noid:$nloc"); ( $name ) = snmpget( $nloc, $$rcfg{snmpoptions}{ $rou }, $noid ) if $nloc; } return ( $last{ _IN_ }, $last{ _OUT_ }, $uptime, $name, $time ); } sub rateupcheck ($) { my $router = shift; if ($?) { my $value = $?; my $signal = $? & 127; #ignore the most significant bit #as it is always one when it is a returning #child says dave ... if (($MRTG_lib::OS ne 'UNIX') || ($signal != 127)) { my $exitval = $? >> 8; warn "$NOW: WARNING: rateup died from Signal $signal\n". " with Exit Value $exitval when doing router '$router'\n". " Signal was $signal, Returncode was $exitval\n" } } } sub clonedirectory { my($router,$cfg, $rcfg) = @_; require File::Copy; import File::Copy; return unless ( $$rcfg{'clonedirectory'}{$router} ); my ($clonedstdir, $clonedsttarget ,$srcname, $dstname); ($clonedstdir, $clonedsttarget ) = split (/,|\s+/, $$rcfg{'clonedirectory'}{$router}) if ( $$rcfg{'clonedirectory'}{$router} =~ /,|\S\s+\S/ ); if ( defined $clonedsttarget ) { $clonedsttarget =~ s/\s+//; $clonedsttarget = lc($clonedsttarget); } else { $clonedstdir = $$rcfg{'clonedirectory'}{$router}; } if ( $$rcfg{'directory'}{$router} ne $clonedstdir) { $clonedstdir =~ s/\s+$//; $clonedstdir .= "/" unless ($clonedstdir =~ /\/$/); my $fullpathsrcdir = "$$cfg{'logdir'}$$rcfg{'directory'}{$router}"; my $fullpathdstdir = "$$cfg{'logdir'}$clonedstdir"; die "$NOW: ERROR: Destination dir: $fullpathdstdir not found for cloning process\n" unless ( -e $fullpathdstdir ); die "$NOW: ERROR: Destination dir: $fullpathdstdir is not a directory destination for cloning process\n" unless ( -d $fullpathdstdir ); die "$NOW: ERROR: Destination dir: $fullpathdstdir is not writable for cloning process\n" unless ( -w $fullpathdstdir ); if ( defined $clonedsttarget ) { debug('base', "Clone directory $fullpathsrcdir to $fullpathdstdir " . "renaming target $router to $clonedsttarget"); } else { debug('base', "Clone directory $fullpathsrcdir to $fullpathdstdir"); } foreach my $srcfile (<$fullpathsrcdir$router\[.-\]*>) { debug('base', "copying $srcfile $fullpathdstdir"); copy("$srcfile","$fullpathdstdir") or warn "$NOW: WARNING: Cloning $srcfile to $fullpathdstdir unsuccessful; $!\n"; if ($srcfile =~ /\.html/i) { debug('base', "altering $fullpathdstdir/$router.$$rcfg{'extension'}{$router}"); # my $dirrel = "../" x ($$rcfg{'clonedirectory'}{$router} =~ tr|/|/|); # debug('base', "dirrel $dirrel $clonedstdir"); open(HTML,"$fullpathdstdir/$router.$$rcfg{'extension'}{$router}"); my @CLONEHTML = <HTML>; close(HTML); foreach ( @CLONEHTML ) { if ( defined $clonedsttarget and /$router/ ) { debug('base', "altering $router to $clonedsttarget in html file"); s/$router/$clonedsttarget/i; } if ( /SRC=/i and /$$rcfg{'directory'}{$router}/ ) { debug('base', "altering from $_"); s|(\.\./)+|$dirrel|; s|$$rcfg{'directory'}{$router}|$clonedstdir|; debug('base', "altering to $_"); } } open(HTML,">$fullpathdstdir/$router.$$rcfg{'extension'}{$router}"); print HTML $_ for ( @CLONEHTML ); close(HTML); } if ( defined $clonedsttarget ) { $srcfile =~ /.+\/(.+)?$/; $srcname = $1; $dstname = $srcname; $dstname =~ s/$router/$clonedsttarget/; debug('base', "Clone renaming $srcname to $dstname at $fullpathdstdir"); rename("$fullpathdstdir/$srcname","$fullpathdstdir/$dstname") or warn "$NOW: WARNING: Renaming $fullpathdstdir/$srcname to $fullpathdstdir/$dstname unsuccessful; $!\n"; } } } else { warn "$NOW: WARNING: Cloning to the same place suspended. ; $!\n"; } } sub writegraphics { my($router, $cfg, $rcfg, $inlast, $outlast, $time,$LOC, $opts) = @_; my($absmax,$maxv, $maxvi, $maxvo, $i, $period, $res); my(@exec, @mxvls, @metas); my(%maxin, %maxout, %maxpercent, %avin, %avout, %avmxin, %avmxout, %avpercent, %cuin, %cuout, %cupercent); my($rrdinfo); @metas = (); $maxvi = $$rcfg{'maxbytes1'}{$router}; $maxvo = $$rcfg{'maxbytes2'}{$router}; if ($maxvi > $maxvo) { $maxv = $maxvi; } else { $maxv = $maxvo; } $absmax = $$rcfg{'absmax'}{$router}; $absmax = $maxv unless defined $absmax; if ($absmax < $maxv) { die "$NOW: ERROR: AbsMax: $absmax is smaller than MaxBytes: $maxv\n"; } # select whether the datasource gives relative or absolute return values. my $up_abs="u"; $up_abs='m' if defined $$rcfg{'options'}{'perminute'}{$router}; $up_abs='h' if defined $$rcfg{'options'}{'perhour'}{$router}; $up_abs='d' if defined $$rcfg{'options'}{'derive'}{$router}; $up_abs='a' if defined $$rcfg{'options'}{'absolute'}{$router}; $up_abs='g' if defined $$rcfg{'options'}{'gauge'}{$router}; my $dotrrd = "$$cfg{'logdir'}$$rcfg{'directory'}{$router}$router.rrd"; my $dotlog = "$$cfg{'logdir'}$$rcfg{'directory'}{$router}$router.log"; my $reallog = $$cfg{logformat} eq 'rrdtool' ? $dotrrd : $dotlog; if (defined $$cfg{maxage} and -e $reallog and time()-$$cfg{maxage} > (stat($reallog))[9]){ warn "$NOW: ERROR: skipping update of $router. As $reallog is older than MaxAge ($$cfg{maxage} s)\n"; return undef; } if ($$cfg{logformat} eq 'rrdtool') { debug('base',"start RRDtool section"); # make sure we got some sane default here my %dstype = qw/u COUNTER a ABSOLUTE g GAUGE h COUNTER m COUNTER d DERIVE/; $up_abs = $dstype{$up_abs}; # update the database. # set minimum/maximum values. use 'U' if we cannot get good values # the lower bound is hardcoded to 0 my $absi = $maxvi; my $abso = $maxvo; $absi = $abso = $$rcfg{'absmax'}{$router} if defined $$rcfg{'absmax'}{$router}; debug('base',"maxi:$absi, maxo:$abso"); $absi = 'U' if $absi == 0; $abso = 'U' if $abso == 0; # check to see if we already have an RRD file or have to create it # maybe we can convert an .log file to the new rrd format if( $RRDs::VERSION >= 1.4 and $$cfg{rrdcached} and $$cfg{rrdcached} !~ /^unix:/ ) { # rrdcached in network mode. No log conversion possible. # In this mode, we cannot use absolute paths. So, we strip logdir from the name. $dotrrd = "$$rcfg{'directory'}{$router}$router.rrd"; if( $RRDs::VERSION < 1.49 ) { # This version of RRD doesnt support info, create and tune debug('base',"Unable to verify RRD file with this version of rrdcached"); if( !$main::verified_rrd{$dotrrd} ) { warn "WARN: Unable to verify $dotrrd with this version of RRDTool\n"; $main::verified_rrd{$dotrrd} = 1; } } elsif( !$main::verified_rrd{$dotrrd} ) { # Test to see if it exists debug('base',"Attempting to verify RRD file via rrdcached"); $rrdinfo = RRDs::info($dotrrd,'--daemon',$$cfg{rrdcached},'--noflush'); if(!$rrdinfo) { # doesnt exist, or cannot be accessed my $e = RRDs::error(); warn "$NOW: Cannot access $dotrrd; will attempt to (re)create it: $e\n" if $e; # don't fail if interval is not set my $interval = $$cfg{interval}; my $minhb = int($$cfg{interval} * 60)*2; $minhb = 600 if ($minhb <600); my $rows = $$rcfg{'rrdrowcount'}{$router} || int( 4000 / $interval); my $rows30m = $$rcfg{'rrdrowcount30m'}{$router} || 800; my $rows2h = $$rcfg{'rrdrowcount2h'}{$router} || 800; my $rows1d = $$rcfg{'rrdrowcount1d'}{$router} || 800; my @args = ($dotrrd, '-b', $time-10, '-s', int($interval * 60), "DS:ds0:$up_abs:$minhb:0:$absi", "DS:ds1:$up_abs:$minhb:0:$abso", "RRA:AVERAGE:0.5:1:$rows", ( $interval < 30 ? ("RRA:AVERAGE:0.5:".int(30/$interval).":".$rows30m):()), "RRA:AVERAGE:0.5:".int(120/$interval).":".$rows2h, "RRA:AVERAGE:0.5:".int(1440/$interval).":".$rows1d, "RRA:MAX:0.5:1:$rows", ( $interval < 30 ? ("RRA:MAX:0.5:".int(30/$interval).":".$rows30m):()), "RRA:MAX:0.5:".int(120/$interval).":".$rows2h, "RRA:MAX:0.5:".int(1440/$interval).":".$rows1d); # do we have holt winters rras defined here ? if (defined $$rcfg{'rrdhwrras'} and defined $$rcfg{'rrdhwrras'}{$router}){ push @args, split(/\s+/, $$rcfg{'rrdhwrras'}{$router}); } push @args,"--daemon", $$cfg{rrdcached}; debug('base',"create $dotrrd via rrdcached"); debug('log', "RRDs::create(".join(',',@args).")"); RRDs::create(@args); $e = RRDs::error(); die "$NOW: ERROR: Cannot create RRD ".join(',',@args)."- $e\n" if $e; } else { # Does the RRD file need to be tuned? if( ($rrdinfo->{"ds[ds0].max"} != $absi) ||($rrdinfo->{"ds[ds1].max"} != $abso) ||($rrdinfo->{"ds[ds0].type"} ne $up_abs) ||($rrdinfo->{"ds[ds1].type"} ne $up_abs) ) { debug('base',"RRD file needs to be tuned"); warn "$NOW: RRDFile $dotrrd needs to be tuned but cannot do this remotely.\n"; } } $main::verified_rrd{$dotrrd} = 1; } else { debug('base',"No need to verify this file again"); } } elsif (-e $dotlog and not -e $dotrrd) { debug('base',"converting $dotlog to RRD format"); if(defined $RRDs::VERSION and $RRDs::VERSION < 1.000271){ die "$NOW: ERROR: RRDtool version 1.0.27 or later required to perform log2rrd conversion\n"; } log2rrd($router,$cfg,$rcfg); } elsif (! -e $dotrrd) { #nope it seems we have to create a new one debug('base',"create $dotrrd"); # create the rrd if it doesn't exist # don't fail if interval is not set my $interval = $$cfg{interval}; my $minhb = int($$cfg{interval} * 60)*2; $minhb = 600 if ($minhb <600); my $rows = $$rcfg{'rrdrowcount'}{$router} || int( 4000 / $interval); my $rows30m = $$rcfg{'rrdrowcount30m'}{$router} || 800; my $rows2h = $$rcfg{'rrdrowcount2h'}{$router} || 800; my $rows1d = $$rcfg{'rrdrowcount1d'}{$router} || 800; my @args = ($dotrrd, '-b', $time-10, '-s', int($interval * 60), "DS:ds0:$up_abs:$minhb:0:$absi", "DS:ds1:$up_abs:$minhb:0:$abso", "RRA:AVERAGE:0.5:1:$rows", ( $interval < 30 ? ("RRA:AVERAGE:0.5:".int(30/$interval).":".$rows30m):()), "RRA:AVERAGE:0.5:".int(120/$interval).":".$rows2h, "RRA:AVERAGE:0.5:".int(1440/$interval).":".$rows1d, "RRA:MAX:0.5:1:$rows", ( $interval < 30 ? ("RRA:MAX:0.5:".int(30/$interval).":".$rows30m):()), "RRA:MAX:0.5:".int(120/$interval).":".$rows2h, "RRA:MAX:0.5:".int(1440/$interval).":".$rows1d); # do we have holt winters rras defined here ? if (defined $$rcfg{'rrdhwrras'} and defined $$rcfg{'rrdhwrras'}{$router}){ push @args, split(/\s+/, $$rcfg{'rrdhwrras'}{$router}); } debug('log', "RRDs::create(".join(',',@args).")"); RRDs::create(@args); my $e = RRDs::error(); die "$NOW: ERROR: Cannot create RRD ".join(',',@args)."- $e\n" if $e; } elsif ( -M $dotrrd > 0 ) { # update the minimum/maximum according to maxbytes/absmax # and (re)set the data-source-type to reflect cfg changes # cost: 1 read/write cycle, but update will reuse the buffered data # in daemon mode this will only happen in the first round my @args = ($dotrrd, '-a', "ds0:$absi", '-a', "ds1:$abso", '-d', "ds0:$up_abs", '-d', "ds1:$up_abs"); debug('log', "RRDs::tune(@args)"); my $start = gettimeofday(); RRDs::tune(@args); debug('prof',sprintf("RRDs::tune $dotrrd - %.3fs",gettimeofday()-$start)); my $e = RRDs::error(); warn "$NOW: ERROR: Cannot tune logfile: $e\n" if $e; } # update the rrd $inlast = 'U' unless defined $inlast and $inlast =~ /\S/ and $inlast ne '##UNDEF##'; $outlast = 'U' unless defined $outlast and $outlast =~ /\S/ and $outlast ne '##UNDEF##'; debug('log', "RRDs::update($dotrrd, '$time:$inlast:$outlast')"); my $start = gettimeofday(); my $rrddata = 0; if ( $RRDs::VERSION >= 1.4 and $$cfg{rrdcached} ){ RRDs::update($dotrrd, '--daemon', $$cfg{rrdcached}, "$time:$inlast:$outlast"); debug('prof',sprintf("RRDs::update $dotrrd (rrdcached) - %.3fs",gettimeofday()-$start)); $rrddata = \{ dummy => "" }; } elsif ( $RRDs::VERSION >= 1.2 ){ $rrddata=RRDs::updatev($dotrrd, "$time:$inlast:$outlast"); debug('prof',sprintf("RRDs::updatev $dotrrd - %.3fs",gettimeofday()-$start)); } else { RRDs::update($dotrrd, "$time:$inlast:$outlast"); debug('prof',sprintf("RRDs::update $dotrrd - %.3fs",gettimeofday()-$start)); } my $e = RRDs::error(); warn "$NOW: ERROR: Cannot update $dotrrd with '$time:$inlast:$outlast' $e\n" if ($e); # Send a copy of the time series data to graphite if(defined $$cfg{sendtographite}) { my @a = split ",",$$cfg{sendtographite}; if (not $graphiteObj) { $graphiteObj = Net::Graphite->new( host => $a[0], port => $a[1], trace => 0, proto => "tcp", timeout => 1, fire_and_forget => 1, return_connect_error => 0 ); if($graphiteObj->connect) { debug('log',"successfully opened graphite socket ($graphiteObj)\n"); } else { debug('log',"graphite connect error: $!\n"); } } # make a copy of the router name for use in the graphite namespace my $graphiterouter = $router; # periods are delimiters in the graphite namespace so change them to underscores $graphiterouter =~ s/_/\./g; # commas are not allowed $graphiterouter =~ s/,//g; #remove commas #set up MRTG's 'in' var naming for graphite my $graphitein; if ($$rcfg{'legendi'}{$router}) { $graphitein = $$rcfg{'legendi'}{$router}; # if the 'in' var contains an underscore, change to a period so graphite will delimit on it $graphitein =~ s/_/\./g; } else { # if legendi is not specified, just use 'in' $graphitein = "in"; } #set up MRTG's 'out' var naming for graphite my $graphiteout; if ($$rcfg{'legendo'}{$router}) { $graphiteout = $$rcfg{'legendo'}{$router}; # if the 'out' var contains an underscore, change to a period so graphite will delimit on it $graphiteout =~ s/_/\./g; } else { # if legendo is not specified, just use 'out' $graphiteout = "out"; } my $graphitensprefix="m2g"; # verify that the 'in' value is numeric (ints, floats, +, -) , and send to graphite if($inlast =~ /^[+-]?([0-9]*[.])?[0-9]+$/) { # send the 'in' var data to graphite, and log it appropriately debug('log', "graphite->send($graphitensprefix.$graphiterouter.$graphitein,$inlast,$time)\n"); $graphiteObj->send( path => "$graphitensprefix.$graphiterouter.$graphitein", value => "$inlast", time => $time, ); } else { debug('log', "WARNING - skipped graphite->send($graphitensprefix.$graphiterouter.$graphitein,$inlast,$time) because value ($inlast) is non-numeric\n"); } # verify that the 'out' value is numeric (ints, floats, +, -) , and send to graphite if($outlast =~ /^[+-]?([0-9]*[.])?[0-9]+$/) { # send the 'out' var data to graphite, and log it appropriately debug('log', "graphite->send($graphitensprefix.$graphiterouter.$graphiteout,$outlast,$time)\n"); $graphiteObj->send( path => "$graphitensprefix.$graphiterouter.$graphiteout", value => "$outlast", time => $time, ); } else { debug('log', "WARNING - skipped graphite->send($graphitensprefix.$graphiterouter.$graphiteout,$outlast,$time) because value ($outlast) is non-numeric\n"); } } # done sending to graphite for this iteration if ( $RRDs::VERSION < 1.2 ){ # get the rrdtool-processed values back from rrdtool # for the threshold checks (we cannot use the fetched data) $start = gettimeofday(); my $info = RRDs::info($dotrrd); debug('prof',sprintf("RRDs::info $dotrrd - %.3fs",gettimeofday()-$start)); my $lasttime = $info->{last_update} - $info->{last_update} % $info->{step}; debug('log', "RRDs::info($dotrrd)"); $e = RRDs::error(); warn "$NOW: ERROR: Cannot 'info' $dotrrd: $e\n" if ($e); $start = gettimeofday(); my $fetch = (RRDs::fetch($dotrrd,'AVERAGE','-s',$lasttime-1,'-e',$lasttime))[3]; debug('prof',sprintf("RRDs::fetch $dotrrd - %.3fs",gettimeofday()-$start)); $e = RRDs::error(); warn "$NOW: ERROR: Cannot 'fetch' $dotrrd: $e\n" if ($e); debug('log', "RRDs::fetch($dotrrd,'AVERAGE','-s',$lasttime,'-e',$lasttime)"); $cuin{d}{$router} = $fetch->[0][0]; $cuout{d}{$router} = $fetch->[0][1]; } elsif ( $RRDs::VERSION >= 1.4 and $$cfg{rrdcached} ){ # Cannot check thresholds } elsif($rrddata) { my $utime = $time - ($time % int($cfg->{interval}*60)); $cuin{d}{$router} = $rrddata->{"[$utime]RRA[AVERAGE][1]DS[ds0]"}; $cuout{d}{$router} = $rrddata->{"[$utime]RRA[AVERAGE][1]DS[ds1]"}; $cuin{d_hwfail}{$router} = $rrddata->{"[$utime]RRA[FAILURES][1]DS[ds0]"}; $cuout{d_hwfail}{$router} = $rrddata->{"[$utime]RRA[FAILURES][1]DS[ds1]"}; } my $in = defined $cuin{d}{$router} ? $cuin{d}{$router} : "???" ; my $out = defined $cuout{d}{$router} ? $cuout{d}{$router} : "???" ; debug('log', " got: $in/$out"); # the html pages and the graphics are created at "call time" so that's it! # (the returned hashes are empty, it's just to minimize the changes to mrtg) if ($$rcfg{'options'}{'dorelpercent'}{$router}) { return (\%maxin, \%maxout, \%maxpercent, \%avin, \%avout, \%avpercent, \%cuin, \%cuout, \%cupercent, \%avmxin, \%avmxout); } return (\%maxin, \%maxout, \%avin, \%avout, \%cuin, \%cuout, \%avmxin, \%avmxout ); } ########## rrdtool users have left here ############### ((($MRTG_lib::OS eq 'NT' or $MRTG_lib::OS eq 'OS2') and (-e "${FindBin::Bin}${MRTG_lib::SL}rateup.exe")) or (($MRTG_lib::OS eq 'NW') and (-e "SYS:/Mrtg/bin/rateup.nlm")) or (-x "${FindBin::Bin}${MRTG_lib::SL}rateup")) or die "$NOW: ERROR: Can't Execute '${FindBin::Bin}${MRTG_lib::SL}rateup'\n"; # rateup does not know about undef so we make inlast and outlast ready for rateup #warn "$NOW: ERROR: inlast is undefined. Skipping $router\n" unless defined $inlast; #warn "$NOW: ERROR: outlast is undefined. Skipping $router\n" unless defined $outlast; #return undef unless defined $inlast and defined $outlast; # set values to -1 to tell rateup about unknown values $inlast = -1 unless defined $inlast; $outlast = -1 unless defined $outlast; # untaint in and out if ($inlast =~ /^([-0-9.]+)$/) { $inlast = $1; } if ($outlast =~ /^([-0-9.]+)$/) { $outlast = $1; } if ($$rcfg{'options'}{'dorelpercent'}{$router}) { @exec = ("${FindBin::Bin}${MRTG_lib::SL}rateup", "$$cfg{'logdir'}$$rcfg{'directory'}{$router}","$router", $time, $$rcfg{'options'}{'unknaszero'}{$router} ? '-z':'-Z', "$up_abs"."p", $inlast, $outlast, $absmax, "C", $$rcfg{'rgb1'}{$router},$$rcfg{'rgb2'}{$router}, $$rcfg{'rgb3'}{$router},$$rcfg{'rgb4'}{$router}, $$rcfg{'rgb5'}{$router}); } else { @exec = ("${FindBin::Bin}${MRTG_lib::SL}rateup", "$$cfg{'logdir'}$$rcfg{'directory'}{$router}","$router", $time, $$rcfg{'options'}{'unknaszero'}{$router} ? '-z':'-Z', "$up_abs", $inlast, $outlast, $absmax, "c", $$rcfg{'rgb1'}{$router},$$rcfg{'rgb2'}{$router}, $$rcfg{'rgb3'}{$router},$$rcfg{'rgb4'}{$router}); } # If this list grows anymore would it be more efficient to have an # array to look up the command line option to send to rateup rather # than have a long list to check? push (@exec, '-t') if defined $$rcfg{'options'}{'transparent'}{$router}; push (@exec, '-0') if defined $$rcfg{'options'}{'withzeroes'}{$router}; push (@exec, '-b') if defined $$rcfg{'options'}{'noborder'}{$router}; push (@exec, '-a') if defined $$rcfg{'options'}{'noarrow'}{$router}; push (@exec, '-i') if defined $$rcfg{'options'}{'noi'}{$router}; push (@exec, '-o') if defined $$rcfg{'options'}{'noo'}{$router}; push (@exec, '-l') if defined $$rcfg{'options'}{'logscale'}{$router}; push (@exec, '-x') if defined $$rcfg{'options'}{'expscale'}{$router}; push (@exec, '-m') if defined $$rcfg{'options'}{'secondmean'}{$router}; push (@exec, '-p') if defined $$rcfg{'options'}{'printrouter'}{$router}; my $maxx = $$rcfg{'xsize'}{$router}; my $maxy = $$rcfg{'ysize'}{$router}; my $xscale = $$rcfg{'xscale'}{$router}; my $yscale = $$rcfg{'yscale'}{$router}; my $growright = 0+($$rcfg{'options'}{'growright'}{$router} or 0); my $bits = 0+($$rcfg{'options'}{'bits'}{$router} or 0); my $integer = 0+($$rcfg{'options'}{'integer'}{$router} or 0); my $step = 5*60; my $rop; my $ytics = $$rcfg{'ytics'}{$router}; my $yticsf= $$rcfg{'yticsfactor'}{$router}; my $timestrfmt = $$rcfg{'timestrfmt'}{$router}; my $timestrpos = ${MRTG_lib::timestrpospattern}{uc $$rcfg{'timestrpos'}{$router}}; if (not defined $$rcfg{'ylegend'}{$router}){ if ($bits){ $$rcfg{'ylegend'}{$router} = &$LOC("Bits per minute") if defined $$rcfg{'options'}{'perminute'}{$router}; $$rcfg{'ylegend'}{$router} = &$LOC("Bits per hour") if defined $$rcfg{'options'}{'perhour'}{$router}; } else { $$rcfg{'ylegend'}{$router} = &$LOC("Bytes per minute") if defined $$rcfg{'options'}{'perminute'}{$router}; $$rcfg{'ylegend'}{$router} = &$LOC("Bytes per hour") if defined $$rcfg{'options'}{'perhour'}{$router}; } } if ($$rcfg{'ylegend'}{$router}) { push (@exec, "l", "[$$rcfg{'ylegend'}{$router}]"); } my $sign = ($$rcfg{'unscaled'}{$router} and $$rcfg{'unscaled'}{$router} =~ /d/) ? 1 : -1; if ($$rcfg{'pngtitle'}{$router}) { push (@exec, "T", "[$$rcfg{'pngtitle'}{$router}]"); } if ($$rcfg{'timezone'}{$router}) { push (@exec, "Z", "$$rcfg{'timezone'}{$router}"); } if ($$rcfg{'kilo'}{$router}) { push (@exec, "k", $$rcfg{'kilo'}{$router}); } if ($$rcfg{'kmg'}{$router}) { push (@exec, "K", $$rcfg{'kmg'}{$router}); } if ($$rcfg{'weekformat'}{$router}) { push (@exec, "W", $$rcfg{'weekformat'}{$router}); } my $SAGE = (time - $main::STARTTIME) / 3600 / 24; # current script age if (not defined $$opts{'log-only'}){ if (not defined $$rcfg{'suppress'}{$router} or $$rcfg{'suppress'}{$router} !~ /d/) { # VMS: should work for both now push (@exec, "i", "$$cfg{'imagedir'}$$rcfg{'directory'}{$router}${router}-day.${main::GRAPHFMT}", $sign*$maxvi, $sign*$maxvo, $maxx, $maxy, ,$xscale, $yscale, $growright, $step, $bits, $ytics, $yticsf, $timestrfmt, $timestrpos); @mxvls = ("d"); push (@metas, "$$cfg{'imagedir'}$$rcfg{'directory'}{$router}${router}-day.${main::GRAPHFMT}", $$cfg{'interval'}); } if (((not -e "$$cfg{'imagedir'}$$rcfg{'directory'}{$router}${router}-week.${main::GRAPHFMT}") or ((-M "$$cfg{'imagedir'}$$rcfg{'directory'}{$router}${router}-week.${main::GRAPHFMT}") + $SAGE >= 0.5/24)) and (not defined $$rcfg{'suppress'}{$router} or $$rcfg{'suppress'}{$router} !~/w/) ) { $step=30*60; $sign = (defined $$rcfg{'unscaled'}{$router} and $$rcfg{'unscaled'}{$router} =~ /w/) ? 1 : -1; push (@mxvls , "w"); $rop =(defined $$rcfg{'withpeak'}{$router} and $$rcfg{'withpeak'}{$router} =~ /w/) ? "p" : "i"; push (@exec, $rop ,"$$cfg{'imagedir'}$$rcfg{'directory'}{$router}${router}-week.${main::GRAPHFMT}", $sign*$maxvi, $sign*$maxvo, $maxx, $maxy, $xscale, $yscale, $growright, $step, $bits, $ytics, $yticsf, $timestrfmt, $timestrpos); push (@metas, "$$cfg{'imagedir'}$$rcfg{'directory'}{$router}${router}-week.${main::GRAPHFMT}", 30); } if (((not -e "$$cfg{'imagedir'}$$rcfg{'directory'}{$router}${router}-month.${main::GRAPHFMT}") or (( -M "$$cfg{'imagedir'}$$rcfg{'directory'}{$router}${router}-month.${main::GRAPHFMT}") + $SAGE >= 2/24)) and (not defined $$rcfg{'suppress'}{$router} or $$rcfg{'suppress'}{$router} !~ /m/)) { $step=2*60*60; $sign = (defined $$rcfg{'unscaled'}{$router} and $$rcfg{'unscaled'}{$router} =~ /m/) ? 1 : -1; push (@mxvls , "m"); $rop =(defined $$rcfg{'withpeak'}{$router} and $$rcfg{'withpeak'}{$router} =~ /m/) ? "p" : "i"; push (@exec, $rop ,"$$cfg{'imagedir'}$$rcfg{'directory'}{$router}${router}-month.${main::GRAPHFMT}", $sign*$maxvi, $sign*$maxvo, $maxx, $maxy, $xscale, $yscale, $growright, $step, $bits, $ytics, $yticsf, $timestrfmt, $timestrpos); push (@metas, "$$cfg{'imagedir'}$$rcfg{'directory'}{$router}${router}-month.${main::GRAPHFMT}", 120); } if (((not -e "$$cfg{'imagedir'}$$rcfg{'directory'}{$router}${router}-year.${main::GRAPHFMT}") or (( -M "$$cfg{'imagedir'}$$rcfg{'directory'}{$router}${router}-year.${main::GRAPHFMT}") + $SAGE >= 1)) and (not defined $$rcfg{'suppress'}{$router} or $$rcfg{'suppress'}{$router} !~/y/)) { $step=24*60*60; $sign = (defined $$rcfg{'unscaled'}{$router} and $$rcfg{'unscaled'}{$router} =~ /y/) ? 1 : -1; push (@mxvls , "y"); $rop =(defined $$rcfg{'withpeak'}{$router} and $$rcfg{'withpeak'}{$router} =~ /y/) ? "p" : "i"; push (@exec, $rop, "$$cfg{'imagedir'}$$rcfg{'directory'}{$router}${router}-year.${main::GRAPHFMT}", $sign*$maxvi, $sign*$maxvo, $maxx, $maxy, $xscale, $yscale, $growright, $step, $bits, $ytics, $yticsf, $timestrfmt, $timestrpos); push (@metas, "$$cfg{'imagedir'}$$rcfg{'directory'}{$router}${router}-year.${main::GRAPHFMT}", 1440); } } # VMS: this might work now ... or does VMS NOT know about pipes? # NT doesn't have fork() so an open(xxx,"-|") won't work # OS2 fork() have bug with socket handles. In RunAsDaemon mode it fail # after first loop (with "socket operation on non socket" message. if ($MRTG_lib::OS eq 'VMS' or $MRTG_lib::OS eq 'NT' or $MRTG_lib::OS eq 'OS2'){ map { s/"/\\"/; $_ = '"'.$_.'"' if /\s/ } @exec; open (RATEUP, join (" ", @exec)."|") or do { warn "$NOW: WARNING: rateup (".(join " ", @exec ). ") did not work: $!\n"; return; } } elsif ($MRTG_lib::OS eq 'NW'){ map { s/"/\\"/; $_ = '"'.$_.'"' if /\s/ } @exec; # Stuff around because of Perl problems. open (NWPARMS, ">"."$$cfg{'imagedir'}$router.dat") or do { warn "$NOW: WARNING: Rateup parameters [$$cfg{'imagedir'}$router.dat] [open] failed.\n"; return; }; print NWPARMS join (" ", @exec); close NWPARMS; # Now run Rateup with path to Parameters. open (RATEUP, "SYS:/Mrtg/bin/rateup -f $$cfg{'imagedir'}$router.dat"."|") or do { warn "$NOW: WARNING: SYS:/Mrtg/bin/rateup -f $$cfg{'imagedir'}$router.dat did NOT work.\n"; return; } } else { $! = undef; open (RATEUP,"-|") or do { exec @exec or warn "$NOW: WARNING: rateup (".(join " ", @exec ). ") did not work: $!\n"; }; } debug('log', join(" ", @exec)); if (open (HTML,"<$$cfg{'htmldir'}$$rcfg{'directory'}{$router}$router.$$rcfg{'extension'}{$router}")) { for ($i=0 ; $i<200 ; $i++) { last if eof(HTML); $_= <HTML>; if (/<!-- maxin ([dwmy]) (\d*)/) { $maxin{$1}{$router}=$2 || 0; } if (/<!-- maxout ([dwmy]) (\d*)/) { $maxout{$1}{$router}=$2 || 0; } if (/<!-- maxpercent ([dwmy]) (\d*)/) { $maxpercent{$1}{$router}=$2 || 0; } if (/<!-- avin ([dwmy]) (\d*)/) { $avin{$1}{$router}=$2 || 0; } if (/<!-- avout ([dwmy]) (\d*)/) { $avout{$1}{$router}=$2 || 0; } if (/<!-- avpercent ([dwmy]) (\d*)/) { $avpercent{$1}{$router}=$2 || 0; } if (/<!-- cuin ([dwmy]) (\d*)/) { $cuin{$1}{$router}=$2 || 0; } if (/<!-- cuout ([dwmy]) (\d+)/) { $cuout{$1}{$router}=$2 || 0; } if (/<!-- cupercent ([dwmy]) (\d+)/) { $cupercent{$1}{$router}=$2 || 0; } if (/<!-- avmxin ([dwmy]) (\d*)/) { $avmxin{$1}{$router}=$2 || 0; } if (/<!-- avmxout ([dwmy]) (\d*)/) { $avmxout{$1}{$router}=$2 || 0; } } close HTML; } foreach $period (@mxvls) { $res = <RATEUP>; if (not defined $res and eof(RATEUP)){ warn "$NOW: ERROR: Skipping webupdates because rateup did not return anything sensible\n"; close RATEUP; rateupcheck $router; return; }; chomp $res; $maxin{$period}{$router}=sprintf("%.0f",$res || 0); chomp($res = <RATEUP>); $maxout{$period}{$router}=sprintf("%.0f",$res || 0); if ($$rcfg{'options'}{'dorelpercent'}{$router}) { chomp($res = <RATEUP>); $maxpercent{$period}{$router}=sprintf("%.0f",$res || 0); } chomp($res = <RATEUP>); $avin{$period}{$router}=sprintf("%.0f",$res || 0); chomp($res = <RATEUP>); $avout{$period}{$router}=sprintf("%.0f",$res || 0); if ($$rcfg{'options'}{'dorelpercent'}{$router}) { chomp($res = <RATEUP>); $avpercent{$period}{$router}=sprintf("%.0f",$res || 0); } chomp($res = <RATEUP>); $cuin{$period}{$router}=sprintf("%.0f",$res || 0); chomp($res = <RATEUP>); $cuout{$period}{$router}=sprintf("%.0f",$res || 0); if ($$rcfg{'options'}{'dorelpercent'}{$router}) { chomp($res = <RATEUP>); $cupercent{$period}{$router}=sprintf("%.0f",$res || 0); } chomp($res = <RATEUP>); debug('avmx',"avmxin $res"); $avmxin{$period}{$router}=sprintf("%.0f",$res || 0); chomp($res = <RATEUP>); debug('avmx',"avmxout $res"); $avmxout{$period}{$router}=sprintf("%.0f",$res || 0); } close(RATEUP); rateupcheck $router; if ( defined $$cfg{'writeexpires'} and $$cfg{'writeexpires'} =~ /^y/i ) { my($fil,$exp); while ( $fil = shift(@metas) ) { $exp = &expistr(shift(@metas)); open(META, ">$fil.meta"); print META "Expires: $exp\n"; close(META); } } if ($$rcfg{'options'}{'dorelpercent'}{$router}) { return (\%maxin, \%maxout, \%maxpercent, \%avin, \%avout, \%avpercent, \%cuin, \%cuout, \%cupercent, \%avmxin, \%avmxout); } else { return (\%maxin, \%maxout, \%avin, \%avout, \%cuin, \%cuout, \%avmxin, \%avmxout); } } #format 10*$kilo to 10 kB/s sub fmi { my($number, $maxbytes, $router, @foo) = @_; return "?????" unless defined $number; my($rcfg,$LOC)=@foo; my @short= (); my $mul = 1; if ($$rcfg{'kmg'}{$router}) { my($i); if (defined $$rcfg{'shortlegend'}{$router}) { foreach $i (split(/,/, $$rcfg{'kmg'}{$router})) { $short[$#short+1] = "$i"."$$rcfg{'shortlegend'}{$router}"; } } elsif ($$rcfg{'options'}{'bits'}{$router}) { foreach $i (split(/,/, $$rcfg{'kmg'}{$router})) { if ($$rcfg{'options'}{'perminute'}{$router}) { $short[$#short+1] = "$i".&$LOC("b/min"); } elsif ($$rcfg{'options'}{'perhour'}{$router}) { $short[$#short+1] = "$i".&$LOC("b/h"); } else { $short[$#short+1] = "$i".&$LOC("b/s"); } } $mul= 8; } else { foreach $i (split(/,/, $$rcfg{'kmg'}{$router})) { if ($$rcfg{'options'}{'perminute'}{$router}) { $short[$#short+1] = "$i".&$LOC ("B/min"); } elsif ($$rcfg{'options'}{'perhour'}{$router}) { $short[$#short+1] = "$i".&$LOC("B/h"); } else { $short[$#short+1] = "$i".&$LOC("B/s"); } } $mul= 1; } } else { if (defined $$rcfg{'options'}{'bits'}{$router}) { if ($$rcfg{'options'}{'perminute'}{$router}) { @short = (&$LOC("b/min"),&$LOC("kb/min"),&$LOC("Mb/min"),&$LOC("Gb/min")); } elsif (defined $$rcfg{'options'}{'perhour'}{$router}) { @short = (&$LOC("b/h"),&$LOC("kb/h"),&$LOC("Mb/h"),&$LOC("Gb/h")); } else { @short = (&$LOC("b/s"),&$LOC("kb/s"),&$LOC("Mb/s"),&$LOC("Gb/s")); } $mul= 8; } else { if ($$rcfg{'options'}{'perminute'}{$router}) { @short = (&$LOC("B/min"),&$LOC("kB/min"),&$LOC("MB/min"),&$LOC("GB/min")); } elsif ($$rcfg{'options'}{'perhour'}{$router}) { @short = (&$LOC("B/h"),&$LOC("kB/h"),&$LOC("MB/h"),&$LOC("GB/h")); } else { @short = (&$LOC("B/s"),&$LOC("kB/s"),&$LOC("MB/s"),&$LOC("GB/s")); } $mul= 1; } if ($$rcfg{'shortlegend'}{$router}) { @short = ("$$rcfg{'shortlegend'}{$router}", "k$$rcfg{'shortlegend'}{$router}", "M$$rcfg{'shortlegend'}{$router}", "G$$rcfg{'shortlegend'}{$router}"); } } my $digits=length("".$number*$mul); my $divm=0; # # while ($digits-$divm*3 > 4) { $divm++; } # my $divnum = $number*$mul/10**($divm*3); my $divnum=$number*$mul*$$rcfg{'factor'}{$router}; # while ($divnum/$$rcfg{'kilo'}{$router} >= 10*$$rcfg{'kilo'}{$router} and $divnum<$#short) { while (($divnum >= 10*$$rcfg{'kilo'}{$router} or $short[$divm] =~ /^-/) and $divm<$#short) { $divm++; $divnum /= $$rcfg{'kilo'}{$router}; } my $perc; if ($number == 0 || $maxbytes == 0) { $perc = 0; } else { $perc = 100/$maxbytes*$number; } if (defined $$rcfg{'options'}{'integer'}{$router}) { if ($$rcfg{'options'}{'nopercent'}{$router}) { return sprintf("%.0f %s",$divnum,$short[$divm]); } else { return sprintf("%.0f %s (%2.1f%%)",$divnum,$short[$divm],$perc); } } else { if (defined $$rcfg{'options'}{'nopercent'}{$router}) { return sprintf("%.1f %s",$divnum,$short[$divm]); # Added: FvW } else { return sprintf("%.1f %s (%2.1f%%)",$divnum,$short[$divm],$perc); } return sprintf("%.1f %s (%2.1f%%)",$divnum,$short[$divm],$perc); } } sub writehtml { my($router, $cfg, $rcfg, $maxin, $maxout, $maxpercent, $avin, $avout, $avmxin, $avmxout, $avpercent, $cuin, $cuout, $cupercent, $uptime, $name, $LOC) = @_; my($VERSION,$Today,$peri); my($persec); if (defined $$rcfg{'options'}{'bits'}{$router}) { $persec = &$LOC("Bits"); } else { $persec = &$LOC("Bytes"); } # Work out the Colour legend my($leg1, $leg2, $leg3, $leg4, $leg5); if ($$rcfg{'legend1'}{$router}) { $leg1 = $$rcfg{'legend1'}{$router}; } else { if ($$rcfg{'options'}{'perminute'}{$router}) { $leg1=&$LOC("Incoming Traffic in $persec per Minute"); } elsif ($$rcfg{'options'}{'perhour'}{$router}) { $leg1=&$LOC("Incoming Traffic in $persec per Hour"); } else { $leg1=&$LOC("Incoming Traffic in $persec per Second"); } } if ($$rcfg{'legend2'}{$router}) { $leg2 = $$rcfg{'legend2'}{$router}; } else { if ($$rcfg{'options'}{'perminute'}{$router}) { $leg2=&$LOC("Outgoing Traffic in $persec per Minute"); } elsif ($$rcfg{'options'}{'perhour'}{$router}) { $leg2=&$LOC("Outgoing Traffic in $persec per Hour"); } else { $leg2=&$LOC("Outgoing Traffic in $persec per Second"); } } if ($$rcfg{'legend3'}{$router}) { $leg3 = $$rcfg{'legend3'}{$router}; } else { $leg3 = &$LOC("Maximal 5 Minute Incoming Traffic"); } if ($$rcfg{'legend4'}{$router}) { $leg4 = $$rcfg{'legend4'}{$router}; } else { $leg4 = &$LOC("Maximal 5 Minute Outgoing Traffic"); } if ($$rcfg{'legend5'}{$router}) { $leg5 = $$rcfg{'legend5'}{$router}; } else { $leg5 = "(($leg1)/($leg2))*100"; } # Translate the color names $$rcfg{'col1'}{$router}=&$LOC($$rcfg{'col1'}{$router}); $$rcfg{'col2'}{$router}=&$LOC($$rcfg{'col2'}{$router}); $$rcfg{'col3'}{$router}=&$LOC($$rcfg{'col3'}{$router}); $$rcfg{'col4'}{$router}=&$LOC($$rcfg{'col4'}{$router}); $$rcfg{'col5'}{$router}=&$LOC($$rcfg{'col5'}{$router}); my $dirrel = "../" x ($$rcfg{'directory_web'}{$router} =~ tr|/|/|); $Today=&$LOC(datestr(time)); $VERSION = "2.17.10"; open (HTML,">$$cfg{'htmldir'}$$rcfg{'directory'}{$router}$router.$$rcfg{'extension'}{$router}") || do { warn ("$NOW: WARNING: Writing $router.$$rcfg{'extension'}{$router}: $!"); next }; # this unfortunately confuses old IE greatly ... so we have to comment # it out for now ... :-( # print HTML '<?xml version="1.0" encoding="' . &$LOC('UTF-8') . '"?>' . "\n"; print HTML '<!DOCTYPE html>' . "\n"; print HTML '<html lang="en">' . "\n"; my $interval =$$cfg{'interval'}; my $expiration = &expistr($interval); my $refresh = defined $$cfg{'refresh'} ? $$cfg{'refresh'} : 300; my $namestring = &$LOC("the device"); print HTML '<!-- MRTG ' . "$VERSION" . ' -->' . "\n"; print HTML '<!-- Begin Head -->' . "\n"; print HTML "\t" . '<head>' . "\n"; print HTML "\t\t" . '<meta charset="' . &$LOC('UTF-8') . '" />' . "\n"; print HTML "\t\t" . '<meta http-equiv="refresh" content="' . "$refresh" . '" />' . "\n"; # Not functional in HTML file in modern web browsers - use HTTP header instead # <meta http-equiv="pragma" content="no-cache" /> # <meta http-equiv="cache-control" content="no-cache" /> # <meta http-equiv="expires" content="$expiration" /> # <meta http-equiv="generator" content="MRTG $VERSION" /> # <meta http-equiv="date" content="$expiration" /> print HTML "\t\t" . '<title>' . "$$rcfg{'title'}{$router}" . '' . "\n"; foreach $peri (qw(d w m y)) { print HTML <<"TEXT"; TEXT if ($$rcfg{'options'}{'dorelpercent'}{$router} and defined $$maxpercent{$peri}{$router}) { print HTML <<"TEXT"; TEXT } print HTML <<"TEXT"; TEXT if ($$rcfg{'options'}{'dorelpercent'}{$router}) { print HTML <<"TEXT"; TEXT } print HTML "\n" if defined $$cuin{$peri}{$router}; print HTML "\n" if defined $$cuout{$peri}{$router}; if ($$rcfg{'options'}{'dorelpercent'}{$router} and $$cupercent{$peri}{$router} ) { print HTML <<"TEXT"; TEXT } print HTML <<"TEXT" if $$avmxin{$peri}{$router} and $$avmxout{$peri}{$router}; TEXT } $namestring = "'$name'" if $name; defined $$rcfg{backgc}{$router} or $$rcfg{backgc}{$router} = "#ffffff"; defined $$rcfg{textcolor}{$router} or $$rcfg{textcolor}{$router} = "#000000"; $$rcfg{'rgb1'}{$router} = "" unless defined $$rcfg{'rgb1'}{$router}; $$rcfg{'rgb2'}{$router} = "" unless defined $$rcfg{'rgb2'}{$router}; $$rcfg{'rgb3'}{$router} = "" unless defined $$rcfg{'rgb3'}{$router}; $$rcfg{'rgb4'}{$router} = "" unless defined $$rcfg{'rgb4'}{$router}; $$rcfg{'rgb5'}{$router} = "" unless defined $$rcfg{'rgb5'}{$router}; $$rcfg{'rgb6'}{$router} = "" unless defined $$rcfg{'rgb6'}{$router}; print HTML " "; # allow for \n in addhead defined $$rcfg{addhead}{$router} or $$rcfg{addhead}{$router} = ""; defined $$rcfg{pagetop}{$router} or $$rcfg{pagetop}{$router} = ""; if (defined $$rcfg{bodytag}{$router}) { if ($$rcfg{bodytag}{$router} !~ / "; print HTML " $$rcfg{bodytag}{$router} $$rcfg{'pagetop'}{$router} "; print HTML "

"; if (defined $$rcfg{'timezone'}{$router}){ print HTML &$LOC("The statistics were last updated $Today $$rcfg{'timezone'}{$router}"); } else { print HTML &$LOC("The statistics were last updated $Today"); } if ($uptime and ! $$rcfg{options}{noinfo}{$router}) { print HTML ",
\n". &$LOC("at which time $namestring had been up for $uptime.") } print HTML "

"; my %sample= ('d' => "`Daily' Graph (".$interval.' Minute', 'w' => "`Weekly' Graph (30 Minute", 'm' => "`Monthly' Graph (2 Hour", 'y' => "`Yearly' Graph (1 Day"); my %full = ('d' => 'day', 'w' => 'week', 'm' => 'month', 'y' => 'year'); my $InCo; if (!(defined $$rcfg{'options'}{'noi'}{$router})) { if (exists $$rcfg{'legendi'}{$router}) { if ($$rcfg{'legendi'}{$router} ne "") { $InCo=$$rcfg{'legendi'}{$router}; } } else { $InCo=&$LOC("In"); } } my $OutCo; if (!(defined $$rcfg{'options'}{'noo'}{$router})) { if (exists $$rcfg{'legendo'}{$router}) { if ($$rcfg{'legendo'}{$router} ne "") { $OutCo=$$rcfg{'legendo'}{$router}; } } else { $OutCo=&$LOC("Out"); } } my $PercentCo; if (defined $$rcfg{'legend5'}{$router}) { if ($$rcfg{'legend5'}{$router} ne "") { $PercentCo=$$rcfg{'legend5'}{$router}; } } else { $PercentCo=&$LOC("Percentage"); } foreach $peri (qw(d w m y)) { next if defined $$rcfg{'suppress'}{$router} and $$rcfg{'suppress'}{$router} =~/$peri/; my $gifw; if ($$rcfg{'options'}{'dorelpercent'}{$router}) { $gifw=sprintf("%.0f",($$rcfg{'xsize'}{$router}*$$rcfg{'xscale'}{$router}+ +100+30) *$$rcfg{'xzoom'}{$router}); } else { $gifw=sprintf("%.0f",($$rcfg{'xsize'}{$router}*$$rcfg{'xscale'}{$router} +100) *$$rcfg{'xzoom'}{$router}); } my $gifh=sprintf("%.0f",($$rcfg{'ysize'}{$router}*$$rcfg{'yscale'}{$router}+35) *$$rcfg{'yzoom'}{$router}); # take the image directory away from the html directory to give us relative links my $imagepath = ( $cfg->{htmldir} ne $cfg->{imagedir} ) ? "$dirrel$$cfg{imagehtml}$$rcfg{directory_web}{$router}" : ""; print HTML "

".&$LOC("$sample{$peri}").&$LOC(' Average)')."

\"$full{$peri}\" "; my(@foo)=($rcfg,$LOC); print HTML " " if $InCo; print HTML " " if $OutCo; print HTML " " if ($$rcfg{'options'}{'dorelpercent'}{$router} and $PercentCo); print HTML " " if ($$rcfg{'options'}{'avgpeak'}{$router} and $InCo and $OutCo); print HTML "
" . &$LOC("Max") . " " . &$LOC("Average") . " " . &$LOC("Current") . "
" . $InCo . " ".&fmi($$maxin{$peri}{$router}, $$rcfg{'maxbytes1'}{$router}, $router, @foo)." ".&fmi($$avin{$peri}{$router}, $$rcfg{'maxbytes1'}{$router}, $router, @foo)." ".&fmi($$cuin{$peri}{$router}, $$rcfg{'maxbytes1'}{$router}, $router, @foo)."
" . $OutCo . " ".&fmi($$maxout{$peri}{$router}, $$rcfg{'maxbytes2'}{$router}, $router, @foo)." ".&fmi($$avout{$peri}{$router}, $$rcfg{'maxbytes2'}{$router}, $router, @foo)." ".&fmi($$cuout{$peri}{$router}, $$rcfg{'maxbytes2'}{$router}, $router, @foo)."
" . $PercentCo . " ".sprintf("%0.1f %%",($$maxpercent{$peri}{$router} || 0))." ".sprintf("%0.1f %%",($$avpercent{$peri}{$router} || 0 ))." ".sprintf("%0.1f %%",($$cupercent{$peri}{$router} || 0 ))."
" . &$LOC("Average max 5 min values for $sample{$peri} interval):") . " $InCo " . &fmi($$avmxin{$peri}{$router}, $$rcfg{'maxbytes1'}{$router}, $router, @foo) . "/ $OutCo " . &fmi($$avmxout{$peri}{$router}, $$rcfg{'maxbytes2'}{$router}, $router, @foo) . "
\n"; } if (!(defined $$rcfg{'options'}{'nolegend'}{$router})) { print HTML "
"; print HTML " " if $InCo; print HTML " " if $OutCo; if ($$rcfg{'withpeak'}{$router}) { print HTML " " if $InCo; print HTML " " if $OutCo; } if ($$rcfg{'options'}{'dorelpercent'}{$router}) { print HTML " "; } print HTML "
$$rcfg{'col1'}{$router} ### $leg1
$$rcfg{'col2'}{$router} ### $leg2
$$rcfg{'col3'}{$router} ### $leg3
$$rcfg{'col4'}{$router} ### $leg4
$$rcfg{'col5'}{$router} ### $leg5
"; } if (!(defined $$rcfg{'options'}{'nobanner'}{$router})) { my $gifPath; if (defined $$cfg{icondir}) { $gifPath = $$cfg{icondir}; #lets make sure there is a trailing path separator $gifPath =~ s|/*$|/|; } else { $gifPath = "$dirrel$$cfg{imagehtml}"; } print HTML<
TEXT } print HTML $$rcfg{'pagefoot'}{$router} if defined $$rcfg{'pagefoot'}{$router}; print HTML < TEXT close HTML; if (defined $$cfg{'writeexpires'} and $$cfg{'writeexpires'} =~ /^y/i) { open(HTMLG, ">$$cfg{'htmldir'}$$rcfg{'directory'}{$router}$router.". "$$rcfg{'extension'}{$router}.meta") || do { warn "$NOW: WARNING: Writing $$cfg{'htmldir'}$$rcfg{'directory'}{$router}$router.". "$$rcfg{'extension'}{$router}.meta: $!\n"; next }; print HTMLG "Expires: $expiration\n"; close(HTMLG); } } sub printusage { print < mrtg-2.17.10 - Multi Router Traffic Grapher Copyright 1995-2006 by Tobias Oetiker Licensed under the Gnu GPL. If you want to know more about this tool, you might want to read the docs. You can find everything on the mrtg website: http://oss.oetiker.ch/mrtg/ USAGEDESC exit(1); } sub lockit { my ($lockfile,$templock) = @_; $main::Cleanfile = $templock; $main::Cleanfile2 = $lockfile; if ($MRTG_lib::OS eq 'VMS' or $MRTG_lib::OS eq 'NT' or $MRTG_lib::OS eq 'OS2') { # too sad NT and VMS can't do links we'll do the diletants lock if (-e $lockfile and not unlink $lockfile) { my($lockage) = time()-(stat($lockfile))[9]; die "$NOW: ERROR: I guess another mrtg is running. A lockfile ($lockfile)\n". " aged $lockage seconds is hanging around and I can't remove\n". " it because another process is still using it."; } open (LOCK, ">$lockfile") or die "$NOW: ERROR: Creating lockfile $lockfile: $!\n"; print LOCK "$$\n"; close LOCK; open (LOCK, "<$lockfile") or die "$NOW: ERROR: Reading lockfile $lockfile for owner check: $!\n"; my($read)=; chomp($read); die "$NOW: ERROR: Someone else just got the lockfile $lockfile\n" unless $$ == $read; } else { # now, lets do it the UNIX way ... Daves work ... if (open my $olf, "<$lockfile"){ my $oldpid = <$olf>; chomp $oldpid; if ($oldpid and not -d '/proc/'.$oldpid){ debug('base', "Remove stale lockfile $lockfile since pid $oldpid seems not to be around anymore"); unlink $lockfile; } close $olf; } open(LOCK,">$templock") or die "$NOW: ERROR: Creating templock $templock: $!"; print LOCK $$; close LOCK; if (!link($templock,$lockfile)) { # Lock file exists - deal with it. my($nlink,$lockage) = (stat($lockfile))[3,9]; $lockage = time() - $lockage; if ($nlink < 2 or $lockage > 30*60) { #lockfile is alone and old unlink($lockfile) || do{ unlink $templock; die "$NOW: ERROR: Can't unlink stale lockfile ($lockfile). Permissions?\n"}; link($templock,$lockfile) || do{ unlink $templock; die "$NOW: ERROR: Can't create lockfile ($lockfile).\n". "Permission problem or another mrtg locking successfully?\n"}; } else { unlink $templock; die "$NOW: ERROR: It looks as if you are running two copies of mrtg in parallel on\n". " the same config file. There is a lockfile ($lockfile) and it is\n". " is only $lockage seconds old ... Check your crontab.\n". " (/etc/crontab and /var/spool/cron/root) \n" if $lockage < 4; die "$NOW: ERROR: I guess another mrtg is running. A lockfile ($lockfile) aged\n". "$lockage seconds is hanging around. If you are sure that no other mrtg\n". "is running you can remove the lockfile\n"; } } } } sub threshmail ($$$$){ my $server = shift; my $from = shift; my $to = shift; my $message = shift; debug('base',"sending threshmail from $from to $to"); my $smtp = Net::SMTP->new([split /\s*,\s*/, $server],Timeout=>5) or do { warn "$NOW: ERROR: could not send thresholdmail to $to"; return }; $smtp->mail($from); $smtp->to(split(/\s*,\s*/, $to)); $smtp->data(); $smtp->datasend($message); $smtp->dataend(); $smtp->quit; } sub threshcheck { # threshold checking by Tom Muggli # ... fsck'd up but fixed by Juha Laine my ($cfg,$rcfg,$cfgfile,$router,$cuin,$cuout) = @_; my $threshfile; my %cu = ( i=> $cuin, o=>$cuout ); # are we going to keep state ? if (defined $$cfg{'threshdir'}){ ensureSL(\$$cfg{'threshdir'}); $threshfile = $$cfg{'threshdir'}.(split /\Q$MRTG_lib::SL\E/, $cfgfile)[-1].".$router"; } # setup environment for external scripts if (defined $rcfg->{'threshdesc'}{$router}) { $ENV{THRESH_DESC}=$rcfg->{'threshdesc'}{$router}; } else { delete $ENV{THRESH_DESC}; } if (defined $rcfg->{'hwthreshdesc'}{$router}) { $ENV{HWTHRESH_DESC}=$rcfg->{'hwthreshdesc'}{$router}; } else { delete $ENV{HWTHRESH_DESC}; } for my $dir (qw(i o)){ # in and out my %thresh = ( thresh => $cu{$dir}{d}{$router}, # if we are looking at an rrd with holtwinters RRAs # we get a failures count. hwthresh => $cu{$dir}{d_hwfail}{$router} ); for my $type (keys %thresh){ for my $bound (qw(min max)){ # it gets set inside the loop because threshval gets modified further # down in the code my $threshval = $thresh{$type}; next if not defined $threshval; my $boundval = $rcfg->{$type.$bound.$dir}{$router}; next unless defined $boundval; my $realval = ""; my $realthresh = ""; if ($boundval =~ s/%$//) { # defined in % of maxbytes # 2 decimals in % $realval = "% ($threshval)"; $realthresh = "% (".sprintf("%.1f",($rcfg->{"maxbytes".($dir eq 'i' ? 1 : 2)}{$router} * $boundval / 100)).")"; $threshval = sprintf "%.1f", ($threshval / $rcfg->{"maxbytes".($dir eq 'i' ? 1 : 2)}{$router} * 100); # the new code } my $msghead = ""; $msghead = "From: $cfg->{threshmailsender}\nTo: $rcfg->{${type}.'mailaddress'}{$router}" if $rcfg->{${type}.'mailaddress'}{$router} and $cfg->{threshmailsender}; my $pagetop = $rcfg->{pagetop}{$router} || ''; $pagetop =~ s|

.*?

||; $pagetop =~ s|\s*\s*(.*?)\s*(.*?)\s*\s*|$1 $2\n|g; $pagetop =~ s|\s*<.+?>\s*\n?||g; my $msgbody = <{title}{$router} Target: $router Type: $type Direction: $dir Bound: $bound Threshold: $boundval$realthresh Current: $threshval$realval $pagetop MESSAGE $msgbody .= "\n$rcfg->{$type.'desc'}{$router}\n" if $rcfg->{$type.'desc'}{$router}; if (($bound eq 'min' and $boundval > $threshval) or ($bound eq 'max' and $boundval < $threshval)) { # threshold was broken... my $message = <{$type.'prog'.$dir}{$router}, $router, $rcfg->{$type.$bound.$dir}{$router}, $threshval,($rcfg->{$type.'desc'}{$router} ||"No Description")); # Check if we use the status file or not... if ( defined $threshfile ) { if ( not -e $threshfile.".".$type.$bound.uc($dir) ) { # Create a file to indicate a threshold problem for the time after the problem open THRESHTOUCH, ">".$threshfile.".".$type.$bound.uc($dir) or warn "$NOW: WARNING: Creating $threshfile.".$bound.uc($dir).": $!\n"; close THRESHTOUCH; if (defined $rcfg->{$type.'prog'.$dir}{$router}){ debug('base',"run threshprog$dir: ".(join ",",@exec)); system @exec; } threshmail $cfg->{threshmailserver},$cfg->{threshmailsender},$rcfg->{$type.'mailaddress'}{$router},$message if $rcfg->{$type.'mailaddress'}{$router} } else { debug('base',"NOT acting on BROKEN threshold since $threshfile.$type$bound$dir exists"); } } elsif ( not defined $cfg->{$type.'hyst'} or ($bound eq 'min' and $boundval - $cfg->{$type.'hyst'}* $boundval < $threshval) or ($bound eq 'max' and $boundval + $cfg->{$type.'hyst'}* $boundval > $threshval) ) { # no threshold dir so run on every 'break' if (defined $rcfg->{$type.'prog'.$dir}{$router}){ debug('base',"run ${type}prog$dir: ".(join ",",@exec)); system @exec; } threshmail $cfg->{threshmailserver},$cfg->{threshmailsender},$rcfg->{$type.'mailaddress'}{$router},$message if $rcfg->{$type.'mailaddress'}{$router}; } } else { # no threshold broken ... my @exec = ( $rcfg->{$type.'progok'.$dir}{$router}, $router, $rcfg->{$type.$bound.$dir}{$router}, $threshval); my $message = <{$type.$bound.$dir}{$router} vs $threshval) Threshold UN-BROKEN ------------------- $msgbody MESSAGE # Check if we use the status file or not... if ( defined $threshfile ) { if ( -e $threshfile.".".$type.$bound.uc($dir) ){ unlink "$threshfile.".$type.$bound.uc($dir); if (defined $rcfg->{$type.'progok'.$dir}{$router}){ debug('base',"run ${type}progok$dir: ".(join ",",@exec)); system @exec; } threshmail $cfg->{threshmailserver},$cfg->{threshmailsender},$rcfg->{$type.'mailaddress'}{$router},$message if $rcfg->{$type.'mailaddress'}{$router}; } } } } # for my $bound ... } # for my $type } # for my $dir } sub getexternal ($) { my $command = shift; my $in=undef; my $out=undef; my $uptime="unknown"; my $name="unknown"; open (EXTERNAL , $command."|") or warn "$NOW: WARNING: Running '$command': $!\n"; warn "$NOW: WARNING: Could not get any data from external command ". "'".$command. "'\nMaybe the external command did not even start. ($!)\n\n" if eof EXTERNAL; chomp( $in=) unless eof EXTERNAL; chomp( $out=) unless eof EXTERNAL; chomp( $uptime=) unless eof EXTERNAL; chomp( $name=) unless eof EXTERNAL; close EXTERNAL; # strip returned date $uptime =~ s/^\s*(.*?)\s*/$1/; $name =~ s/^\s*(.*?)\s*/$1/; # do we have numbers in the external programs answer ? if ( not defined $in ) { warn "$NOW: WARNING: Problem with External get '$command':\n". " Expected a Number for 'in' but nothing'\n\n"; } elsif ( $in eq 'UNKNOWN' ) { $in = undef; } elsif ( $in !~ /([-+]?\d+(.\d+)?)/ ) { warn "$NOW: WARNING: Problem with External get '$command':\n". " Expected a Number for 'in' but got '$in'\n\n"; $in = undef; } else { $in = $1; } if ( not defined $out ) { warn "$NOW: WARNING: Problem with External get '$command':\n". " Expected a Number for 'out' but nothing'\n\n"; } elsif ( $out eq 'UNKNOWN' ) { $out = undef; } elsif ( $out !~ /([-+]?\d+(.\d+)?)/ ) { warn "$NOW: WARNING: Problem with External get '$command':\n". " Expected a Number for 'out' but got '$out'\n\n"; $out = undef; } else { $out = $1; } debug('snpo',"External result:".($in||"undef")." out:".($out||"undef")." uptime:".($uptime||"undef")." name:".($name||"undef")); return ($in,$out,time,$uptime,$name); } sub getsnmparg ($$$$){ my $confcache = shift; my $target = shift; my $cfg = shift; my $populated = shift; my $retry = 0; my $hostname = $$target{Host}; my $hostkey = "$$target{Community}\@$$target{Host}$$target{SnmpOpt}"; if ($$target{ipv4only}) { if (not ( $hostname =~ /^\d+\.\d+\.\d+\.\d+$/ or gethostbyname $hostname) ){ warn "$NOW: WARNING: Skipping host $hostname as it does not resolve to an IPv4 address\n"; return 'DEADHOST'; } } else { if($hostname =~ /^\[(.*)\]$/) { # Numeric IPv6 address. Check that it's valid $hostname = substr($hostname, 1); chop $hostname; if(! inet_pton(AF_INET6(), $hostname)) { warn "$NOW: WARNING: Skipping host $hostname: invalid IPv6 address\n"; return 'DEADHOST'; } } else { # Hostname. Look it up my @res; my ($too,$port,$otheropts) = split(':', $$target{SnmpOpt}, 3); $port = 161 unless defined $port; @res = getaddrinfo($hostname, $port, Socket::AF_UNSPEC(), Socket::SOCK_DGRAM()); if (scalar (@res) < 5) { warn "$NOW: WARNING: Skipping host $hostname as it does not resolve to an IPv4 or IPv6 address\n"; return 'DEADHOST'; } } } RETRY: my @ifnum = (); my @OID = (); # Find appropriate Interface to poll from for my $i (0..1) { if ($$target{IfSel}[$i] eq 'If') { $ifnum[$i] = ".".$$target{Key}[$i]; debug('snpo',"simple If: $ifnum[$i]"); } elsif($$target{IfSel}[$i] eq 'None') { $ifnum[$i] = ""; } else { $$target{Key}[$i] =~ s/\s+$//; # no trailing whitespace in keys ... if (not defined readfromcache($confcache,$hostkey,$$target{IfSel}[$i],$$target{Key}[$i])) { debug('snpo',"($i) Populate ConfCache for $$target{Host}$$target{SnmpOpt}"); populateconfcache($confcache,"$$target{Community}\@$$target{Host}$$target{SnmpOpt}",$$target{ipv4only},1,$$target{snmpoptions}); $$populated{$hostname} = 1; # set cache population to true for this cycle and host } if (not defined readfromcache($confcache,$hostkey,$$target{IfSel}[$i],$$target{Key}[$i])) { warn "$NOW: WARNING: Could not match host:'$$target{Community}\@$$target{Host}$$target{SnmpOpt}' ref:'$$target{IfSel}[$i]' key:'$$target{Key}[$i]'\n"; return 'NOMATCH'; } else { $ifnum[$i] = ".".readfromcache($confcache,$hostkey,$$target{IfSel}[$i],$$target{Key}[$i]); debug('snpo',"($i) Confcache Match $$target{Key}[$i] -> $ifnum[$i]"); } } if ($ifnum[$i] !~ /^$|^\.\d+$/) { warn "$NOW: WARNING: Can not determine". " ifNumber for $$target{Community}\@$$target{Host}$$target{SnmpOpt} \tref: '$$target{IfSel}[$i]' \tkey: '$$target{Key}[$i]'\n"; return 'NOMATCH'; } } for my $i (0..1) { # add ifget methods call for a cross check; for ($$target{IfSel}[$i]) { /^Eth$/ && do { push @OID, "ifPhysAddress".$ifnum[$i]; last }; /^Ip$/ && do { push @OID, "ipAdEntIfIndex".".".$$target{Key}[$i];last }; /^Descr$/ && do { push @OID, "ifDescr".$ifnum[$i]; last }; /^Type$/ && do { push @OID, "ifType".$ifnum[$i]; last }; /^Name$/ && do { push @OID, "ifName".$ifnum[$i]; last }; } push @OID ,$$target{OID}[$i].$ifnum[$i]; } # we also want to know uptime and system name unless we are if ( not defined $$cfg{nomib2} and $$cfg{logformat} ne 'rrdtool' ) { if ( $OID[0] !~ /^cache.+$/ and $OID[0] !~ /^\Q1.3.6.1.4.1.3495.1\E/ ) { push @OID, qw(sysUptime sysName); } else { push @OID, qw(cacheUptime cacheSoftware cacheVersionId) } } # pull that data debug('snpo',"SNMPGet from $$target{Community}\@$$target{Host}$$target{SnmpOpt} -- ".(join ",", @OID)); my @ret; # make sure we have no error messages hanging round. $SNMP_Session::errmsg = undef; $Net_SNMP_util::ErrorMessage = undef; my $targtemp = $$target{Community}.'@'.$$target{Host}.$$target{SnmpOpt}; $targtemp = v4onlyifnecessary($targtemp, $$target{ipv4only}); my @snmpoids = grep !/^(Pseudo|WaLK|GeTNEXT|CnTWaLK)|IndexPOS/, @OID; if (defined $$cfg{singlerequest}){ #LH local $BER::pretty_print_timeticks = 0; foreach my $oid (@snmpoids){ push @ret, snmpget($targtemp,$$target{snmpoptions},$oid); } } else { @ret = snmpget($targtemp,$$target{snmpoptions},@snmpoids); } my @newret; for (@OID) { /^PseudoZero$/ && do { push @newret, 0; next; }; /^PseudoOne$/ && do { push @newret, 1; next; }; s/^WaLK(\d*)// && do { my $idx = $1 || 0; my $oid=$_;push @newret, (split /:/, (snmpwalk($targtemp,$$target{snmpoptions},$oid))[$idx],2)[1]; debug('snpo',"snmpwalk '$oid' -> ".($newret[-1]||'UNDEF'));next}; s/^GeTNEXT// && do { my $oid=$_;push @newret, (split /:/, snmpgetnext($targtemp,$$target{snmpoptions},$oid),2)[1]; debug('snpo',"snmpgetnext '$oid' -> ".($newret[-1]||'UNDEF'));next}; s/^CnTWaLK// && do { my $oid=$_;my @insts= (snmpwalk($targtemp,$$target{snmpoptions},$_)); undef @insts if( $insts[1] || '') =~/no/i; push @newret, scalar @insts; debug('snpo',"snmpCountwalk '$oid' -> ".($newret[-1]||'UNDEF'));next}; /IndexPOS.*\.(\d*)/ && do { my $idx=$1; s/IndexPOS/$idx/; s/\.\d*$//; push @newret, snmpget($targtemp,$$target{snmpoptions},$_); debug('snpo', "snmpget of oid '$_' after replacement of IndexPOS"); next}; push @newret, shift @ret; } @ret = @newret; debug('snpo',"SNMPfound -- ".(join ", ", map {"'".($_||"undef")."'"} @ret)); $ret[-2] = $ret[-2].' '.$ret[-1] if $OID[-1] and $OID[-1] eq 'cacheVersionId'; my $time = time; my @final; # lets do some reality check for my $i (0..1) { # some ifget methods call for a cross check; for ($$target{IfSel}[$i]) { /^Eth$/ && do { my $bin = shift @ret || 0xff; my $eth = unpack 'H*', $bin; my @eth; while ($eth =~ s/^..//){ push @eth, $&; } my $phys=join '-', @eth; if ($phys ne $$target{Key}[$i]) { debug('snpo', "($i) eth if crosscheck got $phys expected $$target{Key}[$i]"); if (not $retry) { $retry=1; # remove broken entry storeincache($confcache,$hostkey,$$target{IfSel}[$i],$$target{Key}[$i],undef); debug('repo',"($i) goto RETRY force if cache repopulation"); goto RETRY; } else { warn "$NOW: WARNING: could not match&get". " $$target{Host}$$target{SnmpOpt}/$$target{OID}[$i] for Eth $$target{Key}[$i]\n"; return 'NOMATCH'; } }; debug ('snpo',"($i) Eth crosscheck OK"); }; /^Ip$/ && do { my $if = shift @ret || 'none'; if ($ifnum[$i] ne '.'.$if) { debug('repo', "($i) IP if crosscheck got .$if expected $ifnum[$i]"); if (not $retry) { $retry=1; # remove broken entry storeincache($confcache,$hostkey,$$target{IfSel}[$i],$$target{Key}[$i],undef); debug('repo',"($i) goto RETRY force if cache repopulation"); goto RETRY; } else { warn "$NOW: WARNING: could not match&get". " $$target{Host}$$target{SnmpOpt}/$$target{OID}[$i] for IP $$target{Key}[$i]\n"; return 'NOMATCH'; } } debug ('snpo',"($i) IP crosscheck OK"); }; /^(Descr|Name|Type)$/ && do { my $descr = shift @ret || 'Empty'; $descr =~ s/[\0- ]+$//; # remove excess spaces and stuff if ($descr ne $$target{Key}[$i]) { debug('repo', "($i) $_ if crosscheck got $descr expected $$target{Key}[$i]"); if (not $retry) { $retry=1; # remove broken entry storeincache($confcache,$hostkey,$$target{IfSel}[$i],$$target{Key}[$i],undef); debug('repo',"($i) goto RETRY force if cache repopulation"); goto RETRY; } else { warn "$NOW: WARNING: could not match&get". " $$target{Host}$$target{SnmpOpt}/$$target{OID}[$i] for $_ '$$target{Key}[$i]'\n"; return 'NOMATCH'; } } debug ('snpo',"($i) $_ crosscheck OK"); }; } # no sense continuing here ... if there is no data ... if (defined $SNMP_Session::errmsg and $SNMP_Session::errmsg =~ /no response received/){ $SNMP_Session::errmsg = undef; warn "$NOW: WARNING: skipping because at least the query for $OID[0] on $$target{Host} did not succeed\n"; return 'DEADHOST'; } if (defined $Net_SNMP_util::ErrorMessage and $Net_SNMP_util::ErrorMessage =~ /No response from remote/){ $Net_SNMP_util::ErrorMessage = undef; warn "$NOW: WARNING: skipping because at least the query for $OID[0] on $$target{Host} did not succeed\n"; return 'DEADHOST'; } if ($$target{OID}[$i] =~ /if(Admin|Oper)Hack/) { push @final, ((shift @ret) == 1) ? 1:0; } else { push @final, shift @ret; } } my @res = ( @final,$time, @ret); # Convert in and out values to integers with a user-defined subroutine # specified by the Conversion target key if( $target->{ Conversion } ) { foreach my $ri( 0..1 ) { next unless defined $res[ $ri ]; local $SIG{__DIE__}; my $exp = "&MRTGConversion::$target->{ Conversion }( \$res[\$ri] )"; $res[ $ri ] = eval $exp; warn "$NOW: WARNING: evaluation of \"$exp\" failed\n$@\n" if $@; } } # have some cleanup first, it seems that some agents # are adding newlines to what they return map{ $_ =~ s/\n|\r//g if defined $_ } @res; map{ $_ =~ s/^\s+//g if defined $_ } @res; map{ $_ =~ s/\s+$//g if defined $_ } @res; # in and out should be numbers only for my $ri (0..1){ # for folks using rrdtool I am allowing numbers # with decimals here if ( defined $res[$ri] and $res[$ri] !~ /^[-+]?\d+(.\d+)?$/ ) { warn "$NOW: WARNING: Expected a number but got '$res[$ri]'\n"; $res[$ri] = undef; } } return @res; } # read target function ... sub readtargets ($$$) { my ($confcache,$target,$cfg) = @_; my $forks = $$cfg{forks}; my $trgnum = $#{$target}+1; if (defined $forks and $forks > 1 and $trgnum > 1){ $forks = $trgnum if $forks > $trgnum; my $split = int($trgnum / $forks) + 1; my @hand; # get them forks to work ... for (my $i = 0; $i < $forks;$i++) { local *D; my $sleep_count=0; my $pid; do { $pid = open(D, "-|"); unless (defined $pid) { warn "$NOW: WARNING cannot fork: $!\n"; die "$NOW: ERROR bailing out after 6 failed forkattempts" if $sleep_count++ > 6; sleep 10; } } until defined $pid; if ($pid) { # parent $hand[$i] = *D; # funky file handle magic ... debug ('fork',"Parent $$ after fork of child $i"); } else { # child debug ('fork',"Child $i ($$) after fork"); my $res = ""; my %deadhost; my %populated; for (my $ii = $i * $split; $ii < ($i+1) * $split and $ii < $trgnum; $ii++){ my $targ = $$target[$ii]; my @res; if ($$targ{Methode} eq 'EXEC') { @res = getexternal($$targ{Command}); } else { # parent if (not $deadhost{$$targ{Community}.$$targ{Host}}) { @res = getsnmparg($confcache,$targ,$cfg,\%populated); if ( $res[0] and $res[0] eq 'DEADHOST') { # guess we got a blank here @res = ( undef,undef,time,undef,undef); $deadhost{$$targ{Community}.$$targ{Host}} = 1; warn "$NOW: WARNING: no data for $$targ{OID}[0]&$$targ{OID}[1]:$$targ{Community}\@$$targ{Host}. Skipping further queries for Host $$targ{Host} in this round.\n" } elsif ($res[0] and $res[0] eq 'NOMATCH'){ @res = (undef,undef,time,undef,undef); } } else { @res = ( undef,undef,time,undef,undef); } } for (my $iii=0;$iii<5;$iii++){ if (defined $res[$iii]){ $res .= "$res[$iii]\n"; } else { $res .= "##UNDEF##\n"; } } } debug ('fork',"Child $i ($$) waiting to deliver"); print $res; # we only talk after the work has been done to # otherwhise we might get blocked # return updated hosts from confcache writeconfcache($confcache,'&STDOUT') if defined $$confcache{___updated}; exit 0; } } # happy reaping ... my $vin =''; # vector of pipe file-descriptors from children for (my $i = 0; $i < $forks;$i++) { vec($vin, fileno($hand[$i]), 1) = 1; } my $left = $forks; while ($left) { my $rout = $vin; # read vector my $eout = $vin; # exception vector my $nfound = select($rout, undef, $eout, undef); # no timeout if (1 > $nfound) { die sprintf("$NOW: ERROR: select returned %d: $!\n", $nfound); } for (my $i = 0; $i < $forks; $i++) { next unless defined $hand[$i] and defined fileno($hand[$i]); # this does not seem to work reliably # if (vec($eout, fileno($hand[$i]), 1)) { # die "$NOW: ERROR: fork $i has died ahead of time?\n"; # } next unless vec($rout, fileno($hand[$i]), 1); vec($vin, fileno($hand[$i]), 1) = 0; # remove this child fd debug ('fork',"Parent reading child $i"); my $h = $hand[$i]; for (my $ii = $i * $split; $ii < ($i+1) * $split and $ii < $trgnum; $ii++){ my $targ = $$target[$ii]; my @res; for (0..4){ my $line = <$h>; # must be a simple scalar here else it wont work die "$NOW: ERROR: fork $i has died ahead of time ...\n" if not defined $line; chomp $line; # debug ('fork',"reading for $ii $line"); $line = undef if $line eq "##UNDEF##"; push @res,$line; }; ($$targ{_IN_}, $$targ{_OUT_}, $$targ{_TIME_}, $$targ{_UPTIME_}, $$targ{_NAME_}) = @res; if ($] >= 5.0061){ $$targ{_IN_} = Math::BigFloat->new($$targ{_IN_}) if $$targ{_IN_}; $$targ{_OUT_} = Math::BigFloat->new($$targ{_OUT_}) if $$targ{_OUT_}; } } # feed confcache entries my $lasthost =""; while (<$h>){ chomp; my ($host,$method,$key,$value) = split (/\t/, $_); if ($host ne $lasthost){ debug ('fork',"start clearing confcache on first entry for target $host"); clearfromcache($confcache,$host); debug ('fork',"finished clearing confcache"); } $lasthost = $host; storeincache($confcache,$host,$method,$key,$value); } close $h; --$left; } } } else { my %deadhost; my %populated; foreach my $targ (@$target) { if ($$targ{Methode} eq 'EXEC') { debug('snpo', "run external $$targ{Command}"); ($$targ{_IN_}, $$targ{_OUT_}, $$targ{_TIME_}, $$targ{_UPTIME_}, $$targ{_NAME_}) = getexternal($$targ{Command}); } elsif ($$targ{Methode} eq 'SNMP' and not $deadhost{$$targ{Host}}) { debug('snpo', "run snmpget from $$targ{OID}[0]&$$targ{OID}[1]:$$targ{Community}\@$$targ{Host}"); ($$targ{_IN_}, $$targ{_OUT_}, $$targ{_TIME_}, $$targ{_UPTIME_}, $$targ{_NAME_}) = getsnmparg($confcache,$targ,$cfg,\%populated); if ( $$targ{_IN_} and $$targ{_IN_} eq 'DEADHOST') { $$targ{_IN_} = undef; $$targ{_TIME_} =time; # guess we got a blank here $deadhost{$$targ{Host}} = 1; warn "$NOW: WARNING: no data for $$targ{OID}[0]&$$targ{OID}[1]:$$targ{Community}\@$$targ{Host}. Skipping further queries for Host $$targ{Host} in this round.\n" } if ( $$targ{_IN_} and $$targ{_IN_} eq 'NOMATCH') { $$targ{_IN_} = undef; $$targ{_TIME_} =time; } } else { $$targ{_IN_} = undef; $$targ{_OUT_} = undef; $$targ{_TIME_} = time; $$targ{_UPTIME_} = undef; $$targ{_NAME_} = undef; } if ($] >= 5.008 ){ $$targ{_IN_} = new Math::BigFloat "$$targ{_IN_}" if $$targ{_IN_}; $$targ{_OUT_} = new Math::BigFloat "$$targ{_OUT_}" if $$targ{_OUT_}; } } } } sub imggen ($) { my $dir = shift; if ( ! -r "$dir${main::SL}mrtg-l.png" and open W, ">$dir${main::SL}mrtg-l.png" ){ binmode W; print W unpack ('u', <<'UUENC'); MB5!.1PT*&@H -24A$4@ #\ 9! , !TA.O' &%!,5$5]9GTT M79A?8HB(9WFR;6G_=DWM=%35<5R_M[A2 6)+1T0'%F&(ZP 1%)1$%4 M>-JMDKUOPD ,Q:E4]CH?S0PMG8-.$6L1A*YMJ,DQ%5?[_ON>$Y (2$R>= MY;-^OF=;GNCM\SFY#_#GW$IU0WMP/#O5HSGNW8"9R)/92$NQ\Z:GUDG/@.@! M)CP#4H\ >LT>)NB!A0]8,"]&0.(#WY92V<\$=FM4WHV? J M=$58=%-I9VYA='5R90!D,C(W8S$dir${main::SL}mrtg-m.png" ){ binmode W; print W unpack ('u', <<'UUENC'); MB5!.1PT*&@H -24A$4@ !D 9! , VQYA0 &%!,5$5]9GTT M79A588QN9(*7:73_=DWL=%31-IC"$4"!0P$>"E&2B:I,%Z((!"(I$)X88H@GJ :A)<$Y@@*I8)YAA">("N( M%PYD"#L+"IJ#Y4!FN(86N4',# )J"4TO*R\O!_$"@::'@HTEQ /K _&$0+P M(.T:6@A2@62?H#B*6TRQN#,C9\ "IT15AT4VEG;F%T M=7)E #1E,S8X-S$P,38Q-S)A96%B.3,Y8SEA,F5D-31B86(U@DWZ,@ ET M15AT1&5L87D ,C4P(RC.$P YT15AT4&%G90 R-7@R-2LP*S"#D2 ? ) $E%3D2N0F"" UUENC close W; } if ( ! -r "$dir${main::SL}mrtg-r.png" and open W, ">$dir${main::SL}mrtg-r.png" ){ binmode W; print W unpack ('u', <<'UUENC'); MB5!.1PT*&@H -24A$4@ 80 9! , ##'$3) &%!,5$4T79@\ M8YQ5=JAPC;>:K\S\_?[5WNFZR-PB%CO! 6)+1T0'%F&(ZP !=5)1$%4 M>-KM6$ESVE@0;BW 58: K_)"YDH(.%=YL/"511)7O""N3AS!WY_^NM^3Q)+, M4C55DZJ1*2&]U]O7Z\,4T"]__0_A;US.O\7$$#H*PR=R[_'@#? A9X3KLW,K MNRX_*L=MGK^#PQ)[$USW+J@'U)E,!JIGS9"+RG0^B!(NDM,ZMB'G,M_?6 MF@^[_#7D[U)*!V_N!#+4$)>M@+Z(.J/1)PNAI4]=5K# 0_,)'Z(4UXH*A<#/ M2SQ\3+?[=!F4Q&M?Z!8@2-?4X+O*L^Q\$PPQ;MA.R= 65RRWR/:[U&#PTVR_ MR4*JI#3?9#E-$U)#W)5*GE&3[Y&!T%P+?QR2)U;UUOB(0@A0"-Z*.AOVC)=^ MY=L&-T/L"$G !,KBW"V-3PU[.\8W@5N7J)W(?L'&WB5LP6_*X10OP+2L21G/ MH7OA=#:1&M)F-1FI\^A+8B&H %;A+\U>LP8A)HN^RZOC9^BZY#=#_&10NA8" M.5E !^R7H/2R=0G!6PH%1\%-!W@<"GU+PN4Q.Z2D6-K!2-;D]-=J"-2H?&C> M7"B$ABCW."HV-PX@%"6$YHS<3:@.K!$K2;N"4-0A\)X'.R[?%R4$MXQ"TT9, M7*Y:IP)!8N0L=Z0IVUJH(9!51H%B1)9A]$%,S3QB[_P0 EA;B\ W*KM/%?%Q M%*@8'$*0K?Y@54'0*+ !XZ@&P;C'2N$W?SU&\BX"Z"YKH08ATBB,^WCHW[U5 MCK6U$!U'H3$WA9<<1\%+2I8R"H:]@ZT=Q8%9LK1%Z!1AA< XH902XAM@X#<; MA?;J) HL-F[!KJ*U%KC:DDD M_NQ\.9M$RD9?TE!AX\HJ8E,+IJE^'Q6+.H1X\K#A;V\FI.B6F=)&B$+E>'9T M51>-EPD:$VVE;#C>'CJ2:=.FJ?9>1_'20-CQ'_ESAN"5Y?Q4LT'=SFS?^.7* MYFU%;!(IFTP>!K!Q%=8AL.)7D@8/AL;K:#3A#LW#*>0H> <0(-"]YF!:*>X2 MUG&GD;D08Z0] ,((4XWG0O;)0-@2UTPW8@V^G0NG46BO^FNB,@I.7A$?EO.W MK+1)V<4R&H<$E]MR-K7@GD!HB;DL!4G%N>VP;?YJCPE?\''#<:4C!?S7?-IH MXG%'2N"B.&2Y/^M(*ZE!6PM.]L..5#4997R@5W:5"SWE* JV([U5 M*6W8H>EBM=_O>9B8CF2C0)M:.1L)@-*(!$_\^+C?S8TF.FJJO;6?& AP20*A MB6DR[*FS':G[7)5<_,&2F1-N>:+LBJ2^+#Z1Q1?WV02(3PR2/'*IX M=,_1!P+ %2,A]5Q'TBSR49QN_$P5\?$9Z>2 P=;DXN8B..I(+ 2/'76SBU,P MC9=6BD28R\^O)=+1&2E2"#/C%CX7M++)J&#SFMP*GD^F,_SCC+.'42'H+;&) M0LH]YTU8>HM#"!3_GI@4.:R%*_3\U\EC:M+I8_I]-,T&9*3H0:4U/RYG:-+9 M):7)9D,JX$_9*=,TW>)74"X0F@ Y50B83W?\'H!$"]80*XF;"P2P>%NUJ&2_ M?-51V7N3)7)?E!]B_$V:OMMJ^,+CZMYPMK??9;'SXBG"J;4C%PBPVX5^T]1" M6U-M/;K_[#>U>Q4<$?_I=?&SS>NP_(5\X=Z<FT="M4^ 0W1%6'13;V9T=V%R90! *",I26UA9V5-86=I8VL@ M-"XR+CD@.3DO,#DO,#$@8W)IC9 M\ "IT15AT4VEG;F%T=7)E #$R,3 '(?:description|port name):\s*\s*([^<\s]+[^<]*?)\s* 'td>\s*([^<\s]+COLO[^<]*?)\s* 0, 'range' => "previous", 'units' => "MB" ); sub walklog ($$$$$); sub sumlog($$$); sub mailout($$); sub main() { # parse options GetOptions(\%opt, 'min=i','help|h', 'catch=s', 'email=s','version','range=s','units=s','man') or exit(1); if($opt{help}) { pod2usage(1) } if($opt{man}) { pod2usage(-exitstatus => 0, -verbose => 2) } if($opt{version}) { print "mrtg-traffic-sum $Revision\n"; exit(0) } my $cfgfile = shift @ARGV; pod2usage(1) unless $cfgfile and -r $cfgfile; my %rcfg; my %cfg; my @routers; my @target; my $report = "Subject: Traffic total for '$cfgfile' ($Revision) "; readcfg($cfgfile,\@routers,\%cfg,\%rcfg); cfgcheck(\@routers, \%cfg, \%rcfg, \@target); walklog \@routers, \%cfg, \%rcfg,\$report,\%opt; if ($opt{email}) { mailout \$report,$opt{email}; } else { print $report; } } main; sub walklog ($$$$$){ my $routers = shift; my $cfg = shift; my $rcfg = shift; my $report = shift; my $opt = shift; my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = localtime(time); my $start = mktime(0, 0, 0, 1, $mon-1, $year, 0, 0, 0); my $end = mktime(0, 0, 0, 1, $mon, $year, 0, 0, 0)-1; if ($opt{range} eq "previous") { $start = mktime(0, 0, 0, 1, $mon-1, $year, 0, 0, 0); $end = mktime(0, 0, 0, 1, $mon, $year, 0, 0, 0)-1; } if ($opt{range} eq "current") { $start = mktime(0, 0, 0, 1, $mon, $year, 0, 0, 0); $end = mktime(0, 0, 0, 1, $mon+1, $year, 0, 0, 0)-1; } my($m,$y) = (localtime($start))[4,5]; $y += 1900; $m ++; $$report .= sprintf "%04d/%02d\n\n", $y,$m; $$report .= "Start: ".localtime($start)."\n"; $$report .= "End: ".localtime($end)."\n"; if ($opt{'units'} eq "GB") { $$report .= sprintf "%-40s %15s\n","Interface","In+Out in GB"; } else { $$report .= sprintf "%-40s %15s\n","Interface","In+Out in MB"; } $$report .= ("-" x 78)."\n"; foreach my $r (@$routers) { my $label; if ($rcfg->{pagetop}{$r} =~ /$opt{catch}/i ) { $label = $1; $label .= " $2" if $2; my ($in,$out) = sumlog $cfg->{logdir}.$rcfg->{directory}{$r}."$r.log",$start,$end; my $sum = ($in+$out)/(10**6); if ($opt{'units'} eq "GB") { $sum = ($in+$out)/(10**9); } else { $sum = ($in+$out)/(10**6); } next if $sum < $opt{'min'}; $$report .= sprintf "%-40s %15.0f\n",$label,$sum; } } } sub sumlog ($$$) { my $log = shift; my $start = shift; my $end = shift; my $in = 0.0; my $out = 0.0; if (open L, "<",$log){ my @this=($end+1,0,0); my @prev; while () { chomp; @prev = @this; @this = (split /\s+/)[0,1,2]; if ($prev[0] <= $end) { my $diff = $prev[0] - $this[0]; $in += $diff * $prev[1]; $out += $diff * $prev[2]; } last if $this[0] <= $start; } close L; } else { warn "WARN Skipping $log\n"; } return $in,$out; } sub mailout ($$) { my $data = shift; my $rec = shift; open S, "|-" or exec $sendmail,'-f',$rec,$rec; print S < [I...] B --man show man-page and exit -h, --help display this help and exit --version output version information and exit --catch=regexp filter out things that match this in PageTop --email=address email the result --min=gigabytes minimal number of gigabites required for report --range= Specify "current" for month-to-date, "previous" for last complete month --units=[GB|MB] Display results in gigabytes (default is MB) =head1 DESCRIPTION The mrtg-traffic-sum goes through the mrtg logs for the targets in the the config file specified and builds the traffic total for the last month in Giga Bytes. (Note in communications Giga is 10^9). The result of this analysis can be sent via email to an address of your choice using the B<--email> option. With the B<--catch> option you can specify a regular expression which will be matched against the contents of the PageTop settings. The regular expression should return a value into $1 and possibly into $2. This will then be used as description for the appropriate traffic sum. By default the catch is set to: (?:description|port name):\s*\s*([^< ]*?[^<]*?)\s* switch to change this number. =head1 COPYRIGHT Copyright (c) 2002 by Tobias Oetiker. All rights reserved. =head1 LICENSE 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 of the License, 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., 675 Mass Ave, Cambridge, MA 02139, USA. =head1 AUTHOR Tobias Oetiker Etobi@oetiker.chE, Keith Dunnett Ekeith@dunnett.nameE =head1 HISTORY 2002-07-13 to Initial Version 2009-12-38 kd New features =cut # Emacs Configuration # # Local Variables: # mode: cperl # eval: (cperl-set-style "PerlStyle") # mode: flyspell # mode: flyspell-prog # End: # # vi: sw=4 et mrtg-2.17.10/lib/mrtg2/Pod/InputObjects.pm0000644000175300017510000006520113057016062017144 0ustar oetikeroep############################################################################# # Pod/InputObjects.pm -- package which defines objects for input streams # and paragraphs and commands when parsing POD docs. # # Copyright (C) 1996-2000 by Bradford Appleton. All rights reserved. # This file is part of "PodParser". PodParser is free software; # you can redistribute it and/or modify it under the same terms # as Perl itself. ############################################################################# package Pod::InputObjects; use strict; use vars qw($VERSION); $VERSION = '1.31'; ## Current version of this package require 5.005; ## requires this Perl version or later ############################################################################# =head1 NAME Pod::InputObjects - objects representing POD input paragraphs, commands, etc. =head1 SYNOPSIS use Pod::InputObjects; =head1 REQUIRES perl5.004, Carp =head1 EXPORTS Nothing. =head1 DESCRIPTION This module defines some basic input objects used by B when reading and parsing POD text from an input source. The following objects are defined: =over 4 =begin __PRIVATE__ =item package B An object corresponding to a source of POD input text. It is mostly a wrapper around a filehandle or C-type object (or anything that implements the C method) which keeps track of some additional information relevant to the parsing of PODs. =end __PRIVATE__ =item package B An object corresponding to a paragraph of POD input text. It may be a plain paragraph, a verbatim paragraph, or a command paragraph (see L). =item package B An object corresponding to an interior sequence command from the POD input text (see L). =item package B An object corresponding to a tree of parsed POD text. Each "node" in a parse-tree (or I) is either a text-string or a reference to a B object. The nodes appear in the parse-tree in the order in which they were parsed from left-to-right. =back Each of these input objects are described in further detail in the sections which follow. =cut ############################################################################# package Pod::InputSource; ##--------------------------------------------------------------------------- =begin __PRIVATE__ =head1 B This object corresponds to an input source or stream of POD documentation. When parsing PODs, it is necessary to associate and store certain context information with each input source. All of this information is kept together with the stream itself in one of these C objects. Each such object is merely a wrapper around an C object of some kind (or at least something that implements the C method). They have the following methods/attributes: =end __PRIVATE__ =cut ##--------------------------------------------------------------------------- =begin __PRIVATE__ =head2 B my $pod_input1 = Pod::InputSource->new(-handle => $filehandle); my $pod_input2 = new Pod::InputSource(-handle => $filehandle, -name => $name); my $pod_input3 = new Pod::InputSource(-handle => \*STDIN); my $pod_input4 = Pod::InputSource->new(-handle => \*STDIN, -name => "(STDIN)"); This is a class method that constructs a C object and returns a reference to the new input source object. It takes one or more keyword arguments in the form of a hash. The keyword C<-handle> is required and designates the corresponding input handle. The keyword C<-name> is optional and specifies the name associated with the input handle (typically a file name). =end __PRIVATE__ =cut sub new { ## Determine if we were called via an object-ref or a classname my $this = shift; my $class = ref($this) || $this; ## Any remaining arguments are treated as initial values for the ## hash that is used to represent this object. Note that we default ## certain values by specifying them *before* the arguments passed. ## If they are in the argument list, they will override the defaults. my $self = { -name => '(unknown)', -handle => undef, -was_cutting => 0, @_ }; ## Bless ourselves into the desired class and perform any initialization bless $self, $class; return $self; } ##--------------------------------------------------------------------------- =begin __PRIVATE__ =head2 B my $filename = $pod_input->name(); $pod_input->name($new_filename_to_use); This method gets/sets the name of the input source (usually a filename). If no argument is given, it returns a string containing the name of the input source; otherwise it sets the name of the input source to the contents of the given argument. =end __PRIVATE__ =cut sub name { (@_ > 1) and $_[0]->{'-name'} = $_[1]; return $_[0]->{'-name'}; } ## allow 'filename' as an alias for 'name' *filename = \&name; ##--------------------------------------------------------------------------- =begin __PRIVATE__ =head2 B my $handle = $pod_input->handle(); Returns a reference to the handle object from which input is read (the one used to contructed this input source object). =end __PRIVATE__ =cut sub handle { return $_[0]->{'-handle'}; } ##--------------------------------------------------------------------------- =begin __PRIVATE__ =head2 B print "Yes.\n" if ($pod_input->was_cutting()); The value of the C state (that the B method would have returned) immediately before any input was read from this input stream. After all input from this stream has been read, the C state is restored to this value. =end __PRIVATE__ =cut sub was_cutting { (@_ > 1) and $_[0]->{-was_cutting} = $_[1]; return $_[0]->{-was_cutting}; } ##--------------------------------------------------------------------------- ############################################################################# package Pod::Paragraph; ##--------------------------------------------------------------------------- =head1 B An object representing a paragraph of POD input text. It has the following methods/attributes: =cut ##--------------------------------------------------------------------------- =head2 Pod::Paragraph-EB my $pod_para1 = Pod::Paragraph->new(-text => $text); my $pod_para2 = Pod::Paragraph->new(-name => $cmd, -text => $text); my $pod_para3 = new Pod::Paragraph(-text => $text); my $pod_para4 = new Pod::Paragraph(-name => $cmd, -text => $text); my $pod_para5 = Pod::Paragraph->new(-name => $cmd, -text => $text, -file => $filename, -line => $line_number); This is a class method that constructs a C object and returns a reference to the new paragraph object. It may be given one or two keyword arguments. The C<-text> keyword indicates the corresponding text of the POD paragraph. The C<-name> keyword indicates the name of the corresponding POD command, such as C or C (it should I contain the C<=> prefix); this is needed only if the POD paragraph corresponds to a command paragraph. The C<-file> and C<-line> keywords indicate the filename and line number corresponding to the beginning of the paragraph =cut sub new { ## Determine if we were called via an object-ref or a classname my $this = shift; my $class = ref($this) || $this; ## Any remaining arguments are treated as initial values for the ## hash that is used to represent this object. Note that we default ## certain values by specifying them *before* the arguments passed. ## If they are in the argument list, they will override the defaults. my $self = { -name => undef, -text => (@_ == 1) ? shift : undef, -file => '', -line => 0, -prefix => '=', -separator => ' ', -ptree => [], @_ }; ## Bless ourselves into the desired class and perform any initialization bless $self, $class; return $self; } ##--------------------------------------------------------------------------- =head2 $pod_para-EB my $para_cmd = $pod_para->cmd_name(); If this paragraph is a command paragraph, then this method will return the name of the command (I any leading C<=> prefix). =cut sub cmd_name { (@_ > 1) and $_[0]->{'-name'} = $_[1]; return $_[0]->{'-name'}; } ## let name() be an alias for cmd_name() *name = \&cmd_name; ##--------------------------------------------------------------------------- =head2 $pod_para-EB my $para_text = $pod_para->text(); This method will return the corresponding text of the paragraph. =cut sub text { (@_ > 1) and $_[0]->{'-text'} = $_[1]; return $_[0]->{'-text'}; } ##--------------------------------------------------------------------------- =head2 $pod_para-EB my $raw_pod_para = $pod_para->raw_text(); This method will return the I text of the POD paragraph, exactly as it appeared in the input. =cut sub raw_text { return $_[0]->{'-text'} unless (defined $_[0]->{'-name'}); return $_[0]->{'-prefix'} . $_[0]->{'-name'} . $_[0]->{'-separator'} . $_[0]->{'-text'}; } ##--------------------------------------------------------------------------- =head2 $pod_para-EB my $prefix = $pod_para->cmd_prefix(); If this paragraph is a command paragraph, then this method will return the prefix used to denote the command (which should be the string "=" or "=="). =cut sub cmd_prefix { return $_[0]->{'-prefix'}; } ##--------------------------------------------------------------------------- =head2 $pod_para-EB my $separator = $pod_para->cmd_separator(); If this paragraph is a command paragraph, then this method will return the text used to separate the command name from the rest of the paragraph (if any). =cut sub cmd_separator { return $_[0]->{'-separator'}; } ##--------------------------------------------------------------------------- =head2 $pod_para-EB my $ptree = $pod_parser->parse_text( $pod_para->text() ); $pod_para->parse_tree( $ptree ); $ptree = $pod_para->parse_tree(); This method will get/set the corresponding parse-tree of the paragraph's text. =cut sub parse_tree { (@_ > 1) and $_[0]->{'-ptree'} = $_[1]; return $_[0]->{'-ptree'}; } ## let ptree() be an alias for parse_tree() *ptree = \&parse_tree; ##--------------------------------------------------------------------------- =head2 $pod_para-EB my ($filename, $line_number) = $pod_para->file_line(); my $position = $pod_para->file_line(); Returns the current filename and line number for the paragraph object. If called in a list context, it returns a list of two elements: first the filename, then the line number. If called in a scalar context, it returns a string containing the filename, followed by a colon (':'), followed by the line number. =cut sub file_line { my @loc = ($_[0]->{'-file'} || '', $_[0]->{'-line'} || 0); return (wantarray) ? @loc : join(':', @loc); } ##--------------------------------------------------------------------------- ############################################################################# package Pod::InteriorSequence; ##--------------------------------------------------------------------------- =head1 B An object representing a POD interior sequence command. It has the following methods/attributes: =cut ##--------------------------------------------------------------------------- =head2 Pod::InteriorSequence-EB my $pod_seq1 = Pod::InteriorSequence->new(-name => $cmd -ldelim => $delimiter); my $pod_seq2 = new Pod::InteriorSequence(-name => $cmd, -ldelim => $delimiter); my $pod_seq3 = new Pod::InteriorSequence(-name => $cmd, -ldelim => $delimiter, -file => $filename, -line => $line_number); my $pod_seq4 = new Pod::InteriorSequence(-name => $cmd, $ptree); my $pod_seq5 = new Pod::InteriorSequence($cmd, $ptree); This is a class method that constructs a C object and returns a reference to the new interior sequence object. It should be given two keyword arguments. The C<-ldelim> keyword indicates the corresponding left-delimiter of the interior sequence (e.g. 'E'). The C<-name> keyword indicates the name of the corresponding interior sequence command, such as C or C or C. The C<-file> and C<-line> keywords indicate the filename and line number corresponding to the beginning of the interior sequence. If the C<$ptree> argument is given, it must be the last argument, and it must be either string, or else an array-ref suitable for passing to B (or it may be a reference to a Pod::ParseTree object). =cut sub new { ## Determine if we were called via an object-ref or a classname my $this = shift; my $class = ref($this) || $this; ## See if first argument has no keyword if (((@_ <= 2) or (@_ % 2)) and $_[0] !~ /^-\w/) { ## Yup - need an implicit '-name' before first parameter unshift @_, '-name'; } ## See if odd number of args if ((@_ % 2) != 0) { ## Yup - need an implicit '-ptree' before the last parameter splice @_, $#_, 0, '-ptree'; } ## Any remaining arguments are treated as initial values for the ## hash that is used to represent this object. Note that we default ## certain values by specifying them *before* the arguments passed. ## If they are in the argument list, they will override the defaults. my $self = { -name => (@_ == 1) ? $_[0] : undef, -file => '', -line => 0, -ldelim => '<', -rdelim => '>', @_ }; ## Initialize contents if they havent been already my $ptree = $self->{'-ptree'} || new Pod::ParseTree(); if ( ref $ptree =~ /^(ARRAY)?$/ ) { ## We have an array-ref, or a normal scalar. Pass it as an ## an argument to the ptree-constructor $ptree = new Pod::ParseTree($1 ? [$ptree] : $ptree); } $self->{'-ptree'} = $ptree; ## Bless ourselves into the desired class and perform any initialization bless $self, $class; return $self; } ##--------------------------------------------------------------------------- =head2 $pod_seq-EB my $seq_cmd = $pod_seq->cmd_name(); The name of the interior sequence command. =cut sub cmd_name { (@_ > 1) and $_[0]->{'-name'} = $_[1]; return $_[0]->{'-name'}; } ## let name() be an alias for cmd_name() *name = \&cmd_name; ##--------------------------------------------------------------------------- ## Private subroutine to set the parent pointer of all the given ## children that are interior-sequences to be $self sub _set_child2parent_links { my ($self, @children) = @_; ## Make sure any sequences know who their parent is for (@children) { next unless (length and ref and ref ne 'SCALAR'); if (UNIVERSAL::isa($_, 'Pod::InteriorSequence') or UNIVERSAL::can($_, 'nested')) { $_->nested($self); } } } ## Private subroutine to unset child->parent links sub _unset_child2parent_links { my $self = shift; $self->{'-parent_sequence'} = undef; my $ptree = $self->{'-ptree'}; for (@$ptree) { next unless (length and ref and ref ne 'SCALAR'); $_->_unset_child2parent_links() if UNIVERSAL::isa($_, 'Pod::InteriorSequence'); } } ##--------------------------------------------------------------------------- =head2 $pod_seq-EB $pod_seq->prepend($text); $pod_seq1->prepend($pod_seq2); Prepends the given string or parse-tree or sequence object to the parse-tree of this interior sequence. =cut sub prepend { my $self = shift; $self->{'-ptree'}->prepend(@_); _set_child2parent_links($self, @_); return $self; } ##--------------------------------------------------------------------------- =head2 $pod_seq-EB $pod_seq->append($text); $pod_seq1->append($pod_seq2); Appends the given string or parse-tree or sequence object to the parse-tree of this interior sequence. =cut sub append { my $self = shift; $self->{'-ptree'}->append(@_); _set_child2parent_links($self, @_); return $self; } ##--------------------------------------------------------------------------- =head2 $pod_seq-EB $outer_seq = $pod_seq->nested || print "not nested"; If this interior sequence is nested inside of another interior sequence, then the outer/parent sequence that contains it is returned. Otherwise C is returned. =cut sub nested { my $self = shift; (@_ == 1) and $self->{'-parent_sequence'} = shift; return $self->{'-parent_sequence'} || undef; } ##--------------------------------------------------------------------------- =head2 $pod_seq-EB my $seq_raw_text = $pod_seq->raw_text(); This method will return the I text of the POD interior sequence, exactly as it appeared in the input. =cut sub raw_text { my $self = shift; my $text = $self->{'-name'} . $self->{'-ldelim'}; for ( $self->{'-ptree'}->children ) { $text .= (ref $_) ? $_->raw_text : $_; } $text .= $self->{'-rdelim'}; return $text; } ##--------------------------------------------------------------------------- =head2 $pod_seq-EB my $ldelim = $pod_seq->left_delimiter(); The leftmost delimiter beginning the argument text to the interior sequence (should be "<"). =cut sub left_delimiter { (@_ > 1) and $_[0]->{'-ldelim'} = $_[1]; return $_[0]->{'-ldelim'}; } ## let ldelim() be an alias for left_delimiter() *ldelim = \&left_delimiter; ##--------------------------------------------------------------------------- =head2 $pod_seq-EB The rightmost delimiter beginning the argument text to the interior sequence (should be ">"). =cut sub right_delimiter { (@_ > 1) and $_[0]->{'-rdelim'} = $_[1]; return $_[0]->{'-rdelim'}; } ## let rdelim() be an alias for right_delimiter() *rdelim = \&right_delimiter; ##--------------------------------------------------------------------------- =head2 $pod_seq-EB my $ptree = $pod_parser->parse_text($paragraph_text); $pod_seq->parse_tree( $ptree ); $ptree = $pod_seq->parse_tree(); This method will get/set the corresponding parse-tree of the interior sequence's text. =cut sub parse_tree { (@_ > 1) and $_[0]->{'-ptree'} = $_[1]; return $_[0]->{'-ptree'}; } ## let ptree() be an alias for parse_tree() *ptree = \&parse_tree; ##--------------------------------------------------------------------------- =head2 $pod_seq-EB my ($filename, $line_number) = $pod_seq->file_line(); my $position = $pod_seq->file_line(); Returns the current filename and line number for the interior sequence object. If called in a list context, it returns a list of two elements: first the filename, then the line number. If called in a scalar context, it returns a string containing the filename, followed by a colon (':'), followed by the line number. =cut sub file_line { my @loc = ($_[0]->{'-file'} || '', $_[0]->{'-line'} || 0); return (wantarray) ? @loc : join(':', @loc); } ##--------------------------------------------------------------------------- =head2 Pod::InteriorSequence::B This method performs any necessary cleanup for the interior-sequence. If you override this method then it is B that you invoke the parent method from within your own method, otherwise I =cut sub DESTROY { ## We need to get rid of all child->parent pointers throughout the ## tree so their reference counts will go to zero and they can be ## garbage-collected _unset_child2parent_links(@_); } ##--------------------------------------------------------------------------- ############################################################################# package Pod::ParseTree; ##--------------------------------------------------------------------------- =head1 B This object corresponds to a tree of parsed POD text. As POD text is scanned from left to right, it is parsed into an ordered list of text-strings and B objects (in order of appearance). A B object corresponds to this list of strings and sequences. Each interior sequence in the parse-tree may itself contain a parse-tree (since interior sequences may be nested). =cut ##--------------------------------------------------------------------------- =head2 Pod::ParseTree-EB my $ptree1 = Pod::ParseTree->new; my $ptree2 = new Pod::ParseTree; my $ptree4 = Pod::ParseTree->new($array_ref); my $ptree3 = new Pod::ParseTree($array_ref); This is a class method that constructs a C object and returns a reference to the new parse-tree. If a single-argument is given, it must be a reference to an array, and is used to initialize the root (top) of the parse tree. =cut sub new { ## Determine if we were called via an object-ref or a classname my $this = shift; my $class = ref($this) || $this; my $self = (@_ == 1 and ref $_[0]) ? $_[0] : []; ## Bless ourselves into the desired class and perform any initialization bless $self, $class; return $self; } ##--------------------------------------------------------------------------- =head2 $ptree-EB my $top_node = $ptree->top(); $ptree->top( $top_node ); $ptree->top( @children ); This method gets/sets the top node of the parse-tree. If no arguments are given, it returns the topmost node in the tree (the root), which is also a B. If it is given a single argument that is a reference, then the reference is assumed to a parse-tree and becomes the new top node. Otherwise, if arguments are given, they are treated as the new list of children for the top node. =cut sub top { my $self = shift; if (@_ > 0) { @{ $self } = (@_ == 1 and ref $_[0]) ? ${ @_ } : @_; } return $self; } ## let parse_tree() & ptree() be aliases for the 'top' method *parse_tree = *ptree = \⊤ ##--------------------------------------------------------------------------- =head2 $ptree-EB This method gets/sets the children of the top node in the parse-tree. If no arguments are given, it returns the list (array) of children (each of which should be either a string or a B. Otherwise, if arguments are given, they are treated as the new list of children for the top node. =cut sub children { my $self = shift; if (@_ > 0) { @{ $self } = (@_ == 1 and ref $_[0]) ? ${ @_ } : @_; } return @{ $self }; } ##--------------------------------------------------------------------------- =head2 $ptree-EB This method prepends the given text or parse-tree to the current parse-tree. If the first item on the parse-tree is text and the argument is also text, then the text is prepended to the first item (not added as a separate string). Otherwise the argument is added as a new string or parse-tree I the current one. =cut use vars qw(@ptree); ## an alias used for performance reasons sub prepend { my $self = shift; local *ptree = $self; for (@_) { next unless length; if (@ptree && !(ref $ptree[0]) && !(ref $_)) { $ptree[0] = $_ . $ptree[0]; } else { unshift @ptree, $_; } } } ##--------------------------------------------------------------------------- =head2 $ptree-EB This method appends the given text or parse-tree to the current parse-tree. If the last item on the parse-tree is text and the argument is also text, then the text is appended to the last item (not added as a separate string). Otherwise the argument is added as a new string or parse-tree I the current one. =cut sub append { my $self = shift; local *ptree = $self; my $can_append = @ptree && !(ref $ptree[-1]); for (@_) { if (ref) { push @ptree, $_; } elsif(!length) { next; } elsif ($can_append) { $ptree[-1] .= $_; } else { push @ptree, $_; } } } =head2 $ptree-EB my $ptree_raw_text = $ptree->raw_text(); This method will return the I text of the POD parse-tree exactly as it appeared in the input. =cut sub raw_text { my $self = shift; my $text = ''; for ( @$self ) { $text .= (ref $_) ? $_->raw_text : $_; } return $text; } ##--------------------------------------------------------------------------- ## Private routines to set/unset child->parent links sub _unset_child2parent_links { my $self = shift; local *ptree = $self; for (@ptree) { next unless (defined and length and ref and ref ne 'SCALAR'); $_->_unset_child2parent_links() if UNIVERSAL::isa($_, 'Pod::InteriorSequence'); } } sub _set_child2parent_links { ## nothing to do, Pod::ParseTrees cant have parent pointers } =head2 Pod::ParseTree::B This method performs any necessary cleanup for the parse-tree. If you override this method then it is B that you invoke the parent method from within your own method, otherwise I =cut sub DESTROY { ## We need to get rid of all child->parent pointers throughout the ## tree so their reference counts will go to zero and they can be ## garbage-collected _unset_child2parent_links(@_); } ############################################################################# =head1 SEE ALSO See L, L =head1 AUTHOR Please report bugs using L. Brad Appleton Ebradapp@enteract.comE =cut 1; mrtg-2.17.10/lib/mrtg2/Pod/Parser.pm0000644000175300017510000017762413057016062016004 0ustar oetikeroep############################################################################# # Pod/Parser.pm -- package which defines a base class for parsing POD docs. # # Copyright (C) 1996-2000 by Bradford Appleton. All rights reserved. # This file is part of "PodParser". PodParser is free software; # you can redistribute it and/or modify it under the same terms # as Perl itself. ############################################################################# package Pod::Parser; use strict; ## These "variables" are used as local "glob aliases" for performance use vars qw($VERSION @ISA %myData %myOpts @input_stack); $VERSION = '1.37'; ## Current version of this package require 5.005; ## requires this Perl version or later ############################################################################# =head1 NAME Pod::Parser - base class for creating POD filters and translators =head1 SYNOPSIS use Pod::Parser; package MyParser; @ISA = qw(Pod::Parser); sub command { my ($parser, $command, $paragraph, $line_num) = @_; ## Interpret the command and its text; sample actions might be: if ($command eq 'head1') { ... } elsif ($command eq 'head2') { ... } ## ... other commands and their actions my $out_fh = $parser->output_handle(); my $expansion = $parser->interpolate($paragraph, $line_num); print $out_fh $expansion; } sub verbatim { my ($parser, $paragraph, $line_num) = @_; ## Format verbatim paragraph; sample actions might be: my $out_fh = $parser->output_handle(); print $out_fh $paragraph; } sub textblock { my ($parser, $paragraph, $line_num) = @_; ## Translate/Format this block of text; sample actions might be: my $out_fh = $parser->output_handle(); my $expansion = $parser->interpolate($paragraph, $line_num); print $out_fh $expansion; } sub interior_sequence { my ($parser, $seq_command, $seq_argument) = @_; ## Expand an interior sequence; sample actions might be: return "*$seq_argument*" if ($seq_command eq 'B'); return "`$seq_argument'" if ($seq_command eq 'C'); return "_${seq_argument}_'" if ($seq_command eq 'I'); ## ... other sequence commands and their resulting text } package main; ## Create a parser object and have it parse file whose name was ## given on the command-line (use STDIN if no files were given). $parser = new MyParser(); $parser->parse_from_filehandle(\*STDIN) if (@ARGV == 0); for (@ARGV) { $parser->parse_from_file($_); } =head1 REQUIRES perl5.005, Pod::InputObjects, Exporter, Symbol, Carp =head1 EXPORTS Nothing. =head1 DESCRIPTION B is a base class for creating POD filters and translators. It handles most of the effort involved with parsing the POD sections from an input stream, leaving subclasses free to be concerned only with performing the actual translation of text. B parses PODs, and makes method calls to handle the various components of the POD. Subclasses of B override these methods to translate the POD into whatever output format they desire. =head1 QUICK OVERVIEW To create a POD filter for translating POD documentation into some other format, you create a subclass of B which typically overrides just the base class implementation for the following methods: =over 2 =item * B =item * B =item * B =item * B =back You may also want to override the B and B methods for your subclass (to perform any needed per-file and/or per-document initialization or cleanup). If you need to perform any preprocessing of input before it is parsed you may want to override one or more of B and/or B. Sometimes it may be necessary to make more than one pass over the input files. If this is the case you have several options. You can make the first pass using B and override your methods to store the intermediate results in memory somewhere for the B method to process. You could use B for several passes with an appropriate state variable to control the operation for each pass. If your input source can't be reset to start at the beginning, you can store it in some other structure as a string or an array and have that structure implement a B method (which is all that B uses to read input). Feel free to add any member data fields you need to keep track of things like current font, indentation, horizontal or vertical position, or whatever else you like. Be sure to read L<"PRIVATE METHODS AND DATA"> to avoid name collisions. For the most part, the B base class should be able to do most of the input parsing for you and leave you free to worry about how to interpret the commands and translate the result. Note that all we have described here in this quick overview is the simplest most straightforward use of B to do stream-based parsing. It is also possible to use the B function to do more sophisticated tree-based parsing. See L<"TREE-BASED PARSING">. =head1 PARSING OPTIONS A I is simply a named option of B with a value that corresponds to a certain specified behavior. These various behaviors of B may be enabled/disabled by setting or unsetting one or more I using the B method. The set of currently accepted parse-options is as follows: =over 3 =item B<-want_nonPODs> (default: unset) Normally (by default) B will only provide access to the POD sections of the input. Input paragraphs that are not part of the POD-format documentation are not made available to the caller (not even using B). Setting this option to a non-empty, non-zero value will allow B to see non-POD sections of the input as well as POD sections. The B method can be used to determine if the corresponding paragraph is a POD paragraph, or some other input paragraph. =item B<-process_cut_cmd> (default: unset) Normally (by default) B handles the C<=cut> POD directive by itself and does not pass it on to the caller for processing. Setting this option to a non-empty, non-zero value will cause B to pass the C<=cut> directive to the caller just like any other POD command (and hence it may be processed by the B method). B will still interpret the C<=cut> directive to mean that "cutting mode" has been (re)entered, but the caller will get a chance to capture the actual C<=cut> paragraph itself for whatever purpose it desires. =item B<-warnings> (default: unset) Normally (by default) B recognizes a bare minimum of pod syntax errors and warnings and issues diagnostic messages for errors, but not for warnings. (Use B to do more thorough checking of POD syntax.) Setting this option to a non-empty, non-zero value will cause B to issue diagnostics for the few warnings it recognizes as well as the errors. =back Please see L<"parseopts()"> for a complete description of the interface for the setting and unsetting of parse-options. =cut ############################################################################# #use diagnostics; use Pod::InputObjects; use Carp; use Exporter; BEGIN { if ($] < 5.006) { require Symbol; import Symbol; } } @ISA = qw(Exporter); ############################################################################# =head1 RECOMMENDED SUBROUTINE/METHOD OVERRIDES B provides several methods which most subclasses will probably want to override. These methods are as follows: =cut ##--------------------------------------------------------------------------- =head1 B $parser->command($cmd,$text,$line_num,$pod_para); This method should be overridden by subclasses to take the appropriate action when a POD command paragraph (denoted by a line beginning with "=") is encountered. When such a POD directive is seen in the input, this method is called and is passed: =over 3 =item C<$cmd> the name of the command for this POD paragraph =item C<$text> the paragraph text for the given POD paragraph command. =item C<$line_num> the line-number of the beginning of the paragraph =item C<$pod_para> a reference to a C object which contains further information about the paragraph command (see L for details). =back B that this method I called for C<=pod> paragraphs. The base class implementation of this method simply treats the raw POD command as normal block of paragraph text (invoking the B method with the command paragraph). =cut sub command { my ($self, $cmd, $text, $line_num, $pod_para) = @_; ## Just treat this like a textblock $self->textblock($pod_para->raw_text(), $line_num, $pod_para); } ##--------------------------------------------------------------------------- =head1 B $parser->verbatim($text,$line_num,$pod_para); This method may be overridden by subclasses to take the appropriate action when a block of verbatim text is encountered. It is passed the following parameters: =over 3 =item C<$text> the block of text for the verbatim paragraph =item C<$line_num> the line-number of the beginning of the paragraph =item C<$pod_para> a reference to a C object which contains further information about the paragraph (see L for details). =back The base class implementation of this method simply prints the textblock (unmodified) to the output filehandle. =cut sub verbatim { my ($self, $text, $line_num, $pod_para) = @_; my $out_fh = $self->{_OUTPUT}; print $out_fh $text; } ##--------------------------------------------------------------------------- =head1 B $parser->textblock($text,$line_num,$pod_para); This method may be overridden by subclasses to take the appropriate action when a normal block of POD text is encountered (although the base class method will usually do what you want). It is passed the following parameters: =over 3 =item C<$text> the block of text for the a POD paragraph =item C<$line_num> the line-number of the beginning of the paragraph =item C<$pod_para> a reference to a C object which contains further information about the paragraph (see L for details). =back In order to process interior sequences, subclasses implementations of this method will probably want to invoke either B or B, passing it the text block C<$text>, and the corresponding line number in C<$line_num>, and then perform any desired processing upon the returned result. The base class implementation of this method simply prints the text block as it occurred in the input stream). =cut sub textblock { my ($self, $text, $line_num, $pod_para) = @_; my $out_fh = $self->{_OUTPUT}; print $out_fh $self->interpolate($text, $line_num); } ##--------------------------------------------------------------------------- =head1 B $parser->interior_sequence($seq_cmd,$seq_arg,$pod_seq); This method should be overridden by subclasses to take the appropriate action when an interior sequence is encountered. An interior sequence is an embedded command within a block of text which appears as a command name (usually a single uppercase character) followed immediately by a string of text which is enclosed in angle brackets. This method is passed the sequence command C<$seq_cmd> and the corresponding text C<$seq_arg>. It is invoked by the B method for each interior sequence that occurs in the string that it is passed. It should return the desired text string to be used in place of the interior sequence. The C<$pod_seq> argument is a reference to a C object which contains further information about the interior sequence. Please see L for details if you need to access this additional information. Subclass implementations of this method may wish to invoke the B method of C<$pod_seq> to see if it is nested inside some other interior-sequence (and if so, which kind). The base class implementation of the B method simply returns the raw text of the interior sequence (as it occurred in the input) to the caller. =cut sub interior_sequence { my ($self, $seq_cmd, $seq_arg, $pod_seq) = @_; ## Just return the raw text of the interior sequence return $pod_seq->raw_text(); } ############################################################################# =head1 OPTIONAL SUBROUTINE/METHOD OVERRIDES B provides several methods which subclasses may want to override to perform any special pre/post-processing. These methods do I have to be overridden, but it may be useful for subclasses to take advantage of them. =cut ##--------------------------------------------------------------------------- =head1 B my $parser = Pod::Parser->new(); This is the constructor for B and its subclasses. You I need to override this method! It is capable of constructing subclass objects as well as base class objects, provided you use any of the following constructor invocation styles: my $parser1 = MyParser->new(); my $parser2 = new MyParser(); my $parser3 = $parser2->new(); where C is some subclass of B. Using the syntax C to invoke the constructor is I recommended, but if you insist on being able to do this, then the subclass I need to override the B constructor method. If you do override the constructor, you I be sure to invoke the B method of the newly blessed object. Using any of the above invocations, the first argument to the constructor is always the corresponding package name (or object reference). No other arguments are required, but if desired, an associative array (or hash-table) my be passed to the B constructor, as in: my $parser1 = MyParser->new( MYDATA => $value1, MOREDATA => $value2 ); my $parser2 = new MyParser( -myflag => 1 ); All arguments passed to the B constructor will be treated as key/value pairs in a hash-table. The newly constructed object will be initialized by copying the contents of the given hash-table (which may have been empty). The B constructor for this class and all of its subclasses returns a blessed reference to the initialized object (hash-table). =cut sub new { ## Determine if we were called via an object-ref or a classname my ($this,%params) = @_; my $class = ref($this) || $this; ## Any remaining arguments are treated as initial values for the ## hash that is used to represent this object. my $self = { %params }; ## Bless ourselves into the desired class and perform any initialization bless $self, $class; $self->initialize(); return $self; } ##--------------------------------------------------------------------------- =head1 B $parser->initialize(); This method performs any necessary object initialization. It takes no arguments (other than the object instance of course, which is typically copied to a local variable named C<$self>). If subclasses override this method then they I be sure to invoke C<$self-ESUPER::initialize()>. =cut sub initialize { #my $self = shift; #return; } ##--------------------------------------------------------------------------- =head1 B $parser->begin_pod(); This method is invoked at the beginning of processing for each POD document that is encountered in the input. Subclasses should override this method to perform any per-document initialization. =cut sub begin_pod { #my $self = shift; #return; } ##--------------------------------------------------------------------------- =head1 B $parser->begin_input(); This method is invoked by B immediately I processing input from a filehandle. The base class implementation does nothing, however, subclasses may override it to perform any per-file initializations. Note that if multiple files are parsed for a single POD document (perhaps the result of some future C<=include> directive) this method is invoked for every file that is parsed. If you wish to perform certain initializations once per document, then you should use B. =cut sub begin_input { #my $self = shift; #return; } ##--------------------------------------------------------------------------- =head1 B $parser->end_input(); This method is invoked by B immediately I processing input from a filehandle. The base class implementation does nothing, however, subclasses may override it to perform any per-file cleanup actions. Please note that if multiple files are parsed for a single POD document (perhaps the result of some kind of C<=include> directive) this method is invoked for every file that is parsed. If you wish to perform certain cleanup actions once per document, then you should use B. =cut sub end_input { #my $self = shift; #return; } ##--------------------------------------------------------------------------- =head1 B $parser->end_pod(); This method is invoked at the end of processing for each POD document that is encountered in the input. Subclasses should override this method to perform any per-document finalization. =cut sub end_pod { #my $self = shift; #return; } ##--------------------------------------------------------------------------- =head1 B $textline = $parser->preprocess_line($text, $line_num); This method should be overridden by subclasses that wish to perform any kind of preprocessing for each I of input (I it has been determined whether or not it is part of a POD paragraph). The parameter C<$text> is the input line; and the parameter C<$line_num> is the line number of the corresponding text line. The value returned should correspond to the new text to use in its place. If the empty string or an undefined value is returned then no further processing will be performed for this line. Please note that the B method is invoked I the B method. After all (possibly preprocessed) lines in a paragraph have been assembled together and it has been determined that the paragraph is part of the POD documentation from one of the selected sections, then B is invoked. The base class implementation of this method returns the given text. =cut sub preprocess_line { my ($self, $text, $line_num) = @_; return $text; } ##--------------------------------------------------------------------------- =head1 B $textblock = $parser->preprocess_paragraph($text, $line_num); This method should be overridden by subclasses that wish to perform any kind of preprocessing for each block (paragraph) of POD documentation that appears in the input stream. The parameter C<$text> is the POD paragraph from the input file; and the parameter C<$line_num> is the line number for the beginning of the corresponding paragraph. The value returned should correspond to the new text to use in its place If the empty string is returned or an undefined value is returned, then the given C<$text> is ignored (not processed). This method is invoked after gathering up all the lines in a paragraph and after determining the cutting state of the paragraph, but before trying to further parse or interpret them. After B returns, the current cutting state (which is returned by C<$self-Ecutting()>) is examined. If it evaluates to true then input text (including the given C<$text>) is cut (not processed) until the next POD directive is encountered. Please note that the B method is invoked I the B method. After all (possibly preprocessed) lines in a paragraph have been assembled together and either it has been determined that the paragraph is part of the POD documentation from one of the selected sections or the C<-want_nonPODs> option is true, then B is invoked. The base class implementation of this method returns the given text. =cut sub preprocess_paragraph { my ($self, $text, $line_num) = @_; return $text; } ############################################################################# =head1 METHODS FOR PARSING AND PROCESSING B provides several methods to process input text. These methods typically won't need to be overridden (and in some cases they can't be overridden), but subclasses may want to invoke them to exploit their functionality. =cut ##--------------------------------------------------------------------------- =head1 B $ptree1 = $parser->parse_text($text, $line_num); $ptree2 = $parser->parse_text({%opts}, $text, $line_num); $ptree3 = $parser->parse_text(\%opts, $text, $line_num); This method is useful if you need to perform your own interpolation of interior sequences and can't rely upon B to expand them in simple bottom-up order. The parameter C<$text> is a string or block of text to be parsed for interior sequences; and the parameter C<$line_num> is the line number corresponding to the beginning of C<$text>. B will parse the given text into a parse-tree of "nodes." and interior-sequences. Each "node" in the parse tree is either a text-string, or a B. The result returned is a parse-tree of type B. Please see L for more information about B and B. If desired, an optional hash-ref may be specified as the first argument to customize certain aspects of the parse-tree that is created and returned. The set of recognized option keywords are: =over 3 =item B<-expand_seq> =E I|I Normally, the parse-tree returned by B will contain an unexpanded C object for each interior-sequence encountered. Specifying B<-expand_seq> tells B to "expand" every interior-sequence it sees by invoking the referenced function (or named method of the parser object) and using the return value as the expanded result. If a subroutine reference was given, it is invoked as: &$code_ref( $parser, $sequence ) and if a method-name was given, it is invoked as: $parser->method_name( $sequence ) where C<$parser> is a reference to the parser object, and C<$sequence> is a reference to the interior-sequence object. [I: If the B method is specified, then it is invoked according to the interface specified in L<"interior_sequence()">]. =item B<-expand_text> =E I|I Normally, the parse-tree returned by B will contain a text-string for each contiguous sequence of characters outside of an interior-sequence. Specifying B<-expand_text> tells B to "preprocess" every such text-string it sees by invoking the referenced function (or named method of the parser object) and using the return value as the preprocessed (or "expanded") result. [Note that if the result is an interior-sequence, then it will I be expanded as specified by the B<-expand_seq> option; Any such recursive expansion needs to be handled by the specified callback routine.] If a subroutine reference was given, it is invoked as: &$code_ref( $parser, $text, $ptree_node ) and if a method-name was given, it is invoked as: $parser->method_name( $text, $ptree_node ) where C<$parser> is a reference to the parser object, C<$text> is the text-string encountered, and C<$ptree_node> is a reference to the current node in the parse-tree (usually an interior-sequence object or else the top-level node of the parse-tree). =item B<-expand_ptree> =E I|I Rather than returning a C, pass the parse-tree as an argument to the referenced subroutine (or named method of the parser object) and return the result instead of the parse-tree object. If a subroutine reference was given, it is invoked as: &$code_ref( $parser, $ptree ) and if a method-name was given, it is invoked as: $parser->method_name( $ptree ) where C<$parser> is a reference to the parser object, and C<$ptree> is a reference to the parse-tree object. =back =cut sub parse_text { my $self = shift; local $_ = ''; ## Get options and set any defaults my %opts = (ref $_[0]) ? %{ shift() } : (); my $expand_seq = $opts{'-expand_seq'} || undef; my $expand_text = $opts{'-expand_text'} || undef; my $expand_ptree = $opts{'-expand_ptree'} || undef; my $text = shift; my $line = shift; my $file = $self->input_file(); my $cmd = ""; ## Convert method calls into closures, for our convenience my $xseq_sub = $expand_seq; my $xtext_sub = $expand_text; my $xptree_sub = $expand_ptree; if (defined $expand_seq and $expand_seq eq 'interior_sequence') { ## If 'interior_sequence' is the method to use, we have to pass ## more than just the sequence object, we also need to pass the ## sequence name and text. $xseq_sub = sub { my ($sself, $iseq) = @_; my $args = join('', $iseq->parse_tree->children); return $sself->interior_sequence($iseq->name, $args, $iseq); }; } ref $xseq_sub or $xseq_sub = sub { shift()->$expand_seq(@_) }; ref $xtext_sub or $xtext_sub = sub { shift()->$expand_text(@_) }; ref $xptree_sub or $xptree_sub = sub { shift()->$expand_ptree(@_) }; ## Keep track of the "current" interior sequence, and maintain a stack ## of "in progress" sequences. ## ## NOTE that we push our own "accumulator" at the very beginning of the ## stack. It's really a parse-tree, not a sequence; but it implements ## the methods we need so we can use it to gather-up all the sequences ## and strings we parse. Thus, by the end of our parsing, it should be ## the only thing left on our stack and all we have to do is return it! ## my $seq = Pod::ParseTree->new(); my @seq_stack = ($seq); my ($ldelim, $rdelim) = ('', ''); ## Iterate over all sequence starts text (NOTE: split with ## capturing parens keeps the delimiters) $_ = $text; my @tokens = split /([A-Z]<(?:<+\s)?)/; while ( @tokens ) { $_ = shift @tokens; ## Look for the beginning of a sequence if ( /^([A-Z])(<(?:<+\s)?)$/ ) { ## Push a new sequence onto the stack of those "in-progress" my $ldelim_orig; ($cmd, $ldelim_orig) = ($1, $2); ($ldelim = $ldelim_orig) =~ s/\s+$//; ($rdelim = $ldelim) =~ tr//; $seq = Pod::InteriorSequence->new( -name => $cmd, -ldelim => $ldelim_orig, -rdelim => $rdelim, -file => $file, -line => $line ); (@seq_stack > 1) and $seq->nested($seq_stack[-1]); push @seq_stack, $seq; } ## Look for sequence ending elsif ( @seq_stack > 1 ) { ## Make sure we match the right kind of closing delimiter my ($seq_end, $post_seq) = ('', ''); if ( ($ldelim eq '<' and /\A(.*?)(>)/s) or /\A(.*?)(\s+$rdelim)/s ) { ## Found end-of-sequence, capture the interior and the ## closing the delimiter, and put the rest back on the ## token-list $post_seq = substr($_, length($1) + length($2)); ($_, $seq_end) = ($1, $2); (length $post_seq) and unshift @tokens, $post_seq; } if (length) { ## In the middle of a sequence, append this text to it, and ## dont forget to "expand" it if that's what the caller wanted $seq->append($expand_text ? &$xtext_sub($self,$_,$seq) : $_); $_ .= $seq_end; } if (length $seq_end) { ## End of current sequence, record terminating delimiter $seq->rdelim($seq_end); ## Pop it off the stack of "in progress" sequences pop @seq_stack; ## Append result to its parent in current parse tree $seq_stack[-1]->append($expand_seq ? &$xseq_sub($self,$seq) : $seq); ## Remember the current cmd-name and left-delimiter if(@seq_stack > 1) { $cmd = $seq_stack[-1]->name; $ldelim = $seq_stack[-1]->ldelim; $rdelim = $seq_stack[-1]->rdelim; } else { $cmd = $ldelim = $rdelim = ''; } } } elsif (length) { ## In the middle of a sequence, append this text to it, and ## dont forget to "expand" it if that's what the caller wanted $seq->append($expand_text ? &$xtext_sub($self,$_,$seq) : $_); } ## Keep track of line count $line += s/\r*\n//; ## Remember the "current" sequence $seq = $seq_stack[-1]; } ## Handle unterminated sequences my $errorsub = (@seq_stack > 1) ? $self->errorsub() : undef; while (@seq_stack > 1) { ($cmd, $file, $line) = ($seq->name, $seq->file_line); $ldelim = $seq->ldelim; ($rdelim = $ldelim) =~ tr//; $rdelim =~ s/^(\S+)(\s*)$/$2$1/; pop @seq_stack; my $errmsg = "*** ERROR: unterminated ${cmd}${ldelim}...${rdelim}". " at line $line in file $file\n"; (ref $errorsub) and &{$errorsub}($errmsg) or (defined $errorsub) and $self->$errorsub($errmsg) or carp($errmsg); $seq_stack[-1]->append($expand_seq ? &$xseq_sub($self,$seq) : $seq); $seq = $seq_stack[-1]; } ## Return the resulting parse-tree my $ptree = (pop @seq_stack)->parse_tree; return $expand_ptree ? &$xptree_sub($self, $ptree) : $ptree; } ##--------------------------------------------------------------------------- =head1 B $textblock = $parser->interpolate($text, $line_num); This method translates all text (including any embedded interior sequences) in the given text string C<$text> and returns the interpolated result. The parameter C<$line_num> is the line number corresponding to the beginning of C<$text>. B merely invokes a private method to recursively expand nested interior sequences in bottom-up order (innermost sequences are expanded first). If there is a need to expand nested sequences in some alternate order, use B instead. =cut sub interpolate { my($self, $text, $line_num) = @_; my %parse_opts = ( -expand_seq => 'interior_sequence' ); my $ptree = $self->parse_text( \%parse_opts, $text, $line_num ); return join '', $ptree->children(); } ##--------------------------------------------------------------------------- =begin __PRIVATE__ =head1 B $parser->parse_paragraph($text, $line_num); This method takes the text of a POD paragraph to be processed, along with its corresponding line number, and invokes the appropriate method (one of B, B, or B). For performance reasons, this method is invoked directly without any dynamic lookup; Hence subclasses may I override it! =end __PRIVATE__ =cut sub parse_paragraph { my ($self, $text, $line_num) = @_; local *myData = $self; ## alias to avoid deref-ing overhead local *myOpts = ($myData{_PARSEOPTS} ||= {}); ## get parse-options local $_; ## See if we want to preprocess nonPOD paragraphs as well as POD ones. my $wantNonPods = $myOpts{'-want_nonPODs'}; ## Update cutting status $myData{_CUTTING} = 0 if $text =~ /^={1,2}\S/; ## Perform any desired preprocessing if we wanted it this early $wantNonPods and $text = $self->preprocess_paragraph($text, $line_num); ## Ignore up until next POD directive if we are cutting return if $myData{_CUTTING}; ## Now we know this is block of text in a POD section! ##----------------------------------------------------------------- ## This is a hook (hack ;-) for Pod::Select to do its thing without ## having to override methods, but also without Pod::Parser assuming ## $self is an instance of Pod::Select (if the _SELECTED_SECTIONS ## field exists then we assume there is an is_selected() method for ## us to invoke (calling $self->can('is_selected') could verify this ## but that is more overhead than I want to incur) ##----------------------------------------------------------------- ## Ignore this block if it isnt in one of the selected sections if (exists $myData{_SELECTED_SECTIONS}) { $self->is_selected($text) or return ($myData{_CUTTING} = 1); } ## If we havent already, perform any desired preprocessing and ## then re-check the "cutting" state unless ($wantNonPods) { $text = $self->preprocess_paragraph($text, $line_num); return 1 unless ((defined $text) and (length $text)); return 1 if ($myData{_CUTTING}); } ## Look for one of the three types of paragraphs my ($pfx, $cmd, $arg, $sep) = ('', '', '', ''); my $pod_para = undef; if ($text =~ /^(={1,2})(?=\S)/) { ## Looks like a command paragraph. Capture the command prefix used ## ("=" or "=="), as well as the command-name, its paragraph text, ## and whatever sequence of characters was used to separate them $pfx = $1; $_ = substr($text, length $pfx); ($cmd, $sep, $text) = split /(\s+)/, $_, 2; ## If this is a "cut" directive then we dont need to do anything ## except return to "cutting" mode. if ($cmd eq 'cut') { $myData{_CUTTING} = 1; return unless $myOpts{'-process_cut_cmd'}; } } ## Save the attributes indicating how the command was specified. $pod_para = new Pod::Paragraph( -name => $cmd, -text => $text, -prefix => $pfx, -separator => $sep, -file => $myData{_INFILE}, -line => $line_num ); # ## Invoke appropriate callbacks # if (exists $myData{_CALLBACKS}) { # ## Look through the callback list, invoke callbacks, # ## then see if we need to do the default actions # ## (invoke_callbacks will return true if we do). # return 1 unless $self->invoke_callbacks($cmd, $text, $line_num, $pod_para); # } # If the last paragraph ended in whitespace, and we're not between verbatim blocks, carp if ($myData{_WHITESPACE} and $myOpts{'-warnings'} and not ($text =~ /^\s+/ and ($myData{_PREVIOUS}||"") eq "verbatim")) { my $errorsub = $self->errorsub(); my $line = $line_num - 1; my $errmsg = "*** WARNING: line containing nothing but whitespace". " in paragraph at line $line in file $myData{_INFILE}\n"; (ref $errorsub) and &{$errorsub}($errmsg) or (defined $errorsub) and $self->$errorsub($errmsg) or carp($errmsg); } if (length $cmd) { ## A command paragraph $self->command($cmd, $text, $line_num, $pod_para); $myData{_PREVIOUS} = $cmd; } elsif ($text =~ /^\s+/) { ## Indented text - must be a verbatim paragraph $self->verbatim($text, $line_num, $pod_para); $myData{_PREVIOUS} = "verbatim"; } else { ## Looks like an ordinary block of text $self->textblock($text, $line_num, $pod_para); $myData{_PREVIOUS} = "textblock"; } # Update the whitespace for the next time around $myData{_WHITESPACE} = $text =~ /^[^\S\r\n]+\Z/m ? 1 : 0; return 1; } ##--------------------------------------------------------------------------- =head1 B $parser->parse_from_filehandle($in_fh,$out_fh); This method takes an input filehandle (which is assumed to already be opened for reading) and reads the entire input stream looking for blocks (paragraphs) of POD documentation to be processed. If no first argument is given the default input filehandle C is used. The C<$in_fh> parameter may be any object that provides a B method to retrieve a single line of input text (hence, an appropriate wrapper object could be used to parse PODs from a single string or an array of strings). Using C<$in_fh-Egetline()>, input is read line-by-line and assembled into paragraphs or "blocks" (which are separated by lines containing nothing but whitespace). For each block of POD documentation encountered it will invoke a method to parse the given paragraph. If a second argument is given then it should correspond to a filehandle where output should be sent (otherwise the default output filehandle is C if no output filehandle is currently in use). B For performance reasons, this method caches the input stream at the top of the stack in a local variable. Any attempts by clients to change the stack contents during processing when in the midst executing of this method I the input stream used by the current invocation of this method. This method does I usually need to be overridden by subclasses. =cut sub parse_from_filehandle { my $self = shift; my %opts = (ref $_[0] eq 'HASH') ? %{ shift() } : (); my ($in_fh, $out_fh) = @_; $in_fh = \*STDIN unless ($in_fh); local *myData = $self; ## alias to avoid deref-ing overhead local *myOpts = ($myData{_PARSEOPTS} ||= {}); ## get parse-options local $_; ## Put this stream at the top of the stack and do beginning-of-input ## processing. NOTE that $in_fh might be reset during this process. my $topstream = $self->_push_input_stream($in_fh, $out_fh); (exists $opts{-cutting}) and $self->cutting( $opts{-cutting} ); ## Initialize line/paragraph my ($textline, $paragraph) = ('', ''); my ($nlines, $plines) = (0, 0); ## Use <$fh> instead of $fh->getline where possible (for speed) $_ = ref $in_fh; my $tied_fh = (/^(?:GLOB|FileHandle|IO::\w+)$/ or tied $in_fh); ## Read paragraphs line-by-line while (defined ($textline = $tied_fh ? <$in_fh> : $in_fh->getline)) { $textline = $self->preprocess_line($textline, ++$nlines); next unless ((defined $textline) && (length $textline)); if ((! length $paragraph) && ($textline =~ /^==/)) { ## '==' denotes a one-line command paragraph $paragraph = $textline; $plines = 1; $textline = ''; } else { ## Append this line to the current paragraph $paragraph .= $textline; ++$plines; } ## See if this line is blank and ends the current paragraph. ## If it isnt, then keep iterating until it is. next unless (($textline =~ /^([^\S\r\n]*)[\r\n]*$/) && (length $paragraph)); ## Now process the paragraph parse_paragraph($self, $paragraph, ($nlines - $plines) + 1); $paragraph = ''; $plines = 0; } ## Dont forget about the last paragraph in the file if (length $paragraph) { parse_paragraph($self, $paragraph, ($nlines - $plines) + 1) } ## Now pop the input stream off the top of the input stack. $self->_pop_input_stream(); } ##--------------------------------------------------------------------------- =head1 B $parser->parse_from_file($filename,$outfile); This method takes a filename and does the following: =over 2 =item * opens the input and output files for reading (creating the appropriate filehandles) =item * invokes the B method passing it the corresponding input and output filehandles. =item * closes the input and output files. =back If the special input filename "-" or "<&STDIN" is given then the STDIN filehandle is used for input (and no open or close is performed). If no input filename is specified then "-" is implied. Filehandle references, or objects that support the regular IO operations (like C$fhE> or C<$fh-getline>) are also accepted; the handles must already be opened. If a second argument is given then it should be the name of the desired output file. If the special output filename "-" or ">&STDOUT" is given then the STDOUT filehandle is used for output (and no open or close is performed). If the special output filename ">&STDERR" is given then the STDERR filehandle is used for output (and no open or close is performed). If no output filehandle is currently in use and no output filename is specified, then "-" is implied. Alternatively, filehandle references or objects that support the regular IO operations (like C, e.g. L) are also accepted; the object must already be opened. This method does I usually need to be overridden by subclasses. =cut sub parse_from_file { my $self = shift; my %opts = (ref $_[0] eq 'HASH') ? %{ shift() } : (); my ($infile, $outfile) = @_; my ($in_fh, $out_fh); if ($] < 5.006) { ($in_fh, $out_fh) = (gensym(), gensym()); } my ($close_input, $close_output) = (0, 0); local *myData = $self; local *_; ## Is $infile a filename or a (possibly implied) filehandle if (defined $infile && ref $infile) { if (ref($infile) =~ /^(SCALAR|ARRAY|HASH|CODE|REF)$/) { croak "Input from $1 reference not supported!\n"; } ## Must be a filehandle-ref (or else assume its a ref to an object ## that supports the common IO read operations). $myData{_INFILE} = ${$infile}; $in_fh = $infile; } elsif (!defined($infile) || !length($infile) || ($infile eq '-') || ($infile =~ /^<&(?:STDIN|0)$/i)) { ## Not a filename, just a string implying STDIN $infile ||= '-'; $myData{_INFILE} = ''; $in_fh = \*STDIN; } else { ## We have a filename, open it for reading $myData{_INFILE} = $infile; open($in_fh, "< $infile") or croak "Can't open $infile for reading: $!\n"; $close_input = 1; } ## NOTE: we need to be *very* careful when "defaulting" the output ## file. We only want to use a default if this is the beginning of ## the entire document (but *not* if this is an included file). We ## determine this by seeing if the input stream stack has been set-up ## already ## Is $outfile a filename, a (possibly implied) filehandle, maybe a ref? if (ref $outfile) { ## we need to check for ref() first, as other checks involve reading if (ref($outfile) =~ /^(ARRAY|HASH|CODE)$/) { croak "Output to $1 reference not supported!\n"; } elsif (ref($outfile) eq 'SCALAR') { # # NOTE: IO::String isn't a part of the perl distribution, # # so probably we shouldn't support this case... # require IO::String; # $myData{_OUTFILE} = "$outfile"; # $out_fh = IO::String->new($outfile); croak "Output to SCALAR reference not supported!\n"; } else { ## Must be a filehandle-ref (or else assume its a ref to an ## object that supports the common IO write operations). $myData{_OUTFILE} = ${$outfile}; $out_fh = $outfile; } } elsif (!defined($outfile) || !length($outfile) || ($outfile eq '-') || ($outfile =~ /^>&?(?:STDOUT|1)$/i)) { if (defined $myData{_TOP_STREAM}) { $out_fh = $myData{_OUTPUT}; } else { ## Not a filename, just a string implying STDOUT $outfile ||= '-'; $myData{_OUTFILE} = ''; $out_fh = \*STDOUT; } } elsif ($outfile =~ /^>&(STDERR|2)$/i) { ## Not a filename, just a string implying STDERR $myData{_OUTFILE} = ''; $out_fh = \*STDERR; } else { ## We have a filename, open it for writing $myData{_OUTFILE} = $outfile; (-d $outfile) and croak "$outfile is a directory, not POD input!\n"; open($out_fh, "> $outfile") or croak "Can't open $outfile for writing: $!\n"; $close_output = 1; } ## Whew! That was a lot of work to set up reasonably/robust behavior ## in the case of a non-filename for reading and writing. Now we just ## have to parse the input and close the handles when we're finished. $self->parse_from_filehandle(\%opts, $in_fh, $out_fh); $close_input and close($in_fh) || croak "Can't close $infile after reading: $!\n"; $close_output and close($out_fh) || croak "Can't close $outfile after writing: $!\n"; } ############################################################################# =head1 ACCESSOR METHODS Clients of B should use the following methods to access instance data fields: =cut ##--------------------------------------------------------------------------- =head1 B $parser->errorsub("method_name"); $parser->errorsub(\&warn_user); $parser->errorsub(sub { print STDERR, @_ }); Specifies the method or subroutine to use when printing error messages about POD syntax. The supplied method/subroutine I return TRUE upon successful printing of the message. If C is given, then the B builtin is used to issue error messages (this is the default behavior). my $errorsub = $parser->errorsub() my $errmsg = "This is an error message!\n" (ref $errorsub) and &{$errorsub}($errmsg) or (defined $errorsub) and $parser->$errorsub($errmsg) or carp($errmsg); Returns a method name, or else a reference to the user-supplied subroutine used to print error messages. Returns C if the B builtin is used to issue error messages (this is the default behavior). =cut sub errorsub { return (@_ > 1) ? ($_[0]->{_ERRORSUB} = $_[1]) : $_[0]->{_ERRORSUB}; } ##--------------------------------------------------------------------------- =head1 B $boolean = $parser->cutting(); Returns the current C state: a boolean-valued scalar which evaluates to true if text from the input file is currently being "cut" (meaning it is I considered part of the POD document). $parser->cutting($boolean); Sets the current C state to the given value and returns the result. =cut sub cutting { return (@_ > 1) ? ($_[0]->{_CUTTING} = $_[1]) : $_[0]->{_CUTTING}; } ##--------------------------------------------------------------------------- ##--------------------------------------------------------------------------- =head1 B When invoked with no additional arguments, B returns a hashtable of all the current parsing options. ## See if we are parsing non-POD sections as well as POD ones my %opts = $parser->parseopts(); $opts{'-want_nonPODs}' and print "-want_nonPODs\n"; When invoked using a single string, B treats the string as the name of a parse-option and returns its corresponding value if it exists (returns C if it doesn't). ## Did we ask to see '=cut' paragraphs? my $want_cut = $parser->parseopts('-process_cut_cmd'); $want_cut and print "-process_cut_cmd\n"; When invoked with multiple arguments, B treats them as key/value pairs and the specified parse-option names are set to the given values. Any unspecified parse-options are unaffected. ## Set them back to the default $parser->parseopts(-warnings => 0); When passed a single hash-ref, B uses that hash to completely reset the existing parse-options, all previous parse-option values are lost. ## Reset all options to default $parser->parseopts( { } ); See L<"PARSING OPTIONS"> for more information on the name and meaning of each parse-option currently recognized. =cut sub parseopts { local *myData = shift; local *myOpts = ($myData{_PARSEOPTS} ||= {}); return %myOpts if (@_ == 0); if (@_ == 1) { local $_ = shift; return ref($_) ? $myData{_PARSEOPTS} = $_ : $myOpts{$_}; } my @newOpts = (%myOpts, @_); $myData{_PARSEOPTS} = { @newOpts }; } ##--------------------------------------------------------------------------- =head1 B $fname = $parser->output_file(); Returns the name of the output file being written. =cut sub output_file { return $_[0]->{_OUTFILE}; } ##--------------------------------------------------------------------------- =head1 B $fhandle = $parser->output_handle(); Returns the output filehandle object. =cut sub output_handle { return $_[0]->{_OUTPUT}; } ##--------------------------------------------------------------------------- =head1 B $fname = $parser->input_file(); Returns the name of the input file being read. =cut sub input_file { return $_[0]->{_INFILE}; } ##--------------------------------------------------------------------------- =head1 B $fhandle = $parser->input_handle(); Returns the current input filehandle object. =cut sub input_handle { return $_[0]->{_INPUT}; } ##--------------------------------------------------------------------------- =begin __PRIVATE__ =head1 B $listref = $parser->input_streams(); Returns a reference to an array which corresponds to the stack of all the input streams that are currently in the middle of being parsed. While parsing an input stream, it is possible to invoke B or B to parse a new input stream and then return to parsing the previous input stream. Each input stream to be parsed is pushed onto the end of this input stack before any of its input is read. The input stream that is currently being parsed is always at the end (or top) of the input stack. When an input stream has been exhausted, it is popped off the end of the input stack. Each element on this input stack is a reference to C object. Please see L for more details. This method might be invoked when printing diagnostic messages, for example, to obtain the name and line number of the all input files that are currently being processed. =end __PRIVATE__ =cut sub input_streams { return $_[0]->{_INPUT_STREAMS}; } ##--------------------------------------------------------------------------- =begin __PRIVATE__ =head1 B $hashref = $parser->top_stream(); Returns a reference to the hash-table that represents the element that is currently at the top (end) of the input stream stack (see L<"input_streams()">). The return value will be the C if the input stack is empty. This method might be used when printing diagnostic messages, for example, to obtain the name and line number of the current input file. =end __PRIVATE__ =cut sub top_stream { return $_[0]->{_TOP_STREAM} || undef; } ############################################################################# =head1 PRIVATE METHODS AND DATA B makes use of several internal methods and data fields which clients should not need to see or use. For the sake of avoiding name collisions for client data and methods, these methods and fields are briefly discussed here. Determined hackers may obtain further information about them by reading the B source code. Private data fields are stored in the hash-object whose reference is returned by the B constructor for this class. The names of all private methods and data-fields used by B begin with a prefix of "_" and match the regular expression C. =cut ##--------------------------------------------------------------------------- =begin _PRIVATE_ =head1 B<_push_input_stream()> $hashref = $parser->_push_input_stream($in_fh,$out_fh); This method will push the given input stream on the input stack and perform any necessary beginning-of-document or beginning-of-file processing. The argument C<$in_fh> is the input stream filehandle to push, and C<$out_fh> is the corresponding output filehandle to use (if it is not given or is undefined, then the current output stream is used, which defaults to standard output if it doesnt exist yet). The value returned will be reference to the hash-table that represents the new top of the input stream stack. I that it is possible for this method to use default values for the input and output file handles. If this happens, you will need to look at the C and C instance data members to determine their new values. =end _PRIVATE_ =cut sub _push_input_stream { my ($self, $in_fh, $out_fh) = @_; local *myData = $self; ## Initialize stuff for the entire document if this is *not* ## an included file. ## ## NOTE: we need to be *very* careful when "defaulting" the output ## filehandle. We only want to use a default value if this is the ## beginning of the entire document (but *not* if this is an included ## file). unless (defined $myData{_TOP_STREAM}) { $out_fh = \*STDOUT unless (defined $out_fh); $myData{_CUTTING} = 1; ## current "cutting" state $myData{_INPUT_STREAMS} = []; ## stack of all input streams } ## Initialize input indicators $myData{_OUTFILE} = '(unknown)' unless (defined $myData{_OUTFILE}); $myData{_OUTPUT} = $out_fh if (defined $out_fh); $in_fh = \*STDIN unless (defined $in_fh); $myData{_INFILE} = '(unknown)' unless (defined $myData{_INFILE}); $myData{_INPUT} = $in_fh; my $input_top = $myData{_TOP_STREAM} = new Pod::InputSource( -name => $myData{_INFILE}, -handle => $in_fh, -was_cutting => $myData{_CUTTING} ); local *input_stack = $myData{_INPUT_STREAMS}; push(@input_stack, $input_top); ## Perform beginning-of-document and/or beginning-of-input processing $self->begin_pod() if (@input_stack == 1); $self->begin_input(); return $input_top; } ##--------------------------------------------------------------------------- =begin _PRIVATE_ =head1 B<_pop_input_stream()> $hashref = $parser->_pop_input_stream(); This takes no arguments. It will perform any necessary end-of-file or end-of-document processing and then pop the current input stream from the top of the input stack. The value returned will be reference to the hash-table that represents the new top of the input stream stack. =end _PRIVATE_ =cut sub _pop_input_stream { my ($self) = @_; local *myData = $self; local *input_stack = $myData{_INPUT_STREAMS}; ## Perform end-of-input and/or end-of-document processing $self->end_input() if (@input_stack > 0); $self->end_pod() if (@input_stack == 1); ## Restore cutting state to whatever it was before we started ## parsing this file. my $old_top = pop(@input_stack); $myData{_CUTTING} = $old_top->was_cutting(); ## Dont forget to reset the input indicators my $input_top = undef; if (@input_stack > 0) { $input_top = $myData{_TOP_STREAM} = $input_stack[-1]; $myData{_INFILE} = $input_top->name(); $myData{_INPUT} = $input_top->handle(); } else { delete $myData{_TOP_STREAM}; delete $myData{_INPUT_STREAMS}; } return $input_top; } ############################################################################# =head1 TREE-BASED PARSING If straightforward stream-based parsing wont meet your needs (as is likely the case for tasks such as translating PODs into structured markup languages like HTML and XML) then you may need to take the tree-based approach. Rather than doing everything in one pass and calling the B method to expand sequences into text, it may be desirable to instead create a parse-tree using the B method to return a tree-like structure which may contain an ordered list of children (each of which may be a text-string, or a similar tree-like structure). Pay special attention to L<"METHODS FOR PARSING AND PROCESSING"> and to the objects described in L. The former describes the gory details and parameters for how to customize and extend the parsing behavior of B. B provides several objects that may all be used interchangeably as parse-trees. The most obvious one is the B object. It defines the basic interface and functionality that all things trying to be a POD parse-tree should do. A B is defined such that each "node" may be a text-string, or a reference to another parse-tree. Each B object and each B object also supports the basic parse-tree interface. The B method takes a given paragraph of text, and returns a parse-tree that contains one or more children, each of which may be a text-string, or an InteriorSequence object. There are also callback-options that may be passed to B to customize the way it expands or transforms interior-sequences, as well as the returned result. These callbacks can be used to create a parse-tree with custom-made objects (which may or may not support the parse-tree interface, depending on how you choose to do it). If you wish to turn an entire POD document into a parse-tree, that process is fairly straightforward. The B method is the key to doing this successfully. Every paragraph-callback (i.e. the polymorphic methods for B, B, and B paragraphs) takes a B object as an argument. Each paragraph object has a B method that can be used to get or set a corresponding parse-tree. So for each of those paragraph-callback methods, simply call B with the options you desire, and then use the returned parse-tree to assign to the given paragraph object. That gives you a parse-tree for each paragraph - so now all you need is an ordered list of paragraphs. You can maintain that yourself as a data element in the object/hash. The most straightforward way would be simply to use an array-ref, with the desired set of custom "options" for each invocation of B. Let's assume the desired option-set is given by the hash C<%options>. Then we might do something like the following: package MyPodParserTree; @ISA = qw( Pod::Parser ); ... sub begin_pod { my $self = shift; $self->{'-paragraphs'} = []; ## initialize paragraph list } sub command { my ($parser, $command, $paragraph, $line_num, $pod_para) = @_; my $ptree = $parser->parse_text({%options}, $paragraph, ...); $pod_para->parse_tree( $ptree ); push @{ $self->{'-paragraphs'} }, $pod_para; } sub verbatim { my ($parser, $paragraph, $line_num, $pod_para) = @_; push @{ $self->{'-paragraphs'} }, $pod_para; } sub textblock { my ($parser, $paragraph, $line_num, $pod_para) = @_; my $ptree = $parser->parse_text({%options}, $paragraph, ...); $pod_para->parse_tree( $ptree ); push @{ $self->{'-paragraphs'} }, $pod_para; } ... package main; ... my $parser = new MyPodParserTree(...); $parser->parse_from_file(...); my $paragraphs_ref = $parser->{'-paragraphs'}; Of course, in this module-author's humble opinion, I'd be more inclined to use the existing B object than a simple array. That way everything in it, paragraphs and sequences, all respond to the same core interface for all parse-tree nodes. The result would look something like: package MyPodParserTree2; ... sub begin_pod { my $self = shift; $self->{'-ptree'} = new Pod::ParseTree; ## initialize parse-tree } sub parse_tree { ## convenience method to get/set the parse-tree for the entire POD (@_ > 1) and $_[0]->{'-ptree'} = $_[1]; return $_[0]->{'-ptree'}; } sub command { my ($parser, $command, $paragraph, $line_num, $pod_para) = @_; my $ptree = $parser->parse_text({<>}, $paragraph, ...); $pod_para->parse_tree( $ptree ); $parser->parse_tree()->append( $pod_para ); } sub verbatim { my ($parser, $paragraph, $line_num, $pod_para) = @_; $parser->parse_tree()->append( $pod_para ); } sub textblock { my ($parser, $paragraph, $line_num, $pod_para) = @_; my $ptree = $parser->parse_text({<>}, $paragraph, ...); $pod_para->parse_tree( $ptree ); $parser->parse_tree()->append( $pod_para ); } ... package main; ... my $parser = new MyPodParserTree2(...); $parser->parse_from_file(...); my $ptree = $parser->parse_tree; ... Now you have the entire POD document as one great big parse-tree. You can even use the B<-expand_seq> option to B to insert whole different kinds of objects. Just don't expect B to know what to do with them after that. That will need to be in your code. Or, alternatively, you can insert any object you like so long as it conforms to the B interface. One could use this to create subclasses of B and B for specific commands (or to create your own custom node-types in the parse-tree) and add some kind of B method to each custom node/subclass object in the tree. Then all you'd need to do is recursively walk the tree in the desired order, processing the children (most likely from left to right) by formatting them if they are text-strings, or by calling their B method if they are objects/references. =head1 CAVEATS Please note that POD has the notion of "paragraphs": this is something starting I a blank (read: empty) line, with the single exception of the file start, which is also starting a paragraph. That means that especially a command (e.g. C<=head1>) I be preceded with a blank line; C<__END__> is I a blank line. =head1 SEE ALSO L, L B defines POD input objects corresponding to command paragraphs, parse-trees, and interior-sequences. B is a subclass of B which provides the ability to selectively include and/or exclude sections of a POD document from being translated based upon the current heading, subheading, subsubheading, etc. =for __PRIVATE__ B is a subclass of B which gives its users the ability the employ I instead of, or in addition to, overriding methods of the base class. =for __PRIVATE__ B and B do not override any methods nor do they define any new methods with the same name. Because of this, they may I be used (in combination) as a base class of the same subclass in order to combine their functionality without causing any namespace clashes due to multiple inheritance. =head1 AUTHOR Please report bugs using L. Brad Appleton Ebradapp@enteract.comE Based on code for B written by Tom Christiansen Etchrist@mox.perl.comE =head1 LICENSE Pod-Parser is free software; you can redistribute it and/or modify it under the terms of the Artistic License distributed with Perl version 5.000 or (at your option) any later version. Please refer to the Artistic License that came with your Perl distribution for more details. If your version of Perl was not distributed under the terms of the Artistic License, than you may distribute PodParser under the same terms as Perl itself. =cut 1; # vim: ts=4 sw=4 et mrtg-2.17.10/lib/mrtg2/Pod/PlainText.pm0000644000175300017510000006126013057016062016444 0ustar oetikeroep# Pod::PlainText -- Convert POD data to formatted ASCII text. # $Id: Text.pm,v 2.1 1999/09/20 11:53:33 eagle Exp $ # # Copyright 1999-2000 by Russ Allbery # # This program is free software; you can redistribute it and/or modify it # under the same terms as Perl itself. # # This module is intended to be a replacement for Pod::Text, and attempts to # match its output except for some specific circumstances where other # decisions seemed to produce better output. It uses Pod::Parser and is # designed to be very easy to subclass. ############################################################################ # Modules and declarations ############################################################################ package Pod::PlainText; use strict; require 5.005; use Carp qw(carp croak); use Pod::Select (); use vars qw(@ISA %ESCAPES $VERSION); # We inherit from Pod::Select instead of Pod::Parser so that we can be used # by Pod::Usage. @ISA = qw(Pod::Select); $VERSION = '2.04'; BEGIN { if ($] < 5.006) { require Symbol; import Symbol; } } ############################################################################ # Table of supported E<> escapes ############################################################################ # This table is taken near verbatim from Pod::PlainText in Pod::Parser, # which got it near verbatim from the original Pod::Text. It is therefore # credited to Tom Christiansen, and I'm glad I didn't have to write it. :) %ESCAPES = ( 'amp' => '&', # ampersand 'lt' => '<', # left chevron, less-than 'gt' => '>', # right chevron, greater-than 'quot' => '"', # double quote "Aacute" => "\xC1", # capital A, acute accent "aacute" => "\xE1", # small a, acute accent "Acirc" => "\xC2", # capital A, circumflex accent "acirc" => "\xE2", # small a, circumflex accent "AElig" => "\xC6", # capital AE diphthong (ligature) "aelig" => "\xE6", # small ae diphthong (ligature) "Agrave" => "\xC0", # capital A, grave accent "agrave" => "\xE0", # small a, grave accent "Aring" => "\xC5", # capital A, ring "aring" => "\xE5", # small a, ring "Atilde" => "\xC3", # capital A, tilde "atilde" => "\xE3", # small a, tilde "Auml" => "\xC4", # capital A, dieresis or umlaut mark "auml" => "\xE4", # small a, dieresis or umlaut mark "Ccedil" => "\xC7", # capital C, cedilla "ccedil" => "\xE7", # small c, cedilla "Eacute" => "\xC9", # capital E, acute accent "eacute" => "\xE9", # small e, acute accent "Ecirc" => "\xCA", # capital E, circumflex accent "ecirc" => "\xEA", # small e, circumflex accent "Egrave" => "\xC8", # capital E, grave accent "egrave" => "\xE8", # small e, grave accent "ETH" => "\xD0", # capital Eth, Icelandic "eth" => "\xF0", # small eth, Icelandic "Euml" => "\xCB", # capital E, dieresis or umlaut mark "euml" => "\xEB", # small e, dieresis or umlaut mark "Iacute" => "\xCD", # capital I, acute accent "iacute" => "\xED", # small i, acute accent "Icirc" => "\xCE", # capital I, circumflex accent "icirc" => "\xEE", # small i, circumflex accent "Igrave" => "\xCD", # capital I, grave accent "igrave" => "\xED", # small i, grave accent "Iuml" => "\xCF", # capital I, dieresis or umlaut mark "iuml" => "\xEF", # small i, dieresis or umlaut mark "Ntilde" => "\xD1", # capital N, tilde "ntilde" => "\xF1", # small n, tilde "Oacute" => "\xD3", # capital O, acute accent "oacute" => "\xF3", # small o, acute accent "Ocirc" => "\xD4", # capital O, circumflex accent "ocirc" => "\xF4", # small o, circumflex accent "Ograve" => "\xD2", # capital O, grave accent "ograve" => "\xF2", # small o, grave accent "Oslash" => "\xD8", # capital O, slash "oslash" => "\xF8", # small o, slash "Otilde" => "\xD5", # capital O, tilde "otilde" => "\xF5", # small o, tilde "Ouml" => "\xD6", # capital O, dieresis or umlaut mark "ouml" => "\xF6", # small o, dieresis or umlaut mark "szlig" => "\xDF", # small sharp s, German (sz ligature) "THORN" => "\xDE", # capital THORN, Icelandic "thorn" => "\xFE", # small thorn, Icelandic "Uacute" => "\xDA", # capital U, acute accent "uacute" => "\xFA", # small u, acute accent "Ucirc" => "\xDB", # capital U, circumflex accent "ucirc" => "\xFB", # small u, circumflex accent "Ugrave" => "\xD9", # capital U, grave accent "ugrave" => "\xF9", # small u, grave accent "Uuml" => "\xDC", # capital U, dieresis or umlaut mark "uuml" => "\xFC", # small u, dieresis or umlaut mark "Yacute" => "\xDD", # capital Y, acute accent "yacute" => "\xFD", # small y, acute accent "yuml" => "\xFF", # small y, dieresis or umlaut mark "lchevron" => "\xAB", # left chevron (double less than) "rchevron" => "\xBB", # right chevron (double greater than) ); ############################################################################ # Initialization ############################################################################ # Initialize the object. Must be sure to call our parent initializer. sub initialize { my $self = shift; $$self{alt} = 0 unless defined $$self{alt}; $$self{indent} = 4 unless defined $$self{indent}; $$self{loose} = 0 unless defined $$self{loose}; $$self{sentence} = 0 unless defined $$self{sentence}; $$self{width} = 76 unless defined $$self{width}; $$self{INDENTS} = []; # Stack of indentations. $$self{MARGIN} = $$self{indent}; # Current left margin in spaces. return $self->SUPER::initialize; } ############################################################################ # Core overrides ############################################################################ # Called for each command paragraph. Gets the command, the associated # paragraph, the line number, and a Pod::Paragraph object. Just dispatches # the command to a method named the same as the command. =cut is handled # internally by Pod::Parser. sub command { my $self = shift; my $command = shift; return if $command eq 'pod'; return if ($$self{EXCLUDE} && $command ne 'end'); if (defined $$self{ITEM}) { $self->item ("\n"); local $_ = "\n"; $self->output($_) if($command eq 'back'); } $command = 'cmd_' . $command; return $self->$command (@_); } # Called for a verbatim paragraph. Gets the paragraph, the line number, and # a Pod::Paragraph object. Just output it verbatim, but with tabs converted # to spaces. sub verbatim { my $self = shift; return if $$self{EXCLUDE}; $self->item if defined $$self{ITEM}; local $_ = shift; return if /^\s*$/; s/^(\s*\S+)/(' ' x $$self{MARGIN}) . $1/gme; return $self->output($_); } # Called for a regular text block. Gets the paragraph, the line number, and # a Pod::Paragraph object. Perform interpolation and output the results. sub textblock { my $self = shift; return if $$self{EXCLUDE}; if($$self{VERBATIM}) { $self->output($_[0]); return; } local $_ = shift; my $line = shift; # Perform a little magic to collapse multiple L<> references. This is # here mostly for backwards-compatibility. We'll just rewrite the whole # thing into actual text at this part, bypassing the whole internal # sequence parsing thing. s{ ( L< # A link of the form L. / ( [:\w]+ # The item has to be a simple word... (\(\))? # ...or simple function. ) > ( ,?\s+(and\s+)? # Allow lots of them, conjuncted. L< / ( [:\w]+ (\(\))? ) > )+ ) } { local $_ = $1; s%L]+)>%$1%g; my @items = split /(?:,?\s+(?:and\s+)?)/; my $string = "the "; my $i; for ($i = 0; $i < @items; $i++) { $string .= $items[$i]; $string .= ", " if @items > 2 && $i != $#items; $string .= " and " if ($i == $#items - 1); } $string .= " entries elsewhere in this document"; $string; }gex; # Now actually interpolate and output the paragraph. $_ = $self->interpolate ($_, $line); s/\s*$/\n/s; if (defined $$self{ITEM}) { $self->item ($_ . "\n"); } else { $self->output ($self->reformat ($_ . "\n")); } } # Called for an interior sequence. Gets the command, argument, and a # Pod::InteriorSequence object and is expected to return the resulting text. # Calls code, bold, italic, file, and link to handle those types of # sequences, and handles S<>, E<>, X<>, and Z<> directly. sub interior_sequence { my $self = shift; my $command = shift; local $_ = shift; return '' if ($command eq 'X' || $command eq 'Z'); # Expand escapes into the actual character now, carping if invalid. if ($command eq 'E') { return $ESCAPES{$_} if defined $ESCAPES{$_}; carp "Unknown escape: E<$_>"; return "E<$_>"; } # For all the other sequences, empty content produces no output. return if $_ eq ''; # For S<>, compress all internal whitespace and then map spaces to \01. # When we output the text, we'll map this back. if ($command eq 'S') { s/\s{2,}/ /g; tr/ /\01/; return $_; } # Anything else needs to get dispatched to another method. if ($command eq 'B') { return $self->seq_b ($_) } elsif ($command eq 'C') { return $self->seq_c ($_) } elsif ($command eq 'F') { return $self->seq_f ($_) } elsif ($command eq 'I') { return $self->seq_i ($_) } elsif ($command eq 'L') { return $self->seq_l ($_) } else { carp "Unknown sequence $command<$_>" } } # Called for each paragraph that's actually part of the POD. We take # advantage of this opportunity to untabify the input. sub preprocess_paragraph { my $self = shift; local $_ = shift; 1 while s/^(.*?)(\t+)/$1 . ' ' x (length ($2) * 8 - length ($1) % 8)/me; return $_; } ############################################################################ # Command paragraphs ############################################################################ # All command paragraphs take the paragraph and the line number. # First level heading. sub cmd_head1 { my $self = shift; local $_ = shift; s/\s+$//s; $_ = $self->interpolate ($_, shift); if ($$self{alt}) { $self->output ("\n==== $_ ====\n\n"); } else { $_ .= "\n" if $$self{loose}; $self->output ($_ . "\n"); } } # Second level heading. sub cmd_head2 { my $self = shift; local $_ = shift; s/\s+$//s; $_ = $self->interpolate ($_, shift); if ($$self{alt}) { $self->output ("\n== $_ ==\n\n"); } else { $_ .= "\n" if $$self{loose}; $self->output (' ' x ($$self{indent} / 2) . $_ . "\n"); } } # third level heading - not strictly perlpodspec compliant sub cmd_head3 { my $self = shift; local $_ = shift; s/\s+$//s; $_ = $self->interpolate ($_, shift); if ($$self{alt}) { $self->output ("\n= $_ =\n"); } else { $_ .= "\n" if $$self{loose}; $self->output (' ' x ($$self{indent}) . $_ . "\n"); } } # fourth level heading - not strictly perlpodspec compliant # just like head3 *cmd_head4 = \&cmd_head3; # Start a list. sub cmd_over { my $self = shift; local $_ = shift; unless (/^[-+]?\d+\s+$/) { $_ = $$self{indent} } push (@{ $$self{INDENTS} }, $$self{MARGIN}); $$self{MARGIN} += ($_ + 0); } # End a list. sub cmd_back { my $self = shift; $$self{MARGIN} = pop @{ $$self{INDENTS} }; unless (defined $$self{MARGIN}) { carp 'Unmatched =back'; $$self{MARGIN} = $$self{indent}; } } # An individual list item. sub cmd_item { my $self = shift; if (defined $$self{ITEM}) { $self->item } local $_ = shift; s/\s+$//s; $$self{ITEM} = $self->interpolate ($_); } # Begin a block for a particular translator. Setting VERBATIM triggers # special handling in textblock(). sub cmd_begin { my $self = shift; local $_ = shift; my ($kind) = /^(\S+)/ or return; if ($kind eq 'text') { $$self{VERBATIM} = 1; } else { $$self{EXCLUDE} = 1; } } # End a block for a particular translator. We assume that all =begin/=end # pairs are properly closed. sub cmd_end { my $self = shift; $$self{EXCLUDE} = 0; $$self{VERBATIM} = 0; } # One paragraph for a particular translator. Ignore it unless it's intended # for text, in which case we treat it as a verbatim text block. sub cmd_for { my $self = shift; local $_ = shift; my $line = shift; return unless s/^text\b[ \t]*\n?//; $self->verbatim ($_, $line); } ############################################################################ # Interior sequences ############################################################################ # The simple formatting ones. These are here mostly so that subclasses can # override them and do more complicated things. sub seq_b { return $_[0]{alt} ? "``$_[1]''" : $_[1] } sub seq_c { return $_[0]{alt} ? "``$_[1]''" : "`$_[1]'" } sub seq_f { return $_[0]{alt} ? "\"$_[1]\"" : $_[1] } sub seq_i { return '*' . $_[1] . '*' } # The complicated one. Handle links. Since this is plain text, we can't # actually make any real links, so this is all to figure out what text we # print out. sub seq_l { my $self = shift; local $_ = shift; # Smash whitespace in case we were split across multiple lines. s/\s+/ /g; # If we were given any explicit text, just output it. if (/^([^|]+)\|/) { return $1 } # Okay, leading and trailing whitespace isn't important; get rid of it. s/^\s+//; s/\s+$//; # Default to using the whole content of the link entry as a section # name. Note that L forces a manpage interpretation, as does # something looking like L. The latter is an # enhancement over the original Pod::Text. my ($manpage, $section) = ('', $_); if (/^(?:https?|ftp|news):/) { # a URL return $_; } elsif (/^"\s*(.*?)\s*"$/) { $section = '"' . $1 . '"'; } elsif (m/^[-:.\w]+(?:\(\S+\))?$/) { ($manpage, $section) = ($_, ''); } elsif (m{/}) { ($manpage, $section) = split (/\s*\/\s*/, $_, 2); } my $text = ''; # Now build the actual output text. if (!length $section) { $text = "the $manpage manpage" if length $manpage; } elsif ($section =~ /^[:\w]+(?:\(\))?/) { $text .= 'the ' . $section . ' entry'; $text .= (length $manpage) ? " in the $manpage manpage" : ' elsewhere in this document'; } else { $section =~ s/^\"\s*//; $section =~ s/\s*\"$//; $text .= 'the section on "' . $section . '"'; $text .= " in the $manpage manpage" if length $manpage; } return $text; } ############################################################################ # List handling ############################################################################ # This method is called whenever an =item command is complete (in other # words, we've seen its associated paragraph or know for certain that it # doesn't have one). It gets the paragraph associated with the item as an # argument. If that argument is empty, just output the item tag; if it # contains a newline, output the item tag followed by the newline. # Otherwise, see if there's enough room for us to output the item tag in the # margin of the text or if we have to put it on a separate line. sub item { my $self = shift; local $_ = shift; my $tag = $$self{ITEM}; unless (defined $tag) { carp 'item called without tag'; return; } undef $$self{ITEM}; my $indent = $$self{INDENTS}[-1]; unless (defined $indent) { $indent = $$self{indent} } my $space = ' ' x $indent; $space =~ s/^ /:/ if $$self{alt}; if (!$_ || /^\s+$/ || ($$self{MARGIN} - $indent < length ($tag) + 1)) { my $margin = $$self{MARGIN}; $$self{MARGIN} = $indent; my $output = $self->reformat ($tag); $output =~ s/\n*$/\n/; $self->output ($output); $$self{MARGIN} = $margin; $self->output ($self->reformat ($_)) if /\S/; } else { $_ = $self->reformat ($_); s/^ /:/ if ($$self{alt} && $indent > 0); my $tagspace = ' ' x length $tag; s/^($space)$tagspace/$1$tag/ or carp 'Bizarre space in item'; $self->output ($_); } } ############################################################################ # Output formatting ############################################################################ # Wrap a line, indenting by the current left margin. We can't use # Text::Wrap because it plays games with tabs. We can't use formline, even # though we'd really like to, because it screws up non-printing characters. # So we have to do the wrapping ourselves. sub wrap { my $self = shift; local $_ = shift; my $output = ''; my $spaces = ' ' x $$self{MARGIN}; my $width = $$self{width} - $$self{MARGIN}; while (length > $width) { if (s/^([^\n]{0,$width})\s+// || s/^([^\n]{$width})//) { $output .= $spaces . $1 . "\n"; } else { last; } } $output .= $spaces . $_; $output =~ s/\s+$/\n\n/; return $output; } # Reformat a paragraph of text for the current margin. Takes the text to # reformat and returns the formatted text. sub reformat { my $self = shift; local $_ = shift; # If we're trying to preserve two spaces after sentences, do some # munging to support that. Otherwise, smash all repeated whitespace. if ($$self{sentence}) { s/ +$//mg; s/\.\n/. \n/g; s/\n/ /g; s/ +/ /g; } else { s/\s+/ /g; } return $self->wrap($_); } # Output text to the output device. sub output { $_[1] =~ tr/\01/ /; print { $_[0]->output_handle } $_[1] } ############################################################################ # Backwards compatibility ############################################################################ # The old Pod::Text module did everything in a pod2text() function. This # tries to provide the same interface for legacy applications. sub pod2text { my @args; # This is really ugly; I hate doing option parsing in the middle of a # module. But the old Pod::Text module supported passing flags to its # entry function, so handle -a and -. while ($_[0] =~ /^-/) { my $flag = shift; if ($flag eq '-a') { push (@args, alt => 1) } elsif ($flag =~ /^-(\d+)$/) { push (@args, width => $1) } else { unshift (@_, $flag); last; } } # Now that we know what arguments we're using, create the parser. my $parser = Pod::PlainText->new (@args); # If two arguments were given, the second argument is going to be a file # handle. That means we want to call parse_from_filehandle(), which # means we need to turn the first argument into a file handle. Magic # open will handle the <&STDIN case automagically. if (defined $_[1]) { my $infh; if ($] < 5.006) { $infh = gensym(); } unless (open ($infh, $_[0])) { croak ("Can't open $_[0] for reading: $!\n"); } $_[0] = $infh; return $parser->parse_from_filehandle (@_); } else { return $parser->parse_from_file (@_); } } ############################################################################ # Module return value and documentation ############################################################################ 1; __END__ =head1 NAME Pod::PlainText - Convert POD data to formatted ASCII text =head1 SYNOPSIS use Pod::PlainText; my $parser = Pod::PlainText->new (sentence => 0, width => 78); # Read POD from STDIN and write to STDOUT. $parser->parse_from_filehandle; # Read POD from file.pod and write to file.txt. $parser->parse_from_file ('file.pod', 'file.txt'); =head1 DESCRIPTION Pod::PlainText is a module that can convert documentation in the POD format (the preferred language for documenting Perl) into formatted ASCII. It uses no special formatting controls or codes whatsoever, and its output is therefore suitable for nearly any device. As a derived class from Pod::Parser, Pod::PlainText supports the same methods and interfaces. See L for all the details; briefly, one creates a new parser with Cnew()> and then calls either parse_from_filehandle() or parse_from_file(). new() can take options, in the form of key/value pairs, that control the behavior of the parser. The currently recognized options are: =over 4 =item alt If set to a true value, selects an alternate output format that, among other things, uses a different heading style and marks C<=item> entries with a colon in the left margin. Defaults to false. =item indent The number of spaces to indent regular text, and the default indentation for C<=over> blocks. Defaults to 4. =item loose If set to a true value, a blank line is printed after a C<=headN> headings. If set to false (the default), no blank line is printed after C<=headN>. This is the default because it's the expected formatting for manual pages; if you're formatting arbitrary text documents, setting this to true may result in more pleasing output. =item sentence If set to a true value, Pod::PlainText will assume that each sentence ends in two spaces, and will try to preserve that spacing. If set to false, all consecutive whitespace in non-verbatim paragraphs is compressed into a single space. Defaults to true. =item width The column at which to wrap text on the right-hand side. Defaults to 76. =back The standard Pod::Parser method parse_from_filehandle() takes up to two arguments, the first being the file handle to read POD from and the second being the file handle to write the formatted output to. The first defaults to STDIN if not given, and the second defaults to STDOUT. The method parse_from_file() is almost identical, except that its two arguments are the input and output disk files instead. See L for the specific details. =head1 DIAGNOSTICS =over 4 =item Bizarre space in item (W) Something has gone wrong in internal C<=item> processing. This message indicates a bug in Pod::PlainText; you should never see it. =item Can't open %s for reading: %s (F) Pod::PlainText was invoked via the compatibility mode pod2text() interface and the input file it was given could not be opened. =item Unknown escape: %s (W) The POD source contained an CE> escape that Pod::PlainText didn't know about. =item Unknown sequence: %s (W) The POD source contained a non-standard internal sequence (something of the form CE>) that Pod::PlainText didn't know about. =item Unmatched =back (W) Pod::PlainText encountered a C<=back> command that didn't correspond to an C<=over> command. =back =head1 RESTRICTIONS Embedded Ctrl-As (octal 001) in the input will be mapped to spaces on output, due to an internal implementation detail. =head1 NOTES This is a replacement for an earlier Pod::Text module written by Tom Christiansen. It has a revamped interface, since it now uses Pod::Parser, but an interface roughly compatible with the old Pod::Text::pod2text() function is still available. Please change to the new calling convention, though. The original Pod::Text contained code to do formatting via termcap sequences, although it wasn't turned on by default and it was problematic to get it to work at all. This rewrite doesn't even try to do that, but a subclass of it does. Look for L. =head1 SEE ALSO L, L, pod2text(1) =head1 AUTHOR Please report bugs using L. Russ Allbery Erra@stanford.eduE, based I heavily on the original Pod::Text by Tom Christiansen Etchrist@mox.perl.comE and its conversion to Pod::Parser by Brad Appleton Ebradapp@enteract.comE. =cut mrtg-2.17.10/lib/mrtg2/Pod/Select.pm0000644000175300017510000005701013057016062015751 0ustar oetikeroep############################################################################# # Pod/Select.pm -- function to select portions of POD docs # # Copyright (C) 1996-2000 by Bradford Appleton. All rights reserved. # This file is part of "PodParser". PodParser is free software; # you can redistribute it and/or modify it under the same terms # as Perl itself. ############################################################################# package Pod::Select; use strict; use vars qw($VERSION @ISA @EXPORT $MAX_HEADING_LEVEL %myData @section_headings @selected_sections); $VERSION = '1.36'; ## Current version of this package require 5.005; ## requires this Perl version or later ############################################################################# =head1 NAME Pod::Select, podselect() - extract selected sections of POD from input =head1 SYNOPSIS use Pod::Select; ## Select all the POD sections for each file in @filelist ## and print the result on standard output. podselect(@filelist); ## Same as above, but write to tmp.out podselect({-output => "tmp.out"}, @filelist): ## Select from the given filelist, only those POD sections that are ## within a 1st level section named any of: NAME, SYNOPSIS, OPTIONS. podselect({-sections => ["NAME|SYNOPSIS", "OPTIONS"]}, @filelist): ## Select the "DESCRIPTION" section of the PODs from STDIN and write ## the result to STDERR. podselect({-output => ">&STDERR", -sections => ["DESCRIPTION"]}, \*STDIN); or use Pod::Select; ## Create a parser object for selecting POD sections from the input $parser = new Pod::Select(); ## Select all the POD sections for each file in @filelist ## and print the result to tmp.out. $parser->parse_from_file("<&STDIN", "tmp.out"); ## Select from the given filelist, only those POD sections that are ## within a 1st level section named any of: NAME, SYNOPSIS, OPTIONS. $parser->select("NAME|SYNOPSIS", "OPTIONS"); for (@filelist) { $parser->parse_from_file($_); } ## Select the "DESCRIPTION" and "SEE ALSO" sections of the PODs from ## STDIN and write the result to STDERR. $parser->select("DESCRIPTION"); $parser->add_selection("SEE ALSO"); $parser->parse_from_filehandle(\*STDIN, \*STDERR); =head1 REQUIRES perl5.005, Pod::Parser, Exporter, Carp =head1 EXPORTS podselect() =head1 DESCRIPTION B is a function which will extract specified sections of pod documentation from an input stream. This ability is provided by the B module which is a subclass of B. B provides a method named B to specify the set of POD sections to select for processing/printing. B merely creates a B object and then invokes the B followed by B. =head1 SECTION SPECIFICATIONS B and B may be given one or more "section specifications" to restrict the text processed to only the desired set of sections and their corresponding subsections. A section specification is a string containing one or more Perl-style regular expressions separated by forward slashes ("/"). If you need to use a forward slash literally within a section title you can escape it with a backslash ("\/"). The formal syntax of a section specification is: =over 4 =item * I/I/... =back Any omitted or empty regular expressions will default to ".*". Please note that each regular expression given is implicitly anchored by adding "^" and "$" to the beginning and end. Also, if a given regular expression starts with a "!" character, then the expression is I (so C would match anything I C). Some example section specifications follow. =over 4 =item * Match the C and C sections and all of their subsections: C =item * Match only the C and C subsections of the C section: C =item * Match the C subsection of I sections: C =item * Match all subsections of C I for C: C =item * Match the C section but do I match any of its subsections: C =item * Match all top level sections but none of their subsections: C =back =begin _NOT_IMPLEMENTED_ =head1 RANGE SPECIFICATIONS B and B may be given one or more "range specifications" to restrict the text processed to only the desired ranges of paragraphs in the desired set of sections. A range specification is a string containing a single Perl-style regular expression (a regex), or else two Perl-style regular expressions (regexs) separated by a ".." (Perl's "range" operator is ".."). The regexs in a range specification are delimited by forward slashes ("/"). If you need to use a forward slash literally within a regex you can escape it with a backslash ("\/"). The formal syntax of a range specification is: =over 4 =item * /I/[../I/] =back Where each the item inside square brackets (the ".." followed by the end-range-regex) is optional. Each "range-regex" is of the form: =cmd-expr text-expr Where I is intended to match the name of one or more POD commands, and I is intended to match the paragraph text for the command. If a range-regex is supposed to match a POD command, then the first character of the regex (the one after the initial '/') absolutely I be a single '=' character; it may not be anything else (not even a regex meta-character) if it is supposed to match against the name of a POD command. If no I<=cmd-expr> is given then the text-expr will be matched against plain textblocks unless it is preceded by a space, in which case it is matched against verbatim text-blocks. If no I is given then only the command-portion of the paragraph is matched against. Note that these two expressions are each implicitly anchored. This means that when matching against the command-name, there will be an implicit '^' and '$' around the given I<=cmd-expr>; and when matching against the paragraph text there will be an implicit '\A' and '\Z' around the given I. Unlike with section-specs, the '!' character does I have any special meaning (negation or otherwise) at the beginning of a range-spec! Some example range specifications follow. =over 4 =item Match all C<=for html> paragraphs: C =item Match all paragraphs between C<=begin html> and C<=end html> (note that this will I work correctly if such sections are nested): C =item Match all paragraphs between the given C<=item> name until the end of the current section: C =item Match all paragraphs between the given C<=item> until the next item, or until the end of the itemized list (note that this will I work as desired if the item contains an itemized list nested within it): C =back =end _NOT_IMPLEMENTED_ =cut ############################################################################# #use diagnostics; use Carp; use Pod::Parser 1.04; @ISA = qw(Pod::Parser); @EXPORT = qw(&podselect); ## Maximum number of heading levels supported for '=headN' directives *MAX_HEADING_LEVEL = \3; ############################################################################# =head1 OBJECT METHODS The following methods are provided in this module. Each one takes a reference to the object itself as an implicit first parameter. =cut ##--------------------------------------------------------------------------- ## =begin _PRIVATE_ ## ## =head1 B<_init_headings()> ## ## Initialize the current set of active section headings. ## ## =cut ## ## =end _PRIVATE_ sub _init_headings { my $self = shift; local *myData = $self; ## Initialize current section heading titles if necessary unless (defined $myData{_SECTION_HEADINGS}) { local *section_headings = $myData{_SECTION_HEADINGS} = []; for (my $i = 0; $i < $MAX_HEADING_LEVEL; ++$i) { $section_headings[$i] = ''; } } } ##--------------------------------------------------------------------------- =head1 B ($head1, $head2, $head3, ...) = $parser->curr_headings(); $head1 = $parser->curr_headings(1); This method returns a list of the currently active section headings and subheadings in the document being parsed. The list of headings returned corresponds to the most recently parsed paragraph of the input. If an argument is given, it must correspond to the desired section heading number, in which case only the specified section heading is returned. If there is no current section heading at the specified level, then C is returned. =cut sub curr_headings { my $self = shift; $self->_init_headings() unless (defined $self->{_SECTION_HEADINGS}); my @headings = @{ $self->{_SECTION_HEADINGS} }; return (@_ > 0 and $_[0] =~ /^\d+$/) ? $headings[$_[0] - 1] : @headings; } ##--------------------------------------------------------------------------- =head1 B $parser->select($section_spec1,$section_spec2,...); This method is used to select the particular sections and subsections of POD documentation that are to be printed and/or processed. The existing set of selected sections is I with the given set of sections. See B for adding to the current set of selected sections. Each of the C<$section_spec> arguments should be a section specification as described in L<"SECTION SPECIFICATIONS">. The section specifications are parsed by this method and the resulting regular expressions are stored in the invoking object. If no C<$section_spec> arguments are given, then the existing set of selected sections is cleared out (which means C sections will be processed). This method should I normally be overridden by subclasses. =cut sub select { my ($self, @sections) = @_; local *myData = $self; local $_; ### NEED TO DISCERN A SECTION-SPEC FROM A RANGE-SPEC (look for m{^/.+/$}?) ##--------------------------------------------------------------------- ## The following is a blatant hack for backward compatibility, and for ## implementing add_selection(). If the *first* *argument* is the ## string "+", then the remaining section specifications are *added* ## to the current set of selections; otherwise the given section ## specifications will *replace* the current set of selections. ## ## This should probably be fixed someday, but for the present time, ## it seems incredibly unlikely that "+" would ever correspond to ## a legitimate section heading ##--------------------------------------------------------------------- my $add = ($sections[0] eq '+') ? shift(@sections) : ''; ## Reset the set of sections to use unless (@sections) { delete $myData{_SELECTED_SECTIONS} unless ($add); return; } $myData{_SELECTED_SECTIONS} = [] unless ($add && exists $myData{_SELECTED_SECTIONS}); local *selected_sections = $myData{_SELECTED_SECTIONS}; ## Compile each spec for my $spec (@sections) { if ( defined($_ = _compile_section_spec($spec)) ) { ## Store them in our sections array push(@selected_sections, $_); } else { carp qq{Ignoring section spec "$spec"!\n}; } } } ##--------------------------------------------------------------------------- =head1 B $parser->add_selection($section_spec1,$section_spec2,...); This method is used to add to the currently selected sections and subsections of POD documentation that are to be printed and/or processed. See for replacing the currently selected sections. Each of the C<$section_spec> arguments should be a section specification as described in L<"SECTION SPECIFICATIONS">. The section specifications are parsed by this method and the resulting regular expressions are stored in the invoking object. This method should I normally be overridden by subclasses. =cut sub add_selection { my $self = shift; return $self->select('+', @_); } ##--------------------------------------------------------------------------- =head1 B $parser->clear_selections(); This method takes no arguments, it has the exact same effect as invoking with no arguments. =cut sub clear_selections { my $self = shift; return $self->select(); } ##--------------------------------------------------------------------------- =head1 B $boolean = $parser->match_section($heading1,$heading2,...); Returns a value of true if the given section and subsection heading titles match any of the currently selected section specifications in effect from prior calls to B and B (or if there are no explicitly selected/deselected sections). The arguments C<$heading1>, C<$heading2>, etc. are the heading titles of the corresponding sections, subsections, etc. to try and match. If C<$headingN> is omitted then it defaults to the current corresponding section heading title in the input. This method should I normally be overridden by subclasses. =cut sub match_section { my $self = shift; my (@headings) = @_; local *myData = $self; ## Return true if no restrictions were explicitly specified my $selections = (exists $myData{_SELECTED_SECTIONS}) ? $myData{_SELECTED_SECTIONS} : undef; return 1 unless ((defined $selections) && @{$selections}); ## Default any unspecified sections to the current one my @current_headings = $self->curr_headings(); for (my $i = 0; $i < $MAX_HEADING_LEVEL; ++$i) { (defined $headings[$i]) or $headings[$i] = $current_headings[$i]; } ## Look for a match against the specified section expressions for my $section_spec ( @{$selections} ) { ##------------------------------------------------------ ## Each portion of this spec must match in order for ## the spec to be matched. So we will start with a ## match-value of 'true' and logically 'and' it with ## the results of matching a given element of the spec. ##------------------------------------------------------ my $match = 1; for (my $i = 0; $i < $MAX_HEADING_LEVEL; ++$i) { my $regex = $section_spec->[$i]; my $negated = ($regex =~ s/^\!//); $match &= ($negated ? ($headings[$i] !~ /${regex}/) : ($headings[$i] =~ /${regex}/)); last unless ($match); } return 1 if ($match); } return 0; ## no match } ##--------------------------------------------------------------------------- =head1 B $boolean = $parser->is_selected($paragraph); This method is used to determine if the block of text given in C<$paragraph> falls within the currently selected set of POD sections and subsections to be printed or processed. This method is also responsible for keeping track of the current input section and subsections. It is assumed that C<$paragraph> is the most recently read (but not yet processed) input paragraph. The value returned will be true if the C<$paragraph> and the rest of the text in the same section as C<$paragraph> should be selected (included) for processing; otherwise a false value is returned. =cut sub is_selected { my ($self, $paragraph) = @_; local $_; local *myData = $self; $self->_init_headings() unless (defined $myData{_SECTION_HEADINGS}); ## Keep track of current sections levels and headings $_ = $paragraph; if (/^=((?:sub)*)(?:head(?:ing)?|sec(?:tion)?)(\d*)\s+(.*?)\s*$/) { ## This is a section heading command my ($level, $heading) = ($2, $3); $level = 1 + (length($1) / 3) if ((! length $level) || (length $1)); ## Reset the current section heading at this level $myData{_SECTION_HEADINGS}->[$level - 1] = $heading; ## Reset subsection headings of this one to empty for (my $i = $level; $i < $MAX_HEADING_LEVEL; ++$i) { $myData{_SECTION_HEADINGS}->[$i] = ''; } } return $self->match_section(); } ############################################################################# =head1 EXPORTED FUNCTIONS The following functions are exported by this module. Please note that these are functions (not methods) and therefore C take an implicit first argument. =cut ##--------------------------------------------------------------------------- =head1 B podselect(\%options,@filelist); B will print the raw (untranslated) POD paragraphs of all POD sections in the given input files specified by C<@filelist> according to the given options. If any argument to B is a reference to a hash (associative array) then the values with the following keys are processed as follows: =over 4 =item B<-output> A string corresponding to the desired output file (or ">&STDOUT" or ">&STDERR"). The default is to use standard output. =item B<-sections> A reference to an array of sections specifications (as described in L<"SECTION SPECIFICATIONS">) which indicate the desired set of POD sections and subsections to be selected from input. If no section specifications are given, then all sections of the PODs are used. =begin _NOT_IMPLEMENTED_ =item B<-ranges> A reference to an array of range specifications (as described in L<"RANGE SPECIFICATIONS">) which indicate the desired range of POD paragraphs to be selected from the desired input sections. If no range specifications are given, then all paragraphs of the desired sections are used. =end _NOT_IMPLEMENTED_ =back All other arguments should correspond to the names of input files containing POD sections. A file name of "-" or "<&STDIN" will be interpreted to mean standard input (which is the default if no filenames are given). =cut sub podselect { my(@argv) = @_; my %defaults = (); my $pod_parser = new Pod::Select(%defaults); my $num_inputs = 0; my $output = '>&STDOUT'; my %opts; local $_; for (@argv) { if (ref($_)) { next unless (ref($_) eq 'HASH'); %opts = (%defaults, %{$_}); ##------------------------------------------------------------- ## Need this for backward compatibility since we formerly used ## options that were all uppercase words rather than ones that ## looked like Unix command-line options. ## to be uppercase keywords) ##------------------------------------------------------------- %opts = map { my ($key, $val) = (lc $_, $opts{$_}); $key =~ s/^(?=\w)/-/; $key =~ /^-se[cl]/ and $key = '-sections'; #! $key eq '-range' and $key .= 's'; ($key => $val); } (keys %opts); ## Process the options (exists $opts{'-output'}) and $output = $opts{'-output'}; ## Select the desired sections $pod_parser->select(@{ $opts{'-sections'} }) if ( (defined $opts{'-sections'}) && ((ref $opts{'-sections'}) eq 'ARRAY') ); #! ## Select the desired paragraph ranges #! $pod_parser->select(@{ $opts{'-ranges'} }) #! if ( (defined $opts{'-ranges'}) #! && ((ref $opts{'-ranges'}) eq 'ARRAY') ); } else { $pod_parser->parse_from_file($_, $output); ++$num_inputs; } } $pod_parser->parse_from_file('-') unless ($num_inputs > 0); } ############################################################################# =head1 PRIVATE METHODS AND DATA B makes uses a number of internal methods and data fields which clients should not need to see or use. For the sake of avoiding name collisions with client data and methods, these methods and fields are briefly discussed here. Determined hackers may obtain further information about them by reading the B source code. Private data fields are stored in the hash-object whose reference is returned by the B constructor for this class. The names of all private methods and data-fields used by B begin with a prefix of "_" and match the regular expression C. =cut ##--------------------------------------------------------------------------- =begin _PRIVATE_ =head1 B<_compile_section_spec()> $listref = $parser->_compile_section_spec($section_spec); This function (note it is a function and I a method) takes a section specification (as described in L<"SECTION SPECIFICATIONS">) given in C<$section_sepc>, and compiles it into a list of regular expressions. If C<$section_spec> has no syntax errors, then a reference to the list (array) of corresponding regular expressions is returned; otherwise C is returned and an error message is printed (using B) for each invalid regex. =end _PRIVATE_ =cut sub _compile_section_spec { my ($section_spec) = @_; my (@regexs, $negated); ## Compile the spec into a list of regexs local $_ = $section_spec; s{\\\\}{\001}g; ## handle escaped backward slashes s{\\/}{\002}g; ## handle escaped forward slashes ## Parse the regexs for the heading titles @regexs = split(/\//, $_, $MAX_HEADING_LEVEL); ## Set default regex for ommitted levels for (my $i = 0; $i < $MAX_HEADING_LEVEL; ++$i) { $regexs[$i] = '.*' unless ((defined $regexs[$i]) && (length $regexs[$i])); } ## Modify the regexs as needed and validate their syntax my $bad_regexs = 0; for (@regexs) { $_ .= '.+' if ($_ eq '!'); s{\001}{\\\\}g; ## restore escaped backward slashes s{\002}{\\/}g; ## restore escaped forward slashes $negated = s/^\!//; ## check for negation eval "m{$_}"; ## check regex syntax if ($@) { ++$bad_regexs; carp qq{Bad regular expression /$_/ in "$section_spec": $@\n}; } else { ## Add the forward and rear anchors (and put the negator back) $_ = '^' . $_ unless (/^\^/); $_ = $_ . '$' unless (/\$$/); $_ = '!' . $_ if ($negated); } } return (! $bad_regexs) ? [ @regexs ] : undef; } ##--------------------------------------------------------------------------- =begin _PRIVATE_ =head2 $self->{_SECTION_HEADINGS} A reference to an array of the current section heading titles for each heading level (note that the first heading level title is at index 0). =end _PRIVATE_ =cut ##--------------------------------------------------------------------------- =begin _PRIVATE_ =head2 $self->{_SELECTED_SECTIONS} A reference to an array of references to arrays. Each subarray is a list of anchored regular expressions (preceded by a "!" if the expression is to be negated). The index of the expression in the subarray should correspond to the index of the heading title in C<$self-E{_SECTION_HEADINGS}> that it is to be matched against. =end _PRIVATE_ =cut ############################################################################# =head1 SEE ALSO L =head1 AUTHOR Please report bugs using L. Brad Appleton Ebradapp@enteract.comE Based on code for B written by Tom Christiansen Etchrist@mox.perl.comE =cut 1; # vim: ts=4 sw=4 et mrtg-2.17.10/lib/mrtg2/Pod/Usage.pm0000644000175300017510000005621213057016062015601 0ustar oetikeroep############################################################################# # Pod/Usage.pm -- print usage messages for the running script. # # Copyright (C) 1996-2000 by Bradford Appleton. All rights reserved. # This file is part of "PodParser". PodParser is free software; # you can redistribute it and/or modify it under the same terms # as Perl itself. ############################################################################# package Pod::Usage; use strict; use vars qw($VERSION @ISA @EXPORT); $VERSION = '1.36'; ## Current version of this package require 5.005; ## requires this Perl version or later =head1 NAME Pod::Usage, pod2usage() - print a usage message from embedded pod documentation =head1 SYNOPSIS use Pod::Usage my $message_text = "This text precedes the usage message."; my $exit_status = 2; ## The exit status to use my $verbose_level = 0; ## The verbose level to use my $filehandle = \*STDERR; ## The filehandle to write to pod2usage($message_text); pod2usage($exit_status); pod2usage( { -message => $message_text , -exitval => $exit_status , -verbose => $verbose_level, -output => $filehandle } ); pod2usage( -msg => $message_text , -exitval => $exit_status , -verbose => $verbose_level, -output => $filehandle ); pod2usage( -verbose => 2, -noperldoc => 1 ) =head1 ARGUMENTS B should be given either a single argument, or a list of arguments corresponding to an associative array (a "hash"). When a single argument is given, it should correspond to exactly one of the following: =over 4 =item * A string containing the text of a message to print I printing the usage message =item * A numeric value corresponding to the desired exit status =item * A reference to a hash =back If more than one argument is given then the entire argument list is assumed to be a hash. If a hash is supplied (either as a reference or as a list) it should contain one or more elements with the following keys: =over 4 =item C<-message> =item C<-msg> The text of a message to print immediately prior to printing the program's usage message. =item C<-exitval> The desired exit status to pass to the B function. This should be an integer, or else the string "NOEXIT" to indicate that control should simply be returned without terminating the invoking process. =item C<-verbose> The desired level of "verboseness" to use when printing the usage message. If the corresponding value is 0, then only the "SYNOPSIS" section of the pod documentation is printed. If the corresponding value is 1, then the "SYNOPSIS" section, along with any section entitled "OPTIONS", "ARGUMENTS", or "OPTIONS AND ARGUMENTS" is printed. If the corresponding value is 2 or more then the entire manpage is printed. The special verbosity level 99 requires to also specify the -sections parameter; then these sections are extracted (see L) and printed. =item C<-sections> A string representing a selection list for sections to be printed when -verbose is set to 99, e.g. C<"NAME|SYNOPSIS|DESCRIPTION|VERSION">. Alternatively, an array reference of section specifications can be used: pod2usage(-verbose => 99, -sections => [ qw(fred fred/subsection) ] ); =item C<-output> A reference to a filehandle, or the pathname of a file to which the usage message should be written. The default is C<\*STDERR> unless the exit value is less than 2 (in which case the default is C<\*STDOUT>). =item C<-input> A reference to a filehandle, or the pathname of a file from which the invoking script's pod documentation should be read. It defaults to the file indicated by C<$0> (C<$PROGRAM_NAME> for users of F). If you are calling B from a module and want to display that module's POD, you can use this: use Pod::Find qw(pod_where); pod2usage( -input => pod_where({-inc => 1}, __PACKAGE__) ); =item C<-pathlist> A list of directory paths. If the input file does not exist, then it will be searched for in the given directory list (in the order the directories appear in the list). It defaults to the list of directories implied by C<$ENV{PATH}>. The list may be specified either by a reference to an array, or by a string of directory paths which use the same path separator as C<$ENV{PATH}> on your system (e.g., C<:> for Unix, C<;> for MSWin32 and DOS). =item C<-noperldoc> By default, Pod::Usage will call L when -verbose >= 2 is specified. This does not work well e.g. if the script was packed with L. The -noperldoc option suppresses the external call to L and uses the simple text formatter (L) to output the POD. =back =head1 DESCRIPTION B will print a usage message for the invoking script (using its embedded pod documentation) and then exit the script with the desired exit status. The usage message printed may have any one of three levels of "verboseness": If the verbose level is 0, then only a synopsis is printed. If the verbose level is 1, then the synopsis is printed along with a description (if present) of the command line options and arguments. If the verbose level is 2, then the entire manual page is printed. Unless they are explicitly specified, the default values for the exit status, verbose level, and output stream to use are determined as follows: =over 4 =item * If neither the exit status nor the verbose level is specified, then the default is to use an exit status of 2 with a verbose level of 0. =item * If an exit status I specified but the verbose level is I, then the verbose level will default to 1 if the exit status is less than 2 and will default to 0 otherwise. =item * If an exit status is I specified but verbose level I given, then the exit status will default to 2 if the verbose level is 0 and will default to 1 otherwise. =item * If the exit status used is less than 2, then output is printed on C. Otherwise output is printed on C. =back Although the above may seem a bit confusing at first, it generally does "the right thing" in most situations. This determination of the default values to use is based upon the following typical Unix conventions: =over 4 =item * An exit status of 0 implies "success". For example, B exits with a status of 0 if the two files have the same contents. =item * An exit status of 1 implies possibly abnormal, but non-defective, program termination. For example, B exits with a status of 1 if it did I find a matching line for the given regular expression. =item * An exit status of 2 or more implies a fatal error. For example, B exits with a status of 2 if you specify an illegal (unknown) option on the command line. =item * Usage messages issued as a result of bad command-line syntax should go to C. However, usage messages issued due to an explicit request to print usage (like specifying B<-help> on the command line) should go to C, just in case the user wants to pipe the output to a pager (such as B). =item * If program usage has been explicitly requested by the user, it is often desirable to exit with a status of 1 (as opposed to 0) after issuing the user-requested usage message. It is also desirable to give a more verbose description of program usage in this case. =back B doesn't force the above conventions upon you, but it will use them by default if you don't expressly tell it to do otherwise. The ability of B to accept a single number or a string makes it convenient to use as an innocent looking error message handling function: use Pod::Usage; use Getopt::Long; ## Parse options GetOptions("help", "man", "flag1") || pod2usage(2); pod2usage(1) if ($opt_help); pod2usage(-verbose => 2) if ($opt_man); ## Check for too many filenames pod2usage("$0: Too many files given.\n") if (@ARGV > 1); Some user's however may feel that the above "economy of expression" is not particularly readable nor consistent and may instead choose to do something more like the following: use Pod::Usage; use Getopt::Long; ## Parse options GetOptions("help", "man", "flag1") || pod2usage(-verbose => 0); pod2usage(-verbose => 1) if ($opt_help); pod2usage(-verbose => 2) if ($opt_man); ## Check for too many filenames pod2usage(-verbose => 2, -message => "$0: Too many files given.\n") if (@ARGV > 1); As with all things in Perl, I, and B adheres to this philosophy. If you are interested in seeing a number of different ways to invoke B (although by no means exhaustive), please refer to L<"EXAMPLES">. =head1 EXAMPLES Each of the following invocations of C will print just the "SYNOPSIS" section to C and will exit with a status of 2: pod2usage(); pod2usage(2); pod2usage(-verbose => 0); pod2usage(-exitval => 2); pod2usage({-exitval => 2, -output => \*STDERR}); pod2usage({-verbose => 0, -output => \*STDERR}); pod2usage(-exitval => 2, -verbose => 0); pod2usage(-exitval => 2, -verbose => 0, -output => \*STDERR); Each of the following invocations of C will print a message of "Syntax error." (followed by a newline) to C, immediately followed by just the "SYNOPSIS" section (also printed to C) and will exit with a status of 2: pod2usage("Syntax error."); pod2usage(-message => "Syntax error.", -verbose => 0); pod2usage(-msg => "Syntax error.", -exitval => 2); pod2usage({-msg => "Syntax error.", -exitval => 2, -output => \*STDERR}); pod2usage({-msg => "Syntax error.", -verbose => 0, -output => \*STDERR}); pod2usage(-msg => "Syntax error.", -exitval => 2, -verbose => 0); pod2usage(-message => "Syntax error.", -exitval => 2, -verbose => 0, -output => \*STDERR); Each of the following invocations of C will print the "SYNOPSIS" section and any "OPTIONS" and/or "ARGUMENTS" sections to C and will exit with a status of 1: pod2usage(1); pod2usage(-verbose => 1); pod2usage(-exitval => 1); pod2usage({-exitval => 1, -output => \*STDOUT}); pod2usage({-verbose => 1, -output => \*STDOUT}); pod2usage(-exitval => 1, -verbose => 1); pod2usage(-exitval => 1, -verbose => 1, -output => \*STDOUT}); Each of the following invocations of C will print the entire manual page to C and will exit with a status of 1: pod2usage(-verbose => 2); pod2usage({-verbose => 2, -output => \*STDOUT}); pod2usage(-exitval => 1, -verbose => 2); pod2usage({-exitval => 1, -verbose => 2, -output => \*STDOUT}); =head2 Recommended Use Most scripts should print some type of usage message to C when a command line syntax error is detected. They should also provide an option (usually C<-H> or C<-help>) to print a (possibly more verbose) usage message to C. Some scripts may even wish to go so far as to provide a means of printing their complete documentation to C (perhaps by allowing a C<-man> option). The following complete example uses B in combination with B to do all of these things: use Getopt::Long; use Pod::Usage; my $man = 0; my $help = 0; ## Parse options and print usage if there is a syntax error, ## or if usage was explicitly requested. GetOptions('help|?' => \$help, man => \$man) or pod2usage(2); pod2usage(1) if $help; pod2usage(-verbose => 2) if $man; ## If no arguments were given, then allow STDIN to be used only ## if it's not connected to a terminal (otherwise print usage) pod2usage("$0: No files given.") if ((@ARGV == 0) && (-t STDIN)); __END__ =head1 NAME sample - Using GetOpt::Long and Pod::Usage =head1 SYNOPSIS sample [options] [file ...] Options: -help brief help message -man full documentation =head1 OPTIONS =over 8 =item B<-help> Print a brief help message and exits. =item B<-man> Prints the manual page and exits. =back =head1 DESCRIPTION B will read the given input file(s) and do something useful with the contents thereof. =cut =head1 CAVEATS By default, B will use C<$0> as the path to the pod input file. Unfortunately, not all systems on which Perl runs will set C<$0> properly (although if C<$0> isn't found, B will search C<$ENV{PATH}> or else the list specified by the C<-pathlist> option). If this is the case for your system, you may need to explicitly specify the path to the pod docs for the invoking script using something similar to the following: pod2usage(-exitval => 2, -input => "/path/to/your/pod/docs"); In the pathological case that a script is called via a relative path I the script itself changes the current working directory (see L) I calling pod2usage, Pod::Usage will fail even on robust platforms. Don't do that. =head1 AUTHOR Please report bugs using L. Marek Rouchal Emarekr@cpan.orgE Brad Appleton Ebradapp@enteract.comE Based on code for B written by Tom Christiansen Etchrist@mox.perl.comE =head1 ACKNOWLEDGMENTS Steven McDougall Eswmcd@world.std.comE for his help and patience with re-writing this manpage. =head1 SEE ALSO L, L, L =cut ############################################################################# #use diagnostics; use Carp; use Config; use Exporter; use File::Spec; @EXPORT = qw(&pod2usage); BEGIN { if ( $] >= 5.005_58 ) { require Pod::Text; @ISA = qw( Pod::Text ); } else { require Pod::PlainText; @ISA = qw( Pod::PlainText ); } } require Pod::Select; ##--------------------------------------------------------------------------- ##--------------------------------- ## Function definitions begin here ##--------------------------------- sub pod2usage { local($_) = shift; my %opts; ## Collect arguments if (@_ > 0) { ## Too many arguments - assume that this is a hash and ## the user forgot to pass a reference to it. %opts = ($_, @_); } elsif (!defined $_) { $_ = ''; } elsif (ref $_) { ## User passed a ref to a hash %opts = %{$_} if (ref($_) eq 'HASH'); } elsif (/^[-+]?\d+$/) { ## User passed in the exit value to use $opts{'-exitval'} = $_; } else { ## User passed in a message to print before issuing usage. $_ and $opts{'-message'} = $_; } ## Need this for backward compatibility since we formerly used ## options that were all uppercase words rather than ones that ## looked like Unix command-line options. ## to be uppercase keywords) %opts = map { my ($key, $val) = ($_, $opts{$_}); $key =~ s/^(?=\w)/-/; $key =~ /^-msg/i and $key = '-message'; $key =~ /^-exit/i and $key = '-exitval'; lc($key) => $val; } (keys %opts); ## Now determine default -exitval and -verbose values to use if ((! defined $opts{'-exitval'}) && (! defined $opts{'-verbose'})) { $opts{'-exitval'} = 2; $opts{'-verbose'} = 0; } elsif (! defined $opts{'-exitval'}) { $opts{'-exitval'} = ($opts{'-verbose'} > 0) ? 1 : 2; } elsif (! defined $opts{'-verbose'}) { $opts{'-verbose'} = (lc($opts{'-exitval'}) eq 'noexit' || $opts{'-exitval'} < 2); } ## Default the output file $opts{'-output'} = (lc($opts{'-exitval'}) eq 'noexit' || $opts{'-exitval'} < 2) ? \*STDOUT : \*STDERR unless (defined $opts{'-output'}); ## Default the input file $opts{'-input'} = $0 unless (defined $opts{'-input'}); ## Look up input file in path if it doesnt exist. unless ((ref $opts{'-input'}) || (-e $opts{'-input'})) { my $basename = $opts{'-input'}; my $pathsep = ($^O =~ /^(?:dos|os2|MSWin32)$/i) ? ';' : (($^O eq 'MacOS' || $^O eq 'VMS') ? ',' : ':'); my $pathspec = $opts{'-pathlist'} || $ENV{PATH} || $ENV{PERL5LIB}; my @paths = (ref $pathspec) ? @$pathspec : split($pathsep, $pathspec); for my $dirname (@paths) { $_ = File::Spec->catfile($dirname, $basename) if length; last if (-e $_) && ($opts{'-input'} = $_); } } ## Now create a pod reader and constrain it to the desired sections. my $parser = new Pod::Usage(USAGE_OPTIONS => \%opts); if ($opts{'-verbose'} == 0) { $parser->select('(?:SYNOPSIS|USAGE)\s*'); } elsif ($opts{'-verbose'} == 1) { my $opt_re = '(?i)' . '(?:OPTIONS|ARGUMENTS)' . '(?:\s*(?:AND|\/)\s*(?:OPTIONS|ARGUMENTS))?'; $parser->select( '(?:SYNOPSIS|USAGE)\s*', $opt_re, "DESCRIPTION/$opt_re" ); } elsif ($opts{'-verbose'} >= 2 && $opts{'-verbose'} != 99) { $parser->select('.*'); } elsif ($opts{'-verbose'} == 99) { my $sections = $opts{'-sections'}; $parser->select( (ref $sections) ? @$sections : $sections ); $opts{'-verbose'} = 1; } ## Now translate the pod document and then exit with the desired status if ( !$opts{'-noperldoc'} and $opts{'-verbose'} >= 2 and !ref($opts{'-input'}) and $opts{'-output'} == \*STDOUT ) { ## spit out the entire PODs. Might as well invoke perldoc my $progpath = File::Spec->catfile($Config{scriptdir}, 'perldoc'); print { $opts{'-output'} } ($opts{'-message'}, "\n") if($opts{'-message'}); if(defined $opts{-input} && $opts{-input} =~ /^\s*(\S.*?)\s*$/) { # the perldocs back to 5.005 should all have -F # without -F there are warnings in -T scripts system($progpath, '-F', $1); if($?) { # RT16091: fall back to more if perldoc failed system(($Config{pager} || $ENV{PAGER} || '/bin/more'), $1); } } else { croak "Unspecified input file or insecure argument.\n"; } } else { $parser->parse_from_file($opts{'-input'}, $opts{'-output'}); } exit($opts{'-exitval'}) unless (lc($opts{'-exitval'}) eq 'noexit'); } ##--------------------------------------------------------------------------- ##------------------------------- ## Method definitions begin here ##------------------------------- sub new { my $this = shift; my $class = ref($this) || $this; my %params = @_; my $self = {%params}; bless $self, $class; if ($self->can('initialize')) { $self->initialize(); } else { $self = $self->SUPER::new(); %$self = (%$self, %params); } return $self; } sub select { my ($self, @sections) = @_; if ($ISA[0]->can('select')) { $self->SUPER::select(@sections); } else { # we're using Pod::Simple - need to mimic the behavior of Pod::Select my $add = ($sections[0] eq '+') ? shift(@sections) : ''; ## Reset the set of sections to use unless (@sections) { delete $self->{USAGE_SELECT} unless ($add); return; } $self->{USAGE_SELECT} = [] unless ($add && $self->{USAGE_SELECT}); my $sref = $self->{USAGE_SELECT}; ## Compile each spec for my $spec (@sections) { my $cs = Pod::Select::_compile_section_spec($spec); if ( defined $cs ) { ## Store them in our sections array push(@$sref, $cs); } else { carp qq{Ignoring section spec "$spec"!\n}; } } } } # Override Pod::Text->seq_i to return just "arg", not "*arg*". sub seq_i { return $_[1] } # This overrides the Pod::Text method to do something very akin to what # Pod::Select did as well as the work done below by preprocess_paragraph. # Note that the below is very, very specific to Pod::Text. sub _handle_element_end { my ($self, $element) = @_; if ($element eq 'head1') { $self->{USAGE_HEADINGS} = [ $$self{PENDING}[-1][1] ]; if ($self->{USAGE_OPTIONS}->{-verbose} < 2) { $$self{PENDING}[-1][1] =~ s/^\s*SYNOPSIS\s*$/USAGE/; } } elsif ($element =~ /^head(\d+)$/ && $1) { # avoid 0 my $idx = $1 - 1; $self->{USAGE_HEADINGS} = [] unless($self->{USAGE_HEADINGS}); $self->{USAGE_HEADINGS}->[$idx] = $$self{PENDING}[-1][1]; } if ($element =~ /^head\d+$/) { $$self{USAGE_SKIPPING} = 1; if (!$$self{USAGE_SELECT} || !@{ $$self{USAGE_SELECT} }) { $$self{USAGE_SKIPPING} = 0; } else { my @headings = @{$$self{USAGE_HEADINGS}}; for my $section_spec ( @{$$self{USAGE_SELECT}} ) { my $match = 1; for (my $i = 0; $i < $Pod::Select::MAX_HEADING_LEVEL; ++$i) { $headings[$i] = '' unless defined $headings[$i]; my $regex = $section_spec->[$i]; my $negated = ($regex =~ s/^\!//); $match &= ($negated ? ($headings[$i] !~ /${regex}/) : ($headings[$i] =~ /${regex}/)); last unless ($match); } # end heading levels if ($match) { $$self{USAGE_SKIPPING} = 0; last; } } # end sections } # Try to do some lowercasing instead of all-caps in headings, and use # a colon to end all headings. if($self->{USAGE_OPTIONS}->{-verbose} < 2) { local $_ = $$self{PENDING}[-1][1]; s{([A-Z])([A-Z]+)}{((length($2) > 2) ? $1 : lc($1)) . lc($2)}ge; s/\s*$/:/ unless (/:\s*$/); $_ .= "\n"; $$self{PENDING}[-1][1] = $_; } } if ($$self{USAGE_SKIPPING} && $element !~ m/^over-/) { pop @{ $$self{PENDING} }; } else { $self->SUPER::_handle_element_end($element); } } # required for Pod::Simple API sub start_document { my $self = shift; $self->SUPER::start_document(); my $msg = $self->{USAGE_OPTIONS}->{-message} or return 1; my $out_fh = $self->output_fh(); print $out_fh "$msg\n"; } # required for old Pod::Parser API sub begin_pod { my $self = shift; $self->SUPER::begin_pod(); ## Have to call superclass my $msg = $self->{USAGE_OPTIONS}->{-message} or return 1; my $out_fh = $self->output_handle(); print $out_fh "$msg\n"; } sub preprocess_paragraph { my $self = shift; local $_ = shift; my $line = shift; ## See if this is a heading and we arent printing the entire manpage. if (($self->{USAGE_OPTIONS}->{-verbose} < 2) && /^=head/) { ## Change the title of the SYNOPSIS section to USAGE s/^=head1\s+SYNOPSIS\s*$/=head1 USAGE/; ## Try to do some lowercasing instead of all-caps in headings s{([A-Z])([A-Z]+)}{((length($2) > 2) ? $1 : lc($1)) . lc($2)}ge; ## Use a colon to end all headings s/\s*$/:/ unless (/:\s*$/); $_ .= "\n"; } return $self->SUPER::preprocess_paragraph($_); } 1; # keep require happy mrtg-2.17.10/src/rateup.c0000644000175300017510000017147314171763414014126 0ustar oetikeroep/* MRTG 2.17.10 -- Rateup ********************* Rateup is a fast add-on to the great MRTG Traffic monitor. It makes the database file updates much faster, and creates the graphic image files, ready for processing by PPMTOGIF. It also reduces memory requirements by a factor of 10, and increases the speed of updates by a factor of at least 10. This makes it feasible to run mrtg every 5 minutes. rateup attempts to compensate for missed updates by repeating the last sample, and also tries to catch bad update times. The .log file stores real history every five minutes for 31 hours, then 'compresses' the history into 30 minute samples for a week, then 2-hour samples for 31 days, then daily samples for two years. This ensures that the log files don't grow in size. The log files are a slightly different format, but convert.perl will fix that for you. Enjoy! Dave Rand dlr@bungi.com 04/26/99 - There was some compilation bug under Watcom 10.6 which was fixed when recompiled with VC++ 6.0 Alexandre Steinberg steinberg@base.com.br */ #include #include /* VC++ does not have unistd.h */ #ifndef WIN32 #ifndef NETWARE #include "../config.h" #endif #endif #include #include #include #include #include #include #include #ifndef GFORM_GD #define GFORM_GD gdImagePng #endif /* BSD* does not have/need malloc.h */ #if !defined(bsdi) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__APPLE__) #include #endif /* MSVCRT.DLL does not know %ll in printf */ #ifdef __MINGW32_VERSION #define LLD "%I64d" #define LLD_FORMAT "I64d" #endif #ifdef __EMX__ /* OS/2 */ #define strtoll _strtoll #define LLD "%Ld" /* EMX lib use %Ld for long long */ #define LLD_FORMAT "Ld" #endif #ifndef LLD #define LLD "%lld" #define LLD_FORMAT "lld" #endif /* WATCOM C/C++ 10.6 under Win95/NT */ /* VC++ 6.0 under Win95/NT */ #if defined(__WATCOMC__) || defined(WIN32) #include #include #include #include #endif #include #include char *VERSION = "2.17.10"; char *program, *router, *routerpath; int histvalid; /* Options */ short options = 0; #define OPTION_WITHZEROES 0x0001 /* withzeros */ #define OPTION_UNKNASZERO 0x0002 /* unknaszero */ #define OPTION_TRANSPARENT 0x0004 /* transparent */ #define OPTION_DORELPERCENT 0x0008 /* dorelpercent */ #define OPTION_NOBORDER 0x0010 /* noborder */ #define OPTION_NOARROW 0x0020 /* noarrow */ #define OPTION_NO_I 0x0040 /* ignore 'I' (first) variable */ #define OPTION_NO_O 0x0080 /* ignore 'O' (second) variable */ #define OPTION_PRINTROUTER 0x0200 /* show title in graph */ #define OPTION_LOGGRAPH 0x0400 /* Use a logarithmic Y axis */ #define OPTION_MEANOVER 0x0800 /* max Y = mean-above-the-mean */ #define OPTION_EXPGRAPH 0x1000 /* exponential scale (opposite of logscale) */ time_t NOW; /* jpt, april 2006 : added 3 lines for date & time logging */ struct tm * stLocal; time_t timestamp; char bufftime[32]; char *short_si_def[] = { "", "k", "M", "G", "T" }; int kMGnumber = 4; char **short_si = short_si_def; char *longup = NULL; char *shortup = NULL; char *pngtitle = NULL; char *rtimezone = NULL; char weekformat = 'V'; /* strftime() fmt char for week # */ #define DAY_COUNT (600) /* 400 samples is 33.33 hours */ #define DAY_SAMPLE (5*60) /* Sample every 5 minutes */ #define WEEK_COUNT (600) /* 400 samples is 8.33 days */ #define WEEK_SAMPLE (30*60) /* Sample every 30 minutes */ #define MONTH_COUNT (600) /* 400 samples is 33.33 days */ #define MONTH_SAMPLE (2*60*60) /* Sample every 2 hours */ #define YEAR_COUNT (2 * 366) /* 1 sample / day, 366 days, 2 years */ #define YEAR_SAMPLE (24*60*60) /* Sample every 24 hours */ /* One 'rounding error' per sample period, so add 4 to total and for good mesure we take 10 :-) */ #define MAX_HISTORY (DAY_COUNT+WEEK_COUNT+MONTH_COUNT+YEAR_COUNT+10) /* These are the colors used for the variouse parts of the graph */ /* the format is Red,Green,Blue */ #define c_blank 245,245,245 #define c_light 194,194,194 #define c_dark 100,100,100 #define c_major 255,0,0 #define c_in 0,235,12 #define c_out 0,94,255 #define c_grid 0,0,0 #define c_inm 0,166,33 #define c_outm 255,0,255 #define c_outp 239,159,79 int col_in[3]; int col_out[3]; int col_inm[3]; int col_outm[3]; int col_outp[3]; long long kilo = (long long) 1000; char *kMG = (char *) NULL; #define MAXL 200 /* Maximum length of last in & out fields */ struct HISTORY { time_t time; double in, out, percent, inmax, outmax; } *history; int Mh; struct LAST { time_t time; char in[MAXL], out[MAXL]; } last; #ifndef max #define max(a,b) ((a) > (b) ? (a) : (b)) #endif #ifndef min #define min(a,b) ((a) < (b) ? (a) : (b)) #endif /* notes about the NEXT macro .... * position n to the entry in the history array so that NOW is between history[n] and history[n+1] * calculate the interval according to steptime and position of now within the history array. for debuging fprintf (stderr,"%s, NOW: %8lu ST: %4lu N: %4u HTN: %8lu HTN+1: %8lu IV: %6.0f\n", \ bufftime,now,steptime,n,history[n].time, history[n+1].time, interval);\ */ #define NEXT(steptime) \ inmax = outmax = avc = 0; \ inr = outr = 0.0;\ nextnow = now - steptime;\ if (now == history[n].time && \ n history[n].time) {\ fprintf(stderr,"%s, ERROR: Rateup is trying to read ahead of the available data\n" ,bufftime);\ } else {\ while (now <= history[n+1].time && n < histvalid){n++;}\ do {\ if (now >= history[n].time) {\ if (nextnow <= history[n+1].time) {\ interval = history[n].time - history[n+1].time;\ } else {\ interval = history[n].time - nextnow;\ }\ } else {\ if (nextnow > history[n+1].time) {\ interval = steptime;\ } else {\ interval = now - history[n+1].time;\ }\ }\ inr += (double) history[n].in * interval;\ outr += (double) history[n].out * interval;\ avc += interval;\ inmax = (long long) max(inmax, history[n].inmax);\ outmax = (long long) max(outmax,history[n].outmax);\ if (nextnow <= history[n+1].time) n++; else break;\ } while (n < histvalid && nextnow < history[n].time);\ \ if (avc != steptime) {\ fprintf(stderr,"%s, ERROR: StepTime does not match Avc %8" LLD_FORMAT ". Please Report this.\n", bufftime, avc);\ }\ \ inr /= avc; outr /= avc;\ }\ } static double logscale(double y, double maxy) { y = (y * (maxy - 1) / maxy) + 1; y = log(y) / log (maxy) * maxy; if (y < 0) return 0; if (y > maxy) return maxy; return y; } static double expscale(double y, double maxy) { y = exp(y / maxy * log(maxy)); return (y - 1) * maxy / (maxy - 1); } static void image (file, maxvi, maxvo, maxx, maxy, xscale, yscale, growright, step, bits, ytics, yticsf, peak, currdatetimeformat, currdatetimepos) char *file; long long maxvi, maxvo; long maxx; long maxy, growright, step, bits; double xscale, yscale; int ytics; /* number of tics on the y axis */ double yticsf; /* scale everything on the y axis with this factor */ int peak; char *currdatetimeformat; int currdatetimepos; { FILE *fo; char file_tmp[10240]; int i, x, n, type; long long maxv; double origmaxvi, origmaxvo; long long maxs, avc, inmax, outmax; long long ytrmax; double y, lmx1, lmx2, mea1, mea2, temp; double inr, outr, muli = 1, interval; time_t now, onow, nextnow; struct tm tm2, *tm = &tm2; char **graph_label; char ylab[30]; /* scaling helpers */ long long maxv_q; long long valsamp, maxin, maxout, digits, digits1, maxpercent = 0; long long sca_ten, sca_hun; double nmax_q; double avmxin, avmxout, avin, avout, latestout = 0, latestin = 0, nmax, avpercent = 0, latestpercent = 0; double nex_ten, nex_hun, nex_rnd; double sca_max_q, dummy; double percent; char *short_si_out; char currdatetimestr[256]; time_t currdatetime; int currdatetimepos_x, currdatetimepos_y; #define NO_TIMESTAMPSTR (0) #define LU_CORNER (1) #define RU_CORNER (2) #define LL_CORNER (3) #define RL_CORNER (4) struct HISTORY *lhist; /* ################################################# */ /* Some general definitions for the graph generation */ #define XSIZE (long)((maxx*xscale)+100+((options & OPTION_DORELPERCENT) ? 1 : 0)*30) #define YSIZE (long)((maxy*yscale)+35) /* position the graph */ #define ytr(y) (long)(maxy*yscale+14-((y)*yscale)) /* translate x/y coord into graph coord */ #define xtr(x) (long)((growright) ? (maxx*xscale+81-((x)*xscale)) : (81+((x)*xscale))) /* ################################################# */ /* GD LIB declarations */ /* Declare the image */ gdImagePtr graph, brush_out, brush_outm, brush_outp; /* Declare color indexes */ int i_light, i_dark, i_blank, i_major, i_in, i_grid, i_inm, i_outpg; /* Dotted style */ int styleDotted[3]; if ((graph_label = (char **) calloc (1, sizeof (char *) * maxx)) == NULL) { fprintf (stderr, "%s, Rateup ERROR: Out of memory in graph creation\n", bufftime); exit (1); } /* multiplicator for bits/bytes */ if (bits) { muli = 8; } maxv = (long long) max (maxvi, maxvo); maxv *= (long long) muli; origmaxvi = maxvi < (long long) 0 ? -maxvi : maxvi; origmaxvo = maxvo < (long long) 0 ? -maxvo : maxvo; if (step > MONTH_SAMPLE) { type = 4; now = (long) (NOW / YEAR_SAMPLE) * YEAR_SAMPLE; } else if (step > WEEK_SAMPLE) { type = 3; now = (long) (NOW / MONTH_SAMPLE) * MONTH_SAMPLE; } else if (step > DAY_SAMPLE) { type = 2; now = (long) (NOW / WEEK_SAMPLE) * WEEK_SAMPLE; } else { type = 1; now = (long) (NOW / DAY_SAMPLE) * DAY_SAMPLE; } if ((lhist = calloc (1, sizeof (struct HISTORY) * maxx)) == NULL) { fprintf (stderr, "%s, Rateup ERROR: Out of memory in graph creation\n", bufftime); exit (1); } onow = now; avin = avout = avmxin = avmxout = 0.0; inmax = outmax = maxin = maxout = 0; valsamp = 0; for (maxs = 0, n = 0, x = 0; x < maxx; x++) { NEXT (step); /*scale with muli */ inr *= muli; outr *= muli; inmax *= muli; outmax *= muli; /* ignore times when we have not sampled */ if (inmax > 0 || outmax > 0 || inr > 0 || outr > 0 || (options & OPTION_WITHZEROES)) valsamp++; if (x == 0) { latestin = inr; latestout = outr; if (outr) { latestpercent = inr * (double) 100. / outr; } } avin += inr; avout += outr; avmxin += inmax; avmxout += outmax; if (peak) { maxin = (long long) max (maxin, inmax); maxout = (long long) max (maxout, outmax); if (!(options & OPTION_NO_I)){ maxs = (long long) max (maxs, inmax); } if (!(options & OPTION_NO_O)){ maxs = (long long) max (maxs, outmax); } } else { maxin = (long long) max (maxin, inr); maxout = (long long) max (maxout, outr); if (!(options & OPTION_NO_I)){ maxs = (long long) max (maxs, inr); } if (!(options & OPTION_NO_O)){ maxs = (long long) max (maxs, outr); } } if ((options & OPTION_DORELPERCENT) && outr) { dummy = (double) 100. *inr / outr; maxpercent = max (dummy, maxpercent); } now -= step; } if (options & OPTION_DORELPERCENT) { if (avout && valsamp) { avpercent = (double) 100. *avin / avout; } else { avpercent = 0; } } if (valsamp) { avin /= valsamp; avout /= valsamp; avmxin /= valsamp; avmxout /= valsamp; } printf ("" LLD "\n", (long long) (maxin / (long long) muli + .5)); printf ("" LLD "\n", (long long) (maxout / (long long) muli + .5)); if (options & OPTION_DORELPERCENT) { printf ("" LLD "\n", (long long) (maxpercent + .5)); } printf ("" LLD "\n", (long long) (avin / (long long) muli + .5)); printf ("" LLD "\n", (long long) (avout / (long long) muli + .5)); if (options & OPTION_DORELPERCENT) { printf ("" LLD "\n", (long long) (avpercent + .5)); } printf ("" LLD "\n", (long long) (latestin / (long long) muli + .5)); printf ("" LLD "\n", (long long) (latestout / (long long) muli + .5)); if (options & OPTION_DORELPERCENT) { printf ("" LLD "\n", (long long) (latestpercent + .5)); } printf ("" LLD "\n", (long long) (avmxin / (long long) muli + .5)); printf ("" LLD "\n", (long long) (avmxout / (long long) muli + .5)); if (maxv < 0 || maxv < maxs) { maxv = maxs; } now = onow; if (maxv <= 0) maxv = 1; if (kMG) { if (short_si[0] != kMG) { short_si_out = kMG; kMGnumber = 0; while ((short_si_out = strchr (short_si_out, ',')) != NULL) { short_si_out++; kMGnumber++; } short_si = calloc(kMGnumber + 1, sizeof(*short_si)); short_si_out = kMG; for (kMGnumber = 0; ; kMGnumber++) { short_si[kMGnumber] = short_si_out; short_si_out = strchr(short_si_out, ','); if (short_si_out == NULL) break; short_si_out[0] = '\0'; short_si_out++; } } } /* mangle the 0.25*maxv value so, that we get a number with either */ /* one or two digits != 0 and these digits should be at the */ /* start of the number ... */ /* the ceil compensates for rounding with small numbers */ maxv_q = ceil ((double) maxv / (double) ytics); /* int */ digits = 0; { double number = (double) maxv_q; number *= yticsf; /* we just want to scale the lables nothing else */ /* while (number/(double) kilo >= (double)kilo && digits= (double) 1000 || short_si[digits / 3][0] == '-')) { number /= (double) 1000; digits += 3; } sca_max_q = (double) ((int) (((double) 100. * (double) number) / (pow ((double) 10., (double) (int) (log10 ((double) number)))) + (double) 9.999) / (int) 10) / (double) 10 * (pow ((double) 10., (double) (int) (log10 ((double) number)))); } short_si_out = short_si[min ((signed) (digits / 3), kMGnumber)]; if (maxv_q * yticsf >= 1) { digits1 = log10 ((double) maxv_q * yticsf); } else { digits1 = 0; } /* sca_ten = maxv_q / pow(10.0,(double)digits); */ /* sca_hun = maxv_q / pow(10.0,(double)digits-1); */ sca_ten = (double) maxv_q *yticsf / pow (10.0, (double) digits1); sca_hun = (double) maxv_q *yticsf / pow (10.0, (double) digits1 - 1); nex_rnd = (sca_hun) * pow (10.0, (double) digits1 - 1); nex_ten = (sca_ten + 1) * pow (10.0, (double) digits1); nex_hun = (sca_hun + 1) * pow (10.0, (double) digits1 - 1); /* if (nex_ten <= (1.1 * maxv_q)) { */ if (nex_ten <= (1.1 * maxv_q * yticsf)) { nmax_q = nex_ten; /* } else if (maxv_q == nex_rnd) { */ } else if ((maxv_q * yticsf) == nex_rnd) { nmax_q = nex_rnd; } else { nmax_q = nex_hun; } sca_max_q = nmax_q / (pow (10.0, (double) ((int) (digits / 3)) * 3)); /* nmax=sca_max_q*ytics*(pow((double)kilo,(double)((int)(digits1/3)))); */ nmax = (sca_max_q / yticsf) * ytics * (pow ((double) kilo, (double) ((int) (digits / 3)))); if (nmax < 1.) { nmax = 1.; } for (n = 0, x = 0; x < maxx; x++) { lhist[x].time = 0; graph_label[x] = NULL; /* this seesm to be necessary to work a round a bug in solaris where tm for complex TZ settings gets modified after the fact ... so we whisk the stuff away into our own memspace just in time */ memcpy (tm, localtime (&history[n].time), sizeof (struct tm)); switch (type) { default: case 1: if (tm->tm_min < 5) { lhist[x].time |= 1; if (tm->tm_hour == 0) lhist[x].time |= 2; } if ((tm->tm_min < 5) && (tm->tm_hour % 2 == 0)) { if ((graph_label[x] = calloc (1, sizeof (char) * 4)) == NULL) { fprintf (stderr, "%s, Rateup ERROR: Out of memory in graph labeling\n", bufftime); exit (0); } else { sprintf (graph_label[x], "%i", tm->tm_hour); } } break; case 2: if (tm->tm_min < 30 && tm->tm_hour == 0) { lhist[x].time |= 1; if (tm->tm_wday == 1) lhist[x].time |= 2; } /* fprintf(stderr,"%s, x: %i, min:%i, hour:%i day: %i\n", bufftime,x,tm->tm_min,tm->tm_hour,tm->tm_wday); */ if ((tm->tm_min < 30) && (tm->tm_hour == 12)) { if ((graph_label[x] = calloc (1, sizeof (char) * 5)) == NULL) { fprintf (stderr, "%s, Rateup ERROR: Out of memory in graph labeling\n", bufftime); exit (0); } else { strftime (graph_label[x], 4, "%a", tm); } } break; case 3: if (tm->tm_hour < 2) { if (tm->tm_wday == 1) lhist[x].time |= 1; if (tm->tm_mday == 1) lhist[x].time |= 2; } /* label goes to thursday noon */ if ((tm->tm_hour > 10) && (tm->tm_hour <= 12) && (tm->tm_wday == 4)) { if ((graph_label[x] = calloc (1, sizeof (char) * 16)) == NULL) { fprintf (stderr, "%s, Rateup ERROR: Out of memory in graph labeling\n", bufftime); exit (0); } else { char fmtbuf[10]; sprintf (fmtbuf, "Week %%%c", weekformat); strftime (graph_label[x], 8, fmtbuf, tm); } } break; case 4: if (tm->tm_mday == 1) lhist[x].time |= 1; if (tm->tm_yday == 0) lhist[x].time |= 2; if (tm->tm_mday == 15) { if ((graph_label[x] = calloc (1, sizeof (char) * 5)) == NULL) { fprintf (stderr, "%s, Rateup Error: Out of memory in graph labeling\n", bufftime); exit (0); } else { strftime (graph_label[x], 4, "%b", tm); } } break; } NEXT (step); /*scale with muli */ inr *= muli; outr *= muli; inmax *= muli; outmax *= muli; y = ((double) inr / nmax) * maxy; if (y >= maxy) y = maxy; lhist[x].in = y; y = ((double) outr / nmax) * maxy; if (y >= maxy) y = maxy; lhist[x].out = y; y = ((double) inmax / nmax) * maxy; if (y >= maxy) y = maxy; lhist[x].inmax = y; y = ((double) outmax / nmax) * maxy; if (y >= maxy) y = maxy; lhist[x].outmax = y; if (options & OPTION_DORELPERCENT) { if (outr != (long long) 0) { percent = (double) inr / (double) outr; } else { percent = (double) 0.; } if (percent > (double) 1) percent = (double) 1.; percent *= maxy; lhist[x].percent = (long long) percent; } else { lhist[x].percent = (long long) 0; } now -= step; } origmaxvi = (origmaxvi * muli / nmax ) * maxy; origmaxvo = (origmaxvo * muli / nmax ) * maxy; /* Log and second-mean scaling added by Benjamin Despres, 2004-10-13 */ if (options & OPTION_MEANOVER) { lmx1 = lmx2 = mea1 = mea2 = temp = 0.0; for (x = 0; x < maxx; x++) { if (lhist[x].in < 1.0) lhist[x].in = 1.0; if (lhist[x].out < 1.0) lhist[x].out = 1.0; if (lhist[x].inmax < 1.0) lhist[x].inmax = 1.0; if (lhist[x].outmax < 1.0) lhist[x].outmax = 1.0; if (lhist[x].in > lmx1) lmx1 = lhist[x].in; if (lhist[x].out > lmx1) lmx1 = lhist[x].out; if (lhist[x].inmax > lmx1) lmx1 = lhist[x].inmax; if (lhist[x].outmax > lmx1) lmx1 = lhist[x].outmax; mea1 += (lhist[x].in + lhist[x].out + lhist[x].inmax + lhist[x].outmax) / 4.0; } if (origmaxvi < 1.0) origmaxvi = 1.0; if (origmaxvo < 1.0) origmaxvo = 1.0; mea1 /= (double) maxx; for (x = 0; x < maxx; x++) { y = (lhist[x].in + lhist[x].out + lhist[x].inmax + lhist[x].outmax) / 4.0; if (y > mea1) { mea2 += y; temp += 1.0; } } mea2 /= temp; for (x = 0; x < maxx; x++) { if (lhist[x].in > mea2) lhist[x].in = mea2; if (lhist[x].out > mea2) lhist[x].out = mea2; if (lhist[x].inmax > mea2) lhist[x].inmax = mea2; if (lhist[x].outmax > mea2) lhist[x].outmax = mea2; } for (x = 0; x < maxx; x++) { if (lhist[x].in > lmx2) lmx2 = lhist[x].in; if (lhist[x].out > lmx2) lmx2 = lhist[x].out; if (lhist[x].inmax > lmx2) lmx2 = lhist[x].inmax; if (lhist[x].outmax > lmx2) lmx2 = lhist[x].outmax; } if (lmx2 > 0.0) lmx2 = (lmx1 / lmx2); for (x = 0; x < maxx; x++) { lhist[x].in *= lmx2; lhist[x].out *= lmx2; lhist[x].inmax *= lmx2; lhist[x].outmax *= lmx2; } origmaxvi *= lmx2; origmaxvo *= lmx2; sca_max_q *= ((float) mea2 / (float) maxy); } else if (options & OPTION_LOGGRAPH) { for (x = 0; x < maxx; x++) { lhist[x].in = logscale (lhist[x].in, maxy); lhist[x].out = logscale (lhist[x].out, maxy); lhist[x].inmax = logscale (lhist[x].inmax, maxy); lhist[x].outmax = logscale (lhist[x].outmax, maxy); } origmaxvi = logscale (origmaxvi, maxy); origmaxvo = logscale (origmaxvo, maxy); } /* end of primary log and second-mean scaling code (more below) */ else if (options & OPTION_EXPGRAPH) { for (x = 0; x < maxx; x++) { lhist[x].in = expscale (lhist[x].in, maxy); lhist[x].out = expscale (lhist[x].out, maxy); lhist[x].inmax = expscale (lhist[x].inmax, maxy); lhist[x].outmax = expscale (lhist[x].outmax, maxy); } origmaxvi = expscale (origmaxvi, maxy); origmaxvo = expscale (origmaxvo, maxy); } /* the graph is made ten pixels higher to acomodate the x labels */ graph = gdImageCreate (XSIZE, YSIZE); brush_out = gdImageCreate (1, 2); brush_outm = gdImageCreate (1, 2); brush_outp = gdImageCreate (1, 2); /* the first color allocated will be the background color. */ i_blank = gdImageColorAllocate (graph, c_blank); i_light = gdImageColorAllocate (graph, c_light); i_dark = gdImageColorAllocate (graph, c_dark); if (options & OPTION_TRANSPARENT) { gdImageColorTransparent (graph, i_blank); } gdImageInterlace (graph, 1); /* do NOT delete the out variables. they are dummies, but the actual color allocation for the brush is essential */ i_major = gdImageColorAllocate (graph, c_major); i_in = gdImageColorAllocate (graph, col_in[0], col_in[1], col_in[2]); gdImageColorAllocate (brush_out, col_out[0], col_out[1], col_out[2]); i_grid = gdImageColorAllocate (graph, c_grid); i_inm = gdImageColorAllocate (graph, col_inm[0], col_inm[1], col_inm[2]); gdImageColorAllocate (brush_outm, col_outm[0], col_outm[1], col_outm[2]); gdImageColorAllocate (brush_outp, col_outp[0], col_outp[1], col_outp[2]); i_outpg = gdImageColorAllocate (graph, col_outp[0], col_outp[1], col_outp[2]); /* draw the image border */ if (!(options & OPTION_NOBORDER)) { gdImageLine (graph, 0, 0, XSIZE - 1, 0, i_light); gdImageLine (graph, 1, 1, XSIZE - 2, 1, i_light); gdImageLine (graph, 0, 0, 0, YSIZE - 1, i_light); gdImageLine (graph, 1, 1, 1, YSIZE - 2, i_light); gdImageLine (graph, XSIZE - 1, 0, XSIZE - 1, YSIZE - 1, i_dark); gdImageLine (graph, 0, YSIZE - 1, XSIZE - 1, YSIZE - 1, i_dark); gdImageLine (graph, XSIZE - 2, 1, XSIZE - 2, YSIZE - 2, i_dark); gdImageLine (graph, 1, YSIZE - 2, XSIZE - 2, YSIZE - 2, i_dark); } /* draw the incoming traffic */ if (!(options & OPTION_NO_I)) { for (x = 0; x < maxx; x++) { /* peak is always above average, we therefore only draw the upper part */ if (peak) gdImageLine (graph, xtr (x), ytr (lhist[x].in), xtr (x), ytr (lhist[x].inmax), i_inm); #ifdef INCOMING_UNFILLED gdImageLine (graph, xtr (x), ytr (lhist[x].in), xtr (x), ytr (lhist[x + 1].in), i_in); #else gdImageLine (graph, xtr (x), ytr (0), xtr (x), ytr (lhist[x].in), i_in); /* draw the line a second time offset slightly. makes the graph * look better if xscale is fractional */ gdImageLine (graph, xtr (x + 0.5), ytr (0), xtr (x + 0.5), ytr (lhist[x].in), i_in); #endif } } /* draw the percentage */ if (options & OPTION_DORELPERCENT) { gdImageSetBrush (graph, brush_outp); for (x = 0; x < maxx - 1; x++) gdImageLine (graph, xtr (x), ytr (lhist[x].percent), xtr (x + 1), ytr (lhist[x + 1].percent), gdBrushed); } /* draw the outgoing traffic */ if (!(options & OPTION_NO_O)) { gdImageSetBrush (graph, brush_outm); if (peak) for (x = 0; x < maxx - 1; x++) gdImageLine (graph, xtr (x), ytr (lhist[x].outmax), xtr (x + 1), ytr (lhist[x + 1].outmax), gdBrushed); gdImageSetBrush (graph, brush_out); for (x = 0; x < maxx - 1; x++) gdImageLine (graph, xtr (x), ytr (lhist[x].out), xtr (x + 1), ytr (lhist[x + 1].out), gdBrushed); } /* print the graph title */ if (pngtitle != NULL) { gdImageString (graph, gdFontSmall, 81, 1, (unsigned char *) pngtitle, i_grid); } else { if (options & OPTION_PRINTROUTER) { gdImageString (graph, gdFontSmall, 81, 1, (unsigned char *) router, i_grid); } } /* draw the graph border */ gdImageRectangle (graph, xtr (0), ytr (0), xtr (maxx), ytr (maxy), i_grid); /*create a dotted style for the grid lines */ styleDotted[0] = i_grid; styleDotted[1] = gdTransparent; styleDotted[2] = gdTransparent; gdImageSetStyle (graph, styleDotted, 3); /* draw the horizontal grid */ if ((longup == NULL) || (shortup == NULL)) { if (!bits) { longup = "Bytes per Second"; shortup = "Bytes/s"; } else { longup = "Bits per Second"; shortup = "Bits/s"; } } if (maxy < gdFontSmall->w * 16) { gdImageStringUp (graph, gdFontSmall, 8, ytr ((maxy - gdFontSmall->w * strlen (shortup)) / 2), (unsigned char *) shortup, i_grid); } else { gdImageStringUp (graph, gdFontSmall, 8, ytr ((maxy - gdFontSmall->w * strlen (longup)) / 2), (unsigned char *) longup, i_grid); } for (i = 0; i <= ytics; i++) { gdImageLine (graph, xtr (-2), ytr (i * maxy / ytics), xtr (1), ytr (i * maxy / ytics), i_grid); gdImageLine (graph, xtr (maxx + 2), ytr (i * maxy / ytics), xtr (maxx - 1), ytr (i * maxy / ytics), i_grid); gdImageLine (graph, xtr (0), ytr (i * maxy / ytics), xtr (maxx), ytr (i * maxy / ytics), gdStyled); /* sprintf(ylab,"%6.1f %s",sca_max_q*i,short_si[digits/3]); */ /* sprintf(ylab,"%6.1f %s",sca_max_q*i*yticsf,short_si_out); */ temp = sca_max_q * i; if (options & OPTION_LOGGRAPH) temp = expscale(maxy * i / ytics, maxy) * ytics * sca_max_q / maxy; else if (options & OPTION_EXPGRAPH) temp = logscale(maxy * i / ytics, maxy) * ytics * sca_max_q / maxy; else temp = sca_max_q * i; sprintf (ylab, "%6.1f %s", temp, short_si_out); /* sprintf(ylab,"%6.1f %s",sca_max_q*i,short_si_out); */ gdImageString (graph, gdFontSmall, 23, ytr (i * maxy / ytics + gdFontSmall->h / 2), (unsigned char *) ylab, i_grid); if (options & OPTION_DORELPERCENT) { /* sprintf(ylab,"% 6.1f%%",(float)25.*i); */ sprintf (ylab, "% 6.1f%%", (float) (temp / (sca_max_q * ytics) * 100)); gdImageString (graph, gdFontSmall, 77 + ((maxx) * xscale) + 1, ytr (i * maxy / ytics + gdFontSmall->h / 2), (unsigned char *) ylab, i_outpg); } } /* draw vertical grid and horizontal labels */ for (x = 0; x < maxx; x++) { if (lhist[x].time) { gdImageLine (graph, xtr (x), ytr (-2), xtr (x), ytr (1), i_grid); gdImageLine (graph, xtr (x), ytr (0), xtr (x), ytr (maxy), gdStyled); } if (graph_label[x] != NULL) { gdImageString (graph, gdFontSmall, (xtr (x) - (strlen (graph_label[x]) * gdFontSmall->w / 2)), ytr (-4), (unsigned char *) graph_label[x], i_grid); free (graph_label[x]); } if (lhist[x].time & 2) gdImageLine (graph, xtr (x), ytr (0), xtr (x), ytr (maxy), i_major); } ytrmax = ytr (origmaxvi); /* draw line at peak In value in i_major color */ /* only draw the line if it's within the graph ... */ if (ytr (maxy) < ytrmax) { styleDotted[0] = i_major; gdImageSetStyle (graph, styleDotted, 3); gdImageLine (graph, xtr (0), ytrmax, xtr (maxx), ytrmax, gdStyled); } /* draw line at peak Out value in i_major color */ /* only draw the line if it's within the graph ... */ ytrmax = ytr (origmaxvo); if (ytr (maxy) < ytrmax) { styleDotted[0] = i_major; gdImageSetStyle (graph, styleDotted, 3); gdImageLine (graph, xtr (0), ytrmax, xtr (maxx), ytrmax, gdStyled); } /* draw a red arrow a 0,0 */ if (!(options & OPTION_NOARROW)) { gdImageLine (graph, xtr (2), ytr (3), xtr (2), ytr (-3), i_major); gdImageLine (graph, xtr (1), ytr (3), xtr (1), ytr (-3), i_major); gdImageLine (graph, xtr (0), ytr (2), xtr (0), ytr (-2), i_major); gdImageLine (graph, xtr (-1), ytr (1), xtr (-1), ytr (-1), i_major); gdImageLine (graph, xtr (-2), ytr (1), xtr (-2), ytr (-1), i_major); gdImageLine (graph, xtr (-3), ytr (0), xtr (-3), ytr (0), i_major); } if (currdatetimepos > NO_TIMESTAMPSTR) { currdatetime = time (NULL); strftime (currdatetimestr, 250, currdatetimeformat, localtime (&currdatetime)); switch (currdatetimepos) { case LL_CORNER: currdatetimepos_x = 3; currdatetimepos_y = YSIZE - gdFontSmall->h - 3; break; case RL_CORNER: currdatetimepos_x = XSIZE - strlen (currdatetimestr) * gdFontSmall->w - 3; currdatetimepos_y = YSIZE - gdFontSmall->h - 3; break; case LU_CORNER: currdatetimepos_x = 3; currdatetimepos_y = 1; break; case RU_CORNER: default: currdatetimepos_x = XSIZE - strlen (currdatetimestr) * gdFontSmall->w - 3; currdatetimepos_y = 1; }; gdImageString (graph, gdFontSmall, currdatetimepos_x, currdatetimepos_y, (unsigned char *)currdatetimestr, i_grid); } snprintf(file_tmp,1000,"%s.tmp_%lu",file,(unsigned long)getpid()); if ((fo = fopen (file_tmp, "wb")) == NULL) { perror (program); fprintf (stderr, "%s, Rateup Error: Can't open %s for write\n", bufftime, file_tmp); exit (1); } GFORM_GD (graph, fo); fclose (fo); gdImageDestroy (graph); gdImageDestroy (brush_out); gdImageDestroy (brush_outm); gdImageDestroy (brush_outp); free (lhist); free (graph_label); /* By commenting out the next 4 lines, short_si will leak exactly one copy of kMG, but otherwise the kMG values for the weekly/monthly/yearly graphs are wrong. This should also fix the crash reported in GitHub issue #3. */ /* if (kMG) { free(short_si); short_si = short_si_def; } */ #ifdef WIN32 /* got to remove the target under win32 or rename will not work ... */ unlink(file); #endif if (rename(file_tmp,file)){ perror (program); fprintf (stderr, "%s, Rateup Error: Can't rename %s to %s\n", bufftime,file_tmp,file); exit (1); } } static double diff (a, b) char *a, *b; { char res[MAXL], *a1, *b1, *r1; int c, x, m; if (*a == '-' && *b == '-') { b1 = b + 1; b = a + 1; a = b1; } while (!isdigit ((int) *a)) a++; while (!isdigit ((int) *b)) b++; a1 = &a[strlen (a) - 1]; m = max (strlen (a), strlen (b)); r1 = &res[m + 1]; for (b1 = res; b1 <= r1; b1++) *b1 = ' '; b1 = &b[strlen (b) - 1]; r1[1] = 0; /* Null terminate result */ c = 0; for (x = 0; x < m; x++) { /* we want to avoid reading off the edge of the string */ char save_a, save_b; save_a = (a1 >= a) ? *a1 : '0'; save_b = (b1 >= b) ? *b1 : '0'; *r1 = save_a - save_b - c + '0'; if (*r1 < '0') { *r1 += 10; c = 1; } else if (*r1 > '9') { /* 0 - 10 */ *r1 -= 10; c = 1; } else { c = 0; } a1--; b1--; r1--; } if (c) { r1 = &res[m + 1]; for (x = 0; isdigit ((int) *r1) && x < m; x++, r1--) { *r1 = ('9' - *r1 + c) + '0'; if (*r1 > '9') { *r1 -= 10; c = 1; } else { c = 0; } } return (-atof (res)); } else return (atof (res)); } static int readhist (file) char *file; { FILE *fi; int x, retcode = 0; char buf[256], tempform[50]; struct HISTORY *hist; long long rd[5]; time_t cur; long lasttime; sprintf (tempform, "%%ld %%%ds %%%ds\n", MAXL - 1, MAXL - 1); if ((fi = fopen (file, "r")) != NULL) { if (fscanf (fi, tempform, &lasttime, &last.in[0], &last.out[0]) != 3) { fprintf (stderr, "%s, Read Error: File %s lin 1\n", bufftime, file); retcode = 1; } last.time = lasttime; cur = last.time; x = histvalid = 0; hist = history; while (fgets (buf, 256, fi) != NULL) { if (sscanf (buf, "" LLD " " LLD " " LLD " " LLD " " LLD "", &rd[0], &rd[1], &rd[2], &rd[3], &rd[4]) < 5) { rd[3] = rd[1]; rd[4] = rd[2]; } /* we are long long now, so don't cut bit 8 for (i=0;i<=4;i++){ if (rd[i] & 0x80000000) rd[i] = 0; } */ hist->time = rd[0]; hist->in = rd[1]; hist->out = rd[2]; hist->inmax = rd[3]; hist->outmax = rd[4]; if (hist->inmax < hist->in) hist->inmax = hist->in; if (hist->outmax < hist->out) hist->outmax = hist->out; if (hist->time > cur) { fprintf (stderr, "%s, Rateup ERROR: %s found %s's log file was corrupt or not in sorted order: time: %ld.\n", bufftime, program, router, (long) hist->time); retcode = 2; break; } cur = hist->time; if (++x >= Mh) { struct HISTORY *lh; Mh += MAX_HISTORY; lh = realloc (history, (Mh + 1) * sizeof (struct HISTORY)); if (lh == NULL) { fprintf (stderr, "%s, Rateup WARNING: (pay attention to this)\nWARNING: %s found %s's log file had too many entries, data discarded\n", bufftime, program, router); break; } hist = lh + (hist - history); history = lh; } hist++; } histvalid = x; fclose (fi); } else { retcode = 1; } return (retcode); } static void readfile () { char buf[128]; int err, x; time_t now; struct HISTORY *hist; sprintf (buf, "%s.log", router); if ((err = readhist (buf)) != 0) { /* Read of log file failed. Try backup */ fprintf (stderr, "%s, Rateup WARNING: %s could not read the primary log file for %s\n", bufftime, program, router); sprintf (buf, "%s.old", router); if ((err = readhist (buf)) != 0) { /* Backup failed too. New file? */ fprintf (stderr, "%s, Rateup WARNING: %s The backup log file for %s was invalid as well\n", bufftime, program, router); if (err == 2) exit (1); /* File does not exist - it must be created */ now = NOW - DAY_SAMPLE; hist = history; histvalid = DAY_COUNT + WEEK_COUNT + MONTH_COUNT + YEAR_COUNT - 1; last.time = now; /* calculating a diff does not make sense */ last.in[0] = 'x'; now /= DAY_SAMPLE; now *= DAY_SAMPLE; for (x = 0; x < DAY_COUNT; x++, hist++) { hist->time = now; hist->in = hist->inmax = hist->out = hist->outmax = 0; now -= DAY_SAMPLE; } now /= WEEK_SAMPLE; now *= WEEK_SAMPLE; for (x = 0; x < WEEK_COUNT; x++, hist++) { hist->time = now; hist->in = hist->inmax = hist->out = hist->outmax = 0; now -= WEEK_SAMPLE; } now /= MONTH_SAMPLE; now *= MONTH_SAMPLE; for (x = 0; x < MONTH_COUNT; x++, hist++) { hist->time = now; hist->in = hist->inmax = hist->out = hist->outmax = 0; now -= MONTH_SAMPLE; } now /= YEAR_SAMPLE; now *= YEAR_SAMPLE; for (x = 0; x < YEAR_COUNT; x++, hist++) { hist->time = now; hist->in = hist->inmax = hist->out = hist->outmax = 0; now -= YEAR_SAMPLE; } } } } static void update (in, out, abs_max, absupdate) char *in, *out; long long abs_max; int absupdate; { FILE *fo; char buf[128], buf1[128], buf2[128]; time_t now, nextnow, plannow; long long inrate, outrate; long long avc, inmax, outmax; double period, interval; int x, n, nout; struct HISTORY *lhist, *hist; double inr, outr; now = NOW; if (now < last.time) { fprintf (stderr, "%s, Rateup ERROR: %s found that %s's log file time of %ld was greater than now (%ld)\nERROR: Let's not do the time warp, again. Logfile unchanged.\n", bufftime, program, router, (long) last.time, (long) now); return; } sprintf (buf, "%s.tmp_%lu", router,(unsigned long)getpid()); sprintf (buf1, "%s.log", router); sprintf (buf2, "%s.old", router); if ((lhist = calloc (1, sizeof (struct HISTORY) * (MAX_HISTORY + 1))) == NULL) { fprintf (stderr, "%s, Rateup ERROR: Out of memory in update\n", bufftime); exit (1); } hist = lhist; period = (now - last.time); if (period <= 0 || period > (60 * 60) || last.in[0] == 'x') { /* if last update is strange */ if (options & OPTION_UNKNASZERO) { inrate = 0; /* sync unknown to zero */ outrate = 0; } else { inrate = history[0].in; /* Sync by using last value */ outrate = history[0].out; } } else { /* gauge and absolute */ if (strcmp (in, "-1") == 0 || /* if current count missing */ strcmp (last.in, "-1") == 0) { /* or previous count missing */ if (options & OPTION_UNKNASZERO) { /* then use 0 or last value */ inrate = 0; } else { inrate = history[0].in; } } else { if ((absupdate != 0) && (absupdate != 3) && (absupdate != 4)) { inr = diff (in, "0"); } else { inr = diff (in, last.in); if (inr < 0) { if (inr > - ((long long) 1 << 32)) { /* wrapped 32-bit counter? */ inr += (long long) 1 << 32; } else { inr = 0; } } } if (absupdate == 2) { inrate = inr + .5; } else if (absupdate == 3) { inrate = inr * (3600.0 / (period * 1.0)) + .5; } else if (absupdate == 4) { inrate = inr * (60.0 / (period * 1.0)) + .5; } else { inrate = inr / period + .5; } } if (strcmp (out, "-1") == 0 || /* if current count missing */ strcmp (last.out, "-1") == 0) { /* or previous count missing */ if (options & OPTION_UNKNASZERO) { /* then use 0 or last value */ outrate = 0; } else { outrate = history[0].out; } } else { if ((absupdate != 0) && (absupdate != 3) && (absupdate != 4)) { outr = diff (out, "0"); } else { outr = diff (out, last.out); if (outr < 0) { /* wrapped counter? */ if (outr > - ((long long) 1 << 32)) { outr += (long long) 1 << 32; } else { outr = 0; /* 64bit counters do not wrap usually */ } } } if (absupdate == 2) { outrate = outr + .5; } else if (absupdate == 3) { outrate = outr * (3600.0 / (period * 1.0)) + .5; } else if (absupdate == 4) { outrate = outr * (60.0 / (period * 1.0)) + .5; } else { outrate = outr / period + .5; } } } if (inrate < 0 || inrate > abs_max) { if (options & OPTION_UNKNASZERO) { inrate = 0; /* sync unknown to zero */ } else { inrate = history[0].in; /* Sync by using last value */ } } if (outrate < 0 || outrate > abs_max) { if (options & OPTION_UNKNASZERO) { outrate = 0; /* sync unknown to zero */ } else { outrate = history[0].out; /* Sync by using last value */ } } if ((fo = fopen (buf, "w")) != NULL) { fprintf (fo, "%ld %s %s\n", (long) now, in, out); last.time = now; /* what is this good for? */ /* gauge und absolute */ if ((absupdate != 0) && (absupdate != 3) && (absupdate != 4)) { strcpy (last.in, "0"); strcpy (last.out, "0"); } else { strncpy (last.in, in, MAXL); last.in[MAXL-1]='\0'; strncpy (last.out, out,MAXL); last.out[MAXL-1]='\0'; } fprintf (fo, "%ld " LLD " " LLD " " LLD " " LLD "\n", (long) now, inrate, outrate, inrate, outrate); nout = 1; hist->time = now; hist->in = inrate; hist->out = outrate; hist->inmax = inrate; hist->outmax = outrate; hist++; /* just in case we were dead for a long time, don't try to gather data from non existing log entries */ now = plannow = history[0].time; plannow /= DAY_SAMPLE; plannow *= DAY_SAMPLE; n = 0; /* gobble up every shred of data we can get ... */ if (plannow < now) { NEXT ((long) (now - plannow)); fprintf (fo, "%ld " LLD " " LLD " " LLD " " LLD "\n", (long) now, (long long) inr, (long long) outr, (long long) inmax, (long long) outmax); hist->time = now; hist->in = inr; hist->out = outr; hist->inmax = inmax; hist->outmax = outmax; nout++; hist++; now = plannow; } for (x = 1; x < DAY_COUNT; x++) { NEXT (DAY_SAMPLE); fprintf (fo, "%ld " LLD " " LLD " " LLD " " LLD "\n", (long) now, (long long) inr, (long long) outr, (long long) inmax, (long long) outmax); hist->time = now; hist->in = inr; hist->out = outr; hist->inmax = inmax; hist->outmax = outmax; nout++; hist++; now -= DAY_SAMPLE; } plannow = now; plannow /= WEEK_SAMPLE; plannow *= WEEK_SAMPLE; if (plannow < now) { NEXT ((long) (now - plannow)); fprintf (fo, "%ld " LLD " " LLD " " LLD " " LLD "\n", (long) now, (long long) inr, (long long) outr, inmax, outmax); hist->time = now; hist->in = inr; hist->out = outr; hist->inmax = inmax; hist->outmax = outmax; nout++; hist++; now = plannow; } for (x = 0; x < WEEK_COUNT; x++) { NEXT (WEEK_SAMPLE); fprintf (fo, "%ld " LLD " " LLD " " LLD " " LLD "\n", (long) now, (long long) inr, (long long) outr, inmax, outmax); hist->time = now; hist->in = inr; hist->out = outr; hist->inmax = inmax; hist->outmax = outmax; nout++; hist++; now -= WEEK_SAMPLE; } plannow = now; plannow /= MONTH_SAMPLE; plannow *= MONTH_SAMPLE; if (plannow < now) { NEXT ((long) (now - plannow)); fprintf (fo, "%ld " LLD " " LLD " " LLD " " LLD "\n", (long) now, (long long) inr, (long long) outr, inmax, outmax); hist->time = now; hist->in = inr; hist->out = outr; hist->inmax = inmax; hist->outmax = outmax; nout++; hist++; now = plannow; } for (x = 0; x < MONTH_COUNT; x++) { NEXT (MONTH_SAMPLE); fprintf (fo, "%ld " LLD " " LLD " " LLD " " LLD "\n", (long) now, (long long) inr, (long long) outr, inmax, outmax); hist->time = now; hist->in = inr; hist->out = outr; hist->inmax = inmax; hist->outmax = outmax; nout++; hist++; now -= MONTH_SAMPLE; } plannow = now; plannow /= YEAR_SAMPLE; plannow *= YEAR_SAMPLE; if (plannow < now) { NEXT ((long) (now - plannow)); fprintf (fo, "%ld " LLD " " LLD " " LLD " " LLD "\n", (long) now, (long long) inr, (long long) outr, inmax, outmax); hist->time = now; hist->in = inr; hist->out = outr; hist->inmax = inmax; hist->outmax = outmax; nout++; hist++; now = plannow; } for (x = 0; x < YEAR_COUNT; x++) { NEXT (YEAR_SAMPLE); fprintf (fo, "%ld " LLD " " LLD " " LLD " " LLD "\n", (long) now, (long long) inr, (long long) outr, inmax, outmax); hist->time = now; hist->in = inr; hist->out = outr; hist->inmax = inmax; hist->outmax = outmax; nout++; hist++; now -= YEAR_SAMPLE; } if (ferror (fo) || fclose (fo)) { perror (program); fprintf (stderr, "%s, Rateup ERROR: Can't write new log file\n", bufftime); exit (1); } #ifdef WIN32 /* another fix to get things working under NT */ if (unlink (buf2)) { fprintf (stderr, "%s, Rateup WARNING: %s Can't remove %s updating log file\n", bufftime, program, buf2); } #endif if (rename (buf1, buf2)) { fprintf (stderr, "%s, Rateup WARNING: %s Can't rename %s to %s updating log file\n", bufftime, program, buf1, buf2); } if (rename (buf, buf1)) { fprintf (stderr, "%s, Rateup WARNING: %s Can't rename %s to %s updating log file\n", bufftime, program, buf, buf1); } for (n = 0; n < nout && n < MAX_HISTORY; n++) { history[n] = lhist[n]; } } else { perror (program); fprintf (stderr, "%s, Rateup ERROR: Can't open %s for write\n", bufftime, buf); exit (1); } free (lhist); } static void init_colour (int *colmap, int c0, int c1, int c2) { *colmap++ = c0; *colmap++ = c1; *colmap = c2; } /* Constants for readparm option */ #define LENGTH_OF_BUFF (2048) #define NUMBER_OF_PARM (100) char buff[LENGTH_OF_BUFF + 1]; char *program; static int readparam (char const *file) { FILE *fp = NULL; int cbuf; /* Open the file */ if ((fp = fopen (file, "r")) == NULL) { fprintf (stderr, "%s, %s ERROR: Can't open parameters file: %s\n", bufftime, program, file); return (1); } /* Check we actually got something */ if (!(cbuf = fread (buff, 1, LENGTH_OF_BUFF, fp))) { fprintf (stderr, "%s, %s ERROR: Parameters file empty\n", bufftime, program); fclose(fp); return (1); } fclose (fp); buff[cbuf] = '\0'; /* #define READPARAM_INFO */ #ifdef READPARAM_INFO fprintf (stderr, "%s, %s INFO: Read: %d bytes from File: '%s'\n", bufftime, program, cbuf, file); #endif return (0); } int main (argc, argv) int argc; char **argv; { int x, argi, used, initarg; program = argv[0]; /* jpt, april 2006 : 3 lines for date & time logging */ (void) time(×tamp); stLocal = localtime(×tamp); strftime(bufftime, 32, "%Y-%m-%d %H:%M:%S", stLocal); /* Is Argv[1] a path/file to passed parameters? */ if ((argc > 1) && (strncasecmp (argv[1], "-F", 2) == 0)) { char *b, *c, *l; if (readparam (argv[2])) { return (1); } /* Parse buffer into argv[] */ argv = calloc (NUMBER_OF_PARM + 1, sizeof (char *)); argc = 0; b = buff; l = b + strlen (b); while (b < l) { if (b[0] == '"') { b++; c = strstr (b, "\""); if (c != NULL) { *c = '\0'; argv[argc] = b; argc++; b = c + 2; } else { fprintf (stderr, "%s, Rateup ERROR: Parameter %d [%s] missing quote\n", bufftime, argc, b); break; } } else { c = strstr (b, " "); if (c != NULL) { *c = '\0'; argv[argc] = b; argc++; b = c + 1; } else { argv[argc] = b; argc++; b = l; } } if (argc == NUMBER_OF_PARM) { break; } } /* Check we didn't fill argv[] */ if (argc == NUMBER_OF_PARM) { fprintf (stderr, "%s, Rateup ERROR: Too many parameters read: %d\n", bufftime, argc); return (1); } /* Check we didn't end early */ if (b < l) { return (1); } /* Mark End of argv[] */ argv[argc] = NULL; #ifdef READPARAM_DEBUG for (i = 0; i < argc; i++) { printf ("ParameterX %2d : '%s'\n", i, argv[i] ? argv[i] : ""); } #endif } if (argc < 3) { fprintf (stderr, "%s, %s for MRTG %s\n" "Usage: %s -f \n" " %s directory basename [sampletime] [t sampletime] " "[-(t)ransparent] [-(b)order]" "[u|a|g|h|m in out abs_max] " "[i/p file maxvi maxvo maxx maxy growright step bits]\n", bufftime, program, VERSION, program, program); return (1); } routerpath = argv[1]; /* this is for NT compatibility, because it does not seem to like rename across directories */ if (chdir (routerpath)) { fprintf (stderr, "%s, Rateup ERROR: Chdir to %s failed ...\n", bufftime, routerpath); return (1); } /* Initialiase the colour variables - should be overwritten */ init_colour (&col_in[0], c_in); init_colour (&col_out[0], c_out); init_colour (&col_inm[0], c_inm); init_colour (&col_outm[0], c_outm); init_colour (&col_outp[0], c_outp); if ((history = calloc (1, sizeof (struct HISTORY) * (MAX_HISTORY + 1))) == NULL) { fprintf (stderr, "%s, Rateup ERROR: Out of memory in main\n", bufftime); exit (1); } #if defined(__WATCOMC__) || defined(NETWARE) memset (history, 0, sizeof (struct HISTORY) * (MAX_HISTORY + 1)); #endif Mh = MAX_HISTORY; router = argv[2]; if (strlen(router) > 120) { fprintf (stderr, "%s, Rateup ERROR: Too long basename\n", bufftime); exit (1); } /* from mrtg-2.x with x>5 rateup calling syntax changed to to support time properly ... this is for backward compat we check if now is remotely reasonable ... */ if (argc > 3) { NOW = atol (argv[3]); if (NOW > 10 * 365 * 24 * 60 * 60) { initarg = 4; } else { initarg = 3; time (&NOW); } } else { initarg = 3; time (&NOW); } readfile (); used = 1; for (argi = initarg; argi < argc; argi += used) { switch (argv[argi][0]) { case '-': /* -options */ switch (argv[argi][1]) { case 'a': /* Turn off the direction arrow */ options |= OPTION_NOARROW; used = 1; break; case 'A': /* Turn on the direction arrow */ options &= ~OPTION_NOARROW; used = 1; break; case 'b': /* Turn off the shaded border */ options |= OPTION_NOBORDER; used = 1; break; case 'B': /* Turn on the shaded border */ options &= ~OPTION_NOBORDER; used = 1; break; case 'i': /* Do not graph the I variable */ options |= OPTION_NO_I; used = 1; break; case 'I': /* Graph the I variable */ options &= ~OPTION_NO_I; used = 1; break; case 'o': /* Do not graph the O variable */ options |= OPTION_NO_O; used = 1; break; case 'O': /* Graph the O variable */ options &= ~OPTION_NO_O; used = 1; break; case 'l': /* logarithmic scaling */ options |= OPTION_LOGGRAPH; options &= ~OPTION_MEANOVER; options &= ~OPTION_EXPGRAPH; used = 1; break; case 'm': /* second-mean scaling */ options |= OPTION_MEANOVER; options &= ~OPTION_LOGGRAPH; options &= ~OPTION_EXPGRAPH; used = 1; break; case 'p': /* print router name in image */ options |= OPTION_PRINTROUTER; used = 1; break; case 't': /* Transparent Image */ options |= OPTION_TRANSPARENT; used = 1; break; case 'T': /* non-Transparent Image */ options &= ~OPTION_TRANSPARENT; used = 1; break; case 'x': /* exponential scaling */ options |= OPTION_EXPGRAPH; options &= ~OPTION_MEANOVER; options &= ~OPTION_LOGGRAPH; used = 1; break; case 'z': /* unknown as zero */ options |= OPTION_UNKNASZERO; used = 1; break; case 'Z': /* repeat last */ options &= ~OPTION_UNKNASZERO; used = 1; break; case '0': /* assume zeroes */ options |= OPTION_WITHZEROES; used = 1; break; default: fprintf (stderr, "%s, Rateup ERROR: Unknown option: %s, sorry!\n", bufftime, argv[argi]); return (1); } break; case 'i': /* Create PPM Image record */ image (argv[argi + 1], /* Image */ strtoll (argv[argi + 2], NULL, 10), /* Max Value In */ strtoll (argv[argi + 3], NULL, 10), /* Max Value Out */ atol (argv[argi + 4]), /* xsize maxx */ atol (argv[argi + 5]), /* ysize maxy */ atof (argv[argi + 6]), /* xscale */ atof (argv[argi + 7]), /* yscale */ atol (argv[argi + 8]), /* growright */ atol (argv[argi + 9]), /* step */ atol (argv[argi + 10]), /* bits */ atol (argv[argi + 11]), /* ytics */ atof (argv[argi + 12]), /* yticsfactor */ 0, argv[argi + 13], atol (argv[argi + 14])); used = 15; break; case 'p': /* Create PPM Image record with Peak values */ image (argv[argi + 1], strtoll (argv[argi + 2], NULL, 10), /* Max Value In */ strtoll (argv[argi + 3], NULL, 10), /* Max Value Out */ atol (argv[argi + 4]), /* xsize maxx */ atol (argv[argi + 5]), /* ysize maxy */ atof (argv[argi + 6]), /* xscale */ atof (argv[argi + 7]), /* yscale */ atol (argv[argi + 8]), /* growright */ atol (argv[argi + 9]), /* step */ atol (argv[argi + 10]), /* bits */ atol (argv[argi + 11]), /* ytics */ atof (argv[argi + 12]), /* yticsfactor */ 1, argv[argi + 13], atol (argv[argi + 14])); used = 15; break; case 'r': /* Create random records, then update */ for (x = 0; x < histvalid; x++) { history[x].in = rand () % atoi (argv[argi + 1]); history[x].out = rand () % atoi (argv[argi + 2]); } /* fallthrough */ case 'u': /* Update file */ if (argv[argi][1] == 'p') { options |= OPTION_DORELPERCENT; } update (argv[argi + 1], argv[argi + 2], strtoll (argv[argi + 3], NULL, 10), 0); used = 4; break; case 'a': /* Absolute Update file */ if (argv[argi][1] == 'p') { options |= OPTION_DORELPERCENT; } update (argv[argi + 1], argv[argi + 2], strtoll (argv[argi + 3], NULL, 10), 1); used = 4; break; case 'g': /* Gauge Update file */ if (argv[argi][1] == 'p') { options |= OPTION_DORELPERCENT; } update (argv[argi + 1], argv[argi + 2], strtoll (argv[argi + 3], NULL, 10), 2); used = 4; break; case 'h': if (argv[argi][1] == 'p') { options |= OPTION_DORELPERCENT; } update (argv[argi + 1], argv[argi + 2], strtoll (argv[argi + 3], NULL, 10), 3); used = 4; break; case 'm': if (argv[argi][1] == 'p') { options |= OPTION_DORELPERCENT; } update (argv[argi + 1], argv[argi + 2], strtoll (argv[argi + 3], NULL, 10), 4); used = 4; break; case 'W': /* Week format */ weekformat = argv[argi + 1][0]; used = 2; break; case 'c': /* Colour Map */ sscanf (argv[argi + 1], "#%2x%2x%2x", &col_in[0], &col_in[1], &col_in[2]); sscanf (argv[argi + 2], "#%2x%2x%2x", &col_out[0], &col_out[1], &col_out[2]); sscanf (argv[argi + 3], "#%2x%2x%2x", &col_inm[0], &col_inm[1], &col_inm[2]); sscanf (argv[argi + 4], "#%2x%2x%2x", &col_outm[0], &col_outm[1], &col_outm[2]); used = 5; break; case 'C': /* Extented Colour Map */ sscanf (argv[argi + 1], "#%2x%2x%2x", &col_in[0], &col_in[1], &col_in[2]); sscanf (argv[argi + 2], "#%2x%2x%2x", &col_out[0], &col_out[1], &col_out[2]); sscanf (argv[argi + 3], "#%2x%2x%2x", &col_inm[0], &col_inm[1], &col_inm[2]); sscanf (argv[argi + 4], "#%2x%2x%2x", &col_outm[0], &col_outm[1], &col_outm[2]); sscanf (argv[argi + 5], "#%2x%2x%2x", &col_outp[0], &col_outp[1], &col_outp[2]); used = 6; break; case 't': NOW = atol (argv[argi + 1]); used = 2; break; case 'k': kilo = atol (argv[argi + 1]); used = 2; break; case 'K': kMG = calloc (strlen (argv[argi + 1]) + 1, sizeof (char)); strcpy (kMG, argv[argi + 1]); used = 2; break; case 'Z': /* Timezone name */ rtimezone = argv[argi + 1]; used = 2; break; case 'l': /* YLegend - rewritten by Oliver Haidi, re-rewritten by Jon Barber */ { int i, j, k, loop = 1; int start = 1, got_esc = 0, append_ok; char *qstr; longup = (char *) calloc (1, 100); *longup = 0; /* this rather twisty argument scanning is necesary because NT command.coms rather dumb argument passing .... or because we don't know better. Under Unix we just would say. if ((sscanf(argv[argi+1],"[%[^]]]", longup); */ /* at start, check 1st char must be [ */ if (argv[argi + 1][0] != '[') { fprintf (stderr, "%s, Rateup ERROR: YLegend: Option must be passed with '[' at start and ']' at end (these will not be printed).\n", bufftime); return (1); } for (i = 1; (i < argc) && loop; i++) { /* check all args until unescaped ']' */ qstr = argv[argi + i]; for (j = start; ((size_t) j < strlen (qstr)) && loop; j++) { start = 0; /* 1st char in 1st arg already checked */ append_ok = 1; /* OK to append unless we find otherwise */ if (qstr[j] == '\\') { if (++got_esc == 1) { append_ok = 0; /* don't append 1st '/' */ } else { got_esc = 0; /* 2nd '/' in a row, i.e. '//' */ } } if (qstr[j] == ']') { /* is this the end? */ if (got_esc == 1) { if (strlen (qstr + j) >= 2) { append_ok = 1; got_esc = 0; } else { fprintf (stderr, "%s, 1a: rateup ERROR: YLegend: use \"\\]\" for \"]\" or \"\\\\\" for \"\\\".\n", bufftime); return (1); } } else { if (strlen (qstr + j) >= 2) { fprintf (stderr, "%s, 2a: rateup ERROR: YLegend: use \"\\]\" for \"]\" or \"\\\\\" for \"\\\".\n", bufftime); return (1); } loop = 0; append_ok = 0; } } if (append_ok == 1) { k = strlen (longup); if ((size_t) (k + 1) > 99) { fprintf (stderr, "%s, 3a: rateup ERROR: YLegend too long\n", bufftime); return (1); } longup[k] = qstr[j]; longup[k + 1] = 0; } } /* for (j=start...) */ /* append space */ k = strlen (longup); if ((size_t) (k + 1) > 99) { fprintf (stderr, "%s, 4a: rateup ERROR: YLegend too long\n", bufftime); return (1); } longup[k] = ' '; longup[k + 1] = 0; } /* for (i =1 ... */ used = i; } /* remove trailing space */ longup[max (0, (signed) strlen (longup) - 1)] = 0; shortup = longup; /* fprintf(stderr, "%s, YLegend = \"%s\"\n", bufftime, longup); */ break; case 'T': /* pngTitle - based on YLegend */ { int i, j, k, loop = 1; int start = 1, got_esc = 0, append_ok; char *qstr; pngtitle = (char *) calloc (1, 100); *pngtitle = 0; /* this rather twisty argument scanning is necesary because NT command.coms rather dumb argument passing .... or because we don't know better. Under Unix we just would say. if ((sscanf(argv[argi+1],"[%[^]]]", pngtitle); */ /* at start, check 1st char must be [ */ if (argv[argi + 1][0] != '[') { fprintf (stderr, "%s, Rateup ERROR: YLegend: Option must be passed with '[' at start and ']' at end (these will not be printed).\n", bufftime); return (1); } for (i = 1; (i < argc) && loop; i++) { /* check all args until unescaped ']' */ qstr = argv[argi + i]; for (j = start; ((size_t) j < strlen (qstr)) && loop; j++) { start = 0; /* 1st char in 1st arg already checked */ append_ok = 1; /* OK to append unless we find otherwise */ if (qstr[j] == '\\') { if (++got_esc == 1) { append_ok = 0; /* don't append 1st '/' */ } else { got_esc = 0; /* 2nd '/' in a row, i.e. '//' */ } } if (qstr[j] == ']') { /* is this the end? */ if (got_esc == 1) { if (strlen (qstr + j) >= 2) { append_ok = 1; got_esc = 0; } else { fprintf (stderr, "%s, 1b: rateup ERROR: YLegend: use \"\\]\" for \"]\" or \"\\\\\" for \"\\\".\n", bufftime); return (1); } } else { if (strlen (qstr + j) >= 2) { fprintf (stderr, "%s, 2b: rateup ERROR: YLegend: use \"\\]\" for \"]\" or \"\\\\\" for \"\\\".\n", bufftime); return (1); } loop = 0; append_ok = 0; } } if (append_ok == 1) { k = strlen (pngtitle); if ((size_t) (k + 1) > 99) { fprintf (stderr, "%s, 3b: rateup ERROR: YLegend too long\n", bufftime); return (1); } pngtitle[k] = qstr[j]; pngtitle[k + 1] = 0; } } /* for (j=start...) */ /* append space */ k = strlen (pngtitle); if ((size_t) (k + 1) > 99) { fprintf (stderr, "%s, 4b: rateup ERROR: YLegend too long\n", bufftime); return (1); } pngtitle[k] = ' '; pngtitle[k + 1] = 0; } /* for (i =1 ... */ used = i; } /* remove trailing space */ pngtitle[max (0, (signed) strlen (pngtitle) - 1)] = 0; /* fprintf(stderr, "%s, YLegend = \"%s\"\n", bufftime, pngtitle); */ break; default: fprintf (stderr, "%s, Rateup ERROR: Can't cope with %s, sorry!\n", bufftime, argv[argi]); return (1); } } return (0); } mrtg-2.17.10/src/strftime.c0000644000175300017510000002416514171763414014456 0ustar oetikeroep/** * * strftime.c * * implements the ansi c function strftime() * * written 6 september 1989 by jim nutt * released into the public domain by jim nutt * * modified 21-Oct-89 by Rob Duff * * modified 08-Dec-04 by Tobi Oetiker (added %V) **/ #include /* for size_t */ #include /* for va_arg */ #include /* for struct tm */ #include "strftime.h" static char *aday[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; static char *day[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; static char *amonth[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; static char *month[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; char *tzname_[2] = {"CST", "CDT"}; /* Add your own defaults here */ static char buf[26]; static void strfmt(char *str, const char *fmt, ...); /** * * size_t strftime_(char *str, * size_t maxs, * const char *fmt, * const struct tm *t) * * this functions acts much like a sprintf for time/date output. * given a pointer to an output buffer, a format string and a * time, it copies the time to the output buffer formatted in * accordance with the format string. the parameters are used * as follows: * * str is a pointer to the output buffer, there should * be at least maxs characters available at the address * pointed to by str. * * maxs is the maximum number of characters to be copied * into the output buffer, included the '\0' terminator * * fmt is the format string. a percent sign (%) is used * to indicate that the following character is a special * format character. the following are valid format * characters: * * %A full weekday name (Monday) * %a abbreviated weekday name (Mon) * %B full month name (January) * %b abbreviated month name (Jan) * %c standard date and time representation * %d day-of-month (01-31) * %H hour (24 hour clock) (00-23) * %I hour (12 hour clock) (01-12) * %j day-of-year (001-366) * %M minute (00-59) * %m month (01-12) * %p local equivalent of AM or PM * %S second (00-59) * %U week-of-year, first day sunday (00-53) * %W week-of-year, first day monday (00-53) * %V ISO 8601 Week number * %w weekday (0-6, sunday is 0) * %X standard time representation * %x standard date representation * %Y year with century * %y year without century (00-99) * %Z timezone name * %% percent sign * * the standard date string is equivalent to: * * %a %b %d %Y * * the standard time string is equivalent to: * * %H:%M:%S * * the standard date and time string is equivalent to: * * %a %b %d %H:%M:%S %Y * * strftime_() returns the number of characters placed in the * buffer, not including the terminating \0, or zero if more * than maxs characters were produced. * **/ size_t strftime_(char *s, size_t maxs, const char *f, const struct tm *t) { int w,d; char *p, *q, *r; p = s; q = s + maxs - 1; while ((*f != '\0')) { if (*f++ == '%') { r = buf; switch (*f++) { case '%' : r = "%"; break; case 'a' : r = aday[t->tm_wday]; break; case 'A' : r = day[t->tm_wday]; break; case 'b' : r = amonth[t->tm_mon]; break; case 'B' : r = month[t->tm_mon]; break; case 'c' : strfmt(r, "%0 %0 %2 %2:%2:%2 %4", aday[t->tm_wday], amonth[t->tm_mon], t->tm_mday,t->tm_hour, t->tm_min, t->tm_sec, t->tm_year+1900); break; case 'd' : strfmt(r,"%2",t->tm_mday); break; case 'H' : strfmt(r,"%2",t->tm_hour); break; case 'I' : strfmt(r,"%2",(t->tm_hour%12)?t->tm_hour%12:12); break; case 'j' : strfmt(r,"%3",t->tm_yday+1); break; case 'm' : strfmt(r,"%2",t->tm_mon+1); break; case 'M' : strfmt(r,"%2",t->tm_min); break; case 'p' : r = (t->tm_hour>11)?"PM":"AM"; break; case 'S' : strfmt(r,"%2",t->tm_sec); break; case 'U' : w = t->tm_yday/7; if (t->tm_yday%7 > t->tm_wday) w++; strfmt(r, "%2", w); break; case 'W' : w = t->tm_yday/7; if (t->tm_yday%7 > (t->tm_wday+6)%7) w++; strfmt(r, "%2", w); break; case 'V': /* ISO 8601 Week Of Year: If the week (Monday - Sunday) containing January 1 has four or more days in the new year, then it is week 1; otherwise it is week 53 of the previous year and the next week is week one. */ w = (t->tm_yday + 7 - (t->tm_wday ? t->tm_wday - 1 : 6)) / 7; d = (t->tm_yday + 7 - (t->tm_wday ? t->tm_wday - 1 : 6)) % 7; if (d >= 4) { w++; } else if (w == 0) { w = 53; } strfmt(r, "%2", w); break; case 'w' : strfmt(r,"%1",t->tm_wday); break; case 'x' : strfmt(r, "%3s %3s %2 %4", aday[t->tm_wday], amonth[t->tm_mon], t->tm_mday, t->tm_year+1900); break; case 'X' : strfmt(r, "%2:%2:%2", t->tm_hour, t->tm_min, t->tm_sec); break; case 'y' : strfmt(r,"%2",t->tm_year%100); break; case 'Y' : strfmt(r,"%4",t->tm_year+1900); break; case 'Z' : r = (t->tm_isdst && tzname_[1][0]) ? tzname_[1] : tzname_[0]; break; default: buf[0] = '%'; /* reconstruct the format */ buf[1] = f[-1]; buf[2] = '\0'; if (buf[1] == 0) f--; /* back up if at end of string */ } while (*r) { if (p == q) { *q = '\0'; return 0; } *p++ = *r++; } } else { if (p == q) { *q = '\0'; return 0; } *p++ = f[-1]; } } *p = '\0'; return p - s; } /* * stdarg.h * typedef void *va_list; #define va_start(vp,v) (vp=((char*)&v)+sizeof(v)) #define va_arg(vp,t) (*((t*)(vp))++) #define va_end(vp) * */ static int pow[5] = { 1, 10, 100, 1000, 10000 }; /** * static void strfmt(char *str, char *fmt); * * simple sprintf for strftime * * each format descriptor is of the form %n * where n goes from zero to four * * 0 -- string %s * 1..4 -- int %?.?d * **/ static void strfmt(char *str, const char *fmt, ...) { int ival, ilen; char *sval; va_list vp; va_start(vp, fmt); while (*fmt) { if (*fmt++ == '%') { ilen = *fmt++ - '0'; if (ilen == 0) /* zero means string arg */ { sval = va_arg(vp, char*); while (*sval) *str++ = *sval++; } else /* always leading zeros */ { ival = va_arg(vp, int); while (ilen) { ival %= pow[ilen--]; *str++ = (char)('0' + ival / pow[ilen]); } } } else *str++ = fmt[-1]; } *str = '\0'; va_end(vp); } #ifdef TEST #include /* for printf */ #include /* for strftime */ char test[80]; int main(int argc, char *argv[]) { int len; char *fmt; time_t now; time(&now); fmt = (argc == 1) ? "%I:%M %p\n%c\n" : argv[1]; len = strftime_(test,sizeof test, fmt, localtime(&now)); printf("%d: %s\n", len, test); return !len; } #endif /* TEST */ mrtg-2.17.10/src/strftime.h0000644000175300017510000000065213057016062014446 0ustar oetikeroep/* ** STRFTIME.H - For older compilers which lack strftime() ** ** Note: To avoid name collision with newer compilers, the function name ** strftime_() is used. */ #ifndef STRFTIME__H #define STRFTIME__H #include /* for size_t */ #include /* for struct tm */ size_t strftime_(char *s, size_t maxs, const char *f, const struct tm *t); extern char * tzname_[2]; #endif /* STRFTIME__H */ mrtg-2.17.10/translate/0000755000175300017510000000000014171763055013654 5ustar oetikeroepmrtg-2.17.10/translate/indonesia.pmd0000644000175300017510000001273313057016062016324 0ustar oetikeroep###### PATCHTAG 00 ################################################### ### Indonesian/Indonesia ### => Jamaludin Ahmad ### taken from malaysian translation ### by Assakhof Ab. Satar ###### PATCHTAG 10 ################################################### &indonesia ###### PATCHTAG 20 ################################################### 'indonesia' => \&indonesia, 'indonesian' => \&indonesia, ###### PATCHTAG 30 ################################################### # Indonesian/Indonesia 'indonesia' => "Terjemahan ke bahasa Indonesia oleh: Jamaludin Ahmad <jamaludin\@jamalinux.com>", ###### PATCHTAG 40 ################################################### $credits::LOCALE{'indonesian'}=$credits::LOCALE{'indonesia'}; ###### PATCHTAG 50 ################################################### # Malaysian/Indonesian/Malay sub indonesia { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Trafik Masuk Maksimum dalam 5 Menit', 'Maximal 5 Minute Outgoing Traffic' => 'Trafik Keluar Maksimum dalam 5 Menit', 'the device' => 'device', 'The statistics were last updated(.*)' => 'Statistik ini terakhir kali diupdate pada $1', ' Average\)' => ')', 'Average' => 'Rata-rata', 'Max' => 'Maksimum', 'Current' => 'Sekarang', 'version' => 'versi', '`Daily\' Graph \((.*) Minute' => 'Grafik Harian (Rata-rata per $1 menit', '`Weekly\' Graph \(30 Minute' => 'Grafik Mingguan (Rata-rata per 30 menit', '`Monthly\' Graph \(2 Hour' => 'Grafik Bulanan (Rata-rata per 2 jam', '`Yearly\' Graph \(1 Day' => 'Grafik Tahunan (Rata-rata per hari', 'Incoming Traffic in (\S+) per Second' => 'Trafik Masuk $1 per detik', 'Outgoing Traffic in (\S+) per Second' => 'Trafik Keluar $1 per detik', 'at which time (.*) had been up for(.*)' => 'Pada saat $1 telah aktif selama $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/j', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Masuk', 'Out' => 'Keluar', 'Percentage' => 'Persentase', 'Ported to OpenVMS Alpha by' => 'Porting ke OpenVMS Alpha oleh', 'Ported to WindowsNT by' => 'Porting ke WindowsNT oleh', 'and' => 'dan', '^GREEN' => 'HIJAU', 'BLUE' => 'BIRU', 'DARK GREEN' => 'HIJAU GELAP', 'MAGENTA' => 'MAGENTA', 'AMBER' => 'AMBAR' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Ahad', 'Sun' => 'Aha', 'Monday' => 'Senin', 'Mon' => 'Sen', 'Tuesday' => 'Selasa', 'Tue' => 'Sel', 'Wednesday' => 'Rabu', 'Wed' => 'Rab', 'Thursday' => 'Kamis', 'Thu' => 'Kam', 'Friday' => 'Jumat', 'Fri' => 'Jum', 'Saturday' => 'Sabtu', 'Sat' => 'Sab' ); %month = ( 'January' => 'Januari', 'February' => 'Februari' , 'March' => 'Maret', 'Jan' => 'Jan', 'Feb' => 'Feb', 'Mar' => 'Mar', 'April' => 'April', 'May' => 'Mei', 'June' => 'Juni', 'Apr' => 'Apr', 'May' => 'Mei', 'Jun' => 'Jun', 'July' => 'Juli', 'August' => 'Agustus', 'September' => 'September', 'Jul' => 'Jul', 'Aug' => 'Ags', 'Sep' => 'Sep', 'October' => 'Oktober', 'November' => 'November', 'December' => 'Desember', 'Oct' => 'Okt', 'Nov' => 'Nov', 'Dec' => 'Des' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." pada ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/catalan.pmd0000644000175300017510000001162214171553254015761 0ustar oetikeroep###### PATCHTAG00 #################################################### ### catalan/Català ### => LLuís Gras ###### PATCHTAG10 #################################################### &catalan ###### PATCHTAG20 #################################################### 'catalan' => \&catalan, 'catalan' => \&catalan, ###### PATCHTAG30 #################################################### # catalan/catalan 'catalan' => "Preparat per a localització per: Lluís Gras", ###### PATCHTAG40 #################################################### $credits::LOCALE{'catalan'}=$credits::LOCALE{'catalan'}; ###### PATCHTAG50 #################################################### # catalan sub catalan { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Tràfic entrant màxim en 5 minuts', 'Maximal 5 Minute Outgoing Traffic' => 'Tràfic sortint màxim en 5 minuts', 'the device' => 'el dispositiu', 'The statistics were last updated(.*)' => 'Estadístiques actualitzades el $1', ' Average\)' => ' Promig)', 'Average' => 'Promig', 'Max' => 'Màxim', 'Current' => 'Actual', 'version' => 'versió', '`Daily\' Graph \((.*) Minute' => 'Gràfic diari ($1 minuts :', '`Weekly\' Graph \(30 Minute' => 'Gràfic setmanal (30 minuts :' , '`Monthly\' Graph \(2 Hour' => 'Gràfic mensual (2 hores :', '`Yearly\' Graph \(1 Day' => 'Gràfic anual (1 dia :', 'Incoming Traffic in (\S+) per Second' => 'Tràfic entrant en $1 per segon', 'Outgoing Traffic in (\S+) per Second' => 'Tràfic sortint en $1 per segon', 'at which time (.*) had been up for(.*)' => '$1 ha estat funcionant durant $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', # '([kMG]?)([bB])/h' => '$1$2/t', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Entrant', 'Out' => 'Sortint', 'Percentage' => 'Percentatge', 'Ported to OpenVMS Alpha by' => 'Portat a OpenVMS Alpha per', 'Ported to WindowsNT by' => 'Portat a WindowsNT per', 'and' => 'i', '^GREEN' => 'VERD', 'BLUE' => 'BLAU', 'DARK GREEN' => 'VERD FOSC', 'MAGENTA' => 'MAGENTA', 'AMBER' => 'AMBAR' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Diumenge', 'Sun' => 'Dg', 'Monday' => 'Dilluns', 'Mon' => 'Dl', 'Tuesday' => 'Dimarts', 'Tue' => 'Dm', 'Wednesday' => 'Dimecres', 'Wed' => 'Dc', 'Thursday' => 'Dijous', 'Thu' => 'Dj', 'Friday' => 'Divendres', 'Fri' => 'Dv', 'Saturday' => 'Dissabte', 'Sat' => 'Ds' ); %month = ( 'January' => 'Gener', 'February' => 'Febrer' , 'March' => 'Març', 'Jan' => 'Gen', 'Feb' => 'Feb', 'Mar' => 'Mar', 'April' => 'Abril', 'May' => 'Maig', 'June' => 'Juny', 'Apr' => 'Abr', 'May' => 'Mai', 'Jun' => 'Jun', 'July' => 'Juliol', 'August' => 'Agost', 'September' => 'Setembre', 'Jul' => 'Jul', 'Aug' => 'Ago', 'Sep' => 'Set', 'October' => 'Octubre', 'November' => 'Novembre', 'December' => 'Desembre', 'Oct' => 'Oct', 'Nov' => 'Nov', 'Dec' => 'Des' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." a les ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] de $month{$foo[2]} de $foo[3]"; }; return $string; }; mrtg-2.17.10/translate/romanian.pmd0000644000175300017510000001361713057016062016161 0ustar oetikeroep###### PATCHTAG 00 ################################################### ### Romn/Romanian ### => Jzsef Szilgyi ###### PATCHTAG 10 ################################################### &romanian ###### PATCHTAG 20 ################################################### 'romanian' => \&romanian, 'romn' => \&romanian, ###### PATCHTAG 30 ################################################### # Romn/romanian 'romanian' => "Tradus de Jzsef Szilgyi <jozsi\@maxiq.ro>", ###### PATCHTAG 40 ################################################### $credits::LOCALE{'romn'}=$credits::LOCALE{'romanian'}; ###### PATCHTAG 50 ################################################### # Romanian sub romanian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-8859-2 %translations = ( 'iso-8859-1' => 'iso-8859-2', 'Maximal 5 Minute Incoming Traffic' => 'Traficul Maxim de intrare pe 5 Minute', 'Maximal 5 Minute Outgoing Traffic' => 'Traficul Maxim de iesire pe 5 Minute', 'the device' => 'echipamentul', 'The statistics were last updated(.*)' => 'Ultima actualizare :$1', ' Average\)' => '', 'Average' => 'Medie', 'Max' => 'Maxim', 'Current' => 'Curent', 'version' => 'versiunea', '`Daily\' Graph \((.*) Minute' => 'Graficul \'Zilnic\' (medie pe $1 minute)', '`Weekly\' Graph \(30 Minute' => 'Graficul \'Sptmnal\' (medie pe 30 de minute)' , '`Monthly\' Graph \(2 Hour' => 'Graficul \'Lunar\' (medie pe 2 ore)', '`Yearly\' Graph \(1 Day' => 'Graficul \'Anual\' (medie pe 1 zi)', 'Incoming Traffic in (\S+) per Second' => 'Traficul de intrare [$1/secund]', 'Outgoing Traffic in (\S+) per Second' => 'Traficul de ieire [$1/secund]', 'at which time (\S+) had been up for (\S+)' => 'cnd $1 funciona de $2', 'at which time (\S+) had been up for (\S+) day, (\S+)' => 'cnd $1 funciona de $2 zi, $3', 'at which time (\S+) had been up for (\S+) days, (\S+)' => 'cnd $1 funciona de $2 zile, $3', #'(.+)/s$' => '$1/s', #'(.+)/min' => '$1/min', '(.+)/h$' => '$1/ora', #'([kMG]?)([bB])/s' => '$1$2/s', #'([kMG]?)([bB])/min' => '$1$2/min', '([kMG]?)([bB])/h' => '$1$2/ora', 'Bits' => 'Bii', 'Bytes' => 'Octei', 'In' => 'int', 'Out' => 'ie', 'Percentage' => 'procent', 'Ported to OpenVMS Alpha by' => 'Translatat sub OpenVMS de', 'Ported to WindowsNT by' => 'Translatat sub WindowsNT de', 'and' => 'i', '^GREEN' => 'VERDE', 'BLUE' => 'ALBASTRU', 'DARK GREEN' => 'VERDE NCHIS', 'MAGENTA' => 'PURPURIU', 'AMBER' => 'GALBEN', ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'duminic', 'Sun' => 'lu', 'Monday' => 'luni', 'Mon' => 'ma', 'Tuesday' => 'mari', 'Tue' => 'mi', 'Wednesday' => 'miercuri', 'Wed' => 'jo', 'Thursday' => 'joi', 'Thu' => 'vi', 'Friday' => 'vineri', 'Fri' => 's', 'Saturday' => 'smbt', 'Sat' => 'du' ); %month = ( 'January' => 'ianuarie', 'February' => 'februarie' , 'March' => 'martie', 'Jan' => 'ian', 'Feb' => 'feb', 'Mar' => 'mar', 'April' => 'aprilie', 'May' => 'mai', 'June' => 'iunie', 'Apr' => 'apr', 'May' => 'mai', 'Jun' => 'iun', 'July' => 'iulie', 'August' => 'august', 'September' => 'septembrie', 'Jul' => 'iul', 'Aug' => 'aug', 'Sep' => 'sep', 'October' => 'octombrie', 'November' => 'noiembrie', 'December' => 'decembrie', 'Oct' => 'oct', 'Nov' => 'noi', 'Dec' => 'dec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].", ora ".$quux[1]; }; return "$wday{$foo[0]}, $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/iso2022jp.pmd0000644000175300017510000001417013057016062016002 0ustar oetikeroep###### PATCHTAG00 #################################################### ### $BF|K\8l(B(ISO-2022-JP) ### => Fuminori Uematsu ###### PATCHTAG10 #################################################### &iso2022jp ###### PATCHTAG20 #################################################### 'iso2022jp' => \&iso2022jp, 'iso-2022-jp' => \&iso2022jp, ###### PATCHTAG30 #################################################### # iso2022jp/iso-2022-jp 'iso2022jp' => "\e\$BF|K\\8lLu\e(B(ISO-2022-JP)\e\$B:n\@.\e(B \e\$B?\">>\e(B \e\$BJ8FA\e(B <uematsu\@kgz.com>", ###### PATCHTAG40 #################################################### $credits::LOCALE{'iso-2022-jp'}=$credits::LOCALE{'iso2022jp'}; ###### PATCHTAG50 #################################################### # iso2022jp sub iso2022jp { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( '^iso-8859-1' => 'iso-2022-jp', '^Maximal 5 Minute Incoming Traffic' => '\e\\$B:GBg\e(B5\e\\$BJ, '\e\\$B:GBg\e(B5\e\\$BJ,Aw?.NL\e(B', '^the device' => '\e\\$B%G%P%\\$%9\e(B', '^The statistics were last updated (.*)' => '\e\\$B99?7F|;~\e(B $1', '^Average\)' => '\e\\$BJ?6Q\e(B)', '^Average$' => '\e\\$BJ?6Q\e(B', '^Max$' => '\e\\$B:GBg\e(B', '^Current' => '\e\\$B:G?7\e(B', '^`Daily\' Graph \((.*) Minute' => '\e\\$BF|%0%i%U\e(B($1\e\\$BJ,4V\e(B', '^`Weekly\' Graph \(30 Minute' => '\e\\$B=5%0%i%U\e(B(30\e\\$BJ,4V\e(B', '^`Monthly\' Graph \(2 Hour' => '\e\\$B7n%0%i%U\e(B(2\e\\$B;~4V\e(B', '^`Yearly\' Graph \(1 Day' => '\e\\$BG/%0%i%U\e(B(1\e\\$BF|\e(B', '^Incoming Traffic in (\S+) per Second' => '\e\\$BKhIC\\$N '\e\\$BKhJ,\\$N '\e\\$BKh;~\\$N '\e\\$BKhIC\\$NAw?.\e(B$1\e\\$B?t\e(B', '^Outgoing Traffic in (\S+) per Minute' => '\e\\$BKhJ,\\$NAw?.\e(B$1\e\\$B?t\e(B', '^Outgoing Traffic in (\S+) per Hour' => '\e\\$BKh;~\\$NAw?.\e(B$1\e\\$B?t\e(B', '^at which time (.*) had been up for (.*)' => '$1\e\\$B\\$N2TF/;~4V\e(B $2', '^Average max 5 min values for `Daily\' Graph \((.*) Minute interval\):' => '\e\\$BF|%0%i%U\\$G\\$N:GBg\e(B5\e\\$BJ,CM\\$NJ?6Q\e(B($1\e\\$BJ,4V3V\e(B):', '^Average max 5 min values for `Weekly\' Graph \(30 Minute interval\):' => '\e\\$B=5%0%i%U\\$G\\$N:GBg\e(B5\e\\$BJ,CM\\$NJ?6Q\e(B(30\e\\$BJ,4V3V\e(B):', '^Average max 5 min values for `Monthly\' Graph \(2 Hour interval\):' => '\e\\$B7n%0%i%U\\$G\\$N:GBg\e(B5\e\\$BJ,CM\\$NJ?6Q\e(B(2\e\\$B;~4V4V3V\e(B):', '^Average max 5 min values for `Yearly\' Graph \(1 Day interval\):' => '\e\\$BG/%0%i%U\\$G\\$N:GBg\e(B5\e\\$BJ,CM\\$NJ?6Q\e(B(1\e\\$BF|4V3V\e(B):', #'^([kMG]?)([bB])/s' => '$1$2/\e\\$BIC\e(B', #'^([kMG]?)([bB])/min' => '$1$2/\e\\$BJ,\e(B', #'^([kMG]?)([bB])/h' => '$1$2/\e\\$B;~\e(B', '^Bits$' => '\e\\$B%S%C%H\e(B', '^Bytes$' => '\e\\$B%P%\\$%H\e(B', '^In$' => '\e\\$B '\e\\$BAw?.\e(B', '^Percentage' => '\e\\$BHfN(\e(B', '^Ported to OpenVMS Alpha by' => 'OpenVMS Alpha\e\\$B\\$X\\$N0\\\?"\e(B', '^Ported to WindowsNT by' => 'WindowsNT\e\\$B\\$X\\$N0\\\?"\e(B', #'^and' => 'and', '^GREEN' => '\e\\$BNP\e(B', '^BLUE' => '\e\\$B\\@D\e(B', '^DARK GREEN' => '\e\\$B? '\e\\$B%^%<%s%?\e(B', '^AMBER' => '\e\\$B`h`a\e(B' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => "(\e\$BF|\e(B)", 'Monday' => "(\e\$B7n\e(B)", 'Tuesday' => "(\e\$B2P\e(B)", 'Wednesday' => "(\e\$B?e\e(B)", 'Thursday' => "(\e\$BLZ\e(B)", 'Friday' => "(\e\$B6b\e(B)", 'Saturday' => "(\e\$BEZ\e(B)", ); %month = ( 'January' => "1\e\$B7n\e(B", 'February' => "2\e\$B7n\e(B", 'March' => "3\e\$B7n\e(B", 'April' => "4\e\$B7n\e(B", 'May' => "5\e\$B7n\e(B", 'June' => "6\e\$B7n\e(B", 'July' => "7\e\$B7n\e(B", 'August' => "8\e\$B7n\e(B", 'September' => "9\e\$B7n\e(B", 'October' => "10\e\$B7n\e(B", 'November' => "11\e\$B7n\e(B", 'December' => "12\e\$B7n\e(B", ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)\s+(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~/at/) { @quux=split(/\s+at\s+/,$foo[3]); } else { @quux=split(/ /,$foo[3],2); }; return "$quux[0]\e\$BG/\e(B$month{$foo[2]}$foo[1]\e\$BF|\e(B$wday{$foo[0]} $quux[1]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/README0000644000175300017510000000031513057016062014522 0ustar oetikeroepIf you want to translate mrtg into a new language, use the file german.pmd as a sample ... you can then integrate your translation into locales_mrtg.pm by running ./mergelocale.pl skeleton.pm0 *.pmd mrtg-2.17.10/translate/turkish.pmd0000644000175300017510000001122213057016062016034 0ustar oetikeroep###### PATCHTAG00 #################################################### ### Turkish/Trke ### => zgr C. Demir ###### PATCHTAG10 #################################################### &turkish ###### PATCHTAG20 #################################################### 'turkish' => \&turkish, 'turkce' => \&turkish, ###### PATCHTAG30 #################################################### # Turkish/Trke 'turkish' => "Trkeletiren zgr C. Demir", ###### PATCHTAG40 #################################################### $credits::LOCALE{'turkce'}=$credits::LOCALE{'turkish'}; ###### PATCHTAG50 #################################################### # Turkish sub turkish { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... %translations = ( 'iso-8859-1' => 'iso-8859-9', 'Maximal 5 Minute Incoming Traffic' => '5 dakika iin en yksek giri trafii', 'Maximal 5 Minute Outgoing Traffic' => '5 dakika iin en yksek k trafii', 'the device' => 'aygt', 'The statistics were last updated(.*)' => 'statistiklerin en son gncellenmesi $1', ' Average\)' => ' Ortalama)', 'Average' => 'Ortalama', 'Max' => 'EnYksek;x', 'Current' => 'uAnki', 'version' => 'srm', '`Daily\' Graph \((.*) Minute' => 'Gnlk ($1 dakika :', '`Weekly\' Graph \(30 Minute' => 'Haftalk (30 dakika :' , '`Monthly\' Graph \(2 Hour' => 'Aylk (2 saat :', '`Yearly\' Graph \(1 Day' => 'Yllk (1 gn :', 'Incoming Traffic in (\S+) per Second' => '$1 deki saniyelik giri trafii', 'Outgoing Traffic in (\S+) per Second' => '$1 deki saniyelik k trafii', 'at which time (.*) had been up for(.*)' => '$1 Ne zamandan $2 beri ayakta', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', # '([kMG]?)([bB])/h' => '$1$2/t', # 'Bits' => 'Bit', # 'Bytes' => 'Byte' 'In' => 'Giri', 'Out' => 'k', 'Percentage' => 'Yzge', 'Ported to OpenVMS Alpha by' => 'OpenVMS Alpha ya uyarlayan', 'Ported to WindowsNT by' => 'WindowsNT ye uyarlayan', 'and' => 've', '^GREEN' => 'YEL', 'BLUE' => 'MAV', 'DARK GREEN' => 'KOYU YEL', 'MAGENTA' => 'MACENTA', 'AMBER' => 'AMBER' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Pazar', 'Pzr' => 'Dom', 'Monday' => 'Pazartesi', 'Pzt' => 'Lun', 'Tuesday' => 'Sal', 'Sal' => 'Mar', 'Wednesday' => 'aramba', 'r' => 'Mié', 'Thursday' => 'Perembe', 'Pr' => 'Jue', 'Friday' => 'Cuma', 'Cum' => 'Vie', 'Saturday' => 'Cumartesi', 'Cmr' => 'Sab' ); %month = ( 'January' => 'Ocak', 'February' => 'ubat', 'March' => 'Mart', 'Jan' => 'Ock', 'Feb' => 'ub', 'Mar' => 'Mar', 'April' => 'Nisan', 'May' => 'Mays', 'June' => 'Haziran', 'Apr' => 'Nis', 'May' => 'May', 'Jun' => 'Hzr', 'July' => 'Temmuz', 'August' => 'Agustos', 'September' => 'Eyll', 'Jul' => 'Tem', 'Aug' => 'Agu', 'Sep' => 'Eyl', 'October' => 'Ekim', 'November' => 'Kasm', 'December' => 'Aralk', 'Oct' => 'Ekm', 'Nov' => 'Kas', 'Dec' => 'Ara' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." a las ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] de $month{$foo[2]} de $foo[3]"; }; } mrtg-2.17.10/translate/icelandic.pmd0000644000175300017510000001461613057016062016270 0ustar oetikeroep# # Sample Translation for mrtg ... # ###################################################################### # Adds support for Icelandic to locales_mrtg.pm. Translate this file to # your language and send the translation to oetiker@ee.ethz.ch if you # want to integrate your translation to the existing locales_mrtg.pm # use # # locales_pt.pl locales_mrtg.pm yourlanguage.pt > locales_mrtg.new.pm # ##################################################################### ###### PATCHTAG 00 ################################################### ### Icelandic/Islenska ### => Halldor Karl Hgnason ###### PATCHTAG 10 ################################################### &icelandic ###### PATCHTAG 20 ################################################### 'icelandic' => \&icelandic, 'islenska' => \&icelandic, ###### PATCHTAG 30 ################################################### # Icelandic/islenska 'icelandic' => "Þýtt yfir á íslensku af Halldór Karl Högnason <halldor.hognason\@islandssimi.is>", ###### PATCHTAG 40 ################################################### $credits::LOCALE{'islenska'}=$credits::LOCALE{'icelandic'}; ###### PATCHTAG 50 ################################################### # Icelandic sub icelandic { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Hámarks 5 mínútna umferð inn', 'Maximal 5 Minute Outgoing Traffic' => 'Hámarks 5 mínútna umferð út', 'the device' => 'tkið', 'The statistics were last updated(.*)' => 'Gögnin voru síðast uppfærð$1', ' Average\)' => ' Meðaltal)', 'Average' => 'Meðaltal', 'Max' => 'Hámark', 'Current' => 'Nú', 'version' => 'útgáfa', '`Daily\' Graph \((.*) Minute' => '`Dagleg\' staða ($1 mínútur', '`Weekly\' Graph \(30 Minute' => '`Vikuleg\' staða (30 mínútur', '`Monthly\' Graph \(2 Hour' => '`Mánaðarleg\' staða (2 klst.', '`Yearly\' Graph \(1 Day' => '`&Aarleg\' staða (1 dags', 'Incoming Traffic in (\S+) per Second' => 'Umferð inn í $1 á sekúndu', 'Outgoing Traffic in (\S+) per Second' => 'Umferð út í $1 á sekúndu', 'at which time (.*) had been up for(.*)' => 'þegar $1 hafði verið uppi í$2', # '([kMG]?)([bB])/s' => '\$1\$2/sek', # '([kMG]?)([bB])/min' => '\$1\$2/mín', '([kMG]?)([bB])/h' => '$1$2/klst', # 'Bits' => 'Bitar', # 'Bytes' => 'Bæti' 'In' => 'Inn', 'Out' => 'Út', 'Percentage' => 'Prósent', 'Ported to OpenVMS Alpha by' => 'Staðfært á OpenVMS af', 'Ported to WindowsNT by' => 'Staðfært á WindowsNT af', 'and' => 'og', '^GREEN' => 'GRÆNt', 'BLUE' => 'BLÁTT', 'DARK GREEN' => 'DÖKK GRÆNN', 'MAGENTA' => 'BLÁRAUÐUR', 'AMBER' => 'GULBRÚNN' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Sunnudagur', 'Sun' => 'Sun', 'Monday' => 'Mánudagur', 'Mon' => 'Mán', 'Tuesday' => 'Þriðjudagur', 'Tue' => 'Þri', 'Wednesday' => 'Miðvikudagur', 'Wed' => 'Mið', 'Thursday' => 'Fimmtudagur', 'Thu' => 'Fim', 'Friday' => 'Föstudagur', 'Fri' => 'Fös', 'Saturday' => 'Laugardagur', 'Sat' => 'Lau' ); %month = ( 'January' => 'Janúar', 'February' => 'Febrúar' , 'March' => 'Mars', 'Jan' => 'Jan', 'Feb' => 'Feb', 'Mar' => 'Mar', 'April' => 'Apríl', 'May' => 'Maí', 'June' => 'Júní', 'Apr' => 'Apr', 'May' => 'Maí', 'Jun' => 'Jún', 'July' => 'Júlí', 'August' => 'Ágúst', 'September' => 'September', 'Jul' => 'Júl', 'Aug' => 'Ágú', 'Sep' => 'Sep', 'October' => 'Október', 'November' => 'Nóvember', 'December' => 'Desember', 'Oct' => 'Okt', 'Nov' => 'Nóv', 'Dec' => 'Des' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." kl.".$quux[1]; }; return "$wday{$foo[0]} den $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/norwegian.pmd0000644000175300017510000001271413057016062016343 0ustar oetikeroep###### PATCHTAG00 #################################################### ### Norwegian/norsk ### => Knut Grneng \&norwegian, 'norsk' => \&norwegian, ###### PATCHTAG30 #################################################### # Danish/dansk 'norwegian' => "Oversatt til norsk av Knut Grneng <knut.groneng\@merkantildata.no>", # the norwegian string means: "Translated to norwegian by" ###### PATCHTAG40 #################################################### $credits::LOCALE{'norsk'}=$credits::LOCALE{'norwegian'}; ###### PATCHTAG50 #################################################### # Norwegian sub norwegian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Maksimal inngående trafikk i 5 minutter', 'Maximal 5 Minute Outgoing Traffic' => 'Maksimal utgående trafikk i 5 minutter', 'the device' => 'enhetden', 'The statistics were last updated(.*)' => 'Statistikken ble sist oppdatert $1', ' Average\)' => ' gjennomsnitt)', 'Average' => 'Gjennomsnitt', 'Max' => 'Max', 'Current' => 'Nå', 'version' => 'versjon', '`Daily\' Graph \((.*) Minute' => '`Daglig\' graf ($1 minutts', '`Weekly\' Graph \(30 Minute' => '`Ukentlig\' graf (30 minutts' , '`Monthly\' Graph \(2 Hour' => '`Månedlig\' graf (2 times', '`Yearly\' Graph \(1 Day' => '`Årlig\' graf (1 dags', 'Incoming Traffic in (\S+) per Second' => 'Inngående trafikk i $1 per sekund', 'Outgoing Traffic in (\S+) per Second' => 'Utgående trafikk i $1 per sekund', 'at which time (.*) had been up for(.*)' => 'hvor $1 hadde vært oppe i $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/t', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Inn', 'Out' => 'Ut', 'Percentage' => 'Prosent', 'Ported to OpenVMS Alpha by' => 'Port til OpenVMS av', 'Ported to WindowsNT by' => 'Port til WindowsNT av', 'and' => 'og', '^GREEN' => 'GRØNN', 'BLUE' => 'BLÅ', 'DARK GREEN' => 'MØRKEGRØNN', 'MAGENTA' => 'MAGENTA', 'AMBER' => 'GUL' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Søndag', 'Sun' => 'Søn', 'Monday' => 'Mandag', 'Mon' => 'Man', 'Tuesday' => 'Tirsdag', 'Tue' => 'Tir', 'Wednesday' => 'Onsdag', 'Wed' => 'Ons', 'Thursday' => 'Torsdag', 'Thu' => 'Tor', 'Friday' => 'Fredag', 'Fri' => 'Fre', 'Saturday' => 'Lørdag', 'Sat' => 'Lør' ); %month = ( 'January' => 'Januar', 'February' => 'Februar' , 'March' => 'Mars', 'Jan' => 'Jan', 'Feb' => 'Feb', 'Mar' => 'Mar', 'April' => 'April', 'May' => 'Mai', 'June' => 'Juni', 'Apr' => 'Apr', 'May' => 'Mai', 'Jun' => 'Jun', 'July' => 'Juli', 'August' => 'August', 'September' => 'September', 'Jul' => 'Jul', 'Aug' => 'Aug', 'Sep' => 'Sep', 'October' => 'Oktober', 'November' => 'November', 'December' => 'Desember', 'Oct' => 'Okt', 'Nov' => 'Nov', 'Dec' => 'Des' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." kl.".$quux[1]; }; return "$wday{$foo[0]} den $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/swedish.pmd0000644000175300017510000001267213057016062016023 0ustar oetikeroep###### PATCHTAG00 #################################################### ### Swedish/Svenska ### => Clas Mayer ###### PATCHTAG10 #################################################### &swedish ###### PATCHTAG20 #################################################### 'swedish' => \&swedish, 'svenska' => \&swedish, ###### PATCHTAG30 #################################################### # Swedish/Svenska 'swedish' => "Översatt till svenska av Clas Mayer <clas\@mayer.se>", # the Swedish string means: "Prepared for languages and translated to Swedish by" ###### PATCHTAG40 #################################################### $credits::LOCALE{'svenska'}=$credits::LOCALE{'swedish'}; ###### PATCHTAG50 #################################################### # Swedish sub swedish { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Maximalt inkommande trafik i 5 minuter', 'Maximal 5 Minute Outgoing Traffic' => 'Maximalt utgående trafik i 5 minuter', 'the device' => 'enheten', 'The statistics were last updated(.*)' => 'Statistiken blev senast uppdaterad$1', ' Average\)' => ')', 'Average' => 'Medel', #'Max' => 'Max', 'Current' => 'Senaste', 'version' => 'version', '`Daily\' Graph \((.*) Minute' => 'Daglig graf (samplingsintervall $1 minut(er)', '`Weekly\' Graph \(30 Minute' => 'Veckovis graf (medelvrde per 30 minuter' , '`Monthly\' Graph \(2 Hour' => 'Månatlig graf (medelvrde per 2 timmar', '`Yearly\' Graph \(1 Day' => 'Årlig graf (medelvrde per dygn', 'Incoming Traffic in (\S+) per Second' => 'Inkommande trafik i $1 per sekund', 'Outgoing Traffic in (\S+) per Second' => 'Utgende trafik i $1 per sekund', 'at which time (.*) had been up for(.*)' => 'd $1 varit igång i$2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/t', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes', #'In' => 'In', 'Out' => 'Ut', 'Percentage' => 'Procent', 'Ported to OpenVMS Alpha by' => 'Portad till OpenVMS av', 'Ported to WindowsNT by' => 'Portad till WindowsNT av', 'and' => 'och', '^GREEN' => 'GRÖN', 'BLUE' => 'BLÅ', 'DARK GREEN' => 'MÖRKGRÖN', 'MAGENTA' => 'MANGENTA', 'AMBER' => 'BRUN', ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'söndag', 'Sun' => 'sön', 'Monday' => 'måndag', 'Mon' => 'mån', 'Tuesday' => 'tisdag', 'Tue' => 'tis', 'Wednesday' => 'onsdag', 'Wed' => 'ons', 'Thursday' => 'torsdag', 'Thu' => 'tor', 'Friday' => 'fredag', 'Fri' => 'fre', 'Saturday' => 'lördag', 'Sat' => 'lör' ); %month = ( 'January' => 'januari', 'February' => 'februari', 'March' => 'mars', 'Jan' => 'jan', 'Feb' => 'feb', 'Mar' => 'mar', 'April' => 'april', 'May' => 'maj', 'June' => 'juni', 'Apr' => 'apr', 'May' => 'maj', 'Jun' => 'jun', 'July' => 'juli', 'August' => 'augusti', 'September' => 'september', 'Jul' => 'jul', 'Aug' => 'aug', 'Sep' => 'sep', 'October' => 'oktober', 'November' => 'november', 'December' => 'december', 'Oct' => 'okt', 'Nov' => 'nov', 'Dec' => 'dec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." kl.".$quux[1]; }; return "$wday{$foo[0]} den $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/french.pmd0000644000175300017510000001306714171553254015630 0ustar oetikeroep###### PATCHTAG00 #################################################### ### French/Francais ### => Fabrice Prigent ### and Stéphane Marzloff ###### PATCHTAG10 #################################################### &french ###### PATCHTAG20 #################################################### 'french' => \&french, 'francais' => \&french, ###### PATCHTAG30 #################################################### # French/francais 'french' => "Localisation effectuée par Fabrice Prigent <fabrice.prigent\@univ-tlse1.fr>", ###### PATCHTAG40 #################################################### $credits::LOCALE{'francais'}=$credits::LOCALE{'french'}; ###### PATCHTAG50 #################################################### # French sub french { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Trafic maximal en entrée sur 5 minutes', 'Maximal 5 Minute Outgoing Traffic' => 'Trafic maximal en sortie sur 5 minutes', 'the device' => 'le matériel', 'The statistics were last updated(.*)' => 'Les statistiques ont été mises à jour le $1', ' Average\)' => ' Moyenne)', 'Average' => 'Moyenne', '>Max' => 'Max', 'Current' => 'Actuel', #'version' => 'version', '`Daily\' Graph \((.*) Minute' => 'Graphique quotidien (sur $1 minutes :', '`Weekly\' Graph \(30 Minute' => 'Graphique hebdomadaire (sur 30 minutes :' , '`Monthly\' Graph \(2 Hour' => 'Graphique mensuel (sur 2 heures :', '`Yearly\' Graph \(1 Day' => 'Graphique annuel (sur 1 jour :', 'Incoming Traffic in (\S+) per Second' => 'Trafic d\'entrée en $1 par seconde', 'Outgoing Traffic in (\S+) per Second' => 'Trafic de sortie en $1 par seconde', 'at which time (.*) had been up for(.*)' => '$1 était alors en marche depuis $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/t', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Entrée', 'Out' => 'Sortie', 'Percentage' => 'Pourcentage', 'Ported to OpenVMS Alpha by' => 'Porté sur OpenVMS Alpha par', 'Ported to WindowsNT by' => 'Porté sur WindowsNT par', 'and' => 'et', '^GREEN' => 'VERT', 'BLUE' => 'BLEU', 'DARK GREEN' => 'VERT SOMBRE', 'MAGENTA' => 'MAGENTA', 'AMBER' => 'AMBRE' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Dimanche', 'Sun' => 'Dim', 'Monday' => 'Lundi', 'Mon' => 'Lun', 'Tuesday' => 'Mardi', 'Tue' => 'Mar', 'Wednesday' => 'Mercredi', 'Wed' => 'Mer', 'Thursday' => 'Jeudi', 'Thu' => 'Jeu', 'Friday' => 'Vendredi', 'Fri' => 'Ven', 'Saturday' => 'Samedi', 'Sat' => 'Sam' ); %month = ( 'January' => 'Janvier', 'February' => 'Février' , 'March' => 'Mars', 'Jan' => 'Jan', 'Feb' => 'Fev', 'Mar' => 'Mar', 'April' => 'Avril', 'May' => 'Mai', 'June' => 'Juin', 'Apr' => 'Avr', 'May' => 'Mai', 'Jun' => 'Jun', 'July' => 'Juillet', 'August' => 'Août', 'September' => 'Septembre', 'Jul' => 'Jul', 'Aug' => 'Aou', 'Sep' => 'Sep', 'October' => 'Octobre', 'November' => 'Novembre', 'December' => 'Décembre', 'Oct' => 'Oct', 'Nov' => 'Nov', 'Dec' => 'Dec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." à ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." à $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/belarusian.pmd0000644000175300017510000001526213057016062016500 0ustar oetikeroep###### PATCHTAG 00 ################################################### ### Belarusian/Беларуская ### => Глеб Валошка <375gnu@gmail.com> ###### PATCHTAG 10 ################################################### &belarusian ###### PATCHTAG 20 ################################################### 'belarusian' => \&belarusian, 'беларуская' => \&belarusian, ###### PATCHTAG 30 ################################################### # Belarusian/беларуская 'belarusian' => "Беларускі пераклад: Глеб Валошка <375gnu\@gmail.com>", ###### PATCHTAG 40 ################################################### $credits::LOCALE{'беларуская'}=$credits::LOCALE{'belarusian'}; ###### PATCHTAG 50 ################################################### # Belarusian sub belarusian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=utf-8 %translations = ( 'iso-8859-1' => 'utf-8', 'Maximal 5 Minute Incoming Traffic' => 'Найбольшы ўваходны трафік за 5 хвілін', 'Maximal 5 Minute Outgoing Traffic' => 'Найбольшы выходны трафік за 5 хвілін', 'the device' => 'прылада', 'The statistics were last updated(.*)' => 'Апошні раз статыстыка абнаўлялася: $1', ' Average\)' => ')', 'Average' => 'спасярэднены', 'Max' => 'найбольшы', 'Current' => 'бягучы', 'version' => 'вэрсія', '`Daily\' Graph \((.*) Minute' => 'Графік трафіку за суткі (за $1 хвілін ', '`Weekly\' Graph \(30 Minute' => 'Графік трафіку за тыдзень (за 30 хвілін ', '`Monthly\' Graph \(2 Hour' => 'Графік трафіку за месяц (за 2 гадзіны ', '`Yearly\' Graph \(1 Day' => 'Графік трафіку за год (за 1 дзень ', 'Incoming Traffic in (\S+) per Second' => 'Уваходны трафік $1 за сэкунду', 'Outgoing Traffic in (\S+) per Second' => 'Выходны трафік $1 за сэкунду', 'Incoming Traffic in (\S+) per Minute' => 'Уваходны трафік $1 за хвіліну', 'Outgoing Traffic in (\S+) per Minute' => 'Выходны трафік $1 за хвіліну', 'Incoming Traffic in (\S+) per Hour' => 'Уваходны трафік $1 за гадзіну', 'Outgoing Traffic in (\S+) per Hour' => 'Выходны трафік $1 за гадзіну', 'at which time (.*) had been up for(.*)' => 'калі $1 працаваў $2', '(\S+) per minute' => '$1 за хвіліну', '(\S+) per hour' => '$1 за гадзіну', '(.+)/s$' => '$1/с', '(.+)/min' => '$1/хв', '(.+)/h$' => '$1/г', '([kMG]?)([bB])/s' => '$1$2/с', '([kMG]?)([bB])/min' => '$1$2/хв', '([kMG]?)([bB])/h' => '$1$2/г', 'Bits' => 'бітах', 'Bytes' => 'байтах', 'In' => 'Уваходны', 'Out' => 'Выходны', 'Percentage' => 'Адсоткі', 'Ported to OpenVMS Alpha by' => 'Перанос на OpenVMS:', 'Ported to WindowsNT by' => 'Перанос на WindowsNT:', 'and' => 'і', '^GREEN' => 'ЗЯЛЁНЫ', 'BLUE' => 'СІНІ', 'DARK GREEN' => 'ЦЁМНАЗЯЛЁНЫ', 'MAGENTA' => 'РУЖОВЫ', 'AMBER' => 'БУРШТЫНАВЫ' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Нядзеля', 'Sun' => 'Нд', 'Monday' => 'Панядзелак', 'Mon' => 'Пн', 'Tuesday' => 'Аўторак', 'Tue' => 'Аў', 'Wednesday' => 'Серада', 'Wed' => 'Ср', 'Thursday' => 'Чацьвер', 'Thu' => 'Чц', 'Friday' => 'Пятніца', 'Fri' => 'Пт', 'Saturday' => 'Субота', 'Sat' => 'Сб' ); %month = ( 'January' => 'Студзень', 'February' => 'Люты' , 'March' => 'Сакавік', 'Jan' => 'Сту', 'Feb' => 'Лют', 'Mar' => 'Сак', 'April' => 'Красавік', 'May' => 'Травень', 'June' => 'Чэрвень', 'Apr' => 'Кра', 'May' => 'Тра', 'Jun' => 'Чэр', 'July' => 'Ліпень', 'August' => 'Жнівень', 'September' => 'Верасень', 'Jul' => 'Ліп', 'Aug' => 'Жні', 'Sep' => 'Вер', 'October' => 'Кастрычнік','November' => 'Лістапад', 'December' => 'Сьнежань', 'Oct' => 'Кас', 'Nov' => 'Ліс', 'Dec' => 'Сьн' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." у ".$quux[1]; }; return "$wday{$foo[0]}, $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/ukrainian.pmd0000644000175300017510000001265313057016062016335 0ustar oetikeroep###### PATCHTAG00 #################################################### ### Ukrainian/ ### => Ǧ ͦΦ ###### PATCHTAG10 #################################################### &ukrainian ###### PATCHTAG20 #################################################### 'ukrainian' => \&ukrainian, '' => \&ukrainian, ###### PATCHTAG30 #################################################### # Ukrainian/ 'ukrainian' => " : Ǧ ͦΦ <gray\@arte-fact.net>", ###### PATCHTAG40 #################################################### $credits::LOCALE{''}=$credits::LOCALE{'ukrainian'}; ###### PATCHTAG50 #################################################### # Ukrainian sub ukrainian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'koi8-u', 'Maximal 5 Minute Incoming Traffic' => ' Ȧ Ʀ 5 ', 'Maximal 5 Minute Outgoing Traffic' => ' Ȧ Ʀ 5 ', 'the device' => 'Ҧ', 'The statistics were last updated(.*)' => 'Τ : $1', ' Average\)' => ')', 'Average' => 'Φ', 'Max' => '.', 'Current' => '', 'version' => 'Ӧ', '`Daily\' Graph \((.*) Minute' => ' Ʀ (Τ $1 ', '`Weekly\' Graph \(30 Minute' => ' Ʀ (Τ 30 ' , '`Monthly\' Graph \(2 Hour' => ' Ʀ (Τ 2 ', '`Yearly\' Graph \(1 Day' => ' Ʀ (Τ 1 ', 'Incoming Traffic in (\S+) per Second' => 'Ȧ Ʀ $1 ', 'Outgoing Traffic in (\S+) per Second' => 'Ȧ Ʀ $1 ', 'at which time (.*) had been up for(.*)' => '$1 $2', #'([kMG]?)([bB])/s' => '$1$1/', #'([kMG]?)([bB])/min' => '$1$2/', '([kMG]?)([bB])/h' => '$1$2/', 'Bits' => '¦', 'Bytes' => '', 'In' => '', 'Out' => '', 'Percentage' => '', 'Ported to OpenVMS Alpha by' => ' OpenVMS Alpha', 'Ported to WindowsNT by' => ' WindowsNT', 'and' => '', '^GREEN' => '', 'BLUE' => '', 'DARK GREEN' => '', 'MAGENTA' => '', 'AMBER' => '' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => ' Ħ', 'Sun' => '', 'Monday' => ' Ħ', 'Mon' => '', 'Tuesday' => ' ', 'Tue' => '', 'Wednesday' => ' ', 'Wed' => '', 'Thursday' => ' ', 'Thu' => '', 'Friday' => ' \'', 'Fri' => '', 'Saturday' => ' ', 'Sat' => '' ); %month = ( 'January' => '', 'February' => '' , 'March' => '', 'Jan' => '', 'Feb' => '', 'Mar' => '', 'April' => 'צ', 'May' => '', 'June' => '', 'Apr' => 'צ', 'May' => '', 'Jun' => '', 'July' => '', 'August' => '', 'September' => '', 'Jul' => '', 'Aug' => '', 'Sep' => '', 'October' => '', 'November' => '', 'December' => '', 'Oct' => '', 'Nov' => '', 'Dec' => '' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].". ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/greek.pmd0000644000175300017510000001265313057016062015451 0ustar oetikeroep###### PATCHTAG00 #################################################### ### Greek/Ellinika ### => Simos Xenitellis ###### PATCHTAG10 #################################################### &greek ###### PATCHTAG20 #################################################### 'greek' => \&greek, 'ellinika' => \&greek, ###### PATCHTAG30 #################################################### # Greek/Ellinika 'greek' => " <S.Xenitellis\@hellug.gr>", ###### PATCHTAG40 #################################################### $credits::LOCALE{'ellinika'}=$credits::LOCALE{'greek'}; ###### PATCHTAG50 #################################################### # Greek sub greek { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'iso-8859-7', 'Maximal 5 Minute Incoming Traffic' => ' 5 ', 'Maximal 5 Minute Outgoing Traffic' => ' 5 ', 'the device' => ' ', 'The statistics were last updated(.*)' => ' ()/ $1', ' Average\)' => ' )', 'Average' => ' ', 'Max' => '', 'Current' => '', 'version' => '', '`Daily\' Graph \((.*) Minute' => ' ( $1 :', '`Weekly\' Graph \(30 Minute' => ' ( 30 :' , '`Monthly\' Graph \(2 Hour' => ' ( 2 :', '`Yearly\' Graph \(1 Day' => ' ( 1 :', 'Incoming Traffic in (\S+) per Second' => ' $1 ', 'Outgoing Traffic in (\S+) per Second' => ' $1 ', 'at which time (.*) had been up for(.*)' => ' $1 $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/t', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => '', 'Out' => '', 'Percentage' => '', 'Ported to OpenVMS Alpha by' => ' OpenVMS Alpha ', 'Ported to WindowsNT by' => ' WindowsNT ', 'and' => '', '^GREEN' => '', 'BLUE' => '', 'DARK GREEN' => ' ', 'MAGENTA' => '', 'AMBER' => '' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => '', 'Sun' => '', 'Monday' => '', 'Mon' => '', 'Tuesday' => '', 'Tue' => '', 'Wednesday' => '', 'Wed' => '', 'Thursday' => '', 'Thu' => '', 'Friday' => '', 'Fri' => '', 'Saturday' => '', 'Sat' => '' ); %month = ( 'January' => '', 'February' => '' , 'March' => '', 'Jan' => '', 'Feb' => '', 'Mar' => '', 'April' => '', 'May' => '', 'June' => '', 'Apr' => '', 'May' => '', 'Jun' => '', 'July' => '', 'August' => '', 'September' => '', 'Jul' => '', 'Aug' => '', 'Sep' => '', 'October' => '', 'November' => '', 'December' => '', 'Oct' => '', 'Nov' => '', 'Dec' => '' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." à $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/russian1251.pmd0000644000175300017510000001357213057016062016352 0ustar oetikeroep###### PATCHTAG00 #################################################### ### Russian1251/1251 ### => ###### PATCHTAG10 #################################################### &russian1251 ###### PATCHTAG20 #################################################### 'russian1251' => \&russian1251, '1251' => \&russian1251, ###### PATCHTAG30 #################################################### # Russian1251/1251 'russian1251' => " ( 1251): <aredyuk\@irmcity.com>", ###### PATCHTAG40 #################################################### $credits::LOCALE{'1251'}=$credits::LOCALE{'russian1251'}; ###### PATCHTAG50 #################################################### # Russian1251 Code sub russian1251 { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'windows-1251', 'Maximal 5 Minute Incoming Traffic' => ' 5 ', 'Maximal 5 Minute Outgoing Traffic' => ' 5 ', 'the device' => '', 'The statistics were last updated(.*)' => ' : $1', ' Average\)' => ')', 'Average' => ' ', 'Max' => '', 'Current' => '', 'version' => '', '`Daily\' Graph \((.*) Minute' => ' ( $1 ', '`Weekly\' Graph \(30 Minute' => ' ( 30 ' , '`Monthly\' Graph \(2 Hour' => ' ( 2 ', '`Yearly\' Graph \(1 Day' => ' ( 1 ', 'Incoming Traffic in (\S+) per Second' => ' $1 ', 'Outgoing Traffic in (\S+) per Second' => ' $1 ', 'at which time (\S+) had been up for (\S+)' => ' $1: $2.', 'at which time (\S+) had been up for (\S+) day, (\S+)' => ' $1: $2 , $3.', 'at which time (\S+) had been up for (\S+) days, (\S+)' => ' $1: $2 , $3.', #'([kMG]?)([bB])/s' => '$1$1/', #'([kMG]?)([bB])/min' => '$1$2/', '([kMG]?)([bB])/h' => '$1$2/', 'Bits' => '', 'Bytes' => '', 'In' => '', 'Out' => '', 'Percentage' => '', 'Ported to OpenVMS Alpha by' => ' OpenVMS Alpha', 'Ported to WindowsNT by' => ' WindowsNT', 'and' => '', '^GREEN' => '', 'BLUE' => '', 'DARK GREEN' => '', 'MAGENTA' => '', 'AMBER' => '' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => ' ', 'Sun' => '', 'Monday' => ' ', 'Mon' => '', 'Tuesday' => ' ', 'Tue' => '', 'Wednesday' => ' ', 'Wed' => '', 'Thursday' => ' ', 'Thu' => '', 'Friday' => ' ', 'Fri' => '', 'Saturday' => ' ', 'Sat' => '' ); %month = ( 'January' => '', 'February' => '' , 'March' => '', 'Jan' => '', 'Feb' => '', 'Mar' => '', 'April' => '', 'May' => '', 'June' => '', 'Apr' => '', 'May' => '', 'Jun' => '', 'July' => '', 'August' => '', 'September' => '', 'Jul' => '', 'Aug' => '', 'Sep' => '', 'October' => '', 'November' => '', 'December' => '', 'Oct' => '', 'Nov' => '', 'Dec' => '' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].". ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/cn.pmd0000644000175300017510000001245613057016062014755 0ustar oetikeroep###### PATCHTAG00 #################################################### ### cn/ĺ ### =>  ### => MSN:chenguang2001@hotmail.com FreeBSD Fan ### => MRTG. ###### PATCHTAG10 #################################################### &cn ###### PATCHTAG20 #################################################### 'cn' => \&cn, 'ĺ' => \&cn, ###### PATCHTAG30 #################################################### # cn/ĺ 'cn' => "
MRTG  <zurkabsd\@yahoo.com.cn>", ###### PATCHTAG40 #################################################### $credits::LOCALE{'ĺ'}=$credits::LOCALE{'cn'}; ###### PATCHTAG50 #################################################### # cn s-Chinese sub cn { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... %translations = ( 'charset=iso-8859-1' => 'charset=gb2312', 'Maximal 5 Minute Incoming Traffic' => '5', 'Maximal 5 Minute Outgoing Traffic' => '5', 'the device' => '豸', 'The statistics were last updated(.*)' => 'ͳʱ䣺$1', ' Average\)

' => ' ƽ)
', 'Average(.*)' => 'ƽ$1', 'Max(.*)' => '$1', 'Current(.*)' => 'ǰ$1', 'version' => '汾', '`Daily\' Graph \((.*) Minute' => '"ÿ" ͼ ($1 ', '`Weekly\' Graph \(30 Minute' => '"ÿ" ͼ (30 ' , '`Monthly\' Graph \(2 Hour' => '"ÿ" ͼ (2 Сʱ', '`Yearly\' Graph \(1 Day' => '"ÿ" ͼ (1 ', 'Incoming Traffic in (\S+) per Second' => 'ÿ $1 ', 'Outgoing Traffic in (\S+) per Second' => 'ÿ $1 ', 'at which time (.*) had been up for(.*)' => 'ʱ $1 ˣ $2 ', '(.+)/s$' => '$1/', '(.+)/min$' => '$1/', '(.+)/h$' => '$1/ʱ', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' ' In:' => ' 룺', ' Out:' => ' ', ' Percentage' => ' ٷֱȣ', 'Ported to OpenVMS Alpha by' => 'ֲ OpenVMS ', 'Ported to WindowsNT by' => 'ֲ WindowsNT ', 'and' => '', '^GREEN' => '', 'BLUE' => '', 'DARK GREEN' => 'ī', 'MAGENTA' => '', 'AMBER' => 'ɫ' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => '', 'Sun' => '', 'Monday' => 'һ', 'Mon' => 'һ', 'Tuesday' => 'ڶ', 'Tue' => '', 'Wednesday' => '', 'Wed' => '', 'Thursday' => '', 'Thu' => '', 'Friday' => '', 'Fri' => '', 'Saturday' => '', 'Sat' => '' ); %month = ( 'January' => ' һ ', 'February' => ' ', 'March' => ' ', 'April' => ' ', 'May' => ' ', 'June' => ' ', 'July' => ' ', 'August' => ' ', 'September' => ' ', 'October' => ' ʮ ', 'November' => 'ʮһ', 'December' => 'ʮ', 'Jan' => '', 'Feb' => '', 'Mar' => '', 'Apr' => '', 'May' => '', 'Jun' => '', 'Jul' => '', 'Aug' => '', 'Sep' => '', 'Oct' => '', 'Nov' => '', 'Dec' => '' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]; $foo[4]=$quux[1]; }; return "$foo[3] $month{$foo[2]} $foo[1] $wday{$foo[0]} $foo[4]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/croatian.pmd0000644000175300017510000001253313057016062016151 0ustar oetikeroep###### PATCHTAG 00 ################################################### ### Croatian/Hrvatski ### => Dinko Korunic ###### PATCHTAG 10 ################################################### &croatian ###### PATCHTAG 20 ################################################### 'croatian' => \&croatian, 'hrvatski' => \&croatian, ###### PATCHTAG 30 ################################################### # Croatian/hrvatski 'croatian' => "Hrvatska lokalizacija - Dinko Korunic <kreator\@fly.srk.fer.hr>", ###### PATCHTAG 40 ################################################### $credits::LOCALE{'hrvatski'}=$credits::LOCALE{'croatian'}; ###### PATCHTAG 50 ################################################### sub croatian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'iso-8859-2', 'Maximal 5 Minute Incoming Traffic' => 'Maksimalni ulazni promet unutar 5 minuta', 'Maximal 5 Minute Outgoing Traffic' => 'Maksimalni izlazni promet unutar 5 minuta', 'the device' => 'ureaj', 'The statistics were last updated(.*)' => 'Statistike su zadnji puta izmijenjene $1', ' Average\)' => ' prosjena vrijednost)', 'Average' => 'Prosjeno', 'Max' => 'Maksimalno', 'Current' => 'Trenutno', 'version' => 'verzija', '`Daily\' Graph \((.*) Minute' => 'Dnevne statistike (svakih $1 minuta', '`Weekly\' Graph \(30 Minute' => 'Tjedne statistike (svakih 30 minuta' , '`Monthly\' Graph \(2 Hour' => 'Mjesene statistike (svakih 2 sata', '`Yearly\' Graph \(1 Day' => 'Godinje statistike (svaki 1 dan', 'Incoming Traffic in (\S+) per Second' => 'Ulazni promet - $1 po sekundi', 'Outgoing Traffic in (\S+) per Second' => 'Izlazni promet - $1 po sekundi', 'at which time (.*) had been up for(.*)' => 'gdje $1 je bio aktivan $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/g', 'Bits' => 'Bitova', 'Bytes' => 'Bajtova', 'In' => 'Unutra', 'Out' => 'Van', 'Percentage' => 'Postotak', 'Ported to OpenVMS Alpha by' => 'Port na OpenVMS Alpha od', 'Ported to WindowsNT by' => 'Post od WindowsNT od', 'and' => 'i', '^GREEN' => 'ZELENA', 'BLUE' => 'PLAVA', 'DARK GREEN' => 'TAMNO ZELENA', 'MAGENTA' => 'LJUBIASTA', 'AMBER' => 'AMBER' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Nedjelja', 'Sun' => 'Ned', 'Monday' => 'Ponedjeljak', 'Mon' => 'Pon', 'Tuesday' => 'Utorak', 'Tue' => 'Uto', 'Wednesday' => 'Srijeda', 'Wed' => 'Sri', 'Thursday' => 'etvrtak', 'Thu' => 'et', 'Friday' => 'Petak', 'Fri' => 'Pet', 'Saturday' => 'Subota', 'Sat' => 'Sub' ); %month = ( 'January' => 'Sijeanj', 'February' => 'Veljaa', 'March' => 'Oujak', 'Jan' => 'Sij', 'Feb' => 'Vel', 'Mar' => 'Ou', 'April' => 'Travanj', 'May' => 'Svibanj', 'June' => 'Lipanj', 'Apr' => 'Tra', 'May' => 'Svi', 'Jun' => 'Lip', 'July' => 'Srpanj', 'August' => 'Kolovoz', 'September' => 'Rujan', 'Jul' => 'Srp', 'Aug' => 'Kol', 'Sep' => 'Ruj', 'October' => 'Listopad', 'November' => 'Studeni', 'December' => 'Prosinac', 'Oct' => 'Lis', 'Nov' => 'Stu', 'Dec' => 'Pro' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." godine"." u".$quux[1]; }; return "$wday{$foo[0]} dana $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/german.pmd0000644000175300017510000001411014171553254015622 0ustar oetikeroep###### PATCHTAG 00 ################################################### ### German/Deutsch ### => Ilja Pavkovic ###### PATCHTAG 10 ################################################### &german ###### PATCHTAG 20 ################################################### 'german' => \&german, 'german' => \&german, ###### PATCHTAG 30 ################################################### # German/deutsch 'german' => "Vorbereitet für die Lokalisation von Ilja Pavkovic <illsen\@gumblfarz.de>", ###### PATCHTAG 40 ################################################### $credits::LOCALE{'deutsch'}=$credits::LOCALE{'german'}; ###### PATCHTAG 50 ################################################### # German sub german { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Maximaler hereinkommender Traffic in 5 Minuten', 'Maximal 5 Minute Outgoing Traffic' => 'Maximaler hinausgehender Traffic in 5 Minuten', 'the device' => 'das Gerät', 'The statistics were last updated(.*)' => 'Die Statistiken wurden am $1 zuletzt aktualisiert', ' Average\)' => '', 'Average' => 'Mittel', 'Max' => 'Maximal', 'Current' => 'Aktuell', 'version' => 'Version', '`Daily\' Graph \((.*) Minute' => 'Tagesübersicht (Skalierung $1 Minute(n)', '`Weekly\' Graph \(30 Minute' => 'Wochenübersicht (Skalierung 30 Minuten', '`Monthly\' Graph \(2 Hour' => 'Monatsübersicht (Skalierung 2 Stunden', '`Yearly\' Graph \(1 Day' => 'Jahresübersicht (Skalierung 1 Tag', 'Incoming Traffic in (\S+) per Second' => 'Hereinkommender Traffic in $1 pro Sekunde', 'Outgoing Traffic in (\S+) per Second' => 'Hinausgehender Traffic in $1 pro Sekunde', 'Incoming Traffic in (\S+) per Minute' => 'Hereinkommender Traffic in $1 pro Minute', 'Outgoing Traffic in (\S+) per Minute' => 'Hinausgehender Traffic in $1 pro Minute', 'Incoming Traffic in (\S+) per Hour' => 'Hereinkommender Traffic in $1 pro Stunde', 'Outgoing Traffic in (\S+) per Hour' => 'Hinausgehender Traffic in $1 pro Stunde', 'at which time (.*) had been up for(.*)' => 'zu diesem Zeitpunkt lief $1 seit $2', '(\S+) per minute' => '$1 pro Minute', '(\S+) per hour' => '$1 pro Stunde', '(.+)/s$' => '$1/s', # '(.+)/min' => '$1/min', '(.+)/h$' => '$1/std', #'([kMG]?)([bB])/s' => '$1$2/s', #'([kMG]?)([bB])/min' => '$1$2/min', #'([kMG]?)([bB])/h' => '$1$2/std', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Herein', 'Out' => 'Hinaus', 'Percentage' => 'Prozent', 'Ported to OpenVMS Alpha by' => 'Portierung nach OpenVMS von', 'Ported to WindowsNT by' => 'Portierung nach WindowsNT von', 'and' => 'und', '^GREEN' => 'GRÜN', 'BLUE' => 'BLAU', 'DARK GREEN' => 'DUNKELGRÜN', # 'MAGENTA' => 'ROSA', # 'AMBER' => 'AMBER', ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Sonntag', 'Sun' => 'So', 'Monday' => 'Montag', 'Mon' => 'Mo', 'Tuesday' => 'Dienstag', 'Tue' => 'Di', 'Wednesday' => 'Mittwoch', 'Wed' => 'Mi', 'Thursday' => 'Donnerstag', 'Thu' => 'Do', 'Friday' => 'Freitag', 'Fri' => 'Fr', 'Saturday' => 'Samstag', 'Sat' => 'Sa' ); %month = ( 'January' => 'Januar', 'February' => 'Februar' , 'March' => 'März', 'Jan' => 'Jan', 'Feb' => 'Feb', 'Mar' => 'Mär', 'April' => 'April', 'May' => 'Mai', 'June' => 'Juni', 'Apr' => 'Apr', 'May' => 'Mai', 'Jun' => 'Jun', 'July' => 'Juli', 'August' => 'August', 'September' => 'September', 'Jul' => 'Jul', 'Aug' => 'Aug', 'Sep' => 'Sep', 'October' => 'Oktober', 'November' => 'November', 'December' => 'Dezember', 'Oct' => 'Okt', 'Nov' => 'Nov', 'Dec' => 'Dez' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." um ".$quux[1]; }; return "$wday{$foo[0]}, den $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/locales_mrtg.pm0000644000175300017510000070046314171763414016676 0ustar oetikeroep# -*- mode: Perl -*- ###################################################################### ### Localization of mrtg output pages ###################################################################### # # # This is a generated perl module file. # # Please see the perl script mergelocale.pl and the language # # databasefiles skelton.pm0 and locale.*.pmd in translate/. # # If you want to contribute to mrtg change in the *.pmd files. # # If you just want to change your own mrtg: Go ahead and edit! # # # ###################################################################### ### Defines programs which handles centralized pattern matching and pattern ### replacements in order to translate the given strings ###################################################################### ### Created by: Morten Storgaard Nielsen ################################################################### # # Distributed under the GNU copyleft # ################################################################### ### Locale by: ### Belarusian/Беларуская ### => Глеб Валошка <375gnu@gmail.com> ### Chinese/c ### => Tate Chen @ ### => Ryan Huang F ### Brazil/Brazilian Portuguese ### => Luiz Felipe R E ### => Gleydson Mazoli da Silva (Atualização) ### Bulgarian/ ### => Yovko Lambrev ### catalan/Català ### => LLuís Gras ### Simplified Chinese/ ### => ƻ ### => QQ:582955 ӭFreeBSD ### => ԭĴ.°汾. ### cn/ĺ ### =>  ### => MSN:chenguang2001@hotmail.com FreeBSD Fan ### => MRTG. ### Croatian/Hrvatski ### => Dinko Korunic ### Czech/esky ### => Martin Och ### Czech/Česky ### => David Toman ### Danish/Dansk ### => Morten Storgaard Nielsen ### Dutch/Nederlands ### => Barry van Dijk ### Estonian/Eesti ### => Klemens Kasemaa ### ܸ(EUC-JP) ### => Fuminori Uematsu ### Finnish/Suomi ### => Jussi Siponen ### French/Francais ### => Fabrice Prigent ### and Stéphane Marzloff ### Galician/Galego ### => David Garabana Barro ### Chinese/庺 ### => Zhanghui Ż ### Chinese/ļ ### => Peter Wong ### German/Deutsch ### => Ilja Pavkovic ### Greek/Ellinika ### => Simos Xenitellis ### Hungarian/Magyar ### => Levente Nagy ### Icelandic/Islenska ### => Halldor Karl Hgnason ### Indonesian/Indonesia ### => Jamaludin Ahmad ### taken from malaysian translation ### by Assakhof Ab. Satar ### $BF|K\8l(B(ISO-2022-JP) ### => Fuminori Uematsu ### Italian/Italiano ### => Andrea Rossi ### Korean ### => Kensoon Hwang ### CHOI Junho ### Lithuanian/Lietuvikai ### => ve ### Macedonian/Makedonski ### => Delev Zoran ### Malaysian/Malay ### => Assakhof Ab. Satar ### Norwegian/norsk ### => Knut Grneng Lukasz Jokiel ### Portuguese/Português ### => Diogo Gomes ### Romn/Romanian ### => Jzsef Szilgyi ### Russian/ ### => ### Russian1251/1251 ### => ### Serbian/Srpski ### => Ratko Bucic ### Slovak/Slovensky ### => Ladislav Mihok ### Slovenian/Slovensko ### => Aljosa Us ### Spanish/Español ### => Marcelo Roccasalva ### Swedish/Svenska ### => Clas Mayer ### Turkish/Trke ### => zgr C. Demir ### Ukrainian/ ### => Ǧ ͦΦ ### Ukrainian/ ### => Olexander Kunytsa ### ### Contributions and fixes by: ### ### 0.05 fixed DARK GREEN entry (msn@ipt.dtu.dk) ### fixed credits for native language (msn@ipt.dtu.dk) ### 0.06 added the PATCHTAGs (msn@ipt.dtu.dk) ### fixed several small errors (msn@ipt.dtu.dk) ### 0.07 changed PATCHTAG to support ### mergelocale.pl (msn@ipt.dtu.dk) ### ###################################################################### ### package locales_mrtg; require 5.002; # make sure we do not get hit by UTF-8 here no locale; use strict; use vars qw(@ISA @EXPORT $VERSION); use Exporter; $VERSION = '0.07'; @ISA = qw(Exporter); @EXPORT = qw ( &english &belarusian &big5 &brazilian &bulgarian &catalan &chinese &cn &croatian &czech &czechutf8 &danish &dutch &estonian &eucjp &german &french &galician &gb &gb2312 &german &greek &hungarian &icelandic &indonesia &iso2022jp &italian &korean &lithuanian &macedonian &malay &norwegianh &polish &portuguese &romanian &russian &russian1251 &serbian &slovak &slovenian &spanish &swedish &turkish &ukrainian &ukrainian1251 ); %lang2tran::LOCALE= ( 'english' => \&english, 'default' => \&english, 'belarusian' => \&belarusian, 'беларуская' => \&belarusian, 'big5' => \&big5, 'c' => \&big5, 'brazil' => \&brazilian, 'brazilian' => \&brazilian, 'bulgarian' => \&bulgarian, '' => \&bulgarian, 'catalan' => \&catalan, 'catalan' => \&catalan, 'chinese' => \&chinese, '' => \&chinese, 'cn' => \&cn, 'ĺ' => \&cn, 'croatian' => \&croatian, 'hrvatski' => \&croatian, 'czech' => \&czech, 'czechutf8' => \&czechutf8, 'danish' => \&danish, 'dansk' => \&danish, 'dutch' => \&dutch, 'nederlands' => \&dutch, 'estonian' => \&estonian, 'eesti' => \&estonian, 'eucjp' => \&eucjp, 'euc-jp' => \&eucjp, 'finnish' => \&finnish, 'suomi' => \&finnish, 'french' => \&french, 'francais' => \&french, 'galician' => \&galician, 'galego' => \&galician, 'gb' => \&gb, '庺' => \&gb, 'gb2312' => \&gb2312, 'ļ' => \&gb2312, 'german' => \&german, 'german' => \&german, 'greek' => \&greek, 'ellinika' => \&greek, 'hungarian' => \&hungarian, 'magyar' => \&hungarian, 'icelandic' => \&icelandic, 'islenska' => \&icelandic, 'indonesia' => \&indonesia, 'indonesian' => \&indonesia, 'iso2022jp' => \&iso2022jp, 'iso-2022-jp' => \&iso2022jp, 'italian' => \&italian, 'italiano' => \&italian, 'korean' => \&korean, 'lithuanian' => \&lithuanian, 'lietuvikai' => \&lithuanian, 'macedonian' => \&macedonian, 'makedonski' => \&macedonian, 'malay' => \&malay, 'malaysian' => \&malay, 'norwegian' => \&norwegian, 'norsk' => \&norwegian, 'polish' => \&polish, 'polski' => \&polish, 'portuguese' => \&portuguese, 'romanian' => \&romanian, 'romn' => \&romanian, 'russian' => \&russian, '' => \&russian, 'russian1251' => \&russian1251, '1251' => \&russian1251, 'serbian' => \&serbian, 'slovak' => \&slovak, 'slovenian' => \&slovenian, 'spanish' => \&spanish, 'espanol' => \&spanish, 'swedish' => \&swedish, 'svenska' => \&swedish, 'turkish' => \&turkish, 'turkce' => \&turkish, 'ukrainian' => \&ukrainian, '' => \&ukrainian, 'ukrainian1251' => \&ukrainian1251, '1251' => \&ukrainian1251, ); %credits::LOCALE= ( # default 'default' => "Prepared for localization by Morten S. Nielsen <msn\@ipt.dtu.dk>", # Belarusian/беларуская 'belarusian' => "Беларускі пераклад: Глеб Валошка <375gnu\@gmail.com>", # Chinese/c 'big5' => "Ƨ@ Tate Chen <tate\@joy-tech.com.tw>
and F <ryan\@asplord.com>", # Brazil/brazilian 'brazilian' => "Localização efetuada por Luiz Felipe R E <luizfelipe\@encarnacao.com>
atualização por Gleydson Mazioli da Silva <gleydson\@debian.org>", # Bulgarian/ 'bulgarian' => " : <yovko\@sdf.lonestar.org>", # catalan/catalan 'catalan' => "Preparat per a localització per: Lluís Gras", # Simplified Chinese/ 'chinese' => "ȫ¼ĺ ƻ <webmaster\@kingisme.com>", # cn/ĺ 'cn' => "
MRTG  <zurkabsd\@yahoo.com.cn>", # Croatian/hrvatski 'croatian' => "Hrvatska lokalizacija - Dinko Korunic <kreator\@fly.srk.fer.hr>", # Czech/esky 'czech' => "esk peklad pipravil Martin Och <martin\@och.cz>", # Czechutf8/Česky 'czechutf8' => "Český překlad do UTF-8 připravil David Toman <david\@idkfa.cz>", # Danish/dansk 'danish' => "Forberedt for sprog samt oversat til dansk af Morten S. Nielsen <msn\@ipt.dtu.dk>", # the danish string means: "Prepared for languages and translated to danish by" # Dutch/nederlands 'dutch' => "Vertaald naar het Nederlands door Barry van Dijk <barry\@dijk.com>
; Aangepast door Paul Slootman <paul\@debian.org>", # Estonian/Eesti 'estonian' => "Tõlge eesti keelde Klemens Kasemaa <klem\@linux.ee>", # the estonian string means: "Translation to estonian by" # eucjp/euc-jp 'eucjp' => "ܸ(EUC-JP) ʸ <uematsu\@kgz.com>", # Finnish/Suomi 'finnish' => "Lokalisoinut Jussi Siponen <jussi.siponen\@online.tietokone.fi>", # the Finnish string means: "Localized by" # French/francais 'french' => "Localisation effectuée par Fabrice Prigent <fabrice.prigent\@univ-tlse1.fr>", # Galician/Galego 'galician' => "Traducido ao galego por David Garabana Barro <dgaraban\@arrakis.es>", # Chinese/庺 'gb' => "Ƨ@ Hui Zhang <zhanghui\@asiainfo.com>", # Chinese/ļ 'gb2312' => "Ļ Peter Wong &webmaster\@tcpip.com.cn>", # German/deutsch 'german' => "Vorbereitet für die Lokalisation von Ilja Pavkovic <illsen\@gumblfarz.de>", # Greek/Ellinika 'greek' => " <S.Xenitellis\@hellug.gr>", # Hungarian/magyar 'hungarian' => "Magyarosította Nagy Levente <levinet\@euroweb.hu>", # the hungarian string means: "Prepared for languages and translated to Hungarian by" # Icelandic/islenska 'icelandic' => "Þýtt yfir á íslensku af Halldór Karl Högnason <halldor.hognason\@islandssimi.is>", # Indonesian/Indonesia 'indonesia' => "Terjemahan ke bahasa Indonesia oleh: Jamaludin Ahmad <jamaludin\@jamalinux.com>", # iso2022jp/iso-2022-jp 'iso2022jp' => "\e\$BF|K\\8lLu\e(B(ISO-2022-JP)\e\$B:n\@.\e(B \e\$B?\">>\e(B \e\$BJ8FA\e(B <uematsu\@kgz.com>", # Italian/Italiano 'italian' => "Localizzazione effettuata da Andrea Rossi <rouge\@shiny.it>", # korean ,'korean' => "ѱ۸޽ : ȲǼ, ȣ", # Lithuanian/lietuvikai 'lithuanian' => "Paruo ir lietuvi kalb ivert ve <ve\@hardcore.lt>", # the lithuanian string means: "Prepared for languages and translated to lithuanian by" # Macedonian/makedonski 'macedonian' => "Makedonska lokalizacija - Delev D Zoran <delevz\@esmak.com.mk>", # the macedonian string means: "Prepared for languages and translated to macedonian by" # Malaysian/Malay 'malay' => "Terjemahan ke bahasa Malaysia/Indonesia oleh: Assakhof Ab. Satar <assakhof\@mimos.my>", # Danish/dansk 'norwegian' => "Oversatt til norsk av Knut Grneng <knut.groneng\@merkantildata.no>", # the norwegian string means: "Translated to norwegian by" # Polish/polski 'polish' => "Polska lokalizacja Lukasz Jokiel <Lukasz.Jokiel\@klonex.com.pl>", # Português/portuguese 'portuguese' => "Traduzido por Diogo Gomes <etdgomes\@ua.pt>", # Romn/romanian 'romanian' => "Tradus de Jzsef Szilgyi <jozsi\@maxiq.ro>", # Russian/ 'russian' => " : <mitya\@cavia.pp.ru>", # Russian1251/1251 'russian1251' => " ( 1251): <aredyuk\@irmcity.com>", # Serbian/Srpski 'serbian' => "Ported to Serbian by / Srpski prevod uradio: Ratko Bui <ratko\@ni.ac.yu>", # Slovak/Slovensky 'slovak' => "Slovensk preklad pripravil Ing. Ladislav Mihok <laco\@mrokh.shmu.sk>", # Slovenian/Slovensko 'slovenian' => "Slovenski prevod pripravil Ragnar Belial Us <us\@sweet-sorrow.com>", # Spanish/español 'spanish' => "Preparado para localización por Marcelo Roccasalva", # Swedish/Svenska 'swedish' => "Översatt till svenska av Clas Mayer <clas\@mayer.se>", # the Swedish string means: "Prepared for languages and translated to Swedish by" # Turkish/Trke 'turkish' => "Trkeletiren zgr C. Demir", # Ukrainian/ 'ukrainian' => " : Ǧ ͦΦ <gray\@arte-fact.net>", # Ukrainian1251/1251 'ukrainian1251' => " (cp1251): <xakep\@snark.ukma.kiev.ua>", ); $credits::LOCALE{'беларуская'}=$credits::LOCALE{'belarusian'}; $credits::LOCALE{'c'}=$credits::LOCALE{'big5'}; $credits::LOCALE{'brazil'}=$credits::LOCALE{'brazilian'}; $credits::LOCALE{''}=$credits::LOCALE{'bulgarian'}; $credits::LOCALE{'catalan'}=$credits::LOCALE{'catalan'}; $credits::LOCALE{''}=$credits::LOCALE{'Chinese'}; $credits::LOCALE{'ĺ'}=$credits::LOCALE{'cn'}; $credits::LOCALE{'hrvatski'}=$credits::LOCALE{'croatian'}; $credits::LOCALE{'czech'}=$credits::LOCALE{'czech'}; $credits::LOCALE{'czechutf8'}=$credits::LOCALE{'czechutf8'}; $credits::LOCALE{'dansk'}=$credits::LOCALE{'danish'}; $credits::LOCALE{'nederlands'}=$credits::LOCALE{'dutch'}; $credits::LOCALE{'eesti'}=$credits::LOCALE{'estonian'}; $credits::LOCALE{'euc-jp'}=$credits::LOCALE{'eucjp'}; $credits::LOCALE{'finnish'}=$credits::LOCALE{'finnish'}; $credits::LOCALE{'francais'}=$credits::LOCALE{'french'}; $credits::LOCALE{'galego'}=$credits::LOCALE{'galician'}; $credits::LOCALE{'庺'}=$credits::LOCALE{'gb'}; $credits::LOCALE{'ļ'}=$credits::LOCALE{'gb2312'}; $credits::LOCALE{'deutsch'}=$credits::LOCALE{'german'}; $credits::LOCALE{'ellinika'}=$credits::LOCALE{'greek'}; $credits::LOCALE{'magyar'}=$credits::LOCALE{'hungarian'}; $credits::LOCALE{'islenska'}=$credits::LOCALE{'icelandic'}; $credits::LOCALE{'indonesian'}=$credits::LOCALE{'indonesia'}; $credits::LOCALE{'iso-2022-jp'}=$credits::LOCALE{'iso2022jp'}; $credits::LOCALE{'italiano'}=$credits::LOCALE{'italian'}; $credits::LOCALE{'korean'}=$credits::LOCALE{'korean'}; $credits::LOCALE{'lietuvikai'}=$credits::LOCALE{'lithuanian'}; $credits::LOCALE{'macedonian'}=$credits::LOCALE{'macedonian'}; $credits::LOCALE{'malaysian'}=$credits::LOCALE{'malay'}; $credits::LOCALE{'norsk'}=$credits::LOCALE{'norwegian'}; $credits::LOCALE{'polski'}=$credits::LOCALE{'polish'}; $credits::LOCALE{'portuguese'}=$credits::LOCALE{'portuguese'}; $credits::LOCALE{'romn'}=$credits::LOCALE{'romanian'}; $credits::LOCALE{''}=$credits::LOCALE{'russian'}; $credits::LOCALE{'1251'}=$credits::LOCALE{'russian1251'}; $credits::LOCALE{'serbian'}=$credits::LOCALE{'serbian'}; $credits::LOCALE{'slovak'}=$credits::LOCALE{'slovak'}; $credits::LOCALE{'slovenian'}=$credits::LOCALE{'slovenian'}; $credits::LOCALE{'espanol'}=$credits::LOCALE{'spanish'}; $credits::LOCALE{'svenska'}=$credits::LOCALE{'swedish'}; $credits::LOCALE{'turkce'}=$credits::LOCALE{'turkish'}; $credits::LOCALE{''}=$credits::LOCALE{'ukrainian'}; $credits::LOCALE{'1251'}=$credits::LOCALE{'ukrainian1251'}; # English - default sub english { return shift; }; # Belarusian sub belarusian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=utf-8 %translations = ( 'iso-8859-1' => 'utf-8', 'Maximal 5 Minute Incoming Traffic' => 'Найбольшы ўваходны трафік за 5 хвілін', 'Maximal 5 Minute Outgoing Traffic' => 'Найбольшы выходны трафік за 5 хвілін', 'the device' => 'прылада', 'The statistics were last updated(.*)' => 'Апошні раз статыстыка абнаўлялася: $1', ' Average\)' => ')', 'Average' => 'спасярэднены', 'Max' => 'найбольшы', 'Current' => 'бягучы', 'version' => 'вэрсія', '`Daily\' Graph \((.*) Minute' => 'Графік трафіку за суткі (за $1 хвілін ', '`Weekly\' Graph \(30 Minute' => 'Графік трафіку за тыдзень (за 30 хвілін ', '`Monthly\' Graph \(2 Hour' => 'Графік трафіку за месяц (за 2 гадзіны ', '`Yearly\' Graph \(1 Day' => 'Графік трафіку за год (за 1 дзень ', 'Incoming Traffic in (\S+) per Second' => 'Уваходны трафік $1 за сэкунду', 'Outgoing Traffic in (\S+) per Second' => 'Выходны трафік $1 за сэкунду', 'Incoming Traffic in (\S+) per Minute' => 'Уваходны трафік $1 за хвіліну', 'Outgoing Traffic in (\S+) per Minute' => 'Выходны трафік $1 за хвіліну', 'Incoming Traffic in (\S+) per Hour' => 'Уваходны трафік $1 за гадзіну', 'Outgoing Traffic in (\S+) per Hour' => 'Выходны трафік $1 за гадзіну', 'at which time (.*) had been up for(.*)' => 'калі $1 працаваў $2', '(\S+) per minute' => '$1 за хвіліну', '(\S+) per hour' => '$1 за гадзіну', '(.+)/s$' => '$1/с', '(.+)/min' => '$1/хв', '(.+)/h$' => '$1/г', '([kMG]?)([bB])/s' => '$1$2/с', '([kMG]?)([bB])/min' => '$1$2/хв', '([kMG]?)([bB])/h' => '$1$2/г', 'Bits' => 'бітах', 'Bytes' => 'байтах', 'In' => 'Уваходны', 'Out' => 'Выходны', 'Percentage' => 'Адсоткі', 'Ported to OpenVMS Alpha by' => 'Перанос на OpenVMS:', 'Ported to WindowsNT by' => 'Перанос на WindowsNT:', 'and' => 'і', '^GREEN' => 'ЗЯЛЁНЫ', 'BLUE' => 'СІНІ', 'DARK GREEN' => 'ЦЁМНАЗЯЛЁНЫ', 'MAGENTA' => 'РУЖОВЫ', 'AMBER' => 'БУРШТЫНАВЫ' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Нядзеля', 'Sun' => 'Нд', 'Monday' => 'Панядзелак', 'Mon' => 'Пн', 'Tuesday' => 'Аўторак', 'Tue' => 'Аў', 'Wednesday' => 'Серада', 'Wed' => 'Ср', 'Thursday' => 'Чацьвер', 'Thu' => 'Чц', 'Friday' => 'Пятніца', 'Fri' => 'Пт', 'Saturday' => 'Субота', 'Sat' => 'Сб' ); %month = ( 'January' => 'Студзень', 'February' => 'Люты' , 'March' => 'Сакавік', 'Jan' => 'Сту', 'Feb' => 'Лют', 'Mar' => 'Сак', 'April' => 'Красавік', 'May' => 'Травень', 'June' => 'Чэрвень', 'Apr' => 'Кра', 'May' => 'Тра', 'Jun' => 'Чэр', 'July' => 'Ліпень', 'August' => 'Жнівень', 'September' => 'Верасень', 'Jul' => 'Ліп', 'Aug' => 'Жні', 'Sep' => 'Вер', 'October' => 'Кастрычнік','November' => 'Лістапад', 'December' => 'Сьнежань', 'Oct' => 'Кас', 'Nov' => 'Ліс', 'Dec' => 'Сьн' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." у ".$quux[1]; }; return "$wday{$foo[0]}, $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Chinese Big5 Code sub big5 { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'big5', 'Maximal 5 Minute Incoming Traffic' => '5̤jyJq', 'Maximal 5 Minute Outgoing Traffic' => '5̤jyXq', 'the device' => '˸m', 'The statistics were last updated(.*)' => 'Wέpsɶ: $1', ' Average\)' => ' )', 'Average' => '', 'Max$' => '̤j', 'Current' => 'ثe', 'version' => '', '`Daily\' Graph \((.*) Minute' => 'C Ϫ ($1 ', '`Weekly\' Graph \(30 Minute' => 'Cg Ϫ (30 ' , '`Monthly\' Graph \(2 Hour' => 'C Ϫ (2 p', '`Yearly\' Graph \(1 Day' => 'C~ Ϫ (1 ', 'Incoming Traffic in (\S+) per Second' => 'CyJq ( $1)', 'Outgoing Traffic in (\S+) per Second' => 'CyXq ( $1)', 'Incoming Traffic in (\S+) per Minute' => 'CyJq ( $1)', 'Outgoing Traffic in (\S+) per Minute' => 'CyXq ( $1)', 'Incoming Traffic in (\S+) per Hour' => 'CpɬyJq ( $1)', 'Outgoing Traffic in (\S+) per Hour' => 'CpɬyXq ( $1)', 'at which time (.*) had been up for(.*)' => ']ƦW $1AwB@ɶ(UPTIME): $2', '(\S+) per minute' => '$1/', '(\S+) per hour' => '$1/p', '(.+)/s$' => '$1/', '(.+)/min$' => '$1/', '(.+)/h$' => '$1/p', #'([kMG]?)([bB])/s' => '$1$2/s', #'([kMG]?)([bB])/min' => '$1$2/min', #'([kMG]?)([bB])/h' => '$1$2/std', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'yJ', 'Out$' => 'yX', 'Percentage' => 'ʤ', 'Ported to OpenVMS Alpha by' => 'Ө OpenVM Alpha @', 'Ported to WindowsNT by' => 'Ө WindowsNT @', 'and' => '', '^GREEN' => '', 'BLUE' => 'Ŧ', 'DARK GREEN' => '', 'MAGENTA' => '', 'AMBER' => '[Ħ' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'P', 'Sun' => '', 'Monday' => 'P@', 'Mon' => '@', 'Tuesday' => 'PG', 'Tue' => 'G', 'Wednesday' => 'PT', 'Wed' => 'T', 'Thursday' => 'P|', 'Thu' => '|', 'Friday' => 'P', 'Fri' => '', 'Saturday' => 'P', 'Sat' => '' ); %month = ( 'January' => '@', 'February' => 'G', 'March' => 'T', 'Jan' => '@', 'Feb' => 'G', 'Mar' => 'T', 'April' => '|', 'May' => '', 'June' => '', 'Apr' => '|', 'May' => '', 'Jun' => '', 'July' => 'C', 'August' => 'K', 'September' => 'E', 'Jul' => 'C', 'Aug' => 'K', 'Sep' => 'E', 'October' => 'Q', 'November' => 'Q@', 'December' => 'QG', 'Oct' => 'Q', 'Nov' => 'Q@', 'Dec' => 'QG' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]; $foo[4]=$quux[1]; }; return "$foo[3] ~ $month{$foo[2]} $foo[1] $wday{$foo[0]} $foo[4]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Brazilian (Portugues) sub brazilian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Tráfego Máximo de Entrada em 5 minutos', 'Maximal 5 Minute Outgoing Traffic' => 'Tráfego Máximo de Saída em 5 minutos', 'the device' => 'dispositivo', 'The statistics were last updated (.*)' => 'Última atualização das estatísticas: $1', ' Average\)' => ' - média)', 'Average' => 'Média', 'Max' => 'Máx', 'Current' => 'Atual', 'version' => 'versão', '`Daily\' Graph \((.*) Minute' => 'Gráfico `Diário\' ($1 minutos', '`Weekly\' Graph \(30 Minute' => 'Gráfico `Semanal\' (30 minutos' , '`Monthly\' Graph \(2 Hour' => 'Gráfico `Mensal\' (2 horas', '`Yearly\' Graph \(1 Day' => 'Gráfico `Anual\' (1 dia', 'Incoming Traffic in (\S+) per Second' => 'Tráfego de Entrada em $1 por segundo', 'Outgoing Traffic in (\S+) per Second' => 'Tráfego de Saída em $1 por segundo', 'at which time (.*) had been up for(.*)' => 'nesta hora $1 estava ativo por $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', # '([kMG]?)([bB])/h' => '$1$2/t', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Entr.', 'Out' => 'Saí', 'Percentage' => 'Porc.', 'Ported to OpenVMS Alpha by' => 'Adaptado para o Alpha OpenVMS por', 'Ported to WindowsNT by' => 'Adaptado para o WindowsNT por', 'and' => 'e', '^GREEN' => 'VERDE', 'BLUE' => 'AZUL', 'DARK GREEN' => 'VERDE ESCURO', 'MAGENTA' => 'LILÁS', 'AMBER' => 'AMBAR' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Domingo', 'Sun' => 'Dom', 'Monday' => 'Segunda', 'Mon' => 'Seg', 'Tuesday' => 'Terça', 'Tue' => 'Ter', 'Wednesday' => 'Quarta', 'Wed' => 'Qua', 'Thursday' => 'Quinta', 'Thu' => 'Qui', 'Friday' => 'Sexta', 'Fri' => 'Sex', 'Saturday' => 'Sábado', 'Sat' => 'Sáb' ); %month = ( 'January' => 'Janeiro', 'February' => 'Fevereiro' , 'March' => 'Março', 'Jan' => 'Jan', 'Feb' => 'Fev', 'Mar' => 'Mar', 'April' => 'Abril', 'May' => 'Maio', 'June' => 'Junho', 'Apr' => 'Abr', 'May' => 'Mai', 'Jun' => 'Jun', 'July' => 'Julho', 'August' => 'Agosto', 'September' => 'Setembro', 'Jul' => 'Jul', 'Aug' => 'Ago', 'Sep' => 'Set', 'October' => 'Outubro', 'November' => 'Novembro', 'December' => 'Dezembro', 'Oct' => 'Out', 'Nov' => 'Nov', 'Dec' => 'Dez' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." às ".$quux[1]; }; return "$wday{$foo[0]}, $foo[1] de $month{$foo[2]} de $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Bulgarian sub bulgarian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'windows-1251', 'Maximal 5 Minute Incoming Traffic' => ' 5 ', 'Maximal 5 Minute Outgoing Traffic' => ' 5 ', 'the device' => '', 'The statistics were last updated(.*)' => ' : $1', ' Average\)' => ' )', 'Average' => '', 'Max' => '.', 'Current' => '', 'version' => '', '`Daily\' Graph \((.*) Minute' => ' ( $1 ', '`Weekly\' Graph \(30 Minute' => ' ( 30 ' , '`Monthly\' Graph \(2 Hour' => ' ( 2 ', '`Yearly\' Graph \(1 Day' => ' ( 1 ', 'Incoming Traffic in (\S+) per Second' => ' $1 ', 'Outgoing Traffic in (\S+) per Second' => ' $1 ', 'at which time (.*) had been up for(.*)' => ' $1 $2', #'([kMG]?)([bB])/s' => '$1$1/', #'([kMG]?)([bB])/min' => '$1$2/', '([kMG]?)([bB])/h' => '$1$2/', 'Bits' => '', 'Bytes' => '', 'In' => '.', 'Out' => '.', 'Percentage' => '', 'Ported to OpenVMS Alpha by' => ' OpenVMS Alpha ', 'Ported to WindowsNT by' => ' WindowsNT ', 'and' => '', '^GREEN' => '', 'BLUE' => '', 'DARK GREEN' => '', 'MAGENTA' => '', 'AMBER' => '' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => ' ', 'Sun' => '', 'Monday' => ' ', 'Mon' => '', 'Tuesday' => ' ', 'Tue' => '', 'Wednesday' => ' ', 'Wed' => '', 'Thursday' => ' ', 'Thu' => '', 'Friday' => ' ', 'Fri' => '', 'Saturday' => ' ', 'Sat' => '' ); %month = ( 'January' => '', 'February' => '' , 'March' => '', 'Jan' => '', 'Feb' => '', 'Mar' => '', 'April' => '', 'May' => '', 'June' => '', 'Apr' => '', 'May' => '', 'Jun' => '', 'July' => '', 'August' => '', 'September' => '', 'Jul' => '', 'Aug' => '', 'Sep' => '', 'October' => '', 'November' => '', 'December' => '', 'Oct' => '', 'Nov' => '', 'Dec' => '' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].". ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # catalan sub catalan { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Tràfic entrant màxim en 5 minuts', 'Maximal 5 Minute Outgoing Traffic' => 'Tràfic sortint màxim en 5 minuts', 'the device' => 'el dispositiu', 'The statistics were last updated(.*)' => 'Estadístiques actualitzades el $1', ' Average\)' => ' Promig)', 'Average' => 'Promig', 'Max' => 'Màxim', 'Current' => 'Actual', 'version' => 'versió', '`Daily\' Graph \((.*) Minute' => 'Gràfic diari ($1 minuts :', '`Weekly\' Graph \(30 Minute' => 'Gràfic setmanal (30 minuts :' , '`Monthly\' Graph \(2 Hour' => 'Gràfic mensual (2 hores :', '`Yearly\' Graph \(1 Day' => 'Gràfic anual (1 dia :', 'Incoming Traffic in (\S+) per Second' => 'Tràfic entrant en $1 per segon', 'Outgoing Traffic in (\S+) per Second' => 'Tràfic sortint en $1 per segon', 'at which time (.*) had been up for(.*)' => '$1 ha estat funcionant durant $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', # '([kMG]?)([bB])/h' => '$1$2/t', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Entrant', 'Out' => 'Sortint', 'Percentage' => 'Percentatge', 'Ported to OpenVMS Alpha by' => 'Portat a OpenVMS Alpha per', 'Ported to WindowsNT by' => 'Portat a WindowsNT per', 'and' => 'i', '^GREEN' => 'VERD', 'BLUE' => 'BLAU', 'DARK GREEN' => 'VERD FOSC', 'MAGENTA' => 'MAGENTA', 'AMBER' => 'AMBAR' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Diumenge', 'Sun' => 'Dg', 'Monday' => 'Dilluns', 'Mon' => 'Dl', 'Tuesday' => 'Dimarts', 'Tue' => 'Dm', 'Wednesday' => 'Dimecres', 'Wed' => 'Dc', 'Thursday' => 'Dijous', 'Thu' => 'Dj', 'Friday' => 'Divendres', 'Fri' => 'Dv', 'Saturday' => 'Dissabte', 'Sat' => 'Ds' ); %month = ( 'January' => 'Gener', 'February' => 'Febrer' , 'March' => 'Març', 'Jan' => 'Gen', 'Feb' => 'Feb', 'Mar' => 'Mar', 'April' => 'Abril', 'May' => 'Maig', 'June' => 'Juny', 'Apr' => 'Abr', 'May' => 'Mai', 'Jun' => 'Jun', 'July' => 'Juliol', 'August' => 'Agost', 'September' => 'Setembre', 'Jul' => 'Jul', 'Aug' => 'Ago', 'Sep' => 'Set', 'October' => 'Octubre', 'November' => 'Novembre', 'December' => 'Desembre', 'Oct' => 'Oct', 'Nov' => 'Nov', 'Dec' => 'Des' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." a les ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] de $month{$foo[2]} de $foo[3]"; }; return $string; }; # Simplified Chinese sub chinese { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... %translations = ( 'iso-8859-1' => 'gb2312', 'Maximal 5 Minute Incoming Traffic' => '5', 'Maximal 5 Minute Outgoing Traffic' => '5', 'the device' => '豸', 'The statistics were last updated(.*)' => 'ͳƸʱ䣺$1', ' Average\)' => ' ƽ)', 'Average' => 'ƽ', 'Max' => '', 'Current' => 'ǰ', 'version' => '汾', '`Daily\' Graph \((.*) Minute' => 'ÿ ͼ ($1 ', '`Weekly\' Graph \(30 Minute' => 'ÿ ͼ (30 ' , '`Monthly\' Graph \(2 Hour' => 'ÿ ͼ (2 Сʱ', '`Yearly\' Graph \(1 Day' => 'ÿ ͼ (1 ', 'Incoming Traffic in (\S+) per Second' => 'ÿ (λ $1 )', 'Outgoing Traffic in (\S+) per Second' => 'ÿ (λ $1 )', 'at which time (.*) had been up for(.*)' => ' $1 ˣ $2 ', '(.+)/s$' => '$1/', '(.+)/min$' => '$1/', '(.+)/h$' => '$1/ʱ', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => '룺', 'Out' => '', 'Percentage' => 'ٷֱȣ', 'Ported to OpenVMS Alpha by' => 'ֲ OpenVMS ', 'Ported to WindowsNT by' => 'ֲ WindowsNT ', 'and' => '', '^GREEN' => 'ɫ', 'BLUE' => 'ɫ', 'DARK GREEN' => 'ī', 'MAGENTA' => 'ɫ', 'AMBER' => 'ɫ' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => '', 'Sun' => '', 'Monday' => 'һ', 'Mon' => 'һ', 'Tuesday' => 'ڶ', 'Tue' => '', 'Wednesday' => '', 'Wed' => '', 'Thursday' => '', 'Thu' => '', 'Friday' => '', 'Fri' => '', 'Saturday' => '', 'Sat' => '' ); %month = ( 'January' => ' һ ', 'February' => ' ', 'March' => ' ', 'April' => ' ', 'May' => ' ', 'June' => ' ', 'July' => ' ', 'August' => ' ', 'September' => ' ', 'October' => ' ʮ ', 'November' => 'ʮһ', 'December' => 'ʮ', 'Jan' => '', 'Feb' => '', 'Mar' => '', 'Apr' => '', 'May' => '', 'Jun' => '', 'Jul' => '', 'Aug' => '', 'Sep' => '', 'Oct' => '10', 'Nov' => '11', 'Dec' => '12' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]; $foo[4]=$quux[1]; }; return "$foo[3] $month{$foo[2]} $foo[1] $wday{$foo[0]} $foo[4]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # cn s-Chinese sub cn { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... %translations = ( 'charset=iso-8859-1' => 'charset=gb2312', 'Maximal 5 Minute Incoming Traffic' => '5', 'Maximal 5 Minute Outgoing Traffic' => '5', 'the device' => '豸', 'The statistics were last updated(.*)' => 'ͳʱ䣺$1', ' Average\)

' => ' ƽ)

', 'Average(.*)' => 'ƽ$1', 'Max(.*)' => '$1', 'Current(.*)' => 'ǰ$1', 'version' => '汾', '`Daily\' Graph \((.*) Minute' => '"ÿ" ͼ ($1 ', '`Weekly\' Graph \(30 Minute' => '"ÿ" ͼ (30 ' , '`Monthly\' Graph \(2 Hour' => '"ÿ" ͼ (2 Сʱ', '`Yearly\' Graph \(1 Day' => '"ÿ" ͼ (1 ', 'Incoming Traffic in (\S+) per Second' => 'ÿ $1 ', 'Outgoing Traffic in (\S+) per Second' => 'ÿ $1 ', 'at which time (.*) had been up for(.*)' => 'ʱ $1 ˣ $2 ', '(.+)/s$' => '$1/', '(.+)/min$' => '$1/', '(.+)/h$' => '$1/ʱ', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' ' In:' => ' 룺', ' Out:' => ' ', ' Percentage' => ' ٷֱȣ', 'Ported to OpenVMS Alpha by' => 'ֲ OpenVMS ', 'Ported to WindowsNT by' => 'ֲ WindowsNT ', 'and' => '', '^GREEN' => '', 'BLUE' => '', 'DARK GREEN' => 'ī', 'MAGENTA' => '', 'AMBER' => 'ɫ' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => '', 'Sun' => '', 'Monday' => 'һ', 'Mon' => 'һ', 'Tuesday' => 'ڶ', 'Tue' => '', 'Wednesday' => '', 'Wed' => '', 'Thursday' => '', 'Thu' => '', 'Friday' => '', 'Fri' => '', 'Saturday' => '', 'Sat' => '' ); %month = ( 'January' => ' һ ', 'February' => ' ', 'March' => ' ', 'April' => ' ', 'May' => ' ', 'June' => ' ', 'July' => ' ', 'August' => ' ', 'September' => ' ', 'October' => ' ʮ ', 'November' => 'ʮһ', 'December' => 'ʮ', 'Jan' => '', 'Feb' => '', 'Mar' => '', 'Apr' => '', 'May' => '', 'Jun' => '', 'Jul' => '', 'Aug' => '', 'Sep' => '', 'Oct' => '', 'Nov' => '', 'Dec' => '' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]; $foo[4]=$quux[1]; }; return "$foo[3] $month{$foo[2]} $foo[1] $wday{$foo[0]} $foo[4]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; sub croatian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'iso-8859-2', 'Maximal 5 Minute Incoming Traffic' => 'Maksimalni ulazni promet unutar 5 minuta', 'Maximal 5 Minute Outgoing Traffic' => 'Maksimalni izlazni promet unutar 5 minuta', 'the device' => 'ureaj', 'The statistics were last updated(.*)' => 'Statistike su zadnji puta izmijenjene $1', ' Average\)' => ' prosjena vrijednost)', 'Average' => 'Prosjeno', 'Max' => 'Maksimalno', 'Current' => 'Trenutno', 'version' => 'verzija', '`Daily\' Graph \((.*) Minute' => 'Dnevne statistike (svakih $1 minuta', '`Weekly\' Graph \(30 Minute' => 'Tjedne statistike (svakih 30 minuta' , '`Monthly\' Graph \(2 Hour' => 'Mjesene statistike (svakih 2 sata', '`Yearly\' Graph \(1 Day' => 'Godinje statistike (svaki 1 dan', 'Incoming Traffic in (\S+) per Second' => 'Ulazni promet - $1 po sekundi', 'Outgoing Traffic in (\S+) per Second' => 'Izlazni promet - $1 po sekundi', 'at which time (.*) had been up for(.*)' => 'gdje $1 je bio aktivan $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/g', 'Bits' => 'Bitova', 'Bytes' => 'Bajtova', 'In' => 'Unutra', 'Out' => 'Van', 'Percentage' => 'Postotak', 'Ported to OpenVMS Alpha by' => 'Port na OpenVMS Alpha od', 'Ported to WindowsNT by' => 'Post od WindowsNT od', 'and' => 'i', '^GREEN' => 'ZELENA', 'BLUE' => 'PLAVA', 'DARK GREEN' => 'TAMNO ZELENA', 'MAGENTA' => 'LJUBIASTA', 'AMBER' => 'AMBER' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Nedjelja', 'Sun' => 'Ned', 'Monday' => 'Ponedjeljak', 'Mon' => 'Pon', 'Tuesday' => 'Utorak', 'Tue' => 'Uto', 'Wednesday' => 'Srijeda', 'Wed' => 'Sri', 'Thursday' => 'etvrtak', 'Thu' => 'et', 'Friday' => 'Petak', 'Fri' => 'Pet', 'Saturday' => 'Subota', 'Sat' => 'Sub' ); %month = ( 'January' => 'Sijeanj', 'February' => 'Veljaa', 'March' => 'Oujak', 'Jan' => 'Sij', 'Feb' => 'Vel', 'Mar' => 'Ou', 'April' => 'Travanj', 'May' => 'Svibanj', 'June' => 'Lipanj', 'Apr' => 'Tra', 'May' => 'Svi', 'Jun' => 'Lip', 'July' => 'Srpanj', 'August' => 'Kolovoz', 'September' => 'Rujan', 'Jul' => 'Srp', 'Aug' => 'Kol', 'Sep' => 'Ruj', 'October' => 'Listopad', 'November' => 'Studeni', 'December' => 'Prosinac', 'Oct' => 'Lis', 'Nov' => 'Stu', 'Dec' => 'Pro' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." godine"." u".$quux[1]; }; return "$wday{$foo[0]} dana $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Czech sub czech { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'windows-1250', 'Maximal 5 Minute Incoming Traffic' => 'Maximln 5 minutov pchoz tok', 'Maximal 5 Minute Outgoing Traffic' => 'Maximln 5 minutov odchoz tok', 'the device' => 'zazen', 'The statistics were last updated(.*)' => 'Posledn aktualizace statistiky:$1', ' Average\)' => ' prmr)', 'Average' => 'Prm.', 'Max' => 'Max.', 'Current' => 'Akt.', 'version' => 'verze', '`Daily\' Graph \((.*) Minute' => 'Denn graf ($1 minutov', '`Weekly\' Graph \(30 Minute' => 'Tdenn graf (30 minutov' , '`Monthly\' Graph \(2 Hour' => 'Msn graf (2 hodinov', '`Yearly\' Graph \(1 Day' => 'Ron graf (1 denn', 'Incoming Traffic in (\S+) per Second' => 'Pchoz tok v $1 za sec.', 'Outgoing Traffic in (\S+) per Second' => 'Odchoz tok v $1 za sec.', 'at which time (.*) had been up for(.*)' => 'od poslednho restartu $1 ubhlo: $2', #'([kMG]?)([bB])/s' => '\$1\$2/s', #'([kMG]?)([bB])/min' => '\$1\$2/min', #'([kMG]?)([bB])/h' => '$1$2/h', 'Bits' => 'bitech', 'Bytes' => 'bajtech', #' In:' => ' In:', #' Out:' => ' Out:', 'Percentage' => 'Proc.', 'Ported to OpenVMS Alpha by' => 'Na OpenVMS portoval', 'Ported to WindowsNT by' => 'Na WindowsNT portoval', 'and' => 'a', '^GREEN' => 'Zelen', 'BLUE' => 'Modr', 'DARK GREEN' => 'Tmav zelen', 'MAGENTA' => 'Fialov', 'AMBER' => 'lut' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Nedle', 'Sun' => 'Ne', 'Monday' => 'Pondli', 'Mon' => 'Po', 'Tuesday' => 'ter', 'Tue' => 't', 'Wednesday' => 'Steda', 'Wed' => 'St', 'Thursday' => 'tvrtek', 'Thu' => 't', 'Friday' => 'Ptek', 'Fri' => 'P', 'Saturday' => 'Sobota', 'Sat' => 'So' ); %month = ( 'January' => 'Leden', 'February' => 'nor', 'March' => 'Bezen', 'Jan' => 'Leden', 'Feb' => 'nor', 'Mar' => 'Bezen', 'April' => 'Duben', 'May' => 'Kvten', 'June' => 'erven', 'Apr' => 'Duben', 'May' => 'Kvten', 'Jun' => 'erven', 'July' => 'ervenec','August' => 'Srpen', 'September' => 'Z', 'Jul' => 'ervenec','Aug' => 'Srpen', 'Sep' => 'Z', 'October' => 'jen', 'November' => 'Listopad', 'December' => 'Prosinec', 'Oct' => 'jen', 'Nov' => 'Listopad', 'Dec' => 'Prosinec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].",".$quux[1]." hod."; }; return "$wday{$foo[0]} $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; } # # Czechutf8 sub czechutf8 { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'utf-8', 'Maximal 5 Minute Incoming Traffic' => 'Maximální 5 minutový příchozí tok', 'Maximal 5 Minute Outgoing Traffic' => 'Maximální 5 minutový odchozí tok', 'the device' => 'zařízení', 'The statistics were last updated(.*)' => 'Poslední aktualizace statistiky:$1', ' Average\)' => ' průměr)', 'Average' => 'Prům.', 'Max' => 'Max.', 'Current' => 'Akt.', 'version' => 'verze', '`Daily\' Graph \((.*) Minute' => 'Denní graf ($1 minutový', '`Weekly\' Graph \(30 Minute' => 'Týdenní graf (30 minutový' , '`Monthly\' Graph \(2 Hour' => 'Měsíční graf (2 hodinový', '`Yearly\' Graph \(1 Day' => 'Roční graf (1 denní', 'Incoming Traffic in (\S+) per Second' => 'Příchozí tok v $1 za sec.', 'Outgoing Traffic in (\S+) per Second' => 'Odchozí tok v $1 za sec.', 'at which time (.*) had been up for(.*)' => 'od posledního restartu $1 uběhlo: $2', #'([kMG]?)([bB])/s' => '\$1\$2/s', #'([kMG]?)([bB])/min' => '\$1\$2/min', #'([kMG]?)([bB])/h' => '$1$2/h', 'Bits' => 'bitech', 'Bytes' => 'bajtech', #' In:' => ' In:', #' Out:' => ' Out:', 'Percentage' => 'Proc.', 'Ported to OpenVMS Alpha by' => 'Na OpenVMS portoval', 'Ported to WindowsNT by' => 'Na WindowsNT portoval', 'and' => 'a', '^GREEN' => 'Zelená', 'BLUE' => 'Modrá', 'DARK GREEN' => 'Tmavě zelená', 'MAGENTA' => 'Fialová', 'AMBER' => 'Žlutá' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Neděle', 'Sun' => 'Ne', 'Monday' => 'Pondělí', 'Mon' => 'Po', 'Tuesday' => 'Úterý', 'Tue' => 'Út', 'Wednesday' => 'Středa', 'Wed' => 'St', 'Thursday' => 'Čtvrtek', 'Thu' => 'Čt', 'Friday' => 'Pátek', 'Fri' => 'Pá', 'Saturday' => 'Sobota', 'Sat' => 'So' ); %month = ( 'January' => 'Leden', 'February' => 'Únor', 'March' => 'Březen', 'Jan' => 'Leden', 'Feb' => 'Únor', 'Mar' => 'Březen', 'April' => 'Duben', 'May' => 'Květen', 'June' => 'Červen', 'Apr' => 'Duben', 'May' => 'Květen', 'Jun' => 'Červen', 'July' => 'Červenec','August' => 'Srpen', 'September' => 'Září', 'Jul' => 'Červenec','Aug' => 'Srpen', 'Sep' => 'Září', 'October' => 'Říjen', 'November' => 'Listopad', 'December' => 'Prosinec', 'Oct' => 'Říjen', 'Nov' => 'Listopad', 'Dec' => 'Prosinec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].",".$quux[1]." hod."; }; return "$wday{$foo[0]} $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; } # # Danish sub danish { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Maksimal indgående trafik i 5 minutter', 'Maximal 5 Minute Outgoing Traffic' => 'Maksimal udgående trafik i 5 minutter', 'the device' => 'enheden', 'The statistics were last updated(.*)' => 'Statistikken blev sidst opdateret$1', ' Average\)' => ' Middel)', 'Average' => 'Middel', 'Max' => 'Max', 'Current' => 'Nu', 'version' => 'version', '`Daily\' Graph \((.*) Minute' => '`Daglig\' graf ($1 minuts', '`Weekly\' Graph \(30 Minute' => '`Ugentlig\' graf (30 minuts' , '`Monthly\' Graph \(2 Hour' => '`Månedlig\' graf (2 times', '`Yearly\' Graph \(1 Day' => '`Årlig\' graf (1 dags', 'Incoming Traffic in (\S+) per Second' => 'Indgående trafik i $1 per sekund', 'Outgoing Traffic in (\S+) per Second' => 'Udgående trafik i $1 per sekund', 'at which time (.*) had been up for(.*)' => 'hvor $1 havde været oppe i$2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/t', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Ind', 'Out' => 'Ud', 'Percentage' => 'Procent', 'Ported to OpenVMS Alpha by' => 'Port til OpenVMS af', 'Ported to WindowsNT by' => 'Port til WindowsNT af', 'and' => 'og', '^GREEN' => 'GRØN', 'BLUE' => 'BLÅ', 'DARK GREEN' => 'MØRKEGRØN', 'MAGENTA' => 'LYSLILLA', 'AMBER' => 'RAV' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Søndag', 'Sun' => 'Søn', 'Monday' => 'Mandag', 'Mon' => 'Man', 'Tuesday' => 'Tirsdag', 'Tue' => 'Tir', 'Wednesday' => 'Onsdag', 'Wed' => 'Ons', 'Thursday' => 'Torsdag', 'Thu' => 'Tor', 'Friday' => 'Fredag', 'Fri' => 'Fre', 'Saturday' => 'Lørdag', 'Sat' => 'Lør' ); %month = ( 'January' => 'Januar', 'February' => 'Februar' , 'March' => 'Marts', 'Jan' => 'Jan', 'Feb' => 'Feb', 'Mar' => 'Mar', 'April' => 'April', 'May' => 'Maj', 'June' => 'Juni', 'Apr' => 'Apr', 'May' => 'Maj', 'Jun' => 'Jun', 'July' => 'Juli', 'August' => 'August', 'September' => 'September', 'Jul' => 'Jul', 'Aug' => 'Aug', 'Sep' => 'Sep', 'October' => 'Oktober', 'November' => 'November', 'December' => 'December', 'Oct' => 'Okt', 'Nov' => 'Nov', 'Dec' => 'Dec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." kl.".$quux[1]; }; return "$wday{$foo[0]} den $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Dutch sub dutch { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Maximaal inkomend verkeer per 5 minuten', 'Maximal 5 Minute Outgoing Traffic' => 'Maximaal uitgaand verkeer per 5 minuten', 'the device' => 'het apparaat', 'The statistics were last updated(.*)' => 'Statistieken voor het laatst bijgewerkt op$1', ' Average\)' => ' gemiddeld)', 'Average' => 'Gemiddeld', 'Max' => 'Max', 'Current' => 'Actueel', 'version' => 'versie', '`Daily\' Graph \((.*) Minute' => '`Dagelijkse\' grafiek ($1 minuten', '`Weekly\' Graph \(30 Minute' => '`Wekelijkse\' grafiek (30 minuten' , '`Monthly\' Graph \(2 Hour' => '`Maandelijkse\' grafiek (2 uur', '`Yearly\' Graph \(1 Day' => '`Jaarlijkse\' grafiek (1 dag', 'Incoming Traffic in (\S+) per Second' => 'Inkomend verkeer in $1 per seconde', 'Outgoing Traffic in (\S+) per Second' => 'Uitgaand verkeer in $1 per seconde', 'at which time (.*) had been up for(.*)' => 'op het moment dat $1 reeds actief was voor$2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/u', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' # ' In:' => ' In:', 'Out' => 'Uit', 'Percentage' => 'Procent', 'Ported to OpenVMS Alpha by' => 'Ported naar OpenVMS door', 'Ported to WindowsNT by' => 'Ported naar WindowsNT door', 'and' => 'en', 'DARK GREEN' => 'DONKER GROEN', '^GREEN' => 'GROEN', 'BLUE' => 'BLAUW', 'MAGENTA' => 'LILA', 'AMBER' => 'AMBER' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'zondag', 'Sun' => 'zon', 'Monday' => 'maandag', 'Mon' => 'maa', 'Tuesday' => 'dinsdag', 'Tue' => 'din', 'Wednesday' => 'woensdag', 'Wed' => 'woe', 'Thursday' => 'donderdag', 'Thu' => 'don', 'Friday' => 'vrijdag', 'Fri' => 'vri', 'Saturday' => 'zaterdag', 'Sat' => 'zat' ); %month = ( 'January' => 'januari', 'February' => 'februari', 'March' => 'maart', 'Jan' => 'jan', 'Feb' => 'feb', 'Mar' => 'mrt', 'April' => 'april', 'May' => 'mei', 'June' => 'juni', 'Apr' => 'apr', 'May' => 'mei', 'Jun' => 'jun', 'July' => 'juli', 'August' => 'augustus', 'September' => 'september', 'Jul' => 'jul', 'Aug' => 'aug', 'Sep' => 'sep', 'October' => 'oktober', 'November' => 'november', 'December' => 'december', 'Oct' => 'okt', 'Nov' => 'nov', 'Dec' => 'dec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." om".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Estonian sub estonian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => '5 minuti maksimaalne sisenev liiklus', 'Maximal 5 Minute Outgoing Traffic' => '5 minuti maksimaalne väljuv liiklus', 'the device' => 'seade', 'The statistics were last updated(.*)' => 'Statistikat uuendati viimati$1', ' Average\)' => ' keskmine)', 'Average' => 'Keskmine', #'Max' => 'Max', 'Current' => 'Hetkel', 'version' => 'versioon', '`Daily\' Graph \((.*) Minute' => '`Päevane\' graafik ($1 minuti', '`Weekly\' Graph \(30 Minute' => '`Nädala\' graafik (30 minuti' , '`Monthly\' Graph \(2 Hour' => '`Kuu \' graafik (2 tunni', '`Yearly\' Graph \(1 Day' => '`Aasta\' graafik (1 päeva', 'Incoming Traffic in (\S+) per Second' => 'Sisenev liiklus $1 sekundi kohta', 'Outgoing Traffic in (\S+) per Second' => 'Väljuv liiklus $1 sekundi kohta', 'at which time (.*) had been up for(.*)' => 'kui $1 on katkematult töötanud$2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/t', 'Bits' => 'bitti', 'Bytes' => 'baiti', 'In' => 'sisse', 'Out' => 'välja', 'Percentage' => 'protsent', 'Ported to OpenVMS Alpha by' => 'portis OpenVMS-le:', 'Ported to WindowsNT by' => 'portis WindowsNT-le:', 'and' => 'ja', '^GREEN' => 'ROHELINE', 'BLUE' => 'SININE', 'DARK GREEN' => 'TUMEROHELINE', 'MAGENTA' => 'LILLA', 'AMBER' => 'HELEROHELINE' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'pühapäev', 'Sun' => 'P', 'Monday' => 'esmaspäev', 'Mon' => 'E', 'Tuesday' => 'teisipäev', 'Tue' => 'T', 'Wednesday' => 'kolmapäev', 'Wed' => 'K', 'Thursday' => 'neljapäev', 'Thu' => 'N', 'Friday' => 'reede', 'Fri' => 'R', 'Saturday' => 'laupäev', 'Sat' => 'L' ); %month = ( 'January' => 'jaanuar', 'February' => 'veebruar' , 'March' => 'märts', 'Jan' => 'jaan', 'Feb' => 'veebr', 'Mar' => 'märts', 'April' => 'aprill', 'May' => 'mai', 'June' => 'juuni', 'Apr' => 'aprill', 'May' => 'mai', 'Jun' => 'juuni', 'July' => 'juuli', 'August' => 'august', 'September' => 'september', 'Jul' => 'juuli', 'Aug' => 'aug', 'Sep' => 'sept', 'October' => 'oktoober', 'November' => 'november', 'December' => 'detsember', 'Oct' => 'okt', 'Nov' => 'nov', 'Dec' => 'dets' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." kl.".$quux[1]; }; return "$wday{$foo[0]}, $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # eucjp sub eucjp { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( '^iso-8859-1' => 'euc-jp', '^Maximal 5 Minute Incoming Traffic' => '5ʬ', '^Maximal 5 Minute Outgoing Traffic' => '5ʬ', '^the device' => 'ǥХ', '^The statistics were last updated (.*)' => ' $1', '^Average\)' => 'ʿ)', '^Average$' => 'ʿ', '^Max$' => '', '^Current' => 'ǿ', '^`Daily\' Graph \((.*) Minute' => '($1ʬ', '^`Weekly\' Graph \(30 Minute' => '(30ʬ', '^`Monthly\' Graph \(2 Hour' => '(2', '^`Yearly\' Graph \(1 Day' => 'ǯ(1', '^Incoming Traffic in (\S+) per Second' => 'äμ$1', '^Incoming Traffic in (\S+) per Minute' => 'ʬμ$1', '^Incoming Traffic in (\S+) per Hour' => 'μ$1', '^Outgoing Traffic in (\S+) per Second' => 'ä$1', '^Outgoing Traffic in (\S+) per Minute' => 'ʬ$1', '^Outgoing Traffic in (\S+) per Hour' => '$1', '^at which time (.*) had been up for (.*)' => '$1βƯ $2', '^Average max 5 min values for `Daily\' Graph \((.*) Minute interval\):' => 'դǤκ5ʬͤʿ($1ʬֳ):', '^Average max 5 min values for `Weekly\' Graph \(30 Minute interval\):' => 'դǤκ5ʬͤʿ(30ʬֳ):', '^Average max 5 min values for `Monthly\' Graph \(2 Hour interval\):' => 'դǤκ5ʬͤʿ(2ֳִ):', '^Average max 5 min values for `Yearly\' Graph \(1 Day interval\):' => 'ǯդǤκ5ʬͤʿ(1ֳ):', #'^([kMG]?)([bB])/s' => '$1$2/', #'^([kMG]?)([bB])/min' => '$1$2/ʬ', #'^([kMG]?)([bB])/h' => '$1$2/', '^Bits$' => 'ӥå', '^Bytes$' => 'Х', '^In$' => '', '^Out$' => '', '^Percentage' => 'Ψ', '^Ported to OpenVMS Alpha by' => 'OpenVMS Alphaؤΰܿ', '^Ported to WindowsNT by' => 'WindowsNTؤΰܿ', #'^and' => 'and', '^GREEN' => '', '^BLUE' => '', '^DARK GREEN' => '', '^MAGENTA' => 'ޥ', '^AMBER' => '' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => '()', 'Monday' => '()', 'Tuesday' => '()', 'Wednesday' => '()', 'Thursday' => '()', 'Friday' => '()', 'Saturday' => '()', ); %month = ( 'January' => '1', 'February' => '2', 'March' => '3', 'April' => '4', 'May' => '5', 'June' => '6', 'July' => '7', 'August' => '8', 'September' => '9', 'October' => '10', 'November' => '11', 'December' => '12', ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)\s+(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~/at/) { @quux=split(/\s+at\s+/,$foo[3]); } else { @quux=split(/ /,$foo[3],2); }; return "$quux[0]ǯ$month{$foo[2]}$foo[1]$wday{$foo[0]} $quux[1]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Finnish sub finnish { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Tulevan liikenteen maksimi 5 minuutin aikana', 'Maximal 5 Minute Outgoing Traffic' => 'Lähtevän liikenteen maksimi 5 minuutin aikana', 'the device' => 'laite', 'The statistics were last updated(.*)' => 'Tiedot päivitetty viimeksi $1', ' Average\)' => '', 'Average' => 'Keskimäärin', 'Max' => 'Maksimi', 'Current' => 'Tällä hetkellä', 'version' => 'versio', '`Daily\' Graph \((.*) Minute' => 'Päiväraportti (skaala $1 minuutti(a))', '`Weekly\' Graph \(30 Minute' => 'Viikkoraportti (skaala 30 minuuttia)' , '`Monthly\' Graph \(2 Hour' => 'Kuukausiraportti (skaala 2 tuntia)', '`Yearly\' Graph \(1 Day' => 'Vuosiraportti (skaala 1 vuorokausi)', 'Incoming Traffic in (\S+) per Second' => 'Tuleva liikenne $1 sekunnissa', 'Outgoing Traffic in (\S+) per Second' => 'Lähtevä liikenne $1 sekunnissa', 'Incoming Traffic in (\S+) per Minute' => 'Tuleva liikenne $1 minuutissa', 'Outgoing Traffic in (\S+) per Minute' => 'Lähtevä liikenne $1 minuutissa', 'Incoming Traffic in (\S+) per Hour' => 'Tuleva liikenne $1 tunnissa', 'Outgoing Traffic in (\S+) per Hour' => 'Lähtevä liikenne $1 tunnissa', 'at which time (.*) had been up for(.*)' => 'jolloin $1 on toiminut yhtäjaksoisesti $2', '(\S+) per minute' => '$1 minuutissa', '(\S+) per hour' => '$1 tunnissa', '(.+)/s$' => '$1/s', # '(.+)/min' => '$1/min', #'(.+)/h$' => '$1/h', #'([kMG]?)([bB])/s' => '$1$2/s', #'([kMG]?)([bB])/min' => '$1$2/min', #'([kMG]?)([bB])/h' => '$1$2/h', 'Bits' => 'bittiä', 'Bytes' => 'tavua', 'In' => 'Tuleva', 'Out' => 'Lähtevä', 'Percentage' => 'Prosenttia', 'Ported to OpenVMS Alpha by' => 'OpenVMS -järjestelmälle sovittanut', 'Ported to WindowsNT by' => 'WindowsNT -järjestelmälle sovittanut', 'and' => 'ja', '^GREEN' => 'VIHREÄ', 'BLUE' => 'SININEN', 'DARK GREEN' => 'TUMMANVIHREÄ', 'MAGENTA' => 'PINKKI', 'AMBER' => 'PUNAINEN', ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Sunnuntai', 'Sun' => 'Su', 'Monday' => 'Maanantai', 'Mon' => 'Ma', 'Tuesday' => 'Tiistai', 'Tue' => 'Ti', 'Wednesday' => 'Keskiviikko', 'Wed' => 'Ke', 'Thursday' => 'Torstai', 'Thu' => 'To', 'Friday' => 'Perjantai', 'Fri' => 'Pe', 'Saturday' => 'Lauantai', 'Sat' => 'La' ); %month = ( 'January' => 'Tammi', 'February' => 'Helmi' , 'March' => 'Maalis', 'Jan' => 'Tam', 'Feb' => 'Hel', 'Mar' => 'Maa', 'April' => 'Huhti', 'May' => 'Touko', 'June' => 'Kesä', 'Apr' => 'Huh', 'May' => 'Tou', 'Jun' => 'Kes', 'July' => 'Heinä', 'August' => 'Elo', 'September' => 'Syys', 'Jul' => 'Hei', 'Aug' => 'Elo', 'Sep' => 'Syy', 'October' => 'Loka', 'November' => 'Marras', 'December' => 'Joulu', 'Oct' => 'Lok', 'Nov' => 'Mar', 'Dec' => 'Kou' ); # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if( $wday{$foo[0]} && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." kello ".$quux[1]; }; return "$wday{$foo[0]}, $foo[1]. $month{$foo[2]} $foo[3]"; }; # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # French sub french { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Trafic maximal en entrée sur 5 minutes', 'Maximal 5 Minute Outgoing Traffic' => 'Trafic maximal en sortie sur 5 minutes', 'the device' => 'le matériel', 'The statistics were last updated(.*)' => 'Les statistiques ont été mises à jour le $1', ' Average\)' => ' Moyenne)', 'Average' => 'Moyenne', '>Max' => 'Max', 'Current' => 'Actuel', #'version' => 'version', '`Daily\' Graph \((.*) Minute' => 'Graphique quotidien (sur $1 minutes :', '`Weekly\' Graph \(30 Minute' => 'Graphique hebdomadaire (sur 30 minutes :' , '`Monthly\' Graph \(2 Hour' => 'Graphique mensuel (sur 2 heures :', '`Yearly\' Graph \(1 Day' => 'Graphique annuel (sur 1 jour :', 'Incoming Traffic in (\S+) per Second' => 'Trafic d\'entrée en $1 par seconde', 'Outgoing Traffic in (\S+) per Second' => 'Trafic de sortie en $1 par seconde', 'at which time (.*) had been up for(.*)' => '$1 était alors en marche depuis $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/t', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Entrée', 'Out' => 'Sortie', 'Percentage' => 'Pourcentage', 'Ported to OpenVMS Alpha by' => 'Porté sur OpenVMS Alpha par', 'Ported to WindowsNT by' => 'Porté sur WindowsNT par', 'and' => 'et', '^GREEN' => 'VERT', 'BLUE' => 'BLEU', 'DARK GREEN' => 'VERT SOMBRE', 'MAGENTA' => 'MAGENTA', 'AMBER' => 'AMBRE' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Dimanche', 'Sun' => 'Dim', 'Monday' => 'Lundi', 'Mon' => 'Lun', 'Tuesday' => 'Mardi', 'Tue' => 'Mar', 'Wednesday' => 'Mercredi', 'Wed' => 'Mer', 'Thursday' => 'Jeudi', 'Thu' => 'Jeu', 'Friday' => 'Vendredi', 'Fri' => 'Ven', 'Saturday' => 'Samedi', 'Sat' => 'Sam' ); %month = ( 'January' => 'Janvier', 'February' => 'Février' , 'March' => 'Mars', 'Jan' => 'Jan', 'Feb' => 'Fev', 'Mar' => 'Mar', 'April' => 'Avril', 'May' => 'Mai', 'June' => 'Juin', 'Apr' => 'Avr', 'May' => 'Mai', 'Jun' => 'Jun', 'July' => 'Juillet', 'August' => 'Août', 'September' => 'Septembre', 'Jul' => 'Jul', 'Aug' => 'Aou', 'Sep' => 'Sep', 'October' => 'Octobre', 'November' => 'Novembre', 'December' => 'Décembre', 'Oct' => 'Oct', 'Nov' => 'Nov', 'Dec' => 'Dec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." à ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." à $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Galician sub galician { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Tr&áfico entrante máximo en 5 minutos', 'Maximal 5 Minute Outgoing Traffic' => 'Tr&áfico saínte máximo en 5 minutos', 'the device' => 'o dispositivo', 'The statistics were last updated(.*)' => 'Estas estatísticas actualizáronse o $1', ' Average\)' => ' de Media)', 'Average' => 'Media', 'Max' => 'Máx', 'Current' => 'Actual', 'version' => 'versión', '`Daily\' Graph \((.*) Minute' => 'Gráfica diaria ($1 minutos', '`Weekly\' Graph \(30 Minute' => 'Gráfica semanal (30 minutos' , '`Monthly\' Graph \(2 Hour' => 'Gráfica mensual (2 horas', '`Yearly\' Graph \(1 Day' => 'Gráfica anual (1 día', 'Incoming Traffic in (\S+) per Second' => 'Tráfico entrante en $1 por segundo', 'Outgoing Traffic in (\S+) per Second' => 'Tráfico saínte en $1 por segundo', 'at which time (.*) had been up for(.*)' => 'nese intre $1 levaba prendida $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/h', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Entrante', 'Out' => 'Saínte', 'Percentage' => 'Tanto por ciento', 'Ported to OpenVMS Alpha by' => 'Portado a OpenVMS Alpha por', 'Ported to WindowsNT by' => 'Portado a Windows NT por', 'and' => 'e', '^GREEN' => 'VERDE', 'BLUE' => 'AZUL', 'DARK GREEN' => 'VERDE OSCURO', 'MAGENTA' => 'ROSA', 'AMBER' => 'AMBAR' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Domingo', 'Sun' => 'Dom', 'Monday' => 'Luns', 'Mon' => 'Lun', 'Tuesday' => 'Martes', 'Tue' => 'Mar', 'Wednesday' => 'Mércores', 'Wed' => 'mér', 'Thursday' => 'Xoves', 'Thu' => 'Xov', 'Friday' => 'Venres', 'Fri' => 'Ven', 'Saturday' => 'Sábado', 'Sat' => 'Sáb' ); %month = ( 'January' => 'Xaneiro', 'February' => 'Febreiro' , 'March' => 'Marzo', 'Jan' => 'Xan', 'Feb' => 'Feb', 'Mar' => 'Mar', 'April' => 'Abril', 'May' => 'Maio', 'June' => 'Xuño', 'Apr' => 'Abr', 'May' => 'Mai', 'Jun' => 'Xuñ', 'July' => 'Xullo', 'August' => 'Agosto', 'September' => 'Setembro', 'Jul' => 'Xul', 'Aug' => 'Ago', 'Sep' => 'Set', 'October' => 'Outubro', 'November' => 'Novembro', 'December' => 'Decembro', 'Oct' => 'Out', 'Nov' => 'Nov', 'Dec' => 'Dec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." ás ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] de $month{$foo[2]} de $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Chinese gb Code sub gb { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'gb', 'Maximal 5 Minute Incoming Traffic' => '5', 'Maximal 5 Minute Outgoing Traffic' => '5', 'the device' => 'ǰ豸', 'The statistics were last updated(.*)' => 'ͳϢ: $1', ' Average\)' => 'ƽ)', 'Average' => 'ƽ', 'Max' => '', 'Current' => 'ǰ', 'version' => '汾', '`Daily\' Graph \((.*) Minute' => 'շͼ($1', '`Weekly\' Graph \(30 Minute' => 'ܷͼ(30' , '`Monthly\' Graph \(2 Hour' => '·ͼ(2Сʱ', '`Yearly\' Graph \(1 Day' => 'ͼ(1', 'Incoming Traffic in (\S+) per Second' => 'ÿ(λ$1)', 'Outgoing Traffic in (\S+) per Second' => 'ÿ(λ$1)', 'at which time (.*) had been up for(.*)' => 'ʱ $1Ѿ(UPTIME): $2', '([kMG]?)([bB])/s' => '$1$2/s', '([kMG]?)([bB])/min' => '$1$2/m', '([kMG]?)([bB])/h' => '$1$2/h', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => '', 'Out' => '', 'Percentage' => 'ٷֱ', 'Ported to OpenVMS Alpha by' => 'OpenVMSĶ˿', 'Ported to WindowsNT by' => 'WindowsNTĶ˿', 'and' => '', '^GREEN' => 'ɫ', 'BLUE' => 'ɫ', 'DARK GREEN' => '', 'MAGENTA' => 'ɫ', 'AMBER' => 'ɫ' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => '', 'Sun' => '', 'Monday' => 'һ', 'Mon' => 'һ@', 'Tuesday' => 'ܶ', 'Tue' => 'ܶG', 'Wednesday' => '', 'Wed' => 'T', 'Thursday' => '', 'Thu' => 'ĥ|', 'Friday' => '', 'Fri' => '', 'Saturday' => '', 'Sat' => '' ); %month = ( 'January' => '1', 'February' => '2', 'March' => '3', 'Jan' => '1', 'Feb' => '2', 'Mar' => '3', 'April' => '4', 'May' => '5', 'June' => '6', 'Apr' => '4', 'May' => '5', 'Jun' => '6', 'July' => '7', 'August' => '8', 'September' => '9', 'Jul' => '7', 'Aug' => '8', 'Sep' => '9', 'October' => '10', 'November' => '11', 'December' => '12', 'Oct' => '10', 'Nov' => '11', 'Dec' => '12' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { @quux=split(/at/,$foo[3]); if($foo[3]=~(/(.*)at(.*)/)) { $foo[3]=$quux[0]; $foo[4]=$quux[1]; }; return "$foo[3] $month{$foo[2]} $foo[1], $wday{$foo[0]}, $foo[4]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Chinese gb2312 Code sub gb2312 { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'gb2312', 'Maximal 5 Minute Incoming Traffic' => '5', 'Maximal 5 Minute Outgoing Traffic' => '5', 'the device' => 'װ', 'The statistics were last updated(.*)' => 'ϴͳƸʱ: $1', ' Average\)' => ' ƽ)', 'Average' => 'ƽ', 'Max' => '', 'Current' => 'Ŀǰ', 'version' => '汾', '`Daily\' Graph \((.*) Minute' => 'ÿ ͼ ($1 ', '`Weekly\' Graph \(30 Minute' => 'ÿ ͼ (30 ' , '`Monthly\' Graph \(2 Hour' => 'ÿ ͼ (2 Сʱ', '`Yearly\' Graph \(1 Day' => 'ÿ ͼ (1 ', 'Incoming Traffic in (\S+) per Second' => 'ÿ (λ $1)', 'Outgoing Traffic in (\S+) per Second' => 'ÿ (λ $1)', 'at which time (.*) had been up for(.*)' => '豸 $1ʱ(UPTIME): $2', '([kMG]?)([bB])/s' => '\$1\$2/', '([kMG]?)([bB])/min' => '\$1\$2/', '([kMG]?)([bB])/h' => '$1$2/ʱ', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => '', 'Out' => '', 'Percentage' => 'ٷֱ', 'Ported to OpenVMS Alpha by' => 'ֲ OpenVM Alpha ', 'Ported to WindowsNT by' => 'ֲ WindowsNT ', 'and' => '', '^GREEN' => 'ɫ', 'BLUE' => 'ɫ', 'DARK GREEN' => 'īɫ', 'MAGENTA' => 'ɫ', 'AMBER' => 'ɫ' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => '', 'Sun' => '', 'Monday' => 'һ', 'Mon' => 'һ', 'Tuesday' => 'ڶ', 'Tue' => '', 'Wednesday' => '', 'Wed' => '', 'Thursday' => '', 'Thu' => '', 'Friday' => '', 'Fri' => '', 'Saturday' => '', 'Sat' => '' ); %month = ( 'January' => 'һ', 'February' => '', 'March' => '', 'Jan' => 'һ', 'Feb' => '', 'Mar' => '', 'April' => '', 'May' => '', 'June' => '', 'Apr' => '', 'May' => '', 'Jun' => '', 'July' => '', 'August' => '', 'September' => '', 'Jul' => '', 'Aug' => '', 'Sep' => '', 'October' => 'ʮ', 'November' => 'ʮһ', 'December' => 'ʮ', 'Oct' => 'ʮ', 'Nov' => 'ʮһ', 'Dec' => 'ʮ' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { @quux=split(/at/,$foo[3]); if($foo[3]=~(/(.*)at(.*)/)) { $foo[3]=$quux[0]; $foo[4]=$quux[1]; }; return "$foo[3] $month{$foo[2]} $foo[1] , $wday{$foo[0]}, $foo[4]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # German sub german { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Maximaler hereinkommender Traffic in 5 Minuten', 'Maximal 5 Minute Outgoing Traffic' => 'Maximaler hinausgehender Traffic in 5 Minuten', 'the device' => 'das Gerät', 'The statistics were last updated(.*)' => 'Die Statistiken wurden am $1 zuletzt aktualisiert', ' Average\)' => '', 'Average' => 'Mittel', 'Max' => 'Maximal', 'Current' => 'Aktuell', 'version' => 'Version', '`Daily\' Graph \((.*) Minute' => 'Tagesübersicht (Skalierung $1 Minute(n)', '`Weekly\' Graph \(30 Minute' => 'Wochenübersicht (Skalierung 30 Minuten', '`Monthly\' Graph \(2 Hour' => 'Monatsübersicht (Skalierung 2 Stunden', '`Yearly\' Graph \(1 Day' => 'Jahresübersicht (Skalierung 1 Tag', 'Incoming Traffic in (\S+) per Second' => 'Hereinkommender Traffic in $1 pro Sekunde', 'Outgoing Traffic in (\S+) per Second' => 'Hinausgehender Traffic in $1 pro Sekunde', 'Incoming Traffic in (\S+) per Minute' => 'Hereinkommender Traffic in $1 pro Minute', 'Outgoing Traffic in (\S+) per Minute' => 'Hinausgehender Traffic in $1 pro Minute', 'Incoming Traffic in (\S+) per Hour' => 'Hereinkommender Traffic in $1 pro Stunde', 'Outgoing Traffic in (\S+) per Hour' => 'Hinausgehender Traffic in $1 pro Stunde', 'at which time (.*) had been up for(.*)' => 'zu diesem Zeitpunkt lief $1 seit $2', '(\S+) per minute' => '$1 pro Minute', '(\S+) per hour' => '$1 pro Stunde', '(.+)/s$' => '$1/s', # '(.+)/min' => '$1/min', '(.+)/h$' => '$1/std', #'([kMG]?)([bB])/s' => '$1$2/s', #'([kMG]?)([bB])/min' => '$1$2/min', #'([kMG]?)([bB])/h' => '$1$2/std', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Herein', 'Out' => 'Hinaus', 'Percentage' => 'Prozent', 'Ported to OpenVMS Alpha by' => 'Portierung nach OpenVMS von', 'Ported to WindowsNT by' => 'Portierung nach WindowsNT von', 'and' => 'und', '^GREEN' => 'GRÜN', 'BLUE' => 'BLAU', 'DARK GREEN' => 'DUNKELGRÜN', # 'MAGENTA' => 'ROSA', # 'AMBER' => 'AMBER', ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Sonntag', 'Sun' => 'So', 'Monday' => 'Montag', 'Mon' => 'Mo', 'Tuesday' => 'Dienstag', 'Tue' => 'Di', 'Wednesday' => 'Mittwoch', 'Wed' => 'Mi', 'Thursday' => 'Donnerstag', 'Thu' => 'Do', 'Friday' => 'Freitag', 'Fri' => 'Fr', 'Saturday' => 'Samstag', 'Sat' => 'Sa' ); %month = ( 'January' => 'Januar', 'February' => 'Februar' , 'March' => 'März', 'Jan' => 'Jan', 'Feb' => 'Feb', 'Mar' => 'Mär', 'April' => 'April', 'May' => 'Mai', 'June' => 'Juni', 'Apr' => 'Apr', 'May' => 'Mai', 'Jun' => 'Jun', 'July' => 'Juli', 'August' => 'August', 'September' => 'September', 'Jul' => 'Jul', 'Aug' => 'Aug', 'Sep' => 'Sep', 'October' => 'Oktober', 'November' => 'November', 'December' => 'Dezember', 'Oct' => 'Okt', 'Nov' => 'Nov', 'Dec' => 'Dez' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." um ".$quux[1]; }; return "$wday{$foo[0]}, den $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Greek sub greek { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'iso-8859-7', 'Maximal 5 Minute Incoming Traffic' => ' 5 ', 'Maximal 5 Minute Outgoing Traffic' => ' 5 ', 'the device' => ' ', 'The statistics were last updated(.*)' => ' ()/ $1', ' Average\)' => ' )', 'Average' => ' ', 'Max' => '', 'Current' => '', 'version' => '', '`Daily\' Graph \((.*) Minute' => ' ( $1 :', '`Weekly\' Graph \(30 Minute' => ' ( 30 :' , '`Monthly\' Graph \(2 Hour' => ' ( 2 :', '`Yearly\' Graph \(1 Day' => ' ( 1 :', 'Incoming Traffic in (\S+) per Second' => ' $1 ', 'Outgoing Traffic in (\S+) per Second' => ' $1 ', 'at which time (.*) had been up for(.*)' => ' $1 $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/t', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => '', 'Out' => '', 'Percentage' => '', 'Ported to OpenVMS Alpha by' => ' OpenVMS Alpha ', 'Ported to WindowsNT by' => ' WindowsNT ', 'and' => '', '^GREEN' => '', 'BLUE' => '', 'DARK GREEN' => ' ', 'MAGENTA' => '', 'AMBER' => '' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => '', 'Sun' => '', 'Monday' => '', 'Mon' => '', 'Tuesday' => '', 'Tue' => '', 'Wednesday' => '', 'Wed' => '', 'Thursday' => '', 'Thu' => '', 'Friday' => '', 'Fri' => '', 'Saturday' => '', 'Sat' => '' ); %month = ( 'January' => '', 'February' => '' , 'March' => '', 'Jan' => '', 'Feb' => '', 'Mar' => '', 'April' => '', 'May' => '', 'June' => '', 'Apr' => '', 'May' => '', 'Jun' => '', 'July' => '', 'August' => '', 'September' => '', 'Jul' => '', 'Aug' => '', 'Sep' => '', 'October' => '', 'November' => '', 'December' => '', 'Oct' => '', 'Nov' => '', 'Dec' => '' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." à $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Hungarian sub hungarian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-2', 'Maximal 5 Minute Incoming Traffic' => 'Maximális bejövõ forgalom 5 perc alatt', 'Maximal 5 Minute Outgoing Traffic' => 'Maximális kimenõ forgalom 5 perc alatt', 'the device' => 'az eszköz', 'The statistics were last updated(.*)' => 'A statisztika utolsó frissítése:$1', ' Average\)' => ' átlag)', 'Average' => 'Átlagos', 'Max' => 'Maximum', 'Current' => 'Pillanatnyi', 'version' => 'verzió', '`Daily\' Graph \((.*) Minute' => '`Napi\' grafikon ($1 perces', '`Weekly\' Graph \(30 Minute' => '`Heti\' grafikon (30 perces' , '`Monthly\' Graph \(2 Hour' => '`Havi\' grafikon (2 órás', '`Yearly\' Graph \(1 Day' => '`Éves\' grafikon (1 napos', 'Incoming Traffic in (\S+) per Second' => 'Bejövõ forgalom $1 per másodpercben', 'Outgoing Traffic in (\S+) per Second' => 'Kimenõ forgalom $1 per másodpercben', 'at which time (.*) had been up for(.*)' => 'amikor a $1 üzemideje $2 volt.', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/t', 'Bits' => 'Bit', 'Bytes' => 'Byte', 'In' => 'be', 'Out' => 'ki', 'Percentage' => 'százale´k', 'Ported to OpenVMS Alpha by' => 'OpenVMS-re portolta', 'Ported to WindowsNT by' => 'WindowsNT-re portolta', 'and' => 'és', '^GREEN' => 'ZÖLD', 'BLUE' => 'KÉK', 'DARK GREEN' => 'SÖTÉT ZÖLD', 'MAGENTA' => 'BÍBOR', 'AMBER' => 'SÁRGA' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'vasárnap', 'Sun' => 'vas', 'Monday' => 'hétfõ', 'Mon' => 'hét', 'Tuesday' => 'kedd', 'Tue' => 'kedd', 'Wednesday' => 'szerda', 'Wed' => 'sze', 'Thursday' => 'csütörtök','Thu' => 'csüt', 'Friday' => 'péntek', 'Fri' => 'pén', 'Saturday' => 'szombat', 'Sat' => 'szo' ); %month = ( 'January' => 'január', 'February' => 'február' , 'March' => 'március', 'Jan' => 'jan', 'Feb' => 'feb', 'Mar' => 'marc', 'April' => 'április', 'May' => 'május', 'June' => 'június', 'Apr' => 'apr', 'May' => 'maj', 'Jun' => 'jun', 'July' => 'július', 'August' => 'augusztus', 'September' => 'szeptember', 'Jul' => 'jul', 'Aug' => 'aug', 'Sep' => 'szept', 'October' => 'október', 'November' => 'november', 'December' => 'december', 'Oct' => 'okt', 'Nov' => 'nov', 'Dec' => 'dec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." kl.".$quux[1]; }; return "$quux[0]. $month{$foo[2]} $foo[1]., $wday{$foo[0]} $quux[1]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Icelandic sub icelandic { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Hámarks 5 mínútna umferð inn', 'Maximal 5 Minute Outgoing Traffic' => 'Hámarks 5 mínútna umferð út', 'the device' => 'tkið', 'The statistics were last updated(.*)' => 'Gögnin voru síðast uppfærð$1', ' Average\)' => ' Meðaltal)', 'Average' => 'Meðaltal', 'Max' => 'Hámark', 'Current' => 'Nú', 'version' => 'útgáfa', '`Daily\' Graph \((.*) Minute' => '`Dagleg\' staða ($1 mínútur', '`Weekly\' Graph \(30 Minute' => '`Vikuleg\' staða (30 mínútur', '`Monthly\' Graph \(2 Hour' => '`Mánaðarleg\' staða (2 klst.', '`Yearly\' Graph \(1 Day' => '`&Aarleg\' staða (1 dags', 'Incoming Traffic in (\S+) per Second' => 'Umferð inn í $1 á sekúndu', 'Outgoing Traffic in (\S+) per Second' => 'Umferð út í $1 á sekúndu', 'at which time (.*) had been up for(.*)' => 'þegar $1 hafði verið uppi í$2', # '([kMG]?)([bB])/s' => '\$1\$2/sek', # '([kMG]?)([bB])/min' => '\$1\$2/mín', '([kMG]?)([bB])/h' => '$1$2/klst', # 'Bits' => 'Bitar', # 'Bytes' => 'Bæti' 'In' => 'Inn', 'Out' => 'Út', 'Percentage' => 'Prósent', 'Ported to OpenVMS Alpha by' => 'Staðfært á OpenVMS af', 'Ported to WindowsNT by' => 'Staðfært á WindowsNT af', 'and' => 'og', '^GREEN' => 'GRÆNt', 'BLUE' => 'BLÁTT', 'DARK GREEN' => 'DÖKK GRÆNN', 'MAGENTA' => 'BLÁRAUÐUR', 'AMBER' => 'GULBRÚNN' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Sunnudagur', 'Sun' => 'Sun', 'Monday' => 'Mánudagur', 'Mon' => 'Mán', 'Tuesday' => 'Þriðjudagur', 'Tue' => 'Þri', 'Wednesday' => 'Miðvikudagur', 'Wed' => 'Mið', 'Thursday' => 'Fimmtudagur', 'Thu' => 'Fim', 'Friday' => 'Föstudagur', 'Fri' => 'Fös', 'Saturday' => 'Laugardagur', 'Sat' => 'Lau' ); %month = ( 'January' => 'Janúar', 'February' => 'Febrúar' , 'March' => 'Mars', 'Jan' => 'Jan', 'Feb' => 'Feb', 'Mar' => 'Mar', 'April' => 'Apríl', 'May' => 'Maí', 'June' => 'Júní', 'Apr' => 'Apr', 'May' => 'Maí', 'Jun' => 'Jún', 'July' => 'Júlí', 'August' => 'Ágúst', 'September' => 'September', 'Jul' => 'Júl', 'Aug' => 'Ágú', 'Sep' => 'Sep', 'October' => 'Október', 'November' => 'Nóvember', 'December' => 'Desember', 'Oct' => 'Okt', 'Nov' => 'Nóv', 'Dec' => 'Des' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." kl.".$quux[1]; }; return "$wday{$foo[0]} den $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Malaysian/Indonesian/Malay sub indonesia { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Trafik Masuk Maksimum dalam 5 Menit', 'Maximal 5 Minute Outgoing Traffic' => 'Trafik Keluar Maksimum dalam 5 Menit', 'the device' => 'device', 'The statistics were last updated(.*)' => 'Statistik ini terakhir kali diupdate pada $1', ' Average\)' => ')', 'Average' => 'Rata-rata', 'Max' => 'Maksimum', 'Current' => 'Sekarang', 'version' => 'versi', '`Daily\' Graph \((.*) Minute' => 'Grafik Harian (Rata-rata per $1 menit', '`Weekly\' Graph \(30 Minute' => 'Grafik Mingguan (Rata-rata per 30 menit', '`Monthly\' Graph \(2 Hour' => 'Grafik Bulanan (Rata-rata per 2 jam', '`Yearly\' Graph \(1 Day' => 'Grafik Tahunan (Rata-rata per hari', 'Incoming Traffic in (\S+) per Second' => 'Trafik Masuk $1 per detik', 'Outgoing Traffic in (\S+) per Second' => 'Trafik Keluar $1 per detik', 'at which time (.*) had been up for(.*)' => 'Pada saat $1 telah aktif selama $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/j', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Masuk', 'Out' => 'Keluar', 'Percentage' => 'Persentase', 'Ported to OpenVMS Alpha by' => 'Porting ke OpenVMS Alpha oleh', 'Ported to WindowsNT by' => 'Porting ke WindowsNT oleh', 'and' => 'dan', '^GREEN' => 'HIJAU', 'BLUE' => 'BIRU', 'DARK GREEN' => 'HIJAU GELAP', 'MAGENTA' => 'MAGENTA', 'AMBER' => 'AMBAR' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Ahad', 'Sun' => 'Aha', 'Monday' => 'Senin', 'Mon' => 'Sen', 'Tuesday' => 'Selasa', 'Tue' => 'Sel', 'Wednesday' => 'Rabu', 'Wed' => 'Rab', 'Thursday' => 'Kamis', 'Thu' => 'Kam', 'Friday' => 'Jumat', 'Fri' => 'Jum', 'Saturday' => 'Sabtu', 'Sat' => 'Sab' ); %month = ( 'January' => 'Januari', 'February' => 'Februari' , 'March' => 'Maret', 'Jan' => 'Jan', 'Feb' => 'Feb', 'Mar' => 'Mar', 'April' => 'April', 'May' => 'Mei', 'June' => 'Juni', 'Apr' => 'Apr', 'May' => 'Mei', 'Jun' => 'Jun', 'July' => 'Juli', 'August' => 'Agustus', 'September' => 'September', 'Jul' => 'Jul', 'Aug' => 'Ags', 'Sep' => 'Sep', 'October' => 'Oktober', 'November' => 'November', 'December' => 'Desember', 'Oct' => 'Okt', 'Nov' => 'Nov', 'Dec' => 'Des' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." pada ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # iso2022jp sub iso2022jp { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( '^iso-8859-1' => 'iso-2022-jp', '^Maximal 5 Minute Incoming Traffic' => '\e\\$B:GBg\e(B5\e\\$BJ, '\e\\$B:GBg\e(B5\e\\$BJ,Aw?.NL\e(B', '^the device' => '\e\\$B%G%P%\\$%9\e(B', '^The statistics were last updated (.*)' => '\e\\$B99?7F|;~\e(B $1', '^Average\)' => '\e\\$BJ?6Q\e(B)', '^Average$' => '\e\\$BJ?6Q\e(B', '^Max$' => '\e\\$B:GBg\e(B', '^Current' => '\e\\$B:G?7\e(B', '^`Daily\' Graph \((.*) Minute' => '\e\\$BF|%0%i%U\e(B($1\e\\$BJ,4V\e(B', '^`Weekly\' Graph \(30 Minute' => '\e\\$B=5%0%i%U\e(B(30\e\\$BJ,4V\e(B', '^`Monthly\' Graph \(2 Hour' => '\e\\$B7n%0%i%U\e(B(2\e\\$B;~4V\e(B', '^`Yearly\' Graph \(1 Day' => '\e\\$BG/%0%i%U\e(B(1\e\\$BF|\e(B', '^Incoming Traffic in (\S+) per Second' => '\e\\$BKhIC\\$N '\e\\$BKhJ,\\$N '\e\\$BKh;~\\$N '\e\\$BKhIC\\$NAw?.\e(B$1\e\\$B?t\e(B', '^Outgoing Traffic in (\S+) per Minute' => '\e\\$BKhJ,\\$NAw?.\e(B$1\e\\$B?t\e(B', '^Outgoing Traffic in (\S+) per Hour' => '\e\\$BKh;~\\$NAw?.\e(B$1\e\\$B?t\e(B', '^at which time (.*) had been up for (.*)' => '$1\e\\$B\\$N2TF/;~4V\e(B $2', '^Average max 5 min values for `Daily\' Graph \((.*) Minute interval\):' => '\e\\$BF|%0%i%U\\$G\\$N:GBg\e(B5\e\\$BJ,CM\\$NJ?6Q\e(B($1\e\\$BJ,4V3V\e(B):', '^Average max 5 min values for `Weekly\' Graph \(30 Minute interval\):' => '\e\\$B=5%0%i%U\\$G\\$N:GBg\e(B5\e\\$BJ,CM\\$NJ?6Q\e(B(30\e\\$BJ,4V3V\e(B):', '^Average max 5 min values for `Monthly\' Graph \(2 Hour interval\):' => '\e\\$B7n%0%i%U\\$G\\$N:GBg\e(B5\e\\$BJ,CM\\$NJ?6Q\e(B(2\e\\$B;~4V4V3V\e(B):', '^Average max 5 min values for `Yearly\' Graph \(1 Day interval\):' => '\e\\$BG/%0%i%U\\$G\\$N:GBg\e(B5\e\\$BJ,CM\\$NJ?6Q\e(B(1\e\\$BF|4V3V\e(B):', #'^([kMG]?)([bB])/s' => '$1$2/\e\\$BIC\e(B', #'^([kMG]?)([bB])/min' => '$1$2/\e\\$BJ,\e(B', #'^([kMG]?)([bB])/h' => '$1$2/\e\\$B;~\e(B', '^Bits$' => '\e\\$B%S%C%H\e(B', '^Bytes$' => '\e\\$B%P%\\$%H\e(B', '^In$' => '\e\\$B '\e\\$BAw?.\e(B', '^Percentage' => '\e\\$BHfN(\e(B', '^Ported to OpenVMS Alpha by' => 'OpenVMS Alpha\e\\$B\\$X\\$N0\\\?"\e(B', '^Ported to WindowsNT by' => 'WindowsNT\e\\$B\\$X\\$N0\\\?"\e(B', #'^and' => 'and', '^GREEN' => '\e\\$BNP\e(B', '^BLUE' => '\e\\$B\\@D\e(B', '^DARK GREEN' => '\e\\$B? '\e\\$B%^%<%s%?\e(B', '^AMBER' => '\e\\$B`h`a\e(B' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => "(\e\$BF|\e(B)", 'Monday' => "(\e\$B7n\e(B)", 'Tuesday' => "(\e\$B2P\e(B)", 'Wednesday' => "(\e\$B?e\e(B)", 'Thursday' => "(\e\$BLZ\e(B)", 'Friday' => "(\e\$B6b\e(B)", 'Saturday' => "(\e\$BEZ\e(B)", ); %month = ( 'January' => "1\e\$B7n\e(B", 'February' => "2\e\$B7n\e(B", 'March' => "3\e\$B7n\e(B", 'April' => "4\e\$B7n\e(B", 'May' => "5\e\$B7n\e(B", 'June' => "6\e\$B7n\e(B", 'July' => "7\e\$B7n\e(B", 'August' => "8\e\$B7n\e(B", 'September' => "9\e\$B7n\e(B", 'October' => "10\e\$B7n\e(B", 'November' => "11\e\$B7n\e(B", 'December' => "12\e\$B7n\e(B", ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)\s+(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~/at/) { @quux=split(/\s+at\s+/,$foo[3]); } else { @quux=split(/ /,$foo[3],2); }; return "$quux[0]\e\$BG/\e(B$month{$foo[2]}$foo[1]\e\$BF|\e(B$wday{$foo[0]} $quux[1]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Italian sub italian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Traffico massimo in entrata su 5 minuti', 'Maximal 5 Minute Outgoing Traffic' => 'Traffico massimo in uscita su 5 minuti', 'the device' => 'Il dispositivo', 'The statistics were last updated(.*)' => 'Le statistiche l\' ultima volta sono state aggiornate $1', ' Average\)' => ' Media)', 'Average' => 'Media', 'Max' => 'Max', 'Current' => 'Attuale', 'version' => 'versione', '`Daily\' Graph \((.*) Minute' => 'Grafico giornaliero (su $1 minuti:', '`Weekly\' Graph \(30 Minute' => 'Grafico settimanale (su 30 minuti:' , '`Monthly\' Graph \(2 Hour' => 'Grafico mensile (su 2 ore:', '`Yearly\' Graph \(1 Day' => 'Grafico annuale (su 1 giorno:', 'Incoming Traffic in (\S+) per Second' => 'Traffico in ingresso in $1 per Secondo', 'Outgoing Traffic in (\S+) per Second' => 'Traffico in uscita in $1 per Secondo', 'Incoming Traffic in (\S+) per Minute' => 'Traffico in ingresso in $1 per Minuto', 'Outgoing Traffic in (\S+) per Minute' => 'Traffico in uscita $1 per Minuto', 'Incoming Traffic in (\S+) per Hour' => 'Traffico in ingresso $1 per Ora', 'Outgoing Traffic in (\S+) per Hour' => 'Traffico in uscita $1 per Ora', 'at which time (.*) had been up for(.*)' => '$1 é attivo da $2', '(\S+) per minute' => '$1 per Minuto', '(\S+) per hour' => '$1 per Ora', '(.+)/s$' => '$1/s', # '(.+)/min' => '$1/min', '(.+)/h$' => '$1/ora', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', # '([kMG]?)([bB])/h' => '$1$2/t', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Ingresso', 'Out' => 'Uscita', 'Percentage' => 'Percentuale', 'Ported to OpenVMS Alpha by' => 'Ported su OpenVMS Alpha da', 'Ported to WindowsNT by' => 'Ported su WindowsNT da', 'and' => 'e', '^GREEN' => 'VERDE', 'BLUE' => 'BLU', 'DARK GREEN' => 'VERDE SCURO', #'MAGENTA' => 'MAGENTA', #'AMBER' => 'AMBRA' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Domenica', 'Sun' => 'Dom', 'Monday' => 'Lunedi', 'Mon' => 'Lun', 'Tuesday' => 'Martedi', 'Tue' => 'Mar', 'Wednesday' => 'Mercoledi', 'Wed' => 'Mer', 'Thursday' => 'Giovedi', 'Thu' => 'Gio', 'Friday' => 'Venerdi', 'Fri' => 'Ven', 'Saturday' => 'Sabato', 'Sat' => 'Sab' ); %month = ( 'January' => 'Gennaio', 'February' => 'Febbraio' , 'March' => 'Marzo', 'Jan' => 'Gen', 'Feb' => 'Feb', 'Mar' => 'Mar', 'April' => 'Aprile', 'May' => 'Maggio', 'June' => 'Giugno', 'Apr' => 'Apr', 'May' => 'Mag', 'Jun' => 'Giu', 'July' => 'Luglio', 'August' => 'Agosto', 'September' => 'Settembre', 'Jul' => 'Lug', 'Aug' => 'Ago', 'Sep' => 'Set', 'October' => 'Ottobre', 'November' => 'Novembre', 'December' => 'Dicembre', 'Oct' => 'Ott', 'Nov' => 'Nov', 'Dec' => 'Dic' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." alle ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." à $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Korean sub korean { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'euc-kr', 'Maximal 5 Minute Incoming Traffic' => '5а ִ ', 'Maximal 5 Minute Outgoing Traffic' => '5а ִ ۽', 'the device' => 'ġ', 'The statistics were last updated(.*)' => ' Ͻ: $1', ' Average\)' => ' հ )', 'Average' => '', 'Max' => 'ִ', 'Current' => '', 'version' => '', '`Daily\' Graph \((.*) Minute' => 'ϰ ׷ ($1 ', '`Weekly\' Graph \(30 Minute' => 'ְ ׷ (30 ' , '`Monthly\' Graph \(2 Hour' => ' ׷ (2 ð ', '`Yearly\' Graph \(1 Day' => ' ׷ (1 ', 'Incoming Traffic in (\S+) per Second' => 'ʴ ŵ Ʈ ($1)', 'Outgoing Traffic in (\S+) per Second' => 'ʴ ۽ŵ Ʈ ($1)', 'at which time (.*) had been up for(.*)' => '$1 ð: $2', '([kMG]?)([bB])/s' => '$1$2/', '([kMG]?)([bB])/min' => '$1$2/', '([kMG]?)([bB])/h' => '$1$2/', 'Bits' => 'Ʈ', 'Bytes' => 'Ʈ', 'In' => '', 'Out' => '۽', 'Percentage' => 'ۼƮ', 'Ported to OpenVMS Alpha by' => 'OpenVMS Alpha ', 'Ported to WindowsNT by' => 'WindowsNT ', 'and' => '', '^GREEN' => '', 'BLUE' => 'û', 'DARK GREEN' => 'ѳ', 'MAGENTA' => 'ȫ', 'AMBER' => 'Ȳ' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Ͽ', 'Sun' => '', 'Monday' => '', 'Mon' => '', 'Tuesday' => 'ȭ', 'Tue' => 'ȭ', 'Wednesday' => '', 'Wed' => '', 'Thursday' => '', 'Thu' => '', 'Friday' => 'ݿ', 'Fri' => '', 'Saturday' => '', 'Sat' => '' ); %month = ( 'January' => '1', 'February' => '2' , 'March' => '3', 'Jan' => '1', 'Feb' => '2', 'Mar' => '3', 'April' => '4', 'May' => '5', 'June' => '6', 'Apr' => '4', 'May' => '5', 'Jun' => '6', 'July' => '7', 'August' => '8', 'September' => '9', 'Jul' => '7', 'Aug' => '8', 'Sep' => '9', 'October' => '10', 'November' => '11', 'December' => '12', 'Oct' => '10', 'Nov' => '11', 'Dec' => '12' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); # $foo[3]=$quux[0]." kl.".$quux[1]; $foo[3]=$quux[0]; $foo[4]=$quux[1]; }; return $foo[3]." $month{$foo[2]} $foo[1] $wday{$foo[0]} $foo[4]"; # return "$wday{$foo[0]} den $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Lithuanian sub lithuanian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'windows-1257', 'Maximal 5 Minute Incoming Traffic' => 'Maksimalus 5 minui einantis srautas', 'Maximal 5 Minute Outgoing Traffic' => 'Maksimalus 5 minui ieinantis srautas', 'the device' => 'renginys', 'The statistics were last updated(.*)' => 'Statistika atnaujinta$1', ' Average\)' => ' vidurkis)', 'Average' => 'vid', 'Max' => 'max', 'Current' => 'dabar', 'version' => 'versija', '`Daily\' Graph \((.*) Minute' => '\'dienos\' grafikas ($1 min.', '`Weekly\' Graph \(30 Minute' => '\'savaits\' grafikas (30 min.' , '`Monthly\' Graph \(2 Hour' => '\'mnesio\' grafikas (2 val.', '`Yearly\' Graph \(1 Day' => '\'met\' grafikas (1 d.', 'Incoming Traffic in (\S+) per Second' => 'einantis srautas, $1 per sekund', 'Outgoing Traffic in (\S+) per Second' => 'Ieinantis srautas i $1 per sekund', 'at which time (.*) had been up for(.*)' => '$1 veikia jau $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', # '([kMG]?)([bB])/h' => '$1$2/h', 'Bits' => 'bitai', 'Bytes' => 'baitai', 'In' => '', 'Out' => 'i', 'Percentage' => 'procentai', 'Ported to OpenVMS Alpha by' => 'Perkl OpenVMS Alpha:', 'Ported to WindowsNT by' => 'Perkl WindowsNT:', 'and' => 'ir', '^GREEN' => 'ALIA ', 'BLUE' => 'MLYNA ', 'DARK GREEN' => 'TAMSIAI ALIA ', 'MAGENTA' => 'RAUDONA ', 'AMBER' => 'GINTARIN ' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'sekmadien', 'Sun' => 'Sek', 'Monday' => 'pirmadien', 'Mon' => 'Pir', 'Tuesday' => 'antradien', 'Tue' => 'Ant', 'Wednesday' => 'treiadien', 'Wed' => 'Tre', 'Thursday' => 'ketvirtadien', 'Thu' => 'Ket', 'Friday' => 'penktadien', 'Fri' => 'Pen', 'Saturday' => 'etadien', 'Sat' => 'e' ); %month = ( 'January' => 'sausio', 'February' => 'vasario' , 'March' => 'kovo', 'Jan' => 'Sau', 'Feb' => 'Vas', 'Mar' => 'Kov', 'April' => 'balandio', 'May' => 'gegus', 'June' => 'birelio', 'Apr' => 'Bal', 'May' => 'Geg', 'Jun' => 'Bir', 'July' => 'liepos', 'August' => 'rugpjio', 'September' => 'rugsjo', 'Jul' => 'Lie', 'Aug' => 'Rgp', 'Sep' => 'Rgs', 'October' => 'spalio', 'November' => 'lapkriio', 'December' => 'gruodio', 'Oct' => 'Spa', 'Nov' => 'Lap', 'Dec' => 'Gru' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[1].", ".$quux[0]; }; return "$foo[3] $month{$foo[2]} $foo[1], $wday{$foo[0]}" ; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Macedonian sub macedonian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=windows-1251', 'Maximal 5 Minute Incoming Traffic' => ' 5 ', 'Maximal 5 Minute Outgoing Traffic' => ' 5 ', 'the device' => '', 'The statistics were last updated(.*)' => ' $1', ' Average\)' => ' )', 'Average' => '', 'Max' => '', 'Current' => 'o', 'version' => '', '`Daily\' Graph \((.*) Minute' => '`\' ($1 ', '`Weekly\' Graph \(30 Minute' => '`\' (30 ' , '`Monthly\' Graph \(2 Hour' => '`\' (2 ', '`Yearly\' Graph \(1 Day' => '`\' (1 ', 'Incoming Traffic in (\S+) per Second' => ' - $1 ', 'Outgoing Traffic in (\S+) per Second' => ' - $1 ', 'at which time (.*) had been up for(.*)' => ' $1 : $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/h', # 'Bits' => '', # 'Bytes' => '' 'In' => '', 'Out' => '', 'Percentage' => '', 'Ported to OpenVMS Alpha by' => ' OpenVMS ', 'Ported to WindowsNT by' => ' WindowsNT ', 'and' => '', '^GREEN' => '', 'BLUE' => '', 'DARK GREEN' => ' ', 'MAGENTA' => '', 'AMBER' => '' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => '', 'Sun' => '', 'Monday' => '', 'Mon' => '', 'Tuesday' => '', 'Tue' => '', 'Wednesday' => '', 'Wed' => '', 'Thursday' => '', 'Thu' => '', 'Friday' => '', 'Fri' => '', 'Saturday' => '', 'Sat' => '' ); %month = ( 'January' => '', 'February' => '' , 'March' => '', 'Jan' => '', 'Feb' => '', 'Mar' => '', 'April' => '', 'May' => '', 'June' => '', 'Apr' => '', 'May' => '', 'Jun' => '', 'July' => '', 'August' => '', 'September' => '', 'Jul' => '', 'Aug' => '', 'Sep' => '', 'October' => '', 'November' => '', 'December' => '', 'Oct' => '', 'Nov' => '', 'Dec' => '' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." kl.".$quux[1]; }; return "$wday{$foo[0]} $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; };# Malaysian/Malay sub malay { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Maksimum 5 Minit Trafik Masuk', 'Maximal 5 Minute Outgoing Traffic' => 'Maksimum 5 Minit Trafik Keluar', 'the device' => 'alatan', 'The statistics were last updated(.*)' => 'Statistik ini kali terakhir dikemaskini pada $1', ' Average\)' => ' secara purata)', 'Average' => 'Purata', 'Max' => 'Maksimum', 'Current' => 'Kini', 'version' => 'versi', '`Daily\' Graph \((.*) Minute' => 'Graf `Harian\' ($1 minit :', '`Weekly\' Graph \(30 Minute' => 'Graf `Mingguan\' (30 minit :' , '`Monthly\' Graph \(2 Hour' => 'Graf `Bulanan\' (2 jam :', '`Yearly\' Graph \(1 Day' => 'Graf `Tahunan\' (1 hari :', 'Incoming Traffic in (\S+) per Second' => 'Trafik Masuk $1 per saat', 'Outgoing Traffic in (\S+) per Second' => 'Traffic Keluar $1 per saat', 'at which time (.*) had been up for(.*)' => 'Sehingga waktu $1 ia telah aktif selama $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/j', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Masuk', 'Out' => 'Keluar', 'Percentage' => 'Peratus', 'Ported to OpenVMS Alpha by' => 'Pengubahsuaian ke OpenVMS Alpha oleh', 'Ported to WindowsNT by' => 'Pengubahsuaian ke WindowsNT oleh', 'and' => 'dan', '^GREEN' => 'HIJAU', 'BLUE' => 'BIRU', 'DARK GREEN' => 'HIJAU GELAP', 'MAGENTA' => 'MAGENTA', 'AMBER' => 'AMBAR' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Ahad', 'Sun' => 'Aha', 'Monday' => 'Isnin', 'Mon' => 'Isn', 'Tuesday' => 'Selasa', 'Tue' => 'Sel', 'Wednesday' => 'Rabu', 'Wed' => 'Rab', 'Thursday' => 'Khamis', 'Thu' => 'Kha', 'Friday' => 'Jumaat', 'Fri' => 'Jum', 'Saturday' => 'Sabtu', 'Sat' => 'Sab' ); %month = ( 'January' => 'Januari', 'February' => 'Februari' , 'March' => 'Mac', 'Jan' => 'Jan', 'Feb' => 'Feb', 'Mar' => 'Mac', 'April' => 'April', 'May' => 'Mei', 'June' => 'Jun', 'Apr' => 'Apr', 'May' => 'Mei', 'Jun' => 'Jun', 'July' => 'Julai', 'August' => 'Ogos', 'September' => 'September', 'Jul' => 'Jul', 'Aug' => 'Ogo', 'Sep' => 'Sep', 'October' => 'Oktober', 'November' => 'November', 'December' => 'Disember', 'Oct' => 'Okt', 'Nov' => 'Nov', 'Dec' => 'Dis' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." pada ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Norwegian sub norwegian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Maksimal inngående trafikk i 5 minutter', 'Maximal 5 Minute Outgoing Traffic' => 'Maksimal utgående trafikk i 5 minutter', 'the device' => 'enhetden', 'The statistics were last updated(.*)' => 'Statistikken ble sist oppdatert $1', ' Average\)' => ' gjennomsnitt)', 'Average' => 'Gjennomsnitt', 'Max' => 'Max', 'Current' => 'Nå', 'version' => 'versjon', '`Daily\' Graph \((.*) Minute' => '`Daglig\' graf ($1 minutts', '`Weekly\' Graph \(30 Minute' => '`Ukentlig\' graf (30 minutts' , '`Monthly\' Graph \(2 Hour' => '`Månedlig\' graf (2 times', '`Yearly\' Graph \(1 Day' => '`Årlig\' graf (1 dags', 'Incoming Traffic in (\S+) per Second' => 'Inngående trafikk i $1 per sekund', 'Outgoing Traffic in (\S+) per Second' => 'Utgående trafikk i $1 per sekund', 'at which time (.*) had been up for(.*)' => 'hvor $1 hadde vært oppe i $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/t', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Inn', 'Out' => 'Ut', 'Percentage' => 'Prosent', 'Ported to OpenVMS Alpha by' => 'Port til OpenVMS av', 'Ported to WindowsNT by' => 'Port til WindowsNT av', 'and' => 'og', '^GREEN' => 'GRØNN', 'BLUE' => 'BLÅ', 'DARK GREEN' => 'MØRKEGRØNN', 'MAGENTA' => 'MAGENTA', 'AMBER' => 'GUL' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Søndag', 'Sun' => 'Søn', 'Monday' => 'Mandag', 'Mon' => 'Man', 'Tuesday' => 'Tirsdag', 'Tue' => 'Tir', 'Wednesday' => 'Onsdag', 'Wed' => 'Ons', 'Thursday' => 'Torsdag', 'Thu' => 'Tor', 'Friday' => 'Fredag', 'Fri' => 'Fre', 'Saturday' => 'Lørdag', 'Sat' => 'Lør' ); %month = ( 'January' => 'Januar', 'February' => 'Februar' , 'March' => 'Mars', 'Jan' => 'Jan', 'Feb' => 'Feb', 'Mar' => 'Mar', 'April' => 'April', 'May' => 'Mai', 'June' => 'Juni', 'Apr' => 'Apr', 'May' => 'Mai', 'Jun' => 'Jun', 'July' => 'Juli', 'August' => 'August', 'September' => 'September', 'Jul' => 'Jul', 'Aug' => 'Aug', 'Sep' => 'Sep', 'October' => 'Oktober', 'November' => 'November', 'December' => 'Desember', 'Oct' => 'Okt', 'Nov' => 'Nov', 'Dec' => 'Des' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." kl.".$quux[1]; }; return "$wday{$foo[0]} den $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; sub polish { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'iso-8859-2', 'Maximal 5 Minute Incoming Traffic' => 'Maksymalny ruch przychodzcy w cigu 5 minut', 'Maximal 5 Minute Outgoing Traffic' => 'Maksymalny ruch wychodzcy w cigu 5 minut', 'the device' => 'urzdzenie', 'The statistics were last updated(.*)' => 'Ostatnie uaktualnienie statystyki $1', ' Average\)' => ' rednia)', 'Average' => 'rednio', 'Max' => 'Maksymalnie', 'Current' => 'Aktualnie', 'version' => 'wersja', '`Daily\' Graph \((.*) Minute' => '`Dzienny\' Graf w cigu ($1 Minut/y - ', '`Weekly\' Graph \(30 Minute' => '`Tygodniowy\' Graf w cigu (30 minut - ' , '`Monthly\' Graph \(2 Hour' => '`Miesiczny\' Graf w cigu (2 Godzin - ', '`Yearly\' Graph \(1 Day' => '`Roczny\' Graf w cigu (1 Dnia - ', 'Incoming Traffic in (\S+) per Second' => 'Ruch przychodzcy - $1 na sekund', 'Outgoing Traffic in (\S+) per Second' => 'Ruch wychodzcy - $1 na sekund', 'at which time (.*) had been up for(.*)' => 'gdy $1 by wczony przez $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/g', 'Bits' => 'Bity', 'Bytes' => 'Bajty', 'In' => 'Do', 'Out' => 'Z', 'Percentage' => 'Procent', 'Ported to OpenVMS Alpha by' => 'Port dla OpenVMS Alpha dziki', 'Ported to WindowsNT by' => 'Port dla WindowsNT dziki', 'and' => 'i', '^GREEN' => 'ZIELONY', 'BLUE' => 'NIEBIESKI', 'DARK GREEN' => 'CIEMNO ZIELONY', 'MAGENTA' => 'KARMAZYNOWY', 'AMBER' => 'BURSZTYNOWY' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Niedziela', 'Sun' => 'Nie', 'Monday' => 'Poniedziaek', 'Mon' => 'Pon', 'Tuesday' => 'Wtorek', 'Tue' => 'Wto', 'Wednesday' => 'roda', 'Wed' => 'ro', 'Thursday' => 'Czwartek', 'Thu' => 'Czw', 'Friday' => 'Pitek', 'Fri' => 'Pi', 'Saturday' => 'Sobota', 'Sat' => 'Sob' ); %month = ( 'January' => 'Stycznia', 'February' => 'Lutego', 'March' => 'Marca', 'Jan' => 'Sty', 'Feb' => 'Lut', 'Mar' => 'Mar', 'April' => 'Kwietnia', 'May' => 'Maja', 'June' => 'Czerwca', 'Apr' => 'Kwi', 'May' => 'Maj', 'Jun' => 'Cze', 'July' => 'Lipca', 'August' => 'Sierpnia', 'September' => 'Wrzenia', 'Jul' => 'Lip', 'Aug' => 'Sie', 'Sep' => 'Wrz', 'October' => 'Padziernika', 'November' => 'Listopada', 'December' => 'Grudnia', 'Oct' => 'Pa', 'Nov' => 'Lis', 'Dec' => 'Gru' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." o godzinie".$quux[1]; }; return "$wday{$foo[0]} dzie $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Português sub portuguese { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Tráfego Maximal Recebido em 5 minutos', 'Maximal 5 Minute Outgoing Traffic' => 'Tráfego Maximal Enviado em 5 minutos', 'the device' => 'o dispositivo', 'The statistics were last updated(.*)' => 'As Estatísticas foram actualizadas pela última vez na $1', ' Average\)
' => '', 'Average' => 'Média', 'Max' => 'Max.', 'Current' => 'Actual', 'version' => 'Versão', '`Daily\' Graph \((.*) Minute' => 'Gráfico Diário (em intervalos de $1 Minutos)

', '`Weekly\' Graph \(30 Minute' => 'Gráfico Semanal (em intervalos de 30 Minutos)' , '`Monthly\' Graph \(2 Hour' => 'Gráfico Mensal (em intervalos de 2 horas)', '`Yearly\' Graph \(1 Day' => 'Gráfico Anual (em intervalos de 24 horas)', 'Incoming Traffic in (\S+) per Second' => 'Tráfego recebido em $1/segundo', 'Outgoing Traffic in (\S+) per Second' => 'Tráfego enviado em $1/segundo', 'Incoming Traffic in (\S+) per Minute' => 'Tráfego recebido em $1/minuto', 'Outgoing Traffic in (\S+) per Minute' => 'Tráfego enviado em $1/minuto', 'Incoming Traffic in (\S+) per Hour' => 'Tráfego recebido em $1/hora', 'Outgoing Traffic in (\S+) per Hour' => 'Tráfego recebido em $1/hora', 'at which time (.*) had been up for(.*)' => 'quando o $1, tinha um uptime de $2', '(\S+) per minute' => '$1/minuto', '(\S+) per hour' => '$1/hora', '(.+)/s$' => '$1/s', # '(.+)/min' => '$1/min', '(.+)/h$' => '$1/h', #'([kMG]?)([bB])/s' => '$1$2/s', #'([kMG]?)([bB])/min' => '$1$2/min', #'([kMG]?)([bB])/h' => '$1$2/h', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Rec.', 'Out' => 'Env.', 'Percentage' => 'Perc.', 'Ported to OpenVMS Alpha by' => 'Portado para OpenVMS Alpha por', 'Ported to WindowsNT by' => 'Portado para WindowsNT por', 'and' => 'e', '^GREEN' => 'VERDE', 'BLUE' => 'AZUL', 'DARK GREEN' => 'VERDE ESCURO', # 'MAGENTA' => 'MAGENTA', # 'AMBER' => 'AMBAR', ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Domingo', 'Sun' => 'Dom', 'Monday' => 'Segunda-Feira', 'Mon' => 'Seg', 'Tuesday' => 'Terça-Feira', 'Tue' => 'Ter', 'Wednesday' => 'Quarta-Feira', 'Wed' => 'Qua', 'Thursday' => 'Quinta-Feira', 'Thu' => 'Qui', 'Friday' => 'Sexta-Feira', 'Fri' => 'Sex', 'Saturday' => 'Sábado', 'Sat' => 'Sab' ); %month = ( 'January' => 'Janeiro', 'February' => 'Fevereiro' , 'March' => 'Março', 'Jan' => 'Jan', 'Feb' => 'Fev', 'Mar' => 'Mar', 'April' => 'Abril', 'May' => 'Maio', 'June' => 'Junho', 'Apr' => 'Abr', 'May' => 'Mai', 'Jun' => 'Jun', 'July' => 'Julho', 'August' => 'Agosto', 'September' => 'Setembro', 'Jul' => 'Jul', 'Aug' => 'Ago', 'Sep' => 'Set', 'October' => 'Outubro', 'November' => 'Novembro', 'December' => 'Dezembro', 'Oct' => 'Out', 'Nov' => 'Nov', 'Dec' => 'Dez' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." pelas ".$quux[1]; }; return "$wday{$foo[0]}, $foo[1] de $month{$foo[2]} de $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Romanian sub romanian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-8859-2 %translations = ( 'iso-8859-1' => 'iso-8859-2', 'Maximal 5 Minute Incoming Traffic' => 'Traficul Maxim de intrare pe 5 Minute', 'Maximal 5 Minute Outgoing Traffic' => 'Traficul Maxim de iesire pe 5 Minute', 'the device' => 'echipamentul', 'The statistics were last updated(.*)' => 'Ultima actualizare :$1', ' Average\)' => '', 'Average' => 'Medie', 'Max' => 'Maxim', 'Current' => 'Curent', 'version' => 'versiunea', '`Daily\' Graph \((.*) Minute' => 'Graficul \'Zilnic\' (medie pe $1 minute)', '`Weekly\' Graph \(30 Minute' => 'Graficul \'Sptmnal\' (medie pe 30 de minute)' , '`Monthly\' Graph \(2 Hour' => 'Graficul \'Lunar\' (medie pe 2 ore)', '`Yearly\' Graph \(1 Day' => 'Graficul \'Anual\' (medie pe 1 zi)', 'Incoming Traffic in (\S+) per Second' => 'Traficul de intrare [$1/secund]', 'Outgoing Traffic in (\S+) per Second' => 'Traficul de ieire [$1/secund]', 'at which time (\S+) had been up for (\S+)' => 'cnd $1 funciona de $2', 'at which time (\S+) had been up for (\S+) day, (\S+)' => 'cnd $1 funciona de $2 zi, $3', 'at which time (\S+) had been up for (\S+) days, (\S+)' => 'cnd $1 funciona de $2 zile, $3', #'(.+)/s$' => '$1/s', #'(.+)/min' => '$1/min', '(.+)/h$' => '$1/ora', #'([kMG]?)([bB])/s' => '$1$2/s', #'([kMG]?)([bB])/min' => '$1$2/min', '([kMG]?)([bB])/h' => '$1$2/ora', 'Bits' => 'Bii', 'Bytes' => 'Octei', 'In' => 'int', 'Out' => 'ie', 'Percentage' => 'procent', 'Ported to OpenVMS Alpha by' => 'Translatat sub OpenVMS de', 'Ported to WindowsNT by' => 'Translatat sub WindowsNT de', 'and' => 'i', '^GREEN' => 'VERDE', 'BLUE' => 'ALBASTRU', 'DARK GREEN' => 'VERDE NCHIS', 'MAGENTA' => 'PURPURIU', 'AMBER' => 'GALBEN', ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'duminic', 'Sun' => 'lu', 'Monday' => 'luni', 'Mon' => 'ma', 'Tuesday' => 'mari', 'Tue' => 'mi', 'Wednesday' => 'miercuri', 'Wed' => 'jo', 'Thursday' => 'joi', 'Thu' => 'vi', 'Friday' => 'vineri', 'Fri' => 's', 'Saturday' => 'smbt', 'Sat' => 'du' ); %month = ( 'January' => 'ianuarie', 'February' => 'februarie' , 'March' => 'martie', 'Jan' => 'ian', 'Feb' => 'feb', 'Mar' => 'mar', 'April' => 'aprilie', 'May' => 'mai', 'June' => 'iunie', 'Apr' => 'apr', 'May' => 'mai', 'Jun' => 'iun', 'July' => 'iulie', 'August' => 'august', 'September' => 'septembrie', 'Jul' => 'iul', 'Aug' => 'aug', 'Sep' => 'sep', 'October' => 'octombrie', 'November' => 'noiembrie', 'December' => 'decembrie', 'Oct' => 'oct', 'Nov' => 'noi', 'Dec' => 'dec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].", ora ".$quux[1]; }; return "$wday{$foo[0]}, $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Russian sub russian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'koi8-r', 'Maximal 5 Minute Incoming Traffic' => ' 5 ', 'Maximal 5 Minute Outgoing Traffic' => ' 5 ', 'the device' => '', 'The statistics were last updated(.*)' => ' : $1', ' Average\)' => ')', 'Average' => '', 'Max' => '.', 'Current' => '', 'version' => '', '`Daily\' Graph \((.*) Minute' => ' ( $1 ', '`Weekly\' Graph \(30 Minute' => ' ( 30 ' , '`Monthly\' Graph \(2 Hour' => ' ( 2 ', '`Yearly\' Graph \(1 Day' => ' ( 1 ', 'Incoming Traffic in (\S+) per Second' => ' $1 ', 'Outgoing Traffic in (\S+) per Second' => ' $1 ', 'at which time (.*) had been up for(.*)' => ' $1 $2', #'([kMG]?)([bB])/s' => '$1$1/', #'([kMG]?)([bB])/min' => '$1$2/', '([kMG]?)([bB])/h' => '$1$2/', 'Bits' => '', 'Bytes' => '', 'In' => '', 'Out' => '', 'Percentage' => '', 'Ported to OpenVMS Alpha by' => ' OpenVMS Alpha', 'Ported to WindowsNT by' => ' WindowsNT', 'and' => '', '^GREEN' => '', 'BLUE' => '', 'DARK GREEN' => '', 'MAGENTA' => '', 'AMBER' => '' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => ' ', 'Sun' => '', 'Monday' => ' ', 'Mon' => '', 'Tuesday' => ' ', 'Tue' => '', 'Wednesday' => ' ', 'Wed' => '', 'Thursday' => ' ', 'Thu' => '', 'Friday' => ' ', 'Fri' => '', 'Saturday' => ' ', 'Sat' => '' ); %month = ( 'January' => '', 'February' => '' , 'March' => '', 'Jan' => '', 'Feb' => '', 'Mar' => '', 'April' => '', 'May' => '', 'June' => '', 'Apr' => '', 'May' => '', 'Jun' => '', 'July' => '', 'August' => '', 'September' => '', 'Jul' => '', 'Aug' => '', 'Sep' => '', 'October' => '', 'November' => '', 'December' => '', 'Oct' => '', 'Nov' => '', 'Dec' => '' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].". ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Russian1251 Code sub russian1251 { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'windows-1251', 'Maximal 5 Minute Incoming Traffic' => ' 5 ', 'Maximal 5 Minute Outgoing Traffic' => ' 5 ', 'the device' => '', 'The statistics were last updated(.*)' => ' : $1', ' Average\)' => ')', 'Average' => ' ', 'Max' => '', 'Current' => '', 'version' => '', '`Daily\' Graph \((.*) Minute' => ' ( $1 ', '`Weekly\' Graph \(30 Minute' => ' ( 30 ' , '`Monthly\' Graph \(2 Hour' => ' ( 2 ', '`Yearly\' Graph \(1 Day' => ' ( 1 ', 'Incoming Traffic in (\S+) per Second' => ' $1 ', 'Outgoing Traffic in (\S+) per Second' => ' $1 ', 'at which time (\S+) had been up for (\S+)' => ' $1: $2.', 'at which time (\S+) had been up for (\S+) day, (\S+)' => ' $1: $2 , $3.', 'at which time (\S+) had been up for (\S+) days, (\S+)' => ' $1: $2 , $3.', #'([kMG]?)([bB])/s' => '$1$1/', #'([kMG]?)([bB])/min' => '$1$2/', '([kMG]?)([bB])/h' => '$1$2/', 'Bits' => '', 'Bytes' => '', 'In' => '', 'Out' => '', 'Percentage' => '', 'Ported to OpenVMS Alpha by' => ' OpenVMS Alpha', 'Ported to WindowsNT by' => ' WindowsNT', 'and' => '', '^GREEN' => '', 'BLUE' => '', 'DARK GREEN' => '', 'MAGENTA' => '', 'AMBER' => '' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => ' ', 'Sun' => '', 'Monday' => ' ', 'Mon' => '', 'Tuesday' => ' ', 'Tue' => '', 'Wednesday' => ' ', 'Wed' => '', 'Thursday' => ' ', 'Thu' => '', 'Friday' => ' ', 'Fri' => '', 'Saturday' => ' ', 'Sat' => '' ); %month = ( 'January' => '', 'February' => '' , 'March' => '', 'Jan' => '', 'Feb' => '', 'Mar' => '', 'April' => '', 'May' => '', 'June' => '', 'Apr' => '', 'May' => '', 'Jun' => '', 'July' => '', 'August' => '', 'September' => '', 'Jul' => '', 'Aug' => '', 'Sep' => '', 'October' => '', 'November' => '', 'December' => '', 'Oct' => '', 'Nov' => '', 'Dec' => '' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].". ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Serbian sub serbian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'windows-1250', 'Maximal 5 Minute Incoming Traffic' => 'Najvei 5 minutni ulazni saobraaj', 'Maximal 5 Minute Outgoing Traffic' => 'Najvei 5 minutni izlazni saobraaj', 'the device' => 'uredjaj', 'The statistics were last updated(.*)' => 'Poslednje auriranje podataka:$1', ' Average\)' => ' prosek)', 'Average' => 'Proseni', 'Max' => 'Maksimalni', 'Current' => 'Trenutni', 'version' => 'verzija', '`Daily\' Graph \((.*) Minute' => 'Dnevni graf ($1 minutni ', '`Weekly\' Graph \(30 Minute' => 'Nedeljni graf (30 minutni ' , '`Monthly\' Graph \(2 Hour' => 'Meseni graf (2 sata ', '`Yearly\' Graph \(1 Day' => 'Godinji graf (1 dnevni ', 'Incoming Traffic in (\S+) per Second' => 'Ulazni saobraaj - $1 u sekundi.', 'Outgoing Traffic in (\S+) per Second' => 'Izlazni saobraaj - $1 u sekundi.', 'Incoming Traffic in (\S+) per Minute' => 'Ulazni saobraaj - $1 u minutu', 'Outgoing Traffic in (\S+) per Minute' => 'Izlazni saobraaj - $1 u minutu', 'Incoming Traffic in (\S+) per Hour' => 'Ulazni saobraaj - $1 na sat', 'Outgoing Traffic in (\S+) per Hour' => 'Izlazni saobraaj - $1 na sat', 'at which time (.*) had been up for(.*)' => 'Vreme neprekidnog rada sistema $1 : $2', #'([kMG]?)([bB])/s' => '\$1\$2/s', #'([kMG]?)([bB])/min' => '\$1\$2/min', #'([kMG]?)([bB])/h' => '$1$2/h', 'Bits' => 'Bita', 'Bytes' => 'Bajta', 'In' => 'Ulaz', 'Out' => 'Izlaz', 'Percentage' => 'Procenat', 'Ported to OpenVMS Alpha by' => 'Na OpenVMS portovao', 'Ported to WindowsNT by' => 'Na WindowsNT portovao', 'and' => 'i', '^GREEN' => 'Zeleno', 'BLUE' => 'Plavo', 'DARK GREEN' => 'Tamnozeleno', 'MAGENTA' => 'Ljubiasto', 'AMBER' => 'Narandasto' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Nedelja', 'Sun' => 'Ned', 'Monday' => 'Ponedeljak', 'Mon' => 'Pon', 'Tuesday' => 'Utorak', 'Tue' => 'Uto', 'Wednesday' => 'Sreda', 'Wed' => 'Sre', 'Thursday' => 'etvrtak', 'Thu' => 'et', 'Friday' => 'Petak', 'Fri' => 'Pet', 'Saturday' => 'Subota', 'Sat' => 'Sub' ); %month = ( 'January' => 'januar', 'February' => 'februar', 'March' => 'mart', 'Jan' => 'Jan', 'Feb' => 'Feb', 'Mar' => 'Mar', 'April' => 'april', 'May' => 'maj', 'June' => 'jun', 'Apr' => 'Apr', 'May' => 'Maj', 'Jun' => 'Jun', 'July' => 'jul', 'August' => 'avgust', 'September' => 'septembar', 'Jul' => 'Jul', 'Aug' => 'Avg', 'Sep' => 'Sep', 'October' => 'oktobar','November' => 'novembar','December' => 'decembar', 'Oct' => 'Okt', 'Nov' => 'Nov', 'Dec' => 'Dec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].",".$quux[1]." "; }; return "$wday{$foo[0]} $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; } # # Slovak sub slovak { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'iso-8859-2', 'Maximal 5 Minute Incoming Traffic' => 'Maximlny 5 mintov prichdzajci tok', 'Maximal 5 Minute Outgoing Traffic' => 'Maximlny 5 mintov odchdzajci tok', 'the device' => 'zariadenie', 'The statistics were last updated(.*)' => 'Posledn aktualizcia tatistk:$1', ' Average\)' => ' priemer)', 'Average' => 'Priem.', 'Max' => 'Max.', 'Current' => 'Akt.', 'version' => 'verzia', '`Daily\' Graph \((.*) Minute' => 'Denn graf ($1 mintov', '`Weekly\' Graph \(30 Minute' => 'Tdenn graf (30 mintov' , '`Monthly\' Graph \(2 Hour' => 'Mesan graf (2 hodinov', '`Yearly\' Graph \(1 Day' => 'Ron graf (1 denn', 'Incoming Traffic in (\S+) per Second' => 'Prichdzajci tok v $1 za sekundu.', 'Outgoing Traffic in (\S+) per Second' => 'Odchdzajci tok v $1 za sekundu.', 'at which time (.*) had been up for(.*)' => 'as od poslednho retartu $1 : $2', #'([kMG]?)([bB])/s' => '\$1\$2/s', #'([kMG]?)([bB])/min' => '\$1\$2/min', #'([kMG]?)([bB])/h' => '$1$2/h', 'Bits' => 'bitoch', 'Bytes' => 'bytoch', #' In:' => ' In:', #' Out:' => ' Out:', 'Percentage' => 'Perc.', 'Ported to OpenVMS Alpha by' => 'Na OpenVMS portoval', 'Ported to WindowsNT by' => 'Na WindowsNT portoval', 'and' => 'a', '^GREEN' => 'Zelen', 'BLUE' => 'Modr', 'DARK GREEN' => 'Tmavozelen', 'MAGENTA' => 'Fialov', 'AMBER' => 'lt' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Nedea', 'Sun' => 'Ne', 'Monday' => 'Pondelok', 'Mon' => 'Po', 'Tuesday' => 'Utorok', 'Tue' => 'Ut', 'Wednesday' => 'Streda', 'Wed' => 'St', 'Thursday' => 'tvrtok', 'Thu' => 't', 'Friday' => 'Piatok', 'Fri' => 'Pi', 'Saturday' => 'Sobota', 'Sat' => 'So' ); %month = ( 'January' => 'Janur', 'February' => 'Februr', 'March' => 'Marec', 'Jan' => 'Janur', 'Feb' => 'Februr', 'Mar' => 'Marec', 'April' => 'Aprl', 'May' => 'Mj', 'June' => 'Jn', 'Apr' => 'Aprl', 'May' => 'Mj', 'Jun' => 'Jn', 'July' => 'Jl', 'August' => 'August', 'September' => 'September', 'Jul' => 'Jl', 'Aug' => 'August', 'Sep' => 'September', 'October' => 'Oktber','November' => 'November','December' => 'December', 'Oct' => 'Oktber','Nov' => 'November','Dec' => 'December' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].",".$quux[1]." hod."; }; return "$wday{$foo[0]} $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; } # # Slovenian sub slovenian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'windows-1250', 'Maximal 5 Minute Incoming Traffic' => 'Najvecji petminutni vhodni promet', 'Maximal 5 Minute Outgoing Traffic' => 'Najvecji petminutni izhodni promet', 'the device' => 'naprava', 'The statistics were last updated(.*)' => 'Zadnja posodobitev podatkov:$1', ' Average\)' => ' povprecje)', 'Average' => 'Povprecje', 'Max' => 'Maksimalno', 'Current' => 'Trenutno', 'version' => 'verzija', '`Daily\' Graph \((.*) Minute' => 'Dnevni graf ($1 min.', '`Weekly\' Graph \(30 Minute' => 'Tedenski graf (30 min.' , '`Monthly\' Graph \(2 Hour' => 'Mesecni graf (2 urno', '`Yearly\' Graph \(1 Day' => 'Letni graf (1 dnevno', 'Incoming Traffic in (\S+) per Second' => 'Vhodni promet v $1 na sekundo.', 'Outgoing Traffic in (\S+) per Second' => 'Izhodni promet v $1 na sekundo.', 'at which time (.*) had been up for(.*)' => 'Cas od zadnjega restarta sistema $1 : $2', #'([kMG]?)([bB])/s' => '\$1\$2/s', #'([kMG]?)([bB])/min' => '\$1\$2/min', #'([kMG]?)([bB])/h' => '$1$2/h', 'Bits' => 'bitov', 'Bytes' => 'bytov', 'In' => 'Vhod', 'Out' => 'Izhod', 'Percentage' => 'Proc.', 'Ported to OpenVMS Alpha by' => 'Na OpenVMS portiral', 'Ported to WindowsNT by' => 'Na WindowsNT portiral', 'and' => 'in', '^GREEN' => 'Zeleno', 'BLUE' => 'Modro', 'DARK GREEN' => 'Temnozeleno', 'MAGENTA' => 'Vijolicasto', 'AMBER' => 'Oranzno' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Nedelja', 'Sun' => 'Ne', 'Monday' => 'Ponedeljek', 'Mon' => 'Po', 'Tuesday' => 'Torek', 'Tue' => 'To', 'Wednesday' => 'Sreda', 'Wed' => 'Sr', 'Thursday' => 'Cetrtek', 'Thu' => 'Ce', 'Friday' => 'Petek', 'Fri' => 'Po', 'Saturday' => 'Sobota', 'Sat' => 'So' ); %month = ( 'January' => 'Januar', 'February' => 'Februar', 'March' => 'Marec', 'Jan' => 'Jan', 'Feb' => 'Feb', 'Mar' => 'Mar', 'April' => 'April', 'May' => 'Maj', 'June' => 'Jun', 'Apr' => 'Apr', 'May' => 'Maj', 'Jun' => 'Jun', 'July' => 'Julij', 'August' => 'Avgust', 'September' => 'September', 'Jul' => 'Jul', 'Aug' => 'Avg', 'Sep' => 'Sep', 'October' => 'Oktober','November' => 'November','December' => 'December', 'Oct' => 'Okt','Nov' => 'Nov','Dec' => 'Dec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].",".$quux[1]." "; }; return "$wday{$foo[0]} $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; } # # Spanish sub spanish { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... %translations = ( #'iso-8859-1' => 'iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Tráfico entrante máximo en 5 minutos', 'Maximal 5 Minute Outgoing Traffic' => 'Tráfico saliente máximo en 5 minutos', 'the device' => 'el dispositivo', 'The statistics were last updated(.*)' => 'Estadísticas actualizadas el $1', ' Average\)' => ' Promedio)', 'Average' => 'Promedio', 'Max' => 'Máx', 'Current' => 'Actual', 'version' => 'version', '`Daily\' Graph \((.*) Minute' => 'Gráfico diario ($1 minutos :', '`Weekly\' Graph \(30 Minute' => 'Gráfico semanal (30 minutos :' , '`Monthly\' Graph \(2 Hour' => 'Gráfico mensual (2 horas :', '`Yearly\' Graph \(1 Day' => 'Gráfico anual (1 día :', 'Incoming Traffic in (\S+) per Second' => 'Tráfico entrante en $1 por segundo', 'Outgoing Traffic in (\S+) per Second' => 'Tráfico saliente en $1 por segundo', 'at which time (.*) had been up for(.*)' => '$1 ha estado funcionando durante $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', # '([kMG]?)([bB])/h' => '$1$2/t', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Entrante:', 'Out' => 'Saliente:', 'Percentage' => 'Porcentaje:', 'Ported to OpenVMS Alpha by' => 'Portado a OpenVMS Alpha por', 'Ported to WindowsNT by' => 'Portado a WindowsNT por', 'and' => 'y', '^GREEN' => 'VERDE', 'BLUE' => 'AZUL', 'DARK GREEN' => 'VERDE OSCURO', 'MAGENTA' => 'MAGENTA', 'AMBER' => 'AMBAR' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Domingo', 'Sun' => 'Dom', 'Monday' => 'Lunes', 'Mon' => 'Lun', 'Tuesday' => 'Martes', 'Tue' => 'Mar', 'Wednesday' => 'Miércoles','Wed' => 'Mié', 'Thursday' => 'Jueves', 'Thu' => 'Jue', 'Friday' => 'Viernes', 'Fri' => 'Vie', 'Saturday' => 'Sábado', 'Sat' => 'Sab' ); %month = ( 'January' => 'Enero', 'February' => 'Febrero' , 'March' => 'Marzo', 'Jan' => 'Ene', 'Feb' => 'Feb', 'Mar' => 'Mar', 'April' => 'Abril', 'May' => 'Mayo', 'June' => 'Junio', 'Apr' => 'Abr', 'May' => 'Mai', 'Jun' => 'Jun', 'July' => 'Julio', 'August' => 'Agosto', 'September' => 'Setiembre', 'Jul' => 'Jul', 'Aug' => 'Ago', 'Sep' => 'Set', 'October' => 'Octubre', 'November' => 'Noviembre', 'December' => 'Diciembre', 'Oct' => 'Oct', 'Nov' => 'Nov', 'Dec' => 'Dic' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." a las ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] de $month{$foo[2]} de $foo[3]"; }; return $string; } # Swedish sub swedish { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Maximalt inkommande trafik i 5 minuter', 'Maximal 5 Minute Outgoing Traffic' => 'Maximalt utgående trafik i 5 minuter', 'the device' => 'enheten', 'The statistics were last updated(.*)' => 'Statistiken blev senast uppdaterad$1', ' Average\)' => ')', 'Average' => 'Medel', #'Max' => 'Max', 'Current' => 'Senaste', 'version' => 'version', '`Daily\' Graph \((.*) Minute' => 'Daglig graf (samplingsintervall $1 minut(er)', '`Weekly\' Graph \(30 Minute' => 'Veckovis graf (medelvrde per 30 minuter' , '`Monthly\' Graph \(2 Hour' => 'Månatlig graf (medelvrde per 2 timmar', '`Yearly\' Graph \(1 Day' => 'Årlig graf (medelvrde per dygn', 'Incoming Traffic in (\S+) per Second' => 'Inkommande trafik i $1 per sekund', 'Outgoing Traffic in (\S+) per Second' => 'Utgende trafik i $1 per sekund', 'at which time (.*) had been up for(.*)' => 'd $1 varit igång i$2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/t', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes', #'In' => 'In', 'Out' => 'Ut', 'Percentage' => 'Procent', 'Ported to OpenVMS Alpha by' => 'Portad till OpenVMS av', 'Ported to WindowsNT by' => 'Portad till WindowsNT av', 'and' => 'och', '^GREEN' => 'GRÖN', 'BLUE' => 'BLÅ', 'DARK GREEN' => 'MÖRKGRÖN', 'MAGENTA' => 'MANGENTA', 'AMBER' => 'BRUN', ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'söndag', 'Sun' => 'sön', 'Monday' => 'måndag', 'Mon' => 'mån', 'Tuesday' => 'tisdag', 'Tue' => 'tis', 'Wednesday' => 'onsdag', 'Wed' => 'ons', 'Thursday' => 'torsdag', 'Thu' => 'tor', 'Friday' => 'fredag', 'Fri' => 'fre', 'Saturday' => 'lördag', 'Sat' => 'lör' ); %month = ( 'January' => 'januari', 'February' => 'februari', 'March' => 'mars', 'Jan' => 'jan', 'Feb' => 'feb', 'Mar' => 'mar', 'April' => 'april', 'May' => 'maj', 'June' => 'juni', 'Apr' => 'apr', 'May' => 'maj', 'Jun' => 'jun', 'July' => 'juli', 'August' => 'augusti', 'September' => 'september', 'Jul' => 'jul', 'Aug' => 'aug', 'Sep' => 'sep', 'October' => 'oktober', 'November' => 'november', 'December' => 'december', 'Oct' => 'okt', 'Nov' => 'nov', 'Dec' => 'dec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." kl.".$quux[1]; }; return "$wday{$foo[0]} den $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Turkish sub turkish { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... %translations = ( 'iso-8859-1' => 'iso-8859-9', 'Maximal 5 Minute Incoming Traffic' => '5 dakika iin en yksek giri trafii', 'Maximal 5 Minute Outgoing Traffic' => '5 dakika iin en yksek k trafii', 'the device' => 'aygt', 'The statistics were last updated(.*)' => 'statistiklerin en son gncellenmesi $1', ' Average\)' => ' Ortalama)', 'Average' => 'Ortalama', 'Max' => 'EnYksek;x', 'Current' => 'uAnki', 'version' => 'srm', '`Daily\' Graph \((.*) Minute' => 'Gnlk ($1 dakika :', '`Weekly\' Graph \(30 Minute' => 'Haftalk (30 dakika :' , '`Monthly\' Graph \(2 Hour' => 'Aylk (2 saat :', '`Yearly\' Graph \(1 Day' => 'Yllk (1 gn :', 'Incoming Traffic in (\S+) per Second' => '$1 deki saniyelik giri trafii', 'Outgoing Traffic in (\S+) per Second' => '$1 deki saniyelik k trafii', 'at which time (.*) had been up for(.*)' => '$1 Ne zamandan $2 beri ayakta', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', # '([kMG]?)([bB])/h' => '$1$2/t', # 'Bits' => 'Bit', # 'Bytes' => 'Byte' 'In' => 'Giri', 'Out' => 'k', 'Percentage' => 'Yzge', 'Ported to OpenVMS Alpha by' => 'OpenVMS Alpha ya uyarlayan', 'Ported to WindowsNT by' => 'WindowsNT ye uyarlayan', 'and' => 've', '^GREEN' => 'YEL', 'BLUE' => 'MAV', 'DARK GREEN' => 'KOYU YEL', 'MAGENTA' => 'MACENTA', 'AMBER' => 'AMBER' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Pazar', 'Pzr' => 'Dom', 'Monday' => 'Pazartesi', 'Pzt' => 'Lun', 'Tuesday' => 'Sal', 'Sal' => 'Mar', 'Wednesday' => 'aramba', 'r' => 'Mié', 'Thursday' => 'Perembe', 'Pr' => 'Jue', 'Friday' => 'Cuma', 'Cum' => 'Vie', 'Saturday' => 'Cumartesi', 'Cmr' => 'Sab' ); %month = ( 'January' => 'Ocak', 'February' => 'ubat', 'March' => 'Mart', 'Jan' => 'Ock', 'Feb' => 'ub', 'Mar' => 'Mar', 'April' => 'Nisan', 'May' => 'Mays', 'June' => 'Haziran', 'Apr' => 'Nis', 'May' => 'May', 'Jun' => 'Hzr', 'July' => 'Temmuz', 'August' => 'Agustos', 'September' => 'Eyll', 'Jul' => 'Tem', 'Aug' => 'Agu', 'Sep' => 'Eyl', 'October' => 'Ekim', 'November' => 'Kasm', 'December' => 'Aralk', 'Oct' => 'Ekm', 'Nov' => 'Kas', 'Dec' => 'Ara' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." a las ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] de $month{$foo[2]} de $foo[3]"; }; } # Ukrainian sub ukrainian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'koi8-u', 'Maximal 5 Minute Incoming Traffic' => ' Ȧ Ʀ 5 ', 'Maximal 5 Minute Outgoing Traffic' => ' Ȧ Ʀ 5 ', 'the device' => 'Ҧ', 'The statistics were last updated(.*)' => 'Τ : $1', ' Average\)' => ')', 'Average' => 'Φ', 'Max' => '.', 'Current' => '', 'version' => 'Ӧ', '`Daily\' Graph \((.*) Minute' => ' Ʀ (Τ $1 ', '`Weekly\' Graph \(30 Minute' => ' Ʀ (Τ 30 ' , '`Monthly\' Graph \(2 Hour' => ' Ʀ (Τ 2 ', '`Yearly\' Graph \(1 Day' => ' Ʀ (Τ 1 ', 'Incoming Traffic in (\S+) per Second' => 'Ȧ Ʀ $1 ', 'Outgoing Traffic in (\S+) per Second' => 'Ȧ Ʀ $1 ', 'at which time (.*) had been up for(.*)' => '$1 $2', #'([kMG]?)([bB])/s' => '$1$1/', #'([kMG]?)([bB])/min' => '$1$2/', '([kMG]?)([bB])/h' => '$1$2/', 'Bits' => '¦', 'Bytes' => '', 'In' => '', 'Out' => '', 'Percentage' => '', 'Ported to OpenVMS Alpha by' => ' OpenVMS Alpha', 'Ported to WindowsNT by' => ' WindowsNT', 'and' => '', '^GREEN' => '', 'BLUE' => '', 'DARK GREEN' => '', 'MAGENTA' => '', 'AMBER' => '' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => ' Ħ', 'Sun' => '', 'Monday' => ' Ħ', 'Mon' => '', 'Tuesday' => ' ', 'Tue' => '', 'Wednesday' => ' ', 'Wed' => '', 'Thursday' => ' ', 'Thu' => '', 'Friday' => ' \'', 'Fri' => '', 'Saturday' => ' ', 'Sat' => '' ); %month = ( 'January' => '', 'February' => '' , 'March' => '', 'Jan' => '', 'Feb' => '', 'Mar' => '', 'April' => 'צ', 'May' => '', 'June' => '', 'Apr' => 'צ', 'May' => '', 'Jun' => '', 'July' => '', 'August' => '', 'September' => '', 'Jul' => '', 'Aug' => '', 'Sep' => '', 'October' => '', 'November' => '', 'December' => '', 'Oct' => '', 'Nov' => '', 'Dec' => '' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].". ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; # Ukrainian1251 - windowze encoding sub ukrainian1251 { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); %translations = ( 'iso-8859-1' => 'windows-1251', 'Maximal 5 Minute Incoming Traffic' => ' 5 ', 'Maximal 5 Minute Outgoing Traffic' => ' 5 ', 'the device' => '', 'The statistics were last updated(.*)' => ' : $1', ' Average\)' => ')', 'Average' => '', 'Max' => '', 'Current' => '', 'version' => '', '`Daily\' Graph \((.*) Minute' => ' ( $1 ', '`Weekly\' Graph \(30 Minute' => ' ( 30 ' , '`Monthly\' Graph \(2 Hour' => '̳ ( i ', '`Yearly\' Graph \(1 Day' => 'г ( ', 'Incoming Traffic in (\S+) per Second' => ' $1 ', 'Outgoing Traffic in (\S+) per Second' => ' $1 ', 'at which time (.*) had been up for(.*)' => '$1 䳿: $2', '([kMG]?)([bB])/s' => '$1$1/', '([kMG]?)([bB])/min' => '$1$2/', '([kMG]?)([bB])/h' => '$1$2/', '([bB])/s' => '$1/', '([bB])/min' => '$1/', '([bB])/h' => '$1/', 'Bits' => '', 'Bytes' => '', 'In' => '', 'Out' => '', 'Percentage' => '³', 'Ported to OpenVMS Alpha by' => ' OpenVMS Alpha', 'Ported to WindowsNT by' => ' WindowsNT', 'and' => '', 'RED' => '', '^GREEN' => '', 'BLUE' => 'Ͳ', 'DARK GREEN' => '', 'MAGENTA' => 'Բ', 'AMBER' => '', ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => ' ', 'Sun' => '', 'Monday' => ' ', 'Mon' => '', 'Tuesday' => ' ³', 'Tue' => '', 'Wednesday' => ' ', 'Wed' => '', 'Thursday' => ' ', 'Thu' => '', 'Friday' => ' \'', 'Fri' => '', 'Saturday' => ' ', 'Sat' => '' ); %month = ( 'January' => 'ѳ', 'February' => '' , 'March' => '', 'Jan' => 'ѳ', 'Feb' => '', 'Mar' => '', 'April' => '', 'May' => '', 'June' => '', 'Apr' => '', 'May' => '', 'Jun' => '', 'July' => '', 'August' => '', 'September' => '', 'Jul' => '', 'Aug' => '', 'Sep' => '', 'October' => '', 'November' => '', 'December' => '', 'Oct' => '', 'Nov' => '', 'Dec' => '' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].". ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/bulgarian.pmd0000644000175300017510000001246113057016062016315 0ustar oetikeroep###### PATCHTAG00 #################################################### ### Bulgarian/ ### => Yovko Lambrev ###### PATCHTAG10 #################################################### &bulgarian ###### PATCHTAG20 #################################################### 'bulgarian' => \&bulgarian, '' => \&bulgarian, ###### PATCHTAG30 #################################################### # Bulgarian/ 'bulgarian' => " : <yovko\@sdf.lonestar.org>", ###### PATCHTAG40 #################################################### $credits::LOCALE{''}=$credits::LOCALE{'bulgarian'}; ###### PATCHTAG50 #################################################### # Bulgarian sub bulgarian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'windows-1251', 'Maximal 5 Minute Incoming Traffic' => ' 5 ', 'Maximal 5 Minute Outgoing Traffic' => ' 5 ', 'the device' => '', 'The statistics were last updated(.*)' => ' : $1', ' Average\)' => ' )', 'Average' => '', 'Max' => '.', 'Current' => '', 'version' => '', '`Daily\' Graph \((.*) Minute' => ' ( $1 ', '`Weekly\' Graph \(30 Minute' => ' ( 30 ' , '`Monthly\' Graph \(2 Hour' => ' ( 2 ', '`Yearly\' Graph \(1 Day' => ' ( 1 ', 'Incoming Traffic in (\S+) per Second' => ' $1 ', 'Outgoing Traffic in (\S+) per Second' => ' $1 ', 'at which time (.*) had been up for(.*)' => ' $1 $2', #'([kMG]?)([bB])/s' => '$1$1/', #'([kMG]?)([bB])/min' => '$1$2/', '([kMG]?)([bB])/h' => '$1$2/', 'Bits' => '', 'Bytes' => '', 'In' => '.', 'Out' => '.', 'Percentage' => '', 'Ported to OpenVMS Alpha by' => ' OpenVMS Alpha ', 'Ported to WindowsNT by' => ' WindowsNT ', 'and' => '', '^GREEN' => '', 'BLUE' => '', 'DARK GREEN' => '', 'MAGENTA' => '', 'AMBER' => '' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => ' ', 'Sun' => '', 'Monday' => ' ', 'Mon' => '', 'Tuesday' => ' ', 'Tue' => '', 'Wednesday' => ' ', 'Wed' => '', 'Thursday' => ' ', 'Thu' => '', 'Friday' => ' ', 'Fri' => '', 'Saturday' => ' ', 'Sat' => '' ); %month = ( 'January' => '', 'February' => '' , 'March' => '', 'Jan' => '', 'Feb' => '', 'Mar' => '', 'April' => '', 'May' => '', 'June' => '', 'Apr' => '', 'May' => '', 'Jun' => '', 'July' => '', 'August' => '', 'September' => '', 'Jul' => '', 'Aug' => '', 'Sep' => '', 'October' => '', 'November' => '', 'December' => '', 'Oct' => '', 'Nov' => '', 'Dec' => '' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].". ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/italian.pmd0000644000175300017510000001375613057016062016002 0ustar oetikeroep###### PATCHTAG 00 #################################################### ### Italian/Italiano ### => Andrea Rossi ###### PATCHTAG 10 #################################################### &italian ###### PATCHTAG 20 #################################################### 'italian' => \&italian, 'italiano' => \&italian, ###### PATCHTAG 30 #################################################### # Italian/Italiano 'italian' => "Localizzazione effettuata da Andrea Rossi <rouge\@shiny.it>", ###### PATCHTAG 40 #################################################### $credits::LOCALE{'italiano'}=$credits::LOCALE{'italian'}; ###### PATCHTAG 50 #################################################### # Italian sub italian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Traffico massimo in entrata su 5 minuti', 'Maximal 5 Minute Outgoing Traffic' => 'Traffico massimo in uscita su 5 minuti', 'the device' => 'Il dispositivo', 'The statistics were last updated(.*)' => 'Le statistiche l\' ultima volta sono state aggiornate $1', ' Average\)' => ' Media)', 'Average' => 'Media', 'Max' => 'Max', 'Current' => 'Attuale', 'version' => 'versione', '`Daily\' Graph \((.*) Minute' => 'Grafico giornaliero (su $1 minuti:', '`Weekly\' Graph \(30 Minute' => 'Grafico settimanale (su 30 minuti:' , '`Monthly\' Graph \(2 Hour' => 'Grafico mensile (su 2 ore:', '`Yearly\' Graph \(1 Day' => 'Grafico annuale (su 1 giorno:', 'Incoming Traffic in (\S+) per Second' => 'Traffico in ingresso in $1 per Secondo', 'Outgoing Traffic in (\S+) per Second' => 'Traffico in uscita in $1 per Secondo', 'Incoming Traffic in (\S+) per Minute' => 'Traffico in ingresso in $1 per Minuto', 'Outgoing Traffic in (\S+) per Minute' => 'Traffico in uscita $1 per Minuto', 'Incoming Traffic in (\S+) per Hour' => 'Traffico in ingresso $1 per Ora', 'Outgoing Traffic in (\S+) per Hour' => 'Traffico in uscita $1 per Ora', 'at which time (.*) had been up for(.*)' => '$1 é attivo da $2', '(\S+) per minute' => '$1 per Minuto', '(\S+) per hour' => '$1 per Ora', '(.+)/s$' => '$1/s', # '(.+)/min' => '$1/min', '(.+)/h$' => '$1/ora', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', # '([kMG]?)([bB])/h' => '$1$2/t', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Ingresso', 'Out' => 'Uscita', 'Percentage' => 'Percentuale', 'Ported to OpenVMS Alpha by' => 'Ported su OpenVMS Alpha da', 'Ported to WindowsNT by' => 'Ported su WindowsNT da', 'and' => 'e', '^GREEN' => 'VERDE', 'BLUE' => 'BLU', 'DARK GREEN' => 'VERDE SCURO', #'MAGENTA' => 'MAGENTA', #'AMBER' => 'AMBRA' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Domenica', 'Sun' => 'Dom', 'Monday' => 'Lunedi', 'Mon' => 'Lun', 'Tuesday' => 'Martedi', 'Tue' => 'Mar', 'Wednesday' => 'Mercoledi', 'Wed' => 'Mer', 'Thursday' => 'Giovedi', 'Thu' => 'Gio', 'Friday' => 'Venerdi', 'Fri' => 'Ven', 'Saturday' => 'Sabato', 'Sat' => 'Sab' ); %month = ( 'January' => 'Gennaio', 'February' => 'Febbraio' , 'March' => 'Marzo', 'Jan' => 'Gen', 'Feb' => 'Feb', 'Mar' => 'Mar', 'April' => 'Aprile', 'May' => 'Maggio', 'June' => 'Giugno', 'Apr' => 'Apr', 'May' => 'Mag', 'Jun' => 'Giu', 'July' => 'Luglio', 'August' => 'Agosto', 'September' => 'Settembre', 'Jul' => 'Lug', 'Aug' => 'Ago', 'Sep' => 'Set', 'October' => 'Ottobre', 'November' => 'Novembre', 'December' => 'Dicembre', 'Oct' => 'Ott', 'Nov' => 'Nov', 'Dec' => 'Dic' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." alle ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." à $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/big5.pmd0000644000175300017510000001351213057016062015175 0ustar oetikeroep###### PATCHTAG 00 ################################################### ### Chinese/c ### => Tate Chen @ ### => Ryan Huang F ###### PATCHTAG 10 ################################################### &big5 ###### PATCHTAG 20 ################################################### 'big5' => \&big5, 'c' => \&big5, ###### PATCHTAG 30 ################################################### # Chinese/c 'big5' => "Ƨ@ Tate Chen <tate\@joy-tech.com.tw>
and F <ryan\@asplord.com>", ###### PATCHTAG 40 ################################################### $credits::LOCALE{'c'}=$credits::LOCALE{'big5'}; ###### PATCHTAG 50 ################################################### # Chinese Big5 Code sub big5 { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'big5', 'Maximal 5 Minute Incoming Traffic' => '5̤jyJq', 'Maximal 5 Minute Outgoing Traffic' => '5̤jyXq', 'the device' => '˸m', 'The statistics were last updated(.*)' => 'Wέpsɶ: $1', ' Average\)' => ' )', 'Average' => '', 'Max$' => '̤j', 'Current' => 'ثe', 'version' => '', '`Daily\' Graph \((.*) Minute' => 'C Ϫ ($1 ', '`Weekly\' Graph \(30 Minute' => 'Cg Ϫ (30 ' , '`Monthly\' Graph \(2 Hour' => 'C Ϫ (2 p', '`Yearly\' Graph \(1 Day' => 'C~ Ϫ (1 ', 'Incoming Traffic in (\S+) per Second' => 'CyJq ( $1)', 'Outgoing Traffic in (\S+) per Second' => 'CyXq ( $1)', 'Incoming Traffic in (\S+) per Minute' => 'CyJq ( $1)', 'Outgoing Traffic in (\S+) per Minute' => 'CyXq ( $1)', 'Incoming Traffic in (\S+) per Hour' => 'CpɬyJq ( $1)', 'Outgoing Traffic in (\S+) per Hour' => 'CpɬyXq ( $1)', 'at which time (.*) had been up for(.*)' => ']ƦW $1AwB@ɶ(UPTIME): $2', '(\S+) per minute' => '$1/', '(\S+) per hour' => '$1/p', '(.+)/s$' => '$1/', '(.+)/min$' => '$1/', '(.+)/h$' => '$1/p', #'([kMG]?)([bB])/s' => '$1$2/s', #'([kMG]?)([bB])/min' => '$1$2/min', #'([kMG]?)([bB])/h' => '$1$2/std', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'yJ', 'Out$' => 'yX', 'Percentage' => 'ʤ', 'Ported to OpenVMS Alpha by' => 'Ө OpenVM Alpha @', 'Ported to WindowsNT by' => 'Ө WindowsNT @', 'and' => '', '^GREEN' => '', 'BLUE' => 'Ŧ', 'DARK GREEN' => '', 'MAGENTA' => '', 'AMBER' => '[Ħ' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'P', 'Sun' => '', 'Monday' => 'P@', 'Mon' => '@', 'Tuesday' => 'PG', 'Tue' => 'G', 'Wednesday' => 'PT', 'Wed' => 'T', 'Thursday' => 'P|', 'Thu' => '|', 'Friday' => 'P', 'Fri' => '', 'Saturday' => 'P', 'Sat' => '' ); %month = ( 'January' => '@', 'February' => 'G', 'March' => 'T', 'Jan' => '@', 'Feb' => 'G', 'Mar' => 'T', 'April' => '|', 'May' => '', 'June' => '', 'Apr' => '|', 'May' => '', 'Jun' => '', 'July' => 'C', 'August' => 'K', 'September' => 'E', 'Jul' => 'C', 'Aug' => 'K', 'Sep' => 'E', 'October' => 'Q', 'November' => 'Q@', 'December' => 'QG', 'Oct' => 'Q', 'Nov' => 'Q@', 'Dec' => 'QG' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]; $foo[4]=$quux[1]; }; return "$foo[3] ~ $month{$foo[2]} $foo[1] $wday{$foo[0]} $foo[4]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/gb2312.pmd0000644000175300017510000001214213057016062015245 0ustar oetikeroep ###### PATCHTAG 00 ################################################### ### Chinese/ļ ### => Peter Wong ###### PATCHTAG 10 ################################################### &gb2312 ###### PATCHTAG 20 ################################################### 'gb2312' => \&gb2312, 'ļ' => \&gb2312, ###### PATCHTAG 30 ################################################### # Chinese/ļ 'gb2312' => "Ļ Peter Wong &webmaster\@tcpip.com.cn>", ###### PATCHTAG 40 ################################################### $credits::LOCALE{'ļ'}=$credits::LOCALE{'gb2312'}; ###### PATCHTAG 50 ################################################### # Chinese gb2312 Code sub gb2312 { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'gb2312', 'Maximal 5 Minute Incoming Traffic' => '5', 'Maximal 5 Minute Outgoing Traffic' => '5', 'the device' => 'װ', 'The statistics were last updated(.*)' => 'ϴͳƸʱ: $1', ' Average\)' => ' ƽ)', 'Average' => 'ƽ', 'Max' => '', 'Current' => 'Ŀǰ', 'version' => '汾', '`Daily\' Graph \((.*) Minute' => 'ÿ ͼ ($1 ', '`Weekly\' Graph \(30 Minute' => 'ÿ ͼ (30 ' , '`Monthly\' Graph \(2 Hour' => 'ÿ ͼ (2 Сʱ', '`Yearly\' Graph \(1 Day' => 'ÿ ͼ (1 ', 'Incoming Traffic in (\S+) per Second' => 'ÿ (λ $1)', 'Outgoing Traffic in (\S+) per Second' => 'ÿ (λ $1)', 'at which time (.*) had been up for(.*)' => '豸 $1ʱ(UPTIME): $2', '([kMG]?)([bB])/s' => '\$1\$2/', '([kMG]?)([bB])/min' => '\$1\$2/', '([kMG]?)([bB])/h' => '$1$2/ʱ', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => '', 'Out' => '', 'Percentage' => 'ٷֱ', 'Ported to OpenVMS Alpha by' => 'ֲ OpenVM Alpha ', 'Ported to WindowsNT by' => 'ֲ WindowsNT ', 'and' => '', '^GREEN' => 'ɫ', 'BLUE' => 'ɫ', 'DARK GREEN' => 'īɫ', 'MAGENTA' => 'ɫ', 'AMBER' => 'ɫ' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => '', 'Sun' => '', 'Monday' => 'һ', 'Mon' => 'һ', 'Tuesday' => 'ڶ', 'Tue' => '', 'Wednesday' => '', 'Wed' => '', 'Thursday' => '', 'Thu' => '', 'Friday' => '', 'Fri' => '', 'Saturday' => '', 'Sat' => '' ); %month = ( 'January' => 'һ', 'February' => '', 'March' => '', 'Jan' => 'һ', 'Feb' => '', 'Mar' => '', 'April' => '', 'May' => '', 'June' => '', 'Apr' => '', 'May' => '', 'Jun' => '', 'July' => '', 'August' => '', 'September' => '', 'Jul' => '', 'Aug' => '', 'Sep' => '', 'October' => 'ʮ', 'November' => 'ʮһ', 'December' => 'ʮ', 'Oct' => 'ʮ', 'Nov' => 'ʮһ', 'Dec' => 'ʮ' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { @quux=split(/at/,$foo[3]); if($foo[3]=~(/(.*)at(.*)/)) { $foo[3]=$quux[0]; $foo[4]=$quux[1]; }; return "$foo[3] $month{$foo[2]} $foo[1] , $wday{$foo[0]}, $foo[4]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/lithuanian.pmd0000644000175300017510000001263413057016062016507 0ustar oetikeroep###### PATCHTAG00 #################################################### ### Lithuanian/Lietuvikai ### => ve ###### PATCHTAG10 #################################################### &lithuanian ###### PATCHTAG20 #################################################### 'lithuanian' => \&lithuanian, 'lietuvikai' => \&lithuanian, ###### PATCHTAG30 #################################################### # Lithuanian/lietuvikai 'lithuanian' => "Paruo ir lietuvi kalb ivert ve <ve\@hardcore.lt>", # the lithuanian string means: "Prepared for languages and translated to lithuanian by" ###### PATCHTAG40 #################################################### $credits::LOCALE{'lietuvikai'}=$credits::LOCALE{'lithuanian'}; ###### PATCHTAG50 #################################################### # Lithuanian sub lithuanian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'windows-1257', 'Maximal 5 Minute Incoming Traffic' => 'Maksimalus 5 minui einantis srautas', 'Maximal 5 Minute Outgoing Traffic' => 'Maksimalus 5 minui ieinantis srautas', 'the device' => 'renginys', 'The statistics were last updated(.*)' => 'Statistika atnaujinta$1', ' Average\)' => ' vidurkis)', 'Average' => 'vid', 'Max' => 'max', 'Current' => 'dabar', 'version' => 'versija', '`Daily\' Graph \((.*) Minute' => '\'dienos\' grafikas ($1 min.', '`Weekly\' Graph \(30 Minute' => '\'savaits\' grafikas (30 min.' , '`Monthly\' Graph \(2 Hour' => '\'mnesio\' grafikas (2 val.', '`Yearly\' Graph \(1 Day' => '\'met\' grafikas (1 d.', 'Incoming Traffic in (\S+) per Second' => 'einantis srautas, $1 per sekund', 'Outgoing Traffic in (\S+) per Second' => 'Ieinantis srautas i $1 per sekund', 'at which time (.*) had been up for(.*)' => '$1 veikia jau $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', # '([kMG]?)([bB])/h' => '$1$2/h', 'Bits' => 'bitai', 'Bytes' => 'baitai', 'In' => '', 'Out' => 'i', 'Percentage' => 'procentai', 'Ported to OpenVMS Alpha by' => 'Perkl OpenVMS Alpha:', 'Ported to WindowsNT by' => 'Perkl WindowsNT:', 'and' => 'ir', '^GREEN' => 'ALIA ', 'BLUE' => 'MLYNA ', 'DARK GREEN' => 'TAMSIAI ALIA ', 'MAGENTA' => 'RAUDONA ', 'AMBER' => 'GINTARIN ' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'sekmadien', 'Sun' => 'Sek', 'Monday' => 'pirmadien', 'Mon' => 'Pir', 'Tuesday' => 'antradien', 'Tue' => 'Ant', 'Wednesday' => 'treiadien', 'Wed' => 'Tre', 'Thursday' => 'ketvirtadien', 'Thu' => 'Ket', 'Friday' => 'penktadien', 'Fri' => 'Pen', 'Saturday' => 'etadien', 'Sat' => 'e' ); %month = ( 'January' => 'sausio', 'February' => 'vasario' , 'March' => 'kovo', 'Jan' => 'Sau', 'Feb' => 'Vas', 'Mar' => 'Kov', 'April' => 'balandio', 'May' => 'gegus', 'June' => 'birelio', 'Apr' => 'Bal', 'May' => 'Geg', 'Jun' => 'Bir', 'July' => 'liepos', 'August' => 'rugpjio', 'September' => 'rugsjo', 'Jul' => 'Lie', 'Aug' => 'Rgp', 'Sep' => 'Rgs', 'October' => 'spalio', 'November' => 'lapkriio', 'December' => 'gruodio', 'Oct' => 'Spa', 'Nov' => 'Lap', 'Dec' => 'Gru' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[1].", ".$quux[0]; }; return "$foo[3] $month{$foo[2]} $foo[1], $wday{$foo[0]}" ; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/malay.pmd0000644000175300017510000001243513057016062015455 0ustar oetikeroep###### PATCHTAG 00 ################################################### ### Malaysian/Malay ### => Assakhof Ab. Satar ###### PATCHTAG 10 ################################################### &malay ###### PATCHTAG 20 ################################################### 'malay' => \&malay, 'malaysian' => \&malay, ###### PATCHTAG 30 ################################################### # Malaysian/Malay 'malay' => "Terjemahan ke bahasa Malaysia/Indonesia oleh: Assakhof Ab. Satar <assakhof\@mimos.my>", ###### PATCHTAG 40 ################################################### $credits::LOCALE{'malaysian'}=$credits::LOCALE{'malay'}; ###### PATCHTAG 50 ################################################### # Malaysian/Malay sub malay { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Maksimum 5 Minit Trafik Masuk', 'Maximal 5 Minute Outgoing Traffic' => 'Maksimum 5 Minit Trafik Keluar', 'the device' => 'alatan', 'The statistics were last updated(.*)' => 'Statistik ini kali terakhir dikemaskini pada $1', ' Average\)' => ' secara purata)', 'Average' => 'Purata', 'Max' => 'Maksimum', 'Current' => 'Kini', 'version' => 'versi', '`Daily\' Graph \((.*) Minute' => 'Graf `Harian\' ($1 minit :', '`Weekly\' Graph \(30 Minute' => 'Graf `Mingguan\' (30 minit :' , '`Monthly\' Graph \(2 Hour' => 'Graf `Bulanan\' (2 jam :', '`Yearly\' Graph \(1 Day' => 'Graf `Tahunan\' (1 hari :', 'Incoming Traffic in (\S+) per Second' => 'Trafik Masuk $1 per saat', 'Outgoing Traffic in (\S+) per Second' => 'Traffic Keluar $1 per saat', 'at which time (.*) had been up for(.*)' => 'Sehingga waktu $1 ia telah aktif selama $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/j', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Masuk', 'Out' => 'Keluar', 'Percentage' => 'Peratus', 'Ported to OpenVMS Alpha by' => 'Pengubahsuaian ke OpenVMS Alpha oleh', 'Ported to WindowsNT by' => 'Pengubahsuaian ke WindowsNT oleh', 'and' => 'dan', '^GREEN' => 'HIJAU', 'BLUE' => 'BIRU', 'DARK GREEN' => 'HIJAU GELAP', 'MAGENTA' => 'MAGENTA', 'AMBER' => 'AMBAR' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Ahad', 'Sun' => 'Aha', 'Monday' => 'Isnin', 'Mon' => 'Isn', 'Tuesday' => 'Selasa', 'Tue' => 'Sel', 'Wednesday' => 'Rabu', 'Wed' => 'Rab', 'Thursday' => 'Khamis', 'Thu' => 'Kha', 'Friday' => 'Jumaat', 'Fri' => 'Jum', 'Saturday' => 'Sabtu', 'Sat' => 'Sab' ); %month = ( 'January' => 'Januari', 'February' => 'Februari' , 'March' => 'Mac', 'Jan' => 'Jan', 'Feb' => 'Feb', 'Mar' => 'Mac', 'April' => 'April', 'May' => 'Mei', 'June' => 'Jun', 'Apr' => 'Apr', 'May' => 'Mei', 'Jun' => 'Jun', 'July' => 'Julai', 'August' => 'Ogos', 'September' => 'September', 'Jul' => 'Jul', 'Aug' => 'Ogo', 'Sep' => 'Sep', 'October' => 'Oktober', 'November' => 'November', 'December' => 'Disember', 'Oct' => 'Okt', 'Nov' => 'Nov', 'Dec' => 'Dis' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." pada ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/eucjp.pmd0000644000175300017510000001233113057016062015453 0ustar oetikeroep###### PATCHTAG00 #################################################### ### ܸ(EUC-JP) ### => Fuminori Uematsu ###### PATCHTAG10 #################################################### &eucjp ###### PATCHTAG20 #################################################### 'eucjp' => \&eucjp, 'euc-jp' => \&eucjp, ###### PATCHTAG30 #################################################### # eucjp/euc-jp 'eucjp' => "ܸ(EUC-JP) ʸ <uematsu\@kgz.com>", ###### PATCHTAG40 #################################################### $credits::LOCALE{'euc-jp'}=$credits::LOCALE{'eucjp'}; ###### PATCHTAG50 #################################################### # eucjp sub eucjp { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( '^iso-8859-1' => 'euc-jp', '^Maximal 5 Minute Incoming Traffic' => '5ʬ', '^Maximal 5 Minute Outgoing Traffic' => '5ʬ', '^the device' => 'ǥХ', '^The statistics were last updated (.*)' => ' $1', '^Average\)' => 'ʿ)', '^Average$' => 'ʿ', '^Max$' => '', '^Current' => 'ǿ', '^`Daily\' Graph \((.*) Minute' => '($1ʬ', '^`Weekly\' Graph \(30 Minute' => '(30ʬ', '^`Monthly\' Graph \(2 Hour' => '(2', '^`Yearly\' Graph \(1 Day' => 'ǯ(1', '^Incoming Traffic in (\S+) per Second' => 'äμ$1', '^Incoming Traffic in (\S+) per Minute' => 'ʬμ$1', '^Incoming Traffic in (\S+) per Hour' => 'μ$1', '^Outgoing Traffic in (\S+) per Second' => 'ä$1', '^Outgoing Traffic in (\S+) per Minute' => 'ʬ$1', '^Outgoing Traffic in (\S+) per Hour' => '$1', '^at which time (.*) had been up for (.*)' => '$1βƯ $2', '^Average max 5 min values for `Daily\' Graph \((.*) Minute interval\):' => 'դǤκ5ʬͤʿ($1ʬֳ):', '^Average max 5 min values for `Weekly\' Graph \(30 Minute interval\):' => 'դǤκ5ʬͤʿ(30ʬֳ):', '^Average max 5 min values for `Monthly\' Graph \(2 Hour interval\):' => 'դǤκ5ʬͤʿ(2ֳִ):', '^Average max 5 min values for `Yearly\' Graph \(1 Day interval\):' => 'ǯդǤκ5ʬͤʿ(1ֳ):', #'^([kMG]?)([bB])/s' => '$1$2/', #'^([kMG]?)([bB])/min' => '$1$2/ʬ', #'^([kMG]?)([bB])/h' => '$1$2/', '^Bits$' => 'ӥå', '^Bytes$' => 'Х', '^In$' => '', '^Out$' => '', '^Percentage' => 'Ψ', '^Ported to OpenVMS Alpha by' => 'OpenVMS Alphaؤΰܿ', '^Ported to WindowsNT by' => 'WindowsNTؤΰܿ', #'^and' => 'and', '^GREEN' => '', '^BLUE' => '', '^DARK GREEN' => '', '^MAGENTA' => 'ޥ', '^AMBER' => '' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => '()', 'Monday' => '()', 'Tuesday' => '()', 'Wednesday' => '()', 'Thursday' => '()', 'Friday' => '()', 'Saturday' => '()', ); %month = ( 'January' => '1', 'February' => '2', 'March' => '3', 'April' => '4', 'May' => '5', 'June' => '6', 'July' => '7', 'August' => '8', 'September' => '9', 'October' => '10', 'November' => '11', 'December' => '12', ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)\s+(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~/at/) { @quux=split(/\s+at\s+/,$foo[3]); } else { @quux=split(/ /,$foo[3],2); }; return "$quux[0]ǯ$month{$foo[2]}$foo[1]$wday{$foo[0]} $quux[1]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/russian.pmd0000644000175300017510000001245113057016062016034 0ustar oetikeroep###### PATCHTAG00 #################################################### ### Russian/ ### => ###### PATCHTAG10 #################################################### &russian ###### PATCHTAG20 #################################################### 'russian' => \&russian, '' => \&russian, ###### PATCHTAG30 #################################################### # Russian/ 'russian' => " : <mitya\@cavia.pp.ru>", ###### PATCHTAG40 #################################################### $credits::LOCALE{''}=$credits::LOCALE{'russian'}; ###### PATCHTAG50 #################################################### # Russian sub russian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'koi8-r', 'Maximal 5 Minute Incoming Traffic' => ' 5 ', 'Maximal 5 Minute Outgoing Traffic' => ' 5 ', 'the device' => '', 'The statistics were last updated(.*)' => ' : $1', ' Average\)' => ')', 'Average' => '', 'Max' => '.', 'Current' => '', 'version' => '', '`Daily\' Graph \((.*) Minute' => ' ( $1 ', '`Weekly\' Graph \(30 Minute' => ' ( 30 ' , '`Monthly\' Graph \(2 Hour' => ' ( 2 ', '`Yearly\' Graph \(1 Day' => ' ( 1 ', 'Incoming Traffic in (\S+) per Second' => ' $1 ', 'Outgoing Traffic in (\S+) per Second' => ' $1 ', 'at which time (.*) had been up for(.*)' => ' $1 $2', #'([kMG]?)([bB])/s' => '$1$1/', #'([kMG]?)([bB])/min' => '$1$2/', '([kMG]?)([bB])/h' => '$1$2/', 'Bits' => '', 'Bytes' => '', 'In' => '', 'Out' => '', 'Percentage' => '', 'Ported to OpenVMS Alpha by' => ' OpenVMS Alpha', 'Ported to WindowsNT by' => ' WindowsNT', 'and' => '', '^GREEN' => '', 'BLUE' => '', 'DARK GREEN' => '', 'MAGENTA' => '', 'AMBER' => '' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => ' ', 'Sun' => '', 'Monday' => ' ', 'Mon' => '', 'Tuesday' => ' ', 'Tue' => '', 'Wednesday' => ' ', 'Wed' => '', 'Thursday' => ' ', 'Thu' => '', 'Friday' => ' ', 'Fri' => '', 'Saturday' => ' ', 'Sat' => '' ); %month = ( 'January' => '', 'February' => '' , 'March' => '', 'Jan' => '', 'Feb' => '', 'Mar' => '', 'April' => '', 'May' => '', 'June' => '', 'Apr' => '', 'May' => '', 'Jun' => '', 'July' => '', 'August' => '', 'September' => '', 'Jul' => '', 'Aug' => '', 'Sep' => '', 'October' => '', 'November' => '', 'December' => '', 'Oct' => '', 'Nov' => '', 'Dec' => '' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].". ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/slovenian.pmd0000644000175300017510000001221713057016062016346 0ustar oetikeroep###### PATCHTAG 00 ################################################### ### Slovenian/Slovensko ### => Aljosa Us ###### PATCHTAG 10 ################################################### &slovenian ###### PATCHTAG 20 ################################################### 'slovenian' => \&slovenian, ###### PATCHTAG 30 ################################################### # Slovenian/Slovensko 'slovenian' => "Slovenski prevod pripravil Ragnar Belial Us <us\@sweet-sorrow.com>", ###### PATCHTAG 40 ################################################### $credits::LOCALE{'slovenian'}=$credits::LOCALE{'slovenian'}; ###### PATCHTAG 50 ################################################### # Slovenian sub slovenian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'windows-1250', 'Maximal 5 Minute Incoming Traffic' => 'Najvecji petminutni vhodni promet', 'Maximal 5 Minute Outgoing Traffic' => 'Najvecji petminutni izhodni promet', 'the device' => 'naprava', 'The statistics were last updated(.*)' => 'Zadnja posodobitev podatkov:$1', ' Average\)' => ' povprecje)', 'Average' => 'Povprecje', 'Max' => 'Maksimalno', 'Current' => 'Trenutno', 'version' => 'verzija', '`Daily\' Graph \((.*) Minute' => 'Dnevni graf ($1 min.', '`Weekly\' Graph \(30 Minute' => 'Tedenski graf (30 min.' , '`Monthly\' Graph \(2 Hour' => 'Mesecni graf (2 urno', '`Yearly\' Graph \(1 Day' => 'Letni graf (1 dnevno', 'Incoming Traffic in (\S+) per Second' => 'Vhodni promet v $1 na sekundo.', 'Outgoing Traffic in (\S+) per Second' => 'Izhodni promet v $1 na sekundo.', 'at which time (.*) had been up for(.*)' => 'Cas od zadnjega restarta sistema $1 : $2', #'([kMG]?)([bB])/s' => '\$1\$2/s', #'([kMG]?)([bB])/min' => '\$1\$2/min', #'([kMG]?)([bB])/h' => '$1$2/h', 'Bits' => 'bitov', 'Bytes' => 'bytov', 'In' => 'Vhod', 'Out' => 'Izhod', 'Percentage' => 'Proc.', 'Ported to OpenVMS Alpha by' => 'Na OpenVMS portiral', 'Ported to WindowsNT by' => 'Na WindowsNT portiral', 'and' => 'in', '^GREEN' => 'Zeleno', 'BLUE' => 'Modro', 'DARK GREEN' => 'Temnozeleno', 'MAGENTA' => 'Vijolicasto', 'AMBER' => 'Oranzno' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Nedelja', 'Sun' => 'Ne', 'Monday' => 'Ponedeljek', 'Mon' => 'Po', 'Tuesday' => 'Torek', 'Tue' => 'To', 'Wednesday' => 'Sreda', 'Wed' => 'Sr', 'Thursday' => 'Cetrtek', 'Thu' => 'Ce', 'Friday' => 'Petek', 'Fri' => 'Po', 'Saturday' => 'Sobota', 'Sat' => 'So' ); %month = ( 'January' => 'Januar', 'February' => 'Februar', 'March' => 'Marec', 'Jan' => 'Jan', 'Feb' => 'Feb', 'Mar' => 'Mar', 'April' => 'April', 'May' => 'Maj', 'June' => 'Jun', 'Apr' => 'Apr', 'May' => 'Maj', 'Jun' => 'Jun', 'July' => 'Julij', 'August' => 'Avgust', 'September' => 'September', 'Jul' => 'Jul', 'Aug' => 'Avg', 'Sep' => 'Sep', 'October' => 'Oktober','November' => 'November','December' => 'December', 'Oct' => 'Okt','Nov' => 'Nov','Dec' => 'Dec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].",".$quux[1]." "; }; return "$wday{$foo[0]} $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; } # mrtg-2.17.10/translate/portuguese.pmd0000644000175300017510000001415614171553254016565 0ustar oetikeroep###### PATCHTAG 00 ################################################### ### Portuguese/Português ### => Diogo Gomes ###### PATCHTAG 10 ################################################### &portuguese ###### PATCHTAG 20 ################################################### 'portuguese' => \&portuguese, ###### PATCHTAG 30 ################################################### # Português/portuguese 'portuguese' => "Traduzido por Diogo Gomes <etdgomes\@ua.pt>", ###### PATCHTAG 40 ################################################### $credits::LOCALE{'portuguese'}=$credits::LOCALE{'portuguese'}; ###### PATCHTAG 50 ################################################### # Português sub portuguese { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Tráfego Maximal Recebido em 5 minutos', 'Maximal 5 Minute Outgoing Traffic' => 'Tráfego Maximal Enviado em 5 minutos', 'the device' => 'o dispositivo', 'The statistics were last updated(.*)' => 'As Estatísticas foram actualizadas pela última vez na $1', ' Average\)

' => '', 'Average' => 'Média', 'Max' => 'Max.', 'Current' => 'Actual', 'version' => 'Versão', '`Daily\' Graph \((.*) Minute' => 'Gráfico Diário (em intervalos de $1 Minutos)

', '`Weekly\' Graph \(30 Minute' => 'Gráfico Semanal (em intervalos de 30 Minutos)' , '`Monthly\' Graph \(2 Hour' => 'Gráfico Mensal (em intervalos de 2 horas)', '`Yearly\' Graph \(1 Day' => 'Gráfico Anual (em intervalos de 24 horas)', 'Incoming Traffic in (\S+) per Second' => 'Tráfego recebido em $1/segundo', 'Outgoing Traffic in (\S+) per Second' => 'Tráfego enviado em $1/segundo', 'Incoming Traffic in (\S+) per Minute' => 'Tráfego recebido em $1/minuto', 'Outgoing Traffic in (\S+) per Minute' => 'Tráfego enviado em $1/minuto', 'Incoming Traffic in (\S+) per Hour' => 'Tráfego recebido em $1/hora', 'Outgoing Traffic in (\S+) per Hour' => 'Tráfego recebido em $1/hora', 'at which time (.*) had been up for(.*)' => 'quando o $1, tinha um uptime de $2', '(\S+) per minute' => '$1/minuto', '(\S+) per hour' => '$1/hora', '(.+)/s$' => '$1/s', # '(.+)/min' => '$1/min', '(.+)/h$' => '$1/h', #'([kMG]?)([bB])/s' => '$1$2/s', #'([kMG]?)([bB])/min' => '$1$2/min', #'([kMG]?)([bB])/h' => '$1$2/h', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Rec.', 'Out' => 'Env.', 'Percentage' => 'Perc.', 'Ported to OpenVMS Alpha by' => 'Portado para OpenVMS Alpha por', 'Ported to WindowsNT by' => 'Portado para WindowsNT por', 'and' => 'e', '^GREEN' => 'VERDE', 'BLUE' => 'AZUL', 'DARK GREEN' => 'VERDE ESCURO', # 'MAGENTA' => 'MAGENTA', # 'AMBER' => 'AMBAR', ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Domingo', 'Sun' => 'Dom', 'Monday' => 'Segunda-Feira', 'Mon' => 'Seg', 'Tuesday' => 'Terça-Feira', 'Tue' => 'Ter', 'Wednesday' => 'Quarta-Feira', 'Wed' => 'Qua', 'Thursday' => 'Quinta-Feira', 'Thu' => 'Qui', 'Friday' => 'Sexta-Feira', 'Fri' => 'Sex', 'Saturday' => 'Sábado', 'Sat' => 'Sab' ); %month = ( 'January' => 'Janeiro', 'February' => 'Fevereiro' , 'March' => 'Março', 'Jan' => 'Jan', 'Feb' => 'Fev', 'Mar' => 'Mar', 'April' => 'Abril', 'May' => 'Maio', 'June' => 'Junho', 'Apr' => 'Abr', 'May' => 'Mai', 'Jun' => 'Jun', 'July' => 'Julho', 'August' => 'Agosto', 'September' => 'Setembro', 'Jul' => 'Jul', 'Aug' => 'Ago', 'Sep' => 'Set', 'October' => 'Outubro', 'November' => 'Novembro', 'December' => 'Dezembro', 'Oct' => 'Out', 'Nov' => 'Nov', 'Dec' => 'Dez' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." pelas ".$quux[1]; }; return "$wday{$foo[0]}, $foo[1] de $month{$foo[2]} de $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/danish.pmd0000644000175300017510000001272013057016062015615 0ustar oetikeroep###### PATCHTAG00 #################################################### ### Danish/Dansk ### => Morten Storgaard Nielsen ###### PATCHTAG10 #################################################### &danish ###### PATCHTAG20 #################################################### 'danish' => \&danish, 'dansk' => \&danish, ###### PATCHTAG30 #################################################### # Danish/dansk 'danish' => "Forberedt for sprog samt oversat til dansk af Morten S. Nielsen <msn\@ipt.dtu.dk>", # the danish string means: "Prepared for languages and translated to danish by" ###### PATCHTAG40 #################################################### $credits::LOCALE{'dansk'}=$credits::LOCALE{'danish'}; ###### PATCHTAG50 #################################################### # Danish sub danish { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Maksimal indgående trafik i 5 minutter', 'Maximal 5 Minute Outgoing Traffic' => 'Maksimal udgående trafik i 5 minutter', 'the device' => 'enheden', 'The statistics were last updated(.*)' => 'Statistikken blev sidst opdateret$1', ' Average\)' => ' Middel)', 'Average' => 'Middel', 'Max' => 'Max', 'Current' => 'Nu', 'version' => 'version', '`Daily\' Graph \((.*) Minute' => '`Daglig\' graf ($1 minuts', '`Weekly\' Graph \(30 Minute' => '`Ugentlig\' graf (30 minuts' , '`Monthly\' Graph \(2 Hour' => '`Månedlig\' graf (2 times', '`Yearly\' Graph \(1 Day' => '`Årlig\' graf (1 dags', 'Incoming Traffic in (\S+) per Second' => 'Indgående trafik i $1 per sekund', 'Outgoing Traffic in (\S+) per Second' => 'Udgående trafik i $1 per sekund', 'at which time (.*) had been up for(.*)' => 'hvor $1 havde været oppe i$2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/t', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Ind', 'Out' => 'Ud', 'Percentage' => 'Procent', 'Ported to OpenVMS Alpha by' => 'Port til OpenVMS af', 'Ported to WindowsNT by' => 'Port til WindowsNT af', 'and' => 'og', '^GREEN' => 'GRØN', 'BLUE' => 'BLÅ', 'DARK GREEN' => 'MØRKEGRØN', 'MAGENTA' => 'LYSLILLA', 'AMBER' => 'RAV' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Søndag', 'Sun' => 'Søn', 'Monday' => 'Mandag', 'Mon' => 'Man', 'Tuesday' => 'Tirsdag', 'Tue' => 'Tir', 'Wednesday' => 'Onsdag', 'Wed' => 'Ons', 'Thursday' => 'Torsdag', 'Thu' => 'Tor', 'Friday' => 'Fredag', 'Fri' => 'Fre', 'Saturday' => 'Lørdag', 'Sat' => 'Lør' ); %month = ( 'January' => 'Januar', 'February' => 'Februar' , 'March' => 'Marts', 'Jan' => 'Jan', 'Feb' => 'Feb', 'Mar' => 'Mar', 'April' => 'April', 'May' => 'Maj', 'June' => 'Juni', 'Apr' => 'Apr', 'May' => 'Maj', 'Jun' => 'Jun', 'July' => 'Juli', 'August' => 'August', 'September' => 'September', 'Jul' => 'Jul', 'Aug' => 'Aug', 'Sep' => 'Sep', 'October' => 'Oktober', 'November' => 'November', 'December' => 'December', 'Oct' => 'Okt', 'Nov' => 'Nov', 'Dec' => 'Dec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." kl.".$quux[1]; }; return "$wday{$foo[0]} den $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/finnish.pmd0000644000175300017510000001410613057016062016005 0ustar oetikeroep###### PATCHTAG 00 ################################################### ### Finnish/Suomi ### => Jussi Siponen ###### PATCHTAG 10 ################################################### &german ###### PATCHTAG 20 ################################################### 'finnish' => \&finnish, 'suomi' => \&finnish, ###### PATCHTAG 30 ################################################### # Finnish/Suomi 'finnish' => "Lokalisoinut Jussi Siponen <jussi.siponen\@online.tietokone.fi>", # the Finnish string means: "Localized by" ###### PATCHTAG 40 ################################################### $credits::LOCALE{'finnish'}=$credits::LOCALE{'finnish'}; ###### PATCHTAG 50 ################################################### # Finnish sub finnish { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Tulevan liikenteen maksimi 5 minuutin aikana', 'Maximal 5 Minute Outgoing Traffic' => 'Lähtevän liikenteen maksimi 5 minuutin aikana', 'the device' => 'laite', 'The statistics were last updated(.*)' => 'Tiedot päivitetty viimeksi $1', ' Average\)' => '', 'Average' => 'Keskimäärin', 'Max' => 'Maksimi', 'Current' => 'Tällä hetkellä', 'version' => 'versio', '`Daily\' Graph \((.*) Minute' => 'Päiväraportti (skaala $1 minuutti(a))', '`Weekly\' Graph \(30 Minute' => 'Viikkoraportti (skaala 30 minuuttia)' , '`Monthly\' Graph \(2 Hour' => 'Kuukausiraportti (skaala 2 tuntia)', '`Yearly\' Graph \(1 Day' => 'Vuosiraportti (skaala 1 vuorokausi)', 'Incoming Traffic in (\S+) per Second' => 'Tuleva liikenne $1 sekunnissa', 'Outgoing Traffic in (\S+) per Second' => 'Lähtevä liikenne $1 sekunnissa', 'Incoming Traffic in (\S+) per Minute' => 'Tuleva liikenne $1 minuutissa', 'Outgoing Traffic in (\S+) per Minute' => 'Lähtevä liikenne $1 minuutissa', 'Incoming Traffic in (\S+) per Hour' => 'Tuleva liikenne $1 tunnissa', 'Outgoing Traffic in (\S+) per Hour' => 'Lähtevä liikenne $1 tunnissa', 'at which time (.*) had been up for(.*)' => 'jolloin $1 on toiminut yhtäjaksoisesti $2', '(\S+) per minute' => '$1 minuutissa', '(\S+) per hour' => '$1 tunnissa', '(.+)/s$' => '$1/s', # '(.+)/min' => '$1/min', #'(.+)/h$' => '$1/h', #'([kMG]?)([bB])/s' => '$1$2/s', #'([kMG]?)([bB])/min' => '$1$2/min', #'([kMG]?)([bB])/h' => '$1$2/h', 'Bits' => 'bittiä', 'Bytes' => 'tavua', 'In' => 'Tuleva', 'Out' => 'Lähtevä', 'Percentage' => 'Prosenttia', 'Ported to OpenVMS Alpha by' => 'OpenVMS -järjestelmälle sovittanut', 'Ported to WindowsNT by' => 'WindowsNT -järjestelmälle sovittanut', 'and' => 'ja', '^GREEN' => 'VIHREÄ', 'BLUE' => 'SININEN', 'DARK GREEN' => 'TUMMANVIHREÄ', 'MAGENTA' => 'PINKKI', 'AMBER' => 'PUNAINEN', ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Sunnuntai', 'Sun' => 'Su', 'Monday' => 'Maanantai', 'Mon' => 'Ma', 'Tuesday' => 'Tiistai', 'Tue' => 'Ti', 'Wednesday' => 'Keskiviikko', 'Wed' => 'Ke', 'Thursday' => 'Torstai', 'Thu' => 'To', 'Friday' => 'Perjantai', 'Fri' => 'Pe', 'Saturday' => 'Lauantai', 'Sat' => 'La' ); %month = ( 'January' => 'Tammi', 'February' => 'Helmi' , 'March' => 'Maalis', 'Jan' => 'Tam', 'Feb' => 'Hel', 'Mar' => 'Maa', 'April' => 'Huhti', 'May' => 'Touko', 'June' => 'Kesä', 'Apr' => 'Huh', 'May' => 'Tou', 'Jun' => 'Kes', 'July' => 'Heinä', 'August' => 'Elo', 'September' => 'Syys', 'Jul' => 'Hei', 'Aug' => 'Elo', 'Sep' => 'Syy', 'October' => 'Loka', 'November' => 'Marras', 'December' => 'Joulu', 'Oct' => 'Lok', 'Nov' => 'Mar', 'Dec' => 'Kou' ); # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if( $wday{$foo[0]} && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." kello ".$quux[1]; }; return "$wday{$foo[0]}, $foo[1]. $month{$foo[2]} $foo[3]"; }; # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/galician.pmd0000644000175300017510000001273513057016062016124 0ustar oetikeroep###### PATCHTAG00 #################################################### ### Galician/Galego ### => David Garabana Barro ###### PATCHTAG10 #################################################### &galician ###### PATCHTAG20 #################################################### 'galician' => \&galician, 'galego' => \&galician, ###### PATCHTAG30 #################################################### # Galician/Galego 'galician' => "Traducido ao galego por David Garabana Barro <dgaraban\@arrakis.es>", ###### PATCHTAG40 #################################################### $credits::LOCALE{'galego'}=$credits::LOCALE{'galician'}; ###### PATCHTAG50 #################################################### # Galician sub galician { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Tr&áfico entrante máximo en 5 minutos', 'Maximal 5 Minute Outgoing Traffic' => 'Tr&áfico saínte máximo en 5 minutos', 'the device' => 'o dispositivo', 'The statistics were last updated(.*)' => 'Estas estatísticas actualizáronse o $1', ' Average\)' => ' de Media)', 'Average' => 'Media', 'Max' => 'Máx', 'Current' => 'Actual', 'version' => 'versión', '`Daily\' Graph \((.*) Minute' => 'Gráfica diaria ($1 minutos', '`Weekly\' Graph \(30 Minute' => 'Gráfica semanal (30 minutos' , '`Monthly\' Graph \(2 Hour' => 'Gráfica mensual (2 horas', '`Yearly\' Graph \(1 Day' => 'Gráfica anual (1 día', 'Incoming Traffic in (\S+) per Second' => 'Tráfico entrante en $1 por segundo', 'Outgoing Traffic in (\S+) per Second' => 'Tráfico saínte en $1 por segundo', 'at which time (.*) had been up for(.*)' => 'nese intre $1 levaba prendida $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/h', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Entrante', 'Out' => 'Saínte', 'Percentage' => 'Tanto por ciento', 'Ported to OpenVMS Alpha by' => 'Portado a OpenVMS Alpha por', 'Ported to WindowsNT by' => 'Portado a Windows NT por', 'and' => 'e', '^GREEN' => 'VERDE', 'BLUE' => 'AZUL', 'DARK GREEN' => 'VERDE OSCURO', 'MAGENTA' => 'ROSA', 'AMBER' => 'AMBAR' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Domingo', 'Sun' => 'Dom', 'Monday' => 'Luns', 'Mon' => 'Lun', 'Tuesday' => 'Martes', 'Tue' => 'Mar', 'Wednesday' => 'Mércores', 'Wed' => 'mér', 'Thursday' => 'Xoves', 'Thu' => 'Xov', 'Friday' => 'Venres', 'Fri' => 'Ven', 'Saturday' => 'Sábado', 'Sat' => 'Sáb' ); %month = ( 'January' => 'Xaneiro', 'February' => 'Febreiro' , 'March' => 'Marzo', 'Jan' => 'Xan', 'Feb' => 'Feb', 'Mar' => 'Mar', 'April' => 'Abril', 'May' => 'Maio', 'June' => 'Xuño', 'Apr' => 'Abr', 'May' => 'Mai', 'Jun' => 'Xuñ', 'July' => 'Xullo', 'August' => 'Agosto', 'September' => 'Setembro', 'Jul' => 'Xul', 'Aug' => 'Ago', 'Sep' => 'Set', 'October' => 'Outubro', 'November' => 'Novembro', 'December' => 'Decembro', 'Oct' => 'Out', 'Nov' => 'Nov', 'Dec' => 'Dec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." ás ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] de $month{$foo[2]} de $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/spanish.pmd0000644000175300017510000001160114171553254016020 0ustar oetikeroep###### PATCHTAG00 #################################################### ### Spanish/Español ### => Marcelo Roccasalva ###### PATCHTAG10 #################################################### &spanish ###### PATCHTAG20 #################################################### 'spanish' => \&spanish, 'espanol' => \&spanish, ###### PATCHTAG30 #################################################### # Spanish/español 'spanish' => "Preparado para localización por Marcelo Roccasalva", ###### PATCHTAG40 #################################################### $credits::LOCALE{'espanol'}=$credits::LOCALE{'spanish'}; ###### PATCHTAG50 #################################################### # Spanish sub spanish { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... %translations = ( #'iso-8859-1' => 'iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Tráfico entrante máximo en 5 minutos', 'Maximal 5 Minute Outgoing Traffic' => 'Tráfico saliente máximo en 5 minutos', 'the device' => 'el dispositivo', 'The statistics were last updated(.*)' => 'Estadísticas actualizadas el $1', ' Average\)' => ' Promedio)', 'Average' => 'Promedio', 'Max' => 'Máx', 'Current' => 'Actual', 'version' => 'version', '`Daily\' Graph \((.*) Minute' => 'Gráfico diario ($1 minutos :', '`Weekly\' Graph \(30 Minute' => 'Gráfico semanal (30 minutos :' , '`Monthly\' Graph \(2 Hour' => 'Gráfico mensual (2 horas :', '`Yearly\' Graph \(1 Day' => 'Gráfico anual (1 día :', 'Incoming Traffic in (\S+) per Second' => 'Tráfico entrante en $1 por segundo', 'Outgoing Traffic in (\S+) per Second' => 'Tráfico saliente en $1 por segundo', 'at which time (.*) had been up for(.*)' => '$1 ha estado funcionando durante $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', # '([kMG]?)([bB])/h' => '$1$2/t', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Entrante:', 'Out' => 'Saliente:', 'Percentage' => 'Porcentaje:', 'Ported to OpenVMS Alpha by' => 'Portado a OpenVMS Alpha por', 'Ported to WindowsNT by' => 'Portado a WindowsNT por', 'and' => 'y', '^GREEN' => 'VERDE', 'BLUE' => 'AZUL', 'DARK GREEN' => 'VERDE OSCURO', 'MAGENTA' => 'MAGENTA', 'AMBER' => 'AMBAR' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Domingo', 'Sun' => 'Dom', 'Monday' => 'Lunes', 'Mon' => 'Lun', 'Tuesday' => 'Martes', 'Tue' => 'Mar', 'Wednesday' => 'Miércoles','Wed' => 'Mié', 'Thursday' => 'Jueves', 'Thu' => 'Jue', 'Friday' => 'Viernes', 'Fri' => 'Vie', 'Saturday' => 'Sábado', 'Sat' => 'Sab' ); %month = ( 'January' => 'Enero', 'February' => 'Febrero' , 'March' => 'Marzo', 'Jan' => 'Ene', 'Feb' => 'Feb', 'Mar' => 'Mar', 'April' => 'Abril', 'May' => 'Mayo', 'June' => 'Junio', 'Apr' => 'Abr', 'May' => 'Mai', 'Jun' => 'Jun', 'July' => 'Julio', 'August' => 'Agosto', 'September' => 'Setiembre', 'Jul' => 'Jul', 'Aug' => 'Ago', 'Sep' => 'Set', 'October' => 'Octubre', 'November' => 'Noviembre', 'December' => 'Diciembre', 'Oct' => 'Oct', 'Nov' => 'Nov', 'Dec' => 'Dic' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." a las ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] de $month{$foo[2]} de $foo[3]"; }; return $string; } mrtg-2.17.10/translate/chinese.pmd0000644000175300017510000001232313057016062015764 0ustar oetikeroep###### PATCHTAG00 #################################################### ### Simplified Chinese/ ### => ƻ ### => QQ:582955 ӭFreeBSD ### => ԭĴ.°汾. ###### PATCHTAG10 #################################################### &chinese ###### PATCHTAG20 #################################################### 'chinese' => \&chinese, '' => \&chinese, ###### PATCHTAG30 #################################################### # Simplified Chinese/ 'chinese' => "ȫ¼ĺ ƻ <webmaster\@kingisme.com>", ###### PATCHTAG40 #################################################### $credits::LOCALE{''}=$credits::LOCALE{'Chinese'}; ###### PATCHTAG50 #################################################### # Simplified Chinese sub chinese { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... %translations = ( 'iso-8859-1' => 'gb2312', 'Maximal 5 Minute Incoming Traffic' => '5', 'Maximal 5 Minute Outgoing Traffic' => '5', 'the device' => '豸', 'The statistics were last updated(.*)' => 'ͳƸʱ䣺$1', ' Average\)' => ' ƽ)', 'Average' => 'ƽ', 'Max' => '', 'Current' => 'ǰ', 'version' => '汾', '`Daily\' Graph \((.*) Minute' => 'ÿ ͼ ($1 ', '`Weekly\' Graph \(30 Minute' => 'ÿ ͼ (30 ' , '`Monthly\' Graph \(2 Hour' => 'ÿ ͼ (2 Сʱ', '`Yearly\' Graph \(1 Day' => 'ÿ ͼ (1 ', 'Incoming Traffic in (\S+) per Second' => 'ÿ (λ $1 )', 'Outgoing Traffic in (\S+) per Second' => 'ÿ (λ $1 )', 'at which time (.*) had been up for(.*)' => ' $1 ˣ $2 ', '(.+)/s$' => '$1/', '(.+)/min$' => '$1/', '(.+)/h$' => '$1/ʱ', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => '룺', 'Out' => '', 'Percentage' => 'ٷֱȣ', 'Ported to OpenVMS Alpha by' => 'ֲ OpenVMS ', 'Ported to WindowsNT by' => 'ֲ WindowsNT ', 'and' => '', '^GREEN' => 'ɫ', 'BLUE' => 'ɫ', 'DARK GREEN' => 'ī', 'MAGENTA' => 'ɫ', 'AMBER' => 'ɫ' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => '', 'Sun' => '', 'Monday' => 'һ', 'Mon' => 'һ', 'Tuesday' => 'ڶ', 'Tue' => '', 'Wednesday' => '', 'Wed' => '', 'Thursday' => '', 'Thu' => '', 'Friday' => '', 'Fri' => '', 'Saturday' => '', 'Sat' => '' ); %month = ( 'January' => ' һ ', 'February' => ' ', 'March' => ' ', 'April' => ' ', 'May' => ' ', 'June' => ' ', 'July' => ' ', 'August' => ' ', 'September' => ' ', 'October' => ' ʮ ', 'November' => 'ʮһ', 'December' => 'ʮ', 'Jan' => '', 'Feb' => '', 'Mar' => '', 'Apr' => '', 'May' => '', 'Jun' => '', 'Jul' => '', 'Aug' => '', 'Sep' => '', 'Oct' => '10', 'Nov' => '11', 'Dec' => '12' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]; $foo[4]=$quux[1]; }; return "$foo[3] $month{$foo[2]} $foo[1] $wday{$foo[0]} $foo[4]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/brazilian.pmd0000644000175300017510000001346214171553254016335 0ustar oetikeroep###### PATCHTAG00 #################################################### ### Brazil/Brazilian Portuguese ### => Luiz Felipe R E ### => Gleydson Mazoli da Silva (Atualização) ###### PATCHTAG10 #################################################### &brazilian ###### PATCHTAG20 #################################################### 'brazil' => \&brazilian, 'brazilian' => \&brazilian, ###### PATCHTAG30 #################################################### # Brazil/brazilian 'brazilian' => "Localização efetuada por Luiz Felipe R E <luizfelipe\@encarnacao.com>
atualização por Gleydson Mazioli da Silva <gleydson\@debian.org>", ###### PATCHTAG40 #################################################### $credits::LOCALE{'brazil'}=$credits::LOCALE{'brazilian'}; ###### PATCHTAG50 #################################################### # Brazilian (Portugues) sub brazilian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Tráfego Máximo de Entrada em 5 minutos', 'Maximal 5 Minute Outgoing Traffic' => 'Tráfego Máximo de Saída em 5 minutos', 'the device' => 'dispositivo', 'The statistics were last updated (.*)' => 'Última atualização das estatísticas: $1', ' Average\)' => ' - média)', 'Average' => 'Média', 'Max' => 'Máx', 'Current' => 'Atual', 'version' => 'versão', '`Daily\' Graph \((.*) Minute' => 'Gráfico `Diário\' ($1 minutos', '`Weekly\' Graph \(30 Minute' => 'Gráfico `Semanal\' (30 minutos' , '`Monthly\' Graph \(2 Hour' => 'Gráfico `Mensal\' (2 horas', '`Yearly\' Graph \(1 Day' => 'Gráfico `Anual\' (1 dia', 'Incoming Traffic in (\S+) per Second' => 'Tráfego de Entrada em $1 por segundo', 'Outgoing Traffic in (\S+) per Second' => 'Tráfego de Saída em $1 por segundo', 'at which time (.*) had been up for(.*)' => 'nesta hora $1 estava ativo por $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', # '([kMG]?)([bB])/h' => '$1$2/t', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => 'Entr.', 'Out' => 'Saí', 'Percentage' => 'Porc.', 'Ported to OpenVMS Alpha by' => 'Adaptado para o Alpha OpenVMS por', 'Ported to WindowsNT by' => 'Adaptado para o WindowsNT por', 'and' => 'e', '^GREEN' => 'VERDE', 'BLUE' => 'AZUL', 'DARK GREEN' => 'VERDE ESCURO', 'MAGENTA' => 'LILÁS', 'AMBER' => 'AMBAR' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Domingo', 'Sun' => 'Dom', 'Monday' => 'Segunda', 'Mon' => 'Seg', 'Tuesday' => 'Terça', 'Tue' => 'Ter', 'Wednesday' => 'Quarta', 'Wed' => 'Qua', 'Thursday' => 'Quinta', 'Thu' => 'Qui', 'Friday' => 'Sexta', 'Fri' => 'Sex', 'Saturday' => 'Sábado', 'Sat' => 'Sáb' ); %month = ( 'January' => 'Janeiro', 'February' => 'Fevereiro' , 'March' => 'Março', 'Jan' => 'Jan', 'Feb' => 'Fev', 'Mar' => 'Mar', 'April' => 'Abril', 'May' => 'Maio', 'June' => 'Junho', 'Apr' => 'Abr', 'May' => 'Mai', 'Jun' => 'Jun', 'July' => 'Julho', 'August' => 'Agosto', 'September' => 'Setembro', 'Jul' => 'Jul', 'Aug' => 'Ago', 'Sep' => 'Set', 'October' => 'Outubro', 'November' => 'Novembro', 'December' => 'Dezembro', 'Oct' => 'Out', 'Nov' => 'Nov', 'Dec' => 'Dez' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." às ".$quux[1]; }; return "$wday{$foo[0]}, $foo[1] de $month{$foo[2]} de $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/ukrainian1251.pmd0000644000175300017510000001213413057016062016640 0ustar oetikeroep###### PATCHTAG00 #################################################### ### Ukrainian/ ### => Olexander Kunytsa ###### PATCHTAG10 #################################################### &ukrainian1251 ###### PATCHTAG20 #################################################### 'ukrainian1251' => \&ukrainian1251, '1251' => \&ukrainian1251, ###### PATCHTAG30 #################################################### # Ukrainian1251/1251 'ukrainian1251' => " (cp1251): <xakep\@snark.ukma.kiev.ua>", ###### PATCHTAG40 #################################################### $credits::LOCALE{'1251'}=$credits::LOCALE{'ukrainian1251'}; ###### PATCHTAG50 #################################################### # Ukrainian1251 - windowze encoding sub ukrainian1251 { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); %translations = ( 'iso-8859-1' => 'windows-1251', 'Maximal 5 Minute Incoming Traffic' => ' 5 ', 'Maximal 5 Minute Outgoing Traffic' => ' 5 ', 'the device' => '', 'The statistics were last updated(.*)' => ' : $1', ' Average\)' => ')', 'Average' => '', 'Max' => '', 'Current' => '', 'version' => '', '`Daily\' Graph \((.*) Minute' => ' ( $1 ', '`Weekly\' Graph \(30 Minute' => ' ( 30 ' , '`Monthly\' Graph \(2 Hour' => '̳ ( i ', '`Yearly\' Graph \(1 Day' => 'г ( ', 'Incoming Traffic in (\S+) per Second' => ' $1 ', 'Outgoing Traffic in (\S+) per Second' => ' $1 ', 'at which time (.*) had been up for(.*)' => '$1 䳿: $2', '([kMG]?)([bB])/s' => '$1$1/', '([kMG]?)([bB])/min' => '$1$2/', '([kMG]?)([bB])/h' => '$1$2/', '([bB])/s' => '$1/', '([bB])/min' => '$1/', '([bB])/h' => '$1/', 'Bits' => '', 'Bytes' => '', 'In' => '', 'Out' => '', 'Percentage' => '³', 'Ported to OpenVMS Alpha by' => ' OpenVMS Alpha', 'Ported to WindowsNT by' => ' WindowsNT', 'and' => '', 'RED' => '', '^GREEN' => '', 'BLUE' => 'Ͳ', 'DARK GREEN' => '', 'MAGENTA' => 'Բ', 'AMBER' => '', ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => ' ', 'Sun' => '', 'Monday' => ' ', 'Mon' => '', 'Tuesday' => ' ³', 'Tue' => '', 'Wednesday' => ' ', 'Wed' => '', 'Thursday' => ' ', 'Thu' => '', 'Friday' => ' \'', 'Fri' => '', 'Saturday' => ' ', 'Sat' => '' ); %month = ( 'January' => 'ѳ', 'February' => '' , 'March' => '', 'Jan' => 'ѳ', 'Feb' => '', 'Mar' => '', 'April' => '', 'May' => '', 'June' => '', 'Apr' => '', 'May' => '', 'Jun' => '', 'July' => '', 'August' => '', 'September' => '', 'Jul' => '', 'Aug' => '', 'Sep' => '', 'October' => '', 'November' => '', 'December' => '', 'Oct' => '', 'Nov' => '', 'Dec' => '' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].". ".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/fixer0000644000175300017510000000030313057016062014677 0ustar oetikeroep$x=' foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday'; s/foreach.+?wday/$x/s; mrtg-2.17.10/translate/macedonian.pmd0000644000175300017510000001306613057016062016451 0ustar oetikeroep###### PATCHTAG00 #################################################### ### Macedonian/Makedonski ### => Delev Zoran ###### PATCHTAG10 #################################################### &macedonian ###### PATCHTAG20 #################################################### 'macedonian' => \&macedonian, 'makedonski' => \&macedonian, ###### PATCHTAG30 #################################################### # Macedonian/makedonski 'macedonian' => "Makedonska lokalizacija - Delev D Zoran <delevz\@esmak.com.mk>", # the macedonian string means: "Prepared for languages and translated to macedonian by" ###### PATCHTAG40 #################################################### $credits::LOCALE{'macedonian'}=$credits::LOCALE{'macedonian'}; ###### PATCHTAG50 #################################################### # Macedonian sub macedonian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=windows-1251', 'Maximal 5 Minute Incoming Traffic' => ' 5 ', 'Maximal 5 Minute Outgoing Traffic' => ' 5 ', 'the device' => '', 'The statistics were last updated(.*)' => ' $1', ' Average\)' => ' )', 'Average' => '', 'Max' => '', 'Current' => 'o', 'version' => '', '`Daily\' Graph \((.*) Minute' => '`\' ($1 ', '`Weekly\' Graph \(30 Minute' => '`\' (30 ' , '`Monthly\' Graph \(2 Hour' => '`\' (2 ', '`Yearly\' Graph \(1 Day' => '`\' (1 ', 'Incoming Traffic in (\S+) per Second' => ' - $1 ', 'Outgoing Traffic in (\S+) per Second' => ' - $1 ', 'at which time (.*) had been up for(.*)' => ' $1 : $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/h', # 'Bits' => '', # 'Bytes' => '' 'In' => '', 'Out' => '', 'Percentage' => '', 'Ported to OpenVMS Alpha by' => ' OpenVMS ', 'Ported to WindowsNT by' => ' WindowsNT ', 'and' => '', '^GREEN' => '', 'BLUE' => '', 'DARK GREEN' => ' ', 'MAGENTA' => '', 'AMBER' => '' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => '', 'Sun' => '', 'Monday' => '', 'Mon' => '', 'Tuesday' => '', 'Tue' => '', 'Wednesday' => '', 'Wed' => '', 'Thursday' => '', 'Thu' => '', 'Friday' => '', 'Fri' => '', 'Saturday' => '', 'Sat' => '' ); %month = ( 'January' => '', 'February' => '' , 'March' => '', 'Jan' => '', 'Feb' => '', 'Mar' => '', 'April' => '', 'May' => '', 'June' => '', 'Apr' => '', 'May' => '', 'Jun' => '', 'July' => '', 'August' => '', 'September' => '', 'Jul' => '', 'Aug' => '', 'Sep' => '', 'October' => '', 'November' => '', 'December' => '', 'Oct' => '', 'Nov' => '', 'Dec' => '' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." kl.".$quux[1]; }; return "$wday{$foo[0]} $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; };mrtg-2.17.10/translate/czechutf8.pmd0000644000175300017510000001230313057016062016247 0ustar oetikeroep###### PATCHTAG 00 ################################################### ### Czech/Česky ### => David Toman ###### PATCHTAG 10 ################################################### &czechutf8 ###### PATCHTAG 20 ################################################### 'czechutf8' => \&czechutf8, ###### PATCHTAG 30 ################################################### # Czechutf8/Česky 'czechutf8' => "Český překlad do UTF-8 připravil David Toman <david\@idkfa.cz>", ###### PATCHTAG 40 ################################################### $credits::LOCALE{'czechutf8'}=$credits::LOCALE{'czechutf8'}; ###### PATCHTAG 50 ################################################### # Czechutf8 sub czechutf8 { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'utf-8', 'Maximal 5 Minute Incoming Traffic' => 'Maximální 5 minutový příchozí tok', 'Maximal 5 Minute Outgoing Traffic' => 'Maximální 5 minutový odchozí tok', 'the device' => 'zařízení', 'The statistics were last updated(.*)' => 'Poslední aktualizace statistiky:$1', ' Average\)' => ' průměr)', 'Average' => 'Prům.', 'Max' => 'Max.', 'Current' => 'Akt.', 'version' => 'verze', '`Daily\' Graph \((.*) Minute' => 'Denní graf ($1 minutový', '`Weekly\' Graph \(30 Minute' => 'Týdenní graf (30 minutový' , '`Monthly\' Graph \(2 Hour' => 'Měsíční graf (2 hodinový', '`Yearly\' Graph \(1 Day' => 'Roční graf (1 denní', 'Incoming Traffic in (\S+) per Second' => 'Příchozí tok v $1 za sec.', 'Outgoing Traffic in (\S+) per Second' => 'Odchozí tok v $1 za sec.', 'at which time (.*) had been up for(.*)' => 'od posledního restartu $1 uběhlo: $2', #'([kMG]?)([bB])/s' => '\$1\$2/s', #'([kMG]?)([bB])/min' => '\$1\$2/min', #'([kMG]?)([bB])/h' => '$1$2/h', 'Bits' => 'bitech', 'Bytes' => 'bajtech', #' In:' => ' In:', #' Out:' => ' Out:', 'Percentage' => 'Proc.', 'Ported to OpenVMS Alpha by' => 'Na OpenVMS portoval', 'Ported to WindowsNT by' => 'Na WindowsNT portoval', 'and' => 'a', '^GREEN' => 'Zelená', 'BLUE' => 'Modrá', 'DARK GREEN' => 'Tmavě zelená', 'MAGENTA' => 'Fialová', 'AMBER' => 'Žlutá' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Neděle', 'Sun' => 'Ne', 'Monday' => 'Pondělí', 'Mon' => 'Po', 'Tuesday' => 'Úterý', 'Tue' => 'Út', 'Wednesday' => 'Středa', 'Wed' => 'St', 'Thursday' => 'Čtvrtek', 'Thu' => 'Čt', 'Friday' => 'Pátek', 'Fri' => 'Pá', 'Saturday' => 'Sobota', 'Sat' => 'So' ); %month = ( 'January' => 'Leden', 'February' => 'Únor', 'March' => 'Březen', 'Jan' => 'Leden', 'Feb' => 'Únor', 'Mar' => 'Březen', 'April' => 'Duben', 'May' => 'Květen', 'June' => 'Červen', 'Apr' => 'Duben', 'May' => 'Květen', 'Jun' => 'Červen', 'July' => 'Červenec','August' => 'Srpen', 'September' => 'Září', 'Jul' => 'Červenec','Aug' => 'Srpen', 'Sep' => 'Září', 'October' => 'Říjen', 'November' => 'Listopad', 'December' => 'Prosinec', 'Oct' => 'Říjen', 'Nov' => 'Listopad', 'Dec' => 'Prosinec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].",".$quux[1]." hod."; }; return "$wday{$foo[0]} $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; } # mrtg-2.17.10/translate/german.pmd.backup0000644000175300017510000001504613057016062017070 0ustar oetikeroep###### PATCHTAG 00 ################################################### ### German/Deutsch ### => Ilja Pavkovic ###### PATCHTAG 10 ################################################### &german ###### PATCHTAG 20 ################################################### 'german' => \&german, 'german' => \&german, ###### PATCHTAG 30 ################################################### # German/deutsch 'german' => "
Vorbereitet fr die Lokalisation von Ilja Pavkovic <illsen\@gumblfarz.de>", ###### PATCHTAG 40 ################################################### $credits::LOCALE{'deutsch'}=$credits::LOCALE{'german'}; ###### PATCHTAG 50 ################################################### # German sub german { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Maximaler hereinkommender Traffic in 5 Minuten', 'Maximal 5 Minute Outgoing Traffic' => 'Maximaler hinausgehender Traffic in 5 Minuten', 'the device' => 'das Gert', 'The statistics were last updated(.*)' => 'Die Statistiken wurden am $1 zuletzt aktualisiert', ' Average\)
' => '', 'Average(.*)' => 'Mittel$1', 'Max(.*)' => 'Maximal$1', 'Current(.*)' => 'Aktuell$1', 'version' => 'Version', '`Daily\' Graph \((.*) Minute' => 'Tagesübersicht (Skalierung $1 Minute(n))
', '`Weekly\' Graph \(30 Minute' => 'Wochenübersicht (Skalierung 30 Minuten)
' , '`Monthly\' Graph \(2 Hour' => 'Monatsübersicht (Skalierung 2 Stunden)
', '`Yearly\' Graph \(1 Day' => 'Jahresübersicht (Skalierung 1 Tag)
', 'Incoming Traffic in (\S+) per Second' => 'Hereinkommender Traffic in $1 pro Sekunde', 'Outgoing Traffic in (\S+) per Second' => 'Hinausgehender Traffic in $1 pro Sekunde', 'Incoming Traffic in (\S+) per Minute' => 'Hereinkommender Traffic in $1 pro Minute', 'Outgoing Traffic in (\S+) per Minute' => 'Hinausgehender Traffic in $1 pro Minute', 'Incoming Traffic in (\S+) per Hour' => 'Hereinkommender Traffic in $1 pro Stunde', 'Outgoing Traffic in (\S+) per Hour' => 'Hinausgehender Traffic in $1 pro Stunde', 'at which time (.*) had been up for(.*)' => 'zu diesem Zeitpunkt lief $1 seit $2', '(\S+) per minute' => '$1 pro Minute', '(\S+) per hour' => '$1 pro Stunde', '(.+)/s$' => '$1/s', # '(.+)/min' => '$1/min', '(.+)/h$' => '$1/std', #'([kMG]?)([bB])/s' => '$1$2/s', #'([kMG]?)([bB])/min' => '$1$2/min', #'([kMG]?)([bB])/h' => '$1$2/std', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' ' In:' => ' Herein:', ' Out:' => ' Hinaus:', ' Percentage' => ' Prozent:', 'Ported to OpenVMS Alpha by' => 'Portierung nach OpenVMS von', 'Ported to WindowsNT by' => 'Portierung nach WindowsNT von', 'and' => 'und', '^GREEN' => 'GRÜN', 'BLUE' => 'BLAU', 'DARK GREEN' => 'DUNKELGRÜN', # 'MAGENTA' => 'ROSA', # 'AMBER' => 'AMBER', ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { if(defined $i && defined $string && $string=~/$i/) { (@dollar)=($string=~/()$i/); # I hope this prevents the autovars $string=$translations{$i}; # And it only works from $1-$9 for($j=1;$dollar[$j];$j++) # s/// doesn't do any good with saved "$1"-exprs. { @quux=(); (@quux)=split(/\$$j/,$string); $string=$quux[0].$dollar[$j].$quux[1]; } ; return $string; }; }; %wday = ( 'Sunday' => 'Sonntag', 'Sun' => 'So', 'Monday' => 'Montag', 'Mon' => 'Mo', 'Tuesday' => 'Dienstag', 'Tue' => 'Di', 'Wednesday' => 'Mittwoch', 'Wed' => 'Mi', 'Thursday' => 'Donnerstag', 'Thu' => 'Do', 'Friday' => 'Freitag', 'Fri' => 'Fr', 'Saturday' => 'Samstag', 'Sat' => 'Sa' ); %month = ( 'January' => 'Januar', 'February' => 'Februar' , 'March' => 'März', 'Jan' => 'Jan', 'Feb' => 'Feb', 'Mar' => 'Mär', 'April' => 'April', 'May' => 'Mai', 'June' => 'Juni', 'Apr' => 'Apr', 'May' => 'Mai', 'Jun' => 'Jun', 'July' => 'Juli', 'August' => 'August', 'September' => 'September', 'Jul' => 'Jul', 'Aug' => 'Aug', 'Sep' => 'Sep', 'October' => 'Oktober', 'November' => 'November', 'December' => 'Dezember', 'Oct' => 'Okt', 'Nov' => 'Nov', 'Dec' => 'Dez' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." um ".$quux[1]; }; return "$wday{$foo[0]}, den $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/serbian.pmd0000644000175300017510000001257013057016062015775 0ustar oetikeroep###### PATCHTAG 00 ################################################### ### Serbian/Srpski ### => Ratko Bucic ###### PATCHTAG 10 ################################################### &serbian ###### PATCHTAG 20 ################################################### 'serbian' => \&serbian, ###### PATCHTAG 30 ################################################### # Serbian/Srpski 'serbian' => "Ported to Serbian by / Srpski prevod uradio: Ratko Bui <ratko\@ni.ac.yu>", ###### PATCHTAG 40 ################################################### $credits::LOCALE{'serbian'}=$credits::LOCALE{'serbian'}; ###### PATCHTAG 50 ################################################### # Serbian sub serbian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'windows-1250', 'Maximal 5 Minute Incoming Traffic' => 'Najvei 5 minutni ulazni saobraaj', 'Maximal 5 Minute Outgoing Traffic' => 'Najvei 5 minutni izlazni saobraaj', 'the device' => 'uredjaj', 'The statistics were last updated(.*)' => 'Poslednje auriranje podataka:$1', ' Average\)' => ' prosek)', 'Average' => 'Proseni', 'Max' => 'Maksimalni', 'Current' => 'Trenutni', 'version' => 'verzija', '`Daily\' Graph \((.*) Minute' => 'Dnevni graf ($1 minutni ', '`Weekly\' Graph \(30 Minute' => 'Nedeljni graf (30 minutni ' , '`Monthly\' Graph \(2 Hour' => 'Meseni graf (2 sata ', '`Yearly\' Graph \(1 Day' => 'Godinji graf (1 dnevni ', 'Incoming Traffic in (\S+) per Second' => 'Ulazni saobraaj - $1 u sekundi.', 'Outgoing Traffic in (\S+) per Second' => 'Izlazni saobraaj - $1 u sekundi.', 'Incoming Traffic in (\S+) per Minute' => 'Ulazni saobraaj - $1 u minutu', 'Outgoing Traffic in (\S+) per Minute' => 'Izlazni saobraaj - $1 u minutu', 'Incoming Traffic in (\S+) per Hour' => 'Ulazni saobraaj - $1 na sat', 'Outgoing Traffic in (\S+) per Hour' => 'Izlazni saobraaj - $1 na sat', 'at which time (.*) had been up for(.*)' => 'Vreme neprekidnog rada sistema $1 : $2', #'([kMG]?)([bB])/s' => '\$1\$2/s', #'([kMG]?)([bB])/min' => '\$1\$2/min', #'([kMG]?)([bB])/h' => '$1$2/h', 'Bits' => 'Bita', 'Bytes' => 'Bajta', 'In' => 'Ulaz', 'Out' => 'Izlaz', 'Percentage' => 'Procenat', 'Ported to OpenVMS Alpha by' => 'Na OpenVMS portovao', 'Ported to WindowsNT by' => 'Na WindowsNT portovao', 'and' => 'i', '^GREEN' => 'Zeleno', 'BLUE' => 'Plavo', 'DARK GREEN' => 'Tamnozeleno', 'MAGENTA' => 'Ljubiasto', 'AMBER' => 'Narandasto' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Nedelja', 'Sun' => 'Ned', 'Monday' => 'Ponedeljak', 'Mon' => 'Pon', 'Tuesday' => 'Utorak', 'Tue' => 'Uto', 'Wednesday' => 'Sreda', 'Wed' => 'Sre', 'Thursday' => 'etvrtak', 'Thu' => 'et', 'Friday' => 'Petak', 'Fri' => 'Pet', 'Saturday' => 'Subota', 'Sat' => 'Sub' ); %month = ( 'January' => 'januar', 'February' => 'februar', 'March' => 'mart', 'Jan' => 'Jan', 'Feb' => 'Feb', 'Mar' => 'Mar', 'April' => 'april', 'May' => 'maj', 'June' => 'jun', 'Apr' => 'Apr', 'May' => 'Maj', 'Jun' => 'Jun', 'July' => 'jul', 'August' => 'avgust', 'September' => 'septembar', 'Jul' => 'Jul', 'Aug' => 'Avg', 'Sep' => 'Sep', 'October' => 'oktobar','November' => 'novembar','December' => 'decembar', 'Oct' => 'Okt', 'Nov' => 'Nov', 'Dec' => 'Dec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].",".$quux[1]." "; }; return "$wday{$foo[0]} $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; } # mrtg-2.17.10/translate/hungarian.pmd0000644000175300017510000001324013057016062016321 0ustar oetikeroep###### PATCHTAG00 #################################################### ### Hungarian/Magyar ### => Levente Nagy ###### PATCHTAG10 #################################################### &hungarian ###### PATCHTAG20 #################################################### 'hungarian' => \&hungarian, 'magyar' => \&hungarian, ###### PATCHTAG30 #################################################### # Hungarian/magyar 'hungarian' => "Magyarosította Nagy Levente <levinet\@euroweb.hu>", # the hungarian string means: "Prepared for languages and translated to Hungarian by" ###### PATCHTAG40 #################################################### $credits::LOCALE{'magyar'}=$credits::LOCALE{'hungarian'}; ###### PATCHTAG50 #################################################### # Hungarian sub hungarian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-2', 'Maximal 5 Minute Incoming Traffic' => 'Maximális bejövõ forgalom 5 perc alatt', 'Maximal 5 Minute Outgoing Traffic' => 'Maximális kimenõ forgalom 5 perc alatt', 'the device' => 'az eszköz', 'The statistics were last updated(.*)' => 'A statisztika utolsó frissítése:$1', ' Average\)' => ' átlag)', 'Average' => 'Átlagos', 'Max' => 'Maximum', 'Current' => 'Pillanatnyi', 'version' => 'verzió', '`Daily\' Graph \((.*) Minute' => '`Napi\' grafikon ($1 perces', '`Weekly\' Graph \(30 Minute' => '`Heti\' grafikon (30 perces' , '`Monthly\' Graph \(2 Hour' => '`Havi\' grafikon (2 órás', '`Yearly\' Graph \(1 Day' => '`Éves\' grafikon (1 napos', 'Incoming Traffic in (\S+) per Second' => 'Bejövõ forgalom $1 per másodpercben', 'Outgoing Traffic in (\S+) per Second' => 'Kimenõ forgalom $1 per másodpercben', 'at which time (.*) had been up for(.*)' => 'amikor a $1 üzemideje $2 volt.', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/t', 'Bits' => 'Bit', 'Bytes' => 'Byte', 'In' => 'be', 'Out' => 'ki', 'Percentage' => 'százale´k', 'Ported to OpenVMS Alpha by' => 'OpenVMS-re portolta', 'Ported to WindowsNT by' => 'WindowsNT-re portolta', 'and' => 'és', '^GREEN' => 'ZÖLD', 'BLUE' => 'KÉK', 'DARK GREEN' => 'SÖTÉT ZÖLD', 'MAGENTA' => 'BÍBOR', 'AMBER' => 'SÁRGA' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'vasárnap', 'Sun' => 'vas', 'Monday' => 'hétfõ', 'Mon' => 'hét', 'Tuesday' => 'kedd', 'Tue' => 'kedd', 'Wednesday' => 'szerda', 'Wed' => 'sze', 'Thursday' => 'csütörtök','Thu' => 'csüt', 'Friday' => 'péntek', 'Fri' => 'pén', 'Saturday' => 'szombat', 'Sat' => 'szo' ); %month = ( 'January' => 'január', 'February' => 'február' , 'March' => 'március', 'Jan' => 'jan', 'Feb' => 'feb', 'Mar' => 'marc', 'April' => 'április', 'May' => 'május', 'June' => 'június', 'Apr' => 'apr', 'May' => 'maj', 'Jun' => 'jun', 'July' => 'július', 'August' => 'augusztus', 'September' => 'szeptember', 'Jul' => 'jul', 'Aug' => 'aug', 'Sep' => 'szept', 'October' => 'október', 'November' => 'november', 'December' => 'december', 'Oct' => 'okt', 'Nov' => 'nov', 'Dec' => 'dec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." kl.".$quux[1]; }; return "$quux[0]. $month{$foo[2]} $foo[1]., $wday{$foo[0]} $quux[1]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/estonian.pmd0000644000175300017510000001272513057016062016174 0ustar oetikeroep###### PATCHTAG00 #################################################### ### Estonian/Eesti ### => Klemens Kasemaa ###### PATCHTAG10 #################################################### &estonian ###### PATCHTAG20 #################################################### 'estonian' => \&estonian, 'eesti' => \&estonian, ###### PATCHTAG30 #################################################### # Estonian/Eesti 'estonian' => "Tõlge eesti keelde Klemens Kasemaa <klem\@linux.ee>", # the estonian string means: "Translation to estonian by" ###### PATCHTAG40 #################################################### $credits::LOCALE{'eesti'}=$credits::LOCALE{'estonian'}; ###### PATCHTAG50 #################################################### # Estonian sub estonian { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => '5 minuti maksimaalne sisenev liiklus', 'Maximal 5 Minute Outgoing Traffic' => '5 minuti maksimaalne väljuv liiklus', 'the device' => 'seade', 'The statistics were last updated(.*)' => 'Statistikat uuendati viimati$1', ' Average\)' => ' keskmine)', 'Average' => 'Keskmine', #'Max' => 'Max', 'Current' => 'Hetkel', 'version' => 'versioon', '`Daily\' Graph \((.*) Minute' => '`Päevane\' graafik ($1 minuti', '`Weekly\' Graph \(30 Minute' => '`Nädala\' graafik (30 minuti' , '`Monthly\' Graph \(2 Hour' => '`Kuu \' graafik (2 tunni', '`Yearly\' Graph \(1 Day' => '`Aasta\' graafik (1 päeva', 'Incoming Traffic in (\S+) per Second' => 'Sisenev liiklus $1 sekundi kohta', 'Outgoing Traffic in (\S+) per Second' => 'Väljuv liiklus $1 sekundi kohta', 'at which time (.*) had been up for(.*)' => 'kui $1 on katkematult töötanud$2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/t', 'Bits' => 'bitti', 'Bytes' => 'baiti', 'In' => 'sisse', 'Out' => 'välja', 'Percentage' => 'protsent', 'Ported to OpenVMS Alpha by' => 'portis OpenVMS-le:', 'Ported to WindowsNT by' => 'portis WindowsNT-le:', 'and' => 'ja', '^GREEN' => 'ROHELINE', 'BLUE' => 'SININE', 'DARK GREEN' => 'TUMEROHELINE', 'MAGENTA' => 'LILLA', 'AMBER' => 'HELEROHELINE' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'pühapäev', 'Sun' => 'P', 'Monday' => 'esmaspäev', 'Mon' => 'E', 'Tuesday' => 'teisipäev', 'Tue' => 'T', 'Wednesday' => 'kolmapäev', 'Wed' => 'K', 'Thursday' => 'neljapäev', 'Thu' => 'N', 'Friday' => 'reede', 'Fri' => 'R', 'Saturday' => 'laupäev', 'Sat' => 'L' ); %month = ( 'January' => 'jaanuar', 'February' => 'veebruar' , 'March' => 'märts', 'Jan' => 'jaan', 'Feb' => 'veebr', 'Mar' => 'märts', 'April' => 'aprill', 'May' => 'mai', 'June' => 'juuni', 'Apr' => 'aprill', 'May' => 'mai', 'Jun' => 'juuni', 'July' => 'juuli', 'August' => 'august', 'September' => 'september', 'Jul' => 'juuli', 'Aug' => 'aug', 'Sep' => 'sept', 'October' => 'oktoober', 'November' => 'november', 'December' => 'detsember', 'Oct' => 'okt', 'Nov' => 'nov', 'Dec' => 'dets' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." kl.".$quux[1]; }; return "$wday{$foo[0]}, $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/dutch.pmd0000644000175300017510000001272313057016062015461 0ustar oetikeroep###### PATCHTAG00 #################################################### ### Dutch/Nederlands ### => Barry van Dijk ###### PATCHTAG10 #################################################### &dutch ###### PATCHTAG20 #################################################### 'dutch' => \&dutch, 'nederlands' => \&dutch, ###### PATCHTAG30 #################################################### # Dutch/nederlands 'dutch' => "Vertaald naar het Nederlands door Barry van Dijk <barry\@dijk.com>
; Aangepast door Paul Slootman <paul\@debian.org>", ###### PATCHTAG40 #################################################### $credits::LOCALE{'nederlands'}=$credits::LOCALE{'dutch'}; ###### PATCHTAG50 #################################################### # Dutch sub dutch { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... %translations = ( #'charset=iso-8859-1' => 'charset=iso-8859-1', 'Maximal 5 Minute Incoming Traffic' => 'Maximaal inkomend verkeer per 5 minuten', 'Maximal 5 Minute Outgoing Traffic' => 'Maximaal uitgaand verkeer per 5 minuten', 'the device' => 'het apparaat', 'The statistics were last updated(.*)' => 'Statistieken voor het laatst bijgewerkt op$1', ' Average\)' => ' gemiddeld)', 'Average' => 'Gemiddeld', 'Max' => 'Max', 'Current' => 'Actueel', 'version' => 'versie', '`Daily\' Graph \((.*) Minute' => '`Dagelijkse\' grafiek ($1 minuten', '`Weekly\' Graph \(30 Minute' => '`Wekelijkse\' grafiek (30 minuten' , '`Monthly\' Graph \(2 Hour' => '`Maandelijkse\' grafiek (2 uur', '`Yearly\' Graph \(1 Day' => '`Jaarlijkse\' grafiek (1 dag', 'Incoming Traffic in (\S+) per Second' => 'Inkomend verkeer in $1 per seconde', 'Outgoing Traffic in (\S+) per Second' => 'Uitgaand verkeer in $1 per seconde', 'at which time (.*) had been up for(.*)' => 'op het moment dat $1 reeds actief was voor$2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/u', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' # ' In:' => ' In:', 'Out' => 'Uit', 'Percentage' => 'Procent', 'Ported to OpenVMS Alpha by' => 'Ported naar OpenVMS door', 'Ported to WindowsNT by' => 'Ported naar WindowsNT door', 'and' => 'en', 'DARK GREEN' => 'DONKER GROEN', '^GREEN' => 'GROEN', 'BLUE' => 'BLAUW', 'MAGENTA' => 'LILA', 'AMBER' => 'AMBER' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'zondag', 'Sun' => 'zon', 'Monday' => 'maandag', 'Mon' => 'maa', 'Tuesday' => 'dinsdag', 'Tue' => 'din', 'Wednesday' => 'woensdag', 'Wed' => 'woe', 'Thursday' => 'donderdag', 'Thu' => 'don', 'Friday' => 'vrijdag', 'Fri' => 'vri', 'Saturday' => 'zaterdag', 'Sat' => 'zat' ); %month = ( 'January' => 'januari', 'February' => 'februari', 'March' => 'maart', 'Jan' => 'jan', 'Feb' => 'feb', 'Mar' => 'mrt', 'April' => 'april', 'May' => 'mei', 'June' => 'juni', 'Apr' => 'apr', 'May' => 'mei', 'Jun' => 'jun', 'July' => 'juli', 'August' => 'augustus', 'September' => 'september', 'Jul' => 'jul', 'Aug' => 'aug', 'Sep' => 'sep', 'October' => 'oktober', 'November' => 'november', 'December' => 'december', 'Oct' => 'okt', 'Nov' => 'nov', 'Dec' => 'dec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." om".$quux[1]; }; return "$wday{$foo[0]} $foo[1] $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/skeleton.pm00000644000175300017510000000533013057016062016106 0ustar oetikeroep###### PATCHTAG00 ################################################### # -*- mode: Perl -*- ###################################################################### ### Localization of mrtg output pages ###################################################################### # # # This is a generated perl module file. # # Please see the perl script mergelocale.pl and the language # # databasefiles skelton.pm0 and locale.*.pmd in translate/. # # If you want to contribute to mrtg change in the *.pmd files. # # If you just want to change your own mrtg: Go ahead and edit! # # # ###################################################################### ### Defines programs which handles centralized pattern matching and pattern ### replacements in order to translate the given strings ###################################################################### ### Created by: Morten Storgaard Nielsen ################################################################### # # Distributed under the GNU copyleft # ################################################################### ### Locale by: ###### PATCHTAG10 ################################################### ### ### Contributions and fixes by: ### ### 0.05 fixed DARK GREEN entry (msn@ipt.dtu.dk) ### fixed credits for native language (msn@ipt.dtu.dk) ### 0.06 added the PATCHTAGs (msn@ipt.dtu.dk) ### fixed several small errors (msn@ipt.dtu.dk) ### 0.07 changed PATCHTAG to support ### mergelocale.pl (msn@ipt.dtu.dk) ### ###################################################################### ### package locales_mrtg; require 5.002; # make sure we do not get hit by UTF-8 here no locale; use strict; use vars qw(@ISA @EXPORT $VERSION); use Exporter; $VERSION = '0.07'; @ISA = qw(Exporter); @EXPORT = qw ( &english ###### PATCHTAG20 ################################################### ); %lang2tran::LOCALE= ( 'english' => \&english, 'default' => \&english, ###### PATCHTAG30 ################################################### ); %credits::LOCALE= ( # default 'default' => "Prepared for localization by Morten S. Nielsen <msn\@ipt.dtu.dk>", ###### PATCHTAG40 ################################################### ); ###### PATCHTAG50 ################################################### # English - default sub english { return shift; }; ###### PATCHTAG60 ################################################### mrtg-2.17.10/translate/slovak.pmd0000644000175300017510000001212213057016062015642 0ustar oetikeroep###### PATCHTAG 00 ################################################### ### Slovak/Slovensky ### => Ladislav Mihok ###### PATCHTAG 10 ################################################### &slovak ###### PATCHTAG 20 ################################################### 'slovak' => \&slovak, ###### PATCHTAG 30 ################################################### # Slovak/Slovensky 'slovak' => "Slovensk preklad pripravil Ing. Ladislav Mihok <laco\@mrokh.shmu.sk>", ###### PATCHTAG 40 ################################################### $credits::LOCALE{'slovak'}=$credits::LOCALE{'slovak'}; ###### PATCHTAG 50 ################################################### # Slovak sub slovak { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'iso-8859-2', 'Maximal 5 Minute Incoming Traffic' => 'Maximlny 5 mintov prichdzajci tok', 'Maximal 5 Minute Outgoing Traffic' => 'Maximlny 5 mintov odchdzajci tok', 'the device' => 'zariadenie', 'The statistics were last updated(.*)' => 'Posledn aktualizcia tatistk:$1', ' Average\)' => ' priemer)', 'Average' => 'Priem.', 'Max' => 'Max.', 'Current' => 'Akt.', 'version' => 'verzia', '`Daily\' Graph \((.*) Minute' => 'Denn graf ($1 mintov', '`Weekly\' Graph \(30 Minute' => 'Tdenn graf (30 mintov' , '`Monthly\' Graph \(2 Hour' => 'Mesan graf (2 hodinov', '`Yearly\' Graph \(1 Day' => 'Ron graf (1 denn', 'Incoming Traffic in (\S+) per Second' => 'Prichdzajci tok v $1 za sekundu.', 'Outgoing Traffic in (\S+) per Second' => 'Odchdzajci tok v $1 za sekundu.', 'at which time (.*) had been up for(.*)' => 'as od poslednho retartu $1 : $2', #'([kMG]?)([bB])/s' => '\$1\$2/s', #'([kMG]?)([bB])/min' => '\$1\$2/min', #'([kMG]?)([bB])/h' => '$1$2/h', 'Bits' => 'bitoch', 'Bytes' => 'bytoch', #' In:' => ' In:', #' Out:' => ' Out:', 'Percentage' => 'Perc.', 'Ported to OpenVMS Alpha by' => 'Na OpenVMS portoval', 'Ported to WindowsNT by' => 'Na WindowsNT portoval', 'and' => 'a', '^GREEN' => 'Zelen', 'BLUE' => 'Modr', 'DARK GREEN' => 'Tmavozelen', 'MAGENTA' => 'Fialov', 'AMBER' => 'lt' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Nedea', 'Sun' => 'Ne', 'Monday' => 'Pondelok', 'Mon' => 'Po', 'Tuesday' => 'Utorok', 'Tue' => 'Ut', 'Wednesday' => 'Streda', 'Wed' => 'St', 'Thursday' => 'tvrtok', 'Thu' => 't', 'Friday' => 'Piatok', 'Fri' => 'Pi', 'Saturday' => 'Sobota', 'Sat' => 'So' ); %month = ( 'January' => 'Janur', 'February' => 'Februr', 'March' => 'Marec', 'Jan' => 'Janur', 'Feb' => 'Februr', 'Mar' => 'Marec', 'April' => 'Aprl', 'May' => 'Mj', 'June' => 'Jn', 'Apr' => 'Aprl', 'May' => 'Mj', 'Jun' => 'Jn', 'July' => 'Jl', 'August' => 'August', 'September' => 'September', 'Jul' => 'Jl', 'Aug' => 'August', 'Sep' => 'September', 'October' => 'Oktber','November' => 'November','December' => 'December', 'Oct' => 'Oktber','Nov' => 'November','Dec' => 'December' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].",".$quux[1]." hod."; }; return "$wday{$foo[0]} $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; } # mrtg-2.17.10/translate/mergelocale.pl0000755000175300017510000000202313057016062016457 0ustar oetikeroep#!/usr/bin/perl # # usage: ./mergelocale.pl skeleton.pm0 lang1.pmd lang2.pmd # the script then creates locales_mrtg.pm # # If you want to modify a locale, modify the pmd file and rerun # this script and copy the generated locales_mrtg.pm to the run directory. # # If you want to translate a locale, copy one of the existing locales and # translate. Then rerun and copy. # ################################################################# # # Distributed under the GNU copyleft # ################################################################### open(OUTFILE,"> locales_mrtg.pm"); @patchdb=( 'PATCHTAG\s*00', 'PATCHTAG\s*10', 'PATCHTAG\s*20', 'PATCHTAG\s*30', 'PATCHTAG\s*40', 'PATCHTAG\s*50', 'PATCHTAG\s*60', ); while(@ARGV){ push(@languages,shift); }; foreach $patchtag (@patchdb) { for $i (@languages) { open(LANGF,"< $i"); $patch=""; while() { if(/\#.\S*PATCHTAG/) { $patch=/$patchtag/; } else { if($patch) { print OUTFILE $_; }; }; }; }; }; mrtg-2.17.10/translate/czech.pmd0000644000175300017510000001210313057016062015436 0ustar oetikeroep###### PATCHTAG 00 ################################################### ### Czech/esky ### => Martin Och ###### PATCHTAG 10 ################################################### &czech ###### PATCHTAG 20 ################################################### 'czech' => \&czech, ###### PATCHTAG 30 ################################################### # Czech/esky 'czech' => "esk peklad pipravil Martin Och <martin\@och.cz>", ###### PATCHTAG 40 ################################################### $credits::LOCALE{'czech'}=$credits::LOCALE{'czech'}; ###### PATCHTAG 50 ################################################### # Czech sub czech { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'windows-1250', 'Maximal 5 Minute Incoming Traffic' => 'Maximln 5 minutov pchoz tok', 'Maximal 5 Minute Outgoing Traffic' => 'Maximln 5 minutov odchoz tok', 'the device' => 'zazen', 'The statistics were last updated(.*)' => 'Posledn aktualizace statistiky:$1', ' Average\)' => ' prmr)', 'Average' => 'Prm.', 'Max' => 'Max.', 'Current' => 'Akt.', 'version' => 'verze', '`Daily\' Graph \((.*) Minute' => 'Denn graf ($1 minutov', '`Weekly\' Graph \(30 Minute' => 'Tdenn graf (30 minutov' , '`Monthly\' Graph \(2 Hour' => 'Msn graf (2 hodinov', '`Yearly\' Graph \(1 Day' => 'Ron graf (1 denn', 'Incoming Traffic in (\S+) per Second' => 'Pchoz tok v $1 za sec.', 'Outgoing Traffic in (\S+) per Second' => 'Odchoz tok v $1 za sec.', 'at which time (.*) had been up for(.*)' => 'od poslednho restartu $1 ubhlo: $2', #'([kMG]?)([bB])/s' => '\$1\$2/s', #'([kMG]?)([bB])/min' => '\$1\$2/min', #'([kMG]?)([bB])/h' => '$1$2/h', 'Bits' => 'bitech', 'Bytes' => 'bajtech', #' In:' => ' In:', #' Out:' => ' Out:', 'Percentage' => 'Proc.', 'Ported to OpenVMS Alpha by' => 'Na OpenVMS portoval', 'Ported to WindowsNT by' => 'Na WindowsNT portoval', 'and' => 'a', '^GREEN' => 'Zelen', 'BLUE' => 'Modr', 'DARK GREEN' => 'Tmav zelen', 'MAGENTA' => 'Fialov', 'AMBER' => 'lut' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Nedle', 'Sun' => 'Ne', 'Monday' => 'Pondli', 'Mon' => 'Po', 'Tuesday' => 'ter', 'Tue' => 't', 'Wednesday' => 'Steda', 'Wed' => 'St', 'Thursday' => 'tvrtek', 'Thu' => 't', 'Friday' => 'Ptek', 'Fri' => 'P', 'Saturday' => 'Sobota', 'Sat' => 'So' ); %month = ( 'January' => 'Leden', 'February' => 'nor', 'March' => 'Bezen', 'Jan' => 'Leden', 'Feb' => 'nor', 'Mar' => 'Bezen', 'April' => 'Duben', 'May' => 'Kvten', 'June' => 'erven', 'Apr' => 'Duben', 'May' => 'Kvten', 'Jun' => 'erven', 'July' => 'ervenec','August' => 'Srpen', 'September' => 'Z', 'Jul' => 'ervenec','Aug' => 'Srpen', 'Sep' => 'Z', 'October' => 'jen', 'November' => 'Listopad', 'December' => 'Prosinec', 'Oct' => 'jen', 'Nov' => 'Listopad', 'Dec' => 'Prosinec' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0].",".$quux[1]." hod."; }; return "$wday{$foo[0]} $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; } # mrtg-2.17.10/translate/korean.pmd0000644000175300017510000001214513057016062015627 0ustar oetikeroep###### PATCHTAG00 #################################################### ### Korean ### => Kensoon Hwang ### CHOI Junho ###### PATCHTAG10 #################################################### &korean ###### PATCHTAG20 #################################################### 'korean' => \&korean, ###### PATCHTAG30 #################################################### # korean ,'korean' => "ѱ۸޽ : ȲǼ, ȣ", ###### PATCHTAG40 #################################################### $credits::LOCALE{'korean'}=$credits::LOCALE{'korean'}; ###### PATCHTAG50 #################################################### # Korean sub korean { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'euc-kr', 'Maximal 5 Minute Incoming Traffic' => '5а ִ ', 'Maximal 5 Minute Outgoing Traffic' => '5а ִ ۽', 'the device' => 'ġ', 'The statistics were last updated(.*)' => ' Ͻ: $1', ' Average\)' => ' հ )', 'Average' => '', 'Max' => 'ִ', 'Current' => '', 'version' => '', '`Daily\' Graph \((.*) Minute' => 'ϰ ׷ ($1 ', '`Weekly\' Graph \(30 Minute' => 'ְ ׷ (30 ' , '`Monthly\' Graph \(2 Hour' => ' ׷ (2 ð ', '`Yearly\' Graph \(1 Day' => ' ׷ (1 ', 'Incoming Traffic in (\S+) per Second' => 'ʴ ŵ Ʈ ($1)', 'Outgoing Traffic in (\S+) per Second' => 'ʴ ۽ŵ Ʈ ($1)', 'at which time (.*) had been up for(.*)' => '$1 ð: $2', '([kMG]?)([bB])/s' => '$1$2/', '([kMG]?)([bB])/min' => '$1$2/', '([kMG]?)([bB])/h' => '$1$2/', 'Bits' => 'Ʈ', 'Bytes' => 'Ʈ', 'In' => '', 'Out' => '۽', 'Percentage' => 'ۼƮ', 'Ported to OpenVMS Alpha by' => 'OpenVMS Alpha ', 'Ported to WindowsNT by' => 'WindowsNT ', 'and' => '', '^GREEN' => '', 'BLUE' => 'û', 'DARK GREEN' => 'ѳ', 'MAGENTA' => 'ȫ', 'AMBER' => 'Ȳ' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Ͽ', 'Sun' => '', 'Monday' => '', 'Mon' => '', 'Tuesday' => 'ȭ', 'Tue' => 'ȭ', 'Wednesday' => '', 'Wed' => '', 'Thursday' => '', 'Thu' => '', 'Friday' => 'ݿ', 'Fri' => '', 'Saturday' => '', 'Sat' => '' ); %month = ( 'January' => '1', 'February' => '2' , 'March' => '3', 'Jan' => '1', 'Feb' => '2', 'Mar' => '3', 'April' => '4', 'May' => '5', 'June' => '6', 'Apr' => '4', 'May' => '5', 'Jun' => '6', 'July' => '7', 'August' => '8', 'September' => '9', 'Jul' => '7', 'Aug' => '8', 'Sep' => '9', 'October' => '10', 'November' => '11', 'December' => '12', 'Oct' => '10', 'Nov' => '11', 'Dec' => '12' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); # $foo[3]=$quux[0]." kl.".$quux[1]; $foo[3]=$quux[0]; $foo[4]=$quux[1]; }; return $foo[3]." $month{$foo[2]} $foo[1] $wday{$foo[0]} $foo[4]"; # return "$wday{$foo[0]} den $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/gb.pmd0000644000175300017510000001205613057016062014741 0ustar oetikeroep ###### PATCHTAG 00 ################################################### ### Chinese/庺 ### => Zhanghui Ż ###### PATCHTAG 10 ################################################### &gb ###### PATCHTAG 20 ################################################### 'gb' => \&gb, '庺' => \&gb, ###### PATCHTAG 30 ################################################### # Chinese/庺 'gb' => "Ƨ@ Hui Zhang <zhanghui\@asiainfo.com>", ###### PATCHTAG 40 ################################################### $credits::LOCALE{'庺'}=$credits::LOCALE{'gb'}; ###### PATCHTAG 50 ################################################### # Chinese gb Code sub gb { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'gb', 'Maximal 5 Minute Incoming Traffic' => '5', 'Maximal 5 Minute Outgoing Traffic' => '5', 'the device' => 'ǰ豸', 'The statistics were last updated(.*)' => 'ͳϢ: $1', ' Average\)' => 'ƽ)', 'Average' => 'ƽ', 'Max' => '', 'Current' => 'ǰ', 'version' => '汾', '`Daily\' Graph \((.*) Minute' => 'շͼ($1', '`Weekly\' Graph \(30 Minute' => 'ܷͼ(30' , '`Monthly\' Graph \(2 Hour' => '·ͼ(2Сʱ', '`Yearly\' Graph \(1 Day' => 'ͼ(1', 'Incoming Traffic in (\S+) per Second' => 'ÿ(λ$1)', 'Outgoing Traffic in (\S+) per Second' => 'ÿ(λ$1)', 'at which time (.*) had been up for(.*)' => 'ʱ $1Ѿ(UPTIME): $2', '([kMG]?)([bB])/s' => '$1$2/s', '([kMG]?)([bB])/min' => '$1$2/m', '([kMG]?)([bB])/h' => '$1$2/h', # 'Bits' => 'Bits', # 'Bytes' => 'Bytes' 'In' => '', 'Out' => '', 'Percentage' => 'ٷֱ', 'Ported to OpenVMS Alpha by' => 'OpenVMSĶ˿', 'Ported to WindowsNT by' => 'WindowsNTĶ˿', 'and' => '', '^GREEN' => 'ɫ', 'BLUE' => 'ɫ', 'DARK GREEN' => '', 'MAGENTA' => 'ɫ', 'AMBER' => 'ɫ' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => '', 'Sun' => '', 'Monday' => 'һ', 'Mon' => 'һ@', 'Tuesday' => 'ܶ', 'Tue' => 'ܶG', 'Wednesday' => '', 'Wed' => 'T', 'Thursday' => '', 'Thu' => 'ĥ|', 'Friday' => '', 'Fri' => '', 'Saturday' => '', 'Sat' => '' ); %month = ( 'January' => '1', 'February' => '2', 'March' => '3', 'Jan' => '1', 'Feb' => '2', 'Mar' => '3', 'April' => '4', 'May' => '5', 'June' => '6', 'Apr' => '4', 'May' => '5', 'Jun' => '6', 'July' => '7', 'August' => '8', 'September' => '9', 'Jul' => '7', 'Aug' => '8', 'Sep' => '9', 'October' => '10', 'November' => '11', 'December' => '12', 'Oct' => '10', 'Nov' => '11', 'Dec' => '12' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { @quux=split(/at/,$foo[3]); if($foo[3]=~(/(.*)at(.*)/)) { $foo[3]=$quux[0]; $foo[4]=$quux[1]; }; return "$foo[3] $month{$foo[2]} $foo[1], $wday{$foo[0]}, $foo[4]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/translate/polish.pmd0000644000175300017510000001263113057016062015646 0ustar oetikeroep###### PATCHTAG 00 ################################################### ### Polish/Polski ### => Lukasz Jokiel ###### PATCHTAG 10 ################################################### &polish ###### PATCHTAG 20 ################################################### 'polish' => \&polish, 'polski' => \&polish, ###### PATCHTAG 30 ################################################### # Polish/polski 'polish' => "Polska lokalizacja Lukasz Jokiel <Lukasz.Jokiel\@klonex.com.pl>", ###### PATCHTAG 40 ################################################### $credits::LOCALE{'polski'}=$credits::LOCALE{'polish'}; ###### PATCHTAG 50 ################################################### sub polish { my $string = shift; return "" unless defined $string; my(%translations,%month,%wday); my($i,$j); my(@dollar,@quux,@foo); # regexp => replacement string NOTE does not use autovars $1,$2... # charset=iso-2022-jp %translations = ( 'iso-8859-1' => 'iso-8859-2', 'Maximal 5 Minute Incoming Traffic' => 'Maksymalny ruch przychodzcy w cigu 5 minut', 'Maximal 5 Minute Outgoing Traffic' => 'Maksymalny ruch wychodzcy w cigu 5 minut', 'the device' => 'urzdzenie', 'The statistics were last updated(.*)' => 'Ostatnie uaktualnienie statystyki $1', ' Average\)' => ' rednia)', 'Average' => 'rednio', 'Max' => 'Maksymalnie', 'Current' => 'Aktualnie', 'version' => 'wersja', '`Daily\' Graph \((.*) Minute' => '`Dzienny\' Graf w cigu ($1 Minut/y - ', '`Weekly\' Graph \(30 Minute' => '`Tygodniowy\' Graf w cigu (30 minut - ' , '`Monthly\' Graph \(2 Hour' => '`Miesiczny\' Graf w cigu (2 Godzin - ', '`Yearly\' Graph \(1 Day' => '`Roczny\' Graf w cigu (1 Dnia - ', 'Incoming Traffic in (\S+) per Second' => 'Ruch przychodzcy - $1 na sekund', 'Outgoing Traffic in (\S+) per Second' => 'Ruch wychodzcy - $1 na sekund', 'at which time (.*) had been up for(.*)' => 'gdy $1 by wczony przez $2', # '([kMG]?)([bB])/s' => '\$1\$2/s', # '([kMG]?)([bB])/min' => '\$1\$2/min', '([kMG]?)([bB])/h' => '$1$2/g', 'Bits' => 'Bity', 'Bytes' => 'Bajty', 'In' => 'Do', 'Out' => 'Z', 'Percentage' => 'Procent', 'Ported to OpenVMS Alpha by' => 'Port dla OpenVMS Alpha dziki', 'Ported to WindowsNT by' => 'Port dla WindowsNT dziki', 'and' => 'i', '^GREEN' => 'ZIELONY', 'BLUE' => 'NIEBIESKI', 'DARK GREEN' => 'CIEMNO ZIELONY', 'MAGENTA' => 'KARMAZYNOWY', 'AMBER' => 'BURSZTYNOWY' ); # maybe expansions with replacement of whitespace would be more appropriate foreach $i (keys %translations) { my $trans = $translations{$i}; $trans =~ s/\|/\|/; return $string if eval " \$string =~ s|\${i}|${trans}| "; }; %wday = ( 'Sunday' => 'Niedziela', 'Sun' => 'Nie', 'Monday' => 'Poniedziaek', 'Mon' => 'Pon', 'Tuesday' => 'Wtorek', 'Tue' => 'Wto', 'Wednesday' => 'roda', 'Wed' => 'ro', 'Thursday' => 'Czwartek', 'Thu' => 'Czw', 'Friday' => 'Pitek', 'Fri' => 'Pi', 'Saturday' => 'Sobota', 'Sat' => 'Sob' ); %month = ( 'January' => 'Stycznia', 'February' => 'Lutego', 'March' => 'Marca', 'Jan' => 'Sty', 'Feb' => 'Lut', 'Mar' => 'Mar', 'April' => 'Kwietnia', 'May' => 'Maja', 'June' => 'Czerwca', 'Apr' => 'Kwi', 'May' => 'Maj', 'Jun' => 'Cze', 'July' => 'Lipca', 'August' => 'Sierpnia', 'September' => 'Wrzenia', 'Jul' => 'Lip', 'Aug' => 'Sie', 'Sep' => 'Wrz', 'October' => 'Padziernika', 'November' => 'Listopada', 'December' => 'Grudnia', 'Oct' => 'Pa', 'Nov' => 'Lis', 'Dec' => 'Gru' ); @foo=($string=~/(\S+),\s+(\S+)\s+(\S+)(.*)/); if($foo[0] && $wday{$foo[0]} && $foo[2] && $month{$foo[2]} ) { if($foo[3]=~(/(.*)at(.*)/)) { @quux=split(/at/,$foo[3]); $foo[3]=$quux[0]." o godzinie".$quux[1]; }; return "$wday{$foo[0]} dzie $foo[1]. $month{$foo[2]} $foo[3]"; }; # # handle two different time/date formats: # return "$wday, $mday $month ".($year+1900)." at $hour:$min"; # return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; # # handle nontranslated strings which ought to be translated # print STDERR "$_\n" or print DEBUG "not translated $_"; # but then again we might not want/need to translate all strings return $string; }; mrtg-2.17.10/contrib/0000755000175300017510000000000014171553254013315 5ustar oetikeroepmrtg-2.17.10/contrib/procmem/0000755000175300017510000000000013057016061014747 5ustar oetikeroepmrtg-2.17.10/contrib/procmem/README0000644000175300017510000000533213057016061015632 0ustar oetikeroep=============================================== Cisco CPU & Memory monitoring =============================================== by Dimitrios Stergiou Contents -------- MRTG Libraries: BER.pm MRTG_lib.pm SNMP_Session.pm SNMP_util.pm locales_mrtg.pl mrtg.cfg creators: create-cfg-mem.pl create-cfg-proc.pl actual mrtg scripts: getproc.pl getmem.pl Quick Installation ------------ 1. Copy getmem.pl and getproc.pl to an appropriate location. Perhaps, in the dir you have the MRTG binary 2. Edit both scripts and change the line: use lib "/home/alexander1/dste/cisco"; make it point to the lib dir on the directory you have the mrtg distribution 3. Edit create-cfg-mem.pl and create-cfg-proc.pl and change the line: Target[$target]: `/home/alexander1/dste/cisco/getmem.pl $ARGV[0] $pool` make it point to the executable you installed on step 1 4. Run create-cfg-mem.pl to create a conf file for mrtg. Use: create-cfg-mem.pl router_to_poll > memory.cfg 5. Run create-cfg-proc.pl to create a conf file for mrtg. Use: create-cfg-proc.pl router_to_poll > proc.cfg 6. Run MRTG with the configuration files generated above Usage ----- 1) Memory monitoring: Cisco routers use memory pools to allocate memory to various subsystems. The only mandatory subsystem is "Processor". Additionaly you may have "PCI", "I/O",etc. create-cfg-mem.pl will query the router about its memory pools, find out how many pools the router uses, and create a configuration file that will monitor all pools found. In order for the graph to be drawn, we need a MaxBytes value. This value is acquired from the router, using the following formula: foreach pool on the router { MaxBytes = memory used for pool + memory free for pool } If you sum up all the pools (MaxBytes value) you will find that the sum is less than the physical memory of your router. I suppose, that the part we are missing is filled by the IOS. References: http://www.cisco.com/public/mibs/v2/CISCO-MEMORY-POOL-MIB.my 2) CPU Utilization monitoring: create-cfg-proc.pl will create a configuration file used to monitor the following 3 variables on a Cisco router: - cpmCPUTotal5sec - cpmCPUTotal1min - cpmCPUTotal15min Unfortunately, this feature seems to work only on 12.0(x)T IOS, so if it doesn't work on your router, dont blame me. The script will try to find out if your router is capable of returning values about its processor usage though. References: http://www.cisco.com/public/mibs/v2/CISCO-PROCESS-MIB.my ---- I hope this is as useful to you as it has been to me. If you have any problems/bug reports/advice/complaints, email me. Enjoy. Dimitrios Stergiou mrtg-2.17.10/contrib/procmem/create-cfg-mem.pl0000755000175300017510000000332413057016061020065 0ustar oetikeroep#!/usr/bin/perl #----------------------------------------------- # Query a router about its memory pools and create MRTG cfg file for the pools # # Author: Dimitrios Stergiou , 25/10/00 # Version : 1.0 # # Usage: ./create-cfg-mem.pl cisco_hostname # # 1.0 Initial version, basic functionality #----------------------------------------------- # Import libraries use lib "/home/alexander1/dste/cisco"; use MRTG_lib "2.090006"; use SNMP_Session "0.77"; use BER "0.77"; use SNMP_util "0.77"; use locales_mrtg "0.07"; # Suppress warnings $SNMP_Session::suppress_warnings = 3; # Locate how many memory pools the router has for ($i = 1; $i <= 5; $i++) { $command = snmpget($ARGV[0], "enterprises.9.9.48.1.1.1.2.$i"); if ($command eq "1") { push @pools, $i; } } # loop through pools and find # 1) pool names # 2) pool usage # 3) pool availability # maximum pool capacity is defined as: PoolSizeUsed + PoolSizeFree foreach $pool (@pools) { @memtype = snmpget($ARGV[0], "enterprises.9.9.48.1.1.1.2.$pool"); if ($memtype[0] eq "I/O") { $memtype[0]="IO"; } $target = "$ARGV[0]"."_"."$memtype[0]"; @pu = snmpget($ARGV[0], "enterprises.9.9.48.1.1.1.5.$pool"); @pf = snmpget($ARGV[0], "enterprises.9.9.48.1.1.1.6.$pool"); $maxbytes = $pu[0]+$pf[0]; print< $nname memory used Suppress[$target]: y LegendI[$target]: kbytes used LegendO[$target]: Legend1[$target]: kbytes used Legend2[$target]: YLegend[$target]: kbytes used ShortLegend[$target]: used Options[$target]: gauge,growright # =================================== EOF } mrtg-2.17.10/contrib/procmem/create-cfg-proc.pl0000755000175300017510000000313213057016061020247 0ustar oetikeroep#!/usr/bin/perl #----------------------------------------------- # Create mrtg.cfg for CPU processor usage # # Author: Dimitrios Stergiou , 25/10/00 # Version : 1.0 # # Usage: ./create-cfg-proc.pl cisco_hostname # # 1.0 Initial version, basic functionality # 1.1 Check if router supports functionality #----------------------------------------------- # Import libraries use lib "/home/alexander1/dste/cisco"; use MRTG_lib "2.090006"; use SNMP_Session "0.77"; use BER "0.77"; use SNMP_util "0.77"; use locales_mrtg "0.07"; # Suppress warnings $SNMP_Session::suppress_warnings = 3; # Define processor counters @counters=("5sec", "1min", "15min"); # Check if router can support CPU proccess MIB # Just poll a "5 sec" valur, for CPU 1, if we get answer it works @test = snmpget($ARGV[0], "enterprises.9.9.109.1.1.1.1.3.1"); die "Processor util poll doesn't work for router $ARGV[0] $!\n" unless ($test[0]=~/[0-9]/); # loop through processor counters foreach $counter (@counters) { $target = "$ARGV[0]"."_"."$counter"; if ($counter eq "5sec") { $instance=3; } if ($counter eq "1min") { $instance=4; } if ($counter eq "15min") { $instance=5; } print< $counter processor usage Suppress[$target]: y LegendI[$target]: % LegendO[$target]: Legend1[$target]: % Legend2[$target]: YLegend[$target]: % ShortLegend[$target]: used Options[$target]: gauge,growright # =================================== EOF } mrtg-2.17.10/contrib/procmem/getproc.pl0000755000175300017510000000163513057016061016757 0ustar oetikeroep#!/usr/bin/perl #----------------------------------------------- # Return processor usage, for a specifig time range (5sec, 1min, 15min) # # Author: Dimitrios Stergiou , 26/10/00 # Version : 1.0 # # Usage: ./getproc.pl cisco_hostname time_range # time_range can be: # 3 (The overall CPU busy percentage in the last 5 secs) # 4 (The overall CPU busy percentage in the last 1 mins) # 5 (The overall CPU busy percentage in the last 15 mins) # # 1.0 Initial version, basic functionality #----------------------------------------------- # Import libraries use lib "/usr/local/mrtg/lib/mrtg2"; use MRTG_lib "2.090006"; use SNMP_Session "0.77"; use BER "0.77"; use SNMP_util "0.77"; use locales_mrtg "0.07"; # Query public community on router, return proc usage for specific time range @command = snmpget($ARGV[0], "enterprises.9.9.109.1.1.1.1.$ARGV[1].1"); print @command[0]; mrtg-2.17.10/contrib/procmem/getmem.pl0000755000175300017510000000124013057016061016562 0ustar oetikeroep#!/usr/bin/perl #----------------------------------------------- # Return memory usage for a specific Cisco memory pool # # Author: Dimitrios Stergiou , 25/10/00 # Version : 1.0 # # Usage: ./getmem.pl cisco_hostname memory_pool # # 1.0 Initial version, basic functionality #----------------------------------------------- # Import libraries use lib "/usr/local/mrtg/lib/mrtg2"; use MRTG_lib "2.090006"; use SNMP_Session "0.77"; use BER "0.77"; use SNMP_util "0.77"; use locales_mrtg "0.07"; # Query public community on router, return memory used in current pool @command = snmpget($ARGV[0], "enterprises.9.9.48.1.1.1.5.$ARGV[1]"); print @command[0]; mrtg-2.17.10/contrib/linux_stat/0000755000175300017510000000000013057016061015477 5ustar oetikeroepmrtg-2.17.10/contrib/linux_stat/readme0000644000175300017510000000036513057016061016663 0ustar oetikeroep I could not find a simple script to get the current traffic off a linux machine, so in open source sprit, I wrote my own. Here it is to share with all those looking for such a tool. Mike Machado mike@innercite.com InnerCite Network Specialist mrtg-2.17.10/contrib/linux_stat/linux_stats.pl0000644000175300017510000000443413057016061020416 0ustar oetikeroep#!/usr/bin/perl -Tw #################################################################### # linux_stats.pl 1.0 Mike Machado # # mike@innercite.com # # 2000-07-19 # # # # Script to read traffic stats off linux 2.2 and greater systems # # # #################################################################### use strict; #### Options #### my $uptimeprog = '/usr/bin/uptime'; # Set to program to give system uptime my $hostnameprog = '/bin/hostname'; # Set to program to give system hostname my $defaultinterface = 'eth0'; # Set to default interface my $defaultstatfile = '/proc/net/dev'; # Set to traffic stats file location ##### Nothing below here should have to be changed ##### if (@ARGV && $ARGV[0] eq '-h') { print "Usage: linux_stats.pl [interface] [stats file]\n"; print "\tIf left blank 'eth0' and '/proc/net/dev' are used\n"; print "\tInterface of 'ALL' will total all interface traffic, excluding lo\n"; exit; } my $interface = shift || $defaultinterface; my $statfile = shift || $defaultstatfile; # Clear path and get uptime delete $ENV{PATH}; delete $ENV{BASH_ENV}; my $uptime = `$uptimeprog`; chomp($uptime); my $hostname = `$hostnameprog`; chomp($hostname); my ($in, $out, $found); open(STATS, $statfile) || die "Cannot open $statfile: $!\n"; while () { my $line = $_; chomp($line); if (uc($interface) eq 'ALL') { if ($line =~ /^\s+(.*):\s*(\d+)\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+(\d+)\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+$/) { next if $1 eq 'lo'; $in += $2; $out += $3; $found++; } } else { if ($line =~ /^\s*$interface:\s*(\d+)\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+(\d+)\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+$/) { $in = $1; $out = $2; $found = 1; last; } } } close(STATS); if (!$found) { print "0\n0\n$uptime\n$hostname: Unknown Interface: $interface\n"; } else { print "$in\n$out\n$uptime\n$hostname: Interface: $interface"; if (uc($interface) eq 'ALL') { print " (counted $found interface"; if ($found > 1) { print "s"; } print ")"; } print "\n"; } mrtg-2.17.10/contrib/iptables_acc_snmp/0000755000175300017510000000000013057016061016753 5ustar oetikeroepmrtg-2.17.10/contrib/iptables_acc_snmp/README0000644000175300017510000000076313057016061017641 0ustar oetikeroepFrom: HERITIER Herv Date: 12 May 2001 18:04:11 -0000 Attached, you find a simple script to capture iptables counter on Linux 2.4, to use it, on each computer run iptables, add a pass line into the snmpd.conf to activate access like this : pass .1.3.6.1.4.1.2055 /usr/bin/perl /usr/local/iptables_acc_snmp It can be useful for ISP's to make easly a main accounting and performance monitoring. I provide a sample MIB file to implement it into mrtg config file. Herv HERITIER mrtg-2.17.10/contrib/iptables_acc_snmp/HANDCO-SNMP-MIB.txt0000644000175300017510000000245313057016061021634 0ustar oetikeroepHANDCO-SNMP-MIB DEFINITIONS ::= BEGIN IMPORTS OBJECT-TYPE, MODULE-IDENTITY, Counter32, Integer32, Opaque, enterprises, Counter64 FROM SNMPv2-SMI TEXTUAL-CONVENTION, DisplayString, TruthValue FROM SNMPv2-TC; handco MODULE-IDENTITY LAST-UPDATED "0104260000Z" ORGANIZATION "Handco" CONTACT-INFO "Primary Author: Herve HERITIER email: hh@handco.org" DESCRIPTION "This file defines the private UCD SNMP MIB extensions." REVISION "0104260000Z" DESCRIPTION "SMIv2 version" ::= { enterprises 2055 } hostname OBJECT-TYPE SYNTAX DisplayString MAX-ACCESS read-only STATUS current DESCRIPTION "The process name we're counting/checking on." ::= { handco 1 } iptables OBJECT-TYPE SYNTAX SEQUENCE OF IpTable MAX-ACCESS read-only STATUS current INDEX {tableName, chainName} DESCRIPTION "" ::= {handco 2} IpTable ::= SEQUENCE { chainName DisplayString chainCounter Counter64 } iptable OBJECT-TYPE SYNTAX IpTable MAX-ACCESS read-only STATUS current DESCRIPTION "" ::= {iptables 1} chainName OBJECT-TYPE SYNTAX DisplayString MAX-ACCESS read-only STATUS current DESCRIPTION "" ::= {iptable 1} chainCounter OBJECT-TYPE SYNTAX Counter32 MAX-ACCESS read-only STATUS current DESCRIPTION "" ::= {iptable 2} END mrtg-2.17.10/contrib/iptables_acc_snmp/iptables_acc_snmp0000755000175300017510000000627413057016061022360 0ustar oetikeroep#!/usr/bin/perl my ($req,$place,$returnOID,$mode, $IPTABLES,@counters); $IPTABLES = "iptables"; # cmdline to iptables $place=".1.3.6.1.4.1.2055"; @counters = loadChains(); main(); sub main { my ($mode,$req); if (scalar(@ARGV) == 2) { ($mode,$req) = @ARGV; } else { ($req) = @ARGV; } SWITCH: for ($mode) { /-s/ && exit; /-n/ && do { SWITCH: for ($req) { /$place$/ && do { $returnOID = "$place.1"; last SWITCH; }; /$place\.1$/ && do { $returnOID = "$place.2.1.1.1"; last SWITCH; }; /$place\.2$/ && do { $returnOID = "$place.2.1.1.1"; last SWITCH; }; /$place\.2\.1$/ && do { $returnOID = "$place.2.1.1.1"; last SWITCH; }; /$place\.2\.1\.1$/ && do { $returnOID = "$place.2.1.1.1"; last SWITCH; }; /$place\.2\.1\.1\.(.*)$/ && do { if ($1 < scalar(@counters)-1) { $returnOID = "$place.2.1.1." . ($1 + 1); } else { $returnOID = "$place.2.1.2.1"; } last SWITCH; }; /$place\.2\.1\.2\.(.*)$/ && do { if ($1 < scalar(@counters)-1) { $returnOID = "$place.2.1.2." . ($1 + 1); } else { exit; } last SWITCH; }; exit; } last SWITCH; }; SWITCH: for ($req) { /$place$/ && exit; /$place\.2\.1$/ && exit; /$place\.2\.1\.1$/ && exit; /$place\.2\.1\.2$/ && exit; $returnOID = $req; } } print "$returnOID\n"; $_ = $returnOID; SWITCH: { /^$place\.1$/ && do { print "string\n", getHostname() ; last SWITCH; }; /^$place\.2\.1\.(1|2)\.(.*)$/ && do { ($a, $b) = split ("=", @counters[$2]); if ($1 == 1) { print "string\n$a\n"; } else { print "counter\n$b\n"; } last SWITCH; }; /^$place\.2\.1\.1\.3\.1\.1\.(1|2|3)$/ && do { print "integer\n$1\n"; last SWITCH; }; /^$place\.2\.1\.1\.2\.(1|2|3)$/ && do { SWITCH: for ($1) { /1/ && do { print "string\nfilter\n"; last SWITCH }; /2/ && do { print "string\nnat\n"; last SWITCH }; /3/ && do { print "string\nmangle\n"; last SWITCH }; } last SWITCH; }; print "string\nack... $returnOID $req\n"; } } sub getHostname { return `/bin/hostname --fqdn`; } sub getChainCount { my ($table); $table = shift(); return scalar(getChainNames($table)); } sub getChainNames { my (@bufLines,$table,@chains); $table = shift(); @bufLines = `$IPTABLES -t $table -nL`; foreach (@bufLines) { if (/^Chain (.*) \((.*)$/) { push (@chains, $1); } } return @chains; } sub getChainCounter { my (@rules, @count, $value); $table = shift(); $chain = shift(); @rules=`$IPTABLES -t $table -vnxL $chain`; splice @rules, 0, 2; $total=0; foreach $value (@rules) { @count=split(' ',$value); $total += $count[1]; } return $total; } sub getChains { my ($table, @result, @names, $counter, $name,@buf); $table = shift(); @chains = getChainNames($table); foreach $name (@chains) { $counter = getChainCounter ($table, $name); push (@result, "$table/$name=$counter"); } return @result; } sub loadChains { my (@result, @buf, $table); foreach $table ("filter","nat","mangle") { @buf = getChains ($table); push (@result, @buf); } return @result; }mrtg-2.17.10/contrib/mrtg_php_portal/0000755000175300017510000000000013057016061016506 5ustar oetikeroepmrtg-2.17.10/contrib/mrtg_php_portal/conf/0000755000175300017510000000000013057016061017433 5ustar oetikeroepmrtg-2.17.10/contrib/mrtg_php_portal/conf/config.inc.php0000644000175300017510000000131513057016061022161 0ustar oetikeroepmrtg-2.17.10/contrib/mrtg_php_portal/readme.txt0000644000175300017510000000334313057016061020507 0ustar oetikeroepMrtg PHP 'Portal' ----------------- Intro: I've made these quick hacks to provide a 'user-friendly' web interface for adding, removing and updating the mrtg polled hosts. The PHP scripts grab the parameters from html forms and run cfgmaker, indexmaker and mrtg with these parameters. Requirement: Web server with PHP4 Perl Configuration of the script: Desarchive the mrtg_php_portal.zip file in your mrtg and put the perl script 'Update.pl' in the mrtg folder (e.g.: c:\mrtg), put the Php script config file 'config.inc.php' in the conf folder (e.g.: c:\mrtg\conf), put the 6 remaining php script in the www folder (e.g.: c:\mrtg\www). Summary of the script usage: - update.pl, this script takes all the .cfg file in conf and update the Mrtg stats for these configs. You can run this script with MrtgSvc or 5mrtg. - config.inc.php, this is the file were all paths and passwords for the script are configured. - index.php, this script generates a single index with a link to all the .html file located in e:\mrtgwww. - login.php, this script protect the admin section with a password configured in the config.inc.php file. - setup.php, this script generate the mrtg config file with cfgmaker, create a index file for the new host and run mrtg with the parameters from the form. - remove.php, this script delete the config file, html file and index file of a host that need to be removed. - admin.php, this script create a html page with the admin choice (add, remove, update). - Update.php, this script re-run mrtg for the selected host. Edit the config.inc.php and configure the path for the environment and configure the admin password also. Thanks: To 'Putzi' (he will recognize himself) for the help with Perl. Contact: Damien Hauser damien@detonate.net mrtg-2.17.10/contrib/mrtg_php_portal/update.pl0000644000175300017510000000102313057016061020321 0ustar oetikeroep#!/bin/perl # # my ($filelist,$file,$result); my @f_list; # Change the path to the folder where you store the mrtg .cfg files $deleted=`del /F /Q c:\\mrtg\\conf\\*_l`; # this is to remove the _l files before running Mrtg $filelist=`dir /B c:\\mrtg\\conf\\*.cfg`; # Get the list of the cfg files @f_list=split(/\n/,$filelist); foreach $file (@f_list){ if($file||($file ne "File not Found")||($file=~/\.cfg$/)){ $result=`perl.exe e:\\mrtg\\bin\\mrtg e:\\mrtg\\conf\\$file`; # Run Mrtg for each host with a cfg file. } } mrtg-2.17.10/contrib/mrtg_php_portal/www/0000755000175300017510000000000013057016061017332 5ustar oetikeroepmrtg-2.17.10/contrib/mrtg_php_portal/www/update.php0000644000175300017510000000232313057016061021325 0ustar oetikeroep MRTG remove switch:

MRTG update switch stats:

Switch:


".$switch."
updated...
"; } echo "
Back to index"; ?>mrtg-2.17.10/contrib/mrtg_php_portal/www/admin.php0000644000175300017510000000100013057016061021122 0ustar oetikeroep MRTG remove switch:

Configuration:


Back to index mrtg-2.17.10/contrib/mrtg_php_portal/www/index.php0000644000175300017510000000144413057016061021155 0ustar oetikeroep Mrtg statistics

Configuration:

Switch list:

"; while($filename=$dir ->read()) { if (eregi("\.(html)$",$filename)) echo "
  • ".substr($filename, 0, -5)."
  • ";; } $dir ->close(); echo ""; ?> mrtg-2.17.10/contrib/mrtg_php_portal/www/login.php0000644000175300017510000000253313057016061021156 0ustar oetikeroep MRTG Admin login

    MRTG Admin login

    Admin Password:

    "; } if($REQUEST_METHOD == "POST"){ if($form_password){ if($form_password == $admin_password1 or $form_password == $admin_password2){ ?> mrtg-2.17.10/contrib/mrtg_php_portal/www/remove.php0000644000175300017510000000415413057016061021344 0ustar oetikeroep MRTG remove switch:

    MRTG remove switch:

    Switch:
    Option: Delete config file
    Delete stats
    Delete html index

    "; unlink($mrtg_config_dir.$switch.".cfg"); unlink($mrtg_config_dir.$switch.".ok"); } if (file_exists($mrtg_html_dir.$switch) && $del_html == "ON") { echo " $switch html files removed...
    "; exec( "rmdir /s /q ".$mrtg_html_dir.$switch); } if (file_exists($mrtg_html_dir.$switch.".html") && $del_index == "ON") { echo " $switch index files removed...
    "; unlink($mrtg_html_dir.$switch.".html"); } } echo "
    Back to index"; ?>mrtg-2.17.10/contrib/mrtg_php_portal/www/setup.php0000644000175300017510000001121613057016061021204 0ustar oetikeroep MRTG New Switch configuration

    MRTG New Switch configuration

    Switch IP or Hostname:
    Snmp community:
    Option: Generate config
    Run mrtg
    Create html index
    Cfgmaker options: Query down interface (--no-down)
    No reverse Dns (--noreversedns)
    Mrtg Options:

    Right starting graph (growright)

    Graph in Bits (bits)
    Interface Name:


    Back to index"; exit(); } // Creating dir for Switch config files and stats files if (!file_exists($switch_ip) && $switch_ip <> "") { mkdir ($switch_ip,700); } // Run Cfg maker and mrtg script with argument from the form if ($switch_ip <> "") { if ($run_cfgmaker == "ON") { //echo $mrtg_html_dir."
    "; //echo $perl_exe." ".$cfgmaker_exe." ".$cfgmaker_param." ".$switch_ip; system($perl_exe." ".$cfgmaker_exe." ".$cfgmaker_param." ".$switch_ip); echo "Mrtg config for ".$switch_ip." created...
    "; } if ($run_mrtg == "ON") { //echo $perl_exe." ".$mrtg_exe." ".$mrtg_config_dir.$switch_ip.".cfg"."
    "; system ($perl_exe." ".$mrtg_exe." ".$mrtg_config_dir.$switch_ip.".cfg"); echo "1st run Mrtg stats generated...
    "; } if ($run_indexmaker == "ON") { system ($perl_exe." ".$indexmaker_exe." ".$indexmaker_option); echo "Mrtg html index generated...
    "; } } } echo "
    Back to index"; ?> mrtg-2.17.10/contrib/mrtgmk/0000755000175300017510000000000013057016061014606 5ustar oetikeroepmrtg-2.17.10/contrib/mrtgmk/doc/0000755000175300017510000000000013057016061015353 5ustar oetikeroepmrtg-2.17.10/contrib/mrtgmk/doc/readme.1st0000644000175300017510000001231213057016061017240 0ustar oetikeroep"mrtgmk" by Iulian Radu (iulian_r@starnets.ro) [v2.0] "mrtgmk" is giftware. It is my contribution to mrtg package. "mrtgmk" is a program that scan a .cfg file and generate a mrtg.cfg style file + a .html file with links to the .html files generated by mrtg. You can use the sources for your inspiration, can change them, BUT you are not allowed to sell them. Cfg file structure: ------------------- The .cfg file can contain any of the next row types. n meens any integer positive (>0): 0 COMMENT - mark a block of rows as a comment, /**/ c like :) 0 ENDCOMMENT 0 XDEBUG on|off - print/don't print the line readed and executed from cfgfile 0 INCLUDE cfgfile - execute de commands from the cfgfile 0 DEFHOST hostname fcfgname port - define a name 'hostname' for the pair 'fcfgname port'. 'fcfgname' is the name of a file precedently generated by cfgmaker. The resolved name for a defined host can be get from HOST_hostname alias when CHECK4ALIAS is on. 0 MRTG.CFG cfgpathdst cfgpathsrc - define the name of a generated mrtg.cfg (cfgpathdst) and the name of a source mrtg.cfg. If the two names are the same, then all the new entries in 'cfgpathdst' will be appended, else will be created a new mrtg.cfg file with the initial contains took from 'cfgpathsrc' 0 HTMLFILE filepath - where will be write the html code 0 HTMLCODE code inserted in html - insert code in the generated html file; not
    nor

    added 0 HTMLLINK link text - insert a link in the html page, making no identation; not
    nor

    added 0 LINK2DH host text - insert a link in the html page, making no identation; not
    nor

    added 0 MRTGTEXT text inserted in mrtg.cfg - insert text in the generated mrtg.cfg 0 CFGDIR cfg_path - append cfg_path in the front of .cfg files generated by cfgmaker 0 NOCFGDIR - not any more cfg_path used 0 TITLE txt - text used between TITLE tags 0 BODY body arguments - define the arguments inserted with BODY tag in the html code 0 NOBODY - erase all arguments for BODY tag 0 BASE url - append this url in front of all references at html pages and gifs 0 NOBASE - use what the user has been wrote in .cfg file 0 EXEC cmd - exec a command in shell 0 GIFD link host - day gif 0 GIFW link host - week gif 0 GIFM link host - month gif 0 GIFY link host - year gif - 0 GIFx link host -> - 0 GIFx # host -> - 0 GIFx link # -> - 0 GIFx # # -> illegal - host-x.gif means that it is searched in defined hosts list for the name cfgmaker assign to that host and append the right extension (e.g. -day.gif) to it 0 ALIAS alias_name alias_body - define an alias named alias_name and that will be used as %alias_name% and CHECK4ALIAS yes 0 DELALIAS alias_name - erase the alias :] 0 CHECK4ALIAS yes|no - if yes, then all input string will be checked for aliases. An alias is a name between %s (%alias_name% :) 0 MSG msg - display the message msg on screen 0 MKLINK dir host path - create a directory 'dir' that contain links through a host page, located in path. If exist old links, theses will be erased - create a htmlfile with day, week, month or year gifs and links through appropiate html file. Theses commandes MUST be done before any 0 DEFHOST commands relative to host from fcfg. 0 MKD fcfg htmlfilename 0 MKW fcfg htmlfilename 0 MKM fcfg htmlfilename 0 MKY fcfg htmlfilename 0 CHNGTRGNAME yes|no - change (or not) the name of the target html files if change, then the name will be the defhost declared name, otherwise will be the name declared in .cfg file by cfgmaker 0 CONVIP2NAME mrtg_out_path/ - change the name of the already existent files from an ip style (somename.x where x is the snmp index) into a defhost style - 0 CHNGTRGNAME yes is required 0 CONVNAME2IP mrtg_out_path/ - change the name of the already existent files from a defhost style into ip style (somename.x where x is the snmp index) - 0 CHNGTRGNAME no is required - mrtg_out_path must be the path where mrtg create the htmls, gifs and logs files and must end with a slash ('/') - must to be present before the definitions of the hosts for with I intend to change the file name; once switched to this action, exist not any way to fall back n HTMLCODE html code - insert code in the html page, making identation; not
    nor

    added but surrounded by

  • n HTMLLINK link text - insert a link in the html page, making identation; not
    nor

    added but surrounded by

  • n LINK2DH host text - insert a link in the html page, making identation; not
    nor

    added but surrounded by

  • n DATA host text - insert a link through a page genetrated by mrtg, making identation; surrounded by
  • # or \n - treated as a comment If you expand the code, please notify me. "mkm" call the gcc to produce the exec "mrtgmk" from mrtgmk.c . "smrtgmk" is an example of calling "mrtgmk". Iulian Radu (iulian_r@starnets.ro). 28th September 1999 12:00pm Romanian time mrtg-2.17.10/contrib/mrtgmk/doc/commands0000644000175300017510000000145513057016061017104 0ustar oetikeroep0 COMMENT 0 ENDCOMMENT 0 XDEBUG on|off 0 INCLUDE cfgfile 0 DEFHOST hostname fcfgname port 0 MRTG.CFG cfgpathdst cfgpathsrc 0 HTMLFILE filepath 0 HTMLCODE code inserted in html 0 HTMLLINK link text 0 LINK2DH host text 0 MRTGTEXT text inserted in mrtg.cfg 0 CFGDIR cfg_path 0 TITLE txt 0 BODY body arguments 0 NOBODY 0 BASE url 0 NOBASE 0 EXEC cmd link = # or RealLink 0 GIFD link host 0 GIFW link host 0 GIFM link host 0 GIFY link host 0 ALIAS alias_name alias_body 0 DELALIAS alias_name 0 CHECK4ALIAS yes|no 0 MSG msg 0 MKLINK dir host path 0 MKD fcfg htmlfilename 0 MKW fcfg htmlfilename 0 MKM fcfg htmlfilename 0 MKY fcfg htmlfilename 0 CHNGTRGNAME yes|no 0 CONVIP2NAME mrtg_out_path 0 CONVNAME2IP mrtg_out_path n HTMLCODE html code n HTMLLINK link text n LINK2DH host text n DATA host text mrtg-2.17.10/contrib/mrtgmk/smrtgmk0000755000175300017510000000011113057016061016211 0ustar oetikeroep#!/bin/sh #this is an example of using mrtgmk clear ./mrtgmk cfg/a.cfg mrtg-2.17.10/contrib/mrtgmk/cfg/0000755000175300017510000000000013057016061015345 5ustar oetikeroepmrtg-2.17.10/contrib/mrtgmk/cfg/today.html0000644000175300017510000000122513057016061017353 0ustar oetikeroep
    Traffic analyses - day

    day .gifs for hosts in the .cfg file 192.168.10.1.cfg



    Traffic analysis for pc1





    Traffic analysis for pc2





    Traffic analysis for pc3



    mrtg-2.17.10/contrib/mrtgmk/cfg/mrtg_cfg0000644000175300017510000004053113057016061017063 0ustar oetikeroep###################################################################### # Multi Router Traffic Grapher -- Example Configuration File ###################################################################### # # * copy this file to ../run and call it mrtg.cfg # * consider using ../run/cfgmaker to build your initial mrtg.cfg file # # This file is for use with mrtg-2.x # # Note: # # * Keywords must start at the begin of a line. # # * Lines which follow a keyword line which do start # with a blank are appended to the keyword line # # * Empty Lines are ignored # # * Lines starting with a # sign are comments. # #################### # Global Configuration # #################### # Where should the logfiles, and webpages be created? WorkDir: /usr/tardis/pub/www/stats/mrtg Options[_]: growright,bits # -------------------------- # Optional Global Parameters # -------------------------- # How many seconds apart should the browser (Netscape) be # instructed to reload the page? If this is not defined, the # default is 300 seconds (5 minutes). # Refresh: 600 # How often do you call mrtg? The default is 5 minutes. If # you call it less often, you should specify it here. This # does two things: # a) the generated HTML page does contain the right # information about the calling interval ... # b) a META header in the generated HTML page will instruct # caches about the time to live of this page ..... # In this example we tell mrtg that we will be calling it # every 10 minutes. If you are calling mrtg every 5 # minutes, you can leave this line commented out. # Interval: 10 # With this switch mrtg will generate .meta files for CERN # and Apache servers which contain Expiration tags for the # html and gif files. The *.meta files will be created in # the same directory as the other files, so you might have # to set "MetaDir ." in your srm.conf file for this to work # # NOTE: If you are running Apache-1.2 you can use the mod_expire # to achieve the same effect ... see the file htaccess-dist #WriteExpires: Yes # If you want to keep the mrtg icons in some place other than the # working directory, use the IconDir varibale to give its url. # IconDir: /mrtgicons/ # ################################################# # Configuration for each Target you want to monitor # ################################################# # The configuration keywords "Target" must be followed by a # unique name. This will also be the name used for the # webpages, logfiles and gifs created for that target. # Note that the "Target" sections can be auto-generated with # the cfgmaker tool. Check readme.html for instructions. # ======== ## ## Target ---------------------------------------- ## # With the "Target" keyword you tell mrtg what it should # monitor. The "Target" keyword takes arguments in a wide # range of formats: # * The most basic format is "port:community@router" # This will generate a traffic graph for port 'port' # of the router 'router' and it will use the community # 'community' for the snmp query. # Target[ezwf]: 2:public@wellfleet-fddi.ethz.ch # * Sometimes you are sitting on the wrong side of the # link. And you would like to have mrtg report Incoming # traffic as outgoing and visa versa. This can be achieved # by adding the '-' sign in front of the "Target" # description. It flips the in and outgoing traffic rates. # Target[ezci]: -1:public@ezci-ether.ethz.ch # * You can also explicitly define the OID to query by using the # following syntax 'OID_1&OID_2:community@router' # The following example will retrieve error input and output # octets/sec on interface 1. MRTG needs to graph two values, so # you need to specify two OID's such as temperature and humidity # or error input and error output. # Target[ezwf]: 1.3.6.1.2.1.2.2.1.14.1&1.3.6.1.2.1.2.2.1.20.1:public@myrouter # * mrtg knows a number of symbolical SNMP variable # names. See the file mibhelp.txt for a list of known # names. One example are the ifInErrors and and ifOutErrors # names. This means you can specify the above as: # Target[ezwf]: ifInErrors.1&ifOutErrors.1:public@myrouter # * if you want to monitor something which does not provide # data via snmp you can use some external program to do # the data gathering. # # The external command must return 4 lines of output: # Line 1 : current state of the 'incoming bytes counter' # Line 2 : current state of the 'outgoing bytes counter' # Line 3 : string, telling the uptime of the target. # Line 4 : string, telling the name of the target. # Depending on the type of data your script returns you # might want to use the 'gauge' or 'absolute' arguments # for the "Options" keyword. # Target[ezwf]: `/usr/local/bin/df2mrtg /dev/dsk/c0t2d0s0` # * You can also use several statements in a mathematical # expression. This could be used to aggregate both B channels # in an ISDN connection or multiple T1's that are aggregated # into a single channel for greater bandwidth. # Note the whitespace arround the target definitions. # Target[ezwf]: 2:public@wellfleetA + 1:public@wellfleetA # * 4:public@ciscoF ## ## RouterUptime --------------------------------------- ## # # In cases where you calculate the used bandwidth from # several interfaces you normaly don't get the routeruptime # and routername displayed on the web page. # If this interface are on the same router and the uptime and # name should be displayed nevertheless you have to specify # its community and address again with the RouterUptime keyword. # Target[kacisco]: 1:public@194.64.66.250 + 2:public@194.64.66.250 # RouterUptime[kacisco]: public@194.64.66.250 ## ## MaxBytes ------------------------------------------- ## # How many bytes per second can this port carry. Since most # links are rated in bits per second, you need to divide # their maximum bandwidth (in bits) by eight (8) in order to get # bytes per second. This is very important to make your # unscaled graphs display realistic information. # T1 = 193000, 56K = 7000, Ethernet = 1250000. The "MaxBytes" # value will be used by mrtg to decide whether it got a # valid response from the router. If a number higher than # "MaxBytes" is returned, it is ignored. Also read the section # on AbsMax for further info. # MaxBytes[ezwf]: 1250000 ## ## Title ----------------------------------------------- ## # Title for the HTML page which gets generated for the graph. # Title[ezwf]: Traffic Analysis for ETZ C 95.1 ## ## PageTop --------------------------------------------- ## # Things to add to the top of the generated HTML page. Note # that you can have several lines of text as long as the # first column is empty. # Note that the continuation lines will all end up on the same # line in the html page. If you want linebreaks in the generated # html use the '\n' sequence. # PageTop[ezwf]:

    Traffic Analysis for ETZ C95.1

    # Our Campus Backbone runs over an FDDI line\n # with a maximum transfer rate of 12.5 Mega Bytes per # Second. ## ## PageFoot --------------------------------------------- ## # Things to add at the very end of the mrtg generated html page # PageFoot[ezwf]:
    This page is managed by Blubber # -------------------------------------------------- # Optional Target Configuration Tags # -------------------------------------------------- ## ## AddHead ----------------------------------------- ## # Use this tag like the PageTop header, but its contents # will be added between and . # AddHead[ezwf]: ## ## AbsMax ------------------------------------------ ## # If you are monitoring a link which can handle more traffic # than the MaxBytes value. Eg, a line which uses compression # or some frame relay link, you can use the AbsMax keyword # to give the absolute maximum value ever to be reached. We # need to know this in order to sort out unrealistic values # returned by the routers. If you do not set absmax, rateup # will ignore values higher then MaxBytes. # AbsMax[ezwf]: 2500000 ## ## Unscaled ------------------------------------------ ## # By default each graph is scaled vertically to make the # actual data visible even when it is much lower than # MaxBytes. With the "Unscaled" variable you can suppress # this. It's argument is a string, containing one letter # for each graph you don't want to be scaled: d=day w=week # m=month y=year. In the example I suppress scaling for the # yearly and the monthly graph. # Unscaled[ezwf]: ym ## ## WithPeak ------------------------------------------ ## # By default the graphs only contain the average transfer # rates for incoming and outgoing traffic. The # following option instructs mrtg to display the peak # 5 minute transfer rates in the [w]eekly, [m]onthly and # [y]early graph. In the example we define the monthly # and the yearly graph to contain peak as well as average # values. # WithPeak[ezwf]: ym ## ## Supress ------------------------------------------ ## # By Default mrtg produces 4 graphs. With this option you # can suppress the generation of selected graphs. The format # is analog to the above option. In this example we suppress # the yearly graph as it is quite empty in the beginning. # Suppress[ezwf]: y ## ## Directory ## # By default, mrtg puts all the files that it generates for each # router (the GIFs, the HTML page, the log file, etc.) in WorkDir. # If the "Directory" option is specified, the files are instead put # into a directory under WorkDir. (For example, given the options in # this mrtg.cfg-dist file, the "Directory" option below would cause all # the ezwf files to be put into /usr/tardis/pub/www/stats/mrtg/ezwf .) # # The directory must already exist; mrtg will not create it. # Directory[ezwf]: ezwf ## ## XSize and YSize ------------------------------------------ ## # By Default mrtgs graphs are 100 by 400 pixels wide (plus # some more for the labels. In the example we get almost # square graphs ... # Note: XSize must be between 20 and 600 # YSize must be larger than 20 # XSize[ezwf]: 300 # YSize[ezwf]: 300 ## ## XZoom YZoom ------------------------------------------------- ## # If you want your graphs to have larger pixels, you can # "Zoom" them. #XZoom[ezwf]: 2.0 #YZoom[ezwf]: 2.0 ## ## XScale YScale ------------------------------------------------- ## # If you want your graphs to be actually scaled use XScale # and YScale. (Beware while this works, the results look ugly # (to be frank) so if someone wants fix this: patches are # welcome. # XScale[ezwf]: 1.5 # YScale[ezwf]: 1.5 ## ## Step ----------------------------------------------------------- ## # Change the default step with from 5 * 60 seconds to # something else I have not tested this well ... # Step[ezwf]: 60 ## ## Options ------------------------------------------ ## # The "Options" Keyword allows you to set some boolean # switches: # # growright - The graph grows to the left by default. # # bits - All the numbers printed are in bits instead # of bytes ... looks much more impressive :-) # # noinfo - Supress the information about uptime and # device name in the generated webpage. # # absolute - This is for data sources which reset their # value when they are read. This means that # rateup has not to build the difference between # this and the last value read from the data # source. Useful for external data gatherers. # # gauge - Treat the values gathered from target as absolute # and not as counters. This would be useful to # monitor things like diskspace, load and so # on .... # # nopercent Don't print usage percentages # # integer Print only integers in the summary # below the graph (No Kilo, Mega, Gigas) ... # # Options[ezwf]: growright, bits ## ## Colours ------------------------------------------ ## # The "Colours" tag allows you to override the default colour # scheme. Note: All 4 of the required colours must be # specified here The colour name ('Colourx' below) is the # legend name displayed, while the RGB value is the real # colour used for the display, both on the graph and n the # html doc. # Format is: Colour1#RRGGBB,Colour2#RRGGBB,Colour3#RRGGBB,Colour4#RRGGBB # where: Colour1 = Input on default graph # Colour2 = Output on default graph # Colour3 = Max input # Colour4 = Max output # RRGGBB = 2 digit hex values for Red, Green and Blue # Colours[ezwf]: GREEN#00eb0c,BLUE#1000ff,DARK GREEN#006600,VIOLET#ff00ff ## ## Background ------------------------------------------ ## # With the "Background" tag you can configure the background # colour of the generated HTML page # Background[ezwf]: #a0a0a0a ## ## YLegend, ShortLegend, Legend[1234] ------------------ ## # The following keywords allow you to override the text # displayed for the various legends of the graph and in the # HTML document # # * YLegend : The Y-Axis of the graph # * ShortLegend: The 'b/s' string used for Max, Average and Current # * Legend[1234IO]: The strings for the colour legend # #YLegend[ezwf]: Bits per Second #ShortLegend[ezwf]: b/s #Legend1[ezwf]: Incoming Traffic in Bits per Second #Legend2[ezwf]: Outgoing Traffic in Bits per Second #Legend3[ezwf]: Maximal 5 Minute Incoming Traffic #Legend4[ezwf]: Maximal 5 Minute Outgoing Traffic #LegendI[ezwf]:  In: #LegendO[ezwf]:  Out: # Note, if LegendI or LegendO are set to an empty string with # LegendO[ezwf]: # The corresponding line below the graph will not be printed at all. # If you live in an international world, you might want to # generate the graphs in different timezones. This is set in the # TZ variable. Under certain operating systems like Solaris, # this will provoke the localtime call to giv the time in # the selected timezone ... # Timezone[ezwf]: Japan # The Timezone is the standard Solaris timezone, ie Japan, Hongkong, # GMT, GMT+1 etc etc. # By default, mrtg (actually rateup) uses the strftime(3) '%W' option # to format week numbers in the monthly graphs. The exact semantics # of this format option vary between systems. If you find that the # week numbers are wrong, and your system's strftime(3) routine # supports it, you can try another format option. The POSIX '%V' # option seems to correspond to a widely used week numbering # convention. The week format character should be specified as a # single letter; either W, V, or U. # Weekformat[ezwf]: V # ############################# # Two very special Target names # ############################# # To save yourself some typing you can define a target # called '^'. The text of every Keyword you define for this # target will be PREPENDED to the corresponding Keyword of # all the targets defined below this line. The same goes for # a Target called '$' but its options will be APPENDED. # # The example will make mrtg use a common header and a # common contact person in all the pages generated from # targets defined later in this file. # #PageTop[^]:

    NoWhere Unis Traffic Stats


    #PageTop[$]: Contact Peter Norton if you have any questions
    ################################################################## ################################################################## ################################################################## # # Now some example mrtg.cfg files # ################################################################## ################################################################## ################################################################## # Minimal mrtg.cfg #-------------------- #WorkDir: /usr/tardis/pub/www/stats/mrtg #Target[r1]: 2:public@myrouter.somplace.edu #MaxBytes[r1]: 64000 #Title[r1]: Traffic Analysis ISDN #PageTop[r1]:

    Stats for our ISDN Line

    # Minimal Cfg for several Routers. #--------------------------------- #WorkDir: /usr/tardis/pub/www/stats/mrtg # #Title[^]: Traffic Analysis for #PageTop[^]:

    Stats for our #PageTop[$]: Contact The Chief if you notice anybody
    # #Title[isdn]: our ISDN Line #PageTop[isdn]: our ISDN Line

    #Target[isdn]: 2:public@router.somplace.edu #MaxBytes[isdn]: 64000 # #Title[backb]: our Campus Backbone #PageTop[backb]: our Campus Backbone #Target[backb]: 1:public@router.somplace.edu #MaxBytes[backb]: 1250000 # the following line removes the default prepend value # defined above #Title[^]: #Title[isdn2]: Traffic for the Backup ISDN Line #PageTop[isdn2]: our ISDN Line #Target[isdn2]: 3:public@router.somplace.edu #MaxBytes[isdn2]: 64000 mrtg-2.17.10/contrib/mrtgmk/cfg/page2.cfg0000644000175300017510000000043313057016061017024 0ustar oetikeroep0 HTMLFILE cfg/page2.html 0 HTMLCODE

    PC from local network - overview

    0 HTMLCODE PC1 Trafic analyses
    0 GIFD # pc1 0 HTMLCODE

    0 HTMLCODE PC2 Trafic analyses
    0 GIFD # pc2 0 HTMLCODE

    0 HTMLCODE PC3 Trafic analyses
    0 GIFD # pc3 0 HTMLCODE

    mrtg-2.17.10/contrib/mrtgmk/cfg/page2.html0000644000175300017510000000110413057016061017225 0ustar oetikeroep
    Traffic analyses

    PC from local network - overview

    PC1 Trafic analyses


    PC2 Trafic analyses


    PC3 Trafic analyses


    mrtg-2.17.10/contrib/mrtgmk/cfg/alias.cfg0000644000175300017510000000016113057016061017115 0ustar oetikeroep0 CHECK4ALIAS yes 0 ALIAS date 07/12/1999 0 ALIAS time 12:25 am 0 ALIAS author Iulian Radu (iulian_r@starnets.ro)mrtg-2.17.10/contrib/mrtgmk/cfg/mrtg.cfg0000644000175300017510000004513613057016061017010 0ustar oetikeroep###################################################################### # Multi Router Traffic Grapher -- Example Configuration File ###################################################################### # # * copy this file to ../run and call it mrtg.cfg # * consider using ../run/cfgmaker to build your initial mrtg.cfg file # # This file is for use with mrtg-2.x # # Note: # # * Keywords must start at the begin of a line. # # * Lines which follow a keyword line which do start # with a blank are appended to the keyword line # # * Empty Lines are ignored # # * Lines starting with a # sign are comments. # #################### # Global Configuration # #################### # Where should the logfiles, and webpages be created? WorkDir: /usr/tardis/pub/www/stats/mrtg Options[_]: growright,bits # -------------------------- # Optional Global Parameters # -------------------------- # How many seconds apart should the browser (Netscape) be # instructed to reload the page? If this is not defined, the # default is 300 seconds (5 minutes). # Refresh: 600 # How often do you call mrtg? The default is 5 minutes. If # you call it less often, you should specify it here. This # does two things: # a) the generated HTML page does contain the right # information about the calling interval ... # b) a META header in the generated HTML page will instruct # caches about the time to live of this page ..... # In this example we tell mrtg that we will be calling it # every 10 minutes. If you are calling mrtg every 5 # minutes, you can leave this line commented out. # Interval: 10 # With this switch mrtg will generate .meta files for CERN # and Apache servers which contain Expiration tags for the # html and gif files. The *.meta files will be created in # the same directory as the other files, so you might have # to set "MetaDir ." in your srm.conf file for this to work # # NOTE: If you are running Apache-1.2 you can use the mod_expire # to achieve the same effect ... see the file htaccess-dist #WriteExpires: Yes # If you want to keep the mrtg icons in some place other than the # working directory, use the IconDir varibale to give its url. # IconDir: /mrtgicons/ # ################################################# # Configuration for each Target you want to monitor # ################################################# # The configuration keywords "Target" must be followed by a # unique name. This will also be the name used for the # webpages, logfiles and gifs created for that target. # Note that the "Target" sections can be auto-generated with # the cfgmaker tool. Check readme.html for instructions. # ======== ## ## Target ---------------------------------------- ## # With the "Target" keyword you tell mrtg what it should # monitor. The "Target" keyword takes arguments in a wide # range of formats: # * The most basic format is "port:community@router" # This will generate a traffic graph for port 'port' # of the router 'router' and it will use the community # 'community' for the snmp query. # Target[ezwf]: 2:public@wellfleet-fddi.ethz.ch # * Sometimes you are sitting on the wrong side of the # link. And you would like to have mrtg report Incoming # traffic as outgoing and visa versa. This can be achieved # by adding the '-' sign in front of the "Target" # description. It flips the in and outgoing traffic rates. # Target[ezci]: -1:public@ezci-ether.ethz.ch # * You can also explicitly define the OID to query by using the # following syntax 'OID_1&OID_2:community@router' # The following example will retrieve error input and output # octets/sec on interface 1. MRTG needs to graph two values, so # you need to specify two OID's such as temperature and humidity # or error input and error output. # Target[ezwf]: 1.3.6.1.2.1.2.2.1.14.1&1.3.6.1.2.1.2.2.1.20.1:public@myrouter # * mrtg knows a number of symbolical SNMP variable # names. See the file mibhelp.txt for a list of known # names. One example are the ifInErrors and and ifOutErrors # names. This means you can specify the above as: # Target[ezwf]: ifInErrors.1&ifOutErrors.1:public@myrouter # * if you want to monitor something which does not provide # data via snmp you can use some external program to do # the data gathering. # # The external command must return 4 lines of output: # Line 1 : current state of the 'incoming bytes counter' # Line 2 : current state of the 'outgoing bytes counter' # Line 3 : string, telling the uptime of the target. # Line 4 : string, telling the name of the target. # Depending on the type of data your script returns you # might want to use the 'gauge' or 'absolute' arguments # for the "Options" keyword. # Target[ezwf]: `/usr/local/bin/df2mrtg /dev/dsk/c0t2d0s0` # * You can also use several statements in a mathematical # expression. This could be used to aggregate both B channels # in an ISDN connection or multiple T1's that are aggregated # into a single channel for greater bandwidth. # Note the whitespace arround the target definitions. # Target[ezwf]: 2:public@wellfleetA + 1:public@wellfleetA # * 4:public@ciscoF ## ## RouterUptime --------------------------------------- ## # # In cases where you calculate the used bandwidth from # several interfaces you normaly don't get the routeruptime # and routername displayed on the web page. # If this interface are on the same router and the uptime and # name should be displayed nevertheless you have to specify # its community and address again with the RouterUptime keyword. # Target[kacisco]: 1:public@194.64.66.250 + 2:public@194.64.66.250 # RouterUptime[kacisco]: public@194.64.66.250 ## ## RouterName ----------------------------------------- ## # # If the default name of the router is incorrect/uninformative, # you can use RouterName to specify a different OID on either the # same or a different host. # Use 1.3.6.1.4.1.4779.1.1.3.0 on the same host: # RouterName[kacisco]: 1.3.6.1.4.1.4779.1.1.3.0 # Use 1.3.6.1.4.1.4779.1.1.3.0 on a differnet host (194.64.66.251): # RouterName[kacisco]: 1.3.6.1.4.1.4779.1.1.3.0:public@194.64.66.251 ## ## MaxBytes ------------------------------------------- ## # How many bytes per second can this port carry. Since most # links are rated in bits per second, you need to divide # their maximum bandwidth (in bits) by eight (8) in order to get # bytes per second. This is very important to make your # unscaled graphs display realistic information. # T1 = 193000, 56K = 7000, Ethernet = 1250000. The "MaxBytes" # value will be used by mrtg to decide whether it got a # valid response from the router. If a number higher than # "MaxBytes" is returned, it is ignored. Also read the section # on AbsMax for further info. # MaxBytes[ezwf]: 1250000 ## ## Title ----------------------------------------------- ## # Title for the HTML page which gets generated for the graph. # Title[ezwf]: Traffic Analysis for ETZ C 95.1 ## ## PageTop --------------------------------------------- ## # Things to add to the top of the generated HTML page. Note # that you can have several lines of text as long as the # first column is empty. # Note that the continuation lines will all end up on the same # line in the html page. If you want linebreaks in the generated # html use the '\n' sequence. # PageTop[ezwf]:

    Traffic Analysis for ETZ C95.1

    # Our Campus Backbone runs over an FDDI line\n # with a maximum transfer rate of 12.5 Mega Bytes per # Second. ## ## PageFoot --------------------------------------------- ## # Things to add at the very end of the mrtg generated html page # PageFoot[ezwf]:
    This page is managed by Blubber # -------------------------------------------------- # Optional Target Configuration Tags # -------------------------------------------------- ## ## AddHead ----------------------------------------- ## # Use this tag like the PageTop header, but its contents # will be added between and . # AddHead[ezwf]: ## ## AbsMax ------------------------------------------ ## # If you are monitoring a link which can handle more traffic # than the MaxBytes value. Eg, a line which uses compression # or some frame relay link, you can use the AbsMax keyword # to give the absolute maximum value ever to be reached. We # need to know this in order to sort out unrealistic values # returned by the routers. If you do not set absmax, rateup # will ignore values higher then MaxBytes. # AbsMax[ezwf]: 2500000 ## ## Unscaled ------------------------------------------ ## # By default each graph is scaled vertically to make the # actual data visible even when it is much lower than # MaxBytes. With the "Unscaled" variable you can suppress # this. It's argument is a string, containing one letter # for each graph you don't want to be scaled: d=day w=week # m=month y=year. In the example I suppress scaling for the # yearly and the monthly graph. # Unscaled[ezwf]: ym ## ## WithPeak ------------------------------------------ ## # By default the graphs only contain the average transfer # rates for incoming and outgoing traffic. The # following option instructs mrtg to display the peak # 5 minute transfer rates in the [w]eekly, [m]onthly and # [y]early graph. In the example we define the monthly # and the yearly graph to contain peak as well as average # values. # WithPeak[ezwf]: ym ## ## Supress ------------------------------------------ ## # By Default mrtg produces 4 graphs. With this option you # can suppress the generation of selected graphs. The format # is analog to the above option. In this example we suppress # the yearly graph as it is quite empty in the beginning. # Suppress[ezwf]: y ## ## Directory ## # By default, mrtg puts all the files that it generates for each # router (the GIFs, the HTML page, the log file, etc.) in WorkDir. # If the "Directory" option is specified, the files are instead put # into a directory under WorkDir. (For example, given the options in # this mrtg.cfg-dist file, the "Directory" option below would cause all # the ezwf files to be put into /usr/tardis/pub/www/stats/mrtg/ezwf .) # # The directory must already exist; mrtg will not create it. # Directory[ezwf]: ezwf ## ## XSize and YSize ------------------------------------------ ## # By Default mrtgs graphs are 100 by 400 pixels wide (plus # some more for the labels. In the example we get almost # square graphs ... # Note: XSize must be between 20 and 600 # YSize must be larger than 20 # XSize[ezwf]: 300 # YSize[ezwf]: 300 ## ## XZoom YZoom ------------------------------------------------- ## # If you want your graphs to have larger pixels, you can # "Zoom" them. #XZoom[ezwf]: 2.0 #YZoom[ezwf]: 2.0 ## ## XScale YScale ------------------------------------------------- ## # If you want your graphs to be actually scaled use XScale # and YScale. (Beware while this works, the results look ugly # (to be frank) so if someone wants fix this: patches are # welcome. # XScale[ezwf]: 1.5 # YScale[ezwf]: 1.5 ## ## Step ----------------------------------------------------------- ## # Change the default step with from 5 * 60 seconds to # something else I have not tested this well ... # Step[ezwf]: 60 ## ## Options ------------------------------------------ ## # The "Options" Keyword allows you to set some boolean # switches: # # growright - The graph grows to the left by default. # # bits - All the numbers printed are in bits instead # of bytes ... looks much more impressive :-) # # noinfo - Supress the information about uptime and # device name in the generated webpage. # # absolute - This is for data sources which reset their # value when they are read. This means that # rateup has not to build the difference between # this and the last value read from the data # source. Useful for external data gatherers. # # gauge - Treat the values gathered from target as absolute # and not as counters. This would be useful to # monitor things like diskspace, load and so # on .... # # nopercent Don't print usage percentages # # integer Print only integers in the summary # below the graph (No Kilo, Mega, Gigas) ... # # Options[ezwf]: growright, bits ## ## Colours ------------------------------------------ ## # The "Colours" tag allows you to override the default colour # scheme. Note: All 4 of the required colours must be # specified here The colour name ('Colourx' below) is the # legend name displayed, while the RGB value is the real # colour used for the display, both on the graph and n the # html doc. # Format is: Colour1#RRGGBB,Colour2#RRGGBB,Colour3#RRGGBB,Colour4#RRGGBB # where: Colour1 = Input on default graph # Colour2 = Output on default graph # Colour3 = Max input # Colour4 = Max output # RRGGBB = 2 digit hex values for Red, Green and Blue # Colours[ezwf]: GREEN#00eb0c,BLUE#1000ff,DARK GREEN#006600,VIOLET#ff00ff ## ## Background ------------------------------------------ ## # With the "Background" tag you can configure the background # colour of the generated HTML page # Background[ezwf]: #a0a0a0a ## ## YLegend, ShortLegend, Legend[1234] ------------------ ## # The following keywords allow you to override the text # displayed for the various legends of the graph and in the # HTML document # # * YLegend : The Y-Axis of the graph # * ShortLegend: The 'b/s' string used for Max, Average and Current # * Legend[1234IO]: The strings for the colour legend # #YLegend[ezwf]: Bits per Second #ShortLegend[ezwf]: b/s #Legend1[ezwf]: Incoming Traffic in Bits per Second #Legend2[ezwf]: Outgoing Traffic in Bits per Second #Legend3[ezwf]: Maximal 5 Minute Incoming Traffic #Legend4[ezwf]: Maximal 5 Minute Outgoing Traffic #LegendI[ezwf]:  In: #LegendO[ezwf]:  Out: # Note, if LegendI or LegendO are set to an empty string with # LegendO[ezwf]: # The corresponding line below the graph will not be printed at all. # If you live in an international world, you might want to # generate the graphs in different timezones. This is set in the # TZ variable. Under certain operating systems like Solaris, # this will provoke the localtime call to giv the time in # the selected timezone ... # Timezone[ezwf]: Japan # The Timezone is the standard Solaris timezone, ie Japan, Hongkong, # GMT, GMT+1 etc etc. # By default, mrtg (actually rateup) uses the strftime(3) '%W' option # to format week numbers in the monthly graphs. The exact semantics # of this format option vary between systems. If you find that the # week numbers are wrong, and your system's strftime(3) routine # supports it, you can try another format option. The POSIX '%V' # option seems to correspond to a widely used week numbering # convention. The week format character should be specified as a # single letter; either W, V, or U. # Weekformat[ezwf]: V # ############################# # Two very special Target names # ############################# # To save yourself some typing you can define a target # called '^'. The text of every Keyword you define for this # target will be PREPENDED to the corresponding Keyword of # all the targets defined below this line. The same goes for # a Target called '$' but its options will be APPENDED. # # The example will make mrtg use a common header and a # common contact person in all the pages generated from # targets defined later in this file. # #PageTop[^]:

    NoWhere Unis Traffic Stats


    #PageTop[$]: Contact Peter Norton if you have any questions
    ################################################################## ################################################################## ################################################################## # # Now some example mrtg.cfg files # ################################################################## ################################################################## ################################################################## # Minimal mrtg.cfg #-------------------- #WorkDir: /usr/tardis/pub/www/stats/mrtg #Target[r1]: 2:public@myrouter.somplace.edu #MaxBytes[r1]: 64000 #Title[r1]: Traffic Analysis ISDN #PageTop[r1]:

    Stats for our ISDN Line

    # Minimal Cfg for several Routers. #--------------------------------- #WorkDir: /usr/tardis/pub/www/stats/mrtg # #Title[^]: Traffic Analysis for #PageTop[^]:

    Stats for our #PageTop[$]: Contact The Chief if you notice anybody
    # #Title[isdn]: our ISDN Line #PageTop[isdn]: our ISDN Line

    #Target[isdn]: 2:public@router.somplace.edu #MaxBytes[isdn]: 64000 # #Title[backb]: our Campus Backbone #PageTop[backb]: our Campus Backbone #Target[backb]: 1:public@router.somplace.edu #MaxBytes[backb]: 1250000 # the following line removes the default prepend value # defined above #Title[^]: #Title[isdn2]: Traffic for the Backup ISDN Line #PageTop[isdn2]: our ISDN Line #Target[isdn2]: 3:public@router.somplace.edu #MaxBytes[isdn2]: 64000 #---------------------------------------------------------------------- #host pc1, cfgfile cfg/192.168.10.1.cfg, port serial0 Target[192.168.10.1.1]: 1:public@192.168.10.1 MaxBytes[192.168.10.1.1]: 1250000 Title[192.168.10.1.1]: : Serial0 PageTop[192.168.10.1.1]:

    Traffic Analysis for Serial0

    System:local-gw in
    Maintainer:
    Interface:Serial0 (1)
    IP:local-gw (192.168.10.1)
    Max Speed: 1250.0 kBytes/s
    #---------------------------------------------------------------------- #host pc2, cfgfile cfg/192.168.10.1.cfg, port serial2 Target[192.168.10.1.3]: 3:public@192.168.10.1 MaxBytes[192.168.10.1.3]: 1250000 Title[192.168.10.1.3]: : Serial2 PageTop[192.168.10.1.3]:

    Traffic Analysis for Serial2

    System:local-gw in
    Maintainer:
    Interface:Serial2 (3)
    IP:local-gw (192.168.10.1)
    Max Speed: 1250.0 kBytes/s
    #---------------------------------------------------------------------- #host pc3, cfgfile cfg/192.168.10.1.cfg, port serial3 Target[192.168.10.1.4]: 4:public@192.168.10.1 MaxBytes[192.168.10.1.4]: 1250000 Title[192.168.10.1.4]: : Serial3 PageTop[192.168.10.1.4]:

    Traffic Analysis for Serial3

    System:local-gw in
    Maintainer:
    Interface:Serial0 (1)
    IP:local-gw (192.168.10.1)
    Max Speed: 1250.0 kBytes/s
    #---------------------------------------------------------------------- mrtg-2.17.10/contrib/mrtgmk/cfg/misc.cfg0000644000175300017510000000017713057016061016766 0ustar oetikeroep0 MSG cfg file made by %author% 0 BASE traffic.isp.ro 0 MSG pc1 is %HOST_pc1% 0 MSG pc2 is %HOST_pc2% 0 MSG pc3 is %HOST_pc3% mrtg-2.17.10/contrib/mrtgmk/cfg/a.cfg0000644000175300017510000000100113057016061016236 0ustar oetikeroep# We have here cfg/ appended in front of each file path because # all this files are relative to the directory from where we # start the mrtgmk. 0 MRTG.CFG cfg/mrtg.cfg cfg/mrtg_cfg 0 INCLUDE cfg/alias.cfg 0 INCLUDE cfg/misc.cfg 0 MKD 192.168.10.1.cfg cfg/today.html 0 INCLUDE cfg/hosts.cfg 0 MSG 0 MSG I create the thml pages 0 INCLUDE cfg/page1.cfg 0 INCLUDE cfg/page2.cfg 0 MSG 0 MSG I create a special directory in cfg, 0 MSG with links through pcn's graphs for admin of pcn 0 INCLUDE cfg/links.cfg 0 MSG mrtg-2.17.10/contrib/mrtgmk/cfg/192.168.10.1.cfg0000644000175300017510000000506513057016061017242 0ustar oetikeroep Target[192.168.10.1.1]: 1:public@192.168.10.1 MaxBytes[192.168.10.1.1]: 1250000 Title[192.168.10.1.1]: : Serial0 PageTop[192.168.10.1.1]:

    Traffic Analysis for Serial0

    System:local-gw in
    Maintainer:
    Interface:Serial0 (1)
    IP:local-gw (192.168.10.1)
    Max Speed: 1250.0 kBytes/s
    #---------------------------------------------------------------------- Target[192.168.10.1.2]: 2:public@192.168.10.1 MaxBytes[192.168.10.1.2]: 1250000 Title[192.168.10.1.2]: : Serial1 PageTop[192.168.10.1.2]:

    Traffic Analysis for Serial1

    System:local-gw in
    Maintainer:
    Interface:Serial1 (2)
    IP:local-gw (192.168.10.1)
    Max Speed: 1250.0 kBytes/s
    #---------------------------------------------------------------------- Target[192.168.10.1.3]: 3:public@192.168.10.1 MaxBytes[192.168.10.1.3]: 1250000 Title[192.168.10.1.3]: : Serial2 PageTop[192.168.10.1.3]:

    Traffic Analysis for Serial2

    System:local-gw in
    Maintainer:
    Interface:Serial2 (3)
    IP:local-gw (192.168.10.1)
    Max Speed: 1250.0 kBytes/s
    #---------------------------------------------------------------------- Target[192.168.10.1.4]: 4:public@192.168.10.1 MaxBytes[192.168.10.1.4]: 1250000 Title[192.168.10.1.4]: : Serial3 PageTop[192.168.10.1.4]:

    Traffic Analysis for Serial3

    System:local-gw in
    Maintainer:
    Interface:Serial0 (1)
    IP:local-gw (192.168.10.1)
    Max Speed: 1250.0 kBytes/s
    #---------------------------------------------------------------------- Target[192.168.10.1.5]: 5:public@192.168.10.1 MaxBytes[192.168.10.1.5]: 1250000 Title[192.168.10.1.5]: : Serial4 PageTop[192.168.10.1.5]:

    Traffic Analysis for Serial4

    System:local-gw in
    Maintainer:
    Interface:Serial4 (5)
    IP:local-gw (192.168.10.1)
    Max Speed: 1250.0 kBytes/s
    mrtg-2.17.10/contrib/mrtgmk/cfg/page1.html0000644000175300017510000000063413057016061017233 0ustar oetikeroep
    Traffic analyses
    mrtg-2.17.10/contrib/mrtgmk/cfg/hosts.cfg0000644000175300017510000000020213057016061017160 0ustar oetikeroep0 CFGDIR cfg 0 DEFHOST pc1 192.168.10.1.cfg serial0 0 DEFHOST pc2 192.168.10.1.cfg serial2 0 DEFHOST pc3 192.168.10.1.cfg serial3 mrtg-2.17.10/contrib/mrtgmk/cfg/convert.cfg0000644000175300017510000000045513057016061017512 0ustar oetikeroep# We have here cfg/ appended in front of each file path because # all this files are relative to the directory from where we # start the mrtgmk. 0 MRTG.CFG mrtg.cfg mrtg_cfg 0 MSG 0 MSG I change the files name 0 CONVIP2NAME /usr/tardis/pub/www/stats/mrtg/ 0 CHNGTRGNAME yes 0 INCLUDE hosts.cfg 0 MSG mrtg-2.17.10/contrib/mrtgmk/cfg/links.cfg0000644000175300017510000000034513057016061017150 0ustar oetikeroep# use the same directory like the one defined in mrtg_cfg 0 MKLINK cfg/link_pc1 pc1 /usr/tardis/pub/www/stats/mrtg 0 MKLINK cfg/link_pc2 pc2 /usr/tardis/pub/www/stats/mrtg 0 MKLINK cfg/link_pc3 pc3 /usr/tardis/pub/www/stats/mrtg mrtg-2.17.10/contrib/mrtgmk/cfg/page1.cfg0000644000175300017510000000025113057016061017021 0ustar oetikeroep0 HTMLFILE cfg/page1.html 1 HTMLCODE

    PC from local network - links

    1 DATA pc1 PC1 Trafic analyses 1 DATA pc2 PC2 Trafic analyses 1 DATA pc3 PC3 Trafic analyses mrtg-2.17.10/contrib/mrtgmk/cfg/EXAMPLE10000755000175300017510000000004313057016061016444 0ustar oetikeroep#!/bin/bash ../mrtgmk convert.cfg mrtg-2.17.10/contrib/mrtgmk/readme.1st0000644000175300017510000000176613057016061016506 0ustar oetikeroep"mrtgmk" by Iulian Radu (iulian_r@starnets.ro) [v2.2] "mrtgmk" is giftware. It is my contribution to mrtg package. "mrtgmk" is a program that scan a .cfg file and generate a mrtg.cfg style file + a .html file with links to the .html files generated by mrtg. Version 2.2 bring you a strong facility: you can rename the target defined inside of genereated mrtg.cfg file. Using this new facility, you will no longer depends on snmp index value. So, if the index of a port is changed on a router, your graphics will still reprezent corect the history of a host. If you need to migrate from v1.x to v2.x read the readme.1st and use the program from v1_to_v2 directory. To learn to use mrtgmk v2.x read the docs from doc directory. In cfg directory you will find an example of a cfg file for mrtgmk v2.x. Because I dont make all the times checkes for receiving of correct arguments, a core dump is posible :( , everything depends on you. Iulian Radu (iulian_r@starnets.ro). 13th July 1999 12:00am Romanian time mrtg-2.17.10/contrib/mrtgmk/src/0000755000175300017510000000000013057016061015375 5ustar oetikeroepmrtg-2.17.10/contrib/mrtgmk/src/vars.h0000644000175300017510000000313013057016061016516 0ustar oetikeroep#ifndef _VARS_H_ #define _VARS_H_ FILE *fh=NULL,*fm=NULL; //html and mrtg files int xdebug=0; //say if produce extreme debug int comment=0; //say if inside of a comment block char cfgdir[257]=""; //path of the cfg file #define N_HOSTS 4096 int nhosts=0; //# of defined states char hostsn[N_HOSTS][65]; //host name char hostsi[N_HOSTS][33]; //host definition as interface int identl=0; char body[257]=""; //code appended to body tag char base[257]=""; //base for html files #define N_ALIAS 128 int nalias=0; //# of defined aliases char aliasn[N_ALIAS][33]; //name of the aliases and their contents char aliasi[N_ALIAS][129]; //name of the interfaces and their resolv int usealias=0; //say if is allowed to use aliases int chngname=0; //say if change the name of the output files int conv=0; //say if change or not the name of the files char title[65]; //title of the html page #define N_MK 128 int nmkr[4]={ 0, //# of files procesed for mkd 0, //# of files procesed for mkw 0, //# of files procesed for mkm 0}; //# of files procesed for mky char mkrn[N_MK][8][257]; //0=name of the cfg procesed for mkd //1=name of the cfg procesed for mkw //2=name of the cfg procesed for mkm //3=name of the cfg procesed for mky //4=name of the router procesed for mkd //5=name of the router procesed for mkw //6=name of the router procesed for mkm //7=name of the router procesed for mky FILE* mkri[N_MK][4]; //0=FILE* for mkd //1=FILE* for mkw //2=FILE* for mkm //3=FILE* for mky char mrtgoutpath[256]; //used be convname2ip and convip2name #endif mrtg-2.17.10/contrib/mrtgmk/src/defhost.c0000644000175300017510000001101713057016061017175 0ustar oetikeroep/* Iulian Radu [v2.0@07.1999] */ int mkndx(char* file){ char tmp[257],xtmp[257],*ptmp; FILE *fcfg,*fndx; unsigned long ofs,xofs; /* open .cfg file */ if(cfgdir[0]) sprintf(tmp,"%s/%s",cfgdir,file); else strcpy(tmp,file); fcfg=fopen(tmp,"rt"); if(!fcfg){ fprintf(stderr,err[0],tmp); return 1;} /* check if file .cfg has length 0 */ if(fseek(fcfg,0,SEEK_END)){ fclose(fcfg); return 1;} if(!ftell(fcfg)){ fprintf(stderr,err[1],tmp); sprintf(xtmp,"rm -f %s",tmp); system(xtmp); return 1;} if(fseek(fcfg,0,SEEK_SET)) return 1; /* create de index file */ sprintf(tmp,"%s.ndx",extractfname(file)); fndx=fopen(tmp,"wb"); if(!fndx){ fclose(fcfg); return 1;} while(!feof(fcfg)){ xofs=ftell(fcfg); tmp[0]=0; fgets(tmp,256,fcfg); if((tmp[0]=='#') || (tmp[0]==0) || (tmp[0]=='\n')) continue; if(!strncmp(tmp,"Target[",7)) ofs=xofs; if(!strncmp(tmp,"Title[",6)){ ptmp=findnc(tmp,2,':'); trim(ptmp); fprintf(fndx,"%08ld %s\n",ofs,ptmp);} } fclose(fndx); fclose(fcfg); return 0; } void setPI(char* buf,unsigned long* pos,char** ifa){ sscanf(buf,"%08ld",pos); *ifa=buf+9; killnl(buf+9); } void gettarget(char* buf,char* target){ //word between [] int i; for(;buf[0]!='[';buf++); buf++; for(i=0;buf[0]!=']';buf++,i++) target[i]=buf[0]; target[i]=0; } char* findhost(char* buf){ int i; for(i=0;i

    %s %s


    \n",btxt[1],host); if(base[0]) fprintf(mkri[j][i],"
    \n",base,target,base,target,txt[i]); else fprintf(mkri[j][i],"
    \n",target,target,txt[i]); break;} } } convertname(host); /* change again the name, this time host var */ switch(conv){ case 1: //convip2name for(i=0;i<7;i++){ sprintf(tmp,"mv %s%s%s %s%s%s",mrtgoutpath,xtarget,xtxt[i],mrtgoutpath,host,xtxt[i]); system(tmp);} break; case 2: //convname2ip for(i=0;i<7;i++){ sprintf(tmp,"mv %s%s%s %s%s%s",mrtgoutpath,host,xtxt[i],mrtgoutpath,xtarget,xtxt[i]); system(tmp);} break; } } mrtg-2.17.10/contrib/mrtgmk/src/gif.c0000644000175300017510000000230613057016061016307 0ustar oetikeroep/* Iulian Radu [v2.0@07.1999] */ void fgif(char* buf,char* ext){ char link[129],host[129],*hosti,url[257]; if(!fh) return; sscanf(buf,"%s %s",link,host); if(strcmp(host,"#")){ //host!=# -> search for a host definition hosti=findhost(host); if(!hosti) return; if(strcmp(link,"#")){ if(base[0]) sprintf(url,"http://%s/%s",base,hosti); else strcpy(url,hosti); fprintf(fh,"",link); fprintf(fh,"",url,ext);} else{ if(base[0]) sprintf(url,"http://%s/%s",base,hosti); else strcpy(url,hosti); fprintf(fh,"",url); fprintf(fh,"",url,ext);} } else{ if(strcmp(link,"#")){ if(base[0]) sprintf(url,"http://%s/%s",base,link); else strcpy(url,link); fprintf(fh,"",url); fprintf(fh,"",url,ext);} else{ fprintf(stderr,"\aERROR: 0 GIF%c # #\n",toupper(ext[1])); return;} } fprintf(fh,"\n"); } void fgifd(char* buf){ fgif(buf,"-day.gif"); } void fgifw(char* buf){ fgif(buf,"-week.gif"); } void fgifm(char* buf){ fgif(buf,"-month.gif"); } void fgify(char* buf){ fgif(buf,"-year.gif"); } mrtg-2.17.10/contrib/mrtgmk/src/parsen.c0000644000175300017510000000203013057016061017024 0ustar oetikeroep/* Iulian Radu [v2.0@07.1999] */ int ident=0; #include "fnctn.c" #include "parsen.ftbl" int formathtml(){ /* put UL or /UL */ int i,j,k; if(ident<1){ return 1;} if(!fh) return 1; if(!identl){ fprintf(fh,"
      \n"); identl++;} if(ident\n");} } if(ident>identl){ i=ident-identl; k=identl; for(;i;i--,k++){ for(j=0;j\n");} } for(i=0;i\n");} fprintf(fh,"%s\n",buf); } void fmrtgtext(char* buf){ if(!fm) return; fprintf(fm,"#%s\n",buf); } void fbody(char* buf){ strcpy(body,buf); } void fnobody(char* buf){ body[0]=0; } void fbase(char* buf){ strcpy(base,buf); } void fnobase(char* buf){ base[0]=0; } void fexec(char* buf){ system(buf); } void fmsg(char* buf){ printf("%s\n",buf); } void ftitle(char* buf){ strcpy(title,buf); } void fmklink(char* buf){ char dir[257],host[65],path[257],*hosti,tmp1[257],tmp2[257],crtdir[257]; sscanf(buf,"%s %s %s",dir,host,path); hosti=findhost(host); if(!hosti){ fprintf(stderr,err[9],host); return;} mkdir(dir,S_IREAD | S_IWRITE | S_IEXEC); getcwd(crtdir,256); if(chdir(dir)){ fprintf(stderr,err[10],dir); return;} /* index.html */ sprintf(tmp1,"%s/%s.html",path,hosti); unlink("index.html"); symlink(tmp1,"index.html"); /* gifs */ sprintf(tmp1,"%s/%s-day.gif",path,hosti); sprintf(tmp2,"%s-day.gif",hosti); unlink(tmp2); symlink(tmp1,tmp2); sprintf(tmp1,"%s/%s-week.gif",path,hosti); sprintf(tmp2,"%s-week.gif",hosti); unlink(tmp2); symlink(tmp1,tmp2); sprintf(tmp1,"%s/%s-month.gif",path,hosti); sprintf(tmp2,"%s-month.gif",hosti); unlink(tmp2); symlink(tmp1,tmp2); sprintf(tmp1,"%s/%s-year.gif",path,hosti); sprintf(tmp2,"%s-year.gif",hosti); unlink(tmp2); symlink(tmp1,tmp2); /* mrtg imgs */ sprintf(tmp1,"%s/mrtg-l.gif",path); unlink("mrtg-l.gif"); symlink(tmp1,"mrtg-l.gif"); sprintf(tmp1,"%s/mrtg-m.gif",path); unlink("mrtg-m.gif"); symlink(tmp1,"mrtg-m.gif"); sprintf(tmp1,"%s/mrtg-r.gif",path); unlink("mrtg-r.gif"); symlink(tmp1,"mrtg-r.gif"); sprintf(tmp1,"%s/mrtg-tl.gif",path); unlink("mrtg-tl.gif"); symlink(tmp1,"mrtg-tl.gif"); chdir(crtdir); } void wrohtml(FILE* f,char* str,char* fcfg){ fprintf(f,"\n"); fprintf(f,"
      \n"); fprintf(f,"\n"); if(title[0]) fprintf(f,"%s - %s",title,str); else fprintf(f,"%s - %s",btxt[0],str); fprintf(f,"\n"); fprintf(f,"
      \n"); if(body[0]) fprintf(f,"\n",body); else fprintf(f,"\n"); fprintf(f,"

      %s %s %s

      \n",str,btxt[2],fcfg); } void wrchtml(FILE* f){ fprintf(f,"\n"); fprintf(f,"\n"); } void fmkd(char* buf){ char fcfg[257],fhtml[257]; FILE* f; int i; sscanf(buf,"%s %s",fcfg,fhtml); for(i=0;i\n");} sscanf(buf,"%s",link); if(base[0]) fprintf(fh,"",base,link); else fprintf(fh,"",link); fprintf(fh,"%s",findnsp(buf,1)); fprintf(fh,"\n"); } void flink2dh0(char* buf){ char host[129],*hosti; int i; if(!fh) return; for(;identl;identl--){ for(i=1;i\n");} sscanf(buf,"%s",host); hosti=findhost(host); if(!hosti){ fprintf(stderr,err[9],host); return;} if(base[0]) fprintf(fh,"",base,hosti); else fprintf(fh,"",hosti); fprintf(fh,"%s",findnsp(buf,1)); fprintf(fh,"\n"); } void fchngtrgname(char* buf){ if(!strcasecmp(buf,"yes")){ chngname=1; return;} if(!strcasecmp(buf,"no")){ chngname=0; return;} fprintf(stderr,err[12],buf); } void fconvip2name(char* buf){ conv=1; sscanf(buf,"%s",mrtgoutpath); } void fconvname2ip(char* buf){ conv=2; sscanf(buf,"%s",mrtgoutpath); } mrtg-2.17.10/contrib/mrtgmk/src/parse.c0000644000175300017510000000143313057016061016654 0ustar oetikeroep/* Iulian Radu [v2.0@07.1999] */ #include "vars.h" void parsex(char* fcfg); void parse(char* fcfg); #include "util.c" #include "parse.ftbl" #include "parse0.c" #include "parsen.c" void parsex(char* fcfg){ char buf[513]; FILE* f; f=fopen(fcfg,"rt"); if(!f) return; while(!feof(f)){ buf[0]=0; //look stupid BUT it is not fgets(buf,512,f); if(xdebug) printf("EXTREM DEBUG: %s\n",buf); trim(buf); if(!buf[0] || (buf[0]=='#')) continue; if(buf[0]=='0') parse0(buf+2); else if(isdigit(buf[0])) if(!comment) parsen(buf); } fclose(f); } void parse(char* fcfg){ int i,j; parsex(fcfg); closehtml(); if(fm) fclose(fm); /* close mk? */ for(i=0;i<4;i++) for(j=0;j%s\n",buf); } void fhtmllinkn(char* buf){ char link[129]; int i; for(i=1;i",base,link); else fprintf(fh,"

    • ",link); fprintf(fh,"%s",findnsp(buf,1)); fprintf(fh,"
    • \n"); } void fdata(char* buf){ char host[129],*text,*hosti,url[257]; sscanf(buf,"%s",host); hosti=findhost(host); if(!hosti) return; text=findnsp(buf,1); if(base[0]) sprintf(url,"http://%s/%s",base,hosti); else strcpy(url,hosti); fprintf(fh,"
    • ",url); fprintf(fh,"%s",text); fprintf(fh,"
    • \n"); } void flink2dhn(char* buf){ char host[129],*hosti; int i; for(i=1;i",base,hosti); else fprintf(fh,"
    • ",hosti); fprintf(fh,"%s",findnsp(buf,1)); fprintf(fh,"
    • \n"); } mrtg-2.17.10/contrib/mrtgmk/src/txte.h0000644000175300017510000000156113057016061016535 0ustar oetikeroep#ifndef _TXT_H_ #define _TXT_H_ char* etxt[]={ "by", "needed", "optionally", "configuration file" }; char* btxt[]={ "Traffic analyses", "Traffic analysis for", ".gifs for hosts in the .cfg file" }; char* err[]={ "\aERROR: openning file %s\n", "\aERROR: index file %s has length 0 and I erase it\n", "\aERROR: was not defined a mrtg.cfg file\n", "\aERROR: port %s missing from %s/%s\n", "\aERROR: port %s missing from %s\n", "\aERROR: configuration file %s is missing\n", "\aERROR: host %s redefined\n", "\aERROR: alias %s redefined\n", "\aERROR: alias %s not precedently defined\n", "\aERROR: host %s not precedently defined\n", "\aERROR: I can't switch in directory %s\n", //10 "\aERROR: argument for CHECK4ALIAS was %s", "\aERROR: argument for CHNGTRGNAME was %s" }; #endif mrtg-2.17.10/contrib/mrtgmk/src/util.c0000644000175300017510000000162613057016061016523 0ustar oetikeroep/* Iulian Radu [v2.0@07.1999] */ char* extractfname(char* fname){ char* cptmp; cptmp=fname+strlen(fname)-1; while((cptmp>=fname) && (cptmp[0]!='/')) cptmp--; return cptmp+1; } void ltrim(char* buf){ char* tmp; for(tmp=buf;tmp[0] && isspace(tmp[0]);tmp++); strcpy(buf,tmp); } void rtrim(char* buf){ char* tmp; for(tmp=buf-1;buf[0];buf++) if(!isspace(buf[0])) tmp=buf; tmp[1]=0; } void trim(char*buf){ ltrim(buf); rtrim(buf); } char* findnsp(char* str,int n){ /*unde incepe cuvintul de dupa al n-lea spatiu*/ while(str[0] && n) if(isspace(str[0])){ n--; for(;str[0] && isspace(str[0]);str++); } else str++; return str; } char* findnc(char* str,int n,char ch){ /*gaseste al n-lea ch*/ for(;str[0] && n;str++) if(str[0]==ch) n--; return str; } void killnl(char* buf){ for(;buf[0];buf++){ if(buf[0]=='\n'){ buf[0]=0; return;} if(buf[0]=='\r'){ buf[0]=0; return;} } } mrtg-2.17.10/contrib/mrtgmk/src/parse.ftbl0000644000175300017510000000017613057016061017364 0ustar oetikeroep/* Iulian Radu [v2.0@07.1999] */ typedef void (*fnct)(char* buf); struct fncttbl{ char* cmd; fnct func; }; mrtg-2.17.10/contrib/mrtgmk/src/html.c0000644000175300017510000000110113057016061016476 0ustar oetikeroep/* Iulian Radu [v2.0@07.1999] */ void mkhtmlh(){ /*use fh global*/ if(!fh) return; fprintf(fh,"\n"); fprintf(fh,"
      \n"); fprintf(fh,"\n"); if(title[0]) fprintf(fh,title); else fprintf(fh,btxt[0]); fprintf(fh,"\n"); fprintf(fh,"
      \n"); if(body[0]) fprintf(fh,"\n",body); else fprintf(fh,"\n"); } void closehtml(){ /*use fh global*/ int i; if(!fh) return; for(;identl;identl--){ for(i=1;i\n");} fprintf(fh,"\n"); fprintf(fh,"\n"); fclose(fh); fh=NULL; } mrtg-2.17.10/contrib/mrtgmk/src/alias.c0000644000175300017510000000250513057016061016634 0ustar oetikeroep/* Iulian Radu [v2.0@07.1999] */ int apos=-1; //memorize position of a free cell char* findalias(char* buf){ int i; apos=-1; for(i=0;i #include #include #include #include #include #include "txte.h" //for english messages //#include "txtro.h" //pentru mesaje in romaneste #include "parse.c" void intro(char* aname){ printf("\n%s (mrtgmk) %s Iulian Radu [v2.2@1.2000]\n\n",extractfname(aname),etxt[0]); } void help(char* aname){ printf("%s \n",aname); printf(" = %s\n",etxt[3]); printf(" <> = %s\n",etxt[1]); printf(" [] = %s\n",etxt[2]); printf("\n"); exit(1); } int main(int argc,char** argv){ intro(argv[0]); if(argc!=2) help(argv[0]); parse(argv[1]); return 0; } mrtg-2.17.10/contrib/mrtgmk/src/mkm0000755000175300017510000000003513057016061016105 0ustar oetikeroepgcc -o mrtgmk mrtgmk.c -Wall mrtg-2.17.10/contrib/14all/0000755000175300017510000000000013057016061014222 5ustar oetikeroepmrtg-2.17.10/contrib/14all/README0000644000175300017510000000027613057016061015107 0ustar oetikeroepBecause Rainer is very active in fixing bugs and enhancing 14all.cgi. Please go to his website to fetch the latest version of his cool tool: http://my14all.sourceforge.net/ cheers tobi mrtg-2.17.10/contrib/rdlog2/0000755000175300017510000000000013057016061014476 5ustar oetikeroepmrtg-2.17.10/contrib/rdlog2/readme.html0000755000175300017510000001377213057016061016636 0ustar oetikeroep RDLOG tool for MRTG

      RDLOG2 tool for MRTG

      Introduction

      Rdlog is a small (and primitive) tool that gives indication on network traffic on a graphic map. It takes information from MRTG log files, and draw a GIF file with links that have colors based on the current traffic on your network. This small test explain how to use this tool :

      History list

      v 1.1, 5.5.97 :

      v1.0, feb. 1997: initial revision, port from rdlog

      RDLOG2 configuration file

      To build a gif, RDLOG2 needs a configuration file, that you must build with XGIF (ftp.x.org, in /contrib/applications/drawing_tools/xfig), a 'X draw' program (tested with version 3.1). You can look at the example (wan.fig) in order to understand how works RDLOG2. When you draw with XFIG, you must observe some rules :

      General Rules

      You can draw : text, polylines, rectangles. Don't try to make rounded corners, arrows, splines, play with line style and width ... All your draw must be 'flat', except for special object. Don't group/ungroup all your objects. The order of object drawing is defined with the xfig 'DEPTH' parameter (biggest first). Here follow a description of all you must know to build a RDLOG2 FIG file :

      Draw text

      RDLOG use the 'gd' package to build GIF files. You can only use one font, one size, and 2 orientations (0, 90). Use the font 'courier 10' to have the better matching between XFIG and the gif output.

      Draw rectangles

      The rectangle are the only figure that you can fill with colors. You can specify a border and a fill color.

      Draw polylines

      The polylines has only a color attribute.

      Rate colors definition

      For each link defined in the FIG file, the color is computed based on the traffic. There are 10 different color, (0-10 %, 10-20%, ...). And they are define with a special text string, that contains 'color:x' (x is 0 for 0-10%, 1 for 10-20%, ...). The text color define the link color for the corresponding rate.

      Draw 'links'

      A link is a polyline whose color change, depending on traffic present on this link (in the mrtg log file). To build a link, you must group the following elements :

      • a polyline the represent the link, with a default color,
      • a text string that define the maximum speed for this link, with the following form 'speed:ssssssss'
      • a text string with the mrtg log file name, of style 'log:link33.log' (maximum input or output), or of style 'log:>link33.log' (maximum output) or 'log:<link33.log' (maximum input)

      The link must only contains this 3 objects.

      Define GIF area

      The GIF area is define with 2 elements, that must be grouped :

      • a rectangle that define the GIF region. The color of the rectangle define the background color of the GIF file.
      • a text string, containing 'gifarea'

      Define clickable region

      With the '-m' command line option, RDLOG2 build a html file, that contains the GIF file, and where you can click to reach the corresponding mrtg files. You must define the clickable region, by creating a group with the following elements :

      • a rectangle that define the clickable region
      • a text string, containing 'url:linkname.html'

      Building RDLOG

      RDLOG use the gd library. In order to built it, you must have the following files :

      • RDLOG2.C

      and from the gd library,

      • GDFONTS.H
      • GDFONTS.C
      • MTABLES.C
      • GD.H
      • GD.C

      To build it, on unix , you can type :

      gcc rdlog2.c -I/yourgdinclude -L/yourgdlibrary -lgd -lm -o RDLOG2

      On a PC with NT or 95, make a project with RDLOG2.C, GD.C, GDFONTS.C

      Calling RDLOG

      The command-line parameters are :

      rdlog2 -i cfile -o gfile [-m htmlfile] -r rounds

      • ifile : input config file name
      • gfile : output gif file (will be overwritten)
      • mfile : html file with clickable map (optional, will be overwritten)
      • rounds : number of 5 min intervals to take

      for example : rdlog2 -i wan.fig -o wan.gif -m wan.html -r 12 > wan1.txt

      You can so make an average of the x last 5 minutes intervals. Here, the map is drawn for the last hour.

      5.5.97, Philippe Simonet, philippe.simonet@swisstelecom.com

      mrtg-2.17.10/contrib/rdlog2/wan.fig0000755000175300017510000001252313057016061015760 0ustar oetikeroep#FIG 3.1 Landscape Center Inches 1200 2 0 32 #c2c9dc 0 33 #aee9c3 0 34 #7cd0a6 0 35 #29a889 0 36 #17855c 0 37 #ffc8c8 0 38 #ffaaaa 0 39 #ff8c8c 0 40 #ff6464 0 41 #ff0000 0 42 #f5f5f5 6 3000 2700 4725 3750 2 2 0 1 0 34 0 0 -1 0.000 0 0 -1 0 0 5 3000 2700 3300 2700 3300 3750 3000 3750 3000 2700 4 0 0 0 0 12 10 0.0000 4 105 1260 3405 3330 url:lk003.html\001 -6 6 4425 600 6975 900 2 2 0 1 0 34 0 0 -1 0.000 0 0 -1 0 0 5 4425 600 5475 600 5475 900 4425 900 4425 600 4 0 0 0 0 12 10 0.0000 4 105 1260 5655 780 url:lk002.html\001 -6 6 7800 2550 9675 3750 2 2 0 1 0 34 0 0 -1 0.000 0 0 -1 0 0 5 7800 2550 8175 2550 8175 3750 7800 3750 7800 2550 4 0 0 0 0 12 10 0.0000 4 105 1260 8355 3180 url:lk001.html\001 -6 6 4425 5175 5775 6300 2 2 0 1 0 34 0 0 -1 0.000 0 0 -1 0 0 5 4500 6000 5700 6000 5700 6300 4500 6300 4500 6000 4 0 0 0 0 12 10 0.0000 4 105 1260 4455 5280 url:lk004.html\001 -6 6 3300 2400 4575 4200 2 1 0 1 0 34 0 0 -1 0.000 0 0 -1 0 0 2 3300 2400 3300 4200 4 0 0 0 0 12 10 0.0000 4 135 1080 3375 2925 speed:262144\001 4 0 0 0 0 12 10 0.0000 4 135 1170 3375 3150 log:lk003.log\001 -6 6 8100 1800 9525 4800 2 1 0 1 0 34 0 0 -1 0.000 0 0 -1 0 0 2 8100 1800 8100 4800 4 0 0 0 0 12 10 0.0000 4 135 1170 8325 2700 log:lk001.log\001 4 0 0 0 0 12 10 0.0000 4 135 1080 8325 2925 speed:262144\001 -6 6 2400 300 10800 7200 2 2 0 1 42 11 5 0 20 0.000 0 0 7 0 0 5 2400 300 10800 300 10800 7200 2400 7200 2400 300 4 0 0 0 0 12 10 0.0000 4 135 630 2580 6985 gifarea\001 -6 6 3675 4125 6525 6450 2 1 0 1 0 34 2 0 -1 0.000 0 0 -1 0 0 16 5098 4198 5536 4198 5973 4417 6411 4855 6521 5293 6411 5731 6083 6168 5536 6387 4660 6387 4222 6168 3784 5731 3675 5293 3784 4855 4222 4417 4660 4198 5098 4198 4 0 0 0 0 12 10 0.0000 4 135 1260 4500 4875 speed:12500000\001 4 0 0 0 0 12 10 0.0000 4 135 1170 4500 5100 log:lk004.log\001 -6 6 3000 975 7200 1800 2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 7 7200 1800 7200 975 3150 975 3150 1800 3000 1575 3150 1800 3300 1575 4 0 0 0 0 12 10 0.0000 4 135 1080 3750 1275 speed:262144\001 4 0 0 0 0 12 10 0.0000 4 135 1260 3675 1500 log:>lk002.log\001 -6 6 3525 1125 6825 1800 2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 7 3525 1800 3525 1125 6675 1125 6675 1800 6825 1575 6675 1800 6525 1575 4 0 0 0 0 12 10 0.0000 4 135 1080 5325 1275 speed:262144\001 4 0 0 0 0 12 10 0.0000 4 135 1260 5325 1425 log: #include #include #include #include #include "gd.h" #include "gdfonts.h" #define FALSE 0 #define TRUE 1 #define TEXT 1 #define RECT 2 #define POLY 3 #define COLOR 4 #define COLORDEF 5 #define LINK 6 #define COMPOUND 7 #define ENDCOMPOUND 8 #define GIFAREA 9 #define URL 10 #define IN 11 #define OUT 12 #define INOUT 13 #define UNKNOWN 99 #ifndef max #define max(a,b) ((a)>(b))?(a):(b) #endif #ifndef min #define min(a,b) ((a)<(b))?(a):(b) #endif int colorratetable[256]; int colortable[256] = { 0x000000, /* 0 BLACK */ 0xff0000, /* 1 BLUE */ 0x00ff00, /* 2 GREEN*/ 0xffff00, /* 3 CYAN */ 0x0000ff, /* 4 RED */ 0xff00ff, /* 5 MAGENTA */ 0x00ffff, /* 6 YELLOW */ 0xffffff, /* 7 WHITE */ 0x900000, /* 8 Blue4 */ 0xb00000, /* 9 Blue3 */ 0xd00000, /* 10 Blue2 */ 0xffce87, /* 11 LtBlue */ 0x009000, /* 12 Green4 */ 0x00b000, /* 13 Green3 */ 0x00d000, /* 14 Green2 */ 0x909000, /* 15 Cyan4 */ 0xb0b000, /* 16 Cyan3 */ 0xd0d000, /* 17 Cyan2 */ 0x000090, /* 18 Red4 */ 0x0000b0, /* 19 Red3 */ 0x0000d0, /* 20 Red2 */ 0x900090, /* 21 Magenta4 */ 0xb000b0, /* 22 Magenta3 */ 0xd000d0, /* 23 Magenta2 */ 0x003080, /* 24 Brown4 */ 0x0040a0, /* 25 Brown3 */ 0x0060c0, /* 26 Brown2 */ 0x8080ff, /* 27 Pink4 */ 0xa0a0ff, /* 28 Pink3 */ 0xc0c0ff, /* 29 Pink2 */ 0xe0e0ff, /* 30 Pink */ 0x00d7ff /* 31 gold */ }; /************************************************************************/ /* each of these entry contain the description of a graphical object */ struct sentry { int type; /* text, line, link, poly */ int depth; /* order in which it appears */ char * str; /* log file name, url, text */ int maxrate; /* max xfer rate */ int rate; /* max xfer rate */ int orientation; /* text orientation, ... */ int color; /* color */ int fillcolor; /* color */ int colorindex; /* color index */ int npoints; /* fig size */ int * coords; /* coordinates list */ struct sentry * next; /* next entry */ }; int xsize, ysize, rounds, xoffset, yoffset; struct sentry * pfirstentry, *pcurrententry, *pareaentry; /************************************************************************/ /* analyze command-line options */ static int optind = 0; /* Global argv index. */ static char *scan = NULL; /* Private scan pointer. */ static int scale = 15; int getopt1( int argc, char *argv[], char *optstring, char ** optarg ) { int c; /* return value */ char *place; char *index(); *optarg = NULL; /* check argument validity */ if (scan == NULL || *scan == '\0') { if (optind == 0) optind++; if (optind >= argc) return EOF; place = argv[optind]; if (place[0] != '-' || place[1] == '\0') return EOF; optind++; if (place[1] == '-' && place[2] == '\0') return EOF; scan = place+1; } c = *scan++; /* get option character */ place = strchr(optstring, c); if (place == NULL || c == ':') return '?'; /* set optarg if needed */ if (*++place == ':') { if (*scan != '\0') { *optarg = scan; scan = NULL; } else { *optarg = argv[optind], optind++; } } return c; } /************************************************************************/ /* computes a traffic in % by reading 'rounds' lines in a MRTG log file */ /* currently, it takes the maximum of the In or OUT traffic. */ void read_entry ( struct sentry * pentry) { FILE * logf; int i, j=0, k=0; logf = fopen ( pentry->str, "r" ); if ( pentry->maxrate == 0 ) { fprintf ( stderr, "Max rate for %s is null.\n", pentry->str ); return; } if ( logf != NULL ) { fscanf(logf, "%*d %d %d", &j, &k); /* get first line */ for ( i = 0; i < rounds; i ++ ) { /* computes mean */ fscanf(logf, "%*d %d %d %*d %*d", &j, &k); /* get line */ /*printf(" - [%d %d]\n", j, k);*/ switch (pentry->orientation) { case IN: pentry->rate += j; break; case OUT: pentry->rate += k; break; default: if ( j > k ) pentry->rate += j; else pentry->rate += k; break; } } /* computes the rate 0-9 */ pentry->rate = pentry->rate / rounds; /*printf ( "%s : %u, %u.\n", pentry->str, (pentry->maxrate*100)/pentry->maxrate, (pentry->rate*10)/pentry->maxrate );*/ pentry->rate = (pentry->rate * 10) / pentry->maxrate; if ( pentry->rate > 9 ) pentry->rate = 9; if ( pentry->rate < 0 ) pentry->rate = 0; fclose ( logf ); } else { fprintf ( stderr, "Cannot open file %s.\n", pentry->str ); }; } /************************************************************************/ /* in case of trouble ... */ void print_error ( void ) { fprintf ( stderr, "Read mrtg configuration files and convert them in gif format.\n" ); fprintf ( stderr, "Use :\n" ); fprintf ( stderr, " rdlog -i cfile -o gfile [-m mapfile] -r rounds\n" ); fprintf ( stderr, " ifile : input fig file name,\n" ); fprintf ( stderr, " gfile : output gif file (will be overwritten),\n" ); fprintf ( stderr, " mapfile : output map file (optional, will be overwritten),\n" ); fprintf ( stderr, " rounds : number of 5 min intervals to take.\n" ); } /************************************************************************/ /* free an 'entry' variable */ void free_entry (struct sentry * pentry) { if ( pentry!= NULL ) { if ( pentry->str != NULL ) free(pentry->str); pentry->str = NULL; if ( pentry->coords != NULL ) free(pentry->coords); pentry->coords = NULL; free(pentry); } } /************************************************************************/ /* print an entry for debug purpose */ void print_entry (struct sentry * pentry) { printf ( "Entry : " ); if ( pentry->str != NULL ) printf ( "str '%s' ", pentry->str ); printf ( ".\n type %i, maxrate %i, orientation %i, npoints %i, color %i, depth %i.\n", pentry->type,pentry->maxrate,pentry->orientation,pentry->npoints,pentry->color,pentry->depth ); } /************************************************************************/ int new_entry( void ) { struct sentry * pentry; if ( ( pentry = malloc ( sizeof (struct sentry) )) == NULL ) { fprintf ( stderr, "Error : memory allocation failure.\n" ); return ( FALSE ); } if ( pfirstentry == NULL ) { pfirstentry = pentry; } else { pcurrententry->next = pentry; } pentry->type = UNKNOWN; pentry->str = NULL; pentry->maxrate = 0; pentry->rate = 0; pentry->orientation = 0; pentry->color = 0; pentry->fillcolor = 0; pentry->depth = 0; pentry->colorindex = 0; pentry->npoints = 0; pentry->coords = NULL; pentry->next = NULL; pcurrententry = pentry; return ( TRUE ); } /************************************************************************/ #define r(color) ((color&0x0000ff)>>0) #define g(color) ((color&0x00ff00)>>8) #define b(color) ((color&0xff0000)>>16) #define rgb(color) ((color&0x0000ff)>>0),((color&0x00ff00)>>8),((color&0xff0000)>>16) /************************************************************************/ /* build a color or find the nearest color in the color table */ int find_color ( gdImagePtr graph, int color ) { int i_col; if ( (i_col = gdImageColorExact(graph,r(color), g(color), b(color))) == -1 ) { if ( (i_col = gdImageColorAllocate(graph,r(color), g(color), b(color))) == -1 ) { i_col = gdImageColorClosest(graph,r(color), g(color), b(color)); } } return (i_col); } /************************************************************************/ /* draw the gif file, based on the tentry desciption */ void draw_gif ( FILE * gif ) { #define c_blank 245,245,245 /* base colors */ #define c_light 194,194,194 #define c_dark 100,100,100 #define c_black 0,0,0 #define c_white 255,255,0 gdImagePtr graph; int i_light,i_dark,i_blank, i_black, i_white; int bkcolor; graph = gdImageCreate(xsize, ysize); /* the first color allocated will be the background color. */ bkcolor = colortable[pareaentry->fillcolor]; i_blank = gdImageColorAllocate(graph,rgb(bkcolor)); i_light = gdImageColorAllocate(graph,c_light); i_dark = gdImageColorAllocate(graph,c_dark); gdImageInterlace(graph, 1); i_black = gdImageColorAllocate(graph,c_black); i_white = gdImageColorAllocate(graph,c_white); /* draw the image border */ gdImageLine(graph,0,0,xsize-1,0,i_light); gdImageLine(graph,1,1,xsize-2,1,i_light); gdImageLine(graph,0,0,0,ysize-1,i_light); gdImageLine(graph,1,1,1,ysize-2,i_light); gdImageLine(graph,xsize-1,0,xsize-1,ysize-1,i_dark); gdImageLine(graph,0,ysize-1,xsize-1,ysize-1,i_dark); gdImageLine(graph,xsize-2,1,xsize-2,ysize-2,i_dark); gdImageLine(graph,1,ysize-2,xsize-2,ysize-2,i_dark); { /* date the graph */ struct tm *newtime; time_t aclock; time( &aclock ); /* Get time in seconds */ newtime = localtime( &aclock ); /* Convert time to struct */ /* tm form */ gdImageString(graph, gdFontSmall,3,3,asctime( newtime ),i_dark); }; while ( 1 ) { int i_col, i_col2, depth; struct sentry * pentry; /* find smallest depth */ pentry = pfirstentry; depth = -1; while ( pentry != NULL ) { if (pentry->depth > depth) { depth = pentry->depth; pcurrententry = pentry; } pentry = pentry->next; } if ( depth == -1 ) break; pcurrententry->depth = -1; /* draw this fig */ switch ( pcurrententry->type) { case RECT: i_col = find_color(graph, colortable[pcurrententry->color]); if ( pcurrententry->fillcolor != -1 ) { i_col2 = find_color(graph, colortable[pcurrententry->fillcolor]); gdImageFilledRectangle(graph, pcurrententry->coords[0], pcurrententry->coords[1], pcurrententry->coords[2], pcurrententry->coords[3],i_col2); } gdImageRectangle(graph, pcurrententry->coords[0], pcurrententry->coords[1], pcurrententry->coords[2], pcurrententry->coords[3],i_col); break; case TEXT: i_col = find_color(graph, colortable[pcurrententry->color]); if (pcurrententry->orientation == 0) { gdImageString(graph, gdFontSmall, pcurrententry->coords[0], pcurrententry->coords[1], pcurrententry->str, i_col ); } else { gdImageStringUp(graph, gdFontSmall, pcurrententry->coords[0], pcurrententry->coords[1], pcurrententry->str, i_col ); } break; case POLY: case LINK: { int x = pcurrententry->coords[0]; int y = pcurrententry->coords[1]; int x2, y2, j, k; gdImagePtr brush_2pix; if (pcurrententry->type == POLY) { i_col = find_color(graph, colortable[pcurrententry->color]); } else { brush_2pix = gdImageCreate(2,2); gdImageColorAllocate( brush_2pix, r(colortable[colorratetable[pcurrententry->rate]]), g(colortable[colorratetable[pcurrententry->rate]]), b(colortable[colorratetable[pcurrententry->rate]]) ); gdImageSetBrush(graph, brush_2pix); i_col = gdBrushed; } k = 2; for ( j = 1; j < pcurrententry->npoints; j ++ ) { x2 = pcurrententry->coords[k++]; y2 = pcurrententry->coords[k++]; gdImageLine(graph, x, y, x2, y2,i_col); x = x2; y = y2; }; if (pcurrententry->type == LINK) { gdImageDestroy(brush_2pix); }; } break; default: break; } pcurrententry = pcurrententry->next; } gdImageGif(graph, gif); gdImageDestroy(graph); } struct sfigrec { int type; char text[500]; int colorindex; int depth; int color; int fillcolor; int angle; int coords[500]; int npoints; }; /************************************************************************/ int getfig ( FILE * config, struct sfigrec * fig ) { char buf[1000], str[1000], *s; int i, n, type, color, colorindex, depth, pen_style, font, flags, x, y; int style, thickness, pen_color, fill_color, fill_style, join_style, cap_style, radius, fa, ba, npts; float tx_size, angle, style_val; fig->type = UNKNOWN; if ( fgets (buf, 1000, config ) == NULL ) { return ( TRUE ); } switch ( buf[0] ) { case '0': /* color ref */ n = sscanf(buf, "%*d %d #%06x", &colorindex, &color ); /*printf ( "colordef : %d, %d.\n", colorindex, color );*/ fig->type = COLORDEF; fig->color = ((color & 0xff0000)>>16) | (color & 0x00ff00) | ((color & 0x0000ff)<<16); fig->colorindex = colorindex; break; case '2': /* polyline */ n = sscanf(buf, "%*d%d%d%d%d%d%d%d%d%f%d%d%d%d%d%d", &type, &style, &thickness, &pen_color, &fill_color, &depth, &pen_style, &fill_style, &style_val, &join_style, &cap_style, &radius, &fa, &ba, &npts); /*puts ( buf );*/ /*printf ("type %d, style %d, thickness %d, pen_color %d, fill_color %d, depth %d, pen_style %d, fill_style %d, style_val %f, join_style %d, cap_style %d, radius %d, fa %d, ba %d, npts %d ", type, style, thickness, pen_color, fill_color, depth, pen_style, fill_style, style_val, join_style, cap_style, radius, fa, ba, npts);*/ fig->depth = depth; fig->color = pen_color; fig->npoints = npts; for ( i = 0; i < npts; i ++ ) { fscanf(config, "%d%d", &x, &y); fig->coords[i*2] = x; fig->coords[i*2+1] = y; /*printf ( "[%d %d] ", x, y );*/ } fig->type = POLY; if ( type == 2 ) { /* rectangle */ fig->type = RECT; if ( fill_style == -1 ) { fig->fillcolor = -1; } else { fig->fillcolor = fill_color; } x = min(fig->coords[0],fig->coords[4]); y = min(fig->coords[1],fig->coords[5]); fig->coords[2] = max(fig->coords[0],fig->coords[4]); fig->coords[3] = max(fig->coords[1],fig->coords[5]); fig->coords[0] = x; fig->coords[1] = y; fig->npoints = 2; } /*printf ( ".\n" );*/ break; case '4': /* text */ n = sscanf(buf, "%*d%d%d%d%d%d%f%f%d%*f%*f%d%d %[^\n]", &type, &color, &depth, &pen_style, &font, &tx_size, &angle, &flags, &x, &y, str); s = strstr ( str, "\\001" ); if ( s != NULL ) s[0] = 0; /*printf ( "text : type %d, color %d, depth %d, pen_style %d, font %d, ty_size %f, angle %f, flags %d, x %d, y %d, s [%s].\n", type, color, depth, pen_style, font, tx_size, angle, flags, x, y, str );*/ fig->type = TEXT; strcpy (fig->text, str); fig->depth = depth; fig->color = color; if ( angle < 1) { fig->angle = 0; fig->coords[0] = x; fig->coords[1] = y-150; } else { fig->angle = 1; fig->coords[0] = x-150; fig->coords[1] = y; } fig->npoints = 1; break; case '6': /* compound */ fig->type = COMPOUND; /*printf ( "compound.\n" );*/ break; case '-': /* compound end */ fig->type = ENDCOMPOUND; /*printf ( "end of compound.\n" );*/ break; default: break; } return ( FALSE ); } /************************************************************************/ void main ( int argc, char * argv[] ) { FILE *config = NULL, *gif = NULL, *map = NULL; char *sconfig = NULL, *sgif = NULL, *smap = NULL; char *optarg; int i; /* globals */ xsize = 100, ysize = 100; rounds = 6; do { /***************************************************************/ /* 0 : read program arguments */ while ( ( i = getopt1( argc, argv, "o:i:r:m:", &optarg ) ) != EOF ) { switch ( i ) { case 'i': sconfig = optarg; break; case 'o': sgif = optarg; break; case 'm': smap = optarg; break; case 'r': rounds = atoi (optarg); if ( rounds < 1 ) { print_error(); exit (0); }; break; case '?': print_error(); exit (0); break; default: break; } } if ( sconfig == NULL || sgif == NULL ) { print_error(); break; } /***************************************************************/ /* 1 : OPEN FILES */ config = fopen ( sconfig, "r" ); if ( config == NULL ) { fprintf ( stderr, "Error opening %s.\n", sconfig ); break; } gif = fopen ( sgif, "wb" ); if ( gif == NULL ) { fprintf ( stderr, "Error opening %s.\n", sgif ); fclose ( config ); break; } if ( smap != NULL ) { map = fopen ( smap, "w" ); if ( map == NULL ) { fprintf ( stderr, "Error opening %s.\n", sgif ); fclose ( config ); fclose ( gif ); break; } fprintf ( map, " \n" ); } /***************************************************************/ /* 2 : SCAN CONFIG FILE */ pcurrententry = NULL; pfirstentry = NULL; pareaentry = NULL; for ( i = 0; i < 256; i++ ) { colorratetable[i] = 0; } for ( i = 32; i < 256; i++ ) { colortable[i] = 0; } while ( TRUE ) { struct sfigrec figrec; /********************************************/ /* get one fig record */ if ( getfig ( config, &figrec ) == TRUE ) break; switch (figrec.type) { case COLORDEF: if ( figrec.colorindex < 256 ) colortable[figrec.colorindex] = figrec.color; /*printf ( "color table[%i] : %i.\n", figrec.colorindex, colortable[figrec.colorindex] );*/ break; case TEXT: if ( new_entry() == FALSE ) break; pcurrententry->type = UNKNOWN; pcurrententry->color = figrec.color; pcurrententry->depth = figrec.depth; if ( strncmp("color:", figrec.text, 6 ) == 0 ) { /* special 'color:' text */ i = atoi ( figrec.text+6 ); if ( i < 256 ) colorratetable[i] = figrec.color; /*printf ( "color rate[%i] : %i.\n", i, colorratetable[i] );*/ break; } if ( (pcurrententry->str = malloc ( strlen(figrec.text) + 1 )) == NULL ) { fprintf ( stderr, "Error : memory allocation failure.\n" ); break; } if ( (pcurrententry->coords = (int *)malloc(figrec.npoints * (sizeof (int)) * 2 )) == NULL ) { fprintf ( stderr, "Error : memory allocation failure.\n" ); break; } pcurrententry->type = TEXT; pcurrententry->npoints = figrec.npoints; pcurrententry->orientation = figrec.angle; strcpy (pcurrententry->str,figrec.text); memcpy (pcurrententry->coords,figrec.coords,figrec.npoints * (sizeof (int)) * 2); break; case POLY: case RECT: if ( new_entry() == FALSE ) break; pcurrententry->type = UNKNOWN; pcurrententry->depth = figrec.depth; pcurrententry->color = figrec.color; pcurrententry->fillcolor = figrec.fillcolor; if ( (pcurrententry->coords = (int *)malloc(figrec.npoints * (sizeof (int)) * 2 )) == NULL ) { fprintf ( stderr, "Error : memory allocation failure.\n" ); continue; } pcurrententry->type = figrec.type; pcurrententry->npoints = figrec.npoints; memcpy (pcurrententry->coords,figrec.coords,figrec.npoints * (sizeof (int)) * 2); break; case COMPOUND: /* compound must be links ... */ if ( new_entry() == FALSE ) break; do { if ( getfig ( config, &figrec ) == TRUE ) break; if ( figrec.type == ENDCOMPOUND ) break; if ( figrec.type == TEXT ) { /*printf (" txt %s.\n", figrec.text );*/ if ( strncmp("gifarea", figrec.text, 7 ) == 0 ) { pcurrententry->type = GIFAREA; pareaentry = pcurrententry; /*printf ( " gifarea : [%i / %i] ", pcurrententry->coords[0], pcurrententry->coords[1]); printf ( " [%i / %i].\n", pcurrententry->coords[2], pcurrententry->coords[3]);*/ } else if ( strncmp("url:", figrec.text, 4 ) == 0 ) { if ( (pcurrententry->str = malloc ( strlen(figrec.text) + 1 )) == NULL ) { fprintf ( stderr, "Error : memory allocation failure.\n" ); break; } pcurrententry->type = URL; strcpy (pcurrententry->str,figrec.text+4); /*printf (" url %s.\n", pcurrententry->str );*/ } else if ( strncmp("log:", figrec.text, 4 ) == 0 ) { char * s = figrec.text + 4; if ( s[0] == '>' ) { pcurrententry->orientation = OUT; s++; } else if ( s[0] == '<' ) { pcurrententry->orientation = IN; s++; } else { pcurrententry->orientation = INOUT; } if ( (pcurrententry->str = malloc ( strlen(s) + 1 )) == NULL ) { fprintf ( stderr, "Error : memory allocation failure.\n" ); break; } pcurrententry->type = LINK; strcpy (pcurrententry->str,s); /*printf (" str %s.\n", pcurrententry->str );*/ } else if ( strncmp("speed:", figrec.text, 6 ) == 0 ) { pcurrententry->maxrate = atoi ( figrec.text+6 ); /*printf (" max rate : %i.\n", pcurrententry->maxrate );*/ } } if ( (figrec.type == POLY) || (figrec.type == RECT) ) { pcurrententry->color = figrec.color; /* default color */ pcurrententry->depth = figrec.depth; pcurrententry->fillcolor = figrec.fillcolor; if ( (pcurrententry->coords = (int *)malloc(figrec.npoints * (sizeof (int)) * 2 )) == NULL ) { fprintf ( stderr, "Error : memory allocation failure.\n" ); break; } pcurrententry->npoints = figrec.npoints; memcpy (pcurrententry->coords,figrec.coords,figrec.npoints * (sizeof (int)) * 2); } } while ( 1 ); if ( pcurrententry->type==LINK && pcurrententry->coords != NULL ) { read_entry ( pcurrententry ); /*printf (" link : log : %s.log, max rate : %i.\n", pcurrententry->str, pcurrententry->maxrate );*/ } break; case ENDCOMPOUND: case UNKNOWN: default: break; } } /***************************************************************/ /* checks */ if ( pareaentry == NULL ) { fprintf ( stderr, "Error : no gif area specified.\n"); break; } xsize = (pareaentry->coords[2] - pareaentry->coords[0]); ysize = (pareaentry->coords[3] - pareaentry->coords[1]); xoffset = pareaentry->coords[0]; yoffset = pareaentry->coords[1]; /*printf ( "size : %i %i.\n", xsize, ysize ); printf ( "offset : %i %i.\n", xoffset, yoffset );*/ /***************************************************************/ /* do translations */ pcurrententry = pfirstentry; while ( pcurrententry != NULL ) { for (i = 0; i < pcurrententry->npoints; i ++) { pcurrententry->coords[i*2] -= xoffset; pcurrententry->coords[i*2+1] -= yoffset; pcurrententry->coords[i*2] /= scale; pcurrententry->coords[i*2+1] /= scale; } if ( smap != NULL ) { if ( pcurrententry->type==URL && pcurrententry->coords != NULL ) { fprintf ( map, " \"%s\"\n", pcurrententry->str,pcurrententry->str, pcurrententry->coords[0],pcurrententry->coords[1], pcurrententry->coords[2],pcurrententry->coords[3] ); } } pcurrententry = pcurrententry->next; } xsize /= scale; ysize /=scale; /***************************************************************/ /* 3 : draw gif file */ draw_gif ( gif ); /***************************************************************/ /* 4 : clean-up all */ { struct sentry * pentry; pcurrententry = pfirstentry; do { pentry = pcurrententry->next; free_entry(pcurrententry); pcurrententry = pentry; } while ( pentry != NULL ); } fclose ( gif ); fclose ( config ); if ( smap != NULL ) { /*lk311.html*/ fprintf ( map, " \n" ); fclose ( map ); } break; } while ( TRUE ); } mrtg-2.17.10/contrib/cpumon/0000755000175300017510000000000013057016061014606 5ustar oetikeroepmrtg-2.17.10/contrib/cpumon/README0000644000175300017510000000171013057016061015465 0ustar oetikeroepcpumon.pl I use this script to monitor cpu usage on any process that maintains a pid file. Usage is very simple: cpumon.pl To install, first edit the "ps" and "psargs" variables as needed. I found it easier to have these defined rather than hardcoded due to differences between ucb-based and SysV-based ps functions. cpumon.pl will return the cpu usage of the pid in the pidfile you specify in the appropriate format for MRTG. For monitoring processes on remote machines that are not snmpable, I run this program out of inetd (so I can tcp_wrap it) on a high port. See http://www.blackened.com/ircstats/ for cpu monitoring examples. To run this from mrtg, the syntax would be like: Target[cpu]: `path/to/cpumon.pl /path/to/pidfile` Direct questions or suggestions to me. Have fun! -mjr mrtg-2.17.10/contrib/cpumon/cpumon.pl0000644000175300017510000000265613057016061016455 0ustar oetikeroep#!/usr/local/bin/perl # This was taken from a PERL script Chris Behrens wrote to monitor # resource usage for his IRC servers and was trimmed down to # report only cpu usage. This has been tweaked to work well with # MRTG (Multi Router Traffic Grapher) and will work fine with # anything that has a pid file (ie: named) # # Matthew Ramsey # Last Modified 31 OCT 1997 $DEBUG = 0; # Which ps do you want to use ? If you use a non-berkeley based ps, # you will need to change the args used in the findcpu function. # Uncomment the line you want or modify one to suit your needs. #$ps = "/usr/ucb/ps"; # Solaris with UCB $ps = "/bin/ps"; # most systems # The ps arguments. For a UCB-based (BSD) ps, -aux will probably # work just fine for you. For SysV-based ps, -eaf works best for # me. $psargs = "-aux"; # UCB-based #$psargs = "-eaf"; # sysV-based if ($ARGV[0]) { $pidfile = $ARGV[0] ; } else { print STDERR "Usage: $0 \n" ; exit 1 ; } open(PID, "< $pidfile"); chomp($pid = ); close(PID); $cpu = findcpu($pid); print "$cpu\n"; print "$cpu\n"; print "$time\n"; print ""; exit; # We're done! sub findcpu { local($pid) = @_; local($cpu, $psline, @ps); open(PS, "$ps $psargs |") || die "Couldn't run a ps: $!"; chomp(@ps = ); close(PS); foreach $psline (@ps) { @blah = split(' ', $psline); print "$pid $blah[1]\n" if ($DEBUG); return $blah[2] if ($blah[1] == $pid); } return -1; } mrtg-2.17.10/contrib/mrtg-blast/0000755000175300017510000000000013057016061015361 5ustar oetikeroepmrtg-2.17.10/contrib/mrtg-blast/tcpblast.c0000644000175300017510000001515413057016061017347 0ustar oetikeroep/* From FreeBSD: */ /* * tcpblast - test and estimate TCP thruput * * Daniel Karrenberg */ /* * Changes: Rafal Maszkowski * * ftp://ftp.torun.pdi.net/pub/blast/README */ char *verstr="FreeBSD + rzm 961003"; #include #include #include #include #include #include #include #include #include #include #include #include #define DEFBLKSIZE (1024) #define MAXBLKSIZE (32*1024) struct sockaddr_in sock_in; struct servent *sp; struct hostent *host; unsigned long starts, startms, stops, stopms, expms; struct timeval ti; struct timezone tiz; char greet[MAXBLKSIZE], *ind; int nblocks, f; int tcp=0, udp=0, randomb=0, blksize=DEFBLKSIZE, setbufsize=-1, port=9, dots=1; /* Long options. */ static const struct option long_options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, { NULL, 0, NULL, 0 } }; void usage(name) char *name; { fprintf(stderr, "\n"); fprintf(stderr, "usage: %s [options] destination nblocks\n\n", name); fprintf(stderr, "tcpblast/udpblast is a simple tool for probing network and estimating its\n"); fprintf(stderr, "throughoutput. It sends nblocks of %d B blocks of data to specified\n", blksize); fprintf(stderr, "destination host\n\n"); fprintf(stderr, "Options:\n"); fprintf(stderr, "-t use TCP (%s)\n", ind[0]=='t' ? "default" : "default if named tcpblast" ); fprintf(stderr, "-u use UDP (%s)\n", ind[0]=='u' ? "default" : "default if named udpblast" ); fprintf(stderr, "-p nnn use port # nnn instead of default %d\n", port); fprintf(stderr, "-r send random data\n"); fprintf(stderr, "-s nnn block size (default %d bytes)\n", blksize); fprintf(stderr, "-b nnn socket buf size (default: %d, %s)\n", setbufsize, setbufsize==-1 ? "don't change" : "change"); fprintf(stderr, "-d nnn print dot every nnn blocks, 0 disables (default %d)\n", dots); fprintf(stderr, "-V, --version version\n"); fprintf(stderr, "-h, --help this help\n"); fprintf(stderr, "destination host name or address\n"); fprintf(stderr, "nblocks number of blocks (1..9999)\n"); fprintf(stderr, "%s version: %s\n", name, verstr); exit(1); } void usage_small(name) char *name; { fprintf(stderr, "type %s --help for help\n", name); } /* randomize the buffer */ void randbuff(blksize) int blksize; { int i; for (i=0; i=10000) { fprintf(stderr, "%s: 1 < nblocks <= 9999 \n", argv[0]); exit(5); } bzero((char *)&sock_in, sizeof (sock_in)); sock_in.sin_family = AF_INET; if (tcp) f = socket(AF_INET, SOCK_STREAM, 0); else f = socket(AF_INET, SOCK_DGRAM, 0); if (f < 0) { perror("tcp/udpblast: socket"); exit(6); } { unsigned int bufsize, size; /* get/setsockopt doesn't return any error really for SO_SNDBUF, at least on Linux, it limits the buffer only [256..65536] */ if (getsockopt(f, SOL_SOCKET, SO_SNDBUF, &bufsize, &size)==-1) printf("tcp/udpblast getsockopt: %s", strerror(errno)); printf("read SO_SNDBUF = %d\n", bufsize); if (setbufsize!=-1) { if (setsockopt(f, SOL_SOCKET, SO_SNDBUF, &setbufsize, sizeof(setbufsize))==-1) printf("tcp/udpblast getsockopt: %s", strerror(errno)); if (getsockopt(f, SOL_SOCKET, SO_SNDBUF, &bufsize, &size)==-1) printf("tcp/udpblast getsockopt: %s", strerror(errno)); printf("set SO_SNDBUF = %d\n", bufsize); } } if (bind(f, (struct sockaddr*)&sock_in, sizeof (sock_in)) < 0) { perror("tcp/udpblast: bind"); exit(7); } host = gethostbyname(argv[optind]); if (host) { sock_in.sin_family = host->h_addrtype; bcopy(host->h_addr, &sock_in.sin_addr, host->h_length); } else { sock_in.sin_family = AF_INET; sock_in.sin_addr.s_addr = inet_addr(argv[optind]); if (sock_in.sin_addr.s_addr == -1) { fprintf(stderr, "%s: %s unknown host\n", argv[0], argv[optind]); exit(8); } } sock_in.sin_port = htons(port); if (connect(f, (struct sockaddr*)&sock_in, sizeof(sock_in)) <0) { perror("tcp/udpblast connect:"); exit(9); } printf("Sending %s %s data using %d B blocks.\n", randomb ? "random":"non-random", tcp ? "TCP":"UDP", blksize); if (gettimeofday(&ti, &tiz) < 0) { perror("tcp/udpblast time:"); exit(10); } starts = ti.tv_sec; startms = ti.tv_usec / 1000L; for (i=0; i Copyright (C) 19yy 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 of the License, 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., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. mrtg-2.17.10/contrib/mrtg-blast/mrtg-blast.cfg0000644000175300017510000000444213057016061020122 0ustar oetikeroep################################################################## # Multi Router Traffic Grapher -- Example Configuration File # to integrate mrtg-blast ################################################################## # This file is for use with mrtg-2.1 # # Note: # # * Keywords must start at the begin of a line. # # * Lines which follow a keyword line which do start # with a blank are appended to the keyword line # # * Empty Lines are ignored # # * Lines starting with a # sign are comments. # ################################################################## ################################################################## # The directory where your files are kept WorkDir: /home/netadmin/traffic_stats/test ################################################################## # Sample entry to blast a host named oktoberfest ################################################################## Title[oktoberfest]: Network Throughput Analysis between Oktoberfest and Mouth PageTop[oktoberfest]:

      Network Throughput Analysis for Oktoberfest/Mouth link

      We're measuring network throughput between the Oktoberfest and Mouth server ################################################################## # We set MaxBytes to the throughput that we consider "normal" for # an unused link, so that the per-cent values show how much you # are off when the line is used more heavily. you also have to # set AbsMax, otherwise values greate than MaxBytes would be # ignored. # Values here reflect a 256 kbps frame relay link MaxBytes[oktoberfest]: 32768 AbsMax[oktoberfest]: 40000 ################################################################## # Set gauge, to treat the values gathered from target as absolute # and not as counters. Options[oktoberfest]: gauge ################################################################## # Call mrtg-blast. You must include arguments: hostname portnumber packetstoblast # experiments showed that blasting 500 packets (=500k!) shows the best results # i.e. it causes the least load while producing the best accuracy. See # INSTALL for more information on that. Target[oktoberfest]: `/home/netadmin/mrtg-2.1/mrtg-blast oktoberfest 23 500` ################################################################## # You might want to include Peaks or not. WithPeak[oktoberfest]: ymwd mrtg-2.17.10/contrib/mrtg-blast/mrtg-blast0000755000175300017510000000415413057016061017367 0ustar oetikeroep#!/usr/bin/perl ################################################################## # # Copyright (c) 1997 by Balthasar Indermuehle # Currently supports Linux 2.0.25 # All Rights Reserved. # # See the file COPYRIGHT in the distribution for the exact terms. # Based on the mrtg-ping-probe script Copyright 1997 by Peter W. Osel # ################################################################## require 5.003; use Getopt::Std; use File::Basename; use Config; $ProgName = "mrtg-blast"; $Usage = "Usage: $ProgName hostname portnumber packets\nTypically: $ProgName my.host.com 9 500\n"; # Parse Command Line: die $Usage unless getopts(''); if (@ARGV > 3) { print STDERR "$ProgName: WARNING: ignoring but the first three arguments\n"; } if (@ARGV < 3) { print STDERR "$ProgName ERROR:\nPlease enter a hostname port number and packets to blast (e.g. 9 or 21) as argument\n"; print STDERR "$Usage"; exit(1); } ($HostToBlast, $PortToBlast, $Packets) = @ARGV; ($blastres) = blast($HostToBlast, $PortToBlast, $Packets); # The external mrtg probe returns up to 4 lines of output: # 1. Line: current state of the 'incoming bytes counter' # 2. Line: current state of the 'outgoing bytes counter' # 3. Line: string, telling the uptime of the target. # 4. Line: telling the name of the target. # We leave out line 3, and 4. print "$blastres\n$blastres\n"; exit(0); ################################################################## # Do the actual blasting # sub blast { my($host, $port, $packets) = @_; # The following path to tcpblast needs to be adjusted for your system unless (open(BLAST, "/home/netadmin/mrtg-2.1/tcpblast -r -t $host $packets -p$port|")) { print STDERR "${ProgName}: FATAL: Can't open tcpblast: $!"; exit(1); } while () { # Handle output from 'real' tcpblast which looks like this: # 100 KB in 1979 msec = 413946.4 b/s = 51743.3 B/s = 50.5 KB/s close(BLAST), return("$4.$5") if /^(\d+) KB in (\d+) msec = (\d+)\.\d b\/s = (\d+)\.\d B\/s = (\d+)\.\d KB\/s/; } #Could not get blast results, link may be down, return 0 close(BLAST), return(0); } mrtg-2.17.10/contrib/mrtg-blast/README0000644000175300017510000000122213057016061016236 0ustar oetikeroepPlease read the INSTALL file after finishing this. I would like to express my thanks to Tobias Oetiker and Dave Rand for writing MRTG. It's people like them that make me believe all software designed for hazardous environments such as missile and aircraft guidance systems should be run under GNU and Copyleft. This would have spared many lost lives and many to come. Many thanks also to Daniel Karrenberg for porting tcpblast to Linux! And last - but definitely not least - Peter W. Osel who wrote mrtg-ping-probe which inspired me and helped getting along with perl regex syntax ;) mrtg-2.17.10/contrib/mrtg-blast/COPYRIGHT0000644000175300017510000000207113057016061016654 0ustar oetikeroep************************************************* * mrtg-blast * * Version 1.0 March 11 1997 * * Network Throughput Monitoring * ************************************************* Add on for MRTG - The Multi Router Traffic Grapher Copyright (c) 1997 Balthasar Indermuehle All rights reserved. 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 of the License, 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., 675 Mass Ave, Cambridge, MA 02139, USA. mrtg-2.17.10/contrib/mrtg-blast/INSTALL0000644000175300017510000000510513057016061016413 0ustar oetikeroep************************************************************************* You need the following software installed on your system: - perl 5.003 http://www.perl.com/perl/info/software.html - MRTG 2.1 http://www.ee.ethz.ch/~oetiker/webtools/mrtg/mrtg.html - gcc to successfully compile tcpblast.c ************************************************************************* mrtg-blast has been tested successfully under: Linux 2.0.25 (S.u.S.E. 4.3) (other versions / OSes might work, but have not been tested.) ------------------------------------------------- The latest version should always be available from ftp://ftp.inside.ch/pub/mrtg-blast If you create a new version, please send it to me so I can keep the archive up to date. ************************************************************************* YOU NEED TO CHANGE THE FOLLOWING: tcpblast: 1 - Type 'make tcpblast' to compile the tcpblast executable 2 - Copy tcpblast to your mrtg binary directory In mrtg-blast: 1 - Line 1: Adjust perl path to your system 2 - Line 55: Adjust tcpblast path to where you put tcpblast 3 - Copy mrtg-blast to your mrtg binary directory Edit your mrtg-blast.cfg file to add statements for the devices you want to blast. See mrtg-blast.cfg for an example. PLEASE NOTE: Blasting causes traffic, which it inherently does. ;) So please don't flood the whole wide world, keep it as local as possible. Blasting can't be that bad though, considering internet radio and tv... at least it tells us something: How fast our next video conference will pass, for example. The program returns traffic estimates which can be off sometimes. Use with care, caution and much love. Here are some estimates I tested at our site locally. Your mileage will most definitely vary, but as a guideline I always use 500 packets if I'm close to the site being blasted otherwise 200 is good enough. Link: 256 kbps = 32 kB/s #of packets: bandwidth as estimated by tcpblast [kB/s]: Error in %: 100 50 +53 % 200 38 +16 % 300 35 +5 % 400 34 +4 % 500 32 0 % 800 32 0 % You should decide yourself how accurate you're trying to be. Once again: Your mileage will vary. Have fun! Balthasar Indermuehle , March 12, Early in the morning... mrtg-2.17.10/contrib/00INDEX0000644000175300017510000003154314171553254014255 0ustar oetikeroep The files in this direectory have been contributed to mrtg ... If you have questions in connection with these please contact the authors ... adm-mrtg -------- From: "Ripley, Scott" This script organizes config files for MRTG and restarts the MRTG processes cleanly. mrtg_php_portal --------------- From: Damien Perl and Php script to provide a 'user-friendly' web interface of adding/removing Mrtg polled hosts iptables_acc_snmp ---------------- From: HERITIER Hervé simple script to capture iptables counter on Linux 2.4 for use with snmpd apc_ups ------- From: Klaus_Klein@mckinsey.com PERL script to extract the load % and remaining battery time from APC UPS systems. cisco_BPX_MGX ------------- From: "Newman, Daniel" Here is an howto on monitoring Cisco BPX and MGX switches with MRTG. mrtg.php -------- From: David Boyer Live Index of all log files TTrafic ------- From: David A. Pérez "TTrafic is a small VBScript to analyse MRTG (http://www.mrtg.org/) log files. By using this script, you will be able to know which amount of traffic is going through your interfaces." iptables-accounting ------------------- From: "Gill, Vern" I have "hacked" together a module for iptables. I used the ipchainacc 1.1.0 from the contrib directory. Total Control Modem CFG ----------------------- From: Fernando Braghetto - Webmaster Hiway config sample for Control Modem Racks (3Com) to do user monitoring. routers ------- From: Steven Shipway check out http://www.cheshire.demon.co.uk/pub/ for about 1000 neat tools for mrtg & rrdtool stfc ---- From: Mihai Claudiu Capatina This is a small script that I use on FreeBSD machines running ALTQ This machines acts like a traffic management system and I need to see the traffic for each class ( CBQ ) gentgucci --------- From: Kevin Benton generate configs for 3com total control chassis procmem ------- From Dimitrios Stergiou Cisco CPU & Memory monitoring iptables_acc ------------ From: Gereon Ruetten i wrote a little script for using mrtg with iptables ipchainacc ---------- From: Ilya Konstantinov I have tweaked version on the ipchainacc perl script provided in MRTG's contrib for which accounts BYTES instead of PACKETS net-hosts --------- From: Adrian Turcu monitor internet connection state on a chosen route (from traceroute) mrtgrq ------ From: Adrian Turcu This script helps to monitor the amount of disk-space quota for each e-Mail user on the system. It allows to acquire statistical data for each of user. linux_stat ---------- From: Mike Machado simple script to get the current traffic off a linux box nt_n_cisco ---------- From: CmdrData running mrtg on NT and SQL db monitoring Cisco gear ... cfgmaker_dlci ------------- From: Graziano Sommariva a modified version of the cfgmaker for people who want to monitor DLCIs ipchains -------- From: John Lange ipchains accounting script for use with MRTG monitor ------- From: Chris Knipe NT/Access/ASP based network monitoring system using mrtg technology. mrtg-archiver-script -------------------- From: Oleg Krotoff I have written a script, that allows to archieve graphs, produced by MRTG, organize and index them. CGI-script for navigation through archive is enclosed. get-equi -------- From: Mike Gaertner The Equinox SST card does not provide SNMP support. Therefor I wrote a small perl script which reads out the byte counter from the Equinox SST board. snmpping -------- From: x see if a device speaks snmp IxDisk ------ From: Miroslaw.Maczka@bze.com.pl Informix Performance monitoring accesslistmon ------------- From: Roddy Strachan Access-list Monitoring via MRTG mrtglog ------- From: Vladimir Vul and Wolfgang Hoffmann This simple prog counts total traffic for given period, parsing mrtg logs. meminfo ------- From: Colin Tinker This one checks /proc/meminfo for the used and free memory parsing it out for MRTG. ipfiler ------- From: Ronald Florence This script comes handy to interface ip-filter, a superb kernel-level packet-filtering router/firewll for Unix and Linux ( http://coombs.anu.edu.au/~avalon/ip-filter.html ). The script graphs connections through the firewall. switchmaker ----------- From: Markley P. Dykeman Switchmaker will make an mrtg config file for a Cisco Catylst 5XXX switch. cpuinfo ----------- From: Matthew Schumacher A short perl script that I wrote that will monitor system and user CPU usage on linux and sun machines that I would like to contrib. cisco_ipaccounting ------------------ From: cramer@dolphins.ch gets IP-accounting data from a Cisco Router NSI (Network Status Imager for MRTG) ------------------------------------ From: "Kloberg Mac (LAM)" Present network status on a map ... 14all ----- From: Rainer Bawidamann Generates mrtg graphs on the fly. Uses RRDtool for graphing and logging. Needs UseRRDTool: Yes in mrtg.cfg ... mrtg-ipacc ---------- From: Cristian Caramida Using Linux IP accounting kernel rules to feed mrtg mrtgmk ------ From: Iulian Radu "mrtgmk" is a program that scan a .cfg file and generate a mrtg.cfg style file + a .html file with links to the .html files generated by mrtg. cfgmaker_cisco -------------- From: Jon Snyder CFGMAKER which instead of just returning an incrimenting port number on the graps, actually makes the following type of lable: Port 4/3, Vlan 128 , multi mode fiber fast ethernet This version also grabs and shows all non-VLAN1 VLANS in a different color, plus provides aggregate VLAN traffic stastics as well by finding out what ports are in the VLAN, then adding those ports together. This means of course that a port will be "hit" however many times it is in a VLAN. cfgmaker_atm ------------ From: Henry Steinhauer Bay ATM Information created from their MIB. OVmrtg ------ From: "Gellatly, Laurie (x8864)" HP OpenView integration for MRTG ... CiscoIndex ---------- From: Tim Cimarusti This PERL script will read in the a Cisco router config file created by the "write network" command and create a HTML index for it's interfaces that corresponds with MRTG. DiskMon (getdisk.pl and showdisk.pl) ------------------------------------ From: Steven Micallef Well, here's the scripts I use for graphing disk space on the hosts on our network. stat.pl ------ From: Calle Olsen this little perlscript helps to monitor your dns server whodo ----- From: "Tony-Farr (Canberra)" Whodo is a set of Perl scripts to analyse IP accounting data from a cisco router. The stats for each traffic source are fed into mrtg. Whodo also generates pie graphs showing traffic split by source or destination. xlsummary --------- From: "Tony-Farr (Canberra)" The script extracts summary figures from the MRTG log files. In particular it summarises all sites (i.e. as many as will fit on a page) into a single Excel chart. Because it uses Excel, it is only useful on Windows. TCH --- From: Eric Billeter Here are some scripts i modified to monitor the modem utilization of my USR Total control racks. jm -- From: Joey Miller joeym@inficad.com a few perl scripts I wrote to collect stats on: # of users logged into a given shell machine, # of players on a quake server, and # of users currently reading news. get-active ---------- get-active From: Russ Wright get-active2 From: Wee-Meng LEE This will look at the $trafficDir directory for MRTG generated HTML files, parse them and generate a listing of the most active interfaces in a file called "active.htlm" in the same directory cpumon ------ From: Matthew Ramsey I use this script to monitor cpu usage on any process that maintains a pid file. mrtg-dynip ---------- From: John Heenan Mrtg-dynip is a contribution to mrtg, enabling mrtg to generate multi interface traffic graphs for various hosts which do not provide a consistent interface name for physical interfaces, such as in a dynamic IP environment. ircstats -------- From: Matt Ramsey (MR227) mjr@geeks.org, mjr@nin.com ircstats.pl is the simple perl script I use to monitor client loads and such on various EFnet IRC servers. ircstats2 --------- From: Lucas Nussbaum ircstats2.pl is a script used to monitor the user load on IRC networks. Contrary to ircstats by Matt Ramsey, it remains connected to the server. PMLines -------- From: Carlos Canau and Many others Here's another script for contrib. It allows one to make a graph of analog/ISDN lines on a Livingston Portmaster 2/3/4. atmmaker -------- From: Mark Trettin I am sending a copy of our atmmaker script that generates a cfg for the FORE ASX switch you may add it to your contrib section. distrib ------- From: Philippe Simonet 'distrib' read mrtg log files and computes traffic distribution in the time. It ouputs a graph with : - in x the percentage of trafic utilisation (% bandwith) - in y how many times the utilization was reached (% time) rdlog2 ------ From: Philippe Simonet Rdlog is a small (and primitive) tool that gives indication on network traffic on a graphic map. It takes information from MRTG log files, and draw a GIF file with links that have colors based on the current traffic on your network. This small test explain how to use this tool. mrtg-ipget ---------- From: Jim Willette I have modified mrtgV2 to record stats based on interface ip address instead of Interface number. It does not do all the great errorchecking and no OS testing but it is functional for my needs. mrtgidx ------- From: Axel Dunkel mrtgidx works like makeindex but the output produced looks different ... ascendget --------- From: John-David Childs SHELL SCRIPT TO GET # of connected users on Ascend use Target[router]: `ascendget` get-multiserial --------------- From: T. Pospisek SHELL scripts to get active tty(-dial-in modem-) lines localy and remotely. I'm using them with a cyclades board but they can be adapted at wish to different tasks. use Target[modems]: `get-multiserial` ping-probe ---------- From: "Peter W. Osel" A perl script to get roundtrip delays to hosts by sending a ping to them. rumb-stat --------- From: Anthony Rumble Heres some handy scripts to get byte stats from apache (web server) 1.1.1 and better and squid (proxy server) 1.1.1 and better. portmaster ---------- From: Chris Johnson Subject: MRTG for portmasters A script and config to produce Modem statistics for Livingston Portmasters. mrtg-blast ---------- From: "Balthasar T. Indermuehle" This is a tcpblast interface available for MRTG 2.1. It works much like the famed ping-probe, instead of ping it uses tcpblast to estimate network bandwidth. GetSNMPLinesUP -------------- From: Carlos Canau GetSNMPLinesUP.pl checks some SNMP variables for a certain value and returns their sum in a format used to feed values to MRTG. mrtgindex.cgi ------------- From: Mick Ghazey like mrtgindex, but runs as a cgi. Thus it will not need SSIs ... mrtg-mail --------- From: Rachel Polanskis plot sendmail mailstats with mrtg there is a second version bz rick horowitz in the directory as well mrtg-archiver ------------- From: Emanuele Leonardi From: Rawlin Blake It wakes up at 23:54 every night and copies all the current daily gifs for the given list of routers to a directory named with the current date (e.g. 970717). The Perl code is extremely straightforward so there should be no problem in understanding it. exim-stats ---------- From: Ray Smith Set of scripts to extract data from exim (MTA) and plot it with mrtg. mrtg-startup-script ------------------- From: Stefan Example of startup script (/etc/init.d/mrtg) for the MRTG daemon. debian-systemd -------------- From: Joao Eriberto Mota Filho systemd and init config files for MRTG. mrtg-2.17.10/contrib/mrtg-ipacc/0000755000175300017510000000000014130032004015317 5ustar oetikeroepmrtg-2.17.10/contrib/mrtg-ipacc/ipacc0000755000175300017510000000756514130032004016341 0ustar oetikeroep#!/usr/bin/perl # # This is just a hack, but it works fine for me. # I'm using the ip accounting kernel rules to feed the mrtg. # You need to have IP accounting compiled in your kernel(2.0), or IPChains # support if you are running 2.1 or 2.2 # Anyway I'm not using the ipchains in here as there's no need to. # The old ipfwadm will do just fine. # So for 2.1 or 2.2 you'll need the ipfwadm-wrapper. # # # Cristian Caramida # but very soon # # Usage: # # You need to have IP accounting compiled in your kernel, and than just add # to the mrtg.cfg # Target[ip_addr]: `ipacc [mode] [-S aaa.bbb.ccc.ddd[/net_bits]] [port1 port2 ...] [-D aaa.bbb.ccc.ddd[/net_bits]] [port1 port2 ...]` # where # - mode - is one of "in" or "out" in lowercase # - aaa.bbb.ccc.ddd - is a dotted IP address (not a host/net name) # - net_bits - is the number of bits used by the network portion of the IP # (eg. 24 for a whole C class, or 25 for half of a C class) # - port1 port2 ... - the ports you want to plot trafic on # I haven't tryied to call it without any parameters! # It will probably make accounting for all trafic. $ipfwadm='/sbin/ipfwadm'; # <-------- ATTENTION $host="com.bbs.ro"; #If you are running with ipchains (kernel 2.1, 2.2 or later) you may #either symlink the ipfwadm-wrapper to that location or simply modify the value #--------------------------------------------------------------------------- # Modify this only if you know what you are doing !!! :-) $mode='both'; $remote=''; $port='8889'; if(!($ARGV[0] =~ /^\-/)){ ($mode)=@ARGV; shift @ARGV;} if($mode eq 'in') {$mode='in ';} $mode=($mode eq 'in')?'in ':$mode; $source_ip='0.0.0.0/0'; $source_port=''; $dest_ip='0.0.0.0/0'; $dest_port=''; $prot='all'; $inBytes=0; $outBytes=0; $upTime=0; while ($ARGV[0] =~ /^\-/) { if($ARGV[0] eq '-S') { shift @ARGV; ($source_ip)=@ARGV; shift @ARGV; while ($ARGV[0] =~ /[0123456789]+/) { $source_port.="$ARGV[0] "; shift @ARGV; } } elsif($ARGV[0] eq '-D') { shift @ARGV; ($dest_ip)=@ARGV; shift @ARGV; while ($ARGV[0] =~ /[0123456789]+/) { $dest_port.="$ARGV[0] "; shift @ARGV; } } else { die "Error: Unknown parameter $ARGV[0] \n"; } } chop $source_port; chop $dest_port; if($source_port.$dest_port ne '') { $prot='tcp';} if($mode eq 'both') { $exec_line="$ipfwadm -A in -a -P $prot -S $source_ip $source_port -D $dest_ip $dest_port; $ipfwadm -A out -a -P $prot -S $dest_ip $dest_port -D $source_ip $source_port"; } else { $exec_line="$ipfwadm -A $mode -a -P $prot -S $source_ip $source_port -D $dest_ip $dest_port"; } $new_sp=($source_port eq '')?'*':join(',',split(/ /,$source_port)); $new_dp=($dest_port eq '')?'*':join(',',split(/ /,$dest_port)); $ports=($source_port.$dest_port eq '')?"\"n/a\"":"\"".$new_sp." -> ".$new_dp."\""; if($mode eq 'both') { $stats_line=($source_port.$dest_port eq '')?"$ipfwadm -A -l -x -n| grep $prot |grep $source_ip |grep $dest_ip | grep \"n/a\"":"$ipfwadm -A -l -x -n| grep $prot |grep $source_ip |grep $dest_ip | grep \"$new_sp\" | grep \"$new_dp\""; } else { $stats_line="$ipfwadm -A -l -x -n |grep \"$mode $prot $source_ip\" | grep $dest_ip | grep $ports "; } open(DATA,$stats_line."|"); @info=; close ; $probe=($mode eq 'both')?2:1; $mode=($mode eq 'in ')?'in':$mode; if(@info<$probe) { system($exec_line); } else { if($probe%2) { eval "\$$mode"."Bytes=(split(/ +/,\$info[0]))[2]"; } else { if($info[0] =~ /in /) { $inBytes=(split(/ +/,$info[0]))[2]; } elsif($info[0] =~ /out /) { $outBytes=(split(/ +/,$info[0]))[2];} if($info[1] =~ /in /) { $inBytes=(split(/ +/,$info[1]))[2]; } elsif($info[1] =~ /out /) { $outBytes=(split(/ +/,$info[1]))[2];} } } open(UPTIME,"uptime |cut -b 13-26|"); $upTime=; close(UPTIME); printf "$inBytes\n$outBytes\n$upTime\n$host"; mrtg-2.17.10/contrib/mrtg-ipacc/README0000644000175300017510000000367313057016061016224 0ustar oetikeroepIPacc v0.1 Using IP accounting kernel rules to feed mrtg. 1. Abstract I am using the old ipfwadm style for doing this for backwards compatibility, and because it's enough for my purpose. For those who have kernels higher than 2.0 (using IPchains), like 2.1 or 2.2. I have included the ipfwadm-wrapper by Paul Russel. So if you if you are running on 2.2 (like me), you should copy this to /sbin/ipfwadm. It's a little slow, but it's done with sh. With this script you may generate trafic grahs for any IP, any networks or subnetworks. I haven't done support for icmp prot. 2. Syntax You use the exact sintax as with ipfwadm ipacc [mode] [-S source_ip/net_bits [port1 port2 ...]] [-D dest_ip/net_bits [port1 port 2 ...]] where: mode - is either "in" or "out", if you don't specify any there will be included 2 rules in this fashion: in -S source_ip/net_bits sport1 sport2 -D dest_ip/net_bits port1 port2 out -S dest_ip/net_bits dport1 dport2 -D source_ip/net_bits sport1 sprot2 source_ip & dest_ip - are the dotted ip address of the source and the destination (IP address not hosts) net_bits - are number of bits used by the network+subnetwork if any (that is 24 for a whole class C or 25 for half a C class ...) you don't have to specify any if you are doing it for a host portN - the ports where the packet it comming from and is going to 3. The printings If you are using one way ipacc will print inbytes, 0, uptime, server_name for an "in" mode rule or 0, outbytes, uptime, server_name for an "out" mode rule for both ways (in - out) it will print inbytes, outbytes, uptime, server_name inbytes, outbytes - the numbers read from the ipfwadm command uptime - is what the uptime command will print server_name - is what you'll write at the server name in the script So you will add something like Target[ipaddr]: `ipacc arguments` Cristian Caramida and soon 4. End mrtg-2.17.10/contrib/mrtg-ipacc/ipfwadm-wrapper0000755000175300017510000005270113057016061020373 0ustar oetikeroep#! /bin/bash # This is a wrapper script to simulate ipfwadm 2.3a. It ain't pretty, # but it should work (for valid commands). `-V' is translated to `-W' # or ignored if a `-W' option is already there, but always warned # about. # Paul ``Rusty'' Russell, Nov-1997. ipchains@rustcorp.com. # 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 of the License, 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., 675 Mass Ave, Cambridge, MA 02139, USA. # # Version: 1.0.1: Fixed -t (no longer de-hexizes). # # Version: 1.0.2: Fixed undocumented `-a masq'. # Should be OK now with bash v1. # If we can't find ip_fwnames, call /sbin/ipfwadm.real # # Version: 1.1: Fixed printing counts for accounting chains list. # Fixed -A -z and -A -f cases to do all 3 acct. rules. # # Version: 1.1.1: Fixed syntax error by escaping ( and ). # # Version: 1.1.2: Fixed REDIR thanks to Ambrose Li. # Fixed "printf --" thanks to Alain Knaff. # Fixed masquerade policy # Fixed bug report message unquoted `;'. # Fixed -k/-y and -S/-D options [ found by Charlie Brady ] # Barf on all ipchains failures. if [ -n "$DEBUG_IPFWADM" ]; then IPCHAINS=print_ipchains; else IPCHAINS=/sbin/ipchains; fi PROC_FIREWALL_NAMES="/proc/net/ip_fwnames" SPECIAL_CHAIN="IpFwAdM!" START_MARK=10000 barf() { echo "$@" echo echo If this command worked with the original ipfwadm 2.3, please echo submit a bug report to \`ipchains@rustcorp.com\'. Note that you echo now need to be root, even to list the chains \(complain to Alan Cox\). echo echo The best way to do this is to submit the output of \`$0 --version\', echo the command used to obtain this error, any previous ipfwadm echo commands, and the output of \`ipchains-save\'. echo echo Then try flushing all the rules \`ipchains -F\; ipchains -X\', echo setting the DEBUG_IPFWADM variable \`export DEBUG_IPFWADM=1\' or echo \`setenv DEBUG_IPFWADM 1\' and rerunning the command\(s\) which echo caused this error. exit 1 } print_ipchains() { echo ipchains "$@" 1>&2 /sbin/ipchains "$@" } setup_chains() { if [ `wc -l < $PROC_FIREWALL_NAMES` != 3 -a -z "$DEBUG_IPFWADM" ] then echo You cannot mix the \`ipfwadm\' wrapper with ipchains. 1>&2 echo You must delete all user chains and flush all built-in chains 1>&2 echo if you want to use the \`ipfwadm\' wrapper. 1>&2 exit 1 fi $IPCHAINS -N acctin $IPCHAINS -N acctout $IPCHAINS -N acctboth $IPCHAINS -N inp $IPCHAINS -N out $IPCHAINS -N fwd # Let all fragments through like the old code used to. $IPCHAINS -A input -f -j ACCEPT $IPCHAINS -A output -f -j ACCEPT $IPCHAINS -A forward -f -j ACCEPT # Jump to accounting rules. Order of traversal of acct rules # doesn't matter. $IPCHAINS -A input -j acctin $IPCHAINS -A input -j acctboth $IPCHAINS -A output -j acctout $IPCHAINS -A output -j acctboth # Now go to `real' chains. $IPCHAINS -A input -j inp $IPCHAINS -A output -j out $IPCHAINS -A forward -j fwd # Create dummy chains to mark this as an ipfwadm-emulation firewall. $IPCHAINS -N $SPECIAL_CHAIN # Insert min and max mark values. $IPCHAINS -A $SPECIAL_CHAIN -m $START_MARK $IPCHAINS -A $SPECIAL_CHAIN -m $(($START_MARK + 1)) } # SIGH. We use identical marks to indicate which rules are actually # the same rule (to simulate multiple ports, and -y without -P tcp). # We start the marks at 1,000,000, so we can insert before them or append # after them. # In the accounting chain, marks are unique between the three acct* chains, # so we can tell ordering. print_count() { count=$(($1)) if let $(($count > 99999)) then cntkb=$((($count + 500) / 1000)) if let $((cntkb > 9999)) then cntmb=$((($count + 500000) / 1000000)) printf "%4sM " $cntmb else printf "%4sK " $cntkb fi else printf "%5s " $count fi } dump_rule() { # ARGS: $LIST_VERBOSE $EXPAND_NUMBERS $BIDIR $SYN_NO_PROTO $SRCPORTS $DSTPTS # $PCNT $BCNT $TARG $PROTO $FLAGS $TOSA $TOSX $IFNM $NUM $SRCIP $DSTIP $REDIR # $PRINT_COUNTS # The ipfwadm code looks like: (* = -e only) # * * * * * * * # pcnt bcnt kind proto bkyo TOSA TXOR IFNM IFADD SRC DST SPTs -> DPTs REDIR if [ -n "$1" -o -n "${19}" ] then # Packet and byte counts. if [ -n "$2" ]; then printf "%8u " $7; else print_count $7; fi if [ -n "$2" ]; then printf "%8u " $8; else print_count $8; fi fi # Kind case "$9" in in) printf "%-3s " "$9" ;; out) printf "%-3s " "$9" ;; i/o) printf "%-3s " "$9" ;; *) printf "%-5s " "$9" ;; esac # Proto printf "%-5s" "${10}" if [ -n "$1" ] then # Flags if [ "$3" != 0 ]; then printf "b"; else printf "%s" "-"; fi case "${11}" in *!y*) printf "k-" ;; *y*) printf "%s" "-y" ;; *) printf "%s" "--" ;; esac case "${11}" in *l*) printf "l " ;; *) printf "%s" "- " ;; esac # TOS printf "${12} ${13} " # Interface name printf "%-7.16s " "${14}" # Interface address if [ -n "${15}" ]; then printf "%-15s " 0.0.0.0; else printf "%-15s " any; fi fi # Source and dest. printf "%-20s " "${16}" printf "%-20s" "${17}" # Source Ports. if [ "${10}" != tcp -a "${10}" != udp -a "${10}" != icmp ] then echo " n/a" return fi printf " " printf "$5" | tr ' ' ',' if [ "${10}" = icmp ] then echo return fi # Dest ports. if [ "$5" != "n/a" ] then printf " -> " printf "$6" | tr ' ' ',' fi # redirect ports. if [ "$9" = "acc/r" ] then printf " => %s" "${18}" fi echo } get_policy() # CHAIN { case "`ipchains -L $1 | head -1`" in *ACCEPT*) echo accept;; *MASQ*) echo accept/masquerade;; *REJECT*) echo reject;; *DENY*) echo deny;; *) barf "Unknown policy for \`$1' - `ipchains -L $1 2>&1`" esac } list_chain() # $CHAIN $LIST_VERBOSE $NUMERIC $EXPAND_NUMBERS { # if (!(format & FMT_NOCOUNTS)) { # if (format & FMT_KILOMEGA) { # fprintf(fp, FMT("%5s ","%s "), "pkts"); # fprintf(fp, FMT("%5s ","%s "), "bytes"); # } else { # fprintf(fp, FMT("%8s ","%s "), "pkts"); # fprintf(fp, FMT("%10s ","%s "), "bytes"); # } # } IS_ACCT="" case "$1" in acct*) IS_ACCT="Y";; inp) printf "IP firewall input rules, default policy: " get_policy input ;; out) printf "IP firewall output rules, default policy: " get_policy output ;; fwd) printf "IP firewall forward rules, default policy: " get_policy forward ;; *) barf "Unknown chain for list_chain - \`$1'" ;; esac if [ -n "$2" -o -n "$IS_ACCT" ] then if [ -z "$4" ] then printf "%5s " pkts printf "%5s " bytes else printf "%8s " pkts printf "%10s " bytes fi fi # if (!(format & FMT_NOKIND)) { # if (chain == CHN_ACCT) # fprintf(fp, FMT("%-3s ","%s "), "dir"); # else # fprintf(fp, FMT("%-5s ","%s "), "type"); # } case "$1" in acct*) printf "%-3s " dir ;; *) printf "%-5s " type ;; esac # fputs("prot ", fp); printf "prot " # if (format & FMT_OPTIONS) # fputs("opt ", fp); # if (format & FMT_TOS) # fputs("tosa tosx ", fp); # if (format & FMT_VIA) { # fprintf(fp, FMT("%-7s ","(%s "), "ifname"); # fprintf(fp, FMT("%-15s ","%s) "), "ifaddress"); # } if [ -n "$2" ] then printf "opt tosa tosx %-7s %-15s " ifname ifaddress fi # fprintf(fp, FMT("%-20s ","%s "), "source"); # fprintf(fp, FMT("%-20s ","%s "), "destination"); # fputs("ports\n", fp); # } printf "%-20s %-20s ports" source destination echo case "$1" in acct*) shift; (list_chain_real acctin "$@" "1" "1" list_chain_real acctout "$@" "1" "1" list_chain_real acctboth "$@" "1" "1") | sort -n | cut -c11-;; *) list_chain_real "$@" ;; esac } list_chain_real() # $CHAIN $LIST_VERBOSE $NUMERIC $EXPAND_NUMBERS $PRINT_COUNTS $PREPEND_MARK { CHAIN="$1" LIST_VERBOSE="$2" NUMERIC="$3" EXPAND_NUMBERS="$4" PRINT_COUNTS="$5" PREPEND_MARK="$6" # The ipfwadm code looks like: (* = -e only) # * * * * * * * # pcnt bcnt kind proto bkyo TOSA TXOR IFNM IFADD SRC DST SPTs -> DPTs REDIR # # The ipchains code looks like: (* = -v only) # * * * * * * * # pcnt bcnt targ proto !yfl TOSA TXOR IFNM MARK SRC DST SPTs -> DPTs REDIR LAST_MARK=xxx BIDIR=0 SYN_NO_PROTO=0 SRCPORTS="" DSTPORTS="" [ -z "$NUMERIC" ] || NUMERIC="-n" $IPCHAINS -L $CHAIN -v -x $NUMERIC | tail +3 | while true do if ! read PCNT BCNT TARG PROTO FLAGS TOSA TOSX IFNM MARK SRCIP DSTIP SRCPTS IGN1 DSTPTS REDIR then # Dump last rule. if [ "$LAST_MARK" != "xxx" ] then [ -z "$PREPEND_MARK" ] || printf "%-10s " "$LAST_MARK" dump_rule "$LIST_VERBOSE" "$EXPAND_NUMBERS" $BIDIR $SYN_NO_PROTO "$SRCPORTS" "$DSTPORTS" $LAST_PCNT $LAST_BCNT $LAST_TARG $LAST_PROTO $LAST_FLAGS $LAST_TOSA $LAST_TOSX "$LAST_IFNM" "$NUMERIC" $LAST_SRCIP $LAST_DSTIP "$LAST_REDIR" "$PRINT_COUNTS" fi return fi [ -z "$DEBUG_IPFWADM" ] || echo RULE is "$PCNT $BCNT $TARG $PROTO $FLAGS $TOSA $TOSX "$IFNM" $MARK $SRCIP $DSTIP $SRCPTS $IGN1 $DSTPTS $REDIR" 1>&2 if [ "$LAST_MARK" = "$MARK" ] then # Fold rules back together. # We combine for any of the following reasons: # -k or -y used with no protocol: first rule has proto TCP and 'y'. # -b used: SRC & DST reversed. # Multiple ports: all the same but for port. # Worst cases: # ipfwadm -I -a accept -b -P tcp -S 0/0 1 4 -D 1/1 5 9 # => pcnt bcnt targ proto !yfl TOSA TXOR IFNM MARK SRC DST SPTs -> DPTs REDIR # ? ? ? TCP ? ? ? ? ? 0/0 1/1 1 5 # ? ? ? TCP ? ? ? ? ? 1/1 0/0 5 1 # ? ? ? TCP ? ? ? ? ? 0/0 1/1 1 9 # ? ? ? TCP ? ? ? ? ? 1/1 0/0 9 1 # ? ? ? TCP ? ? ? ? ? 0/0 1/1 4 5 # ? ? ? TCP ? ? ? ? ? 1/1 0/0 5 4 # ? ? ? TCP ? ? ? ? ? 0/0 1/1 4 9 # ? ? ? TCP ? ? ? ? ? 1/1 0/0 9 4 # # ipfwadm -I -a accept -b -y -S 0/0 -D 1/1 # => pcnt bcnt targ proto !yfl TOSA TXOR IFNM MARK SRC DST SPTs -> DPTs REDIR # ? ? ? TCP ?y?? ? ? ? ? 0/0 1/1 # ? ? ? TCP ?y?? ? ? ? ? 1/1 0/0 # ? ? ? ANY ?-?? ? ? ? ? 0/0 1/1 # ? ? ? ANY ?-?? ? ? ? ? 1/1 0/0 # if [ -n "$DEBUG_IPFWADM" ] # then # echo LAST_PROTO = \`"$LAST_PROTO"\' # echo PROTO = \`"$PROTO"\' # echo LAST_SRCIP = \`"$LAST_SRCIP"\' # echo DSTIP = \`"$DSTIP"\' # echo LAST_DSTIP = \`"$LAST_DSTIP"\' # echo SRCIP = \`"$SRCIP"\' # echo LAST_SRCPTS = \`"$LAST_SRCPTS"\' # echo DSTPTS = \`"$DSTPTS"\' # echo LAST_DSTPTS = \`"$LAST_DSTPTS"\' # echo SRCPTS = \`"$SRCPTS"\' # fi if [ "$LAST_PROTO" = \!tcp -a "$PROTO" = tcp ] then [ -n "$DEBUG_IPFWADM" ] && echo "Found SYN rule." SYN_NO_PROTO=1 PCNT=$(($LAST_PCNT + $PCNT)) BCNT=$(($LAST_BCNT + $BCNT)) PROTO="all" elif [ "$LAST_SRCIP" = "$DSTIP" -a "$LAST_DSTIP" = "$SRCIP" -a "$LAST_SRCPTS" = "$DSTPTS" -a "$LAST_DSTPTS" = "$SRCPTS" ] then [ -n "$DEBUG_IPFWADM" ] && echo "Found bidir rule." BIDIR=1 LAST_PCNT=$(($LAST_PCNT + $PCNT)) LAST_BCNT=$(($LAST_BCNT + $BCNT)) # Don't transfer this rule to LAST_ vars - effectively ignore. continue; else [ -n "$DEBUG_IPFWADM" ] && echo "Found port rule." # For n source ports and m dest ports, there will be # n x m rules. So, we add to SRCPORTS when we see a new # SRCPTS, but only add to DSTPORTS for the first SRCPORTS. if [ "$SRCPTS" != "$LAST_SRCPTS" ] then SRCPORTS="$SRCPORTS $SRCPTS" fi if [ "$SRCPORTS" = "$SRCPTS" ] then DSTPORTS="$DSTPORTS $DSTPTS" fi PCNT=$(($LAST_PCNT + $PCNT)) BCNT=$(($LAST_BCNT + $BCNT)) fi else # Dump last rule. if [ "$LAST_MARK" != "xxx" ] then [ -z "$PREPEND_MARK" ] || printf "%-10s " "$LAST_MARK" dump_rule "$LIST_VERBOSE" "$EXPAND_NUMBERS" $BIDIR $SYN_NO_PROTO "$SRCPORTS" "$DSTPORTS" $LAST_PCNT $LAST_BCNT $LAST_TARG $LAST_PROTO $LAST_FLAGS $LAST_TOSA $LAST_TOSX "$LAST_IFNM" "$NUMERIC" $LAST_SRCIP $LAST_DSTIP "$LAST_REDIR" "$PRINT_COUNTS" fi BIDIR=0 SYN_NO_PROTO=0 SRCPORTS="$SRCPTS" DSTPORTS="$DSTPTS" fi # Save for next iteration, in case mark the same. LAST_PCNT=$PCNT LAST_BCNT=$BCNT LAST_PROTO=$PROTO LAST_FLAGS=$FLAGS LAST_TOSA=$TOSA LAST_TOSX=$TOSX LAST_IFNM="$IFNM" LAST_MARK=$MARK LAST_SRCIP=$SRCIP LAST_DSTIP=$DSTIP LAST_REDIR="$REDIR" LAST_SRCPTS="$SRCPTS" LAST_DSTPTS="$DSTPTS" case "$CHAIN" in acctin) LAST_TARG=in ;; acctout) LAST_TARG=out ;; acctboth) LAST_TART=i/o ;; *) case "$TARG" in REDIRECT) LAST_TARG="acc/r" ;; MASQ) LAST_TARG="acc/m" ;; ACCEPT) LAST_TARG="acc" ;; REJECT) LAST_TARG="rej" ;; DENY) LAST_TARG="deny" ;; *) barf Unknown target \`"$TARG"\'. ;; esac ;; esac done } ############################################################################ if [ ! -f $PROC_FIREWALL_NAMES ] then if [ -f /proc/net/ip_input -o -f /proc/net/ip_acct ] then # Old kernel. Let's play nice. [ -x /sbin/ipfwadm.real ] && exec /sbin/ipfwadm.real "$@" fi echo "Generic IP Firewall Chains not in this kernel" 1>&2 exit 1 fi while [ $# != 0 ] do case "$1" in -A) case x"$2" in x-*) CHAIN=acctboth ;; xboth) CHAIN=acctboth; shift ;; xin) CHAIN=acctin; shift ;; xout) CHAIN=acctout; shift ;; x) CHAIN=acctboth ;; *) barf Unknown option \`"$2"\' ;; esac ;; -I) CHAIN=inp ;; -O) CHAIN=out ;; -F) CHAIN=fwd ;; -M) MASQ_MODE=1 ;; -a) COMMAND=-A case x"$2" in x-*) TARGET="" ;; x) TARGET="" ;; xr*) TARGET=REJECT; shift ;; xd*) TARGET=DENY; shift ;; xa*) TARGET=ACCEPT; shift ;; xm*) TARGET=ACCEPT; MASQ=1; shift ;; *) barf Unknown policy for append: \`"$2"\' ;; esac ;; -i) COMMAND="-I " case x"$2" in x-*) TARGET="" ;; x) TARGET="" ;; xr*) TARGET=REJECT; shift ;; xd*) TARGET=DENY; shift ;; xa*) TARGET=ACCEPT; shift ;; *) barf Unknown policy for insert: \`"$2"\' ;; esac ;; -d) COMMAND=-D case x"$2" in x-*) TARGET="" ;; x) TARGET="" ;; xr*) TARGET=REJECT; shift ;; xd*) TARGET=DENY; shift ;; xa*) TARGET=ACCEPT; shift ;; *) barf Unknown policy for delete: \`"$2"\' ;; esac ;; -l) LIST=1 ;; -z) COMMAND=-Z ;; -f) COMMAND=-F ;; -p) COMMAND=-P case "$2" in r*) TARGET=REJECT; shift ;; d*) TARGET=DENY; shift ;; a*) TARGET=ACCEPT; shift ;; m*) TARGET=MASQ; shift ;; *) barf Unknown policy for -p: \`"$2"\' ;; esac ;; -s) COMMAND=-S OPTIONS="$2 $3 $4" shift 3 ;; -c) COMMAND=-C ;; -h) print_help ;; -P) PROTOCOL="-p $2" shift ;; -S) SRC_OPTIONS="-s $2" shift while true do case x"$2" in x) break ;; x-*) break ;; x?*) SRC_PORTS="$2 $SRC_PORTS" ;; esac shift done ;; -D) DST_OPTIONS="-d $2" shift while true do case x"$2" in x) break ;; x-*) break ;; x?*) DST_PORTS="$2 $DST_PORTS" ;; esac shift done ;; -V) VIA_ADDR="$2" shift ;; -W) INTERFACE="$2" OPTIONS="$OPTIONS -i $2" shift ;; -b) OPTIONS="$OPTIONS -b" ;; -e) LIST_VERBOSE=1 ;; -k) TCPSYN="! -y" ;; -m) MASQ=1 ;; -n) NUMERIC=1 ;; -o) OPTIONS="$OPTIONS -l" ;; -r) case x"$2" in x-*) REDIR=0 ;; x) REDIR=0 ;; x?*) REDIR="$2"; shift ;; esac ;; -t) TOSAND=$(($2 | 0x01)) TOSXOR=$(($3 & 0xFE)) OPTIONS="$OPTIONS -t "`printf "0x%02x 0x%02x" $TOSAND $TOSXOR` shift 2 ;; -v) OPTIONS="$OPTIONS -v" ;; -x) EXPAND_NUMBERS=1; ;; -y) TCPSYN="-y" ;; --version) echo "ipfwadm wrapper version 1.1.2" exit 0 ;; -??*) echo "ERROR: Please separate arguments, eg \`-Mle' => \`-M -l -e'." >&2 exit 1 ;; *) barf Unexpected argument \`"$1"\'. ;; esac shift done # Variables to worry about: # $CHAIN - actual chain to work on. # X$MASQ_MODE - set if -M given. # X$COMMAND - set if this is a simple command conversion. # X$TARGET - set for COMMAND of -A, -I, -D or -P (but see REDIR and MASQ). # X$LIST - set if they want a list. # X$NUMERIC - list with -n. # X$LIST_VERBOSE - list all info. # X$EXPAND_NUMBERS - list full numbers. # X$OPTIONS - miscellaneous easy-to-convert options. # X$SRC_OPTIONS - set if a source address is specified. # X$SRC_PORTS - space-separated list of specified source ports/ranges. # X$DST_OPTIONS - set if a dest address is specified. # X$DST_PORTS - space-separated list of specified dest ports/ranges. # $VIA_ADDR - an interface address if one is specified. # $INTERFACE - an interface name if one is specified. # X$TCPSYN - set if `-k' or `-y' is specified. # X$MASQ - set if `-m' is specified. # X$REDIR - set to the port if `-r port' is specified if [ -n "$MASQ_MODE" ] then if [ -n "$LIST" ] then $IPCHAINS -M -L $OPTIONS else $IPCHAINS $COMMAND $OPTIONS fi elif [ -n "$LIST" ] then if ! grep -q IpFwAdM! < $PROC_FIREWALL_NAMES then echo "Chains are empty. (ie. ipfwadm has not been used on them)." 1>&2 exit 0 fi # Construct a list. if [ x$COMMAND = x-Z ] then # We have to atomically zero and list a chain. This is # currently impossible, so we: # 1) stop all packets on the given chain. # 2) list the values. # 3) clear the counters. # 4) resume on the given chain. case "$CHAIN" in acct*) $IPCHAINS -I 1 input -j DENY $IPCHAINS -I 1 output -j DENY ;; inp) $IPCHAINS -I 1 input -j DENY ;; out) $IPCHAINS -I 1 output -j DENY ;; fwd) $IPCHAINS -I 1 forward -j DENY ;; *) barf Unknown chain to stop: \`"$CHAIN"\'. esac list_chain $CHAIN "$LIST_VERBOSE" "$NUMERIC" "$EXPAND_NUMBERS" $IPFWADM -Z $CHAIN case "$CHAIN" in acct*) $IPCHAINS -D 1 input $IPCHAINS -D 1 output ;; inp) $IPCHAINS -D 1 input ;; out) $IPCHAINS -D 1 output ;; fwd) $IPCHAINS -D 1 forward ;; *) barf Unknown chain to restart: \`"$CHAIN"\'. esac else list_chain $CHAIN "$LIST_VERBOSE" "$NUMERIC" "$EXPAND_NUMBERS" fi elif [ x"$COMMAND" = x"-F" -o x"$COMMAND" = x"-Z" -o x"$COMMAND" = x"-C" ] then if ! grep -q IpFwAdM! < $PROC_FIREWALL_NAMES then echo "Chains are empty. (ie. ipfwadm has not been used on them)." 1>&2 exit 0 fi if [ "$CHAIN" = acctboth ] then # Do it to all of them. $IPCHAINS $COMMAND acctin $OPTIONS $IPCHAINS $COMMAND acctout $OPTIONS fi $IPCHAINS $COMMAND $CHAIN $OPTIONS else grep -q IpFwAdM! < $PROC_FIREWALL_NAMES || setup_chains # Figure out what the target should be. if [ -n "$REDIR" ] then TARGET="REDIRECT $REDIR" elif [ -n "$MASQ" ] then TARGET=MASQ fi if [ x"$COMMAND" = x"-P" ] then case "$CHAIN" in inp) CHAIN=input ;; out) CHAIN=output ;; fwd) CHAIN=forward ;; *) barf Illegal chain for -P: \`"$CHAIN"\'.;; esac $IPCHAINS $COMMAND $CHAIN $TARGET $OPTIONS else # If they used -V, and not -W, then try to figure out interface # name. ALWAYS warn about difference. if [ -n "$VIA_ADDR" ] then if [ -n "$INTERFACE" ] then echo Warning: \`-V $VIA_ADDR\' option ignored\; using \`-W $INTERFACE\' only. else INTERFACE=`ifconfig | awk -v ADDR=$VIA_ADDR '/^[a-z0-9A-Z]/ { IFNAME=$1 } $0 ~ "^[^A-Za-z0-9:]*inet addr:" ADDR { print IFNAME}'` if [ -z "$INTERFACE" ] then echo Can\'t handle -V option: can\'t find interface name for the address \`$VIA_ADDR\'. 1>&2 echo Please replace the -V with the appropriate -W option. 1>&2 exit 1 fi echo Replacing \`-V $VIA_ADDR\' with \`-W $INTERFACE\'. OPTIONS="$OPTIONS -i $INTERFACE" fi fi # Insert, append or delete. case $COMMAND in # For Insert, get (and decrement) minimal mark #. -I*) MARK=$(set $($IPCHAINS -L $SPECIAL_CHAIN -v | head -3 | tail -1); echo $9) $IPCHAINS -R $SPECIAL_CHAIN 1 -m $(($MARK - 1)) MARK="-m $MARK" ;; # For Append, get (and increment) maximum mark #. -A) MARK=$(set $($IPCHAINS -L $SPECIAL_CHAIN -v | head -4 | tail -1); echo $9) $IPCHAINS -R $SPECIAL_CHAIN 2 -m $(($MARK + 1)) MARK="-m $MARK" ;; esac # Only care about TCP SYN if -p TCP not specified. if [ -n "$TCPSYN" ] then case "$PROTOCOL" in *[Tt][Cc][Pp]) OPTIONS="$OPTIONS $PROTOCOL $TCPSYN" TCPSYN="" ;; esac else OPTIONS="$OPTIONS $PROTOCOL" fi # Mangle source port and dest port args. if [ -z "$SRC_PORTS" ]; then SRC_PORTS="X"; fi if [ -z "$DST_PORTS" ]; then DST_PORTS="X"; fi [ -n "$TARGET" ] && TARGET="-j $TARGET" for SRC in $SRC_PORTS do if [ $SRC = "X" ]; then SRC=""; fi for DST in $DST_PORTS do if [ $DST = "X" ]; then DST=""; fi if [ -n "$TCPSYN" ] then $IPCHAINS $COMMAND $CHAIN $SRC_OPTIONS $SRC $DST_OPTIONS $DST $OPTIONS -p ! tcp $TARGET $MARK || barf "ipchains failed!" $IPCHAINS $COMMAND $CHAIN $SRC_OPTIONS $SRC $DST_OPTIONS $DST $OPTIONS -p tcp $TCPSYN $TARGET $MARK || barf "ipchains failed!" else $IPCHAINS $COMMAND $CHAIN $SRC_OPTIONS $SRC $DST_OPTIONS $DST $OPTIONS $TARGET $MARK || barf "ipchains failed!" fi done done fi fi mrtg-2.17.10/contrib/atmmaker/0000755000175300017510000000000013057016061015106 5ustar oetikeroepmrtg-2.17.10/contrib/atmmaker/atmmaker0000644000175300017510000003176613057016061016647 0ustar oetikeroep#!/opt/gnu/bin/perl # -*- mode: Perl -*- ################################################################## # Config file creator ################################################################## # Cloned form cfgmaker Mark Trettin # Created by Tobias Oetiker # this produces a config file for one router, by bulling info # off the router via snmp ################################################################# # # Distributed under the GNU copyleft # # $Id: atmmaker,v 1.1.1.1 2002/02/26 10:16:31 oetiker Exp $ # use SNMP_Session; use BER; use Socket; use strict; %snmpget::OIDS = ( 'sysDescr' => '1.3.6.1.2.1.1.1.0', 'sysContact' => '1.3.6.1.2.1.1.4.0', 'sysName' => '1.3.6.1.2.1.1.5.0', 'sysLocation' => '1.3.6.1.2.1.1.6.0', 'sysUptime' => '1.3.6.1.2.1.1.3.0', 'ifNumber' => '1.3.6.1.2.1.2.1.0', ################################### # add the ifNumber .... 'ifDescr' => '1.3.6.1.2.1.2.2.1.2', 'ifType' => '1.3.6.1.2.1.2.2.1.3', 'ifIndex' => '1.3.6.1.2.1.2.2.1.1', 'ifSpeed' => '1.3.6.1.2.1.2.2.1.5', 'ifOperStatus' => '1.3.6.1.2.1.2.2.1.8', 'ifAdminStatus' => '1.3.6.1.2.1.2.2.1.7', # up 1, down 2, testing 3 'ipAdEntAddr' => '1.3.6.1.2.1.4.20.1.1', 'ipAdEntIfIndex' => '1.3.6.1.2.1.4.20.1.2', 'sysObjectID' => '1.3.6.1.2.1.1.2.0', 'CiscolocIfDescr' => '1.3.6.1.4.1.9.2.2.1.1.28', # asx port group info 'asxPortAdmnStat' => '1.3.6.1.4.1.326.2.2.2.1.2.2.1.2', 'asxPortOperStat' => '1.3.6.1.4.1.326.2.2.2.1.2.2.1.3', 'asxPortRemoteIpAddress'=> '1.3.6.1.4.1.326.2.2.2.1.2.2.1.6', 'asxPortILMIRemoteIpAddress' => '1.3.6.1.4.1.326.2.2.2.1.2.2.1.22', 'asxPortMaxBandwidthIn' => '1.3.6.1.4.1.326.2.2.2.1.2.2.1.9', 'asxhwPortName' => '1.3.6.1.4.1.326.2.2.1.1.2.3.1.13', 'asxPortNumber' => '1.3.6.1.4.1.326.2.2.2.1.2.2.1.1', ); sub main { my(%ifType_d)=('1'=>'Other', '2'=>'regular1822', '3'=>'hdh1822', '4'=>'ddnX25', '5'=>'rfc877x25', '6'=>'ethernetCsmacd', '7'=>'iso88023Csmacd', '8'=>'iso88024TokenBus', '9'=>'iso88025TokenRing', '10'=>'iso88026Man', '11'=>'starLan', '12'=>'proteon10Mbit', '13'=>'proteon80Mbit', '14'=>'hyperchannel', '15'=>'fddi', '16'=>'lapb', '17'=>'sdlc', '18'=>'ds1', '19'=>'e1', '20'=>'basicISDN', '21'=>'primaryISDN', '22'=>'propPointToPointSerial', '23'=>'ppp', '24'=>'softwareLoopback', '25'=>'eon', '26'=>'ethernet-3Mbit', '27'=>'nsip', '28'=>'slip', '29'=>'ultra', '30'=>'ds3', '31'=>'sip', '32'=>'frame-relay', '33'=>'rs232', '34'=>'para', '35'=>'arcnet', '36'=>'arcnetPlus', '37'=>'atm', '38'=>'miox25', '39'=>'sonet', '40'=>'x25ple', '41'=>'iso88022llc', '42'=>'localTalk', '43'=>'smdsDxi', '44'=>'frameRelayService', '45'=>'v35', '46'=>'hssi', '47'=>'hippi', '48'=>'modem', '49'=>'aal5', '50'=>'sonetPath', '51'=>'sonetVT', '52'=>'smdsIcip', '53'=>'propVirtual', '54'=>'propMultiplexor', '55'=>'100BaseVG' ); my($community,$router) = split /\@/, $ARGV[0]; die <>mrtg.cfg USAGE my($sysDescr,$sysContact,$sysName,$sysLocation,$ifNumber,$sysObjectID) = snmpget($router,$community, 'sysDescr','sysContact','sysName', 'sysLocation', 'ifNumber', 'sysObjectID'); $sysDescr =~ s/\r/
      /g; # Change returns to
      my($cisco_router_sysid) = '1\.3\.6\.1\.4\.1\.9'; my($ciscobox) = ($sysObjectID =~ /^$cisco_router_sysid/); my($foreasx_switch_sysid) = '1\.3\.6\.1\.4\.1\.326'; my($foreasx) = ($sysObjectID =~ /^$foreasx_switch_sysid/); print <Traffic Analysis for $sportname{$index} ${c} ${c} ${c} ${c} ${c} ECHO print < ECHO print < ECHO print < ${c} ${c}
      System:$sysName in $sysLocation
      Maintainer:$sysContact
      Interface:$sportname{$index} ($index)
      Remote IP:$iphost{$index} ($ipaddr{$index})
      Remote ILMI IP:$ipilhost{$index} ($ipiladdr{$index})
      Max Speed:$speed_str (Sonet)
      ${c} #--------------------------------------------------------------- ECHO } } else { my(%sifdesc,%siftype,%sifspeed,%sifadminstatus,%sifoperstatus,%sciscodescr); while (scalar @ifindex) { # as these arrays get filled from the bottom, # we need to empty them from the botom as well ... # fifo $index = shift @ifindex; $sifdesc{$index} = shift @ifdescr; $siftype{$index} = shift @iftype; print STDERR $siftype{$index}; $sifspeed{$index} = shift @ifspeed; $sifadminstatus{$index} = shift @ifadminstatus; $sifoperstatus{$index} = shift @ifoperstatus; # especially since cisco does not return a if # descr for each interface it has ... $sciscodescr{$index} = "
      " . (shift @ciscodescr) if @ciscodescr; } foreach $index (keys %sifdesc) { my $c; my $speed = int($sifspeed{$index} / 8); # bits to byte my $speed_str=&fmi($speed); my $name="$router.$index"; if (($sifadminstatus{$index} != 1) || ($siftype{$index} == 24) || ($speed == 0 ) || ($speed > 400 * 10**6) #speeds of 400 MByte/s are not realistic || ($sifoperstatus{$index} == 3)) { print <Traffic Analysis for $sifdesc{$index} ${c} $sciscodescr{$index} ${c} ${c} ${c} ${c} ${c} ${c} ${c} ${c}
      System:$sysName in $sysLocation
      Maintainer:$sysContact
      Interface:$sifdesc{$index} ($index)
      IP:$iphost{$index} ($ipaddr{$index})
      Max Speed:$speed_str ($ifType_d{$siftype{$index}})
      ${c} #--------------------------------------------------------------- ECHO } } } main; exit(0); sub snmpget{ my($host,$community,@vars) = @_; my(@enoid, $var,$response, $bindings, $binding, $value, $inoid,$outoid, $upoid,$oid,@retvals); foreach $var (@vars) { die "Unknown SNMP var $var\n" unless $snmpget::OIDS{$var}; push @enoid, encode_oid((split /\./, $snmpget::OIDS{$var})); } srand(); my $session = SNMP_Session->open ($host , $community, 161); if ($session->get_request_response(@enoid)) { $response = $session->pdu_buffer; ($bindings) = $session->decode_get_response ($response); $session->close (); while ($bindings) { ($binding,$bindings) = decode_sequence ($bindings); ($oid,$value) = decode_by_template ($binding, "%O%@"); my $tempo = pretty_print($value); $tempo=~s/\t/ /g; $tempo=~s/\n/ /g; $tempo=~s/^\s+//; $tempo=~s/\s+$//; push @retvals, $tempo; } return (@retvals); } else { die "No answer from $ARGV[0]. You may be using the wrong community\n"; } } sub snmpgettable{ my($host,$community,$var) = @_; my($next_oid,$enoid,$orig_oid, $response, $bindings, $binding, $value, $inoid,$outoid, $upoid,$oid,@table,$tempo); die "Unknown SNMP var $var\n" unless $snmpget::OIDS{$var}; $orig_oid = encode_oid(split /\./, $snmpget::OIDS{$var}); $enoid=$orig_oid; srand(); my $session = SNMP_Session->open ($host , $community, 161); for(;;) { if ($session->getnext_request_response(($enoid))) { $response = $session->pdu_buffer; ($bindings) = $session->decode_get_response ($response); ($binding,$bindings) = decode_sequence ($bindings); ($next_oid,$value) = decode_by_template ($binding, "%O%@"); # quit once we are outside the table last unless BER::encoded_oid_prefix_p($orig_oid,$next_oid); $tempo = pretty_print($value); #print "$var: '$tempo'\n"; $tempo=~s/\t/ /g; $tempo=~s/\n/ /g; $tempo=~s/^\s+//; $tempo=~s/\s+$//; push @table, $tempo; } else { die "No answer from $ARGV[0]\n"; } $enoid=$next_oid; } $session->close (); return (@table); } sub fmi { my($number) = $_[0]; my(@short); @short = ("Bytes/s","kBytes/s","MBytes/s","GBytes/s","TBytes/s"); my $digits=length("".$number); my $divm=0; while ($digits-$divm*3 > 4) { $divm++; } my $divnum = $number/10**($divm*3); return sprintf("%1.1f %s",$divnum,$short[$divm]); } mrtg-2.17.10/contrib/mrtgindex.cgi/0000755000175300017510000000000014171553254016057 5ustar oetikeroepmrtg-2.17.10/contrib/mrtgindex.cgi/mrtgindx.cgi0000755000175300017510000001424014171553254020403 0ustar oetikeroep#!/usr/local/bin/perl # mrtgindex.cgi v 1.1 # (c) 1997, Mick Ghazey mick@lowdown.com # Thanks to Dave Rand, Peter W. Osel and Tobias Oetiker. # Why CGI? # Mrtgindx.cgi has features that only CGI can provide. # Runtime index: # The index page is built every time the page is requested. # Changes to config files are visible on the next update. # Clickable graphs: # Each graph is a clickable hyperlink to more information. # Automatic updates: # The index page automatically updates every 5 minutes. # Modify $interval to adjust this period. # Timely updates: # Mrtgindx.cgi predicts when to update based on when the # current graphs were completed. # Updates occurs shortly after the graphs are completed # regardless of when the page was initially requested. # Modify $guardband to adjust this period. # If the guardband is too small you run the risk of attempting # an update while a graph is under construction. # Predictable graph order: # Graphs appear in the same order as Titles in the config files. # If there are multiple config files graphs from the first config # file appear before those from the second, etc. # Customizable graph order: # If you want your index ordered differently than your # config files you can use a dummy config file. Mrtgindex.cgi is # only interested in "Title" statements. You could, for example, # have different dummy config files for different arangements # of graphs. # Web based graph order selection: # Click Top, Up, Down, or Bot to change the position of a graph. # Multiple config files: # Mrtgindex.cgi supports multiple config files. Some users # run mrtg with more than one config file. The reason may be # because certain events are run on a different schedules, # 5 and 10 minute intervals for example. # Or perhaps multiple instances of mrtg are run # to assure completion within a 5 minute interval. # Ping-probes have longer run times than measuring traffic # on local routers, for example. However, CPU load is similar. # Modify the @config_files array below to suit your environment. # Runs fast: # Mrtgindx.cgi is fast because it doesn't create graph files or # maintain log files. In addition, web based graph order changes # benefit from browser cacheing of graphs. # Index.cgi: # You might want to rename this file "index.cgi". Then it # will load automatically when when the directory is browsed - # much as index.html loads automatically. You might have to # modify "DirectoryIndex" in srm.conf if you're using Apache # to allow CGI programs to be index files. # CGI.pm required: # Mrtgindex.cgi requires CGI.pm by Lincoln Stein # http://www-genome.wi.mit.edu/ftp/pub/software/WWW/cgi_docs.html #------------------------------------------------------- # Modify this statement to match your configuration @config_files = ('mrtg.cfg'); # Single config file #@config_files = ('mrtg.cfg', 'mrtg-ping.cfg'); # Two config files #@config_files = ('mrtg.cfg', 'yahoo.ping', 'netscape.ping', 'msn..ping', # 'att.ping'); # anal retentive #------------------------------------------------------- require 'stat.pl'; use CGI ':all'; use CGI::Carp qw(fatalsToBrowser); #use diagnostics; $gifdone = 0; # Scan for newest graph and save info for later while(@config_files > 0){ open(In, $cfg = shift @config_files) || die "Can't open $cfg. Check \@config_files array.\n"; while(){ chdir($1) if /^WorkDir:\s*(.+)$/; next unless /^Title\[(.*)\]:\s*(.+)$/; # Look for a title keyword $router = lc $1; Stat("$router-day.png"); @$router = ($st_mtime, $2); # Save the mod date and title push @routers, $router; # Remember the router name so we can find above info $gifdone = $st_mtime if $st_mtime > $gifdone; # Find the newest file } close In; } # Time the next update to occur a little while after the next interval completes $interval = 300; # 5 min update interval $guardband = 15; # updates occur this many seconds after predicted gif completion $refresh = $interval + $guardband + $gifdone - time; # predict how long until next update $refresh = $interval if $refresh <= $guardband; $expires = gmtime (time + $interval * 2 + $guardband); print header, start_html(-TITLE=>'Daily Stats', -BGCOLOR=>'#e6e6e6'), "\n", "\n", "\n", table({-width=>"100\%"}, TR( #------------------------------------------------------- # Uncomment the following line if you have Count.cgi installed. # td({-align=>left, width=>"25\%"}, img({-src=>"/cgi-bin/Count.cgi?display=clock"})), #------------------------------------------------------- td("Click graph for more info"))); @router_order = (0..$#routers); @router_order = split /:/, param('ord') if defined param('ord'); $selfurl = url; $selfurl =~ s/\?.*//; # Remove arguments for $index (0..$#routers){ @spliced = @router_order; $router_num = splice @spliced, $index, 1; # Router removed $router = $routers[$router_num]; $time = localtime $$router[0]; # $st_mtime saved in above loop ($time) = $time =~ /(\d+:\d+:\d+)/; # Just the time print hr, "\n"; print a({-name=>$index}); # Print re-ordering links top, bot, up, dn $mv_dn = $mv_up = ""; $" = ':'; if($index > 0){ @top = ($router_num, @spliced); @up = @spliced; $indxup = $index - 1; splice @up, $indxup, 0, $router_num; $mv_up = sprintf "%s %s ", a({-href=>"$selfurl?ord=@top#0"}, "Top"), # move to top a({-href=>"$selfurl?ord=@up#$indxup"}, "Up"); # move up } if($index < $#routers){ @bot = (@spliced, $router_num); @down = @spliced; $indxdn = $index + 1; splice @down, $indxdn, 0, $router_num; $indxbot = @routers - 3; while($indxbot < 0){$indxbot += 1} $mv_dn = sprintf "%s %s ", a({-href=>"$selfurl?ord=@down#$indxdn"}, "Down"), # move down a({-href=>"$selfurl?ord=@bot#$indxbot"}, "Bot"); # move to bottom } undef $"; print table({-width=>"100\%"}, TR(td({-align=>"left",-width=>"20\%"}, "$mv_up $mv_dn"), td({-align=>"left"}, b($$router[1]), " $time"))); print a({-href=>"$router.html"}, img{-src=>"$router-day.png"}); } print "\n",hr,"Direct questions and feedback to Mick Ghazey: ", a({-href=>"mailto:mick\@lowdown.com"}, "mick\@lowdown.com"), end_html; mrtg-2.17.10/contrib/mrtgindex.cgi/README0000644000175300017510000000120713057016061016727 0ustar oetikeroepDate: Fri, 14 Mar 1997 14:40:56 +0000 From: Mick Ghazey My program, mrtgindex.cgi, is similar to indexmaker. There are some signficant differences however. Mrtgindex.cgi graphs update every 5 minutes. Mrtgindex.cgi *graphs* are clickable. Indexmaker's *text* is clickable. Mrtgindex.cgi supports multiple config files. Mrtgindex.cgi graphs are in the same order as targets in config files. Indexmaker graphs are ordered alphabetically by title. Perhaps mrtgindex.cgi will run on more servers because it doesn't require SSI. OTOH, it requires CGI.pm. Between the two we should have a program that works on all servers. :=) mrtg-2.17.10/contrib/get-active/0000755000175300017510000000000013057016061015335 5ustar oetikeroepmrtg-2.17.10/contrib/get-active/get-active.pl0000644000175300017510000001277613057016061017737 0ustar oetikeroep#!/usr/local/bin/perl # # Author: Russ Wright, Lawrence Berkeley National Laboratory December 1997 # # This will look at the $trafficDir directory for MRTG generated HTML # files, parse them and generate a listing of the most active interfaces # in a file called "active.htlm" in the same directory # # modify this if you wish as long as the above credit is not removed # # The only weird thing I do is to skip tunnel interfaces (see code below) # # TWO VARIABLES YOU MUST CHANGE # ##$trafficDir="/usr/ns-home/htdocs/traffic"; # # I put it in a file and include it because I use it in other scripts # if you don't - comment this out and uncomment the above line require "trafficdir.include"; # CHANGE THIS to your organization name $orgName="LBNL"; $outFile = "$trafficDir/active.html"; # The following may be changed and I admit that it isn't perfect how I decide # to highlight stuff. # # if over this value, will bold entry $highlightThresh = 15; # if max is over this value, will bold entry $highlightMaxThresh = 40; # Refresh interval (minutes) for HTML doc $refreshInt=10; # $refreshSeconds=60*$refreshInt; # # Max % to look at (if the Max is lower then we do not include in the list) $maxThresh = 5; $theDate=`date +"%m/%d/%y %H:%M"`; open(LS, "ls $trafficDir/*.[0-9]*.html|") || die "Couldn't list directory"; while () { chop; $theFile = $_; open(IN, "$theFile") || die "Couldn't open $theFile\n"; $i=0; while () { if (/Traffic Analysis for .*[0-9]
      (.*)<\/H1> /) { if ($1 =~ /tunnel/i) { # skip tunnels last; } $desc{$theFile} = $1; } if (/\(([0-9.]*\%)\)/) { $theList{$theFile}[$i++] = $1; } } close(IN); } close(LS); # # # the array contains all the percentages: the following 6 for # daily, weekly, monthly, yearly # # 0 Max In # 1 Avg In # 2 Cur In # 3 Max Out # 4 Avg Out # 5 Cur Out # # open(OUT, ">$outFile") || die "Couldn't create $outFile"; &PrintHead; foreach $key (keys %theList) { # get sum of both max in and out $sumInOut = $theList{$key}[0] + $theList{$key}[4]; if ( ($sumInOut > $maxThresh) || ($curIn > $highlightThresh) || ($curOut > $highlightThresh) || ($avgIn > $highlightThresh) || ($avgOut > $highlightThresh) ) { $printList{$key} = $sumInOut; } } foreach $key (sort by_percent (keys %printList)) { $theRouter = $key; $theRouter =~ s/.*\///; $theRouter =~ s/\.html//; $theFile = $key; $theFile =~ s/.*traffic\///; $maxIn= $theList{$key}[0]; $avgIn= $theList{$key}[1]; $curIn= $theList{$key}[2]; $maxOut= $theList{$key}[3]; $avgOut= $theList{$key}[4]; $curOut= $theList{$key}[5]; if ($maxIn > $highlightMaxThresh) { $maxIn= "$maxIn"; } if ($maxOut > $highlightMaxThresh) { $maxOut= "$maxOut"; } if ($curOut > $highlightThresh) { $curOut= "$curOut"; } if ($curIn > $highlightThresh) { $curIn= "$curIn"; } if ($avgIn > $highlightThresh) { $avgIn= "$avgIn"; } if ($avgOut > $highlightThresh) { $avgOut= "$avgOut"; } printf(OUT "< TD>
      $curIn
      \n"); } &PrintTail; close(OUT); sub by_percent { $printList{$b} <=> $printList{$a}; } sub PrintTail { print OUT < EOF } sub PrintHead { $expTime=&expistr; print OUT < $orgName Most Active Subnets

      LBNL Most Active Subnets as of $theDate

      The following are sorted by the sum of the daily maximum input and daily ma ximum output interface octets. This table is updated every $refreshInt minutes and will automatically be updated if you are using Netscape.

      Note: Tunnels are not included in this list

      Values are in RED if the current or average is above $highlightThresh or if the maximum value is over $highlightMaxThresh

      $maxIn

      $maxOut< /CENTER>

      $avgIn
      $avgOut
      $curOut
      $theRouter - $desc{$key}
      EOF } sub expistr { my ($time) = time+$refreshInt*60+5; my ($wday) = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat')[(gmtime($time))[6]]; my ($month) = ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep', 'Oct','Nov','Dec')[(gmtime($time))[4]]; my ($mday,$year,$hour,$min,$sec) = (gmtime($time))[3,5,2,1,0]; if ($mday<10) {$mday = "0$mday"}; if ($hour<10) {$hour = "0$hour"}; if ($min<10) {$min = "0$min";} if ($sec<10) {$sec = "0$sec";} return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; } mrtg-2.17.10/contrib/get-active/README0000644000175300017510000000100013057016061016204 0ustar oetikeroepFrom leewm@hpsgmx18.sgp.hp.com Mon Nov 3 09:19:59 1997 Date: Sat, 01 Nov 1997 23:03:45 SGP From: Wee-Meng LEE To: oetiker@ee.ethz.ch Subject: get-active.pl Hi Tobi, A collegue and I did some improvements in the get-active.pl script written by Russ Wright in the contrib directory. get-active2.pl does a summary page of all the router interfaces being monitored and it proved to be very useful. I'm not able to contact Russ but feel free to pass the code around. Rgds, weemeng mrtg-2.17.10/contrib/get-active/get-active2.pl0000644000175300017510000001654513057016061020017 0ustar oetikeroep#!/usr/bin/perl # # Author: Russ Wright, Lawrence Berkeley National Laboratory December 1997 # Local modifications by Wee-Meng Lee HP Singapore (colour/lynx) # and Mark Mushkin HP Santa Clara (avg/max/min that suit our needs) # Last Update on Oct 14, 1997 # # This will look at the $trafficDir directory for MRTG generated HTML # files, parse them and generate a listing of the most active interfaces # in a file called "active.htlm" in the same directory # # modify this if you wish as long as the above credit is not removed # # The only weird thing I do is to skip tunnel interfaces (see code below) # # TWO VARIABLES YOU MUST CHANGE # $trafficDir="/usr/local/httpd/htdocs"; # # I put it in a file and include it because I use it in other scripts # if you don't - comment this out and uncomment the above line #require "trafficdir.include"; # CHANGE THIS to your organization name $orgName="HP Singapore - IT Site Infrastructure"; $outFile = "$trafficDir/active.html"; # The following may be changed and I admit that it isn't perfect how I decide # to highlight stuff. # #values over this will be displayed in the specified color # these are for the MAX values $maxAMBER = 70; $maxRED = 90; # these are for the Average and Current values $AMBER = 30; $RED = 60; #Defining the colors $REDcolor="#ff0000"; $AMBERcolor="#ffff00"; $GREENcolor="#00ff00"; # Refresh interval (minutes) for HTML doc $refreshInt=10; # $refreshSeconds=60*$refreshInt; # # Max % to look at (if the Max is lower then we do not include in the list) #$maxThresh = 5; $maxThresh = 0; $theDate=`date +"%m/%d/%y %H:%M"`; open(LS, "ls $trafficDir/*.[0-9]*.html|") || die "Couldn't list directory"; while () { chop; $theFile = $_; open(IN, "$theFile") || die "Couldn't open $theFile\n"; $i=0; while () { if (/Traffic Analysis for .*[0-9]
      (.*)<\/H1>
      In Max % Out Max % In Avg % Out Avg % In Current % Out Current % Interface
      /) { if ($1 =~ /tunnel/i) { # skip tunnels last; } $desc{$theFile} = $1; } if (/\(([0-9.]*\%)\)/) { $theList{$theFile}[$i++] = $1; } } close(IN); } close(LS); # # # the array contains all the percentages: the following 6 for # daily, weekly, monthly, yearly # # 0 Max In # 1 Avg In # 2 Cur In # 3 Max Out # 4 Avg Out # 5 Cur Out # # open(OUT, ">$outFile") || die "Couldn't create $outFile"; &PrintHead; foreach $key (keys %theList) { # get sum of both max in and out # $sumInOut = $theList{$key}[0] + $theList{$key}[4]; # use for max $sumInOut = $theList{$key}[1] + $theList{$key}[4]; # use for avg if ( ($sumInOut > $maxThresh) || ($curIn > $highlightThresh) || ($curOut > $highlightThresh) || ($avgIn > $highlightThresh) || ($avgOut > $highlightThresh) ) { $printList{$key} = $sumInOut; } } foreach $key (sort by_percent (keys %printList)) { $theRouter = $key; $theRouter =~ s/.*\///; $theRouter =~ s/\.html//; $theFile = $key; $theFile =~ s/.*traffic\///; $maxIn= $theList{$key}[0]; $avgIn= $theList{$key}[1]; $curIn= $theList{$key}[2]; $maxOut= $theList{$key}[3]; $avgOut= $theList{$key}[4]; $curOut= $theList{$key}[5]; printf(OUT ""); if ($maxIn > $maxRED) { printf(OUT ""); } elsif ($maxIn > $maxAMBER) { printf(OUT ""); } else { printf(OUT ""); } printf(OUT " "); if ($maxOut > $maxRED) { printf(OUT ""); } elsif ($maxOut > $maxAMBER) { printf(OUT ""); } else { printf(OUT ""); } printf(OUT " "); if ($avgIn > $RED) { printf(OUT ""); } elsif ($avgIn > $AMBER) { printf(OUT ""); } else { printf(OUT ""); } printf(OUT " "); if ($avgOut > $RED) { printf(OUT ""); } elsif ($avgOut > $AMBER) { printf(OUT ""); } else { printf(OUT ""); } printf(OUT " "); if ($curIn > $RED) { printf(OUT ""); } elsif ($curIn > $AMBER) { printf(OUT ""); } else { printf(OUT ""); } printf(OUT " "); if ($curOut > $RED) { printf(OUT ""); } elsif ($curOut > $AMBER) { printf(OUT ""); } else { printf(OUT ""); } printf(OUT " "); printf(OUT "

      \n"); } &PrintTail; close(OUT); sub by_percent { $printList{$b} <=> $printList{$a}; } sub PrintTail { print OUT < EOF } sub PrintHead { $expTime=&expistr; print OUT < $orgName Most Active Interface

      Most Active Interfaces as of $theDate

      The following are sorted by the sum of the daily average input and daily average output (In Avg% + Out Avg%) interface octets. This table is updated every $refreshInt minutes and will automatically be updated if you are using Netscape.

      Value ranges:

      MAX Values are: RED if \> $maxRED , and YELLOW if \> $maxAMBER

      Average & Current Values are: RED if \> $RED , and YELLOW if \> $AMBER

      $maxIn
      $maxIn
      $maxIn
      $maxOut
      $maxOut
      $maxOut
      $avgIn
      $avgIn
      $avgIn
      $avgOut
      $avgOut
      $avgOut
      $curIn
      $curIn
      $curIn
      $curOut
      $curOut
      $curOut
      $theRouter

      EOF } sub expistr { my ($time) = time+$refreshInt*60+5; my ($wday) = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat')[(gmtime($time))[6]]; my ($month) = ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep', 'Oct','Nov','Dec')[(gmtime($time))[4]]; my ($mday,$year,$hour,$min,$sec) = (gmtime($time))[3,5,2,1,0]; if ($mday<10) {$mday = "0$mday"}; if ($hour<10) {$hour = "0$hour"}; if ($min<10) {$min = "0$min";} if ($sec<10) {$sec = "0$sec";} return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; } mrtg-2.17.10/contrib/TCH/0000755000175300017510000000000013057016061013723 5ustar oetikeroepmrtg-2.17.10/contrib/TCH/hiperdsp.pl0000644000175300017510000000437413057016061016106 0ustar oetikeroep#!c:\perl\bin # hiperdsp.pl # # # Created by Eric Billeter # returns: # Modems in use (value1) # Chassis capacity (value2) # Capacity is total of Idle, Connected, and Ringing use SNMP_Session; use BER; use Socket; use strict; %snmpget::OIDS = ( 'value1' => '1.3.6.1.4.1.429.1.27.2.1.26', ); my($community,$router) = split /\@/, $ARGV[0]; die <open ($host , $community, 161); for(;;) { if ($session->getnext_request_response(($enoid))) { $response = $session->pdu_buffer; ($bindings) = $session->decode_get_response ($response); ($binding,$bindings) = decode_sequence ($bindings); ($next_oid,$value) = decode_by_template ($binding, "%O%@"); # quit once we are outside the table last unless BER::encoded_oid_prefix_p($orig_oid,$next_oid); my $bulkindex = 2; while( $bulkindex < "52" ){ $tempo = substr ($value,$bulkindex,1); $bulkindex=$bulkindex+2; if( ord($tempo) eq '5' or ord($tempo) eq '3' or ord($tempo) eq '22' ){$value1=$value1 + 1 ; } if( ord($tempo) eq '2' or ord($tempo) eq '5' or ord($tempo) eq '3' or ord($tempo) eq '22' ){$value2=$value2 + 1 ; } } push @table, $tempo; } else { die "No answer from $ARGV[0]\n"; } $enoid=$next_oid; } $session->close (); if( $value1 eq ''){$value1 = 0 }; if( $value2 eq ''){$value2 = 0 }; print "$value1\n"; print "$value2\n"; return (@table); } mrtg-2.17.10/contrib/TCH/dualpri.pl0000644000175300017510000000431313057016061015721 0ustar oetikeroep#!c:\perl\bin # dualpri.pl # # # Created by Eric Billeter # returns: # Modems in use (value1) # Chassis Capacity (value2) use SNMP_Session; use BER; use Socket; use strict; %snmpget::OIDS = ( 'value1' => '1.3.6.1.4.1.429.1.16.4.1.2', ); my($community,$router) = split /\@/, $ARGV[0]; die <open ($host , $community, 161); for(;;) { if ($session->getnext_request_response(($enoid))) { $response = $session->pdu_buffer; ($bindings) = $session->decode_get_response ($response); ($binding,$bindings) = decode_sequence ($bindings); ($next_oid,$value) = decode_by_template ($binding, "%O%@"); # quit once we are outside the table last unless BER::encoded_oid_prefix_p($orig_oid,$next_oid); my $bulkindex = 3; while( $bulkindex < "96" ){ $tempo = substr ($value,$bulkindex,1); $bulkindex=$bulkindex+4; if( ord($tempo) eq '5' or ord($tempo) eq '3' or ord($tempo) eq '22' ){$value1=$value1 + 1 ; } if( ord($tempo) eq '2' or ord($tempo) eq '5' or ord($tempo) eq '3' or ord($tempo) eq '22' ){$value2=$value2 + 1 ; } } push @table, $tempo; } else { die "No answer from $ARGV[0]\n"; } $enoid=$next_oid; } $session->close (); if( $value1 eq ''){$value1 = 0 }; if( $value2 eq ''){$value2 = 0 }; print "$value1\n"; print "$value2\n"; return (@table); } mrtg-2.17.10/contrib/TCH/dualt1.pl0000644000175300017510000000430513057016061015454 0ustar oetikeroep#!c:\perl\bin # dualt1.pl # # # Created by Eric Billeter # returns: # Modems in use (value1) # Chassis capacity (value2) use SNMP_Session; use BER; use Socket; use strict; %snmpget::OIDS = ( 'value1' => '1.3.6.1.4.1.429.1.5.4.1.3', ); my($community,$router) = split /\@/, $ARGV[0]; die <open ($host , $community, 161); for(;;) { if ($session->getnext_request_response(($enoid))) { $response = $session->pdu_buffer; ($bindings) = $session->decode_get_response ($response); ($binding,$bindings) = decode_sequence ($bindings); ($next_oid,$value) = decode_by_template ($binding, "%O%@"); # quit once we are outside the table last unless BER::encoded_oid_prefix_p($orig_oid,$next_oid); my $bulkindex = 2; while( $bulkindex < "50" ){ $tempo = substr ($value,$bulkindex,1); $bulkindex=$bulkindex+2; if( ord($tempo) eq '5' or ord($tempo) eq '3' or ord($tempo) eq '22' ){$value1=$value1 + 1 ; } if( ord($tempo) eq '2' or ord($tempo) eq '5' or ord($tempo) eq '3' or ord($tempo) eq '22' ){$value2=$value2 + 1 ; } } push @table, $tempo; } else { die "No answer from $ARGV[0]\n"; } $enoid=$next_oid; } $session->close (); if( $value1 eq ''){$value1 = 0 }; if( $value2 eq ''){$value2 = 0 }; print "$value1\n"; print "$value2\n"; return (@table); } mrtg-2.17.10/contrib/TCH/README0000644000175300017510000000076613057016061014614 0ustar oetikeroepDate: Tue, 16 Feb 1999 16:44:12 -0700 From: Eric Billeter Here are some scripts i modified to monitor the modem utilization of my USR Total control racks. They work great even though I am not a programmer. If there is anything you see that would work more efficiently it would be appreciated. The files are as follows dualt1.pl - TCH with dual t1 card. dualpri.pl - TCH with dual pri card. hiperdsp.pl - TCH with hiperdsp cards. mrtg-cfg.txt - snippet of cfg file mrtg-2.17.10/contrib/TCH/mrtg.cfg0000644000175300017510000000457713057016061015372 0ustar oetikeroepworkdir: c:\mywebfiles Unscaled[_]:ymwd #..................................................................... Target[tch1]: `perl c:\perl\lib\dualpri.pl public@127.1.1.1` MaxBytes[tch1]: 46 Unscaled[tch1]:ymwd Title[tch1]: Total Control Hub #1 PageTop[tch1]:

      TCH1 Modem Utilization

      YLegend[tch1]:Modem Capacity Options[tch1]:gauge,growright ShortLegend[tch1]:Modems Legend1[tch1]:  Utilization   Legend2[tch1]:  Capacity   Legend3[tch1]:  Connections   Legend4[tch1]:  Capacity   LegendI[tch1]:  Utilization   LegendO[tch1]:  Capacity   #..................................................................... Target[tch2]: `perl c:\perl\lib\dualt1.pl public@127.1.1.2` MaxBytes[tch2]: 46 Title[tch2]: Total Control Hub #2 PageTop[tch2]:

      TCH2 Modem Utilization

      YLegend[tch2]:Modem Capacity Options[tch2]:gauge,growright ShortLegend[tch2]:Modems Legend1[tch2]:  Utilization   Legend2[tch2]:  Capacity   Legend3[tch2]:  Connections   Legend4[tch2]:  Capacity   LegendI[tch2]:  Utilization   LegendO[tch2]:  Capacity   #..................................................................... Target[tch3]: `perl c:\perl\lib\hiperdsp.pl public@127.1.1.3` MaxBytes[tch3]: 46 Title[tch3]: Total Control Hub #3 PageTop[tch3]:

      TCH3 Modem Utilization

      YLegend[tch3]:Modem Capacity Options[tch3]:gauge,growright ShortLegend[tch3]:Modems Legend1[tch3]:  Utilization   Legend2[tch3]:  Capacity   Legend3[tch3]:  Connections   Legend4[tch3]:  Capacity   LegendI[tch3]:  Utilization   LegendO[tch3]:  Capacity   #..................................................................... Target[tchtotal]: `perl c:\perl\lib\dualpri.pl public@127.1.1.1`+`perl c:\perl\lib\dualt1.pl public@127.1.1.2`+`perl c:\perl\lib\hiperdsp.pl public@127.1.1.3` MaxBytes[tchtotal]: 138 Title[tchtotal]: Total Control Hub Totals PageTop[tchtotal]:

      Total Modem Utilization

      YLegend[tchtotal]:Modem Capacity Options[tchtotal]:gauge,growright ShortLegend[tchtotal]:Modems Legend1[tchtotal]:  Utilization   Legend2[tchtotal]:  Capacity   Legend3[tchtotal]:  Connections   Legend4[tchtotal]:  Capacity   LegendI[tchtotal]:  Utilization   LegendO[tchtotal]:  Capacity   mrtg-2.17.10/contrib/IxDisk/0000755000175300017510000000000013057016061014500 5ustar oetikeroepmrtg-2.17.10/contrib/IxDisk/ixdisk.pl0000755000175300017510000000134113057016061016332 0ustar oetikeroep#!/usr/bin/perl # # Miroslaw M. Maczka: Miroslaw_Maczka@hotmail.com, mmm@bze.com.pl # Date 2000-1-6 # open(FI,"/usr/informix/bin/tbstat -p |") or die ""; while(){ #if(/RSAM Version 5.04.UC3 -- On-Line -- Up 1 days 21:56:47 -- 10960 Kbytes/){ if(/.+Version\s+(.+) --\s+(.+)\s+-- Up\s+(.+)\s+--.*/){ #print "[$1|$2|$3]\n"; $db="$2 $1"; $uptime=$3; } if(/dskreads pagreads bufreads %cached dskwrits pagwrits bufwrits \%cached/){ $_=; ($dskreads,$pagreads,$bufreads,$cached1,$dskwrits,$pagwrits,$bufwrits,$cached2)=split(); #print "[$dskreads,$pagreads,$bufreads,$cached1,$dskwrits,$pagwrits,$bufwrits,$cached2]\n"; # #$uname = `/bin/uname -n`; print "$dskreads\n$dskwrits\n$uptime\n$db"; # }#if }#while close(FI); #-=EOF=- mrtg-2.17.10/contrib/IxDisk/ixdisk.cfg0000755000175300017510000000065013057016061016460 0ustar oetikeroepIconDir: /MRTG/mrtgicons/ WorkDir: /opt/hppd/etc/NCSAhttpd/MRTG/ixdisk Target[ix]: `/opt/MRTG/run/IxDisk/ixdisk.pl` Title[ix]: Informix reads and writes from disk PageTop[ix]:

      Informix reads and writes from disk

      MaxBytes1[ix]: 2000000000 MaxBytes2[ix]: 2000000000 LegendI[ix]: reads  LegendO[ix]: writes  Legend1[ix]: reads  Legend2[ix]: writes  YLegend[ix]: Informix ShortLegend[ix]: # mrtg-2.17.10/contrib/IxDisk/README0000644000175300017510000000026013057016061015356 0ustar oetikeroepFrom: Miroslaw.Maczka@bze.com.pl This is my script for monitoring database activity, database is Informix version 5, system is Hewlett-Packard unix (hp-ux), versions 9,10,11. mrtg-2.17.10/contrib/jm/0000755000175300017510000000000013057016061013713 5ustar oetikeroepmrtg-2.17.10/contrib/jm/finger-mrtg.pl0000755000175300017510000000177013057016061016501 0ustar oetikeroep#!/usr/bin/perl5 # # finger-mrtg.pl - # # executes "finger @hostname" (hostname is the argument passed into # the script) and counts how many logins there currently are on that # machine. # # if machine is 'localhost', we just execute 'finger' instead, w/ no # arguments. # # example Target line: # # Target[shellbox1]: `/path/to/finger-mrtg.pl shellbox1.mydomain.com` # # # -joey miller, inficad communications, llc. # if ( ! $ARGV[0] ) { exit; } # output: # # [user1.inficad.com] # Login Name Tty Idle Login Time Office Office Phone # username blah blah *pd 43 Feb 3 16:55 # hello lada lada pa 5:16 Feb 3 15:21 if ( $ARGV[0] =~ /localhost/ ) { open(FINGER, "/usr/bin/finger |") || exit; } else { open(FINGER, "/usr/bin/finger \@$ARGV[0] |") || exit; } while () { if ( /^\[.*\]/ ) { next; } if ( /^Login/ ) { next; } $count++; } print "$count\n"; print "$count\n"; print "0\n"; print "$ARGV[0]\n"; mrtg-2.17.10/contrib/jm/README0000644000175300017510000000061213057016061014572 0ustar oetikeroepFrom: joeym@inficad.com Date: Tue, 9 Feb 1999 16:51:50 -0700 Enclosed are a few perl scripts I wrote to collect stats on: # of users logged into a given shell machine, # of players on a quake server, and # of users currently reading news. They each have a little blurb in the header describing their use. -- Joey Miller Lead Programmer Inficad Communications 602.265.4423 / 888.265.4423 mrtg-2.17.10/contrib/jm/quake-mrtg.pl0000755000175300017510000000213213057016061016326 0ustar oetikeroep#!/usr/bin/perl5 # # quake-mrtg.pl # # counts the number of players currently on a given # quake2/quakeworld/unreal/etc server, using the 'qstat' # program available from: ftp://ftp.activesw.com/pub/quake/ # # Usage: # Target[quakeserv]: `quake-mrtg.pl quake.server.com 27910 Q2` # # ^^^ Gets usage from a Q2 server running on quake.server.com, # port 27910. # # - joey miller, inficad communications, llc. # , 2/5/1999 # my($qstat) = "./qstat"; $| = 1; if ( scalar(@ARGV) < 3 ) { print STDERR "usage: $0 server.address port game-type\n\n"; print STDERR "\tgame-types: QS, QW, QWM, H2S, HWS, Q2, UNS, HLS, SNS\n"; print STDERR "\tQW = quakeworld, Q2 = quake2, etc, etc\n"; exit -1; } my($serv) = $ARGV[0]; my($port) = $ARGV[1]; my($game) = $ARGV[2]; if ( ! open(QSTAT, "$qstat -raw : -default $game $serv:$port |") ) { print STDERR "Couldn't exec $qstat\n"; exit -2; } my($users); while() { ($users) = (split(/:/))[6]; last; } close(QSTAT); print "$users\n"; print "$users\n"; print "0\n"; print "$serv:$port\n"; mrtg-2.17.10/contrib/jm/mrtg-jm.tar.gz0000644000175300017510000000255713057016061016430 0ustar oetikeroep6Wms8+p 6vLLIo3@. p+ˮ%0odi܇31+Z~v|JVʩ{n:p{wSn빻m]owqg$Ey4c'3 Дu*O*O`v(g a8Br*4 3 $f" 2F5$iH `g\ s_! )qHF!h&%"YȩN 7,ܩ7aN>_]II3\:,4R` x ǯ8k0PkWřL2 v!ZߩP=M^|i >9EB> #Ff沂$П;`ܮc*Wc$ 沊D}nfa<E NqZ'7^=| 'jI\+P& })*,Ĥ5s>8CpzV1Ӽ9V/ӧ:Im x}K{m8Uۖ?sq}ڻKw^z(D] "VTcZsX-S L{wWWFHk}HjӔ&y䷭KP-60B̠S۝ QVq5jfKO1Vs Su>.Ԗ1UXJ ZJNӬ9ߨPZT%#=b%pw{=k¨WW-<Ϣ?F^ts4 o<2yMpwɎ>b7J-]ϕWʧN*:*kVEXM9 d ZzCߴߞ_n~!+BRZ}%rneu!oJ^ksxxoZT܄Wk.(QD%J(QD%J(Q)(mrtg-2.17.10/contrib/jm/news-mrtg.pl0000644000175300017510000000120413057016061016170 0ustar oetikeroep#!/usr/bin/perl5 # # news-mrtg.pl - # # # joey miller, inficad communications, llc # 1999/02/02 # if ( ! $ARGV[0] ) { exit; } if ( ! $ARGV[1] ) { $port = 22; } else { $port = $ARGV[1]; } if ( $ARGV[0] =~ /localhost/ ) { open(NFO, " (uptime ; ps auxw |grep nnrp |grep -v grep) |") || exit -1; } else { open(NFO, "ssh -p $port $ARGV[0] 'uptime ; ps auxw |grep nnrp |grep -v grep' |") || exit -1; } while () { if ( ! $count ) { ($uptime) = $_ =~ /^.*(up.*),\s\d+user/; } $count++; } close(NFO); $count--; $uptime =~ s/,$//; print "$count\n"; print "$count\n"; print "$uptime\n"; print "$ARGV[0]\n"; mrtg-2.17.10/contrib/iptables-accounting/0000755000175300017510000000000014130554613017243 5ustar oetikeroepmrtg-2.17.10/contrib/iptables-accounting/README0000644000175300017510000000123613057016061020122 0ustar oetikeroepFrom: "Gill, Vern" Date: Fri, 9 Mar 2001 18:43:30 -0800 Subject: New Module for MRTG -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 I have "hacked" together a module for iptables. I used the ipchainacc 1.1.0 from the contrib directory. Here's the scoop; Requires Perl There is one argument required, and it can be any of the following; filter nat mangle You may extend the functionality, but it also requires editing the script. To use, place the following in your mrtg.cfg; Target[iptables]: `/path-to/iptables-accounting argument` The script is probably ugly to perl gurus, but for a guy who has never used perl, I think it's pretty good. mrtg-2.17.10/contrib/iptables-accounting/iptables-accounting0000755000175300017510000000465314130554613023134 0ustar oetikeroep#!/usr/bin/perl # iptables-accounting .9 # # Author: Vern Gill # Date: March 9, 2001 # # Adapted from code used in ipchainacc # # ipchainacc 1.1.0 # # Author: John Lange john@darkcore.net # Date : September 12, 2000 # # # The command takes one argument: # Argument: what filter do you want to view # I.E. iptables-accounting filter # iptables-accounting nat # # Also, you can check bytes or packets. Check the $bytec below # and the text above it for details # # This command must return 4 lines of output: # Line 1 : current state of the 'incoming bytes counter' # Line 2 : current state of the 'outgoing bytes counter' # Line 3 : string, telling the uptime of the target. # Line 4 : string, telling the name of the target. # # To add more counters, just edit the commented out if lines # below. For instance, to count the filter table and the # INPUT chain, just change the elsif to filter, and the # $inrule to INPUT # Share and enjoy # edit for your system $iptables='/usr/local/sbin/iptables'; # path to iptables $host=`/bin/hostname --fqdn`; # local hostname (for information only) $table = $ARGV[0]; if ( $table =~ /^filter/i ) { $inrule='FORWARD'; $outrule='OUTPUT'; } elsif ( $table =~ /^nat/i ) { $inrule='PREROUTING'; $outrule='POSTROUTING'; } elsif ( $table =~ /^mangle/i ) { $inrule='PREROUTING'; $outrule='OUTPUT'; #} elsif ( $table =~ /^table-name-here/i ) { # $inrule='CHAIN-NAME-HERE'; # $outrule='OTHER-CHAIN-NAME'; #} elsif ( $table =~ /^table-name-here/i ) { # $inrule='CHAIN-NAME-HERE'; # $outrule='OTHER-CHAIN-NAME'; } # What should we graph? packet counters = 4, bytes = 6 # If you used the ipchainacc script before and you want to keep counting # packets, then set this to 4. If you would rather do the # sensible thing and count bytes, then set this to 6. If you change # from one to the other, then you should delete all the previous # history since it will be meaningless. $bytec=6; ## -- don't edit below here ---- # fetch the status from iptables $_=`$iptables -t $table -L $inrule -v -n -x | grep Chain`; @in_bytes = split; $_=`$iptables -t $table -L $outrule -v -n -x | grep Chain`; @out_bytes = split; # uptime of the machine open(UPTIME,"uptime |cut -b 13-27|"); $upTime=; close(UPTIME); chop $upTime; # 4 lines of output only. printf "$in_bytes[$bytec]\n$out_bytes[$bytec]\n$upTime\n$host"; mrtg-2.17.10/contrib/accesslistmon/0000755000175300017510000000000014130554613016157 5ustar oetikeroepmrtg-2.17.10/contrib/accesslistmon/mrtg.cfg0000644000175300017510000000135213057016061017607 0ustar oetikeroep# Add a WorkDir: /some/path line to this file Refresh: 300 WriteExpires: Yes Target[examplescript]: `/usr/local/mrtg/configs/accesslist/examplescript` Options[examplescript]: gauge MaxBytes[examplescript]: 1000 Title[examplescript]: Number of Ping attempts on machinename YLegend[examplescript]: Ping Attempts ShortLegend[examplescript]: Ping LegendO[examplescript]: PageTop[examplescript]:

      Number of Ping attempts on machinename

      In Max % Out Max % In Avg % Out Avg % In Current % Out Current % Interface
      System:machinename
      Maintainer:whoever
      Interface:Number of Ping attempts on machinename
      IP:x.x.x.x
      Max Amount: 1000
      mrtg-2.17.10/contrib/accesslistmon/INSTALL0000644000175300017510000000366713057016061017221 0ustar oetikeroepINSTALL file for Access-list Monitoring via MRTG First there are a few pre-requisites required in order to get the scripts going : A. MRTG :), which can be downloaded from :- http://ee-staff.ethz.ch/~oetiker/webtools/mrtg/mrtg.html B. A Cisco Router. C. Rsh enabled on the Cisco Router, this is done as follows : ip rcmd rsh-enable <--- Enabled the 'rsh' command/feature. ip rcmd remote-host root x.x.x.x root enable <---- Allows the username of root from the host x.x.x.x to execute commands via rsh. Once these commands have been enabled on the router you will be able to start executing commands using 'rsh' from the shell of the machine you have allowed access from, I suggest as an example try the following : rsh x.x.x.x sh ru If successful it should return a copy of you current 'running config' to the screen If you get an error message like this 'Permission denied.' Please check the rsh enable feature on the router to make sure you allow access for that host/username. Copy the scripts (which I have included in this package) into an appropriate directory to run from, example I use the following : /usr/local/mrtg/configs/accesslist Its up to you what you use. Also make sure the scripts are executable 'chmod 755' should do the trick. I have also included a copy of the mrtg.cfg file required to run the scripts and feed them onto the graph, this has the filename mrtg.cfg included in this package. There is one slight problem which I havent worked out as yet (if someone could help, hint, hint) is that when MRTG doesnt receive an integer for 'out' in other words if the access-list has returned 0 matches it will display an error message, the graph will still plot. This can be very annoying if you are running it from cron, as you mailbox can get filled up with cron error message, in my case I filter them to /dev/null using procmail. Thats it! I can be contacted by the following means : Email : roddy@satlink.com.au ICQ : 1987890 Enjoy! mrtg-2.17.10/contrib/accesslistmon/README0000644000175300017510000000137013057016061017035 0ustar oetikeroepREADME file for Access-list Monitoring via MRTG MRTG can be found at : http://ee-staff.ethz.ch/~oetiker/webtools/mrtg/mrtg.html What this script does : Basically I wanted to monitor how many hits I had to a particular access-list for a Cisco router. Rather than having to login and type the necessary commands, I thought it would be easier to write a shell script to do it for me. As MRTG is a graphing program, you can do almost anything with it, it then came into the equation that it is possible to graph it by feeding it into MRTG. Please see the INSTALL file for further instructions. N.B Please note I take no responsibility for any damage that is caused (not that it would I dont think). Feel free to modify the script any which way you wish. mrtg-2.17.10/contrib/accesslistmon/examplescript0000755000175300017510000000100214130554613020756 0ustar oetikeroep#!/bin/bash rsh x.x.x.x sh access-list 102 | grep icmp | grep matches | grep x.x.x.x | awk ' { print $8 }' | sed s/\(// echo "0" #The first line will rsh into the router and display access-list number 102 (this will change #depending on your config), it will grep the access-list entry type in this case 'icmp', it #will also grep the ip of the machine in question, and output the relevant information. Eg: 10 0 10 = the number of times the ACL has matched. Remember you can change this to whatever you want. mrtg-2.17.10/contrib/rumb-stat/0000755000175300017510000000000013057016061015223 5ustar oetikeroepmrtg-2.17.10/contrib/rumb-stat/gethttpstats0000644000175300017510000000212213057016061017701 0ustar oetikeroep#!/usr/bin/perl ####################################################### # Get Web stats from Apache 1.1.1 and better ####################################################### # Author: Anthony Rumble # # Revision: $Revision: 1.1.1.1 $ ####################################################### use strict; use Socket; my($request) = "/status/?auto"; # Request to send my($host) = "enterprise.ce.com.au"; # Host to send it to my($p) = 80; # Port no my ($sin, $port, $iaddr, $paddr, $proto, $line, $uptime, $bytes); $proto = getprotobyname('tcp'); if (!$proto) { die("getsockbyname"); } socket(S, PF_INET, SOCK_STREAM, $proto) || die "socket: $!"; $port = shift || $p; $iaddr = gethostbyname($host); if (!$iaddr) { die("gethostbyname"); } $sin = sockaddr_in($port, $iaddr); if (!$sin) { die("sockaddr_in"); } connect(S, $sin) || die "connect: $!"; select(S); $| = 1; select(STDOUT); print S "GET $request\n"; while () { $bytes=$1 if (m|^Total\ Bytes:\ (\S+)|); $uptime=$1 if (m|^Uptime:\ (\S+)|); } close(S); print "0\n$bytes\n$uptime\nenterprise\n"; mrtg-2.17.10/contrib/rumb-stat/getsquidstats0000644000175300017510000000226713057016061020061 0ustar oetikeroep#!/usr/bin/perl ####################################################### # Get Web stats from Squid version 1.1.1 or higher ####################################################### # Author: Anthony Rumble # # Revision: $Revision: 1.1.1.1 $ ####################################################### use strict; use Socket; my ($request) = "cache_object://localhost/stats/utilization HTTP/1.0\n";# Request my ($host) = "localhost"; # Host my ($p) = 8080; # Port number my ($j, $good, $junk, $sin, $port, $iaddr, $paddr, $proto, $line, $uptime, $bytes); $proto = getprotobyname('tcp'); if (!$proto) { die("getsockbyname"); } socket(S, PF_INET, SOCK_STREAM, $proto) || die "socket: $!"; $port = shift || $p; $iaddr = gethostbyname($host); if (!$iaddr) { die("gethostbyname"); } $sin = sockaddr_in($port, $iaddr); if (!$sin) { die("sockaddr_in"); } connect(S, $sin) || die "connect: $!"; select(S); $| = 1; select(STDOUT); print S "GET $request\n"; while () { ($junk, $b, $junk, $junk, $junk, $junk, $junk, $junk, $junk, $j) = split(' '); if ($b eq "TOTAL") { ($good) = split('}', $j); printf ("0\n%u\n1\nsquid\n", $good*1000); exit(0); } } close(S); mrtg-2.17.10/contrib/rumb-stat/README0000644000175300017510000000105713057016061016106 0ustar oetikeroepFrom anthonyr@ce.com.au Wed Feb 26 16:29:59 1997 Date: Mon, 24 Feb 1997 11:17:36 +1100 (EST) From: Anthony Rumble To: mrtg@list.ee.ethz.ch Subject: Some handy scripts Resent-Date: Mon, 24 Feb 1997 01:19:13 +0100 (MET) Resent-From: mrtg@list.ee.ethz.ch Heres some handy scripts to get byte stats from apache (web server) 1.1.1 and better and squid (proxy server) 1.1.1 and better. -- Anthony Rumble - Online Ordering Systems Corporate Express Australia Limited Phone 02-9335-0669 Fax 02-9335-0753 Mobile 015-955-042 Pager 016-634-997 mrtg-2.17.10/contrib/xlsummary/0000755000175300017510000000000013057016062015347 5ustar oetikeroepmrtg-2.17.10/contrib/xlsummary/ReadMe.txt0000644000175300017510000000276513057016062017257 0ustar oetikeroepDate: Wed, 17 Feb 1999 18:47:20 +1100 From: "Tony-Farr (Canberra)" This script extracts summary figures from the MRTG log files. In particular it summarises all sites (i.e. as many as will fit on a page) into a single Excel chart. The summary is placed in an Excel spreadsheet & chart. The Excel worksheet will have the same name as this program & be placed in the MRTG log file directory. I wrote this to summarise ping round trip times as generated by "mrtg-ping-probe". However it will process any mrtg log file. Some formatting type stuff would need to be changed though if it were to be used for things other than ping response times. If, like us, you use PWS/IIS & IE, you can just link to the spreadsheet and read it with IE. A trap for novices: If you have problems running Excel from "at", it's probably because of a bug/limitation in "at". The problem is that regardless of which user submits the job, it gets executed by the "system" user. (Great security, huh?) However Excel probably isn't installed for the user "system". I changed the schedule service to run as me rather than "system". Args are: h help d,w,m do stats for last day, week or month f directory containing mrtg log files For example, once a week I run a CMD file that includes: perl c:\perl\mrtg\contrib\xlsummary\xlsummary.pl -w -f d:\www\mrtg\ping del d:\www\mrtg\ping\weeksummary.xls ren d:\www\mrtg\ping\xlsummary.xls weeksummary.xls Feel free to contact me regarding bugs. Tony.Farr@austrade.gov.au mrtg-2.17.10/contrib/xlsummary/xlsummary.pl0000644000175300017510000001130313057016062017743 0ustar oetikeroep# xlsummary.pl # # Extract summary figures from the MRTG log files. In particular it summarises # all sites (i.e. as many as will fit on a page) into a single Excel chart. # # Args are: # h help # d,w,m do stats for last day, week or month # f directory containing mrtg log files # # v1.1 17/2/99 Tony Farr # use Getopt::Std; use File::Basename; use strict; my $progname = basename($0); my $usage = "Usage: $progname [-h] [-dwm] [-f path_of_logs]\n"; use vars qw/$opt_h $opt_d $opt_w $opt_m $opt_f/; getopts('hdwmf:') || die $usage; if ( defined($opt_h) ) { print $usage; exit(0); } if ( $opt_d + $opt_w + $opt_m != 1) { die $usage; } if ( $opt_f ) { chdir $opt_f || die "$progname: Unable to chdir to $opt_f; $!"; } my ($start, $end) = &get_duration; my $fin= $ENV{"TMP"}."\\$$.csv"; write_csv($start, $end, $fin); my $fout = "$opt_f\\" . basename($progname,".pl") . ".xls"; graph_csv($start, $end, $fin, $fout); unlink($fin); exit(0); sub write_csv { my ($start, $end, $fname)= @_; # Process all the log files open(CSV, ">$fname"); print CSV "Site, Maximum, Minimum, Halfway\n"; foreach my $fname (sort glob("*.log")) { my ($t, $lastt, $sumt, $deltat, $max, $lastmax, $summax, $min, $lastmin, $summin); open(LOG, "<$fname") || die "$progname: Unable to open $fname; $!"; ; # Skip the header line while () { chomp; ($t, $max, $min)= split/ /; if ($t < $start) { last }; # Log has latest first if ($t <= $end) { if ($lastmax) { # Zeroes mean the link was down. $deltat= $lastt - $t; $sumt += $deltat; $summax += $lastmax * $deltat; $summin += $lastmin * $deltat; } ($lastt, $lastmax, $lastmin)= ($t, $max, $min); } } # This is site specific. The devices we ping have names like SSSS-rtr # or SSSS-lan where SSSS is the site name. This strips off the "-rtr" # or "-lan" suffix. my $target= ucfirst( basename($fname, "-lan\.log", "-rtr\.log", "\.log") ); if ($sumt) { print CSV "$target, ". ($summax/$sumt) .", ". ($summin/$sumt) .", ". (($summax+$summin)/(2*$sumt)) ."\n"; } close(LOG); } close(CSV); } sub get_duration { # Returns the starttime & endtime to be reported on my($starttime, $endtime); my $t= time; my ($sec,$min,$hour,$mday,$mon,$year,$wday) = localtime($t); if ($opt_d) { $endtime= $t - ($sec + 60*$min + 60*60*$hour); $starttime= $endtime - 24*60*60; } elsif ($opt_w) { $endtime= $t - ($sec + 60*$min + 60*60*$hour + 24*60*60*$wday); $starttime= $endtime - 7*24*60*60; } else { # opt_m $endtime= $t - ($sec + 60*$min + 60*60*$hour + 24*60*60*($mday-1)); $starttime= $endtime - days_in_month($mon - 1, $year)*24*60*60; } ($starttime, $endtime); } sub days_in_month { (31, $_[1] % 4 ? 28 : 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)[${_[0]}]; } sub graph_csv { use Win32::OLE::Const 'Microsoft Excel'; use Win32::OLE::Const 'Microsoft Office'; use POSIX; my ($start, $end, $fin, $fout)= @_; # use existing instance if Excel is already running my $xl; eval {$xl = Win32::OLE->GetActiveObject('Excel.Application')}; die "$progname: Excel not installed" if $@; unless (defined $xl) { $xl = Win32::OLE->new('Excel.Application', sub {$_[0]->Quit;}) || die "$progname: Cannot start Excel; $!"; } # open the CSV my $book = $xl->Workbooks->Open($fin); # Sort data into descending order my $sheet = $book->Worksheets(1); my $a1 = $sheet->Cells(1, 1); my $range = $sheet->Range($a1, $a1->End(xlDown)->End(xlToRight)); $range->Sort( {Key1 => $sheet->Range("D2"), Order1 => xlDescending} ); # Put data into a chart. The most that can be sensibly squeezed in # is 52 sites. So select the slowest. $sheet->Range($a1, $sheet->Cells(53, 4))->Select; $book->Charts->Add; # And format it. my $chart= $book->ActiveChart; $chart->{'ChartType'} = xlStockHLC; $chart->{'HasLegend'} = msoFalse; $chart->{'HasTitle'} = msoTrue; # The description here fits ping response times. $chart->ChartTitle->Characters->{'Text'} = "Typical Maximum & Minimum Round Trip Times (msecs) between ". localtime($start) ." and ". localtime($end); $chart->PlotArea->Interior->{'ColorIndex'} = xlNone; $chart->ChartGroups(1)->HiLoLines->Border->{'Weight'} = xlMedium; $chart->PageSetup->{'LeftMargin'} = 5; $chart->PageSetup->{'RightMargin'} = 5; $chart->PageSetup->{'TopMargin'} = 5; $chart->PageSetup->{'BottomMargin'} = 10; $chart->PageSetup->{'Orientation'} = xlLandscape; $chart->Axes(xlCategory)->TickLabels->Font->{'Size'} = 8; $chart->Axes(xlValue)->TickLabels->Font->{'Size'} = 8; # save and exit $book->SaveAs($fout, xlWorkbookNormal); $book->Close; undef $xl; }mrtg-2.17.10/contrib/ipchainacc/0000755000175300017510000000000013057016061015367 5ustar oetikeroepmrtg-2.17.10/contrib/ipchainacc/README0000644000175300017510000000134313057016061016250 0ustar oetikeroepFrom: Ilya Konstantinov Date: 06 Sep 2000 18:53:33 -0200 I have tweaked the ipchainacc perl script provided in MRTG's contrib for our own use at our LUG, and I thought the rest of the users might find my changes helpful. Changes: 1. Made it account BYTES instead of PACKETS, like it used to do before. 2. It now accepts (optional) two command-line arguments to make it return results for the 2nd etc. rules in the chain, so for example, I can insert rules into the 'acctin' and 'acctout' chains which'll match traffic with destination and source (respectively) port set to 80, so I could see how much traffic passes through HTTP only. so: ipchainacc 1 1 should return counters of 2nd acctin and 2nd acctout rules. mrtg-2.17.10/contrib/ipchainacc/ipchainacc0000644000175300017510000000502713057016061017400 0ustar oetikeroep#!/usr/bin/perl # ipchainacc version 1.0.2 # Author: John Lange, john@darkcore.net Ilya Konstantinov, mrtg-ipchains@future.galanet.net # Date: Sep 06, 2000 # # This script was written to provide output for MRTG # (multi router traffic grapher) via ipchains. # # http://ee-staff.ethz.ch/~oetiker/webtools/mrtg/mrtg.html # ## USAGE EXAMPLE (line from mrtg.conf) # # Target[traffic]: /usr/local/mrtg-2/bin/ipchainacc 0 0 # # The arguments 0 0 mean it should report the bytes count # for the 1st (1st is 0, 2st is 1 and so on) rule in # the 'acctin' chain (supposed to be the incoming traffic) # and the 1st rule in the 'acctout' chain. # ## Changelog # v1.0.2 Made it actually account bytes instead of packages. # Now ipchainacc requires 2 command-line arguments. # This allows having more than one rule in the accounting # chains, so you could have traffic cuts by protocol # or IP blocks which match your rules. # v1.0.1 added -x to ipchains to expand byte counters # v1.0.0 Inital Release # # # This command must return 4 lines of output: # Line 1 : current state of the 'incoming bytes counter' # Line 2 : current state of the 'outgoing bytes counter' # Line 3 : string, telling the uptime of the target. # Line 4 : string, telling the name of the target. # This script relies on you having setup your ipchains rules beforehand ## edit for your system $ipchains='/sbin/ipchains'; # path to ipchains $host=`/bin/hostname --fqdn`; # local hostname (for information only) # if you use the ipchains rules above, you don't have to change these $inrule='acctin'; # name of input accounting rule $outrule='acctout'; # name of output accounting rule ## -- don't edit below here ---- # get command line params my ($in_rule,$out_rule) = @ARGV; # fetch the status from ipchains @rules=`$ipchains -L $inrule -v -n -x`; splice @rules, 0, 2; @in_bytes=split(' ',$rules[$in_rule]); @rules=`$ipchains -L $outrule -v -n -x`; splice @rules, 0, 2; @out_bytes = split(' ',$rules[$out_rule]); print "$out_line"; # just for debugging #$c=1; #foreach $value (@in_bytes) { # printf "$c: $value\n"; # $c++; #}; # uptime of the machine my $upTimeLine = `uptime`; my $upTime; if ($upTimeLine =~ /\s+?.*?\s+?up (\d+ days,\s+.*?),/) { $upTime = $1; } # 4 lines of output only. if (!$in_bytes[1]) { $in_bytes[1] = 0; } if (!$out_bytes[1]) { $out_bytes[1] = 0; } print "$in_bytes[1]\n", "$out_bytes[1]\n", "$upTime\n$host"; #print ($in_bytes[1] ne ''?$in_bytes[1]:'0'),"\n", # ($out_bytes[1] ne ''?$out_bytes[1]:'0'),"\n", # "$upTime\n$host"; mrtg-2.17.10/contrib/mrtg.php/0000755000175300017510000000000013057016061015044 5ustar oetikeroepmrtg-2.17.10/contrib/mrtg.php/README.txt0000644000175300017510000000275013057016061016546 0ustar oetikeroep=============================== MRTG-PHP The MTRG log file lister =============================== Version 1.021 Written by David Boyer & Jo Joseph =============================== * Intro * MRTG-PHP is a php based web page that will look for log files from MRTG and list them on a single page. It also grabs certain bits of information from the linked log file to show a description of what file is linked. The way is was written allows it to automatically find and update itself if any new log files appear. It will list them and add the proper links and text. Hopefully it will also work with any future versions of MRTG. It was written because I wanted a way to list MRTG log files, and didn't want to always come back and update it. I've found it very handy, I hope someone out there does too. * Requirements * Web server (IIS,Apache etc..) PHP 3 or higher * Compatibility * This is know to work with MRTG V2.9.7 running on a linux apache server. It's unknown if it'll work with other versions as I've been unable to try it out on any others. If you have a different versions of MRTG or run it on a Windows machine, let me know if it works. If it doesn't I will try and fix it, if you fix the code send me some info on what you changed so I can update the next release and credit you with the bug fix. * Contact * David Boyer E-Mail : crazydave@ntlworld.com WebSite : http://www.efsection31.com Jo Jeseph E-Mail : joseph_j@glan-hafren.ac.uk mrtg-2.17.10/contrib/mrtg.php/mrtg.php0000644000175300017510000001333113057016061016527 0ustar oetikeroep Welcome to MRTG-PHP

      - MRTG-PHP , the MRTG log file veiwer -

      Page jumps
      "; traverse_dir("$dir/$file"); chdir($dir); } } else if (stristr($file,"html") <> "" AND stristr($file,"~") <> "~") { $j =0; $oldfile=$namefile; $namefile = ""; While ($file[$j] <> "_") { $namefile = $namefile . $file[$j]; $j++ ;} $count++; $filearray[$count][0] = $file; $filearray[$count][1] = $namefile; if ($oldfile!=$namefile and $first=1) echo "$namefile
      "; $first=0; } } echo "
      "; $first=1; $namefile=""; $tablestart = 1; $alt = 1; for ($counter=0; $counter<=$count; $counter++) { if ($counter>0) $oldfile = $filearray[$counter-1][1]; if ($oldfile!=$filearray[$counter][1] and $first=1) { if ($tablestart == 1) $tablestart = 0; else echo ""; echo "

      " . $filearray[$counter][1] . "
      "; } $first=0; $j =0; $ifname=""; $iftype=""; $system=""; $maintain=""; $des=""; $speed=""; $log=file($filearray[$counter][0]); while (strchr($log[$j],"

      ")=="") $j++; $logline=$log[$j]; $i=strpos($logline,"ifName")+21; While ($logline[$i] <> "<") {$ifname=$ifname.$logline[$i]; $i++;} If (!$ifname) $ifname = "Not set"; $i=strpos($logline,"ifType")+21; While ($logline[$i] <> "<") {$iftype=$iftype.$logline[$i]; $i++;} If (!$iftype) $iftype = "Not set"; $i=strpos($logline,"System")+21; While ($logline[$i] <> "<") {$system=$system.$logline[$i]; $i++;} If (!$system) $system = "Not set"; $i=strpos($logline,"Maintain")+21; While ($logline[$i] <> "<") {$maintain=$maintain.$logline[$i]; $i++;} If (!$maintain) $maintain = "Not set"; $i=strpos($logline,"Description")+21; While ($logline[$i] <> "<") {$des=$des.$logline[$i]; $i++;} If (strlen($des)<4) $des = "Not set"; $i=strpos($logline,"Max Speed")+21; While ($logline[$i] <> "<") {$speed=$speed.$logline[$i]; $i++;} If (!$speed) $speed = "Not set"; ?>
      >

      align="right">Description >
      align="right">Maintainer >
      align="right">System >
      align="right">Connection Name >
      align="right">Connection Type >
      align="right">Max Speed >
      -Back to top-

      MRTG-PHP Written by David Boyer and Jo Joseph

      mrtg-2.17.10/contrib/mrtg-archiver-script/0000755000175300017510000000000013057016061017361 5ustar oetikeroepmrtg-2.17.10/contrib/mrtg-archiver-script/mrtg-archiver0000755000175300017510000001523313057016061022065 0ustar oetikeroep#!/usr/bin/perl # # MRTG Archiver by O.Krotoff # # Version 0.2 # use strict; use Getopt::Long; use File::Copy; use POSIX qw(strftime); my @targets; my %titles; my $target; my $ArchiveDir = 'archive'; my $WorkDir = 'mrtgdata'; my $ConfigFile = 'mrtg.cfg'; my ($subdir, $timedir, $archpath, $archindex, $suffix, $img_suffix); my ($archperiod); my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $week); my ($cur_target, $cur_date, $cur_group); my $DayPartRE = '^\\`Daily\''; my $WeekPartRE = '^\\`Weekly\''; my $MonthPartRE = '^\\`Monthly\''; my $YearPartRE = '^\\`Yearly\''; my $GroupRE = '^(\d+\.\d+\.\d+\.\d+)'; # To group targets by router IP my $BackShift = 0; my ($DayFlag, $WeekFlag, $MonthFlag, $YearFlag); ($DayFlag, $WeekFlag, $MonthFlag, $YearFlag) = (0, 0, 0, 0); $img_suffix = 'png'; GetOptions('d!' => \$DayFlag, 'w!' => \$WeekFlag, 'm!' => \$MonthFlag, 'y!' => \$YearFlag, 'conf=s' => \$ConfigFile, 'arch=s' => \$ArchiveDir, 'back=i' => \$BackShift ); $timedir = 'days' if $DayFlag; $timedir = 'weeks' if $WeekFlag; $timedir = 'months' if $MonthFlag; $timedir = 'years' if $YearFlag; $suffix = 'day' if $DayFlag; $suffix = 'week' if $WeekFlag; $suffix = 'month' if $MonthFlag; $suffix = 'year' if $YearFlag; $archperiod = 'Daily' if $DayFlag; $archperiod = 'Weekly' if $WeekFlag; $archperiod = 'Monthly' if $MonthFlag; $archperiod = 'Yearly' if $YearFlag; @targets = (); open(CFGFILE, $ConfigFile) || die "Can't open configuration file $ConfigFile\n"; while() { if(/^WorkDir:\s*(.*)\s*$/) { $WorkDir = $1; } elsif(/^Target\[(.*)\]:/) { $cur_target = $1; push @targets, $cur_target; } elsif(/^Title\[$cur_target\]:\s*(.*)\s*$/) { $titles{$cur_target} = $1; } } ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = localtime(time - $BackShift); $week = strftime("%W", $sec, $min, $hour, $mday, $mon, $year); $year += 1900; $mon += 1; # $week = int($yday / 7) + 1; if($DayFlag) { $subdir = sprintf "%4d-%02d-%02d", $year, $mon, $mday; $cur_date = sprintf "%02d/%02d/%4d", $mday, $mon, $year; } elsif($WeekFlag) { $subdir = sprintf "%4d-%02d", $year, $week; $cur_date = sprintf "%02d/%4d, week %2d", $mon, $year, $week; } elsif($MonthFlag) { $subdir = sprintf "%4d-%02d", $year, $mon; $cur_date = sprintf "%02d/%4d", $mon, $year; } elsif($YearFlag) { $subdir = sprintf "%4d", $year; $cur_date = $subdir; } $archpath = "$ArchiveDir/$timedir/$subdir"; $archindex = "$ArchiveDir/$timedir/index.html"; if(-f $archindex) { open(ARCHINDEX, "< $archindex") || die "Can't open $archindex !\n"; open(OUTARCHINDEX, "> $archindex.new") || die "Can't open $archindex.new !\n"; while() { if(m{^\<\!-- Start --\>}) { print OUTARCHINDEX $_; print OUTARCHINDEX "
    • $cur_date \n"; if($DayFlag && $mday == 1) { print OUTARCHINDEX "

    • \n"; } if($WeekFlag && $week == 1) { print OUTARCHINDEX "

    • \n"; } if($MonthFlag && $mon == 1) { print OUTARCHINDEX "

    • \n"; } } else { print OUTARCHINDEX $_; } } close(ARCHINDEX); close(OUTARCHINDEX); unlink($archindex); rename("$archindex.new", $archindex); } else { open(OUTARCHINDEX, "> $archindex") || die "Can't create $archindex !\n"; print OUTARCHINDEX < MRTG Statistics $archperiod Archive

      MRTG Statistics $archperiod Archive

      Back to archive index

      MRTG Statistics Archiver by Krot. ARCHINDSTOP } # print "Archive dir is: $archpath \n"; unless(-d $archpath) { mkdir($archpath, 0755) || die "Can't create archive dir! \n"; } open(INDEXFILE, "> $archpath/index.html") || die "Can't create index.html file!\n"; print INDEXFILE < MRTG Statistics Archive --- $cur_date

      MRTG Statistics Archive --- $cur_date

      < Prev  Back to $archperiod archive index  Next >
        INDEXTOP $cur_group = ''; foreach $target (@targets) { if(open(HTMLFILE, "$WorkDir/$target.html")) { # print "Processing $target...\n"; if($GroupRE) { $target =~ /$GroupRE/; # $titles{$target} =~ /$GroupRE/; if($cur_group ne $1) { print INDEXFILE "
      " if $cur_group; $cur_group = $1; print INDEXFILE "
    • $cur_group\n
        \n"; } } print INDEXFILE "
      • $titles{$target} \n"; copy("$WorkDir/$target-$suffix.$img_suffix", "$archpath/$target-$suffix.$img_suffix") || die "Failed to copy file $archpath/$target-$suffix.$img_suffix !\n"; open(OUTFILE, "> $archpath/$target.html") || die "Can't create archive file $archpath/$target.html !\n"; my $inHead = 0; my $inDayPart = 0; my $inWeekPart = 0; my $inMonthPart = 0; my $inYearPart = 0; my $inTail = 0; while() { chomp; if(/^\< Prev  Index  Next > NAVBLOCK print OUTFILE "
        " unless $inHead; } elsif(/$DayPartRE/) { $inDayPart = 1 } elsif(/^\
        }{ --- $cur_date\} if $inHead; s{SRC=\"(mrtg\-[lmr])}{SRC=\"/mrtg-images/$1}g if $inTail; print OUTFILE $_."\n" if ($inHead || ($inDayPart && $DayFlag) || ($inWeekPart && $WeekFlag) || ($inMonthPart && $MonthFlag) || ($inYearPart && $YearFlag) || $inTail); } close(OUTFILE); close(HTMLFILE); } } print INDEXFILE "
      " if $GroupRE; print INDEXFILE <
      MRTG Statistics Archiver by Krot. INDEXTAIL mrtg-2.17.10/contrib/mrtg-archiver-script/README0000644000175300017510000000541713057016061020250 0ustar oetikeroepMRTG Statistics Archiever Version 0.2 Oleg Krotoff 16/06/2000 --------- Intro and Disclaimer This script was written as a result of attempts to provide automatic archiving of graphs, generated by MRTG for all targets. I failed to customize the scripts written by Emanuele Leonardi and Rawlin Blake (their scripts supplied with MRTG in contrib) so I wrote my own. The script provided "as-is", just because it may be usefull for someone with the same needs. It works for me, but I can't be sure that it will work for you. It was tested only with Linux 2.2.14 -- 2.2.16, Apache 1.3.6 -- 1.3.12 and Perl 5.6. --------- * mrtg-archiver Main part is the 'mrtg-archiver' script itself. It tries to parse MRTG configuration file and extracts the list of targets. Then the script copies graphs and necessary parts of html file to the archive. * Command-line options: -conf=/path/to/config-file MRTG configuration file -arch=/path/to/archive Path to folder, where the archive will be stored. You should create folders 'days', 'weeks', 'months' 'years' in it and also you can place the supplied index.html to the archive folder. All other indexes are produced automaticaly. -d Produce daily archive -w Produce weekly archive -m Produce monthly archive -y Produce yearly archive -back=n Tell the archiever, that date, to which the archiving process is made was n seconds earlier. This allows to make daily archives at, for example, 3:00am but mark them by correct (yesterday) date. The script relies heavily on the structure of html files produced by MRTG, so if the structure change substantialy the script will possibly crash. * What you can customize in script: The variable $GroupRE contains regular expression to group targets. Currently it groups targets by router IP in target itself, assuming that target name starts from router IP. You can change it to anything you want and also you can group targets by some parts in Title. For this you should comment out line 178 and uncomment line 179. The variable $img_suffix contains the suffix (currently 'png') of graph files produced by MRTG. If your MRTG produces gifs, you can change this variable's value to 'gif'. * Starting the archiver mrtg-archive supposed to be started by cron. The example lines to be put in crontab are supplied in file 'to-crontab' * Navigating through archives To provide the navigation through archives, the cgi-script 'mrtgnav' should be placed into /cgi-bin/mrtg of your WWW server. It requires URI.pm to be installed on your site. You may need to change the value of $HtmlBase, it should contain the location of Web server document root. The idea of the navigation script was inspired by Cooler (http://cooler.irk.ru). mrtg-2.17.10/contrib/mrtg-archiver-script/index.html0000644000175300017510000000067213057016061021363 0ustar oetikeroep MRTG Statistics Archive

      MRTG Statistics Archive


      MRTG Statistics Archiver by Krot. mrtg-2.17.10/contrib/mrtg-archiver-script/mrtgnav0000755000175300017510000000313613057016061020770 0ustar oetikeroep#!/usr/bin/perl use strict; use URI; my $dirc = 'none'; my $HtmlBase = "/usr/lib/apache/htdocs"; my ($rq, $rf, $prevDir, $nextDir, $newLocation); my ($basedir, $subdir, $file, $TheDir, $host); my (@dirs, @pathsegs); $rq = URI->new($ENV{"REQUEST_URI"}); $dirc = $rq->query; $rf = URI->new($ENV{"HTTP_REFERER"}); $host = $rf->host; $subdir = $rf->path; @pathsegs = $rf->path_segments; $file = $pathsegs[-1]; $subdir = $pathsegs[-2]; $basedir = join('/', @pathsegs[0..$#pathsegs-2]); opendir(DIRHNDL, "$HtmlBase/$basedir"); while($TheDir = readdir(DIRHNDL)) { if($TheDir =~ /^\w/ && -d "$HtmlBase/$basedir/$TheDir") { push @dirs, $TheDir; } } @dirs = sort @dirs; for(my $i = 0; $i <= $#dirs; $i++) { if ($dirs[$i] eq $subdir) { if($i > 0) { $prevDir = $dirs[$i - 1] } else { $prevDir = $subdir } if($i < $#dirs) { $nextDir = $dirs[$i + 1] } else { $nextDir = $subdir } last; } } if($dirc eq 'prev') { if(-f "$HtmlBase/$basedir/$prevDir/$file") { $newLocation = "http://$host$basedir/$prevDir/$file"; } else { $newLocation = "http://$host$basedir/$subdir/$file"; } } elsif ($dirc eq 'next') { if(-f "$HtmlBase/$basedir/$nextDir/$file") { $newLocation = "http://$host$basedir/$nextDir/$file"; } else { $newLocation = "http://$host$basedir/$subdir/$file"; } } elsif ($dirc eq 'index') { if($file eq 'index.html') { $newLocation = "http://$host$basedir/index.html"; } else { $newLocation = "http://$host$basedir/$subdir/index.html"; } } else { $newLocation = $ENV{"HTTP_REFERER"}; } print "Location:$newLocation\n\n"; mrtg-2.17.10/contrib/mrtg-archiver-script/to-crontab0000644000175300017510000000106713057016061021360 0ustar oetikeroep19 0 * * * /usr/local/lib/mrtg/mrtg-archiver -d --conf=/usr/local/lib/mrtg/mrtg.cfg --arch=/usr/lib/apache/htdocs/mrtg/archive --back=1200 19 0 * * mon /usr/local/lib/mrtg/mrtg-archiver -w --conf=/usr/local/lib/mrtg/mrtg.cfg --arch=/usr/lib/apache/htdocs/mrtg/archive --back=1200 19 0 1 * * /usr/local/lib/mrtg/mrtg-archiver -m --conf=/usr/local/lib/mrtg/mrtg.cfg --arch=/usr/lib/apache/htdocs/mrtg/archive --back=1200 19 0 1 Jan * /usr/local/lib/mrtg/mrtg-archiver -y --conf=/usr/local/lib/mrtg/mrtg.cfg --arch=/usr/lib/apache/htdocs/mrtg/archive --back=1200mrtg-2.17.10/contrib/cfgmaker_cisco/0000755000175300017510000000000013057016061016244 5ustar oetikeroepmrtg-2.17.10/contrib/cfgmaker_cisco/cfgmaker.cisco0000644000175300017510000004507613057016061021061 0ustar oetikeroep#! /pkg/gnu/bin/perl # -*- mode: Perl -*- ################################################################## # MRTG 2.7.2 -- Config file creator ################################################################## # Created by Tobias Oetiker # this produces a config file for one router, by bulling info # off the router via snmp ################################################################# # # Distributed under the GNU copyleft use BER "0.57"; use SNMP_Session "0.59"; use SNMP_util "0.57"; use Socket; use strict; use vars '$DEBUG'; my $DEBUG = 0; my ($session, %ipaddr, %iphost); sub main { snmpmapOID('ipAdEntAddr' => '1.3.6.1.2.1.4.20.1.1', 'ipAdEntIfIndex' => '1.3.6.1.2.1.4.20.1.2', 'sysObjectID' => '1.3.6.1.2.1.1.2.0', 'CiscolocIfDescr' => '1.3.6.1.4.1.9.2.2.1.1.28', 'ifAlias' => '1.3.6.1.2.1.31.1.1.1.18'); my(%ifType_d)=('1'=>'Other', '2'=>'regular1822', '3'=>'hdh1822', '4'=>'ddnX25', '5'=>'rfc877x25', '6'=>'ethernetCsmacd', '7'=>'iso88023Csmacd', '8'=>'iso88024TokenBus', '9'=>'iso88025TokenRing', '10'=>'iso88026Man', '11'=>'starLan', '12'=>'proteon10Mbit', '13'=>'proteon80Mbit', '14'=>'hyperchannel', '15'=>'fddi', '16'=>'lapb', '17'=>'sdlc', '18'=>'ds1', '19'=>'e1', '20'=>'basicISDN', '21'=>'primaryISDN', '22'=>'propPointToPointSerial', '23'=>'ppp', '24'=>'softwareLoopback', '25'=>'eon', '26'=>'ethernet-3Mbit', '27'=>'nsip', '28'=>'slip', '29'=>'ultra', '30'=>'ds3', '31'=>'sip', '32'=>'frame-relay', '33'=>'rs232', '34'=>'para', '35'=>'arcnet', '36'=>'arcnetPlus', '37'=>'atm', '38'=>'miox25', '39'=>'sonet', '40'=>'x25ple', '41'=>'iso88022llc', '42'=>'localTalk', '43'=>'smdsDxi', '44'=>'frameRelayService', '45'=>'v35', '46'=>'hssi', '47'=>'hippi', '48'=>'modem', '49'=>'aal5', '50'=>'sonetPath', '51'=>'sonetVT', '52'=>'smdsIcip', '53'=>'propVirtual', '54'=>'propMultiplexor', '55'=>'100BaseVG', #### New IF Types added 9/24/98 by Russ Carleton (roccor@livenetworking.com) #### based on the IANA file updated at ftp://ftp.isi.edu/mib/ianaiftype.mib '56'=>'Fibre Channel', '57'=>'HIPPI Interface', '58'=>'Obsolete for FrameRelay', '59'=>'ATM Emulation of 802.3 LAN', '60'=>'ATM Emulation of 802.5 LAN', '61'=>'ATM Emulation of a Circuit', '62'=>'FastEthernet (100BaseT)', '63'=>'ISDN & X.25', '64'=>'CCITT V.11/X.21', '65'=>'CCITT V.36', '66'=>'CCITT G703 at 64Kbps', '67'=>'Obsolete G702 see DS1-MIB', '68'=>'SNA QLLC', '69'=>'Full Duplex Fast Ethernet (100BaseFX)', '70'=>'Channel', '71'=>'Radio Spread Spectrum (802.11)', '72'=>'IBM System 360/370 OEMI Channel', '73'=>'IBM Enterprise Systems Connection', '74'=>'Data Link Switching', '75'=>'ISDN S/T Interface', '76'=>'ISDN U Interface', '77'=>'Link Access Protocol D (LAPD)', '78'=>'IP Switching Opjects', '79'=>'Remote Source Route Bridging', '80'=>'ATM Logical Port', '81'=>'AT&T DS0 Point (64 Kbps)', '82'=>'AT&T Group of DS0 on a single DS1', '83'=>'BiSync Protocol (BSC)', '84'=>'Asynchronous Protocol', '85'=>'Combat Net Radio', '86'=>'ISO 802.5r DTR', '87'=>'Ext Pos Loc Report Sys', '88'=>'Apple Talk Remote Access Protocol', '89'=>'Proprietary Connectionless Protocol', '90'=>'CCITT-ITU X.29 PAD Protocol', '91'=>'CCITT-ITU X.3 PAD Facility', '92'=>'MultiProtocol Connection over Frame/Relay', '93'=>'CCITT-ITU X213', '94'=>'Asymetric Digitial Subscriber Loop (ADSL)', '95'=>'Rate-Adapt Digital Subscriber Loop (RDSL)', '96'=>'Symetric Digitial Subscriber Loop (SDSL)', '97'=>'Very High Speed Digitial Subscriber Loop (HDSL)', '98'=>'ISO 802.5 CRFP', '99'=>'Myricom Myrinet', '100'=>'Voice recEive and transMit (voiceEM)', '101'=>'Voice Foreign eXchange Office (voiceFXO)', '102'=>'Voice Foreign eXchange Station (voiceFXS)', '103'=>'Voice Encapulation', '104'=>'Voice Over IP Encapulation', '105'=>'ATM DXI', '106'=>'ATM FUNI', '107'=>'ATM IMA', '108'=>'PPP Multilink Bundle', '109'=>'IBM IP over CDLC', '110'=>'IBM Common Link Access to Workstation', '111'=>'IBM Stack to Stack', '112'=>'IBM Virtual IP Address (VIPA)', '113'=>'IBM Multi-Protocol Channel Support', '114'=>'IBM IP over ATM', '115'=>'ISO 802.5j Fiber Token Ring', '116'=>'IBM Twinaxial Data Link Control (TDLC)', '117'=>'Gigabit Ethernet', '118'=>'Higher Data Link Control (HDLC)', '119'=>'Link Access Protocol F (LAPF)', '120'=>'CCITT V.37', '121'=>'CCITT X.25 Multi-Link Protocol', '122'=>'CCITT X.25 Hunt Group', '123'=>'Transp HDLC', '124'=>'Interleave Channel', '125'=>'Fast Channel', '126'=>'IP (for APPN HPR in IP Networks)', '127'=>'CATV MAC Layer', '128'=>'CATV Downstream Interface', '129'=>'CATV Upstream Interface', '130'=>'Avalon Parallel Processor', '131'=>'Encapsulation Interface', '132'=>'Coffee Pot', '133'=>'Circuit Emulation Service', '134'=>'ATM Sub Interface', '135'=>'Layer 2 Virtual LAN using 802.1Q', '136'=>'Layer 3 Virtual LAN using IP', '137'=>'Layer 3 Virtual LAN using IPX', '138'=>'IP Over Power Lines', '139'=>'Multi-Media Mail over IP', '140'=>'Dynamic synchronous Transfer Mode (DTM)', '141'=>'Data Communications Network', '142'=>'IP Forwarding Interface' ); my($vendor)=0; if ($ARGV[0] eq '--vendor') { $vendor = 1; shift @ARGV}; my($community,$router) = ($1,$2) if $ARGV[0] =~ /(.*)\@(.*)/; die <>mrtg.cfg USAGE print "# Add a WorkDir: /some/path line to this file\n\n"; $session = SNMP_Session->open ($router, $community, 161) || die "Error opening SNMP session to $router"; my($sysDescr,$sysContact,$sysName,$sysLocation,$ifNumber,$sysObjectID) = snmpget("$community\@$router", 'sysDescr','sysContact','sysName', 'sysLocation', 'ifNumber', 'sysObjectID'); $sysDescr =~ s/\r\n?/
      /g; # Change returns to
      my($cisco_router_sysid) = '1\.3\.6\.1\.4\.1\.9'; my($livingston_router_sysid) = '1\.3\.6\.1\.4\.1\.307'; my($ciscobox) = ($sysObjectID =~ /^$cisco_router_sysid/); my($portmaster) = ($sysObjectID =~ /^$livingston_router_sysid/); print <map_table ([[1,3,6,1,2,1,4,20,1,1], # ipAdEntAddr [1,3,6,1,2,1,4,20,1,2]], # ipAdEntIf sub ($@) { my ($index, $ipadentaddr, $ipadentif) = @_; grep (defined $_ && ($_=pretty_print $_), ($ipadentif, $ipadentaddr)); $ipaddr{$ipadentif} = $ipadentaddr; $iphost{$ipadentif} = gethostbyaddr(pack('C4',split(/\./,$ipaddr{$ipadentif})), AF_INET); if (!defined $iphost{$ipadentif} || ($iphost{$ipadentif} eq '')){ $iphost{$ipadentif} = 'No hostname defined for IP address'; } }); print STDERR "Got Addresses\n" if $DEBUG; print STDERR "Got IfTable\n" if $DEBUG; my(%sifdesc,%siftype,%sifspeed,%sifadminstatus,%sifoperstatus,%sciscodescr,%sifrawdesc); ### May need the cisco IOS version number so we know which oid to use ### to get the cisco description. ### ### - mjd 2/5/98 (Mike Diehn) (mdiehn@mindspring.net) ### my ($cisco_ver, $cisco_descr_oid, @ciscodescr); if ( $ciscobox ) { ($cisco_ver) = ($sysDescr =~ m/Version\s+([\d\.]+)\(\d/o); $cisco_descr_oid = ($cisco_ver ge "11.2") ? "ifAlias" : "CiscolocIfDescr"; } #mod by jon: create a hash table to map ifIndex integers to module/port names: my $cat5500 = 0; if ( $sysDescr =~ /WS-C55.*/i ) { $cat5500 = 1; } my (%iftomp, %iftovlan); if ($cat5500) { $session->map_table ([[1,3,6,1,4,1,9,5,1,4,1,1,11]], #5500 port group sub ($@) { my ($rowindex, $index) = @_; grep (defined $_ && ($_=pretty_print $_), ($index)); # $rowindex =~ s/\./\//g; $iftomp{$index} = $rowindex; # print "row:$rowindex; idx:$index"; # print "\n\n"; }); #foreach my $key (sort(keys %iftomp)) { # print $key, '=', $iftomp{$key}, "\n"; #} $session->map_table ([[1,3,6,1,4,1,9,5,1,9,3,1,3]], sub ($@) { my ($rowindex, $vlan_no) = @_; grep (defined $_ && ($_=pretty_print $_), ($vlan_no)); my $ifindex; foreach my $key (keys %iftomp) { if ($iftomp{$key} eq $rowindex) { $ifindex = $key; } } $iftovlan{$ifindex} = $vlan_no; }); #foreach my $key (sort(keys %iftovlan)) { # print $key, '=', $iftovlan{$key}, "\n"; #} } #end if cat5500 $session->map_table ([[1,3,6,1,2,1,2,2,1,1], # ifIndex [1,3,6,1,2,1,2,2,1,2], # ifDescr [1,3,6,1,2,1,2,2,1,3], # ifType [1,3,6,1,2,1,2,2,1,5], # ifSpeed [1,3,6,1,2,1,2,2,1,7], # ifAdminStatus [1,3,6,1,2,1,2,2,1,8]], # ifOperStatus sub ($@) { my ($rowindex,$index,$ifdescr,$iftype,$ifspeed,$ifadminstatus,$ifoperstatus) = @_; grep (defined $_ && ($_=pretty_print $_), ($index,$ifdescr,$iftype,$ifspeed,$ifadminstatus,$ifoperstatus)); if ($cat5500) { my ($intname, $tmp_vlan_no) = split (' ',$ifdescr); if ( ($intname eq "sc0") || ($intname eq "sl0") ) { return; } if ($intname eq "VLAN") { if ($tmp_vlan_no >= 1000) { return; } #The Catalyst software version 4.5 seems to return '0' as the ifSpeed for a #VLAN. We set it to 100Mb because we want to watch aggregate VLAN traffic. if ($ifspeed == 0) { $ifspeed = 100 * 10**6; } } my ($port_num, $vlan_desc); $port_num = $iftomp{$index}; $port_num =~ s/\./\//g; if ($iftovlan{$index} != 1) { $vlan_desc = " Vlan $iftovlan{$index} "; } else { $vlan_desc = "Vlan $iftovlan{$index}"; } if ($iftype != 53) { $sifdesc{$index} = "Port $port_num, $vlan_desc, $ifdescr"; } else { $sifdesc{$index} = " Aggregate Traffic: $ifdescr "; $sifrawdesc{$index} = $ifdescr; } } else { $sifdesc{$index} = $ifdescr; } $siftype{$index} = $iftype; $sifspeed{$index} = $ifspeed; $sifadminstatus{$index} = $ifadminstatus; $sifoperstatus{$index} = $ifoperstatus; if ($portmaster && $vendor) { # We can only approximate speeds # # so we think that ppp can do 76800 bit/s, and slip 38400. # (actualy, slip is a bit faster, but usualy users with newer modems # use ppp). Alternatively, you can set async speed to 115200 or # 230400 (the maximum speed supported by portmaster). # # But if the interface is ptpW (sync), max speed is 128000 # change it to your needs. On various Portmasters there are # various numbers of sync interfaces, so modify it. # # The most commonly used PM-2ER has only one sync. # # Paul Makeev (mac@redline.ru) # if ($siftype{$index} eq '23') { if ($sifdesc{$index} eq 'ptpW1') { $sifspeed{$index} = 128000; } else { $sifspeed{$index} = 76800; } } elsif ($siftype{$index} eq '28') { $sifspeed{$index} = 38400; } elsif ($siftype{$index} eq '6') { $sifspeed{$index} = 10000000; } } ### Move this section south so we know what type of ### circuit we're looking at before we retrieve ### the cisco interface alias. ### ### This whole cicso thing should be re-written, but since ### this script doesn't need to run quickly... ### ### - mjd 2/5/98 ### # Get the user configurable interface description entered in the config # if it's a cisco-box # if ($ciscobox && $vendor) { my ($enoid, @descr); $enoid = $cisco_descr_oid . "." . $index; if ( $cisco_ver ge "11.2" or $siftype{$index} != '32' ) { ### This is either not a frame-relay sub-interface or ### this router is running IOS 11.2+ and interface ### type won't matter. In either of these cases, it's ### ok to try getting the ifAlias or ciscoLocIfDesc. ### @descr = snmpget("$community\@$router", $enoid); } else { ### This is a frame-relay sub-interface *and* the router ### is running an IOS older than 11.2. Therefore, we can ### get neither ifAlias nor ciscoLocIfDesc. Do something ### useful. ### @descr = ("Cisco PVCs descriptions require IOS 11.2+."); } # end if else ### Put whatever I got into the array we'll use later to append the result ### of this operation onto the results from the ifDescr fetch. ### push @ciscodescr, shift @descr; } # end if ($cisco_box && $vendor) # especially since cisco does not return a if # descr for each interface it has ... ## JB 2/8/97 - sometimes IOS inserts E1 controllers in the standard-MIB ## interface table, but not in the local interface table. This puts the ## local interface description table out-of-sync. the following ## modification skips over E1 cards as interfaces. # ### I suspect that the mod I made above, to use the ifAlias ### oid if possible, may cause problems here. If it seems ### that your descriptions are out of sync, try commenting ### out the "if ( condition )" and it's closing right brace ### so that the "shift @ciscodescr" get executed for *all* ### iterations of this loop. ### ### - mjd 2/5/95 ### if ($ciscobox && $siftype{$index} != 18) { $sciscodescr{$index} = "
      " . (shift @ciscodescr) if @ciscodescr; } }); my $index; foreach $index ( sort { $a <=> $b } keys %sifdesc) { my $c; my $speed = int($sifspeed{$index} / 8); # bits to byte my $speed_str=&fmi($speed); my $name="$iphost{$index}"; $name = "$router.$index" if not $name or $name =~ /\s/; if (($sifadminstatus{$index} != 1) # this check added by Josh - don't query E1-stack controllers || ($siftype{$index} == 18) || ($siftype{$index} == 24) || ($speed == 0 ) || ($speed > 400 * 10**6) #speeds of 400 MByte/s are not realistic || ($sifoperstatus{$index} == 3)) { print <Traffic Analysis for $sifdesc{$index} ${c} $sciscodescr{$index} ${c} ${c} ${c} ${c} ${c} ${c} ${c} ${c}
      System:$sysName in $sysLocation
      Maintainer:$sysContact
      Interface:$sifdesc{$index} ($index)
      IP:$iphost{$index} ($ipaddr{$index})
      Max Speed:$speed_str ($ifType_d{$siftype{$index}})
      ${c} #--------------------------------------------------------------- ECHO } } main; exit(0); sub fmi { my($number) = $_[0]; my(@short); @short = ("Bytes/s","kBytes/s","MBytes/s","GBytes/s"); my $digits=length("".$number); my $divm=0; while ($digits-$divm*3 > 4) { $divm++; } my $divnum = $number/10**($divm*3); return sprintf("%1.1f %s",$divnum,$short[$divm]); } mrtg-2.17.10/contrib/cfgmaker_cisco/README0000644000175300017510000000230613057016061017125 0ustar oetikeroepFolks, Jon Snyder here at Portland State University, made some modifications to the CFGMAKER file which instead of just returning an incrimenting port number on the graps, actually makes the following type of lable: Port 4/3, Vlan 128 , multi mode fiber fast ethernet This version also grabs and shows all non-VLAN1 VLANS in a different color, plus provides aggregate VLAN traffic stastics as well by finding out what ports are in the VLAN, then adding those ports together. This means of course that a port will be "hit" however many times it is in a VLAN. Anyhow, as it is such a small file, I included it as an attachment. We don't exacily have the time to provide support for this CFGMAKER modification, but if you have questions or comments, please direct them to JON@PDX.EDU. Michael P. Burton ________________________________________________________________________ Michael P. Burton "Love is like racing across the frozen tundra Network Engineer, DCII on a snowmobile which flips over, Portland State University trapping you underneath. At night, the ice-weasels come." - Nietchze ------------------------------------------------------------------------ mrtg-2.17.10/contrib/mrtglog/0000755000175300017510000000000013057016061014760 5ustar oetikeroepmrtg-2.17.10/contrib/mrtglog/mrtglog.h0000644000175300017510000000174013057016061016606 0ustar oetikeroep/***************************** ** woho's MRTG Logfile cgi ** *****************************/ // define the path to your htmldocs here: #define PFAD "/usr/local/httpd/htdocs" // default HTML header: #define HTMLHEAD "Content-type: text/html\n\n" // in english you'd write "Statistics" here: #define STATS "Auswertung" // just replace the german word, if necessary: #define FROM "von" // just replace the german word, if necessary: #define TO "bis" // This is the information at the end of the page. It tells that those month, // where no data exists, are skipped. // More info would be usefull, e.g. that mrtg logfiles only collect averages. #define INFOTEXT "ACHTUNG: Hier sind lediglich Durchschnittswerte der Messzeiträume (je 5 Min.) aufsummiert.
      Diese Statististik ist somit nicht sehr genau!
      Monate, für die keine Mengenaufzeichnungen existieren, werden automatisch ausgeblendet." // and in the end, the love you take, is equal to the love you make. (John Lennon)mrtg-2.17.10/contrib/mrtglog/mrtglog.c0000644000175300017510000001633213057016061016604 0ustar oetikeroep/***************************** ** woho's MRTG Logfile cgi ** *****************************/ #define VERSION "1.2" #include "./mrtglog.h" #include #include typedef struct { time_t t; float in; float out; } mrtg; int str2time(char *s); signed long runden(float zahl); /************************************/ int main(int argc, char *argv[]) { mrtg ar[3000]; int i, y, a1, a2, a3, a4 , a5, diff, newmon, oldmon=13, year; char s[128], *str, *ctmp, *start, *stop, *log, ch, ch2, ch3, hex[8]; time_t t1, t2; struct tm *zeit; float IN, OUT, ISUM=0, OSUM=0; FILE *fp; if (argc==4) { start = argv[1]; stop = argv[2]; log = argv[3]; } else { ctmp = (char *) getenv("QUERY_STRING"); //printf("%sQUERY_STRING: '%s'\n",HTMLHEAD,ctmp); if (ctmp) { y = strlen(ctmp) + 1; str = (char *)malloc (y * sizeof(char)); *str = '\0'; for (i = 0; i < strlen(ctmp); i++) { ch = ctmp[i]; // fflush (stdout); if (ctmp[i] == '+') ch = ' '; if (ctmp[i] == '%') { ch2 = ctmp[i+1]; ch3 = ctmp[i+2]; i += 2; snprintf (hex, sizeof(hex), "%c%c", ch2, ch3); ch = strtol (hex, NULL, 16); if ((ch == 10) || (ch == 13)) ch = ' '; } snprintf (&str[strlen(str)], y-strlen(str),"%c",ch); } while (str) { ctmp = str; while (*ctmp != '=' && *ctmp != '&') { *ctmp = tolower (*ctmp); ctmp++; } if ((char *)strstr(str,"start") == str) { start = ctmp+1; ctmp = (char *) strchr(start, '&'); } else if ((char *)strstr(str,"stop") == str) { stop = ctmp+1; ctmp = (char *) strchr(stop, '&'); } else if ((char *)strstr(str,"log") == str) { log = ctmp+1; ctmp = (char *) strchr(log, '&'); } else { printf("%sParameter '%s' Fehlerhaft\n",HTMLHEAD,str); exit(1); } if (ctmp) { str = ctmp+1; *ctmp = '\0'; } else str = NULL; } } } if (!start || !stop || !log) { printf("%sUsage: mrtglog 01/05/03 31/05/03 mrtg.log # Count all traffic in May 2003\n",HTMLHEAD); exit(1); } i = y = IN = OUT = 0; t1 = str2time(start); t2 = str2time(stop); sprintf(s,"%s%s.log",PFAD,log); fp = fopen(s,"r"); if (fp) { while (fgets(s, 100, fp)) { if (sscanf(s, "%d %d %d %d %d\n", &a1, &a2, &a3, &a4, &a5) == 5) { ar[y].t = a1; ar[y].in = a2; ar[y].out = a3; y++; } } fclose(fp); } else { printf("%scan't open '%s'!\n",HTMLHEAD,s); exit(1); } str = (char *) strrchr(log,'/'); if (str) *str++; else str = log; if (ctmp = (char *) strstr(str,".log")) *ctmp=0; printf("%s\n\n%s %s %s %s %s %s\n" "\n\n\ \n\ \n\ \n\ \n", HTMLHEAD,str,STATS,FROM,start,TO,stop,str,STATS,FROM,start,TO,stop); for (i = 0; i < y; i++) { if ((t1 <= ar[i].t) && (ar[i].t <= t2)) { zeit = gmtime((const time_t *)&ar[i].t); newmon = zeit->tm_mon; if ((oldmon != 13 && newmon != oldmon) || i+1 == y) { if (i+1 == y) { diff = ar[i].t - ar[i+1].t; IN = IN + ar[i].in * diff; OUT = OUT + ar[i].out * diff; } if (IN == 0 && OUT == 0) break; ISUM += IN; OSUM += OUT; printf("\n", year+1900,oldmon+1,runden(IN/1024/1024),runden(OUT/1024/1024),runden((IN+OUT)/1024/1024)); IN = OUT = 0; } if (i+1 < y) { oldmon = newmon; year = zeit->tm_year; diff = ar[i].t - ar[i+1].t; IN = IN + ar[i].in * diff; OUT = OUT + ar[i].out * diff; } } } /*if (IN != 0 || OUT != 0) { ISUM += IN; OSUM += OUT; printf("\n", year+1900,oldmon+1,runden(IN/1024/1024),runden(OUT/1024/1024),runden((IN+OUT)/1024/1024)); }*/ printf("\n\ \n

      %s

      \n\

      %s %s %s %s %s

      INOUTTOTAL
      %04i/%i%d MB%d MB%d MB
      %04i/%i%d MB%d MB%d MB
      TOTAL%d MB%d MB%d MB
      \n
      \n\ von \n\ bis \n\ \n\ \n\
      \n

      %s

      \n\ mrtglog %s, copyleft 2000 by http://www.netpark.at\n\n", runden(ISUM/1024/1024),runden(OSUM/1024/1024),runden((ISUM+OSUM)/1024/1024), argv[0],start,stop,log,INFOTEXT,VERSION); return 0; } /************************************/ int str2time(char *s) { struct tm tim; int d, m, y; if (sscanf(s, "%d.%d.%d", &d, &m, &y) != 3) { printf("%scant convert %s to date\n",HTMLHEAD, s); exit(10); } if (y < 100) y = y + 2000; tim.tm_sec = tim.tm_min = tim.tm_hour = 0; tim.tm_mday = d; tim.tm_mon = m - 1; tim.tm_year = y - 1900; return mktime(&tim); } /************************************/ signed long runden(float zahl) { signed long basis, nachkomma; if (!zahl) return 0; basis = zahl; if ((nachkomma = labs((zahl-basis)*10)) == 0) return basis; if (nachkomma > 5) { if (basis > 0) return ++basis; else return --basis; } else if (nachkomma < 5) return basis; else { nachkomma = labs((zahl-basis)*100); if (nachkomma > 50) { if (basis > 0) return ++basis; else return --basis; } else if (nachkomma < 50) return basis; else { nachkomma = labs((zahl-basis)*1000); if (nachkomma > 500) { if (basis > 0) return ++basis; else return --basis; } else if (nachkomma < 500) return basis; else { nachkomma = labs((zahl-basis)*10000); if (nachkomma > 5000) { if (basis > 0) return ++basis; else return --basis; } else if (nachkomma < 5000) return basis; else return basis; } } } } // and in the end, the love you take, is equal to the love you make. (John Lennon)mrtg-2.17.10/contrib/mrtglog/README0000644000175300017510000000160413057016061015641 0ustar oetikeroep/***************************** ** woho's MRTG Logfile cgi ** *****************************/ This is a very simple MRTG logfile summarizer. I don't give any warranties at all. I wrote and use it under Linux (SuSE Distribution). How to use: At first you should read and correct the enclosed mrtglog.h, e.g. for english language, if necessary. Then compile the code, using gcc -o /mrtglog.cgi ./mrtglog.c The usage is simple, e.g.: ./mrtglog 01/05/03 31/05/03 mrtg.log counts all traffic in May 2003. B-) I use a simple PHP3 script for calling it from my stats.php3 page: LOG", date("y",time()),date("d.m.y",time())); ?> If you have questions, please send me an e-mail: woho@netpark.at Wolfgang Hoffmann, Austria, http://www.woho.at #mrtg-2.17.10/contrib/GetSNMPLinesUP/0000755000175300017510000000000013057016061015762 5ustar oetikeroepmrtg-2.17.10/contrib/GetSNMPLinesUP/COPYRIGHT0000644000175300017510000000145213057016061017257 0ustar oetikeroep GetSNMPLinesUP.pl for MRTG - The Multi Router Traffic Grapher. Copyright (c) 1997 Carlos Canau . All rights reserved. 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 of the License, 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., 675 Mass Ave, Cambridge, MA 02139, USA. mrtg-2.17.10/contrib/GetSNMPLinesUP/sample.cfg0000644000175300017510000000136513057016061017731 0ustar oetikeroepTarget[dial-machine]: `/home/mrtg/bin/GetSNMPLinesUP.pl dial-machine` WithPeak[dial-machine]: wym Directory[dial-machine]: data Options[dial-machine]: growright, absolute, gauge MaxBytes[dial-machine]: 32 AbsMax[dial-machine]: 32 Title[dial-machine]: dial-machine : MODEMS/RDIS Unscaled[dial-machine]: dwyn YLegend[dial-machine]: Interfaces Colours[dial-machine]: GOLD1#ffd700,BLUE#1000ff,DARK GREEN#006600,VIOLET#ff00ff XSize[dial-machine]: 340 YSize[dial-machine]: 100 ShortLegend[dial-machine]: if's Legend1[dial-machine]: Legend2[dial-machine]: IF's Legend3[dial-machine]: Legend4[dial-machine]: Maximal 5 Minute IF's UP LegendI[dial-machine]: LegendO[dial-machine]:   if's: PageTop[dial-machine]:

      Number of Interfaces UP for dial-machine

      mrtg-2.17.10/contrib/GetSNMPLinesUP/COPYING0000644000175300017510000004307013057016061017021 0ustar oetikeroep GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy 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 of the License, 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., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. mrtg-2.17.10/contrib/GetSNMPLinesUP/ModemTable.dial-machine0000644000175300017510000000137713057016061022240 0ustar oetikeroepinterfaces.ifTable.ifEntry.ifOperStatus.3 interfaces.ifTable.ifEntry.ifOperStatus.4 interfaces.ifTable.ifEntry.ifOperStatus.5 interfaces.ifTable.ifEntry.ifOperStatus.6 interfaces.ifTable.ifEntry.ifOperStatus.7 interfaces.ifTable.ifEntry.ifOperStatus.8 interfaces.ifTable.ifEntry.ifOperStatus.9 interfaces.ifTable.ifEntry.ifOperStatus.10 interfaces.ifTable.ifEntry.ifOperStatus.11 interfaces.ifTable.ifEntry.ifOperStatus.12 interfaces.ifTable.ifEntry.ifOperStatus.13 interfaces.ifTable.ifEntry.ifOperStatus.14 interfaces.ifTable.ifEntry.ifOperStatus.15 interfaces.ifTable.ifEntry.ifOperStatus.16 interfaces.ifTable.ifEntry.ifOperStatus.17 interfaces.ifTable.ifEntry.ifOperStatus.18 interfaces.ifTable.ifEntry.ifOperStatus.19 interfaces.ifTable.ifEntry.ifOperStatus.20 mrtg-2.17.10/contrib/GetSNMPLinesUP/README0000644000175300017510000000167713057016061016655 0ustar oetikeroep GetSNMPLinesUP.pl for MRTG - The Multi Router Traffic Grapher. Copyright (c) 1997 Carlos Canau . All rights reserved. See the file COPYRIGHT in the distribution for the exact terms. See the file INSTALL for installation instructions. GetSNMPLinesUP.pl checks some SNMP variables for a certain value and returns their sum in a format used to feed values to MRTG. This was written in RedHat Linux 3.0.3 with a 2.0.29 kernel with perl 5.003. Other SO's may vary. Use at your own risk :> As usual no time to write much documentation. As usual read the source, send me questions, comments, changes, improvements and patches. I have to thank the following people: - Tobias Oetiker and Dave Rand for MRTG. - Peter W. Osel from whom I've ripped the README, INSTALL and COPYRIGHT file format from his wonderfull mrtg-ping-probe :>. mrtg-2.17.10/contrib/GetSNMPLinesUP/GetSNMPLinesUP.pl0000755000175300017510000000324313057016061021001 0ustar oetikeroep#!/usr/bin/perl # # Copyright (c) 1997 by Carlos Canau , EUnet Portugal. # All Rights Reserved. # # See the file COPYRIGHT in the distribution for the exact terms. # $SNMPGet = '/usr/bin/snmpget'; $TableBase = '/store/lib/mrtg/GetSNMPLinesUP/ModemTable'; $Community = "public"; $progname = 'GetSNMPLinesUP.pl'; $Router = $ARGV[0]; $Table = $ARGV[1] || "$TableBase.$Router"; $MAGICLEN = 20; $UPTIME = "system.sysUpTime.0"; $NAME = "system.sysName.0"; if (!$Router) { die "$progname: $progname ROUTER [TableFile]\n"; } $var = "$UPTIME $NAME "; $varlen = 2; $buzy = 0; if ( ! -r "$Table") { $Table = "$TableBase.$Router"; } open( TABLE, "$Table" ); while () { chop; $var = $var . $_ . " "; $varlen++; if ($varlen >= $MAGICLEN) { open( GET, "$SNMPGet -v 1 $Router $Community $var |" ); while ( ) { chop; ### printf "---%s\n", $_; if (/up\(1\)/) { $buzy++; }; ### if (/$UPTIME/) { if (/^system\.sysUpTime/) { ($dummy, $Uptime) = split(' = ', $_, 9999); } ### if (/$NAME/) { if (/^system\.sysName/) { ($dummy, $Name) = split(' = ', $_, 9999); } } close ( GET ); $var = ""; $varlen = 0; } } close( TABLE ); if ($varlen) { open( GET, "$SNMPGet -v 1 $Router $Community $var |" ); while ( ) { chop; ### printf "+++%s\n", $_; if (/up\(1\)/) { $buzy++; }; ### if (/$UPTIME/) { if (/^system\.sysUpTime/) { ($dummy, $Uptime) = split(' = ', $_, 9999); } ### if (/$NAME/) { if (/^system\.sysName/) { ($dummy, $Name) = split(' = ', $_, 9999); } } close ( GET ); } printf "$buzy\n"; printf "0\n"; # Unused printf "$Uptime\n"; printf "$Name\n"; mrtg-2.17.10/contrib/GetSNMPLinesUP/INSTALL0000644000175300017510000000065213057016061017016 0ustar oetikeroep Read the docs from MRTG :). Learn to use MRTG :). Change "ADMINDIR" in the Makefile to where you want to put the executable and the tables. Change "$SNMPGet", "$TableBase" and "$Community" in GetSNMPLinesUP.pl for your correct values. See sample.cfg for a sample configuration entry of a machine with some modems connected. See ModemTable.dial-machine for the corresponding variables to check in this sample. mrtg-2.17.10/contrib/GetSNMPLinesUP/Makefile0000644000175300017510000000151513057016061017424 0ustar oetikeroep# # # $Id: Makefile,v 1.1.1.1 2002/02/26 10:16:30 oetiker Exp $ # $Source: /home/oetiker/data/cvs-repo/AABM-mrtg/contrib/GetSNMPLinesUP/Makefile,v $ # $Log: Makefile,v $ # Revision 1.1.1.1 2002/02/26 10:16:30 oetiker # Intial Import # ADMINDIR=/home/mrtg/bin # RCSFILES CI = -ci CO = -co COFLAGS = -l CC = gcc CFLAGS = -O LIBS = -lresolv -l44bsd .c.o: $(CC) $(CFLAGS) -c $*.c TARGETS = ModemTable.dial-machine PROGS = GetSNMPLinesUP.pl RCSFILES = $(TARGETS) $(PROGS) all: install checkin: make clean $(CI) $(RCSFILES) $(CI) -u Makefile checkout: $(CO) $(COFLAGS) $(RCSFILES) $(CO) -l Makefile linux: make CFLAGS="-O -DLINUX" LIBS="" all install: $(PROGS) $(TARGETS) install -g staff -m 0644 -o root $(TARGETS) $(ADMINDIR) install -g staff -m 0755 -o root $(PROGS) $(ADMINDIR) clean: /bin/rm -f *~ *.o ,* core tmp* mrtg-2.17.10/contrib/ipchains/0000755000175300017510000000000013057016061015103 5ustar oetikeroepmrtg-2.17.10/contrib/ipchains/ipchainacc0000755000175300017510000000572513057016061017124 0ustar oetikeroep#!/usr/bin/perl # ipchainacc version 1.1.0 # Author: John Lange, john@darkcore.net # Date: September 12, 2000 # # This script was written to provide output for MRTG # (multi router traffic grapher) via ipchains. # # http://ee-staff.ethz.ch/~oetiker/webtools/mrtg/mrtg.html # ## Changelog # Sept 12, 2000 # v1.1.0 added flag for selection of graphing either packets, or bytes. # The default is packets (which is pretty useless), but since # the previous releases were graphing packets I kept the default # the same. # I always meant for this to be bytes but I only recently noticed # this bug so I added a config flag for bytes. # Also changed the uptime slightly, but its still broken. When # goes past 99 days, it will hack the last digit off (used to happen # after 9 days) # # June 22, 2000 # v1.0.1 added -x to ipchains to expand byte counters # # v1.0.0 Inital Release # # # This command must return 4 lines of output: # Line 1 : current state of the 'incoming bytes counter' # Line 2 : current state of the 'outgoing bytes counter' # Line 3 : string, telling the uptime of the target. # Line 4 : string, telling the name of the target. # This script relies on you having setup your ipchains rules beforehand #--- sample ipchains rules that will work with this script ## Add some empty rules for accounting purposes only # #/sbin/ipchains -F acctin #/sbin/ipchains -F acctout # ## add the new rules #/sbin/ipchains -N acctin #/sbin/ipchains -N acctout # ## empty rules on the chains #/sbin/ipchains -A acctin #/sbin/ipchains -A acctout # #/sbin/ipchains -I input -j acctin #/sbin/ipchains -I output -j acctout #----------- end --------------- ## edit for your system $ipchains='/sbin/ipchains'; # path to ipchains $host=`/bin/hostname --fqdn`; # local hostname (for information only) # if you use the ipchains rules above, you don't have to change these $inrule='acctin'; # name of input accounting rule $outrule='acctout'; # name of output accounting rule # What should we graph? packet counters = 0, bytes = 1 # If you used this script before and you want to keep counting # packets, then set this to 0. If you would rather do the # sensible thing and count bytes, then set this to 1. If you change # from one to the other, then you should delete all the previous # history since it will be meaningless. $bytec=0; ## -- don't edit below here ---- # fetch the status from ipchains $_=`$ipchains -L $inrule -v -n -x |grep -v -i Chain |grep -v -i pkts`; @in_bytes = split; printf "$in_line"; # just for debugging $_=`$ipchains -L $outrule -v -n -x |grep -v -i Chain |grep -v -i pkts`; @out_bytes = split; printf "$out_line"; # just for debugging #$c=1; #foreach $value (@in_bytes) { # printf "$c: $value\n"; # $c++; #}; # uptime of the machine open(UPTIME,"uptime |cut -b 13-27|"); $upTime=; close(UPTIME); chop $upTime; # 4 lines of output only. printf "$in_bytes[$bytec]\n$out_bytes[$bytec]\n$upTime\n$host"; mrtg-2.17.10/contrib/ipchains/README0000644000175300017510000000441513057016061015767 0ustar oetikeroepipchainacc 1.1.0 Author: John Lange john@darkcore.net Date : September 12, 2000 ipchains accounting script for use with MRTG *** New in this version *** *** please read before *** *** using this script *** *** In version 1.0.1, the script is actually counting packets, NOT bytes as was intended. I apologize for this mistake. By default, this new version of the script also counts packets NOT bytes. I've done this to maintain compatibility with the previous (buggy) version so that people who blindly upgrade won't suddenly find all of their output out of whack. To change to counting bytes, please edit the ipchainacc script. *** In order for this script to work: 1) You need a kernel which was compiled with the configuration option CONFIG_IP_FIREWALL set to y. You also need the front end to ip firewall and ip accounting, that is, the tool 'ipchains'. I used version 1.3.9. 2) Add input and output rules to ipchains for accounting. I've included the small script ipchainacc.rules. If you run it, it will do what it needs for ipchains to work with this script. I recommend you have a look at it before running it. It shouldn't break anything because it just adds some empty rules at the top of the input and output chains for accounting purposes. One concern however is that these rules have to be first on the chains to work. If you have some bad IPs black-holed these rules will still count packets from them which might be bad for server load. 2) edit the script ipchainacc for your system. You only need give it the path to ipchains and hostname. Alternatively, you can just remove the call to hostname and assign it manually. The ipchainacc script can also be run from the console if you want to see the output. 3) edit your mrtg.cfg for your system. For this script to be incorperated into mrtg, you need only add the following line to mrtg.cfg: Target[ipchains]: `/sbin/ipchainacc` 4) set mrtg to run as a cron (see the mrtg docs) ------ NOTE: this script is very basic. It captures accounting information for EVERYTHING coming in and out of your machine on all interfaces and IPs. If you need to narrow the accounting rules, you will have to edit the ipchainacc.rules script. I've included a very simple example in that script on how to narrow the accounting but it remains untested. mrtg-2.17.10/contrib/ipchains/ipchainacc.rules0000755000175300017510000000212713057016061020246 0ustar oetikeroep#!/bin/bash #--- sample ipchains rules for accounting # Flush the rules in case they exist already /sbin/ipchains -F acctin /sbin/ipchains -F acctout # add the new rule chains /sbin/ipchains -N acctin /sbin/ipchains -N acctout # add empty rules to the new chains just for accounting /sbin/ipchains -A acctin /sbin/ipchains -A acctout # insert rules into the input and output streams. # Packets will first pass through these rules before # returning to the other rules in the chains # You might not want this if you are trying to # completely ignore certain hosts. /sbin/ipchains -I input -j acctin /sbin/ipchains -I output -j acctout # if you wanted to narrow the accouting to a single IP # you could do these lines instead of the above 2 (not tested) # (assuming your IP address was 192.168.1.1) #/sbin/ipchains -I input -d 192.168.1.1 -j acctin #/sbin/ipchains -I output -s 192.168.1.1 -j acctout # By changing the rules, you can make it filter only exactly # what you want as long as it jumps to acctin, or acctout. # Be careful not to double count packets though. #----------- end --------------- mrtg-2.17.10/contrib/NSI/0000755000175300017510000000000013057016061013736 5ustar oetikeroepmrtg-2.17.10/contrib/NSI/Mrtg_nsi.cfg0000644000175300017510000004670313057016061016213 0ustar oetikeroep###################################################################### # Network Status Imager for MRTG -- Example Configuration File ###################################################################### # # * copy this file to ../run and call it mrtg-nsi.cfg # # Note: # # * Keywords must start at the begin of a line. # # * Lines which follow a keyword line which do start # with a blank are appended to the keyword line # # * Empty Lines are ignored # # * Lines starting with a # sign are comments. # #################### # Global Configuration # #################### # Where should the images be created? (Also location of the mrtg .log files) WorkDir: C:\\InetPub\\wwwroot\\mrtg # Where should your event-log page be created? EventLog: C:\\InetPub\\wwwroot\\mrtg\\mrtg-nsi-log.html # The maximum number of events kept in the event-log EventLogMax: 300 # What should the status map image be called? StatusMapImageName: map.gif # What is the main background image called? StatusMapBackGround: C:\\InetPub\\wwwroot\\mrtg\\mrtg_nsi-images\\sourcemap.gif # Where are your icons stored? IconDir: C:\\InetPub\\wwwroot\\mrtg\\mrtg_nsi-images # What is the absolute path to your message file MsgFile: C:\\InetPub\\mrtg\\run\\mrtg-nsi-msg.txt # What should be in the from field when sending out status e-mails? StatusEmailOrigin: mrtg-nsi.status-monitor@liebherr-us.com # -------------------------- # Optional Global Parameters # -------------------------- # How often do you call mrtg-nsi? The default is 5 minutes. If # you call it less often, you should specify it here. This # is to recoginze when we lost contact with a device. Interval: 5 # If you want to keep the mrtg-nsi source images in some place other than the # working directory, use the ImgSourceDir varibale to give its url. ImgSourceDir: C:\\InetPub\\wwwroot\\mrtg\\mrtg_nsi-images # To precisely locate your nodes on the map, this parameter allows you # to >ONLY< display a crosshair centered on the loaction of each particular node. TestNodeLocations: n # ################################################# # Configuration for each Note you want to image # ################################################# # The configuration keywords "Node" must be followed by a # unique name. ## ## Options ------------------------------------------ ## # The "Options" Keyword allows you to set some boolean # switches: # # AlarmIfNull - Sometimes a node needs to be recognized as in In, Alarm state when # mrtg reports zero (use with "mrtg-ping-probe"). ## ## A note about colors ------------------------------ ## # # .gif's always have a so called color table inside of them. Basically # a database of RGB values that have been allocated to the image already. # The problem with that is this: If the color table already has 255 entries # (and that's all a gif image takes) you'll see the following phenomenon: # Nsi will try to match the colors it produces itself by going though # the color pallette of the image, the result might sometimes look funny, # because it wasn't able to allocate the colors as close as you would have # expected it (they simply where not there)... # There is something you can do about this though: When you makeup the background # image for your status map, simply leave about 16 colors un-allocated... OR # put a small allocator bar in a corner that has the size of 16x1 pixels and # put 16 colored dots in there with the system colors... # ## ## A note about events, status log entries and e-mails - ## # # It is imperative that you run mrtg-nsi right after mrtg itself and NOT more # often than that, which is nonsense anyways, because the data nsi collects # from mrtg won't change during that period of course. Bad configurations are for example to # have nsi run in it's own cron or nt-at entry which could put it out of sync. # Best is to call mrtg through some type of shell script that has mrtg-nsi as # the next thing to do... # I'm mentioning this here because what is going to happen is this: Since nsi # triggers its events, subsequently log entries and status e-mails by looking # at the previous period in the mrtg logs and comparing it with the current # period, classifying the values as normal,warning or alert. When it does that, # it looks for a change in status and will trigger the event if there is a change. # The result is that you will get the same log entries/status e-mails twice or even more # often, depending on how often you run it between the period of time that mrtg # itself updates its data... This is not what you want, hard to track down and # this is why I mention this here. # ## ## Network Nodes ---------------------------------------- ## Node[Saline]: cisco01.ping.lgt.liebherr.com NodeCenterX[Saline]: 386 NodeCenterY[Saline]: 124 NodeWarningThreshhold[Saline]: 1300 NodeAlarmThreshhold[Saline]: 5000 NodeInCoolMsgID[Saline]: Saline0050 NodeInWarningMsgID[Saline]: Saline0051 NodeInAlarmMsgID[Saline]: Saline0052 NodeStatusEmail[Saline]: cwa NodeStatusEmailTarget[Saline]: mac.kloberg@lam.liebherr.com; chris.rock@lgt.liebherr.com Options[Saline]: AlarmIfNull Action.000100[Saline]: DrawNodeLine(In, Cool, NewportNews, Saline, LineStyleC1) Action.000200[Saline]: DrawNodeLine(In, Warning, NewportNews, Saline, LineStyleW1) #Action.000300[Saline]: DrawNodeLine(In, Alarm, NewportNews, Saline, LineStyleA1) Action.000900[Saline]: CopyImage(, Always, network1.gif, Saline.x - 16, Saline.y - 18) Action.000910[Saline]: DrawText(, Always,3,Saline.x-20,Saline.y+12,Saline0001,black) Action.000911[Saline]: DrawText(, Always,3,Saline.x-24,Saline.y+22,Saline0002,black) Node[Toronto]: cisco-lca-1.ping.lca.liebherr.com NodeCenterX[Toronto]: 447 NodeCenterY[Toronto]: 96 NodeWarningThreshhold[Toronto]: 1300 NodeAlarmThreshhold[Toronto]: 5000 NodeInCoolMsgID[Toronto]: Toronto0050 NodeInWarningMsgID[Toronto]: Toronto0051 NodeInAlarmMsgID[Toronto]: Toronto0052 NodeStatusEmail[Toronto]: cwa NodeStatusEmailTarget[Toronto]: mac.kloberg@lam.liebherr.com Options[Toronto]: AlarmIfNull Action.000100[Toronto]: DrawNodeLine(In, Cool, NewportNews, Toronto, LineStyleC1) Action.000200[Toronto]: DrawNodeLine(In, Warning, NewportNews, Toronto, LineStyleW1) #Action.000300[Toronto]: DrawNodeLine(In, Alarm, NewportNews, Toronto, LineStyleA1) Action.000900[Toronto]: CopyImage(, Always, network1.gif, Toronto.x - 16, Toronto.y - 18) Action.000910[Toronto]: DrawText(, Always,3,Toronto.x-24,Toronto.y+12,Toronto0001,black) Action.000911[Toronto]: DrawText(, Always,3,Toronto.x-23,Toronto.y+22,Toronto0002,black) Node[Montreal]: cisco-lca-2.ping.lca.liebherr.com NodeCenterX[Montreal]: 549 NodeCenterY[Montreal]: 56 NodeWarningThreshhold[Montreal]: 1300 NodeAlarmThreshhold[Montreal]: 5000 NodeInCoolMsgID[Montreal]: Montreal0050 NodeInWarningMsgID[Montreal]: Montreal0051 NodeInAlarmMsgID[Montreal]: Montreal0052 NodeStatusEmail[Montreal]: cwa NodeStatusEmailTarget[Montreal]: mac.kloberg@lam.liebherr.com Options[Montreal]: AlarmIfNull Action.000100[Montreal]: DrawNodeLine(In, Cool, NewportNews, Montreal, LineStyleC1) Action.000200[Montreal]: DrawNodeLine(In, Warning, NewportNews, Montreal, LineStyleW1) #Action.000300[Montreal]: DrawNodeLine(In, Alarm, NewportNews, Montreal, LineStyleA1) Action.000900[Montreal]: CopyImage(, Always, network1.gif, Montreal.x - 16, Montreal.y - 18) Action.000910[Montreal]: DrawText(, Always,3,Montreal.x-34,Montreal.y+12,Montreal0001,black) Action.000911[Montreal]: DrawText(, Always,3,Montreal.x-26,Montreal.y+22,Montreal0002,black) Node[Houston]: cisco-lcr-1.ping.lcr.liebherr.com NodeCenterX[Houston]: 191 NodeCenterY[Houston]: 391 NodeWarningThreshhold[Houston]: 1300 NodeAlarmThreshhold[Houston]: 5000 NodeInCoolMsgID[Houston]: Houston0050 NodeInWarningMsgID[Houston]: Houston0051 NodeInAlarmMsgID[Houston]: Houston0052 NodeStatusEmail[Houston]: cwa NodeStatusEmailTarget[Houston]: mac.kloberg@lam.liebherr.com Options[Houston]: AlarmIfNull Action.000100[Houston]: DrawNodeLine(In, Cool, NewportNews, Houston, LineStyleC1) Action.000200[Houston]: DrawNodeLine(In, Warning, NewportNews, Houston, LineStyleW1) #Action.000300[Houston]: DrawNodeLine(In, Alarm, NewportNews, Houston, LineStyleA1) Action.000900[Houston]: CopyImage(, Always, network1.gif, Houston.x - 16, Houston.y - 18) Action.000910[Houston]: DrawText(, Always,3,Houston.x+20,Houston.y+2,Houston0001,black) Action.000911[Houston]: DrawText(, Always,3,Houston.x+26,Houston.y+12,Houston0002,black) Node[Baxter]: cisco-lme-1.ping.lme.liebherr.com NodeCenterX[Baxter]: 196 NodeCenterY[Baxter]: 233 NodeWarningThreshhold[Baxter]: 1300 NodeAlarmThreshhold[Baxter]: 5000 NodeInCoolMsgID[Baxter]: Baxter0050 NodeInWarningMsgID[Baxter]: Baxter0051 NodeInAlarmMsgID[Baxter]: Baxter0052 NodeStatusEmail[Baxter]: cwa NodeStatusEmailTarget[Baxter]: mac.kloberg@lam.liebherr.com; allen.cunningham@lme.liebherr.com Options[Baxter]: AlarmIfNull Action.000100[Baxter]: DrawNodeLine(In, Cool, NewportNews, Baxter, LineStyleC1) Action.000200[Baxter]: DrawNodeLine(In, Warning, NewportNews, Baxter, LineStyleW1) #Action.000300[Baxter]: DrawNodeLine(In, Alarm, NewportNews, Baxter, LineStyleA1) Action.000900[Baxter]: CopyImage(, Always, network1.gif, Baxter.x - 16, Baxter.y - 18) Action.000910[Baxter]: DrawText(, Always,3,Baxter.x-50,Baxter.y+12,Baxter0001,black) Action.000911[Baxter]: DrawText(, Always,3,Baxter.x-20,Baxter.y+22,Baxter0002,black) Node[Gillette]: cisco-lme-2.ping.lme.liebherr.com NodeCenterX[Gillette]: 22 NodeCenterY[Gillette]: 82 NodeWarningThreshhold[Gillette]: 1300 NodeAlarmThreshhold[Gillette]: 5000 NodeInCoolMsgID[Gillette]: Gillette0050 NodeInWarningMsgID[Gillette]: Gillette0051 NodeInAlarmMsgID[Gillette]: Gillette0052 NodeStatusEmail[Gillette]: cwa NodeStatusEmailTarget[Gillette]: mac.kloberg@lam.liebherr.com; allen.cunningham@lme.liebherr.com Options[Gillette]: AlarmIfNull Action.000100[Gillette]: DrawNodeLine(In, Cool, NewportNews, Gillette, LineStyleC1) Action.000200[Gillette]: DrawNodeLine(In, Warning, NewportNews, Gillette, LineStyleW1) #Action.000300[Gillette]: DrawNodeLine(In, Alarm, NewportNews, Gillette, LineStyleA1) Action.000900[Gillette]: CopyImage(, Always, network1.gif, Gillette.x - 16, Gillette.y - 18) Action.000910[Gillette]: DrawText(, Always,3,Gillette.x-15,Gillette.y+12,Gillette0001,black) Action.000911[Gillette]: DrawText(, Always,3,Gillette.x-10,Gillette.y+22,Gillette0002,black) Node[InternetGW]: newportnews-gw1-ping.lam.liebherr.com NodeCenterX[InternetGW]: 547 NodeCenterY[InternetGW]: 180 NodeWarningThreshhold[InternetGW]: 1300 NodeAlarmThreshhold[InternetGW]: 5000 NodeInCoolMsgID[InternetGW]: InternetGW0050 NodeInWarningMsgID[InternetGW]: InternetGW0051 NodeInAlarmMsgID[InternetGW]: InternetGW0052 NodeStatusEmail[InternetGW]: cwa NodeStatusEmailTarget[InternetGW]: mac.kloberg@lam.liebherr.com; chris.rock@lgt.liebherr.com; allen.cunningham@lme.liebherr.com Options[InternetGW]: AlarmIfNull Action.000001[InternetGW]: DrawNodeLine(In, Cool, NewportNews, InternetGW, LineStyleC1) Action.000002[InternetGW]: DrawNodeLine(In, Warning, NewportNews, InternetGW, LineStyleW1) Action.000020[InternetGW]: CopyImage(In, Cool, attcerfnet.gif, InternetGW.x-22, InternetGW.y) Action.000021[InternetGW]: CopyImage(In, Warning, attcerfnet.gif, InternetGW.x-22, InternetGW.y) Node[Eurotunnel]: pptp.hamptonkirchdorf NodeCenterX[Eurotunnel]: 575 NodeCenterY[Eurotunnel]: 235 NodeWarningThreshhold[Eurotunnel]: 1300 NodeAlarmThreshhold[Eurotunnel]: 5000 NodeInCoolMsgID[Eurotunnel]: Eurotunnel0050 NodeInWarningMsgID[Eurotunnel]: Eurotunnel0051 NodeInAlarmMsgID[Eurotunnel]: Eurotunnel0052 NodeStatusEmail[Eurotunnel]: cwa NodeStatusEmailTarget[Eurotunnel]: mac.kloberg@lam.liebherr.com; dieter.kummerer@zdv.liebherr.com; brian.check@lme.liebherr.com Options[Eurotunnel]: AlarmIfNull Action.000100[Eurotunnel]: DrawNodeLine(In, Cool, NewportNews, Eurotunnel, LineStyleC1) Action.000200[Eurotunnel]: DrawNodeLine(In, Warning, NewportNews, Eurotunnel, LineStyleW1) Action.000900[Eurotunnel]: CopyImage(In, Cool, sgflag.gif, Eurotunnel.x - 26, Eurotunnel.y+2) Action.000901[Eurotunnel]: CopyImage(In, Warning, sgflag.gif, Eurotunnel.x - 26, Eurotunnel.y+2) Action.000910[Eurotunnel]: DrawText(In, Cool,2,Eurotunnel.x-53,Eurotunnel.y-13,Eurotunnel0001,black) Action.000911[Eurotunnel]: DrawText(In, Warning,2,Eurotunnel.x-53,Eurotunnel.y-13,Eurotunnel0001,black) Node[NewportNews]: cisco-lam-1.lam.liebherr.com NodeCenterX[NewportNews]: 499 NodeCenterY[NewportNews]: 235 NodeWarningThreshhold[NewportNews]: 1300 NodeAlarmThreshhold[NewportNews]: 5000 NodeStatusEmail[NewportNews]: cwa NodeStatusEmailTarget[NewportNews]: mac.kloberg@lam.liebherr.com Options[NewportNews]: AlarmIfNull Action.000900[NewportNews]: CopyImage(, Always, network1.gif, NewportNews.x - 16, NewportNews.y - 18) Action.000910[NewportNews]: DrawText(, Always,3,NewportNews.x-40,NewportNews.y+12,NewportNews0001,black) Action.000911[NewportNews]: DrawText(, Always,3,NewportNews.x-26,NewportNews.y+22,NewportNews0002,black) # # E-Mail/MTA Monitoring # Node[NewportNewsEmailX400Kirchdorf]: hampton.mta.x400hamptonkirchdorf.lam.liebherr.com NodeCenterX[NewportNewsEmailX400Kirchdorf]: 557 NodeCenterY[NewportNewsEmailX400Kirchdorf]: 255 NodeWarningThreshhold[NewportNewsEmailX400Kirchdorf]: 30 NodeAlarmThreshhold[NewportNewsEmailX400Kirchdorf]: 100 NodeInCoolMsgID[NewportNewsEmailX400Kirchdorf]: NewportNewsEmailX400Kirchdorf0050 NodeInWarningMsgID[NewportNewsEmailX400Kirchdorf]: NewportNewsEmailX400Kirchdorf0051 NodeInAlarmMsgID[NewportNewsEmailX400Kirchdorf]: NewportNewsEmailX400Kirchdorf0052 NodeStatusEmail[NewportNewsEmailX400Kirchdorf]: cwa NodeStatusEmailTarget[NewportNewsEmailX400Kirchdorf]: mac.kloberg@lam.liebherr.com Action.000900[NewportNewsEmailX400Kirchdorf]: MultiCopyImage(, Always, envelope.gif, NewportNewsEmailX400Kirchdorf.x, NewportNewsEmailX400Kirchdorf.y, $incurrent / 10, 1, 35, -5, 270) Node[NewportNewsEmailX400Baxter]: hampton.mta.x400hamptonlti.lam.liebherr.com NodeCenterX[NewportNewsEmailX400Baxter]: 451 NodeCenterY[NewportNewsEmailX400Baxter]: 229 NodeWarningThreshhold[NewportNewsEmailX400Baxter]: 30 NodeAlarmThreshhold[NewportNewsEmailX400Baxter]: 100 NodeInCoolMsgID[NewportNewsEmailX400Baxter]: NewportNewsEmailX400Baxter0050 NodeInWarningMsgID[NewportNewsEmailX400Baxter]: NewportNewsEmailX400Baxter0051 NodeInAlarmMsgID[NewportNewsEmailX400Baxter]: NewportNewsEmailX400Baxter0052 NodeStatusEmail[NewportNewsEmailX400Baxter]: cwa NodeStatusEmailTarget[NewportNewsEmailX400Baxter]: mac.kloberg@lam.liebherr.com; allen.cunningham@lme.liebherr.com Action.000900[NewportNewsEmailX400Baxter]: MultiCopyImage(, Always, envelope.gif, NewportNewsEmailX400Baxter.x, NewportNewsEmailX400Baxter.y, $incurrent / 10, 1, 23, -5, 180) Node[NewportNewsEmailX400Saline]: hampton.mta.x400hamptongarfield.lam.liebherr.com NodeCenterX[NewportNewsEmailX400Saline]: 465 NodeCenterY[NewportNewsEmailX400Saline]: 203 NodeWarningThreshhold[NewportNewsEmailX400Saline]: 30 NodeAlarmThreshhold[NewportNewsEmailX400Saline]: 100 NodeInCoolMsgID[NewportNewsEmailX400Saline]: NewportNewsEmailX400Saline0050 NodeInWarningMsgID[NewportNewsEmailX400Saline]: NewportNewsEmailX400Saline0051 NodeInAlarmMsgID[NewportNewsEmailX400Saline]: NewportNewsEmailX400Saline0052 NodeStatusEmail[NewportNewsEmailX400Saline]: cwa NodeStatusEmailTarget[NewportNewsEmailX400Saline]: mac.kloberg@lam.liebherr.com; chris.rock@lgt.liebherr.com Action.000900[NewportNewsEmailX400Saline]: MultiCopyImage(, Always, envelope.gif, NewportNewsEmailX400Saline.x, NewportNewsEmailX400Saline.y, $incurrent / 10, 1, 10, -5, 135) Node[NewportNewsEmailX400Burlington]: hampton.mta.x400hamptonburlington.lam.liebherr.com NodeCenterX[NewportNewsEmailX400Burlington]: 481 NodeCenterY[NewportNewsEmailX400Burlington]: 195 NodeWarningThreshhold[NewportNewsEmailX400Burlington]: 30 NodeAlarmThreshhold[NewportNewsEmailX400Burlington]: 100 NodeInCoolMsgID[NewportNewsEmailX400Burlington]: NewportNewsEmailX400Burlington0050 NodeInWarningMsgID[NewportNewsEmailX400Burlington]: NewportNewsEmailX400Burlington0051 NodeInAlarmMsgID[NewportNewsEmailX400Burlington]: NewportNewsEmailX400Burlington0052 NodeStatusEmail[NewportNewsEmailX400Burlington]: cwa NodeStatusEmailTarget[NewportNewsEmailX400Burlington]: mac.kloberg@lam.liebherr.com Action.000900[NewportNewsEmailX400Burlington]: MultiCopyImage(, Always, envelope.gif, NewportNewsEmailX400Burlington.x, NewportNewsEmailX400Burlington.y, $incurrent / 10, 1, 10, -5, 111) Node[NewportNewsEmailIMC]: hampton.mta.x400hamptonimc.lam.liebherr.com NodeCenterX[NewportNewsEmailIMC]: 515 NodeCenterY[NewportNewsEmailIMC]: 207 NodeWarningThreshhold[NewportNewsEmailIMC]: 30 NodeAlarmThreshhold[NewportNewsEmailIMC]: 100 NodeInCoolMsgID[NewportNewsEmailIMC]: NewportNewsEmailIMC0050 NodeInWarningMsgID[NewportNewsEmailIMC]: NewportNewsEmailIMC0051 NodeInAlarmMsgID[NewportNewsEmailIMC]: NewportNewsEmailIMC0052 NodeStatusEmail[NewportNewsEmailIMC]: cwa NodeStatusEmailTarget[NewportNewsEmailIMC]: mac.kloberg@lam.liebherr.com Action.000900[NewportNewsEmailIMC]: MultiCopyImage(, Always, envelope.gif, NewportNewsEmailIMC.x, NewportNewsEmailIMC.y, $incurrent / 10, 1, 20, -5, 0) Node[SalineEmailX400Hampton]: garfield.mta.x400garfieldhampton.lgt.liebherr.com NodeCenterX[SalineEmailX400Hampton]: 418 NodeCenterY[SalineEmailX400Hampton]: 157 NodeWarningThreshhold[SalineEmailX400Hampton]: 30 NodeAlarmThreshhold[SalineEmailX400Hampton]: 100 NodeInCoolMsgID[SalineEmailX400Hampton]: SalineEmailX400Hampton0050 NodeInWarningMsgID[SalineEmailX400Hampton]: SalineEmailX400Hampton0051 NodeInAlarmMsgID[SalineEmailX400Hampton]: SalineEmailX400Hampton0052 NodeStatusEmail[SalineEmailX400Hampton]: cwa NodeStatusEmailTarget[SalineEmailX400Hampton]: mac.kloberg@lam.liebherr.com; chris.rock@lgt.liebherr.com Action.000900[SalineEmailX400Hampton]: MultiCopyImage(, Always, envelope.gif, SalineEmailX400Hampton.x, SalineEmailX400Hampton.y, $incurrent / 10, 1, 20, -5, 315) Node[TorontoEmailX400Hampton]: burlington.mta.x400burlingtonhampton.lca.liebherr.com NodeCenterX[TorontoEmailX400Hampton]: 456 NodeCenterY[TorontoEmailX400Hampton]: 131 NodeWarningThreshhold[TorontoEmailX400Hampton]: 30 NodeAlarmThreshhold[TorontoEmailX400Hampton]: 100 NodeInCoolMsgID[TorontoEmailX400Hampton]: TorontoEmailX400Hampton0050 NodeInWarningMsgID[TorontoEmailX400Hampton]: TorontoEmailX400Hampton0051 NodeInAlarmMsgID[TorontoEmailX400Hampton]: TorontoEmailX400Hampton0052 NodeStatusEmail[TorontoEmailX400Hampton]: cwa NodeStatusEmailTarget[TorontoEmailX400Hampton]: mac.kloberg@lam.liebherr.com Action.000900[TorontoEmailX400Hampton]: MultiCopyImage(, Always, envelope.gif, TorontoEmailX400Hampton.x, TorontoEmailX400Hampton.y, $incurrent / 10, 1, 20, -5, 291) Node[BaxterEmailX400Hampton]: hampton.mta.x400hamptonlti.lam.liebherr.com NodeCenterX[BaxterEmailX400Hampton]: 217 NodeCenterY[BaxterEmailX400Hampton]: 229 NodeWarningThreshhold[BaxterEmailX400Hampton]: 30 NodeAlarmThreshhold[BaxterEmailX400Hampton]: 100 NodeInCoolMsgID[BaxterEmailX400Hampton]: BaxterEmailX400Hampton0050 NodeInWarningMsgID[BaxterEmailX400Hampton]: BaxterEmailX400Hampton0051 NodeInAlarmMsgID[BaxterEmailX400Hampton]: BaxterEmailX400Hampton0052 NodeStatusEmail[BaxterEmailX400Hampton]: cwa NodeStatusEmailTarget[BaxterEmailX400Hampton]: mac.kloberg@lam.liebherr.com; allen.cunningham@lme.liebherr.com Action.000900[BaxterEmailX400Hampton]: MultiCopyImage(, Always, envelope.gif, BaxterEmailX400Hampton.x, BaxterEmailX400Hampton.y, $incurrent / 10, 1, 23, -5, 0) mrtg-2.17.10/contrib/NSI/mrtg-nsi-msg.txt0000644000175300017510000001476613057016061017041 0ustar oetikeroep###################################################################### # Network Status Imager for MRTG -- Example Message File ###################################################################### # # All texts displayed by NSI have to be defined here # # * copy this file to ../run and call it mrtg-nsi-msg.txt # # Note: #ri # * Every text entry should have the syntax: # # * Keys can be everything, but must match what you've defined in the # config file. Keys are case insensitive. # # * Empty Lines are ignored # # * Lines starting with a # sign are comments. # # * Valid variables in these lines are: # - $NodeWarningThreshhold #The nodes warning threshold # - $NodeAlarmThreshhold #The nodes alarm threshold # - $NodeIn #In value of the node # - $NodeOut #Out value of the node # # Node Names and Descriptions # Saline0001: Saline, Saline0002: Michigan Saline0050: Frame relay connection to Saline is back up. Saline0051: Frame relay connection to Saline is congested. Ping response time ($NodeInms) exceeded limit ($NodeWarningThreshholdms). Saline0052: Frame relay connection to Saline is down. (prt.$NodeInms/max.$NodeAlarmThreshholdms) Toronto0001: Toronto, Toronto0002: Ontario Toronto0050: Frame relay connection to Toronto is back up. Toronto0051: Frame relay connection to Toronto is congested. Ping response time ($NodeInms) exceeded limit ($NodeWarningThreshholdms). Toronto0052: Frame relay connection to Toronto is down. (prt.$NodeInms/max.$NodeAlarmThreshholdms) Montreal0001: Montreal, Montreal0002: Quebec Montreal0050: Frame relay connection to Montreal is back up. Montreal0051: Frame relay connection to Montreal is congested. Ping response time ($NodeInms) exceeded limit ($NodeWarningThreshholdms). Montreal0052: Frame relay connection to Montreal is down. (prt.$NodeInms/max.$NodeAlarmThreshholdms) Baxter0001: Baxter Springs, Baxter0002: Kansas Baxter0050: Frame relay connection to Baxter Springs is back up. Baxter0051: Frame relay connection to Baxter Springs is congested. Ping response time ($NodeInms) exceeded limit ($NodeWarningThreshholdms). Baxter0052: Frame relay connection to Baxter Springs is down. (prt.$NodeInms/max.$NodeAlarmThreshholdms) Gillette0001: Gillette, Gillette0002: Wyoming Gillette0050: Frame relay connection to Gillette is back up. Gillette0051: Frame relay connection to Gillette is congested. Ping response time ($NodeInms) exceeded limit ($NodeWarningThreshholdms). Gillette0052: Frame relay connection to Gillette is down. (prt.$NodeInms/max.$NodeAlarmThreshholdms) NewportNews0001: Newport News, NewportNews0002: Virginia Houston0001: Houston, Houston0002: Texas Houston0050: Frame relay connection to Houston is back up. Houston0051: Frame relay connection to Houston is congested. Ping response time ($NodeInms) exceeded limit ($NodeWarningThreshholdms). Houston0052: Frame relay connection to Houston is down. (prt.$NodeInms/max.$NodeAlarmThreshholdms) InternetGW0001: Internet Connection InternetGW0050: Internet Connection is back up. InternetGW0051: Internet Connection is congested. Ping response time ($NodeInms) exceeded limit ($NodeWarningThreshholdms). InternetGW0052: Internet Connection is down. (prt.$NodeInms/max.$NodeAlarmThreshholdms) Eurotunnel0001: IP-Tunnel Eurotunnel0050: PPTP connection to Kirchdorf is back up. (prt.$NodeInms/max.$NodeAlarmThreshholdms) Eurotunnel0051: PPTP connection to Kirchdorf is congested. Ping response time ($NodeInms) exceeded limit ($NodeWarningThreshholdms). Eurotunnel0052: PPTP connection to Kirchdorf is down. (prt.$NodeInms/max.$NodeAlarmThreshholdms) NewportNewsEmailX400Kirchdorf0050: MTA Hampton -> Kirchdorf is clearing up again (Currently $NodeIn messages in queue). NewportNewsEmailX400Kirchdorf0051: MTA Hampton -> Kirchdorf is starting to show signs of congestion (Currently $NodeIn messages in queue and building up). NewportNewsEmailX400Kirchdorf0052: MTA Hampton -> Kirchdorf is congested. (Currently $NodeIn messages in queue). NewportNewsEmailX400Baxter0050: MTA Hampton -> Baxter Springs is clearing up again (Currently $NodeIn messages in queue). NewportNewsEmailX400Baxter0051: MTA Hampton -> Baxter Springs is starting to show signs of congestion (Currently $NodeIn messages in queue and building up). NewportNewsEmailX400Baxter0052: MTA Hampton -> Baxter Springs is congested. (Currently $NodeIn messages in queue). NewportNewsEmailX400Saline0050: MTA Hampton -> Saline is clearing up again (Currently $NodeIn messages in queue). NewportNewsEmailX400Saline0051: MTA Hampton -> Saline is starting to show signs of congestion (Currently $NodeIn messages in queue and building up). NewportNewsEmailX400Saline0052: MTA Hampton -> Saline is congested. (Currently $NodeIn messages in queue). NewportNewsEmailX400Burlington0050: MTA Hampton -> Toronto is clearing up again (Currently $NodeIn messages in queue). NewportNewsEmailX400Burlington0051: MTA Hampton -> Toronto is starting to show signs of congestion (Currently $NodeIn messages in queue and building up). NewportNewsEmailX400Burlington0052: MTA Hampton -> Toronto is congested. (Currently $NodeIn messages in queue). NewportNewsEmailIMC0050: Internet Mail Service is clearing up again (Currently $NodeIn messages in queue). NewportNewsEmailIMC0051: Internet Mail Service is starting to show signs of congestion (Currently $NodeIn messages in queue and building up). NewportNewsEmailIMC0052: Internet Mail Service is congested. (Currently $NodeIn messages in queue). SalineEmailX400Hampton0050: MTA Saline -> Hampton is clearing up again (Currently $NodeIn messages in queue). SalineEmailX400Hampton0051: MTA Saline -> Hampton is starting to show signs of congestion (Currently $NodeIn messages in queue and building up). SalineEmailX400Hampton0052: MTA Saline -> Hampton is congested. (Currently $NodeIn messages in queue). TorontoEmailX400Hampton0050: MTA Toronto -> Hampton is clearing up again (Currently $NodeIn messages in queue). TorontoEmailX400Hampton0051: MTA Toronto -> Hampton is starting to show signs of congestion (Currently $NodeIn messages in queue and building up). TorontoEmailX400Hampton0052: MTA Toronto -> Hampton is congested. (Currently $NodeIn messages in queue). BaxterEmailX400Hampton0050: MTA Baxter Springs -> Hampton is clearing up again (Currently $NodeIn messages in queue). BaxterEmailX400Hampton0051: MTA Baxter Springs -> Hampton is starting to show signs of congestion (Currently $NodeIn messages in queue and building up). BaxterEmailX400Hampton0052: MTA Baxter Springs -> Hampton is congested. (Currently $NodeIn messages in queue). # # Common messages # mrtg-2.17.10/contrib/NSI/Mrtg_nsi0000644000175300017510000012516513057016061015455 0ustar oetikeroep#! /usr/bin/perl # -*- mode: Perl -*- BEGIN{ #$main::OS = 'UNIX'; $main::OS = 'NT'; #$main::OS = 'VMS'; ################################################################## # MRTG-NSI 1.0 Network Status Imager for MRTG ################################################################## # Created by: Mac Kloberg # # WARNING: This thing was developed 'quick and dirty' on WinNT... # I've never actually tried this on Unix or VMS, so I # don't know if it will work. Guess you'll find out... # Send me mail... # # Built and based on: MRTG by Tobias Oetiker # and Dave Rand # # Credits: THANKS, TOBI AND DAVE!!! K.U.T.G.W. # ################################################################# # # Distributed under the GNU copyleft # ################################################################### # The path separator is a slash, backslash or semicolon, depending # on the platform. $main::SL = { UNIX=>'/', WINDOWS=>'\\', NT=>'\\', VMS=>'' }->{$main::OS}; # The search path separator is a colon or semicolon depending on the # operating system. $main::PS = { UNIX=>':', WINDOWS=>';', NT=>';', VMS=>':' }->{$main::OS}; # We need to find the place where mrtg is installed, and # then take it from there... $main::binpath =""; if ($0 =~ /^(.+\Q${main::SL}\E)/) { $main::binpath="$1"; } else { foreach $pathname ( split ${main::PS}, $ENV{'PATH'}) { if ((($main::OS eq 'NT') && (-e "$pathname${main::SL}$0")) || (-x "$pathname${main::SL}$0")) { $main::binpath=$pathname; last; } } } die "ERROR: Can\'t find location of mrtg executable\n" unless $main::binpath; unshift (@INC,$main::binpath); } # There older perls tend to behave peculiar with # large integers ... require 5.003; if ($main::OS eq 'UNIX' || $main::OS eq 'NT') { use GD; use Net::SMTP; #requires libnet package to be installed #use SNMP_Session "0.71"; #use BER "0.66"; #use SNMP_util "0.71"; use locales_mrtg "0.01"; use Config; #$main::SNMPDEBUG =0; } #Doesn't seem to work very well with the win32 port of GD #use strict; if($main::OS eq 'UNIX') { my($i) = 0; my($name); foreach $name (split(/ /, $Config{sig_name})) { $main::signo{$name} = $i; $main::signame[$i++] = $name; } } $main::DEBUG=1; sub END { local($?, $!); unlink ${main::Cleanfile} if($main::Cleanfile); } sub main { my ($router, $target ,$gdstyles, $neweventcounter, $eventcounter, $newevents, $neweventstype); # unbuffer stdout to see everything immediately $|=1 if $main::DEBUG; print "\nMRTG - Network Status Imager loading & initializing...\n\n" if $main::DEBUG; my ($routers, $cfg, $rcfg, $cfgfile) = readcfg(); $target = cfgcheck($routers, $cfg, $rcfg); print "Locking Config Files...\n"; # Check the config and create the target object # lets make sure that there are not two mrtg-nsi's running in parallel. # so we lock on the cfg file. Nothing fancy, just a lockfile # my $lockfile = $cfgfile."_l"; my $templock = $cfgfile."_l_" . $$ ; if ($main::OS eq 'VMS' || $main::OS eq 'NT') { # too sad NT and VMS can't do links we'll do the diletants lock if (-e $lockfile && not unlink $lockfile){ my($lockage) = time()-(stat($lockfile))[9]; die ("ERROR: I guess another mrtg-nsi is running. A lockfile ($lockfile) aged $lockage seconds is hanging around and I can't remove it because another process is still using it."); } open (LOCK, ">$lockfile") or die "ERROR: Can't create lockfile $lockfile\n"; print LOCK "$$\n"; close LOCK; open (LOCK, "<$lockfile") or die "ERROR: Can't open lockfile $lockfile for owner check\n"; my($read)=; chomp($read); die "ERROR: Someone else just got the lockfile $lockfile\n" unless $$ == $read; } else { # now, lets do it the UNIX way ... Daves work ... open(LOCK,">$templock") || die "Can't create templock $templock"; $main::Cleanfile = $templock; if (!link($templock,$lockfile)) { # Lock file exists - deal with it. my($nlink,$lockage) = (stat($lockfile))[3,9]; $lockage = time() - $lockage; if ($nlink < 2 || $lockage > 30*60) { #lockfile is alone and old unlink($lockfile) || do{ unlink $templock; die "ERROR: Can't unlink stale lockfile ($lockfile). Permissions?\n"}; link($templock,$lockfile) || do{ unlink $templock; die "ERROR: Can't create lockfile ($lockfile).\n". "Permission problem or another mrtg locking succesfully?\n"}; } else { unlink $templock; die ("ERROR: I guess another mrtg is running. A lockfile ($lockfile) aged\n". "$lockage seconds is hanging around. If you are sure that no other mrtg\n". "is running you can remove the lockfile\n"); } } } #Read the messages my($msg) = readmsgfile($$cfg{'msgfile'}); open (BACKGROUNDIMG,"<$$cfg{'statusmapbackground'}") || die "ERROR: Can't open StatusMapBackGround\n"; my($ImageData) = newFromGif GD::Image(BACKGROUNDIMG) || die "ERROR: GD::newFromGif\n"; close BACKGROUNDIMG; #Allocate colors for this image... my %defcolors = (#Color allocation table 'black', "0,0,0", 'red', "255,0,0", 'green', "0,255,0", 'blue', "0,0,255", 'yellow', "255,250,205", 'white', "255,0,0" ); %colors = (); while(($color, $cvalue) = each(%defcolors)){ #Try to allocate our color if($ImageData->colorAllocate(split(/,/,$cvalue)) ne "-1"){ $colors{$color} = $ImageData->colorAllocate(split(/,/,$cvalue)); }else{ #Didn't work, we'll have to match the closest then $colors{$color} = $ImageData->colorClosest(split(/,/,$cvalue)); } } #Define our linestyles $$gdstyles{'linestylec1'}{'style'} = "$colors{'yellow'},$colors{'yellow'},$colors{'yellow'},$colors{'yellow'},$colors{'blue'},$colors{'blue'},$colors{'blue'},$colors{'blue'},gdTransparent,gdTransparent"; $$gdstyles{'linestylew1'}{'style'} = "$colors{'red'},$colors{'red'},$colors{'red'},$colors{'red'},$colors{'blue'},$colors{'blue'},$colors{'blue'},$colors{'blue'},gdTransparent,gdTransparent"; $$gdstyles{'linestylea1'}{'style'} = "$colors{'red'},$colors{'red'},$colors{'blue'},$colors{'red'},$colors{'red'},$colors{'red'},$colors{'blue'},$colors{'blue'},gdTransparent,gdTransparent,gdTransparent,gdTransparent,gdTransparent,gdTransparent,gdTransparent,gdTransparent,gdTransparent"; drawtext($ImageData, $gdstyles, $cfg, $rcfg, $routers, $router, "cool", "cool", "", "always", "1", "baxter.x", "baxter.y", "baxtersprings", "black",); $neweventcounter = 0; foreach $router (@$routers) { my($savetz) = $ENV{'TZ'}; if ($$rcfg{'timezone'}{$router} ne '') { $ENV{'TZ'} = $$rcfg{'timezone'}{$router} } print "Imaging node: $router\n"; # set the locale my($LOC); if( $$cfg{'language'} && defined($lang2tran::LOCALE{"\L$$cfg{'language'}\E"})) { $LOC=$lang2tran::LOCALE{"\L$$cfg{'language'}\E"}; } else { $LOC=$lang2tran::LOCALE{'default'}; }; #Node test... if($$cfg{'testnodelocations'} =~ /y/i){ action_draw_crosshair($ImageData, $cfg, $rcfg, $routers, $router, $$rcfg{'nodecenterx'}{$router},$$rcfg{'nodecentery'}{$router},$black); next; #Normal node processing }else{ my ($incurrent, $outcurrent, $inlast, $outlast) = getnodevalues($$rcfg{'node'}{$router}, $router, $rcfg, $cfg); #DEBUG --- DEBUG --- DEBUG --- DEBUG --- DEBUG --- DEBUG --- DEBUG --- #if ($router =~ /NewportNewsEmailX400Kirchdorf/i){ #$inlast = 0;$incurrent = 50; #$inlast = 5000;$incurrent = 100; #} #DEBUG --- DEBUG --- DEBUG --- DEBUG --- DEBUG --- DEBUG --- DEBUG --- my ($nodeinstatus,$nodeoutstatus) = getnodestatus($incurrent,$outcurrent,$$rcfg{'node'}{$router}, $router, $rcfg, $cfg); my ($nodeinlaststatus,$nodeoutlaststatus) = getnodestatus($inlast,$outlast,$$rcfg{'node'}{$router}, $router, $rcfg, $cfg); print "NodeStatus-Old: $nodeinlaststatus($inlast)/$nodeoutlaststatus($outlast)\n"; print "NodeStatus-New: $nodeinstatus($incurrent)/$nodeoutstatus($outcurrent)\n"; #Generate events for the log and status-email my $ineventid = ""; my $outeventid = ""; my $ineventtype = ""; my $outeventtype = ""; #Cool event (in) if($nodeinstatus eq "cool" && $nodeinlaststatus eq "alarm" && defined $$rcfg{'nodeincoolmsgid'}{$router}){$ineventid = lc($$rcfg{'nodeincoolmsgid'}{$router});$ineventtype = "Cool";}; #Cool event (in) if($nodeinstatus eq "warning" && $nodeinlaststatus eq "alarm" && defined $$rcfg{'nodeincoolmsgid'}{$router}){$ineventid = lc($$rcfg{'nodeincoolmsgid'}{$router});$ineventtype = "Cool";}; #Warning event (in) if($nodeinstatus eq "warning" && $nodeinlaststatus eq "cool" && defined $$rcfg{'nodeinwarningmsgid'}{$router}){$ineventid = lc($$rcfg{'nodeinwarningmsgid'}{$router});$ineventtype = "Warn";}; #Alarm event (in) if($nodeinstatus eq "alarm" && ($nodeinlaststatus eq "cool" || $nodeinlaststatus eq "warning") && defined $$rcfg{'nodeinalarmmsgid'}{$router}){$ineventid = lc($$rcfg{'nodeinalarmmsgid'}{$router});$ineventtype = "Alarm";}; #Cool event (out) if($nodeoutstatus eq "cool" && $nodeoutlaststatus eq "alarm" && defined $$rcfg{'nodeoutcoolmsgid'}{$router}){$outeventid = lc($$rcfg{'nodeoutcoolmsgid'}{$router});$outeventtype = "Cool";}; #Cool event (out) if($nodeoutstatus eq "warning" && $nodeoutlaststatus eq "alarm" && defined $$rcfg{'nodeoutcoolmsgid'}{$router}){$outeventid = lc($$rcfg{'nodeoutcoolmsgid'}{$router});$outeventtype = "Cool";}; #Warning event (out) if($nodeoutstatus eq "warning" && $nodeoutlaststatus eq "cool" && defined $$rcfg{'nodeoutwarningmsgid'}{$router}){$outeventid = lc($$rcfg{'nodeoutwarningmsgid'}{$router});$outeventtype = "Warn";}; #Alarm event (out) if($nodeoutstatus eq "alarm" && ($nodeoutlaststatus eq "cool" || $nodeoutlaststatus eq "warning") && defined $$rcfg{'nodeoutalarmmsgid'}{$router}){$outeventid = lc($$rcfg{'nodeoutalarmmsgid'}{$router});$outeventtype = "Cool";}; #Log events (in) if($ineventid ne ""){ $newevents[$neweventcounter] = $$msg{$ineventid}; #Translate variables in the event message $newevents[$neweventcounter] = transeventvar($cfg, $rcfg, $routers, $router, $incurrent, $outcurrent, $newevents[$neweventcounter]); #Anybody needs to know about this? if($$rcfg{'email'}{lc($ineventtype)}{$router}){ $neweventstype[$neweventcounter] = "$ineventtype/e"; sendmail($cfg, $rcfg, $routers, $router, $incurrent, $outcurrent, $newevents[$neweventcounter],$neweventstype[$neweventcounter],$$rcfg{'nodestatusemailtarget'}{$router}); }else{ $neweventstype[$neweventcounter] = $ineventtype; } $neweventcounter++; } #Log events (out) if($outeventid ne ""){ $newevents[$neweventcounter] = $$msg{$outeventid}; $neweventstype[$neweventcounter] = $outeventtype; #Translate variables in the event message $newevents[$neweventcounter] = transeventvar($cfg, $rcfg, $routers, $router, $incurrent, $outcurrent, $newevents[$neweventcounter]); #Anybody needs to know about this? if($$rcfg{'email'}{lc($outeventtype)}{$router}){ $neweventstype[$neweventcounter] = "$outeventtype/e"; sendmail($cfg, $rcfg, $routers, $router, $incurrent, $outcurrent, $newevents[$neweventcounter],$neweventstype[$neweventcounter],$$rcfg{'nodestatusemailtarget'}{$router}); }else{ $neweventstype[$neweventcounter] = $outeventtype; } $neweventcounter++; } #Main action loop, the right sequencing is important because of overlappling graphics in the status map for ($actioncounter = 0; $actioncounter <= $$rcfg{maxaction}{$router}; $actioncounter++){ if (exists $$rcfg{"action.$actioncounter"}{$router}) { my $action = $$rcfg{"action.$actioncounter"}{$router}; my @acfunctelements = split(/\(/,$action); my $acfunc = $acfunctelements[0]; #Cleanup the function name $acfunc=~s/\s/ /g; $acfunc=~s/^ *//g; $acfunc=~s/ *$//g; $acfunc=lc($acfunc); my @acfunctelements = split(/[\(\)]/,$action); my @acargs = split(/,/,$acfunctelements[1]); #Cleanup the functions arguments and put them in parethesis... foreach $acarg (@acargs){ $acarg=~s/\s/ /g; $acarg=~s/^ *//g; $acarg=~s/ *$//g; $acarg=lc($acarg); $acarg="\"$acarg\","; } #Execute Action eval("$acfunc(\$ImageData, \$gdstyles, \$cfg, \$rcfg, \$routers, \$router, \$msg, \"$nodeinstatus\", \"$nodeoutstatus\", \"$incurrent\" , \"$outcurrent\", @acargs);"); die "* Problem with action statement: $acfunc(\$ImageData, \$gdstyles, \$cfg, \$rcfg, \$routers, \$router, \$msg, \"$nodeinstatus\", \"$nodeoutstatus\", \"$incurrent\" , \"$outcurrent\", @acargs);\n" if $@; } } } #put TZ things back in shape ... if ($savetz) {$ENV{'TZ'} = $savetz;} else {delete $ENV{'TZ'}}; } #If there are no events, don't do anything if ($neweventcounter > 0){ #Open current log file and get the old log entries open (LOGFILE,"<$$cfg{'workdir'}\\mrtg-nsi.log") || print "WARNING: Couldn't open eventlog file for reading: $$cfg{'workdir'}//mrtg-nsi.log\n"; my @oldeventloglines = ; close LOGFILE; #Open eventlog again and add new events open (LOGFILE,">$$cfg{'workdir'}\\mrtg-nsi.log") || die "ERROR: Couldn't open eventlog file for writing: $$cfg{'workdir'}//mrtg-nsi.log\n"; open (HTMLLOG,">$$cfg{'eventlog'}") || die "ERROR: Couldn't open eventlog file for writing: $$cfg{'eventlog'}\n"; #Add header to the html-log print HTMLLOG "\n"; print HTMLLOG "\n"; print HTMLLOG "\n"; print HTMLLOG "\n"; print HTMLLOG "\n"; print HTMLLOG "Home Page\n"; print HTMLLOG "\n"; print HTMLLOG "\n"; print HTMLLOG "\n"; print HTMLLOG "\n"; print HTMLLOG "

      Network Status Imager: Event Log
      \n"; print HTMLLOG "
      NSI v1.0 for MRTG, Created by Mac\n"; print HTMLLOG "Kloberg <mac.kloberg\@lam.liebherr.com> <mac\@nacs.net>)
      \n"; print HTMLLOG "Credits to Tobias Oetiker <oetiker\@ee.ethz.ch> and Dave Rand <dlr\@bungi.com>.
      \n"; print HTMLLOG "Sofware distributed under the GNU copyleft."; print HTMLLOG "
      \n"; print HTMLLOG "

      \n"; print HTMLLOG "\n"; print HTMLLOG "
      \n"; print HTMLLOG " \n"; print HTMLLOG " \n"; print HTMLLOG " \n"; print HTMLLOG " \n"; print HTMLLOG " \n"; print HTMLLOG " \n"; print HTMLLOG "
      DateTimeType Event
      \n"; print HTMLLOG "\n"; print HTMLLOG " \n"; for ($logfileeventcounter = 0; $logfileeventcounter <= $$cfg{'eventlogmax'}; $logfileeventcounter++){ #Add new events if($logfileeventcounter eq 0){ for ($neweventlogcounter = 0; $neweventlogcounter < $neweventcounter; $neweventlogcounter++){ my $shortdatestr = &shortdatestr(time); print LOGFILE "$shortdatestr - $neweventstype[$neweventlogcounter] - $newevents[$neweventlogcounter]\n"; my($htmldate,,$htmltime) = split(/ - /,$shortdatestr); print HTMLLOG " \n"; print HTMLLOG " \n"; print HTMLLOG " \n"; print HTMLLOG " \n"; print HTMLLOG " \n"; if($neweventstype[$neweventlogcounter] =~ /cool.*/i){ print HTMLLOG " \n"; print HTMLLOG " \n"; print HTMLLOG " \n"; print HTMLLOG " \n"; print HTMLLOG " \n"; } } #Add old events if($logfileeventcounter > 0 && $oldeventloglines[$logfileeventcounter-1] ne ""){ print LOGFILE "$oldeventloglines[$logfileeventcounter-1]"; #print "Writing oldevent ($logfileeventcounter): $oldeventloglines[$logfileeventcounter-1]
      "; my($htmldate,$htmltime,$htmleventtype,$htmlevent) = split(/ - /,$oldeventloglines[$logfileeventcounter-1]); print HTMLLOG " \n"; print HTMLLOG " \n"; print HTMLLOG " \n"; print HTMLLOG " \n"; print HTMLLOG " \n"; if($htmleventtype =~ /cool.*/i){ print HTMLLOG " \n"; print HTMLLOG " \n"; print HTMLLOG " \n"; print HTMLLOG " \n"; print HTMLLOG " \n"; } } print HTMLLOG "
      $htmldate-$htmltime$neweventstype[$neweventlogcounter]$newevents[$neweventlogcounter]\n"; } if($neweventstype[$neweventlogcounter] =~ /warn.*/i){ print HTMLLOG " $newevents[$neweventlogcounter]\n"; } if($neweventstype[$neweventlogcounter] =~ /alarm.*/i){ print HTMLLOG " $newevents[$neweventlogcounter]\n"; } print HTMLLOG "
      $htmldate-$htmltime$htmleventtype$htmlevent\n"; } if($htmleventtype =~ /warn.*/i){ print HTMLLOG " $htmlevent\n"; } if($htmleventtype =~ /alarm.*/i){ print HTMLLOG " $htmlevent\n"; } print HTMLLOG "
      \n"; print HTMLLOG "\n"; print HTMLLOG "\n"; close HTMLLOG; close LOGFILE; } #Finally, timestamp the image my($ImgSizeX,$ImgSizeY) = $ImageData->getBounds; $Today=&datestr(time); my $stampstring = "Network Status Imager for MRTG - $Today"; my $stringwidth = GD::Font::width(gdSmallFont) * length($stampstring); $ImageData->string(gdSmallFont,$ImgSizeX - $stringwidth - 3,$ImgSizeY - 13,"$stampstring",$colors{'black'}); #Write the whole thing to the status map open (STATUSMAP,">$$cfg{'workdir'}\\\\$$cfg{statusmapimagename}") || die "ERROR: Couldn't write to status map image $$cfg{'workdir'}\\\\$$cfg{statusmapimagename}"; binmode STATUSMAP; print STATUSMAP $ImageData->gif; close STATUSMAP; # OK we are done, remove the lock files ... print "Removing Lockfiles\n"; close LOCK; unlink ($templock, $lockfile); print "\nMRTG - Network Status Imager unloading, gone and done...\n\n" if $main::DEBUG; } main; exit(0); sub readcfg { my ($first,$second,$key); my (%seen); my (@routers); my (%rcfg,%cfg,%pre,%post,%deflt,%defaulted); my ($cfgfile) = pop(@ARGV); open (CFG, $cfgfile) || do { print "ERROR: unable to open config file: $cfgfile\n\n"; &printusage }; while () { s/\s+$//g; #remove whitespace at the end of the line s/\s/ /g; #replace whitespace by space next if /^\s*\#/; #ignore comment lines next if /^\s*$/; #ignore empty lines # oops spelling error s/^supress/suppress/gi; #Trashcan leading zeros in action statements s/^action\.0+/action\./gi; #Also lets record the number of the highest action given for later if ($first =~ /^action.+/){ $actionnumber = $first; $actionnumber =~ s/action\.//gi; if($actionnumber > $rcfg{'maxaction'}{$second}){ $rcfg{'maxaction'}{$second} = $actionnumber; } } # append mode if ($first && /^\s+(.*\S)\s*$/) { if ($second eq '^') { $pre{$first} .= " $1"; next; } if ($second eq '$' ) { $post{$first} .= " $1"; next; } if ($second eq '_') { $deflt{$first} .= " $1"; next; } if ($second) { $rcfg{$first}{$second} .= " $1"; } else { $cfg{$first} .= " $1"; } next; } if ($first && $second && $post{$first} && ($second !~ /^[\$^_]$/)) { if ($defaulted{$first}{$second}) { $rcfg{$first}{$second} = $post{$first}; delete $defaulted{$first}{$second}; } else { $rcfg{$first}{$second} .= " $post{$first}" } } if ($first && exists $deflt{$first} && ($second eq '_')) { &quickcheck($first,$second,$deflt{$first},$.) } elsif ($first && $second && ($second !~ /^[\$^_]$/)) { &quickcheck($first,$second,$rcfg{$first}{$second},$.) } elsif ($first && ($second !~ /^[\$^_]$/)) { &quickcheck($first,0,$cfg{$first},$.) } if (/^([A-Za-z0-9\.]+)\[(\S+)\]\s*:\s*(.*\S?)\s*$/) { print "readcfg: rcfg $1 $2 = $3\n" if $main::DEBUG > 1; $first = lc($1); $second = lc($2); if ($second eq '^') { if ($3 ne '') {$pre{$first}=$3} else {delete $pre{$first}}; next; } if ($second eq '$') { if ($3 ne '') {$post{$first}=$3} else {delete $post{$first}}; next; } if ($second eq '_') { if ($3 ne '') {$deflt{$first}=$3} else {delete $deflt{$first}}; next; } push (@routers, $second) unless grep (/^$second$/, @routers); # make sure that default tags spring into existance upon first # call of a router foreach $key (keys %deflt) { if (! exists $rcfg{$key}{$second}) { $rcfg{$key}{$second} = $deflt{$key}; $defaulted{$key}{$second} = 1; } } # make sure that prefix-only tags spring into existance upon first # call of a router foreach $key (keys %pre) { if (! exists $rcfg{$key}{$second}) { delete $defaulted{$key}{$second} if $defaulted{$key}{$second}; $rcfg{$key}{$second} = "$pre{$key} "; } } if ($seen{$first}{$second}) { die ("\nLine $. in CFG file contains a duplicate definition for\n". "$first\[$second]. First definition is on line $seen{$first}{$second}\n") } else { $seen{$first}{$second} = $.; } if ($defaulted{$first}{$second}) { $rcfg{$first}{$second} = ''; delete $defaulted{$first}{$second}; } $rcfg{$first}{$second} .= $3; next; } if (/^(\S+):\s*(.*\S)\s*$/) { $first = lc($1); $cfg{$first} = $2; $second = ''; next; } die ( "\nLine $. in CFG file does not make sense\n" ); } # append $ stuff to the very last tag in cfg file if necessary if ($first && $second && $post{$first} && ($second !~ /^[\$^_]$/)) { if ($defaulted{$first}{$second}) { $rcfg{$first}{$second} = $post{$first}; delete $defaulted{$first}{$second}; } else { $rcfg{$first}{$second} .= " $post{$first}" } } #Tobi, I don't know how you did this, but this is something else: #Get highest action number for the last line in the config file... if ($first =~ /^action.+/){ $actionnumber = $first; $actionnumber =~ s/action\.//gi; if($actionnumber > $rcfg{'maxaction'}{$second}){ $rcfg{'maxaction'}{$second} = $actionnumber; } } #check the last input line if ($first && exists $deflt{$first} && ($second eq '_')) { &quickcheck($first,$second,$deflt{$first},$.) } elsif ($first && $second) { &quickcheck($first,$second,$rcfg{$first}{$second},$.) } elsif ($first) { &quickcheck($first,0,$cfg{$first},$.) } close (CFG); (\@routers, \%cfg, \%rcfg, $cfgfile); } sub cfgcheck { my ($routers, $cfg, $rcfg) = @_; my ($rou, $confname, $one_option); my %node; my $error="no"; my(@known_options) = qw(alarmifnull); if (! $$cfg{workdir}) { warn ("\nERROR: \"WorkDir\" not specified\n"); $error = "yes"; } foreach $rou (@$routers) { if ($$rcfg{'directory'}{$rou}) { # They specified a directory for this router. Append the # pathname seperator to it (so that it can either be present or # absent, and the rules for including it are the same). $$rcfg{'directory'}{$rou} .= ${main::SL}; # remove any stray spaces ... $$rcfg{'directory'}{$rou} =~ s/\s//g; } # Configure e-mail notification for this node if (defined($$rcfg{'nodestatusemail'}{$rou})){ if($$rcfg{'nodestatusemailtarget'}{$rou} ne ""){ if($$rcfg{'nodestatusemail'}{$rou} =~ /[^cwa *]/i ){ warn ("\nERROR: NodeStatusEmail[$rou]: \"$$rcfg{'nodestatusemail'}{$rou}\" contains invalid options [cwa].\n"); $error="yes"; }else{ if($$rcfg{'nodestatusemail'}{$rou} =~ /c/i ){ $$rcfg{'email'}{'cool'}{$rou} = 1; } if($$rcfg{'nodestatusemail'}{$rou} =~ /w/i ){ $$rcfg{'email'}{'warn'}{$rou} = 1; } if($$rcfg{'nodestatusemail'}{$rou} =~ /a/i ){ $$rcfg{'email'}{'alarm'}{$rou} = 1; } } }else{ warn ("\nERROR: NodeStatusEmail[$rou]: \"$$rcfg{'nodestatusemail'}{$rou}\" is given but no NodeStatusEmailTarget[$rou] was found.\n"); $error="yes"; } } if (exists $$rcfg{"options"}{$rou}) { foreach $one_option (split /[,\s]+/, lc($$rcfg{"options"}{$rou})) { if (grep {$one_option eq $_} @known_options) { $$rcfg{'options'}{$one_option}{$rou} = 1; } else { warn ("\nERROR: Option[$rou]: \"$one_option\" is unknown\n"); $error="yes"; } } } if ($error eq "yes") { die ("\n\nABORT: Please fix the error(s) in your config file\n\n"); } } \%node; } sub quickcheck { my ($first,$second,$arg,$line) = @_; my %rules = (# General CFG 'workdir' => ['$arg && (-d $arg)','"Directory $arg does not exist"'], 'eventlog' => ['$arg','"Eventlog path is missing"'], 'eventlogmax' => ['$arg =~ /\d+/','"You must specify a value"'], 'icondir' => ['$arg && (-d $arg)','"Directory $arg does not exist"'], 'statusmapbackground' => ['$arg && (-f $arg)','"Image file $arg does not exist"'], 'statusmapimagename' => ['$arg','"Target image name is missing"'], 'imgsourcedir' => ['$arg && (-d $arg)','"Directory $arg does not exist"'], 'msgfile' => ['$arg && (-f $arg)','"Message file $arg does not exist"'], 'statusemailorigin' => ['$arg =~ /\w+/','"You must specify something for this option"'], 'refresh' => ['int($arg) >= 300', '"$arg should be 300 seconds or more"'], 'interval' => ['int($arg) >= 5','"$arg should be more than 5 Minutes"'], 'testnodelocations' => ['$arg =~ /[ynYN]/','"This option is either y or n"'], #Nodes CFG 'node[]' => ['$arg =~ /\w+/','"You must specify something for this option"'], 'nodecenterx[]' => ['int($arg) >= 0', '"$arg <-- Value cannot be negative"'], 'nodecentery[]' => ['int($arg) >= 0', '"$arg <-- Value cannot be negative"'], 'nodealarmthreshhold[]' => ['$arg =~ /\d+/','"You must specify a value"'], 'nodewarningthreshhold[]' => ['$arg =~ /\d+/','"You must specify a value"'], 'nodeincoolmsgid[]' => ['$arg =~ /\w+/','"You must specify something for this option"'], 'nodeinwarningmsgid[]' => ['$arg =~ /\w+/','"You must specify something for this option"'], 'nodeinalarmmsgid[]' => ['$arg =~ /\w+/','"You must specify something for this option"'], 'nodeoutcoolmsgid[]' => ['$arg =~ /\w+/','"You must specify something for this option"'], 'nodeoutwarningmsgid[]' => ['$arg =~ /\w+/','"You must specify something for this option"'], 'nodeoutalarmmsgid[]' => ['$arg =~ /\w+/','"You must specify something for this option"'], 'nodestatusemail[]' => ['$arg =~ /\w+/','"You must specify something for this option"'], 'nodestatusemailtarget[]' => ['$arg =~ /\w+/','"You must specify something for this option"'], 'options[]' => ['1','"Internal Error"'], 'action[]' => ['$arg =~ /\w+/','"You must specify something for this option"'], ); my $braces = $second ? '[]':''; #The actions are different from the other options if ($first =~ /^action.+/){ if ($first =~ /action.\d*/) { return 1; } }elsif (exists $rules{$first.$braces}) { if (eval($rules{$first.$braces}[0])) { return 1; } else { if ($second) { die "\nCFG Error in \"$first\[$second\]\", line $line: ". eval($rules{$first.$braces}[1])."\n\n"; } else { die "\nCFG Error in \"$first\", line $line: ". eval($rules{$first.$braces}[1])."\n\n"; } } } die "\nCFG Error: Unknown Option \"$first\" on line $line or above.\n". " Check readme.html for Help\n\n"; } sub readmsgfile { my ($msgfile) = @_; my ($first,$second,$key); my (%seen); my (%rmsg,%msg,%pre,%post); open (MSGFILE, $msgfile) || do { print "ERROR: unable to open message file: $msgfile\n\n"}; while () { s/\s+$//g; #remove whitespace at the end of the line s/\s/ /g; #replace whitespace by space next if /^\s*\#/; #ignore comment lines next if /^\s*$/; #ignore empty lines # append mode if ($first && /^\s+(.*\S)\s*$/) { if ($second eq '^') { $pre{$first} .= " $1"; next; } if ($second eq '$' ) { $post{$first} .= " $1"; next; } if ($second) { $rmsg{$first}{$second} .= " $1"; } else { $msg{$first} .= " $1"; } next; } if (/^(\S+):\s*(.*\S)\s*$/) { $first = lc($1); $msg{$first} = $2; $second = ''; next; } die ( "\nLine $. in MSGFILE file does not make sense\n" ); } close (MSGFILE); (\%msg); } sub action_draw_crosshair { #This one draws a crosshair symbol my($ImageData, $cfg, $rcfg, $routers, $router, $cox, $coy,$color) = @_; $cox = nsi_eval($ImageData, $cfg, $rcfg, $routers, $router, $cox); $cox = $cox + nsi_eval($ImageData, $cfg, $rcfg, $routers, $router, $$rcfg{'nodelabeloffsetx'}{$router}); $coy = nsi_eval($ImageData, $cfg, $rcfg, $routers, $router, $coy); $coy = $coy + nsi_eval($ImageData, $cfg, $rcfg, $routers, $router, $$rcfg{'nodelabeloffsety'}{$router}); #Draw the crosshair... $ImageData->arc($cox,$coy,30,30,0,360,$color); $ImageData->arc($cox,$coy,20,20,0,360,$color); $ImageData->arc($cox,$coy,10,10,0,360,$color); $ImageData->line($cox-17,$coy,$cox+17,$coy,$color); $ImageData->line($cox,$coy-17,$cox,$coy+17,$color); } sub datestr { my ($time) = shift(@_) || return 0; my ($wday) = ('Sunday','Monday','Tuesday','Wednesday', 'Thursday','Friday','Saturday')[(localtime($time))[6]]; my ($month) = ('January','February' ,'March' ,'April' , 'May' , 'June' , 'July' , 'August' , 'September' , 'October' , 'November' , 'December' )[(localtime($time))[4]]; my ($mday,$year,$hour,$min,$sec) = (localtime($time))[3,5,2,1,0]; if ($min<10) {$min = "0$min";} if ($sec<10) {$sec = "0$sec";} return "$wday, $month $mday, ".($year+1900)." - $hour:$min:$sec"; } sub shortdatestr { my ($time) = shift(@_) || return 0; my ($mday,$month,$year,$hour,$min,$sec) = (localtime($time))[3,4,5,2,1,0]; $month++; if ($min<10) {$min = "0$min";} if ($sec<10) {$sec = "0$sec";} return "$month/$mday/".($year+1900)." - $hour:$min:$sec"; } sub nsi_eval { #Replace references to other nodes and evaluate expressions my($ImageData, $cfg, $rcfg, $routers, $router, $evali) = @_; #Replace .xy-references to other nodes foreach $eval_node (@$routers) { my $lceval_node = lc($eval_node); #Replace "node.x" $evali =~ s/[\W]$lceval_node\.x/$$rcfg{'nodecenterx'}{$eval_node}/gie; $evali =~ s/^$lceval_node\.x/$$rcfg{'nodecenterx'}{$eval_node}/gie; #Replace "node.y" $evali =~ s/[\W]$lceval_node\.y/$$rcfg{'nodecentery'}{$eval_node}/gie; $evali =~ s/^$lceval_node\.y/$$rcfg{'nodecentery'}{$eval_node}/gie; } #If something else expanded from the nodecenter, evaluate that too... $evali = lc($evali); foreach $eval_node (@$routers) { my $lceval_node = lc($eval_node); #Replace "node.x" $evali =~ s/[\W]$lceval_node\.x/$$rcfg{'nodecenterx'}{$eval_node}/gie; $evali =~ s/^$lceval_node\.x/$$rcfg{'nodecenterx'}{$eval_node}/gie; #Replace "node.y" $evali =~ s/[\W]$lceval_node\.y/$$rcfg{'nodecentery'}{$eval_node}/gie; $evali =~ s/^$lceval_node\.y/$$rcfg{'nodecentery'}{$eval_node}/gie; } #Evaluate and format the expression $evali = sprintf("%.0f",eval($evali)); return $evali; } sub getnodevalues { my ($target, $rou, $rcfg, $cfg) = @_; my $period = 0; my $lastperiod = 0; my $incurrent=0; my $outcurrent=0; my $inlast = 0; my $outlast = 0; open (LOG, "<$$cfg{'workdir'}\\\\$target.log") or die "ERROR: Can't open .log file for this node: $target\n"; my($counterline,$line,$lastline) = ; ($period,$incurrent,$outcurrent)=split(/\D/,$line); ($lastperiod,$inlast,$outlast)=split(/\D/,$lastline); close LOG; #Check the period (if we're too far out, we've probably lost contact with the node) $time = time unless defined $time; my($timediff)=$time - $period; #Give it 2 more minutes, then report the node as down if($timediff > $$cfg{'interval'} * 60 + 120){ $incurrent = -1; $outcurrent = -1; } ($incurrent, $outcurrent, $inlast, $outlast); } sub getnodestatus{ my ($incurrent,$outcurrent,$target, $router, $rcfg, $cfg) = @_; my $nodeinstatus = "cool"; my $nodeoutstatus = "cool"; #Node down? if($incurrent eq -1){ $nodeinstatus = "alarm"; $nodeoutstatus = "alarm"; }else{ #Which direction are we looking? if($$rcfg{'nodealarmthreshhold'}{$router} >= $$rcfg{'nodewarningthreshhold'}{$router}){ #Straight forward if($incurrent > $$rcfg{'nodewarningthreshhold'}{$router}){ $nodeinstatus = "warning"; } if($outcurrent > $$rcfg{'nodewarningthreshhold'}{$router}){ $nodeoutstatus = "warning"; } if($incurrent > $$rcfg{'nodealarmthreshhold'}{$router}){ $nodeinstatus = "alarm"; } if($outcurrent > $$rcfg{'nodealarmthreshhold'}{$router}){ $nodeoutstatus = "alarm"; } }else{ #Backwards if($incurrent < $$rcfg{'nodewarningthreshhold'}{$router}){ $nodeinstatus = "warning"; } if($outcurrent < $$rcfg{'nodewarningthreshhold'}{$router}){ $nodeoutstatus = "warning"; } if($incurrent < $$rcfg{'nodealarmthreshhold'}{$router}){ $nodeinstatus = "alarm"; } if($outcurrent < $$rcfg{'nodealarmthreshhold'}{$router}){ $nodeoutstatus = "alarm"; } } } #Check for nulls if($$rcfg{'options'}{'alarmifnull'}{$router}){ if($incurrent eq "0"){ $nodeinstatus = "alarm"; } if($outcurrent eq "0"){ $nodeoutstatus = "alarm"; } } ($nodeinstatus,$nodeoutstatus); } sub drawnodeline{ my ($ImageData, $gdstyles, $cfg, $rcfg, $routers, $router, $msg, $nodeinstatus, $nodeoutstatus, $incurrent, $outcurrent, $direction, $cond, $source, $destination, $style) = @_; #Expand our numeric arguments my $sourcex = nsi_eval($ImageData, $cfg, $rcfg, $routers, $router, "$source.x"); my $sourcey = nsi_eval($ImageData, $cfg, $rcfg, $routers, $router, "$source.y"); my $destinationx = nsi_eval($ImageData, $cfg, $rcfg, $routers, $router, "$destination.x"); my $destinationy = nsi_eval($ImageData, $cfg, $rcfg, $routers, $router, "$destination.y"); my $absnodestatus = "$direction$cond"; my $absnodeinstatus = "in$nodeinstatus"; my $absnodeoutstatus = "out$nodeoutstatus"; #Draw something depending on the node's status if ($absnodestatus eq $absnodeinstatus || $absnodestatus =~ /always/i){ $ImageData->setStyle(split(/,/,$$gdstyles{$style}{'style'})); #$ImageData->setStyle($$gdstyles{$style}{'style'}); $ImageData->line($sourcex,$sourcey,$destinationx,$destinationy,gdStyled); } } sub copyimage{ my ($ImageData, $gdstyles, $cfg, $rcfg, $routers, $router, $msg, $nodeinstatus, $nodeoutstatus, $incurrent, $outcurrent, $direction, $cond, $image, $coordx, $coordy) = @_; #Expand our numeric arguments my $coordx = nsi_eval($ImageData, $cfg, $rcfg, $routers, $router, "$coordx"); my $coordy = nsi_eval($ImageData, $cfg, $rcfg, $routers, $router, "$coordy"); my $absnodestatus = "$direction$cond"; my $absnodeinstatus = "in$nodeinstatus"; my $absnodeoutstatus = "out$nodeoutstatus"; #Draw something depending on the node's status if ($absnodestatus eq $absnodeinstatus || $absnodestatus =~ /always/i){ open (SRCIMG,"<$$cfg{'icondir'}\\\\$image") || die "ERROR: Can't open source image for copy: $$cfg{'icondir'}\\\\$image\n"; my($srcImageData) = newFromGif GD::Image(SRCIMG) || die "ERROR: GD::newFromGif\n"; close SRCIMG; my($srcImgDataSizeX,$srcImgDataSizeY) = $srcImageData->getBounds; $ImageData->copy($srcImageData,$coordx,$coordy,0,0,$srcImgDataSizeX,$srcImgDataSizeY); } } sub multicopyimage{ my ($ImageData, $gdstyles, $cfg, $rcfg, $routers, $router, $msg, $nodeinstatus, $nodeoutstatus, $incurrent, $outcurrent, $direction, $cond, $image, $coordx, $coordy, $howoften, $minoften, $maxoften, $stepsize, $angle) = @_; #Expand our numeric arguments print "Coordinates: $coordx/$coordy\n"; my $coordx = nsi_eval($ImageData, $cfg, $rcfg, $routers, $router, "$coordx"); my $coordy = nsi_eval($ImageData, $cfg, $rcfg, $routers, $router, "$coordy"); my $howoften = nsi_eval($ImageData, $cfg, $rcfg, $routers, $router, "$howoften"); print "Coordinates: $coordx/$coordy\n"; if ($howoften < $minoften){ $howoften = $minoften; } if ($howoften > $maxoften){ $howoften = $maxoften; } my $absnodestatus = "$direction$cond"; my $absnodeinstatus = "in$nodeinstatus"; my $absnodeoutstatus = "out$nodeoutstatus"; #Draw something depending on the node's status if ($absnodestatus eq $absnodeinstatus || $absnodestatus =~ /always/i){ open (SRCIMG,"<$$cfg{'icondir'}\\\\$image") || die "ERROR: Can't open source image for copy: $$cfg{'icondir'}\\\\$image\n"; my($srcImageData) = newFromGif GD::Image(SRCIMG) || die "ERROR: GD::newFromGif\n"; close SRCIMG; my($srcImgDataSizeX,$srcImgDataSizeY) = $srcImageData->getBounds; my $rad = ($angle * 3.141592654) / 180; if ($stepsize >= 0){ for($multicounter = 0; $multicounter < $howoften; $multicounter++){ my $hyp = $multicounter * $stepsize; my $a = sprintf("%.0f",sin($rad) * $hyp); my $b = sprintf("%.0f",cos($rad) * $hyp); #print "Angle: $angle, Rad: $rad, a: $a, b: $b\n"; $ImageData->copy($srcImageData,$coordx + $b,$coordy - $a,0,0,$srcImgDataSizeX,$srcImgDataSizeY); } }else{ $stepsize = abs($stepsize); for($multicounter = $howoften - 1; $multicounter >= 0; $multicounter--){ my $hyp = $multicounter * $stepsize; my $a = sprintf("%.0f",sin($rad) * $hyp); my $b = sprintf("%.0f",cos($rad) * $hyp); #print "Angle: $angle, Rad: $rad, a: $a, b: $b\n"; $ImageData->copy($srcImageData,$coordx + $b,$coordy - $a,0,0,$srcImgDataSizeX,$srcImgDataSizeY); } } } } sub drawtext{ my ($ImageData, $gdstyles, $cfg, $rcfg, $routers, $router, $msg, $nodeinstatus, $nodeoutstatus, $incurrent, $outcurrent, $direction, $cond, $font, $coordx, $coordy, $textid, $color) = @_; #Expand our numeric arguments my $coordx = nsi_eval($ImageData, $cfg, $rcfg, $routers, $router, "$coordx"); my $coordy = nsi_eval($ImageData, $cfg, $rcfg, $routers, $router, "$coordy"); my $absnodestatus = "$direction$cond"; my $absnodeinstatus = "in$nodeinstatus"; my $absnodeoutstatus = "out$nodeoutstatus"; #Draw something depending on the node's status if ($absnodestatus eq $absnodeinstatus || $absnodestatus =~ /always/i){ if(!defined($$msg{$textid})){ $$msg{$textid} = "MSG not defined!"; } if($font eq 1){$ImageData->string(gdTinyFont,$coordx,$coordy,$$msg{$textid},$colors{$color});} if($font eq 2){$ImageData->string(gdSmallFont,$coordx,$coordy,$$msg{$textid},$colors{$color});} if($font eq 3){$ImageData->string(gdMediumBoldFont,$coordx,$coordy,$$msg{$textid},$colors{$color});} if($font eq 4){$ImageData->string(gdLargeFont,$coordx,$coordy,$$msg{$textid},$colors{$color});} } } sub transeventvar{ my ($cfg, $rcfg, $routers, $router, $incurrent, $outcurrent, $transstring) = @_; my @transsplit = split(/\$/,$transstring); my $maxelements = $transsplit; print "MAXELEMNTS: $transstring\n"; for ($transcounter = 0; $transcounter <= $maxelements; $transcounter++){ $transstring =~ s/\$NodeWarningThreshhold/$$rcfg{nodewarningthreshhold}{$router}/i; $transstring =~ s/\$NodeAlarmThreshhold/$$rcfg{nodealarmthreshhold}{$router}/i; $transstring =~ s/\$NodeIn/$incurrent/i; $transstring =~ s/\$NodeOut/$outcurrent/i; } return $transstring; } sub sendmail{ my ($cfg, $rcfg, $routers, $router, $incurrent, $outcurrent, $event, $eventtype, $address) = @_; print "Sending e-mail to: $address from $$cfg{'statusemailorigin'}\n"; my $smtp = Net::SMTP->new('hampton.lam.liebherr.com'); # connect to an SMTP server foreach $target (split(/;/,$address)){ $smtp->mail( $$cfg{'statusemailorigin'} ); # use the sender's address here $smtp->to($target); # recipient's address $smtp->data(); # Start the mail # Send the header. $smtp->datasend("To: $address\n"); $smtp->datasend("From: $$cfg{'statusemailorigin'}\n"); $smtp->datasend("Subject: $eventtype on Node \"$router\"\n"); $smtp->datasend("\n"); # Send the body. $smtp->datasend("$event\n"); $smtp->datasend("\n"); $smtp->datasend("\n"); $smtp->datasend("*******************************************************\n"); $smtp->datasend("*** This was an automated network status update ***\n"); $smtp->datasend("*** message generated by: ***\n"); $smtp->datasend("*** NSI v1.0 for MRTG, Created by Mac Kloberg ***\n"); $smtp->datasend("*** ***\n"); $smtp->datasend("*******************************************************\n"); $smtp->dataend(); # Finish sending the mail } $smtp->quit; # Close the SMTP connection } mrtg-2.17.10/contrib/TotalControlModem/0000755000175300017510000000000013057016061016713 5ustar oetikeroepmrtg-2.17.10/contrib/TotalControlModem/example.txt0000644000175300017510000000532413057016061021113 0ustar oetikeroepFrom webmaster@hiway.com.br Fri Feb 16 23:24:20 2001 From: Fernando Braghetto - Webmaster Hiway Date: Thu, 15 Feb 2001 09:51:27 -0300 Subject: [Contribution] TCH Modem [ Part 1.1, Text/PLAIN 86 lines. ] [ Unable to print this part. ] Tobias, I want to contrib with the MRTG. I do not have time for add this to indexmaker / cfgmaker. Sorry! Actually I'm found some very good Objects IDs for the Total Control Modem Racks (3Com). To make management for the number of users connected in a HyperARC card (with HyperDSP modem) or Netserver card (with Quad-Modens and DualPri card) use this cfg: (sorry for my bad english) # Example of configuration by # Fernando Braghetto/Brazil - braghetto@hiway.com.br # created in Feb/15 2001 # TotalControl Temperature # change the IP Address 10.0.0.1 with the IP of Hyper NMC card (Network Management Card) # Target[TCTemp]: 1.3.6.1.4.1.429.1.2.2.5.0&1.3.6.1.4.1.429.1.2.2.5.0:public@10.0.0.1 MaxBytes[TCTemp]: 36 Title[TCTemp]: Temperature ShortLegend[TCTemp]: C Unscaled[TCTemp]: ymwd YLegend[TCTemp]: Temperature LegendI[TCTemp]:  System Temp  LegendO[TCTemp]:  System Temp  Options[TCTemp]: gauge PageTop[TCTemp]:

      Temperatura do TotalControl E1

      # TotalControl Connected Users in HyperARC (using HyperDSP E1 modens) # change the IP Address 10.0.0.2 with the IP of Hyper ARC card (Routing Card) # Target[TCHDSP]: 1.3.6.1.4.1.429.4.2.1.10.0&1.3.6.1.4.1.429.4.2.1.10.0:public@10.0.0.2: MaxBytes[TCHDSP]: 420 Title[TCHDSP]: Connected Users ShortLegend[TCHDSP]: Users YLegend[TCHDSP]: Users LegendI[TCHDSP]:  Connected Users  LegendO[TCHDSP]:  Connected Users  Options[TCHDSP]: gauge PageTop[TCHDSP]:

      Number of Connected Users

      # TotalControl Connected Users in Netserver Card (using Quad modens and Dual Pri Card) # change the IP Address 10.0.0.3 with the IP of Netserver card (Routing Card) # Target[TCNetserver]: 1.3.6.1.2.1.2.1.0&1.3.6.1.2.1.2.1.0:public@10.0.0.3 MaxBytes[TCNetserver]: 56 Title[TCNetserver]: Connected Users ShortLegend[TCNetserver]: Users Unscaled[TCNetserver]: ymwd YLegend[TCNetserver]: Users Legend1[TCNetserver]: Users Legend2[TCNetserver]: Users Legend3[TCNetserver]: Users Legend4[TCNetserver]: Users LegendI[TCNetserver]:  Digital Connections  LegendO[TCNetserver]:  Analog Connections  Options[TCNetserver]: gauge PageTop[TCNetserver]:

      Number of Connected Users

      Sincerly, Fernando Braghetto IT Manager, Network Admin, Webmaster Hiway Internet Provider - Brazil [IMAGE] [ Part 2, Image/GIF 7.6KB. ] [ Unable to print this part. ] mrtg-2.17.10/contrib/routers/0000755000175300017510000000000013057016061015010 5ustar oetikeroepmrtg-2.17.10/contrib/routers/README0000644000175300017510000000031713057016061015671 0ustar oetikeroepFolks, Steve is much faster with putting out new versions of his great tools, than I can release new versions of mrtg ... so please fetch hist stuff from http://www.steveshipway.org/software/ cheers tobi mrtg-2.17.10/contrib/mrtg-dynip/0000755000175300017510000000000013057016061015377 5ustar oetikeroepmrtg-2.17.10/contrib/mrtg-dynip/FAQ0000644000175300017510000002253613057016061015741 0ustar oetikeroepFAQ for mrtg-dynip version 0.41b 0. What are the problems that gave rise to mrtg-dynip? 0.1 What is dynamic IP 0.2 What is static or fixed IP 0.3 What is SNMP and what information can it provide? 0.4 What is MRTG? 0.5 Can the configuration file MRTG runs on remain unchanged? 1. What does mrtg-dynip do? 1.1 Can mrtg-dynip act as a front end to MRTG? 1.2 Can mrtg-dynip monitor modem banks? 2. What do I need to run mrtg-dynip and where can I get it? 3. What platforms does mrtg-dynip run on? 4. Are there special considerations to running mrtg-dynip? 4.1 How do I make mrtg-dynip executable? 4.2 How can I ensure mrtg-dynip can write to directories and files 5. How do I prevent errors and interpret error messages? 5.0 What problems external to mrtg-dynip affect it? 5.0.1 Why am I getting losts of weird email from cron? 5.0.2 Why does the mrtg-dynip log have weird messages from snmp modules? 5.1 Why doesn't my email address and web page link show? 5.2 I have configured everything, yet my index page does not update 5.3 Your crontab example looks really odd, please explain. 6. Why do the in and out graphs closely follow each other in my modem bank graphs? 7. I cannot find a solution to my problem in the docmentation and web sites. What support exists and is there a mailing list? 0. What are the problems that gave rise to mrtg-dynip? The initial problem that gave rise to the creation of mrtg-dynip is that MRTG relies on snmp target numbers having a fixed association with file names representing physical interfaces. In environments where the snmp target number of a physical interface can vary, such as in a PPP dial in environment, it is necessary to ensure that file names associated with real physical interfaces are associated with the current snmp target number for the device. This is what mrtg-dynip does. 0.1 What is dynamic IP To someone dialling in, dynamic IP means when they dial a rotary number they do not get a consistent IP address. To the service provider it means a unique IP number is assinged to each telephone line/modem/port. 0.2 What is static or fixed IP To someone dialling in, static or fixed IP means that their user name is approved to use a unique IP address, whether they dial into a rotary for a modem bank or into a non rotary number. To the service provider, it means if someone is dialling into a rotary for a modem pool, they allow the modem port use a unique approved IP number for that user, that overrides the IP address used when a dial in user does not request a fixed or static IP. 0.3 What is SNMP and what information can it provide? SNMP stands for Simple Network Management Protocol. Like much relating to the Internet, it is described by a set of Internet Engineering Task Force documents known as RFCs (Requests for Comments). SNMP is a means by which network linked devices can have a wide variety of device status information reported from them, and have action performed on them, according to known protocols. 0.4 What is MRTG? MRTG stands for 'Multi Router Traffic Grapher'. Among much else, it provides a means for graphing traffic quantity information through various interfaces, typically routers, in web acessible means, using information reurned from SNMP requests. 0.5 Can the configuration file MRTG runs on remain unchanged? Not in environmants that the SNMP target number varies for physical interface devices you are interested in gathering information on. 1. What does mrtg-dynip do? #Mrtg-dynip is a contribution to mrtg, enabling mrtg to generate multi #interface traffic graphs for IP interfaces on hosts that do not provide #consistent SNMP target numbers for their interfaces. Such IP interfaces #include IP active serial interfaces attached to modems in a PPP dial in #environment. The hosts must run snmp agents. For completeness, information #about interface devices with unvarying SNMP target numbers, such as #ethernet cards, can be configured to be included. #Mrtg-dynip's configuration is simplest where static (or fixed) IP is not #used for dial into a rotary modem pool. #Mrtg-dynip can be considred to have sophisticated modem bank monitoring #capacity, when the modems carry PPP or SLIP traffic. #Regenerates a named 'mrtg.cfg' file to ensure snmp data remains with a #consistent IP number, or overridable IP number of a real physical device #in a dial in IP environment, rather than with an interface name which #can get assinged to different real physical devices, and runs mrtg on #the generated file. #Generates a web index file of stats web pages. #Please see the section 6 of this FAQ for this version for information on #for differences in interpreting graphs between some devices 1.1 Can mrtg-dynip act as a front end to MRTG for traffic graphing? In a sense yes for interface or router traffic, but this is not ADVISABLE or necessarily efficient, see above. Future versions may make mrtg-dynip more suitable as a front end to MRTG for some purposes, see the TODO file. 2. What do I need to run mrtg-dynip? You need the contribution to MRTG called mrtg-dynip. Latest version available from http://www.heenan.ironbark.id.au/mrtg-dynip. MRTG needs to be successfully installed. MRTG can be obtained from http://www.ee.ethz.ch/~oetiker/webtools/mrtg/mrtg.html. MRTG itself needs the GD graphics library, see the MRTG package for details. 3. What platforms does mrtg-dynip run on? mrtg-dynip should run on all platforms MRTG runs on, including Windows NT. Mrtg-dynip's comments are oriented towards running on UNIX style systems. such as Linux. There are some comments on configuring directoy names for Windows NT. Issues involved in differences between running Perl scripts on UNIX systems and NT systems should be known to you, if you run run MRTG on an NT machine. 4. Are there special considerations to running mrtg-dynip? Not really. You must of course ensure mrtg-dynip is executable and can write to directories and files it needs to when executed. 4.1 How do I make mrtg-dynip executable? In UNIX the command chmod 744 mrtg-dynip will make the file executable to the owner of the file 4.2 How can I ensure mrtg-dynip can write to directories and files You need to ensure directories (and files if they exist already) have appropriate write permissions. This is beyond the scope of this FAQ. Basically if you have mrtg working, you will be able to get mrtg-dynip working. 5. How do I prevent errors and interpret error messages? Please see section 4 above. Set up log file generation as indicated in the install file. With regard to starup error messages from rateup, see MRTG. Confirm SNMP agents are running correctly. After a reboot I have found it sometimes necesary to stop and restart the snmp daemon. Changing order around in startup file may have fixed this problem. I have found running mrtg-dynip manually outside its crond schedule may alter graph data, starting anew on some. 5.0 What problems external to mrtg-dynip have been experienced? Such is the burden of the system adminstrator to be the victim of cryptic error messages 5.0.1 Why am I getting losts of weird email from cron? Check you only have one crond running. If more than one is running then expect weird mesages and data loss. 5.0.2 Why does the mrtg-dynip log have weird messages from snmp modules? If you think your configuration is correct, try killing your snmp daemon, restarting it and wait to see if the messages come up again before worrying about the messages. 5.2 Why doesn't my email address and web page link show? Did you remove the comment symbol '#' in the configuration file? 5.3 I have configured everything, yet my index page does not update The default option is to die if there are any response problems. Try changing the $suicidal option. Examine the log file. 5.4 Your crontab example looks really odd, please explain. First the script gets mrtg to run on the regenerated 'mrtg-dynip.cfg' file. The crontab entry is designed to send any error mwessages from standard output and error to a log file with a date and time indicator. If you don't do this you may end up perplexing/annoying/frightening those on the root email distribution list (who are automatically emailed unredirected standard output and error from cron jobs), if you run the script as user root. The error messages can be confusing to those inexperienced with mrtg and snmp, and can be lengthy and frequent! 6. Why do the in and out graphs closely follow each other in my modem bank graphs? This has to do with the way information is reported by by the snmp agent for the interface devices. On mainstream ISDN router devices, 'in' appears to indicate incoming packets on one side and 'out' appears to be outgoing packets on the same side. For some interfaces, 'in' appears to indicate incoming packets to both sides and 'out' appears to mean the forwarded packet out of the interface from either sides. It appears as snmp counts both sides of an interface for counting on some devices but one side for other devices. This problem needs to be sorted out. 7. I cannot find a solution to my problem in the docmentation and web sites. What support exists and is there a mailing list? This depends on the problem. For problems to do with mrtg there is an active mailing list and extensive archive. For problems specific to mrtg-dynip please send an email to me at john@heenan.ironbark.id.au. I will set up a mailing list if necessasry. mrtg-2.17.10/contrib/mrtg-dynip/mrtg-dynip-sydnet0000644000175300017510000006440013057016061020724 0ustar oetikeroep#!/usr/local/bin/perl ################################################################## # Multi Dynamic IP Traffic Grapher contibution to mrtg ################################################################## # # Created by John Heenan # # Available from http://www.heenan.ironbark.id.au/mrtg-dynip # ################################################################## # # Distributed under the GPL copyleft of GNU # # mrtg-dynip, v 0.41b 1997/10/25 # # Copyright John Heenan, with exception of datestr subroutine # (copied from mrtg executable) and much of internal_walk # subroutine (manner of using snmp modules copied from an example # by Simon Lenine) # ################################################################### #Mrtg-dynip is a contribution to MRTG, enabling MRTG to generate multi #interface traffic graphs for IP interfaces on hosts that do not provide #consistent SNMP target numbers for their interfaces. Such IP interfaces #include IP active serial interfaces attached to modems in a PPP dial in #environment. The hosts must run snmp agents. For completeness, information #about interface devices with unvarying SNMP target numbers, such as #ethernet cards, can be configured to be included. #Mrtg-dynip's configuration is simplest where static (or fixed) IP is not #used for dial into a rotary modem pool. #Mrtg-dynip can be considred to have sophisticated modem bank monitoring #capacity, when the modems carry PPP or SLIP traffic. #Regenerates a named 'mrtg.cfg' file to ensure snmp data remains with a #consistent IP number, or overridable IP number of a real physical device #in a dial in IP environment, rather than with an interface name which #can get assinged to different real physical devices, and runs mrtg on #the generated file. #Generates a web index file of stats web pages. #Please see the section 6 of the FAQ for this version for information on #for differences in interpreting graphs between some devices #Briefly, to someone dialling in, dynamic IP means when they dial a rotary #number they do not get a consistent IP address. To the service provider it #means a unique IP number is assinged to each telephone line/modem/port. #To someone dialling in, static or fixed IP means that their user name is #approved to use a unique IP address, whether they dial into a rotary for #a modem bank or into a non rotary number. To the service provider, it means #if someone is dialling into a rotary for a modem pool, they allow the modem #port use a unique approved IP number for that user, that overrides the IP #address used when a dial in user does not request a fixed or static IP. #The public community should be used, however the public community on a #particular host does not need to be named 'public'. This is catered for. #There is a large 'TODO' list for this contribution, including #testing use of the 'ifLastChange' snmp object. #SET UP #Runs independently of an existing configured mrtg installation. Following #the commented example will make the set up clearer. The examples are for a #live ISP using web page http://www.stats.syd.net.au, you must change values #for your own use # 0 Ensure the path to the perl binary is set correctly on first line # 1 $HTTP_Work_Dir ** Must set # 2 $HTTP_index_file Default index.html may be OK if unique # 3 $mrtg_Dir ** Must set # 4 $mrtgcfg_Dir Setting to $mrtgDir is probably OK # 5 $mrtgcfg_file Default mrtg-dynip.cfg should be OK # 6 $update Default will work (five minutes) # 7 $community_default Default for this default may be OK (public) # 8 $email Set to "" to show nothing # 9 $home_page Set to "" to show nothing # 10 $home_page_descr Set to "" to show nothing # 11 $suicidal Non zero: bomb out if there are problems # 12 $firewall_masq_tran_if Best to leave as 0 (zero) if sufficient # 13 $use_non_dyn_IP_for_tty Safe to set to 0 (the non set value) # 14 $Dir_PID Must set if 13 is non zero # 15 External settings if 13 is set to non zero # 16 $interfaces ** Must set #Ensure mrtg-dynip has executable permission. See below as to where #mrtg-dynip may need to be installed. #Place a crontab entry, consistent with update time, similar to #0,5,10,15,20,25,30,35,40,45,50,55 * * * * #cd /usr/src/mrtg/mrtg-2.5/; date >>/var/log/mrtg-dynip.log; # ./mrtg-dynip >>/var/log/mrtg-dynip.log 2>&1 # #Redirecting standard output and error to a log file with an indication #of time from 'date' is valuable for sorting out errors and preventing #messages from being emailed to the root account. # #If Perl5 snmp modules are not installed in standard libraries and #the internal 'walk' is being used, then it is necessary to ensure #mrtg-dynip in installed in, and run from, a directory where the modules #are, typically the same directory the mrtg executable is in. #The most difficult part in a dynamic IP environment may be choosing the IP #addresses to use for the scaler constant $interfaces, as you must ensure #the IP address used will always correspond to the physical interface #device, unless exception facility configured in. #For Internet Service Providers running ppp dial in lines, the choice will #be clear. The IP addressess to use will be the 'remote' IP part of the #command line options for the real physical device (:remote_ip in #/etc/ppp/options.ttyXY file), unless static or fixed IP is allowed to #override this. For dial out lines that can get a variable 'remote' IP, you #should be able to control what remote IP you get, no matter who you dial #into and what remote IP they may offer you, by configuring a remote IP as #for a dial in line above. #If the final negotiated ppp address pair as seen by your machine, #local_ip:remote_ip, is equal to a_ip:b_ip, then the local_ip:remote_ip as #seen by the other machine is b_ip:a_ip. Since the remote IP seen by your #side of the line is the local IP as seen and negotiated by the machine on #the other side of the line, you can choose whatever remote IP address suits #your side of the connection. Specifying a 'remote' IP other than 0.0.0.0 #will, by default with pppd, result in an IP the other machine will have to #accept as their local to succesfully negotiate a connection. However it is #two way: the other machine can do the same to you for its corresponding #'remote' IP. Hence mrtg-dynip can work on both machines. #Please note: If you have interface devices which register ppp10 or #above, your snmp daemon may not supply information. This is not due #to a bug in mrtg, the snmp modules or this mrtg-dynip. #Latest version of this software should be available from #http://www.heenan.ironbark.id.au/source/mrtg-dynip #The configuration herein is provivded as an example only. #This file is used to generate http://www.stats.syd.net.au. ######## Start of configuration section, numbered 0 to 16. ######## Set this, 0 #Check the perl path is correct on the very first line! ######## Set this, 1 #Define $WorkDir to be the directory for web pages and data to be housed #Ensure each directory path ends with a seperator. If intending to run on #an NT machine, then ensure the directory seperator is '\\' instead of '/' $HTTP_Work_Dir='/var/lib/httpd/htdocs/mrtg/'; ######## Set this, 2 #Define name of index html file, only condition is that it not the same name #as a html that will be regenerated. All names of generated files contain #an IP address. $HTTP_index_file='index.html'; ####### Set this, 3 #Set to full directory path the mrtg executable is in. Place this file #it if that is where the Perl 5 snmp modules are and $use_internal_walk #will not be set to 1 (see below). #Ensure each directory path ends with a seperator. If intending to run on #an NT machine, then ensure the directory seperator is '\\' instead of '/' $mrtg_Dir="/usr/src/mrtg/mrtg-2.5/"; ####### Set this, 4 #Set to full directory path the 'mrtg.cfg' file below is to be placed in. #The default choice is to choose same directory as for $mrtg_Dir above #Ensure each directory path ends with a seperator. If intending to run on #an NT machine, then ensure the directory seperator is '\\' instead of '/' ###$mrtgcfg_Dir="/usr/src/mrtg/mrtg-2.5/"; $mrtgcfg_Dir=$mrtg_Dir; ####### Set this, 5 #Set the name you would like the 'mrtg.cfg' file to be. By locating or #naming differently from existing 'mrtg.cfg' files, you can run this #software independently of your existing mrtg installation. $mrtgcfg_file="mrtg-dynip.cfg"; ####### Set this, 6 #Set this to update interval in amount of minutes. Ensure when this file #is run from crond and that the cron run inteval matches this update #interval $update=5; ######## Set this, 7 #Default community "public" may be sufficient. The community defined here #is the default community to use if no community is defined in the #for a particular interface in configuration of $interface in section 12. $community_default="public"; ######## Set this, 8 #Email address of network manager(s). Ensure a '\' appears before #'@' in email address, as in example. #$email=""; #No attempt to display if null $email="admin\@syd.net.au"; ######## Set this, 9 #Web address of home page for your system, do not include http:// at start #$home_page=""; #No attempt to display if null $home_page="www.syd.net.au"; ######## Set this, 10 #Text for clickable link to home page of your system #$home_page_descr=""; #No attempt to display if null $home_page_descr="SydNet Internet and Network Services"; ######## Set this, 11 #Set to a non zero if you want the program to die if there are problems #with responses from agents or hosts. Useful in testing phase. #$suicidal = 0; #Program is to soldier on if there are no responses from a host $suicidal = 1; #Program is to bomb out if there are problems with reponses ######## Set this, 12 #Set this to a non zero if you have interfaces with the same IP number on #different masquerading firewall, or address translation, routers/hosts, #otherwise leave as 0. This adds the name of the host to all web page file #names as well as the IP addresses. Avoid using this option as its use make #it more difficult to keep track of interface data. #$firewall_masq_tran_if = 1; $firewall_masq_tran_if = 0; ######## Set this, 13 #If you have hosts upon which you do not make it a requirement that an #interface device uses a partciular IP number (that is you might provide #fixed IP address use into a rotary modem pool) then you can set this option #on and set item 17 appropriately. Set to zero not to use, non zero to use $use_non_dyn_IP_for_tty=1; #$use_non_dyn_IP_for_tty=0; ######## Set this, 14 #If you set option 13 above, then set to full directory path external #process will place a single line with the IP address into a file #with name that includes name of SNMP hsot and physical interface device #name. # #Ensure each directory path ends with a seperator. If intending to run on an #NT machine, then ensure the directory seperator is '\\' instead of '/' $Dir_PID="/var/run/"; ######## Set this, 15 #If you haVe set option 13 above then you need to ensure #an external program provides required information from whatever #hosts you indicate in 16 are ports that can have their preferred #IP overridden. # #For UNIX style localhosts the following lines can be inserted in #/etc/ppp/ip-up and /etc/ppp/ipdown. Following a reboot stale #files should be removed automatically by startup, lest the machine #crashed. For hosts other than the host upon which this script is #running, ip-up and ip-down will need to be modified to ensure the #information goes to /var/run of appropriate host. This can be done #using remote shell or other mechanisms, such as remote copy, nfs, #auto processed email and special client/server networking. # #It is vital the 'host_name' for writing to /var/run/, as indicated in #/var/run/mrtg-dynip.host_name~~ttyXY, matches exactly the equivalent #host name in mrtg-dynip. This 'host_name' may be a single name, #a dotted name or a dotted numeric IP address. # #/etc/ppp/ip-up for a localhost running a bash shell can include # #tty_name="$2" #IP_remote="$5" #/bin/echo $IP_remote > /var/run/mrtg-dynip.localhost~~${tty_name##/*/} # #The name of the file must exactly matched that sought for. # #/etc/ppp/ip-down for a localhost running a bash shell can include # #tty_name=$2 #/bin/rm -f /var/run/mrtg-dynip.localhost~~${tty_name##/*/} ######## Set this, 16 #A pair of lines between blank lines represents an interface on a #particular host. # #You can comment out a single pair of lines with a '#' or any non digit #(except whitespace) as the first character of a pair of lines. # #The first line has the following format #'n' 'IP-addr' 'if-speed' 'snmp host' 'snmp community' # #The second line has the following format # 'Any free text description of interface' # #The items must not be enclosed by '"' or '''. Plese see example #below before reading any further. Any whitespace or combination #of whitespace (tabs or spaces) can seperate the items. However it #is important the two lines with 'END_OF_INTERFACES' end without #whitespace. # #'n' is place this entry is to appear in the index of interfaces web file. #The number of digits should be the same for each interface, for example #use sequence 000 010 020 for successive numbers. You can temporarily #take an interface out of consideration by placing any non digit #(except whitespace) before these digits, for example replace 010 #by N010 or #010 # #'IP-addr' is a consistent IP address of a physical interface. Exceptions #can be catered for. If you allow fixed (or static) IP into the physical #interface to override, then you can ensure the line is still marked active #in addition to the static IP entry being marked active. To ensure this #occurs, append '~~ttyXY' to the IP address where ttyXY is the value #returned by ${tty_name##/*/} for the phyical device (or port) as indicated #in section 15. To keep a value in place, even if the port is not part of #an IP overridable rotary pool, append a '~' to the end, such that complete #appendage to the IP address is now '~~ttyXY~'. You can keep the appendages #even if you turn off, or do nor use, $use_non_dyn_IP_for_tty. # #'if-speed' is the interface speed in integer bits/sec. K and M multipliers #for Kb/s and Mb/s can be used (see example). If you want to use decimal #values then rewrite with a lower multiplier, for example write #33.3K as 34099 (integer portion of 33.3 multiplied by 1024). # #'snmp host' is a common and consistent DNS name, or IP address, for #interfaces that belong to a particular machine. For efficiency of snmp #agent use it is better all interfaces that belong to a particular machine #use a consistent name. # #'snmp community' is the community name of the 'public' community #for an interface (the public community does not have to be named #'public'). This vale does not have to be set: if this value is #not set then the value of $community_default is used instead. # #'Any free text description of the interface ' on the second line #is as indicated. It need not begin with whitepace (tabs or spaces). # #For dynamic IP interfaces, you must use unvarying 'remote' IPs as indicated #above. Virtual interface devices should not be used, they provide the same #statistics as the real interface they are a virtual interface of. #The configuration herein is provivded as an example only. #This file is used to generate http://www.stats.syd.net.au. { $interfaces = <$mrtg_Dir"."$mrtgcfg_file" || die "$mrtg_Dir"."$mrtgcfg_file file could not be opened\n"; $ip_descr_ptr = \%ip_descr; foreach $ip_i (keys(%target)) { if ($$ip_descr_ptr{$ip_i}->[0] =~ /^\d/) { ($speed_fig,$speed_mult) = $$ip_descr_ptr{$ip_i}->[1] =~ /^(\d+)(\D*)/; if ($speed_mult =~ /M|m/) { $scale = int ( $speed_fig * 1024 * 1024 / 8 ); } elsif ($speed_mult =~ /K|k/) { $scale = int ( $speed_fig * 1024 / 8 ); } elsif ( $speed_mult eq "" ) { $scale = int ( $speed_fig / 8 ); } else { die("Incorrect speed format in scaler constant $interfaces\n"); } ($ip_if,$host) = split (/@/,$ip_i); if ($firewall_masq_tran_if != 0) { $snmp_target=$ip_i; } else { $snmp_target=$ip_if; } print MRTGCFG <[2]\@$host MaxBytes[$snmp_target]: $scale Title[$snmp_target]: Traffic Analysis through interface device with IP address $ip_if of host $host PageTop[$snmp_target]:

      Stats for interface device with description $$ip_descr_ptr{$ip_i}->[3]

      END } } { print MRTGCFG <$HTTP_Work_Dir"."$HTTP_index_file" || die "Mrtg web index file could not be created\n"; { print MRTGCFGWEB < Index of stats pages for interface devices on interfaces described below

      Active and inactive interace device stats on interfaces described below

      This page last updated on $now

      END } if ($home_page && $home_page_descr) { print MRTGCFGWEB < A network management service courtesy of $home_page_descr

      END } if ($email) { print MRTGCFGWEB < Information and contact address: network management at email $email

      END } { print MRTGCFGWEB < Static IP address and rotary line both marked active if line in use by a static IP address

      END } { print MRTGCFGWEB < END } foreach $ip_i (keys %ip_descr) { $ip_order{$$ip_descr_ptr{$ip_i}->[0]} = $ip_i if ($$ip_descr_ptr{$ip_i}->[0] =~ /^\d/); } foreach $i (sort (keys %ip_order)) { $ip_i = $ip_order{$i}; if ($firewall_masq_tran_if != 0) { $file_name=$ip_i; } else { ($file_name) = split (/@/,$ip_i); } if ( defined ($target{$ip_i}) ) { print MRTGCFGWEB < END } else { print MRTGCFGWEB < END } } { print MRTGCFGWEB <

      This web page (but not the web pages above) generated by mrtg-dynip, version 0.41b, 1997/10/25 created by
      John Heenan, john\@heenan.ironbark.id.au

      Mrtg-dynip is a contribution to MRTG, enabling MRTG to generate multi interface traffic graphs for IP interfaces on hosts that do not provide consistent SNMP target numbers for their interfaces. Such IP interfaces include IP active serial interfaces attached to modems in a PPP dial in environment. The hosts must run snmp agents. For completeness, information about interface devices with unvarying SNMP target numbers, such as ethernet cards, can be configured to be included.

      Mrtg-dynip can be considred to have sophisticated modem bank monitoring capacity, when the modems carry PPP or SLIP traffic.

      This web page and web pages above, auto update details, and refresh, every $update minutes.

      Source code for the latest non beta version of the mrtg-dynip software contribution is available from http://www.heenan.ironbark.id.au/source/mrtg-dynip

      END } print MRTGCFGWEB "","\n"; close MRTGCFGWEB; exec ("$mrtg_Dir"."mrtg $mrtgcfg_Dir"."$mrtgcfg_file"); sub datestr { ($time) = shift(@_) || return 0; ($wday) = ('Sunday','Monday','Tuesday','Wednesday', 'Thursday','Friday','Saturday')[(localtime($time))[6]]; ($month) = ('January','February' ,'March' ,'April' , 'May' , 'June' , 'July' , 'August' , 'September' , 'October' , 'November' , 'December' )[(localtime($time))[4]]; ($mday,$year,$hour,$min) = (localtime($time))[3,5,2,1]; if ($min<10) {$min = "0$min";} return "$wday, $mday $month ".($year+1900)." at $hour:$min"; } sub snmp_get_response { use BER; use SNMP_Session; SOLDIER_ON: foreach $comm_host (keys (%snmp_comm_host)) { ($community,$host) = split (/@/,$comm_host); if ($session = SNMP_Session->open ($host, $community, 161)) { @ipRouteIfIndex = split ('\.', '1.3.6.1.2.1.4.21.1.2'); @ipAdEntIfIndex = split ('\.', '1.3.6.1.2.1.4.20.1.2'); $if_route_index_index = encode_oid (@ipRouteIfIndex); $if_index_index = encode_oid (@ipAdEntIfIndex); @oids = ($if_route_index_index); for (;;) { if ($session->getnext_request_response (@oids)) { $response = $session->pdu_buffer; ($bindings) = $session->decode_get_response ($response); @next_oids = (); ($binding,$bindings) = decode_sequence ($bindings); ($oid,$value) = decode_by_template ($binding, "%O%@"); last unless BER::encoded_oid_prefix_p ($if_route_index_index, $oid); push @next_oids, $oid; ($ip_if) = pretty_print ($oid) =~ /.*\.(\d+\.\d+\.\d+\.\d+)$/; $target_i = pretty_print ($value); $target{$ip_if."@".$host} = $target_i if ( defined ($snmp_comm_host{$community."@".$host}{$ip_if}) ); } else { die ("Suicide: no response from community $community on host $host","\n") if ($suicidal != 0); print ("Soldiering on: no response from community $community on host $host","\n"); $session->close (); last SOLDIER_ON; } @oids = @next_oids; } @oids = ($if_index_index); for (;;) { if ($session->getnext_request_response (@oids)) { $response = $session->pdu_buffer; ($bindings) = $session->decode_get_response ($response); @next_oids = (); ($binding,$bindings) = decode_sequence ($bindings); ($oid,$value) = decode_by_template ($binding, "%O%@"); last unless BER::encoded_oid_prefix_p ($if_index_index, $oid); push @next_oids, $oid; ($ip_if) = pretty_print ($oid) =~ /.*\.(\d+\.\d+\.\d+\.\d+)$/; $target_i = pretty_print ($value); $target{$ip_if."@".$host} = $target_i if ( defined ($snmp_comm_host{$community."@".$host}{$ip_if}) ); } else { die ("Suicide: no response from community $community on host $host","\n") if ($suicidal != 0); print ("Soldiering on: no response from community $community on host $host","\n"); $session->close (); last SOLDIER_ON; } @oids = @next_oids; } $session->close (); } else { die ("Suicide: unable to open SNMP session to community $community on host $host","\n") if ($suicidal != 0); print ("Soldiering on: unable to open SNMP session to community $community on host $host","\n"); } } } mrtg-2.17.10/contrib/mrtg-dynip/Changes0000644000175300017510000000461713057016061016702 0ustar oetikeroepVersion 0.41b 25 October 1997 Becomes a package again, minor code changes Version 0.41a 22 October 1997 Merging of new configuration section for fixed IP into $interfaces Comments updated Version 0.41 21 October 1997 Caters for static or fixed IP on all hosts Version 0.40Beta 21 October 1997 Caters for static or fixed IP on localhost Version 0.35x 12 October 1997 mrtg-dynip becomes a package instead of a single file. Minor changes to comments Version 0.35r 11 October 1997 Minor corrections and changes to comments Version 0.35f 9 October 1997 Capacity introduced to deal with hosts upon which interface IP addresses are the same on different hosts, such as on masquerading firewall hosts and on address translation hosts. Avoids need to run more than one copy for this situation. Version 0.35c 8 October 1997 Capacity introduced to deal with sets of hosts with inconsistent names for public community. Avoids need to run more than one copy for this situation. Version 0.35 6 October 1997 Capacity to Capacity to deal with information from multiple hosts introducedy for each host examined. This meant it was no longer necessary to run a copy for each host examined. 'Free form' configuration of interfaces introduced. Dropped option to use external snmpwalk. Version 0.32 5 October 1997 Improved error handling Version 0.31 28 September 1997 Changed name from regen to mrtg-dynip. Changed from 'all interfaces found on localhost' approach to deciding which interfaces to be included on a named host. Inactive interfaces labelled inactive instead of not being included. Free text descriptions of interfaces included. Reliance on ouput of 'ifconfig' dropped, this allows use of script by non UNIX machines and other hosts to be examined. Version 0.10 23 Sptember 1997 Generalised use of pattern matching on snmpwalk command output to enable either UCD or CMU compiled versions found in path to work. Stats for multiple ethernet cards generated. Versions 0.03 to 0.05 September 1997 Use of index page of interface stats page. General configuration options added. Added use of Simon Leinen's Perl 5 SNMP modules to query snmp daemon, as an alternative to using snmpwalk from a package other than mrtg. Version 0.01 to 0.02 28 August 1997 Concept proven with a basic working script. Testing begins on home Linux PC and on SydNet Internet and Network Services. mrtg-2.17.10/contrib/mrtg-dynip/README0000644000175300017510000000516113057016061016262 0ustar oetikeroep################################################################# Multi Dynamic IP Traffic Grapher contibution to mrtg ################################################################# Created by John Heenan Available from the mrtg-dynip web page at http://www.heenan.ironbark.id.au/mrtg-dynip ################################################################# Distributed under the GPL copyleft of GNU mrtg-dynip, v 0.41b 1997/10/25 Copyright John Heenan, with exception of datestr subroutine (copied from mrtg executable) and much of internal_walk subroutine (manner of using snmp modules copied from an example by Simon Lenine) ################################################################## Mrtg-dynip is a contribution to MRTG, enabling MRTG to generate multi interface traffic graphs for IP interfaces on hosts that do not provide consistent SNMP target numbers for their interfaces. Such IP interfaces include IP active serial interfaces attached to modems in a PPP dial in environment. The hosts must run snmp agents. For completeness, information about interface devices with unvarying SNMP target numbers, such as ethernet cards, can be configured to be included. Mrtg-dynip can be considred to have sophisticated modem bank monitoring capacity, when the modems carry PPP or SLIP traffic. Regenerates a named 'mrtg.cfg' file to ensure snmp data remains with a consistent IP number, or overridable IP number of a real physical device in a dial in IP environment, rather than with an interface name which can get assinged to different real physical devices, and runs mrtg on the generated file. Generates a web index file of stats web pages. Mrtg-dynip's configuration is simplest where static (or fixed) IP is not used for dial into a rotary modem pool. Please see the FAQ for more information. The names of the files packaged into mrtg-dynip-0.41b.tar.gz are README This file Install Install details FAQ 'Frequently Asked Questions' mrtg-dynip A full configuartion commented executable mrtg-dynip-sydnet The complete mrtg-dynip file in use at www.stats.syd.net.au Changes Change history TODO What the future might hold The package is oriented towards UNIX systems, there is no reason mrtg-dynip should nor run under Windows NT, some comments are made relevant to this. Please note the first task under Windows NT is to ensure the UNIX new lines are converted to DOS new lines or are readable. If you use this please let me know. If you would also like your site to be linked from the mrtg-dynip web page, please let me know. John Heenan john@heenan.ironbark.id.au www.heenan.ironbark.id.au/mrtg-dynip mrtg-2.17.10/contrib/mrtg-dynip/Install0000644000175300017510000000134113057016061016727 0ustar oetikeroepInstallation of the mrtg-dynip contribution to mrtg This contribution to mrtg runs independently of an existing running mrtg installation. Only one file is necessary, mrtg-dynip. It is necessary to have mrtg successfully installed first and to have an snmp daemon, the snmp agent server, running on target hosts. See the FAQ for information on obtaining mrtg-dynip and MRTG. Instructions for configuring mrtg-dynip are included in the mrtg-dynip file. To assist with configuration, the actual configuration file used in a live ISP is included in the mrtg-dynip-sydnet file Ensure mrtg-dynip has executable permission (for example, run command chmod 744 mrtg-dynip) and can write to directories files it is configured to write to. mrtg-2.17.10/contrib/mrtg-dynip/TODO0000644000175300017510000000253013057016061016067 0ustar oetikeroepInvestigate integration with terminal server software. such as the RADIUS server. The current release of mrtg-dynip, mrtg-dynip-0.41b, appears to be stable, robust and free of major problems arising from misconfiguration and lack of response. While it might seem rather trivial to introduce changes to make mrtg-dynip more suitable as a front end to MRTG, this in a sense is somewhat trivial in terms of the design goal of mrtg-dynip, namely to enable mrtg-dynip to work in environments with inconsistent snmp target names for the same phyical interface. This design goal has been achieved. The goal of having a convenient and efficient 'front end' to MRTG and mrtg-dynip is a different design goal in itself. It is planned to investigate and test use of the 'ifLastChange' snmp object. It is planned to introduce configuration to indicate if a host or router has unvarying SNMP target numbers for its interfaces, or not. Suitable coding will reduce processing demands and reduce the amount of snmp traffic generated. This may be trialed with tesing use of the 'ifLastChange' snmp object There are plans to try out terminal server software, such as RADIUS server software, with a RADIUS client Livingstone emulator, and see if there are any special issues or convenient outcomes involved. There is much scope for introducing a menu based configuration. mrtg-2.17.10/contrib/mrtg-dynip/mrtg-dynip0000755000175300017510000006063613057016061017432 0ustar oetikeroep#!/usr/local/bin/perl ################################################################## # Multi Dynamic IP Traffic Grapher contibution to mrtg ################################################################## # # Created by John Heenan # # Available from http://www.heenan.ironbark.id.au/mrtg-dynip # ################################################################## # # Distributed under the GPL copyleft of GNU # # mrtg-dynip, v 0.41b 1997/10/25 # # Copyright John Heenan, with exception of datestr subroutine # (copied from mrtg executable) and much of internal_walk # subroutine (manner of using snmp modules copied from an example # by Simon Lenine) # ################################################################### #Mrtg-dynip is a contribution to MRTG, enabling MRTG to generate multi #interface traffic graphs for IP interfaces on hosts that do not provide #consistent SNMP target numbers for their interfaces. Such IP interfaces #include IP active serial interfaces attached to modems in a PPP dial in #environment. The hosts must run snmp agents. For completeness, information #about interface devices with unvarying SNMP target numbers, such as #ethernet cards, can be configured to be included. #Mrtg-dynip's configuration is simplest where static (or fixed) IP is not #used for dial into a rotary modem pool. #Mrtg-dynip can be considred to have sophisticated modem bank monitoring #capacity, when the modems carry PPP or SLIP traffic. #Regenerates a named 'mrtg.cfg' file to ensure snmp data remains with a #consistent IP number, or overridable IP number of a real physical device #in a dial in IP environment, rather than with an interface name which #can get assinged to different real physical devices, and runs mrtg on #the generated file. #Generates a web index file of stats web pages. #Please see the section 6 of the FAQ for this version for information on #for differences in interpreting graphs between some devices #Briefly, to someone dialling in, dynamic IP means when they dial a rotary #number they do not get a consistent IP address. To the service provider it #means a unique IP number is assinged to each telephone line/modem/port. #To someone dialling in, static or fixed IP means that their user name is #approved to use a unique IP address, whether they dial into a rotary for #a modem bank or into a non rotary number. To the service provider, it means #if someone is dialling into a rotary for a modem pool, they allow the modem #port use a unique approved IP number for that user, that overrides the IP #address used when a dial in user does not request a fixed or static IP. #The public community should be used, however the public community on a #particular host does not need to be named 'public'. This is catered for. #There is a large 'TODO' list for this contribution, including #testing use of the 'ifLastChange' snmp object. #SET UP #Runs independently of an existing configured mrtg installation. Following #the commented example will make the set up clearer. Examples for a live #ISP, using stats page http://www.stats.syd.net.au, are included in file #mrtg-dynip-sydnet. You must make appropriate changes # 0 Ensure the path to the perl binary is set correctly on first line # 1 $HTTP_Work_Dir ** Must set # 2 $HTTP_index_file Default index.html may be OK if unique # 3 $mrtg_Dir ** Must set # 4 $mrtgcfg_Dir Setting to $mrtgDir is probably OK # 5 $mrtgcfg_file Default mrtg-dynip.cfg should be OK # 6 $update Default will work (five minutes) # 7 $community_default Default for this default may be OK (public) # 8 $email Set to "" to show nothing # 9 $home_page Set to "" to show nothing # 10 $home_page_descr Set to "" to show nothing # 11 $suicidal Non zero: bomb out if there are problems # 12 $firewall_masq_tran_if Best to leave as 0 (zero) if sufficient # 13 $use_non_dyn_IP_for_tty Safe to set to 0 (the non set value) # 14 $Dir_PID Must set if 13 is non zero # 15 External settings if 13 is set to non zero # 16 $interfaces ** Must set #Ensure mrtg-dynip has executable permission. See below as to where #mrtg-dynip may need to be installed. #Place a crontab entry, consistent with update time, similar to #0,5,10,15,20,25,30,35,40,45,50,55 * * * * #cd /usr/src/mrtg/mrtg-2.5/; date >>/var/log/mrtg-dynip.log; # ./mrtg-dynip >>/var/log/mrtg-dynip.log 2>&1 # #Redirecting standard output and error to a log file with an indication #of time from 'date' is valuable for sorting out errors and preventing #messages from being emailed to the root account. # #If Perl5 snmp modules are not installed in standard libraries and #the internal 'walk' is being used, then it is necessary to ensure #mrtg-dynip in installed in, and run from, a directory where the modules #are, typically the same directory the mrtg executable is in. #The most difficult part in a dynamic IP environment may be choosing the IP #addresses to use for the scaler constant $interfaces, as you must ensure #the IP address used will always correspond to the physical interface #device, unless exception facility configured in. #For Internet Service Providers running ppp dial in lines, the choice will #be clear. The IP addressess to use will be the 'remote' IP part of the #command line options for the real physical device (:remote_ip in #/etc/ppp/options.ttyXY file), unless static or fixed IP is allowed to #override this. For dial out lines that can get a variable 'remote' IP, you #should be able to control what remote IP you get, no matter who you dial #into and what remote IP they may offer you, by configuring a remote IP as #for a dial in line above. #If the final negotiated ppp address pair as seen by your machine, #local_ip:remote_ip, is equal to a_ip:b_ip, then the local_ip:remote_ip as #seen by the other machine is b_ip:a_ip. Since the remote IP seen by your #side of the line is the local IP as seen and negotiated by the machine on #the other side of the line, you can choose whatever remote IP address suits #your side of the connection. Specifying a 'remote' IP other than 0.0.0.0 #will, by default with pppd, result in an IP the other machine will have to #accept as their local to succesfully negotiate a connection. However it is #two way: the other machine can do the same to you for its corresponding #'remote' IP. Hence mrtg-dynip can work on both machines. #Please note: If you have interface devices which register ppp10 or #above, your snmp daemon may not supply information. This is not due #to a bug in mrtg, the snmp modules or this mrtg-dynip. #Latest version of this software should be available from #http://www.heenan.ironbark.id.au/source/mrtg-dynip ######## Start of configuration section, numbered 0 to 16. ######## Set this, 0 #Check the perl path is correct on the very first line! ######## Set this, 1 #Define $WorkDir to be the directory for web pages and data to be housed #Ensure each directory path ends with a seperator. If intending to run on #an NT machine, then ensure the directory seperator is '\\' instead of '/' $HTTP_Work_Dir='/var/lib/httpd/htdocs/mrtg/'; ######## Set this, 2 #Define name of index html file, only condition is that it not the same name #as a html that will be regenerated. All names of generated files contain #an IP address. $HTTP_index_file='index.html'; ####### Set this, 3 #Set to full directory path the mrtg executable is in. Place this file #it if that is where the Perl 5 snmp modules are and $use_internal_walk #will not be set to 1 (see below). #Ensure each directory path ends with a seperator. If intending to run on #an NT machine, then ensure the directory seperator is '\\' instead of '/' $mrtg_Dir="/usr/src/mrtg/mrtg-2.5/"; ####### Set this, 4 #Set to full directory path the 'mrtg.cfg' file below is to be placed in. #The default choice is to choose same directory as for $mrtg_Dir above #Ensure each directory path ends with a seperator. If intending to run on #an NT machine, then ensure the directory seperator is '\\' instead of '/' ###$mrtgcfg_Dir="/usr/src/mrtg/mrtg-2.5/"; $mrtgcfg_Dir=$mrtg_Dir; ####### Set this, 5 #Set the name you would like the 'mrtg.cfg' file to be. By locating or #naming differently from existing 'mrtg.cfg' files, you can run this #software independently of your existing mrtg installation. $mrtgcfg_file="mrtg-dynip.cfg"; ####### Set this, 6 #Set this to update interval in amount of minutes. Ensure when this file #is run from crond and that the cron run inteval matches this update #interval $update=5; ######## Set this, 7 #Default community "public" may be sufficient. The community defined here #is the default community to use if no community is defined in the #for a particular interface in configuration of $interface in section 12. $community_default="public"; ######## Set this, 8 #Email address of network manager(s). Ensure a '\' appears before #'@' in email address, as in example. #$email=""; #No attempt to display if null $email="admin\@our.net"; ######## Set this, 9 #Web address of home page for your system, do not include http:// at start #$home_page=""; #No attempt to display if null $home_page="www.our.net"; ######## Set this, 10 #Text for clickable link to home page of your system #$home_page_descr=""; #No attempt to display if null $home_page_descr="Our Network"; ######## Set this, 11 #Set to a non zero if you want the program to die if there are problems #with responses from agents or hosts. Useful in testing phase. #$suicidal = 0; #Program is to soldier on if there are no responses from a host $suicidal = 1; #Program is to bomb out if there are problems with reponses ######## Set this, 12 #Set this to a non zero if you have interfaces with the same IP number on #different masquerading firewall, or address translation, routers/hosts, #otherwise leave as 0. This adds the name of the host to all web page file #names as well as the IP addresses. Avoid using this option as its use make #it more difficult to keep track of interface data. #$firewall_masq_tran_if = 1; $firewall_masq_tran_if = 0; ######## Set this, 13 #If you have hosts upon which you do not make it a requirement that an #interface device uses a partciular IP number (that is you might provide #fixed IP address use into a rotary modem pool) then you can set this option #on and set item 17 appropriately. Set to zero not to use, non zero to use #$use_non_dyn_IP_for_tty=1; $use_non_dyn_IP_for_tty=0; ######## Set this, 14 #If you set option 13 above, then set to full directory path external #process will place a single line with the IP address into a file #with name that includes name of SNMP hsot and physical interface device #name. # #Ensure each directory path ends with a seperator. If intending to run on an #NT machine, then ensure the directory seperator is '\\' instead of '/' $Dir_PID="/var/run/"; ######## Set this, 15 #If you haVe set option 13 above then you need to ensure #an external program provides required information from whatever #hosts you indicate in 16 are ports that can have their preferred #IP overridden. # #For UNIX style localhosts the following lines can be inserted in #/etc/ppp/ip-up and /etc/ppp/ipdown. Following a reboot stale #files should be removed automatically by startup, lest the machine #crashed. For hosts other than the host upon which this script is #running, ip-up and ip-down will need to be modified to ensure the #information goes to /var/run of appropriate host. This can be done #using remote shell or other mechanisms, such as remote copy, nfs, #auto processed email and special client/server networking. # #It is vital the 'host_name' for writing to /var/run/, as indicated in #/var/run/mrtg-dynip.host_name~~ttyXY, matches exactly the equivalent #host name in mrtg-dynip. This 'host_name' may be a single name, #a dotted name or a dotted numeric IP address. # #/etc/ppp/ip-up for a localhost running a bash shell can include # #tty_name="$2" #IP_remote="$5" #/bin/echo $IP_remote > /var/run/mrtg-dynip.localhost~~${tty_name##/*/} # #The name of the file must exactly matched that sought for. # #/etc/ppp/ip-down for a localhost running a bash shell can include # #tty_name=$2 #/bin/rm -f /var/run/mrtg-dynip.localhost~~${tty_name##/*/} ######## Set this, 16 #A pair of lines between blank lines represents an interface on a #particular host. # #You can comment out a single pair of lines with a '#' or any non digit #(except whitespace) as the first character of a pair of lines. # #The first line has the following format #'n' 'IP-addr' 'if-speed' 'snmp host' 'snmp community' # #The second line has the following format # 'Any free text description of interface' # #The items must not be enclosed by '"' or '''. Plese see example #below before reading any further. Any whitespace or combination #of whitespace (tabs or spaces) can seperate the items. However it #is important the two lines with 'END_OF_INTERFACES' end without #whitespace. # #'n' is place this entry is to appear in the index of interfaces web file. #The number of digits should be the same for each interface, for example #use sequence 000 010 020 for successive numbers. You can temporarily #take an interface out of consideration by placing any non digit #(except whitespace) before these digits, for example replace 010 #by N010 or #010 # #'IP-addr' is a consistent IP address of a physical interface. Exceptions #can be catered for. If you allow fixed (or static) IP into the physical #interface to override, then you can ensure the line is still marked active #in addition to the static IP entry being marked active. To ensure this #occurs, append '~~ttyXY' to the IP address where ttyXY is the value #returned by ${tty_name##/*/} for the phyical device (or port) as indicated #in section 15. To keep a value in place, even if the port is not part of #an IP overridable rotary pool, append a '~' to the end, such that complete #appendage to the IP address is now '~~ttyXY~'. You can keep the appendages #even if you turn off, or do nor use, $use_non_dyn_IP_for_tty. # #'if-speed' is the interface speed in integer bits/sec. K and M multipliers #for Kb/s and Mb/s can be used (see example). If you want to use decimal #values then rewrite with a lower multiplier, for example write #33.3K as 34099 (integer portion of 33.3 multiplied by 1024). # #'snmp host' is a common and consistent DNS name, or IP address, for #interfaces that belong to a particular machine. For efficiency of snmp #agent use it is better all interfaces that belong to a particular machine #use a consistent name. # #'snmp community' is the community name of the 'public' community #for an interface (the public community does not have to be named #'public'). This value does not have to be set: if this value is #not set then the value of $community_default is used instead. # #'Any free text description of the interface ' on the second line #is as indicated. It need not begin with whitepace (tabs or spaces). # #For dynamic IP interfaces, you must use unvarying 'remote' IPs as indicated #above. Virtual interface devices should not be used, they provide the same #statistics as the real interface they are a virtual interface of. { $interfaces = <$mrtg_Dir"."$mrtgcfg_file" || die "$mrtg_Dir"."$mrtgcfg_file file could not be opened\n"; $ip_descr_ptr = \%ip_descr; foreach $ip_i (keys(%target)) { if ($$ip_descr_ptr{$ip_i}->[0] =~ /^\d/) { ($speed_fig,$speed_mult) = $$ip_descr_ptr{$ip_i}->[1] =~ /^(\d+)(\D*)/; if ($speed_mult =~ /M|m/) { $scale = int ( $speed_fig * 1024 * 1024 / 8 ); } elsif ($speed_mult =~ /K|k/) { $scale = int ( $speed_fig * 1024 / 8 ); } elsif ( $speed_mult eq "" ) { $scale = int ( $speed_fig / 8 ); } else { die("Incorrect speed format in scaler constant $interfaces\n"); } ($ip_if,$host) = split (/@/,$ip_i); if ($firewall_masq_tran_if != 0) { $snmp_target=$ip_i; } else { $snmp_target=$ip_if; } print MRTGCFG <[2]\@$host MaxBytes[$snmp_target]: $scale Title[$snmp_target]: Traffic Analysis through interface device with IP address $ip_if of host $host PageTop[$snmp_target]:

      Stats for interface device with description $$ip_descr_ptr{$ip_i}->[3]

      END } } { print MRTGCFG <$HTTP_Work_Dir"."$HTTP_index_file" || die "Mrtg web index file could not be created\n"; { print MRTGCFGWEB < Index of stats pages for interface devices on interfaces described below

      Active and inactive interace device stats on interfaces described below

      This page last updated on $now

      END } if ($home_page && $home_page_descr) { print MRTGCFGWEB < A network management service courtesy of $home_page_descr

      END } if ($email) { print MRTGCFGWEB < Information and contact address: network management at email $email

      END } { print MRTGCFGWEB < Static IP address and rotary line both marked active if line in use by a static IP address

      END } { print MRTGCFGWEB <

      ACTIVE $$ip_descr_ptr{$ip_i}->[3]
      INACTIVE $$ip_descr_ptr{$ip_i}->[3]
      END } foreach $ip_i (keys %ip_descr) { $ip_order{$$ip_descr_ptr{$ip_i}->[0]} = $ip_i if ($$ip_descr_ptr{$ip_i}->[0] =~ /^\d/); } foreach $i (sort (keys %ip_order)) { $ip_i = $ip_order{$i}; if ($firewall_masq_tran_if != 0) { $file_name=$ip_i; } else { ($file_name) = split (/@/,$ip_i); } if ( defined ($target{$ip_i}) ) { print MRTGCFGWEB < END } else { print MRTGCFGWEB < END } } { print MRTGCFGWEB <

      This web page (but not the web pages above) generated by mrtg-dynip, version 0.41b, 1997/10/25 created by
      John Heenan, john\@heenan.ironbark.id.au

      Mrtg-dynip is a contribution to MRTG, enabling MRTG to generate multi interface traffic graphs for IP interfaces on hosts that do not provide consistent SNMP target numbers for their interfaces. Such IP interfaces include IP active serial interfaces attached to modems in a PPP dial in environment. The hosts must run snmp agents. For completeness, information about interface devices with unvarying SNMP target numbers, such as ethernet cards, can be configured to be included.

      Mrtg-dynip can be considred to have sophisticated modem bank monitoring capacity, when the modems carry PPP or SLIP traffic.

      This web page and web pages above, auto update details, and refresh, every $update minutes.

      Source code for the latest non beta version of the mrtg-dynip software contribution is available from http://www.heenan.ironbark.id.au/source/mrtg-dynip

      END } print MRTGCFGWEB "","\n"; close MRTGCFGWEB; exec ("$mrtg_Dir"."mrtg $mrtgcfg_Dir"."$mrtgcfg_file"); sub datestr { ($time) = shift(@_) || return 0; ($wday) = ('Sunday','Monday','Tuesday','Wednesday', 'Thursday','Friday','Saturday')[(localtime($time))[6]]; ($month) = ('January','February' ,'March' ,'April' , 'May' , 'June' , 'July' , 'August' , 'September' , 'October' , 'November' , 'December' )[(localtime($time))[4]]; ($mday,$year,$hour,$min) = (localtime($time))[3,5,2,1]; if ($min<10) {$min = "0$min";} return "$wday, $mday $month ".($year+1900)." at $hour:$min"; } sub snmp_get_response { use BER; use SNMP_Session; SOLDIER_ON: foreach $comm_host (keys (%snmp_comm_host)) { ($community,$host) = split (/@/,$comm_host); if ($session = SNMP_Session->open ($host, $community, 161)) { @ipRouteIfIndex = split ('\.', '1.3.6.1.2.1.4.21.1.2'); @ipAdEntIfIndex = split ('\.', '1.3.6.1.2.1.4.20.1.2'); $if_route_index_index = encode_oid (@ipRouteIfIndex); $if_index_index = encode_oid (@ipAdEntIfIndex); @oids = ($if_route_index_index); for (;;) { if ($session->getnext_request_response (@oids)) { $response = $session->pdu_buffer; ($bindings) = $session->decode_get_response ($response); @next_oids = (); ($binding,$bindings) = decode_sequence ($bindings); ($oid,$value) = decode_by_template ($binding, "%O%@"); last unless BER::encoded_oid_prefix_p ($if_route_index_index, $oid); push @next_oids, $oid; ($ip_if) = pretty_print ($oid) =~ /.*\.(\d+\.\d+\.\d+\.\d+)$/; $target_i = pretty_print ($value); $target{$ip_if."@".$host} = $target_i if ( defined ($snmp_comm_host{$community."@".$host}{$ip_if}) ); } else { die ("Suicide: no response from community $community on host $host","\n") if ($suicidal != 0); print ("Soldiering on: no response from community $community on host $host","\n"); $session->close (); last SOLDIER_ON; } @oids = @next_oids; } @oids = ($if_index_index); for (;;) { if ($session->getnext_request_response (@oids)) { $response = $session->pdu_buffer; ($bindings) = $session->decode_get_response ($response); @next_oids = (); ($binding,$bindings) = decode_sequence ($bindings); ($oid,$value) = decode_by_template ($binding, "%O%@"); last unless BER::encoded_oid_prefix_p ($if_index_index, $oid); push @next_oids, $oid; ($ip_if) = pretty_print ($oid) =~ /.*\.(\d+\.\d+\.\d+\.\d+)$/; $target_i = pretty_print ($value); $target{$ip_if."@".$host} = $target_i if ( defined ($snmp_comm_host{$community."@".$host}{$ip_if}) ); } else { die ("Suicide: no response from community $community on host $host","\n") if ($suicidal != 0); print ("Soldiering on: no response from community $community on host $host","\n"); $session->close (); last SOLDIER_ON; } @oids = @next_oids; } $session->close (); } else { die ("Suicide: unable to open SNMP session to community $community on host $host","\n") if ($suicidal != 0); print ("Soldiering on: unable to open SNMP session to community $community on host $host","\n"); } } } mrtg-2.17.10/contrib/adm-mrtg/0000755000175300017510000000000013057016061015015 5ustar oetikeroepmrtg-2.17.10/contrib/adm-mrtg/adm-mrtg.README0000644000175300017510000000461013057016061017405 0ustar oetikeroepThis script organizes config files for MRTG and restarts the MRTG processes cleanly. Author: Scott Ripley, U.S. House of Representatives Version: 1.0 (and all that a 1.0 release entails) Contact: scott.ripley@mail.house.gov Copyright: (C) 2001 Scott Ripley 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 of the License, 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. 1.0 Installing Since this is just a shell script, it can be installed anywhere. The standard location is the /usr/local/sbin directory. It creates temp files in the same directory as the MRTG binaries, which are cleared out at the end of the script. 2.0 Configuration You will need to set your pathnames for MRTG, a back-up directory, and the location of your log files. That's it. Note: This script only works if you are running MRTG as a daemon. It relies on the presence of .pid files to identify your scripts. 3.0 Using adm-mrtg The script reads mrtg's bin directory for pid files and displays the appropriate config name on-screen. If you make a change to a config file and want to reload it, type in the number of the config file name. It will kill the process, remove the .pid file and restart it. Once you go back to the home screen, you should see a new date for that config under the "Running" column. 4.0 Backing up with adm-mrtg It is vitally important that you back up your config and log files from time to time. Adm-mrtg will do that for you with the simple press of the 'b' key. It puts all your config files into a tar file with the format "MRTG_.cfgs.tar." It does the same with your .log and .old files. If you want to gzip the files, you can uncomment the gzip lines in the script. 5.0 Technical notes The script was written in ksh on Solaris 7, but there's nothing particularly machine-specific in it. It should only require minor tweaking for other OS/shell combinations. If you have changes or additions you'd like to make, I would enjoy seeing a copy. Please e-mail your changes/comments/ideas to: scott.ripley@mail.house.gov, or nevada@mac.com. Thank you. mrtg-2.17.10/contrib/adm-mrtg/adm-mrtg0000755000175300017510000000777713057016061016475 0ustar oetikeroep#!/usr/bin/ksh # This script organizes config files for MRTG # and restarts the MRTG processes cleanly. # Author: Scott Ripley, U.S. House of Representatives # Version: 1.0 (and all that a 1.0 release entails) # Contact: scott.ripley@mail.house.gov # Copyright: (C) 2001 Scott Ripley # 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 # of the License, 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 # See the GNU General Public License for more details. # Change these directores to match your configuration for MRTG MRTG=/usr/local/mrtg/bin # TARHOME is the location of the back-up files. It should be another volume TARHOME=/usr/local/mrtg/bin # Location of log files WEBHOME=/usr/local/apache/htdocs/mrtg_images cd $MRTG # Initialize the variables and temp files typeset -i CFGLINE typeset -i MAXLINE CFGLINE=1 MAXLINE=1 CFG="$MRTG"/mrtgcfgs.run CFGNUM="$MRTG"/cfgnum.run MCNAME=`uname -n` EXIT=N DATE=`date '+%m%d%y%H%M' ` # TARHOME is the location of the back-up files. It should be another volume TARHOME=/usr/local/mrtg/bin WEBHOME=/usr/local/apache/htdocs/mrtg_images # Set tabs for display columns stty tabs tabs 10,30,40,45 # Main loop while [ "$EXIT" = N ] do # reads the pid files and inputs them into a file ls -go *pid | sed 's/[ ][ ]/ /g' | cut -d"." -f1 > "$CFG" nl -bt -nrz -w2 "$CFG" > "$CFGNUM" # numbers the lines in the file # sets the number of configs loaded, for error testing MAXLINE=`wc -l "$CFG" | cut -d" " -f7 ` clear printf "\n\nThe following MRTG configs are running on "$MCNAME":\n" printf "\n\tConfig name\t\tRunning Since\n" printf "\t-----------\t\t-------------\n" # prints out the appropriate fields on-screen nawk ' { print "\t" $1,$8".cfg \t\t" $5,$6,$7 } ' "$CFGNUM" printf "\n" printf " Which file would you like to reload? (b to back-up, q to quit) \c" read X case "$X" in [qQ] ) EXIT=Y # I quit! ;; [bB] ) printf "\n Backup *.cfg & *.log files? \c" read V case "$V" in 'y' | 'Y' ) CNAME=MRTG_"$DATE".cfgs.tar tar cvf "$TARHOME"/"$CNAME" "$MRTG"/*.cfg chmod 0400 "$TARHOME"/"$CNAME" LNAME=MRTG_"$DATE".logs.tar find "$WEBHOME" | egrep -e "\.log$|\.old$" > mrtgtar.run tar cvf "$LNAME" -I mrtgtar.run chmod 0600 "$TARHOME"/"$CNAME" chmod 0600 "$TARHOME"/"$LNAME" # printf "\nGzipping files..." # gzip "$TARHOME"/"$CNAME" # gzip "$TARHOME"/"$LNAME" printf "\nConfig files backed up to `ls "$TARHOME"/MRTG_"$DATE".cfg*` " printf "\nLog files backed up to `ls "$TARHOME"/MRTG_"$DATE".log*` " printf "\nPress return to continue..." read U ;; * ) printf "\nBackup aborted." sleep 3 ;; esac ;; [0-9][0-9] ) # If the number entered is between 0 and 99... # and if the number is <= the no. of configs loaded if [ "$X" -le "$MAXLINE" ] # then FILE=`sed -n ''$X'p' "$CFGNUM" | cut -d" " -f11 ` # put filename into $FILE echo " Okay to restart "$FILE".cfg? \c" read Y case "$Y" in 'y' | 'Y' ) FKILL=`cat "$MRTG""/""$FILE"".pid"` # Set the variable with the PID kill -9 $FKILL # Kill it rm $MRTG/$FILE".pid" # Remove the file $MRTG"/mrtg" $FILE".cfg" # Restart MRTG with the config file sleep 8 # Wait for new PID file to be created echo "New PID for "$FILE".cfg is `cat "$MRTG"/"$FILE".pid` " ;; *) echo "\nRestart aborted!" ;; esac else echo "Entry Invalid! Press return to continue..." read ZZ fi ;; *) echo "Entry Invalid! Press return to continue..." read ZZ ;; esac done # For security/housekeeping reasons, we clean out the temp files here. cat /dev/null > "$MRTG"/mrtgcfgs.run cat /dev/null > "$MRTG"/cfgnum.run cat /dev/null > "$MRTG"/cfgsed.run cat /dev/null > "$MRTG"/mrtgtar.run exit 0 mrtg-2.17.10/contrib/ovmrtg/0000755000175300017510000000000013057016061014623 5ustar oetikeroepmrtg-2.17.10/contrib/ovmrtg/buildrtov0000644000175300017510000000175113057016061016564 0ustar oetikeroep#Echo This file builds the router config files for MRTG for each router"s interfaces #Echo See NEWRTR.TXT for details on buiding a new router to include rm *.cfg perl cfgmakerov 10.26.254.1 > nrgiga.cfg perl cfgmakerov 203.20.28.1 > zenith.cfg perl cfgmakerov 193.20.1.1 > cwdrtr1.cfg perl cfgmakerov 193.20.1.2 > cwdrtr2.cfg perl cfgmakerov 193.250.1.19 > cwdrtr3.cfg perl cfgmakerov 193.250.1.20 > cwdrtr4.cfg perl cfgmakerov 193.22.1.1 > melrtr1.cfg perl cfgmakerov 193.21.1.1 > sydrtr1.cfg perl cfgmakerov 193.21.1.2 > sydrtr2.cfg perl cfgmakerov 193.250.1.3 > sydrtr3.cfg perl cfgmakerov 10.224.124.0 > tasc1r01.cfg perl cfgmakerov 10.224.124.1 > tasc2r02.cfg perl cfgmakerov 10.25.252.3 > strc1r01.cfg perl cfgmakerov 10.27.252.3 > nrdc1r01.cfg perl cfgmakerov 10.24.253.21 > strrtr01.cfg perl cfgmakerov 10.24.253.22 > strrtr02.cfg perl cfgmakerov 193.250.1.145 > shrtr1.cfg perl cfgmakerov 10.20.20.1 > voda_router.cfg perl cfgmakerov 190.55.55.9 > total-tel-tulla.cfg mrtg-2.17.10/contrib/ovmrtg/ovadd0000644000175300017510000001252713057016061015652 0ustar oetikeroep#!/usr/local/bin/perl5 # -*- mode: Perl -*- ################################################################## # This file controls the creation of all the MRTG config files from OV ################################################################## # Created by Laurie Gellatly # See newrtrov.txt for a description of what is performed ################################################################# # # Distributed under the GNU copyleft # # $Id: ovadd,v 1.1.1.1 2002/02/26 10:16:36 oetiker Exp $ # use Socket; use strict; use vars '$DEBUG'; my $DEBUG = 0; my $company = "Company"; my $rundir = "/opt/mrtg/run"; my $webdir = "/var/opt/ns-fasttrack/docs/mrtg/"; my $cronfile = "mrtgc"; my $roothtml = "routers.html"; my $buildhtf = "buildht"; my $dnsfile = "ovmrtgc.csv"; # Change the next line to be " &" to submit all jobs at once my $backgrnd = " "; my($at,$router,$sysn,$sysncfg,$sysnhtml,$head,$cnt); my(@buildhtt,@sysipnms,@mrtgc,@sysnms); sub main { $router = $ARGV[0]; die < collects`; # Start the collection happening on these interfaces `xnmcollect -merge collects`; `xnmcollect -event`; for ($cnt = 0; $cnt < @sysipnms ; $cnt++){ ($router,$sysn) = split /\,/, $sysipnms[$cnt]; $sysn = lc($sysn); $sysncfg = $sysn.".cfg"; $sysnhtml = $sysn.".html"; # Create the .cfg file for each device `perl $rundir\/cfgmakerov $router > $sysncfg`; # Create the root HTML file for this device in its directory `perl $rundir\/index $sysncfg "Router $sysn" $sysn > $webdir$sysn\/$sysnhtml`; $mrtgc[@mrtgc] = $sysn; } @mrtgc = sort(@mrtgc); $cnt = 0; $head = 0; $at = 0; open(BUILDHT, "<".$buildhtf); # This next piece of code assumes that the $buildhtf file is in alpha order # This code leaves old lines untouched (in case the IP address rather than # the sysName was used as the target while(){ chomp; if (/index (.*)\.cfg/){ $sysn = $1; $head = $_; if (($sysn lt $mrtgc[$at]) || ($at >= @mrtgc)) { $buildhtt[@buildhtt] = $head; }else { do{ $cnt = $mrtgc[$at]; $buildhtt[@buildhtt] = "perl $rundir\/index $cnt.cfg \"Router $cnt\" $cnt > $webdir$cnt\/$cnt.html"; ++$at; }while (($sysn ge $mrtgc[$at]) && ($at < @mrtgc)); if ($sysn ne $mrtgc[$at-1]){ $buildhtt[@buildhtt] = $head; } } } } close (BUILDHT); # In case there were none to start with add it the new members while ($at < @mrtgc){ $cnt = $mrtgc[$at]; $buildhtt[@buildhtt] = "perl $rundir\/index $cnt.cfg \"Router $cnt\" $cnt > $webdir$cnt\/$cnt.html"; ++$at; } open (BUILDHT,">".$buildhtf); print BUILDHT <){ chomp; $sysipnms[@sysipnms] = $_; } close (DNSFILE); @sysipnms = sort srtipnms @sysipnms; $sysn = "."; for ($cnt = 0; $cnt < @sysipnms ; $cnt++){ $head = lc((split /\,/,$sysipnms[$cnt])[1]); if($sysn eq $head){ next; } $sysn = $head; $sysipnms[@sysnms] = $sysipnms[$cnt]; $sysnms[@sysnms] = $sysn; } # Now sysnms has the exact number of targets in it while sysipnms has # the first @sysnms entries correct! open (DNSFILE,">".$dnsfile); for ($cnt = 0; $cnt < @sysnms ; $cnt++){ print DNSFILE "$sysipnms[$cnt]\n"; } close (DNSFILE); open (HTMLF,">".$webdir.$roothtml); print HTMLF <

      $company Router MRTG Traffic Analysis

      ACTIVE $$ip_descr_ptr{$ip_i}->[3]
      INACTIVE $$ip_descr_ptr{$ip_i}->[3]
      ECHO for ($cnt = 0; $cnt < @sysnms ; $cnt++){ $sysn = $sysnms[$cnt]; $sysnhtml = $sysn.".html"; print HTMLF "$sysn<\/A>
      \n"; } print HTMLF <
      ECHO close(HTMLF); open (MRTGC,">".$cronfile); print MRTGC < ################################################################# # # Distributed under the GNU copyleft # # $Id: ovdel,v 1.1.1.1 2002/02/26 10:16:36 oetiker Exp $ # use Socket; use strict; use vars '$DEBUG'; my $DEBUG = 0; my $company = "Company"; my $rundir = "/opt/mrtg/run"; my $webdir = "/var/opt/ns-fasttrack/docs/mrtg/"; my $cronfile = "mrtgc"; my $roothtml = "routers.html"; my $ov_conf = "/etc/opt/OV/share/conf"; my $ovconf = $ov_conf."/snmpCol.conf"; my $buildhtf = "buildht"; my $dnsfile = "ovmrtgc.csv"; # Change the next line to " &" if all jobs are to be submitted at once my $backgrnd = " "; my($router,$sysn,$sysncfg,$sysnhtml,$head,$cnt,$at); my(@sysipnms,@mrtgc,@mrtgd,@sysnms,@ovconfd,@ovmrtgc,@buildhtt); sub main { $router = $ARGV[0]; die < collects`; `xnmcollect -merge collects`; # eventaully HP may decide to remove lines using xnmcollect and then we would # not need the following loop: open (SNMPCOL,"<".$ovconf); # This next piece of code removes any lines in snmpCol.conf that start with XC while(){ if (/^XC /){ next; } else { $ovconfd[@ovconfd] = $_; } } close (SNMPCOL); open (SNMPCOL,">".$ovconf); for ($cnt = 0; $cnt < @ovconfd ; $cnt++){ print SNMPCOL "$ovconfd[$cnt]"; } close (SNMPCOL); `xnmcollect -event`; # Remove the .cfg and .ok files as no longer needed for ($cnt = 0; $cnt < @sysipnms ; $cnt++){ ($router,$mrtgd[@mrtgd]) = split /\,/, lc($sysipnms[$cnt]); unlink($mrtgd[$cnt].".cfg",$mrtgd[$cnt].".ok"); } @mrtgd = sort(@mrtgd); # Assumes that the mrtgc.csv file is in alpha order open (DNSFILE,"<".$dnsfile); $at = 0; while(){ chomp; $head = $_; $sysn = lc((split /\,/,$head)[1]); if ($sysn gt $mrtgd[$at]) { while($at < @mrtgd) { if($sysn le $mrtgd[++$at]){last; } } } if (($sysn lt $mrtgd[$at]) || ($at >= @mrtgd)) { #keep these lines $mrtgc[@mrtgc] = $sysn; $ovmrtgc[@ovmrtgc] = $head; } # } } close (DNSFILE); #Now rebuild the mrtgc.csv file open (DNSFILE,">".$dnsfile); for ($cnt = 0 ; $cnt < @ovmrtgc ; ++$cnt){ print DNSFILE "$ovmrtgc[$cnt]\n"; } close (DNSFILE); #Build the index by keeping the original lines. open (BUILDHT,"<".$buildhtf); $head = 0; $at = 0; # This next piece of code assumes that the $buildhtf file is in alpha order while(){ chomp; if (/index (.*)\.cfg/){ $sysn = $1; $head = $_; if ($sysn gt $mrtgd[$at]) { while($at < @mrtgd) { if($sysn le $mrtgd[++$at]){last; } } } if (($sysn lt $mrtgd[$at]) || ($at >= @mrtgd)) { $buildhtt[@buildhtt] = $head; } } } close (BUILDHT); open (BUILDHT,">".$buildhtf); print BUILDHT <".$webdir.$roothtml); print HTMLF <

      $company Router MRTG Traffic Analysis

      ECHO for ($cnt = 0; $cnt < @mrtgc ; $cnt++){ $sysn = $mrtgc[$cnt]; $sysnhtml = $sysn.".html"; print HTMLF "$sysn<\/A>
      \n"; } print HTMLF <
      ECHO close(HTMLF); open (MRTGC,">".$cronfile); print MRTGC < # based on mrtg cfgmaker by Tobias Oetiker # this produces a config file for one router, by pulling info # off the router via snmp and then writing files ready for # snmpCollect to use (via xnmcollect) and later ovlg calls ################################################################# # # Distributed under the GNU copyleft # # $Id: cfgmakerov,v 1.1.1.1 2002/02/26 10:16:36 oetiker Exp $ # use SNMP_Session "0.58"; use BER "0.57"; use Socket; use strict; use vars '$DEBUG'; my $DEBUG = 0; my $webdir = "/var/opt/ns-fasttrack/docs/mrtg/"; %snmpget::OIDS = ( 'sysDescr' => '1.3.6.1.2.1.1.1.0', 'sysContact' => '1.3.6.1.2.1.1.4.0', 'sysName' => '1.3.6.1.2.1.1.5.0', 'sysLocation' => '1.3.6.1.2.1.1.6.0', 'sysUptime' => '1.3.6.1.2.1.1.3.0', 'ifNumber' => '1.3.6.1.2.1.2.1.0', ################################### # add the ifNumber .... 'ifDescr' => '1.3.6.1.2.1.2.2.1.2', 'ifType' => '1.3.6.1.2.1.2.2.1.3', 'ifIndex' => '1.3.6.1.2.1.2.2.1.1', 'ifSpeed' => '1.3.6.1.2.1.2.2.1.5', 'ifOperStatus' => '1.3.6.1.2.1.2.2.1.8', 'ifAdminStatus' => '1.3.6.1.2.1.2.2.1.7', # up 1, down 2, testing 3 'ipAdEntAddr' => '1.3.6.1.2.1.4.20.1.1', 'ipAdEntIfIndex' => '1.3.6.1.2.1.4.20.1.2', 'sysObjectID' => '1.3.6.1.2.1.1.2.0', 'CiscolocIfDescr' => '1.3.6.1.4.1.9.2.2.1.1.28', 'ifAlias' => '1.3.6.1.2.1.31.1.1.1.18', 'ifName' => '1.3.6.1.2.1.31.1.1.1.1' ); sub main { my(%ifType_d)=('1'=>'Other', '2'=>'regular1822', '3'=>'hdh1822', '4'=>'ddnX25', '5'=>'rfc877x25', '6'=>'ethernetCsmacd', '7'=>'iso88023Csmacd', '8'=>'iso88024TokenBus', '9'=>'iso88025TokenRing', '10'=>'iso88026Man', '11'=>'starLan', '12'=>'proteon10Mbit', '13'=>'proteon80Mbit', '14'=>'hyperchannel', '15'=>'fddi', '16'=>'lapb', '17'=>'sdlc', '18'=>'ds1', '19'=>'e1', '20'=>'basicISDN', '21'=>'primaryISDN', '22'=>'propPointToPointSerial', '23'=>'ppp', '24'=>'softwareLoopback', '25'=>'eon', '26'=>'ethernet-3Mbit', '27'=>'nsip', '28'=>'slip', '29'=>'ultra', '30'=>'ds3', '31'=>'sip', '32'=>'frame-relay', '33'=>'rs232', '34'=>'para', '35'=>'arcnet', '36'=>'arcnetPlus', '37'=>'atm', '38'=>'miox25', '39'=>'sonet', '40'=>'x25ple', '41'=>'iso88022llc', '42'=>'localTalk', '43'=>'smdsDxi', '44'=>'frameRelayService', '45'=>'v35', '46'=>'hssi', '47'=>'hippi', '48'=>'modem', '49'=>'aal5', '50'=>'sonetPath', '51'=>'sonetVT', '52'=>'smdsIcip', '53'=>'propVirtual', '54'=>'propMultiplexor', '55'=>'100BaseVG' ); my($vendor)=0; my($router) = $ARGV[0]; die <>mrtg.cfg USAGE my($sysDescr,$sysContact,$sysName,$sysLocation,$ifNumber,$sysObjectID) = snmpget($router, 'sysDescr','sysContact','sysName', 'sysLocation', 'ifNumber', 'sysObjectID'); ### The next three lines can be deleted once Someone gives this box a name if ($router eq '10.26.254.1') { $sysName = 'nrgiga'; } if ($sysName eq "") { $sysName = $router; } my($sysNameL) = $sysName; $sysNameL =~ tr/[A-Z]/[a-z]/; $sysDescr =~ s/\r/
      /g; # Change returns to
      my($ciscobox) = ($sysObjectID =~ /cisco/); my($portmaster) = ($sysObjectID =~ /livingston/); $vendor = ($ciscobox || $portmaster) ; my($ifInErrors) = '1.3.6.1.2.1.2.2.1.14'; my($ifOutErrors) = '1.3.6.1.2.1.2.2.1.20'; ### Create the directory if it does not exist mkdir("$webdir$sysNameL",0777); print <CPU Load % ShortLegend[$sysNameL.cpu]: % XSize[$sysNameL.cpu]: 380 YSize[$sysNameL.cpu]: 100 YLegend[$sysNameL.cpu]: CPU Utilization Legend1[$sysNameL.cpu]: CPU Utilization in % (Load) Legend2[$sysNameL.cpu]: CPU Utilization in % (Load) Legend3[$sysNameL.cpu]: Legend4[$sysNameL.cpu]: LegendI[$sysNameL.cpu]: LegendO[$sysNameL.cpu]:  Usage: Options[$sysNameL.cpu]: growright, gauge #--------------------------------------------------------------- ECHO } my @ipadent = snmpgettable($router, 'ipAdEntAddr'); print STDERR "Got Addresses\n" if $DEBUG; my @ipadentif = snmpgettable($router, 'ipAdEntIfIndex'); print STDERR "Got IfTable\n" if $DEBUG; my(%ipaddr, %iphost,$index); while (scalar @ipadentif){ $index = shift @ipadentif; $ipaddr{$index} = shift @ipadent; $iphost{$index} = gethostbyaddr(pack('C4',split(/\./,$ipaddr{$index})), AF_INET); if ($iphost{$index} eq ''){ $iphost{$index} = $ipaddr{$index}; } } my(@ifdescr) = snmpgettable($router, 'ifDescr'); print STDERR "Got IfDescr\n" if $DEBUG; my(@iftype) = snmpgettable($router, 'ifType'); print STDERR "Got IfType\n" if $DEBUG; my(@ifspeed) = snmpgettable($router, 'ifSpeed'); print STDERR "Got IfSpeed\n" if $DEBUG; my(@ifadminstatus) = snmpgettable($router, 'ifAdminStatus'); print STDERR "Got IfStatus\n" if $DEBUG; my(@ifoperstatus) = snmpgettable($router, 'ifOperStatus'); print STDERR "Got IfOperStatus\n" if $DEBUG; my(@ifindex) = snmpgettable($router, 'ifIndex'); print STDERR "Got IfIndex\n" if $DEBUG; my(@ifname) = snmpgettable($router, 'ifName'); print STDERR "Got IfName\n" if $DEBUG; my(%sifdesc,%siftype,%sifspeed,%sifadminstatus,%sifoperstatus,%sciscodescr,%sifname); ### May need the cisco IOS version number so we know which oid to use ### to get the cisco description. ### ### - mjd 2/5/98 (Mike Diehn) (mdiehn@mindspring.net) ### my ($cisco_ver, $cisco_descr_oid, @ciscodescr); if ( $ciscobox ) { ($cisco_ver) = ($sysDescr =~ /Version\s+([\d.]+)/); $cisco_descr_oid = ($cisco_ver ge "11.3") ? "ifAlias" : "CiscolocIfDescr"; } while (scalar @ifindex) { # as these arrays get filled from the bottom, # we need to empty them from the botom as well ... # fifo $index = shift @ifindex; $sifdesc{$index} = shift @ifdescr; $sifname{$index} = shift @ifname; $siftype{$index} = shift @iftype; $sifspeed{$index} = shift @ifspeed; $sifadminstatus{$index} = shift @ifadminstatus; $sifoperstatus{$index} = shift @ifoperstatus; if ($portmaster) { # Trying to extract extra info livingston # We can only approximate speeds # # so we think that ppp can do 76800 bit/s, and slip 38400. # (actualy, slip is a bit faster, but usualy users with newer modems # use ppp). Alternatively, you can set async speed to 115200 or # 230400 (the maximum speed supported by portmaster). # # But if the interface is ptpW (sync), max speed is 128000 # change it to your needs. On various Portmasters there are # various numbers of sync interfaces, so modify it. # # The most commonly used PM-2ER has only one sync. # # Paul Makeev (mac@redline.ru) # if ($siftype{$index} eq 'ppp') { if ($sifdesc{$index} eq 'ptpW1') { $sifspeed{$index} = 128000; } else { $sifspeed{$index} = 76800; } } elsif ($siftype{$index} eq 'slip') { $sifspeed{$index} = 38400; } elsif ($siftype{$index} eq 'ethernetCsmacd') { $sifspeed{$index} = 10000000; } } ### Move this section south so we know what type of ### circuit we're looking at before we retrieve ### the cisco interface alias. ### ### This whole cicso thing should be re-written, but since ### this script doesn't need to run quickly... ### ### - mjd 2/5/98 ### # Get the user configurable interface description entered in the config # if it's a cisco-box # if ($ciscobox) { my ($enoid, @descr); $enoid = $snmpget::OIDS{"$cisco_descr_oid"} . "." . $index; if ( $cisco_ver ge "11.2" or $siftype{$index} ne 'frame-relay' ) { ### This is either not a frame-relay sub-interface or ### this router is running IOS 11.2+ and interface ### type won't matter. In either of these cases, it's ### ok to try getting the ifAlias or ciscoLocIfDesc. ### @descr = snmpget($router, $enoid); } else { ### This is a frame-relay sub-interface *and* the router ### is running an IOS older than 11.2. Therefore, we can ### get neither ifAlias nor ciscoLocIfDesc. Do something ### useful. ### @descr = ("Cisco PVCs descriptions require IOS 11.2+."); } # end if else ### Put whatever I got into the array we'll use later to append the result ### of this operation onto the results from the ifDescr fetch. ### push @ciscodescr, shift @descr; } # end if ($ciscobox) # especially since cisco does not return a if # descr for each interface it has ... ## JB 2/8/97 - sometimes IOS inserts E1 controllers in the standard-MIB ## interface table, but not in the local interface table. This puts the ## local interface description table out-of-sync. the following ## modification skips over E1 cards as interfaces. # ### I suspect that the mod I made above, to use the ifAlias ### oid if possible, may cause problems here. If it seems ### that your descriptions are out of sync, try commenting ### out the "if ( condition )" and it's closing right brace ### so that the "shift @ciscodescr" get executed for *all* ### iterations of this loop. ### ### - mjd 2/5/95 ### if ($ciscobox && $siftype{$index} ne 'ds1') { $sciscodescr{$index} = "
      " . (shift @ciscodescr) if @ciscodescr; } } foreach $index ( sort { $a <=> $b } keys %sifdesc) { my $c; my $speed = int($sifspeed{$index} / 8); # bits to byte # LJG Change to report in Bits # my $speed_str=&fmi($speed); my $speed_str=&fmi($sifspeed{$index}); my $name="$sysNameL.$index"; my $namerr="$sysNameL.$index.err"; if (($sifadminstatus{$index} ne "up") # this check added by Josh - don't query E1-stack controllers || ($siftype{$index} eq 'ds1') || ($siftype{$index} eq 'softwareLoopback') || ($speed == 0 ) # LJG Change to report all in Bits # || ($speed > 400 * 10**6) #speeds of 400 MByte/s are not realistic || ($speed > 3200 * 10**6) #speeds of 400 MByte/s are not realistic || ($sifoperstatus{$index} eq 'down') || (($sifdesc{$index}=~ /Dialer/) && ($ciscobox))) { print <Traffic Analysis for $sifdesc{$index} ${c} $sciscodescr{$index} ${c} ${c} ${c} ${c} ${c} ${c} ${c} ${c}
      System:$sysName in $sysLocation
      Maintainer:$sysContact
      Interface:$sifdesc{$index} ($index - $sifname{$index})
      IP:$iphost{$index} ($ipaddr{$index})
      Max Speed:$speed_str ($siftype{$index})
      ${c} #--------------------------------------------------------------- # In and Out Error Counts ${c} ${c}Target[$namerr]: `perl ovcvtfile $router $index 0` ${c}MaxBytes[$namerr]: 2147483600 ${c}Title[$namerr]: $sysName ($iphost{$index}): $sifdesc{$index} $sifname{$index} I/O Errors ${c}Options[$namerr]: growright, gauge ${c}PageTop[$namerr]:

      I/O Error Analysis for $sifdesc{$index} ${c} $sciscodescr{$index}

      ${c}YLegend[$namerr]: Errors/Period ${c}Legend1[$namerr]: Inward Errors ${c}Legend2[$namerr]: Outward Errors ${c}Legend3[$namerr]: ${c}Legend4[$namerr]: ${c}LegendI[$namerr]:  In : ${c}LegendO[$namerr]:  Out : ${c} #--------------------------------------------------------------- ECHO } } main; exit(0); sub snmpget{ my($host,@vars) = @_; my(@enoid, $var,$response, $bindings, $binding, $value, $inoid,$outoid, $upoid,$oid,@retvals,$t1,$t2,@resp,$tempo); my($hackcisco); foreach $var (@vars) { die "Unknown SNMP var $var\n" unless $snmpget::OIDS{$var} || $var =~ /^\d+[\.\d+]*\.\d+$/; if ($var =~ /^\d+[\.\d+]*\.\d+/) { $value = $value.$var." "; $hackcisco = 1; } else { $value = $value.$snmpget::OIDS{$var}." "; $hackcisco = 0; } } open(SNMPG, "snmpget $host $value |"); # print STDERR $value; while ($tempo =){ # print STDERR $tempo; ($t1, $t2, $tempo ) = split /:/ , $tempo, 3; if (!$tempo){ if ($t2){ $t1 = $t1 .":".$t2; } $tempo = pop(@retvals)." ".$t1 ; } $tempo=~s/\t/ /g; $tempo=~s/\n/ /g; $tempo=~s/^\s+//; $tempo=~s/\s+$//; push @retvals, $tempo; } # print STDERR @retvals; close (SNMPG); return (@retvals); } sub snmpgettable{ my($host,$var) = @_; my($next_oid,$enoid,$orig_oid, $response, $bindings, $binding, $t1, $t2,$outoid, $upoid,$oid,@table,$tempo); die "Unknown SNMP var $var\n" unless $snmpget::OIDS{$var}; $orig_oid = $snmpget::OIDS{$var}." "; $enoid=$orig_oid; open(SNMPG, "snmpwalk $host $orig_oid |"); # print STDERR $orig_oid; while ($tempo =){ # print STDERR $tempo; ($t1, $t2, $tempo ) = split /:/ , $tempo ,3; if (!$tempo){ if ($t2){ $t1 = $t1 .":".$t2; } $tempo = pop(@table)." ".$t1 ; } $tempo=~s/\t/ /g; $tempo=~s/\n/ /g; $tempo=~s/^\s+//; $tempo=~s/\s+$//; push @table, $tempo; } close (SNMPG); return (@table); } sub fmi { my($number) = $_[0]; my(@short); # LJG Change to report in Bits # @short = ("Bytes/s","kBytes/s","MBytes/s","GBytes/s"); @short = ("Bits/s","kBits/s","MBits/s","GBits/s"); my $digits=length("".$number); my $divm=0; while ($digits-$divm*3 > 3) { $divm++; } my $divnum = $number/10**($divm*3); return sprintf("%1.1f %s",$divnum,$short[$divm]); } mrtg-2.17.10/contrib/ovmrtg/ovmrtg.pm0000644000175300017510000003064013057016061016502 0ustar oetikeroep#!/usr/local/bin/perl5 # -*- mode: Perl -*- ################################################################## # Config file creator ################################################################## # Created by Laurie Gellatly # this produces an array of ip address and system names for each # ip address passed to it, by pulling info # off the device via snmp ################################################################# # # Distributed under the GNU copyleft # # $Id: ovmrtg.pm,v 1.1.1.1 2002/02/26 10:16:36 oetiker Exp $ # package ovmrtg; use Socket; use strict; use vars qw(@ISA @EXPORT $VERSION); use Exporter; $VERSION = '0.00'; @ISA = qw(Exporter); @EXPORT = qw(ovsysnms ovcols); sub ovsysnms(@); sub ovcols(@); my $DEBUG = 0; my($router,$routerip,@res,@result,$cnt); my($op,$vendor); %snmpget::OIDS = ( 'sysDescr' => '1.3.6.1.2.1.1.1.0', 'sysContact' => '1.3.6.1.2.1.1.4.0', 'sysName' => '1.3.6.1.2.1.1.5.0', 'sysLocation' => '1.3.6.1.2.1.1.6.0', 'sysUptime' => '1.3.6.1.2.1.1.3.0', 'ifNumber' => '1.3.6.1.2.1.2.1.0', ################################### # add the ifNumber .... 'ifDescr' => '1.3.6.1.2.1.2.2.1.2', 'ifType' => '1.3.6.1.2.1.2.2.1.3', 'ifIndex' => '1.3.6.1.2.1.2.2.1.1', 'ifSpeed' => '1.3.6.1.2.1.2.2.1.5', 'ifOperStatus' => '1.3.6.1.2.1.2.2.1.8', 'ifAdminStatus' => '1.3.6.1.2.1.2.2.1.7', # up 1, down 2, testing 3 'ipAdEntAddr' => '1.3.6.1.2.1.4.20.1.1', 'ipAdEntIfIndex' => '1.3.6.1.2.1.4.20.1.2', 'sysObjectID' => '1.3.6.1.2.1.1.2.0', 'CiscolocIfDescr' => '1.3.6.1.4.1.9.2.2.1.1.28', 'ifAlias' => '1.3.6.1.2.1.31.1.1.1.18' ); sub ovcols(@) { my @args = @_; my @r; $op = $args[0]; shift @args; if ($op eq "+"){ $op = "C"; } else { $op = "XC"; } while($router=$args[0]){ my($sysDescr,$sysContact,$sysName,$sysLocation,$ifNumber,$sysObjectID) = snmpget($router, 'sysDescr','sysContact','sysName', 'sysLocation', 'ifNumber', 'sysObjectID'); my ($sint2mon); my $cc = " "; $sysDescr =~ s/\r/
      /g; # Change returns to
      my($ciscobox) = ($sysObjectID =~ /cisco/); my($portmaster) = ($sysObjectID =~ /livingston/); $vendor = ($ciscobox || $portmaster) ; my($ifInErrors) = '1.3.6.1.2.1.2.2.1.14'; my($ifOutErrors) = '1.3.6.1.2.1.2.2.1.20'; my @ipadent = snmpgettable($router, 'ipAdEntAddr'); print STDERR "Got Addresses\n" if $DEBUG; my @ipadentif = snmpgettable($router, 'ipAdEntIfIndex'); print STDERR "Got IfTable\n" if $DEBUG; my(%ipaddr, %iphost,$index); while (scalar @ipadentif){ $index = shift @ipadentif; $ipaddr{$index} = shift @ipadent; $iphost{$index} = gethostbyaddr(pack('C4',split(/\./,$ipaddr{$index})), AF_INET); if ($iphost{$index} eq ''){ $iphost{$index} = $ipaddr{$index}; } } my(@ifdescr) = snmpgettable($router, 'ifDescr'); print STDERR "Got IfDescr\n" if $DEBUG; my(@iftype) = snmpgettable($router, 'ifType'); print STDERR "Got IfType\n" if $DEBUG; my(@ifspeed) = snmpgettable($router, 'ifSpeed'); print STDERR "Got IfSpeed\n" if $DEBUG; my(@ifadminstatus) = snmpgettable($router, 'ifAdminStatus'); print STDERR "Got IfStatus\n" if $DEBUG; my(@ifoperstatus) = snmpgettable($router, 'ifOperStatus'); print STDERR "Got IfOperStatus\n" if $DEBUG; my(@ifindex) = snmpgettable($router, 'ifIndex'); print STDERR "Got IfIndex\n" if $DEBUG; my(%sifdesc,%siftype,%sifspeed,%sifadminstatus,%sifoperstatus,%sciscodescr); ### May need the cisco IOS version number so we know which oid to use ### to get the cisco description. ### ### - mjd 2/5/98 (Mike Diehn) (mdiehn@mindspring.net) ### my ($cisco_ver, $cisco_descr_oid, @ciscodescr); if ( $ciscobox ) { ($cisco_ver) = ($sysDescr =~ /Version\s+([\d.]+)/); $cisco_descr_oid = ($cisco_ver ge "11.3") ? "ifAlias" : "CiscolocIfDescr"; } while (scalar @ifindex) { # as these arrays get filled from the bottom, # we need to empty them from the botom as well ... # fifo $index = shift @ifindex; $sifdesc{$index} = shift @ifdescr; $siftype{$index} = shift @iftype; $sifspeed{$index} = shift @ifspeed; $sifadminstatus{$index} = shift @ifadminstatus; $sifoperstatus{$index} = shift @ifoperstatus; if ($portmaster) { # Trying to extract extra info livingston # We can only approximate speeds # # so we think that ppp can do 76800 bit/s, and slip 38400. # (actualy, slip is a bit faster, but usualy users with newer modems # use ppp). Alternatively, you can set async speed to 115200 or # 230400 (the maximum speed supported by portmaster). # # But if the interface is ptpW (sync), max speed is 128000 # change it to your needs. On various Portmasters there are # various numbers of sync interfaces, so modify it. # # The most commonly used PM-2ER has only one sync. # # Paul Makeev (mac@redline.ru) # if ($siftype{$index} eq 'ppp') { if ($sifdesc{$index} eq 'ptpW1') { $sifspeed{$index} = 128000; } else { $sifspeed{$index} = 76800; } } elsif ($siftype{$index} eq 'slip') { $sifspeed{$index} = 38400; } elsif ($siftype{$index} eq 'ethernetCsmacd') { $sifspeed{$index} = 10000000; } } ### Move this section south so we know what type of ### circuit we're looking at before we retrieve ### the cisco interface alias. ### ### This whole cicso thing should be re-written, but since ### this script doesn't need to run quickly... ### ### - mjd 2/5/98 ### # Get the user configurable interface description entered in the config # if it's a cisco-box # if ($ciscobox) { my ($enoid, @descr); $enoid = $snmpget::OIDS{"$cisco_descr_oid"} . "." . $index; if ( $cisco_ver ge "11.2" or $siftype{$index} ne 'frame-relay' ) { ### This is either not a frame-relay sub-interface or ### this router is running IOS 11.2+ and interface ### type won't matter. In either of these cases, it's ### ok to try getting the ifAlias or ciscoLocIfDesc. ### @descr = snmpget($router, $enoid); } else { ### This is a frame-relay sub-interface *and* the router ### is running an IOS older than 11.2. Therefore, we can ### get neither ifAlias nor ciscoLocIfDesc. Do something ### useful. ### @descr = ("Cisco PVCs descriptions require IOS 11.2+."); } # end if else ### Put whatever I got into the array we'll use later to append the result ### of this operation onto the results from the ifDescr fetch. ### push @ciscodescr, shift @descr; } # end if ($ciscobox) # especially since cisco does not return a if # descr for each interface it has ... ## JB 2/8/97 - sometimes IOS inserts E1 controllers in the standard-MIB ## interface table, but not in the local interface table. This puts the ## local interface description table out-of-sync. the following ## modification skips over E1 cards as interfaces. # ### I suspect that the mod I made above, to use the ifAlias ### oid if possible, may cause problems here. If it seems ### that your descriptions are out of sync, try commenting ### out the "if ( condition )" and it's closing right brace ### so that the "shift @ciscodescr" get executed for *all* ### iterations of this loop. ### ### - mjd 2/5/95 ### if ($ciscobox && $siftype{$index} ne 'ds1') { $sciscodescr{$index} = "
      " . (shift @ciscodescr) if @ciscodescr; } } foreach $index ( sort { $a <=> $b } keys %sifdesc) { my $speed = int($sifspeed{$index} / 8); # bits to byte # LJG Change to report in Bits # my $speed_str=&fmi($speed); my $speed_str=&fmi($sifspeed{$index}); my $name="$router.$index"; my $namerr="$router.$index.err"; if (($sifadminstatus{$index} ne "up") # this check added by Josh - don't query E1-stack controllers || ($siftype{$index} eq 'ds1') || ($siftype{$index} eq 'softwareLoopback') || ($speed == 0 ) # LJG Change to report all in Bits # || ($speed > 400 * 10**6) #speeds of 400 MByte/s are not realistic || ($speed > 3200 * 10**6) #speeds of 400 MByte/s are not realistic || ($sifoperstatus{$index} eq 'down') || (($sifdesc{$index}=~ /Dialer/) && ($ciscobox))) { ######## ######## This Interface is one of the following ######## - administratively not UP ######## - it is in test mode ######## - it is a softwareLoopback interface ######## - has a unrealistic speed setting ######## It is commented out for this reason. ######## }else { $sint2mon = $sint2mon .$cc.$index; $cc = ","; } } if ($ciscobox){ $r[@r]="MIB .1.3.6.1.4.1.9.2.1.58 avgBusy5 units INTEGER R"; $r[@r]="$op $router .1.3.6.1.* 300 > 0 1 <= 0 1 xA s 58720263 ALL -"; } $r[@r]="MIB .1.3.6.1.2.1.1.3 sysUpTime units TIMETICKS R"; $r[@r]="$op $router .1.3.6.1.* 300 > 0 1 <= 0 1 xA s 58720263 ALL -"; $r[@r]="MIB .1.3.6.1.2.1.2.2.1.10 IfInOctets units/sec COUNTER R"; $r[@r]="$op $router .1.3.6.1.* 300 > 0 1 <= 0 1 xA s 58720263 LIST $sint2mon"; $r[@r]="MIB .1.3.6.1.2.1.2.2.1.16 IfOutOctets units/sec COUNTER R"; $r[@r]="$op $router .1.3.6.1.* 300 > 0 1 <= 0 1 xA s 58720263 LIST $sint2mon"; $r[@r]="MIB .1.3.6.1.2.1.2.2.1.14 IfInErrors units/sec COUNTER R"; $r[@r]="$op $router .1.3.6.1.* 300 > 0 1 <= 0 1 xA s 58720263 LIST $sint2mon"; $r[@r]="MIB .1.3.6.1.2.1.2.2.1.20 IfOutErrors units/sec COUNTER R"; $r[@r]="$op $router .1.3.6.1.* 300 > 0 1 <= 0 1 xA s 58720263 LIST $sint2mon"; shift @args; } return (@r); } sub snmpgettable{ my($host,$var) = @_; my($next_oid,$enoid,$orig_oid, $response, $bindings, $binding, $t1, $t2,$outoid, $upoid,$oid,@table,$tempo); die "Unknown SNMP var $var\n" unless $snmpget::OIDS{$var}; $orig_oid = $snmpget::OIDS{$var}." "; $enoid=$orig_oid; open(SNMPG, "snmpwalk $host $orig_oid |"); # print STDERR $orig_oid; while ($tempo =){ # print STDERR $tempo; ($t1, $t2, $tempo ) = split /:/ , $tempo ,3; if (!$tempo){ if ($t2){ $t1 = $t1 .":".$t2; } $tempo = pop(@table)." ".$t1 ; } $tempo=~s/\t/ /g; $tempo=~s/\n/ /g; $tempo=~s/^\s+//; $tempo=~s/\s+$//; push @table, $tempo; } close (SNMPG); return (@table); } sub fmi { my($number) = $_[0]; my(@short); # LJG Change to report in Bits # @short = ("Bytes/s","kBytes/s","MBytes/s","GBytes/s"); @short = ("Bits/s","kBits/s","MBits/s","GBits/s"); my $digits=length("".$number); my $divm=0; while ($digits-$divm*3 > 3) { $divm++; } my $divnum = $number/10**($divm*3); return sprintf("%1.1f %s",$divnum,$short[$divm]); } sub ovsysnms (@){ my @args = @_; while($router = $args[0]){ my($sysName)= snmpget($router, 'sysName'); ### The next three lines can be deleted once Someone gives this box a name if ($router eq '10.26.254.1') { $sysName = 'nrgiga'; } if ($sysName eq ""){ $sysName = $router; } # $sysName =~ tr/[A-Z]/[a-z]/; # Don't like to do it this way but... # @res=`ovtopodump $router`; # for ($cnt = 0 ; $cnt < @res; $cnt++){ # $_ = $res[$cnt]; # if (/IP ADDR: (.*)/){ @res=`ping $router -n 1`; for ($cnt = 0 ; $cnt < @res; $cnt++){ $_ = $res[$cnt]; if (/from (.*):.*/) { $routerip = $1; last; } } @res= `ovobjprint -a "IP Hostname" "SNMP sysName"=$sysName`; $_ = $res[4]; if(!/NO FIELD VALUES FOUND/){ ($router) = ($res[4] =~ m@\"(.*)\"@ ); } $result[@result]= $routerip."\,".$sysName."\,".$router; shift @args; } return @result; } sub snmpget{ my($host,@vars) = @_; my(@enoid, $var,$response, $bindings, $binding, $value, $inoid,$outoid, $upoid,$oid,@retvals,$t1,$t2,@resp,$tempo); my($hackcisco); foreach $var (@vars) { die "Unknown SNMP var $var\n" unless $snmpget::OIDS{$var} || $var =~ /^\d+[\.\d+]*\.\d+$/; if ($var =~ /^\d+[\.\d+]*\.\d+/) { $value = $value.$var." "; $hackcisco = 1; } else { $value = $value.$snmpget::OIDS{$var}." "; $hackcisco = 0; } } open(SNMPG, "snmpget $host $value |"); while ($tempo =){ ($t1, $t2, $tempo ) = split /:/ , $tempo, 3; if (!$tempo){ if ($t2){ $t1 = $t1 .":".$t2; } $tempo = pop(@retvals)." ".$t1 ; } $tempo=~s/\t/ /g; $tempo=~s/\n/ /g; $tempo=~s/^\s+//; $tempo=~s/\s+$//; push @retvals, $tempo; } close (SNMPG); return (@retvals); } 1; mrtg-2.17.10/contrib/ovmrtg/ovtst0000644000175300017510000000176613057016061015737 0ustar oetikeroep#!/usr/local/bin/perl5 # -*- mode: Perl -*- ################################################################## # This file controls the creation of all the MRTG config files from OV ################################################################## # Created by Laurie Gellatly # See newrtrov.txt for a description of what is performed ################################################################# # # Distributed under the GNU copyleft # # $Id: ovtst,v 1.1.1.1 2002/02/26 10:16:36 oetiker Exp $ # use Socket; use strict; use vars '$DEBUG'; my $DEBUG = 0; my $webdir = "/var/opt/ns-fasttrack/docs/mrtg/"; my $rundir = "/opt/mrtg/run"; my $testout = "test.out"; my $roothtml = "routers.html"; my($router,$sysn,$sysncfg,$sysnhtml,$cnt,@sysipnms,@mrtgc,@sysnms); sub main { chdir $rundir; @sysnms=%ENV; chomp(@sysipnms); open (MRTGC,">".$testout); for ($cnt = 0; $cnt < @sysnms ; $cnt++){ print MRTGC "$sysnms[$cnt]\n"; } close (MRTGC); } main; exit(0); mrtg-2.17.10/contrib/ovmrtg/README0000644000175300017510000001007113057016061015502 0ustar oetikeroepThe following requirements/outstanding issues exist for OVMRTG. =============================================================== Installation Version 0.2 ------------------------ After installing MRTG and HPOV the following additional customisation needs to be done. The file $rundir/installov.cmds should be modified to reflect the locations of 1) the mrtg executables ($rundir) 2) the web output directory ($webdir) 3) the name of the cron file within $rundir ($cronfile) 4) the name of the root HTML file within $webdir ($roothtml). 5) the name of the HTML rebuild file ($buildhtf) 6) the company name for display in the HTML ($company) 7) the directory where the HPOV databases exist {$OV_DB} ($ov_db) 8) the directory where snmpCol.conf is found {$OV_CONF} ($ov_conf) 9) Any command line changes to run the perl from within HPOV. May need full directory paths to both perl and ovmrtg scripts NT: Suggested defaults for the above items under NT: 3) mrtgkick.bat 5) buildht.bat 7) /OpenView/databases 8) /OpenView/conf Then installov should be run from within the mrtg directory to update the scripts. Next the perl script ovupdate should be run to create the new ovmrtgc.csv file mrtgmenu then needs to be placed into $OV_REGISTRATION/C and be readable by the group of users that might need to change mrtg targets. You will need to shutdown and restart ovw to see the menu items appear under the Misc menu. You do not need to do an ovstop! The gif files for MRTG banner are located in the common directory $webdir for all the HTML's to reference a single copy. ISSUES ------ It is assumed that the HPOV host is also the web server for MRTG so that mkdir's can be executed in the WEB directories. As the target/s are selected from the HPOV screen, it is assumed that HPOV already knows what the read community names are for these devices. OVMRTG uses this fact to alleviate the need for it to know community names. Little error checking and reporting is currently done. If someone is displaying the data collection screen then ovadd and ovdel will fail and will NOT report failure to the user. The SNMP sysName is used to create directories in the web area and is also used for most file and web names for that device. As such, the system name needs to be unique and set for each device that will be monitored. If it is not set for each device then the IP address is used instead. Code that translates IP Address to sysname can be setup in ovsysnms and in cfgmakerov if desired. All directories, configs html files etc are produced for each target by the unique sysname. At present the data collects into the snmpCollect directory forever. I've started to write a cleanup routine that will be able to keep only recent history. (see ovcullfile) ovdel does not destroy the directories that are created for the deleted target (a safety measure). If you want to clean them up it is currently a manual process. Access ------ $rundir & $webdir files & directories should be rw for the group of people that might be changing mrtg targets from within HPOV $OV_CONF/snmpCol.conf needs to be rw for OVMRTG users In the mrtg executable directory, the .cfg files are created. A file called 'collects' is also created as a work file. DO NOT create a file in this directory with this name. CRON ---- cron needs to be setup by the user. Typically a line like this works: 0,5,10,15,20,25,30,35,40,45,50,55 * * * * /opt/mrtg/run/mrtgc 2>/opt/mrtg/run/log 1>&2 The equivalent job should be setup under NT. OVMRTG should not care if the host is Unix or NT. The end of ovadd and ovdel may be customised to perform extra tasks by the cron job. Usage ----- Once setup, the user selects the OVMRTG target/s from the OV screen. The Misc menu item is then selected, followed by Mrtg Actions and then select either the 'Add/Update' or 'Stop collecting' options. The third option, Show MRTG Targets, works on Unix systems ONLY at present. I only have the UNIX NNM developers kit. This option 'selects' the current targets on the screen for easy updates. To understand what happens for an add/update, see the file newrtrov.txt mrtg-2.17.10/contrib/ovmrtg/ovupdate0000644000175300017510000000313313057016061016375 0ustar oetikeroep#!/usr/local/bin/perl5 # -*- mode: Perl -*- ################################################################## # This file controls the creation of all the MRTG config files from OV ################################################################## # Created by Laurie Gellatly # See newrtrov.txt for a description of what is performed ################################################################# # # Distributed under the GNU copyleft # # $Id: ovupdate,v 1.1.1.1 2002/02/26 10:16:36 oetiker Exp $ # use Socket; use strict; use ovmrtg; use vars '$DEBUG'; my $DEBUG = 0; my $rundir = "/opt/mrtg/run"; my $cronfile = "mrtgc"; my $dnsfile = "ovmrtgc.csv"; my($sysncfg,$cnt); my(@sysipnms,@sysips,@mrtgc,@sysnms); sub main { chdir $rundir; $cnt = 0; open (MRTGC,"<".$cronfile); while(){ chomp; if (/mrtg (.*)\.cfg/){ $mrtgc[@mrtgc] = $1; } } close (MRTGC); @mrtgc = sort(@mrtgc); for($cnt=0;$cnt<@mrtgc;++$cnt){ $sysncfg=$mrtgc[$cnt].".cfg"; open (MRTGC,"<".$sysncfg); while(){ if (/^Target/){ if (/^Target.*ovcvtfile ([0-9\.]*)/){ $sysips[@sysips] = $1; last; } if (/^Target.*\@([0-9\.]*)/){ $sysips[@sysips] = $1; last; } } } close (MRTGC); } @sysipnms=ovsysnms @sysips; open (DNSFILE,">".$dnsfile); for ($cnt = 0; $cnt < @sysipnms ; $cnt++){ # $sysipnms[$cnt] =~ s/ /,/; print DNSFILE "$sysipnms[$cnt]\n"; } close (DNSFILE); } main; exit(0); mrtg-2.17.10/contrib/ovmrtg/buildht0000644000175300017510000000027013057016061016200 0ustar oetikeroep#This file builds the HTML for each device being monitored cd /opt/mrtg/run/ #perl index sydrtr1.cfg "Router sydrtr1" sydrtr1 > /var/opt/ns-fasttrack/docs/mrtg/sydrtr1/sydrtr1.html mrtg-2.17.10/contrib/ovmrtg/ovtgts0000755000175300017510000006001713057016061016103 0ustar oetikeroep @*`4@|ttL< `4Gj~(& @P*  92453-07B10.287[?' 92453-07A10.441@ @@X" LX 4P$PtX 9)X!:x <*x <X 8D4X HF 6 X IF6X XF6(>(P@`>(P@<>( P@P>(P @ h>(Q(@(t>(&Q0H@0H >('Qx@x>((Q@>(R@>`44Y &? P@ $PRIVATE$$DLT$$PLT$ $SHLIB_DATA$$TEXT$ $SHLIB_INFO$ $DATA_START$ $MILLICODE$$LIT$$CODE$$UNWIND_START$$UNWIND$MILLICODE$$UNWIND$ $UNWIND_END$$RECOVER_START$$RECOVER$MILLICODE$ $RECOVER$ $RECOVER_END$ $PFA_COUNTER$$PFA_COUNTER_END$$DATA$ $SHORTDATA$$GLOBAL$ $SHORTBSS$$BSS$$ANS$$CI$00$ 08@0T@0 d*0p @0 | @0 x d1 t+d0  @0  @0  @  + + U-OU*0 +0 +0 +0 ,0  40 460 D60 X60 l@0 |@0 @0 h 0 @0  @0  @0  @0 @0 @  @  P, ) 1 ,@ A- 1[ 0  % 0 0'<@ 1{ 1 1  2 ,10 D60 \@ 0 d) 82; D2X0 @(0D@0L@0X@0d@0 A33 < @Ul02U2U(2U2U 2U83U3 0 $ 0 $ 0 ,$ 0 <$ 0 L$ 0 \$ $ % % 0 l$ 0 |%  (% 0 %7 0 %O 4%d 0 % 0 % @% P% \& 0 &3 l&D 0 &W 0 &k x&x 0 & 0  & & 0 & 0 ,& ', & & ' '$ '0 '< 'd 't 0 <' 0 L' ' 0 \' 0 l' ' 0 |' 0 ' (( ( (` (P ) ) 0 )0 $60 0@0 <@0 P@*3030303030l30300 A302s0 , *{main __text_start ___stack_zero __data_startcrt0.oPA-RISC 2.0 Assembler HP92453-03UX.10.20.02 (DAVIS)mapdld ccom options = -ESlit -DA1.0 -DS1.0 -Oq02,al,ag,cn,Lm,sz,Ic,vo,lc,Mf,Po,es,rs,sp,in,vc,Pi,fa,pe,Rr,Fl,pv,pa,nf,cp,lx! -AcHPC HP92453-01 A.10.31._is_89_0L$0002L$0004L$0001 __map_dld DS$mapdlderrorC$2writestrlenitoa__exitopenreadlseekmmapclose_utssyssyserror$global$$START$$ARGV_environ _fp_status _CPU_REVISION_CPU_KEYBITS_1 _FPU_MODEL_start_mcount_clear_counters _sr4export__d_trap $UNWIND_START $UNWIND_END$RECOVER_START $RECOVER_END __dld_flags __dld_hook __dld_list __SYSTEM_ID _SYSTEM_ID _FPU_REVISIONenviron __d_trap_fptr $PFA_C_START $PFA_C_ENDerrno $$divI_10$$remI __dld_loc_etext_end $$dyncallunix95 ccom options = -ESlit -DA1.0 -DS1.1c -Oq03,al,ag,cn,Lm,sz,Ic,vo,lc,Mf,Po,es,rs,sp,In,vc,Pi,fa,pe,Rr,Fl,pv,pa,nf,cp,Lx! -Ac__xpg4_extended_maskt ccom options = A.10.32M$2mapobjectsclearobj_OVwInitSessionprintf OVwGetMapInfoOVwSelectObjectOVwDbFieldNameToFieldIdOVwDbNameToObjectIdOVwDone div_const$neg3$pos$neg$neg5$neg6 $pos_for_17$neg10 $neg_for_17$neg12$neg15$neg17$neg7$7$pos7$1$2$8 $neg7_shift$3$4$neg9$neg14$$divide_by_constant$$divI_2$$divI_4$$divI_8 $$divI_16$$divI_3$$divU_3$$divI_5$$divU_5$$divI_6$$divU_6 $$divU_10 $$divI_12 $$divU_12 $$divI_15 $$divU_15 $$divI_17 $$divU_17$$divI_7$$divU_7$$divI_9$$divU_9 $$divI_14 $$divU_14remI neg_denomneg_num regular_seq neg_num_2finish$$remoIdyncallUnoshlibs$$dyncall_externaletextedataend_etext_edata_end __SYSTEM_ID _fp_statusLXt0?E0?D$4H11`XXt0?Xt$4H1y/O$407[?&7[?"Xt0SI0SIXt0SY0SYXt0Sk0Skyp O $`x0 +ASmF  }@@@U@ U@(U@U@U@U@UL2pUQ*xU Q@pU Z(8Qt/usr/OV/lib/libovw.2/usr/OV/lib/libov.2/usr/OV/lib/libXovw.2/usr/lib/libntl.1/usr/lib/Motif1.2/libXm.1/usr/lib/libc.1errno__dld_loc_CPU_REVISION_FPU_MODEL__xpg4_extended_mask_SYSTEM_ID_environ_endenviron_startprintfOVwDoneOVwSelectObjectOVwDbFieldNameToFieldIdOVwGetMapInfo_OVwInitSessionOVwDbNameToObjectIdmain__d_traperrnoXZ]XZ]XZ]XZ]d@"Z]> ZZ]> ZZ]9 Z8 =@Y :Z @Z@ ZZZ] ZZ @"ZY :ZZ@= ZZZ@= Z ZY :Z]ya: =]: =]  : =@4ZBu ZZZZ ZZ]ya: =]: =]  : = @4ZB ZZZM ZZY :}@4Be]yZZ5@*Z@ya AZ@ya AZ]ya A @Z@] Z]: =] y a: =4Y(ZYY8Z@] Z]: =] y a: =4Y(Z YY8Z]Y Z @*Z@YA AZ@YA AZ]YA A @ ZZmZ7!?92 p2@` :Z: @Z 9 J4=? "2@` A  @V   @A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A  !A ˡF ! !V @ k? k?crt0: errno: ERROR couldn't open ERROR reading ERROR bad magic number/system id for ERROR bad hpux aux header for (text) (bss) (data)@@K?@ @Ku?AKs?I k?#`(7{ 7 +h# +h8 'y 4yEe'y7D7%767+4># "744445 rנjb+h% +h%  (4Ц @Ц D(43 H?(ਃ 43 ` z7+4>7D7%7744z#*74444+H8 #% 7@@@@ 7K?@ @@@@k?7k?#Ak? 7Y4k?@ 84 @@K?K?X@ 4K? *@K? K? X@ 4K? rKa?H:@7?#74@ p4@x7?7?X@ @4#!794@ 4Ka?@ H:K>@7?@ \\@B7?@B?7?B?@ U7344Z7`?5Z_U@k?ok= k=k=+4& k=9Z4k=AY4k=I4$@k=Q$k=YK=Y7=@ 44$G=4 G=4$XK=@@K=YK=Y7>@4`4` G>( ""X6x_YK>K>K>k=!+H" k=)@ 0k=1K>@ߟԿԟK>K=Yk?ZWK=!k?@X4 C4?#K=1 Rk?4?ZK=1k?4@W4?#DK=) zK=1@$"K=)K=YK>k?8 k?Կ_4@`W4?#8EK=Y@0@k?)+`4 K=!C?aK=1k?!  K>K>h%+48 k?9 +K=Ak?14: +k?Q4= ( k?Y48+k?7?!4?H" k?\ 4k?q ( c?a4= x+`k?4&0XK=IK=QK=9K?ak?A`  k?yWk?Ik?ak?uBKK=Yk?Z4K=)k?@HW4??eEK=)Ek?7YX@(7?!C?K4p 4r C?M4\ ?8\K>@7?  4 "@@@@  4 "@@@@  4 "@R@@@  4 "@@@@  4 "@@@@  4& "@@@@  4 "@R@@@  4r "@@@@Ka?4! <4?@@@p@K?@ @Ku?Ks? k?Ku?QKs?Y k?Ku?Ks? k?Ku?qKs?y k?Ku?Ks? k?Ku?Ks? k?Ku?aKs?i k?k?7k?9k?14 +49`K?1H8# %7 (k?+4:# %@7# %p7+` (h<+4:# %@7K?9@2+`H:44# %7+4:# %7+`h<(4k?K?K?9A:+`H:(K?1K? # &7+`h< +`H? +`H:+`H9 4# %7+`h< +`H3 ` 2+4:+`H9 # %@7K?6k?K?K?96^@# &07K?Y@7?$'X')@))X))))*++++++++++,, , ,,,,,,,---H-L/0/101 1T1X1t1x111111112224282T2X2l304*x * 2p 2 * @r$Revision: 1.1.1.1 $/usr/lib/dld.slERROR: mmap failed for dldMRTG Actionsovwinit failed getmapinfo failed IP HostnameSelection process failed = %d *2322223*x@fR@fb  @ mrtg-2.17.10/contrib/ovmrtg/index0000644000175300017510000001021413057016061015653 0ustar oetikeroep#!/usr/local/gnu/bin/perl5 # -*- mode: Perl -*- ################################################################## # Multi Router Traffic Grapher: Index Generator ################################################################## # # This reads a mrtg.cfg file form std input or cmdline argument # and it takes a regexp on the cmdline to specify which # targets to look at. # # from this info it produces a router index on std out. # ################################################################## # Created by Tobias Oetiker # Modifications by Laurie Gellatly # Distributed under the GNU copyleft # # $Id: index,v 1.1.1.1 2002/02/26 10:16:36 oetiker Exp $ ################################################################## $regexp = pop @ARGV; $Title = pop @ARGV; if (defined($Title) && -f $Title) { push(@ARGV, $Title); $Title = "$Title Overview ($regexp)"; } if (! -f $ARGV[0]) { print " USAGE: index <regular expression> This tool will read the contents of the mrtg.cfg file and will return the HTML code of a webpage contanig the 'daily' graphs of all the routers whose titles match the regular expression. NOTE: you have to adjust this tool to your needs as the HTML contains our logo and our name ... "; exit ; } #slurp the cfg file while(<>) { s/\t/ /g; #replace tabs by spac next if /^\s+$/; #ignore white space next if /^\s*\#/; #ignore comments if (/$regexp/i && ! /\[\^\]/ && ! /\[\$\]/ && /^title\[([^\]]+)\]:\s*(.*\S)/i) { $router=lc($1); $arg=$2; $titles{$router} = $arg; next; } if (/^directory\[([^\]]+)\]:\s*(.*\S)/i) { $arg = $2; $tmp = lc($1); $dirs{$tmp} = "$arg/"; } if ($router && /^pagetop\[([^\]]+)\]:\s*(.*\S)/i) { next; } if ($router && /^\s+(.*?)<\/H1>/) { $titles{$router} .= " $1"; } $router = ''; } $Today=datestr(time); print <<ECHO; <HTML> <HEAD> <TITLE>$Title

      $Title

      These statistics were last updated $Today ECHO foreach $router (sort {$titles{$a} cmp $titles{$b}} keys %titles) { $dirs{$router} = "" if (!defined($dirs{$router})); $rdir = $dirs{$router}; print <$titles{$router}


      ECHO } '$Revision: 1.1.1.1 $ ' =~ /Revision: (\S*)/; $rev=$1; '$Date: 2002/02/26 10:16:36 $ ' =~ /Date: (\S*)/; $date=$1; print <
      $rev-$date Tobias Oetiker <oetiker\@ee.ethz.ch> and Dave Rand <dlr\@bungi.com>
      Back to Main Router List
      ECHO sub datestr { my ($time) = shift(@_) || return 0; my ($wday) = ('Sunday','Monday','Tuesday','Wednesday', 'Thursday','Friday','Saturday')[(localtime($time))[6]]; my ($month) = ('January','February' ,'March' ,'April' , 'May' , 'June' , 'July' , 'August' , 'September' , 'October' , 'November' , 'December' )[(localtime($time))[4]]; my ($mday,$year,$hour,$min) = (localtime($time))[3,5,2,1]; if ($min<10) {$min = "0$min";} return "$wday, $mday $month ".($year+1900)." at $hour:$min"; } mrtg-2.17.10/contrib/ovmrtg/installov0000755000175300017510000000014213057016061016561 0ustar oetikeroepperl installov.pl installov.cmds ovsho ovadd ovdel ovtst ovcvtfile ovcullfile mrtgmenu cfgmakerov mrtg-2.17.10/contrib/ovmrtg/ovcullfile0000644000175300017510000000545613057016061016724 0ustar oetikeroep#!/usr/local/bin/perl5 # -*- mode: Perl -*- ################################################################## # Remove old data from OV_DB files ################################################################## # Created by Laurie Gellatly # This reads an OV_DB file for the cut off and interface # and calculates how many lines can be removed ################################################################# # # Distributed under the GNU copyleft # # $Id: ovcullfile,v 1.1.1.1 2002/02/26 10:16:36 oetiker Exp $ # use strict; use vars '$DEBUG'; my $ov_db = "/var/opt/OV/share/databases"; my $ovdb= $ov_db."/snmpCollect/"; my $DEBUG = 0; my($days2keep, $interface, $io , $cutoff) ; my($cnt, $data, $recno, $junk); my @names = ( "IfInErrors", "IfOutErrors", "IfInOctets", "IfOutOctets", "avgBusy5"); my @namext = (".err", "", ".cpu"); my ($val); my $recsz = 24; my $fsize = -1; my $p = "',\$p'"; my $parms = '-F\\t \'{printf("%d\\t%d\\t%s\\t%lg\\n", $4, $5, $6, $3)}\''; my @resu; sub main { my($extn) = ""; $days2keep = $ARGV[0]; $interface = $ARGV[1]; $io = $ARGV[2]; die < -1; if (($fsize == $cfsize) && ($recno > 1)){ seek(RAWIN,($recno - 2) * $recsz, 0); $notfound = ($recsz == read(RAWIN, $data, $recsz)); ($starttime, $entime, $IPAdd1, $IPAdd2, $IPAdd3, $IPAdd4, $cnt, $val) = unpack("LLCCCCLd",$data); if ($cutoff < $entime) { seek(RAWIN, 0, 0); $recno = 1; } } else { $fsize = $cfsize; $recno = 1; } while ($notfound){ # Read from the beginning of file $notfound = ($recsz == read(RAWIN, $data, $recsz)); ($starttime, $entime, $IPAdd1, $IPAdd2, $IPAdd3, $IPAdd4, $cnt, $val) = unpack("LLCCCCLd",$data); if ($cutoff < $entime) { $notfound = 0; } else { $recno++; } } close (RAWIN); if ($recno > 1){ @resu = `snmpColDump -tTI $file | sed -n $recno$p | awk $parms | snmpColDump -r - $file` # wc -l` } return ($recno); } mrtg-2.17.10/contrib/ovmrtg/ovcvtfile0000644000175300017510000000720213057016061016550 0ustar oetikeroep#!/usr/local/bin/perl5 # -*- mode: Perl -*- ################################################################## # Extract Input and Output values for target ################################################################## # Created by Laurie Gellatly # This reads an OV_DB file for the target and interface # and prints a single line for In, Out, "UPTIME" and Target ################################################################# # # Distributed under the GNU copyleft # # $Id: ovcvtfile,v 1.1.1.1 2002/02/26 10:16:36 oetiker Exp $ # use strict; use vars '$DEBUG'; my $ov_db = "/var/opt/OV/share/databases"; my $DEBUG = 0; my($target, $interface, $io , $in, $out, $uptime) ; my ($cnt, $data, $recno, $junk); my @names = ( "IfInErrors", "IfOutErrors", "IfInOctets", "IfOutOctets", "avgBusy5", "sysUpTime"); my @namext = (".err", "", ".cpu"); my ($val); my $recsz = 24; my ($oldtime) = time - 550; sub main { my($extn) = ""; $target = $ARGV[0]; $interface = $ARGV[1]; $io = $ARGV[2]; die < -1; binmode(RAWIN); while ($notfound){ # Read from the end of file backwards seek(RAWIN,$recno * $recsz, 0); read(RAWIN, $data, $recsz); ($starttime, $entime, $IPAdd1, $IPAdd2, $IPAdd3, $IPAdd4, $junk, $cnt, $val) = unpack("NNCCCCNNN",$data); if ($oldtime > $entime) { $val = 0; $notfound = 0; } elsif ($target eq $IPAdd1.".".$IPAdd2.".".$IPAdd3.".".$IPAdd4){ if((pack"s",1) eq (pack"v",1)){ $notfound = $cnt; $cnt = $val; $val = $notfound; } $notfound = 0; $val = unpack"d",pack"LL",$cnt,$val; } else { $recno--; if ( $recno < 0 ){ $notfound = 0; } } } close (RAWIN); if ($ind < 2){ $val = $val * ($entime - $starttime); } $val = int($val); return ($val); } sub pretty_uptime_value () { my ($uptime) = get(5,0); if ($uptime == 0){ return "An unknown amount of time"; } my ($seconds,$minutes,$hours,$days,$result); ## We divide the uptime by hundred since we're not interested in ## sub-second precision. $uptime = int ($uptime / 100); $days = int ($uptime / (60 * 60 * 24)); $uptime %= (60 * 60 * 24); $hours = int ($uptime / (60 * 60)); $uptime %= (60 * 60); $minutes = int ($uptime / 60); $seconds = $uptime % 60; if ($days == 0){ $result = sprintf ("%d:%02d:%02d", $hours, $minutes, $seconds); } elsif ($days == 1) { $result = sprintf ("%d day, %d:%02d:%02d", $days, $hours, $minutes, $seconds); } else { $result = sprintf ("%d days, %d:%02d:%02d", $days, $hours, $minutes, $seconds); } return $result; } mrtg-2.17.10/contrib/ovmrtg/installov.cmds0000644000175300017510000000117613057016061017513 0ustar oetikeroeps~^my \$webdir .*~my $webdir = "/var/opt/ns-fasttrack/docs/mrtg/";~ s~^my \$rundir .*~my $rundir = "/opt/mrtg/run";~ s~^my \$company .*~my $company = "Company";~ s~^my \$cronfile .*~my $cronfile = "mrtgc";~ s~^my \$roothtml .*~my $roothtml = "routers.html";~ s~^my \$buildhtf .*~my $buildhtf = "buildht";~ s~^my \$dnsfile .*~my $dnsfile = "ovmrtgc.csv";~ s~^my \$ov_db .*~my $ov_db = "/var/opt/OV/share/databases";~ s~^my \$ov_conf .*~my $ov_conf = "/etc/opt/OV/share/conf";~ s~Command ".*ovadd~Command "perl /opt/mrtg/run/ovadd~ s~Command ".*ovdel~Command "perl /opt/mrtg/run/ovdel~ s~Command ".*ovsho~Command "perl /opt/mrtg/run/ovsho~ mrtg-2.17.10/contrib/ovmrtg/ovin0000644000175300017510000000024213057016061015517 0ustar oetikeroepmv cwdrtr1.cfg cwdrtr1.$1 mv sydrtr2.cfg sydrtr2.$1 mv sydrtr3.cfg sydrtr3.$1 mv cwdrtr1.$2 cwdrtr1.cfg mv sydrtr2.$2 sydrtr2.cfg mv sydrtr3.$2 sydrtr3.cfg mrtg-2.17.10/contrib/ovmrtg/ovcols0000644000175300017510000000205013057016061016050 0ustar oetikeroep#!/usr/local/bin/perl5 # -*- mode: Perl -*- ################################################################## # Config file creator ################################################################## # Created by Laurie Gellatly # based on mrtg cfgmaker by Tobias Oetiker # this produces a config file for one router, by pulling info # off the router via snmp and then writing files ready for # snmpCollect to use (via xnmcollect) and later ovcvtfile calls ################################################################# # # Distributed under the GNU copyleft # # $Id: ovcols,v 1.1.1.1 2002/02/26 10:16:36 oetiker Exp $ # use Socket; use strict; use vars '$DEBUG'; use ovmrtg; my $DEBUG = 0; my($op,$router,@res); sub main { $op = $ARGV[0]; $router = $ARGV[1]; die < "Misc" _i { <90> "MRTG Actions" _R f.menu "MRTG Actions"; } Menu "MRTG Actions" { <100> "Add/Update Target/s" _A CONTEXT "AllContexts || isIP" f.action "MRTGADD"; <100> "Stop Collecting Target/s" _S CONTEXT "AllContexts || isIP" f.action "MRTGDEL"; <100> "Show Current Target/s" _C CONTEXT "AllContexts || isIP" f.action "MRTGSHO"; } Action "MRTGADD" { SelectionRule (isNode || isInterface) && isIP; NameField "IP Hostname", "IP Address"; Command "perl /opt/mrtg/run/ovadd ${OVwSelections}"; } Action "MRTGDEL" { SelectionRule (isNode || isInterface) && isIP; NameField "IP Hostname", "IP Address"; Command "perl /opt/mrtg/run/ovdel ${OVwSelections}"; } Action "MRTGSHO" { Command "perl /opt/mrtg/run/ovsho"; } } mrtg-2.17.10/contrib/ovmrtg/ovsho0000644000175300017510000000161713057016061015711 0ustar oetikeroep#!/usr/local/bin/perl5 # -*- mode: Perl -*- ################################################################## # This file controls the creation of all the MRTG config files from OV ################################################################## # Created by Laurie Gellatly # See newrtrov.txt for a description of what is performed ################################################################# # # Distributed under the GNU copyleft # # $Id: ovsho,v 1.1.1.1 2002/02/26 10:16:36 oetiker Exp $ # use Socket; use strict; use vars '$DEBUG'; my $DEBUG = 0; my $rundir = "/opt/mrtg/run"; my $dnsfile = "ovmrtgc.csv"; my($line,@sysnms); sub main { chdir $rundir; open (DNSFILE,"<".$dnsfile); while(){ chomp; $line = $_; $sysnms[@sysnms]= (split /\,/,$line)[2]; } close (DNSFILE); `ovtgts $ENV{OVwSessionID} @sysnms`; } main; exit(0); mrtg-2.17.10/contrib/ovmrtg/ovsysnms0000644000175300017510000000166613057016061016460 0ustar oetikeroep#!/usr/local/bin/perl5 # -*- mode: Perl -*- ################################################################## # Config file creator ################################################################## # Created by Laurie Gellatly # this produces an array of ip address and system names for each # ip address passed to it, by pulling info # off the device via snmp ################################################################# # # Distributed under the GNU copyleft # # $Id: ovsysnms,v 1.1.1.1 2002/02/26 10:16:36 oetiker Exp $ # use Socket; use strict; use ovmrtg; use vars '$DEBUG'; my $DEBUG = 0; my($router,@res,$cnt); sub main { $router = $ARGV[0]; die <> resolved USAGE @res = ovsysnms(@ARGV); for($cnt = 0 ; $cnt < @res; ++$cnt){ print "$res[$cnt]\n"; } } main; exit(0); mrtg-2.17.10/contrib/ovmrtg/oveval.txt0000644000175300017510000000116413057016061016662 0ustar oetikeroepOVMRTG evaluation questions: ============================ What is your name: What is your company name: Your E-mail address: What HPOV platform do you run (Unix/NT & Version): What types of systems are you monitoring (Manufacturer & Router/Hub..): How many systems are you monitoring with OVMRTG: Can you comment on the resource utilisation from OVMRTG and the original MRTG? Any suggestions for OVMRTG improvements? What other details might be useful in understanding problems with OVMRTG? =================================== Please E-mail this page to : net_improvement@hotmail.com mrtg-2.17.10/contrib/ovmrtg/installov.pl0000644000175300017510000000307213057016061017175 0ustar oetikeroep#!/usr/local/bin/perl5 # -*- mode: Perl -*- ################################################################## # This file updates the installation specific values ################################################################## # Created by Laurie Gellatly ################################################################# # # Distributed under the GNU copyleft # # $Id: installov.pl,v 1.1.1.1 2002/02/26 10:16:36 oetiker Exp $ # use strict; use vars '$DEBUG'; my $DEBUG = 0; my($cmdfile,$cnt,$cntl,$infile,$delim,$s,$sysn,@cmds,@lines,@to,@from); sub main { $cmdfile = $ARGV[0]; shift @ARGV; $infile = $ARGV[0]; die <; close (CMD); chomp (@cmds); for ($cnt = 0; $cnt < @cmds; ++$cnt){ if ('s' eq substr($cmds[$cnt],0,1)){ $delim = substr($cmds[$cnt],1,1); ($s,$from[$cnt],$to[$cnt]) = split (/$delim/,$cmds[$cnt]); } } while ($infile){ open (SCRIPTF,"<".$infile); @lines = ; close (SCRIPTF); chomp(@lines); for ($cntl = 0; $cntl < @lines; ++$cntl){ for ($cnt = 0; $cnt < @to; ++$cnt){ $lines[$cntl] =~ s~$from[$cnt]~$to[$cnt]~; } } open (SCRIPTF,">".$infile); for ($cntl = 0; $cntl < @lines; ++$cntl){ print SCRIPTF $lines[$cntl]."\n"; } close (SCRIPTF); shift @ARGV; $infile = $ARGV[0]; } } main; exit(0); mrtg-2.17.10/contrib/cfgmaker_dlci/0000755000175300017510000000000013057016061016057 5ustar oetikeroepmrtg-2.17.10/contrib/cfgmaker_dlci/cfgmaker_dlci0000644000175300017510000005425713057016061020571 0ustar oetikeroep#! /usr/bin/perl # -*- mode: Perl -*- ################################################################## # New MRTG 2.8.12 Based -- Config file creator ################################################################## # this produces a config file for one router, by pulling info # off the router via snmp # Modified by Graziano Sommariva # to monitor DLCI's and to include some code from newer release(2.9.12). # NOTE: IPONLY has been disabled. # Added --ip option ################################################################# # # Distributed under the GNU copyleft require 5.004; use strict; BEGIN { # Automatic OS detection ... do NOT touch if ( $^O =~ /^(?:(ms)?(dos|win(32|nt)?))/i ) { $main::OS = 'NT'; $main::SL = '\\'; $main::PS = ';'; } elsif ( $^O =~ /^VMS$/i ) { $main::OS = 'VMS'; $main::SL = '.'; $main::PS = ':'; } else { $main::OS = 'UNIX'; $main::SL = '/'; $main::PS = ':'; } } use FindBin; use lib "${FindBin::Bin}"; use lib "${FindBin::Bin}${main::SL}..${main::SL}lib${main::SL}mrtg2"; use BER "0.57"; use SNMP_Session "0.59"; use SNMP_util "0.57"; use Getopt::Long; use Socket; use strict; use vars '$DEBUG'; my $DEBUG = 0; my (%optctl) = (); my ($session, %ipaddr, %iphost); sub main { snmpmapOID('ipAdEntAddr' => '1.3.6.1.2.1.4.20.1.1', 'ipAdEntIfIndex' => '1.3.6.1.2.1.4.20.1.2', 'sysObjectID' => '1.3.6.1.2.1.1.2.0', 'CiscolocIfDescr' => '1.3.6.1.4.1.9.2.2.1.1.28', 'ifAlias' => '1.3.6.1.2.1.31.1.1.1.18'); my(%ifType_d)=('1'=>'Other', '2'=>'regular1822', '3'=>'hdh1822', '4'=>'ddnX25', '5'=>'rfc877x25', '6'=>'ethernetCsmacd', '7'=>'iso88023Csmacd', '8'=>'iso88024TokenBus', '9'=>'iso88025TokenRing', '10'=>'iso88026Man', '11'=>'starLan', '12'=>'proteon10Mbit', '13'=>'proteon80Mbit', '14'=>'hyperchannel', '15'=>'fddi', '16'=>'lapb', '17'=>'sdlc', '18'=>'ds1', '19'=>'e1', '20'=>'basicISDN', '21'=>'primaryISDN', '22'=>'propPointToPointSerial', '23'=>'ppp', '24'=>'softwareLoopback', '25'=>'eon', '26'=>'ethernet-3Mbit', '27'=>'nsip', '28'=>'slip', '29'=>'ultra', '30'=>'ds3', '31'=>'sip', '32'=>'frame-relay', '33'=>'rs232', '34'=>'para', '35'=>'arcnet', '36'=>'arcnetPlus', '37'=>'atm', '38'=>'miox25', '39'=>'sonet', '40'=>'x25ple', '41'=>'iso88022llc', '42'=>'localTalk', '43'=>'smdsDxi', '44'=>'frameRelayService', '45'=>'v35', '46'=>'hssi', '47'=>'hippi', '48'=>'modem', '49'=>'aal5', '50'=>'sonetPath', '51'=>'sonetVT', '52'=>'smdsIcip', '53'=>'propVirtual', '54'=>'propMultiplexor', '55'=>'100BaseVG', '56'=>'Fibre Channel', '57'=>'HIPPI Interface', '58'=>'Obsolete for FrameRelay', '59'=>'ATM Emulation of 802.3 LAN', '60'=>'ATM Emulation of 802.5 LAN', '61'=>'ATM Emulation of a Circuit', '62'=>'FastEthernet (100BaseT)', '63'=>'ISDN & X.25', '64'=>'CCITT V.11/X.21', '65'=>'CCITT V.36', '66'=>'CCITT G703 at 64Kbps', '67'=>'Obsolete G702 see DS1-MIB', '68'=>'SNA QLLC', '69'=>'Full Duplex Fast Ethernet (100BaseFX)', '70'=>'Channel', '71'=>'Radio Spread Spectrum (802.11)', '72'=>'IBM System 360/370 OEMI Channel', '73'=>'IBM Enterprise Systems Connection', '74'=>'Data Link Switching', '75'=>'ISDN S/T Interface', '76'=>'ISDN U Interface', '77'=>'Link Access Protocol D (LAPD)', '78'=>'IP Switching Opjects', '79'=>'Remote Source Route Bridging', '80'=>'ATM Logical Port', '81'=>'AT&T DS0 Point (64 Kbps)', '82'=>'AT&T Group of DS0 on a single DS1', '83'=>'BiSync Protocol (BSC)', '84'=>'Asynchronous Protocol', '85'=>'Combat Net Radio', '86'=>'ISO 802.5r DTR', '87'=>'Ext Pos Loc Report Sys', '88'=>'Apple Talk Remote Access Protocol', '89'=>'Proprietary Connectionless Protocol', '90'=>'CCITT-ITU X.29 PAD Protocol', '91'=>'CCITT-ITU X.3 PAD Facility', '92'=>'MultiProtocol Connection over Frame/Relay', '93'=>'CCITT-ITU X213', '94'=>'Asymetric Digitial Subscriber Loop (ADSL)', '95'=>'Rate-Adapt Digital Subscriber Loop (RDSL)', '96'=>'Symetric Digitial Subscriber Loop (SDSL)', '97'=>'Very High Speed Digitial Subscriber Loop (HDSL)', '98'=>'ISO 802.5 CRFP', '99'=>'Myricom Myrinet', '100'=>'Voice recEive and transMit (voiceEM)', '101'=>'Voice Foreign eXchange Office (voiceFXO)', '102'=>'Voice Foreign eXchange Station (voiceFXS)', '103'=>'Voice Encapulation', '104'=>'Voice Over IP Encapulation', '105'=>'ATM DXI', '106'=>'ATM FUNI', '107'=>'ATM IMA', '108'=>'PPP Multilink Bundle', '109'=>'IBM IP over CDLC', '110'=>'IBM Common Link Access to Workstation', '111'=>'IBM Stack to Stack', '112'=>'IBM Virtual IP Address (VIPA)', '113'=>'IBM Multi-Protocol Channel Support', '114'=>'IBM IP over ATM', '115'=>'ISO 802.5j Fiber Token Ring', '116'=>'IBM Twinaxial Data Link Control (TDLC)', '117'=>'Gigabit Ethernet', '118'=>'Higher Data Link Control (HDLC)', '119'=>'Link Access Protocol F (LAPF)', '120'=>'CCITT V.37', '121'=>'CCITT X.25 Multi-Link Protocol', '122'=>'CCITT X.25 Hunt Group', '123'=>'Transp HDLC', '124'=>'Interleave Channel', '125'=>'Fast Channel', '126'=>'IP (for APPN HPR in IP Networks)', '127'=>'CATV MAC Layer', '128'=>'CATV Downstream Interface', '129'=>'CATV Upstream Interface', '130'=>'Avalon Parallel Processor', '131'=>'Encapsulation Interface', '132'=>'Coffee Pot', '133'=>'Circuit Emulation Service', '134'=>'ATM Sub Interface', '135'=>'Layer 2 Virtual LAN using 802.1Q', '136'=>'Layer 3 Virtual LAN using IP', '137'=>'Layer 3 Virtual LAN using IPX', '138'=>'IP Over Power Lines', '139'=>'Multi-Media Mail over IP', '140'=>'Dynamic synchronous Transfer Mode (DTM)', '141'=>'Data Communications Network', '142'=>'IP Forwarding Interface', '162'=>'Cisco Express Forwarding Interface' ); my($vendor)=0; # my($iponly)=0; my($workdir)=0; my($ip)=0; my($community,$router,%defaults); my($res); # Just need to make sure that all perl installations have the GetOpt module # - fwo@obsidian.co.za # # $res = GetOptions(\%optctl,"vendor","iponly","workdir=s","options=s","ip=s"); $res = GetOptions(\%optctl,"vendor","workdir=s","options=s","ip=s"); if($res == 0 ) { print "\nError in arguments. Please run cfgmaker with no arguments for help!\n\n"; exit 1; } if($optctl{"vendor"}) { $vendor = 1; } # if($optctl{"iponly"}) { $iponly = 1; } if($optctl{"workdir"}) { $workdir = $optctl{"workdir"}; } if($optctl{"ip"}) { $ip = $optctl{"ip"}; } if($optctl{"options"}) { foreach $res(split(',',$optctl{"options"})) { chomp($res); next if($res eq "growright"); next if($res eq "bits"); next if($res eq "perminute"); next if($res eq "perhour"); next if($res eq "noinfo"); next if($res eq "nopercent"); next if($res eq "transparent"); next if($res eq "integer"); next if($res eq "dorelpercent"); next if($res eq "gauge"); next if($res eq "absolute"); next if($res eq "unknaszero"); print "\nERROR:$res is not a valid option for --options, exiting!\n"; exit 1; } } $res = 0; #TODO: check for conflicting info in options - l->r and r->l # print STDERR "iponly=$iponly\n" if $DEBUG; print STDERR "vendor=$vendor\n" if $DEBUG; print STDERR "workdir=$workdir\n" if $DEBUG; ($community,$router) = ($1,$2) if $ARGV[0] =~ /(.*)\@(.*)/; if(!($community) && !($router)) { print <>mrtg.cfg USAGE exit 1; } # if($iponly) { # # We only want to work with ip numbers and not names # # Check to see whether the name is a valid ip address # # If not bail - we do not want to deal with reverse dns # # issues - fwo@obsidian.co.za 2000/01/17 # chomp($router); # if(!($router =~ /^[0-9]{1,3}.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/)){ # print "\nERROR: when specifying --iponly, please use a valid\n"; # print "ip address for the router. Do not use a symbolic name.\n\n"; # exit 1; # } # } print "IconDir: /mrtgicons/\n\n"; if($workdir) { print "WorkDir: $workdir\n\n"; } else { print "# Add a WorkDir: /html line to this file\n\n"; } my($sysDescr,$sysContact,$sysName,$sysLocation,$ifNumber,$sysObjectID); my($sysDescr_orig,$cisco_router_sysid,$livingston_router_sysid,$ciscobox,$portmaster); if($optctl{"ip"}) { $session = SNMP_Session->open ($ip, $community, 161) || die "Error opening SNMP session to $ip"; ($sysDescr,$sysContact,$sysName,$sysLocation,$ifNumber,$sysObjectID) = snmpget("$community\@$ip",'sysDescr','sysContact','sysName','sysLocation','ifNumber', 'sysObjectID'); $sysDescr_orig=$sysDescr; $sysDescr_orig =~ s/[\r\n ]+/ /g; $sysDescr =~ s/[\r\n]+/
      /g; # Change returns to
      $cisco_router_sysid = '1\.3\.6\.1\.4\.1\.9'; $livingston_router_sysid = '1\.3\.6\.1\.4\.1\.307'; $ciscobox = ($sysObjectID =~ /^$cisco_router_sysid/); $portmaster = ($sysObjectID =~ /^$livingston_router_sysid/); } else { $session = SNMP_Session->open ($router, $community, 161) || die "Error opening SNMP session to $router"; ($sysDescr,$sysContact,$sysName,$sysLocation,$ifNumber,$sysObjectID) = snmpget("$community\@$router",'sysDescr','sysContact','sysName','sysLocation','ifNumber', 'sysObjectID'); $sysDescr_orig=$sysDescr; $sysDescr_orig =~ s/[\r\n ]+/ /g; $sysDescr =~ s/[\r\n]+/
      /g; # Change returns to
      $cisco_router_sysid = '1\.3\.6\.1\.4\.1\.9'; $livingston_router_sysid = '1\.3\.6\.1\.4\.1\.307'; $ciscobox = ($sysObjectID =~ /^$cisco_router_sysid/); $portmaster = ($sysObjectID =~ /^$livingston_router_sysid/); } print <map_table ([[1,3,6,1,2,1,4,20,1,1], # ipAdEntAddr [1,3,6,1,2,1,4,20,1,2]], # ipAdEntIf sub ($@) { my ($index, $ipadentaddr, $ipadentif) = @_; grep (defined $_ && ($_=pretty_print $_), ($ipadentif, $ipadentaddr)); $ipaddr{$ipadentif} = $ipadentaddr; $iphost{$ipadentif} = gethostbyaddr(pack('C4',split(/\./,$ipaddr{$ipadentif})), AF_INET); if (!defined $iphost{$ipadentif} || ($iphost{$ipadentif} eq '')){ $iphost{$ipadentif} = 'No hostname defined for IP address'; } }); print STDERR "Got Addresses\n" if $DEBUG; print STDERR "Got IfTable\n" if $DEBUG; my(%sifdesc,%siftype,%sifspeed,%sifadminstatus,%sifoperstatus,%sciscodescr); ### May need the cisco IOS version number so we know which oid to use ### to get the cisco description. ### ### - mjd 2/5/98 (Mike Diehn) (mdiehn@mindspring.net) ### my ($cisco_ver, $cisco_descr_oid, @ciscodescr); if ( $ciscobox ) { ($cisco_ver) = ($sysDescr =~ m/Version\s+([\d\.]+)\(\d/o); $cisco_descr_oid = ($cisco_ver ge "11.2") ? "ifAlias" : "CiscolocIfDescr"; } $session->map_table ([[1,3,6,1,2,1,2,2,1,1], # ifIndex [1,3,6,1,2,1,2,2,1,2], # ifDescr [1,3,6,1,2,1,2,2,1,3], # ifType [1,3,6,1,2,1,2,2,1,5], # ifSpeed [1,3,6,1,2,1,2,2,1,7], # ifAdminStatus [1,3,6,1,2,1,2,2,1,8]], # ifOperStatus sub ($@) { my ($rowindex,$index,$ifdescr,$iftype,$ifspeed,$ifadminstatus,$ifoperstatus) = @_; grep (defined $_ && ($_=pretty_print $_), ($index,$ifdescr,$iftype,$ifspeed,$ifadminstatus,$ifoperstatus)); $sifdesc{$index} = $ifdescr; $siftype{$index} = $iftype; $sifspeed{$index} = $ifspeed; $sifadminstatus{$index} = $ifadminstatus; $sifoperstatus{$index} = $ifoperstatus; if ($portmaster && $vendor) { # We can only approximate speeds # # so we think that ppp can do 76800 bit/s, and slip 38400. # (actualy, slip is a bit faster, but usualy users with newer modems # use ppp). Alternatively, you can set async speed to 115200 or # 230400 (the maximum speed supported by portmaster). # # But if the interface is ptpW (sync), max speed is 128000 # change it to your needs. On various Portmasters there are # various numbers of sync interfaces, so modify it. # # The most commonly used PM-2ER has only one sync. # # Paul Makeev (mac@redline.ru) # if ($siftype{$index} eq '23') { if ($sifdesc{$index} eq 'ptpW1') { $sifspeed{$index} = 128000; } else { $sifspeed{$index} = 76800; } } elsif ($siftype{$index} eq '28') { $sifspeed{$index} = 38400; } elsif ($siftype{$index} eq '6') { $sifspeed{$index} = 10000000; } } ### Move this section south so we know what type of ### circuit we're looking at before we retrieve ### the cisco interface alias. ### ### This whole cicso thing should be re-written, but since ### this script doesn't need to run quickly... ### ### - mjd 2/5/98 ### # Get the user configurable interface description entered in the config # if it's a cisco-box # my($cisco_descr_oid); if ($ciscobox && $vendor) { my ($enoid, @descr); $enoid = $cisco_descr_oid . "." . $index; if ( $cisco_ver ge "11.2" or $siftype{$index} != '32' ) { ### This is either not a frame-relay sub-interface or ### this router is running IOS 11.2+ and interface ### type won't matter. In either of these cases, it's ### ok to try getting the ifAlias or ciscoLocIfDesc. ### @descr = snmpget("$community\@$router", $enoid); } else { ### This is a frame-relay sub-interface *and* the router ### is running an IOS older than 11.2. Therefore, we can ### get neither ifAlias nor ciscoLocIfDesc. Do something ### useful. ### @descr = ("Cisco PVCs descriptions require IOS 11.2+."); } # end if else ### Put whatever I got into the array we'll use later to append the result ### of this operation onto the results from the ifDescr fetch. ### push @ciscodescr, shift @descr; } # end if ($cisco_box && $vendor) # especially since cisco does not return a if # descr for each interface it has ... ## JB 2/8/97 - sometimes IOS inserts E1 controllers in the standard-MIB ## interface table, but not in the local interface table. This puts the ## local interface description table out-of-sync. the following ## modification skips over E1 cards as interfaces. # ### I suspect that the mod I made above, to use the ifAlias ### oid if possible, may cause problems here. If it seems ### that your descriptions are out of sync, try commenting ### out the "if ( condition )" and it's closing right brace ### so that the "shift @ciscodescr" get executed for *all* ### iterations of this loop. ### ### - mjd 2/5/95 ### if ($ciscobox && $siftype{$index} != 18) { $sciscodescr{$index} = "
      " . (shift @ciscodescr) if @ciscodescr; } }); my $index; foreach $index ( sort { $a <=> $b } keys %sifdesc) { my $c; my $speed = int($sifspeed{$index} / 8); # bits to byte my $speed_str=&fmi($speed); my $name="$iphost{$index}"; # $name = "$router.int.$index" if not $name or $name =~ /\s/ or $iponly; $name = "$router.int.$index"; my $err_msg; $err_msg .= "######## - administratively not UP\n" if ($sifadminstatus{$index} != 1); # this check added by Josh - don't query E1-stack controllers $err_msg .= "######## - DS1 type\n" if ($siftype{$index} == 18); # i might be mistaken on this one - fwo@obsidian.co.za $err_msg .= "######## - E1 type\n" if ($siftype{$index} == 19); $err_msg .= "######## - it is a softwareLoopback interface\n" if ($siftype{$index} == 24); $err_msg .= "######## - it is a a DS3 contorller\n" if ($siftype{$index} == 30); $err_msg .= "######## - it is a ISDN S/T Interface\n" if ($siftype{$index} == 75); $err_msg .= "######## - it is a AT&T DS0 Point (64 Kbps)\n" if ($siftype{$index} == 81); $err_msg .= "######## - it is a CEF Sub-interface\n" if ($siftype{$index} == 162); $err_msg .= "######## - has an unrealistic speed setting\n" if (($speed == 0 ) || ($speed > 400 * 10**6)); $err_msg .= "######## - administratively not UP\n" if ($sifoperstatus{$index} == 3) ; if($err_msg ne "") { print <Traffic Analysis for $sifdesc{$index} ${c} $sciscodescr{$index} ${c} ${c} ${c} ${c} ${c} ${c} ${c} ${c}
      System:$sysName in $sysLocation
      Maintainer:$sysContact
      Interface:$sifdesc{$index} ($index)
      IP:$iphost{$index} ($ipaddr{$index})
      Max Speed:$speed_str ($ifType_d{$siftype{$index}})
      ${c} #--------------------------------------------------------------- ECHO } # # Frame-Relay # my(%circuits); $session->map_table ([[1,3,6,1,2,1,10,32,2,1,1], # Ifindex [1,3,6,1,2,1,10,32,2,1,2]],# DLCI sub ($@) { my ($rwindex,$crindex,$dlci) = @_; grep (defined $_ && ($_=pretty_print $_), ($rwindex,$crindex,$dlci) ); my($tmpindex); $tmpindex = $crindex.".".$dlci; $circuits{$tmpindex} = $tmpindex; }); foreach $index ( sort { $a <=> $b } keys %circuits) { my ($tmpname) = $router.".dlci.".$index; printf "\n\n"; printf "Options[%s]: bits, noinfo, growright, nopercent\n",$tmpname; printf "YSize[%s]: 300\n",$tmpname; printf "XSize[%s]: 600\n",$tmpname; printf "YLegend[%s]: Bits per Second\n",$tmpname; printf "Suppress[%s]: y\n",$tmpname; if($optctl{"ip"}) { printf "Target[%s]: .1.3.6.1.2.1.10.32.2.1.9.%s\&.1.3.6.1.2.1.10.32.2.1.7.%s:%s\@%s\n",$tmpname,$index,$index,$community,$ip; } else { printf "Target[%s]: .1.3.6.1.2.1.10.32.2.1.9.%s\&.1.3.6.1.2.1.10.32.2.1.7.%s:%s\@%s\n",$tmpname,$index,$index,$community,$router; } printf "MaxBytes[%s]: 1250000\n",$tmpname; printf "Title[%s]: Traffic Analysis for DLCI %s\n",$tmpname,$index; printf "PageTop[%s]:

      Traffic Analysis for DLCI %s

      \n",$tmpname,$index; printf " "; printf " ",$sysName,$sysLocation; printf " ",$sysContact; printf " ",$tmpname; printf "
      System:%s in %s
      Maintainer:%s
      InterfaceID.DLCI:%s
      "; } } main; exit(0); sub fmi { my($number) = $_[0]; my(@short); @short = ("Bytes/s","kBytes/s","MBytes/s","GBytes/s"); my $digits=length("".$number); my $divm=0; while ($digits-$divm*3 > 4) { $divm++; } my $divnum = $number/10**($divm*3); return sprintf("%1.1f %s",$divnum,$short[$divm]); } mrtg-2.17.10/contrib/PMLines/0000755000175300017510000000000013057016061014614 5ustar oetikeroepmrtg-2.17.10/contrib/PMLines/README0000644000175300017510000000204713057016061015477 0ustar oetikeroepFrom: Butch Kemper Date: Tue, 27 Apr 1999 12:11:55 -0500 Tobias, I have included a new module "PMLines.pl" for the "contrib" directory which replaces "PM3Lines.pl" and the new module now supports both Livingston PM2 and PM3 servers. Butch From: Carlos Canau Dear Tobias, Here's another script for contrib. It allows one to make a graph of analog/ISDN lines on a Livingston Portmaster 3. No docs, sorry... Date: Tue, 19 Sep 2000 12:07:36 -0400 Here is a new modified version of the PMlines.pl script. This one works with the newest version of PortMaster 4 firmware and all other Portmaster 2/3/4 products. # 2000/9/19 # # Modified again by Robert Boyle (robert@tellurian.net) to work with # all Lucent Portmaster 2/3/4 chassis. Now uses port speed to determine if # call is ISDN or analog. If speed is 56000 or 64000 then call is ISDN. # This may cause a false ISDN reading if someone has a perfect v.90 connection. # # Changed name back to PMlines.pl # mrtg-2.17.10/contrib/PMLines/PMLines.pl0000644000175300017510000001207413057016061016464 0ustar oetikeroep#!/usr/bin/perl # PMLines.pl # # 1998/08/04 # # Created by Carlos.Canau@EUnet.pt with cfgmaker from Tobias Oetiker # as skeleton # # returns: # #modems # #isdn # sysName # sysUptime # # 1998/10/30 # # Modified by Butch Kemper to allow multiple PortMasters # to be specified on the argument line and to output the totals. # # 1999/4/18 # # Modified by Butch Kemper to process PM2 systems and # to distingish between async and isdn ports. # # Changed name to PM2lines.pl # # 1999/4/19 # # Modified by Butch Kemper to process both PM2 and PM3 # systems. # # Changed name to PMlines.pl # # 2000/9/5 # # Modified by Robert Boyle (robert@tellurian.net) to work with # Lucent's VERY broken PM4 SNMP. Now uses modem number in use to determine if # call is ISDN or analog. If modem = "M0" then call is ISDN # Not pretty, but it does work. Somone who is a better PERL programmer than I # may want to integrate these changes into the base PMlines.pl script and make # determination of which method to use based on chassis type. # # Changed name to PM4lines.pl # # 2000/9/19 # # Modified AGAIN by Robert Boyle (robert@tellurian.net) to work with # all Lucent Portmaster 2/3/4 chassis. Now uses port speed to determine if # call is ISDN or analog. If speed is 56000 or 64000 then call is ISDN. # This may cause a false ISDN reading if someone has a perfect v.90 connection. # # Changed name back to PMlines.pl # use SNMP_Session; use BER; use Socket; use strict; %snmpget::OIDS = ( 'sysName' => '1.3.6.1.2.1.1.5.0', 'sysUptime' => '1.3.6.1.2.1.1.3.0', 'ifNumber' => '1.3.6.1.2.1.2.1.0', 'PMip' => '1.3.6.1.4.1.307.3.2.1.1.1.14', 'PMty' => '1.3.6.1.4.1.307.3.2.1.1.1.11', ); my($tot_isdn,$tot_modems,$args) = (0,0,0); my($input_string,$PROGNAME,$sysUptime,$sysName,$interfaces)=""; ($PROGNAME = $0) =~ s/.*\///; diexit(0) if $#ARGV < 0; for ($args=0; $args < $#ARGV+1; $args++) { $input_string = $ARGV[$args]; my($community,$router) = split /\@/, $input_string; diexit(0) unless $community && $router; ($sysName,$sysUptime,$interfaces) = snmpget($router,$community,'sysName','sysUptime','ifNumber'); my @PMip = snmpgettable($router,$community,'PMip'); my @PMty = snmpgettable($router,$community,'PMty'); my ($i); for ($i=0; $i < $#PMip+1; $i++) { if ($PMip[$i] ne "0.0.0.0") { if ($PMty[$i] ne "56000" and $PMty[$i] ne "64000") { $tot_modems++; } else { $tot_isdn++; } } } } printf "$tot_modems\n"; printf "$tot_isdn\n"; printf "$sysUptime\n"; printf "$sysName\n"; exit(0); sub diexit { die ("USAGE: $PROGNAME community\@portmaster [community\@portmaster]" . " \.\.\.\n" . " community = snmp read community string\n" . " portmaster = FQN of PortMaster\n"); } sub snmpget{ my($host,$community,@vars) = @_; my(@enoid, $var,$response, $bindings, $binding, $value, $inoid,$outoid, $upoid,$oid,@retvals); foreach $var (@vars) { die "Unknown SNMP var $var\n" unless $snmpget::OIDS{$var}; push @enoid, encode_oid((split /\./, $snmpget::OIDS{$var})); } srand(); my $session = SNMP_Session->open ($host , $community, 161); if ($session->get_request_response(@enoid)) { $response = $session->pdu_buffer; ($bindings) = $session->decode_get_response ($response); $session->close (); while ($bindings) { ($binding,$bindings) = decode_sequence ($bindings); ($oid,$value) = decode_by_template ($binding, "%O%@"); my $tempo = pretty_print($value); $tempo=~s/\t/ /g; $tempo=~s/\n/ /g; $tempo=~s/^\s+//; $tempo=~s/\s+$//; push @retvals, $tempo; } return (@retvals); } else { die "No answer from $input_string. You may be using the wrong community\n"; } } sub snmpgettable{ my($host,$community,$var) = @_; my($next_oid,$enoid,$orig_oid, $response, $bindings, $binding, $value, $inoid,$outoid, $upoid,$oid,@table,$tempo); die "Unknown SNMP var $var\n" unless $snmpget::OIDS{$var}; $orig_oid = encode_oid(split /\./, $snmpget::OIDS{$var}); $enoid=$orig_oid; srand(); my $session = SNMP_Session->open ($host , $community, 161); for(;;) { if ($session->getnext_request_response(($enoid))) { $response = $session->pdu_buffer; ($bindings) = $session->decode_get_response ($response); ($binding,$bindings) = decode_sequence ($bindings); ($next_oid,$value) = decode_by_template ($binding, "%O%@"); # quit once we are outside the table last unless BER::encoded_oid_prefix_p($orig_oid,$next_oid); $tempo = pretty_print($value); #print "$var: '$tempo'\n"; $tempo=~s/\t/ /g; $tempo=~s/\n/ /g; $tempo=~s/^\s+//; $tempo=~s/\s+$//; push @table, $tempo; } else { die "No answer from $input_string\n"; } $enoid=$next_oid; } $session->close (); return (@table); } mrtg-2.17.10/contrib/PMLines/mrtg.cfg-demo0000644000175300017510000000174513057016061017177 0ustar oetikeroep# # Usage example on .cfg file: # Target[dial]: `/usr/local/mrtg/PM3Lines.pl public@dial` WithPeak[dial]: wym Directory[dial]: data Options[dial]: growright, absolute, gauge MaxBytes[dial]: 30 AbsMax[dial]: 30 Title[dial]: dial.EUnet.pt : MODEMS/ISDN Unscaled[dial]: dwyn YLegend[dial]: Interfaces Colours[dial]: GOLDENROD#D2A13B,BLUE1#0000ff,DARK GREEN#006600,VIOLET#ff00ff XSize[dial]: 340 YSize[dial]: 100 ShortLegend[dial]: if's Legend1[dial]: Modems Legend2[dial]: ISDN Legend3[dial]: Maximal 5 Minute Modems Legend4[dial]: Maximal 5 Minute ISDN LegendI[dial]:   modems: LegendO[dial]:   ISDN: PageTop[dial]:

      Interface Number for dial.EUnet.pt
      dial.EUnet.pt Interfaces

      System:dial.EUnet.pt
      Maintainer:
      Interface:MODEMS/ISDN
      IP:dial.EUnet.pt (127.0.0.1)
      Max Interfaces: 10 Asyncs / 30 ISDN
      mrtg-2.17.10/contrib/meminfo/0000755000175300017510000000000013057016061014737 5ustar oetikeroepmrtg-2.17.10/contrib/meminfo/README0000644000175300017510000000056213057016061015622 0ustar oetikeroepFrom: Colin Tinker Date: Sat, 15 Jan 2000 20:23:32 -0000 You may like to include the perl script below in the next release someone may find it useful. It checks /proc/meminfo for the used and free memory parsing it out for MRTG. it is my first attempt at a perl program so if any one can suggest any improvements feel free. Colin Tinker mrtg-2.17.10/contrib/meminfo/memory.pl0000644000175300017510000000254713057016061016614 0ustar oetikeroep#!/usr/bin/perl # This small utility is used to collect the available memory and # used memory. For free memory, it sums the free, cached and buffers. # You must enable the "gauge" feature to have a proper graph # as those numbers do not grow # # Colin Tinker # g1gsw@titanic.demon.co.uk # setup local vars my($machine); # Enter default macine name here $machine = "g1gsw.ampr.org"; # This allows command args to override defaults listed above if (scalar(@ARGV) > 1 ) { print("USAGE: memory.pl {machine}\n"); exit(-1); } if ($ARGV[0] ne '' && $ARGV[0] ne '#') { $machine = $ARGV[0]; } # Calculate free memory $getfree = `cat /proc/meminfo | grep Mem:`; $getfree =~ /^Mem:\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/; # Each (\D+) = $1 or $2 or $3 etc $outfree = $3; $outbuffers = $5; $outcached = $6; # Total free memory $gettotal = $outfree+$outcached+$outbuffers; print $gettotal."\n"; # Get used memory free $getused = `cat /proc/meminfo | grep Swap:`; $outused = $1-$gettotal; print $outused."\n"; # Get uptime $getuptime = `/usr/bin/uptime`; # Parse though getuptime and get data $getuptime =~ /^\s+(\d{1,2}:\d{2}..)\s+up\s+(\d+)\s+(\w+),/; #Print getuptime data for mrtg print $2." ".$3."\n"; # Print machine name for mrtg print $machine."\n"; mrtg-2.17.10/contrib/cisco_BPX_MGX/0000755000175300017510000000000013057016061015631 5ustar oetikeroepmrtg-2.17.10/contrib/cisco_BPX_MGX/howto.html0000644000175300017510000006705613057016061017675 0ustar oetikeroep Monitoring Cisco BPX ATM Switches with MRTG:

      Monitoring Cisco BPX ATM Switches with MRTG:

      <[!if !supportEmptyParas]> <[!endif]>

      These OIDs work for monitoring total cells transmitted and received on  a trunk on the Cisco BPX Switch.

      X=slot number Y=1st digit of port number Z=2nd digit of port number(If single digit number ie.8, Z=0)

      <[!if !supportEmptyParas]> <[!endif]>

      .1.3.6.1.4.1.351.100.4.2.4.4.1.25.X0YZ000

      atmTrkStatsTotalCellsTxtoLns

      <[!if !supportEmptyParas]> <[!endif]>

      OBJECT-TYPE -- FROM                    STRATACOM-MIB

      SYNTAX                             Counter

      MAX-ACCESS                                read-only

      STATUS                              Mandatory

      DESCRIPTION                    "The number of total cells transmitted to the line."

      ::= { iso(1) org(3) dod(6) internet(1) private(4) enterprises(1) stratacom(351) snmpAgents(100) strmSwitchMIB(4) switchServiceObjects(2) trunkServiceObjects(4) atmTrunkStatsTable(4) atmTrkStatsEntry(1) atmTrkStatsTotalCellsTxtoLns(25)

      <[!if !supportEmptyParas]> <[!endif]>

      <[!if !supportEmptyParas]> <[!endif]>

      .1.3.6.1.4.1.351.100.4.2.4.4.1.26.X0YZ000

      atmTrkStatsTotalCellsRxFromPorts

      <[!if !supportEmptyParas]> <[!endif]>

      OBJECT-TYPE-- FROM                STRATACOM-MIB

                      SYNTAX                             Counter

                      MAX-ACCESS                                read-only

                      STATUS                              Mandatory

                      DESCRIPTION   "The number of total cells received from the port."

      ::= { iso(1) org(3) dod(6) internet(1) private(4) enterprises(1) stratacom(351) snmpAgents(100) strmSwitchMIB(4) switchServiceObjects(2) trunkServiceObjects(4) atmTrunkStatsTable(4) atmTrkStatsEntry(1) atmTrkStatsTotalCellsRxFromPorts(26)

      <[!if !supportEmptyParas]> <[!endif]>

      example MRTG.cfg entry:

        Target[Switchname_2.1]:.1.3.6.1.4.1.351.100.4.2.4.4.1.25.X0YZ000&.1.3.6.1.4.1.351.100.4.2.4.4.1.26.X0YZ000:community@x.x.x.x*53

      #multiply above by 53(53 bytes in a cell)

      Options[Switchname_2.1]:bits

      PageTop[ Switchname_2.1]:<H1>Traffic for switchname, FDR trunk 2.1 to switchname(MGX)</H1>

      AbsMax[Switchname_2.1]:149759768

      MaxBytes[Switchname_2.1]:149759768

      Directory[Switchname_2.1]:xxxxx

      Ylegend[Switchname_2.1]:Bits per second

      ShortLegend[Switchname_2.1]:bps

      Title[Switchname_2.1]:Traffic for Switchname, FDR trunk 2.1 to switchname(MGX)

      <[!if !supportEmptyParas]> <[!endif]>

      <[!if !supportEmptyParas]> <[!endif]>

      <[!if !supportEmptyParas]> <[!endif]>

      <[!if !supportEmptyParas]> <[!endif]>

      <[!if !supportEmptyParas]> <[!endif]>

      <[!if !supportEmptyParas]> <[!endif]>

      <[!if !supportEmptyParas]> <[!endif]>

      These OIDs work for monitoring total cells transmitted and received on a port on the Cisco BPX Switch.

      X=slot number Y=port number

      <[!if !supportEmptyParas]> <[!endif]>

      .1.3.6.1.4.1.351.100.4.2.2.3.1.8.X.Y

      atmPortStatCellsRxs OBJECT-TYPE

              -- FROM        STRATACOM-MIB

              SYNTAX              Counter

              MAX-ACCESS        read-only

              STATUS              Mandatory

              DESCRIPTION    "Total numbers of cells received."

      ::= { iso(1) org(3) dod(6) internet(1) private(4) enterprises(1) stratacom(351) snmpAgents(100) strmSwitchMIB(4) switchServiceObjects(2) atmServiceObjects(2) atmPortStatTable(3) atmPortStatEntry(1) 8 }

      <[!if !supportEmptyParas]> <[!endif]>

      <[!if !supportEmptyParas]> <[!endif]>

      .1.3.6.1.4.1.351.100.4.2.2.3.1.12.X.Y

      atmPortStatCellsTxs OBJECT-TYPE

              -- FROM        STRATACOM-MIB

              SYNTAX              Counter

              MAX-ACCESS        read-only

              STATUS              Mandatory

              DESCRIPTION    "Total numbers of cells transmitted."

      ::= { iso(1) org(3) dod(6) internet(1) private(4) enterprises(1) stratacom(351) snmpAgents(100) strmSwitchMIB(4) switchServiceObjects(2) atmServiceObjects(2) atmPortStatTable(3) atmPortStatEntry(1) 12 }

      <[!if !supportEmptyParas]> <[!endif]>

      Example MRTG.cfg entry:

      <[!if !supportEmptyParas]> <[!endif]>

      <[!if !supportEmptyParas]> <[!endif]>

      Target[SYRTGB01_6.10]:.1.3.6.1.4.1.351.100.4.2.2.3.1.8.6.10&.1.3.6.1.4.1.351.100.4.2.2.3.1.12.6.10:public@10.1.1.34*53

      #multiply cells by 53 to convert to bytes

      Options[Switchname_6.10]:bits

      PageTop[Switchname_6.10]:<H1>Port Bandwidth DS-3</H1>

      MaxBytes[Switchname_6.10]:4608000

      Directory[Switchname_6.10]:xxxxxx

      Ylegend[Switchname_6.10]:Bits per second

      ShortLegend[Switchname_6.10]:bps

      Title[Switchname_6.10]:Port Bandwidth  DS-3

      <[!if !supportEmptyParas]> <[!endif]>

      <[!if !supportEmptyParas]> <[!endif]>

      <[!if !supportEmptyParas]> <[!endif]>

      <[!if !supportEmptyParas]> <[!endif]>

      <[!if !supportEmptyParas]> <[!endif]>

      <[!if !supportEmptyParas]> <[!endif]>

      <[!if !supportEmptyParas]> <[!endif]>

      <[!if !supportEmptyParas]> <[!endif]>

      <[!if !supportEmptyParas]> <[!endif]>

      <[!if !supportEmptyParas]> <[!endif]>

      <[!if !supportEmptyParas]> <[!endif]>

      <[!if !supportEmptyParas]> <[!endif]>

      <[!if !supportEmptyParas]> <[!endif]>

      <[!if !supportEmptyParas]> <[!endif]>

      <[!if !supportEmptyParas]> <[!endif]>

      <[!if !supportEmptyParas]> <[!endif]>

      Monitoring Cisco MGX Frame Relay connections with MRTG:

      These OIDs work for monitoring total cells transmitted and received on a port on the Cisco BPX Switch.

      <[!if !supportEmptyParas]> <[!endif]>

      .1.3.6.1.4.1.351.110.2.5.1.1.4.1

      xmtCells OBJECT-TYPE

              -- FROM        AXIPOP-MIB

              SYNTAX              Counter

              MAX-ACCESS        read-only

              STATUS              Mandatory

              DESCRIPTION    "The number of cells transmitted on this channel."

      ::= { iso(1) org(3) dod(6) internet(1) private(4) enterprises(1) stratacom(351) basis(110) cardGeneric(2) sarChannelCounter(5) sarChannelCounterTable(1) sarChannelCounterEntry(1) xmtCells(4) 1 }

      <[!if !supportEmptyParas]> <[!endif]>

      .1.3.6.1.4.1.351.110.2.5.1.1.12.1

      rcvCells OBJECT-TYPE

              -- FROM        AXIPOP-MIB

              SYNTAX              Counter

              MAX-ACCESS        read-only

              STATUS              Mandatory

              DESCRIPTION    "The number of cells that were received on this channel."

      ::= { iso(1) org(3) dod(6) internet(1) private(4) enterprises(1) stratacom(351) basis(110) cardGeneric(2) sarChannelCounter(5) sarChannelCounterTable(1) sarChannelCounterEntry(1) rcvCells(12) 1 }

      <[!if !supportEmptyParas]> <[!endif]>

      <[!if !supportEmptyParas]> <[!endif]>

      ######enterprises.351.110.2.5.1.1.4.1.x.yy =Transmit Cells from SAR

      ######enterprises.351.110.2.5.1.1.12.1.x.yy =Recieve Cells from SAR

      ######x=slotnumber

      ######yy=channel number

      <[!if !supportEmptyParas]> <[!endif]>

      Target[Switchname_11_142]:enterprises.351.110.2.5.1.1.4.1.x.yy&enterprises.351.110.2.5.1.1.12.1.x.yy:POPEYE\@SM_11@10.1.1.35*53

      #\@ the \breaks out of Perl so the @ is not processedthanks Tobi.

      #POPEYE is always the community name of the switch, SM_11 means service module 11, if you need stats from #the active PXM the community is POPEYE@PXM_ACTIVE

      Options[Switchname_11_142]: bits

      PageTop[Switchname_11_142]:<H1>xxxx Frame Statistics</H1>

      AbsMax[Switchname_11_142]:1536000

      #Port Speed

      MaxBytes[Switchname_11_142]:1536000

      #MaxBytes=CIR

      Directory[Switchname_11_142]:xxxx

      Ylegend[Switchname_11_142]:Bits per second

      ShortLegend[Switchname_11_142]:bps

      Title[Switchname_11_142]: 11.19.0.17 DLCI 17

      mrtg-2.17.10/contrib/mrtg-mail/0000755000175300017510000000000013057016061015176 5ustar oetikeroepmrtg-2.17.10/contrib/mrtg-mail/mqueue.cfg0000644000175300017510000000063713057016061017166 0ustar oetikeroepInterval: 5 #--------------------------------------------------------------- Target[mq]: `/opt/mrtg/bin/mqueue` MaxBytes[mq]: 32000 AbsMax[mq]: 64000 Options[mq]: gauge Title[mq]: Sendmail Statistics PageTop[mq]:

      Sendmail MailQueue Statistics

      XSize[mq]: 500 Supress[mq]: y YSize[mq]: 128 WithPeak[mq]: my YLegend[mq]: No. of messages in mailq ShortLegend[mq]: Mailq LegendO[mq]:  Mailq: LegendI[mq]: mrtg-2.17.10/contrib/mrtg-mail/mailstats0000755000175300017510000000503513057016061017130 0ustar oetikeroep#!/usr/local/bin/perl # # Author: Petter Reinholdtsen # Date: 1997-07-09 # The original was written by Rachel Polanskis # # Fetches output from mailstats(1) either via TCP or via exec and # feeds changes on smtp to mrtg. # # Irix 6.x seems to lack mailstats # # Usage mailstats [host] # if host is missing, localhost is used use strict; use Socket; my($datafile, $source, $sourceport, @mailstatspaths, $oldfrm, $oldto, $newfrm, $newto, $uptime); # Adjust this to your own mailserver. Uses local `mailstats` if set # to 'localhost' $source = $ARGV[0] || "localhost"; $sourceport = "7256"; $datafile = "/tmp/mailstat-$source.old"; @mailstatspaths = ( "/usr/sbin/mailstats", "/usr/bin/mailstats" ); ($oldfrm, $oldto) = getOldStats($datafile); ($newfrm, $newto, $uptime) = getStats($source, $sourceport); putOldStats($datafile, $newfrm, $newto) || warn "$0: Unable to save stats to $datafile"; print $newfrm-$oldfrm,"\n",$newto-$oldto,"\n","$uptime\n$source\n" if ($oldfrm); ## # Returns first line of file given as param splittet on space sub getOldStats { my($filename) = @_; open(OLD, $filename) || warn "$0: Unable to open $filename for reading"; my($line) = ; close(OLD); return split(/ /, $line); } sub findFirstExecutable { my($filename); foreach $filename (@_) { return $filename if ( -x $filename && ! -d $filename ); } } sub getStats { my($source, $sourceport) = @_; my(@output, $port, $proto, $iaddr, $paddr); if ( $source eq "localhost" ) { my($progpath) = findFirstExecutable(@mailstatspaths); @output = `$progpath`; chomp(@output); } else { $port = getservbyname ($sourceport, 'tcp') if ($sourceport =~ /\D/); die "$0: Bad port \"$sourceport\"" unless ($port); $proto = getprotobyname ('tcp') || die "$0: Bad prototype tcp"; $iaddr = inet_aton($source) or die "$0: no host \"$source\""; $paddr = sockaddr_in($port, $iaddr); socket (SOCK, PF_INET, SOCK_STREAM, $proto) or die "$0: socket error $!"; connect (SOCK, $paddr) or die "$0: connect error $!"; while () { push(@output); } close(SOCK) || warn "$0: socket close error $!"; } my($curfrm, $curto, $uptime); foreach (@output) { ($curfrm, $curto) = (split(/ +/))[2,4] if (/e?smtp/); ($uptime) = m/Statistics from (.*)/ if (/Stati/); } return ($curfrm, $curto, $uptime); } sub putOldStats { my($filename, $frm, $to) = @_; open(STAT, ">$filename") || return ""; print STAT "$frm $to\n"; close(STAT); return "1"; } mrtg-2.17.10/contrib/mrtg-mail/mailstats-alternate0000644000175300017510000000116713057016061021104 0ustar oetikeroep# use this method if you think it is better... # I did this one after I learnt a bit more perl! ## # munge the output data # while () { $line = $_; ($a, $curfrm, $b, $curto, $c, $d) = split(' ',$line); } if ($a = "T") { # do some sums $msgsfrm = $curfrm - $oldfrm; $msgsto = $curto - $oldto; chomp $msgsfrm; chomp $msgsto; # open the old file for overwrite open (OLD,">/tmp/mailstat.old") or die "can't open file!\n"; # print the data for mrtg print "$msgsfrm\n$msgsto\n1\n$remote\n"; # print the data to the old file print OLD "$curfrm $curto\n"; } #endif close (SOCK) or die "close: $!"; exit; mrtg-2.17.10/contrib/mrtg-mail/README0000644000175300017510000001462713057016061016070 0ustar oetikeroep Using Mailstats with MRTG # 17/04/97: These files are based on a post # made to the MRTG discussion list. # I was then asked if I would contribute them to the distribution. # Now I've cleaned up one or two minor things, but the message below # is essentially the same as the distribution I have contributed. # I also posted this to comp.mail.sendmail some time back. # rachel polanskis This is some experimenting I have done using sendmail and mrtg. Currently I am using Solaris 2.5.1 as the mailhost, and then plotting the goodies using mrtg-2.0 on Linux 1.2.13 and displaying the graphs on the linux box. There are some caveats on my method for plotting these charts: 1: I use a previously undefined port and run the Solaris /bin/mailstats program out of inetd. For this reason, I can only assume the mailstat on Solaris works - I have tried no other platforms. * Q: Is there a security risk involved in running Solaris Mailstat out of inetd? 2: You must have Perl-5.002 or better installed on the plotting host. 3: You must have MRTG-2.0 installed - you must know how to use it! 4: I am only interested in SMTP connections, and my scripts only plot In and Out, since mrtg can only plot 2 lines per graph. If you want any more than that - experiment! And then tell me since I am only learning. Here goes: 1: Ensure you have "/bin/mailstat" on your system. 2: Enable "/etc/mail/sendmail.st" To do this you can just make sure the entry for "sendmail.st" in "sendmail.cf" is uncommented, and then do the command: # touch /etc/mail/sendmail.st And restart sendmail: # /etc/init.d/sendmail stop # /etc/init.d/sendmail start 3: Create the following shell-script: #!/bin/sh # smtp-stats: exec Solaris mailstats # if [ -x "/bin/mailstats" ] then exec /bin/mailstats -f/etc/mail/sendmail.st fi I run this out of /opt/local/bin, and call it "smtp-stats" 4: Now add the following to /etc/services: # /etc/services # smtp-stats 7256/tcp # smtp-stats I used port 7256 as it was undefined. You might like to select something else. 5: Add the following to /etc/inetd.conf: # /etc/inetd.conf # smtp-stats stream tcp nowait root \ /opt/local/bin/smtp-stats smtp-stats ***Ensure that the above is all on *one* line. The sample above is broken on 2 lines for legibility!! 6: Restart inetd 7: Test the port. you should see the following: # telnet localhost 7256 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. Statistics from Thu Feb 27 01:12:47 1997 M msgsfr bytes_from msgsto bytes_to Mailer 0 0 0K 96 393K prog 3 34 94K 0 0K local 5 93 474K 31 47K esmtp ======================================== T 127 568K 127 440K Connection closed by foreign host. OK!! The line we are interested in is line 5: The "esmtp" line. This is the line we will use to get our stats. You might want to adjust this depending on how many mailer progs you use... I find the Totals to be useless, since it includes a lot of filtering from procmail. I am only interested in SMTP connections... #################################### Stage 2: MRTG Here is a perl script I wrote to glom the values of the "esmtp" line (5) and massage them into something mrtg understands. A file called "mailstats.old" is written to /tmp to allow for doing my sums. I am a Perl Newbie - please don't be offended at my code. I would like it if someone can help me with better methods one day! #!/usr/bin/perl # # rachel polanskis - 240297 # this script relies on the sendmail.st file being activated. # the data is called via "mailstats" which comes with SunOS/Solaris. # mailstats is run out of inetd, on port 7256. # require 5.002; use strict; use Socket; my ($remote, $port, $iaddr, $paddr, $proto, $line, $count, $oldfrm, $oldto, $curfrm, $curto, $msgsfrm, $msgsto, $a, $b, $c, $d); ## # open the old stats file for reading - we use this to get the differences # open (OLD,") { if ($. == "1") { $count = $_; } ($oldfrm, $oldto) = split (' ',$count); } close (OLD); ## # Straight out of the blue Camel - pp. 349 # # Change these next 2 lines to suit yourself. # $remote = "juno"; $port = "7256"; # if ($port =~ /\D/) {$port = getservbyname ($port, 'tcp')} die "No port" unless $port; $iaddr = inet_aton($remote) or die "no host: $remote"; $paddr = sockaddr_in($port, $iaddr); $proto = getprotobyname ('tcp'); socket (SOCK, PF_INET, SOCK_STREAM, $proto) or die "socket: $!"; connect (SOCK, $paddr) or die "connect: $!"; ## # munge the output data # while () { if ($. == "5" ) { $line = $_; ($a, $curfrm, $b, $curto, $c, $d) = split(' ',$line); # do some sums $msgsfrm = $curfrm - $oldfrm; $msgsto = $curto - $oldto; chomp $msgsfrm; chomp $msgsto; # open the old file for overwrite open (OLD,">/tmp/mailstat.old") or die "can't open file!\n"; # print the data for mrtg print "$msgsfrm\n$msgsto\n1\njuno\n"; # print the data to the old file print OLD "$curfrm $curto\n"; } #endif } close (SOCK) or die "close: $!"; exit; ########################## Now, Here is my mrtg.cfg file for mail. I call it "mail.cfg" I run mrtg from cron on my Linux box every 10 minutes to plot the stats. It is up to the individual what they do with their own setup. # # Mail: MRTG.cfg file for sendmail stats on mailhost. # WorkDir: /usr/local/etc/httpd/htdocs/stats/mrtg Interval: 10 #--------------------------------------------------------------- Target[mail]: `/usr/local/bin/mrtg/mailstats` MaxBytes[mail]: 150 Options[mail]: gauge Title[mail]: Juno Sendmail Statistics PageTop[mail]: Juno Sendmail Statistics XSize[mail]: 500 Supress[mail]: my YSize[mail]: 200 WithPeak[mail]: dwmy YLegend[mail]: No. of messages ShortLegend[mail]: messages LegendI[mail]:  Incoming: LegendO[mail]:  Outgoing: That's it!! You should have no problems running this stuff if you follow my instructions. Any comments, advice or interesting suggestions would be much appreciated. Do with my little hack as you like, as long as the developers of sendmail, perl, and mrtg get some credit, as well as lil ol me for dreaming this up!!! have fun... rachel polanskis 17/04/97 mrtg-2.17.10/contrib/mrtg-mail/smtp-stats0000755000175300017510000000027013057016061017242 0ustar oetikeroep#!/bin/sh # # smtp-stats: invoke mailstats from a wrapper for use in inetd. # PATH=/bin:/sbin if [ -x "/bin/mailstats" ] then exec /bin/mailstats -f/etc/mail/sendmail.st fi mrtg-2.17.10/contrib/mrtg-mail/mqueue0000755000175300017510000000041413057016061016424 0ustar oetikeroep#!/store/bin/perl # simple mqueue done with find2perl $hostname = "apollo"; require "find.pl"; # Traverse desired filesystems $counter = 0; &find('/var/spool/mqueue/'); sub wanted { /^qf.*$/ && $counter++; } chomp $counter; print "0\n$counter\n1\n$hostname\n"; mrtg-2.17.10/contrib/mrtg-mail/mailstats.cfg0000644000175300017510000000110613057016061017656 0ustar oetikeroep# # Mail.cfg: Mailstats plotting with MRTG # WorkDir: /usr/local/etc/httpd/htdocs/stats/mrtg Interval: 10 #--------------------------------------------------------------- Target[mail]: `/usr/local/bin/mrtg/mailstats` MaxBytes[mail]: 150 # AbsMax[mail]: 1800 #Unscaled[mail]: dwmy Options[mail]: gauge Title[mail]: Juno Sendmail Statistics PageTop[mail]: Juno Sendmail Statistics XSize[mail]: 500 #Supress[mail]: my YSize[mail]: 200 WithPeak[mail]: dwmy YLegend[mail]: No. of messages ShortLegend[mail]: messages LegendI[mail]:  Incoming: LegendO[mail]:  Outgoing: mrtg-2.17.10/contrib/mrtg-mail/services-dist0000644000175300017510000000020613057016061017703 0ustar oetikeroep# You can add this simply by doing "cat services-dist >> /etc/services" smtp-stats 7256/tcp # smtp-stats mrtg-2.17.10/contrib/mrtg-mail/mailstats-horowitz0000644000175300017510000003523413057016061021014 0ustar oetikeroep#!/usr/bin/perl # # Author by Rick Horowitz 1998-12-16 # Inspired by, and may show remnants of code from: # "mailstats" by Petter Reinholdtsen # dated 1997-07-09 and part of mrtg2.54c dist # Petter credits Rachel Polanskis for # the original. # Type "perldoc mrtg-mailstat" from a shell prompt for more information # on this script and its use. # use strict; use Socket; use Getopt::Long; # IMPORTANT: THIS NEXT LINE ENSURE THAT CASE MATTERS ON OPTIONS!!! $Getopt::Long::ignorecase = 0; use vars qw($datafile $server $sourceport $oldfrm $oldto $help $newfrm $newto $uptime $mailtype $logbase); # Assign options. ("Illegal" options will be possible, # but we'll warn about them via Usage().) # h = runs the perldoc program to show the mrtg-mailstat manual # m = specifies the type of mail we're checking for # p = specifies the port for reaching the mailstats on the mailserver # s = specifies the location of the mailserver # See the mrtg-mailstat man page for details. GetOptions("help" => \$help, "logbase=s" => \$logbase, "mailtype=s" => \$mailtype, "port=i" => \$sourceport, "server=s" => \$server, "<>" => \&Usage); # HARDCODING SECTION -- MODIFY THESE ONLY IF YOU KNOW WHAT YOU ARE DOING!!! # Set these ONLY if you don't wish to use command line options. For more # information, type 'mrtg-mailstat -h' or 'perldoc mrtg-mailstat' from a # shell prompt. $logbase = '/tmp' unless $logbase; $mailtype = '' unless $mailtype; $server = '' unless $server; $sourceport = '' unless $sourceport; # Location for keeping mail statistics. The numbers stored here are # compared to the new numbers at each run of this script. $datafile = "$logbase/${mailtype}-mailstat.old"; # Core portions of the program. Most of retained code from original # comes into play here. GetHelp() if $help; Usage() unless ($mailtype && $server && $sourceport); ($oldfrm, $oldto) = GetOldStats($datafile); ($newfrm, $newto, $uptime) = GetNewStats($server, $sourceport); PutOldStats($datafile, $newfrm, $newto) || warn "$0: Unable to save stats to $datafile"; print $newfrm-$oldfrm,"\n",$newto-$oldto,"\n","$uptime\nthe mail server\n" if ($oldfrm); ## # Returns first line of file given as param split on (a single) space sub GetOldStats { my($datafile) = @_; if (-e $datafile) { open(OLD, $datafile) || warn "$0: Unable to open $datafile for reading"; my($line) = ; close(OLD); return split(/ /, $line); } else { return(0, 0); } } sub GetNewStats { my($server, $sourceport) = @_; my(@output, $port, $proto, $iaddr, $paddr, $tempuptime, $curfrm, $curto, $uptime); if ( $server eq "localhost" ) { @output = `/usr/sbin/mailstats`; chomp(@output); } else { if ($sourceport =~ /\D/) { $port = getservbyname ($sourceport, 'tcp'); } else { $port = $sourceport; } die "$0: Bad port \"$sourceport\"" unless ($port); $proto = getprotobyname ('tcp') || die "$0: Bad prototype tcp"; $iaddr = inet_aton($server) or die "$0: no host \"$server\""; $paddr = sockaddr_in($port, $iaddr); socket (SOCK, PF_INET, SOCK_STREAM, $proto) or die "$0: socket error $!"; connect (SOCK, $paddr) or die "$0: connect error $!"; while () { push(@output, $_); } close(SOCK) || warn "$0: socket close error $!"; } # Parse only the interesting lines. foreach (@output) { ($curfrm, $curto) = (split(/ +/))[2,4] if (/$mailtype/); if (/UPTIME.*?up\s*(.*?), [0-9]* user/) { $uptime = $1; $uptime =~ s/:([0-9]*)/ hours, $1 minutes/; } } # This line ensures no negative numbers. See "perldoc mrtg-mailstat". ($curfrm, $curto) = noNeg($curfrm, $curto); return ($curfrm, $curto, $uptime); } # End GetNewStats(). # Saves the information to the log file. (Note: Overwrites old contents # which aren't needed anymore, anyway.) sub PutOldStats { my($datafile, $frm, $to) = @_; open(STAT, ">$datafile") || return ""; print STAT "$frm $to\n"; close(STAT); return "1"; } # End PutOldStats(). # Negative values should only occur the first time the script is ever run. # These must be converted to positives so subsequent runs of the script # correctly compute new values. sub noNeg { my ($frm, $to) = @_; $frm = -($frm) if ($frm < 0); $to = -($to) if ($to < 0); return($frm, $to); } # End noNeg(). # Usage() simply checks to see that no "illegal" options # have been entered. If the program is thus improperly # called, it issues a notice explaining how to read the # man page for this program. sub Usage { my $option = shift; print STDERR "You may wish to read the documentation \n"; print STDERR "(type \"perldoc mrtg-mailstat\" or \"mrtg-mailstat -h\")\n"; exit(5); } # End Usage(). sub GetHelp { system("perldoc mrtg-mailstat"); exit(0); } # End GetHelp(). __END__ =head1 NAME mrtg-mailstat - Mail Statistics Collector for MRTG =head1 SYNOPSIS mrtg-mailstat S<[B<-h>]> S<[B<-m> I]> S<[B<-p> I]> S<[B<-s> I]> =head1 DESCRIPTION The B program retrieves statistical information from the mail server. It does not matter whether the script is run on the mail server itself, or on a machine remote from the mail server. =head1 S< Running mrtg-mailstat > S< > The proper way to run B is to call it from an MRTG configuration file. The following provides an example of a valid configuration file entry: =over 2 =item C S S S SH1ETechStop SMTP Mail Statistics E/H1E> S S S S S S S > =back This makes certain assumptions which are outlined below under I. =head1 S< Switches > S< > =head2 Hardcoding versus Using Switches It is not necessary to provide switches to the program, if you prefer to "hardcode" the information in the script itself. "Hardcoding" allows you to call the script with less (or no) flags; information needed by the script, and not provided by a flag, must be "hardcoded" by you before this will work. (This was provided for diehards who hate the flexibility of switches. I provided enough flexibility for them to be inflexible. ;)) To "hardcode" your information into the script, look for the section near the top of the script labeled "HARDCODING SECTION". Change the "null" entries represented by the double double quotes ("") so that they contain the appropriate values. Example: =over 4 =item C<$server = "" unless $server; > =back becomes =over 4 =item C<$server = "mail.techstop.com" unless $server; > =back As stated, this is not necessary; it is not even preferred. You may, and probably should, use the switches in the next subsection. =head2 Invoking Switches B switches adhere to the POSIX syntax for command-line options. This means options can take a variety of forms. For example, to specify running B against port C<7258> of the mail server to obtain reports on smtp mail (see "I under I below) you could use any of the following forms: =over 5 =item C<% mrtg-mailstat -m smtp -p 7258> =item C<% mrtg-mailstat -m=smtp -p=7258> =item C<% mrtg-mailstat -mailtype smtp -port 7258> =item C<% mrtg-mailstat -mailtype=smtp -port=7258> =item C<% mrtg-mailstat --m smtp --p 7258> =item C<% mrtg-mailstat --m=smtp --p=7258> =item C<% mrtg-mailstat --mailtype smtp --port 7258> =item C<% mrtg-mailstat --mailtype=smtp --port=7258> =back Any of the last four forms are preferred. One way of doing options which is I possible is: =over 5 =item C<% mrtg-mailstat --msmtp --p7258> =back Use of that last form may cause results other than you expected. (Important Note: The above examples would also require that the server be "hardcoded" into the script as noted in the subsection on I above.) =head2 Available Switches The following switches are available: =over 2 =item B<--h[elp]> The B<-h> flag causes B to print this manual to standard output. For obvious reasons, this is not normally included in an MRTG configuration file, nor invoked by cron. =item B<--l[ogbase]> The B<-l> flag can be used to specify the directory in which to store the file that holds the values from each run. By default, this file is created in I, but if you need to store it in another directory, this is the flag for you. By the way, if the file doesn't exist, one is created. A side-effect of this is that if you try to use one "logbase" one time, and another the next, the program has no way of warning you. It simply creates a new file, and uses zero values to begin its calculations. This can have strange consequences for your mail statistics. Try to remember where you store your log, or use the hardcoding option (see I above). =item B<--m[ailtype]> The B<-m> flag is used to specify the mail type. The two types reported by I are "esmtp" and "local". The "esmtp" line reports traffic between the mail server and other systems. The "local" line reports traffic between users on the mail server. For most smaller networks, this likely means that "esmtp" reports mail between their network and the Internet, and "local" reports mail between users within the small network's organization. Possible values for this flag are "smtp" and "local". B =item B<--p[ort]> The B<-p> flag specifies the port whence the statistics are obtained. See the I section below. =item B<--s[erver]> The B<-s> flag specifies the mail server. This can be either a DNS name, or an IP number. =back =head1 DEPENDENCIES The B program makes certain assumptions. The following is quoted with a few changes from the documentation for the original B script upon which B is based. In particular, it is important to note that the original instructions were Solaris-centric. Your system may have different commands for starting and stopping the mail server, and your paths may be different (i.e., may use /usr/local instead of /opt, or whatever). You are assumed to be able to figure that out yourself. =over 2 =item 1: Ensure you have I (or I)on your system. =item 2: Enable I To do this you can just make sure the entry for "sendmail.st" in "sendmail.cf" is uncommented. On the BSD/OS 3.1 system mrtg-mailstat was tested on, the /etc/sendmail.cf entries look like this: OS/var/log/sendmail.st O StatusFile=/var/log/sendmail.st Then do the command: # touch /var/log/sendmail.st And restart sendmail: # /etc/init.d/sendmail stop # /etc/init.d/sendmail start =item 3: Create the following shell-script (B This section is different than the original version!): #!/bin/sh # # smtp-stats: invoke mailstats from a wrapper for use in inetd. # PATH=/bin:/sbin if [ -x "/usr/sbin/mailstats" ] then temp1=`/usr/sbin/mailstats -f/var/log/sendmail.st` fi if [ -x "/usr/bin/uptime" ] then temp2=`/usr/bin/uptime` fi echo -e "$temp1\nUPTIME: $temp2" I run this out of /usr/local/bin, and call it "smtp-stats" =item 4: Now add the following to /etc/services: # /etc/services # smtp-stats 7256/tcp # smtp-stats I used port 7256 as it was undefined. You might like to select something else. =item 5: Add the following to /etc/inetd.conf: # /etc/inetd.conf # smtp-stats stream tcp nowait root \ /usr/local/bin/smtp-stats smtp-stats ***Ensure that the above is all on *one* line. The sample above is broken on 2 lines for legibility!! =item 6: Restart inetd =item 7: Test the port. you should see the following: S< > S S S S S S< M msgsfr bytes_from msgsto bytes_to Mailer > S< 3 79372 3623347K 143989 6954437K local > S< 5 9941 483230K 6669 652586K esmtp > S<======================================== > S< T 89313 4106577K 150658 7607023K > S S =back =head1 FILES Strictly speaking, you needn't worry about the files. If you've created the smtp-stats script noted above, and made the appropriate changes, the only other I you need to be concerned with is B itself. For completeness sake, I list all the files with which B may depend upon, utilize, create, or use. =over 5 =item I =item I =item I =item I =item I =item I =item I<$logbase/${mailtype}-mailstat.old> =back =head1 AUTHOR This B program was written by Rick Horowitz , tested, and released to the MRTG mailing list on December 16, 1998. It was inspired by, and contains remnants of code from: =over 10 =item "mailstats" by Petter Reinholdtsen dated 1997-07-09 and part of mrtg2.54c dist =back Petter credits Rachel Polanskis for the original. =cut mrtg-2.17.10/contrib/mrtg-mail/inetd.conf-dist0000644000175300017510000000026413057016061020113 0ustar oetikeroep# smtp stats for mrtg # you can add this simply by doing "cat inetd.conf-dist >>/etc/inetd.conf" smtp-stats stream tcp nowait root /opt/local/bin/smtp-stats smtp-stats mrtg-2.17.10/contrib/mrtgrq/0000755000175300017510000000000014130032004014605 5ustar oetikeroepmrtg-2.17.10/contrib/mrtgrq/redball.gif0000644000175300017510000000156113057016061016720 0ustar oetikeroepGIF89a f3̙f3f3ffffff3f3333f333f3f3̙f3̙̙̙̙f̙3̙ffffff3f3333f333f3̙f3̙̙f3̙f3ff̙ffff3f33̙33f333̙f3ffffff3ffff̙fff3fffffff3ffffffffffff3fff3f3f3f3ff33f3ffffff3f3333f333333̙3f3333333f3333f3f3f3ff3f33f33333333f333333333f333f3̙f3f3ffffff3f3333f333f3!, N=H 8T`! @0xAG$ \ÈG8LcƑ!:xC9d%ˈ]̘s#@z;mrtg-2.17.10/contrib/mrtgrq/grnball.gif0000644000175300017510000000156313057016061016736 0ustar oetikeroepGIF89a f3̙f3f3ffffff3f3333f333f3f3̙f3̙̙̙̙f̙3̙ffffff3f3333f333f3̙f3̙̙f3̙f3ff̙ffff3f33̙33f333̙f3ffffff3ffff̙fff3fffffff3ffffffffffff3fff3f3f3f3ff33f3ffffff3f3333f333333̙3f3333333f3333f3f3f3ff3f33f33333333f333333333f333f3̙f3f3ffffff3f3333f333f3!, P=H ={@),aBP@ <@ e%z@@Bі tFM4d4O.3&L5ij*h;o Zh@;mrtg-2.17.10/contrib/mrtgrq/mrtgrq.css0000644000175300017510000000172313057016061016652 0ustar oetikeroep/* Author: Adrian Turcu Created: 16 April 2000 Version: 1 */ BODY { background-color: f5fffa; } A { text-decoration: none; } A:link { color: 0000cd; } A:visited { color: 0000cd; } A:active { color: 0000cd; } H1 {white-space: nowrap; border: none; padding: 0.5em; margin-top: 25px; position: relative;} H1 A {text-decoration: none;} H1, H1 A {color: #f8f8ff; background: #4169e1;} .pt { border: none; padding: 0.25em; width: 1020px; text-align: center; font-weight: 800;} .pt, .pt A {text-decoration: none; color: #f8f8ff; background: #0000cd;} .ptl { border: none; padding: 0.25em; width: 1020px; text-align: left; font-weight: 800;} .ptl, .ptl A {text-decoration: none; color: #f8f8ff; background: #0000cd;} .pth { border: none;text-decoration: none; background: #e8e8ff; color: #111111; text-align: left; font-weight: 800;} .ptb { border: none;text-decoration: none; color: #0000cd; text-align: left; font-weight: 800;} mrtg-2.17.10/contrib/mrtgrq/make-mrtg.cfg.awk0000644000175300017510000000674514130032004017747 0ustar oetikeroepBEGIN { # # Global Variables Initialization mrtg_var_WorkDir = "/home/httpd/html/mrtg/mrtgrq" # it will be inserted into MRTG config file mrtg_var_IconDir = "/img/" # it will be inserted into MRTG config file and it will be used on HTML documents mrtg_var_Interval = "10" # it will be inserted into MRTG config file mrtg_executable = "/usr/local/mrtg/mrtg" # MRTG executable file with full path mrtg_mrtgrq_cfg = "/usr/local/mrtg/contrib/mrtgrq/mrtg-awk.cfg" # MRTG config file for mrtgrq mrtgrq_css_file = "http://your.web.server/css/mrtg/mrtg.css" # CSS File definition for HTML documents mrtgrq_maintainer_email = "Your Name <your@email.address>" # Maintainer email address # # Start index number for array lines = 1 startdate = systime() dataexpirarii = startdate+(mrtg_var_Interval*60) # Expire date for HTML documents, +5 min (mrtg_var_Interval) dataexp = strftime("%c %Z", dataexpirarii) dataexpirarii = strftime("%d-%m-%Y %T %Z",dataexpirarii) } { if ( $1 !~ /^Try/ && $1 !~ /^Conn/ && $1 !~ /^Escape/){ array[lines, 1] = $1 array[lines, 3] = $3 array[lines, 4] = $4 lines++ } } END{ # print ("WorkDir: " mrtg_var_WorkDir) > mrtg_mrtgrq_cfg print ("IconDir: " mrtg_var_IconDir) > mrtg_mrtgrq_cfg print ("Interval: " mrtg_var_Interval) > mrtg_mrtgrq_cfg print "\n\n#----------------------------------------------------------------------------\n\n" > mrtg_mrtgrq_cfg # ## # for ( k = 1; k < lines; k++ ){ # print array[k, 1]"\t"array[k, 3]"\t"array[k, 4] > mrtg_mrtgrq_cfg print ("Target[" array[k, 1] "]: `echo | gawk '{ print \"" array[k, 3]"\\n" array[k, 4]"\\n..., last check on: " strftime("%c %Z", startdate) "\\n" array[k, 1] "@cfrcta.ro\\n\"; exit }'`") > mrtg_mrtgrq_cfg print ("Title[" array[k, 1] "]: Diskspace Quota Report For " array[k, 1] "@cfrcta.ro") > mrtg_mrtgrq_cfg print ("MaxBytes[" array[k, 1] "]: " array[k, 4]) > mrtg_mrtgrq_cfg print ("AbsMax[" array[k, 1] "]: " int(array[k, 4]*1.1)) > mrtg_mrtgrq_cfg print ("AddHead[" array[k, 1] "]: ") > mrtg_mrtgrq_cfg print ("PageTop[" array[k, 1] "]:

      Diskspace Quota Report For    " array[k, 1] "@cfrcta.ro") > mrtg_mrtgrq_cfg print ("

      ") > mrtg_mrtgrq_cfg print (" ") > mrtg_mrtgrq_cfg print (" ") > mrtg_mrtgrq_cfg print (" ") > mrtg_mrtgrq_cfg print (" ") > mrtg_mrtgrq_cfg print ("
      Service:Diskspace Quota
      Maintainer:" mrtgrq_maintainer_email "
      Last Checked On:" strftime("%c %Z", startdate) "
      ") > mrtg_mrtgrq_cfg print ("Suppress[" array[k, 1] "]: y") > mrtg_mrtgrq_cfg print ("LegendI[" array[k, 1] "]: used") > mrtg_mrtgrq_cfg print ("LegendO[" array[k, 1] "]: ") > mrtg_mrtgrq_cfg print ("Legend1[" array[k, 1] "]: used ") > mrtg_mrtgrq_cfg print ("Legend2[" array[k, 1] "]: ") > mrtg_mrtgrq_cfg print ("YLegend[" array[k, 1] "]: used ") > mrtg_mrtgrq_cfg print ("ShortLegend[" array[k, 1] "]: used ") > mrtg_mrtgrq_cfg print ("Options[" array[k, 1] "]: gauge") > mrtg_mrtgrq_cfg print ("\n\n#-------------------\n\n") > mrtg_mrtgrq_cfg } # ## # system((mrtg_executable " " mrtg_mrtgrq_cfg " 2> /dev/null")) # ## # } mrtg-2.17.10/contrib/mrtgrq/Net-Telnet-3.02.tar.gz0000644000175300017510000007434213057016061020321 0ustar oetikeroep+09Net-Telnet-3.02.tarmt7v<^ozHju9T*JU%u2.ԇ r/~;;O·;OзT8yRUwg`&YD gd}利Y3RJ)KwpPy{Oo=㏢sYte8Ň\)W7Q/\߄^,rTC]=klr?yPC֫Vn׹2@,F총^猀c|̀Y;XYiş<%NOoUK^ܙ͏ٱ߮TůU^6P 6X0^<Fy"EO@,ZZ"dkjoF  ׇ"Y$ET2 4m\|C;O0`)"j=:P6"0@Drn,4^FKς74a=_F";y,\c/6*Ņ%+`rH"fr6NyCrW.!<q>rcWx34r\oOE ZGd#7 +¡tArRSʝ6䧹h :Ój:l ?`.x,ɄO1E\xrY0 uaisG=F0.B?qPBݹWq="FΠ!bNIp#@a>,b4Ü#翳'@qGD‚h!, PY\1qUL*fKS ( gfm8O=9 Pq 0%QzNPfXB$`H,"Dg9"(z[bh00#@3/#JKmy-f5qc\?v=5g NtF ,r^¸ٌl g;'F]4F;&" :x ,p()VWɗ47bĜMꠑ3$ H,` ]| qM|nM="(a0ԯ%m^TMB1 "@׿aevWy!3 7 ѩw)EPoIzpYbH'\3BkHLqmaqgB׮V?P,,Rڋ-o[|܍͇%eFdS&(rIZa~Nylh0 3Pه]wez5,7cr`2K8]eDSaG`aaFʃ.;}NG.b. r)+Ǚ(L*ˊts#i' 4.z@DnP Tf8 Fu3$K 7ٰEQ-,Ekc`GQ{$ݖQaGq9)ʸ]GV_Bb@`ܸ ;i24`]2xj'h 7_f?L5/YXn4|*{{[~v~?3;'>~QԂM]LbBіio QH@0;\aCA!nPk7G&X@,$UC,2`@0 aa7h:׫!-6ۗ*iCʀ9pT!0l7FtC7tG\F~ L=! . ,- Bm¢œn7p:rq6:jMEN$j66ԯs-dVN2խ{o~jw Dktzsy7Ωi~׮ѝ.jwBj^vsՏ}>gdtPY2vHFtZs7 jrONO멑SSSm_k6΋Ϋ}n87LcUbèn2߮:53/G2viX g߬1݃JyHƾVYI6u꼱&l7:uzߵ(uZu~u <iZuLڵ޻sfydm*Lϛ% 3{/ 6%D`pSZS  t ;!Fz{՗j: ylgoa`NK}w7z7Uؽzz IvhٺAæ߁;:z4zuPzjffnFOfOH L`O\8^yiiTkZ_#@FP6 #BC VXސL0eDU/+5hҶ|Ho/в]O8L:hquGqK=M2݉sdZs㉃C`xKt||xbFO BiKlHU䌶 af ;eh1c#Y2&X*3ȓ]dXfnt)q]2IJOe*U2 ;t"2s?dW俜/fu'[8Z%JTpY~a1! ,5[K$?Dʜ QXjcD )D{ ytPM)TSdy%dY_m]dz9rw6Y,xeC! Ru HkCω>x)1"1dS-oɢQSOrjEє֎EEKFj0&i:2KΞFz!:`x>Z|Mx C(EmiAA?㢸d ~ -ӺD9'KH> ҆XX(m<]? gxX0/?WGoGz::V@&k%R.a tƮKl:VkЬ$|Xzc=  ;Q헰u9֦e`2H]F[KKԎm}u= NkV;7C]?LǸaɋ\FRuXd@. kPm)7\E yd";^%$6$P EJ [mKfOF1^n]%Loiɧ2MhXK갎0&rxItma4>G/KK7nh-cb/#|%BfK\J9GM$ɛ8N-1V dmW n ^lo@<$?)BȭvSy<:I2 :v&>BٚjJ1YS4$L1Rw[ZJGRxIOb58 ڗD%#W(Z̸|rBU$XBq/m (MA>EI]h X (f?0J\ oZ ~Ԙ2Օ]DX҇<9Hj0Ba)FV*Ye2S_ 5k,ɐqqFI2LbTHFa"JJ{ =$u_^1]^k[kk[|q[pz8ʐ֠pk+(\[1LǓS3o80u#<*CJ :$bW>f n`v;!`* a! s~[6{0p/NU@IY.k>x4.*/yz_^Rr8 D|3 yz_ml7Q5EuOl):\I~OyE<5/ĩޖ?V>@1/x-!(U&^{лwÝ EX!. *VtCH˵Gش=ߋ=X?fQbQ}s?;?$\uvU=(9%䫺wX޷q%οOQHD3~Ƙ$ܱ /p V-Ygz&-jM+(\)ͪKS Z(b9^ & ʭEbȶ}{۸yEC&+S&JAi$& `#GQOHg>jZeNL.yLRa﷚-3214Gjv) uoBW;4h#`93PTGpOe4G㱹OIMxZ CP}z5oDm[kP3P>j%?]iάՊ!wߏ)&#Xk$I$Jk VaA?qe'}cSnA7}t ]?Ȅd̕z+ %:nzFۙtpfѣA{"M} == G2C+q!iqNNMq +X?ZK֦Git=,fM-2I|>s%?(L JFE |'&<>^ƨ?7^>%EU%_VklmВ=BΝ"75GhKb;}hBwUSW05z @`زy< n: e&`*!2U(P-\CZ EK"p[gL;=:XQ<ŝѽ+(0y Dynb^m7'"\Ȧ/oɿ#!CNǤh(JZ8\s b0 t5e>ƵuRnC=|D.}B~[߸݄ T9N$nrXxoxYk;0m}]5Y4sfzƷہ MVD"-B7i ~va@};GK/nuYC$+7Qx Gkw?G,T& Zx< zB#HY&R~NgpdсC*.6L8`6SfutK\3Bm&zjr]Y:HӸ=ZaKfp@@;.xc*yqܣOG?YkS|t%n᭎hs]  f&jb34bi 1?ߏ`z\Y` BH)y)%F#^;94"p\sMd}w侘^k emi@,pVJmSH~<c\^ toK7Ϋ&h:f7QGO/zo3쑉u޴fXq]zei.|߿6TG w:s:['Ľ;r t{dH60+ I&Tz-Aɹn}K"B(~U6u<󷓡 (<(%k9'ra}n0yh߸:OKX ?mrMn5Ӌ+b@ly/⠳\7 .7oZ mnI6!)z+v;e p_ve/cB{^ʯܶܔ#rLz,pMm' ]5Y2%V =?^x +~%;%2gɂSo<3hQwwں\gi7y[, f0Q s=htH\y B&<_{r7A3qцV^aI5{Α çW|,m񾄽ܺbb ?i-198;nl\IJ&&JGv"8pNA9hǒ67Db8 8P҆=Aӈ{и b%._|x`_Z>A?mkް, 6>?]@Ɲ`naUU{k9w `ktlܫeeT-mvL 5Cki%[[D>  q:m !R96ꀳ5z8ኼU5iSo(&1N]ʠ),/0kDXjBWC#YH4+\^r% yRc=Ewl,8(Qˬ'6wo|c>AF3k1OO ,Lr'V1B[pD;S,¢u>#iqCH\,B6 |\<:iI_iRTOXb>D(mEL] >j,)3 `?zҝ⥾bbh2Pi+3j\\2W#yi8S`, >f %/'i|/Kj3H.g&vor fAR|k$%Rd\^S#yW0k/djܗ(7B5+XJ)+Ta'}/7*8R:Fmk:n"Q|W-kֹ|ؖ\5=(6ʟՀT_6&K`؅)VQOٷ\ ݾG=0 ۃx 8jZHA!/HsTh@|&a/dd;欼]ʙ<4~Áswe2 \ 34qXn MGCǤBɢ~OC@v YV@_V2%g )FeA?Iq5țSQI T@"Ȱ8`H*㬑a5S[/HT$ԑIWڣkA,~{p/{S`k o 3K o٥5ZZvZ }JG/$P̃҄%4pJBZh'O!nikBI%_c>o 9w#hgnϞnB|oڐ.!-Ƨ*}GeW1d5:@):)!&oos ѹ3Cpsak1 79~t&/)r9F;xMC,4HmiV5EU#8yZMrS\}6[ uTc5BqB/Z&kgEjCqc6kpζ`]vJ9@ (~HC8-1AnO݀ 6۳ 3Goz"$qE'mΥH3༱)wƏids=bGe0[2I yZ2Tis?FHxfE- =\o,#1(rC+3@Nop2N˔T¼۝X3~3~ S%y2fBZt ,+4(7 W:Gq6FA(1RQz``F˹*"WphrNzl( 6I-2U@;VϏElk& raNMo(=@ wߣ.bLTˬS025ЈkH{.&8n4҇rjO1pi_+2L>A'W(ɿʇ+1Jg-<׺~3/yl?V@k`nYd:~Zp1ZU IX q]H&G[2s<>jB9lɘDu"^XCq ѼnL!a,XBX{ ^k>oM;3vQNē)g gBւ]3/Sp2ZEU[ޝ$@:t .$BߥP,d• N cLTH([j01Xs7\XtN'Hu B~<+A79(wsipw+x| |, (Ou?=cY\vM|VǕ$<);Ժ(wU\\ǯb AHCK?9a ֊+jՂW`+>Yk K{]6E{cXKZd%ܦ̔t𖑵^MM\݉d%3S Բ&U@!Ga(0áC0tCjR Nn)G3K~zjm9vJi\-{Ȕ n 3WC+,봜{J3^S<ԭ(=-dpWAȡ3mR B{>"`ڊ]V59\OG,fȧۛ= n+Da|3A!M6KyQ;+RuY6(@n6Kנ6>#x j71l ȈƊM퀮\oZ6F:ճgHWR!Ȭv|ejbB $xo4-<CEOx u~K c WIG߫Py[7 "DinV`I ʔEi x,Aґt w?:_lZ@p/rUlG1A=j"'Gw2$ V ӆog^"4޾NdRxio{>W@1Ke}rA*D Jzu:›Ѐqjbl)L#_/ez~RaHb4\4(6{wZd/G^wu6֮h7h x#,Npjr5`tsݦ` _](-c482rĆb1(l=iؓ@,O7Zp5N4Vz%  !LW1S1}eDV(E}M%Y2ݕEuLmi}Э%6GJ",Y: m+kYT2D^RI)HێZ ME»d"_rTr6GD| ep(ZvhgdsqN~1nf6pBUd0ۿFkՕgU3m9 ՕsF!(ewo~E%i]GN5Eױci^$ !!Ɩ dF\Rm|o5Qeո jfBt0.ʶ8kP<`o,-ݢ<0 /67&N} B ';Dn)򏓌#B?" VQ^tM[0m(B \ݶ_Yݶ}' i RbwaJ%)P|z3]Yۼ~~ʛ{vVtVT )&rw;;aW !@HA^M,-F/nCoB̽j+iJ/Bq|hM|)gkΩ0 p7 tqa'{CA%# 3q_c4_K8k{~в'gG<6A33H <9KPp@:/Y) ~ݶGփݻ})usΛi'ڗ,Xgu-508h)1^pI,w[ ܦz,:Rص36t=YSo&o%"'`N[y_N,yCr (TW)b9S!>K~q,iVwb;w޲EXJ^M߻}c$'}4~ xG[#,)__ba$N4f] ۍn'!Fya45⢄ĉflѣr_ߪR[Fae`L#x{5GjBkܲAF3c*||A32G%o)mt1o'9hNc05ta)rJ\+*lq[l7;3Cx@lh𗴝TF'聖 0~Axi'(Rk@R0ZSZa{Dl@&H=IIGU.xLUP߄F4ov ,]'5C{#ZS&d~cNOؿ"Cf3|߈c a甪V:jzP3gk=_k^TxF)kZqqO=שLьǾ.+Xߪ{eY5|#1'5. Bl a9xQY2`ydP`$W^N߯-;6MJ}IU)i*$YGG8GN\dn z Usܗa@ދ_Ws3X`wЍZقꇬrSoK,ŝz6jX3#jT5$ӳpF̸F`K\VQerW38[0 'VׇTL r, ln†y?M8a:O cVkW.+.]ǽBqVaFN(:jW۴Ү 5ԌdYr,[:ͯt-^]e~J.-_|ԟ8zQX RbsaZ@%1gtI1jfL±h7cfDŽ 9Xg{.8~PpiueIYʰ@_>< <#xWjmy]w <&PA8tV7:mt_.G+v`Ѵf%Q\ nĠ7=s{9kee! /!@vԊjn3:rpzEpy.M|@RH r:[t&UZe7zOT{#Heilb #J٧Wưp V"ܒƒ;wl+s_٦/}/E)zU8kb.z) 5}xJ dtbNo;Euz]xq"r4mR!!DouCk⸩ >}uOL*lm,.D%voDɜ{ 0,1m޾K]p1fHN"7g [YA+B?[Y )+:0o{`b8M2Q'P??&'п Pi8Azߋdvea7 -P5 mv |Įi(v_.r](H/Gɠ jp&6^,ա&ᤠܬ5w0vyyCOdХǵpC~7fO8nJxi' omrżLK m7(C@sdk:~~hz0nC}/Nm#9IjR؆GM#Qv*瀴~vM{arf"?|`Jk`/93_gylA˧˯kˎRQiVh ?A ?0%'|XTz%lLݼ~cl1~G)_߶Y/j`wNYcr|X~ ׶ó_U3#-!xn1"=}tG>5m0UܯY`YQrQ\!}A<{/>6Nߏ;$"I'CTS`Ǭ@8Ey1UVCGAAW#p6OO)e䜁_Q6n"m /+Ѱ1ZܿM)|,z n/@:asd8?8;;-`CSx^v~zK7Ý{x5%x B9<)_J]Gkouww9Kr"VG8N O6E:>{(evQڤClghR{z#>.)fI41mDd^i9ܥx~E]-,N4";gb1|`EוbT@e) D BǼrʚ] яSʖbbR, Ga atN08O\n | d_34 4DP&{%*\(X_En~BA%F :3]"$)XXCĕ%~y~/MM560֣n{/.1F:Xj1ZsX6`/cNhbōdUDg mF`$ݿn??x{p8W$S| k?A3* #@awY9|p_. <o-fNa40Jϐ&}&lQwv rz2ï"pɌܞEMtī wEVi ]ψC$NjI(/,gH! 3#LQ6 f't+1νG2DDNkU;d _D$=̝D 1"V>@]Ҿʖܓ"Z Ty a3y(-$. `9t[dFwOQ\?+x+T&SXA%]PW}"/ xGGG)Qr@-MJu„pd wOi,QBŬ.xqoQ8H:4ʸ<@`ǪZ s&Ql(vnkI!$Ṡ2d~WU<{EVCll$ZϦC@EM/PbƬXabE ]V>Qn+S)1Ui>~G08O KvUd&}h9(68A {8ځ8W A"#6j-i60A*WƫonPwѷ ?Kќ#DgvmSWtdE1HV=GYNii"/z wLmoKzS! rd 'X454J' 5 ,X]׵ys~. QO]y[mAD[8fD Y*꠽'xT/7jKUGD;?XӉj_k%jE_يI+%|ی݈tfMbŧE }{"׈q%"#Ur|*]YG,*7@'-_,)\(j3qxh8AE?%Wvbج32GDxJGk6&/qCt곥8?B :IǗșX>HLn&gߕJ\K !L}H;jH`k--˿42jg3F1)|*͂;[)(/)-Om?b+<^>,4}|!̊_B%8g-:(gRB9ΠiKJߦ0ta?"32jFO;Kec}^@@g~5 š~F^U%H腋l#@q{T1^5t>UUU'ށr/#!]q>XJi1C@_bv$e{ʍؓ9S&kqn0YG gƺ U!NAlsɹh6Jj8n<땈CY͕V ɛk 9Ca %i鎇'Zˋ(!gL5+սZ*Pa{jU{؅Ef&qiG;1aZ2',5PYNe2'­N}Q哋 !#Pख़qT c+Di+ XL1획> N}!fpoV$2;\3@M8Ykx>GhG[ R;  **k_aAߋI´јXL (+!wI̗"ԝw8`0&e19O'1%>Za^Gt`"'Ez:3/L;VO.s&NZL=5~_q&֫veDIKwB 亪̳~-\OOyC;#8o1"; ye#b#*D2pK(Z"Ys*IA+A+ ؞1)"Pt3L! z\E'8+n))1oxXAD5؛U$èퟁWrk 2br2ePdcf* MG('5s{.1tZ[@+"iЕ,6ؐ8Z=v]y1 ~M@$|ԙDL*3z.Q\ye+QKPC4g8 (q(Ez )Mv/F`*AJYx0"K',BeIѩ} Mi!|L")Pk;F܆ұ .̬^9lؽ=}ьSڙ T{FYˏA\R9f4-QjGqr^Uf<1/`Aw])*8~ /sHFG2=Ӕ4:Б݉y.~X QǢ)^".l" e񃘜ej7G| h>HYP W! xdC=VK*%q.$ B}F6ADZ"ͳFℋæ!&82ԇcCV3eN;t`Y@I"q"Lo=bhTc_,7[p<QaB~oHy)1B֎1Ǹ Gyc&-cv*ҏGB;(zQF;PVp(0z.-"NV r_>9P\웴. 'QDSg ll x}\;APc+a.$()0'c'$'Ar{D/ +n&DW6uhr%ŁI4nz?PQ%IV~z,8L 톢KhYGOz_p;CsӐbؕ| '"[p^XF^,kUi~XBkI{5HMCR>JI aDqi v$f. }ƐEU_w0#qfkbz>خyeh2-v9Ɣ9SRxmܱp8:;G6 x +)q䝠?,#[r¦nCîqQǕ c zdÿ5E$7{gxXKH|xP]dTF-kxtak(a$>lAe܎2"$ 3ȡFbA-Fql;$u3_c VIm4xTy LLֺOD0}m]{V! a^~4C ׅ8:Wf8Q%Iҙ_}H3ࠜApfLhk4۹zyi5Zĭ#^֧\c*`~-u8mkȶ^JkLA~ 2k&Æsx }Bצ$j'WUw$Z)w*u`gF՝NF YJ]gӦgMR:EAGraĿ~If YQ__+.,$?30+Xʓk(fnB)`u⒦)5%;*/-f} 6NP#YW +㇮êa^V钕:|nwd[boHK0W$d>)rԇQ\Ѹohr 7T^c|z "#$$=.ɻnHlI&Ho8z{wJZZdY!ALj&FeDYVpje*Lm52lٱ8htܸ.(HGI>ӳ!Fss|>S+E#sj4f)juYNKqrx\c8CtyS2 x)E|2NTHIS؆CcDz|z ņzUCjifFV?^ȥg5 L1(m)7e:qꅡIKicJϬ~vudzHT>o)xt%޵*j roN;NQ£8Wvk[iwOR8I09U(٥ o[vOF]$Śbd'ʅM~4i` \pՆ)AU`D%G\| NA[gƣyv"gux㵓k`!M.7 ." #O* CMϡ^H#-p١d<:"'xy_#mU+RUNH=m5RYY"qdQ ,T 2@E;9u2էҚ$'>:WX#{bι ?]emjs#1ĄX1^ui^ '/hV)'<ЭN1bǹ޺E^ RX(3݋R\fb+v7];|ɎGְ3?Bzذ֡LmiC|zuGMXӋSNcOUe=%DIR^GTZlĻ>bwVUF_ kyʃ[BudėRkRJ iMKrBEE$݊(G;@aK ###tn j u5| u)O~kEm7yTYԛsA4%beB*!n<=쭐+ϡBOR $|F5N"MaΚLQ(BWrk.u( +(/ {,٧«,A)^z%Ub`<+^"Xԧ!bn5njL9:=Vs̮`-I1O9.]j/4V+'s4gyκ73翖(ɘX)%z%y OdUoKꧽM!4 Qή,!cSl9g Q-g: keTRV~ej܇js}!7 iEXSVpk `u)lˣCY41>eTEWG/t b͹/ypKs$ѧY/yGb|dWևՏR{m]c*/Ǻuy7{ ދh Kqؗ1 src,vt&)6ˠb@lj嵃'vfe#Km[R3?o]*ju-.,)d3FF yۭ'wfOƓw7%_q'_˛*Dy&oަ*8ld tUXf':Pڌ,1T-=GR>uKZX)V/yOCfԩf4yFm\Q/̧5 opl?ͳ]?V?kXԢ3wPr4)4'QZ`rqBZ`t |]&kt+6Ӣ[YI9q:fVbd\d[D9| cV\rʻ,|K.>'@$ԆJAd&{V+D"I(WJf#O-\Ӛ>S:JiɵK^EdL ?uRe}5b& 9!RƬ`.0"hD_E!sf)q6v aIr6qk7̋"c c-1];KڥrjJαKk}dIĸ@NJfNBQ|ucҍ}HH,{hj'W :IT<M;\^ˬ'\ZTӺKSKՍ?ۓ,MJ\5<]hDtZI<^W1%pk9Rc5uKJRmD )EO~$E](Vh-$TB`#<XϯvC=vTZdWv}q1 JGgT0%ƣM$e Q>j*pz(VިƊ[~Z:㿞Ki[y /I@ZO`Y}$Dz*8v<`6e'5$^K(<"zok1DD!|>JؕT7Yg]xBaQTˉ'|S[N _<ګ\XYq9rz.K8_iLísR͆``bC]_* F qN\MɫV 7_elEZ:_ǯgb3I5:ϴR;Cr/Y?۪ERi$;C穙}Y?ᓗO/5[s`xG&`7_'F@5Ln YK>_C᬴@"ȪeMdUHEM4\GT4ηĥ{rK1a ݵcͱ-Kch^m3ul/!ot^ւv(NZcL&CSFDT5'ѶW?z\;D ef邛nKw&3Jə}ޙ_JM(}دYZ4g^Iܥ'v@\+_bDPwep=uʺqV 'ȊrYDӔo]i IEN<׏Rģ䒅|#/s?Ovdgn0=B]@t# СU?Ĥ]MUc;2rQW҈-z{ 1~Z" dnW+q.`0ɳx_&e|E}@B XH{$n؎=wyUV7ך i3l߲*S]C6y[2ș.Mz.W\/.nPzU/x1X%Uifa. -T[ ~Gˌz VEGr*]qbh1^f/ %\pq-!w_Q`v1R}R&Z:{rU=PG @: K7חKL nX ?sCrA!W^ڝHb8"b5J==uO, 1x\|'x/Sf_Xo=b-3.? (o;{OGfpx5*ӽvO?QAIFJOP/=J5;ց(:J1[(;AS6i DjWj͔2wf,VXmW?{w7ޅxmW~͵;-;)՟ ^85gĂO17|sݥ?{nټ yޝ?ko ?WU4GI@к@|1:N."b99.N[ '")޶Y7%ض;M {;C`:CTKpr!}{> Qk]v,۶uPӧ'_Zߥ%ڣE`͗pv<)z]db[[?e/<ӬVJPx$`I&g.ӭ5?MFAgIE<0Г^=pJ&(&'_[ ,FCaԭ-aGmst҅Q(OUy|1o޻oƝ;7K4©!bDÞ^.[zMe>6W]蟏)bO㕚ڤX{l&&dV)EHQGѨτe:">:"k{>ɁX ICrHa8?C!EΊ]wƧ΀`y_u%\4aS2#Zn?#0Lb9]MQt)$aJ]̻@IO" _;' H'"D)d23׀nf0 wNh4#hnvLFaۣ9N,g{{ v):~2|}Z\pW]#B t0)d!AٺN>:[=;=윏/̃QJ.ktS|LąkXM~YH->%|g<^W"l_|h^lrAkB\U(Yf͐>vX=^HBRQeehi 0[oǩ\ e, nwһ.%-18mtTK":PryQ Fy`E><'#[2T93t`WU̯[גEgW%|ra/-W9O.FqdG?/xm|eLQɽߨ9̿&҈{%c#LՈI*1" @_A)+S4)C09Ri炩A~~d]TsVdTrF&LQSآ֯E(J̡/ V)(m{:kΤerDs2wAg!J_ųҏcfal?=aWH ZU9GoqWERC0b'hQ Ō2QV~jYAڢ+K1Q* d@RkPƼSrj/&וėg/eĔ8e)%.)vڶg1kZgr.F25Q2bΓ%?8`' TWЄX+)Y 8ExOO[⨄a>8 6#gūG*ҏ&'?Ea٥M5NhuTY65< )>wǴxZ9V|X !w{P|p1L뉱:\2^b1 Ws*M4ss,3""@bJْ/S1G(kUf)ط6*"x5%c6aAOKT߉GϞ!lɣ¼ͧ{/KV~4to w0NMTrTlH}t7@{frLJr,Ib˄? 'LRkU;4~En49$DE"Wp~= 9000 You should see the result from the repquota utility. The MRTG side is following: mrtgrq I use this script to monitor the disk-space used by e-mail users on MailServer ( I am using Qmail ). Usage is very simple: - Put in your crontab file a line which have to be run every ten (10) minute or any other time interval you want (but you have to edit, according with this new value, 'make-mrtg.cfg.awk' file). I am using Linux RedHat 6.2 and in my /etc/cron.d I put a file named 'net-hosts' with the following structure: ################################## # /etc/cron.d/net-hosts -rw-r--r-- # */10 * * * * root /usr/local/mrtg/contrib/mrtgrq/mrtgrq # # EOF ################################## - Restart your cron daemon... and wait To install, first edit the variables from both 'make-mrtg.cfg.awk' and 'mrtgrq' files as needed. I found it easier to have these defined rather than hardcoded due to differences between code interpretations. You don't have to insert any other target in your own mrtg.cfg file that you already have, because this script is launched by the cron daemon. make-mrtg.cfg.awk This is the core of the entire task. Here I make 'mrtg-awk.cfg' file using the output of 'getreport.pl' from a temporary file 'mrtgrq-temp.tmp' which finally will be erased. After doing this, internaly is lauched 'mrtg' executable for mrtgrq's mrtg.cfg file (named 'mrtg-awk.cfg'). You could use 'indexmaker' script provided with MRTG for doing an index.html file (see an example in 'mrtgrq'). Be aware ! You have to place icons (MRTG) and image files (grnball.gif, redball.gif, cubprev.gif) in the same location. You also have to place 'mrtgrq.css' into declared location inside that AWK script file. getreport.pl This script in Perl requires Net::Telnet module instaled. Its only task is to read the client on port 9000 (or other you want) and print this output. This output is redirected into a temporary file which will be the input for the AWK script. ---------- Direct questions or suggestions to me. Have fun! -Adrian Turcu mrtg-2.17.10/contrib/mrtgrq/getreport.pl0000755000175300017510000000140513057016061017174 0ustar oetikeroep#!/usr/bin/perl # This script is used to establish a TCP connection with a host to get the # report of disk-space quota provided by repquota utility. # # use: ./getreport.pl # # By Steven Micallef on the 24/4/1999. # Modified by Adrian Turcu on 18/9/2000. use Net::Telnet (); $hostname = $ARGV[0]; $port = $ARGV[1]; # If you've changed the port showdisk.pl runs on, change it here too. #$port = 9047; $i = 0; if ($hostname eq "" || $port eq "" ) { print "Usage: $0 \n"; exit; } $t = new Net::Telnet ( Host => $hostname, Port => $port); $t->open("$hostname"); do { $data = $t->getline(Timeout => 40); print $data; } while ( $data ); mrtg-2.17.10/contrib/mrtgrq/mrtgrq0000755000175300017510000000247613057016061016074 0ustar oetikeroep#!/bin/sh ## ## OUTPUT_FILE has to have the same path with WorkDir value setted in the make-mrtg.cfg.awk file ## MRTGRQ_CFG has to be the same file declared in the make-mrtg.cfg.awk file ## AWK_EXE is awk executable with full path ## MRTGRQ_AWK_FILE is the AWK file which will generate the config file in MRTG format ( core ) ## AWK_EXE="/bin/awk" MRTGRQ_AWK_FILE="/usr/local/mrtg/contrib/mrtgrq/make-mrtg.cfg.awk" MRTGRQ_PATH="/usr/local/mrtg/contrib/mrtgrq" MRTGRQ_CONFIG="/usr/local/mrtg/contrib/mrtgrq/mrtg-awk.cfg" MRTGRQ_TEMP="/usr/local/mrtg/contrib/mrtgrq/mrtgrq-temp.tmp" MRTGRQ_TELNET_HOST="your.email.server" MRTGRQ_TELNET_PORT="9000" ## rm -f $MRTGRQ_CONFIG $MRTGRQ_PATH/getreport.pl $MRTGRQ_TELNET_HOST $MRTGRQ_TELNET_PORT > $MRTGRQ_TEMP /bin/cat $MRTGRQ_TEMP | $AWK_EXE -f $MRTGRQ_AWK_FILE rm -f $MRTGRQ_TEMP ## ## ##################################################################################################### ## Index Maker in MRTG Style ############################ # # OUTPUT_FILE="/home/httpd/html/mrtg/mrtgrq/index.html" # MRTGRQ_CFG="/usr/local/mrtg/contrib/mrtgrq/mrtg-awk.cfg" # export OUTPUT_FILE MRTGRQ_CFG # # /usr/local/mrtg/indexmaker -b '#ffffff' -1 -t 'Diskspace Quota' -o $OUTPUT_FILE $MRTGRQ_CFG # ###################################################################################################### mrtg-2.17.10/contrib/ciscoindex/0000755000175300017510000000000013057016061015435 5ustar oetikeroepmrtg-2.17.10/contrib/ciscoindex/ciscoindex.pl0000644000175300017510000001312213057016061020121 0ustar oetikeroep# ciscoindex.pl ############################################################################### # Written 6/14/1999 by Tim Cimarusti tim@cimware.com # # This PERL script will read in the MRTG config file and a Cisco router # config file (created by the "write network" command) and create a HTML # index for the interfaces that corresponds with MRTG. # It sorts the output by interface type and adds descriptions, # IP addresses, DLCI numbers, and bandwidth to the HTML. # ############################################################################### # usage : ciscoindex.pl # # Note: The HTML document will be named .html # where is whatever is in the router config. # ############################################################################### # # Revised 2/5/2001 - Now works with version 2.9.7 of MRTG # ############################################################################### $MRTGCFG = $ARGV[0]; $CiscoCFG = $ARGV[1]; &ProcessMRTGFile; &ProcessCiscoFile; &PrintHTML; exit(0); # # Read the MRTG config file to find out the interfaces. # sub ProcessMRTGFile { open (MRTGFile, $MRTGCFG ) || die "Can't find MRTG config file. $!\n"; while() { chomp; if ($_ =~ /SetEnv/) { @a=split " ", $_; if ($a[0] eq "#") { next; } # Skip commented interfaces $intf[$x]=substr($a[2],16,-1); # Find the Interface name @c=split "]", substr($a[0],7); # Find the name of the mrtg html page $num[$x]=$c[0]; $x++; } } close MRTGFile; } # # Read down the Cisco Router config file to find out info about each interface. # sub ProcessCiscoFile { open (CiscoFile, $CiscoCFG ) || die "Can't find Cisco config file. $!\n"; while() { chomp; if ($_ =~ /hostname /) { $hostname = substr(lc,9); next;} if ($_ eq "no ip address") { next; } if ($_ eq "!") { $found="n"; } if ($_ =~ /interface /) { @x=split " ", $_; for ($i=0; $i <= $#num; $i++) { if ($x[1] eq $intf[$i]) { $found = "y"; last;} } } if ($found eq "y") { if ($_ =~ /description/) { $description[$i] = substr($_,13); } if ($_ =~ /bandwidth/) { @x=split " ", $_; $bandwidth[$i] = $x[1]; } if ($_ =~ /interface-dlci/) { @x=split " ", $_; $dlci[$i] = $x[2]; } if ($_ =~ /ip address/) { @x=split " ", $_; $ipaddress[$i] = $x[2]; } } } close CiscoFile; } # # Create a HTML document. # sub PrintHTML { # Change this to whatever directory you use for serving up the files $mrtgdir="/mrtg/$hostname/"; $HTMLOut = $hostname.".html"; open (HTMLFile, ">$HTMLOut") || die "Couldn't create HTMLOUT file. $!\n"; # use binmode on UNIX servers binmode HTMLFile; print HTMLFile "\n"; print HTMLFile "\n"; print HTMLFile "".$hostname.": Summary of today's activity\n"; print HTMLFile "\n"; print HTMLFile "\n"; print HTMLFile "

      ".$hostname."

      \n"; print HTMLFile "
      \n\n"; # print HTMLFile "CPU
      \n"; # print HTMLFile "
      \n"; # print HTMLFile " \n"; # print HTMLFile "

      \n\n"; print HTMLFile "\n"; # I like to sort my interfaces. for ($i=0; $i <= $#num; $i++) { if (substr($intf[$i],0,4) eq "Fddi") { &PrintRecord; } } for ($i=0; $i <= $#num; $i++) { if (substr($intf[$i],0,12) eq "FastEthernet") { &PrintRecord; } } for ($i=0; $i <= $#num; $i++) { if (substr($intf[$i],0,8) eq "Ethernet") { &PrintRecord; } } for ($i=0; $i <= $#num; $i++) { if (substr($intf[$i],0,9) eq "TokenRing") { &PrintRecord; } } for ($i=0; $i <= $#num; $i++) { if (substr($intf[$i],0,7) eq "Serial0") { &PrintRecord; } } for ($i=0; $i <= $#num; $i++) { if (substr($intf[$i],0,7) eq "Serial1") { &PrintRecord; } } for ($i=0; $i <= $#num; $i++) { if (substr($intf[$i],0,7) eq "Serial2") { &PrintRecord; } } for ($i=0; $i <= $#num; $i++) { if (substr($intf[$i],0,7) eq "Serial3") { &PrintRecord; } } for ($i=0; $i <= $#num; $i++) { if (substr($intf[$i],0,7) eq "Serial4") { &PrintRecord; } } for ($i=0; $i <= $#num; $i++) { if (substr($intf[$i],0,7) eq "Serial5") { &PrintRecord; } } for ($i=0; $i <= $#num; $i++) { if (substr($intf[$i],0,7) eq "Serial6") { &PrintRecord; } } for ($i=0; $i <= $#num; $i++) { if (substr($intf[$i],0,7) eq "Serial7") { &PrintRecord; } } for ($i=0; $i <= $#num; $i++) { if (substr($intf[$i],0,7) eq "Serial8") { &PrintRecord; } } for ($i=0; $i <= $#num; $i++) { if (substr($intf[$i],0,7) eq "Serial9") { &PrintRecord; } } print HTMLFile "\n"; print HTMLFile "\n"; close (HTMLOut); } # Print section for each record. sub PrintRecord { print HTMLFile "".$intf[$i]."
      \n"; print HTMLFile "
      \n"; if ($description[$i] ne "") { print HTMLFile " Description : ".$description[$i]."
      \n"; } if ($ipaddress[$i] ne "") { print HTMLFile " IP Address : ".$ipaddress[$i]."
      \n"; } if ($bandwidth[$i] ne "") { print HTMLFile " Bandwidth : ".$bandwidth[$i]."
      \n"; } if ($dlci[$i] ne "") { print HTMLFile " DLCI : ".$dlci[$i]."
      \n"; } print HTMLFile " \n"; print HTMLFile "

      \n\n"; print HTMLFile "\n"; } mrtg-2.17.10/contrib/ciscoindex/README0000644000175300017510000000106013057016061016312 0ustar oetikeroep# # ciscoindex.pl # # Written 1/20/99 by Tim Cimarusti # # This PERL script will read in the a Cisco router config file # created by the "write network" command and create a HTML index # for it's interfaces that corresponds with MRTG. # It sorts the output by interface type and adds descriptions, # IP addresses, DLCI numbers, and bandwidth to the HTML. # # usage : ciscoindex.pl # # Note: The HTML document will be named .html # where is whatever is in the router config. # # Feedback : cimarust@mercernet.com # mrtg-2.17.10/contrib/whodo/0000755000175300017510000000000013057016062014426 5ustar oetikeroepmrtg-2.17.10/contrib/whodo/README0000644000175300017510000001336113057016062015312 0ustar oetikeroepWHODO This is Whodo 1.11. Whodo is a set of Perl scripts to analyse IP accounting data from a cisco router. The stats for each traffic source are fed into mrtg. Whodo also generates pie graphs showing traffic split by source or destination. HOW TO 1. Put the scripts in the appropriate directories. There are 3 sets of files in whodo. (i) Whodo/gifgraph contains a perl module written by Martien Verbruggen. I've made some changes to it so it does what I need. However I haven't been able to contact Martien & get them included in his distribution. GIFgraph is used by pie.pl. You'll need to copy this to wherever you put your Perl modules. Note that gifgraph uses another module GD.pm. GD is available in/for the standard Perl distribution and ActivePerl. However if you use Perl for Win32, you are on your own. (ii) Whodo/wwwscripts contains 2 CGI script. Put them wherever your CGI scripts live. (iii) Whodo/* contains everything else. I keep this stuff under mrtg/contrib/whodo. You'll also need the module SNMP_Session. If you don't have it, get it from ftp://ftp.switch.ch/software/sources/network/snmp/perl/ 2. Start IP accounting on the router. If you don't know what you are doing here, tread carefully you can bring the router to its knees. The community string that you will supply in the next step, for the $HOST variable, must have READ-WRITE access to the router. COLLECT.PL clears the accounting list (SNMPSET) once the data is collected to not be double counted and surely to keep reduce the memory requirements on the router. To do this at the (config) prompt type : snmp-server community (your community name) RW. DO NOT do it to the community public, this will leave your router open to attack. 3. You'll need to customise some constants at the start of collect.pl. You'll need to change $HOST & $SOURCEDIR. $LOGPATH isn't relevant until step 6 but you should set it up now. $BIGBYTES you'll probably need to keep tweaking. Basically, any source that generates more than $BIGBYTES between polls will get its own MRTG graph for ever more. Sources that never generate this much traffic will be grouped together as Miscellaneous. $LOGPATH also occurs in pie.pl & makeanalyse.pl 4. You'll want to create a networks file such as the standard networks file found in C:\winnt\system32\drivers\etc or /etc/networks. Collect.pl scans the file including comments following a normal line of data. The file is used to map destination addresses to network names. Which makes the output (see step 6) much more user friendly. The file has a second function. If a trailing comment includes a / followed by a number, this is taken as the classless representation of the subnet mask size. If not, the network/subnet is assumed to be Class C. A sample networks file is included. 5. Set collect.pl up to run periodically. I run it every 30 minutes with something like: collect.pl -a c:\perl\mrtg\contrib\whodo\sources.cfg -n \ c:\winnt\system32\drivers\etc\networks mrtg c:\perl\mrtg\contrib\whodo\sources.cfg I've included a vestigial sources.cfg. You can use it to get you started. Collect.pl maintains the file automatically. You should now be getting mrtg graphs showing traffic generated by your traffic sources over time. Bask in it for a day. 6. collect.pl generates a new log/csv file every time it runs. By now you are probably up to your armpits in these files. I've included a script (summarise.pl) that I run every night to condense the day's log files into a single file. It doesn't need any arguments to run. However it does include a constant ($LOGPATH) that you'll need to change. Try running it. 7. So now you want to generate pie graphs breaking down traffic by source or destination? OK. You'll need to run makeanalyse.pl. It generates an HTML page that is used to generate the graphs. For example: perl c:\perl\mrtg\contrib\whodo\makeanalyse.pl >d:\www\analyse.html The page generated contains drop down lists containing the current sources and destinations. Since these will change over time, I run makeanalyse every night. 8. What's that? You want a more flexible way of mapping source addresses to text? You'd like to group multiple addresses under the same name? You want to use a name other than that in DNS? OK. Create a file with two columns the address and then name you want. In place of an address, you can use regular expressions. Thus the line 203.167.223.13[456] Exchange maps addresses 203.167.223.134, 203.167.223.135 and 203.167.223.136 to the name Exchange. Note that the character . has its literal meaning it is not a metacharacter. If a source address does not appear in the sources file, it will be looked up with a normal reverse lookup. If that fails, the address is used. A sample sources file is included. To make use of a sources file, change the command running collect.pl to something like: collect.pl -a c:\perl\mrtg\contrib\whodo\sources.cfg -n \ c:\winnt\system32\drivers\etc\networks-s c:\perl\mrtg\contrib\whodo\sources Mind you, if you'd had any sense you would have done this before step 5. VOODOO 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 of the License, 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 TOO Tobi has agreed to include this set of scripts in the mrtg distribution. So, if you make any improvements or bug fixes, please provide them to him. But please be aware that he can't support the scripts himself. Tony Farr 24/3/99 mrtg-2.17.10/contrib/whodo/sources0000644000175300017510000000023413057016062016033 0ustar oetikeroep203.167.223.13[456] Exchange 203.167.216.32 Exchange 203.167.216.(25|48|5[56]|199) PlOps_Monitoring 172 DFAT_Addresses 192.168.[23][0-9] Test_Nets mrtg-2.17.10/contrib/whodo/summarise.pl0000644000175300017510000000553413057016062016777 0ustar oetikeroep# summarise.pl # # Summarise some whodo log/csv files into a single file. The old files # are then deleted. # # Args are: # i path of input log/CSV files. If no arg is given, this defaults to # yesterday's files. # o path of output CSV file. If no arg is given, this defaults to # YYYYMMDD.csv where the date is the latest date in the input data. # # v1.0 11/11/98 Tony Farr # use Getopt::Std; use File::Basename; use strict; use vars qw/ $opt_i $opt_o /; # Directory for output logs/csv files. my $LOGPATH= "D:\\logs\\whodo\\"; my $progname = basename($0); my $usage= "Usage: $progname -i input_path -o output_file\n"; getopts('i:o:') || die $usage; my @flist= get_input_files($opt_i); if ( scalar(@flist) < 1 ) { die "$progname: No files to process!"; } my ($trafficref, $endtime, $duration)= get_traffic(@flist); if (! $opt_o) { ($_)= split(/ /, $endtime); my ($d,$m,$y) = split/\//; $opt_o= dirname($flist[0]) . "\\" . sprintf "%d%02d%02d.csv",$y,$m,$d; } print_stats($trafficref, $endtime, $duration, $opt_o); unlink @flist; exit 0; sub get_input_files { # Returns a list of input files to be processed my($path)= @_; if (! $path) { my $t = time() - 24*60*60; my ($mday,$mon,$year) = ( localtime($t) )[3..5]; $path= $LOGPATH . sprintf("%d%02d%02d-*.csv",$year+1900,$mon+1,$mday); } glob($path); } sub get_traffic { # Read the log files (specified in @_) & summarise into a hash my($fname, $lastf, $lasttime, $hr, $min, $sec, $duration, $src, $dst, $bytes, %traffic); foreach $fname (@_) { open(CSV, "< $fname") || warn "$progname: unable to open $fname; $!"; # First line is a header giving end time $_= || warn "$progname: $fname is empty\n"; chomp; $_= (split/,/)[1]; if ($fname gt $lastf) { $lastf= $fname; $lasttime= $_; } # Second line is a header giving period covered by this log $_= || die "$progname: $fname lacks second header line\n"; chomp; $_= (split/,/)[1]; ($hr, $min, $sec)= split/:/; $duration += $sec + 60 * ($min + 60*$hr); # The rest of the file has traffic for particular sources & destinations while () { ($src, $dst, $bytes)= split/,/; $traffic{$src}{$dst} += $bytes; } close(CSV); } return(\%traffic, $lasttime, $duration); } sub print_stats { # Print out the traffictab in csv format use integer; my ($trafficref, $endtime, $duration, $fname)= @_; open (CSVFILE,">$fname") || die "$progname: Could not open file $fname; $!\n"; print CSVFILE "End Time:,$endtime\n"; my $sec= $duration % 60; $_= ($duration - $sec) / 60; my $min= $_ % 60; my $hr= ($_ - $min) / 60; print CSVFILE "Duration:,$hr:$min:$sec\n"; foreach my $s (sort keys %$trafficref) { foreach my $d (sort keys %{$$trafficref{$s}}) { print CSVFILE "$s,$d,$$trafficref{$s}{$d}\n"; } } close(CSVFILE); } mrtg-2.17.10/contrib/whodo/networks0000644000175300017510000000103213057016062016221 0ustar oetikeroep# Networks # loopback 127 Sydney 203.167.218 # /23 Melbourne 203.167.220 Perth 203.167.221 # /25 Brisbane 203.167.222 # /26 CbrExportOffice 203.167.223.192 # /28 SAP 194.39.139 Almaty 172.20.197 Ankara 172.20.81 Auckland 172.20.53 Bangkok 172.20.225 Beijing 172.20.88 Brunei 172.20.56 Budapest 172.20.104.64 # /26 Buenos_Aires 172.20.209 Cairo 172.20.29 Dubai 172.20.16.128 # /25 Guangzhou 172.20.201 DfatInternal 172.16 # /14 DfatInternal 172.21 DfatInternal 172.22 # /15 NetworkLinks 192.168mrtg-2.17.10/contrib/whodo/sources.cfg0000644000175300017510000000114313057016062016571 0ustar oetikeroepWorkDir: D:\www\mrtg\whodo IconDir: /mrtg/ Interval: 30 Title[Miscellaneous]: Traffic from Miscellaneous PageTop[Miscellaneous]:

      Traffic from Miscellaneous

      MaxBytes[Miscellaneous]: 12500000 Options[Miscellaneous]: growright, bits, absolute, nopercent Colours[Miscellaneous]: w#ffffff,blue#0000e0,w#ffffff,r#ff0000 Target[Miscellaneous]: `perl -e "print \"0\n27945056\""` YLegend[Miscellaneous]: Bits per Second ShortLegend[Miscellaneous]: bps Legend1[Miscellaneous]: Legend2[Miscellaneous]: Traffic from Miscellaneous LegendI[Miscellaneous]: LegendO[Miscellaneous]:  Traffic: mrtg-2.17.10/contrib/whodo/GIFgraph/0000755000175300017510000000000013057016062016055 5ustar oetikeroepmrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/0000755000175300017510000000000013057016062017504 5ustar oetikeroepmrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/legend.pm0000644000175300017510000001322613057016062021304 0ustar oetikeroep#========================================================================== # Copyright (c) 1995-1998 Martien Verbruggen #-------------------------------------------------------------------------- # # Name: # GIFgraph::legend.pm # # $Id: legend.pm,v 1.0 1999/02/18 # #========================================================================== package GIFgraph::legend; use strict qw(vars refs subs); use GIFgraph; use GIFgraph::utils qw(:all); @GIFgraph::legend::ISA = qw( GIFgraph ); my %Defaults = ( # Size of the legend markers legend_marker_height => 8, legend_marker_width => 12, legend_spacing => 4, legend_placement => 'BC', # '[B][LCR]' ); { # PUBLIC sub plot_legend($) # GD::Image { my $s = shift; my $g = shift; $s->setup_legend(); $s->draw_legend($g); } sub set_legend(@) # List of legend keys { my $self = shift; $self->set( legend => [@_]); } sub set_legend_font($) # (font name) { my $self = shift; $self->{lgf} = shift; $self->set( lgfw => $self->{lgf}->width, lgfh => $self->{lgf}->height, ); } # PRIVATE # called on construction, by new # use inherited defaults sub initialise() { my $self = shift; $self->SUPER::initialise(); my $key; foreach $key (keys %Defaults) { $self->set( $key => $Defaults{$key} ); } $self->set_legend_font(GD::gdTinyFont); } # # Legend # sub setup_legend() { my $s = shift; return unless defined($s->{legend}); my $maxlen = 0; my $num = 0; # Save some variables $s->{r_margin_abs} = $s->{r_margin}; $s->{b_margin_abs} = $s->{b_margin}; my $legend; foreach $legend (@{$s->{legend}}) { if (defined($legend) and $legend ne "") { my $len = length($legend); $maxlen = ($maxlen > $len) ? $maxlen : $len; $num++; } } $s->{lg_num} = $num; # calculate the height and width of each element my $text_width = $maxlen * $s->{lgfw}; my $legend_height = _max($s->{lgfh}, $s->{legend_marker_height}); $s->{lg_el_width} = $text_width + $s->{legend_marker_width} + 3 * $s->{legend_spacing}; $s->{lg_el_height} = $legend_height + 2 * $s->{legend_spacing}; my ($lg_pos, $lg_align) = split(//, $s->{legend_placement}); if ($lg_pos eq 'R') { # Always work in one column $s->{lg_cols} = 1; $s->{lg_rows} = $num; # Just for completeness, might use this in later versions $s->{lg_x_size} = $s->{lg_cols} * $s->{lg_el_width}; $s->{lg_y_size} = $s->{lg_rows} * $s->{lg_el_height}; # Adjust the right margin for the rest of the graph $s->{r_margin} += $s->{lg_x_size}; # Set the x starting point $s->{lg_xs} = $s->{gifx} - $s->{r_margin}; # Set the y starting point, depending on alignment if ($lg_align eq 'T') { $s->{lg_ys} = $s->{t_margin}; } elsif ($lg_align eq 'B') { $s->{lg_ys} = $s->{gify} - $s->{b_margin} - $s->{lg_y_size}; } else # default 'C' { my $height = $s->{gify} - $s->{t_margin} - $s->{b_margin}; $s->{lg_ys} = int($s->{t_margin} + $height/2 - $s->{lg_y_size}/2) ; } } else # 'B' is the default { # What width can we use my $width = $s->{gifx} - $s->{l_margin} - $s->{r_margin}; (!defined($s->{lg_cols})) and $s->{lg_cols} = int($width/$s->{lg_el_width}); $s->{lg_cols} = _min($s->{lg_cols}, $num); $s->{lg_rows} = int($num/$s->{lg_cols}) + (($num % $s->{lg_cols}) ? 1 : 0); $s->{lg_x_size} = $s->{lg_cols} * $s->{lg_el_width}; $s->{lg_y_size} = $s->{lg_rows} * $s->{lg_el_height}; # Adjust the bottom margin for the rest of the graph $s->{b_margin} += $s->{lg_y_size}; # Set the y starting point $s->{lg_ys} = $s->{gify} - $s->{b_margin}; # Set the x starting point, depending on alignment if ($lg_align eq 'R') { $s->{lg_xs} = $s->{gifx} - $s->{r_margin} - $s->{lg_x_size}; } elsif ($lg_align eq 'L') { $s->{lg_xs} = $s->{l_margin}; } else # default 'C' { $s->{lg_xs} = int($s->{l_margin} + $width/2 - $s->{lg_x_size}/2); } } } sub draw_legend($) # (GD::Image) { my $s = shift; my $g = shift; return unless defined($s->{legend}); my $xl = $s->{lg_xs} + $s->{legend_spacing}; my $y = $s->{lg_ys} + $s->{legend_spacing} - 1; my $i = 0; my $row = 1; my $x = $xl; # start position of current element my $legend; foreach $legend (@{$s->{legend}}) { $i++; my $xe = $x; # position within an element next unless (defined($legend) && $legend ne ""); $s->draw_legend_marker($g, $i, $xe, $y); $xe += $s->{legend_marker_width} + $s->{legend_spacing}; my $ys = int($y + $s->{lg_el_height}/2 - $s->{lgfh}/2); $g->string($s->{lgf}, $xe, $ys, $legend, $s->{tci}); $x += $s->{lg_el_width}; if (++$row > $s->{lg_cols}) { $row = 1; $y += $s->{lg_el_height}; $x = $xl; } } } # This will be virtual; every sub class should define their own # if this one doesn't suffice sub draw_legend_marker($$$$) # (GD::Image, data_set_number, x, y) { my $s = shift; my $g = shift; my $n = shift; my $x = shift; my $y = shift; my $ci = $s->set_clr( $g, $s->pick_data_clr($n) ); $y += int($s->{lg_el_height}/2 - $s->{legend_marker_height}/2); $g->filledRectangle( $x, $y, $x + $s->{legend_marker_width}, $y + $s->{legend_marker_height}, $ci ); $g->rectangle( $x, $y, $x + $s->{legend_marker_width}, $y + $s->{legend_marker_height}, $s->{acci} ); } } # End of package GIFgraph::legend 1; mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/colour.pm0000644000175300017510000001446413057016062021356 0ustar oetikeroep#========================================================================== # Copyright (c) 1995-1998 Martien Verbruggen #-------------------------------------------------------------------------- # # Name: # GIFgraph::colour.pm # # Description: # Package of colour manipulation routines, to be used # with GIFgraph. # # $Id: colour.pm,v 1.1.1.1 2002/02/26 10:16:37 oetiker Exp $ # #========================================================================== package GIFgraph::colour; use vars qw( @EXPORT_OK %EXPORT_TAGS ); use strict qw( vars refs subs ); require Exporter; @GIFgraph::colour::ISA = qw( Exporter ); $GIFgraph::colour::prog_name = 'GIFgraph::colour.pm'; $GIFgraph::colour::prog_rcs_rev = '$Revision: 1.1.1.1 $'; $GIFgraph::colour::prog_version = ($GIFgraph::colour::prog_rcs_rev =~ /\s+(\d*\.\d*)/) ? $1 : "0.0"; @EXPORT_OK = qw( _rgb _luminance _hue colour_list sorted_colour_list read_rgb ); %EXPORT_TAGS = ( colours => [qw( _rgb _luminance _hue )], lists => [qw( colour_list sorted_colour_list )], files => [qw( read_rgb )], ); { my %RGB = ( white => [0xFF,0xFF,0xFF], lgray => [0xBF,0xBF,0xBF], gray => [0x7F,0x7F,0x7F], dgray => [0x3F,0x3F,0x3F], black => [0x00,0x00,0x00], lblue => [0x00,0x00,0xFF], blue => [0x00,0x00,0xBF], dblue => [0x00,0x00,0x7F], gold => [0xFF,0xD7,0x00], lyellow => [0xFF,0xFF,0x00], yellow => [0xBF,0xBF,0x00], dyellow => [0x7F,0x7F,0x00], lgreen => [0x00,0xFF,0x00], green => [0x00,0xBF,0x00], dgreen => [0x00,0x7F,0x00], lred => [0xFF,0x00,0x00], red => [0xBF,0x00,0x00], dred => [0x7F,0x00,0x00], lpurple => [0xFF,0x00,0xFF], purple => [0xBF,0x00,0xBF], dpurple => [0x7F,0x00,0x7F], lorange => [0xFF,0xB7,0x00], orange => [0xFF,0x7F,0x00], pink => [0xFF,0xB7,0xC1], dpink => [0xFF,0x69,0xB4], marine => [0x7F,0x7F,0xFF], cyan => [0x00,0xFF,0xFF], lbrown => [0xD2,0xB4,0x8C], dbrown => [0xA5,0x2A,0x2A], ); sub colour_list { my $n = ( $_[0] ) ? $_[0] : keys %RGB; return (keys %RGB)[0 .. $n-1]; } sub sorted_colour_list { my $n = $_[0] ? $_[0] : keys %RGB; return (sort by_luminance keys %RGB)[0 .. $n-1]; # return (sort by_hue keys %rgb)[0..$n-1]; sub by_luminance { _luminance(@{$RGB{$b}}) <=> _luminance(@{$RGB{$a}}); } sub by_hue { _hue(@{$RGB{$b}}) <=> _hue(@{$RGB{$a}}); } } # return the luminance of the colour (RGB) sub _luminance { (0.212671 * $_[0] + 0.715160 * $_[1] + 0.072169 * $_[2])/0xFF; } # return the hue of the colour (RGB) sub _hue { ($_[0] + $_[1] + $_[2])/(3 * 0xFF); } my %WarnedColours = (); # return the RGB values of the colour name sub _rgb { my $clr = shift; my $rgb_ref; $rgb_ref = $RGB{$clr} or do { $rgb_ref = $RGB{'black'}; unless ($WarnedColours{$clr}) { $WarnedColours{$clr} = 1; warn "Colour $clr is not defined, reverting to black"; } }; @{$rgb_ref}; } sub version { return $GIFgraph::colour::prog_version; } sub dump_colours { my $max = $_[0] ? $_[0] : keys %RGB; my $n = 0; my $clr; foreach $clr (sorted_colour_list($max)) { last if $n > $max; print "colour: $clr, " . "${$RGB{$clr}}[0], ${$RGB{$clr}}[1], ${$RGB{$clr}}[2]\n" } } # # Read a rgb.txt file (X11) # # Expected format of the file: # # R G B colour name # # Fields can be separated by any number of whitespace # Lines starting with an exclamation mark (!) are comment and # will be ignored. # # returns number of colours read sub read_rgb($) # (filename) { my $fn = shift; my $n = 0; my $line; open(RGB, $fn) or return 0; while (defined($line = )) { next if ($line =~ /\s*!/); chomp($line); # remove leading white space $line =~ s/^\s+//; # get the colours my ($r, $g, $b, $name) = split(/\s+/, $line, 4); # Ignore bad lines next unless (defined $name); $RGB{$name} = [$r, $g, $b]; $n++; } close(RGB); return $n; } $GIFgraph::colour::prog_name; } # End of package Colour __END__ =head1 NAME Colour - Colour manipulation routines for use with GIFgraph =head1 SYNOPSIS use GIFgraph::colour qw( :colours :lists :files ); =head1 DESCRIPTION The B Package provides a few routines to convert some colour names to RGB values. Also included are some functions to calculate the hue and luminance of the colours, mainly to be able to sort them. The :colours tags can be used to import the I<_rgb>, I<_hue>, and I<_luminance> functions, the :lists tag for I and I, and the :files tag exports the I function. =head1 FUNCTIONS =over 4 =item Colour::colour_list( I ) Returns a list of I colour names known to the package. =item Colour::sorted_colour_list( I ) Returns a list of I colour names known to the package, sorted by luminance or hue. B Right now it always sorts by luminance. Will add an option in a later stage to decide sorting method at run time. =item Colour::_rgb( I ) Returns a list of the RGB values of I. =item Colour::_hue( I ) Returns the hue of the colour with the specified RGB values. =item Colour::_luminance( I ) Returns the luminance of the colour with the specified RGB values. =item Colour::read_rgb( F ) Reads in colours from a rgb file as used by the X11 system. Doing something like: use GIFgraph::bars; use GIFgraph::colour; GIFgraph::colour::read_rgb("rgb.txt") or die "cannot read colours"; Will allow you to use any colours defined in rgb.txt in your graph. =back =head1 PREDEFINED COLOUR NAMES white, lgray, gray, dgray, black, lblue, blue, dblue, gold, lyellow, yellow, dyellow, lgreen, green, dgreen, lred, red, dred, lpurple, purple, dpurple, lorange, orange, pink, dpink, marine, cyan, lbrown, dbrown. =cut mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/lines.pm0000644000175300017510000000713613057016062021163 0ustar oetikeroep#========================================================================== # Copyright (c) 1995-1998 Martien Verbruggen #-------------------------------------------------------------------------- # # Name: # GIFgraph::lines.pm # # $Id: lines.pm,v 1.1.1.1 2002/02/26 10:16:37 oetiker Exp $ # #========================================================================== package GIFgraph::lines; use strict qw(vars refs subs); use GD; use GIFgraph::axestype; @GIFgraph::lines::ISA = qw( GIFgraph::axestype ); my %Defaults = ( # The width of the line to use in the lines and linespoints graphs # in pixels line_width => 1, # Set the scale of the line types line_type_scale => 8, # Which line typess to use line_types => [1], ); { sub initialise() { my $self = shift; $self->SUPER::initialise(); my $key; foreach $key (keys %Defaults) { $self->set( $key => $Defaults{$key} ); } } # PRIVATE sub draw_data_set($$$) # GD::Image, \@data { my $s = shift; my $g = shift; my $d = shift; my $ds = shift; my $dsci = $s->set_clr( $g, $s->pick_data_clr($ds) ); my $type = $s->pick_line_type($ds); my ($xb, $yb) = (defined $d->[0]) ? $s->val_to_pixel( 1, $d->[0], $ds) : (undef, undef); my $i; for $i (1 .. $s->{numpoints}) { next unless (defined $d->[$i]); my ($xe, $ye) = $s->val_to_pixel($i+1, $d->[$i], $ds); $s->draw_line( $g, $xb, $yb, $xe, $ye, $type, $dsci ) if defined $xb; ($xb, $yb) = ($xe, $ye); } } sub pick_line_type($) { my $s = shift; my $num = shift; if ( exists $s->{line_types} ) { return $s->{line_types}[ $num % (1 + $#{$s->{line_types}}) - 1 ]; } return $num % 4 ? $num % 4 : 4; } sub draw_line($$$$$$) # ($xs, $ys, $xe, $ye, $type, $colour_index) { my $s = shift; my $g = shift; my ($xs, $ys, $xe, $ye, $type, $clr) = @_; my $lw = $s->{line_width}; my $lts = $s->{line_type_scale}; my $style = gdStyled; my @pattern = (); LINE: { ($type == 2) && do { # dashed for (1 .. $lts) { push(@pattern, $clr) } for (1 .. $lts) { push(@pattern, gdTransparent) } $g->setStyle(@pattern); last LINE; }; ($type == 3) && do { # dotted, for (1 .. 2) { push(@pattern, $clr) } for (1 .. 2) { push(@pattern, gdTransparent) } $g->setStyle(@pattern); last LINE; }; ($type == 4) && do { # dashed and dotted for (1 .. $lts) { push(@pattern, $clr) } for (1 .. 2) { push(@pattern, gdTransparent) } for (1 .. 2) { push(@pattern, $clr) } for (1 .. 2) { push(@pattern, gdTransparent) } $g->setStyle(@pattern); last LINE; }; # default: solid $style = $clr; } # Tried the line_width thing with setBrush, ugly results # TODO: This loop probably should be around the datasets # for nicer results my $i; for $i (1..$lw) { my $yslw = $ys + int($lw/2) - $i; my $yelw = $ye + int($lw/2) - $i; # Need the setstyle to reset $g->setStyle(@pattern) if (@pattern); $g->line( $xs, $yslw, $xe, $yelw, $style ); } } sub draw_legend_marker($$$$) # (GD::Image, data_set_number, x, y) { my $s = shift; my $g = shift; my $n = shift; my $x = shift; my $y = shift; my $ci = $s->set_clr( $g, $s->pick_data_clr($n) ); my $type = $s->pick_line_type($n); $y += int($s->{lg_el_height}/2); $s->draw_line( $g, $x, $y, $x + $s->{legend_marker_width}, $y, $type, $ci ); } } # End of package GIFgraph::lines 1; mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/EvenlySpaced.pm0000644000175300017510000000775513057016062022442 0ustar oetikeroeppackage GIFgraph::EvenlySpaced; use strict; use MRP::BaseClass; use vars qw(@ISA %fields $AUTOLOAD $VERSION); $VERSION = 1.0; sub AUTOLOAD { my $thing = shift; my ($package, $function) = $AUTOLOAD =~ m/^(.*)::([^:]+)$/; return if $function eq 'DESTROY'; if(ref($thing)) { return $thing->_DelegateGraph->$function(@_); } # my $super = join '::', 'SUPER', $function; # return $thing->$super(@_); die "Could not find $AUTOLOAD via $thing "; } sub new { my $class = shift; my $graph = shift; my $self = new MRP::BaseClass; $self->rebless($class); $self->_DelegateGraph($graph); return $self; } sub plot { my ($self, $data) = @_; my $fudge = $self->fudge; my @processed; my @x = @{$data->[0]}; my @distances; my ($min, $max) = ($x[0], $x[$#x]); my $len = $max-$min; foreach my $i (1 .. $#x) { $distances[$i-1] = $x[$i] - $x[$i-1]; } my @sdist = sort { $a<=>$b } @distances; my $sd = shift @sdist; while(@sdist) { my $nd = shift @sdist; my $diff = $nd/$sd; $diff = $diff - int($diff); $diff = 1-$diff if $diff > 0.5; next if $diff < $fudge; my $rat = $nd/$sd; my $continue = 1; for(my $ax = 2; $continue; $ax++) { my $yx = $ax*$rat; if($yx !~ /\./) { $sd = $nd/$yx; $continue = 0; } } } my $lowest = shift @x; my $column = 0; for(my $newX = $min; ($newX-$sd) < $max; $newX+=$sd) { if($newX >= $lowest) { foreach my $series (0 .. $#$data) { push @{$processed[$series]}, $data->[$series][$column]; } $column++; $lowest = shift @x; } else { foreach my $series (0 .. $#$data) { push @{$processed[$series]}, undef; } } } local $^W = undef; return $self->_DelegateGraph->plot(\@processed); } sub isa { my ($thing, $type) = @_; return $thing->_DelegateGraph->isa($type) || $thing->SUPER::isa($type); } BEGIN { @ISA = qw(MRP::BaseClass); %fields = ( fudge => 0.1, _DelegateGraph => undef, ); GIFgraph::EvenlySpaced->check4Clashes; } $VERSION; __END__ =head1 NAME GIFgraph::EvenlySpaced - spaces the data points evenly =head1 DESCRIPTION This module wraps a GIFgraph object so that the data points become numericaly spaced (aproximately). =head1 SYNOPSIS Wrapps a GIFgraph object (probably a GIFgraph::lines) so that the x values are spaced numericaly. Use exactly as your GIFgraph object. Due to a problem I had with AUTOLOAD, it must be the outer wrapper class. =head1 Use $graph = new GIFgraph::lines(400,300); $es = new GIFgraph::EvenlySpaced($graph); or $graph = new GIFgraph::lines(400,300); $withmap = new GIFgraph::WithMap($graph); $es = new GIFgraph::EvenlySpaced($withmap); or even $es = new GIFgraph::EvenlySpaced(new GIFgraph::WithMap(new GIFgraph::lines(400,300))); etc. etc. etc. =head1 Functions =over =item new Returns a new GIFgraph::EvenlySpaced object $es = new GIFgraph::EvenlySpaced($parentGraph); where $parentGraph is any object that behaves like a GIFgraph::lines type object such as a GIFgraph::WithMap. =item plot This function is overridden to space the data numericaly along the x-axis. =back =head1 Fields =over =item fudge This is a fudge factor used in checking whether one number roughly devides into another. It defaults to 0.1 but if it is obviously doing silly things then change it. Good luck - I don't realy know how it works. =back =head1 Guts This module uses MRP::BaseClass to implement member access functions. To make the 'parent' object behave as if it the super class I have done some magic with AUTOLOAD. This has produced the restriction that you can not wrap an EvenlySpaced object inside another - such as WithMap - that also uses magic. @ISA does not include the parent type as it is not known. The isa() method is overridden to account for this. =head1 AUTHOR Matthew Pocock mrp@sanger.ac.uk mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/0000755000175300017510000000000013057016062021150 5ustar oetikeroepmrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample16.htm0000644000175300017510000000064713057016062023321 0ustar oetikeroep GIFgraph.pm - example 1-6

      GIFgraph.pm - example 1-3


      The code.


      NOTES
      There was no data for the credits on the third and the debets on the 7th day. mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample11.htm0000644000175300017510000000050613057016062023306 0ustar oetikeroep GIFgraph.pm - example 1-1

      GIFgraph.pm - example 1-1


      The code.


      mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample12.pl0000644000175300017510000000117213057016062023132 0ustar oetikeroepuse GIFgraph::bars; print STDERR "Processing sample 1-2\n"; @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 5, 12, 24, 33, 19, 8, 6, 15, 21], [ 1, 2, 5, 6, 3, 1.5, 1, 3, 4], ); $my_graph = new GIFgraph::bars(); $my_graph->set( x_label => 'X Label', y_label => 'Y label', title => 'Two data sets', long_ticks => 1, y_max_value => 40, y_tick_number => 8, y_label_skip => 2, bar_spacing => 4, ); $my_graph->set_legend( 'Data set 1', 'Data set 2' ); $my_graph->plot_to_gif( "sample12.gif", \@data ); exit; mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample62.pl0000644000175300017510000000147713057016062023147 0ustar oetikeroepuse GIFgraph::mixed; print STDERR "Processing sample 6-2\n"; @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 9, 8, 9, 8.4, 7.1, 7.5, 8, 3, 3], [ .4, .3, 1, 1, .3, 1.5, 2, 1, 0], ); $my_graph = new GIFgraph::mixed(); $my_graph->set( x_label => 'X Label', y1_label => 'Y1 label', y2_label => 'Y2 label', title => 'A Mixed Type Graph with Two Axes', two_axes => 1, y1_max_value => 10, y2_max_value => 2.5, y_min_value => 0, y_tick_number => 5, long_ticks => 1, x_ticks => 0, legend_marker_width => 24, line_width => 5, bar_spacing => 4, types => [ qw( bars lines ) ], ); $my_graph->set_legend( qw( one two three four five six ) ); $my_graph->plot_to_gif( "sample62.gif", \@data ); exit; mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample51.htm0000644000175300017510000000050613057016062023312 0ustar oetikeroep GIFgraph.pm - example 5-1

      GIFgraph.pm - example 5-1


      The code.


      mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample94.pl0000644000175300017510000000067413057016062023152 0ustar oetikeroepuse GIFgraph::pie; print STDERR "Processing sample 9-4\n"; @data = ( [ qw( 1st 2nd 3rd 4th 5th 6th 7th ) ], [ sort { $b <=> $a} (5.6, 2.1, 3.03, 4.05, 1.34, 0.2, 2.56) ] ); $my_graph = new GIFgraph::pie( 260, 300 ); $my_graph->set( start_angle => 90, '3d' => 0 ); $my_graph->set_legend( 'Alpha', 'Beta', 'Gamma', 'Delta', 'Epsilon', 'Forget', 'Rest'); $my_graph->plot_to_gif( "sample94.gif", \@data ); exit; mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample13.pl0000644000175300017510000000104313057016062023130 0ustar oetikeroepuse GIFgraph::bars; print STDERR "Processing sample 1-3\n"; @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 5, 12, 24, 33, 19, 8, 6, 15, 21], [ 1, 2, 5, 6, 3, 1.5, 1, 3, 4] ); $my_graph = new GIFgraph::bars(); $my_graph->set( x_label => 'X Label', y_label => 'Y label', title => 'Bars in front of each other', y_tick_number => 8, y_label_skip => 2, overwrite => 1, ); $my_graph->plot_to_gif( "sample13.gif", \@data ); exit; mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/rgb.txt0000644000175300017510000004272013057016062022470 0ustar oetikeroep199 21 133 medium violet red 176 196 222 light steel blue 102 139 139 paleturquoise4 159 121 238 mediumpurple2 141 182 205 lightskyblue3 0 238 118 springgreen2 255 160 122 light salmon 154 205 50 yellowgreen 178 58 238 darkorchid2 69 139 116 aquamarine4 71 60 139 slateblue4 131 111 255 slateblue1 192 255 62 olivedrab1 139 105 20 goldenrod4 205 155 29 goldenrod3 142 229 238 cadetblue2 255 211 155 burlywood1 112 128 144 slategrey 255 228 225 mistyrose 50 205 50 limegreen 224 255 255 lightcyan 218 165 32 goldenrod 220 220 220 gainsboro 135 206 255 skyblue1 240 255 240 honeydew 238 238 0 yellow2 205 79 57 tomato3 135 206 235 skyblue 85 26 139 purple4 205 133 0 orange3 205 183 158 bisque3 238 213 183 bisque2 87 87 87 grey34 252 252 252 gray99 161 161 161 gray63 112 112 112 gray44 94 94 94 gray37 84 84 84 gray33 66 66 66 gray26 240 255 255 azure1 139 137 137 snow4 205 133 63 peru 219 112 147 pale violet red 139 129 76 lightgoldenrod4 60 179 113 mediumseagreen 255 240 245 lavender blush 209 95 238 mediumorchid2 176 226 255 lightskyblue1 72 61 139 darkslateblue 25 25 112 midnightblue 255 160 122 lightsalmon1 255 250 205 lemonchiffon 173 255 47 green yellow 255 160 122 lightsalmon 240 128 128 light coral 24 116 205 dodgerblue3 139 69 0 darkorange4 106 90 205 slate blue 39 64 139 royalblue4 255 69 0 orange red 50 205 50 lime green 224 255 255 light cyan 148 0 211 darkviolet 233 150 122 darksalmon 255 140 0 darkorange 95 158 160 cadet blue 255 20 147 deep pink 238 0 238 magenta2 139 71 38 sienna4 238 230 133 khaki2 191 191 191 grey75 189 189 189 grey74 186 186 186 grey73 176 176 176 grey69 173 173 173 grey68 89 89 89 grey35 33 33 33 grey13 229 229 229 gray90 207 207 207 gray81 140 140 140 gray55 130 130 130 gray51 79 79 79 gray31 238 233 233 snow2 205 145 158 pink3 18 18 18 grey7 3 3 3 gray1 139 0 0 red4 205 0 0 red3 210 180 140 tan 255 0 0 red 199 21 133 mediumvioletred 119 136 153 lightslategrey 135 206 250 lightskyblue 139 87 66 lightsalmon4 34 139 34 forestgreen 16 78 139 dodgerblue4 153 50 204 dark orchid 188 143 143 rosy brown 205 175 149 peachpuff3 124 205 124 palegreen3 238 64 0 orangered2 122 139 139 lightcyan4 139 58 58 indianred4 205 85 85 indianred3 0 0 128 navyblue 105 105 105 dim grey 255 20 147 deeppink 139 76 57 salmon4 205 112 84 salmon3 196 196 196 grey77 145 145 145 gray57 28 28 28 gray11 205 150 205 plum3 23 23 23 gray9 20 20 20 gray8 0 0 139 blue4 245 245 220 beige 250 250 210 light goldenrod yellow 139 131 134 lavenderblush4 0 206 209 dark turquoise 0 206 209 darkturquoise 47 79 79 darkslategrey 205 129 98 lightsalmon3 139 105 105 rosybrown4 255 228 225 misty rose 78 238 148 seagreen2 205 92 92 indianred 255 20 147 deeppink1 0 0 139 dark blue 230 230 250 lavender 253 245 230 oldlace 199 199 199 grey78 138 138 138 grey54 115 115 115 grey45 54 54 54 grey21 247 247 247 gray97 245 245 245 gray96 242 242 242 gray95 224 224 224 gray88 222 222 222 gray87 219 219 219 gray86 179 179 179 gray70 97 97 97 gray38 31 31 31 gray12 250 240 230 linen 72 209 204 medium turquoise 72 61 139 dark slate blue 139 137 112 lemonchiffon4 193 255 193 darkseagreen1 205 192 176 antiquewhite3 186 85 211 mediumorchid 0 255 127 springgreen 0 134 139 turquoise4 79 148 205 steelblue3 238 213 210 mistyrose2 209 238 238 lightcyan2 205 92 92 indian red 238 44 44 firebrick2 65 105 225 royalblue 95 158 160 cadetblue 108 166 205 skyblue3 205 205 0 yellow3 255 140 105 salmon1 139 90 0 orange4 255 105 180 hotpink 229 229 229 grey90 143 143 143 gray56 99 99 99 gray39 46 46 46 gray18 36 36 36 gray14 139 102 139 plum4 15 15 15 grey6 15 15 15 gray6 205 173 0 gold3 255 215 0 gold1 0 0 238 blue2 238 154 73 tan2 0 255 255 cyan 0 250 154 mediumspringgreen 188 238 104 darkolivegreen2 238 232 170 pale goldenrod 176 196 222 lightsteelblue 244 164 96 sandy brown 255 239 213 papaya whip 102 205 0 chartreuse3 139 34 82 violetred4 67 110 238 royalblue2 72 118 255 royalblue1 255 239 213 papayawhip 205 183 181 mistyrose3 224 255 255 lightcyan1 127 255 212 aquamarine 74 112 139 skyblue4 139 58 98 hotpink4 205 96 144 hotpink3 238 106 167 hotpink2 169 169 169 darkgrey 105 105 105 dimgray 255 99 71 tomato 168 168 168 grey66 166 166 166 grey65 163 163 163 grey64 84 84 84 grey33 69 69 69 grey27 194 194 194 gray76 176 176 176 gray69 173 173 173 gray68 0 0 0 grey0 240 255 255 azure 0 250 154 medium spring green 139 101 8 darkgoldenrod4 205 149 12 darkgoldenrod3 238 173 14 darkgoldenrod2 184 134 11 darkgoldenrod 139 69 19 saddle brown 238 149 114 lightsalmon2 0 104 139 deepskyblue4 0 154 205 deepskyblue3 0 178 238 deepskyblue2 0 191 255 deepskyblue 255 127 0 darkorange1 205 50 120 violetred3 238 58 140 violetred2 255 62 150 violetred1 105 89 205 slateblue3 122 103 238 slateblue2 107 142 35 olive drab 255 106 106 indianred1 255 48 48 firebrick1 83 134 139 cadetblue4 208 32 144 violetred 188 143 143 rosybrown 0 0 128 navy blue 178 34 34 firebrick 139 0 0 dark red 255 255 255 grey100 139 126 102 wheat4 201 201 201 grey79 194 194 194 grey76 156 156 156 grey61 237 237 237 gray93 214 214 214 gray84 166 166 166 gray65 92 92 92 gray36 82 82 82 gray32 33 33 33 gray13 26 26 26 gray10 193 205 205 azure3 255 250 250 snow1 255 165 79 tan1 119 136 153 light slate gray 202 255 112 darkolivegreen1 100 149 237 cornflower blue 255 235 205 blanched almond 205 193 197 lavenderblush3 238 224 229 lavenderblush2 255 240 245 lavenderblush1 85 107 47 darkolivegreen 255 240 245 lavenderblush 118 238 198 aquamarine2 208 32 144 violet red 179 238 58 olivedrab2 139 125 123 mistyrose4 255 228 225 mistyrose1 180 205 205 lightcyan3 240 128 128 lightcoral 127 255 0 chartreuse 255 218 185 peachpuff 152 251 152 palegreen 245 255 250 mintcream 126 192 238 skyblue2 255 228 181 moccasin 255 99 71 tomato1 205 105 201 orchid3 205 41 144 maroon3 250 128 114 salmon 207 207 207 grey81 158 158 158 grey62 99 99 99 grey39 97 97 97 grey38 94 94 94 grey37 235 235 235 gray92 212 212 212 gray83 168 168 168 gray66 138 138 138 gray54 127 127 127 gray50 77 77 77 gray30 48 48 48 gray19 38 38 38 gray15 131 139 139 azure4 8 8 8 grey3 205 133 63 tan3 255 192 203 pink 190 190 190 gray 0 0 255 blue 188 210 238 lightsteelblue2 202 225 255 lightsteelblue1 32 178 170 light sea green 119 136 153 lightslategray 238 233 191 lemonchiffon2 0 255 127 springgreen1 173 255 47 greenyellow 118 238 0 chartreuse2 112 128 144 slate grey 58 95 205 royalblue3 176 224 230 powderblue 238 203 173 peachpuff2 144 238 144 palegreen2 245 255 250 mint cream 106 90 205 slateblue 238 229 222 seashell2 238 18 137 deeppink2 189 183 107 darkkhaki 139 28 98 maroon4 160 82 45 sienna 181 181 181 grey71 171 171 171 grey67 46 46 46 grey18 150 150 150 gray59 110 110 110 gray43 64 64 64 gray25 255 228 196 bisque 255 0 0 red1 123 104 238 mediumslateblue 255 236 139 lightgoldenrod1 238 221 130 light goldenrod 150 205 205 paleturquoise3 96 123 139 lightskyblue4 0 255 127 spring green 255 255 224 light yellow 245 245 245 white smoke 0 0 205 medium blue 248 248 255 ghost white 54 100 139 steelblue4 205 155 155 rosybrown3 255 218 185 peachpuff1 154 255 154 palegreen1 138 43 226 blueviolet 139 134 130 seashell4 169 169 169 darkgray 205 104 57 sienna3 102 102 102 grey40 232 232 232 gray91 209 209 209 gray82 13 13 13 gray5 0 238 238 cyan2 0 255 255 cyan1 0 0 255 blue1 255 250 250 snow 238 220 130 lightgoldenrod2 132 112 255 lightslateblue 180 82 205 mediumorchid3 105 139 105 darkseagreen4 0 205 102 springgreen3 34 139 34 forest green 108 123 139 slategray4 159 182 205 slategray3 185 211 238 slategray2 65 105 225 royal blue 139 119 101 peachpuff4 84 139 84 palegreen4 152 251 152 pale green 205 55 0 orangered3 255 193 37 goldenrod1 248 248 255 ghostwhite 139 26 26 firebrick4 205 38 38 firebrick3 122 197 205 cadetblue3 112 128 144 slategray 205 197 191 seashell3 193 205 193 honeydew3 139 136 120 cornsilk4 238 232 205 cornsilk2 155 48 255 purple1 105 105 105 dimgrey 139 0 0 darkred 255 246 143 khaki1 205 205 193 ivory3 179 179 179 grey70 153 153 153 grey60 82 82 82 grey32 56 56 56 grey22 31 31 31 grey12 250 250 250 gray98 227 227 227 gray89 181 181 181 gray71 163 163 163 gray64 153 153 153 gray60 125 125 125 gray49 224 238 238 azure2 8 8 8 gray3 187 255 255 paleturquoise1 171 130 255 mediumpurple1 147 112 219 medium purple 255 250 205 lemonchiffon1 0 191 255 deep sky blue 205 179 139 navajowhite3 191 62 255 darkorchid1 255 140 0 dark orange 238 180 34 goldenrod2 189 183 107 dark khaki 238 118 33 chocolate2 238 197 145 burlywood2 240 255 240 honeydew1 0 100 0 darkgreen 205 181 205 thistle3 238 210 238 thistle2 255 225 255 thistle1 0 0 139 darkblue 216 191 216 thistle 238 48 167 maroon2 255 52 179 maroon1 135 135 135 grey53 112 112 112 grey44 64 64 64 grey25 189 189 189 gray74 115 115 115 gray45 105 105 105 gray41 89 89 89 gray35 69 69 69 gray27 59 59 59 gray23 41 41 41 gray16 139 35 35 brown4 245 222 179 wheat 255 127 80 coral 139 90 43 tan4 250 250 210 lightgoldenrodyellow 132 112 255 light slate blue 85 107 47 dark olive green 47 79 79 dark slate gray 205 104 137 palevioletred3 93 71 139 mediumpurple4 137 104 205 mediumpurple3 139 69 19 saddlebrown 176 224 230 powder blue 104 34 139 darkorchid4 154 50 205 darkorchid3 255 218 185 peach puff 105 139 34 olivedrab4 104 131 139 lightblue4 255 182 193 lightpink 211 211 211 lightgray 224 238 224 honeydew2 255 248 220 cornsilk1 253 245 230 old lace 255 130 71 sienna1 139 125 107 bisque4 218 112 214 orchid 205 198 115 khaki3 214 214 214 grey84 212 212 212 grey83 209 209 209 grey82 184 184 184 grey72 133 133 133 grey52 110 110 110 grey43 66 66 66 grey26 36 36 36 grey14 26 26 26 grey10 191 191 191 gray75 135 135 135 gray53 54 54 54 gray21 51 51 51 gray20 205 51 51 brown3 20 20 20 grey8 238 0 0 red2 0 0 128 navy 190 190 190 grey 255 215 0 gold 102 205 170 mediumaquamarine 238 221 130 lightgoldenrod 82 139 139 darkslategray4 155 205 155 darkseagreen3 180 238 180 darkseagreen2 139 131 120 antiquewhite4 250 235 215 antique white 0 139 69 springgreen4 139 139 122 lightyellow4 255 250 240 floral white 127 255 212 aquamarine1 0 197 205 turquoise3 92 172 238 steelblue2 238 180 180 rosybrown2 255 182 193 light pink 211 211 211 light gray 238 99 99 indianred2 30 144 255 dodgerblue 0 100 0 dark green 84 255 159 seagreen1 139 10 80 deeppink4 240 248 255 aliceblue 255 0 255 magenta1 255 105 180 hot pink 238 121 66 sienna2 255 131 250 orchid1 255 255 255 gray100 247 247 247 grey97 240 240 240 grey94 222 222 222 grey87 219 219 219 grey86 130 130 130 grey51 107 107 107 grey42 48 48 48 grey19 240 240 240 gray94 217 217 217 gray85 156 156 156 gray61 238 59 59 brown2 240 230 140 khaki 3 3 3 grey1 139 117 0 gold4 123 104 238 medium slate blue 60 179 113 medium sea green 47 79 79 dark slate grey 175 238 238 pale turquoise 175 238 238 paleturquoise 122 55 139 mediumorchid4 238 223 204 antiquewhite2 238 238 209 lightyellow2 144 238 144 light green 148 0 211 dark violet 233 150 122 dark salmon 127 255 0 chartreuse1 0 245 255 turquoise1 244 164 96 sandybrown 255 69 0 orangered1 255 174 185 lightpink1 178 223 238 lightblue2 191 239 255 lightblue1 211 211 211 light grey 46 139 87 seagreen4 67 205 128 seagreen3 173 216 230 lightblue 205 16 118 deeppink3 169 169 169 dark grey 0 139 139 dark cyan 222 184 135 burlywood 255 245 238 seashell 255 110 180 hotpink1 105 105 105 dim gray 0 139 139 darkcyan 139 139 0 yellow4 255 255 0 yellow 160 32 240 purple 255 165 0 orange 139 139 131 ivory4 252 252 252 grey99 227 227 227 grey89 161 161 161 grey63 148 148 148 grey58 125 125 125 grey49 79 79 79 grey31 61 61 61 grey24 51 51 51 grey20 0 139 0 green4 0 255 0 green1 186 186 186 gray73 171 171 171 gray67 205 91 69 coral3 238 106 80 coral2 238 174 238 plum2 139 99 108 pink4 255 255 240 ivory 10 10 10 gray4 5 5 5 gray2 238 201 0 gold2 102 205 170 medium aquamarine 119 136 153 light slate grey 205 190 112 lightgoldenrod3 162 205 90 darkolivegreen3 255 185 15 darkgoldenrod1 184 134 11 dark goldenrod 186 85 211 medium orchid 255 250 205 lemon chiffon 139 121 94 navajowhite4 0 191 255 deepskyblue1 255 255 224 lightyellow 255 250 240 floralwhite 30 144 255 dodger blue 0 0 205 mediumblue 144 238 144 lightgreen 139 69 19 chocolate4 205 102 29 chocolate3 139 115 85 burlywood4 64 224 208 turquoise 70 130 180 steelblue 46 139 87 sea green 124 252 0 lawngreen 131 139 131 honeydew4 169 169 169 dark gray 46 139 87 seagreen 139 71 137 orchid4 255 231 186 wheat1 238 130 238 violet 255 255 240 ivory1 224 224 224 grey88 217 217 217 grey85 145 145 145 grey57 143 143 143 grey56 140 140 140 grey55 122 122 122 grey48 120 120 120 grey47 117 117 117 grey46 77 77 77 grey30 43 43 43 grey17 120 120 120 gray47 74 74 74 gray29 238 169 184 pink2 13 13 13 grey5 10 10 10 grey4 0 255 0 green 0 0 0 gray0 165 42 42 brown 110 123 139 lightsteelblue4 110 139 61 darkolivegreen4 139 71 93 palevioletred4 135 206 250 light sky blue 121 205 205 darkslategray3 141 238 238 darkslategray2 151 255 255 darkslategray1 255 235 205 blanchedalmond 238 232 170 palegoldenrod 25 25 112 midnight blue 32 178 170 lightseagreen 205 201 165 lemonchiffon3 47 79 79 darkslategray 154 205 50 yellow green 143 188 143 darkseagreen 250 235 215 antiquewhite 238 118 0 darkorange2 69 139 0 chartreuse4 70 130 180 steel blue 255 193 193 rosybrown1 154 205 50 olivedrab3 238 162 173 lightpink2 255 69 0 orangered 139 123 139 thistle4 135 206 235 sky blue 255 248 220 cornsilk 238 130 98 salmon2 238 122 233 orchid2 238 238 224 ivory2 237 237 237 grey93 235 235 235 grey92 232 232 232 grey91 92 92 92 grey36 74 74 74 grey29 71 71 71 grey28 41 41 41 grey16 201 201 201 gray79 199 199 199 gray78 196 196 196 gray77 122 122 122 gray48 43 43 43 gray17 139 62 47 coral4 255 114 86 coral1 255 187 255 plum1 255 181 197 pink1 23 23 23 grey9 5 5 5 grey2 18 18 18 gray7 0 139 139 cyan4 0 0 205 blue3 221 160 221 plum 100 149 237 cornflowerblue 164 211 238 lightskyblue2 255 239 219 antiquewhite1 238 207 161 navajowhite2 255 222 173 navajowhite1 205 205 180 lightyellow3 139 0 139 dark magenta 255 222 173 navajowhite 205 102 0 darkorange3 245 245 245 whitesmoke 0 229 238 turquoise2 99 184 255 steelblue1 139 95 101 lightpink4 154 192 205 lightblue3 124 252 0 lawn green 255 127 36 chocolate1 240 248 255 alice blue 107 142 35 olivedrab 211 211 211 lightgrey 210 105 30 chocolate 139 0 139 magenta4 205 0 205 magenta3 255 255 0 yellow1 125 38 205 purple3 145 44 238 purple2 238 154 0 orange2 255 165 0 orange1 255 0 255 magenta 255 228 196 bisque1 238 216 174 wheat2 176 48 96 maroon 139 134 78 khaki4 245 245 245 grey96 242 242 242 grey95 204 204 204 grey80 127 127 127 grey50 105 105 105 grey41 38 38 38 grey15 28 28 28 grey11 204 204 204 gray80 148 148 148 gray58 102 102 102 gray40 87 87 87 gray34 56 56 56 gray22 255 64 64 brown1 205 201 201 snow3 72 209 204 mediumturquoise 162 181 205 lightsteelblue3 238 121 159 palevioletred2 255 130 171 palevioletred1 174 238 238 paleturquoise2 143 188 143 dark sea green 219 112 147 palevioletred 224 102 255 mediumorchid1 255 222 173 navajo white 147 112 219 mediumpurple 255 255 224 lightyellow1 28 134 238 dodgerblue2 30 144 255 dodgerblue1 139 0 139 darkmagenta 138 43 226 blue violet 102 205 170 aquamarine3 198 226 255 slategray1 112 128 144 slate gray 139 37 0 orangered4 205 140 149 lightpink3 173 216 230 light blue 153 50 204 darkorchid 152 245 255 cadetblue1 205 170 125 burlywood3 255 245 238 seashell1 205 200 177 cornsilk3 139 54 38 tomato4 238 92 66 tomato2 205 186 150 wheat3 250 250 250 grey98 150 150 150 grey59 59 59 59 grey23 0 205 0 green3 0 238 0 green2 184 184 184 gray72 158 158 158 gray62 133 133 133 gray52 117 117 117 gray46 107 107 107 gray42 71 71 71 gray28 61 61 61 gray24 255 255 255 white 0 205 205 cyan3 0 0 0 black mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample61.pl0000644000175300017510000000226613057016062023143 0ustar oetikeroepuse GIFgraph::mixed; print STDERR "Processing sample 6-1 (The error message is intended)\n"; @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 1, 2, 5, 6, 3, 1.5, -1, -3, -4], [ -4, -3, 1, 1, -3, -1.5, -2, -1, 0], [ 9, 8, 9, 8.4, 7.1, 7.5, 8, 3, -3], [ 0.1, 0.2, 0.5, 0.4, 0.3, 0.5, 0.1, 0, 0.4], [ -0.1, 2, 5, 4, -3, 2.5, 3.2, 4, -4], [ -0.1, 2, 5, 4, -3, 2.5, 3.2, 4, -4], ); $my_graph = new GIFgraph::mixed(); $my_graph->set( types => [ qw( lines bars points area linespoints wrong_type ) ], default_type => 'points', ); $my_graph->set( x_label => 'X Label', y_label => 'Y label', title => 'A Mixed Type Graph', y_max_value => 10, y_min_value => -5, y_tick_number => 3, y_label_skip => 1, x_plot_values => 0, y_plot_values => 0, long_ticks => 1, x_ticks => 0, legend_marker_width => 24, line_width => 3, marker_size => 5, bar_spacing => 8, ); $my_graph->set_legend( qw( one two three four five six ) ); $my_graph->plot_to_gif( "sample61.gif", \@data ); exit; mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample91.htm0000644000175300017510000000050613057016062023316 0ustar oetikeroep GIFgraph.pm - example 9-1

      GIFgraph.pm - example 9-1


      The code.


      mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample11.pl0000644000175300017510000000076613057016062023141 0ustar oetikeroepuse GIFgraph::bars; use GIFgraph::colour; print STDERR "Processing sample 1-1\n"; @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 1, 2, 5, 6, 3, 1.5, 1, 3, 4], ); $my_graph = new GIFgraph::bars(); $my_graph->set( x_label => 'X Label', y_label => 'Y label', title => 'A Simple Bar Chart', y_max_value => 8, y_tick_number => 8, y_label_skip => 2, ); $my_graph->plot_to_gif( "sample11.gif", \@data ); exit; mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample93.pl0000644000175300017510000000054113057016062023142 0ustar oetikeroepuse GIFgraph::pie; print STDERR "Processing sample 9-3\n"; @data = ( [ qw( 1st 2nd 3rd 4th 5th 6th 7th ) ], [ sort { $b <=> $a} (5.6, 2.1, 3.03, 4.05, 1.34, 0.2, 2.56) ] ); $my_graph = new GIFgraph::pie( 200, 200 ); $my_graph->set( start_angle => 90, '3d' => 0 ); $my_graph->plot_to_gif( "sample93.gif", \@data ); exit; mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample14.pl0000644000175300017510000000150013057016062023127 0ustar oetikeroepuse GIFgraph::bars; print STDERR "Processing sample 1-4\n"; @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 5, 12, 24, 33, 19, 8, 6, 15, 21], [ 1, 2, 5, 6, 3, 1.5, 1, 3, 4] ); $my_graph = new GIFgraph::bars( ); $my_graph->set( x_label => 'X Label', y1_label => 'Y1 label', y2_label => 'Y2 label', title => 'Using two axes', y1_max_value => 40, y2_max_value => 8, y_tick_number => 8, y_label_skip => 2, long_ticks => 1, two_axes => 1, legend_placement => 'RT', x_labels_vertical => 1, x_label_position => 1/2, bar_spacing => 2, logo => 'logo.gif', logo_position => 'BR', ); $my_graph->set_legend( 'left axis', 'right axis'); $my_graph->plot_to_gif( "sample14.gif", \@data ); exit; mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample62.htm0000644000175300017510000000050613057016062023314 0ustar oetikeroep GIFgraph.pm - example 6-2

      GIFgraph.pm - example 6-2


      The code.


      mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample15.pl0000644000175300017510000000126113057016062023134 0ustar oetikeroepuse GIFgraph::bars; print STDERR "Processing sample 1-5\n"; @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 11, 12, 15, 16, 3, 1.5, 1, 3, 4], [ 5, 12, 24, 15, 19, 8, 6, 15, 21], [ 12, 3, 1, 5, 12, 9, 16, 25, 11], ); $my_graph = new GIFgraph::bars(); $my_graph->set( x_label => 'X Label', y_label => 'Y label', title => 'Stacked Bars (incremental)', y_max_value => 50, y_tick_number => 10, y_label_skip => 2, overwrite => 2, ); $my_graph->set_legend( qw(offset increment more)); $my_graph->plot_to_gif( "sample15.gif", \@data ); exit; mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample92.pl0000644000175300017510000000064713057016062023150 0ustar oetikeroepuse GIFgraph::pie; print STDERR "Processing sample 9-2\n"; @data = ( ["1st","2nd","3rd","4th","5th","6th"], [ 4, 2, 3, 4, 3, 3.5] ); $my_graph = new GIFgraph::pie( 250, 200 ); $my_graph->set( title => 'A Pie Chart', label => 'Label', axislabelclr => 'white', dclrs => [ 'lblue' ], accentclr => 'lgray', ); $my_graph->plot_to_gif( "sample92.gif", \@data ); exit; mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/Makefile0000644000175300017510000000114313057016062022607 0ustar oetikeroepPERL = perl .SUFFIXES: .gif .pl .SILENT: LIB = .. OPTIONS = -Tw GIFS = sample11.gif sample12.gif sample13.gif sample14.gif \ sample15.gif sample16.gif \ sample21.gif \ sample31.gif \ sample41.gif sample42.gif\ sample51.gif sample52.gif sample53.gif sample54.gif \ sample61.gif sample62.gif \ sample91.gif sample92.gif sample93.gif all: $(GIFS) .pl.gif: $(PERL) $(OPTIONS) -I$(LIB) $< clean: rm -f $(GIFS) test: $(PERL) $(OPTIONS) -I$(LIB) -M$(MODULE) sample91.pl # Dependencies sample14.gif: logo.gif sample42.gif: sample42.dat sample54.gif: sample54.dat mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample41.htm0000644000175300017510000000061013057016062023305 0ustar oetikeroep GIFgraph.pm - example 4-1

      GIFgraph.pm - example 4-1


      The code.


      NOTES
      Note that both data sets have a point missing. mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample91.pl0000644000175300017510000000065713057016062023150 0ustar oetikeroepuse GIFgraph::pie; print STDERR "Processing sample 9-1\n"; @data = ( ["1st","2nd","3rd","4th","5th","6th"], [ 4, 2, 3, 4, 3, 3.5] ); $my_graph = new GIFgraph::pie( 250, 200 ); #$my_graph = new GIFgraph::pie( ); $my_graph->set( title => 'A Pie Chart', label => 'Label', axislabelclr => 'black', pie_height => 36, ); $my_graph->plot_to_gif( "sample91.gif", \@data ); exit; mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample16.pl0000644000175300017510000000174313057016062023142 0ustar oetikeroepuse GIFgraph::bars; print STDERR "Processing sample 1-6\n"; @data = ( [ qw( 1st 2nd 3rd 4th 5th 6th 7th 8th 9th ) ], [ 5, 12,undef, 33, 19, 8, 5, 15, 21], [ -6, -5, -9, -8, -11, -9.3,undef, -9, -12] ); $my_graph = new GIFgraph::bars(); $my_graph->set( x_label => 'Day', y_label => 'AUD', title => 'Credits and Debits', y_max_value => 35, y_min_value => -15, y_tick_number => 10, y_label_skip => 2, overwrite => 1, dclrs => [ qw( green lred ) ], axislabelclr => 'black', legend_placement => 'RB', zero_axis_only => 0, y_number_format => \&y_format, x_label_position => 1/2, ); my $refit = 4; sub y_format { my $value = shift; my $ret; if ($value >= 0) { $ret = sprintf("\$%3d", $value * $refit); } else { $ret = sprintf("-\$%3d", abs($value) * $refit); } } $my_graph->set_legend( 'credits', 'debets' ); $my_graph->plot_to_gif( "sample16.gif", \@data ); exit; mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/logo.gif0000644000175300017510000000147013057016062022601 0ustar oetikeroepGIF89a@@#0g < PmJоĬnqL^`FaVbRp+OS͒tln'L̗00`iՊoѺ*6] (gԂF(嵅mjR`g6nAd$裔)0HಅH( ΰQlK\srvf+h̬$$WIhkopz,p/2Ћ}{Xx/q]X9OLolԤLܬ808MslB,OwLqOu?D r T߾̈́W0XԌ)UTL/U gY̕qRY,/B ˦l,L/boK\/Rp,,țZ/T,O ѠWnHpg Άnh7dq_lT,8o lrLROɨm尼R]5вLmr||f4в0ynҳRD ёDas]P 1aw qvUbw7m *ﯪPwnJ,pZqwݏqu5ziddUqkn6w8Z9LZ7Zn!,@@@ H*\pamrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample42.dat0000644000175300017510000000016013057016062023266 0ustar oetikeroep1st,undef,60 2nd,52,61 3rd,53,61 4th,54,undef 5th,55,68 6th,56,66 7th,undef,65 8th,58,61 9th,59,undef mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample41.pl0000644000175300017510000000116513057016062023136 0ustar oetikeroepuse GIFgraph::linespoints; print STDERR "Processing sample 4-1\n"; @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [undef, 52, 53, 54, 55, 56, undef, 58, 59], [60, 61, 61, undef, 68, 66, 65, 61, undef], ); $my_graph = new GIFgraph::linespoints( ); $my_graph->set( x_label => 'X Label', y_label => 'Y label', title => 'A Lines and Points Graph', y_max_value => 80, y_tick_number => 6, y_label_skip => 2, markers => [ 1, 5 ], ); $my_graph->set_legend( 'data set 1', 'data set 2' ); $my_graph->plot_to_gif( "sample41.gif", \@data ); exit; mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample93.htm0000644000175300017510000000050613057016062023320 0ustar oetikeroep GIFgraph.pm - example 9-3

      GIFgraph.pm - example 9-3


      The code.


      mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample42.htm0000644000175300017510000000066313057016062023316 0ustar oetikeroep GIFgraph.pm - example 4-2

      GIFgraph.pm - example 4-2


      The code.


      NOTES
      This is the same graph as sample41, but this time the data has been read from a CSV file. mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample31.pl0000644000175300017510000000125513057016062023135 0ustar oetikeroepuse GIFgraph::points; print STDERR "Processing sample 3-1\n"; @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 5, 12, 24, 33, 19, 8, 6, 15, 21], [ 1, 2, 5, 6, 3, 1.5, undef, 3, 4], ); $my_graph = new GIFgraph::points(); $my_graph->set( x_label => 'X Label', y_label => 'Y label', title => 'A Points Graph', y_max_value => 40, y_tick_number => 8, y_label_skip => 2, legend_placement => 'RC', long_ticks => 1, marker_size => 6, markers => [ 1, 7, 5 ], ); $my_graph->set_legend( qw( one two ) ); $my_graph->plot_to_gif( "sample31.gif", \@data ); exit; mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample21.htm0000644000175300017510000000050613057016062023307 0ustar oetikeroep GIFgraph.pm - example 2-1

      GIFgraph.pm - example 2-1


      The code.


      mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample54.pl0000644000175300017510000000202113057016062023132 0ustar oetikeroepuse GIFgraph::lines; print STDERR "Processing sample 5-4\n"; # The reverse is in here, because I thought the falling line was # depressing, but I was too lazy to retype the data set @data = read_data("sample54.dat") or die "Cannot read data from sample54.dat"; $my_graph = new GIFgraph::lines(); $my_graph->set( x_label => 'Wavelength (nm)', y_label => 'Absorbance', title => 'Numerical X axis', y_min_value => 0, y_max_value => 2, y_tick_number => 8, y_label_skip => 4, x_tick_number => 'auto', box_axis => 0, line_width => 2, x_label_position => 1/2, r_margin => 15, ); $my_graph->set_legend('Thanks to Scott Prahl'); $my_graph->plot_to_gif( "sample54.gif", \@data ); exit; sub read_data { my $fn = shift; my @d = (); open(ZZZ, $fn) || return (); while () { chomp; my @row = split; for (my $i = 0; $i <= $#row; $i++) { undef $row[$i] if ($row[$i] eq 'undef'); push @{$d[$i]}, $row[$i]; } } close (ZZZ); return @d; } mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample53.htm0000644000175300017510000000050613057016062023314 0ustar oetikeroep GIFgraph.pm - example 5-3

      GIFgraph.pm - example 5-3


      The code.


      mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample54.htm0000644000175300017510000000050613057016062023315 0ustar oetikeroep GIFgraph.pm - example 5-4

      GIFgraph.pm - example 5-4


      The code.


      mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample61.htm0000644000175300017510000000050613057016062023313 0ustar oetikeroep GIFgraph.pm - example 6-1

      GIFgraph.pm - example 6-1


      The code.


      mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample54.dat0000644000175300017510000010103613057016062023275 0ustar oetikeroep700.000 0.003485 699.750 -0.001097 699.500 -0.002087 699.250 0.001198 699.000 0.000286 698.750 -0.000158 698.500 0.000168 698.250 -0.000262 698.000 0.001695 697.750 0.001520 697.500 0.000413 697.250 0.001776 697.000 -0.000226 696.750 -0.001634 696.500 0.001075 696.250 0.002390 696.000 -0.000109 695.750 0.000572 695.500 0.000110 695.250 0.000005 695.000 -0.000334 694.750 -0.000543 694.500 0.000820 694.250 0.000451 694.000 0.001651 693.750 -0.000832 693.500 0.000726 693.250 0.000399 693.000 -0.001413 692.750 -0.000926 692.500 0.001384 692.250 0.000304 692.000 0.000731 691.750 0.000284 691.500 -0.001864 691.250 0.002392 691.000 -0.002022 690.750 -0.001963 690.500 0.000652 690.250 0.001707 690.000 0.001195 689.750 0.001182 689.500 0.001832 689.250 -0.001381 689.000 0.001112 688.750 0.000403 688.500 0.000576 688.250 -0.001397 688.000 0.001534 687.750 -0.000616 687.500 0.000276 687.250 -0.000747 687.000 -0.000232 686.750 -0.000382 686.500 0.000031 686.250 -0.001819 686.000 0.001683 685.750 0.000853 685.500 0.000385 685.250 0.001108 685.000 -0.001241 684.750 0.001103 684.500 0.001127 684.250 -0.000541 684.000 0.000518 683.750 0.000284 683.500 -0.000656 683.250 0.000395 683.000 0.000378 682.750 0.001463 682.500 0.001554 682.250 0.000277 682.000 0.001752 681.750 0.001333 681.500 0.002022 681.250 0.001392 681.000 0.000737 680.750 0.000205 680.500 0.001799 680.250 -0.001171 680.000 -0.000689 679.750 0.001249 679.500 0.002911 679.250 0.000199 679.000 -0.000050 678.750 -0.000738 678.500 0.000714 678.250 -0.002703 678.000 0.001025 677.750 0.000583 677.500 0.002166 677.250 0.001560 677.000 0.005364 676.750 0.001962 676.500 0.000031 676.250 0.001134 676.000 0.001617 675.750 -0.000237 675.500 -0.001913 675.250 0.000409 675.000 -0.000626 674.750 -0.000785 674.500 0.000176 674.250 0.000385 674.000 0.001106 673.750 0.000414 673.500 0.000475 673.250 0.002717 673.000 0.001492 672.750 0.002600 672.500 0.000252 672.250 0.002480 672.000 0.000457 671.750 0.000962 671.500 0.002991 671.250 0.001473 671.000 0.003620 670.750 0.001495 670.500 0.002955 670.250 0.006124 670.000 0.002939 669.750 0.000903 669.500 0.000541 669.250 -0.000725 669.000 0.001060 668.750 0.000069 668.500 0.002306 668.250 0.002930 668.000 0.001625 667.750 -0.001658 667.500 0.001622 667.250 0.002226 667.000 0.001875 666.750 0.001441 666.500 0.001486 666.250 0.001678 666.000 -0.002652 665.750 0.001211 665.500 0.001754 665.250 0.002511 665.000 -0.000742 664.750 0.003748 664.500 0.000592 664.250 0.003531 664.000 0.001268 663.750 0.002753 663.500 0.001279 663.250 0.002106 663.000 -0.000628 662.750 0.003597 662.500 0.000905 662.250 -0.001147 662.000 0.000835 661.750 0.001582 661.500 0.000192 661.250 0.002283 661.000 0.000832 660.750 0.000271 660.500 -0.000217 660.250 0.000852 660.000 0.001018 659.750 -0.000924 659.500 0.002043 659.250 0.001838 659.000 -0.000131 658.750 0.002503 658.500 0.002001 658.250 0.001777 658.000 -0.000453 657.750 0.001435 657.500 -0.000089 657.250 0.003333 657.000 0.000484 656.750 -0.001547 656.500 0.001847 656.250 0.003163 656.000 0.001798 655.750 -0.001625 655.500 0.001741 655.250 -0.000855 655.000 0.002662 654.750 0.002060 654.500 -0.000580 654.250 -0.000509 654.000 -0.001555 653.750 0.000236 653.500 0.002695 653.250 0.000810 653.000 0.000186 652.750 -0.000797 652.500 -0.001033 652.250 0.000642 652.000 0.000284 651.750 -0.000660 651.500 0.000113 651.250 0.001203 651.000 -0.000545 650.750 0.002602 650.500 -0.000550 650.250 -0.000873 650.000 0.002922 649.750 0.002667 649.500 -0.001198 649.250 -0.001668 649.000 -0.000872 648.750 0.000872 648.500 -0.000782 648.250 0.001165 648.000 0.001180 647.750 0.002938 647.500 -0.000021 647.250 0.001230 647.000 0.003165 646.750 -0.001589 646.500 -0.001688 646.250 -0.001920 646.000 -0.000839 645.750 -0.000133 645.500 0.003075 645.250 0.000394 645.000 -0.000885 644.750 -0.000866 644.500 0.001828 644.250 0.001108 644.000 -0.000129 643.750 0.000601 643.500 -0.000420 643.250 -0.000986 643.000 -0.000769 642.750 0.001334 642.500 0.000676 642.250 0.001345 642.000 -0.001207 641.750 -0.000712 641.500 0.001083 641.250 0.002568 641.000 -0.000668 640.750 -0.001999 640.500 0.000531 640.250 0.001468 640.000 0.000154 639.750 0.001899 639.500 0.000923 639.250 0.000379 639.000 0.001225 638.750 0.002069 638.500 0.000196 638.250 -0.000645 638.000 -0.000330 637.750 0.001110 637.500 0.000983 637.250 0.000027 637.000 -0.000023 636.750 -0.000348 636.500 -0.000624 636.250 0.001612 636.000 0.000451 635.750 -0.000827 635.500 0.002637 635.250 0.002549 635.000 0.001107 634.750 0.000468 634.500 0.000526 634.250 0.000395 634.000 0.000030 633.750 0.003069 633.500 0.000996 633.250 0.002051 633.000 0.001829 632.750 0.002402 632.500 0.000911 632.250 0.001727 632.000 -0.001005 631.750 0.001516 631.500 0.002026 631.250 0.001725 631.000 0.000992 630.750 -0.000457 630.500 -0.000459 630.250 0.001449 630.000 0.000957 629.750 0.001148 629.500 -0.001836 629.250 -0.002367 629.000 0.001593 628.750 0.000480 628.500 0.000451 628.250 -0.000803 628.000 0.000530 627.750 0.000069 627.500 0.001225 627.250 -0.000237 627.000 0.002603 626.750 -0.000488 626.500 -0.002227 626.250 0.001372 626.000 0.000540 625.750 0.001948 625.500 0.002627 625.250 -0.001437 625.000 0.000955 624.750 -0.000582 624.500 0.002640 624.250 -0.001048 624.000 0.002180 623.750 -0.003305 623.500 0.002353 623.250 -0.000908 623.000 0.001728 622.750 0.000160 622.500 0.001645 622.250 -0.000651 622.000 0.001856 621.750 0.001581 621.500 0.000985 621.250 0.000942 621.000 0.002110 620.750 0.000117 620.500 -0.001055 620.250 0.003015 620.000 -0.000091 619.750 0.000835 619.500 0.001019 619.250 0.002355 619.000 -0.000704 618.750 -0.000790 618.500 0.000019 618.250 -0.000134 618.000 -0.000123 617.750 0.000831 617.500 0.001568 617.250 -0.000491 617.000 0.002866 616.750 0.000143 616.500 0.000490 616.250 0.001049 616.000 0.002870 615.750 0.001223 615.500 0.000982 615.250 -0.000359 615.000 0.002900 614.750 0.000677 614.500 0.000658 614.250 0.002700 614.000 0.000002 613.750 0.000213 613.500 0.001694 613.250 -0.000312 613.000 0.000419 612.750 0.000414 612.500 0.001325 612.250 0.000094 612.000 0.001089 611.750 -0.000198 611.500 0.001635 611.250 0.000737 611.000 -0.000046 610.750 0.000068 610.500 0.001006 610.250 0.000079 610.000 0.001836 609.750 0.002766 609.500 0.001276 609.250 0.000247 609.000 0.000628 608.750 0.002193 608.500 0.002646 608.250 0.002348 608.000 0.000857 607.750 -0.000423 607.500 -0.000218 607.250 0.000280 607.000 0.001252 606.750 0.000404 606.500 0.002017 606.250 -0.000554 606.000 0.001009 605.750 0.001266 605.500 0.000968 605.250 0.000284 605.000 0.001797 604.750 0.000838 604.500 0.002422 604.250 -0.000424 604.000 -0.000080 603.750 0.000215 603.500 -0.001128 603.250 0.001883 603.000 0.000773 602.750 -0.000565 602.500 0.002195 602.250 0.000088 602.000 0.001426 601.750 0.003078 601.500 0.002494 601.250 0.000300 601.000 0.000579 600.750 0.000186 600.500 -0.000276 600.250 0.001364 600.000 0.001982 599.750 0.002404 599.500 0.001908 599.250 0.000279 599.000 -0.001049 598.750 0.002265 598.500 -0.001644 598.250 0.000101 598.000 0.001239 597.750 0.000955 597.500 0.002879 597.250 0.000817 597.000 0.001023 596.750 0.001283 596.500 0.001764 596.250 -0.000999 596.000 0.000187 595.750 0.001942 595.500 -0.000854 595.250 -0.002409 595.000 0.000357 594.750 -0.000563 594.500 0.000600 594.250 0.003749 594.000 0.000623 593.750 0.001857 593.500 0.000868 593.250 -0.000006 593.000 -0.000283 592.750 0.001902 592.500 0.002514 592.250 0.001302 592.000 0.002633 591.750 0.000916 591.500 0.002026 591.250 -0.000080 591.000 0.001555 590.750 0.000751 590.500 0.001497 590.250 0.001723 590.000 0.001914 589.750 0.000415 589.500 -0.001266 589.250 0.001488 589.000 -0.001072 588.750 0.001006 588.500 0.001584 588.250 0.000532 588.000 -0.001322 587.750 -0.000756 587.500 0.000532 587.250 -0.000355 587.000 0.001842 586.750 0.000552 586.500 0.001010 586.250 0.002049 586.000 0.000164 585.750 -0.000412 585.500 0.001661 585.250 -0.000271 585.000 -0.000731 584.750 0.000704 584.500 0.000736 584.250 0.000654 584.000 0.000001 583.750 -0.002251 583.500 0.000575 583.250 -0.000178 583.000 0.000916 582.750 0.001753 582.500 -0.000349 582.250 -0.000609 582.000 0.000580 581.750 -0.000375 581.500 0.000991 581.250 -0.000937 581.000 0.000842 580.750 0.000026 580.500 -0.000214 580.250 -0.000118 580.000 0.000073 579.750 0.000877 579.500 0.002605 579.250 0.000737 579.000 0.000471 578.750 -0.000426 578.500 0.001335 578.250 -0.000555 578.000 0.002658 577.750 0.001066 577.500 0.001994 577.250 0.000393 577.000 0.000466 576.750 0.000646 576.500 0.001826 576.250 0.001087 576.000 0.000825 575.750 -0.002147 575.500 0.000255 575.250 0.000812 575.000 0.001162 574.750 0.000711 574.500 0.000311 574.250 0.001773 574.000 0.002306 573.750 0.001012 573.500 0.000637 573.250 0.001111 573.000 0.000362 572.750 0.001144 572.500 0.000562 572.250 0.001344 572.000 0.001589 571.750 0.000117 571.500 -0.000055 571.250 -0.000233 571.000 0.000308 570.750 0.000407 570.500 0.000665 570.250 -0.000233 570.000 0.001547 569.750 -0.001147 569.500 0.000613 569.250 0.000644 569.000 0.001209 568.750 0.002192 568.500 0.000225 568.250 0.001281 568.000 0.000971 567.750 0.000647 567.500 0.002784 567.250 0.002174 567.000 0.000563 566.750 -0.000070 566.500 0.001362 566.250 -0.000124 566.000 0.000341 565.750 0.003329 565.500 0.001766 565.250 0.000939 565.000 0.000516 564.750 0.002648 564.500 0.002011 564.250 0.001208 564.000 0.000322 563.750 -0.000868 563.500 0.001683 563.250 0.000417 563.000 0.003694 562.750 0.001758 562.500 0.002178 562.250 0.002440 562.000 -0.000152 561.750 0.001334 561.500 0.002478 561.250 0.001767 561.000 0.001378 560.750 0.002441 560.500 0.001331 560.250 0.002275 560.000 0.001786 559.750 0.000310 559.500 0.001405 559.250 0.000688 559.000 0.000435 558.750 0.001321 558.500 0.000936 558.250 0.001423 558.000 0.000207 557.750 0.001619 557.500 0.000612 557.250 0.002336 557.000 -0.000278 556.750 0.000278 556.500 0.000520 556.250 0.003567 556.000 0.002057 555.750 0.001919 555.500 0.000676 555.250 0.002609 555.000 0.001933 554.750 0.000364 554.500 0.000712 554.250 0.001593 554.000 0.000677 553.750 0.003557 553.500 0.001873 553.250 0.003056 553.000 0.002430 552.750 0.001535 552.500 0.002336 552.250 0.002086 552.000 0.000928 551.750 0.001911 551.500 0.002301 551.250 0.002146 551.000 0.001152 550.750 0.002746 550.500 0.002402 550.250 0.002560 550.000 0.002081 549.750 0.001410 549.500 0.001859 549.250 0.000054 549.000 0.000729 548.750 0.001124 548.500 0.002000 548.250 0.002374 548.000 0.003516 547.750 0.001118 547.500 0.004229 547.250 0.003176 547.000 0.001539 546.750 0.002328 546.500 0.002866 546.250 0.002322 546.000 0.001054 545.750 0.002090 545.500 0.002408 545.250 0.002877 545.000 0.001585 544.750 0.002585 544.500 0.002317 544.250 0.002914 544.000 0.002064 543.750 0.002194 543.500 0.003035 543.250 0.003390 543.000 0.001940 542.750 0.003991 542.500 0.001357 542.250 0.002414 542.000 0.000320 541.750 0.002636 541.500 0.000484 541.250 0.002455 541.000 0.001985 540.750 0.002848 540.500 0.003139 540.250 0.002187 540.000 0.002249 539.750 0.002824 539.500 0.001102 539.250 0.002202 539.000 0.002262 538.750 0.002717 538.500 0.003449 538.250 0.004284 538.000 0.002760 537.750 0.001382 537.500 0.002016 537.250 0.003520 537.000 0.004057 536.750 0.001832 536.500 0.000519 536.250 0.001278 536.000 0.004109 535.750 0.003109 535.500 0.002729 535.250 0.003620 535.000 0.003616 534.750 0.005985 534.500 0.003052 534.250 0.002422 534.000 0.002318 533.750 0.003863 533.500 0.002440 533.250 0.002440 533.000 0.003424 532.750 0.003696 532.500 0.002383 532.250 0.005181 532.000 0.004266 531.750 0.003357 531.500 0.002836 531.250 0.002791 531.000 0.004392 530.750 0.004000 530.500 0.005537 530.250 0.003467 530.000 0.004364 529.750 0.006034 529.500 0.005192 529.250 0.004109 529.000 0.005158 528.750 0.003946 528.500 0.003974 528.250 0.006072 528.000 0.007039 527.750 0.005294 527.500 0.004768 527.250 0.005977 527.000 0.006458 526.750 0.004524 526.500 0.005562 526.250 0.004991 526.000 0.007509 525.750 0.006177 525.500 0.004608 525.250 0.005739 525.000 0.007256 524.750 0.006819 524.500 0.007188 524.250 0.006378 524.000 0.007247 523.750 0.007964 523.500 0.007976 523.250 0.008371 523.000 0.008495 522.750 0.007874 522.500 0.009637 522.250 0.008548 522.000 0.007169 521.750 0.008511 521.500 0.009225 521.250 0.009122 521.000 0.010348 520.750 0.009869 520.500 0.012080 520.250 0.011043 520.000 0.011500 519.750 0.011698 519.500 0.012692 519.250 0.012226 519.000 0.013552 518.750 0.012339 518.500 0.014122 518.250 0.013902 518.000 0.013401 517.750 0.014588 517.500 0.016467 517.250 0.016510 517.000 0.016411 516.750 0.017746 516.500 0.017125 516.250 0.018484 516.000 0.019682 515.750 0.020348 515.500 0.019410 515.250 0.020820 515.000 0.021084 514.750 0.023799 514.500 0.024193 514.250 0.024466 514.000 0.026420 513.750 0.024900 513.500 0.028586 513.250 0.028666 513.000 0.028609 512.750 0.030678 512.500 0.031081 512.250 0.031811 512.000 0.032660 511.750 0.033620 511.500 0.037438 511.250 0.034871 511.000 0.037713 510.750 0.038781 510.500 0.040564 510.250 0.044399 510.000 0.043881 509.750 0.046421 509.500 0.046741 509.250 0.046794 509.000 0.049522 508.750 0.052733 508.500 0.054422 508.250 0.053607 508.000 0.057517 507.750 0.060001 507.500 0.058060 507.250 0.062783 507.000 0.062952 506.750 0.067736 506.500 0.068677 506.250 0.068596 506.000 0.072423 505.750 0.074690 505.500 0.078619 505.250 0.079714 505.000 0.084549 504.750 0.085463 504.500 0.089676 504.250 0.092779 504.000 0.094395 503.750 0.097944 503.500 0.102598 503.250 0.106443 503.000 0.106442 502.750 0.112589 502.500 0.115285 502.250 0.117788 502.000 0.123433 501.750 0.126776 501.500 0.130905 501.250 0.136913 501.000 0.142013 500.750 0.144770 500.500 0.150715 500.250 0.153160 500.000 0.161046 499.750 0.165289 499.500 0.171208 499.250 0.175056 499.000 0.182432 498.750 0.186069 498.500 0.193270 498.250 0.198940 498.000 0.205717 497.750 0.208447 497.500 0.219067 497.250 0.223011 497.000 0.230423 496.750 0.237589 496.500 0.247289 496.250 0.254037 496.000 0.260339 495.750 0.266421 495.500 0.276830 495.250 0.281242 495.000 0.290877 494.750 0.301098 494.500 0.307344 494.250 0.317485 494.000 0.325439 493.750 0.335905 493.500 0.344531 493.250 0.354326 493.000 0.362063 492.750 0.372033 492.500 0.381660 492.250 0.390094 492.000 0.399778 491.750 0.404125 491.500 0.411818 491.250 0.420785 491.000 0.432287 490.750 0.442628 490.500 0.453151 490.250 0.464478 490.000 0.473760 489.750 0.485156 489.500 0.495804 489.250 0.506534 489.000 0.519081 488.750 0.530027 488.500 0.541662 488.250 0.555836 488.000 0.567276 487.750 0.579372 487.500 0.588890 487.250 0.602199 487.000 0.615152 486.750 0.627062 486.500 0.639785 486.250 0.654855 486.000 0.667859 485.750 0.678458 485.500 0.689456 485.250 0.707747 485.000 0.720609 484.750 0.729401 484.500 0.747311 484.250 0.761109 484.000 0.771278 483.750 0.788845 483.500 0.803751 483.250 0.816788 483.000 0.829087 482.750 0.842090 482.500 0.857695 482.250 0.873934 482.000 0.887415 481.750 0.902979 481.500 0.914144 481.250 0.932168 481.000 0.944113 480.750 0.960203 480.500 0.973121 480.250 0.987002 480.000 1.001077 479.750 1.017602 479.500 1.034350 479.250 1.046191 479.000 1.059908 478.750 1.079969 478.500 1.097367 478.250 1.109840 478.000 1.126115 477.750 1.140256 477.500 1.151599 477.250 1.170288 477.000 1.187523 476.750 1.200290 476.500 1.216126 476.250 1.233279 476.000 1.249161 475.750 1.265606 475.500 1.280025 475.250 1.290943 475.000 1.309434 474.750 1.326134 474.500 1.340813 474.250 1.349204 474.000 1.367864 473.750 1.377791 473.500 1.393125 473.250 1.409705 473.000 1.418322 472.750 1.431218 472.500 1.443075 472.250 1.454210 472.000 1.467261 471.750 1.485638 471.500 1.489768 471.250 1.496841 471.000 1.510198 470.750 1.522041 470.500 1.531030 470.250 1.545328 470.000 1.560172 469.750 1.570888 469.500 1.580139 469.250 1.593152 469.000 1.594805 468.750 1.605464 468.500 1.616219 468.250 1.621754 468.000 1.632535 467.750 1.644631 467.500 1.650524 467.250 1.656282 467.000 1.667263 466.750 1.673635 466.500 1.686621 466.250 1.693873 466.000 1.696128 465.750 1.704764 465.500 1.711756 465.250 1.714948 465.000 1.728853 464.750 1.729348 464.500 1.743019 464.250 1.746787 464.000 1.752885 463.750 1.760666 463.500 1.760704 463.250 1.768180 463.000 1.766523 462.750 1.778626 462.500 1.778225 462.250 1.783692 462.000 1.792741 461.750 1.797693 461.500 1.795760 461.250 1.804503 461.000 1.810953 460.750 1.813487 460.500 1.816123 460.250 1.819425 460.000 1.819624 459.750 1.816466 459.500 1.823444 459.250 1.836482 459.000 1.830087 458.750 1.834800 458.500 1.841166 458.250 1.840140 458.000 1.839459 457.750 1.836853 457.500 1.837930 457.250 1.840912 457.000 1.847599 456.750 1.847373 456.500 1.846104 456.250 1.851409 456.000 1.852811 455.750 1.850807 455.500 1.854914 455.250 1.856802 455.000 1.852359 454.750 1.853096 454.500 1.853795 454.250 1.854348 454.000 1.855929 453.750 1.856634 453.500 1.855813 453.250 1.848005 453.000 1.857326 452.750 1.851605 452.500 1.850387 452.250 1.853856 452.000 1.854881 451.750 1.847421 451.500 1.847991 451.250 1.857937 451.000 1.854583 450.750 1.858615 450.500 1.845350 450.250 1.858381 450.000 1.854062 449.750 1.851552 449.500 1.843309 449.250 1.846660 449.000 1.844071 448.750 1.839074 448.500 1.830719 448.250 1.836334 448.000 1.835399 447.750 1.834972 447.500 1.834846 447.250 1.830959 447.000 1.814837 446.750 1.825482 446.500 1.817394 446.250 1.827438 446.000 1.822202 445.750 1.819161 445.500 1.808851 445.250 1.801431 445.000 1.805995 444.750 1.810186 444.500 1.814813 444.250 1.802981 444.000 1.809521 443.750 1.807120 443.500 1.800821 443.250 1.790042 443.000 1.794777 442.750 1.783619 442.500 1.786601 442.250 1.779207 442.000 1.790295 441.750 1.787355 441.500 1.775297 441.250 1.771944 441.000 1.768527 440.750 1.766404 440.500 1.765948 440.250 1.763506 440.000 1.760175 439.750 1.753914 439.500 1.748948 439.250 1.751297 439.000 1.744780 438.750 1.738644 438.500 1.742462 438.250 1.733294 438.000 1.731909 437.750 1.724946 437.500 1.713200 437.250 1.712755 437.000 1.722690 436.750 1.696102 436.500 1.697120 436.250 1.704847 436.000 1.691638 435.750 1.690900 435.500 1.695534 435.250 1.683187 435.000 1.682039 434.750 1.667432 434.500 1.674124 434.250 1.666470 434.000 1.667341 433.750 1.649206 433.500 1.654528 433.250 1.648213 433.000 1.636745 432.750 1.640029 432.500 1.637619 432.250 1.622890 432.000 1.623684 431.750 1.619482 431.500 1.608657 431.250 1.612524 431.000 1.604380 430.750 1.592960 430.500 1.593769 430.250 1.588738 430.000 1.580874 429.750 1.583372 429.500 1.564663 429.250 1.563121 429.000 1.563412 428.750 1.549781 428.500 1.554880 428.250 1.542450 428.000 1.542101 427.750 1.526977 427.500 1.529820 427.250 1.525953 427.000 1.517332 426.750 1.513895 426.500 1.508433 426.250 1.498621 426.000 1.489842 425.750 1.488509 425.500 1.484847 425.250 1.478670 425.000 1.469083 424.750 1.459923 424.500 1.452635 424.250 1.446755 424.000 1.437943 423.750 1.435912 423.500 1.427282 423.250 1.416570 423.000 1.419523 422.750 1.407179 422.500 1.399733 422.250 1.391979 422.000 1.389844 421.750 1.384139 421.500 1.381486 421.250 1.361263 421.000 1.359125 420.750 1.347285 420.500 1.340171 420.250 1.339171 420.000 1.327270 419.750 1.318870 419.500 1.314066 419.250 1.305208 419.000 1.299636 418.750 1.290758 418.500 1.282128 418.250 1.269650 418.000 1.268674 417.750 1.259497 417.500 1.254514 417.250 1.246204 417.000 1.236159 416.750 1.230592 416.500 1.219814 416.250 1.208552 416.000 1.206094 415.750 1.201313 415.500 1.196249 415.250 1.185113 415.000 1.178991 414.750 1.176668 414.500 1.166433 414.250 1.154901 414.000 1.151682 413.750 1.140955 413.500 1.130924 413.250 1.129338 413.000 1.121470 412.750 1.109495 412.500 1.112846 412.250 1.098981 412.000 1.101536 411.750 1.094811 411.500 1.088235 411.250 1.077106 411.000 1.070724 410.750 1.065664 410.500 1.054043 410.250 1.044583 410.000 1.041445 409.750 1.035140 409.500 1.032585 409.250 1.023565 409.000 1.015033 408.750 1.008563 408.500 1.001095 408.250 0.997377 408.000 0.985273 407.750 0.984415 407.500 0.970997 407.250 0.967440 407.000 0.961576 406.750 0.950522 406.500 0.951770 406.250 0.941268 406.000 0.940969 405.750 0.927263 405.500 0.919785 405.250 0.913934 405.000 0.903149 404.750 0.899691 404.500 0.894056 404.250 0.891572 404.000 0.882521 403.750 0.875929 403.500 0.864006 403.250 0.864889 403.000 0.859166 402.750 0.850735 402.500 0.843364 402.250 0.838488 402.000 0.831549 401.750 0.827026 401.500 0.815881 401.250 0.812708 401.000 0.808612 400.750 0.801094 400.500 0.794788 400.250 0.788117 400.000 0.784465 399.750 0.779231 399.500 0.773893 399.250 0.768103 399.000 0.758542 398.750 0.750166 398.500 0.746501 398.250 0.744711 398.000 0.732846 397.750 0.729293 397.500 0.726528 397.250 0.712691 397.000 0.710217 396.750 0.705656 396.500 0.699080 396.250 0.693714 396.000 0.685906 395.750 0.676197 395.500 0.670175 395.250 0.669454 395.000 0.662164 394.750 0.654837 394.500 0.650481 394.250 0.644421 394.000 0.640018 393.750 0.631024 393.500 0.627066 393.250 0.620201 393.000 0.618361 392.750 0.610644 392.500 0.606236 392.250 0.596042 392.000 0.591400 391.750 0.584576 391.500 0.586497 391.250 0.579418 391.000 0.570761 390.750 0.571627 390.500 0.565790 390.250 0.561336 390.000 0.551768 389.750 0.547165 389.500 0.543238 389.250 0.536130 389.000 0.532471 388.750 0.530376 388.500 0.527796 388.250 0.518375 388.000 0.514024 387.750 0.511162 387.500 0.506842 387.250 0.504771 387.000 0.499727 386.750 0.492431 386.500 0.493567 386.250 0.484988 386.000 0.481181 385.750 0.477143 385.500 0.473275 385.250 0.470359 385.000 0.465429 384.750 0.460725 384.500 0.457158 384.250 0.456887 384.000 0.450583 383.750 0.443172 383.500 0.440244 383.250 0.439282 383.000 0.433423 382.750 0.436229 382.500 0.424293 382.250 0.423676 382.000 0.418072 381.750 0.416187 381.500 0.410521 381.250 0.410703 381.000 0.406220 380.750 0.405959 380.500 0.397956 380.250 0.394971 380.000 0.390174 379.750 0.388047 379.500 0.384419 379.250 0.380012 379.000 0.383473 378.750 0.374935 378.500 0.369261 378.250 0.365915 378.000 0.364646 377.750 0.362120 377.500 0.357627 377.250 0.355601 377.000 0.351923 376.750 0.349981 376.500 0.343197 376.250 0.343363 376.000 0.336080 375.750 0.338200 375.500 0.331339 375.250 0.331295 375.000 0.327159 374.750 0.324800 374.500 0.316912 374.250 0.321584 374.000 0.317157 373.750 0.314394 373.500 0.311933 373.250 0.307991 373.000 0.305850 372.750 0.300357 372.500 0.302398 372.250 0.300119 372.000 0.301788 371.750 0.294374 371.500 0.289817 371.250 0.289715 371.000 0.283722 370.750 0.284413 370.500 0.280980 370.250 0.282786 370.000 0.276642 369.750 0.277362 369.500 0.274303 369.250 0.269527 369.000 0.271239 368.750 0.263047 368.500 0.261197 368.250 0.261002 368.000 0.260707 367.750 0.256858 367.500 0.252833 367.250 0.251443 367.000 0.249702 366.750 0.251339 366.500 0.246414 366.250 0.241847 366.000 0.244070 365.750 0.239116 365.500 0.236174 365.250 0.236369 365.000 0.235509 364.750 0.228521 364.500 0.231901 364.250 0.226640 364.000 0.225582 363.750 0.225079 363.500 0.227058 363.250 0.221091 363.000 0.225328 362.750 0.217849 362.500 0.218292 362.250 0.214232 362.000 0.215715 361.750 0.210092 361.500 0.209317 361.250 0.210199 361.000 0.207231 360.750 0.205099 360.500 0.205093 360.250 0.202446 360.000 0.200532 359.750 0.203341 359.500 0.199270 359.250 0.196662 359.000 0.195995 358.750 0.191428 358.500 0.195964 358.250 0.197531 358.000 0.189168 357.750 0.191085 357.500 0.192020 357.250 0.188696 357.000 0.182438 356.750 0.184706 356.500 0.176496 356.250 0.183932 356.000 0.175004 355.750 0.178355 355.500 0.179858 355.250 0.179899 355.000 0.177043 354.750 0.175541 354.500 0.173554 354.250 0.167817 354.000 0.173603 353.750 0.176040 353.500 0.174166 353.250 0.170477 353.000 0.167256 352.750 0.164269 352.500 0.171244 352.250 0.167618 352.000 0.163031 351.750 0.163608 351.500 0.165996 351.250 0.159724 351.000 0.162176 350.750 0.160044 350.500 0.153497 350.250 0.154399 350.000 0.156709 349.750 0.159592 349.500 0.158326 349.250 0.162303 349.000 0.154231 348.750 0.143696 348.500 0.158352 348.250 0.157700 348.000 0.148508 347.750 0.156349 347.500 0.148151 347.250 0.153139 347.000 0.147673 346.750 0.148098 346.500 0.153938 346.250 0.152076 346.000 0.152298 345.750 0.142747 345.500 0.145213 345.250 0.153900 345.000 0.146978 344.750 0.147138 344.500 0.150859 344.250 0.143783 344.000 0.151068 343.750 0.148105 343.500 0.141355 343.250 0.140875 343.000 0.143040 342.750 0.146450 342.500 0.147139 342.250 0.141078 342.000 0.141793 341.750 0.153308 341.500 0.148057 341.250 0.147297 341.000 0.147653 340.750 0.150010 340.500 0.142927 340.250 0.146266 340.000 0.148453 339.750 0.156465 339.500 0.148291 339.250 0.146827 339.000 0.146956 338.750 0.148063 338.500 0.143521 338.250 0.148606 338.000 0.144162 337.750 0.153081 337.500 0.149483 337.250 0.150997 337.000 0.150044 336.750 0.153076 336.500 0.162385 336.250 0.155170 336.000 0.154031 335.750 0.146523 335.500 0.159546 335.250 0.164967 335.000 0.154491 334.750 0.149409 334.500 0.152782 334.250 0.155691 334.000 0.146996 333.750 0.157165 333.500 0.158794 333.250 0.158724 333.000 0.162895 332.750 0.161968 332.500 0.159997 332.250 0.157223 332.000 0.162192 331.750 0.160337 331.500 0.154666 331.250 0.166325 331.000 0.163170 330.750 0.160672 330.500 0.167714 330.250 0.167915 330.000 0.163880 329.750 0.164373 329.500 0.166254 329.250 0.169905 329.000 0.166488 328.750 0.171528 328.500 0.174559 328.250 0.165377 328.000 0.169938 327.750 0.175941 327.500 0.179443 327.250 0.172176 327.000 0.170810 326.750 0.179400 326.500 0.177425 326.250 0.173978 326.000 0.175459 325.750 0.175955 325.500 0.187965 325.250 0.183506 325.000 0.179989 324.750 0.184163 324.500 0.179882 324.250 0.185322 324.000 0.192224 323.750 0.190439 323.500 0.185054 323.250 0.187270 323.000 0.191856 322.750 0.192442 322.500 0.187779 322.250 0.189883 322.000 0.198279 321.750 0.190099 321.500 0.196479 321.250 0.196946 321.000 0.198823 320.750 0.202542 320.500 0.194340 320.250 0.196445 320.000 0.203024 319.750 0.199329 319.500 0.202523 319.250 0.201017 319.000 0.198086 318.750 0.199690 318.500 0.203814 318.250 0.206346 318.000 0.208664 317.750 0.209464 317.500 0.205052 317.250 0.212960 317.000 0.208087 316.750 0.214934 316.500 0.210078 316.250 0.208640 316.000 0.212058 315.750 0.209844 315.500 0.211461 315.250 0.213439 315.000 0.218150 314.750 0.214387 314.500 0.217037 314.250 0.215708 314.000 0.220565 313.750 0.221578 313.500 0.214118 313.250 0.223177 313.000 0.220233 312.750 0.222263 312.500 0.225229 312.250 0.221214 312.000 0.224047 311.750 0.226373 311.500 0.225933 311.250 0.223556 311.000 0.221582 310.750 0.220336 310.500 0.229840 310.250 0.233339 310.000 0.230065 309.750 0.230394 309.500 0.230573 309.250 0.232903 309.000 0.233199 308.750 0.239265 308.500 0.231477 308.250 0.232984 308.000 0.227587 307.750 0.230493 307.500 0.233081 307.250 0.239346 307.000 0.238054 306.750 0.236219 306.500 0.236882 306.250 0.229527 306.000 0.236100 305.750 0.241625 305.500 0.245136 305.250 0.237689 305.000 0.239350 304.750 0.243502 304.500 0.244706 304.250 0.244038 304.000 0.249938 303.750 0.246604 303.500 0.244041 303.250 0.241025 303.000 0.248219 302.750 0.238866 302.500 0.247556 302.250 0.244228 302.000 0.245991 301.750 0.251647 301.500 0.252827 301.250 0.243687 301.000 0.249091 300.750 0.256465 300.500 0.247661 300.250 0.251606 300.000 0.248964 299.750 0.252268 299.500 0.250951 299.250 0.249106 299.000 0.255694 298.750 0.257666 298.500 0.255988 298.250 0.257628 298.000 0.256609 297.750 0.253869 297.500 0.250451 297.250 0.258887 297.000 0.263199 296.750 0.257040 296.500 0.253775 296.250 0.258138 296.000 0.258213 295.750 0.261633 295.500 0.262931 295.250 0.260412 295.000 0.263835 294.750 0.267593 294.500 0.260730 294.250 0.257485 294.000 0.261625 293.750 0.261443 293.500 0.263428 293.250 0.258649 293.000 0.265758 292.750 0.271056 292.500 0.264563 292.250 0.268447 292.000 0.266045 291.750 0.263747 291.500 0.267238 291.250 0.268309 291.000 0.274134 290.750 0.272555 290.500 0.272974 290.250 0.269241 290.000 0.265992 289.750 0.274277 289.500 0.273740 289.250 0.272384 289.000 0.271253 288.750 0.274891 288.500 0.279346 288.250 0.277111 288.000 0.273747 287.750 0.277344 287.500 0.278157 287.250 0.278262 287.000 0.278972 286.750 0.280832 286.500 0.277159 286.250 0.286144 286.000 0.278156 285.750 0.277891 285.500 0.280443 285.250 0.277367 285.000 0.280821 284.750 0.277663 284.500 0.280531 284.250 0.281540 284.000 0.289916 283.750 0.279915 283.500 0.277901 283.250 0.289338 283.000 0.287156 282.750 0.284366 282.500 0.283675 282.250 0.292629 282.000 0.282890 281.750 0.284116 281.500 0.280611 281.250 0.287628 281.000 0.283177 280.750 0.287964 280.500 0.287014 280.250 0.285804 280.000 0.291663 279.750 0.284617 279.500 0.288047 279.250 0.285506 279.000 0.292081 278.750 0.289202 278.500 0.290395 278.250 0.281847 278.000 0.291420 277.750 0.289075 277.500 0.290129 277.250 0.287856 277.000 0.286223 276.750 0.291591 276.500 0.291828 276.250 0.285657 276.000 0.291369 275.750 0.282416 275.500 0.292265 275.250 0.291572 275.000 0.294789 274.750 0.289152 274.500 0.286162 274.250 0.293733 274.000 0.284931 273.750 0.288638 273.500 0.290369 273.250 0.288736 273.000 0.288824 272.750 0.293727 272.500 0.288399 272.250 0.287643 272.000 0.290198 271.750 0.288596 271.500 0.286238 271.250 0.288016 271.000 0.289589 270.750 0.287425 270.500 0.284982 270.250 0.293242 270.000 0.291171 269.750 0.291055 269.500 0.287614 269.250 0.285780 269.000 0.287755 268.750 0.289843 268.500 0.287788 268.250 0.289634 268.000 0.286127 267.750 0.285383 267.500 0.288344 267.250 0.288631 267.000 0.289175 266.750 0.285403 266.500 0.286425 266.250 0.288959 266.000 0.293827 265.750 0.287069 265.500 0.287558 265.250 0.293491 265.000 0.290901 264.750 0.290559 264.500 0.290980 264.250 0.297674 264.000 0.292210 263.750 0.289555 263.500 0.288041 263.250 0.294963 263.000 0.291411 262.750 0.293384 262.500 0.296503 262.250 0.299751 262.000 0.294547 261.750 0.293179 261.500 0.295129 261.250 0.298605 261.000 0.296387 260.750 0.303467 260.500 0.297811 260.250 0.300513 260.000 0.300330 259.750 0.301772 259.500 0.299348 259.250 0.303467 259.000 0.302518 258.750 0.308689 258.500 0.308930 258.250 0.314558 258.000 0.311470 257.750 0.307254 257.500 0.311549 257.250 0.321780 257.000 0.326667 256.750 0.330390 256.500 0.325364 256.250 0.329821 256.000 0.335945 255.750 0.333252 255.500 0.336778 255.250 0.339673 255.000 0.343333 254.750 0.338764 254.500 0.349499 254.250 0.349318 254.000 0.353904 253.750 0.356977 253.500 0.361135 253.250 0.364462 253.000 0.373863 252.750 0.372712 252.500 0.372288 252.250 0.377149 252.000 0.379380 251.750 0.379883 251.500 0.391014 251.250 0.397669 251.000 0.399963 250.750 0.413173 250.500 0.411242 250.250 0.415035 250.000 0.413945 249.750 0.424185 249.500 0.434087 249.250 0.447793 249.000 0.434247 248.750 0.446772 248.500 0.451104 248.250 0.446940 248.000 0.457072 247.750 0.464649 247.500 0.463968 247.250 0.471274 247.000 0.478035 246.750 0.472998 246.500 0.488234 246.250 0.492785 246.000 0.489170 245.750 0.497396 245.500 0.514458 245.250 0.514914 245.000 0.516976 244.750 0.533890 244.500 0.522568 244.250 0.539249 244.000 0.559919 243.750 0.544205 243.500 0.560541 243.250 0.562978 243.000 0.577710 242.750 0.578995 242.500 0.594804 242.250 0.593923 242.000 0.592221 241.750 0.599145 241.500 0.628855 241.250 0.599058 241.000 0.600732 240.750 0.601622 240.500 0.571203 240.250 0.627491 240.000 0.542981 239.750 0.581265 mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample42.pl0000644000175300017510000000160113057016062023132 0ustar oetikeroepuse GIFgraph::linespoints; print STDERR "Processing sample 4-2\n"; @data = read_data_from_csv("sample42.dat") or die "Cannot read data from sample42.dat"; $my_graph = new GIFgraph::linespoints( ); $my_graph->set( x_label => 'X Label', y_label => 'Y label', title => 'A Lines and Points Graph, reading a CSV file', y_max_value => 80, y_tick_number => 6, y_label_skip => 2, markers => [ 1, 5 ], ); $my_graph->set_legend( 'data set 1', 'data set 2' ); $my_graph->plot_to_gif( "sample42.gif", \@data ); exit; sub read_data_from_csv { my $fn = shift; my @d = (); open(ZZZ, $fn) || return (); while () { chomp; # you might want Text::CSV here my @row = split /,/; for (my $i = 0; $i <= $#row; $i++) { undef $row[$i] if ($row[$i] eq 'undef'); push @{$d[$i]}, $row[$i]; } } close (ZZZ); return @d; } mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/index.htm0000644000175300017510000000207413057016062022774 0ustar oetikeroep GIFgraph examples

      GIFgraph examples

      mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample14.htm0000644000175300017510000000050613057016062023311 0ustar oetikeroep GIFgraph.pm - example 1-4

      GIFgraph.pm - example 1-4


      The code.


      mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample13.htm0000644000175300017510000000050613057016062023310 0ustar oetikeroep GIFgraph.pm - example 1-3

      GIFgraph.pm - example 1-3


      The code.


      mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample31.htm0000644000175300017510000000063313057016062023311 0ustar oetikeroep GIFgraph.pm - example 3-1

      GIFgraph.pm - example 3-1


      The code.


      NOTE
      Notice that the green set doesn't have an entry for the 7th point. mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample92.htm0000644000175300017510000000050613057016062023317 0ustar oetikeroep GIFgraph.pm - example 9-2

      GIFgraph.pm - example 9-2


      The code.


      mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample21.pl0000644000175300017510000000110413057016062023125 0ustar oetikeroepuse GIFgraph::area; print STDERR "Processing sample 2-1\n"; @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 5, 12, 24, 33, 19, 8, 6, 15, 21], [ 1, 2, 5, 6, 3, 1.5, 1, 3, 4] ); $my_graph = new GIFgraph::area(); $my_graph->set( x_label => 'X Label', y_label => 'Y label', title => 'An Area Graph', y_max_value => 40, y_tick_number => 8, y_label_skip => 2, ); $my_graph->set_legend( 'one', 'two' ); $my_graph->plot_to_gif( "sample21.gif", \@data ); exit; mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample51.pl0000644000175300017510000000121113057016062023127 0ustar oetikeroepuse GIFgraph::lines; print STDERR "Processing sample 5-1\n"; # The reverse is in here, because I thought the falling line was # depressing, but I was too lazy to retype the data set @data = ( [ qw( Jan Feb Mar Apr May Jun Jul Aug Sep ) ], [ reverse(4, 3, 5, 6, 3, 1.5, -1, -3, -4)], ); $my_graph = new GIFgraph::lines(); $my_graph->set( x_label => 'Month', y_label => 'Measure of success', title => 'A Simple Line Graph', y_max_value => 8, y_min_value => -6, y_tick_number => 14, y_label_skip => 2, box_axis => 0, line_width => 3, ); $my_graph->plot_to_gif( "sample51.gif", \@data ); exit; mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample12.htm0000644000175300017510000000050613057016062023307 0ustar oetikeroep GIFgraph.pm - example 1-2

      GIFgraph.pm - example 1-2


      The code.


      mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample15.htm0000644000175300017510000000050613057016062023312 0ustar oetikeroep GIFgraph.pm - example 1-4

      GIFgraph.pm - example 1-5


      The code.


      mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample52.pl0000644000175300017510000000132113057016062023132 0ustar oetikeroepuse GIFgraph::lines; print STDERR "Processing sample 5-2\n"; # The reverse is in here, because I thought the falling line was # depressing, but I was too lazy to retype the data set @data = ( [ qw( Jan Feb Mar Apr May Jun Jul Aug Sep ) ], [ reverse(4, 3, 5, 6, 3, 1.5, -1, -3, -4)] ); $my_graph = new GIFgraph::lines(); $my_graph->set( x_label => 'Month', y_label => 'Measure of success', title => 'A Simple Line Graph', y_max_value => 8, y_min_value => -6, y_tick_number => 14, y_label_skip => 2, box_axis => 0, line_width => 3, zero_axis_only => 1, x_label_position => 1, y_label_position => 1, ); $my_graph->plot_to_gif( "sample52.gif", \@data ); exit; mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample52.htm0000644000175300017510000000050613057016062023313 0ustar oetikeroep GIFgraph.pm - example 5-2

      GIFgraph.pm - example 5-2


      The code.


      mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/samples/sample53.pl0000644000175300017510000000211113057016062023131 0ustar oetikeroepuse GIFgraph::lines; use GIFgraph::colour; GIFgraph::colour::read_rgb("rgb.txt") or die "Cannot read colours from rgb.txt"; print STDERR "Processing sample 5-3\n"; @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 1, 2, 5, 6, 3, 1.5, -1, -3, -4], [ -4, -3, 1, 1, -3, -1.5, -2, -1, 0], [ 9, 8, 9, 8.4, 7.1, 7.5, 8, 3, -3], [ 0.1, 0.2, 0.5, 0.4, 0.3, 0.5, 0.1, 0, 0.4], ); $my_graph = new GIFgraph::lines(); $my_graph->set( x_label => 'X Label', y_label => 'Y label', title => 'A Multiple Line Graph', y_max_value => 10, y_min_value => -5, y_tick_number => 3, y_label_skip => 1, zero_axis_only => 0, long_ticks => 1, x_ticks => 0, dclrs => [ qw( darkorchid2 mediumvioletred deeppink darkturquoise ) ], line_types => [ 1, 2, 3, 4 ], line_type_scale => 8, legend_marker_width => 24, line_width => 3, ); $my_graph->set_legend( 'one', 'two', undef, 'four' ); $my_graph->plot_to_gif( "sample53.gif", \@data ); exit; mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/points.pm0000644000175300017510000001000413057016062021351 0ustar oetikeroep#========================================================================== # Copyright (c) 1995-1998 Martien Verbruggen #-------------------------------------------------------------------------- # # Name: # GIFgraph::points.pm # # $Id: points.pm,v 1.1.1.1 2002/02/26 10:16:37 oetiker Exp $ # #========================================================================== package GIFgraph::points; use strict qw(vars refs subs); use GIFgraph::axestype; use GIFgraph::utils qw(:all); @GIFgraph::points::ISA = qw( GIFgraph::axestype ); my %Defaults = ( # The size of the marker to use in the points and linespoints graphs # in pixels marker_size => 4, ); { sub initialise() { my $s = shift; $s->SUPER::initialise(); my $key; foreach $key (keys %Defaults) { $s->set( $key => $Defaults{$key} ); } } # PRIVATE sub draw_data_set($$$) # GD::Image, \@data { my $s = shift; my $g = shift; my $d = shift; my $ds = shift; # Pick a colour my $dsci = $s->set_clr( $g, $s->pick_data_clr($ds) ); my $type = $s->pick_marker($ds); my $i; for $i (0 .. $s->{numpoints}) { next unless (defined $d->[$i]); my ($xp, $yp) = $s->val_to_pixel($i+1, $d->[$i], $ds); $s->marker( $g, $xp, $yp, $type, $dsci ); } } # Pick a marker type sub pick_marker($) # number { my $s = shift; my $num = shift; if ( exists $s->{markers} ) { return $s->{markers}[ $num % (1 + $#{$s->{markers}}) - 1 ]; } return ($num % 8) || 8; } # Draw a marker sub marker($$$$$) # $graph, $xp, $yp, type (1-7), $colourindex { my $self = shift; my ($graph, $xp, $yp, $mtype, $mclr) = @_; my $l = $xp - $self->{marker_size}; my $r = $xp + $self->{marker_size}; my $b = $yp + $self->{marker_size}; my $t = $yp - $self->{marker_size}; MARKER: { ($mtype == 1) && do { # Square, filled $graph->filledRectangle( $l, $t, $r, $b, $mclr ); last MARKER; }; ($mtype == 2) && do { # Square, open $graph->rectangle( $l, $t, $r, $b, $mclr ); last MARKER; }; ($mtype == 3) && do { # Cross, horizontal $graph->line( $l, $yp, $r, $yp, $mclr ); $graph->line( $xp, $t, $xp, $b, $mclr ); last MARKER; }; ($mtype == 4) && do { # Cross, diagonal $graph->line( $l, $b, $r, $t, $mclr ); $graph->line( $l, $t, $r, $b, $mclr ); last MARKER; }; ($mtype == 5) && do { # Diamond, filled $graph->line( $l, $yp, $xp, $t, $mclr ); $graph->line( $xp, $t, $r, $yp, $mclr ); $graph->line( $r, $yp, $xp, $b, $mclr ); $graph->line( $xp, $b, $l, $yp, $mclr ); $graph->fillToBorder( $xp, $yp, $mclr, $mclr ); last MARKER; }; ($mtype == 6) && do { # Diamond, open $graph->line( $l, $yp, $xp, $t, $mclr ); $graph->line( $xp, $t, $r, $yp, $mclr ); $graph->line( $r, $yp, $xp, $b, $mclr ); $graph->line( $xp, $b, $l, $yp, $mclr ); last MARKER; }; ($mtype == 7) && do { # Circle, filled $graph->arc( $xp, $yp, 2 * $self->{marker_size}, 2 * $self->{marker_size}, 0, 360, $mclr ); $graph->fillToBorder( $xp, $yp, $mclr, $mclr ); last MARKER; }; ($mtype == 8) && do { # Circle, open $graph->arc( $xp, $yp, 2 * $self->{marker_size}, 2 * $self->{marker_size}, 0, 360, $mclr ); last MARKER; }; } } sub draw_legend_marker($$$$) # (GD::Image, data_set_number, x, y) { my $s = shift; my $g = shift; my $n = shift; my $x = shift; my $y = shift; my $ci = $s->set_clr( $g, $s->pick_data_clr($n) ); my $old_ms = $s->{marker_size}; my $ms = _min($s->{legend_marker_height}, $s->{legend_marker_width}); ($s->{marker_size} > $ms/2) and $s->{marker_size} = $ms/2; $x += int($s->{legend_marker_width}/2); $y += int($s->{lg_el_height}/2); $n = $s->pick_marker($n); $s->marker($g, $x, $y, $n, $ci); $s->{marker_size} = $old_ms; } } # End of package GIFgraph::Points 1; mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/pie.pm0000644000175300017510000002017013057016062020617 0ustar oetikeroep#========================================================================== # Copyright (c) 1995-1998 Martien Verbruggen #-------------------------------------------------------------------------- # # Name: # GIFgraph::pie.pm # # $Id: pie.pm,v 1.1.1.1 2002/02/26 10:16:37 oetiker Exp $ # #========================================================================== package GIFgraph::pie; use strict qw(vars refs subs); use GIFgraph; use GIFgraph::legend; use GIFgraph::utils qw(:all); use GIFgraph::colour qw(:colours :lists); @GIFgraph::pie::ISA = qw( GIFgraph::legend GIFgraph ); my $ANGLE_OFFSET = 90; my %Defaults = ( # Set the height of the pie. # Because of the dependency of this on runtime information, this # is being set in GIFgraph::pie::initialise # pie_height => _round(0.1*${'gifx'}), # Do you want a 3D pie? '3d' => 1, # The angle at which to start the first data set # 0 is at the front/bottom start_angle => 0, ); { # PUBLIC methods, documented in pod sub plot($) # (\@data) { my $self = shift; my $data = shift; $self->check_data($data); $self->init_graph($self->{graph}); $self->plot_legend($self->{graph}); $self->setup_coords(); $self->draw_text($self->{graph}); $self->draw_pie($self->{graph}); $self->draw_data($data, $self->{graph}); return $self->{graph}->gif; } sub set_label_font($) # (fontname) { my $self = shift; $self->{lf} = shift; $self->set( lfw => $self->{lf}->width, lfh => $self->{lf}->height, ); } sub set_value_font($) # (fontname) { my $self = shift; $self->{vf} = shift; $self->set( vfw => $self->{vf}->width, vfh => $self->{vf}->height, ); } # Inherit defaults() from GIFgraph # PRIVATE # called on construction by new. sub initialise() { my $self = shift; $self->SUPER::initialise(); my $key; foreach $key (keys %Defaults) { $self->set( $key => $Defaults{$key} ); } $self->set( pie_height => _round(0.1 * $self->{gify}) ); $self->set_value_font(GD::gdTinyFont); $self->set_label_font(GD::gdSmallFont); } # inherit checkdata from GIFgraph # Setup the coordinate system and colours, calculate the # relative axis coordinates in respect to the gif size. sub setup_coords() { my $s = shift; # Make sure we're not reserving space we don't need. $s->set(tfh => 0) unless ( $s->{title} ); $s->set(lfh => 0) unless ( $s->{label} ); $s->set('3d' => 0) if ( $s->{pie_height} <= 0 ); $s->set(pie_height => 0) unless ( $s->{'3d'} ); # Calculate the bounding box for the pie, and # some width, height, and centre parameters $s->{bottom} = $s->{gify} - $s->{pie_height} - $s->{b_margin} - ( $s->{lfh} ? $s->{lfh} + $s->{text_space} : 0 ); $s->{top} = $s->{t_margin} + ( $s->{tfh} ? $s->{tfh} + $s->{text_space} : 0 ); $s->{left} = $s->{l_margin}; $s->{right} = $s->{gifx} - $s->{r_margin}; ( $s->{w}, $s->{h} ) = ( $s->{right}-$s->{left}, $s->{bottom}-$s->{top} ); ( $s->{xc}, $s->{yc} ) = ( ($s->{right}+$s->{left})/2, ($s->{bottom}+$s->{top})/2 ); die "Vertical Gif size too small" if ( ($s->{bottom} - $s->{top}) <= 0 ); die "Horizontal Gif size too small" if ( ($s->{right} - $s->{left}) <= 0 ); } # inherit open_graph from GIFgraph # Put the text on the canvas. sub draw_text($) # (GD::Image) { my $s = shift; my $g = shift; if ( $s->{tfh} ) { my $tx = $s->{xc} - length($s->{title}) * $s->{tfw}/2; $g->string($s->{tf}, $tx, $s->{t_margin}, $s->{title}, $s->{tci}); } if ( $s->{lfh} ) { my $tx = $s->{xc} - length($s->{label}) * $s->{lfw}/2; my $ty = $s->{gify} - $s->{b_margin} - $s->{lfh}; $g->string($s->{lf}, $tx, $ty, $s->{label}, $s->{lci}); } } # draw the pie, without the data slices sub draw_pie($) # (GD::Image) { my $s = shift; my $g = shift; my $left = $s->{xc} - $s->{w}/2; $g->arc( $s->{xc}, $s->{yc}, $s->{w}, $s->{h}, 0, 360, $s->{acci} ); $g->arc( $s->{xc}, $s->{yc} + $s->{pie_height}, $s->{w}, $s->{h}, 0, 180, $s->{acci} ) if ( $s->{'3d'} ); $g->line( $left, $s->{yc}, $left, $s->{yc} + $s->{pie_height}, $s->{acci} ); $g->line( $left + $s->{w}, $s->{yc}, $left + $s->{w}, $s->{yc} + $s->{pie_height}, $s->{acci} ); } # Draw the data slices sub draw_data($$) # (\@data, GD::Image) { my $s = shift; my $data = shift; my $g = shift; my $total = 0; my $j = 1; # for now, only one pie.. my $i; for $i ( 0 .. $s->{numpoints} ) { $total += $data->[$j][$i]; } die "no Total" unless $total; my $ac = $s->{acci}; # Accent colour my $pb = $s->{start_angle}; my $val = 0; for $i ( 0..$s->{numpoints} ) { # Set the data colour. Colours index from 1 not 0. my $dc = $s->set_clr( $g, $s->pick_data_clr($i+1) ); # Set the angles of the pie slice my $pa = $pb; $pb += 360 * $data->[1][$i]/$total; # Calculate the end points of the lines at the boundaries of # the pie slice my ($xe, $ye) = cartesian( $s->{w}/2, $pa, $s->{xc}, $s->{yc}, $s->{h}/$s->{w} ); $g->line($s->{xc}, $s->{yc}, $xe, $ye, $ac); # Draw the lines on the front of the pie $g->line($xe, $ye, $xe, $ye + $s->{pie_height}, $ac) if ( in_front($pa) && $s->{'3d'} ); # Make an estimate of a point in the middle of the pie slice # And fill it ($xe, $ye) = cartesian( 3 * $s->{w}/8, ($pa+$pb)/2, $s->{xc}, $s->{yc}, $s->{h}/$s->{w} ); $g->fillToBorder($xe, $ye, $ac, $dc); # Horrible kludge by AF # $s->put_label($g, $xe, $ye, $data->[0][$i]); # If it's 3d, colour the front ones as well if ( $s->{'3d'} ) { my ($xe, $ye) = $s->_get_pie_front_coords($pa, $pb); $g->fillToBorder($xe, $ye + $s->{pie_height}/2, $ac, $dc) if (defined($xe) && defined($ye)); } } # More horrible kludge by AF $pb = $s->{start_angle}; for $i ( 0..$s->{numpoints} ) { my $pa = $pb; $pb += 360*$data->[1][$i]/$total; my ($xe, $ye) = cartesian( 3 * $s->{w}/8, ($pa+$pb)/2, $s->{xc}, $s->{yc}, $s->{h}/$s->{w} ); $s->put_label($g, $xe, $ye, $$data[0][$i]); } } #GIFgraph::pie::draw_data sub _get_pie_front_coords($$) # (angle 1, angle 2) { my $s = shift; my $pa = level_angle(shift); my $pb = level_angle(shift); if (in_front($pa)) { if (in_front($pb)) { # both in front # don't do anything } else { # start in front, end in back $pb = $ANGLE_OFFSET; } } else { if (in_front($pb)) { # start in back, end in front $pa = $ANGLE_OFFSET - 180; } else { # both in back return; } } my ($x, $y) = cartesian( $s->{w}/2, ($pa+$pb)/2, $s->{xc}, $s->{yc}, $s->{h}/$s->{w} ); return ($x, $y); } # return true if this angle is on the front of the pie sub in_front($) # (angle) { my $a = level_angle( shift ); ( $a > ($ANGLE_OFFSET - 180) && $a < $ANGLE_OFFSET ) ? 1 : 0; } # return a value for angle between -180 and 180 sub level_angle($) # (angle) { my $a = shift; return level_angle($a-360) if ( $a > 180 ); return level_angle($a+360) if ( $a <= -180 ); return $a; } # put the label on the pie sub put_label($) # (GD:Image) { my $s = shift; my $g = shift; my ($x, $y, $label) = @_; $x -= length($label) * $s->{vfw}/2; $y -= $s->{vfw}/2; $g->string($s->{vf}, $x, $y, $label, $s->{alci}); } # return x, y coordinates from input # radius, angle, center x and y and a scaling factor (height/width) # # $ANGLE_OFFSET is used to define where 0 is meant to be sub cartesian($$$$$) { my ($r, $phi, $xi, $yi, $cr) = @_; my $PI=4*atan2(1, 1); return ( $xi + $r * cos($PI * ($phi + $ANGLE_OFFSET)/180), $yi + $cr * $r * sin($PI * ($phi + $ANGLE_OFFSET)/180) ); } } # End of package GIFgraph::pie 1; mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/WithMap.pm0000644000175300017510000001233113057016062021413 0ustar oetikeroeppackage GIFgraph::WithMap; use strict; use vars qw (@ISA %fields $AUTOLOAD $VERSION); use Carp; use CGI; use MRP::BaseClass; $VERSION = 1.0; # use AUTOLOAD to pass everything that we can't do to _GIFgraph. # don't know if this is kosha. AHHHH. sub AUTOLOAD { my $thing = shift; my ($package, $function) = $AUTOLOAD =~ m/^(.*)::([^:]+)$/; if(ref($thing)) { my $delegate = $thing->_GIFgraph; $function = join '::', $delegate, $function; return $thing->$function(@_); } die "Could not find method $AUTOLOAD via $thing"; } sub isa { my ($thing, $type) = @_; return $thing->_GIFgraph->isa($type) || $thing->SUPER::isa($type); } sub new { my $class = shift; my $GIFgraph = shift; my $baseClass = new MRP::BaseClass; my $self = $class->rebless($GIFgraph, $baseClass); $self->_GIFgraph(ref $GIFgraph); return $self; } sub draw_data { my ($self, $gd, $data) = @_; my $fuzz = $self->fuzz; my $map = ""; my $mapname = $self->mapname || confess "You must set the name for this map before calling plot"; my $seriesnames = $self->seriesnames; my $links = $self->links; my $delegateFunc = join '::', $self->_GIFgraph, 'draw_data'; $self->$delegateFunc($gd, $data); $map = ''."\n"; foreach my $series (1 .. $self->{numsets}) { my (@up, @down); foreach my $point (0 .. $self->{numpoints}) { next unless defined($$data[$series][$point]); my ($x, $y) = $self->val_to_pixel($point+1, $$data[$series][$point], $series); push @up, $x, $y+$fuzz; unshift @down, $x, $y-$fuzz; } my $seriesname = $seriesnames->[$series-1] || 'series '.$series; my $link = $links->[$series-1] || "#$seriesname"; $map .= join("\n\t", 'map($map); } BEGIN { @ISA = qw (MRP::BaseClass); %fields = ( 'fuzz' => 1, 'map' => undef, 'mapname' => undef, 'seriesnames' => [], 'links' => [], '_GIFgraph' => undef, ); GIFgraph::WithMap->check4Clashes; } $VERSION; __END__ =head1 NAME GIFgraph::WithMap - generates HTML map text while plotting graph =head1 DESCRIPTION Generates the html map block for a graph so that data series become 'clickable', =head1 SYNOPSIS This module extends GIFgraph objects such as GIFgraph::lines. You can do everything that you would with a GIFgraph object. In addition, when the data is plotted, it generates some MAP html text. The series will be labeled 'series 1', 'series 2' etc. unless the $obj->seriesnames has been set. For each series, it will create a polygon area, with the following structure (assuming series is named 'Green', and that the links member array is empty: Green So - clicking on the series will take you to #Green. If you don't specify #Green in the document, clicking on it will do very little. If you have (e.g. in the key) then it should take you there. =head1 new Use something like $map = new GIFgraph::WithMap(new GIFgraph::lines(400,300)); =head1 fields =over =item map Once plot has been called, map contains the map text. print $graphWithMap->map; =item fuzz This is the up/down fuzz used to construct the ploygon. It defaults to 1 - so the polygon will be three pixles wide (the pixle drawn and one above and below it). =item mapname Set this before calling plot. This is the name of the map, as given by usemap="#mapname" in . It is a fatal error to try to plot without a name. =item seriesnames Array of names for the series. If a name is absent for a series (or all series) then it will be named Series #. This must be set before the graph is plotted. $graphWithMap->seriesnames('name1', 'name2'); =links Array of links for the series. If a link is absent for a series (or all series) then it will be named #SeriesName (where SeriesName is generated as described in L). =back =head1 Guts This module uses MRP::BaseClass to implement member access functions. In the constructor, a new object is created that is a meld of an MRP::BaseClass derived object, and the GIFgraph object passed in. The type of that object is stoored in _GIFgraph. In AUTOLOAD, first I check to see if the GIFgraph object's package named in _GIFgraph implements the function. If it does, then I return the value of that function - i.e. it behaves as if the object inherits from that package. If that fails, then I return the value of SUPER::AUTLOLOAD, which will presumably handle it or die gracefully. Hey presto - dynamic parenting. @ISA does not include anything to implement a GIFgraph object as a parent. However, I have overridden 'isa' to account for this. mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/mixed.pm0000644000175300017510000000465213057016062021157 0ustar oetikeroep#========================================================================== # Copyright (c) 1995-1998 Martien Verbruggen #-------------------------------------------------------------------------- # # Name: # GIFgraph::mixed.pm # # $Id: mixed.pm,v 1.1.1.1 2002/02/26 10:16:37 oetiker Exp $ # #========================================================================== package GIFgraph::mixed; use strict; use GIFgraph::axestype; use GIFgraph::lines; use GIFgraph::points; use GIFgraph::linespoints; use GIFgraph::bars; use GIFgraph::area; # Even though multiple inheritance is not really a good idea, I will # do it here, because I need the functionality of the markers and the # line types We'll include axestype as the first one, to make sure # that's where we look first for methods. @GIFgraph::mixed::ISA = qw( GIFgraph::axestype GIFgraph::lines GIFgraph::points ); my %Defaults = ( default_type => 'lines', mixed => 1, ); { sub initialise() { my $s = shift; $s->SUPER::initialise(); my $key; foreach $key (keys %Defaults) { $s->set( $key => $Defaults{$key} ); } $s->GIFgraph::lines::initialise(); $s->GIFgraph::points::initialise(); $s->GIFgraph::bars::initialise(); } sub draw_data_set($$$) # GD::Image, \@data, $ds { my $s = shift; my $g = shift; my $d = shift; my $ds = shift; my $type = $s->{types}->[$ds-1] || $s->{default_type}; # Try to execute the draw_data_set function in the package # specified by type # eval '$s->GIFgraph::'.$type.'::draw_data_set($g, $d, $ds)'; # If we fail, we try it in the package specified by the # default_type, and warn the user # if ($@) { warn "Set $ds, unknown type $type, assuming $s->{default_type}\n"; eval '$s->GIFgraph::'. $s->{default_type}.'::draw_data_set($g, $d, $ds)'; } # If even that fails, we bail out # die "Set $ds: unknown default type $s->{default_type}\n" if $@; } sub draw_legend_marker($$$$) # (GD::Image, data_set_number, x, y) { my $s = shift; my $g = shift; my $ds = shift; my $x = shift; my $y = shift; my $type = $s->{types}->[$ds-1] || $s->{default_type}; eval '$s->GIFgraph::'.$type.'::draw_legend_marker($g, $ds, $x, $y)'; eval '$s->GIFgraph::'. $s->{default_type}.'::draw_legend_marker($g, $ds, $x, $y)' if $@; } } # End of package GIFgraph::linesPoints 1; mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/linespoints.pm0000644000175300017510000000301413057016062022407 0ustar oetikeroep#========================================================================== # Copyright (c) 1995-1998 Martien Verbruggen #-------------------------------------------------------------------------- # # Name: # GIFgraph::linespoints.pm # # $Id: linespoints.pm,v 1.1.1.1 2002/02/26 10:16:37 oetiker Exp $ # #========================================================================== package GIFgraph::linespoints; use strict qw(vars refs subs); use GIFgraph::axestype; use GIFgraph::lines; use GIFgraph::points; # Even though multiple inheritance is not really a good idea, # since lines and points have the same parent class, I will do it here, # because I need the functionality of the markers and the line types @GIFgraph::linespoints::ISA = qw( GIFgraph::lines GIFgraph::points ); { sub initialise() { my $s = shift; $s->GIFgraph::lines::initialise(); $s->GIFgraph::points::initialise(); } # PRIVATE sub draw_data_set($$$) # GD::Image, \@data, $ds { my $s = shift; my $g = shift; my $d = shift; my $ds = shift; $s->GIFgraph::points::draw_data_set( $g, $d, $ds ); $s->GIFgraph::lines::draw_data_set( $g, $d, $ds ); } sub draw_legend_marker($$$$) # (GD::Image, data_set_number, x, y) { my $s = shift; my $g = shift; my $n = shift; my $x = shift; my $y = shift; $s->GIFgraph::points::draw_legend_marker($g, $n, $x, $y); $s->GIFgraph::lines::draw_legend_marker($g, $n, $x, $y); } } # End of package GIFgraph::linesPoints 1; mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/install/0000755000175300017510000000000013057016062021152 5ustar oetikeroepmrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/install/README0000644000175300017510000000766413057016062022047 0ustar oetikeroepThis is GIFgraph 1.10, a package to generate GIF charts, using Lincoln Stein's GD.pm. INSTALLATION needed to install (also see TESTED PLATFORMS): perl 5.004 GD > 1.14 to install: perl Makefile.PL make make test make install NB: make test may report errors. If you are not using GD 1.18 this is normal. Because of differences in the way GD implements fonts and polygons in the various versions, the produced GIFs will differ very slightly. If you see this behaviour, please 'make' the samples in the samples directory, and check the produced GIFs visually. If they look ok, then GIFgraph is ok. to see some samples: cd samples make That should generate a set of gifs, which you can view using the HTML pages in the same directory (or whichever other way pleases you). The documentation available is contained in GIFgraph.pm, as pod. The latest release should normally be available from CPAN and from http://www.tcp.chem.tue.nl/~tgtcmv/perl/ TESTED PLATFORMS (also see NOTES FOR WIN32) Latest version: - perl 5.004_04 on Solaris 2.6, GD 1.18 - perl 5.005_02 on Solaris 2.6, GD 1.18 Version 1.01: - perl 5.004_04 on Solaris 2.5.1, GD 1.15 - perl 5.004_02 for win32 by Gurusamy Sarathy, GD (1.14 I think) - perl 5.004_04 HP-UX 10.20, GD 1.18 (Ronald Post) AUTHOR Martien Verbruggen mgjv@comdyn.com.au tgtcmv@chem.tue.nl MOST IMPORTANT CHANGES SINCE VERSION 1.04 - added bar_spacing option - added limited support for numerical X axis for equidistant X values (NOT for a real numerical graph!), thanks to Scott Prahl. - routines to automatically 'guess' nice upper and lower values for graphs have been replaced by one written by Scott Prahl MOST IMPORTANT CHANGES SINCE VERSION 1.03 - Added mixed type graph. GIFgraph::mixed options types and default_type - Added callback functionality to format y values option y_number_format - Added control over axis label placement option [xy]_label_position MOST IMPORTANT CHANGES SINCE VERSION 1.01 - Vertical printing of X axis labels - CHANGED DEFAULTS for zero_axis and zero_axis_only - Fixed problems with negative values, data ranges without 0, and printing of the x axis labels (I hope) - No more support for perl 5.003. Since perl 5.005 is out, and I don't have a 5.003 here to test all the time, I won't support it anymore. MOST IMPORTANT CHANGES SINCE VERSION 0.91 - Legends - Support for negative numbers - Ticks for X axis - line types and widths - Allow entries in data set to be undef (to skip them) - Changed 'zero' angle for pie charts (was right, now is front/bottom) - Definition of colours now possible. See GIFgraph::colour::read_rgb for details - See file CHANGES for more TODO - 3d look for graphs - logarithmic scaling - numerical X axes (halfway there) - Autoloading/splitting, etc BUG FIXES IN THIS VERSION See file BUGS NOTES FOR WIN32 GIFgraph installs and runs well under Gurusamy Sarathy's port of perl for win32, and its usage is exactly the same as documented. The ActiveState port 5.003 for win32 can be used with Dave Roth's port of GD for win32. This port, however has a peculiarity. It is impossible to manipulate the gif data in memory (the GD::Image::gif() method always writes to a file descriptor, instead of returning the data). This makes the use of GIFgraph with that port impossible without a lot of work. This means that until someone ports GD for the ActiveState perl with full support for all its functionality, GIFgraph will not work on ActiveState's port 5.003. It may very well, and _should_ work on the 5.005 ports, although I have personally not tested that yet. THANKS Scott Prahl brian d foy Honza Pazdziora Dave Belcher Vegard Vesterheim COPYRIGHT Copyright (c) 1995-1997 Martien Verbruggen. All rights reserved. This package is free software; you can redistribute it and/or modify it under the same terms as Perl itself. mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/install/CHANGES0000644000175300017510000000712213057016062022147 0ustar oetikeroepTue August 25 1998 - Fixed bug with undef values for first value in lines graphs - Changed one or two samples, and samples Makefile dependencies Tue August 25 1998 - Added bar_spacing option. - Fixed a slight drawing 'bug' while doing that. - Changed a few of the samples to use bar_spacing - Implemented numerical X axis, based on a changed axestype.pm from Scott Prahl . many thanks. - Added sample54 to illustrate Tue August 18 1998 - Added rudimentary mixed type graph Mon August 17 1998 - Added control over axis label placement through x_label_position and y_label_position. - Added possibility to call a coderef to format the y labels. See y_number_format. (Idea: brian d foy ) - Fixed some bugs (see file BUGS, version 1.04) Fri August 14 1998 - Uploaded version 1.03 to CPAN - Finally able to make some fixes - Changed defaults for zero_axis and zero_axis_only to 0. Were both 1. Needed to do this, because of all the confusion they cause - Test for defined $s->{y_(min|max)_value} (Honza Pazdziora ) (Vegard Vesterheim ) - Fixed handling of negative values (I hope) (brian d foy ) - From now on, require 5.004. 5.003 is dead, and should be deprecated now that 5.005 is out. - Added 5.005 specific MakeMaker fields to Makefile.PL Tue May 12 1998 - Cleaned up a bit, finalised version 1.02, because of time contraints, and the need to get these bug fixes out. Didn't succeed. Mon Jan 19 1998 - Fixed some bugs (see file BUGS, version 1.02) - Added option x_all_ticks, to force all x ticks to be printed, even if x_label_skip is set. - Added option x_labels_vertical, to print x labels vertical (Thanks to DBelcher for a patch) Fri Jan 9 1998 - Fixed some bugs (see file BUGS, version 1.01) - Added formatting for y labels (option y_label_format) Tue Dec 23 1997 - Changed PERL=perl5 to PERL=perl in samples/Makefile (D'OH!) - Added read_rgb to GIFgraph::colour to allow definition of own colours - Added t/colour.t - Removed a lot of unnecessary quotes all over the place Mon Dec 22 1997 - Center graph titles on axes, not on gif - Added line types - Moved initialise() to each module with $self->SUPER inheritance - Added check for duplicate GD::Image object initialisation - Added binmode() to t/ff.pl to make tests compatible with Win32 platforms (D'OH). Thu Dec 18 1997 - Allow undef values in data sets, and skip them - Added prototyping of functions - Legends, finally requests from Petter Reinholdtsen Giorgos Andreadakis Tue Dec 16 1997 - Added documentation for dclrs and markers options - removed line_width and ReadFile from the documentation (unimplemented) - Started on port to win32 - Changed Area to use Polygon and to work with negative numbers Mon Dec 15 1997 - Added support for negative numbers in lines, points and linespoints graphs - Added new options: zero_axis, and zero_axis_only (code and documentation) - Added new options: y_min_value, y1_min_value, y2_min_value Fri Dec 12 1997 - Changed 0 angle for pies to be at front/bottom, to make calculations a bit easier - Added test scripts for 'make test' Before Fri Dec 05 1997 - Lots of minor tuning - Added x_ticks option requests from Will Mitayai Keeso Rowe - thelab@nmarcom.com mparvataneni@quadravision.com (Murali Parvataneni) - Added binmode() here and there to accommodate for platforms that need it. mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/install/Makefile.PL0000644000175300017510000000146113057016062023126 0ustar oetikeroep# This -*- perl -*- script makes the Makefile # $Id: Makefile.PL,v 1.1.1.1 2002/02/26 10:16:37 oetiker Exp $ #--- Distribution section --- $MODNAME = 'GIFgraph'; BEGIN { require 5.001 } use ExtUtils::MakeMaker; my @clean = qw(*% *.html *.b[ac]k *.old .[A-z]* tags); push @clean, map { "*/$_" } @clean; WriteMakefile( 'VERSION_FROM' => $MODNAME . '.pm', #finds $VERSION 'DISTNAME' => $MODNAME, 'NAME' => $MODNAME, ($] >= 5.005 ? ('ABSTRACT' => 'Produces GIF graph plots', 'AUTHOR' => 'Martien Verbruggen (mgjv@comdyn.com.au)', ) : () ), 'PREREQ_PM' => { 'GD' => 0, }, 'dist' => { 'COMPRESS' => 'gzip -9f', 'SUFFIX' => 'gz', }, 'clean' => { 'FILES' => join(" ", @clean), }, ); mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/install/MANIFEST0000644000175300017510000000272613057016062022312 0ustar oetikeroepMANIFEST BUGS CHANGES README Makefile.PL GIFgraph.pm GIFgraph/area.pm GIFgraph/axestype.pm GIFgraph/bars.pm GIFgraph/colour.pm GIFgraph/lines.pm GIFgraph/linespoints.pm GIFgraph/mixed.pm GIFgraph/pie.pm GIFgraph/points.pm GIFgraph/utils.pm t/area.t t/area1.gif t/area2.gif t/bars.t t/bars1.gif t/bars2.gif t/colour.t t/colour_rgb.txt t/ff.pl t/legend.t t/legend1.gif t/legend2.gif t/legend3.gif t/lines.t t/lines1.gif t/linespoints.t t/linespoints1.gif t/logo.gif t/pie.t t/pie1.gif t/points.t t/points1.gif t/points2.gif samples/index.htm samples/sample11.htm samples/sample12.htm samples/sample13.htm samples/sample14.htm samples/sample15.htm samples/sample16.htm samples/sample21.htm samples/sample31.htm samples/sample41.htm samples/sample42.htm samples/sample51.htm samples/sample52.htm samples/sample53.htm samples/sample54.htm samples/sample61.htm samples/sample62.htm samples/sample91.htm samples/sample92.htm samples/sample93.htm samples/sample11.pl samples/sample12.pl samples/sample13.pl samples/sample14.pl samples/sample15.pl samples/sample16.pl samples/sample21.pl samples/sample31.pl samples/sample41.pl samples/sample42.pl samples/sample51.pl samples/sample52.pl samples/sample53.pl samples/sample54.pl samples/sample61.pl samples/sample62.pl samples/sample91.pl samples/sample92.pl samples/sample93.pl samples/sample42.dat samples/sample54.dat samples/rgb.txt samples/logo.gif samples/Makefile mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/install/BUGS0000644000175300017510000000632413057016062021642 0ustar oetikeroepUNRESOLVED BUGS + two_axes doesn't work correctly with negative numbers and zero_axis + y_max_value doesn't get adapted for bars and area if all negative values + init_graph does too much work for pies. Needs to be split up. + area chart doesn't do overwrite? Workaround: sum up your data sets, and order them backwards (highest one first). Output graph will look like it's incremental. + only bar charts do overwrite. Necessary to implement generally? NOT REALLY BUGS - The whole naming of x_label.*, x_tick.*, x_axis.* is very confused and confusing. Hard to fix without breaking backward compatibility. - overwrite == 2 only makes sense if all the data is either positive, or negative - A positive y_min_value doesn't work with bars or area, bars and area always are set off against 0. Wether this is a bug, or wanted behaviour might be a point for discussion. - y_min_value doesn't automatically get adapted for bars and area if 0 is not included in the range, but only if user sets it. If left to figure it out itself, GIFgraph does it right. FIXED IN 1.10 ! When first value of a dataset is undef for a lines graph, things go wrong. (report by Arto Nurmela ) FIXED IN 1.04 ! logo positioning and legends don't work very well together. FIXED IN 1.03 ! When data values are large, and x_min_value is larger than 0, the horizontal axis doesn't get drawm correctly. (check zero_axis option) (see sample41) (problem found after report from jackb@pgw.picker.com) FIXED IN 1.02 ! GIFgraph::Colour::read_rgb() falls over on comment lines. (reported: adamm@genomecorp.com) ! GIFgraph::Colour::read_rgb() contains inline my-declaration of $line, breaks perl5.003 (reported: Pat Becker ) ! if a colour name doesn't exist, program falls over with a cryptic message about some undefined array index. (reported: adamm@genomecorp.com) ! x_label_skip doesn't skip ticks. (also added x_all_ticks option) (reported: adamm@genomecorp.com) FIXED IN 1.01 ! for loops break in 5.003 because of 'my' scoping (grrrr) (reported: Brian Eitrem ) ! ticks get drawn in front of the data set (reported: Honza Pazdziora ) ! length estimate of y labels needs to be done better (reported: Honza Pazdziora ) FIXED IN 1.00 ! GIFgraph::colour::sorted_colour_list() syntax error ! GIFgraph::colour pod documentation fixed ! placement of title is centered on gif, not on graph. ! linespoints graph type initialises two GD::Image objects ! 'make test' fails on all tests on win32. binmode() needed. FIXED IN 0.99 ! Cannot use any 'null' values in graphs (reported: Lee Khandelwal ) FIXED IN 0.95 ! filled markers don't fill correctly when overlapping FIXED IN 0.94 ! area doesn't work with negative numbers ! Right axis doesn't get drawn when box_axis == 0 and two_axes == 1 ! Color on front of 3D pies wrong with some data sets (reported: by various people) FIXED IN 0.91 ! Segmentation fault for 3d pies where last slice is small (reported: Dave Stafford ) mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/area.pm0000644000175300017510000000333013057016062020751 0ustar oetikeroep#========================================================================== # Copyright (c) 1995-1998 Martien Verbruggen #-------------------------------------------------------------------------- # # Name: # GIFgraph::area.pm # # $Id: area.pm,v 1.1.1.1 2002/02/26 10:16:37 oetiker Exp $ # #========================================================================== package GIFgraph::area; use strict qw(vars refs subs); use GIFgraph::axestype; @GIFgraph::area::ISA = qw( GIFgraph::axestype ); { # PRIVATE sub draw_data_set($$$) # GD::Image, \@data, $ds { my $s = shift; # object reference my $g = shift; # gd object reference my $d = shift; # reference to data set my $ds = shift; # number of the data set my $num = 0; # Select a data colour my $dsci = $s->set_clr( $g, $s->pick_data_clr($ds) ); # Create a new polygon my $poly = new GD::Polygon(); # Add the first 'zero' point my ($x, $y) = $s->val_to_pixel(1, 0, $ds); $poly->addPt($x, $y); # Add the data points my $i; for $i (0 .. $s->{numpoints}) { next unless (defined $d->[$i]); ($x, $y) = $s->val_to_pixel($i + 1, $d->[$i], $ds); $poly->addPt($x, $y); $num = $i; } # Add the last zero point ($x, $y) = $s->val_to_pixel($num + 1, 0, $ds); $poly->addPt($x, $y); # Draw a filled and a line polygon $g->filledPolygon($poly, $dsci); $g->polygon($poly, $s->{acci}); # Draw the accent lines for $i (1 .. ($s->{numpoints} - 1)) { next unless (defined $d->[$i]); ($x, $y) = $s->val_to_pixel($i + 1, $d->[$i], $ds); $g->dashedLine( $x, $y, $x, $s->{zeropoint}, $s->{acci} ); } } } # End of package GIFgraph::area 1; mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/utils.pm0000644000175300017510000000302013057016062021175 0ustar oetikeroep#========================================================================== # Copyright (c) 1995-1998 Martien Verbruggen #-------------------------------------------------------------------------- # # Name: # GIFgraph::utils.pm # # Description: # Package of general utilities. # # $Id: utils.pm,v 1.1.1.1 2002/02/26 10:16:37 oetiker Exp $ # #========================================================================== package GIFgraph::utils; use strict qw(vars subs refs); use vars qw( @EXPORT_OK %EXPORT_TAGS ); require Exporter; @GIFgraph::utils::ISA = qw( Exporter ); @EXPORT_OK = qw( _max _min _round ); %EXPORT_TAGS = ( all => [qw(_max _min _round)],); $GIFgraph::utils::prog_name = 'GIFgraph::utils.pm'; $GIFgraph::utils::prog_rcs_rev = '$Revision: 1.1.1.1 $'; $GIFgraph::utils::prog_version = ($GIFgraph::utils::prog_rcs_rev =~ /\s+(\d*\.\d*)/) ? $1 : "0.0"; { sub _max { my ($a, $b) = @_; return undef if (!defined($a) and !defined($b)); return $a if (!defined($b)); return $b if (!defined($a)); ( $a >= $b ) ? $a : $b; } sub _min { my ($a, $b) = @_; return undef if (!defined($a) and !defined($b)); return $a if (!defined($b)); return $b if (!defined($a)); ( $a <= $b ) ? $a : $b; } sub _round { my($n) = shift; sprintf("%.0f", $n); } sub version { $GIFgraph::utils::prog_version; } $GIFgraph::utils::prog_name; } # End of package MVU mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/t/0000755000175300017510000000000013057016062017747 5ustar oetikeroepmrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/t/legend.t0000644000175300017510000000275713057016062021405 0ustar oetikeroepuse lib './t'; use strict; use GIFgraph::bars; use GIFgraph::area; use GIFgraph::linespoints; $::WRITE = 0; require 'ff.pl'; my @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 6, 7, -8, -2, -4, 8.5, -1, 5, 9], [ 4, 2, 5, -6, 3, -3.5, 3, -3, -4], [ -3, -7, undef, 2, -4, 8.5, 2, 5, -9], [ 4, 2, -5, 6, -3, -2.5, -3, -3, 4], ); my @opts = ( {}, { 'legend_placement' => 'RT', 'legend' => [ qw( one two three four five six ) ], }, { 'legend_placement' => 'BL', 'legend_marker_width' => 16, 'legend_marker_height' => 16, 'legend' => [ 'One is a long one', undef, "Three is here" ], }, { 'lg_cols' => 2, 'marker_size' => 10, 'legend' => [ qw( one two three four five six ) ], }, ); print "1..3\n"; ($::WARN) && warn "\n"; foreach my $i (1..3) { my $fn = 't/legend' . $i . '.gif'; my $checkImage = get_test_data($fn); my $opts = $opts[$i]; if ($i == 2) { foreach (@{$data[1]}) { $_ *= -1; } } my $g = undef; if ($i == 1) { $g = new GIFgraph::bars(); } elsif ($i == 2) { $g = new GIFgraph::area(); } else { $g = new GIFgraph::linespoints(); } $g->set( %$opts ); my $Image = $g->plot( \@data ); print (($checkImage eq $Image ? "ok" : "not ok"). " $i\n"); ($::WARN) && warn (($checkImage eq $Image ? "ok" : "not ok"). " $i\n"); write_file($fn, $Image) if ($::WRITE); } mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/t/bars.t0000644000175300017510000000306513057016062021067 0ustar oetikeroepuse lib './t'; use strict; use GIFgraph::bars; $::WRITE = 0; require 'ff.pl'; my @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 1, 2, 5, 6, 3, 1.5, 1, 3, 4], [ 3, 7, 8, 2, 4, 1.5, 2, 5, 1] ); my @opts = ( {}, { 'x_label' => 'X2 Label', 'y_label' => 'Y2 label', 'title' => 'A Double axis Bar Chart', 'y_max_value' => 20, 'y_tick_number' => 5, 'y_label_skip' => 2, 'logo' => 't/logo.gif', 'logo_resize' => 0.5, 'logo_position' => 'UR', 't_margin' => 20, 'r_margin' => 20, 'l_margin' => 20, 'b_margin' => 20, 'long_ticks' => 1, 'x_ticks' => 1, 'two_axes' => 1, 'axis_space' => 8, }, { 'x_label' => 'X Label', 'y_label' => 'Y label', 'title' => 'A Simple Bar Chart', 'y_max_value' => 8, 'y_tick_number' => 8, 'y_label_skip' => 2, 'transparent' => 1, 'interlaced' => 1, 'bgclr' => 'blue', 'fgclr' => 'lyellow', 'textclr' => 'lred', 'labelclr' => 'lblue', 'axislabelclr' => 'lgreen', 'accentclr' => 'lgray', }, ); print "1..2\n"; ($::WARN) && warn "\n"; foreach my $i (1..2) { my $fn = 't/bars' . $i . '.gif'; my $checkImage = get_test_data($fn); my $opts = $opts[$i]; my $g = new GIFgraph::bars( ); $g->set( %$opts ); my $Image = $g->plot( \@data ); print (($checkImage eq $Image ? "ok" : "not ok"). " $i\n"); ($::WARN) && warn (($checkImage eq $Image ? "ok" : "not ok"). " $i\n"); write_file($fn, $Image) if ($::WRITE); } mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/t/points.t0000644000175300017510000000236713057016062021460 0ustar oetikeroepuse lib './t'; use strict; use GIFgraph::points; $::WRITE = 0; require 'ff.pl'; my @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 3, 7, 8, 2, 4, 1.5, 2, 5, 1], [ 1, 2, 5, 6, 3, 1.5, 1, 3, 4], ); my @opts = ( {}, { 'x_label' => 'X Label', 'y_label' => 'Y label', 'title' => 'A points chart with default markers', 'y_max_value' => 10, 'y_tick_number' => 5, 'y_label_skip' => 2, 'x_ticks' => 1, }, { 'x_label' => 'X Label', 'y_label' => 'Y label', 'title' => 'A points chart with big markers', 'y_max_value' => 10, 'y_tick_number' => 5, 'y_label_skip' => 2, 'x_ticks' => 1, 'marker_size' => 16, 'long_ticks' => 1, 'markers' => [ 7, 5 ], }, ); print "1..2\n"; ($::WARN) && warn "\n"; foreach my $i (1..2) { my $fn = 't/points' . $i . '.gif'; my $checkImage = get_test_data($fn); my $opts = $opts[$i]; my $g = new GIFgraph::points( ); $g->set( %$opts ); my $Image = $g->plot( \@data ); print (($checkImage eq $Image ? "ok" : "not ok"). " $i\n"); ($::WARN) && warn (($checkImage eq $Image ? "ok" : "not ok"). " $i\n"); write_file($fn, $Image) if ($::WRITE); } mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/t/area.t0000644000175300017510000000217613057016062021052 0ustar oetikeroepuse lib './t'; use strict; use GIFgraph::area; $::WRITE = 0; require 'ff.pl'; my @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 3, 7, 8, 2, 4, 8.5, 2, 5, 9], [ 4, 2, 5, 6, 3, 2.5, 3, 3, 4], ); my @opts = ( {}, { 'x_label' => 'X Label', 'y_label' => 'Y label', 'title' => 'An area chart', 'transparent' => 1, 'interlaced' => 1, }, { 'x_label' => 'X Label', 'y_label' => 'Y label', 'title' => 'An area chart', 'y_max_value' => 10, 'transparent' => 1, 'interlaced' => 1, }, ); print "1..2\n"; ($::WARN) && warn "\n"; foreach my $i (1..2) { my $fn = 't/area' . $i . '.gif'; my $checkImage = get_test_data($fn); my $opts = $opts[$i]; if ($i == 2) { foreach (@{$data[1]}) { $_ *= -1; } } my $g = new GIFgraph::area( ); $g->set( %$opts ); my $Image = $g->plot( \@data ); print (($checkImage eq $Image ? "ok" : "not ok"). " $i\n"); ($::WARN) && warn (($checkImage eq $Image ? "ok" : "not ok"). " $i\n"); write_file($fn, $Image) if ($::WRITE); } mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/t/colour.t0000644000175300017510000000142513057016062021441 0ustar oetikeroepuse strict; use GIFgraph::colour qw( :colours :files :lists ); my $n_def = scalar @{[colour_list()]}; print "1..6\n"; # Test 1 .. 2 : read_rgb my $n = read_rgb("t/colour_rgb.txt"); print $n == 44 ? "" : "not " , "ok 1\n"; $n = scalar @{[colour_list()]}; print $n == $n_def + 44 ? "" : "not " , "ok 2\n"; # Test 3 .. 5 : _rgb, _luminance, _hue my @rgb = _rgb('light steel blue'); print $rgb[0]==176 && $rgb[1]==196 && $rgb[2]==222 ? "" : "not " , "ok 3\n"; $n = sprintf "%8f", _hue(@rgb); print $n == 0.776471 ? "" : "not " , "ok 4\n"; $n = sprintf "%8f", _luminance(@rgb); print $n == 0.759306 ? "" : "not " , "ok 5\n"; # Test 6 .. 6 : lists my @list = sorted_colour_list(10); print scalar(@list) == 10 && $list[0] eq 'white' ? "" : "not " , "ok 6\n"; mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/t/linespoints.t0000644000175300017510000000211413057016062022501 0ustar oetikeroepuse lib './t'; use strict; use GIFgraph::linespoints; $::WRITE = 0; require 'ff.pl'; my @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 1, 2, 5, 6, 3, 1.5, 1, 3, 4], [ 3, 7, 8, 2, 4, 1.5, 2, 5, 1] ); my @opts = ( {}, { 'x_label' => 'X Label', 'y_label' => 'Y label', 'title' => 'A line and point chart', 'y_max_value' => 10, 'y_tick_number' => 5, 'y_label_skip' => 2, 'x_ticks' => 1, 'axis_space' => 8, 'transparent' => 1, 'interlaced' => 1, 'markers' => [ 7, 5 ], 'marker_size' => 8, }, ); print "1..1\n"; ($::WARN) && warn "\n"; foreach my $i (1) { my $fn = 't/linespoints' . $i . '.gif'; my $checkImage = get_test_data($fn); my $opts = $opts[$i]; my $g = new GIFgraph::linespoints( ); $g->set( %$opts ); my $Image = $g->plot( \@data ); print (($checkImage eq $Image ? "ok" : "not ok"). " $i\n"); ($::WARN) && warn (($checkImage eq $Image ? "ok" : "not ok"). " $i\n"); write_file($fn, $Image) if ($::WRITE); } mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/t/colour_rgb.txt0000644000175300017510000000217413057016062022651 0ustar oetikeroep! $XConsortium: rgb.txt,v 10.41 94/02/20 18:39:36 rws Exp $ 199 21 133 medium violet red 176 196 222 light steel blue 102 139 139 paleturquoise4 159 121 238 mediumpurple2 141 182 205 lightskyblue3 0 238 118 springgreen2 255 160 122 light salmon 154 205 50 yellowgreen 178 58 238 darkorchid2 69 139 116 aquamarine4 ! This is a comment 71 60 139 slateblue4 131 111 255 slateblue1 192 255 62 olivedrab1 139 105 20 goldenrod4 205 155 29 goldenrod3 142 229 238 cadetblue2 255 211 155 burlywood1 112 128 144 slategrey 255 228 225 mistyrose 50 205 50 limegreen 224 255 255 lightcyan 218 165 32 goldenrod 220 220 220 gainsboro 135 206 255 skyblue1 240 255 240 honeydew 238 238 0 yellow2 205 79 57 tomato3 135 206 235 skyblue 85 26 139 purple4 205 133 0 orange3 205 183 158 bisque3 238 213 183 bisque2 87 87 87 grey34 252 252 252 gray99 161 161 161 gray63 112 112 112 gray44 94 94 94 gray37 84 84 84 gray33 66 66 66 gray26 240 255 255 azure1 139 137 137 snow4 205 133 63 peru 219 112 147 pale violet red 139 129 76 lightgoldenrod4 mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/t/ff.pl0000644000175300017510000000101313057016062020672 0ustar oetikeroepuse strict; $::WRITE = 1 if (defined($ARGV[0]) and $ARGV[0] eq '--write'); $::WARN = 0; sub get_test_data { my $fn = shift; local($/); undef $/; open(GIF, $fn) or die "Cannot open $fn: $!\n"; binmode(GIF); my $im = ; close (GIF); return defined($im) ? $im : ""; } sub write_file { my $fn = shift; my $im = shift; local($/); undef $/; print "writing\n"; open(GIF, '>' . $fn) or die "Cannot open $fn: $!\n"; binmode(GIF); print GIF $im; close (GIF); } 1; mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/t/pie.t0000644000175300017510000000135513057016062020715 0ustar oetikeroepuse lib './t'; use strict; use GIFgraph::pie; $::WRITE = 0; require 'ff.pl'; my @data = ( ["1st","2nd","3rd","4th","5th","6th"], [ 1, 2, 5, 6, 3, 1.5], ); my @opts = ( {}, { 'start_angle' => 90, 'title' => 'A pie chart', 'label' => 'Just data', }, ); print "1..1\n"; ($::WARN) && warn "\n"; foreach my $i (1) { my $fn = 't/pie' . $i . '.gif'; my $checkImage = get_test_data($fn); my $opts = $opts[$i]; my $g = new GIFgraph::pie( ); $g->set( %$opts ); my $Image = $g->plot( \@data ); print (($checkImage eq $Image ? "ok" : "not ok"). " $i\n"); ($::WARN) && warn (($checkImage eq $Image ? "ok" : "not ok"). " $i\n"); write_file($fn, $Image) if ($::WRITE); } mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/t/lines.t0000644000175300017510000000206313057016062021247 0ustar oetikeroepuse lib './t'; use strict; use GIFgraph::lines; $::WRITE = 0; require 'ff.pl'; my @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 9, 2, 5, 6, 3, 1.5, 9, 3, 4], [ 3, 7, 8, 2, 4, 1.5, 2, 5, 1] ); my @opts = ( {}, { 'x_label' => 'X Label', 'y_label' => 'Y label', 'title' => 'A line chart', 'y_max_value' => 11, 'y_min_value' => 1, 'y_tick_number' => 5, 'y_label_skip' => 2, 'x_ticks' => 1, 'axis_space' => 8, 'transparent' => 1, 'interlaced' => 1, 'line_types' => [3,4,1,2], }, ); print "1..1\n"; ($::WARN) && warn "\n"; foreach my $i (1) { my $fn = 't/lines' . $i . '.gif'; my $checkImage = get_test_data($fn); my $opts = $opts[$i]; my $g = new GIFgraph::lines( ); $g->set( %$opts ); my $Image = $g->plot( \@data ); print (($checkImage eq $Image ? "ok" : "not ok"). " $i\n"); ($::WARN) && warn (($checkImage eq $Image ? "ok" : "not ok"). " $i\n"); write_file($fn, $Image) if ($::WRITE); } mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/bars.pm0000644000175300017510000000722613057016062021000 0ustar oetikeroep#========================================================================== # Copyright (c) 1995-1998 Martien Verbruggen #-------------------------------------------------------------------------- # # Name: # GIFgraph::bars.pm # # $Id: bars.pm,v 1.1.1.1 2002/02/26 10:16:37 oetiker Exp $ # #========================================================================== package GIFgraph::bars; use strict qw(vars refs subs); use GIFgraph::axestype; use GIFgraph::utils qw(:all); @GIFgraph::bars::ISA = qw( GIFgraph::axestype ); my %Defaults = ( # Spacing between the bars bar_spacing => 0, ); { sub initialise() { my $self = shift; $self->SUPER::initialise(); my $key; foreach $key (keys %Defaults) { $self->set( $key => $Defaults{$key} ); } } # PRIVATE sub draw_data{ my $s = shift; my $g = shift; my $d = shift; if ( $s->{overwrite} ) { $s->draw_data_overwrite($g, $d); } else { $s->SUPER::draw_data($g, $d); } # redraw the 'zero' axis $g->line( $s->{left}, $s->{zeropoint}, $s->{right}, $s->{zeropoint}, $s->{fgci} ); } # Draws the bars on top of each other sub draw_data_overwrite { my $s = shift; my $g = shift; my $d = shift; my $bar_s = _round($s->{bar_spacing}/2); my $zero = $s->{zeropoint}; my $i; for $i (0 .. $s->{numpoints}) { my $bottom = $zero; my ($xp, $t); my $j; for $j (1 .. $s->{numsets}) { next unless (defined $d->[$j][$i]); # get data colour my $dsci = $s->set_clr( $g, $s->pick_data_clr($j) ); # get coordinates of top and center of bar ($xp, $t) = $s->val_to_pixel($i + 1, $d->[$j][$i], $j); # calculate left and right of bar my $l = $xp - _round($s->{x_step}/2) + $bar_s; my $r = $xp + _round($s->{x_step}/2) - $bar_s; # calculate new top $t -= ($zero - $bottom) if ($s->{overwrite} == 2); # draw the bar if ($d->[$j][$i] >= 0) { # positive value $g->filledRectangle( $l, $t, $r, $bottom, $dsci ); $g->rectangle( $l, $t, $r, $bottom, $s->{acci} ); } else { # negative value $g->filledRectangle( $l, $bottom, $r, $t, $dsci ); $g->rectangle( $l, $bottom, $r, $t, $s->{acci} ); } # reset $bottom to the top $bottom = $t if ($s->{overwrite} == 2); } } } sub draw_data_set($$$) { my $s = shift; my $g = shift; my $d = shift; my $ds = shift; my $bar_s = _round($s->{bar_spacing}/2); # Pick a data colour my $dsci = $s->set_clr( $g, $s->pick_data_clr($ds) ); my $i; for $i (0 .. $s->{numpoints}) { next unless (defined $d->[$i]); # get coordinates of top and center of bar my ($xp, $t) = $s->val_to_pixel($i + 1, $d->[$i], $ds); # calculate left and right of bar my ($l, $r); if ($s->{mixed}) { $l = $xp - _round($s->{x_step}/2) + $bar_s; $r = $xp + _round($s->{x_step}/2) - $bar_s; } else { $l = $xp - _round($s->{x_step}/2) + _round(($ds - 1) * $s->{x_step}/$s->{numsets}) + $bar_s; $r = $xp - _round($s->{x_step}/2) + _round($ds * $s->{x_step}/$s->{numsets}) - $bar_s; } # draw the bar if ($d->[$i] >= 0) { # positive value $g->filledRectangle( $l, $t, $r, $s->{zeropoint}, $dsci ); $g->rectangle( $l, $t, $r, $s->{zeropoint}, $s->{acci} ); } else { # negative value $g->filledRectangle( $l, $s->{zeropoint}, $r, $t, $dsci ); $g->rectangle( $l, $s->{zeropoint}, $r, $t, $s->{acci} ); } } } } # End of package GIFgraph::bars 1; mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph/axestype.pm0000644000175300017510000005151213057016062021710 0ustar oetikeroep#========================================================================== # Copyright (c) 1995-1998 Martien Verbruggen #-------------------------------------------------------------------------- # # Name: # GIFgraph::axestype.pm # # $Id: axestype.pm,v 1.1.1.1 2002/02/26 10:16:37 oetiker Exp $ # #========================================================================== package GIFgraph::axestype; use strict; use GIFgraph; use GIFgraph::legend; use GIFgraph::utils qw(:all); @GIFgraph::axestype::ISA = qw( GIFgraph::legend GIFgraph ); my %Defaults = ( # Set the length for the 'short' ticks on the axes. tick_length => 4, # Do you want ticks to span the entire width of the graph? long_ticks => 0, # Number of ticks for the y axis y_tick_number => 5, x_tick_number => undef, # CONTRIB Scott Prahl # Skip every nth label. if 1 will print every label on the axes, # if 2 will print every second, etc.. x_label_skip => 1, y_label_skip => 1, # Do we want ticks on the x axis? x_ticks => 1, x_all_ticks => 0, # Where to place the x and y labels x_label_position => 3/4, y_label_position => 1/2, # vertical printing of x labels x_labels_vertical => 0, # Draw axes as a box? (otherwise just left and bottom) box_axis => 1, # Use two different axes for the first and second dataset. The first # will be displayed using the left axis, the second using the right # axis. You cannot use more than two datasets when this option is on. two_axes => 0, # Print values on the axes? x_plot_values => 1, y_plot_values => 1, # Space between axis and text axis_space => 4, # Do you want bars to be drawn on top of each other, or side by side? overwrite => 0, # Draw the zero axis in the graph in case there are negative values zero_axis => 0, # Draw the zero axis, but do not draw the bottom axis, in case # box-axis == 0 # This also moves the x axis labels to the zero axis zero_axis_only => 0, # Format of the numbers on the x and y axis y_number_format => undef, x_number_format => undef, # CONTRIB Scott Prahl ); { # PUBLIC sub plot($) # (\@data) { my $self = shift; my $data = shift; $self->check_data($data); $self->init_graph($self->{graph}); $self->plot_legend($self->{graph}); $self->setup_coords($data); $self->draw_text($self->{graph}); $self->draw_axes($self->{graph}, $data); $self->draw_ticks($self->{graph}, $data); $self->draw_data($self->{graph}, $data); return $self->{graph}->gif } sub set_x_label_font($) # (fontname) { my $self = shift; $self->{xlf} = shift; $self->set( xlfw => $self->{xlf}->width, xlfh => $self->{xlf}->height, ); } sub set_y_label_font($) # (fontname) { my $self = shift; $self->{ylf} = shift; $self->set( ylfw => $self->{ylf}->width, ylfh => $self->{ylf}->height, ); } sub set_x_axis_font($) # (fontname) { my $self = shift; $self->{xaf} = shift; $self->set( xafw => $self->{xaf}->width, xafh => $self->{xaf}->height, ); } sub set_y_axis_font($) # (fontname) { my $self = shift; $self->{yaf} = shift; $self->set( yafw => $self->{yaf}->width, yafh => $self->{yaf}->height, ); } # PRIVATE # called on construction, by new # use inherited defaults sub initialise() { my $self = shift; $self->SUPER::initialise(); my $key; foreach $key (keys %Defaults) { $self->set( $key => $Defaults{$key} ); } $self->set_x_label_font(GD::gdSmallFont); $self->set_y_label_font(GD::gdSmallFont); $self->set_x_axis_font(GD::gdTinyFont); $self->set_y_axis_font(GD::gdTinyFont); } # inherit check_data from GIFgraph sub setup_coords($) { my $s = shift; my $data = shift; # Do some sanity checks $s->{two_axes} = 0 if ( $s->{numsets} != 2 || $s->{two_axes} < 0 ); $s->{two_axes} = 1 if ( $s->{two_axes} > 1 ); delete $s->{y_label2} unless ($s->{two_axes}); # Set some heights for text $s->set( tfh => 0 ) unless ( $s->{title} ); $s->set( xlfh => 0 ) unless ( $s->{x_label} ); if ( ! $s->{y1_label} && $s->{y_label} ) { $s->{y1_label} = $s->{y_label}; } $s->set( ylfh1 => $s->{y1_label} ? 1 : 0 ); $s->set( ylfh2 => $s->{y2_label} ? 1 : 0 ); $s->set( xafh => 0, xafw => 0 ) unless ($s->{x_plot_values}); $s->set( yafh => 0, yafw => 0 ) unless ($s->{y_plot_values}); $s->{x_axis_label_height} = $s->get_x_axis_label_height($data); my $lbl = ($s->{xlfh} ? 1 : 0) + ($s->{xafh} ? 1 : 0); # calculate the top and bottom of the bounding box for the graph $s->{bottom} = $s->{gify} - $s->{b_margin} - 1 - ( $s->{xlfh} ? $s->{xlfh} : 0 ) - ( $s->{x_axis_label_height} ? $s->{x_axis_label_height} : 0) - ( $lbl ? $lbl * $s->{text_space} : 0 ); $s->{top} = $s->{t_margin} + ( $s->{tfh} ? $s->{tfh} + $s->{text_space} : 0 ); $s->{top} = $s->{yafh}/2 if ( $s->{top} == 0 ); $s->set_max_min($data); # Create the labels for the y_axes, and calculate the max length $s->create_y_labels(); $s->create_x_labels(); # CONTRIB Scott Prahl # calculate the left and right of the bounding box for the graph my $ls = $s->{yafw} * $s->{y_label_len}[1]; $s->{left} = $s->{l_margin} + ( $ls ? $ls + $s->{axis_space} : 0 ) + ( $s->{ylfh1} ? $s->{ylfh} + $s->{text_space} : 0 ); $ls = $s->{yafw} * $s->{y_label_len}[2] if $s->{two_axes}; $s->{right} = $s->{gifx} - $s->{r_margin} - 1 - $s->{two_axes} * ( ( $ls ? $ls + $s->{axis_space} : 0 ) + ( $s->{ylfh2} ? $s->{ylfh} + $s->{text_space} : 0 ) ); # CONTRIB Scott Prahl # make sure that we can generate valid x tick marks undef($s->{x_tick_number}) if $s->{numpoints} < 2; undef($s->{x_tick_number}) if ( !defined $s->{x_max} || !defined $s->{x_min} || $s->{x_max} == $s->{x_min} ); # calculate the step size for x data # CONTRIB Changes by Scott Prahl if (defined $s->{x_tick_number}) { my $delta = ($s->{right}-$s->{left})/($s->{x_max}-$s->{x_min}); $s->{x_offset} = ($s->{true_x_min} - $s->{x_min}) * $delta + $s->{left}; $s->{x_step} = ($s->{true_x_max} - $s->{true_x_min}) * $delta/$s->{numpoints}; } else { $s->{x_step} = ($s->{right} - $s->{left})/($s->{numpoints} + 2); $s->{x_offset} = $s->{left}; } # get the zero axis level my $dum; ($dum, $s->{zeropoint}) = $s->val_to_pixel(0, 0, 1); # Check the size die "Vertical Gif size too small" if ( ($s->{bottom} - $s->{top}) <= 0 ); die "Horizontal Gif size too small" if ( ($s->{right} - $s->{left}) <= 0 ); # More sanity checks $s->{x_label_skip} = 1 if ( $s->{x_label_skip} < 1 ); $s->{y_label_skip} = 1 if ( $s->{y_label_skip} < 1 ); $s->{y_tick_number} = 1 if ( $s->{y_tick_number} < 1 ); } sub create_y_labels { my $s = shift; $s->{y_label_len}[1] = 0; $s->{y_label_len}[2] = 0; my $t; foreach $t (0 .. $s->{y_tick_number}) { my $a; foreach $a (1 .. ($s->{two_axes} + 1)) { my $label = $s->{y_min}[$a] + $t * ($s->{y_max}[$a] - $s->{y_min}[$a])/$s->{y_tick_number}; $s->{y_values}[$a][$t] = $label; if (defined $s->{y_number_format}) { if (ref $s->{y_number_format} eq 'CODE') { $label = &{$s->{y_number_format}}($label); } else { $label = sprintf($s->{y_number_format}, $label); } } my $len = length($label); $s->{y_labels}[$a][$t] = $label; ($len > $s->{y_label_len}[$a]) and $s->{y_label_len}[$a] = $len; } } } # CONTRIB Scott Prahl sub create_x_labels { my $s = shift; return unless defined($s->{x_tick_number}); $s->{x_label_len} = 0; my $t; foreach $t (0..$s->{x_tick_number}) { my $label = $s->{x_min} + $t * ($s->{x_max} - $s->{x_min})/$s->{x_tick_number}; $s->{x_values}[$t] = $label; if (defined $s->{x_number_format}) { if (ref $s->{x_number_format} eq 'CODE') { $label = &{$s->{x_number_format}}($label); } else { $label = sprintf($s->{x_number_format}, $label); } } my $len = length($label); $s->{x_labels}[$t] = $label; ($len > $s->{x_label_len}) and $s->{x_label_len} = $len; } } sub get_x_axis_label_height { my $s = shift; my $data = shift; return $s->{xafh} unless $s->{x_labels_vertical}; my $len = 0; my $labels = $data->[0]; my $label; foreach $label (@$labels) { my $llen = length($label); ($llen > $len) and $len = $llen; } return $len * $s->{xafw} } # inherit open_graph from GIFgraph sub draw_text($) # GD::Image { my $s = shift; my $g = shift; # Title if ($s->{tfh}) { my $tx = $s->{left} + ($s->{right} - $s->{left})/2 - length($s->{title}) * $s->{tfw}/2; my $ty = $s->{top} - $s->{text_space} - $s->{tfh}; $g->string($s->{tf}, $tx, $ty, $s->{title}, $s->{tci}); } # X label if ($s->{xlfh}) { my $tx = $s->{left} + $s->{x_label_position} * ($s->{right} - $s->{left}) - $s->{x_label_position} * length($s->{x_label}) * $s->{xlfw}; my $ty = $s->{gify} - $s->{xlfh} - $s->{b_margin}; $g->string($s->{xlf}, $tx, $ty, $s->{x_label}, $s->{lci}); } # Y labels if ($s->{ylfh1}) { my $tx = $s->{l_margin}; my $ty = $s->{bottom} - $s->{y_label_position} * ($s->{bottom} - $s->{top}) + $s->{y_label_position} * length($s->{y1_label}) * $s->{ylfw}; $g->stringUp($s->{ylf}, $tx, $ty, $s->{y1_label}, $s->{lci}); } if ( $s->{two_axes} && $s->{ylfh2} ) { my $tx = $s->{gifx} - $s->{ylfh} - $s->{r_margin}; my $ty = $s->{bottom} - $s->{y_label_position} * ($s->{bottom} - $s->{top}) + $s->{y_label_position} * length($s->{y2_label}) * $s->{ylfw}; $g->stringUp($s->{ylf}, $tx, $ty, $s->{y2_label}, $s->{lci}); } } sub draw_axes($) # GD::Image { my $s = shift; my $g = shift; my $d = shift; my ($l, $r, $b, $t) = ( $s->{left}, $s->{right}, $s->{bottom}, $s->{top} ); if ( $s->{box_axis} ) { $g->rectangle($l, $t, $r, $b, $s->{fgci}); } else { $g->line($l, $t, $l, $b, $s->{fgci}); $g->line($l, $b, $r, $b, $s->{fgci}) unless ($s->{zero_axis_only}); $g->line($r, $b, $r, $t, $s->{fgci}) if ($s->{two_axes}); } if ($s->{zero_axis} or $s->{zero_axis_only}) { my ($x, $y) = $s->val_to_pixel(0, 0, 1); $g->line($l, $y, $r, $y, $s->{fgci}); } } # # Ticks and values for y axes # sub draw_y_ticks($$) # GD::Image, \@data { my $s = shift; my $g = shift; my $d = shift; # # Ticks and values for y axes # my $t; foreach $t (0 .. $s->{y_tick_number}) { my $a; foreach $a (1 .. ($s->{two_axes} + 1)) { my $value = $s->{y_values}[$a][$t]; my $label = $s->{y_labels}[$a][$t]; my ($x, $y) = $s->val_to_pixel(0, $value, $a); #my ($x, $y) = $s->val_to_pixel( # ($a-1) * ($s->{numpoints} + 2), # $value, # $a #); $x = ($a == 1) ? $s->{left} : $s->{right}; if ($s->{long_ticks}) { $g->line( $x, $y, $x + $s->{right} - $s->{left}, $y, $s->{fgci} ) unless ($a-1); } else { $g->line( $x, $y, $x + (3 - 2 * $a) * $s->{tick_length}, $y, $s->{fgci} ); } next if ( $t % ($s->{y_label_skip}) || ! $s->{y_plot_values} ); $x -= (2-$a) * length($label) * $s->{yafw} + (3 - 2 * $a) * $s->{axis_space}; $y -= $s->{yafh}/2; $g->string($s->{yaf}, $x, $y, $label, $s->{alci}); } } } # # Ticks and values for x axes # sub draw_x_ticks($$) # GD::Image, \@data { my $s = shift; my $g = shift; my $d = shift; # # Ticks and values for X axis # my $i; for $i (0 .. $s->{numpoints}) { my ($x, $y) = $s->val_to_pixel($i + 1, 0, 1); $y = $s->{bottom} unless $s->{zero_axis_only}; next if ( !$s->{x_all_ticks} and $i%($s->{x_label_skip}) and $i != $s->{numpoints} ); if ($s->{x_ticks}) { if ($s->{long_ticks}) { $g->line( $x, $s->{bottom}, $x, $s->{top}, $s->{fgci} ); } else { $g->line( $x, $y, $x, $y - $s->{tick_length}, $s->{fgci} ); } } next if ( $i%($s->{x_label_skip}) and $i != $s->{numpoints} ); if ($s->{x_labels_vertical}) { $x -= $s->{xafw}; my $yt = $y + $s->{text_space}/2 + $s->{xafw} * length($d->[0][$i]); $g->stringUp($s->{xaf}, $x, $yt, $d->[0][$i], $s->{alci}); } else { $x -= $s->{xafw} * length($d->[0][$i])/2; my $yt = $y + $s->{text_space}/2; $g->string($s->{xaf}, $x, $yt, $d->[0][$i], $s->{alci}); } } } # CONTRIB Scott Prahl # Assume x array contains equally spaced x-values # and generate an appropriate axis # sub draw_x_ticks_number($$) # GD::Image, \@data { my $s = shift; my $g = shift; my $d = shift; my $i; for $i (0 .. $s->{x_tick_number}) { my $value = $s->{numpoints} * ($s->{x_values}[$i] - $s->{true_x_min}) / ($s->{true_x_max} - $s->{true_x_min}); my $label = $s->{x_values}[$i]; my ($x, $y) = $s->val_to_pixel($value + 1, 0, 1); $y = $s->{bottom} unless $s->{zero_axis_only}; if ($s->{x_ticks}) { if ($s->{long_ticks}) { $g->line($x, $s->{bottom}, $x, $s->{top},$s->{fgci}); } else { $g->line( $x, $y, $x, $y - $s->{tick_length}, $s->{fgci} ); } } next if ( $i%($s->{x_label_skip}) and $i != $s->{x_tick_number} ); if ($s->{x_labels_vertical}) { $x -= $s->{xafw}; my $yt = $y + $s->{text_space}/2 + $s->{xafw} * length($d->[0][$i]); $g->stringUp($s->{xaf}, $x, $yt, $label, $s->{alci}); } else { # $x -= $s->{xafw} * length($$d[0][$i])/2; $x -= length($d->[0][$i])/2; my $yt = $y + $s->{text_space}/2; $g->string($s->{xaf}, $x, $yt, $label, $s->{alci}); } } } sub draw_ticks($$) # GD::Image, \@data { my $s = shift; my $g = shift; my $d = shift; $s->draw_y_ticks($g, $d); return unless ( $s->{x_plot_values} ); if (defined $s->{x_tick_number}) { $s->draw_x_ticks_number($g, $d); } else { $s->draw_x_ticks($g, $d); } } sub draw_data($$) # GD::Image, \@data { my $s = shift; my $g = shift; my $d = shift; my $ds; foreach $ds (1 .. $s->{numsets}) { $s->draw_data_set($g, $d->[$ds], $ds); } } # draw_data_set is in sub classes sub draw_data_set() { # ABSTRACT my $s = shift; $s->die_abstract( "sub draw_data missing, ") } # Figure out the maximum values for the vertical exes, and calculate # a more or less sensible number for the tops. sub set_max_min($) { my $s = shift; my $d = shift; my @max_min; # First, calculate some decent values if ( $s->{two_axes} ) { my $i; for $i (1 .. 2) { my $true_y_min = get_min_y(@{$$d[$i]}); my $true_y_max = get_max_y(@{$$d[$i]}); ($s->{y_min}[$i], $s->{y_max}[$i], $s->{y_tick_number}) = _best_ends($true_y_min, $true_y_max, $s->{y_tick_number}); } } else { my ($true_y_min, $true_y_max) = $s->get_max_min_y_all($d); ($s->{y_min}[1], $s->{y_max}[1], $s->{y_tick_number}) = _best_ends($true_y_min, $true_y_max, $s->{y_tick_number}); } if (defined( $s->{x_tick_number} )) { $s->{true_x_min} = get_min_y(@{$d->[0]}); $s->{true_x_max} = get_max_y(@{$d->[0]}); ($s->{x_min}, $s->{x_max}, $s->{x_tick_number}) = _best_ends( $s->{true_x_min}, $s->{true_x_max}, $s->{x_tick_number}); } # Make sure bars and area always have a zero offset if (ref($s) eq 'GIFgraph::bars' or ref($s) eq 'GIFgraph::area') { $s->{y_min}[1] = 0 if $s->{y_min}[1] > 0; $s->{y_min}[2] = 0 if $s->{y_min}[2] && $s->{y_min}[2] > 0; } # Overwrite these with any user supplied ones $s->{y_min}[1] = $s->{y_min_value} if defined $s->{y_min_value}; $s->{y_min}[2] = $s->{y_min_value} if defined $s->{y_min_value}; $s->{y_max}[1] = $s->{y_max_value} if defined $s->{y_max_value}; $s->{y_max}[2] = $s->{y_max_value} if defined $s->{y_max_value}; $s->{y_min}[1] = $s->{y1_min_value} if defined $s->{y1_min_value}; $s->{y_max}[1] = $s->{y1_max_value} if defined $s->{y1_max_value}; $s->{y_min}[2] = $s->{y2_min_value} if defined $s->{y2_min_value}; $s->{y_max}[2] = $s->{y2_max_value} if defined $s->{y2_max_value}; $s->{x_min} = $s->{x_min_value} if defined $s->{x_min_value}; $s->{x_max} = $s->{x_max_value} if defined $s->{x_max_value}; # Check to see if we have sensible values if ( $s->{two_axes} ) { my $i; for $i (1 .. 2) { die "Minimum for y" . $i . " too large\n" if ( $s->{y_min}[$i] > get_min_y(@{$d->[$i]}) ); die "Maximum for y" . $i . " too small\n" if ( $s->{y_max}[$i] < get_max_y(@{$d->[$i]}) ); } } # else # { # die "Minimum for y too large\n" # if ( $s->{y_min}[1] > $max_min[1] ); # die "Maximum for y too small\n" # if ( $s->{y_max}[1] < $max_min[0] ); # } } # return maximum value from an array sub get_max_y(@) # array { my $max = undef; my $i; foreach $i (@_) { next unless defined $i; $max = (defined($max) && $max >= $i) ? $max : $i; } return $max } sub get_min_y(@) # array { my $min = undef; my $i; foreach $i (@_) { next unless defined $i; $min = ( defined($min) and $min <= $i) ? $min : $i; } return $min } # get maximum y value from the whole data set sub get_max_min_y_all($) # \@data { my $s = shift; my $d = shift; my $max = undef; my $min = undef; if ($s->{overwrite} == 2) { my $i; for $i (0 .. $s->{numpoints}) { my $sum = 0; my $j; for $j (1 .. $s->{numsets}) { $sum += $d->[$j][$i]; } $max = _max( $max, $sum ); $min = _min( $min, $sum ); } } else { my $i; for $i ( 1 .. $s->{numsets} ) { $max = _max( $max, get_max_y(@{$d->[$i]}) ); $min = _min( $min, get_min_y(@{$d->[$i]}) ); } } return ($max, $min) } # CONTRIB Scott Prahl # # Calculate best endpoints and number of intervals for an axis and # returns ($nice_min, $nice_max, $n), where $n is the number of # intervals and # # $nice_min <= $min < $max <= $nice_max # # Usage: # ($nmin,$nmax,$nint) = _best_ends(247, 508); # ($nmin,$nmax) = _best_ends(247, 508, 5); # use 5 intervals # ($nmin,$nmax,$nint) = _best_ends(247, 508, 4..7); # best of 4,5,6,7 intervals sub _best_ends { my ($min, $max, @n) = @_; my ($best_min, $best_max, $best_num) = ($min, $max, 1); # fix endpoints, fix intervals, set defaults ($min, $max) = ($max, $min) if ($min > $max); ($min, $max) = ($min) ? ($min * 0.5, $min * 1.5) : (-1,1) if ($max == $min); @n = (3..6) if (@n <= 0 || $n[0] =~ /auto/i); my $best_fit = 1e30; my $range = $max - $min; # create array of interval sizes my $s = 1; while ($s < $range) { $s *= 10 } while ($s > $range) { $s /= 10 } my @step = map {$_ * $s} (0.2, 0.5, 1, 2, 5); for (@n) { # Try all numbers of intervals my $n = $_; next if ($n < 1); for (@step) { next if ($n != 1) && ($_ < $range/$n); # $step too small my $nice_min = $_ * int($min/$_); $nice_min -= $_ if ($nice_min > $min); my $nice_max = ($n == 1) ? $_ * int($max/$_ + 1) : $nice_min + $n * $_; my $nice_range = $nice_max - $nice_min; next if ($nice_max < $max); # $nice_min too small next if ($best_fit <= $nice_range - $range); # not closer fit $best_min = $nice_min; $best_max = $nice_max; $best_fit = $nice_range - $range; $best_num = $n; } } return ($best_min, $best_max, $best_num) } # Convert value coordinates to pixel coordinates on the canvas. sub val_to_pixel($$$) # ($x, $y, $i) in real coords ($Dataspace), { # return [x, y] in pixel coords my $s = shift; my ($x, $y, $i) = @_; my $y_min = ($s->{two_axes} && $i == 2) ? $s->{y_min}[2] : $s->{y_min}[1]; my $y_max = ($s->{two_axes} && $i == 2) ? $s->{y_max}[2] : $s->{y_max}[1]; my $y_step = abs(($s->{bottom} - $s->{top})/($y_max - $y_min)); return ( _round( ($s->{x_tick_number} ? $s->{x_offset} : $s->{left}) + $x * $s->{x_step} ), _round( $s->{bottom} - ($y - $y_min) * $y_step ) ) } } # End of package GIFgraph::axestype 1; mrtg-2.17.10/contrib/whodo/GIFgraph/GIFgraph.pm0000644000175300017510000006711513057016062020054 0ustar oetikeroep#========================================================================== # Copyright (c) 1995-1998 Martien Verbruggen #-------------------------------------------------------------------------- # # Name: # GIFgraph.pm # # Description: # Module to create graphs from a data set, outputting # GIF format graphics. # # Package of a number of graph types: # GIFgraph::bars # GIFgraph::lines # GIFgraph::points # GIFgraph::linespoints # GIFgraph::area # GIFgraph::pie # GIFgraph::mixed # # $Id: GIFgraph.pm,v 1.1.1.1 2002/02/26 10:16:37 oetiker Exp $ # #========================================================================== require 5.004; use strict; use vars qw(@ISA); # Use Lincoln Stein's GD and Thomas Boutell's libgd.a use GD; # # GIFgraph # # Parent class containing data all graphs have in common. # package GIFgraph; $GIFgraph::prog_name = 'GIFgraph.pm'; $GIFgraph::prog_rcs_rev = '$Revision: 1.1.1.1 $'; $GIFgraph::prog_version = ($GIFgraph::prog_rcs_rev =~ /\s+(\d*\.\d*)/) ? $1 : "0.0"; $GIFgraph::VERSION = '1.10'; # Some tools and utils use GIFgraph::colour qw(:colours); my $OS; # Let's guess what the OS is # (from CGI.pm by Lincoln Stein) # OVERRIDE THE OS HERE IF THE GUESS IS WRONG # $OS = 'UNIX'; # $OS = 'MACINTOSH'; # $OS = 'WINDOWS'; # $OS = 'VMS'; # $OS = 'OS2'; # FIGURE OUT THE OS WE'RE RUNNING UNDER # Some systems support the $^O variable. If not # available then require() the Config library unless ($OS) { unless ($OS = $^O) { require Config; $OS = $Config::Config{'osname'}; } if ($OS=~/Win/i) { $OS = 'WINDOWS'; } elsif ($OS=~/vms/i) { $OS = 'VMS'; } elsif ($OS=~/Mac/i) { $OS = 'MACINTOSH'; } elsif ($OS=~/os2/i) { $OS = 'OS2'; } else { $OS = 'UNIX'; } } $GIFgraph::needs_binmode = $OS=~/^(WINDOWS|VMS|OS2)/; my %GIFsize = ( 'x' => 400, 'y' => 300 ); my %Defaults = ( # Set the top, bottom, left and right margin for the GIF. These # margins will be left empty. t_margin => 0, b_margin => 0, l_margin => 0, r_margin => 0, # Set the factor with which to resize the logo in the GIF (need to # automatically compute something nice for this, really), set the # default logo file name, and set the logo position (UR, BR, UL, BL) logo_resize => 1.0, logo => undef, logo_position => 'LR', # Write a transparent GIF? transparent => 1, # Write an interlaced GIF? interlaced => 1, # Set the background colour, the default foreground colour (used # for axes etc), the textcolour, the colour for labels, the colour # for numbers on the axes, the colour for accents (extra lines, tick # marks, etc..) bgclr => 'white', fgclr => 'dblue', textclr => 'dblue', labelclr => 'dblue', axislabelclr => 'dblue', accentclr => 'gray', # number of pixels to use as text spacing text_space => 8, ); { # # PUBLIC methods, documented in pod. # sub new # ( width, height ) optional; { my $type = shift; my $self = {}; bless $self, $type; if (@_) { # If there are any parameters, they should be the size $self->{gifx} = shift; # If there's an x size, there should also be a y size. die "Usage: GIFgraph::::new( [x_size, y_size] )\n" unless @_; $self->{gify} = shift; } else { # There were obviously no parameters, so use defaults $self->{gifx} = $GIFsize{'x'}; $self->{gify} = $GIFsize{'y'}; } # Initialise all relevant parameters to defaults # These are defined in the subclasses. See there. $self->initialise( ); return $self; } sub set { my $s = shift; my %args = @_; foreach (keys %args) { $s->{$_} = $args{$_}; } } # These should probably not be used, or be rewritten to # accept some keywords. Problem is that GD is very limited # on fonts, and this routine just accepts GD font names. # But.. it's not nice to require the user to include GD.pm # just because she might want to change the font. sub set_title_font # (fontname) { my $self = shift; $self->{tf} = shift; $self->set( tfw => $self->{tf}->width, tfh => $self->{tf}->height, ); } sub set_text_clr # (colour name) { my $s = shift; my $c = shift; $s->set( textclr => $c, labelclr => $c, axislabelclr => $c, ); } sub plot # (\@data) { # ABSTRACT my $s = shift; $s->die_abstract( "sub plot missing," ); } sub plot_to_gif # ("file.gif", \@data) { my $s = shift; my $file = shift; my $data = shift; open (GIFPLOT,">$file") || do { warn "Cannot open $file for writing: $!"; return 0; }; binmode GIFPLOT if ($GIFgraph::needs_binmode); print GIFPLOT $s->plot( $data ); close(GIFPLOT); } # Routine to read GNU style data files # NOT USEABLE sub ReadFile { my $file = shift; my @cols = @_; my (@out, $i, $j); @cols = 1 if ( $#cols < 1 ); open (DATA, $file) || do { warn "Cannot open file: $file"; return []; }; $i=0; while (defined()) { s/^\s+|\s+$//; next if ( /^#/ || /^!/ || /^[ \t]*$/ ); @_ = split(/[ \t]+/); $out[0][$i] = $_[0]; $j=1; foreach (@cols) { if ( $_ > $#_ ) { warn "Data column $_ not present"; return []; } $out[$j][$i] = $_[$_]; $j++; } $i++; } close(DATA); return @out; } # ReadFile # # PRIVATE methods # # Set defaults that apply to all graph/chart types. # This is called by the default initialise methods # from the objects further down the tree. sub initialise() { my $self = shift; foreach (keys %Defaults) { $self->set( $_ => $Defaults{$_} ); } $self->set_title_font(GD::gdLargeFont); $self->open_graph(); } # Check the integrity of the submitted data # # Checks are done to assure that every input array # has the same number of data points, it sets the variables # that store the number of sets and the number of points # per set, and kills the process if there are no datapoints # in the sets, or if there are no data sets. sub check_data($) # \@data { my $self = shift; my $data = shift; $self->set(numsets => $#$data); $self->set(numpoints => $#{@$data[0]}); ( $self->{numsets} < 1 || $self->{numpoints} < 0 ) && die "No Data"; my $i; for $i ( 1..$self->{numsets} ) { die "Data array $i: length misfit" unless ( $self->{numpoints} == $#{@$data[$i]} ); } } # Open the graph output canvas by creating a new GD object. sub open_graph() { my $self = shift; if ( !exists $self->{graph} ) { my $graph = new GD::Image($self->{gifx}, $self->{gify}); $self->{graph} = $graph; return $graph; } else { return $self->{graph}; } } # Initialise the graph output canvas, setting colours (and getting back # index numbers for them) setting the graph to transparent, and # interlaced, putting a logo (if defined) on there. sub init_graph($) # GD::Image { my $self = shift; my $graph = shift; $self->{bgci} = $self->set_clr( $graph, _rgb($self->{bgclr}) ); $self->{fgci} = $self->set_clr( $graph, _rgb($self->{fgclr}) ); $self->{tci} = $self->set_clr( $graph, _rgb($self->{textclr}) ); $self->{lci} = $self->set_clr( $graph, _rgb($self->{labelclr}) ); $self->{alci} = $self->set_clr( $graph, _rgb($self->{axislabelclr}) ); $self->{acci} = $self->set_clr( $graph, _rgb($self->{accentclr}) ); $graph->transparent($self->{bgci}) if $self->{transparent}; $graph->interlaced($self->{interlaced}); $self->put_logo($graph); } # read in the logo, and paste it on the graph canvas sub put_logo($) # GD::Image { my $self = shift; my $graph = shift; return unless(defined($self->{logo})); my ($x, $y, $glogo); my $r = $self->{logo_resize}; my $r_margin = (defined $self->{r_margin_abs}) ? $self->{r_margin_abs} : $self->{r_margin}; my $b_margin = (defined $self->{b_margin_abs}) ? $self->{b_margin_abs} : $self->{b_margin}; open(GIFLOGO, $self->{logo}) || return; binmode(GIFLOGO) if ($GIFgraph::needs_binmode); unless ( $glogo = newFromGif GD::Image(\*GIFLOGO) ) { warn "Problems reading $self->{logo}"; close(GIFLOGO); return; } close(GIFLOGO); my ($w, $h) = $glogo->getBounds; LOGO: for ($self->{logo_position}) { /UL/i && do { $x = $self->{l_margin}; $y = $self->{t_margin}; last LOGO; }; /UR/i && do { $x = $self->{gifx} - $r_margin - $w * $r; $y = $self->{t_margin}; last LOGO; }; /LL/i && do { $x = $self->{l_margin}; $y = $self->{gify} - $b_margin - $h * $r; last LOGO; }; # default "LR" $x = $self->{gifx} - $r_margin - $r * $w; $y = $self->{gify} - $b_margin - $r * $h; last LOGO; } $graph->copyResized($glogo, $x, $y, 0, 0, $r * $w, $r * $h, $w, $h); undef $glogo; } # Set a colour to work with on the canvas, by rgb value. # Return the colour index in the palette sub set_clr($$$$) # GD::Image, r, g, b { my $s = shift; my $g = shift; my $i; # Check if this colour already exists on the canvas if ( ( $i = $g->colorExact( @_ ) ) < 0 ) { # if not, allocate a new one, and return it's index return $g->colorAllocate( @_ ); } return $i; } # Set a colour, disregarding wether or not it already exists. sub set_clr_uniq($$$$) # GD::Image, r, g, b { my $s=shift; my $g=shift; $g->colorAllocate( @_ ); } # Return an array of rgb values for a colour number sub pick_data_clr($) # number { my $s = shift; # Set up the data colour list if it doesn't exist yet. # It seemed easier & more robust to me to do it here rather than # relying on users doing it. AF $s->set( dclrs => [ qw(lred lgreen lblue lyellow lpurple lbrown cyan lorange marine dyellow red green yellow blue lgray dbrown purple orange pink gold)] ) unless ( exists $s->{dclrs} ); return _rgb( $s->{dclrs}[ $_[0] % (1+$#{$s->{dclrs}}) -1 ] ); } # DEBUGGING # data_dump obsolete now, use Data::Dumper sub die_abstract() { my $s = shift; my $msg = shift; # ABSTRACT die "Subclass (" . ref($s) . ") not implemented correctly: " . (defined($msg) ? $msg : "unknown error"); } # Return the gif contents sub gifdata() { my $s = shift; return $s->{graph}->gif; } } # End of package GIFgraph $GIFgraph::prog_name; __END__ =head1 NAME GIFgraph - Graph Plotting Module for Perl 5 =head1 SYNOPSIS use GIFgraph::moduleName; =head1 DESCRIPTION B is a I module to create and display GIF output for a graph. The following classes for graphs with axes are defined: =over 4 =item C Create a line chart. =item C Create a bar chart. =item C Create an chart, displaying the data as points. =item C Combination of lines and points. =item C Create a graph, representing the data as areas under a line. =item C Create a mixed type graph, any combination of the above. At the moment this is fairly limited. Some of the options that can be used with some of the individual graph types won't work very well. Multiple bar graphs in a mixed graph won't display very nicely. =back Additional types: =over 4 =item C Create a pie chart. =back =head1 EXAMPLES See the samples directory in the distribution. =head1 USAGE Fill an array of arrays with the x values and the values of the data sets. Make sure that every array is the same size, otherwise I will complain and refuse to compile the graph. @data = ( ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], [ 1, 2, 5, 6, 3, 1.5, 1, 3, 4] [ sort { $a <=> $b } (1, 2, 5, 6, 3, 1.5, 1, 3, 4) ] ); If you don't have a value for a point in a certain dataset, you can use B, and I will skip that point. Create a new I object by calling the I operator on the graph type you want to create (I is I or I). $my_graph = new GIFgraph::chart( ); Set the graph options. $my_graph->set( x_label => 'X Label', y_label => 'Y label', title => 'Some simple graph', y_max_value => 8, y_tick_number => 8, y_label_skip => 2 ); Output the graph $my_graph->plot_to_gif( "sample01.gif", \@data ); =head1 METHODS AND FUNCTIONS =head2 Methods for all graphs =over 4 =item new GIFgraph::chart([width,height]) Create a new object $graph with optional width and heigth. Default width = 400, default height = 300. I is either I or I. =item set_text_clr( I ) Set the colour of the text. This will set the colour of the titles, labels, and axis labels to I. Also see the options I, I and I. =item set_title_font( I ) Set the font that will be used for the title of the chart. Possible choices are defined in L. B If you want to use this function, you'll need to use L. At some point I'll rewrite this, so you can give this a number from 1 to 4, or a string like 'large' or 'small'. On the other hand, I might not, if Thomas Boutell decides to support more fonts. =item plot( I<\@data> ) Plot the chart, and return the GIF data. =item plot_to_gif( F, I<\@data> ) Plot the chart, and write the GIF data to I. =item set( key1 => value1, key2 => value2 .... ) Set chart options. See OPTIONS section. =back =head2 Methods for Pie charts =over 4 =item set_label_font( I ) =item set_value_font( I ) Set the font that will be used for the label of the pie or the values on the pie. Possible choices are defined in L. See also I. =back =head2 Methods for charts with axes. =over 4 =item set_x_label_font ( I ) =item set_y_label_font ( I ) =item set_x_axis_font ( I ) =item set_y_axis_font ( I ) Set the font for the x and y axis label, and for the x and y axis value labels. See also I. =back =head1 OPTIONS =head2 Options for all graphs =over 4 =item gifx, gify The width and height of the gif file in pixels Default: 400 x 300. B At the moment, these are read-only options. If you want to set the size of a graph, you will have to do that with the I method. =item t_margin, b_margin, l_margin, r_margin Top, bottom, left and right margin of the GIF. These margins will be left blank. Default: 0 for all. =item logo Name of a logo file. This should be a GIF file. Default: no logo. =item logo_resize, logo_position Factor to resize the logo by, and the position on the canvas of the logo. Possible values for logo_position are 'LL', 'LR', 'UL', and 'UR'. (lower and upper left and right). Default: 'LR'. =item transparent If set to a true value, the produced GIF will have the background colour marked as transparent (see also option I). Default: 1. =item interlaced If set to a true value, the produced GIF will be interlaced. Default: 1. =item bgclr, fgclr, textclr, labelclr, axislabelclr, accentclr Background, foreground, text, label, axis label and accent colours. =item dclrs (short for datacolours) This controls the colours for the bars, lines, markers, or pie slices. This should be a reference to an array of colour names as defined in L (C> for the names available). $graph->set( dclrs => [ qw(green pink blue cyan) ] ); The first (fifth, ninth) data set will be green, the next pink, etc. Default: [ qw(lred lgreen lblue lyellow lpurple cyan lorange) ] =back =head2 Options for graphs with axes. options for I, I, I, I and I charts. =over 4 =item long_ticks, tick_length If I is a true value, ticks will be drawn the same length as the axes. Otherwise ticks will be drawn with length I. if I is negative, the ticks will be drawn outside the axes. Default: long_ticks = 0, tick_length = 4. =item x_ticks If I is a true value, ticks will be drawm for the x axis. These ticks are subject to the values of I and I. Default: 1. =item y_tick_number Number of ticks to print for the Y axis. Use this, together with I to control the look of ticks on the y axis. Default: 5. =item y_number_format This can be either a string, or a reference to a subroutine. If it is a string, it will be taken to be the first argument to an sprintf, with the value as the second argument: $label = sprintf( $s->{y_number_format, $value ); If it is a code reference, it will be executed with the value as the argument: $label = &{$s->{y_number_format}}($value); This can be useful, for example, if you want to reformat your values in currency, with the - sign in the right spot. Something like: sub y_format { my $value = shift; my $ret; if ($value >= 0) { $ret = sprintf("\$%d", $value * $refit); } else { $ret = sprintf("-\$%d", abs($value) * $refit); } return $ret; } $my_graph->set( 'y_number_format' => \&y_format ); (Yes, I know this can be much shorter and more concise) Default: undef. =item x_label_skip, y_label_skip Print every Ith number under the tick on the x axis, and every Ith number next to the tick on the y axis. Default: 1 for both. =item x_all_ticks Force a print of all the x ticks, even if x_label_skip is set to a value Default: 0. =item x_label_position Controls the position of the X axis label (title). The value for this should be between 0 and 1, where 0 means aligned to the left, 1 means aligned to the right, and 1/2 means centered. Default: 3/4 =item y_label_position Controls the position of both Y axis labels (titles). The value for this should be between 0 and 1, where 0 means aligned to the bottom, 1 means aligned to the top, and 1/2 means centered. Default: 1/2 =item x_labels_vertical If set to a true value, the X axis labels will be printed vertically. This can be handy in case these labels get very long. Default: 0. =item x_plot_values, y_plot_values If set to a true value, the values of the ticks on the x or y axes will be plotted next to the tick. Also see I. Default: 1 for both. =item box_axis Draw the axes as a box, if true. Default: 1. =item two_axes Use two separate axes for the first and second data set. The first data set will be set against the left axis, the second against the right axis. If this is set to a true value, trying to use anything else than 2 datasets will generate an error. Default: 0. =item zero_axis If set to a true value, the axis for y values of 0 will always be drawn. This might be useful in case your graph contains negative values, but you want it to be clear where the zero value is. (see also I and I). Default: 0. =item zero_axis_only If set to a true value, the zero axis will be drawn (see I), and no axis at the bottom of the graph will be drawn. The labels for X values will be placed on the zero exis. Default: 0. =item y_max_value, y_min_value Maximum and minimum value displayed on the y axis. If two_axes is a true value, then y1_min_value, y1_max_value (for the left axis), and y2_min_value, y2_max_value (for the right axis) take precedence over these. The range (y_min_value..y_max_value) has to include all the values of the data points, or I will die with a message. For bar and area graphs, the range (y_min_value..y_max_value) has to include 0. If it doesn't, the values will be adapted before attempting to draw the graph. Default: Computed from data sets. =item axis_space This space will be left blank between the axes and the text. Default: 4. =item overwrite If set to 0, bars of different data sets will be drawn next to each other. If set to 1, they will be drawn in front of each other. If set to 2 they will be drawn on top of each other. Default: 0. If you have negative values in your data sets, setting overwrite to 2 might produce odd results. Of course, the graph itself would be quite meaningless, because overwrite = 2 is meant to show some cumulative effect. =back =head2 Options for graphs with a numerical X axis First of all: GIFgraph does B support numerical x axis the way it should. Data for X axes should be equally spaced. That understood: There is some support to make the printing of graphs with numerical X axis values a bit better, thanks to Scott Prahl. If the option C is set to a defined value, GIFgraph will attempt to treat the X data as numerical. Extra options are: =over 4 =item x_tick_number If set to I<'auto'>, GIFgraph will attempt to format the X axis in a nice way, based on the actual X values. If set to a number, that's the number of ticks you will get. If set to undef, GIFgraph will treat X data as labels. Default: undef. =item x_min_value, x_max_value The minimum and maximum value to use for the X axis. Default: computed. =item x_number_format See y_number_format =item x_label_skip See y_label_skip =back =head2 Options for graphs with bars =over 4 =item bar_spacing Number of pixels to leave open between bars. This works well in most cases, but on some platforms, a value of 1 will be rounded off to 0. Default: 0 =back =head2 Options for graphs with lines =over 4 =item line_types Which line types to use for I and I graphs. This should be a reference to an array of numbers: $graph->set( line_types => [3, 2, 4] ); Available line types are 1: solid, 2: dashed, 3: dotted, 4: dot-dashed. Default: [1] (always use solid) =item line_type_scale Controls the length of the dashes in the line types. default: 6. =item line_width The width of the line used in I and I graphs, in pixels. Default: 1. =back =head2 Options for graphs with points =over 4 =item markers This controls the order of markers in I and I graphs. This should be a reference to an array of numbers: $graph->set( markers => [3, 5, 6] ); Available markers are: 1: filled square, 2: open square, 3: horizontal cross, 4: diagonal cross, 5: filled diamond, 6: open diamond, 7: filled circle, 8: open circle. Default: [1,2,3,4,5,6,7,8] =item marker_size The size of the markers used in I and I graphs, in pixels. Default: 4. =back =head2 Options for mixed graphs =over 4 =item types A reference to an array with graph types, in the same order as the data sets. Possible values are: $graph->set( types => [qw(lines bars points area linespoints)] ); $graph->set( types => ['lines', undef, undef, 'bars'] ); values that are undefined or unknown will be set to C. Default: all set to C =item default_type The type of graph to draw for data sets that either have no type set, or that have an unknown type set. Default: lines =back =head2 Graph legends (axestype graphs only) At the moment legend support is minimal. B =over 4 =item set_legend( I<@legend_keys> ); Sets the keys for the legend. The elements of @legend_keys correspond to the data sets as provided to I or I. If a key is I or an empty string, the legend entry will be skipped. =item set_legend_font( I ); Sets the font for the legend text (see also I). Default: GD::gdTinyFont. =back B =over 4 =item legend_placement Where to put the legend. This should be a two letter key of the form: 'B[LCR]|R[TCB]'. The first letter sigifies the placement (Iottom or Iight), and the second letter signifies the alignment (Ieft, Iight, Ienter, Iop, or Iottom). Default: 'BC' If the legend is placed at the bottom, some calculations will be made to ensure that there is some 'intelligent' wrapping going on. if the legend is placed at the right, all entries will be placed below each other. =item legend_spacing The number of pixels to place around a legend item, and between a legend 'marker' and the text. Default: 4 =item legend_marker_width, legend_marker_height The width and height of a legend 'marker' in pixels. Defaults: 12, 8 =item lg_cols If you, for some reason, need to force the legend at the bottom to have a specific number of columns, you can use this. Default: computed =back =head2 Options for pie graphs =over 4 =item 3d If set to a true value, the pie chart will be drawn with a 3d look. Default: 1. =item pie_height The thickness of the pie when I<3d> is true. Default: 0.1 x GIF y size. =item start_angle The angle at which the first data slice will be displayed, with 0 degrees being "6 o'clock". Default: 0. =back =head1 NOTES All references to colours in the options for this module have been shortened to clr. The main reason for this was that I didn't want to support two spellings for the same word ('colour' and 'color') Wherever a colour is required, a colour name should be used from the package L. C> should give you the documentation for that module, containing all valid colour names. I will probably change this to read the systems rgb.txt file if it is available. Wherever a font name is required, a font from L should be used. =head1 AUTHOR Martien Verbruggen =head2 Contact info email: mgjv@comdyn.com.au =head2 Copyright Copyright (C) 1995-1998 Martien Verbruggen. All rights reserved. This package is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut # WWW: L mrtg-2.17.10/contrib/whodo/collect.pl0000644000175300017510000002244313057016062016415 0ustar oetikeroep# collect.pl # # Collect IP accounting data from a cisco router and summarise it # into a CSV file. The file shows number of bytes sent from each # source device to each destination network. # Optionally, the data is also summarised by source (all destinations added # together) and written out to an mrtg config file. # There are also two input files. "networks" is used to map network # addresses to names. "sources" is optional & is used to map source # addresses to host names. # # Args are: # h help # a path of mrtg config file for data by source # n path of a "networks" file used to map network addresses to names # o path of output CSV file. Defaults to YYYYMMDD-HHMMSS.CSV # s path of a "sources" file mapping source addresses to host names # # v1.0 17/9/98 Tony Farr Original # v1.1 16/12/98 Tony Farr Add horrid kludge to collect Exchange traffic # by source # v1.2 22/3/99 Tony Farr Tidy up # v1.3 25/3/99 Tony Farr Remove v1.1 kludge # Just generate one mrtg line/data set # use SNMP_util; use Getopt::Std; use File::Basename; use strict; use Socket; use vars qw/$opt_h $opt_a $opt_n $opt_o $opt_s/; # CONSTANTS # Note inclusion of the write community string my $HOST= '0ztrad3@canb-wan'; # Directory for output logs/csv files. my $LOGPATH= "D:\\logs\\whodo\\"; # Directory for MRTG config files for traffic sources my $SOURCEDIR= "D:\\www\\mrtg\\whodo"; # Any source generating more than BIGBYTES per poll will be added to the sources config file automatically my $BIGBYTES= 40000000; my(@dstdesc, @dstaddr, @dstmask, @srcaddr, @srcdesc, %traffictab); my $progname = basename($0); my $usage = "Usage: $progname [-h] [-a mrtg_config_file] [-n network_file] [-o output_file] [-s source_address_file]\n"; # Parse Command Line: die $usage unless getopts('ha:n:o:s:'); if ( defined($opt_h) ) { print $usage; exit(0); } if ( defined($opt_n) ) { load_nets($opt_n); } unless ( defined($opt_o) ) { my ($sec,$min,$hour,$mday,$month,$year) = localtime; $opt_o= $LOGPATH . sprintf("%d%02d%02d-%02d%02d%02d.csv", $year+1900,++$month,$mday,$hour,$min,$sec); } if ( defined($opt_s) ) { load_sources($opt_s); } my $age= checkpoint_stats($HOST); get_stats($HOST); print_stats($opt_o); if ( defined($opt_a) ) { make_sources_config($opt_a); } exit(0); sub load_nets { # Loads 3 arrays: # @dstaddr - a list of IP addresses # @dstdesc - a list of the corresponding descriptions # @dstmask - a list of the corresponding bitmasks # The tables are loaded from a list of filenames passed in @_. That file # can be a networks file. The file(s) should have format: # netdescription 10.10.10 /25 # The "/25" is the mask & may be preceeded by a "#". It is optional. my(@flist)= @_; my ($desc, $end, $masksz); while (my $fname= shift(@flist)) { open(NETWORKS, "<$fname") || warn "$progname: unable to open $fname; $!"; while () { # Process #includes after dealing with the current file if ( /^#\s*include\s+(\S+)/ ) { push(@flist, $1); next; } if ( /^\s*(\w+)\s+(\S+)(.*)/ ) { $desc= $1; $_= $2; $end= $3; push(@dstdesc, $desc); my $octets = 1 + tr/././; $_ .= ".0" x (4 - $octets); push( @dstaddr, aton($_) ); if ( $end =~ /\/(\d+)/ ) { $masksz= $1; } else { $masksz= $octets * 8; } push( @dstmask, pack("B32", "1" x $masksz . "0" x 32) ); } } close(NETWORKS); } } sub load_sources { # Loads a pair of arrays: @srcaddr (a list of IP addresses) and @srcdesc # (a list of the corresponding descriptions). The files are loaded from # a list of filenames passed in @_. That file can be a hosts file. However "address" entries # can be perl regular exprs as well literal addresses. For compatibility, # "." when used as a wild card must be expressed "\." - i.e. the reverse of normal. my(@flist)= @_; while (my $fname= shift(@flist)) { open(HOSTS, "<$fname") || warn "$progname: unable to open $fname; $!"; while () { # Process #includes after dealing with the current file if ( /^#\s*include\s+(\S+)/ ) { push(@flist, $1); next; } ($_)= split(/#/); if ( /(\S+)\s+(\S+)/ ) { push(@srcdesc, $2); $_= $1; s/\./\\\./g; # Replace "." with "\." s/\\\\\././g; # If we now have "\\.", replace with "." push(@srcaddr, $_); } } close(HOSTS); } } sub checkpoint_stats { # Take a checkpoint on IP accounting on the given router & return the duration of it. # The checkpoint is done by doing a get then a set on actCheckPoint my ($age); # Find how long since the last checkpoint ($age) = snmpget ($_[0], '1.3.6.1.4.1.9.2.4.8.0'); warn "$progname: No actAge returned.\n" unless $age; # Check to see if we've lost any data ($_) = snmpget ($_[0], '1.3.6.1.4.1.9.2.4.6.0'); warn "$progname: Accounting table overflow - $_ bytes lost.\n" if $_ > 0; # Do a new checkpoint ($_) = snmpget ($_[0], '1.3.6.1.4.1.9.2.4.11.0'); die "$progname: No actCheckPoint returned.\n" unless defined; snmpset ($_[0], '1.3.6.1.4.1.9.2.4.11.0', 'integer', $_); $age; } sub get_stats { # Summarise the checkpoint by destination network (not host). # Summary is placed into %traffictab - a hash of hashes indexed by # source device & destination network. my($src, $dstnet); my @response = snmpwalk ($_[0], '1.3.6.1.4.1.9.2.4.9.1.4' ); foreach $_ (@response) { /(\d+\.\d+\.\d+\.\d+)\.(\d+\.\d+\.\d+\.\d+):(\d+)/ || die "$progname: Cannot parse response from walk.\n"; $dstnet= addr_to_net($2); $src= addr_to_src($1); $traffictab{$src}{$dstnet} += $3; } } sub print_stats { # Print out the traffictab in csv format my ($sec,$min,$hour,$mday,$month,$year) = localtime(time()); $year += 1900; $month++; open (CSVFILE,">$_[0]") || die "$progname: Could not open file $_[0]; $!\n"; printf CSVFILE "End Time:,%d/%02d/%d %d:%02d:%02d\n",$mday,$month,$year,$hour,$min,$sec; print CSVFILE "Duration:,$age\n"; # Bug alert. This breaks if $age > 1 day my($s, $d); foreach $s (sort keys %traffictab) { foreach $d (sort keys %{$traffictab{$s}}) { print CSVFILE "$s,$d,$traffictab{$s}{$d}\n"; } } close(CSVFILE); } sub make_sources_config { # Print out an mrtg config file my($cfgfile)= @_; my(%cfgentries, $src, $dst, $t, $misc); # Load current cfg entries if ( open(CFG, "<$cfgfile") ) { while () { if ( /^\s*Target\[([^\]]*)/ && $1 ne "Miscellaneous" ) { $cfgentries{ uc($1) }= 1; } } close(CFG); } # Write out the header of a new config file open(CFG,">$cfgfile") || die "$progname: Could not open file $cfgfile; $!\n"; write_sources_header(); # For each traffictab entry, if it's large or there's an existing CFG entry, write out a new CFG entry foreach $src (keys %traffictab) { $t= 0; foreach $dst (keys %{$traffictab{$src}}) { $t += $traffictab{$src}{$dst}; } if ( $cfgentries{ uc($src) } ) { delete $cfgentries{ uc($src) }; write_source_entry($src, $t); } elsif ( $t > $BIGBYTES ) { write_source_entry($src, $t); } else { $misc += $t; } } # Write out new entries for any CFG entries that existed previously but we've # missed because they generated no traffic this time. foreach $src (keys %cfgentries) { write_source_entry($src, 0); } # Write an entry for the miscellaneous odds & ends write_source_entry("Miscellaneous", $misc); close(CFG); } sub write_sources_header { print CFG <Traffic from $_[0] MaxBytes[$_[0]]: 12500000 Options[$_[0]]: growright, bits, absolute, nopercent Colours[$_[0]]: w#ffffff,blue#0000e0,w#ffffff,r#ff0000 Target[$_[0]]: `perl -e "print \\"0\\n$_[1]\\""` YLegend[$_[0]]: Bits per Second ShortLegend[$_[0]]: bps Legend1[$_[0]]: Legend2[$_[0]]: Traffic from $_[0] LegendI[$_[0]]: LegendO[$_[0]]:  Traffic: END_OF_ENTRY } sub addr_to_net { # Returns the name/description of the network of the given address. # Addresses are looked up in @dstaddr first. If that fails, the address is returned. my($i, $dst); $dst= aton($_[0]); for ($i=0; $i < @dstaddr; $i++) { if ( ($dst & $dstmask[$i]) eq $dstaddr[$i] ) { return $dstdesc[$i]; } } $_[0] =~ /(.*)\..*/; # Assume Class C & strip off the last octet $1; } sub BEGIN { my ($lastaddr, $lastsrc); sub addr_to_src { # Returns the name/description of the given address. # Addresses are looked up in @srcaddr first. If there's no match, a dns lookup is tried. # If that fails, the address is returned. if ( $_[0] eq $lastaddr ) { return $lastsrc; } else { $lastaddr= $_[0]; for (my $i=0; $i < @srcaddr; $i++) { if ($_[0] =~ /^$srcaddr[$i]$/ ) { $lastsrc= $srcdesc[$i]; return $lastsrc; } } my $addr= aton($_[0]); if ($lastsrc= gethostbyaddr($addr, AF_INET)) { $lastsrc =~ s/\.austrade\.gov\.au$//i; } else { $lastsrc= $_[0]; } return $lastsrc; } } } sub aton { # I found the standard "inet_aton" very slow (on Windows). # Hence this version. It only handles dotted decimal addresses - # not names. $_[0] =~ /(\d+).(\d+).(\d+).(\d+)/; chr($1).chr($2).chr($3).chr($4); }mrtg-2.17.10/contrib/whodo/wwwscripts/0000755000175300017510000000000013057016062016662 5ustar oetikeroepmrtg-2.17.10/contrib/whodo/wwwscripts/pie.pl0000644000175300017510000001121513057016062017774 0ustar oetikeroep# pie.pl # # CGI script to generate a pie graph (GIF) showing WAN traffic broken down by # source or destination. # This script is currently invoked via CGI by analyse.pl # # Modification History ###################### # v1.0 Oct 98 Tony Farr Original coding # v2.0 17 Nov 98 Tony Farr Change to CGI script. Split out analyse as separate script. # v2.1 23/12/98 Tony Farr Add description of period to top of graph ############################################################################## use strict; use File::Basename; use CGI; use CGI::Carp qw(fatalsToBrowser); use GIFgraph::pie; use GD; my ($period, $field, $str, $summarise); my $LOGPATH= "D:\\logs\\whodo"; # Directory where csv/logs are stored. my $q = new CGI; if ($q->param('src_duration')) { # Show sources $period= $q->param('src_duration'); $str= $q->param('dest'); $field= 1; } else { # Show destinations $period= $q->param('dest_duration'); $str= $q->param('src'); $field= 2; } $summarise= $q->param('summarise'); my ($end, @flist)= get_input_files($period, $LOGPATH); my $trafficref= get_traffic($str, $summarise, $field, @flist); print $q->header('image/gif'); make_graph($period, $end, $trafficref, "-"); exit 0; sub get_input_files { # Returns a list of input files to be processed my($period, $path)= @_; my(@retvals, $fname, $lastfname, $start, $end); if ($period ne "30 minutes") { my($t,$mday,$mon,$year,$wday); $t= time(); if ($period eq "day") { $t -= 24*60*60; ($mday,$mon,$year) = ( localtime($t) )[3..5]; $end= $start= sprintf("%d%02d%02d",$year+1900,$mon+1,$mday); } elsif ($period eq "week") { $wday = (localtime($t))[6]; $t -= ($wday+1)*24*60*60; ($mday,$mon,$year) = ( localtime($t) )[3..5]; $end= sprintf("%d%02d%02d",$year+1900,$mon+1,$mday); $t -= 6*24*60*60; ($mday,$mon,$year) = ( localtime($t) )[3..5]; $start= sprintf("%d%02d%02d",$year+1900,$mon+1,$mday); } elsif ($period eq "month") { $mday = (localtime($t))[3]; $t -= $mday*24*60*60; ($mday,$mon,$year) = ( localtime($t) )[3..5]; $end= sprintf("%d%02d%02d",$year+1900,$mon+1,$mday); $t -= (days_in_month($mon,$year+1900) - 1) * 24 * 60 * 60; ($mday,$mon,$year) = ( localtime($t) )[3..5]; $start= sprintf("%d%02d%02d",$year+1900,$mon+1,$mday); } else { die "$0: Logic error; $!"; } } while ( $fname = glob("$path/*.csv") ) { if ($period eq "30 minutes") { if ($fname gt $retvals[0]) { $retvals[0]= $fname; $lastfname= basename($fname); } } else { my $datepart= substr( basename($fname), 0, 8 ); if ($datepart ge $start && $datepart le $end) { push(@retvals, $fname); if ($datepart gt $lastfname) { $lastfname= $datepart; } } } } if (length($lastfname) > 8) { $lastfname =~ s|^(\d\d\d\d)(\d\d)(\d\d)-(\d\d)(\d\d).*|$4:$5 on $3/$2/$1|; } else { $lastfname =~ s|^(\d\d\d\d)(\d\d)(\d\d).*|$3/$2/$1|; } ($lastfname, @retvals); } sub days_in_month { (31, $_[1] % 4 ? 28 : 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)[${_[0]}]; } sub get_traffic { # Read the log files (specified in @flist) & summarise into a hash my($s, $summarise, $field, @flist)= @_; my($fname, $src, $dst, $bytes, $key, %traffic, $sum); foreach $fname (@flist) { open(CSV, "< $fname") || warn "$0: unable to open $fname; $!"; ; # Logs start with a couple of header lines ; while () { ($src, $dst, $bytes)= split(/,/, $_); if ( $field == 1 ? $dst =~ $s : $src =~ $s ) { $key= ($field == 1) ? $src : $dst ; $traffic{$key} += $bytes; $sum+= $bytes; } } close(CSV); } if ( $summarise ) { my $significant= $sum * .025; foreach $s (keys %traffic) { if ( $traffic{$s} < $significant ) { $traffic{"Miscellaneous"} += $traffic{$s}; delete $traffic{$s}; } } } return \%traffic; } sub make_graph { # Take a (reference to a) hash containing traffic stats & create a pie chart my($period, $end, $dataref, $fname)= @_; my @sources= sort( {uc($a) cmp uc($b)} keys(%$dataref) ); my @traffic= map($$dataref{$_},@sources); my ($t, $sum); foreach $t (@traffic) { $sum+= $t; } for (my $i = 0; $i <= $#sources; $i++) { $t= int(100*$traffic[$i]/$sum + .5); $sources[$i]= $i+1 . ". $sources[$i] ($t%)"; } my $my_graph = new GIFgraph::pie(500, 510 + $#sources*11); $my_graph->set( 'start_angle' => 180, '3d' => 0, 'title' => "For the $period ending $end" ); $my_graph->set_text_clr("black"); $my_graph->set_legend(@sources); $my_graph->set_legend_font(gdSmallFont); $my_graph->plot_to_gif( $fname, [[1..$#sources+1], \@traffic] ); } mrtg-2.17.10/contrib/whodo/wwwscripts/analyse.pl0000644000175300017510000000241313057016062020653 0ustar oetikeroep# analyse.pl # # CGI script to generate an HTML page showing WAN traffic broken down by source # or destination. Most of the work is done by another script "pie.pl". # This script is invoked by http://netmanager/whodo/analyse.html # # Modification History ###################### # 17 Nov 98 Tony Farr Original coding ############################################################################## use strict; use CGI; use CGI::Carp qw(fatalsToBrowser); my $q = new CGI; my $title= "WAN Traffic by ".( defined($q->param('src')) ? "Destination" : "Source" ); print $q->header, $q->start_html($title), $q->h1($title), $q->hr; my $gifurl= $q->url(-query=>1); $gifurl =~ s/analyse\.pl/pie.pl/i; # pie.pl uses same path & arguments print $q->img({-src=>$gifurl, -align=>'CENTER', -alt=>'Generating pie graph...'}); print $q->hr, $q->small, $q->ul( $q->li("This page was produced at ".localtime(time)." (aest)." ), $q->li( $q->param("src") ? "Only sources matching the expression \"".$q->param("src")."\" have been included." : $q->param("dest") ? "Only destinations matching the expression \"".$q->param("dest")."\" have been included." : "All WAN traffic is included." ) ); print $q->end_html; exit 0; mrtg-2.17.10/contrib/whodo/makeanalyse.pl0000644000175300017510000000604713057016062017264 0ustar oetikeroep# makeanalyse.pl # # Generate an HTML page containing a list of networks and a list of traffic # sources. This page invokes the CGI script analyse.pl. The page is written to # STDOUT. # # Modification History ###################### # 23 Dec 98 Tony Farr Original coding ############################################################################## use strict; my(@sources, @dests); # Globals my $LOGPATH= "D:\\logs\\whodo\\"; # Directory where csv/logs are stored. get_sources_and_dests(); write_html(); exit(0); sub get_sources_and_dests { # Initialises @sources & @dests with yesterday's traffic sources and destinations my(%srchash, %dsthash, $src, $dst); my $fname= get_input_file(); open(LOG,"<$fname") || die "$0: unable to open input file $fname; $!"; # First 2 lines are headers || die "$0: $fname is empty\n"; || die "$0: $fname lacks second header line\n"; # The rest of the file has traffic for particular sources & destinations while () { ($src, $dst)= split/,/; $srchash{$src}= 1; $dsthash{$dst}= 1; } close(LOG); # Transfer them from the hashes to the arrays @sources= sort( keys(%srchash) ); @dests= sort( keys(%dsthash) ); } sub get_input_file { # Returns the file name of yesterday's whodo log my $t = time() - 24*60*60; my ($mday,$mon,$year) = ( localtime($t) )[3..5]; $LOGPATH . sprintf("%d%02d%02d.csv",$year+1900,$mon+1,$mday); } sub write_html { print <Analyse traffic sources or destinations

      Analyse traffic sources or destinations


      Show sources sending traffic to: 30 minutes day week month

      Summarise minor sources:

      OR

      Show destinations receiving traffic from: 30 minutes day week month

      Summarise minor destinations:


      TAIL }mrtg-2.17.10/contrib/debian-systemd/0000755000175300017510000000000014171553254016225 5ustar oetikeroepmrtg-2.17.10/contrib/debian-systemd/mrtg.service0000644000175300017510000000102514171553254020556 0ustar oetikeroep# Systemd config for MRTG on Debian # 2021 Joao Eriberto Mota Filho [Unit] Description=Multi Router Traffic Grapher Documentation=https://oss.oetiker.ch/mrtg/doc/index.en.html [Service] Environment=LANG=C ExecStart=/usr/bin/mrtg --daemon --fhs --user=mrtg KillMode=process LogsDirectory=mrtg LogsDirectoryMode=0750 PIDFile=/run/mrtg/mrtg.pid PrivateTmp=yes ReadOnlyDirectories=/etc RuntimeDirectory=mrtg StateDirectory=mrtg StateDirectoryMode=0750 Type=forking User=mrtg [Install] WantedBy=multi-user.target mrtg-2.17.10/contrib/debian-systemd/mrtg.init0000755000175300017510000000410314171553254020064 0ustar oetikeroep#!/bin/sh # Start/stop the MRTG # Original author: Stefan SF (for Fedora Project) # Updates for Debian: Joao Eriberto Mota Filho # ### BEGIN INIT INFO # Provides: mrtg # Required-Start: $network # Required-Stop: $network # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Starts the The Multi Router Traffic Grapher # Description: The Multi Router Traffic Grapher is a tool primarily used to # monitor the traffic load on network links (typically by using # SNMP). MRTG generates HTML pages containing PNG images which # provide a LIVE visual representation of this traffic. MRTG # typically produces daily, weekly, monthly, and yearly graphs. ### END INIT INFO # source function library . /lib/lsb/init-functions MRTG="/usr/bin/mrtg" USERMRTG="mrtg" CONFIG="/etc/mrtg/mrtg.cfg" PIDFILE="/run/mrtg/mrtg.pid" OPTIONS="--daemon --fhs --user=${USERMRTG}" RETVAL=0 start() { if [ ! -e $PIDFILE ] then WORKDIR=$(cat ${CONFIG} | grep -i WorkDir | cut -d: -f2 | tr -d " ") if [ -z ${WORKDIR} ] then echo "ERROR: WorkDir not defined in config file" exit 1 fi if [ ! -d ${WORKDIR} ] then echo "ERROR: no such directory: ${WORKDIR}" exit 1 fi OWNERWORKDIR=$(stat -c '%U' ${WORKDIR}) if [ ${OWNERWORKDIR} != ${USERMRTG} ] then echo "ERROR: ${WORKDIR} is not owned by ${USERMRTG}" exit 1 fi echo "Starting MRTG" LANG=C ${MRTG} ${OPTIONS} ${CONFIG} RETVAL=$? else echo "MRTG is already running" RETVAL=$? fi } stop() { if [ -e $PIDFILE ] then echo "Stopping MRTG" kill `cat ${PIDFILE}` RETVAL=$? else echo "MRTG is not running" RETVAL=$? fi } restart() { stop sleep 1 start } case "$1" in start) start ;; stop) stop ;; restart|force-reload) restart ;; status) if [ -e $PIDFILE ]; then echo "MRTG is enabled" RETVAL=0 else echo "MRTG is disabled" RETVAL=3 fi ;; *) echo "Usage: $0 {start|stop|status|restart|force-reload}" exit 1 esac exit $RETVAL mrtg-2.17.10/contrib/debian-systemd/README0000644000175300017510000000145314171553254017110 0ustar oetikeroepsystemd and init.d config files for MRTG ---------------------------------------- Hello everyone, These are the systemd and init scripts that I will provide for Debian as of October 2021. Debian usually provides these two files to help to start and stop services. These config files are using some new features released in MRTG 2.17.9, as the option --fhs updated from FHS 2.3 to 3.0, the new location for default mrtg.cfg (/etc/mrtg/mrtg.cfg) and the dynamic creation for main directories, as /run/mrtg/. The init script (/etc/init.d/mrtg) was originally written by Stefan SF for Fedora Project and updated by me to be used in Debian. The original init is being provided in contrib/mrtg-start-script/ -- Joao Eriberto Mota Filho Wed, 20 Oct 2021 22:15:51 -0300 mrtg-2.17.10/contrib/mrtg-ipget/0000755000175300017510000000000013057016061015364 5ustar oetikeroepmrtg-2.17.10/contrib/mrtg-ipget/mrtg-ipget.patch0000644000175300017510000000264213057016061020470 0ustar oetikeroepdiff -u ../xxx/SNMP_util.pm ./SNMP_util.pm --- ../xxx/SNMP_util.pm Tue Feb 23 23:01:32 1999 +++ ./SNMP_util.pm Fri Mar 12 14:00:46 1999 @@ -53,6 +53,7 @@ #frame relay stuff ... see the docs for explanations 'frInOctets' => '1.3.6.1.2.1.10.32.2.1.9', 'frOutOctets' => '1.3.6.1.2.1.10.32.2.1.7', + 'ipRouteifIndex' => '1.3.6.1.2.1.4.21.1.2', # squid mib 'cacheServerRequests' => '1.3.6.1.4.1.3495.1.3.2.1.10', 'cacheServerErrors' => '1.3.6.1.4.1.3495.1.3.2.1.11', Only in .: diff diff -u ../xxx/mrtg ./mrtg --- ../xxx/mrtg Tue Feb 23 23:01:32 1999 +++ ./mrtg Fri Mar 12 14:02:35 1999 @@ -616,8 +616,18 @@ $target{$targ}{'oid1'} = "ifInOctets.$port"; $target{$targ}{'oid2'} = "ifOutOctets.$port"; } else { + if (!$01 && !$02 && $port) { + $target{$targ}{'port'} = "ipRouteifIndex.$port"; + ($port)= + &snmpget($target{$targ}{'community'}."@".$target{$targ}{'router'}, + $target{$targ}{'port'}); + + $target{$targ}{'oid1'} = "ifInOctets.$port"; + $target{$targ}{'oid2'} = "ifOutOctets.$port"; + } else { my($o1, $o2) = split(/\&/, $port,2); - if (!$o1 || !$o2) { + + if (!$o1 || !$o2) { warn ("\nERROR: If specifying the full OID, you must specify\n". "2 full OID's separated by '&'. Error found with\n". "\"$&\" in \"Target[$rou]\"\n"); @@ -625,6 +635,7 @@ } $target{$targ}{'oid1'} = $o1; $target{$targ}{'oid2'} = $o2; + } } } mrtg-2.17.10/contrib/mrtg-ipget/README0000644000175300017510000000102713057016061016244 0ustar oetikeroepDate: Fri, 17 Jan 1997 21:39:06 -0500 From: Jim Willette Again I must state that this does no error checking what so ever. Just a quick hack to get me the results I needed. I have modified mrtgV2 to record stats based on interface ip address instead of Interface number. It does not do all the great errorchecking and no OS testing but it is functional for my needs. applie the patch by typing patch Stats for PageTop[$]:
      #----------------------------------------------------- Title[eu-ups01]: EU-UPS01 PageTop[eu-ups01]: EU-UPS01 Background[eu-ups01]: #FFFFCC Target[eu-ups01]: `/home/mrtguser/upsdata01.pl` MaxBytes[eu-ups01]: 600 Options[eu-ups01]: growright, gauge, nopercent WithPeak[eu-ups01]: wmy YLegend[eu-ups01]: value ShortLegend[eu-ups01]: Legend1[eu-ups01]: remaining time Legend2[eu-ups01]: % utilization Legend3[eu-ups01]: Maximal remaining time Legend4[eu-ups01]: Maximal % utilization LegendI[eu-ups01]:  time(minutes): LegendO[eu-ups01]:  load(%): mrtg-2.17.10/contrib/apc_ups/README0000644000175300017510000000045113057016061015617 0ustar oetikeroepFrom: Klaus_Klein@mckinsey.com Date: Thu, 3 May 2001 16:31:45 +0200 Hi tobias, As suggested, I send you some of my configuration files: these ones are using a PERL script to extract the load % and remaining battery time from APC UPS systems. prerequisite: have PERL and an SNMP suite installed. mrtg-2.17.10/contrib/apc_ups/upsdata01.pl0000644000175300017510000000054613057016061017103 0ustar oetikeroep#!/usr/bin/perl # # Script to convert runtime MIB variable for UPS into minutes $a=`/usr/bin/snmpget .1.3.6.1.4.1.318.1.1.1.2.2.3.0`; chomp $a; @b=split(/ /,$a); @c=split(/:/,$b[4]); @d=split(/ /,`/usr/bin/snmpget .1.3.6.1.4.1.318.1.1.1.4.2.3.0`); chomp $d; print eval($c[0] * 60 + $c[1]),"\n"; print $d[3];mrtg-2.17.10/contrib/nt_n_cisco/0000755000175300017510000000000013057016061015423 5ustar oetikeroepmrtg-2.17.10/contrib/nt_n_cisco/builder.bat0000644000175300017510000000064713057016061017550 0ustar oetikeroepset target=%1 set snmpStr=%2 set targetIP=%3 set NewDir=%mrtgwebroot%\%target% set mrtgcurr=e:\mrtg\prod\bats e: cd\ MD %NewDir% if not exist %mrtgwebroot%\%target%\default.asp copy %mrtgcurr%\default.asp %mrtgwebroot%\%target%\default_fixme.asp cd %mrtgbin% %perlbin%\perl %mrtgbin%\cfgmaker --workdir %mrtgwebroot%\%target% %snmpstr%@%targetIP% > %Mrtgcfgbin%\%target%.cfg e: cd\mrtg\prod\bats exitmrtg-2.17.10/contrib/nt_n_cisco/cisco_devices_to_poll.txt0000644000175300017510000000025613057016061022521 0ustar oetikeroeproutername1 public 127.0.0.2 routername2 public 127.0.0.3 routername3 public 127.0.0.4 routername4 public 127.0.0.5 routername5 public 127.0.0.6 routername6 public 127.0.0.7 mrtg-2.17.10/contrib/nt_n_cisco/RunCcfgs.cmd0000644000175300017510000000035513057016061017625 0ustar oetikeroep@ECHO OFF @set lDir=e:\mrtg\prod\bats @Set hostsfile=e:\cisco_devices_to_poll.txt @Set PARSEARG="eol=; tokens=1,2,3* delims=:, " @For /F %PARSEARG% %%i in (%hostsfile%) Do START /BELOWNORMAL %lDir%\queryone.bat %%i @exit mrtg-2.17.10/contrib/nt_n_cisco/make_all_cisco_configs.bat0000644000175300017510000000033113057016061022545 0ustar oetikeroep Set hostsfile=e:\cisco_devices_to_poll.txt Set PARSEARG="eol=; tokens=1,2,3* delims=:, " For /F %PARSEARG% %%i in (%hostsfile%) Do START /BELOWNORMAL e:\mrtg\prod\bats\RUN_builder.bat %%i %%j %%k exit mrtg-2.17.10/contrib/nt_n_cisco/nt_template.cfg0000644000175300017510000002423013057016061020421 0ustar oetikeroep WorkDir: e:\inetpub\wwwroot\mrtg\pages\your-machine-name-here #IconDir: /systap/images/ Title[^]: CPU #1 Usage (%) on Servers: Target[your-machine-name-here_DSK_C]: 1.3.6.1.4.1.311.1.1.3.1.1.5.1.4.6.48.58.48.58.67.58&1.3.6.1.4.1.311.1.1.3.1.1.5.1.4.6.48.58.48.58.67.58:public@your-machine-name-here MaxBytes[your-machine-name-here_DSK_C]: 8700000 Title[your-machine-name-here_DSK_C]: your-machine-name-here PageTop[your-machine-name-here_DSK_C]:

      Disk Space Remaining (MB) on C: on "your-machine-name-here"

      Options[your-machine-name-here_DSK_C]: gauge, absolute, growright Unscaled[your-machine-name-here_DSK_C]: dwmy XSize[your-machine-name-here_DSK_C]: 320 YSize[your-machine-name-here_DSK_C]: 100 YLegend[your-machine-name-here_DSK_C]: DISK Free (MB) ShortLegend[your-machine-name-here_DSK_C] : MB Legend1[your-machine-name-here_DSK_C]: Disk Space Available Available in MBytes Legend2[your-machine-name-here_DSK_C]: Disk Space Available Available in MBytes LegendI[your-machine-name-here_DSK_C]: DiskFree: LegendO[your-machine-name-here_DSK_C]: DiskFree: Target[your-machine-name-here_IP_STATS]: 1.3.6.1.4.1.311.1.1.3.1.1.10.2.0&1.3.6.1.4.1.311.1.1.3.1.1.10.9.0:public@your-machine-name-here MaxBytes[your-machine-name-here_IP_STATS]: 20 AbsMax[your-machine-name-here_IP_STATS]: 30 Title[your-machine-name-here_IP_STATS]: your-machine-name-here PageTop[your-machine-name-here_IP_STATS]:

      IP Datagram Statistics on "your-machine-name-here"

      Options[your-machine-name-here_IP_STATS]: gauge, nopercent, growright Unscaled[your-machine-name-here_IP_STATS]: dwmy #Supress[your-machine-name-here_IP_STATS]:dwmy XSize[your-machine-name-here_IP_STATS]: 320 YSize[your-machine-name-here_IP_STATS]: 100 YLegend[your-machine-name-here_IP_STATS]: Datagrams/Sec ShortLegend[your-machine-name-here_IP_STATS]: Datagrams Legend1[your-machine-name-here_IP_STATS]: IP Datagrams Received/Second Legend2[your-machine-name-here_IP_STATS]: IP Datagrams Sent/Second #Legend3[your-machine-name-here_IP_STATS]: #Legend4[your-machine-name-here_IP_STATS]: LegendI[your-machine-name-here_IP_STATS]: Recv'd: LegendO[your-machine-name-here_IP_STATS]: Sent: Target[your-machine-name-here_MEM]: 1.3.6.1.4.1.311.1.1.3.1.1.1.1.0&1.3.6.1.4.1.311.1.1.3.1.1.1.2.0:public@your-machine-name-here MaxBytes[your-machine-name-here_MEM]: 256000000 AbsMax[your-machine-name-here_MEM]: 1024000000 Title[your-machine-name-here_MEM]: your-machine-name-here PageTop[your-machine-name-here_MEM]:

      Memory: Available Bytes vs. Committed Bytes on "your-machine-name-here"

      Dotted red line indicates physical memory actually installed (256MB)

      Options[your-machine-name-here_MEM]: gauge, absolute, growright Unscaled[your-machine-name-here_MEM]: dwmy #Supress[your-machine-name-here_MEM]:dwmy XSize[your-machine-name-here_MEM]: 320 YSize[your-machine-name-here_MEM]: 100 YLegend[your-machine-name-here_MEM]: Bytes (MB) ShortLegend[your-machine-name-here_MEM]: Bytes Legend1[your-machine-name-here_MEM]: Memory Available in MBytes Legend2[your-machine-name-here_MEM]: Memory Committed in MBytes #Legend3[your-machine-name-here_MEM]: #Legend4[your-machine-name-here_MEM]: LegendI[your-machine-name-here_MEM]: Available:  LegendO[your-machine-name-here_MEM]: Committed:  Target[your-machine-name-here_NIC]: 2:public@your-machine-name-here MaxBytes[your-machine-name-here_NIC]: 1250000 Title[your-machine-name-here_NIC]: your-machine-name-here PageTop[your-machine-name-here_NIC]:

      NIC Statistics on "your-machine-name-here"

      Options[your-machine-name-here_NIC]: bits, growright XSize[your-machine-name-here_NIC]: 320 YSize[your-machine-name-here_NIC]: 100 LegendI[your-machine-name-here_NIC]: Bytes-In: LegendO[your-machine-name-here_NIC]: Bytes-Out: #, growright Target[your-machine-name-here_Q_THREADS]: 1.3.6.1.4.1.311.1.1.3.1.1.18.1.3.14.66.108.111.99.107.105.110.103.32.81.117.101.117.101&1.3.6.1.4.1.311.1.1.3.1.1.18.1.4.14.66.108.111.99.107.105.110.103.32.81.117.101.117.101:public@your-machine-name-here MaxBytes[your-machine-name-here_Q_THREADS]: 20 AbsMax[your-machine-name-here_Q_THREADS]: 30 Title[your-machine-name-here_Q_THREADS]: your-machine-name-here PageTop[your-machine-name-here_Q_THREADS]:

      your-machine-name-here: Queue Length vs. Active Threads on "your-machine-name-here"

      Options[your-machine-name-here_Q_THREADS]: gauge, nopercent, growright Unscaled[your-machine-name-here_Q_THREADS]: dwmy #Supress[your-machine-name-here_Q_THREADS]:dwmy XSize[your-machine-name-here_Q_THREADS]: 320 YSize[your-machine-name-here_Q_THREADS]: 100 YLegend[your-machine-name-here_Q_THREADS]: Value ShortLegend[your-machine-name-here_Q_THREADS]:   Legend1[your-machine-name-here_Q_THREADS]: Server Queue Length Legend2[your-machine-name-here_Q_THREADS]: Server Active Threads #Legend3[your-machine-name-here_Q_THREADS]: #Legend4[your-machine-name-here_Q_THREADS]: LegendI[your-machine-name-here_Q_THREADS]:  QueueLength:  LegendO[your-machine-name-here_Q_THREADS]:  Threads:  Target[your-machine-name-here_CPU]: 1.3.6.1.4.1.311.1.1.3.1.1.2.1.5.0&1.3.6.1.4.1.311.1.1.3.1.1.2.1.4.0:public@your-machine-name-here MaxBytes[your-machine-name-here_CPU]: 100 Title[your-machine-name-here_CPU]: your-machine-name-here PageTop[your-machine-name-here_CPU]:

      CPU #1 Usage (%) on "your-machine-name-here"

      Options[your-machine-name-here_CPU]: gauge, nopercent, absolute, growright Unscaled[your-machine-name-here_CPU]: dwmy #Supress[your-machine-name-here_CPU]:dwmy XSize[your-machine-name-here_CPU]: 320 YSize[your-machine-name-here_CPU]: 100 YLegend[your-machine-name-here_CPU]: CPU Usage (%) ShortLegend[your-machine-name-here_CPU]: % Legend1[your-machine-name-here_CPU]: Privileged (NT system) CPU use in percent Legend2[your-machine-name-here_CPU]: User (application) CPU use in percent #Legend3[your-machine-name-here_CPU]: #Legend4[your-machine-name-here_CPU]: LegendI[your-machine-name-here_CPU]: PrivCPU: LegendO[your-machine-name-here_CPU]: UserCPU: #--------------------------------------------------pageflts Target[your-machine-name-here_MSMPFS]: 1.3.6.1.4.1.311.1.1.3.1.1.1.4.0&1.3.6.1.4.1.311.1.1.3.1.1.1.4.0:public@your-machine-name-here MaxBytes[your-machine-name-here_MSMPFS]: 50 Title[your-machine-name-here_MSMPFS]: your-machine-name-here PageTop[your-machine-name-here_MSMPFS]:

      Memory Page Faults per Second on "your-machine-name-here"

      Options[your-machine-name-here_MSMPFS]: gauge, nopercent, absolute, growright Unscaled[your-machine-name-here_MSMPFS]: dwmy #Supress[your-machine-name-here_MSMPFS]:dwmy XSize[your-machine-name-here_MSMPFS]: 320 YSize[your-machine-name-here_MSMPFS]: 100 YLegend[your-machine-name-here_MSMPFS]: Pages Faults per Second ShortLegend[your-machine-name-here_MSMPFS]: PFS Legend1[your-machine-name-here_MSMPFS]: Memory Pages Faults per Second #Legend2[your-machine-name-here_MSMPFS]: #Legend3[your-machine-name-here_MSMPFS]: #Legend4[your-machine-name-here_MSMPFS]: LegendI[your-machine-name-here_MSMPFS]: MemPageFaults:  LegendO[your-machine-name-here_MSMPFS]: MemPageFaults:  #---------------------------------------------------pagespersec Target[your-machine-name-here_MEMPPS]: 1.3.6.1.4.1.311.1.1.3.1.1.1.9.0&1.3.6.1.4.1.311.1.1.3.1.1.1.9.0:public@your-machine-name-here MaxBytes[your-machine-name-here_MEMPPS]: 50 Title[your-machine-name-here_MEMPPS]: your-machine-name-here PageTop[your-machine-name-here_MEMPPS]:

      Memory: Pages per Second on "your-machine-name-here"

      Options[your-machine-name-here_MEMPPS]: gauge, nopercent, absolute, growright Unscaled[your-machine-name-here_MEMPPS]: dwmy #Supress[your-machine-name-here_MEMPPS]:dwmy XSize[your-machine-name-here_MEMPPS]: 320 YSize[your-machine-name-here_MEMPPS]: 100 YLegend[your-machine-name-here_MEMPPS]: Pages per Second ShortLegend[your-machine-name-here_MEMPPS]: PPS Legend1[your-machine-name-here_MEMPPS]: Memory Pages per Second #Legend2[your-machine-name-here_MEMPPS]: #Legend3[your-machine-name-here_MEMPPS]: #Legend4[your-machine-name-here_MEMPPS]: LegendI[your-machine-name-here_MEMPPS]: MemPages: LegendO[your-machine-name-here_MEMPPS]: MemPages: #---------------------------------------------------pagereadspersec Target[your-machine-name-here_MEMPRS]: 1.3.6.1.4.1.311.1.1.3.1.1.1.11.0&1.3.6.1.4.1.311.1.1.3.1.1.1.11.0:public@your-machine-name-here MaxBytes[your-machine-name-here_MEMPRS]: 5 AbsMax[your-machine-name-here_MEMPRS]: 25 Title[your-machine-name-here_MEMPRS]: your-machine-name-here PageTop[your-machine-name-here_MEMPRS]:

      Memory: Page Reads (hard faults) per Second on "your-machine-name-here" (sustained rate of 5 or more per second indicates RAM shortage and performance hit!)

      Options[your-machine-name-here_MEMPRS]: gauge, nopercent, absolute, growright Unscaled[your-machine-name-here_MEMPRS]: dwmy #Supress[your-machine-name-here_MEMPRS]:dwmy XSize[your-machine-name-here_MEMPRS]: 320 YSize[your-machine-name-here_MEMPRS]: 100 YLegend[your-machine-name-here_MEMPRS]: Page Reads per Second ShortLegend[your-machine-name-here_MEMPRS]: PRS Legend1[your-machine-name-here_MEMPRS]: Memory Page Reads per Second Legend2[your-machine-name-here_MEMPRS]: Memory Page Reads per Second #Legend3[your-machine-name-here_MEMPRS]: #Legend4[your-machine-name-here_MEMPRS]: LegendI[your-machine-name-here_MEMPRS]: MemPages: LegendO[your-machine-name-here_MEMPRS]: MemPages: #-------NEW---------NEW--------- # My additional OID's # tcpCurrEstab/tcpAttemptFails Title[your-machine-name-here_tcpCurrEstab__tcpAttemptFails]: your-machine-name-here PageTop[your-machine-name-here_tcpCurrEstab__tcpAttemptFails]:

      tcpCurrEstab/tcpAttemptFails on "your-machine-name-here"

      Target[your-machine-name-here_tcpCurrEstab__tcpAttemptFails]: 1.3.6.1.2.1.6.9.0&1.3.6.1.2.1.6.7.0:public@your-machine-name-here MaxBytes[your-machine-name-here_tcpCurrEstab__tcpAttemptFails]: 1250000 Options[your-machine-name-here_tcpCurrEstab__tcpAttemptFails]: gauge, nopercent, absolute, growright XSize[your-machine-name-here_tcpCurrEstab__tcpAttemptFails]: 320 YSize[your-machine-name-here_tcpCurrEstab__tcpAttemptFails]: 100 mrtg-2.17.10/contrib/nt_n_cisco/queryone.bat0000644000175300017510000000017313057016061017763 0ustar oetikeroep e: cd\ cd\mrtg\run sleep.exe 5 %perlbin%\perl.exe %mrtgbin%\mrtg %mrtgcfgbin%\%1.cfg cd\mrtg\prod\bats EXITmrtg-2.17.10/contrib/nt_n_cisco/RUN_builder.bat0000644000175300017510000000015413057016061020265 0ustar oetikeroepREM should look like this : builder.bat you-devicename-here public 10.0.0.2 builder.bat %1 %2 %3 exitmrtg-2.17.10/contrib/nt_n_cisco/README0000644000175300017510000000620613057016061016307 0ustar oetikeroepFrom: CmdrData Subject: mrtg for nt and cisco I have been using MRTG running on Windows NT now for a few months and find it to be pretty cool. Thanks so much for making a free tool. The first time I installed it was on a Proliant 2500 w/ dual 200 Mhz CPUs , and the setup was sloppy b/c I was learning how to run the program and make the config files, programatically. The setup I had was less than ideal. So I built a new Proliant 6500 w/ 4 x 200 Mhz CPUs and 3/4 GB RAM and hardware RAID5 using 6 drives a couple of months later. I also install Microsoft SQL server and IIS on the box. What I now have is an mrtg database in sql wh/ has 2 tables 1 for NT devices and 1 for Cisco Devices. The main web page I use has 2 combo boxes which load from these table devices descriptors which are names and not ips. The main reason I used sql was so the web page would get auto updated when a devices was added and also so I could automate the configuration file creation and the list of devices it choose to poll. I made a DTS package in sql which every 2 hours dumps parts of the two tables to text files (the sql 7.0 DTS wizard for this makes it easy to dump parts of a table to a file). these 2 files are used to update all the configs every 12 hours. To accomplish this I had to write a bunch of batch files that would read text file input and do some very repeatable tasks. I also set a few environment variables to make the writing and reading easier. Since your site was very useful in getting me started I wanted to give a little back. I have attached a few nt batch files which would be useful for anyone trying to set it up on NT. I still have more automating to do like making the default.asp page without needing hand editing, and I haven't automated the ntconfig process. But right now to add cisco devices all I need to do is add a record to a database! I am using this setup to monitor about 2700 + ports on mainly catalyst 6500's right now and it finishes its polling cycle in about 4 minutes. The machine seems to be cpu and disk bound. Quad 450's would be better and a raid with more drive heads would also be better. I used the START command with the /BELOWNORMAL switch in a couple of places to allow the OS to jump in if it needs to b/c the CPU rides at about 99-100% for most of the 4 minutes. SQL is not needed to make use of the attached scripts. The files just contain 3 items, name (wh/equals part of the workdir path), comm str and IP [or netbiosname]. I also had to hunt around for the nt info and put it in to one file which you can do a find and replace on to customize what nt targets you poll. Feel free to post these files if you like. What I still have not figured out is how to get the detailed port description to be used instead of the ifIndexs. The post you have on this doesn't work with the port for NT and I don't know Perl. If you have any suggestions on this I would appreciate it. I tried to compare the mrtg file from the nt port and the hack and the files were too different for me to splice together without real knowlegde of perl, etc. Anyhow love the app. I work for a web hosting company. thanks, -Jon mrtg-2.17.10/contrib/nt_n_cisco/default.asp0000644000175300017510000000217013057016061017554 0ustar oetikeroep<%@ LANGUAGE="VBSCRIPT" %> MRTG DATA

      Your-Router-Name_here

      Ports on Router

      <% Set fs = CreateObject("Scripting.FileSystemObject") Dim fs, f, f1, fc, fstr, linklen, bufflink Set fs = CreateObject("Scripting.FileSystemObject") Set f = fs.GetFolder("e:\inetpub\wwwroot\mrtg\pages\Your-Router-Name_here") Set fc = f.Files For Each f1 in fc fstr = LCase(f1.name) If Right(fstr, 8) = "-day.gif" Then linklen = Len(fstr) buffLink = Mid(fstr,1,(linklen - 8)) Response.Write ("
      ") Response.Write("") Response.Write (" ") Response.write ("") Response.write (bufflink & "
      ") Response.Write VbCrLf Response.write "
      " & VbCrLf End If Next %> mrtg-2.17.10/contrib/stat/0000755000175300017510000000000013057016062014261 5ustar oetikeroepmrtg-2.17.10/contrib/stat/README0000644000175300017510000000343413057016062015145 0ustar oetikeroep# $Id: README,v 1.1.1.1 2002/02/26 10:16:37 oetiker Exp $ stat.pl You could use this script to monitor youre DNS activities. Its a very simple perl script and youre free to do any updates on it, but please send a copy to me calle@volvo.se. you have to do some small changes like hostname and path to named.stats. if youre using it please let me know so i could send you updates. INSTALLATION: To get it to work do execute the script once before you make mrtg to do it for you. This will make an OLD file with the last requested queries. You might get an error messages , but the next time you execute it the stats will come as you want it. USAGE: If you run this on a DNS server just add an script that will make a stat file (Bind 4 (kill -ABRT `/var/run/named.pid`)), (Bind 8.1. (kill -ILL `/var/run/named.pid)) and remove the old named.stats. and put this into cron. For Bind 8.2.1 you will need to be using ndc (ndc stats). ex. script to run from cron #!/bin/sh rm /var/tmp/named.stats kill -ABRT `cat /var/run/named.pid` /mrtg MRTG: To set up this in MRTG: Target[dns]: `//stat.pl` REMOTE: I did a small script called dns.named that will collect named from a remote DNS, but i strongly recomend to rewrite this so instead of using FTP use scp. this script requires expect. UPDATES: The new stat.pl you could use 2 diffrent graph in one session , that is lets say you want to logg all Requested queries and maybe count of zone transfers. all you have to do is to specify these in $OUTGOING and $INCOMING in stat.pl. The script also looks how for how long the named have been runing without a reset. mrtg-2.17.10/contrib/stat/mrtg.cfg0000755000175300017510000000122213057016062015713 0ustar oetikeroep# this is a mrtg test setup #im gonna try using some fine examples (hopefully) to make this work. # this is gonna be a DNS graph (when if ever im ready). # $Id: mrtg.cfg,v 1.1.1.1 2002/02/26 10:16:37 oetiker Exp $ WorkDir: WWW/PATH/TO/SITE/ ## Intervall set to 5 min Interval: 10 # now lets set up a Target to get stats from Target[bn]: `PATH/stat.pl` MaxBytes[bn]: 32000 AbsMax[bn]: 64000 Options[bn]: gauge Title[bn]: DNS statististics PageTop[bn]:

      DNS1 statistic

      \n XSize[bn]: 500 Supress[bn]: y Ysize[bn]: 200 YLegend[bn]: No. Questions asked/10 min ShortLegend[bn]: q/10 min LegendO[bn]:   dnsqueries: LegendI[bn]: WithPeak[bn]: ym mrtg-2.17.10/contrib/stat/dns_mrtg0000755000175300017510000000027013057016062016023 0ustar oetikeroep#!/bin/sh # $Id: dns_mrtg,v 1.1.1.1 2002/02/26 10:16:37 oetiker Exp $ #thnis file should be run by cron DIRECTORY/TO/THIS/SCRIPT/dns.named /PATH/TO/MRTG/mrtg PATH/TO/MRTG.CFG/mrtg.cfg mrtg-2.17.10/contrib/stat/dns.named0000755000175300017510000000060613057016062016060 0ustar oetikeroep#!/usr/bin/expect # $Id: dns.named,v 1.1.1.1 2002/02/26 10:16:37 oetiker Exp $ spawn ftp HOST.YOURE.DOMAIN expect "Name" send "USER\r" expect "^Password:" send "PASSWORD\r" expect "ftp>" send "cd /var/tmp\r" expect "ftp>" send "ascii\r" expect "ftp>" send "lcd DIRECTORY/WICH/STAT.pl/WILL/USE/TO/GET/NAMED.STATS\r" expect "ftp>" send "get named.stats\r" expect "ftp>" send "quit\r" sleep 4 mrtg-2.17.10/contrib/stat/stat.pl0000755000175300017510000001154513057016062015602 0ustar oetikeroep#!/usr/bin/perl -w # $Id: stat.pl,v 1.1.1.1 2002/02/26 10:16:37 oetiker Exp $ #################### # New updates for stat.pl #################### %D_STAT=( RQ => 0, RR => 1, RIQ => 2, RNXD => 3, RFwdQ => 4, RFwdR => 5, RDupQ => 6, RDupR => 7, RFail => 8, RFErr => 9, RErr => 10, RTCP => 11, RAXFR => 12, RLame => 13, ROpts => 14, SSysQ => 15, SAns => 16, SFwdQ => 17, SDupQ => 18, SFail => 19, SFErr => 20, SErr => 21, RNotNsq => 22, SNaAns => 23, SNXD => 24, ); # This file is to feed mrtg with right information. # You could do this more fancy with up-time and stuff like that, # but that will be maybe in a couple of versions upward. # This works and i dont want to be like other big companys that gives out # Programs that want work but is all that fancy. # # Any way please do change this files so the right PATH to youre scripts # are there. # Requirements: # this scripts require MRTG (of course), i wont get in how to configure this, # because im not sure how to do it correctly, i manged to get it to work. # but i sugest you take a real good look how to configure MRTG. # more requirement is , perl version 5.004_05. Look at the documentation # on MRTG this one needs you to have some patches for some OS. # # If you want to use getting iformation from a remote DNS, sure you could use # my script dns.named but beware that this is NOT safe maybe you should use # If you want to use getting iformation from a remote DNS, sure you could use # scp to get youre file, but if not, be sure to set the rights so no non-auth # could see what password is. # dns.named requires expect version 5.26.0 (i havent tested on other versions) # # im not the greatest script maker but i managed this to work, but if # you have any comments or you have some great changes please be free to send them to calle@volvo.se # HOSTNAME youre domain this will show up in the web-page # # OK now to this new version of this program # $LOG is where you find youre named.stats * # in Bind 8.2.1 the way to get youre named.stats is "ndc stats" # in Bind 4.9.3 kill -ABRT `cat /var/run/named.pid` # in Bind kill -ILL `cat /var/run/named.pid` # # $RUN you have to set that to where youre script is set to run ex my $RUN = "/home/myhomeaccount/"; # # now to the real new thing that is you can have 2 graphs in one MRTG session # you have to set the $INCOMING and $OUTGOING, $INCOMING = $D_STAT{"RQ"}; <-- this one needs to be set to look # for wich Data you want to see on the first Graph (RQ is Requested Queries) # # now to the other $OUTGOING = $D_STAT{"RFail"}; i set default but can be changed for what you want # RFail Requested Failure i done a short list of What some of them means , but if you want to have a complete list # you could look into the DNS and Bind book from O'reilly page 166 # # Short list of some of the things you could pull out # # RQ: Requested Queries. # RR: Count of responses recieved from relay. # RIQ: Count of reverse queries recieved from relay. # RNXD: Count of "no such domain" answeres. # RFwdQ: Count of queries received from relay that nedded more processing # RFwdR: Count of is the reponses recived from relay that answered the # original query and were passed back to application. # RDupR: Is the count of duplicat response from relay. # RFail: Is the count of SERVFAIL response from relay. # RFErr: is the count of FORMERR response from relay. # RErr: is the count of errors that werent either SERVFAIL or FORMERR # RLame: Count of lame DELEGATIONS. # and so on read the book. my $HOSTNAME = "HOST\.YOURE\.DOMAIN"; my $LOG = "/home/"; my $RUN = "/home/"; my $INCOMING = $D_STAT{"RQ"}; my $OUTGOING = $D_STAT{"RFail"}; ####################################### #### Please Dont toch this part ###################################### my $QUE_P_MIN =(); my $QUE_P_OTHER = (); my @N_STATS=(); my @OLD_S=(); my $UPTIME = (); sub HIST { open (STAT , "$LOG") or die "could not find or open file $LOG"; @N_STAT = ; close (STAT); open (V_OLD , "$RUN/OLD"); my @OLD_S = ; close (V_OLD); my $G_FLAG = "no"; foreach $line (@N_STAT) { if ( $line =~ m/^([0-9]+)\s+\S+\s+\S+\sreset/ ){ $UPTIME = $1; } if ( $G_FLAG =~ /yes/) { my @NUM_QUE=split ' ',$line; open ( LOGGER , "> $RUN/OLD"); print LOGGER "$NUM_QUE[$INCOMING]\n"; print LOGGER "$NUM_QUE[$OUTGOING]\n"; close ( LOGGER ); $QUE_P_MIN = $NUM_QUE[$INCOMING]-$OLD_S[0]; $QUE_P_OTHER = $NUM_QUE[$OUTGOING]-$OLD_S[1]; $G_FLAG = "no"; } if ($line =~ /(Global)/) { $G_FLAG = "yes"; } } print "$QUE_P_MIN\n$QUE_P_OTHER\n$UPTIME\n$HOSTNAME\n"; } &HIST(); mrtg-2.17.10/contrib/portmasters/0000755000175300017510000000000013057016061015670 5ustar oetikeroepmrtg-2.17.10/contrib/portmasters/portm.cfg0000644000175300017510000000523213057016061017514 0ustar oetikeroepWorkDir: /home/admin/pmgraph Target[portmaster]: `cat /home/admin/pmgraph/bin/pmgrand` Title[portmaster]: Modem Traffic for Nantucket.net PageTop[portmaster]:

      Modem Traffic for Nantucket.net

      This page shows the total modem use at Nantucket.net. We currently have three Livingston Portmaster terminal servers that each control thirty modems, giving us a grand total of 90 dial-in lines. We also graph each Portmaster out separately, See: MaxBytes[portmaster]: 90 AbsMax[portmaster]: 90 Options[portmaster]: absolute, gauge Ylegend[portmaster]: Total lines in use RouterUptime[portmaster]: ShortLegend[portmaster]: Modems Online Unscaled[portmaster]: mwy LegendI[portmaster]: LegendO[portmaster]: Total Legend2[portmaster]: Total count of all modems online at Nantucket.net Target[sconset]: `cat /home/admin/pmgraph/bin/pm1-log` PageTop[sconset]:

      Modem Traffic on Portmaster Sconset

      MaxBytes[sconset]: 30 AbsMax[sconset]: 30 Options[sconset]: absolute, gauge Title[sconset]: Modem Traffic on Portmaster Sconset Ylegend[sconset]: Lines in use RouterUptime[sconset]:public@sconset.nantucket.net ShortLegend[sconset]: Modems Online Unscaled[sconset]: dmwy LegendI[sconset]: LegendO[sconset]: Total Legend2[sconset]: Total count of modems used on Portmaster Sconset Target[scallop]: `cat /home/admin/pmgraph/bin/pm2-log` PageTop[scallop]:

      Modem Traffic on Portmaster Scallop

      MaxBytes[scallop]: 30 AbsMax[scallop]: 30 Options[scallop]: absolute, gauge Title[scallop]: Modem Traffic on Portmaster Scallop Ylegend[scallop]: Lines in use RouterUptime[scallop]:public@scallop.nantucket.net ShortLegend[scallop]: Modems Online Unscaled[scallop]: dmwy LegendI[scallop]: LegendO[scallop]: Total Legend2[scallop]: Total count of modems used on Portmaster Scallop Target[surfside]: `cat /home/admin/pmgraph/bin/pm3-log` PageTop[surfside]:

      Modem Traffic on Portmaster Surfside

      MaxBytes[surfside]: 30 AbsMax[surfside]: 30 Options[surfside]: absolute, gauge Title[surfside]: Modem Traffic on Portmaster Surfside Ylegend[surfside]: Lines in use RouterUptime[surfside]:public@surfside.nantucket.net ShortLegend[surfside]: Modems Online Unscaled[surfside]: dmwy LegendI[surfside]: LegendO[surfside]: Total Legend2[surfside]: Total count of modems used on Portmaster Surfside mrtg-2.17.10/contrib/portmasters/gather0000644000175300017510000000435213057016061017071 0ustar oetikeroep#!/bin/csh # run this script ever 5 minutes via cron with a crontab something like: # 1,6,11,16,21,26,31,36,41,46,51,56 * * * * /home/admin/pmgraph/bin/getstats # note that this script calls MRTG # set the names or IP's of your Portmasters set Portmaster1="sconset.nantucket.net" set Portmaster2="scallop.nantucket.net" set Portmaster3="surfside.nantucket.net" # set the SNMP read community of your Portmasters set P1comm="public" set P2comm="public" set P3comm="public" # Grab a user count for each Portmaster via the snmpwalk command # You may need to use "snmpwalk -v 1" depending on your version of snmpwalk # You may also need to grep for something other than "23" set PM1=`snmpwalk $Portmaster1 $P1comm interfaces.ifTable.ifEntry.ifType|grep 23 |wc -l` set PM2=`snmpwalk $Portmaster2 $P2comm interfaces.ifTable.ifEntry.ifType|grep 23 |wc -l` set PM3=`snmpwalk $Portmaster3 $P3comm interfaces.ifTable.ifEntry.ifType|grep 23 |wc -l` # Get a grand total of users online @ TOTAL=$PM1 + $PM2 + $PM3 # MRTG needs 4 lines of input to be happy, we're only interested in the 2nd # line and possibly the first so we fill the others with junk # write out the various logs # grand total of all your Portmasters echo "0" > /home/admin/pmgraph/bin/pmgrand echo $TOTAL >> /home/admin/pmgraph/bin/pmgrand echo "0" >> /home/admin/pmgraph/bin/pmgrand echo "0" >> /home/admin/pmgraph/bin/pmgrand # Portmaster #1 echo "0" > /home/admin/pmgraph/bin/pm1-log echo $PM1 >> /home/admin/pmgraph/bin/pm1-log echo "time" >> /home/admin/pmgraph/bin/pm1-log echo "pm1" >> /home/admin/pmgraph/bin/pm1-log # Portmaster #2 echo "0" > /home/admin/pmgraph/bin/pm2-log echo $PM2 >> /home/admin/pmgraph/bin/pm2-log echo "time" >> /home/admin/pmgraph/bin/pm2-log echo "pm2" >> /home/admin/pmgraph/bin/pm2-log # Portmaster #3 echo "0" > /home/admin/pmgraph/bin/pm3-log echo $PM3 >> /home/admin/pmgraph/bin/pm3-log echo "time" >> /home/admin/pmgraph/bin/pm3-log echo "pm3" >> /home/admin/pmgraph/bin/pm3-log # and finally, run MRTG specifying our customized .cfg file eval `/home/admin/pmgraph/bin/mrtg /home/admin/pmgraph/bin/portmaster.cfg` mrtg-2.17.10/contrib/portmasters/README0000644000175300017510000000135613057016061016555 0ustar oetikeroepFrom admin@nantucket.net Mon Mar 10 06:15:36 1997 Date: Wed, 05 Mar 1997 14:22:55 -0500 From: Chris Johnson Subject: MRTG for portmasters Hey Tobias, I was fooling around with your wonderful program and I ended up hacking out a script and config to produce Modem statistics for Livingston Portmasters. You can see the results at http://www.nantucket.net/users/admin/pmgraph/ if you're interested . I've enclosed my work here since, maybe you can post it somewhere and save other Portmaster owners some work. Your Nantucket postcard is on it's way! ===================================================== Chris Johnson admin@nantucket.net ===================================================== mrtg-2.17.10/contrib/switchmaker/0000755000175300017510000000000013057016062015627 5ustar oetikeroepmrtg-2.17.10/contrib/switchmaker/README0000644000175300017510000000137513057016062016515 0ustar oetikeroepFrom: Markley P. Dykeman Date: Sun, 21 Nov 1999 15:14:00 -0700 I have enjoyed using your MRTG program to accomplish my tasks. Thank you for a wonderful toolbox. Attached to this document is a perl program called switchmaker which will simply make an mrtg config file for a Cisco Catylst 5XXX switch. Unfortunatly, I had to use the SNMP-Util-1.6 and SNMP-1.8 libraries because I had trouble getting the libraries distrubuted with 2.7.2 to work correctly with my code--more of an inadequacy on my part. But, providing you have those libraries or are willing to port it, it does work very well. At any rate it does document the MIBS you need to know to get the correct port information out of the switch... Enjoy. -- Markley Dykeman mrtg-2.17.10/contrib/switchmaker/switchmaker0000644000175300017510000001677613057016062020114 0ustar oetikeroep#!/usr/local/bin/perl ####################################################### # switchmaker for MRTG ####################################################### # Author: Markley Dykeman - 04/27/99 # Purpose: This program makes an MRTG configuration # file for Cisco 5500 switches. # Usage: switchmaker # Requires: SNMP-Util-1.6 and SNMP-1.8 ####################################################### my $testing = 0; # Libraries use SNMP::Util; use Socket; use strict; # Environment $ENV{'MAX_LOG_LEVEL'} = 'status'; # Usage display if (@ARGV < 1){ print "Usage: \n"; print " switchmaker \n"; print "\n"; print " IP = IP address or Switch name\n"; print " comm = defaults to hostname\n"; exit; } # Arrays my(%iftype)=( '1'=>'other', '2'=>'cddi', '3'=>'fddi', '4'=>'tppmd', '5'=>'mlt3', '6'=>'sddi', '7'=>'smf', '8'=>'e10BaseT', '9'=>'e10BaseF', '10'=>'scf', '11'=>'e100BaseTX', '12'=>'e100BaseT4', '13'=>'e100BaseF', '14'=>'atmOc3mmf', '15'=>'atmOc3smf', '16'=>'atmOc3utp', '17'=>'e100BaseFsm', '18'=>'e10a100BaseTX', '19'=>'mii', '20'=>'vlanRouter', '22'=>'tokenring', '23'=>'atmOc12mmf', '24'=>'atmOc12smf', '25'=>'atmDs3', '26'=>'tokenringMmf', '27'=>'e1000BaseLX' ); # Declare working variables my ($sysDescr, $sysName, $sysIpAddr, %portGrp, $portIfIndex, $interfacecnt, @result, @oid_list, $iphost); my (@oid_cutoff, $i); # Get command line arguments my $IP = $ARGV[0]; my $Comm_string = $ARGV[1]; # Open connection to device my $snmp = new SNMP::Util(-device => $IP, -community => $Comm_string); ######################## # Get system information ######################## @result = $snmp->next( 'ne', '1.3.6.1.2.1.1.1'); #sysDescr $sysDescr = $result[1]; @result = $snmp->next( 'ne', '1.3.6.1.2.1.1.5'); #sysName $sysName = $result[1]; @result = $snmp->next( 'ne', '1.3.6.1.4.1.9.5.1.1.2'); #sysIpAddr $sysIpAddr = $result[1]; $iphost = gethostbyaddr(pack('C4',split(/\./,$sysIpAddr)), AF_INET); #iphost if (!defined $iphost || ($iphost eq '')){ $iphost = 'Unknown DNS name'; } ######################### # Walk through ports ######################### @oid_list = ( '1.3.6.1.4.1.9.5.1.4.1.1.11', #portIfIndex '1.3.6.1.4.1.9.5.1.4.1.1.5', #portType '1.3.6.1.4.1.9.5.1.4.1.1.10', #portDuplex '1.3.6.1.4.1.9.5.1.4.1.1.1', #portModuleIndex '1.3.6.1.4.1.9.5.1.4.1.1.2', #portIndex '1.3.6.1.4.1.9.5.1.4.1.1.4', #portName ); @oid_cutoff = '1.3.6.1.4.1.9.5.1.4.1.1.11'; # Walk the MIBs... my ($more) = 1; while ($more) { @result = $snmp->next( -format => 'one', -oids => \@oid_list, ); # Are we done walking? if (@result[0] !~ /@oid_cutoff/) { $more = 0; } # if not, process the data if ($more) { $portIfIndex = $result[2]; $interfacecnt = $result[2]; $portGrp{$portIfIndex}{'portIfIndex'} = $result[2]; $portGrp{$portIfIndex}{'portType'} = $result[5]; $portGrp{$portIfIndex}{'portDuplex'} = $result[8]; $portGrp{$portIfIndex}{'portModuleIndex'} = $result[11]; $portGrp{$portIfIndex}{'portIndex'} = $result[14]; $portGrp{$portIfIndex}{'portName'} = $result[17]; } # Update OID for snmp->next @oid_list = ($result[0],$result[3],$result[6],$result[9],$result[12],$result[15]); } ############################## # Walk through MIB2 interfaces ############################## @oid_list = ( '1.3.6.1.2.1.2.2.1.1', #ifIndex '1.3.6.1.2.1.2.2.1.2', #ifDescr '1.3.6.1.2.1.2.2.1.3', #ifType '1.3.6.1.2.1.2.2.1.5', #ifSpeed '1.3.6.1.2.1.2.2.1.7', #ifAdminStatus '1.3.6.1.2.1.2.2.1.8', #ifOperStatus ); @oid_cutoff = '1.3.6.1.2.1.2.2.1.1'; # Walk the MIBs... my ($more) = 1; while ($more) { @result = $snmp->next( -format => 'one', -oids => \@oid_list, ); # Are we done walking? if (@result[0] !~ /@oid_cutoff/) { $more = 0; } # if not, process the data if ($more) { $portIfIndex = $result[2]; # deal with non-workgroup ports (1 & 2 if ($portGrp{$portIfIndex}{'portIfIndex'} eq "") { $portGrp{$portIfIndex}{'portIfIndex'} = $result[2]; if ($portIfIndex eq "1") { $portGrp{$portIfIndex}{'portName'} = $iphost } else { $portGrp{$portIfIndex}{'portName'} = $result[5]; $portGrp{$portIfIndex}{'ifDescr'} = $result[8]; } } $portGrp{$portIfIndex}{'ifDescr'} = $result[5] if (!($portGrp{$portIfIndex}{'ifDescr'} eq $result[8])); $portGrp{$portIfIndex}{'ifType'} = $result[8]; $portGrp{$portIfIndex}{'ifSpeed'} = $result[11]; $portGrp{$portIfIndex}{'ifAdminStatus'} = $result[14]; $portGrp{$portIfIndex}{'ifOperStatus'} = $result[17]; } # Update OID for snmp->next @oid_list = ($result[0],$result[3],$result[6],$result[9],$result[12],$result[15]); } if ($testing) { print "Summary for $sysName ($sysIpAddr), $sysDescr\n"; for ($i = 1;$i <= $interfacecnt; $i++) { print "$portGrp{$i}{'portIfIndex'} "; print "$portGrp{$i}{'portType'} "; print "$portGrp{$i}{'portDuplex'} "; print "$portGrp{$i}{'portModuleIndex'}/"; print "$portGrp{$i}{'portIndex'} "; print "$portGrp{$i}{'portName'}\n"; print "$portGrp{$i}{'ifDescr'} "; print "$portGrp{$i}{'ifType'} "; print "$portGrp{$i}{'ifSpeed'} "; print "$portGrp{$i}{'ifAdminStatus'} "; print "$portGrp{$i}{'ifOperStatus'}\n"; } } ####################################### # Start creating the configuration file ####################################### print "# Add a WorkDir: /some/path line to this file\n\n"; for ($i = 1;$i <= $interfacecnt; $i++) { my $slash; if ($portGrp{$i}{'portModuleIndex'} eq '') { $slash = " "; } else { $slash = "/"; } my $c; my $ifSpeed = $portGrp{$i}{'ifSpeed'}; my $speedStr = &fmi($ifSpeed); if (!($portGrp{$i}{'ifAdminStatus'} eq "up")) { print <Traffic Analysis for $portGrp{$i}{'portModuleIndex'}$slash$portGrp{$i}{'portIndex'} $portGrp{$i}{'portName'} ${c} ${c} ${c} ${c} ${c} ${c}
      System:$iphost.$i
      Interface: $portGrp{$i}{'portModuleIndex'}$slash$portGrp{$i}{'portIndex'} $portGrp{$i}{'portName'} -- $portGrp{$i}{'ifDescr'} ($i)
      Max Speed: $speedStr ($portGrp{$i}{'portType'}) ($portGrp{$i}{'portDuplex'})
      ${c} ##--------------------------------------------------------------- ECHO } ############################## # Any errors? ############################## my $error = $snmp->error; if ($error){ print "error = $error\n"; } sub fmi { my($number) = $_[0]; my(@short); $number=$number; @short = ("b/s","kb/s","Mb/s","Gb/s"); my $digits=length("".$number); my $divm=0; while ($digits-$divm*3 > 4) { $divm++; } my $divnum = $number/10**($divm*3); return sprintf("%1.1f %s",$divnum,$short[$divm]); } mrtg-2.17.10/contrib/mrtg-archiver/0000755000175300017510000000000013057016061016057 5ustar oetikeroepmrtg-2.17.10/contrib/mrtg-archiver/mrtg.archive.pl0000755000175300017510000001174313057016061021016 0ustar oetikeroep#!/usr/bin/perl -w # # Filename: mrtg.archive.pl # Archive mrtg gifs and summary files # Original author: Emanuele Leonardi # Modified by: Rawlin Blake # # Default placement of mrtg.archive.* is in /usr/local/sbin # If you place them elsewhere, change the $Conf_File setting later in this file. # # The cron entry I use is: # 57 23 * * * /usr/local/sbin/mrtg.archive.pl 1>> /var/log/mrtg.archive.log 2>&1 # # At 23:57 every night it copies the current gifs for the given list of router # interfaces to a directory named with the current date (e.g. 970717). # # 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 of the License, 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. # # revision 1.1 09/10/1999 # Improved error handling # Most configurations moved to separate file # # revision 1.0 07/01/1999 # Named my version mrtg.archive.pl, allowing Emanuele to update his # software without confusion resulting :-) # Weekly archiving of week gifs, monthly archiving of month gifs, yearly # archiving of year gifs. # Specification of which interfaces summary files are saved for. # Terse log messages. # Creation of the archive directory if it doesn't exist. # Symlinking of the mrtg gifs instead of copying (I have limited disk space). # # backup.pl 07/17/97 # Author: Emanuele Leonardi # use strict # # User configuration # # Change this setting if the mrtg.archive files are # not placed in /usr/local/sbin/ # $Conf_File = "/usr/local/sbin/mrtg.archive.conf"; # # End user configuration # # Check for configuration file open(CONF,"$Conf_File") || die "Error opening configuration file $Conf_File: $!\n"; close(CONF); # Get date and time of execution chomp ($date = `date +%y%m%d`); chomp ($time = `date +%H:%M:%S`); chomp ($week = `date +%w`); chomp ($month = `date +%d`); chomp ($year = `date +%m%d`); require "$Conf_File"; print "===\nArchive $date at $time\n"; # Create daily directory and copy default GIF files if (!-e $ARCHIVE_DIR) { mkdir($ARCHIVE_DIR, 0755) || die "Error creating $ARCHIVE_DIR: $!\n"; chmod(0755, $ARCHIVE_DIR); print "Create $ARCHIVE_DIR\n"; } mkdir($TO_DIR, 0755) || die "Error creating $TO_DIR: $!\n"; chmod(0755, $TO_DIR); print "Create $TO_DIR\n"; foreach $mgif ( @common_gifs ) { symlink("$MRTG_DIR" . "\/" . "$mgif", "$TO_DIR" . "\/" . "$mgif"); } # For each node copy the daily gifs foreach $node ( @nodes_to_archive ) { system(sprintf("cp -a %s/%s.*-day.gif %s",$MRTG_DIR,$node,$TO_DIR)); } # For each node copy the weekly gifs on Sunday if ($week == "0") { foreach $node ( @nodes_to_archive ) { system(sprintf("cp -a %s/%s.*-week.gif %s",$MRTG_DIR,$node,$TO_DIR)); } } # For each node copy the monthly gifs on the first if ($month == "01") { foreach $node ( @nodes_to_archive ) { system(sprintf("cp -a %s/%s.*-month.gif %s",$MRTG_DIR,$node,$TO_DIR)); } } # For each node copy the yearly gifs on January first if ($year == "0101") { foreach $node ( @nodes_to_archive ) { system(sprintf("cp -a %s/%s.*-year.gif %s",$MRTG_DIR,$node,$TO_DIR)); } } # For each node copy the daily summary file and create the index file foreach $summary ( @nodes_to_summary ) { printf("%s\n",$summary); $Summary_Source = "$MRTG_DIR/$summary.html"; $Summary_Destination = "$TO_DIR/$summary.html"; open(SRC,"<$Summary_Source") || die "Error opening $Summary_Source: $!\n"; open(DST,">$Summary_Destination") || die "Error opening $Summary_Destination: $!\n"; while () { s/]*>//g; s/<\/A>//g; s/Router Overview/Router Overview of $date/; s///; print DST; } close(SRC); close(DST); chmod(0644, $Summary_Destination); } # Create the general index file $INDEX = "$TO_DIR/index.html"; print "Create $INDEX\n"; open(IDX,">$INDEX") || die "Could not open $INDEX: $!\n"; printf IDX " Router Summary for %s

      Router Summary for %s

      "; close(IDX); chmod(0644, $INDEX); @common_gifs = ""; chomp ($time = `date +%H:%M:%S`); print "Archive $date done at $time\n"; exit(0); # Eof mrtg.archive.pl mrtg-2.17.10/contrib/mrtg-archiver/mrtg.archive.conf0000644000175300017510000000167713057016061021332 0ustar oetikeroep# Filename: mrtg.archive.conf # Configuration file for mrtg.archive.pl # # Place this file in the same directory as mrtg-archive.pl. # Default placement of these files is in /usr/local/sbin # # If you place them elsewhere, change the $Conf_File setting in mrtg.archive.pl. # # # User configuration section # # Define list of nodes to archive #@nodes_to_archive = ('router1','router2','router3','etc'); @nodes_to_archive = ('192.168.1.1','192.168.99.16','192.168.17.1'); # Define list of interfaces for summary files #@nodes_to_summary = ('router1.iface#','etc'); @nodes_to_summary = ('192.168.1.1.2','192.168.1.17.1'); # Define list of common gifs to link @common_gifs = ('mrtg-l.gif','mrtg-m.gif','mrtg-r.gif','mrtg-ti.gif'); # Define working directories $MRTG_DIR = "/home/httpd/html/mrtg"; $ARCHIVE_DIR = "$MRTG_DIR/archive"; $TO_DIR = "$ARCHIVE_DIR/$date"; # # End user configuration section # 1; #do not remove this line # Eof: mrtg.archive.conf mrtg-2.17.10/contrib/mrtg-archiver/README0000644000175300017510000000356213057016061016745 0ustar oetikeroep.... backup.pl ,.... Date: Thu, 17 Jul 1997 14:31:32 +0200 From: Emanuele Leonardi To: mrtg@list.ee.ethz.ch It wakes up at 23:54 every night and copies all the current daily gifs for the given list of routers to a directory named with the current date (e.g. 970717). The Perl code is extremely straightforward so there should be no problem in understanding it. The cron entry I use is: 54 23 * * * /usr/local/lib/mrtg-2.2/backup.pl 1>> /usr/local/lib/mrtg-2.2/backup.log 2>&1 I'll be very happy to discuss any possible improvement or modification. Ciao Emanuele ... mrtg.archiver.pl ..... From: Rawlin Blake To: dlr@bungi.com, oetiker@ee.ethz.ch, Emanuele Leonardi Date: Mon, 4 Jan 1999 15:05:38 -0800 (PST) Subject: mrtg-archiver I have made some revisions to mrtg-archiver for use at my site. In the hopes that those changes will help others, I have appended my version. Changes include: Weekly archiving of week gifs, monthly archiving of month gifs, yearly archiving of year gifs. Specification of which interfaces you want summary files saved for. Terse error messages. (I happen to prefer shorter messages, to each their own :-) ) Creation of the archive directory if it doesn't exist. Symlinking of the mrtg gifs instead of copying (I have limited disk space) --------- blake@nevada.edu http://www.nevada.edu/~blake How far would Moses have gone if he had taken a poll in Egypt? What would Jesus Christ have preached if he had taken a poll in the land of Israel? What would have happened to the Reformation if Martin Luther had taken a poll? It isn't polls or public opinion of the moment that counts. It is right and wrong and leadership. -- USA President Harry S Truman ========================================================================== mrtg-2.17.10/contrib/mrtg-archiver/backup.pl0000644000175300017510000000361113057016061017662 0ustar oetikeroep#!/usr/bin/perl # Define list of nodes to backup @nodes_to_backup = ('router1','router2','router3','etc'); # Get date and time of execution chop ($date = `date +%y%m%d`); chop ($time = `date +%H:%M:%S`); # Define working directories $MRTG_DIR = "/home/httpd/html/mrtg"; $BACKUP_DIR = "$MRTG_DIR/backup"; $TO_DIR = "$BACKUP_DIR/$date"; print "================================================== Starting backup for day $date at $time.\n"; # Create daily directory and copy default GIF files print "Creating directory $TO_DIR.\n"; mkdir($TO_DIR,"755") || die "Error creating directory $TO_DIR.\n"; chmod(0755,$TO_DIR); system(sprintf("cp -a %s/mrtg-*.gif %s",$MRTG_DIR,$TO_DIR)); # For each node copy the daily summary file and create the index file foreach $node ( @nodes_to_backup ) { printf("Executing backup for node %s.\n",$node); system(sprintf("cp -a %s/%s.*-day.gif %s",$MRTG_DIR,$node,$TO_DIR)); $Summary_Source = "$MRTG_DIR/$node.html"; $Summary_Destination = "$TO_DIR/$node.html"; open(SRC,"<$Summary_Source"); open(DST,">$Summary_Destination"); while () { s/]*>//g; s/<\/A>//g; s/Router Overview/Router Overview of $date/; s///; print DST; } close(SRC); close(DST); chmod(0644,$Summary_Destination); } # Create the general index file $INDEX = "$TO_DIR/index.html"; print "Creating index file $INDEX.\n"; open(IDX,">$INDEX") || die "Could not open index file $INDEX.\n"; printf IDX " Server Summary for %s

      Server Summary for %s

      "; close(IDX); chmod(0644,$INDEX); chop ($time = `date +%H:%M:%S`); print "Backup for day $date finished at $time.\n"; mrtg-2.17.10/contrib/ircstats2/0000755000175300017510000000000013057016061015223 5ustar oetikeroepmrtg-2.17.10/contrib/ircstats2/crontab.script0000755000175300017510000000243113057016061020104 0ustar oetikeroep#! /bin/sh # # Crontab script for ircstats2 #------------------------------ # You can use that script to check whether the stats generation script is # running. # # No bugs are known in this software. So if it crashes, please tell me, even if # you don't know anything about the crash ! # # To check for your script every 10 minutes, put the following line in your # crontab: # 0,30 * * * * /home/mydir/crontab.script # And if you don't want to get email from crontab when it checks you script, # put the following in your crontab: # 0,30 * * * * /home/mydir/crontab.script >/dev/null 2>&1 # # change this to the directory you run the script from: ircstatsdir="/home/lucas/ircstats2" ########## you probably don't need to change anything below here ########## cd $ircstatsdir if test -r ircstats2.pid then pid=`cat ircstats2.pid` if `kill -CHLD $pid >/dev/null 2>&1` then exit 0 fi echo "" echo "Stale ircstats2.pid file, erasing..." rm -f ircstats2.pid fi echo "" echo "ircstats2.pl restarting ..." echo "This software is supposed to be bug-free. If the bot has to restart," echo "and if that's not for a good reason (server reboot for example), please notify" echo "the author (lucas@schickler.net) even if you don't know why the script crashed." ./ircstats2.pl exit 0 mrtg-2.17.10/contrib/ircstats2/README0000644000175300017510000000221013057016061016076 0ustar oetikeroepircstats2.pl v1.3 (06/04/2001) ircstats2.pl is a perl script I use to monitor the user load of the Langochat.net IRC Network. - Lucas Nussbaum Homepage : http://www.schickler.net/lucas/ircstats2/ Usage : All the configuration is done in ircstats2.pl. You can look at example.cf to learn how to configure mrtg with this script. To restart the script if it crashes (this soft is supposed to be bug-free, so that shouldn't happen), you can use the crontab script included. Changes : 1.3 (21/03/2001) - Now counts servers and ircops too. 1.2 (25/01/2001) - Better calculation of the global user load, when the list of servers isn't up to date. - Now counts the number of channels too :) - Can display the global users and channels count in plain text file, enabling those files to be used in other scripts. 1.1 (24/08/2000) - Initial public release Licence : This software is subject to the GNU GENERAL PUBLIC LICENCE version 2 or above It can be found on http://www.gnu.org/copyleft/gpl.html However, if you modify something in this script, I would strongly appreciate that you send me a copy. mrtg-2.17.10/contrib/ircstats2/example.cf0000644000175300017510000000214313057016061017170 0ustar oetikeroepWorkDir: /home/lucas/public_html/mrtg Refresh: 300 Interval: 5 WriteExpires: Yes IconDir: images/ RunAsDaemon: Yes #..................................................................... # Default settings MaxBytes[_]: 10000 Options[_]: gauge, noinfo, nopercent, integer, growright Background[_]: #FFFFC0 YLegend[_]: Users WithPeak[_]: wym ShortLegend[_]: Users Legend1[_]: Users Legend2[_]: Legend3[_]: Max Users Legend4[_]: LegendI[_]:  Users : Colours[_]: BLUE#0000FF,BLUE#0000FF,LIGHT BLUE#C0C0FF,LIGHT BLUE#C0C0FF Target[global]: `cat /home/lucas/ircstats2/temp/globalusersmrtg` Title[global]: Irc.Kewl.Org User Load LegendO[global]: PageTop[global]:

      Irc.Kewl.Org User Load

      Stats Maintainer :Lucas@Kewl.Org
      Target[angers]: `cat /home/lucas/ircstats2/temp/angers.fr.eu.kewl.org` Title[angers]: Angers.FR.EU.Kewl.Org User Load LegendO[angers]: PageTop[angers]:

      Angers.FR.EU.Kewl.Org User Load

      Stats Maintainer :Lucas@Kewl.Org
      mrtg-2.17.10/contrib/ircstats2/ircstats2.pl0000755000175300017510000001415113057016061017503 0ustar oetikeroep#!/usr/bin/perl # ircstats2.pl v1.3 06 Apr 2001 Lucas Nussbaum # More info can be found on http://www.schickler.net/lucas/ircstats2.php # based on ircstats from Matt Ramsey (MR227) mjr@geeks.org, mjr@nin.com # Used to generate stats on the Kewl.Org IRC Network # If you see something that should be changed, please notify me ! use Socket; # pseudo-client parameters $nick = "StatsMaker234"; $ident = "Stats"; $realname = "http://www.schickler.net/lucas/"; # server and port to connect to $ircserver = "127.0.0.1"; $ircport = "6667"; # Where to store the output data (directory MUST exist) # The number of users on each server will be in a file named like the server. # An additionnal file named 'global' will be created, containing the sum of # all servers' users. # An example configuration file is included. $datapath = "/home/lucas/ircstats2/temp"; # Where to put the PID file $pidfile = "/home/lucas/ircstats2/ircstats2.pid"; # NOTE: Set those variables to 0 to enable, put a # in front of the # lines to disable. # Count the global number of users in "globalusersmrtg" file (MRTG format) $globalusersmrtg=0; # Count the channels in "channelsmrtg" file (MRTG format) $channelsmrtg=0; # Count the global number of ircops in "ircopsmrtg" file (MRTG format) $ircopsmrtg=0; # Count the number of servers in "serversmrtg" file (MRTG format) $serversmrtg=0; # Count the global number of users in "globalusersplain" file # (Plain text, to be used with others scripts) $globalusersplain=0; # Count the channels in "channelsplain" file (Plain text, # to be used with others scripts) $channelsplain=0; # Count the global number of ircops in "ircopsplain" file # (Plain text, to be used with others scripts) $ircopsplain=0; # Count the number of servers in "serversmrtg file (MRTG format) $serversplain=0; # ircops number offset (not to count services, for example) $ircopsoffset=0; # servers number offset (not to count services, for example) $serversoffset=0; # Servers to poll $server{"cybernet.langochat.net"}=0; $server{"sicfa.langochat.net"}=0; $server{"free.langochat.net"}=0; $server{"jeuxgroup.langochat.net"}=0; $server{"diligo.langochat.net"}=0; ############################################## ### DO NOT MODIFY ANYTHING BELOW THIS LINE ### ############################################## print "Now daemonizing ...\n"; &daemonize; if (!(($globalusersmrtg eq "")&&($globalusersplain eq "")&&($channelsmrtg eq "")&&($channelsplain eq "")&&($ircopsmrtg eq "")&&($ircopsplain eq "")&&($serversplain eq "")&&($serversmrtg eq ""))) { $needlusers=1; } ($g, $g, $proto) = getprotobyname("tcp"); while (true) { ($g, $g, $g, $g, $rawserver) = gethostbyname($ircserver); if ($rawserver) { $serveraddr = pack("Sna4x8", 2, $ircport, $rawserver); socket(SOCKET, AF_INET, SOCK_STREAM, $proto) || die "No socket: $!"; if (connect(SOCKET, $serveraddr)){ select(SOCKET); $| = 1; select(STDOUT); $| = 1; print SOCKET "USER $ident a b :$realname\n"; print SOCKET "NICK $nick\n"; while (){ @i = split(" ",$_); if ($i[1] eq "433") {print SOCKET "NICK ".$nick.time()."\n";} elsif ($i[1] eq "437") {print SOCKET "NICK ".$nick.time()."\n";} elsif ($i[1] eq "376") {&getinfo;} elsif ($i[1] eq "402") {$server{lc($i[3])}=0;} elsif ($i[1] eq "265") { $i[0]=~s/\://; $server{lc($i[0])}=$i[6]; } elsif ($i[1] eq "266") { if ($globalusersmrtg ne "") { $globalusersmrtg=$i[6]; } if ($globalusersplain ne "") { $globalusersplain=$i[6]; } } elsif ($i[1] eq "254") { if ($channelsmrtg ne "") { $channelsmrtg=$i[3]; } if ($channelsplain ne "") { $channelsplain=$i[3]; } } elsif ($i[1] eq "251") { if ($serversmrtg ne "") { $serversmrtg=$i[11]-$serversoffset; } if ($serversplain ne "") { $serversplain=$i[11]-$serversoffset; } } elsif ($i[1] eq "252") { if ($ircopsmrtg ne "") { $ircopsmrtg=$i[3]-$ircopsoffset; } if ($ircopsplain ne "") { $ircopsplain=$i[3]-$ircopsoffset; } } elsif ($i[0] eq "PING") { &saveinfo; print SOCKET "PONG $i[1]\n"; &getinfo; } } } close(SOCKET); } sleep(120); } sub saveinfo { foreach $s (keys %server){ open(OUTPUT,">$datapath/$s"); print OUTPUT "$server{$s}\n$server{$s}\n$time\n"; close(OUTPUT); } if ($globalusersmrtg ne "") { open(OUTPUT, ">$datapath/globalusersmrtg"); print OUTPUT "$globalusersmrtg\n$globalusersmrtg\n$time\n"; close(OUTPUT); } if ($channelsmrtg ne "") { open(OUTPUT, ">$datapath/channelsmrtg"); print OUTPUT "$channelsmrtg\n$channelsmrtg\n$time\n"; close(OUTPUT); } if ($serversmrtg ne "") { open(OUTPUT, ">$datapath/serversmrtg"); print OUTPUT "$serversmrtg\n$serversmrtg\n$time\n"; close(OUTPUT); } if ($ircopsmrtg ne "") { open(OUTPUT, ">$datapath/ircopsmrtg"); print OUTPUT "$ircopsmrtg\n$ircopsmrtg\n$time\n"; close(OUTPUT); $ircopsmrtg=0; # raw 252 pas disp si pas opers } if ($globalusersplain ne "") { open(OUTPUT,">$datapath/globalusersplain"); print OUTPUT "$globalusersplain"; close(OUTPUT); } if ($channelsplain ne "") { open(OUTPUT, ">$datapath/channelsplain"); print OUTPUT "$channelsplain"; close(OUTPUT); } if ($serversplain ne "") { open(OUTPUT, ">$datapath/serversplain"); print OUTPUT "$serversplain"; close(OUTPUT); } if ($ircopsplain ne "") { open(OUTPUT, ">$datapath/ircopsplain"); print OUTPUT "$ircopsplain"; close(OUTPUT); $ircopsplain=0; # raw 252 pas disp si pas opers } } sub getinfo { foreach $s (keys %server) { print SOCKET "lusers * $s\n"; } $time=time(); if ($needlusers==1) { print SOCKET "lusers\n"; } } sub daemonize () { chdir "/" or die "Can't chdir to /: $!"; open STDIN, "/dev/null" or die "Can't read /dev/null: $!"; open STDOUT, ">/dev/null" or die "Can't write to /dev/null: $!"; defined (my $pid = fork) or die "Can't fork: $!"; if ($pid) { if ($pidfile) { open(PIDFILE,">$pidfile"); print PIDFILE "$pid\n"; close(PIDFILE); } exit; } setsid or die "Can't start a new session: $!"; open STDERR, ">&STDOUT" or die "Can't dup stdout: $!"; } mrtg-2.17.10/contrib/mrtg-startup-script/0000755000175300017510000000000013057016061017260 5ustar oetikeroepmrtg-2.17.10/contrib/mrtg-startup-script/README0000644000175300017510000000140213057016061020135 0ustar oetikeroepFrom: Stefan Date: Thu, 3 Aug 2006 14:47:59 +0200 Subject: mrtg startup script Hi, while discussing on a fedora irc channel about a startup script (/etc/init.d/mrtg) for the mrtg daemon we came to a conclussion that it would be the best to include such a script in the main sourcecode distribution. Many people don't run mrtg through cron and a startup script is very handy. But we don't want to confuse them while installing a startup script + a cron file. The best sollution we came out would be to include a startup file in the contrib directory of mrtg. There is also a bugzilla entry for the file and a little conclussio. Maybe you could add the file to the contrib directory so that it's easier to run mrtg as a daemon. Best regards, Stefan mrtg-2.17.10/contrib/mrtg-startup-script/mrtg0000644000175300017510000000274113057016061020160 0ustar oetikeroep#!/bin/bash # # mrtg This shell script starts mrtg # # Author: Stefan SF # # chkconfig: 345 90 35 # # description: mrtg The Multi Router Traffic Grapher # processname: mrtg # config: /etc/mrtg/mrtg.conf # ### BEGIN INIT INFO # Provides: mrtg # Required-Start: $network # Default-Stop: 0 1 6 # Short-Description: Starts the The Multi Router Traffic Grapher # Description: The Multi Router Traffic Grapher (MRTG) is a tool to monitor \ # the traffic load on network-links. MRTG generates HTML pages \ # containing GIF/PNG images which provide a live visual \ # representation of this traffic. ### END INIT INFO # source function library . /etc/rc.d/init.d/functions MRTG="/usr/bin/mrtg" CONFIG="/etc/mrtg/mrtg.cfg" PIDFILE="/var/run/mrtg.pid" LOCKFILE="/var/lock/mrtg/mrtg" OPTIONS="--daemon" RETVAL=0 start() { echo -n $"Enabling MRTG: " rm -f ${LOCKFILE} 2> /dev/null env LANG=C ${MRTG} --pid-file=${PIDFILE} --lock-file=${LOCKFILE} ${OPTIONS} ${CONFIG} RETVAL=$? echo } stop() { echo -n $"Disabling MRTG: " kill `cat ${PIDFILE}` && rm -f ${LOCKFILE} RETVAL=$? echo } restart() { stop start } case "$1" in start) start ;; stop) stop ;; restart|force-reload) restart ;; status) if [ -f $LOCKFILE ]; then echo $"MRTG is enabled." RETVAL=0 else echo $"MRTG is disabled." RETVAL=3 fi ;; *) echo $"Usage: $0 {start|stop|status|restart|force-reload}" exit 1 esac exit $RETVAL mrtg-2.17.10/contrib/TTrafic/0000755000175300017510000000000014133217116014641 5ustar oetikeroepmrtg-2.17.10/contrib/TTrafic/TTraffic.asp0000644000175300017510000001354713057016061017062 0ustar oetikeroep<% '******************************************************************************* '* * '* TTraffic 1.0.0 (distributed under GNU GENERAL PUBLIC LICENSE) * '* by kamborio * '* * '* ------------------------------------------------------ * '* _ _ _ * '* | | __ __ _ _ __ ___ | |__ ___ _ __ (_) ___ * '* | |/ / / _` || '_ ` _ \ | '_ \ / _ \ | '__|| | / _ \ * '* | < | (_| || | | | | || |_) || (_) || | | || (_) | * '* |_|\_\ \__,_||_| |_| |_||_.__/ \___/ |_| |_| \___/ * '* ------------------------------------------------------ * '* http://www.kamborio.com/ * '* * '* Copyright (C) 2001 David A. Prez (david@kamborio.com) * '* * '* 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 of the License, 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 * '* * '******************************************************************************* Const ForReading = 1, ForWriting = 2 Dim LogsMode LogsMode = 1 Dim Order, Period Dim fso, f, p, n, TheFile, LineNumber, TheLine, TheValues Dim ReadAt, LastRan, TotalBytesIn, TotalBytesOut Dim PeriodIn, PeriodOut, MonthIn, MonthOut Period = Request("Period") Order = Trim(CStr(Request("Order"))) If Not IsNumeric(Period) Then Period = 30 Else If Period < 1 Then Period = 30 End If End If If Order = "" Then Order = "G" End If Set fso = CreateObject("Scripting.FileSystemObject") Set f = fso.GetFile(Request.ServerVariables("PATH_TRANSLATED")) If LogsMode = 1 Then ReDim p(0) p(0) = Replace(f.Name, ".asp", "") & ".log" Else p = Split(f.Path, "\") For n = 1 To (UBound(p) - 2) p(0) = p(0) & "\" & p(n) Next p(0) = p(0) & "\logs\" & p(n) & "\" & Replace(f.Name, ".asp", "") & ".log" End If Set TheFile = fso.OpenTextFile(p(0), ForReading) LineNumber = -1 While Not TheFile.AtEndOfStream LineNumber = LineNumber + 1 TheLine = TheFile.ReadLine TheValues = Split(TheLine) If LineNumber = 0 Then LastRan = UNIXToDay(TheValues(0)) TotalBytesIn = CDbl(TheValues(1)) TotalBytesOut = CDbl(TheValues(2)) Else If DateDiff("d", UNIXToDay(TheValues(0)), Now) < CLng(Period) Then PeriodIn = PeriodIn + CDbl(TheValues(1) * (ReadAt - TheValues(0))) PeriodOut = PeriodOut + CDbl(TheValues(2) * (ReadAt - TheValues(0))) End If If Month(UNIXToDay(TheValues(0))) = Month(Now) And Year(UNIXToDay(TheValues(0))) = Year(Now) Then MonthIn = MonthIn + CDbl(TheValues(1) * (ReadAt - TheValues(0))) MonthOut = MonthOut + CDbl(TheValues(2) * (ReadAt - TheValues(0))) End If End If ReadAt = TheValues(0) Wend Set TheFile = Nothing set f = Nothing Set fso = Nothing Response.Write "

      " Response.Write "" Response.Write "" Response.Write "" Response.Write "" Response.Write "" Response.Write "
      Interface:" & BytesTo(TotalBytesIn, Order) & " In and " & BytesTo(TotalBytesOut, Order) & " Out, making a total of " & BytesTo((TotalBytesIn + TotalBytesOut), Order) & "
      " & MonthName(Month(Now)) & ":" & BytesTo(MonthIn, Order) & " In and " & BytesTo(MonthOut, Order) & " Out, making a total of " & BytesTo((MonthIn + MonthOut), Order) & "
      Last " & Period & " days:" & BytesTo(PeriodIn, Order) & " In and " & BytesTo(PeriodOut, Order) & " Out, making a total of " & BytesTo((PeriodIn + PeriodOut), Order) & "
      " Function UNIXToDay(Value) UNIXToDay = DateAdd("s", Value, "1/Jan/1970 0:00") End Function Function BytesTo(Value, Order) Dim NumericalOrder, OrderName Select Case UCase(Order) Case "K" NumericalOrder = "1" OrderName = "Kb" Case "M" NumericalOrder = "2" OrderName = "Mb" Case "G" NumericalOrder = "3" OrderName = "Gb" Case "T" NumericalOrder = "4" OrderName = "Tb" Case "P" NumericalOrder = "5" OrderName = "Pb" Case Else NumericalOrder = "0" OrderName = "Bytes" End Select BytesTo = Round((Value / 1024 ^ NumericalOrder), 2) & " " & OrderName End Function %>mrtg-2.17.10/contrib/TTrafic/gpl.txt0000644000175300017510000004377714133217116016206 0ustar oetikeroep GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 of the License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. mrtg-2.17.10/contrib/TTrafic/readme.txt0000644000175300017510000001105213057016061016636 0ustar oetikeroep'******************************************************************************* '* * '* TTraffic 1.0.0 (distributed under GNU GENERAL PUBLIC LICENSE) * '* by kamborio * '* * '* ------------------------------------------------------ * '* _ _ _ * '* | | __ __ _ _ __ ___ | |__ ___ _ __ (_) ___ * '* | |/ / / _` || '_ ` _ \ | '_ \ / _ \ | '__|| | / _ \ * '* | < | (_| || | | | | || |_) || (_) || | | || (_) | * '* |_|\_\ \__,_||_| |_| |_||_.__/ \___/ |_| |_| \___/ * '* ------------------------------------------------------ * '* http://www.kamborio.com/ * '* * '* Copyright (C) 2001 David A. Prez (david@kamborio.com) * '* * '* 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 of the License, 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 * '* * '******************************************************************************* TTrafic is a small VBScript to analyse MRTG (http://www.mrtg.org/) log files. By using this script, you will be able to know which amount of traffic is going through your interfaces. INSTALLATION Copy the file TTrafic.asp to the directory where MRTG is generating the HTML pages. The files generated by MRTG have the extension HTML by default. You have to edit your MRTG config file and modify it to make MRTG generate the HTML pages with the extension ASP. You should add or edit this line to your config file: Extension[_]: asp Now, you only need to include the file on the generated pages. The best way to do this, is by editing the MRTG config file and adding this line, to the PageTop option. For example: Target[core.router.4]: 4:public@core.router MaxBytes[core.router.4]: 1310720 Title[core.router.4]: core.router: Ethernet0 PageTop[core.router.4]:

      Traffic Analysis for core.router: Ethernet0

      System:core.router in the office
      Maintainer:Myself
      Interface:Ethernet0 (4)
      IP: (10.0.0.1)
      Max Speed:2.0 MBits/s
      QUERYS If the generated page is "core.router.4.asp", you can try to query the page like this: http://server/MRTG/core.router.4.asp?Period=365&Order=M This will give you the traffic information for the last 365 days. You can enter any value here. The default is 30 days. Order can be any of these values: K, M, G, T or P. K stands for kbytes, M for Megabytes, G for Gigabytes, T for Terabytes and P for Petabytes. If you enter any other value, you will receive the information in Bytes. The default is Gigabytes.mrtg-2.17.10/contrib/get-multiserial/0000755000175300017510000000000013057016061016414 5ustar oetikeroepmrtg-2.17.10/contrib/get-multiserial/get-modems.pl0000644000175300017510000000152413057016061021014 0ustar oetikeroep#!/usr/local/bin/perl # # Returns number of active analog and digital dial-ins # # This script could be very much improved - it's a quick hack # and it works ... # # I'm doing a "w" sorting out all the important tty's (ttyC for cyclades # boards) and checking if the correspond to the digita lines # # T.Pospisek : # # Distributed under the GNU copyleft # # Number of active tty's $isdn = 0; $modem = 0; # Name of this host $my_name = "Dial-In"; # Our digital lines $tty{"ttyC12"}="i"; $tty{"ttyC13"}="i"; $tty{"ttyC14"}="i"; $tty{"ttyC15"}="i"; $tty{"ttyC16"}="i"; $tty{"ttyC24"}="i"; $tty{"ttyC25"}="i"; open(TTYS, "w -hs|cut -b 10-17|fgrep ttyC|"); while() { chop; s/\s+//; if( $tty{"$_"} ) { $isdn++; } else { $modem++; } } print "$modem\n"; print "$isdn\n"; print "0\n"; print "$my_name\n"; mrtg-2.17.10/contrib/get-multiserial/get-modems-remote.pl0000644000175300017510000000324413057016061022306 0ustar oetikeroep#! /usr/bin/perl # # get-modems-remote.pl # # Connects to a TCP port get's there the number of occupied modems # and prints'em out # # The other side consists of a silly programm (a la get-modems.pl ;) # that just prints the number of active lines. # # ex: # /etc/services : # getmodems 9999/tcp # /etc/inetd.conf: # getmodems stream tcp nowait nobody /usr/bin/get-modems.pl get-modems.pl # # Thanks to Larry Wall for the nice example in the Lama Perl-tutorial # # (c) T.Pospisek Distributed under GNU copyleft # # History: # ??-??-97 initial release for mrtg # 13-05-99 cleaned up a little bit - thanks to Dancho Kanev # for "buging" me ;-) # ---- please adapt the following two lines to your local configuration --- # The name of the remote server $remote_server='jesus'; # The name of the service $service='getmodems'; #-- end of user configurable stuff --- use Socket; $sockaddr = 'S n a4 x8'; chop($hostname = `hostname`); ($name, $aliases, $proto) = getprotobyname('tcp'); ($name, $aliases, $port) = getservbyname($service,'tcp'); ($name, $aliases, $type, $len, $thisaddr) = gethostbyname($hostname); ($name, $aliases, $type, $len, $thataddr) = gethostbyname($remote_server); $thisport = pack($sockaddr, &AF_INET, 0, $thisaddr); $thatport = pack($sockaddr, &AF_INET, $port, $thataddr); socket(S, &PF_INET, &SOCK_STREAM, $proto) || die "dial-in-check : cannot create socket\n"; bind(S, $thisport) || die "dial-in-check : cannot bind socket\n"; connect(S, $thatport) || die "dial-in-check : cannot bind socket\n"; while () { print; } # print "0\n"; # print "0\n"; # print "$remote_server\n"; mrtg-2.17.10/contrib/gentcucci-1.0.0/0000755000175300017510000000000013057016061015703 5ustar oetikeroepmrtg-2.17.10/contrib/gentcucci-1.0.0/tcnowtemp0000755000175300017510000000272713057016061017661 0ustar oetikeroep#!/bin/bash grep_it() { value="`cat $TEMP_FILE | head -$1 | tail -1`" color="" if [ ${value:=0} -ge 100 ] then color=" bgcolor=red" elif [ ${value:=0} -ge 85 ] then color=" bgcolor=yellow" elif [ ${value:=0} -le 50 ] then color=" bgcolor=cyan" else color=" bgcolor=lightgreen" fi echo " $value" } ############################################################################### export DIR=/world/mrtg/tcdegree export MACH="`echo \"$1\" | sed -e 's/+/_/g'`" export MAXB="$2" export TEMP_FILE=/tmp/tcnowtemp.$$ ############################################################################### if [ ! -r "$DIR/${MACH}.html" ] then exit fi cat "$DIR/${MACH}.html" | \ grep '<\!-- ' | \ grep "out " | \ cut -d' ' -f4 >$TEMP_FILE trap "rm -f $TEMP_FILE ; exit" 1 2 15 echo "" echo " " echo " " echo " " echo " " echo " " echo " " echo " " echo " " echo " " grep_it 1 grep_it 2 grep_it 3 echo " " echo " " echo " " grep_it 4 grep_it 5 grep_it 6 echo " " echo " " echo " " grep_it 7 grep_it 8 grep_it 9 echo " " echo " " echo " " grep_it 10 grep_it 11 grep_it 12 echo " " echo "
      MaxAvgNow
      Day
      Week
      Month
      Year
      " echo "" trap - 1 2 15 rm -f $TEMP_FILE 2>/dev/null mrtg-2.17.10/contrib/gentcucci-1.0.0/tcnowstat0000755000175300017510000000312313057016061017656 0ustar oetikeroep#!/bin/bash grep_it() { value="`cat $TEMP_FILE | head -$1 | tail -1`" perc="`expr \"$value\" \* 100 / \"${MAXB:=1}\"`" color="" if [ ${perc:=0} -ge 90 ] then color=" bgcolor=red" elif [ ${perc:=0} -ge 80 ] then color=" bgcolor=yellow" elif [ ${perc:=0} -le 25 ] then color=" bgcolor=cyan" else color=" bgcolor=lightgreen" fi echo " $value${perc}%" } ############################################################################### export DIR=/usr/local/mrtg-2.8.12/local-config/www/tcusercount export MACH="`echo \"$1\" | sed -e 's/+/_/g'`" export MAXB="$2" export TEMP_FILE=/tmp/tcnowstat.$$ ############################################################################### if [ ! -r "$DIR/${MACH}.html" ] then exit fi cat "$DIR/${MACH}.html" | \ grep '<\!-- ' | \ grep "in " | \ cut -d' ' -f4 >$TEMP_FILE trap "rm -f $TEMP_FILE ; exit" 1 2 15 echo "" echo " " echo " " echo " " echo " " echo " " echo " " echo " " echo " " echo " " grep_it 1 grep_it 2 grep_it 3 echo " " echo " " echo " " grep_it 4 grep_it 5 grep_it 6 echo " " echo " " echo " " grep_it 7 grep_it 8 grep_it 9 echo " " echo " " echo " " grep_it 10 grep_it 11 grep_it 12 echo " " echo "
      MaxAvgNow
      Day
      Week
      Month
      Year
      " echo "" trap - 1 2 15 rm -f $TEMP_FILE 2>/dev/null mrtg-2.17.10/contrib/gentcucci-1.0.0/README0000644000175300017510000000137613057016061016572 0ustar oetikeroepFrom: Kevin Benton To: Tobias Oetiker Date: Tue, 17 Oct 2000 09:42:18 -0400 (EDT) Subject: MRTG Thanks and a contrib Please find included a nice little package which automatically generates configs for 3Com Total Control chassis, but also generates a little colored table to the left of the graph on the index to display usage history at a glance. mrtg-2.17.10/contrib/gentcucci-1.0.0/nmcs.list0000644000175300017510000000037213057016061017542 0ustar oetikeroep# NMC's for Temperature monitoring. # # format # # ip_name:description # # example # # tc1b.i40:Coshocton 1 (tc1b.i40) # tc1.i40 Ping host # Coshocton 1 (tc1b.i40) Title for device # tc1b.i40:Coshocton TC (tc1.i40) tc1b.nwk:Newark TC (tc1.nwk) mrtg-2.17.10/contrib/gentcucci-1.0.0/gwcs.list0000644000175300017510000000241013057016061017540 0ustar oetikeroep# tc users logged on # # format # # ip_name(+ip_name(+ip_name...)):max acceptable users:absolute graphable max # # example # # tc1.i40:Coshocton 1:48:336 # tc1.i40 Access Server # Coshocton 1 Title for device # 48 Maximum (red line) users possible per T1 count # 336 Absolute maxmimum possible number of users # # tc3.i40+tc5.i40:Coshocton Total (w/o Omni):368:672 # tc3.i40+tc5.i40 Access Servers # Coshocton Total (w/o Omni) Title for device # 48 Maximum (red line) users possible per T1 count # 336 Absolute maxmimum possible number of users # # Note: Absolute maximum is the highest potential number of users who can be # on-line on a particular chassis (HARC) at one time, which is not the # same as the number of channels plugged in to the chassis. Absolute # maximum is used in the event that someone forgets to reconfigure this # file before adding additional capacity. At present, one HARC can # handle up to approximately 336 users. If a chassis has 3 PRI's # plugged into it, then 69:336 would be appropriate because each PRI # will provide 23 channels for users, but the HARC can still handle a # lot more than that. # tc1.i40:Coshocton TC (tc1.i40):69:336 tc1.nwk:Newark TC (tc1.nwk):69:336 mrtg-2.17.10/contrib/gentcucci-1.0.0/mrtg_autorun0000755000175300017510000000047313057016061020363 0ustar oetikeroep#!/bin/sh # # Should be run every n minutes (generally either 5 or 10) in cron as in the # crontab example below... # # */5 * * * * /home/autorun/bin/mrtg_autorun # # Edit the paths for your system's needs. # cd /usr/local/mrtg/local-config gentcucci ../run/mrtg mrtg.tcusercount.cfg ../run/mrtg mrtg.tcdegree.cfg mrtg-2.17.10/contrib/gentcucci-1.0.0/gentcucci0000755000175300017510000002267013057016061017604 0ustar oetikeroep#!/bin/bash ############################################################################### # gentcucci - Generate Total Control User Count (and temp) Config and Index # (pronounced like Gent Cookie) an MRTG Tool # # Version 1.0.0 # # Copyright and written by Kevin Benton, 1999. # # Please be sure that if you choose to use this code that you let Tobi or # myself know that it's useful to you. Tobi - thanks for writing MRTG and # making it freely available to those of us who weren't quite so creative. # # NOTE 1 - At the time of this writing, we've been using this script for over # a year and it's worked like a champ. Don't let the version number fool # you - this stuff is tried and tested. # # NOTE 2 - Please be sure to pick the target method below. Look for # "INTENTIONAL ERROR" in this file, uncomment the appropriate line and delete # the two "error" lines as directed. # # NOTE 3 - This could have been written in Perl to make it a lot faster, but at # the time I wrote it, I didn't know enough Perl to do it. I certainly didn't # feel like spending the time to write it in C. I may soon rewrite this # entire script in Perl not only to make it faster, but to clean things as far # as temp files go and what not. # # NOTE 4 - tcf2mrtg returns the number of users on-line for a particular # target. This works on both ARCs and NetServers and gives us the ability to # split apart DSP's. It can of course be adapted to whatever your platform # needs require. If you only need data for the HARC aggregated together, use # the MIB .1.3.6.1.4.1.429.4.2.1.10.0 or whatever is current for the HARC code # you're using. ############################################################################### ############################################################################### # store in users index file stf() { echo "$1" >>$TEMP_FILE } ############################################################################### # store in temperature index file stfd() { echo "$1" >>$TEMP_FILE2 } ############################################################################### # store in temperature config stod() { echo "$1" >>$degree_file } ############################################################################### # store in users config stou() { echo "$1" >>$output_file } ############################################################################### ########################## CONFIGURATION PARAMETERS ########################### # output_dir is where MRTG will be storing configs. A directory www should # exist under that with the directories tcusercount and tcdegree below that. export output_dir=/usr/local/mrtg-2.8.12/local-config # output_file is the MRTG user count config file. export output_file=$output_dir/mrtg.tcusercount.cfg # degree_file is the MRTG chassis temperature config file. export degree_file=$output_dir/mrtg.tcdegree.cfg # ro_comm is the read only SNMP community to use to grab data with. export ro_comm=public ########################## CONFIGURATION PARAMETERS ########################### export TEMP_FILE=/tmp/gentcuc.$$ export TEMP_FILE2=/tmp/gentcuc.$$.2 rm -f $TEMP_FILE 2>/dev/null >/dev/null trap "rm -f $TEMP_FILE $TEMP_FILE2 2>/dev/null >/dev/null ; exit" 1 2 15 touch $TEMP_FILE index=${output_dir}/www/tcusercount/index.htm bigindex=${output_dir}/www/tcusercount/bigindex.htm degreeindex=${output_dir}/www/tcdegree/index.htm bigdegreeindex=${output_dir}/www/tcdegree/bigindex.htm # Create mrtg.tcusercount.cfg header cat >$output_file < PageTop[\$]: Total Control Chassis User Count Options[^]: gauge noinfo YLegend[^]: Users On ShortLegend[^]: Users Title[$]: Total Control Chassis User Count XZoom[^]: 2.0 YZoom[^]: 2.0 SH_EOF1 # Create mrtg.tcdegree.cfg header cat >$degree_file < PageTop[\$]: Total Control Chassis Temperature Options[^]: gauge noinfo nopercent YLegend[^]: Fahrenheit ShortLegend[^]: Temp Title[$]: Total Control Chassis Temperature XZoom[^]: 2.0 YZoom[^]: 2.0 SH_EOF2 # Create master index temp file stf "" stf "Total Control SED_REPLACE_WITH_NAME" stf "" stf "

      Total Control SED_REPLACE_WITH_NAME

      " stf "Updated `date`

      " stf "Click here for SED_REPLACE_WITH_SIZE size images
      " stf "" # Process into mrtg.tcusercount.cfg and master user count index from gwcs.list while read line do if echo "$line" | egrep '^#' >/dev/null 2>/dev/null then continue fi if [ -z "$line" ] then continue fi target="`echo \"$line\" | cut -d: -f1 | sed -e 's/+/ /g'`" tag="`echo \"$line\" | \ cut -d: -f1 | \ sed -e 's/+/_/g' | \ sed -e 's/\_.*\@/_/g' | \ cut -d@ -f2`" title="`echo \"$line\" | cut -d: -f2`" maxb="`echo \"$line\" | cut -d: -f3`" absm="`echo \"$line\" | cut -d: -f4`" INTENTIONAL ERROR: YOU MUST PICK 1 OF THE 2 TARGETS BELOW AND DELETE THIS LINE # stou "Target[$tag]: \`/usr/local/mrtg-2.8.12/local-config/tcf2mrtg \"$target\"\`" # stou "Target[$tag]: .1.3.6.1.4.1.429.4.2.1.10.0:${ro_comm}@$target" INTENTIONAL ERROR: YOU MUST PICK ONE OF THE TARGETS ABOVE AND DELETE THIS LINE stou "Title[$tag]: $title" stou "PageTop[$tag]: $title" if [ ! "$absm" = "0" ] then stou "AbsMax[$tag]: $absm" fi stou "MaxBytes[$tag]: $maxb" stou "WithPeak[$tag]: ymwd" stou "" stf " " stf " " stf " " stf " " stf " " stf " " stf " " stf " " done " stfd "Total Control SED_REPLACE_WITH_NAME" stfd "" stfd "

      Total Control SED_REPLACE_WITH_NAME

      " stfd "Updated `date`

      " stfd "Click here for SED_REPLACE_WITH_SIZE size images
      " stfd "

      " stf "
      $title
      " stf " `/home/httpd/cgi-bin/tcnowstat \"$tag\" \"$maxb\"`
      " stf " Potential Users: $maxb
      " stf "
      Today
      5 Min
      " stf " " stf "
      This Week
      30 Min
      " stf " " stf "
      " # Process into mrtg.tcusercount.cfg and master user count index from gwcs.list while read line do if echo "$line" | egrep '^#' >/dev/null 2>/dev/null then continue fi if [ -z "$line" ] then continue fi name="`echo \"$line\" | cut -d: -f1 | sed -e 's/+/ /g'`" tag="`echo \"$line\" | cut -d: -f1 | sed -e s/+/_/g`" title="`echo \"$line\" | cut -d: -f2`" stod "##################################################################" stod "Target[$tag]: .1.3.6.1.4.1.429.1.2.2.5.0&.1.3.6.1.4.1.429.1.2.2.5.0:public@$name * 1.8 + 32" stod "Title[$tag]: $title" stod "PageTop[$tag]: $title" stod "MaxBytes[$tag]: 200" stfd " " stfd " " stfd " " stfd " " stfd " " stfd " " stfd " " done " stfd "
      " stfd "
      $title
      " stfd " `/home/httpd/cgi-bin/tcnowtemp \"$tag\"`
      " stfd "
      Today
      5 Min
      " stfd " " stfd "
      This Week
      30 Min
      " stfd " " stfd "
      " # create normal and big indexes for user count and temperature. cat $TEMP_FILE | sed -e 's/SED_REPLACE_WITH_INDEX.HTM/bigindex.htm/g' | \ sed -e 's/SED_REPLACE_WITH_SIZE/double/g' | \ sed -e 's/SED_REPLACE_WITH_NAME/User Count Analysis/g' | \ sed -e 's/SED_REPLACE_WITH_PICSIZE//g' >$index cat $TEMP_FILE | sed -e 's/SED_REPLACE_WITH_INDEX.HTM/index.htm/g' | \ sed -e 's/SED_REPLACE_WITH_SIZE/normal/g' | \ sed -e 's/SED_REPLACE_WITH_NAME/User Count Analysis/g' | \ sed -e 's/SED_REPLACE_WITH_PICSIZE/WIDTH=1000 HEIGHT=270/g' >$bigindex cat $TEMP_FILE2 | sed -e 's/SED_REPLACE_WITH_INDEX.HTM/bigindex.htm/g' | \ sed -e 's/SED_REPLACE_WITH_SIZE/double/g' | \ sed -e 's/SED_REPLACE_WITH_NAME/Chassis Temperature/g' | \ sed -e 's/SED_REPLACE_WITH_PICSIZE//g' >$degreeindex cat $TEMP_FILE2 | sed -e 's/SED_REPLACE_WITH_INDEX.HTM/index.htm/g' | \ sed -e 's/SED_REPLACE_WITH_SIZE/normal/g' | \ sed -e 's/SED_REPLACE_WITH_NAME/Chassis Temperature/g' | \ sed -e 's/SED_REPLACE_WITH_PICSIZE/WIDTH=1000 HEIGHT=270/g' >$bigdegreeindex rm $TEMP_FILE $TEMP_FILE2 mrtg-2.17.10/contrib/cisco_ipaccounting/0000755000175300017510000000000013057016061017150 5ustar oetikeroepmrtg-2.17.10/contrib/cisco_ipaccounting/CHANGELOG0000644000175300017510000000011513057016061020357 0ustar oetikeroepCHANGELOG cisco_ip_acc_collect.pl - V0.9 20-Sep-1999 Initial Public Release mrtg-2.17.10/contrib/cisco_ipaccounting/README0000644000175300017510000000430413057016061020031 0ustar oetikeroepREADME - cisco_ip_acc_collect.pl This is cisco_ip_acc_collect.pl V0.9 This Script gets IP-accounting data from a Cisco Router and generates output that can be fed into MRTG. Configzration: -------------- First of all, I sugest you make a backup of your router config, before you configure IP accounting and run this script... If something happens, I've told you ... In the networks you can enter the networks you like to analyse in the following form: xxx.xxx.xxx.xxx/CDIR Name xxx.xxx.xxx.xxx is the IP Adress of the Network CDIR is the CDIR Bitmask /32 = 255.255.255.255 /24 = 255.255.255.0 /16 = 255.255.0.0 etc. Name Is the name of the network. This name can apear more than once. The traffic of all networks that have same name will be added into one output. In the .pl file you have to change some variables. See the .pl file for more informations. In the mrtg config file you can enter something like this: Target[tagretname]: `cat /usr/local/mrtg/cisco_ipaccounting/log_test` Running this script: -------------------- I start this script with cron, yost before mrtg like this: */5 * * * * cramer /usr/local/mrtg/cisco_ipaccounting/collect.pl ; /usr/local/mrtg/mrtg /usr/local/mrtg/accounting.conf Where to get updates: --------------------- You can download new versions from ftp://ftp.dolphins.ch/pub/Dolphins/mrtg Copyrigth & Warranty: --------------------- This script is (c) 1999 by Dolphins Network Systems, Matthias Cramer 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 of the License, 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., 675 Mass Ave, Cambridge, MA 02139, USA. mrtg-2.17.10/contrib/cisco_ipaccounting/networks0000644000175300017510000000012513057016061020745 0ustar oetikeroep192.168.3.0/28 Dummy 192.168.2.12/32 Dummy 10.10.1.0/27 Sample 172.1.0.1/32 Test mrtg-2.17.10/contrib/cisco_ipaccounting/cisco_ip_acc_collect.pl0000755000175300017510000000676013057016061023624 0ustar oetikeroep#!/usr/bin/perl ############################################################################## # # cisco_ip_acc_collect.pl # (c) 1999 by Dolphins Network Systems, Matthias Cramer # # Licence: LGPL # ############################################################################## # # This Script is very loosly based on whodo from Tony Farr # # This Script gets IP-accounting data from a Cisco Router # In the network file you can define networks which you like to analyse. # # Special modules : Net::Netmask, SNMP_util # ############################################################################## # # Version History # V0.9 First Public Release # ############################################################################## use Getopt::Std; use File::Basename; use Net::Netmask; use strict; use Socket; # Adjust this path to where you MRTG resides, so that SNMP_util # can be found. use lib "/usr/local/mrtg"; use SNMP_util; # # Some variables to adjust. # # The write community of your router my $HOST= 'writecommunity@router'; # Where is your network file my $NETWORK = "/usr/local/mrtg/cisco_ipaccounting/networks"; # Where to write the accounting info my $OUTDIR = "/usr/local/mrtg/cisco_ipaccounting/"; # Below here you should have to be changed my %network; my %in; my %out; open (NET, $NETWORK); my $line; my $block; while ($line = ) { $line =~ /(.+?)[\s]+(.+)/; my $name = $2; $block=new Net::Netmask($1); $block->storeNetblock(); $in{$block->base()}=0; $out{$block->base()}=0; $network{$name} .= $block->base() . ":"; } &checkpoint_stats($HOST); &get_stats($HOST); # print "Base \tIn\tOut\n"; # print "$base\t$in{$base}\t$out{$base}\n"; foreach my $k_network (keys %network) { my @base = split(/:/, $network{$k_network}); my $base_in = 0; my $base_out = 0; foreach my $i_base (@base) { $base_in += $in{$i_base}; $base_out += $out{$i_base}; } open(OUT, ">$OUTDIR"."log_"."$k_network"); print OUT "$base_in\n"; print OUT "$base_out\n"; print OUT "\n"; print OUT "$k_network\n"; close (OUT); } sub checkpoint_stats { # Take a checkpoint on IP accounting on the given router & return the duration # The checkpoint is done by doing a get then a set on actCheckPoint my ($age); # Find how long since the last checkpoint ($age) = snmpget ($_[0], '1.3.6.1.4.1.9.2.4.8.0'); warn "No actAge returned.\n" unless $age; # Check to see if we've lost any data ($_) = snmpget ($_[0], '1.3.6.1.4.1.9.2.4.6.0'); warn "Accounting table overflow - $_ bytes lost.\n" if $_ > 0; # Do a new checkpoint ($_) = snmpget ($_[0], '1.3.6.1.4.1.9.2.4.11.0'); die "No actCheckPoint returned.\n" unless defined; snmpset ($_[0], '1.3.6.1.4.1.9.2.4.11.0', 'integer', $_); $age; } sub get_stats { # Summarise the checkpoint by destination network (not host). # Summary is placed into %traffictab - a hash of hashes indexed by # source device & destination network. my($src, $dst,$traffic); my @response = snmpwalk ($_[0], '1.3.6.1.4.1.9.2.4.9.1.4' ); foreach $_ (@response) { /(\d+\.\d+\.\d+\.\d+)\.(\d+\.\d+\.\d+\.\d+):(\d+)/ || die "Cannot parse response from walk.\n"; $dst=$2; $src=$1; $traffic=$3; $block = findNetblock($src); if ($block) { $out{$block->base()} += $traffic; } $block = findNetblock($dst); if ($block) { $in{$block->base()} += $traffic; } } } mrtg-2.17.10/contrib/cisco_ipaccounting/TODO0000644000175300017510000000010713057016061017636 0ustar oetikeroepTODO - cisco_ip_acc_collect.pl * Make the script multi router capable mrtg-2.17.10/contrib/iptables_acc/0000755000175300017510000000000013057016061015716 5ustar oetikeroepmrtg-2.17.10/contrib/iptables_acc/README0000644000175300017510000000067613057016061016607 0ustar oetikeroepDate : Mit Sep 27 09:06:26 MEST 2000 Author : Gereon Ruetten Because there is no default policy for user-chains, you have to insert a rule which counts all pakets/bytes going through the chain. You can do that by inserting (must be the first rule in the chain) a rule like : iptables -t filter -A httpin in your mrtg config file you have to add a line : Target[iptables]: /firewall/stats/mrtg/iptables_acc httpin httpout mrtg-2.17.10/contrib/iptables_acc/iptables_acc0000755000175300017510000000323013057016061020253 0ustar oetikeroep#!/usr/bin/perl # iptables_acc version 0.1 # Author: Gereon Ruetten, g.ruetten@gmx.de # # for further informations about mrtg : # # http://ee-staff.ethz.ch/~oetiker/webtools/mrtg/mrtg.html # # usage : # Target[traffic]: /usr/local/mrtg-2/bin/iptables_acc httpin httpout # # the two arguments are the user chains you want to read use strict; my ($IPTABLES, $host, $in_chain, $out_chain, $in_data, $out_data); $IPTABLES='/usr/local/bin/iptables'; # where to find iptables $host=`/bin/hostname --fqdn`; # local hostname (for information only) # these are defaults, yu can ovveride them with command-line parameters $in_chain='httpin'; # name of input accounting rule $out_chain='httpout'; # name of output accounting rule $in_data = 0; # edit these settings if you want to monitor something else $out_data = 0; # then the bytes counter ## -- don't edit below here ---- my (@rules, @in_count, @out_count, $upTime, $value, $c); # get command line params ($in_chain,$out_chain) = @ARGV; # fetch the status from iptables @rules=`$IPTABLES -L $in_chain -v -n -x`; splice @rules, 0, 2; @in_count=split(' ',$rules[$in_data]); @rules=`$IPTABLES -L $out_chain -v -n -x`; splice @rules, 0, 2; @out_count = split(' ',$rules[$out_data]); #$c=1; #foreach $value (@in_count) { # printf "in $c: $value\n"; # $c++; #}; #$c=1; #foreach $value (@out_count) { # printf "out $c: $value\n"; # $c++; #}; # uptime of the machine open(UPTIME,"uptime |cut -b 13-26|"); $upTime=; close(UPTIME); chop $upTime; # 4 lines of output only. if (!$in_count[1]) { $in_count[1] = 0; } if (!$out_count[1]) { $out_count[1] = 0; } print "$in_count[1]\n", "$out_count[1]\n", "$upTime\n$host"; mrtg-2.17.10/contrib/monitor/0000755000175300017510000000000013057016061014774 5ustar oetikeroepmrtg-2.17.10/contrib/monitor/config.asp0000644000175300017510000003160513057016061016753 0ustar oetikeroep<% @LANGUAGE="VBSCRIPT" %> <% Response.Expires = 0 %> <% Server.ScriptTimeout = 1200 %> <% If ID = "" Then Response.Redirect(NoAuthURL) End If ' We only execute this code if the user actually submitted the configuration form from the page. If Request.ServerVariables("REQUEST_METHOD") = "POST" Then ' Get the values that he or she entered at the configuration page. Password = Request.Form("Password") ' The circuit password. NewPassword = Request.Form("NewPassword") ' Change password. NewConfirmedPassword = Request.Form("ConfirmPassword") ' Change password confirmation. EMail = Request.Form("TechEMail") ' Technical E-Mail address. Graph_Daily = Request.Form("Daily_Graph") ' Display Daily Graphs. Graph_Weekly = Request.Form("Weekly_Graph") ' Display Weekly Grahps. Graph_Monthly = Request.Form("Monthly_Graph") ' Dispaly Monthly Graphs. Graph_Yearly = Request.Form("Yearly_Graph") ' Display Yearly Graphs. ' Check Graph_Daily If Graph_Daily = "" Then Graph_Daily = 0 Else Graph_Daily = 1 End If ' Check Graph_Weekly If Graph_Weekly = "" Then Graph_Weekly = 0 Else Graph_Weekly = 1 End If ' Check Graph_Monthly If Graph_Monthly = "" Then Graph_Monthly = 0 Else Graph_Monthly = 1 End If ' Check Graph_Yearly If Graph_Yearly = "" Then Graph_Yearly = 0 Else Graph_Yearly = 1 End If ' Did the user enter his or her password? If Password = "" Then ' We dont have a password! Error = "Please Enter Your Password" End If ' Now that we have the password, compare in in the database... set rsPassword = DBConn.Execute("SELECT LinePassword FROM Monitor_Authenticate WHERE ID=" & ID) TempPass = rsPassword("LinePassword") ' Get the password in the database. rsPassword.close ' Close the lookup record. Set rsPassword = Nothing If Password <> TempPass Then ' The password did not match the database. Error = "Invalid Password" End If If NewPassword <> "" Then ' Compare the NewPassword with the ' ConfirmedPassword... If NewPassword <> NewConfirmedPassword Then ' The two password do not match. Error="Your Passwords Did Not Match" Else Password = NewPassword ' Set the new password to be updated in the ' database. End If End If If Error = "" Then ' If we do not have a error, everything is ' well, lets update the records. If ID <> 1 Then ' ID 1 is the guest account, dont update the ' database. set rsUpdate = DBConn.Execute("UPDATE Monitor_Authenticate SET LinePassword='" & Password & "', " &_ "EMail_Address='" & EMail & "', " &_ "Graph_Day=" & Graph_Daily & ", " &_ "Graph_Week=" & Graph_Weekly & ", " &_ "Graph_Month=" & Graph_Monthly & ", " &_ "Graph_Year=" & Graph_Yearly &_ " WHERE (ID=" & ID & ")") Set rsUpdate = nothing ' Database update successfull. End If ' Update Session information... Session("DBLinePassword") = Password ' Update the password for the session. Session("DBEMail_Address") = EMail ' Update the E-Mail for the session. If Graph_Daily = 1 Then ' Daily Graph Session("DBGraph_Day") = True Else Session("DBGraph_Day") = False End If If Graph_Weekly = 1 Then ' Weekly Graph Session("DBGraph_Week") = True Else Session("DBGraph_Week") = False End If If Graph_Monthly = 1 Then ' Monthly Graph Session("DBGraph_Month") = True Else Session("DBGraph_Month") = False End If If Graph_Yearly = 1 Then ' Yearly Graph Session("DBGraph_Year") = True Else Session("DBGraph_Year") = False End If Response.Redirect(MonitorURL) ' Everything is updated, go back to ' monitor. End If End If %>

      Monitor Configuration For Circuit Number: <%= LineNumber %>

      Logout of MonitorBandwidth Details

      Circuit Number: <%= LineNumber %> Circuit Speed: <%= LineSpeed %> bps Technical Contact: <%= EMail_Address %>
      You Last Visited Monitor On: <%= LastVisit %>

      <%' Do we have a error that the user needs to know about? If Error <> "" Then %>

      <%= Error %>

      <% End If %>

      Please take note, for your changes to take affect, you must enter your password in the first password field.  If you wish to change your password, you may then also complete the "New Password" and "Confirm Password" fields.

      Your Password:

      Required For ANY changes to be made

      Change Your Password: New Password
        Confirm Password
      Technical Contact E-Mail Address:
      Show The Daily Graph: checked <% end if%>>
      Show The Weekly Graph: checked<% end if %>>
      Show The Monthly Graph: checked<% end if %>>
      Show The Yearly Graph: checked<% end if %>>


      2000 Chris Knipe.  All Rights Reserved.


       
      MRTG
      Tobias Oetiker <tobi@oetiker.ch> and Dave Rand <dlr@bungi.com>

       

      mrtg-2.17.10/contrib/monitor/monitor.html0000644000175300017510000001161413057016061017354 0ustar oetikeroep

      What is Monitor.SunnyLine.co.za?

      Monitor is a bandwidth monitoring system implemented by SunnyLine Internet Services.

      With the use of Monitor! we allow our customers to see real-time statistics about their bandwidth usage.  Monitor creates detailed graphs based on a daily, weekly, monthly, and yearly bases, graphing your in- and outgoing bandwidth usage.  Monitor also aids in the detection and prevention of Network Congestion (or lag), by allowing Network Administrators to see possible network bottlenecks before they actually happen.

      Monitor is a value added services from SunnyLine Internet Services for all of their Leased Line clients with permanent connections.  Due to the manner in which Network Data is being monitored, we are unable to provide information on dial-up ports.  At least for now.

      MRTG consists of a Perl script which uses SNMP to read the traffic counters of your routers and a fast C program which logs the traffic data and creates beautiful graphs representing the traffic on the monitored network connection. These graphs are embedded into WebPages which can be viewed from any modern Web-browser.  In addition to a detailed daily view, MRTG also creates visual representations of the traffic seen during the last seven days, the last four weeks and the last twelve months. This is possible because MRTG keeps a log of all the data it has pulled from the router. This log is automatically consolidated, so that it does not grow over time, but still contains all the relevant data for all the traffic seen over the last two years. This is all performed in an efficient manner. Therefore you can monitor 50 or more network links from any halfway decent UNIX box.

      MRTG is not limited to monitoring traffic though, it is possible to monitor any SNMP variable you choose. You can even use an external program to gather the data which should be monitored via MRTG. People are using MRTG, to monitor things such as System Load, Login Sessions, Modem availability and more. MRTG even allows you to accumulate two or more data sources into a single graph.

       
      mrtg-2.17.10/contrib/monitor/login.asp0000644000175300017510000001702513057016061016616 0ustar oetikeroep<% @LANGUAGE="VBSCRIPT" %> <% Response.Expires = 0 %> <% Server.ScriptTimeout = 1200 %> <% If ID = "" Then ' The Session Expired Response.Redirect(NoAuthURL) End If Set fs = CreateObject("Scripting.FileSystemObject") ' FileSystemObject to copy graphs fs.CopyFile "c:\mrtg\targets\" & LineNumber & "-*.gif", "c:\InetPub\monitor.sunnyline.co.za\images\mrtg\" %>

      Bandwidth Statistics For Circuit Number: <%= LineNumber %>

      Logout of MonitorConfigure Monitor

      Circuit Number: <%= LineNumber %> Circuit Speed: <%= LineSpeed %> bps Technical Contact: <%= EMail_Address %>
      You Last Visited Monitor On: <%= LastVisit %>

      <% If Graph_Day = True Then %>
      Shows Your Bandwidth Usage Over the last  24 Hours
      Daily Bandwidth Graph

       


      <% End If %> <% If Graph_Week = True Then %>
      Shows Your Bandwidth Usage Over the Last 7 Days
      Weekly Bandwidth Graph



      <% End If %> <% If Graph_Month = True Then %>
      Shows Your Bandwidth Usage Over The Last Month
      Monthly Bandwidth Graph

       


      <% End If %> <% If Graph_Year = True Then %>
      Shows Your Bandwidth Usage Over The Last Year
      Yearly Bandwidth Graph

       


      <% End If %>

      2000 Chris Knipe.  All Rights Reserved.


       
      MRTG
      Tobias Oetiker <oetiker@ee.ethz.ch> and Dave Rand <dlr@bungi.com>

       

      mrtg-2.17.10/contrib/monitor/global.asa0000644000175300017510000000132013057016061016716 0ustar oetikeroepmrtg-2.17.10/contrib/monitor/global/0000755000175300017510000000000013057016061016234 5ustar oetikeroepmrtg-2.17.10/contrib/monitor/global/main.css0000644000175300017510000001665513057016061017707 0ustar oetikeroepBODY { font : x-small Verdana, Arial, Helvetica, sans-serif; font-size : 7.5pt; color : 000000;} .NNBold-MCSP { font : bold x-small Verdana, Arial, Helvetica, sans-serif; font-size : 7.5pt; font-weight : bold; color : 3366CC; } .NNBold-DA { font : bold x-small Verdana, Arial, Helvetica, sans-serif; font-size : 7.5pt; font-weight : bold; color : 003399; } .NNBold-Gen { font : bold x-small Verdana, Arial, Helvetica, sans-serif; font-size : 7.5pt; font-weight : bold; color : 000000; } .Greenhead { font : bold x-small Verdana, Arial, Helvetica, sans-serif; font-size : 7.5pt; font-weight : bold; color : 36B236; text-decoration : underline; } .HEADING { font : x-small Verdana, Arial, Helvetica, sans-serif; color : 000000; font-size : 10pt; font-weight : bold; } .SEARCH { font : x-small Verdana, Arial, Helvetica, sans-serif; color : 003399; font-size : 7.5pt; } .MCSP { font : x-small Verdana, Arial, Helvetica, sans-serif; color : 3366CC; font-size : 7.5pt; } .MSDA { font : x-small Verdana, Arial, Helvetica, sans-serif; color : 003399; font-size : 7.5pt; } .COLUMN { font : x-small Verdana, Arial, Helvetica, sans-serif; color : FFFFFF; font-size : 7.5pt; font-weight : bold; } .COLUMNRED { font : x-small Verdana, Arial, Helvetica, sans-serif; color : FF3300; font-size : 7.5pt; font-weight : bold; } .BUTTON { background : 6699CC; text-align : center; font-weight : bold; color : White; font : 10px; border-left-color : White; border-top-color : White; border-right-color : Black; border-bottom-color : Black; } .INPUT{ height : 20px; width : 100px; } DIV.Jobs { position: relative; width : 310; height : 85; border : 1px solid; background-color:white; padding : 8px; text-align : left; border-bottom-color : 003399; border-color : 003399 003399 003399 003399; border-left-color : 003399; border-right-color : 003399; border-top-color : 003399; } A.MCSPLEVEL1 { font-size:7.5pt; line-height:10pt; color:3366cc; cursor:hand; text-decoration:none; font-weight:bold;} A.MCSPLEVEL1:VISITED { font-size:7.5pt; line-height:10pt; color:3366cc; cursor:hand; text-decoration:none; font-weight:bold;} A.MCSPLEVEL1:ACTIVE { font-size:7.5pt; line-height:10pt; color:3366cc; cursor:hand; text-decoration:none; font-weight:bold;} A.MCSPLEVEL2 { font-size:7.5pt; line-height:10pt; color:3366cc; cursor:hand; font-weight : bold; text-decoration : underline; } A.MCSPLEVEL2:VISITED { font-size:7.5pt; line-height:10pt; color:3366cc; cursor:hand; text-decoration:none;} A.MCSPLEVEL2:ACTIVE { font-size:7.5pt; line-height:10pt; color:3366cc; cursor:hand; text-decoration:none;} A.MCSPLEVEL2:HOVER { font-size:7.5pt; line-height:10pt; color:FF3300; cursor:hand; text-decoration:underline;} A.DALEVEL1 { font-size:7.5pt; line-height:10pt; color:003399; cursor:hand; text-decoration:none; font-weight:bold;} A.DALEVEL1:VISITED { font-size:7.5pt; line-height:10pt; color:003399; cursor:hand; text-decoration:none; font-weight:bold;} A.DALEVEL1:ACTIVE { font-size:7.5pt; line-height:10pt; color:003399; cursor:hand; text-decoration:none; font-weight:bold;} A.DALEVEL2 { font-size:7.5pt; line-height:10pt; color:003399; cursor:hand; font-weight : bold; text-decoration : underline;} A.DALEVEL2:VISITED { font-size:7.5pt; line-height:10pt; color:003399; cursor:hand; text-decoration:none;} A.DALEVEL2:ACTIVE { font-size:7.5pt; line-height:10pt; color:003399; cursor:hand; text-decoration:none;} A.DALEVEL2:HOVER { font-size:7.5pt; line-height:10pt; color:FF3300; cursor:hand; text-decoration:underline;} .HRRED { color:FF3300; height : 1px;} DIV.Menu { position:absolute; left:160; top: 200w; width: 150; border : 1px solid; background-color:white; padding : 3px; text-align : left; border-bottom-color : 003399; border-color : 003399 003399 003399 003399; border-left-color : 003399; border-right-color : 003399; border-top-color : 003399; padding-left : 10px; padding-right : 4px; padding-top : 4px; padding-bottom : 4px; } .STANDARD { font-size:8.5pt; line-height:10pt; color:000000;} .STANDARDSMALL { font-size:7.5pt; line-height:10pt; color:000000;} A.DEFAULT { font-size:8.5pt; line-height:10pt; color:003399; cursor:hand;} A.DEFAULT:VISITED { font-size:8.5pt; line-height:10pt; color:003399; cursor:hand;} A.DEFAULT:ACTIVE { font-size:8.5pt; line-height:10pt; color:003399; cursor:hand;} A.DEFAULT:HOVER { font-size:8.5pt; line-height:10pt; color:FF3300; cursor:hand;} A.DEFAULTSMALL { font-size:7.5pt; line-height:5pt; color:003399; cursor:hand;} A.DEFAULTSMALL:VISITED { font-size:7.5pt; line-height:5pt; color:003399; cursor:hand;} A.DEFAULTSMALL:ACTIVE { font-size:7.5pt; color:003399; line-height:5pt; cursor:hand;} A.DEFAULTSMALL:HOVER { font-size:7.5pt; line-height:5pt; color:FF3300; cursor:hand;} A.DEFAULTSMALLSUB { font-size:7.5pt; line-height:8pt; color:003399; cursor:hand;} A.DEFAULTSMALLSUB:VISITED { font-size:7.5pt; line-height:8pt; color:003399; cursor:hand;} A.DEFAULTSMALLSUB:ACTIVE { font-size:7.5pt; color:003399; line-height:8pt; cursor:hand;} A.DEFAULTSMALLSUB:HOVER { font-size:7.5pt; line-height:8pt; color:FF3300; cursor:hand;} A.BOLD { font-size:8.5pt; line-height:10pt; color:003399; cursor:hand; text-decoration:none; font-weight:bold;} A.BOLD:VISITED { font-size:8.5pt; line-height:10pt; color:003399; cursor:hand; text-decoration:none; font-weight:bold;} A.BOLD:ACTIVE { font-size:8.5pt; line-height:10pt; color:003399; cursor:hand; text-decoration:none; font-weight:bold;} A.BOLD:HOVER { font-size:8.5pt; line-height:10pt; color:FF3300; cursor:hand; text-decoration:underline; font-weight:bold;} A.RED { font-size:7.5pt; line-height:10pt; color:FF3300; cursor:hand; text-decoration:none; font-weight:bold;} A.RED:VISITED { font-size:7.5pt; line-height:10pt; color:FF3300; cursor:hand; text-decoration:none; font-weight:bold;} A.RED:ACTIVE { font-size:7.5pt; line-height:10pt; color:FF3300; cursor:hand; text-decoration:none; font-weight:bold;} A.RED:HOVER { font-size:7.5pt; line-height:10pt; color:003399; cursor:hand; text-decoration:underline; font-weight:bold;} A.LEVEL1 { font-size:7.5pt; line-height:10pt; color:black; cursor:hand; text-decoration:none; font-weight:bold;} A.LEVEL1:VISITED { font-size:7.5pt; line-height:10pt; color:black; cursor:hand; text-decoration:none; font-weight:bold;} A.LEVEL1:ACTIVE { font-size:7.5pt; line-height:10pt; color:black; cursor:hand; text-decoration:none; font-weight:bold;} A.LEVEL2 { font-size:7.5pt; line-height:10pt; color:003399; cursor:hand;} A.LEVEL2:VISITED { font-size:7.5pt; line-height:10pt; color:003399; cursor:hand;} A.LEVEL2:ACTIVE { font-size:7.5pt; line-height:10pt; color:black; cursor:hand;} A.LEVEL2:HOVER { font-size:7.5pt; line-height:10pt; color:FF3300; cursor:hand; text-decoration:underline;} mrtg-2.17.10/contrib/monitor/readme.txt0000644000175300017510000002067013057016061016777 0ustar oetikeroepMonitor v.1.1b ~~~~~~~~~~~~~~ Hi, welcome to the world of Monitor. This is my first ASP based contribution towards the Internet community at large, but I hope that there will be lots more to come. Monitor is a system designed by me with the use of MRTG. This application will be of most use to Internet Service Providers who may have a range of clients on Lease Lines running from their backbone. The system uses a database which keeps record of all the customers who have Leased Lines. The database holds the following information: LineNumber (Or Circuit Number) LinePassword (A Password Protecting The Circuit On Monitor) EMail_Address (This will be used in a later version) Graph_Day (Enable The Daily Graph) Graph_Week (Enable The Weekly Graph) Graph_Month (Enable The Monthly Graph) Graph_Year (Enable The Yearly Graph) Graph_EMail (This will be used in a later version) With this information, Monitor provides an easy way for clients to see and monitor their traffic usage after logging into the monitoring system. The users are then also provided with the option to customise the layout of their monitoring system, allowing them to only see the graphs that they need. Because this is a ASP application, the system has to be hosted on Windows NT Server, or a Unix based server that supports ASP code. For Unix based servers (or if this application is ported to the PHP3 Lanuage), the database routines will need to be redone. Unix' clones will almost certainly not support the same database methods as NT (This application is designed to work with Microsoft's ADO engine for interest sakes). What's Included: ~~~~~~~~~~~~~~~~ I've included the following files in the distribution: config.asp - This is the ASP file where clients can customise the output from the Monitoring system. default.asp - This is the ASP file where the authentication process will happen. global.asa - global.asa takes care of the deletation of the graph images when a session is abandoned or expires. We also make sure here that users start on the correct page when entering the web site at any point or file. login.asp - After successfull authentication, this page displays the graphs to the users. monitor.html - A page that you can use to explain the service to your clients. monitor.inc - This file holds reference to the Database connection strings, aswell as Session information. readme.txt - You're reading it. monitor.mdb - The Database provided in Microsoft Access 2000 format. (Please read below for more information.) Setup: ~~~~~~ Firstly, for the setup of this application on a NT based server, you need to install MRTG on Windows, and have this working. If you want for some reason not to run MRTG from Windows NT, then please use Samba file sharing, and MAP THE DRIVE to the Windows NT machine that will host the web pages. NT will need PHYSICAL FILE ACCESS to the files (Read Only Access will be sufficient). Next, you can take the database (Monitor.mdb), and place this somewhere on your system. The location of the database does not matter that much, seeing that you need to setup a ODBC DataSource Name (DSN), to point the the database file. If you do not want to use DSN connections, have a look in Monitor.inc and change the DSN entry there to point to the file path (DBQ entry). You will also need to change Monitor.inc to have the correct DSN name in for the DSN you have just created. Thirdly, you need to setup a bit of file permissions. This is more than likely the trickiest part of the installation. Because MRTG graphs are updated dynamically, we need to implement a system where the graphs are stored OUTSIDE of the web server. We need the graphs outside the web server, so that people can't just link to the images on the monitoring system with a simple tag in ther html on a local web server. This is accomplished with the use of the built in ASP objects CopyFile and DeleteFile. After a successfull login occured, the ASP code will copy the images (all four - daily, weekly, monthly, and yearly), from a pre determined MRTG "spool" directory. This directory will be a global directory where MRTG saves the images from it's targets. It can either be a share that is mapped to the local server, or a local path on the Windows NT host. You need to explictly give the Iusr_machinename user (or the user under which the IIS process run), READ access on both the directory, aswell as all the files within. This will allow the ASP code, to read the binary images from the directory, and copy them to inside the web site. Next, what you need to do permission wise, is assign READ, WRITE, and DELETE permissions on both the file and directory inside the Monitor web site, where the target images will be copied to. In this example package, the images are copied to the images/mrtg/ folder. Once you have your database setup, and the file permissions set up correctly, the site should work. After login, the application will copy the files from the MRTG spool directory, into it's target directory. The graphs will then be displayed to the user, and will reside on the web server for as long as the session exist. Once the user logs out, or when the session expires, the ASP code will automatically issue the DeleteFiles directive which removes the images that are copied from the MRTG spool directory after the user has logged in. The images are re-copied at every refresh of the page, so this will also ensure that images on the monitor web site will remain up-to-date, for as long as the client is logged into the system. The supplied database is in Access 2000 form. From what I've heard, Access 2000 is not compatible with older versions. Should you have troubles using this database, please upgrade to Access 2000. If this is a bit of a harsh thing to ask (which I also presume), I have decided to include an SQL Script for the creation of the database. The script is based on Microsoft SQL Server 6.5, but will give you a pretty good idea on how the database should look inside Access... Microsoft SQL 6.5 Database Script: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /****** Object: Table dbo.Monitor_Authenticate Script Date: 00/06/17 07:45:08 ******/ CREATE TABLE dbo.Monitor_Authenticate ( ID int IDENTITY (1, 1) NOT NULL , LineNumber numeric(18, 0) NOT NULL , LinePassword varchar (8) NOT NULL , LineSpeed numeric(18, 0) NOT NULL , EMail_Address varchar (50) NOT NULL , Graph_Day bit NOT NULL , Graph_Week bit NOT NULL , Graph_Month bit NOT NULL , Graph_Year bit NOT NULL , Graph_EMail bit NOT NULL , LastVisit datetime NULL , Comment varchar (255) NULL ) GO Bugs & Problems: ~~~~~~~~~~~~~~~~ Yes, there are a few of them inside the code at the date when I released this. Although they are nothing serious, I feel that you should take note of this. - Client Authentication: If the web user enteres a Curcuit number and password that do not exist in the database, the Database engine responds with an error. This will be fixed in a next release and is not a serious problem to overcome. Possible solution is to code in a additional if statement to check that the circuit number exist BEFORE the authentication process is initiated. - Client Passwords: The client password is limited in the database to 8 characters. A JavaScript or something similar should be implemented in the config page which will limit the passwords entered to 8 characters to reflect the limitation in the database. As it is now, the entire password is accepected, although only the first 8 are saved. - Date Formating: The 'LastVisit' date that is displayed on the pages needs to be re-formatted so that it is more readable. This change will more than likely be so that the dates will read: Mon, 19 June 2000, 20:13:11 If there is anything else that is 'misbehaving' or that you believe can pose to be a problem, please do not hesitate to contact me where I will look into the matter, aswell as issue a update to the code should it be neccessary. Contacting me: ~~~~~~~~~~~~~~ Please feel free to contact me at any time by sending mail to cgknipe@mweb.co.za, I'm always looking forward to hearing from people who uses my code and appreciates the value of implementations done by me. mrtg-2.17.10/contrib/monitor/default.asp0000644000175300017510000002402613057016061017131 0ustar oetikeroep<% @LANGUAGE="VBSCRIPT" %> <% Response.Expires = 0 %> <% Server.ScriptTimeout = 1200 %> <% On Error Resume Next %> <% ' Check if we have to log out... If Request.QueryString("mode") = "logout" Then ' Update the circuit access date ' Get the record ID to update LineID = Session("DBID") If LineID = "" Then ' The Session Expired Response.Redirect(LogOutURL) End If Set rsAuthenticate = DBConn.Execute("UPDATE Monitor_Authenticate SET LastVisit='" &_ Month(Date()) & "/" & Day(Date()) & "/" &_ Year(Date()) & " " & Time &"' WHERE (ID=" & LineID & ")") Session.Abandon Response.Redirect(LogOutURL) End If ' Status is a universal indicator implemented to show us which part of the authentication process is ' failing. ' For now, Status has the following values. ' 0) No errors, everything was successfull. ' 1) Circuit number not found in the database. ' 2) The given password did not match for the circuit number. ' 3) We are logged out and should redirect back to SunnyLine ' We only execute this code if the user actually submitted the login form from the page. If Request.ServerVariables("REQUEST_METHOD") = "POST" Then ' Get the values that he or she entered at the login page. Number = Request.Form("Number") Password = Request.Form("Password") ' Setup a default error code. We use a incorrect circuit number here. Status = 1 ' Did The User Enter a circuit number & password? If Number = "" Then Status = 1 ' No circuit number Elseif Password = "" Then Status = 2 ' No password Else Status = 0 ' We have a circuit number & password, lets continue. End If ' If we have both circuit number and password, compare it to the database. If Status = 0 Then ' Pull the circuit number from the database. Set rsAuthenticate = DBConn.Execute("SELECT * FROM Monitor_Authenticate WHERE LineNumber=" & Number) Do While not rsAuthenticate.EOF ' We need to give DBPassword an initial value. If for instance, a client enteres a circuit ' number which is not located in the database, the lookup will fail and DBPassword won't have a ' value for us to compare to. The Rnd Function should be secure enough? DBPassword = Rnd(10) DBID = rsAuthenticate("ID") DBLine = rsAuthenticate("LineNumber") DBPassword = rsAuthenticate("LinePassword") DBSpeed = rsAuthenticate("LineSpeed") DBEMail = rsAuthenticate("EMail_Address") DBG_Day = rsAuthenticate("Graph_Day") DBG_Week = rsAuthenticate("Graph_Week") DBG_Month = rsAuthenticate("Graph_Month") DBG_Year = rsAuthenticate("Graph_Year") DBG_EMail = rsAuthenticate("Graph_EMail") DBDate = rsAuthenticate("LastVisit") If DBPassword = Password Then ' We got what we wanted, close the database connection... Just for incase. rsAuthenticate.close Set rsAuthenticate = nothing ' We setup the values inside the session before or after we move into monitor. ' This is just so that we don't have to do the entire lookup process again at displaying the graps to the user, if ' we save the values now, we are able to reference any setting in the DataBase that we would need at any given time. Session("DBID") = DBID Session("DBLineNumber") = DBLine Session("DBLinePassword") = DBPassword Session("DBLineSpeed") = DBSpeed Session("DBEMail_Address") = DBEMail Session("DBGraph_Day") = DBG_Day Session("DBGraph_Week") = DBG_Week Session("DBGraph_Month") = DBG_Month Session("DBGraph_Year") = DBG_Year Session("DBGraph_EMail") = DBG_EMail Session("DBLastVisit") = DBDate ' And we redirect !! Response.Redirect(MonitorURL) Else ' Passwords didnt match. We are not going to worry about incorrect circuit numbers, that ' will just make it easier for someone to maybe guess a line number if he or she has ' nothing better to do! Status = 2 End If rsAuthenticate.MoveNext Loop ' If we are here, there was serious error. This means perhaps a incorrect curciut number and or ' incorrect password. In any case, the lookup did fail, and we have no reference what so ever to the given value for ' the circuit number or password. Close the database and send the user back to the login section. rsAuthenticate.close Set rsAuthenticate = nothing End If End If %> Welcome To Monitor!!

      Welcome to Monitor.SunnyLine.co.za

      Congratulations on the purchase of your high-speed permanent connections to the Internet.  Please take a moment and log on to our monitoring system to see you bandwidth usage.

      Your Circuit number will be the number printed on your Data Unit installed by Telkom (The small black box where your NTU or Modem plugs into).  If you have any problems locating your Circuit number, or have problems authenticating with this service, please contact us for immediate assistance at support@sunnyline.co.za

      Wondering what is Monitor! Well, don't worry, read up all about monitor by clicking here.

      Circuit Number:

      <% If Status = 1 Then Response.Write ("Invalid Circuit Number!!!") End If %>

      Your Password:

      <% If Status = 2 Then Response.Write ("Invalid Password!!!") End If %>

       

      Guest Users:

      Please log in with Circuit Number:  1234567890
      and Password:  12345678

      to see a demo of this service right now.

       

      2000 SunnyLine Internet Services.  All Rights Reserved.


       
      MRTG
      Tobias Oetiker <oetiker@ee.ethz.ch> and Dave Rand <dlr@bungi.com>

       

      mrtg-2.17.10/contrib/monitor/Monitor.mdb0000644000175300017510000033000013057016061017103 0ustar oetikeroepStandard Jet DBnb` Ugr@?~1y0̝cßFNt7˜(K9` {6߱/{C 3ly[:|*|fkՁf_Љ$g'DeFx -bT4.0dv @ @ @     ) JJ KS@8PK K K`K KKKK쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍쌍}_9@_9@dbo_WWWLogst88888888886  ~Y9@c^9@ VtQoDefTemp0000t&@ dbo.WWWLogs.<4#AO}_}_9@ :@dbo_WWWLogst88888888886  U9@!O@dbo_POP_Listingt@LLL@@@@@@@> @L9@1M@dbo_Monitor_Authenticatet@^^^RRRRRRRP @PB9@5W/K@dbo_Link_Linkst<@JJJ>>>>>>>< @c?<9@-'I@dbo_Link_Catst@HHH<<<<<<<: @z49@1#H@dbo_Holidayst@FFF:::::::8 @+%8@9J7G@dbo_History_Todayt@PPPDDDDDDDB @18@lE@dbo_Exchange_Codest@RRRFFFFFFFD @  ط d@,d@Admint@8,,,,,,,,,* mѴ@Ӵ@MSysAccessObjectstDDDDDDDDDDB  D?T@D?T@UserDefinedt88888888886  S@%2c@SummaryInfoth@ DDD88888886 @ Ѱ@I@AccessLayoutt4MR2KeepLocal T@zz:::::::8 @y!X@y!X@SysRelt.........., VW@VW@Scriptst0000000000. VW@VW@Reportst0000000000. VW@VW@Modulest0000000000. 2W@2W@Formst,,,,,,,,,,* d@d@DataAccessPagest@@@@@@@@@@> UQ@UQ@MSysRelationshipsvDDDDDDDDDDB UQ@UQ@MSysQueriesv88888888886 UQ@UQ@MSysACEsv22222222220 UQ@UQ@MSysObjectsv88888888886 UQ@ĸ@MSysDbt@:::......., @UQ@UQ@Rel YS  Y   Y Y  Y Y  Y  Y  Y   Y  Y  Y  Y  Y 2Y  Y   Y  Y ConnectDatabaseDateCreateDateUpdate FlagsForeignNameIdLvLvExtraLvModule LvPropName OwnerParentIdRmtInfoLongRmtInfoShortTypeYYIdParentIdName        OY7SY Y Y  Y 2ACMFInheritableObjectIdSID  AtYObjectId  Root Entry 0葲ٿ VBA0葲ٿ0葲ٿVBAProject0葲ٿ0葲ٿVBA0葲ٿ0葲ٿdir_VBA_PROJECTPROJECT&(PROJECTwm+  !"#$%'()*0* pHdMonitorQ(@= l pt: J< rstdole>stdoleP f%\*\G{00020430-C 0046}#2.0#0#D:\WINNT\System32\STDOLE2.TLB# Automation^gADO DB> ADOBC.CD1C10-8CAA006D2EA4C1CProgram Files\Co0mmonM\Ado\msado15.dll#Microsoft ActiveX Data Objects 2.1 LibraryH am  *\G{000204EF-0000-0000-C000-000000000046}#4.0#9#D:\PROGRA~1\COMMON~1\MICROS~1\VBA\VBA6\VBE6.DLL#Visual Basic For Applications*\G{4AFFC9A0-5F99-101B-AF4E-00AA003F0F07}#9.0#0#D:\Program Files\Microsoft Office\Office\MSACC9.OLB#Microsoft Access 9.0 Object Library*\G{00020430-0000-0000-C000-000000000046}#2.0#0#D:\WINNT\System32\STDOLE2.TLB#OLE Automation*\G{00000201-0000-0010-8000-00AA006D2EA4}#2.1#0#D:\Program Files\Common Files\System\Ado\msado15.dll# YSY  Y Y Y  Y  Y Y  Y AttributeExpressionFlagLvExtra Name1 Name2ObjectId Ordernzf edY"ObjectIdAttributex %AccessVBAWin16~Win32MacVBA6#Project1 stdole`Monitor߬ADODBs<  ID="{A5790BB3-4591-11D4-A166-004033410036}" Name="Monitor" HelpContextID="0" VersionCompatible32="393222000" CMG="CFCD93E6AD7A787E787E787E787E" DPB="9E9CC2375EC92CCA2CCA2C" GC="6D6F3104CFD2D0D2D02D" [Host Extender Info] &H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000 ijMSysDbAcessVBAData,Forms  0葲ٿ0葲ٿCmdbars0葲ٿ0葲ٿModules 0葲ٿ0葲ٿReports0葲ٿ0葲ٿScripts 0葲ٿ0葲ٿPropData-Databases0葲ٿ0葲ٿ00葲ٿ0葲ٿBlob DirData.CustomGroups0葲ٿ0葲ٿDataAccessPages 0葲ٿ0葲ٿ -YSY Y Y  Y  Y  Y  Y  Y ccolumn grbiticolumnszColumnszObject$szReferencedColumn$szReferencedObjectszRelationship   YYYszObject$szReferencedObjectszRelationshipx %AccessVBAWin16~Win32MacVBA6#Project1 stdole`Monitor߬ADODBs<  ID="{A5790BB3-4591-11D4-A166-004033410036}" Name="Monitor" HelpContextID="0" VersionCompatible32="393222000" CMG="CFCD93E6AD7A787E787E787E787E" DPB="9E9CC2375EC92CCA2CCA2C" GC="6D6F3104CFD2D0D2D02D" [Host Extender Info] &H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000 ijMSysDbAcessVBAData,Forms  0葲ٿ0葲ٿCmdbars0葲ٿ0葲ٿModules 0葲ٿ0葲ٿReports0葲ٿ0葲ٿScripts 0葲ٿ0葲ٿPropData-Databases0葲ٿ0葲ٿ00葲ٿ0葲ٿBlob DirData.CustomGroups0葲ٿ0葲ٿDataAccessPages 0葲ٿ0葲ٿYv1b N  : k & W  C t/ m Z G  H7 ܴwSysAccessObjectsfLLLLLLLLLLJ @@t    @ OJmJJMMQkkfJUQkOJmJLJkQkSdi`k `dOo^Qk iQ^JmYdbkWYfkiQfdimk kMiYfmk kvkiQ^ mJL^Qk`dbYmdi+JomWQbmYMJmQ`kvkJMMQkkdL[QMmk`kvkJMQk`kvkdL[QMmk`kvkhoQiYQk`kvkiQ^JmYdbkWYfkJMMQkk^Jvdom`kvkOLko``JivYbSdokQiOQSYbQO  !"# SI@SI@TablesMSysRelationshipsT2& SI@SI@TablesMSysQueriesH2& SI@SI@TablesMSysObjectsH2& SI@SI@TablesMSysACEsB2& b[W@Z\W@TablesMSysAccessObjectsT2& K@`L@TablesMonitor_AuthenticateZ2&u  @ @      Root Entry E(ٿ VBAE(ٿE(ٿVBAProjectE(ٿE(ٿVBAE(ٿE(ٿdir_VBA_PROJECTPROJECT&(PROJECTwm+  !"#$%'()*0* pHdMonitorQ(@= l pt: J< rstdole>stdoleP f%\*\G{00020430-C 0046}#2.0#0#D:\WINNT\System32\STDOLE2.TLB# Automation^gADO DB> ADOBC.CD1C10-8CAA006D2EA4C1CProgram Files\Co0mmonM\Ado\msado15.dll#Microsoft ActiveX Data Objects 2.1 LibraryH am  *\G{000204EF-0000-0000-C000-000000000046}#4.0#9#D:\PROGRA~1\COMMON~1\MICROS~1\VBA\VBA6\VBE6.DLL#Visual Basic For Applications*\G{4AFFC9A0-5F99-101B-AF4E-00AA003F0F07}#9.0#0#D:\Program Files\Microsoft Office\Office\MSACC9.OLB#Microsoft Access 9.0 Object Library*\G{00020430-0000-0000-C000-000000000046}#2.0#0#D:\WINNT\System32\STDOLE2.TLB#OLE Automation*\G{00000201-0000-0010-8000-00AA006D2EA4}#2.1#0#D:\Program Files\Common Files\System\Ado\msado15.dll#1  @ @ @ @ @ @ @    $%./0,-123456&'()*+  !"#g d;QE/:ywc-dsG= ozwиpwV}ӣFjg``#"DϷwqg d;QE/:ywc-dsG= ozwиpwV}ӣFjg``#"DϷwqw>eǚ*p f g d;QE/:ywc-dsG= ozwиpwV}ӣFjg``#"DϷwqw>eǚ*p f g d;QE/:ywc-dsG= ozwиpwV}ӣFjg``#"DϷwqw>eǚ*p f g Td;QE/:ywc-dsG= ozwиpwV}ӣFjg``#"DϷwqw>eǚ*p f Td;QE/:ywc-dsG= ozwиpwV}ӣFjg``#"DϷwqw>eǚ*p f g g d;QE/:ywcJ6v@jX@TempMSysAccessObjectsfLLLLLLLLLLJ K@`L@Monitor_Authenticatef@VVVJJJJJJJH @ ƩI@ƩI@UserDefinedfA@DDD88888886 @ -I@۴Q@SummaryInfof@DDD88888886 @ fTW@fTW@AccessLayoutf4MR2KeepLocal T@zz:::::::8 @vI@vI@SysRelf.........., SI@SI@Scriptsf0000000000. /dI@/dI@Reportsf0000000000. SI@SI@Modulesf0000000000. /dI@/dI@Formsf,,,,,,,,,,* vI@vI@DataAccessPagesf@@@@@@@@@@> SI@SI@MSysRelationshipsgDDDDDDDDDDB SI@SI@MSysQueriesg88888888886 SI@SI@MSysACEsg22222222220 SI@SI@MSysObjectsg88888888886 SI@ V@MSysDbf@:::......., @SI@SI@Relationshipsg<<<<<<<<<<: SI@SI@Databasesg44444444442 SI@SI@Tablesg..........,      d _ Z g  ~  I      ʾMonitor_Authenticate6v@jX@MSysAccessObjects-DDDDDDDDDDB K@`L@Monitor_Authenticate-@VVVJJJJJJJH @ ƩI@ƩI@UserDefined-A@DDD88888886 @ -I@۴Q@SummaryInfo-@DDD88888886 @ fTW@fTW@AccessLayout-4MR2KeepLocal T@zz:::::::8 @vI@vI@SysRel-.........., SI@SI@Scripts-0000000000. /dI@/dI@Reports-0000000000. SI@SI@Modules-0000000000. /dI@/dI@Forms-,,,,,,,,,,* vI@vI@DataAccessPages-@@@@@@@@@@> SI@SI@MSysRelationships/DDDDDDDDDDB SI@SI@MSysQueries/88888888886 SI@SI@MSysACEs/22222222220 SI@SI@MSysObjects/88888888886 SI@ V@MSysDb-@:::......., @SI@SI@Relationships/<<<<<<<<<<: SI@SI@Databases/44444444442 SI@SI@Tables/..........,  gYrcuit N  Y Yti Y nYX Y 0SdYYYYY  Y   Y  dIDLineNumberLinePasswordLineSpeedEMail_AddressGraph_DayGraph_WeekGraph_MonthGraph_YearGraph_EMailLastVisitCommentdvN   Y   Y Y Y XY`Y Y ydYYYYY  Y  CommentIDLineNumberLinePasswordLineSpeedEMail_AddressGraph_DayGraph_WeekGraph_MonthGraph_YearGraph_EMailLastVisit+@i@Monitor_AuthenticateHHHHHHHHHHH  +@+@UserDefined66666666666  +@+@SummaryInfo66666666666  @@AccessLayout88888888888 Oq@Oq@SysRel,,,,,,,,,,, Oq@Oq@Scripts........... Oq@Oq@Reports........... Oq@Oq@Modules........... Oq@Oq@Forms*********** Oq@Oq@DataAccessPages>>>>>>>>>>> ,3@,3@MSysRelationships/DDDDDDDDDDB ,3@,3@MSysQueries/88888888886 ,3@,3@MSysACEs/22222222220 ,3@,3@MSysObjects/88888888886 ,3@,3@MSysDb-......... Gy@I12345678@nobody@sunnyline.co.zaExample Circuit Added For Monitor Example To Potential New Clientsl@/  Y NY Y KDataIDPXJKYAOIndexv1pK[   H7 ܴwSysAccessObjectsfLLLLLLLLLLJ JJK[ࡱ>   Root Entry E(ٿ VBAE(ٿE(ٿVBAProjectE(ٿE(ٿVBAE(ٿE(ٿdir_VBA_PROJECTPROJECT&(PROJECTwm+  !"#$%'()*0* pHdMonitorQ(@= l pt: J< rstdole>stdoleP f%\*\G{00020430-C 0046}#2.0#0#D:\WINNT\System32\STDOLE2.TLB# Automation^gADO DB> ADOBC.CD1C10-8CAA006D2EA4C1CProgram Files\Co0mmonM\Ado\msado15.dll#Microsoft ActiveX Data Objects 2.1 LibraryH am  *\G{000204EF-0000-0000-C000-000000000046}#4.0#9#D:\PROGRA~1\COMMON~1\MICROS~1\VBA\VBA6\VBE6.DLL#Visual Basic For Applications*\G{4AFFC9A0-5F99-101B-AF4E-00AA003F0F07}#9.0#0#D:\Program Files\Microsoft Office\Office\MSACC9.OLB#Microsoft Access 9.0 Object Library*\G{00020430-0000-0000-C000-000000000046}#2.0#0#D:\WINNT\System32\STDOLE2.TLB#OLE Automation*\G{00000201-0000-0010-8000-00AA006D2EA4}#2.1#0#D:\Program Files\Common Files\System\Ado\msado15.dll#K[Microsoft ActiveX Data Objects 2.1 Librarypt:x %AccessVBAWin16~Win32MacVBA6#Project1 stdole`Monitor߬ADODBs<  ID="{A5790BB3-4591-11D4-A166-004033410036}" Name="Monitor" HelpContextID="0" VersionCompatible32="393222000" CMG="CFCD93E6AD7A787E787E787E787E" DPB="9E9CC2375EC92CCA2CCA2C" GC="6D6F3104CFD2D0D2D02D" [Host Extender Info] &H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000 ijMSysDbAcessVBAData,Forms  E(ٿE(ٿCmdbarsE(ٿE(ٿModules E(ٿE(ٿReportsE(ٿE(ٿScripts E(ٿE(ٿPropData-DatabasesE(ٿE(ٿ0E(ٿE(ٿBlob DirData.CustomGroupsE(ٿE(ٿDataAccessPages E(ٿE(ٿConnectDatabaseDateCreateDateUpdate FlagsForeignNameIdLvLvExtraLvModule LvPropName OwnerParentIdRmtInfoLongRmtInfoShortTypeYYIdParentIdName        7vcP=*z @ -  } j C 0  m Z G p]\I6"DataIDPXJKYAOIndex     - g,i-Sy®TCkX⊝A91r㽘>rv%^oSٝ:QƤo,CL٢0B̓} 7(p - - g,i-Sy®TCkX⊝A91r㽘>rv%^oSٝ:QƤo,CL٢0B̓} 7(p - - Tg,i-Sy®TCkX⊝A91r㽘>rv%^oSٝ:QƤo,CL٢0B̓} 7(p - Tg,i-Sy®TCkX⊝A91r㽘>rv%^oSٝ:QƤo,CL٢0B̓} 7(p - - g,i-Sy®TCkX⊝A91r㽘>rv%^oSٝ:QƤo,CL٢0B̓} 7(p - - g,i-Sy®TCkX⊝A91r㽘>rv%^oSٝ:QƤo,CL٢0B̓} 7(p - - - g,i-Sy®TCkX⊝A91r㽘>rv%^oSٝ:QƤo,CL٢0B̓} 7(p - - - g,i-Sy®TCkX⊝A91r㽘>rv%^oSٝ:QƤo,CL٢0B̓} 7(p - ( ( - g,i-Sy®TCkX⊝A91r㽘>rv%^oSٝ:QƤo,CL٢0B̓} 7(p - ( - g,i-Sy®TCkX⊝A91r㽘>rv%^oSٝ:QƤo,CL٢0B̓} 7(p - ( - g,i-Sy®TCkX⊝A91r㽘>rv%^oSٝ:QƤo,CL٢0B̓} 7(p - - g,i-Sy®TCkX⊝A91r㽘>rv%^oSٝ:QƤo,CL٢0B̓} 7(p - ( ( - g,i-Sy®TCkX⊝A91r㽘>rv%^oSٝ:QƤo,CL٢0B̓} 7(p - ( - g,i-Sy®TCkX⊝A91r㽘>rv%^oSٝ:QƤo,CL٢0B̓} 7(p - - ( - g,i-Sy®TCkX⊝A91r㽘>rv%^oSٝ:QƤo,CL٢0B̓} 7(p - .LVAL> @ @ @ @     ʾMonitor_Authenticate f^3 LVAL "=*z @ -  } j C 0  m Z G MR2OrderByOnColumnWidthColumnOrderColumnHidden FilterOrderBy 1 ID Y  ALineNumber (  ELinePassword   ?LineSpeed   G EMail_Address $  ?Graph_Day   AGraph_Week d  CGraph_Month   AGraph_Year   CGraph_EMail U  ?LastVisit   ;Comment   MR2( ReplicateProject MR2@ Title AuthorCompanySubject Monitor Chris Knipe> 6Bandwidth Monitoring System> 6SunnyLine Internet ServicesMR2FAccessVersion BuildAuto Compact0Perform Name AutoCorrect8Log Name AutoCorrect Changes6Track Name AutoCorrect Info4Four-Digit Year Formatting"Show Values Limit,Show Values in Indexed4Show Values in Non-Indexed*Show Values in Remote.Show Values in Snapshot*Show Values in ServerRow Limit 08.50                  'mrtg-2.17.10/contrib/monitor/images/0000755000175300017510000000000013057016061016241 5ustar oetikeroepmrtg-2.17.10/contrib/monitor/images/mrtg-r.gif0000644000175300017510000000336313057016061020145 0ustar oetikeroepGIF89a4]=x\;^p&]AXu gU1D]~M-كrY~!!Ԃfdm@T|(zRI.߁vrTJ81*e_D0Q[k8.FrV]ay؅Q"@GmwZLV9AYKB2}a';7a?eeR(@%HRK&m餡b!R1J*a F5 cɪ6 }ה.YH'$5Q${  zj(V5I54iD^](c0Up>Rc!; XIŲYq`TCֳIBQ6%Ph+ x L+&9(1B8'g@&s+Iħ ̦r CfEqM"в0""U?<#BbleZ;*cjDlFXҶff8KTĢ O'{r@7 E5a؂7SdMyZAf&<2hV3H(͋J>1Laȏ8< *qYLC"C*ѢpBB@ġp N5+ZI +\p&zMbؾ6,d'KZ"H;mrtg-2.17.10/contrib/monitor/images/mrtg-l.gif0000644000175300017510000000052713057016061020136 0ustar oetikeroepGIF89a?}f}4]_bgymivMtTq\!,?X0I8`e:* Am mײr@UtLǖjs:(XLjem=3$đsT|GYz j<`h@p,t=+ppH,W&:dxXP`x~h KM Cp( {?>}hV^  M1j,.QTt \ Uub e {V b]tf>iPn'&xVefYdV  [Y9RplrA8 bcgv>±Yfk0BU"Ry 3kh[IJ`sG2<ҠL.};#V7`Q.} ;U f1 לpȧXXjʵ=O3Zz=j ]k֦Iq~O2xDVK᪄ u\ތaɆGFqRi)rC|[З(fNvQh3;@/m]v{̲C >rIFmHB}RǂGeO #ڽA( HoMlϴE5a5C) S e~cׅTnK CD^QхلfBCT Q'PЄCЎ;CSr@s1="ISE3[~F)VqcUdƌq"(/`9P='+}bJ55>SL8^Ҟ{S+.9N Q#KF_w1"vy{= pᅉ%J)z&^:y1"TkzvV! ,XP@Q:yGNWiRg ,F8Eה 4@NH(a4R,V*~Ƃ2/7xƤ{ M;ZwmmRnzSj+v_AӸ9i  )5! HHŋ3^T \@2thx34r7?Ô`Ğ(Dyd!2`D "*ET2(79`8wڙ$W0{ Թ3Vjp!nO\@l@wT q-X5 nTʬCJVE|pɵ'ŪL [ ,ԯǸ1^2[K_!bS *\"EGw%$:o%NɢzϿY"M=Q #εDCsoA(>HŤeYac[(`K3hbUO4ԇiڝvNO<*1hBU )+JWS&^8묳`Bt*[RYehv U ' z9*%z U5Dĉ^@t% )t(y1vJS&NPeQ*%dUI6XIF|f_&bI&hzODɈLƪI\ ,z(\1J)Q`r@$:ƈ+r5p*1<[3 `9jn.TV| DG+-/ _Kgh6,P E[f V4#u| }Sn6-3!5c1,l,.;@mPP )i\F4d;/dF'F:99v: ty?gb/`.ƻAd{0A@^ &S8 GG(!$߆nC  41HtF(E1C&6qZ#@ V/2À*Z?%  ӑVZ(>TP'KX^ hF0U>|/ѲO?R`Xd"MBҨSnʺkb˞M6k7»o Nȓ`ϟAҕkνTů;m@Aph386 ޗ >qp) >r `@{ŭLw| ݢ34uނW^1@*yJwu"\7_"܋hY( 8Р!d7{&q6ua88$sy=Ȣyw$Dhalɀl6.HL6 #!8pNZZ)܏=kvj(#>|HWvm_w"h=4('v z0򡄸Ywwz‹iܕ8(" Sg p9'Jτi-[@h" ت(O ty.s`Y$[evEb`{aAEVh#Y^8h@#w=..(`ˎ*3BT圊vJIF"1,BD! ,X0 @j͟I}">,BT3Rjũ `rxlOô<W khUt8" 4( TpPum d2M KGS'1(B-+UK2vU=,prDg ~OT(U.=Lq@v~N'WOX1   qh"gB EʂB4вK,Ռ gM3k4ҭ+Rc:ŋɜ@fƏ4HBÆ=HA{E.,0gl煑A@ljԃH)#%vbNg $y  @ c>:qKp)AeUc2tZ|6dm `TywF070ad*soުIJ\$ 9pY†k`!ku3М,g.h¹A6F/BƘL߶jG3(PTgiFiOkvcwX!X]L`Ve=Ȟ D % ,` Cd3!0!~>"Pa; b(Nfb@6Um43K;,8bOa%7hc1NXTXi&~ cO:hffi睦|*蠄j衈&Z @6裐_%QF:飱5Zi6!*ꨤ֩ꪬꪫ3C(4 @52 p %l.@ɲ (&!J*b>+ ʦ Ɔm AX+Dx *B8FmRҀ .qq$-xũ,!1˯zM Oڣ8;kX22+ +&m$mḨb~,8+Mc}MnP@!,,XPI8S@(dihB,tmx㎓. 4,nP\|4 ,EX,1͠0y z*X [/*EUkJ wkkoJU =pu }/w#F JIXYMnJm P O > do MMUlr YqPI 1XZD։JܶEՉvXNS' T^rؤB\`W3.t tHAj%d^]h9&1 'J<-ٳhӪ]>t(6kD3_\鵀ݏR͘#2ĸgNc@* &T}bKTA>Р2,KƬBuMT`MxEONB]X"۷兹8kyˢ,tE1}`E9q2E%`YT (@ $o-=wVT\^(}@{ipԁυ3|9oMKd&q b ߕ6ć8x|`VC8 @s\AUPgABAY !\aŧ?hz?{)v٦DLi2)[-0 ;A'G,qZ! ,XP^K'[ChLj.FJ雜OC!8\ bXpLGC(X@pTc'F\VlU<< eQ &>]hIsHSX[Pqb0oX ' vX=r=22v)1/<=4 >;ɸ ZѸ(( 9 5 A_ "ThA‚&ŋ3jȱG6H%II P:Xɲ˗0cʜ93ɛ8Stj*o\'-mܩ@>BQb6Mʦ-Fh6at)I ZʃTS-@탦&v:e6\0 _aL6+UIBWG{,K\6L傥Fj5 XT+~&=+ bμw*EN]+cl BA 1&q`e5@_yтꇫ2| Az)8@0*ty=g,B @J &X+kru$ Hc%8 :̌4hc*#کD RERWD%I:Ҥ $`I*qgMj䁒01e.hwUyAp;)HdFpc-HdJbQeX`P"}Lt)Q Y){ 0`$fMqwUIwThq [Ȇ%}ǡJV^{UZ^U僭$5l&Ǭ* *ՙ Gq- Qc"\`I,bJ8~)%KZ~JSL44XciX _^A<Nm` l8@B 0ӀJ;T*W=Tr> bHw"?'@W 3aqVE\u4"Ad7qI_W_mOw +z} 2)GƝ݈xNnǝ#3) 7 Jb! ,XP8_j@x`<82ua"/GNI+MďHBHix lXI5۰LN2BBޣnld +Ci_#{~ A| i=Utn sys N| ~!Z #',e ?l tn(.2 @YVN5 K ,"#gjp lx q2:0'=NPS#odC7&! ffz9#^ 0 & , `+Al\m0ٿ+bx-7qcL@ױoLZxڅٱk?K˞j.شsv%t N4XμУKNztֳkΝ'so'CTXs='.g"@)'`*WUt0؞| V"{ ,S ^{dogb?`bF.UPF$x&sX,~)ƈzbM9:ȜtJ(F&:bRbycWay!}#yZ6e>l1h^{T!!+K#LM)75`sW+Td?ۂOצ(ey*L}ydjک!޳.*Nqv5D! ,X0 @8M⏲=S-`>Ԁpx*HвaXHR* p<EhP> n߀ e8.R<@[xl(& #=}h@oq+,cJz*~x~lvK, ,61G7  ^_~ i|ϺrkxS'|/~ _q@*/m嫎[# XK8z @0'Xjz`1C!ԍ* ]Ȍ%-p /$:-E3AG <2-cCY([E 2Yϊ ٔ *hS =39wj''\xqҋ/+Uf *xaW݇ M!G9ޘGB!W#1y5 ԅQĆ^v|L;DH`jXz(Xa0<Dl2q^՚x>C aInbeUC 6FJ)Ii{n kOC[ ^ sO` [Vn!d$L5v (S3ejU&N1xh& 9}]aiФ֡Q]qlJ2AW̨0Є4G ЄX6t% ylycBKMd1P'q0R=P"m&IC%J}܉3 4+XJgo&p)oIa"!.ʩhß2XJft:*B*?8)&Is+ d4˦?:Piβ1)X^irЂħ+kKB! ,XP@_7,^Cq$=Tl(mm>D=C'P(LO"A=a3ݾr) .K XCYT`A{ϰwBf^`5 2h==?"lI7_71*i~Dl"-gf5UC&Dm& c))=м   {!*\ȰÅ LH3btǏ C)RAĐ U\EO:\ & 8Ivaǔ-qh*cP|M<$8AAQ zѥ* >03bzy eȯ5U˲,+{=|,  KE_[D–1p}.ɌS'xm +Wگ_ IZ;L%8SyfLt]p`Y1W 89fd%F;@$!mwǻa*%Q"pr* i`0VL8.?Ιu C +,tFYBacrL7=!3=[Ccl1I?! ,XP 7{,` 6γL@』`֤9af ¥dYHy) 'CrAPQ|@Tk ,!3^4^.i“YkvQ7E≯1> Dlq('W٢˜7-AӨS^ͺװc~`Z۸qg^6 䆍 v$j7S7wq PH]pǎ[n3M& ;2=6߯yw\WtmQiwӲ-b@SSPoC $@Kfs|,`x0ڣ! k@uU WAA'e$ 6&.Y,620A,+06 +E@vHy}{$oqXZ1o!(?xAz &\U=c: .  m wIO6Q Aaĩ0ɀaCD`#ܜ,GpA`%*\HB5Jķ-A?%\!A& wZTɲ˗@Xă1<i/xKOK]0)j% H%x@jϥ&V}CK< 2&$ |;z鼓/+ y0iu~{ؽA{6wNu"Wa|^z h W%FA@Xh!%4T0Q$%D2 +/Xd| SXPF9STw"1Y\P|/92dihl香NY%՜tIg6 "S|'7cTFy2@6裐F*餔Vji q \/B0򨩝2/**5#*.]MkB c>x/*l2jC69Qn0$>PSg>vL2es0 ,뤤Blyҩ!`¨wU&Lkr{Œ[rΪһ Klۦq[ӂt11 øzjL̞|zp@uaFМ 5JPuhkֳOܙKY2Dd'O_!Bk3 1Z`%@^1g.Xzmcnud.Ň}47X⺘k:\\Rb ImQmwG=-t2LQS>Ⲙ cxg}0|(]|Qj-݊ك_"R!M&Z[!AVpy7xA ˤnT{tCvr' 2`Or܊a 8|QC$ ڷ`=(ؐ, ^hHL#@GC'Ë3 !O !1 f{HVT2؅}p'rqe$e:f>fyQAgYi^f~gJ>!J\q(6*`2DOJa&Y'Y#"bVJ(gư),PDji3 pS,l(R~+k[n@+[o! ,XPI\*$N#`(cڴɛ% `0Gx,$0GBE ̕*/aPŌp$ [L) % U)%{-V~-:j >ssy! E ?C>2`/ :WG KM Z J} Z?o?2JJJJ I_+/o"Հ "<ȠC 8( NXF8dH'(˗0cʜIM72ɳO@ JѣG(]JP[$J$Jb%k `rM(EhӬ|Ҫ]ˇQmЧ@{/%w2~ X̸N,\SXys &%¤>\uD74?7hЃ%cR.AUXx-g3~* .'{J)Oڡj̈́Wƺ#W*%i{VEe [\o9t0}%UheZ*"R@j $v_?)$$@Y~9nd> T[VP$H]u|~MNX& 5eGa(l)'%}d>ᘣPT\JuJd2QP uMZwO]p)ftD%jdeL@@d^{L՛#eYybN e`=kabGo jp[2.ۜ>ot $ p|Ph(ʪ[C pi+иJa+KQR" 73.)g7,,20f5Ba(*EwHR "prYggL1gp 7 &@yK Z\4> ; 6. mD"nL xN3feʬ0L,e-8 LD O087. 㳇 DlKȓ(O6hrefM/lU1 @͂: A66 K ,"F )U@,"#ti:((KDg  D7VɑxH+q|/SgQ$crRBmg>\uV#DHnAhFXR,Y+yP `D0Fםh%N ~M:D zLp(27_SzBDx A>ebmEWPWZ%әQQ!Rg` EBkLs6M[ #l(X8P!)(0̈.-Vxkd37#?FNK'67 P > ,ХC&_$u~2#չ%x)fL ١"zĢ6裐F*U`饘f u~çz"V꩕V!ͫ*무j뭸ӫЮX@ +*,c! ذ2l*ԆK&AjKn J#F 륈v!8-tM?hе0;  єҶ; k!B ++qJk4p0b ZiWA"mðBj/\a]-^*Ƞ|)غJB_tE!#created with Microsoft GIF Animator!X,XI*ͻ`>`h@p,t=+ppH,W&:dxXP`x~h KM Cp( {?>}hV^  M1j,.QTt \ Uub e {V b]tf>iPn'&xVefYdV  [Y9RplrA8 bcgv>±Yfk0BU"Ry 3kh[IJ`sG2<ҠL.};#V7`Q.} ;U f1 לpȧXXjʵ=O3Zz=j ]k֦Iq~O2xDVK᪄ u\ތaɆGFqRi)rC|[З(fNvQh3;@/m]v{̲C >rIFmHB}RǂGeO #ڽA( HoMlϴE5a5C) S e~cׅTnK CD^QхلfBCT Q'PЄCЎ;CSr@s1="ISE3[~F)VqcUdƌq"(/`9P='+}bJ55>SL8^Ҟ{S+.9N Q#KF_w1"vy{= pᅉ%J)z&^:y1"TkzvV!#created with Microsoft GIF Animator;mrtg-2.17.10/contrib/monitor/images/mrtg-ti.gif0000644000175300017510000001113013057016061020307 0ustar oetikeroepGIF89a4]emuMq\its!,(0I8ͻ`(dihlp,tmx|pH,Ȥrl:ШtJZجvzxL.ۀ8`~rquySkv& kx26Pr&uw'3źwMʵϵ!تn"/uK!$(( r ZCXBxӪ> rec Tvu[d뾺T/-.L΍vQ~eț`09PhfpO( :aK oT؅ϠC@Ufuz [Z]]as=o8k}l[ޘxm0užk|nìկ*?ubޢ|9~_]  IaY-HaS{n9H!?ه&(/i"<硗O%(O966RP=βTL?h($G!IERTt=9R䙗"AU$f{Z] g%~j"&gY\ucKU%z9lOΥ(,WVp:]ՠu1j[> whB *b VGN˪j!PkojS Z*tOl$b~0>MZ DZ$յ sôV)f1kTGRPLf ]FÚ x>ѫ36Um ᎧiYkk_'ʨ ,.+k A!Mmq/(\q9 s46B'A#L?}; 3Sئ ^300u[М-)v .:5zSFDqGAx $v_2#>@bB6|^u%!6A 2 V}ou:G/C?Bd^s+O飵ESHv azU~ݚ;L3iʃ8!?ė1 j64t GLDDF@okОBpA c@)`~7A! 1kX}!}D=*Cn ?߼|XD9I/a|,L (s!gr 9"w:eר p"|Ʀxc^tqsGabZDNuu4#'5~-.aex`F<t$הO zJPf`!8.^ Wr!2f1BI_L683!;7l9Ʒ]0j'$v)~ x#'`z7E3sJjpZڙՊ^)|ꧦ٥vܑ@șGYz\\Iࣦ؄ IʧJKb  bG‹ٌqy4~XuڔʱٕaZZjӰ>?誫ئO9'밃j菂 :ZGʴp ܺ-ʵ_I zjT`|س 6z(C :^ ~X%(myr;pVZZYrXۢyZZ{p۱@g˳9ȘۺNKj-ԙΈ˷i; ?*'ۓRꚔ{;ыa{ ^dAhjRZٽI{;0뤌 +䫲@[2+h˃뿢wH 2l<5-=6ď^YRHꏿ 2ۻ.gj]ok_% ˫bڒKkUY[QBk#?{!`5344` D"BVX \dLFfUH cV. O ;p#-3A" !,}f}4]ZbisscvMtRr[Xܾ3DpP|h:\f i Y)BqF(!G +H4 !,}f}4]YbjrscvMtRrZXܾ3DpP1|h:\Vxi˱@+ՉL+ _p TWlE׊'> xs(4u-F ʮg(ϢkP~Y}Spq-7Y{ rJ5G'!G.- !,}f}4][bisscvMtRr[Xܾ1DpP1|h:`NUi ,S, A#ByI 8 RVXRˍm9jC%m 6-\>F '#a7C T:W1I zCP"$Wx ;mrtg-2.17.10/contrib/monitor/images/msie.gif0000644000175300017510000002165413057016061017675 0ustar oetikeroepGIF89aXf3fff3̙f3fffffff̙ffffff3fffffffff3fff333f33333333f3f3f̙f33f3ff3f33f̙f̙3̙3333f33333333fffff333f333f3̙̙f̙f! NETSCAPE2.0!,XH*\p!#JHŋ3VǏVIɓ(S\r`GYTie抆 orS&#޴y犚,q.ɤG*ЧH5 OBTʤ">}*jUX P+t`Zu,%60"۝kChca!;ФxBŋ#\pS; Qʒ/46/DCD"^fbX-OFzN-VYp p&t {' uG|_2x}KF_rЁ |A{*G^bQV^PQ8xuTM\hF8!d0 +'A馛h Bb%V@XIX׆z1FMe #tW I ٗ~r1܍3RTvH@0 9EzvH@#4qP괂UPU%ŵ@Ag"e"y&wIgVXSXVØ*@ #G0n(osWDw 'PiKA9Z@dY` LLXO|5V !NBm5Yy[aH!/];(iɨW1WeieD8WDgzF(L@$UfZXEQZ`6-i}._Bzu9M1'@'w*!,ޛgk9F35zi\I`QrEϭk>˱fqtMY1t}E@EMVH8BM̒6椗n騧Nz@!,<H*\Ȥ" a# #1*\R䅕OF8pɒ/D<)`ˆ#DȄ&A#*DTbD"ry`N(4'FlLIA:]hAZ\ARSd #2TPB/T!a# Y UL!=T)0@$.!۷9`/g:U&-K AYG^XVhEHMP"4+7)2]vA$rqI"G(@!,<H @ QrH @0E#Kq(Pqq_*D$%/DTb"D\|y0(V&5*UBhHY()Z + F̪(Z0$8a /XbnQ ;aȈ#RTMAb}U` v0.d GGydv^9B-!~a*`jUXA챲ؤ x,:%0b"-ABƍHgɒUxlh˫F,ZT a$!,<H 40ȐXذa.X@0FEgPPQd",B+"D$h"&X3 #exS 8E$H͂E'PIP:Uċ"E1)*FP!%#@8! B֦Q\sOBE?Ԯ0\ڪh̐ *U'N0H*jL"z )~t؁G/QC豀'(5ST[֠37#A ~9Z m**"N$7\垀&`A!,<H`Ah`¡La "FB|1"< #F"%%> ‡SΣ2,8EJ5`/Tp⅐FwXJ"d"F" pWB׆CUI8#辐ǐ5xV" 7p # $̔4^rĠA9&a8>  k, W )pfbݧ"R8wRH&mrߟ? !,<H 4h0 BfѰ02fGE/^Y"xBňE.Q1 /E1B$R#vi$hA2!jU"|tpeUE)A Y՘Y"DHj<aF\"@|dETA@OH0ȋG<q&&@0oA"/p(nʑ&$ǒ"@*7A[I)-;_%_5rcU752 "S/bdR@!,<HذA qC+ . 8`È#T)hE%8b"bDMFNq/TT!舕KbM5ka$L L "DE- Lx1Q`ر+ `A)s+A F4B D@# )4)*hOy@?ڄ #42 _XjA#*G&/ LX 0=h""{W@~oAʽQ6Ɩb7%Fo0t` AvsgA`FF(!,<H ܡ0aErѐAnhDFrbD \b˒*xQ[Ƹ!$%Ed 1}D\x )_ONs E[s%G\$5_^/fQKK̥^EvaB!,<H*\Ȥ" .yFrPAT8p ;qC7^(PÆF 02qIs̐•WPPBD+( v\ʃB`1BAp`1aB7$*Uq`RV8a WИa # 0BDh8cH!ADN e#0/1C"ANH@B"9q(-R;b6^hO.EHAH&K yz zE`\@Kا~W|xDz[ї0\A *vu !,<H*\Ȥ" .y.1 !KnLh"*HF&8.qYȈ `%1 <d-f̸ŋ$,Dń fmTB]ڜ  bBOPa,8Ub(-2e9<H+patHHpђ׫ YЈ9N =ka~ C'Z~!bDn| ;&'H5& )R?~>=͓?pɑ%!qTBD`K G 6!,<H*\Ȥ" .yHd%DxG#ET#Hq4 `K"ȕ-f\ɒ#gQQtJ ZИ"s4GeyЈI#8xBE8^}!bD WXB_a$H = 1q΃)_pР"f$$PКOA^$C @qe@U@ʘA D^<>7QZ HwIЇo-H"4OPt>W'v 6!,<H*\Ȥ" .ya A .YG#ETbGqHdHbdb"$Wh\q JAT5:%Ap,x# #eU9 vD #zBլ0=zPRjԼAÕ@z8@B xW( !@nj!f 5f (f*l )IF880@ԩ044ɖcxN 19BR&/d%kEq+#{_H}hL!,<H*\Ȥ" . Ɂ A\ 8rPѣEJ|C!#TGL1iC H Ѡ PB^82i4)(`{B6|,¡ J<G] Sh0`F#Li V 0`"/hd +OCi;E^-r)+-A#:_)m2 "aK#3Jj ʶd3 Ȑ!CEĈ$B"yCс&P@!,<H*\Ȥȋ"E\D%LYh#8^xF/Tc"F8*`Ā!bD!a x /z!)Ѝ' &}A$HM@>S2G hjaN"8|) X]h)3sŇAYØA :Eǎ.E4@YhD1>PD!JaX`@!,<H*\Ȥ" . / .Y/`3qR4}*jUX P+t`Zu,%60"۝kChca!;Фxbċ#\pS; Qʒ/46/DD K6f[֫^Ve˴U\28߿GN؈pٷkE-{ foŗXT&W8u^USZ :@Dz7_5V e^@S_YyaA0&n/ dbjɥr.dS#I1!gJ K :WA,BWU5 ^7ۖx —;$a&ifu؋5ASću80A|%Z&6\R&$p mrtg-2.17.10/contrib/get-equi/0000755000175300017510000000000013057016061015025 5ustar oetikeroepmrtg-2.17.10/contrib/get-equi/README0000644000175300017510000000040313057016061015702 0ustar oetikeroepFrom: Mike Gaertner Date: Tue, 25 Apr 2000 19:06:52 +0700 (ICT) The Equinox SST card does not provide SNMP support. Therefor I wrote a small perl script which reads out the byte counter from the Equinox SST board. Regards Mike Gaertner mrtg-2.17.10/contrib/get-equi/get-equi.pl0000644000175300017510000000362613057016061017111 0ustar oetikeroep#!/usr/bin/perl # # byte counter for a Equinox SST card with analog modem pool # for use with mrtg2 # # by Mike Gaertner # 20 Apr 2000 # # Returns the total sum of the input and output character counter # from an SST card for all ports you specify # # NEEDS the Linux driver version 3-35c for SST based boards # # --- sample.cfg file --- # #MaxBytes = (8 x 56kbit/s modems) / 8 = 56000 bytes/s total capacity # # adjust this to the number of modems you have # # Target[modems]: `/usr/local/mlog3/bin/mrtg/get-equi.pl` # MaxBytes[modems]: 56000 # Title[modems]: OFIX modem pool traffic (8 Modems) # Options[modems]: growright # XSize[modems]: 500 # YSize[modems]: 200 # WithPeak[modems]: my # PageTop[modems]:

      Traffic Analysis modem pool (8 Modems)

      # ------- # # Edit the @m array # @m = Modems you want to monitor without ttyQ # # check the $sstty path # use strict; my(@m,$sstty,$port,$i,$o,$new_i,$new_o,$source); # modems @m = ("1a5","1a6","1a7","1a8","1a9","1a10","1a11","1a12") ; $sstty = "/usr/bin/sstty -s "; $source = "equinox modempool"; $new_i = 0; $new_o = 0; foreach $port ( @m ) { open ( STAT, "$sstty $port |" ) ; while( ) { if ( /input/ ) { ($i,$o) = (split(/ +/))[8,11] ; $new_i += hex($i); $new_o += hex($o); } } close(STAT); } print $new_i,"\n",$new_o,"\n",&uptime(),"\n$source\n" ; #find out when the board driver was last loaded sub uptime { my($start,$now,$diff,$s,$m,$h,$d,$hms); $start = (stat("/etc/eqnx/logfile"))[10] ; $now = time() ; $diff = $now - $start ; $s = $diff % 60; $diff = ($diff - $s) / 60; $m = $diff % 60; $diff = ($diff - $m) / 60; $h = $diff % 24; $diff = ($diff - $h) / 24; $d = $diff ; $hms.= ($h < 10 ? " " : "") . $h; $hms.= ($m < 10 ? ":0" : ":") . $m; $hms.= ($s < 10 ? ":0" : ":") . $s; return "$d days, $hms"; } mrtg-2.17.10/contrib/mrtgidx/0000755000175300017510000000000013057016061014763 5ustar oetikeroepmrtg-2.17.10/contrib/mrtgidx/mrtgidx0000755000175300017510000000305213057016061016367 0ustar oetikeroep#!/usr/tardis/local/gnu/bin/perl5 # mrtgidx - generate html index page based on mrtg.cfg # # Syntax: mrtgidx # # v0.1 1996-11 by Axel Dunkel (ad@Dunkel.de) # # --- start of configuration section --- $include_inactive = 1; # include interfaces that are commented out # --- eof of configuration section --- if ($#ARGV < 0) { print "mrtgidx: generate HTML index page based on MRTG config file\n"; print "\nUsage: mrtgidx \n"; exit 2; } while ($line = <>) { chop $line; if ($line =~ /^(#*).*Title\[(\S+)\]:\s*([^:]*):\s*(.*)$/) { $cmt = $1; $itf = $2; $title = $3; $title_if = $4; if ($cmt ne "#" || $include_inactive) { if ($itf =~ /(.*)\.([0-9]+)/) { $router{$1,$2} = $title_if; $router_f{$1,$2} = $itf; $router_n{$1} = $title; $active{$1,$2} = $cmt; } else { print STDERR "Warning: can not interpret : $itf\n"; } } } } # print HTML header print "MRTG Index\n"; print "\n"; print "

      MRTG - Index

      \n"; print "generated by mrtgidx by Axel Dunkel\n"; print "\n"; mrtg-2.17.10/contrib/diskmon/0000755000175300017510000000000013057016061014751 5ustar oetikeroepmrtg-2.17.10/contrib/diskmon/showdisk.pl0000644000175300017510000000060713057016061017144 0ustar oetikeroep#!/usr/bin/perl # Displays disk info to the hosts that connect to it. # # No command line options, just put it in /etc/inetd.conf as shown in # the README file. # # By Steven Micallef on the 24/4/1999. foreach $_ (`df -k | grep -v "Filesystem"`) { ($device, $size, $used, $free, $percent, $mount) = split(/\s+/); chop($percent); print "$percent\n"; } mrtg-2.17.10/contrib/diskmon/sample.cfg0000644000175300017510000000144213057016061016714 0ustar oetikeroepTarget[hostAdisk]: `/mrtg/getdisk.pl hostA 1` Title[hostAdisk]: HostA's Root partition % used MaxBytes[hostAdisk]: 100 PageTop[hostAdisk]:

      HostA's Root partition % used

      Suppress[hostAdisk]: y LegendI[hostAdisk]: % used LegendO[hostAdisk]: Legend1[hostAdisk]: % used Legend2[hostAdisk]: YLegend[hostAdisk]: percent used ShortLegend[hostAdisk]: used Options[hostAdisk]: gauge Target[hostBdisk]: `/mrtg/getdisk.pl hostB 1` Title[hostBdisk]: HostB's Root partition % used MaxBytes[hostBdisk]: 100 PageTop[hostBdisk]:

      HostB's Root partition % used

      Suppress[hostBdisk]: y LegendI[hostBdisk]: % used LegendO[hostBdisk]: Legend1[hostBdisk]: % used Legend2[hostBdisk]: YLegend[hostBdisk]: percent used ShortLegend[hostBdisk]: used Options[hostBdisk]: gauge mrtg-2.17.10/contrib/diskmon/getdisk.pl0000644000175300017510000000134513057016061016743 0ustar oetikeroep#!/usr/bin/perl # This script is used to establish a TCP connection with a host to get the # disk info provided by showdisk.pl. # # use: ./getdisk.pl # # By Steven Micallef on the 24/4/1999. # Externale bug fixed by Alon Goldberg 27/2/2000. use Net::Telnet; $hostname = $ARGV[0]; $disk_no = $ARGV[1]; # If you've changed the port showdisk.pl runs on, change it here too. $port = 9047; $i = 0; if (!defined($disk_no)) { print "Usage: $0 \n"; exit } $t = new Net::Telnet ( Host => $hostname, Port => $port); $t->open("$hostname"); while ($i ne $disk_no) { $data = $t->getline(Timeout => 40); $i++; print $data, 0, "\n" if $i eq $disk_no; } mrtg-2.17.10/contrib/diskmon/README0000644000175300017510000000577513057016061015647 0ustar oetikeroep====================================== DiskMon (getdisk.pl and showdisk.pl) ====================================== by Steven Micallef --------------- What they do --------------- getdisk.pl and showdisk.pl work on the client/server principal. showdisk.pl - runs off the 'server' displaying disk partition % used. getdisk.pl - runs off the 'client' and connects to the 'server' to get disk info off showdisk.pl. ------------------- Before you begin ------------------- Before you Install, you need the following: - Perl - Net::Telnet Perl Module. You can get this straight from: ftp.oleane.net/pub/CPAN/mirrors/modules/by-module/Net/Net-Telnet-3.01.tar.gz ------------- Installation ------------- The following steps apply to EACH MACHINE YOU WANT TO MONITOR... 1. Copy the showdisk.pl script to the host you wish to monitor. 2. In your /etc/inetd.conf, insert the line: df stream tcp nowait root Of course, the TCP wrapper isn't mandatory, but if you want to restrict access to the viewing of free disk space, I really recommend you install it. 3. In your /etc/services file, put in the following line: df 9047/tcp The port you choose is up to you, but if you do change it from 9047, be sure to update getdisk.pl too (the port number is specified in the first few lines of the script). 4. kill -HUP your inetd 5. Test it by telnetting to the host at port 9047. You should get the following: bash~# telnet hostname 9047 < usual connect messages > 30 40 10 20 . . etc.. Of course, the output depends on a) how many disks are on the machine, and b) how much space in % is used on each disk. If you didn't get any output, go back and make sure you did everything properly. -------------------------------- Setting up getdisk.pl with MRTG -------------------------------- The getdisk.pl script runs like so: ./getdisk.pl For example, doing a ./getdisk sparky 1 will show how much % of the first partition (usually the root partition) on sparky is used. So how do you map a number to a partition? On the host you installed showdisk.pl on, do the following: bash~# df -k Filesystem 1024-blocks Used Available Capacity Mounted on /dev/hda1 202222 78786 112993 41% / /dev/hdc3 2486311 1247138 1110635 53% /usr /dev/hdc1 1486150 375570 1033782 27% /backup ^ The first disk is 1, the second 2, and so on.. | Example: | bash~# ./getdisk.pl hostname 3 | 27 <-------------------------------------' Please look at sample.cfg to see how to setup getdisk.pl with MRTG. --- I hope this is as useful to you as it has been to me. If you have any problems/bug reports/advice/complaints, email me. Enjoy. Steven Micallef mrtg-2.17.10/contrib/net-hosts/0000755000175300017510000000000014130032004015215 5ustar oetikeroepmrtg-2.17.10/contrib/net-hosts/grnball.gif0000644000175300017510000000156313057016061017346 0ustar oetikeroepGIF89a f3̙f3f3ffffff3f3333f333f3f3̙f3̙̙̙̙f̙3̙ffffff3f3333f333f3̙f3̙̙f3̙f3ff̙ffff3f33̙33f333̙f3ffffff3ffff̙fff3fffffff3ffffffffffff3fff3f3f3f3ff33f3ffffff3f3333f333333̙3f3333333f3333f3f3f3ff3f33f33333333f333333333f333f3̙f3f3ffffff3f3333f333f3!, P=H ={@),aBP@ <@ e%z@@Bі tFM4d4O.3&L5ij*h;o Zh@;mrtg-2.17.10/contrib/net-hosts/redball.gif0000644000175300017510000000156113057016061017330 0ustar oetikeroepGIF89a f3̙f3f3ffffff3f3333f333f3f3̙f3̙̙̙̙f̙3̙ffffff3f3333f333f3̙f3̙̙f3̙f3ff̙ffff3f33̙33f333̙f3ffffff3ffff̙fff3fffffff3ffffffffffff3fff3f3f3f3ff33f3ffffff3f3333f333333̙3f3333333f3333f3f3f3ff3f33f33333333f333333333f333f3̙f3f3ffffff3f3333f333f3!, N=H 8T`! @0xAG$ \ÈG8LcƑ!:xC9d%ˈ]̘s#@z;mrtg-2.17.10/contrib/net-hosts/internet0000644000175300017510000000277613057016061017020 0ustar oetikeroep212.93.136.193:eth1-sub2-HFC-H1A-10M.rds-cons.rdsct.ro:969099666:1 212.93.136.130:10Me0-Ct-E1-Buc.noc-ct.rdsct.ro:969099666:1 212.93.152.1:212.93.152.1:969099666:1 193.231.227.182:bucharest-bb3-fe2-0.rdsnet.ro:969106997:1 195.158.251.1:robuc101-ta-f0-0.ebone.net:969099666:1 213.174.70.62:atvie103-ta-s1-0.ebone.net:969099666:1 195.158.245.9:atvie101-tc-p0-0.ebone.net:969099666:1 195.158.242.45:czpra103-tc-p2-0.ebone.net:969106395:1 213.174.70.45:debln302-tc-p2-0.ebone.net:969099666:1 213.174.70.37:debln301-tc-p1-0.ebone.net:969099666:1 213.174.70.41:dedus206-tc-p6-0.ebone.net:969099666:1 213.174.70.125:dedus205-tc-p7-0.ebone.net:969099666:1 213.174.70.134:nlams303-tc-p2-0.ebone.net:969099666:1 195.158.225.85:bebru203-tc-p1-0.ebone.net:969106997:1 195.158.225.82:bebru204-tc-p2-0.ebone.net:969099666:1 195.158.232.41:gblon505-tc-p1-0.ebone.net:969099666:1 195.158.229.21:usnyk106-tc-p1-0.ebone.net:969099666:1 4.24.187.49:p6-0.nycmny1-cr8.bbnplanet.net:969099666:1 4.24.8.93:p7-1.nycmny1-ba2.bbnplanet.net:969099666:1 4.24.6.233:p7-0.nycmny1-br2.bbnplanet.net:969099666:1 4.24.9.65:so-4-0-0.chcgil2-br1.bbnplanet.net:969099666:1 4.24.9.70:p6-0.chcgil1-br1.bbnplanet.net:969099666:1 4.0.2.226:p5-0.lsanca1-br2.bbnplanet.net:969099666:1 4.24.4.13:p2-0.lsanca1-br1.bbnplanet.net:969099666:1 4.24.4.1:p7-0.lsanca1-ba1.bbnplanet.net:969099666:1 4.24.4.18:p0-0-0.lsanca1-cr3.bbnplanet.net:969106997:1 4.24.40.14:s0.uscisi.bbnplanet.net:969106997:1 198.32.16.49:dmz-isi.isi.edu:969099666:1 128.9.0.107:b.root-servers.net:969099666:1 mrtg-2.17.10/contrib/net-hosts/README0000644000175300017510000000614113057016061016113 0ustar oetikeroepPREREQUISITES: - Linux operating system ( I am using RedHat 6.2 ); - MRTG version ( I used 2.8.8 version ); - SHELL scripting language; - AWK scripting language; - FPING utility ( I used 2.2b1 ); - CRON daemon installed; - TCP/IP Network connection {:-) net-hosts I use this script to monitor internet connection state on a chosen route (from traceroute). Usage is very simple: - Put in your crontab file a line which have to be run every five (5) minute or any other time interval you want (but you have to edit, according with this new value, 'make-mrtg.cfg.awk' file). I am using Linux RedHat 6.2 and in my /etc/cron.d I put a file named 'net-hosts' with the following structure: ################################## # /etc/cron.d/net-hosts -rw-r--r-- # */05 * * * * root /usr/local/mrtg/contrib/net-hosts/net-hosts # # EOF ################################## - Restart your cron daemon... and wait To install, first edit the variables from both 'make-mrtg.cfg.awk' and 'net-hosts files' as needed. I found it easier to have these defined rather than hardcoded due to differences between code interpretations. You don't have to insert any other target in your own mrtg.cfg file that you already have, because this script is launced by the cron daemon. internet This is the file which keep the IPs, FQDNs, dates and states for hosts you want to monitor. The format of this file is: ::: ::: ::: . . . where: - IP_xxx is IP address (IPv4) for host xxx - FQDN_xxx is Fully Qualified Domain Name of host xxx - LAST-MODIFIED_1 is the date when the state of host xxx was last modified - STATE_1 is the current state of host xxx (1 = UP; 0 = DOWN) First time you create this file you just need IPs and FQDNs, blank dates and 1 (or 0) for the state of every hosts, like this: aaa.aaa.aaa.aaa:your.router.name::1 bbb.bbb.bbb.bbb:yourISP.router.name::1 . . . zzz.zzz.zzz.zzz:that.host.name::1 HINT: You could have an ordered list using traceroute and awk (or any other shell-script). The file 'internet' shipped with this package it is a demo. make-mrtg.cfg.awk This is the core of the entire task. Here I make 'mrtg-awk.cfg' file using the content of 'internet' file and the state read from fping utility (Fast Ping - it was not written by me...). After doing this, internaly is lauched 'mrtg' executable for net-hosts's mrtg.cfg file (named 'mrtg-awk.cfg'). Of course, it is created a file, 'internet.html', used like an index file for the all targets in 'mrtg-awk.cfg', but you could use 'indexmaker' script provided with MRTG for doing this (see an example in 'net-hosts'). Be aware ! You have to place icons (MRTG) and image files (grnball.gif, redball.gif, cubprev.gif) in the same location. You also have to place 'net-hosts.css' into declared location inside that AWK script file. ---------- Direct questions or suggestions to me. Have fun! -Adrian Turcu mrtg-2.17.10/contrib/net-hosts/cubprev.gif0000644000175300017510000000316013057016061017366 0ustar oetikeroepGIF89a sssk1cZRcRBZRJZR)c1s9JRZk9{BZk9J)Z1c{JsBcR9R1cZJ{{sRRJckc֥ƌZs{Rks{cs{猜޵kRk{Jcsss1ZsZsBZk{cBc{ZJ!BZ电{c9Zs1RkscskR{cskZcRBkZR1Z{)Rs{sZk{kJc{筽Υƌ諒k{cs眽ޔc{ZssRkcsZ{BZskRs{cs9RkJkZkBccR{1JcJsZ9Z{RZ1RsJ{9cBs)Jk1Z!Bc!Js9Z1R9cZkcZ{RscR{Js9Z1R{)Js!Bk9c1Z)RޥsRc{ZsJcBZ{9Rs)Bc)J{RsJZsBRk1Z)RJZ{Ɣs{ε!, @ H A  " Ӕ)fe)LF.q5Z:3/xq28HDHZc6DTҥ0|zդ`DnJV2]TE +G$}I/;ztr1 !2|  صKk(1LJUNWa- o:\tK]uz).ɺt[Q1cV!8j<4h #f@r%YQ  J`(at;KfG4K%YDӖ-<1,ƘHta-hH3&e01qLPJ'5* /\aaFiNfR쁇f&x *aK/c\FS(ydn[u".Ƭ!@ !##lVD%p'0#sܱ/P $aTK)Q ,̰`Ŵ'V$X(:$!$l'Be%Wl$ɭ^L#5"?"d`LzOD`mK+~i2E @@vEK,d.u,L'&0 @]"9f) 0Ǒ'\|p@(O"i.̈́Hb~ S <KPZ.{!'glT b$P(]2^(AXm܈YS=I XL';0pmL2 mZqL'uAd3("$MU-XI-^! 8BK Sl.#\ P6 0ռ! NMi $`;mrtg-2.17.10/contrib/net-hosts/make-mrtg.cfg.awk0000644000175300017510000001744314130032004020354 0ustar oetikeroep BEGIN { # ## Global Variables Initialization (Feel you free to edit as needed) # # mrtg_var_WorkDir = "/usr/local/mrtg/contrib/net-hosts" # it will be inserted into MRTG config file mrtg_var_IconDir = "http://www.your.domain/img/" # it will be inserted into MRTG config file and it will be used on HTML documents mrtg_var_Interval = "5" # it will be inserted into MRTG config file mrtg_executable = "/usr/local/mrtg/mrtg" # MRTG executable file with full path mrtg_nethosts_cfg = "/usr/local/mrtg/contrib/net-hosts/mrtg-awk.cfg" # MRTG config file for net-hosts nethosts_internet_path = "/usr/local/mrtg/contrib/net-hosts" # the path for internet IPs file (without / at the end) nethosts_css_file = "http://www.your.domain/css/mrtg/net-hosts.css" # CSS File definition for HTML documents nethosts_maintainer_email = "Your Name <your@email.address>" # Maintainer email address # ## Start index number for array # lines = 1 startdate = systime() dataexpirarii = startdate+300 # Expire date for HTML documents, +5 min (mrtg_var_Interval) dataexp = strftime("%c %Z", dataexpirarii) dataexpirarii = strftime("%d-%m-%Y %T %Z",dataexpirarii) system((">" mrtg_nethosts_cfg)) } { # # The state from fping for every IP is inserted into array state=$2$3 ip=$1 array[lines,1] = ip array[lines,2] = state lines++ } END { close(FILENAME) # ## Variables Definition # header=" \ \ \ \ \ \ \ \ Internet Conection Statistics Overview \ \ \

      Main Index +++ Internet Conection Statistics Overview

      " footer="
      " # lastmod=("
      Last modified: " strftime("%d-%m-%Y %T %Z",startdate) ".
      ") expire="
      Expire on: "dataexpirarii".
      " # tablestart=" \ \ \ \ \ \ \ " tableend="
      IndexNameIPStatusLast Changed On

      " # startraw="" endrow="" # startcell="" endcell="" # startlongcell="" # imgdown=("") imgup=("") # pstart="

      " pend="

      " # ## # print header > (mrtg_var_WorkDir "/internet.html") print tablestart >> (mrtg_var_WorkDir "/internet.html") # # print ("WorkDir: " mrtg_var_WorkDir) > mrtg_nethosts_cfg print ("IconDir: " mrtg_var_IconDir) > mrtg_nethosts_cfg print ("Interval: " mrtg_var_Interval) > mrtg_nethosts_cfg print "\n\n#----------------------------------------------------------------------------\n\n" > mrtg_nethosts_cfg # ## # xx = 1 kontor = 0 succesiv = "0" # ## Fping results processing # while ((getline line < (nethosts_internet_path "/internet")) > 0 ){ split(line, l, ":") for ( i = 1 ; i < lines; i++ ){ if ( array[i, 1] == l[1] ){ break } } if ( l[4] == 1 ){ last_state = "isalive" } else { last_state = "isdad" } myfun(xx, i, l[2], l[3], last_state) i++ xx++ } close((nethosts_internet_path "/internet")) # ## # print tableend >> (mrtg_var_WorkDir "/internet.html") print lastmod >> (mrtg_var_WorkDir "/internet.html") print expire >> (mrtg_var_WorkDir "/internet.html") print footer >> (mrtg_var_WorkDir "/internet.html") # ## # system(("mv -f " nethosts_internet_path "/tmpinternet " nethosts_internet_path "/internet")) system((mrtg_executable " " mrtg_nethosts_cfg " 2> /dev/null")) } function myfun(f_rindex, f_index, f_name, f_olddate, f_last_state) { if( ! f_olddate ){ f_olddate = startdate } # if(array[f_index, 2] == "isalive"){ statew = 1 succesiv = "0" kontor = 0 if ( f_last_state == array[f_index, 2] ) { datew = f_olddate } else { datew = startdate } print array[f_index, 1]":"f_name":"datew":"statew > (nethosts_internet_path "/tmpinternet") print startrow startcell f_rindex endcell > (mrtg_var_WorkDir "/internet.html") print (startcell "" f_name "" endcell) > (mrtg_var_WorkDir "/internet.html") print startcell array[f_index, 1] endcell > (mrtg_var_WorkDir "/internet.html") print startcell imgup endcell > (mrtg_var_WorkDir "/internet.html") print startcell strftime("%c %Z", datew) endcell > (mrtg_var_WorkDir "/internet.html") print endrow > (mrtg_var_WorkDir "/internet.html") print "Target[" f_name "]: `echo | gawk '{ print \"1\\n1\\n..., last changed on: " strftime("%c %Z", datew) "\\n" array[f_index, 1] "\\n\"; exit }'`" > mrtg_nethosts_cfg } else { statew = 0 if( succesiv == "0" ){ succesiv = "1" } kontor++ if ( f_last_state == array[f_index, 2] ) { datew = f_olddate } else { datew = startdate } print array[f_index, 1]":"f_name":"datew":"statew > (nethosts_internet_path "/tmpinternet") print startrow startcell f_rindex endcell > (mrtg_var_WorkDir "/internet.html") print (startcell "" f_name "" endcell) > (mrtg_var_WorkDir "/internet.html") print startcell array[f_index, 1] endcell > (mrtg_var_WorkDir "/internet.html") print startcell imgdown endcell > (mrtg_var_WorkDir "/internet.html") print startcell strftime("%c %Z", datew) endcell > (mrtg_var_WorkDir "/internet.html") print endrow > (mrtg_var_WorkDir "/internet.html") print "Target[" f_name "]: `echo | awk '{ print \"0\\n0\\n..., last changed on: " strftime("%c %Z", datew) "\\n" array[f_index, 1] "\\n\"; exit }'`" > mrtg_nethosts_cfg } print "Title[" f_name "]: " f_name > mrtg_nethosts_cfg print "MaxBytes[" f_name "]: 1" > mrtg_nethosts_cfg print "AbsMax[" f_name "]: 1" > mrtg_nethosts_cfg print ("AddHead[" f_name "]: ") > mrtg_nethosts_cfg print ("PageTop[" f_name "]:

      Connection State for   " f_name "") > mrtg_nethosts_cfg print "

      " > mrtg_nethosts_cfg print " " > mrtg_nethosts_cfg print " " > mrtg_nethosts_cfg print (" ") > mrtg_nethosts_cfg print " " > mrtg_nethosts_cfg print " " > mrtg_nethosts_cfg print " " > mrtg_nethosts_cfg print "
      System:" f_name " (" array[f_index, 1] ")
      Maintainer:" nethosts_maintainer_email "
      Service:Internet Connection
      IP:" f_name " (" array[f_index, 1] ")
      Last Changed On:" strftime("%c %Z", datew) "
      " > mrtg_nethosts_cfg print "Suppress[" f_name "]: y" > mrtg_nethosts_cfg print "LegendI[" f_name "]: used" > mrtg_nethosts_cfg print "LegendO[" f_name "]: " > mrtg_nethosts_cfg print "Legend1[" f_name "]: used " > mrtg_nethosts_cfg print "Legend2[" f_name "]: " > mrtg_nethosts_cfg print "YLegend[" f_name "]: used " > mrtg_nethosts_cfg print "ShortLegend[" f_name "]: used " > mrtg_nethosts_cfg print "Options[" f_name "]: gauge" > mrtg_nethosts_cfg print "YTics[" f_name "]: 1" > mrtg_nethosts_cfg print "\n\n#-------------------\n\n" > mrtg_nethosts_cfg } mrtg-2.17.10/contrib/net-hosts/net-hosts.css0000644000175300017510000000172313057016061017672 0ustar oetikeroep/* Author: Adrian Turcu Created: 16 April 2000 Version: 1 */ BODY { background-color: f5fffa; } A { text-decoration: none; } A:link { color: 0000cd; } A:visited { color: 0000cd; } A:active { color: 0000cd; } H1 {white-space: nowrap; border: none; padding: 0.5em; margin-top: 25px; position: relative;} H1 A {text-decoration: none;} H1, H1 A {color: #f8f8ff; background: #4169e1;} .pt { border: none; padding: 0.25em; width: 1020px; text-align: center; font-weight: 800;} .pt, .pt A {text-decoration: none; color: #f8f8ff; background: #0000cd;} .ptl { border: none; padding: 0.25em; width: 1020px; text-align: left; font-weight: 800;} .ptl, .ptl A {text-decoration: none; color: #f8f8ff; background: #0000cd;} .pth { border: none;text-decoration: none; background: #e8e8ff; color: #111111; text-align: left; font-weight: 800;} .ptb { border: none;text-decoration: none; color: #0000cd; text-align: left; font-weight: 800;} mrtg-2.17.10/contrib/net-hosts/net-hosts0000755000175300017510000000241714130032004017073 0ustar oetikeroep#!/bin/sh ## ## OUTPUT_FILE has to have the same path with WorkDir value setted in the make-mrtg.cfg.awk file ## MRTG_NETHOSTS_CFG has to be the same file declared in the make-mrtg.cfg.awk file ## MRTG_EXECUTABLE is the MRTG executable file with full path ## NETHOSTST_INTERNET_PATH is the path for internet IPs file (without / in the end) and has to be the same path declared in the make-mrtg.cfg.awk file ## NETHOSTST_AWK_FILE is the make-mrtg.cfg.awk file with full path ## MRTG_EXECUTABLE="/usr/local/mrtg/mrtg" NETHOSTST_INTERNET_PATH="/usr/local/mrtg/contrib/net-hosts" NETHOSTST_AWK_FILE="/usr/local/mrtg/contrib/net-hosts/make-mrtg.cfg.awk" ## ## /bin/cat $NETHOSTST_INTERNET_PATH/internet | /usr/bin/gawk -F: '{print $1}' | /usr/sbin/fping | /usr/bin/gawk -f $NETHOSTST_AWK_FILE ## ## ##################################################################################################### ## Index Maker in MRTG Style ############################ # # OUTPUT_FILE="/usr/local/mrtg/contrib/net-hosts/1/index.html" # MRTG_NETHOSTS_CFG="/usr/local/mrtg/contrib/net-hosts/mrtg-awk.cfg" # # /usr/local/mrtg/indexmaker -b "#ffffff" -1 -t 'Internet Nodes' -o $OUTPUT_FILE $MRTG_NETHOSTS_CFG # ###################################################################################################### mrtg-2.17.10/contrib/snmpping/0000755000175300017510000000000013057016062015141 5ustar oetikeroepmrtg-2.17.10/contrib/snmpping/README0000644000175300017510000000034413057016061016021 0ustar oetikeroepFrom: x I came up with a diagnostic tool called snmpping.pl to make sure I have the right information on a device. I have posted it bellow. It just goes out and grabs a gid and displays it on the screen. mrtg-2.17.10/contrib/snmpping/snmpping.pl0000755000175300017510000000123613057016062017336 0ustar oetikeroep#!/usr/sepp/bin/perl use lib qw(../../run); use BER; require 'SNMP_Session.pm'; my $host = @ARGV[0]; my $community = @ARGV[1]; my $port = 161; $session = SNMP_Session->open ($host, $community, $port) || die "couldn't open SNMP session to $host"; $oid1 = encode_oid (1, 3, 6, 1, 2, 1, 1, 1, 0); if ($session->get_request_response ($oid1)) { ($bindings) = $session->decode_get_response($session->{pdu_buffer}); while ($bindings ne '') { ($binding,$bindings) = &decode_sequence ($bindings); ($oid,$value) = &decode_by_template ($binding, "%O%@"); print $pretty_oids{$oid}," => ", &pretty_print ($value), "\n"; } } mrtg-2.17.10/contrib/ping-probe/0000755000175300017510000000000013057016061015347 5ustar oetikeroepmrtg-2.17.10/contrib/ping-probe/README0000644000175300017510000000141613057016061016231 0ustar oetikeroepFrom: Peter W. Osel To: Tobias Oetiker Date: Wed, 9 Dec 1998 16:19:18 -0800 Subject: mrtg distribution and mrtg-ping-probe Tobi, to prevent people from using older versions of mrtg-ping-probe, could you use the latest version for your next release ( ftp://ftp.pwo.de/pub/pwo/mrtg/) or maybe even removeit from the current distribution of mrtg and just add a README file in the contrib directory or so. Cheers --pwo -- Peter W. Osel Sr. Network Systems Administrator Siemens Microelectronics, Inc. Email: pwo@SMI.Siemens.COM 10950 North Tantau Avenue Phone: +1 (408) 895 5050 Cupertino, CA 95014 Fax: +1 (408) 895 5020 USA WWW: http://www.AgiX.NET/~pwo/ mrtg-2.17.10/contrib/ipfilter/0000755000175300017510000000000013057016061015123 5ustar oetikeroepmrtg-2.17.10/contrib/ipfilter/ip-filter.readme0000644000175300017510000000177413057016061020206 0ustar oetikeroepI've found the simple enclosed perl script useful to use mrtg to graph traffic through our IP-Filter firewall. The script may need some fiddling with the regular expressions to graph what you need at your site; our if-filter configuration blocks everything on the WAN interface by default and allows specific protocols in with `pass in quick' and `block in quick' rules on groups from 100-190; hence the simple regular expressions. The usage in mrtg.cfg here is: # firewall Target[firewall]: `./fw.pl` Options[firewall]: growright, noinfo, perhour MaxBytes[firewall]: 50000 Title[firewall]: IP-Filter PageTop[firewall]:

      Firewall Traffic Analysis

      Syn/Ack Packets Passed (Connections) on le1 (24.7.4.75)

      YLegend[firewall]: Packets per Hour ShortLegend[firewall]: pkts/hr Legend1[firewall]: Inbound connections per hour Legend2[firewall]: Outbound connections per hour -- Ronald Florence http://members.home.net/18james mrtg-2.17.10/contrib/ipfilter/fw.pl0000644000175300017510000000106413057016061016075 0ustar oetikeroep#!/usr/local/bin/perl # reads stats and uptime from ip-filter for mrtg # ron@rosie.18james.com, 2 Jan 2000 my $firewall = "IP Filter v3.3.3"; my($in_pkts,$out_pkts) = (0,0); open(FW, "/sbin/ipfstat -hio|") || die "cannot open ipfstat\n"; while () { $in_pkts += $1 if (/^(\d+)\s+pass\s+in\s+quick.*group\s+1\d0/); $out_pkts += $1 if (/^(\d+)\s+pass\s+out\s+quick.*group\s+1\d0/); } print "$in_pkts\n", "$out_pkts\n"; my $uptime = `/usr/bin/uptime`; $uptime =~ /^\s+(\d{1,2}:\d{2}..)\s+up\s+(\d+)\s+(......),/; print "$2 $3\n", "$firewall\n"; mrtg-2.17.10/contrib/ircstats/0000755000175300017510000000000013057016061015141 5ustar oetikeroepmrtg-2.17.10/contrib/ircstats/README0000644000175300017510000000024113057016061016016 0ustar oetikeroepircstats.pl is the simple perl script I use to monitor client loads and such on various EFnet IRC servers. - Matt Ramsey (MR227) mjr@geeks.org, mjr@nin.com mrtg-2.17.10/contrib/ircstats/ircstats.pl0000644000175300017510000000512313057016061017333 0ustar oetikeroep#!/usr/local/bin/perl5 # client.pl v1.5 7 Oct 1997 Matthew Ramsey # http://www.blackened.com/ircstats/ # A simple perl script I use to grab client info on IRC Servers. While # it was designed for connecting to an IRC Server, it can easily be # modified to be used for other purposes. # Special thanks to Chris Behrens and Doug McLaren. use Socket; $DEBUG = 0; if ($ARGV[0]) { $irchost = $ARGV[0] ; } else { print STDERR "Usage: $0 \n" ; exit 1 ; } #$irchost = "irc-e.primenet.com"; $ircport = "6666"; $nick1 = "alskdjf"; $nick2 = "aselkr"; ($locclients, $totclients, $numserv, $numchan) = getinfo($irchost, $ircport); $time = time(); print "$locclients\n"; print "$locclients\n"; print "$time\n"; print ""; exit; # We're done! sub connect_host { local($ip, $port) = @_; ($d1, $d2, $proto) = getprotobyname("tcp"); ($d1, $d2, $d3, $d4, $rawclient) = gethostbyname(`hostname`); ($d1, $d2, $d3, $d4, $rawserver) = gethostbyname($ip); $clientaddr = pack("Sna4x8", 2, 0, $rawclient); $serveraddr = pack("Sna4x8", 2, $port, $rawserver); socket(SOCKET, AF_INET, SOCK_STREAM, $proto) || die "No socket: $!"; bind(SOCKET, $clientaddr); connect(SOCKET, $serveraddr) || die "connect failed: $!"; select(SOCKET); $| = 1; select(STDOUT); } sub getinfo { local($host, $port) = @_; local($lc, $ts, $ns, $nc); $lc = "0"; $ts = "0"; $ns = "0"; $nc = "0"; connect_host($host, $port); print SOCKET "user efnet jskd fksj fkjs fkjsfk jfk\nnick $nick1\nlusers\n"; while() { chomp(); @args = split(' ', "$_"); if (substr($args[0], 0, 1) eq ":") { if ($args[1] eq "433") { print SOCKET "nick $nick2\nlusers\n"; } elsif ($args[1] eq "251") { $tc = $args[5] + $args[8]; $ns = $args[11]; } elsif ($args[1] eq "254") { $nc = $args[3]; } elsif ($args[1] eq "255") { $lc = $args[5]; last; } } } close(SOCKET); return ($lc, $tc, $ns, $nc); } mrtg-2.17.10/contrib/distrib/0000755000175300017510000000000013057016061014745 5ustar oetikeroepmrtg-2.17.10/contrib/distrib/distrib.c0000644000175300017510000004717413057016061016566 0ustar oetikeroep/****************************************************************/ /* */ /* distrib.c (see readme.html for program explanation) */ /* */ /* author : Philippe Simonet, Philippe.Simonet@swiisstelecom.com*/ /* */ /* change log : */ /* */ /* v. 1.00 : initial update (SIP) (23.06.97) */ /* */ /* */ /* */ /************************************************************************/ #include #include #include #include #include #include "gd.h" #include "gdfonts.h" #define FALSE 0 #define TRUE 1 #define TEXT 1 #define RECT 2 #define POLY 3 #define COLOR 4 #define COLORDEF 5 #define LINK 6 #define COMPOUND 7 #define ENDCOMPOUND 8 #define GIFAREA 9 #define URL 10 #define IN 11 #define OUT 12 #define INOUT 13 #define UNKNOWN 99 #ifndef max #define max(a,b) ((a)>(b))?(a):(b) #endif #ifndef min #define min(a,b) ((a)<(b))?(a):(b) #endif int distcount; int xsize, ysize, rounds, rate; int dist[1000][2]; /************************************************************************/ /* analyze command-line options */ static int optind = 0; /* Global argv index. */ static char *scan = NULL; /* Private scan pointer. */ static int scale = 15; int getopt1( int argc, char *argv[], char *optstring, char ** optarg ) { int c; /* return value */ char *place; char *index(); *optarg = NULL; /* check argument validity */ if (scan == NULL || *scan == '\0') { if (optind == 0) optind++; if (optind >= argc) return EOF; place = argv[optind]; if (place[0] != '-' || place[1] == '\0') return EOF; optind++; if (place[1] == '-' && place[2] == '\0') return EOF; scan = place+1; } c = *scan++; /* get option character */ place = strchr(optstring, c); if (place == NULL || c == ':') return '?'; /* set optarg if needed */ if (*++place == ':') { if (*scan != '\0') { *optarg = scan; scan = NULL; } else { *optarg = argv[optind], optind++; } } return c; } /************************************************************************/ void computes_distrib ( FILE * fi, int length, int nb, unsigned int maxbytes ) { int i,j; unsigned long time, in, out, maxin, maxout; for ( i = 0; i < length; i ++ ) { in = 0; out = 0; /* compute mean on 'nb' items */ for (j = 0; j < nb; j ++ ) { unsigned long wi, wo; if (fscanf(fi,"%lu %lu %lu %lu %lu\n",&time,&wi,&wo,&maxin, &maxout) != 5) { printf ( "config file error !!!\n" ); } else { in += wi; out += wo; } } in /= nb; out /= nb; if ( in >= maxbytes ) in = maxbytes-1; if ( out >= maxbytes ) out = maxbytes-1; dist[(( in*distcount)/maxbytes)][0] ++; dist[((out*distcount)/maxbytes)][1] ++; } }; /************************************************************************/ /* in case of trouble ... */ void print_error ( void ) { fprintf ( stderr, "Read mrtg log files and build distribution graphs.\n" ); fprintf ( stderr, "Version 1.1, 27.06.97.\n" ); fprintf ( stderr, "Use : case 1 : (1 distr. log file)\n" ); fprintf ( stderr, " distrib -i logfile -o gfile -w width -h height -t type -r rate -d count\n" ); fprintf ( stderr, " ifile : input log file name,\n" ); fprintf ( stderr, " gfile : output gif file (will be overwritten),\n" ); fprintf ( stderr, " count : histogram count,\n" ); fprintf ( stderr, " rate : line rate,\n" ); fprintf ( stderr, " type : length of measurement (d/w/m/y).\n" ); fprintf ( stderr, "Use : case 2 : (distr. from distrib. file)\n" ); fprintf ( stderr, " distrib -i distrib -o gfile -w width -h height -t x -r top -d count\n" ); fprintf ( stderr, " ifile : input distribution summary file name,\n" ); fprintf ( stderr, " gfile : output gif file (will be overwritten),\n" ); fprintf ( stderr, " top : how may top n,\n" ); fprintf ( stderr, " count : histogram count,\n" ); fprintf ( stderr, " type : 'x'.\n" ); } /************************************************************************/ #define r(color) ((color&0x0000ff)>>0) #define g(color) ((color&0x00ff00)>>8) #define b(color) ((color&0xff0000)>>16) #define rgb(color) ((color&0x0000ff)>>0),((color&0x00ff00)>>8),((color&0xff0000)>>16) /************************************************************************/ /* build a color or find the nearest color in the color table */ int find_color ( gdImagePtr graph, int color ) { int i_col; if ( (i_col = gdImageColorExact(graph,r(color), g(color), b(color))) == -1 ) { if ( (i_col = gdImageColorAllocate(graph,r(color), g(color), b(color))) == -1 ) { i_col = gdImageColorClosest(graph,r(color), g(color), b(color)); } } return (i_col); } /************************************************************************/ /* draw the gif file */ void draw_distrib_gif ( FILE * score, FILE * gif ) { #define c_blank 245,245,245 /* base colors */ #define c_light 194,194,194 #define c_dark 100,100,100 #define c_black 0,0,0 #define c_white 255,255,0 #define c_blue 0,0,255 #define c_red 255,0,0 #define c_green 0,255,0 gdImagePtr graph; int i_light,i_dark,i_blank, i_black, i_white, i_blue, i_red, i_green; int color[4000][2]; graph = gdImageCreate(xsize, ysize); /* the first color allocated will be the background color. */ i_blank = gdImageColorAllocate(graph,c_blank); i_light = gdImageColorAllocate(graph,c_light); i_dark = gdImageColorAllocate(graph,c_dark); gdImageInterlace(graph, 1); i_black = gdImageColorAllocate(graph,c_black); i_white = gdImageColorAllocate(graph,c_white); i_red = gdImageColorAllocate(graph,c_red); i_green = gdImageColorAllocate(graph,c_green); i_blue = gdImageColorAllocate(graph,c_blue); { int i; for (i = 0; i <= distcount; i++ ) { color[distcount - i - 1][0] = gdImageColorAllocate(graph, (255*i)/distcount, 255, (255*i)/distcount); } for (i = 0; i <= distcount; i++ ) { color[distcount - i - 1][1] = gdImageColorAllocate(graph, (255*i)/distcount, (255*i)/distcount, 255); } } /* draw the image border */ gdImageLine(graph,0,0,xsize-1,0,i_light); gdImageLine(graph,1,1,xsize-2,1,i_light); gdImageLine(graph,0,0,0,ysize-1,i_light); gdImageLine(graph,1,1,1,ysize-2,i_light); gdImageLine(graph,xsize-1,0,xsize-1,ysize-1,i_dark); gdImageLine(graph,0,ysize-1,xsize-1,ysize-1,i_dark); gdImageLine(graph,xsize-2,1,xsize-2,ysize-2,i_dark); gdImageLine(graph,1,ysize-2,xsize-2,ysize-2,i_dark); { /* date the graph */ struct tm *newtime; time_t aclock; time( &aclock ); /* Get time in seconds */ newtime = localtime( &aclock ); /* Convert time to struct */ /* tm form */ gdImageString(graph, gdFontSmall,gdFontSmall->w,3,asctime( newtime ),i_dark); }; /*i_col = find_color(graph, colortable[pcurrententry->color]); gdImageFilledRectangle(graph, pcurrententry->coords[0], pcurrententry->coords[1], pcurrententry->coords[2], pcurrententry->coords[3],i_col2); } gdImageString(graph, gdFontSmall, pcurrententry->coords[0], pcurrententry->coords[1], pcurrententry->str, i_col ); gdImageStringUp(graph, gdFontSmall, pcurrententry->coords[0], pcurrententry->coords[1], pcurrententry->str, i_col ); gdImagePtr brush_2pix; brush_2pix = gdImageCreate(2,2); gdImageColorAllocate( brush_2pix, r(colortable[colorratetable[pcurrententry->rate]]), g(colortable[colorratetable[pcurrententry->rate]]), b(colortable[colorratetable[pcurrententry->rate]]) ); gdImageSetBrush(graph, brush_2pix); i_col = gdBrushed; gdImageLine(graph, x, y, x2, y2,i_col); gdImageDestroy(brush_2pix);*/ /* draw axes and graphs */ { int w = gdFontSmall->w, h = gdFontSmall->h, i, j, k, incrx, incry; char str[4000]; int nbaxesx = (rate + 1); int nbaxesy = 6; int textx = 7; int texty = 15; incry = (ysize-(h*2)-(w*texty))/(nbaxesy-1); incrx = (xsize-(w*(textx+2)))/(nbaxesx-1); j = 100; for ( i = h*2; i <= ((h*2) + (incry * (nbaxesy-1))) ; i+= incry ) { gdImageLine(graph,w*textx,i,w*textx + (incrx*(nbaxesx-1)),i,i_black); /* horizontal */ sprintf ( str, "%3u%%", j ); j-= 100/(nbaxesy-1); gdImageString(graph, gdFontSmall,w,i-h/2,str,i_black ); } j = 0; for ( i = w*7; i <= ((w*7) + (incrx * (nbaxesx-1))) ; i+= incrx ) { /*gdImageLine(graph,i,h*2,i,h*2 + (incry*(AXESY-1)),i_black);*/ /* vertical */ /*sprintf ( str, "%3u%%", j ); j+= (100/(AXESX-1)); gdImageStringUp(graph, gdFontSmall, i - w/2, ysize - h, str, i_black );*/ } for ( i = 0; i < rate; i ++ ) { char *name,*ptr; int tin=0, tout=0; int x1, x2, y1, y2, mrgx; if ( fscanf ( score, "%s", str ) == EOF ) break; /*printf ( "%s\n", str );*/ name = str; if ((ptr = strtok( str, ":")) == NULL) continue; /*printf ( "%s:", name );*/ for ( j = 0; j < distcount; j++ ) { dist[j][0] = dist[j][0] = 0; if ((ptr = strtok( NULL, "/,")) == NULL) continue; dist[j][0] = atoi(ptr); tin += dist[j][0]; if ((ptr = strtok( NULL, "/,")) == NULL) continue; dist[j][1] = atoi(ptr); tout += dist[j][1]; /*printf ( "%u/%u,",dist[j][0],dist[j][1] );*/ } /*printf ( "\n" );*/ /* draw label and graphs */ mrgx = incrx/5; x1 = (w*textx) + (i*incrx) + (incrx/2) - (h/2); y1 = ysize-h; gdImageStringUp( graph, gdFontSmall, x1, y1, str, i_black ); for (k = 0; k < 2; k ++ ) { y1 = ysize-((texty-4) * w); if ( k == 0 ) { x1 = (w*textx) + (i*incrx) + mrgx; x2 = x1 + (incrx/3); gdImageStringUp( graph, gdFontSmall, x1, y1, "in", i_black ); } else { x2 = (w*textx) + ((i+1)*incrx) - mrgx; x1 = x2 - (incrx/3); gdImageStringUp( graph, gdFontSmall, x1, y1, "out", i_black ); } y2 = h*2 + (incry*(nbaxesy-1)); for ( j = distcount-1; j >=0 ; j-- ) { y1 = y2 - (((ysize-(h*2)-(w*texty) - 2) * dist[j][k]) / tin); if (j == 0) { /* 'correct' cumulative error */ y1 = h*2; } gdImageFilledRectangle(graph, x1, y1, x2, y2,color[j][k]); gdImageRectangle(graph, x1, y1, x2, y2,i_black); y2 = y1; } } /* int x1, x2, y1, y2, mrgx; mrgx = incrx/5; x1 = (w*7) + (i*incrx) + mrgx; x2 = x1 + (incrx/3); y2 = h*2 + (incry*(AXESY-1)) - 2; y1 = y2 - (((ysize-(h*2)-(w*7) - 2) * dist[i][0]) / rounds); gdImageFilledRectangle(graph, x1, y1, x2, y2,i_green); gdImageRectangle(graph, x1, y1, x2, y2,i_dark); x2 = (w*7) + ((i+1)*incrx) - mrgx; x1 = x2 - (incrx/3); y2 = h*2 + (incry*(AXESY-1)) - 2; y1 = y2 - (((ysize-(h*2)-(w*7) - 2) * dist[i][1]) / rounds); gdImageFilledRectangle(graph, x1, y1, x2, y2,i_blue); gdImageRectangle(graph, x1, y1, x2, y2,i_dark); */ } } gdImageGif(graph, gif); gdImageDestroy(graph); } /************************************************************************/ /* draw the gif file, based on the tentry desciption */ void draw_gif ( FILE * gif ) { #define c_blank 245,245,245 /* base colors */ #define c_light 194,194,194 #define c_dark 100,100,100 #define c_black 0,0,0 #define c_white 255,255,0 #define c_blue 0,0,255 #define c_red 255,0,0 #define c_green 0,255,0 gdImagePtr graph; int i_light,i_dark,i_blank, i_black, i_white, i_blue, i_red, i_green; graph = gdImageCreate(xsize, ysize); /* the first color allocated will be the background color. */ i_blank = gdImageColorAllocate(graph,c_blank); i_light = gdImageColorAllocate(graph,c_light); i_dark = gdImageColorAllocate(graph,c_dark); gdImageInterlace(graph, 1); i_black = gdImageColorAllocate(graph,c_black); i_white = gdImageColorAllocate(graph,c_white); i_red = gdImageColorAllocate(graph,c_red); i_green = gdImageColorAllocate(graph,c_green); i_blue = gdImageColorAllocate(graph,c_blue); /* draw the image border */ gdImageLine(graph,0,0,xsize-1,0,i_light); gdImageLine(graph,1,1,xsize-2,1,i_light); gdImageLine(graph,0,0,0,ysize-1,i_light); gdImageLine(graph,1,1,1,ysize-2,i_light); gdImageLine(graph,xsize-1,0,xsize-1,ysize-1,i_dark); gdImageLine(graph,0,ysize-1,xsize-1,ysize-1,i_dark); gdImageLine(graph,xsize-2,1,xsize-2,ysize-2,i_dark); gdImageLine(graph,1,ysize-2,xsize-2,ysize-2,i_dark); { /* date the graph */ struct tm *newtime; time_t aclock; time( &aclock ); /* Get time in seconds */ newtime = localtime( &aclock ); /* Convert time to struct */ /* tm form */ gdImageString(graph, gdFontSmall,gdFontSmall->w,3,asctime( newtime ),i_dark); }; /*i_col = find_color(graph, colortable[pcurrententry->color]); gdImageFilledRectangle(graph, pcurrententry->coords[0], pcurrententry->coords[1], pcurrententry->coords[2], pcurrententry->coords[3],i_col2); } gdImageString(graph, gdFontSmall, pcurrententry->coords[0], pcurrententry->coords[1], pcurrententry->str, i_col ); gdImageStringUp(graph, gdFontSmall, pcurrententry->coords[0], pcurrententry->coords[1], pcurrententry->str, i_col ); gdImagePtr brush_2pix; brush_2pix = gdImageCreate(2,2); gdImageColorAllocate( brush_2pix, r(colortable[colorratetable[pcurrententry->rate]]), g(colortable[colorratetable[pcurrententry->rate]]), b(colortable[colorratetable[pcurrententry->rate]]) ); gdImageSetBrush(graph, brush_2pix); i_col = gdBrushed; gdImageLine(graph, x, y, x2, y2,i_col); gdImageDestroy(brush_2pix);*/ /* draw axes and graphs */ { int w = gdFontSmall->w, h = gdFontSmall->h, i, j, incrx, incry, maxio; char str[20]; #define AXESX (distcount + 1) #define AXESY 6 maxio = 0; for ( i = 0; i < distcount; i ++ ) { if (maxio < dist[i][0]) maxio = dist[i][0]; if (maxio < dist[i][1]) maxio = dist[i][1]; } incry = (ysize-(h*2)-(w*7))/(AXESY-1); incrx = (xsize-(w*9))/(AXESX-1); j = 100; for ( i = h*2; i <= ((h*2) + (incry * (AXESY-1))) ; i+= incry ) { gdImageLine(graph,w*7,i,w*7 + (incrx*(AXESX-1)),i,i_black); /* horizontal */ sprintf ( str, "%3u%%", j ); j-= 100/(AXESY-1); gdImageString(graph, gdFontSmall,w,i-h/2,str,i_black ); } j = 0; for ( i = w*7; i <= ((w*7) + (incrx * (AXESX-1))) ; i+= incrx ) { gdImageLine(graph,i,h*2,i,h*2 + (incry*(AXESY-1)),i_black); /* vertical */ sprintf ( str, "%3u%%", j ); j+= (100/(AXESX-1)); gdImageStringUp(graph, gdFontSmall, i - w/2, ysize - h, str, i_black ); } for ( i = 0; i < distcount; i ++ ) { int x1, x2, y1, y2, mrgx; mrgx = incrx/5; x1 = (w*7) + (i*incrx) + mrgx; x2 = x1 + (incrx/3); y2 = h*2 + (incry*(AXESY-1)) - 2; y1 = y2 - (((ysize-(h*2)-(w*7) - 2) * dist[i][0]) / rounds); /* printf ( "x1 %u, y1 %u, x2 %u, y2 %u.\n", x1, y1, x2, y2 );*/ gdImageFilledRectangle(graph, x1, y1, x2, y2,i_green); gdImageRectangle(graph, x1, y1, x2, y2,i_dark); x2 = (w*7) + ((i+1)*incrx) - mrgx; x1 = x2 - (incrx/3); y2 = h*2 + (incry*(AXESY-1)) - 2; y1 = y2 - (((ysize-(h*2)-(w*7) - 2) * dist[i][1]) / rounds); /* printf ( "x1 %u, y1 %u, x2 %u, y2 %u.\n", x1, y1, x2, y2 );*/ gdImageFilledRectangle(graph, x1, y1, x2, y2,i_blue); gdImageRectangle(graph, x1, y1, x2, y2,i_dark); } } gdImageGif(graph, gif); gdImageDestroy(graph); } /************************************************************************/ void main ( int argc, char * argv[] ) { FILE *config = NULL, *gif = NULL; char *sconfig = NULL, *sgif = NULL; char *optarg; char type; int i; /* globals */ xsize = 400, ysize = 150; type = 'd'; rate = 1250000; distcount = 10; do { /***************************************************************/ /* 0 : read program arguments */ while ( ( i = getopt1( argc, argv, "o:i:t:w:h:r:d:", &optarg ) ) != EOF ) { switch ( i ) { case 'i': sconfig = optarg; break; case 'o': sgif = optarg; break; case 'w': if ( optarg != NULL ) { xsize = atoi (optarg); } break; case 'r': if ( optarg != NULL ) { rate = atoi (optarg); } break; case 'd': if ( optarg != NULL ) { distcount = atoi (optarg); } break; case 'h': if ( optarg != NULL ) { ysize = atoi (optarg); } break; case 't': if ( optarg != NULL ) type = optarg[0]; if (type != 'd' && type != 'm' && type != 'w' && type != 'y' && type != 'x' ) { print_error(); exit (0); } break; case '?': print_error(); exit (0); break; default: break; } } if ( sgif == NULL || sconfig == NULL ) { print_error(); break; } /***************************************************************/ /* 1 : OPEN FILES */ gif = fopen ( sgif, "wb" ); if ( gif == NULL ) { fprintf ( stderr, "Error opening %s.\n", sgif ); fclose ( config ); break; } config = fopen ( sconfig, "r" ); if ( config == NULL ) { fprintf ( stderr, "Error opening %s.\n", sconfig ); break; } if ( type != 'x' ) { /***************************************************************/ for ( i = 0; i < distcount; i ++ ) { dist[i][0] = 0; dist[i][1] = 0; } { /* read first line ... */ unsigned long time, in, out; fscanf ( config, "%lu %lu %lu\n", &time, &in, &out ); /* read first line */ } switch ( type ) { case 'd': computes_distrib ( config, 288, 1, rate ); rounds = 288; /* 288 * 5' = 24 hours */ break; case 'w': computes_distrib ( config, 100, 6, rate ); /* 600 * 5', with mean on 6 (30')*/ computes_distrib ( config, 236, 1, rate ); rounds = 336; /* 336 * 30' = 7 days */ break; case 'm': computes_distrib ( config, 25, 24, rate ); /* 600 * 5', with mean on 24 (2hours) */ computes_distrib ( config, 150, 4, rate ); /* 600 *30', with mean on 4 */ computes_distrib ( config, 185, 1, rate ); rounds = 360; /* 260 * 2 hours = 30 days */ break; case 'y': computes_distrib ( config, 2,300, rate ); /* 600 * 5', with mean on 300 ~= 1 day */ computes_distrib ( config, 12, 50, rate ); /* 600 *30', with mean on 50 ~= 1 day */ computes_distrib ( config, 50, 12, rate ); /* 600 * 2h, with mean on 12 */ computes_distrib ( config, 300, 1, rate ); rounds = 364; break; } for ( i = 0; i < distcount; i ++ ) { printf ( "%u:%u,%u.\n", i, dist[i][0],dist[i][1] ); } /***************************************************************/ draw_gif ( gif ); /***************************************************************/ fclose ( gif ); fclose ( config ); break; } else { draw_distrib_gif ( config, gif ); fclose ( config ); fclose ( gif ); break; } } while ( TRUE ); } mrtg-2.17.10/contrib/distrib/readme.txt0000644000175300017510000000260213057016061016743 0ustar oetikeroepDistrib for MRTG contribution. Introduction ------------ - 'distrib' read mrtg log files and computes traffic distribution in the time. It ouputs a graph with : usage 1 : distrib -i infile -o giffile -w width -h height -t mode -r rate -d count (width / height in pixels) mode : d(ay), w(eek), m(onth), y(ear) count : how many categories of trafic must be taken - in x the percentage of trafic utilisation (% bandwith) - in y how many times the utilization was reached (% time) usage 2 : distrib -i infile -o giffile -w width -h height -t x -r top -d count (width / height in pixels) this option builds another graph, with more than interface, but the same informations 'stacked' one on the other ... - 'distrib.pl' use distrib to make a complete html ('distrib.html, distrib.gif') file with all target defined in the file mrtg.cfg (!). usage : distrib.pl Installation ------------ - distrib uses the GD library, as mrtg does. In order to compile it, you must have the following files : GDFONTS.H GDFONTS.C MTABLES.C GD.H GD.C and ... distrib.c on unix, gcc distrib.c -I/yourgdinclude -L/yourgdlibrary -lgd -lm -o distrib on a PC with NT or 95, make a project with RDLOG2.C, GD.C, GDFONTS.C All suggestions, bugs reports and others are welcome ... Philippe Simonet, Philippe.Simonet@swisstelecom.com, 24.06.97mrtg-2.17.10/contrib/distrib/distrib.pl0000755000175300017510000000761113057016061016752 0ustar oetikeroep#!/usr/local/bin/perl # version 1.1, 27.06.97, philippe.simonet@swisstelecom.com $outFile = 'distrib.html'; $mode = 'd'; $title = 'Mrtg Trafic Distribution'; $width = 300; $height = 160; $count = 8; $period = 'day'; $refreshInt=120; $refreshSeconds = $refreshInt * 60; $theDate=localtime(time); ########################################################### # read config files $i = 0; open(CFG, "mrtg.cfg") || die "Couldn't read mrtg.cfg"; while () { $_ =~ tr/A-Z/a-z/; if (/^maxbytes\[(.*)\]: (\d*).*/i) { $maxbytes{$1} = $2; #print $maxbytes{$1}; } if (/^pagetop\[(.*)\]: (.*)/i) { $pagetop{$1} = $2; #print $pagetop{$1}, "\n"; } } close (CFG); foreach $i ( keys %pagetop ) { next if ($maxbytes{$i} eq undef); next if ($pagetop{$i} eq undef); for ($j = 0; $j < $count; $j++ ) { $distr{$i}[$j][0] = 0; $distr{$i}[$j][1] = 0; $tot{$i} = 0; } open ( PIPE, "distrib -i $i.log -o $i.dist.$mode.gif -t $mode -w $width -h $height -r $maxbytes{$i} -d $count |" ); while ( ) { if ( /(\d*):(\d*),(\d*).*/ ) { $distr{$i}[$1][0] = $2; $distr{$i}[$1][1] = $3; } } for ($j = 0; $j < $count; $j++ ) { $tot{$i} += ($j+1) * ($distr{$i}[$j][0] + $distr{$i}[$j][1]); } close ( PIPE ); } ########################################################### # open files open(OUT, ">$outFile") || die "Couldn't create $outFile"; open(SCORE, ">distrib.txt") || die "Couldn't create distrib.txt"; ########################################################### # print html head $expTime=&expistr; print OUT < $title

      $title ($theDate)

      These graphs presents the trafic distribution information for last $period, based on data collected each 5 minutes by MRTG.

      They are refreshed each $refreshInt minutes. (green = input traffic, blue = output). Darker is the color, bigger is the trafic. Bigger is the rectangle, bigger is the time when the traffic was effective.

      Top 10 interfaces for last $period

      All trafic distribution for last $period

      Vertical scale: % of time/

      Horizontal scale: % of Maxbyte

      EOF foreach $i ( sort by_number (keys %pagetop) ) { next if ($maxbytes{$i} eq undef); next if ($pagetop{$i} eq undef); print SCORE "$i:"; for ($j=0; $j < ($count-1); $j++) { print SCORE $distr{$i}[$j][0], "/", $distr{$i}[$j][1], ","; } print SCORE $distr{$i}[$count-1][0], "/", $distr{$i}[$count-1][1], "\n"; print OUT < EOF } print OUT < EOF close(OUT); close(SCORE); # computes top 10 lines distribution (-r 10) `distrib -i distrib.txt -o distrib.gif -t x -w 700 -h 300 -d $count -r 10`; exit (0); # expiration time & date ######################################## sub expistr { my ($time) = time+$refreshInt*60+5; my ($wday) = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat')[(gmtime($time))[6]]; my ($month) = ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep', 'Oct','Nov','Dec')[(gmtime($time))[4]]; my ($mday,$year,$hour,$min,$sec) = (gmtime($time))[3,5,2,1,0]; if ($mday<10) {$mday = "0$mday"}; if ($hour<10) {$hour = "0$hour"}; if ($min<10) {$min = "0$min";} if ($sec<10) {$sec = "0$sec";} return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; } # for sorting ######################################## sub by_number { $tot{$b} <=> $tot{$a}; } mrtg-2.17.10/contrib/ascendget/0000755000175300017510000000000013057016061015242 5ustar oetikeroepmrtg-2.17.10/contrib/ascendget/ascendget0000644000175300017510000000245013057016061017123 0ustar oetikeroep#!/bin/csh # You will need to use the included snmpwalk program, which has been # modified from the original version supplied with the SCOTTY Tcl # Extensions for Network Management: # (http://wwwsnmp.cs.utwente.nl/~schoenw/scotty) # If you don't already have TCL, you will need tcl 7.5 too. # # IF YOU DON'T ALREADY HAVE IT, you will also need to download the # ASCEND.MIB file from Ascend's FTP site (ftp.ascend.com) and # autoload it in your tnm-2.1.X/library/init.tcl library file. # # change bank1name to the domain name or IP address of your first Ascend # change bank2name to the domain name or IP address of your second Ascend # change bank1community to the SNMP community string of bank1 # change bank2community to the SNMP community string of bank2 set bank1name="bank1.domain.com" set bank2name="bank2.domain.com" set bank1community="bank1community" set bank2community="bank2community" set MODEMS1=`snmpwalk $bank1name $bank2name mdmLineState|grep -i connect| wc -l` set MODEMS2=`snmpwalk mso2 ism2MARS mdmLineState|grep -i connect| wc -l` set UPTIME=`/usr/local/bin/snmpwalk mso1 ism2MARS system.sysUpTime|cut -c 20-80` set DESCRIP=`/usr/local/bin/snmpwalk mso1 ism2MARS system.sysDescr|cut -c 20-80` set MODEMS=`calc $MODEMS1 + $MODEMS2` echo $MODEMS echo $MODEMS echo $UPTIME echo $DESCRIP mrtg-2.17.10/contrib/cfgmaker_ATM/0000755000175300017510000000000013057016061015565 5ustar oetikeroepmrtg-2.17.10/contrib/cfgmaker_ATM/cfgmaker_atm.pl0000644000175300017510000004310313057016061020543 0ustar oetikeroep#!/usr/drwho/local/bin/perl # -*- mode: Perl -*- ################################################################## # Config file creator ################################################################## # Created by Tobias Oetiker # this produces a config file for one router, by bulling info # off the router via snmp ################################################################# # # Distributed under the GNU copyleft # # $Id: cfgmaker_atm.pl,v 1.1.1.1 2002/02/26 10:16:31 oetiker Exp $ # use SNMP_Session "0.56"; use BER "0.54"; use Socket; use strict; use vars '$DEBUG'; my $DEBUG = 0; %snmpget::OIDS = ( 'sysDescr' => '1.3.6.1.2.1.1.1.0', 'sysContact' => '1.3.6.1.2.1.1.4.0', 'sysName' => '1.3.6.1.2.1.1.5.0', 'sysLocation' => '1.3.6.1.2.1.1.6.0', 'sysUptime' => '1.3.6.1.2.1.1.3.0', 'ifNumber' => '1.3.6.1.2.1.2.1.0', ################################### # add the ifNumber .... 'ifDescr' => '1.3.6.1.2.1.2.2.1.2', 'ifType' => '1.3.6.1.2.1.2.2.1.3', 'ifIndex' => '1.3.6.1.2.1.2.2.1.1', 'ifSpeed' => '1.3.6.1.2.1.2.2.1.5', 'ifOperStatus' => '1.3.6.1.2.1.2.2.1.8', 'ifAdminStatus' => '1.3.6.1.2.1.2.2.1.7', # up 1, down 2, testing 3 'ipAdEntAddr' => '1.3.6.1.2.1.4.20.1.1', 'ipAdEntIfIndex' => '1.3.6.1.2.1.4.20.1.2', 'sysObjectID' => '1.3.6.1.2.1.1.2.0', 'CiscolocIfDescr' => '1.3.6.1.4.1.9.2.2.1.1.28', 'ifAlias' => '1.3.6.1.2.1.31.1.1.1.18', 'ifAtmLecConfigEntry' => '1.3.6.1.4.1.18.3.5.9.5.20.1.1.8', 'ifAtmLecConfigName' => '1.3.6.1.4.1.18.3.5.9.5.20.1.1.3', 'ifAtmVclConfEntry' => '1.3.6.1.4.1.18.3.4.23.1.5.1.22', 'ifAtmVclConf2' => '1.3.6.1.4.1.18.3.4.23.1.5.1.2', 'ifAtmVclConf3' => '1.3.6.1.4.1.18.3.4.23.1.5.1.4', 'ifAtmizerVclStatsEntry' => '1.3.6.1.4.1.18.3.4.23.3.4.1.7', 'ifAtmizerVclStatsEntr1' => '1.3.6.1.4.1.18.3.4.23.3.4.1.1', 'ifAtmizerVclStatsEntr2' => '1.3.6.1.4.1.18.3.4.23.3.4.1.3', ); sub main { my(%ifType_d)=('1'=>'Other', '2'=>'regular1822', '3'=>'hdh1822', '4'=>'ddnX25', '5'=>'rfc877x25', '6'=>'ethernetCsmacd', '7'=>'iso88023Csmacd', '8'=>'iso88024TokenBus', '9'=>'iso88025TokenRing', '10'=>'iso88026Man', '11'=>'starLan', '12'=>'proteon10Mbit', '13'=>'proteon80Mbit', '14'=>'hyperchannel', '15'=>'fddi', '16'=>'lapb', '17'=>'sdlc', '18'=>'ds1', '19'=>'e1', '20'=>'basicISDN', '21'=>'primaryISDN', '22'=>'propPointToPointSerial', '23'=>'ppp', '24'=>'softwareLoopback', '25'=>'eon', '26'=>'ethernet-3Mbit', '27'=>'nsip', '28'=>'slip', '29'=>'ultra', '30'=>'ds3', '31'=>'sip', '32'=>'frame-relay', '33'=>'rs232', '34'=>'para', '35'=>'arcnet', '36'=>'arcnetPlus', '37'=>'atm', '38'=>'miox25', '39'=>'sonet', '40'=>'x25ple', '41'=>'iso88022llc', '42'=>'localTalk', '43'=>'smdsDxi', '44'=>'frameRelayService', '45'=>'v35', '46'=>'hssi', '47'=>'hippi', '48'=>'modem', '49'=>'aal5', '50'=>'sonetPath', '51'=>'sonetVT', '52'=>'smdsIcip', '53'=>'propVirtual', '54'=>'propMultiplexor', '55'=>'100BaseVG' ); my($vendor)=0; if ($ARGV[0] eq '--vendor') { $vendor = 1; shift @ARGV}; my($community,$router) = split /\@/, $ARGV[0]; die <>mrtg.cfg USAGE my($sysDescr,$sysContact,$sysName,$sysLocation,$ifNumber,$sysObjectID) = snmpget($router,$community, 'sysDescr','sysContact','sysName', 'sysLocation', 'ifNumber', 'sysObjectID'); $sysDescr =~ s/\r/
      /g; # Change returns to
      my($cisco_router_sysid) = '1\.3\.6\.1\.4\.1\.9'; my($livingston_router_sysid) = '1\.3\.6\.1\.4\.1\.307'; my($ciscobox) = ($sysObjectID =~ /^$cisco_router_sysid/); my($portmaster) = ($sysObjectID =~ /^$livingston_router_sysid/); print < atm_name 'ifAtmVclConfEntry' my(%ipaddr, %iphost,$index); while (scalar @ipadentif){ $index = shift @ipadentif; $ipaddr{$index} = shift @ipadent; # $iphost{$index} = # gethostbyaddr(pack('C4',split(/\./,$ipaddr{$index})), AF_INET); # if ($iphost{$index} eq ''){ $iphost{$index} = ' '; # } } my(@ifdescr) = snmpgettable($router,$community, 'ifDescr'); print "Got IfDescr\n" if $DEBUG; my(@iftype) = snmpgettable($router,$community, 'ifType'); print "Got IfType\n" if $DEBUG; my(@ifspeed) = snmpgettable($router,$community, 'ifSpeed'); print "Got IfSpeed\n" if $DEBUG; my(@ifadminstatus) = snmpgettable($router,$community, 'ifAdminStatus'); print "Got IfAdminStatus\n" if $DEBUG; my(@ifoperstatus) = snmpgettable($router,$community, 'ifOperStatus'); print "Got IfOperStatus\n" if $DEBUG; my(@ifindex) = snmpgettable($router,$community, 'ifIndex'); print "Got IfIndex\n" if $DEBUG; my(%sifdesc,%siftype,%sifspeed,%sifadminstatus,%sifoperstatus,%sciscodescr); ### May need the cisco IOS version number so we know which oid to use ### to get the cisco description. ### ### - mjd 2/5/98 (Mike Diehn) (mdiehn@mindspring.net) ### my ($cisco_ver, $cisco_descr_oid, @ciscodescr); my (%atmindex, %atmindex2, %atmCir, %atmindex5, $atmindex2); if ( $ciscobox ) { ($cisco_ver) = ($sysDescr =~ m/Version\s+([\d.]+)\(\d+\)\w*?,/o); $cisco_descr_oid = ($cisco_ver ge "11.2") ? "ifAlias" : "CiscolocIfDescr"; } print "Print from ifatmlecname \n" if $DEBUG; while (scalar @ifatmlecName) { $index = shift @ifatmlecName; $sifdesc{$index} = shift @ifatmlec; $siftype{$index} = ''; $sifspeed{$index} = ''; $sifadminstatus{$index} = ''; $sifoperstatus{$index} = ''; my $atm_Index = $index; my $name = "$router.$index"; my $name2 = "$router.$sifdesc{$index}"; print "$sifdesc{$index}: '$sifdesc{$index}'\n" if $DEBUG; print "$index: $atm_Index: $name: $name2: $sifdesc{$index}\n" if $DEBUG; } my $jet2; print " sifdesc \n" if $DEBUG; foreach $jet2 (%sifdesc) { print "$jet2 \n" if $DEBUG; } print "Print from ifatmpvc1 \n" if $DEBUG; while (scalar @ifatmpvc2) { $index = shift @ifatmpvc2; $atmindex{$index} = $index; $atmCir{$index} = shift @ifatmpvc1; my $atm_Index_Base = $index; my $atm_Index = $atmindex{$index}; my $name = $atmCir{$index}; my $atm_index2 = $atmindex2{$index}; print "$index: $atm_Index_Base: $atm_Index: $name: $atm_index2\n" if $DEBUG; print "$index: '$index'\n" if $DEBUG; print "$atmindex{$index}: '$atmindex{$index}'\n" if $DEBUG; print "$atmCir{$index}: '$atmCir{$index}'\n" if $DEBUG; print "$atmindex2{$index}: '$atmindex2{$index}'\n" if $DEBUG; } while (scalar @ifatmVclConf3) { $index = shift @ifatmVclConf3; $atmindex2{$index} = shift @ifatmvcl; } print " atmindex \n" if $DEBUG; foreach $jet2 (%atmindex) { print "$jet2 \n" if $DEBUG; } print " atmCir \n" if $DEBUG; foreach $jet2 (%atmCir) { print "$jet2 \n" if $DEBUG; } print " atmindex2 \n" if $DEBUG; foreach $jet2 (%atmindex2) { print "$jet2 \n" if $DEBUG; } print "Print from ifatmVclconf3 \n" if $DEBUG; while (scalar @ifindex) { # as these arrays get filled from the bottom, # we need to empty them from the botom as well ... # fifo $index = shift @ifindex; $sifdesc{$index} = shift @ifdescr; $siftype{$index} = shift @iftype; $sifspeed{$index} = shift @ifspeed; $sifadminstatus{$index} = shift @ifadminstatus; $sifoperstatus{$index} = shift @ifoperstatus; if ($portmaster && $vendor) { # We can only approximate speeds # # so we think that ppp can do 76800 bit/s, and slip 38400. # (actualy, slip is a bit faster, but usualy users with newer modems # use ppp). Alternatively, you can set async speed to 115200 or # 230400 (the maximum speed supported by portmaster). # # But if the interface is ptpW (sync), max speed is 128000 # change it to your needs. On various Portmasters there are # various numbers of sync interfaces, so modify it. # # The most commonly used PM-2ER has only one sync. # # Paul Makeev (mac@redline.ru) # if ($siftype{$index} eq '23') { if ($sifdesc{$index} eq 'ptpW1') { $sifspeed{$index} = 128000; } else { $sifspeed{$index} = 76800; } } elsif ($siftype{$index} eq '28') { $sifspeed{$index} = 38400; } elsif ($siftype{$index} eq '6') { $sifspeed{$index} = 10000000; } } ### Move this section south so we know what type of ### circuit we're looking at before we retrieve ### the cisco interface alias. ### ### This whole cicso thing should be re-written, but since ### this script doesn't need to run quickly... ### ### - mjd 2/5/98 ### # Get the user configurable interface description entered in the config # if it's a cisco-box # if ($ciscobox && $vendor) { my ($enoid, @descr); $enoid = $snmpget::OIDS{"$cisco_descr_oid"} . "." . $index; if ( $cisco_ver ge "11.2" or $siftype{$index} != '32' ) { ### This is either not a frame-relay sub-interface or ### this router is running IOS 11.2+ and interface ### type won't matter. In either of these cases, it's ### ok to try getting the ifAlias or ciscoLocIfDesc. ### @descr = snmpget($router,$community, $enoid); } else { ### This is a frame-relay sub-interface *and* the router ### is running an IOS older than 11.2. Therefore, we can ### get neither ifAlias nor ciscoLocIfDesc. Do something ### useful. ### @descr = ("Cisco PVCs descriptions require IOS 11.2+."); } # end if else ### Put whatever I got into the array we'll use later to append the result ### of this operation onto the results from the ifDescr fetch. ### push @ciscodescr, shift @descr; } # end if ($cisco_box && $vendor) # especially since cisco does not return a if # descr for each interface it has ... ## JB 2/8/97 - sometimes IOS inserts E1 controllers in the standard-MIB ## interface table, but not in the local interface table. This puts the ## local interface description table out-of-sync. the following ## modification skips over E1 cards as interfaces. # ### I suspect that the mod I made above, to use the ifAlias ### oid if possible, may cause problems here. If it seems ### that your descriptions are out of sync, try commenting ### out the "if ( condition )" and it's closing right brace ### so that the "shift @ciscodescr" get executed for *all* ### iterations of this loop. ### ### - mjd 2/5/95 ### if ($ciscobox && $siftype{$index} != 18) { $sciscodescr{$index} = "
      " . (shift @ciscodescr) if @ciscodescr; } } my $jet; print " atmindex2 \n" if $DEBUG; foreach $jet (%atmindex2) { print "$jet \n" if $DEBUG; } print " sifdesc \n" if $DEBUG; foreach $jet (%sifdesc) { print "$jet \n" if $DEBUG; } print " atmCir \n" if $DEBUG; foreach $jet (%atmCir) { print "$jet \n" if $DEBUG; } print " atmindex \n" if $DEBUG; foreach $jet (%atmindex) { print "$jet \n" if $DEBUG; } print " Possible Targets \n" if $DEBUG; foreach $index ( sort { $atmindex2{$a} <=> $atmindex2{$b} } keys %atmindex2) { my $c; my $index2 = $atmindex2{$index}; # my $name = "$router.$sifdesc{$index2}.$atmindex2{$index}.$index"; my $name = "$router.$index2.$index"; my $target1 = "1.3.6.1.4.1.18.3.4.23.3.4.1.7.$atmCir{$index}.0.$index"; my $target2 = "1.3.6.1.4.1.18.3.4.23.3.4.1.21.$atmCir{$index}.0.$index"; print "$index: $index2: $name: $target1: $target2: \n" if $DEBUG; $c = ''; print <Traffic Analysis for $index2 <- $index $sifdesc{$index2} ${c} $sciscodescr{$index} ${c}
      maxbytes pagetop target URL
      $maxbytes{$i}
      $pagetop{$i} $pc $post
      $i, score $tot{$i}
      ${c} ${c} ${c} ${c} ${c} ${c} ${c}
      System:$sysName in $sysLocation
      Maintainer:$sysContact
      Interface:$sifdesc{$index} ($index)
      IP:$iphost{$index} ($ipaddr{$index})
      Max Speed:19.4MB ($ifType_d{$siftype{$index}})
      ${c} #--------------------------------------------------------------- ECHO } } main; exit(0); sub snmpget{ my($host,$community,@vars) = @_; my(@enoid, $var,$response, $bindings, $binding, $value, $inoid,$outoid, $upoid,$oid,@retvals); my($hackcisco); foreach $var (@vars) { die "Unknown SNMP var $var\n" unless $snmpget::OIDS{$var} || $var =~ /^\d+[\.\d+]*\.\d+$/; if ($var =~ /^\d+[\.\d+]*\.\d+/) { push @enoid, encode_oid((split /\./, $var)); $hackcisco = 1; } else { push @enoid, encode_oid((split /\./, $snmpget::OIDS{$var})); $hackcisco = 0; } } srand(); my $session = SNMP_Session->open ($host , $community, 161); if ($session->get_request_response(@enoid)) { $response = $session->pdu_buffer; ($bindings) = $session->decode_get_response ($response); $session->close (); while ($bindings) { ($binding,$bindings) = decode_sequence ($bindings); ($oid,$value) = decode_by_template ($binding, "%O%@"); my $tempo = pretty_print($value); $tempo=~s/\t/ /g; $tempo=~s/\n/ /g; $tempo=~s/^\s+//; $tempo=~s/\s+$//; push @retvals, $tempo; } return (@retvals); } else { if ($hackcisco) { return (""); } else { die "No answer from $ARGV[0]. You may be using the wrong community\n"; } } } sub snmpgettable{ my($host,$community,$var) = @_; my($next_oid,$enoid,$orig_oid, $response, $bindings, $binding, $value, $inoid,$outoid, $upoid,$oid,@table,$tempo); die "Unknown SNMP var $var\n" unless $snmpget::OIDS{$var}; $orig_oid = encode_oid(split /\./, $snmpget::OIDS{$var}); $enoid=$orig_oid; srand(); my $session = SNMP_Session->open ($host , $community, 161); for(;;) { if ($session->getnext_request_response(($enoid))) { $response = $session->pdu_buffer; ($bindings) = $session->decode_get_response ($response); ($binding,$bindings) = decode_sequence ($bindings); ($next_oid,$value) = decode_by_template ($binding, "%O%@"); # quit once we are outside the table last unless BER::encoded_oid_prefix_p($orig_oid,$next_oid); $tempo = pretty_print($value); print "$var: '$tempo'\n" if $DEBUG; $tempo=~s/\t/ /g; $tempo=~s/\n/ /g; $tempo=~s/^\s+//; $tempo=~s/\s+$//; push @table, $tempo; } else { warn "No sensible answer from $ARGV[0] for $var ... results may be wrong!\n"; last; } $enoid=$next_oid; } $session->close (); return (@table); } sub fmi { my($number) = $_[0]; my(@short); @short = ("Bytes/s","kBytes/s","MBytes/s","GBytes/s"); my $digits=length("".$number); my $divm=0; while ($digits-$divm*3 > 4) { $divm++; } my $divnum = $number/10**($divm*3); return sprintf("%1.1f %s",$divnum,$short[$divm]); } mrtg-2.17.10/contrib/cfgmaker_ATM/README0000644000175300017510000000067013057016061016450 0ustar oetikeroepFrom: Henry Steinhauer Date: Tue, 15 Jun 1999 17:00:07 -0500 This is gutted code from the other CFGmaker_ATM.pl code. This will pull the information from the Bay MIB for the SVC ATM setup and then create a target for each channel in the ATM that is defined. The Targets created can be sorted in the Indexmaker such that the Named ATM channel will have all the Subchannels grouped together. Enjoy. Henry Steinhauer mrtg-2.17.10/contrib/cpuinfo/0000755000175300017510000000000013057016061014750 5ustar oetikeroepmrtg-2.17.10/contrib/cpuinfo/cpuinfo.pl0000755000175300017510000001214013057016061016751 0ustar oetikeroep#!/usr/bin/perl # ============================================================================ # CPU Usage script for mrtg # # File: cpuinfo.pl # Author: Matthew Schumacher | schu@schu.net # Version: 1.3 # # Date: 8/17/2000 # Purpose: This script reports CPU usage for user # and system to mrtg, along with uptime # and the machine's hostname. # # Usage: ./cpuinfo.pl [machine] [os] # # For now [os] can only be "sun" or "linux" # # # Info: Designed on RedHat linux 6.2 with perl # version 5.005_03. The script itself has # only been tested on Linux, however, it # has been tested to connect to, and graph # CPU usage on sun and linux. # # This script requires both sar and rsh to # be installed and working. Because linux # does not come with sar (mine didn't) it # may be necessary to download and install # it. Get sar here: # # ftp://metalab.unc.edu/pub/Linux/system/status/sysstat-3.2.4.tar.gz # # How it works: # # The script uses rsh (or ssh) to run sar on the the # remote machine. Sar samples the cpu time # for both user and system once per second # for 10 seconds. It then reports an average # to the script, which parses out the information # and formats it in a way mrtg can understand. # The script also runs uptime to get the machine's # uptime and passes it to mrtg. # # # [History] # # 1/4/2000 - Added support for different rsh programs. # I also made the default rsh program ssh for security # reasons. # # 3/9/2000 - Removed the default os because it seemed # redundant. Added code to support localhost as a machine # name. # # 8/17/2000 - Updated sar regex for sar command. Sorry # for not keeping up with the email, I had some email # issues then finnaly I got my own domain and changed it # to schu@schu.net. # # ============================================================================ # Sample cfg: # # WorkDir: /home/httpd/html/mrtg # Target[machine]: `/home/mrtg/run/cpuinfo.pl localhost linux` # MaxBytes[machine]: 100 # Options[machine]: gauge, nopercent # Unscaled[machine]: dwym # YLegend[machine]: % of CPU used # ShortLegend[machine]: % # LegendO[machine]:  CPU System: # LegendI[machine]:  CPU User: # Title[machine]: Machine name # PageTop[machine]:

      CPU usage for machine (schu's workstation) #

      # # #
      System:Machine
      # # ============================================================================ # setup local vars my($machine, $os); # ============================================================================ # == Enter your rsh program here here == $rsh = "/usr/local/bin/ssh -x"; # Enter your rsh command here # == You shouldn't need to edit anything below this line == #======================================================== # This checks for options passed cpuinfo.pl from the cmd line if (scalar(@ARGV) < 2) { print("USAGE: cpuinfo.pl {machine} {os}\n"); exit(-1); } if ($ARGV[0] ne '' && $ARGV[0] ne '#') { $machine = $ARGV[0]; } if ($ARGV[1] ne '' && $ARGV[1] ne '#') { $os = $ARGV[1]; } # Validate the os SWITCH: { if ($os =~ /^sun$/){last SWITCH;} if ($os =~ /^linux$/){last SWITCH;} # DEFAULT: Die if we can't figure out what the os is die "Can't figure out which OS the machine is.\n"; } # Execute the appropriate subroutine based on the os &$os; exit(0); #======================================================= # Subroutines: names of subroutines are supported OSs. #======================================================== sub sun { # Run commands if ($machine =~ 'localhost') { $getcpu = `sar -u 1 10 | grep Average`; $getuptime = `uptime`; } else { $getcpu = `$rsh $machine "sar -u 1 10" | grep Average`; $getuptime = `$rsh $machine "uptime"`; } # Parse though getcpu and get data $getcpu =~ /^Average\s+(\d+)\s+(\d+)\s+/; $outputusr = $1; $outputsys = $2; # Print getcpu data for mrtg print $outputusr."\n"; print $outputsys."\n"; # Parse though getuptime and get data $getuptime =~ /^\s+\d{1,2}:\d{2}..\s+up\s+(\d+)\s+(......),/; # Print getuptime data for mrtg print $1." ".$2."\n"; # Print machine name for mrtg print $machine."\n"; } sub linux { # Run commands if ($machine =~ 'localhost') { $getcpu = `/usr/local/bin/sar -u 1 10 | grep Average`; $getuptime = `/usr/bin/uptime`; } else { $getcpu = `$rsh $machine "/usr/local/bin/sar -u 1 10 | grep Average"`; $getuptime = `$rsh $machine "/usr/bin/uptime"`; } # Parse though getcpu and get data $getcpu =~ /^Average:\s+all\s+(\d+)\.\d+\s+\d+\.\d+\s+(\d+)\.\d+\s+\d+\.\d+/; $getcpuusr = $1; $getcpusys = $2; # Print getcpu data for mrtg print $getcpuusr."\n"; print $getcpusys."\n"; # Parse though getuptime and get data $getuptime =~ /^\s+\d{1,2}:\d{2}..\s+up\s+(\d+)\s+(\w+),/; # Print getuptime data for mrtg print $1." ".$2."\n"; # Print machine name for mrtg print $machine."\n"; } exit(0); mrtg-2.17.10/contrib/cpuinfo/README0000644000175300017510000000125413057016061015632 0ustar oetikeroepThis script allows mrtg to monitor cpu usage for both system and user on linux and sun solaris. All of the information you need to set it up, including a sample cfg file is documented in the header of the script itself. If you have any questions, you can email me at schu@schu.net and I'll try to get back to you. Hope it works for you as well as it does for me :) schu PLEASE NOTE THAT I NO LONGER WORK FOR 7X. DO *NOT* SEND EMAIL TO SCHU@7X.COM. THAT ADDRESS IS NOW ALIASED TO THE 7X GENERAL MANAGER. ANY MAIL SENT THERE WILL GO TO THE WRONG PERSON. Apparently 7x is to lame to remove my old address and let the server bounce it. Matthew Schumacher mrtg-2.17.10/contrib/cpuinfo/sample.cfg0000644000175300017510000000063213057016061016713 0ustar oetikeroepTarget[machine]: `./cpuinfo.pl machine os` MaxBytes[machine]: 100 Options[machine]: gauge, nopercent Unscaled[machine]: dwym YLegend[machine]: % of CPU used ShortLegend[machine]: % LegendO[machine]:  CPU System: LegendI[machine]:  CPU User: Title[machine]: Machine name PageTop[machine]:

      CPU usage for Machine name

      System:Machine name
      mrtg-2.17.10/contrib/stfc/0000755000175300017510000000000013057016062014245 5ustar oetikeroepmrtg-2.17.10/contrib/stfc/README0000644000175300017510000000255713057016062015136 0ustar oetikeroep Mihai Claudiu Capatina aka Mick This is a small script that I use on FreeBSD machines running ALTQ This machines acts like a traffic management system and I need to see the traffic for each class ( CBQ ) All you need to change in this script is the path to "altqstat" and the name of the interfaces In my case fxp0 is connected to my LAN and fxp1 is connected to my ISP so...I measure on fxp0 the download and on the fxp1 the upload for each class This script has only one parameter....this is the class number assigned by ALTQ. If you want to use this script I suppose that you already instaled ALTQ In any case do "altqstat -w 0 -c 2 -i your_interface" to see what your class number is...for each class If you want to count packets instead of bytes change the st line of the script instead of $octeti_down and $octeti_up put $pakete_down and $pakete_up You will call this script from mrtg.conf like this : Target[name]: `/your/path/to/my/script/stfc [class_number] - name - can be an ip address or a client name or whatever you want - class_number - explained above... VERY IMPORTANT : always define classes in the same order for upload and download...so they will have the same class number If you need additional information please feel free to mail me...I'll be glad to help you...;-)) Mick mrtg-2.17.10/contrib/stfc/stfc0000755000175300017510000000427713057016062015144 0ustar oetikeroep#!/usr/bin/perl # # Mihai Claudiu Capatina # aka Mick # # This is a small script that I use on FreeBSD machines running ALTQ # This machines acts like a traffic management system and I need to see # the traffic for each class ( CBQ ) # All you need to change in this script is the path to "altqstat" # and the name of the interfaces # In my case fxp0 is connected to my LAN and fxp1 is connected to my ISP # so...I measure on fxp0 the download and on the fxp1 the upload for each class # # This script has only one parameter....this is the class number assigned # by ALTQ. # If you want to use this script I suppose that you already instaled ALTQ # In any case do "altqstat -w 0 -c 2 -i your_interface" to see what your # class number is...for each class # If you want to count packets instead of bytes change the st line of the script# instead of $octeti_down and $octeti_up put $pakete_down and $pakete_up # # You will call this script from mrtg.conf like this : # Target[name]: `/your/path/to/my/script/stfc [class_number] # - name - can be an ip address or a client name or whatever you want # - class_number - explained above... # VERY IMPORTANT : always define classes in the same order for upload and # download...so they will have the same class number # # If you need additional information please feel free to mail me...I'll be glad # to help you...;-)) $numar_clasa = $ARGV[0]; @rezultat_down=`/usr/local/bin/altqstat -w 0 -c 2 -i fxp0`; foreach (@rezultat_down) { $count++; if ( /^Class(\s+)(\d+)(.*)/ ) { if ( $2 == $numar_clasa) { if ($rezultat_down[$count+2] =~ /^(\s+)pkts: (\d+),(\s+)bytes: (\d+)(.*)/) { $pakete_down = $2; $octeti_down = $4; } } } } @rezultat_up=`/usr/local/bin/altqstat -w 0 -c 2 -i fxp1`; foreach (@rezultat_up) { $count1++; if ( /^Class(\s+)(\d+)(.*)/ ) { if ( $2 == $numar_clasa) { if ($rezultat_up[$count1+2] =~ /^(\s+)pkts: (\d+),(\s+)bytes: (\d+)(.*)/) { $pakete_up = $2; $octeti_up = $4; } } } } open(UPTIME,"uptime |cut -b 13-26|"); $upTime=; close(UPTIME); chop $upTime; $host=`/bin/hostname --fqdn`; print("$octeti_down\n$octeti_up\n$upTime\n$host"); mrtg-2.17.10/contrib/exim-stats/0000755000175300017510000000000014130554613015406 5ustar oetikeroepmrtg-2.17.10/contrib/exim-stats/email-totals10000644000175300017510000000042014130554613020001 0ustar oetikeroep#! /bin/sh finger @$1 > /tmp/$1 IN=`grep "Number of messages received so far today:" /tmp/$1 | awk '{print $8}'` OUT=`grep "Number of messages delivered so far today:" /tmp/$1 | awk '{print $8}'` echo $IN echo $OUT date "+%H hours and %M minutes" echo $1-email-totals mrtg-2.17.10/contrib/exim-stats/email-count10000644000175300017510000000107114130554613017626 0ustar oetikeroep#! /bin/sh INFILE=/home/rcsmith/mrtg/aux/$1.infile OUTFILE=/home/rcsmith/mrtg/aux/$1.outfile finger @$1 > /tmp/$1 NEWIN=`grep "Number of messages received so far today:" /tmp/$1 | awk '{print $8}'` NEWOUT=`grep "Number of messages delivered so far today:" /tmp/$1 | awk '{print $8}'` OLDIN=`cat $INFILE` OLDOUT=`cat $OUTFILE` if [ $NEWIN -lt $OLDIN ] ; then IN=$NEWIN OUT=$NEWOUT else IN=`expr $NEWIN - $OLDIN` OUT=`expr $NEWOUT - $OLDOUT` fi echo $IN echo $OUT date "+%H hours and %M minutes" echo $1-email-count echo $NEWIN > $INFILE echo $NEWOUT > $OUTFILE mrtg-2.17.10/contrib/exim-stats/email-queue10000644000175300017510000000024214130554613017621 0ustar oetikeroep#! /bin/sh QUEUELEN=`finger @$1 | grep 'Number of messages currently in the queue:' | awk '{print $8}'` echo $QUEUELEN echo 0 echo sometime echo $1-email-queue mrtg-2.17.10/contrib/exim-stats/check-email0000644000175300017510000000112714130554613017474 0ustar oetikeroep#!/bin/sh #/usr/local/bin/mailq -v echo "Working." LOGFILE=/var/spool/exim/log/mainlog DAY=`date "+19%y-%m-%d"` QUE=`ls /var/spool/exim/input/*-H | wc -l | sed -e "s/ //g"` DAYDEL=`/usr/local/bin/grep -c " [=-]> " $LOGFILE` DAYREC=`/usr/local/bin/grep -c " <= " $LOGFILE` cat << EOM ====================================================================== E-mail status information for `hostname` Current Date/Time is: `date "+%A, %D %R %Z"` Number of messages currently in the queue: $QUE Number of messages received so far today: $DAYREC Number of messages delivered so far today: $DAYDEL EOM mrtg-2.17.10/contrib/exim-stats/email.cfg0000644000175300017510000000512614130554613017162 0ustar oetikeroepWorkDir: /WEB/pages/SNMP/email ### IN ALL CASES YOU WILL WANT TO CHANGE THE PATH TO THE THREE EXECUTABLES FROM ### /home/rcsmith/mrtg/aux/email-totals1 TO WHEREEVER YOU PUT THEM ### ### YOU WILL ALSO NEED TO CHANGE WorkDir UP ABOVE ### Target[MAIL-HOST-email-totals]:`/home/rcsmith/mrtg/aux/email-totals1 MAIL-HOST` Title[MAIL-HOST-email-totals]:MAIL-HOST Electronic Mail Processing Status PageTop[MAIL-HOST-email-totals]:

      MAIL-HOST Electronic Mail Processing Status

      The following graphs represent a running total of the amount of electronic mail MAIL-HOST has processed today. The averages listed on the 5-minute chart are actually the sample times as opposed to a true average.

      MaxBytes[MAIL-HOST-email-totals]:100000 Options[MAIL-HOST-email-totals]:gauge,noinfo XSize[MAIL-HOST-email-totals]:500 YSize[MAIL-HOST-email-totals]:200 WithPeak[MAIL-HOST-email-totals]:dwmy YLegend[MAIL-HOST-email-totals]:No. Of Messages ShortLegend[MAIL-HOST-email-totals]: messages LegendI[MAIL-HOST-email-totals]:  Incoming: LegendO[MAIL-HOST-email-totals]:  Outgoing: Target[MAIL-HOST-email-queue]:`/home/rcsmith/mrtg/aux/email-queue1 MAIL-HOST` Title[MAIL-HOST-email-queue]:MAIL-HOST Electronic Mail Processing Queue PageTop[MAIL-HOST-email-queue]:

      MAIL-HOST Electronic Mail Processing Queue

      The following charts represent the Electronic Mail queue on MAIL-HOST.

      MaxBytes[MAIL-HOST-email-queue]:100000 Options[MAIL-HOST-email-queue]:gauge,noinfo XSize[MAIL-HOST-email-queue]:500 YSize[MAIL-HOST-email-queue]:200 WithPeak[MAIL-HOST-email-queue]:dwmy YLegend[MAIL-HOST-email-queue]:Number Of Messages ShortLegend[MAIL-HOST-email-queue]: msgs LegendI[MAIL-HOST-email-queue]:  Queue: LegendO[MAIL-HOST-email-queue]: Target[MAIL-HOST-email-count]:`/home/rcsmith/mrtg/aux/email-count1 MAIL-HOST` Title[MAIL-HOST-email-count]:MAIL-HOST Electronic Mail Processing Counts PageTop[MAIL-HOST-email-count]:

      MAIL-HOST Electronic Mail Processing Counts

      The following charts represent the amount of electronic mail MAIL-HOST received and delivered.

      MaxBytes[MAIL-HOST-email-count]:5500 Options[MAIL-HOST-email-count]:gauge,noinfo XSize[MAIL-HOST-email-count]:500 YSize[MAIL-HOST-email-count]:200 WithPeak[MAIL-HOST-email-count]:dwmy YLegend[MAIL-HOST-email-count]:Number Of Messages ShortLegend[MAIL-HOST-email-count]: msgs LegendI[MAIL-HOST-email-count]:  Received: LegendO[MAIL-HOST-email-count]:  Delivered: mrtg-2.17.10/contrib/exim-stats/README0000644000175300017510000000575414130554613016301 0ustar oetikeroepHere are the scripts I put together to gather EXIM processing information for MRTG to display. Please excuse the lack of elegance this whole thing has. It was thrown together in about an hour and I haven't had time to go back and make it pretty. There are a couple of ways I can easily think of to make this better. One would be to not use 'finger' for the gathering of information. The other would be to make one call every five minutes and use the output from it for all three items being graphed (rather than three calls every 5 minutes). One of these days I'll get around to incorporating these enhancements... The scripts that are called from MRTG (email-cout1, email-queue1, and email-totals1) get their information by 'fingering' the remote hosts. On the remote hosts, the 'fingerd' process is replaced with the check-email script. This is usually done by replacing the INETD entry on the mail host from something that looks like this: finger stream tcp nowait nobody /usr/sbin/in.fingerd in.fingerd to something that looks like this: finger stream tcp nowait nobody /usr/local/bin/check-email check-email (Note the path is where ever you decide to put the check-email script) Also, the path to GNU grep is hardcoded in the 'check-email' script. I use GNU grep for the counts which is alot faster than the normal system grep's out there. The output of check-email is: Working. ====================================================================== E-mail status information for mercury.csc.com Current Date/Time is: Monday, 01/04/99 07:07 EST Number of messages currently in the queue: 54 Number of messages received so far today: 3465 Number of messages delivered so far today: 3945 END OF OUTPUT Now then for what the scripts do. email-count1 takes the count of messages received and delivered so far today and subtracts the prior values from the current values obtained from 'check-email'. This gives you the number of messages received and delivered in the last five minutes (since MRTG is called every five minutes). email-count1 has two files it tries to read without checking to see if they exist. Yes this is bad. To make it work, create files called 'HOST-NAME.infile' and 'HOST-NAME.outfile' in a directory (see the script) and put just the number 0 in there before you run the scripts. email-queue1 simply takes the queue information from 'check-email' and returns something that MRTG wants. Lastly email-totals1 takes the same count information and does a running total of the amount received and delivered since the last time the log was cleaned (for us that is every day at midnight). The file 'email.cfg' is the MRTG config file for a single host to get all three stats going. If you don't want a particular bit of information, remove the section. You will have to globally replace the TAG 'MAIL-HOST' with the name of the host you want to check. You will also probably want to change the verbage around each bit of information. That is entirely up to you :-) mrtg-2.17.10/doc/cfgmaker.pod0000777000175300017510000000000014171763413017367 2../bin/cfgmakerustar oetikeroepmrtg-2.17.10/doc/indexmaker.pod0000777000175300017510000000000014171763413020307 2../bin/indexmakerustar oetikeroepmrtg-2.17.10/doc/mrtg-contrib.pod0000644000175300017510000000377414171763414015551 0ustar oetikeroep=head1 NAME mrtg-contrib - Contribution Guidelines for MRTG =head1 DESCRIPTION If you have written an extension to mrtg or created a bug fix, please consider contributing it to the project. As I get quite a number of contributions every week, here are a few guidelines which explain how to contribute so that I can use the contribution without too much additional work. =head2 Translations MRTG messages have been translated to a number of languages but there are still many which have not been covered yet. If you want to add yours, go into the F directory and follow the instructions given in the F file. =head2 Patches When you have created your modification or extension to mrtg and want to submit it to me, please crate a patch for the files which you have modified. Do not send entire files unless they are new. To create a patch, get hold of a copy of GNU diff (Many Unix systems will have this installed already. In the NT world you might want to get http://sources.redhat.com/cygwin/ to get all the nice GNU tools available.) and type diff --unified --ignore-space-change old-file new-file > simple.patch or if you have modified several files do diff --recursive --unified --ignore-space-change old-dir/ new-dir/ >long.patch =head2 Documentation All documentation of mrtg is done with the perl B system. If you want to learn about it, type perldoc perlpod and read the instructions. If you have bugfixes or additions to the existing documents, make sure you modify the B files and not the html or txt versions. I take documentation very seriously. Whenever you create a new feature for mrtg which you want to get included in the official release, your patch must also contain modifications for the relevant B file in the F tree or for the documentation sections of F and F. =head1 ADDRESS Send your patches, translations and contributions to Tobias Oetiker Etobi@oetiker.chE =head1 AUTHOR Tobias Oetiker Etobi@oetiker.chE mrtg-2.17.10/doc/mrtg-faq.pod0000644000175300017510000000750714171763414014656 0ustar oetikeroep=head1 NAME mrtg-faq - How to get help if you have problems with MRTG =head1 SYNOPSIS MRTG seems to raise a lot of questions. There are a number of resources apart from the documentation where you can find help for mrtg. =head1 FAQ In the following sections you'll find some additional Frequently Asked Questions, with Answers. =head2 Why is there no "@#$%" (my native language) version of MRTG? Nobody has contributed a F<@#$%.pmd> file yet. Go into the F directory and create your own translation file. When you are happy with it send it to me for inclusion with the next mrtg release. =head2 I need a script to make mrtg work with my xyz device. Probably this has already been done. Check the stuff in the F directory. There is a file called F<00INDEX> in that directory which tells what you can find in there. =head2 How does this SNMP thing work There are many resources on the net that explain SNMP. Take a look at this article from the Linux Journal by David Guerrero http://www.david-guerrero.com/papers/snmp/ And at this rather long document from CISCO. http://www.cisco.com/univercd/cc/td/doc/cisintwk/ito_doc/snmp.htm =head2 The images created by MRTG look very strange. Remove the *-{week,day,month,year}.png files and start MRTG again. Using MRTG for the first time, you might have to do this twice. This will also help when you introduce new routers into the cfg file. =head2 What is my Community Name? Ask the person in charge of your Router or try 'public', as this is the default Community Name. =head2 My graphs show a flat line during an outage. Why ? Well, the short answer is that when an SNMP query goes out and a response doesn't come back, MRTG has to assume something to put in the graph, and by default it assumes that the last answer we got back is probably closer to the truth than zero. This assumption is not perfect (as you have noticed). It's a trade-off that happens to fail during a total outage. If this is an unacceptable trade-off, use the B option. You may want to know what you're trading off, so in the spirit of trade-offs, here's the long answer: The problem is that MRTG doesn't know *why* the data didn't come back, all it knows is that it didn't come back. It has to do something, and it assumes it's a stray lost packet rather than an outage. Why don't we always assume the circuit is down and use zero, which will (we think) be more nearly right? Well, it turns out that you may be taking advantage of MRTG's "assume last" behaviour without being aware of it. MRTG uses SNMP (Simple Network Management Protocol) to collect data, and SNMP uses UDP (User Datagram Protocol) to ship packets around. UDP is connectionless (not guaranteed) unlike TCP where packets are tracked and acknowledged and, if needed, retransmitted. UDP just throws packets at the network and hopes they arrive. Sometimes they don't. One likely cause of lost SNMP data is congestion; another is busy routers. Other possibilities include transient telecommunications problems, router buffer overflows (which may or may not be congestion-related), "dirty lines" (links with high error rates), and acts of God. These things happen all the time; we just don't notice because many interactive services are TCP-based and the lost packets get retransmitted automatically. In the above cases where some SNMP packets are lost but traffic is flowing, assuming zero is the wrong thing to do - you end up with a graph that looks like it's missing teeth whenever the link fills up. MRTG interpolates the lost data to produce a smoother graph which is more accurate in cases of intermittent packet loss. But with V2.8.4 and above, you can use the "unknaszero" option to produce whichever graph is best under the conditions typical for your network. =head1 AUTHOR Tobias Oetiker Etobi@oetiker.chE mrtg-2.17.10/doc/mrtg-forum.pod0000644000175300017510000000624714171763414015237 0ustar oetikeroep=head1 NAME mrtg-forum - Interactive Help for MRTG users =head1 SYNOPSIS There is a lot of written documentation for mrtg, but nevertheless you may have a problem where you can't find the solution. In this case some Human Help may be necessary. With MRTG there are several ways to get Humans to help you. =head1 MAILING-LIST There are three mailing lists for MRTG available. =over =item mrtg for discussion among mrtg users. =item mrtg-announce for announcements regarding new versions of mrtg related software. =item mrtg-developers for discussion among people who write software in connection with mrtg or who hack mrtg itself. =back =head2 THE RULES Please note that the members of the mrtg mailinglist value politeness highly. This means behave in a way you would like others to behave towards you. =over =item * No shouting. (NO CAPS) =item * No rude language =item * No demands. everybody is on the list out of their own free will. If you do not get an answer to your question, chances are high that you did not give sufficient details about the nature of your problem or that the answer to your problem is in the documentation. =item * If you do not follow the rules you will be unsubscribed from the list with no further questions asked. =item * Decisions about your unsubscription from the list will be taken by Alex van den Bogaerdt Paul C. Williamson If you feel that you have been treated unfairly, you may send mail to me and explain the situation. Tobi Oetiker =back =head2 SUBSCRIBING These lists are managed by a mailing-list management program (listar). It allows you to subscribe to these lists by sending a message with the subject: B to the following address: listname-request@lists.oetiker.ch You will then get a message asking you to confirm your subscription. For posting to the lists use the following address listname@lists.oetiker.ch Note that only people who are subscribed to the list can post. Further information about the usage of the mailing lists is available by sending a message with the subject line B to either one of the request addresses. There is also a webinterface to the lists on http://lists.oetiker.ch List archives are on http://www.mail-archive.com/index.php?hunt=mrtg and http://gmane.org/find.php?list=mrtg =head1 NEWSGROUP For discussion of MRTG or related topics on the Usenet, please send your posts to: news:comp.dcom.net-management Many MRTG users are in this forum and will help you. You can also find an archive of past activity from this Newsgroup on: http://groups.google.com/group/comp.dcom.net-management =head1 IRC Channel For discussion of MRTG and related topics on IRC, the `#mrtg' channel on EFNet has been created. More information can be found at http://mrtg.easymac.org =head1 MRTG Japan There is a special Mailinglist for MRTG Users in Japan. It carries translations of the traffic from MRTG-ANNOUNCE as well as updates on the Japanese Translation of the MRTG documentation. Go to http://www.mrtg.jp/ for further Information. =head1 AUTHOR Tobias Oetiker Etobi@oetiker.chE and many contributors mrtg-2.17.10/doc/mrtg-ipv6.pod0000644000175300017510000000633414171763414014770 0ustar oetikeroep=head1 NAME mrtg-ipv6 - IPv6 support in MRTG =head1 OVERVIEW MRTG and cfgmaker support SNMP over IPv6. IPv6 targets can be specified by hostname or IPv6 address, and if the required libraries are present (see below), queries will use IPv6. =head1 USAGE =head2 Enabling IPv6 IPv6 is currently disabled by default and must be explicitly enabled. In MRTG this is done by turning on the B global option in the configuration file. In cfgmaker, it is enabled with the B<--enable-ipv6> command-line option. If IPv6 is disabled, MRTG and cfgmaker should behave in exactly the same way as previous versions. So the addition of IPv6 support should have no effect on existing MRTG setups unless IPv6 is enabled. IPv6 support requires the Socket6 and INET6 libraries (see below). If MRTG can't find them, IPv6 is disabled. =head2 Specifying IPv6 targets IPv6 targets may be specified by name or IPv6 address. Numeric IPv6 addresses may be used with both cfgmaker and MRTG, but they must be enclosed in square brackets. For example, a target could be specified as: public@[2001:760:4::]:161 Hostnames work as expected: first an IPv6 name lookup is tried, then an IPv4 lookup. =head2 Targets that do not support SNMP over IPv6 Many targets (this currently includes all Cisco routers) do not yet support SNMP over IPv6 and must be monitored over IPv4. This can cause problems if you specify a target through its DNS name and the name maps to both the IPv6 address and the IPv4 address of the target: MRTG will only try IPv6, and will fail. To query these targets, use the B per-target option, which tells MRTG not to use SNMP over IPv6 for the target. MRTG does not fall back to IPv4 for performance and correctness reasons. If there are many routers to query, a timeout for every router would make MRTG take too long to query them all. And if, for some reason, IPv6 connectivity to the target is lost, MRTG's error messages can help figure out what is wrong. cfgmaker does fall back from IPv6 to IPv4. If IPv6 is enabled and cfgmaker is given a hostname that resolves to both an IPv6 and an IPv4 address, it first tries to query the target over IPv6. If it receives no answer, it tries again using IPv4. If the target answers, cfgmaker sets the IPv4Only option in the generated config file. =head1 IPv6 LIBRARIES =head2 Libraries required IPv6 support requires the B and B Perl modules. Both can be downloaded from CPAN: http://search.cpan.org/author/UMEMOTO/Socket6/ http://search.cpan.org/author/MONDEJAR/INET6/ If you use Debian, you will need the packages B and B, which are (or should soon be) in unstable. So far, IPv6 support has been tested on Linux only, and only with Socket6 version 0.12. Also note that IPv6 won't work at all if you don't have INET6.pm version 2.00 or newer. =head2 Installing the libraries Building and installing Socket6 and INET6 is very simple. For each module, just unpack the archive and then do: perl Makefile.PL make and then: su make install If you have installed the libraries successfully, cfgmaker and mrtg should automatically detect them and allow IPv6 support to be enabled. =head1 AUTHOR Lorenzo Colitti Elorenzo location colitti.comE mrtg-2.17.10/doc/mrtglib.pod0000777000175300017510000000000014171763413020534 2../lib/mrtg2/MRTG_lib.pmustar oetikeroepmrtg-2.17.10/doc/mrtg-logfile.pod0000644000175300017510000000500114171763414015513 0ustar oetikeroep=head1 NAME mrtg-logfile - description of the mrtg-2 logfile format =head1 SYNOPSIS This document provides a description of the contents of the mrtg-2 logfile. =head1 OVERVIEW The logfile consists of two main sections. =over =item The first Line It stores the traffic counters from the most recent run of mrtg. =item The rest of the File Stores past traffic rate averages and maximum at increasing intervals. =back The first number on each line is a unix time stamp. It represents the number of seconds since 1970. =head1 DETAILS =head2 The first Line The first line has 3 numbers which are: =over =item A (1st column) A timestamp of when MRTG last ran for this interface. The timestamp is the number of non-skip seconds passed since the standard UNIX "epoch" of midnight on 1st of January 1970 GMT. =item B (2nd column) The "incoming bytes counter" value. =item C (3rd column) The "outgoing bytes counter" value. =back =head2 The rest of the File The second and remaining lines of the file contains 5 numbers which are: =over =item A (1st column) The Unix timestamp for the point in time the data on this line is relevant. Note that the interval between timestamps increases as you progress through the file. At first it is 5 minutes and at the end it is one day between two lines. This timestamp may be converted in OpenOffice Calc or MS Excel by using the following formula =(x+y)/86400+DATE(1970;1;1) (instead of ";" it may be that you have to use "," this depends on the context and your locale settings) you can also ask perl to help by typing perl -e 'print scalar localtime(x),"\n"' B is the unix timestamp and B is the offset in seconds from UTC. (Perl knows B). =item B (2nd column) The average incoming transfer rate in bytes per second. This is valid for the time between the A value of the current line and the A value of the previous line. =item C (3rd column) The average outgoing transfer rate in bytes per second since the previous measurement. =item D (4th column) The maximum incoming transfer rate in bytes per second for the current interval. This is calculated from all the updates which have occurred in the current interval. If the current interval is 1 hour, and updates have occurred every 5 minutes, it will be the biggest 5 minute transfer rate seen during the hour. =item E (5th column) The maximum outgoing transfer rate in bytes per second for the current interval. =back =head1 AUTHOR Butch Kemper Ekemper@bihs.netE and Tobias Oetiker Etobi@oetiker.chE mrtg-2.17.10/doc/mrtg-mibhelp.pod0000644000175300017510000001135114171763414015517 0ustar oetikeroep=head1 NAME mrtg-mibhelp - A Table of some interesting OIDs =head1 OVERVIEW This File Contains a collection of interesting MIB Entries ... mrtg knows about their names ... depending on the ASN.1 Syntax you may have to put B into the B parameter. For information about how to create a B parameter which references these MIB entries, please consult mrtg-reference. =head1 MIB LIST =head2 ifOperStatus Descriptor: ifOperStatus Identifier: 1.3.6.1.2.1.2.2.1.8 ASN.1 Syntax: INTEGER Enumeration: up 1, down 2, testing 3 The current operational state of the interface. The testing(3) state indicates that no operational packets can be passed. =head2 ifAdminStatus Descriptor: ifAdminStatus Identifier: 1.3.6.1.2.1.2.2.1.7 ASN.1 Syntax: INTEGER Enumeration: up 1, down 2, testing 3 The current administrative state of the interface. The testing(3) state indicates that no operational packets can be passed. =head2 ifInOctets Descriptor: ifInOctets Identifier: 1.3.6.1.2.1.2.2.1.10 ASN.1 Syntax: Counter32 The total number of octets received on the interface, including framing characters. =head2 ifInUcastPkts Descriptor: ifInUcastPkts Identifier: 1.3.6.1.2.1.2.2.1.11 ASN.1 Syntax: Counter32 The number of subnetwork-unicast packets delivered to a higher-layer protocol. =head2 ifInNUcastPkts Descriptor: ifInNUcastPkts Identifier: 1.3.6.1.2.1.2.2.1.12 ASN.1 Syntax: Counter32 The number of non-unicast (i.e., subnetwork- broadcast or subnetwork-multicast) packets delivered to a higher-layer protocol. =head2 ifInDiscards Descriptor: ifInDiscards Identifier: 1.3.6.1.2.1.2.2.1.13 ASN.1 Syntax: Counter32 The number of inbound packets which were chosen to be discarded even though no errors had been detected to prevent their being deliverable to a higher-layer protocol. One possible reason for discarding such a packet could be to free up buffer space. =head2 ifInErrors Descriptor: ifInErrors Identifier: 1.3.6.1.2.1.2.2.1.14 ASN.1 Syntax: Counter32 The number of inbound packets that contained errors preventing them from being deliverable to a higher-layer protocol. =head2 ifInUnknownProtos Descriptor: ifInUnknownProtos Identifier: 1.3.6.1.2.1.2.2.1.15 ASN.1 Syntax: Counter32 The number of packets received via the interface which were discarded because of an unknown or unsupported protocol. =head2 ifOutOctets Descriptor: ifOutOctets Identifier: 1.3.6.1.2.1.2.2.1.16 ASN.1 Syntax: Counter32 The total number of octets transmitted out of the interface, including framing characters. =head2 ifOutUcastPkts Descriptor: ifOutUcastPkts Identifier: 1.3.6.1.2.1.2.2.1.17 ASN.1 Syntax: Counter32 The total number of packets that higher-level protocols requested be transmitted to a subnetwork-unicast address, including those that were discarded or not sent. =head2 ifOutNUcastPkts Descriptor: ifOutNUcastPkts Identifier: 1.3.6.1.2.1.2.2.1.18 ASN.1 Syntax: Counter32 The total number of packets that higher-level protocols requested be transmitted to a non- unicast (i.e., a subnetwork-broadcast or subnetwork-multicast) address, including those that were discarded or not sent. =head2 ifOutDiscards Descriptor: ifOutDiscards Identifier: 1.3.6.1.2.1.2.2.1.19 ASN.1 Syntax: Counter32 The number of outbound packets which were chosen to be discarded even though no errors had been detected to prevent their being transmitted. One possible reason for discarding such a packet could be to free up buffer space. =head2 ifOutErrors Descriptor: ifOutErrors Identifier: 1.3.6.1.2.1.2.2.1.20 ASN.1 Syntax: Counter32 The number of outbound packets that could not be transmitted because of errors. =head2 ifOutQLen Descriptor: ifOutQLen Identifier: 1.3.6.1.2.1.2.2.1.21 ASN.1 Syntax: Unsigned32 The length of the output packet queue (in packets). =head2 frInOctets From: Simon Ferrett 'frInOctets' => '1.3.6.1.2.1.10.32.2.1.9' 'frOutOctets' => '1.3.6.1.2.1.10.32.2.1.7' which when used in the form: frInOctets.pp.dd&frOutOctets.pp.dd:community@cisco.router where pp is the physical port that the frame relay pvc is defined on and dd is the DLCI of the pvc gets you the in and out octets for just that pvc. =head2 ifAdminHack and ifOperHack The return values of ifAdminStatus and ifOperStatus are not very useful for graphing. Use ifOperHack and ifAdminHack instead. They return 1 for UP and 0 otherwise. Note these are not real MIB entities but mrtg hacks =head2 PseudoZero and PseudoOne will return 0 and 1 respectively Note these are not real MIB entities but mrtg hacks =head1 AUTHOR Tobias Oetiker Etobi@oetiker.chE mrtg-2.17.10/doc/mrtg-nt-guide.pod0000644000175300017510000003277014171763414015623 0ustar oetikeroep=head1 NAME mrtg-nt-guide - The MRTG 2.17.10 Windows Installation Guide =head1 SYNOPSIS Installing MRTG on a Windows box is not quite as "click and point" as some might want it to be. But then again, it is not all that difficult if you follow the instructions below. =head1 PREREQUISITES To get MRTG to work on Windows you need the following: =over =item * A current copy of Perl. For Example ActivePerl 5.8.8 from ActiveState http://www.activestate.com/store/activeperl/download/ =item * The latest version of MRTG from http://oss.oetiker.ch/mrtg/pub. Look for mrtg-2.17.10.zip or better. The archive also contains a precompiled copy of rateup.exe for Win32. =back =head1 INSTALLING I suggest you do the following from the machine that will be running MRTG, which, in this case, is also a web server. All examples are for doing things to a LOCAL machine. =over =item First Unzip MRTG to C:\mrtg-2.17.10 on the Windows machine of your choice. =item Next Install Perl on the same Windows machine. You might want to make sure that the Perl binary directory is listed in your system path. C:\Perl\bin;%SystemRoot%\system32;%SystemRoot%;... You can manually check this by going to [Control Panel]->[System]->[Environment] =back To see if everything is installed properly you can open a Command Shell and go into F. Type: perl mrtg This should give you a friendly error message complaining about the missing MRTG configuration file. Now, you have successfully installed MRTG and Perl. =head1 CONFIGURING MRTG Now it is time to create a configuration for MRTG. But before we begin you need to know a few things. Take an opportunity to gather the following information: =over =item * The IP address or hostname and the SNMP port number, (if non standard), of the device you want to monitor. =item * If you want to monitor something other than bytes in and out, you must also know the SNMPOID of what you want to monitor. =item * Finally you need to know the read-only SNMP community string for your device. If you don't know it, try B, that is the default. =back For the rest of this document we will be using device B<10.10.10.1> ( a CISCO Catalyst 5000) with Community string B. We are interested in monitoring traffic, and the CPU load. Let's begin. The first thing we do in setting up MRTG is making a default config file. Get to a cmd prompt and change to the F directory. Type the following command: perl cfgmaker public@10.10.10.1 --global "WorkDir: c:\www\mrtg" --output mrtg.cfg This creates an initial MRTG config file for you. Note that in this file all interfaces of your router will be stored by number. Unfortunately, these numbers are likely to change whenever you reconfigure your router. In order to work around this you can get F to produce a configuration which is based on Ip numbers, or even Interface Descriptions. Check L If you get an error message complaining about B or B, your community name is probably wrong. Now, let's take a look at the mrtg.cfg file that was created. In Perl, a C<#> is a comment, synonymous with C in DOS. Add the following to the top of the mrtg.cfg file: WorkDir: c:\www\mrtg This is where the web pages are created, usually a web root. ###################################################################### # Description: LCP SUWGB # Contact: Administrator # System Name: LC-Bridge # Location: Here #..................................................................... TargetDevice's IP Address:Interface Number:Community:IP Address Target[10.10.10.1.1]: 1:public@10.10.10.1 This is the interface speed (Default is 10 megabits; for 100Mbit devices use 12500000 and so on...) MaxBytes[10.10.10.1.1]: 1250000 Title[10.10.10.1.1]: LC-Bridge (sample.device): ether0 This section determines how the web page headers will look PageTop[10.10.10.1.1]:

      Traffic Analysis for ether0

      System:LC-Bridge inAndover
      Maintainer:Administrator
      Interface:ether0(1)
      IP:sample.device(10.10.10.1)
      Max Speed: 1250.0 kBytes/s (ethernetCsmacd)
      Target[10.10.10.1.2]: 2:public@10.10.10.1 MaxBytes[10.10.10.1.2]: 1250000 Title[10.10.10.1.2]: LC-Bridge (): ulink0 PageTop[10.10.10.1.2]:

      Traffic Analysis for ulink0

      System:LC-Bridge inAndover
      Maintainer:Administrator
      Interface:ulink0(2)
      IP:()
      Max Speed: 1250.0 kBytes/s (ethernetCsmacd)
      #--------------------------------------------------------------- And that's a very basic MRTG config file. You can run this and see your results by going into the F directory and typing: perl mrtg mrtg.cfg It is normal to get errors for the first two times you run this command. The errors will alert you about the fact that there have not been any log files in existence before. If you take a look at those web pages they are not very exciting (yet). You need to have the MRTG files run every five minutes to produce the desired results. Just run it again after a few minutes. You should now be able to see the first lines in your graphs. =head1 MAKE MRTG RUN ALL THE TIME Starting MRTG by hand every time you want to run it is not going to make you happy I guess. There is a special option you can set in the MRTG configuration file so so that MRTG will not terminate after it was started. Instead it will wait for 5 minutes and then run again. Add the option RunAsDaemon: yes to your mrtg.cfg file and start it with: start /Dc:\mrtg-2.17.10\bin wperl mrtg --logging=eventlog mrtg.cfg If you use B instead of B, no console window will show. MRTG is now running in the background. If it runs into problems it will tell you so over the EventLog. To stop MRTG, open the Task Manager and terminate the B process. If mrtg has anything to tell you these messages can be found in the event log. If you put a shortcut with Target: wperl mrtg --logging=eventlog mrtg.cfg Start in: c:\mrtg-2.17.10\bin into your start-up folder, MRTG will now start whenever you login to your NT box. If you do not want to log into your box just to start MRTG. Have a look at http://www.firedaemon.com/mrtg-howto.html which describes a free tool to start any program as a Service. The pages gives specific instructions for MRTG users. =head1 HOW TO SETUP MRTG AS A WINDOWS SERVICE =head2 Additional Prerequisites =over =item * MRTG must be installed and fully configured on the target system. In the following exercise the assumption is that MRTG is installed under c:\mrtg\ and all the sample files use this location. =item * Microsoft Tools B (Applications as Services Utility) and B (Service Installer) - Those files can be downloaded from Microsoft as a part of Windows 2000 Resource Kit at L. They are also available from other locations such as L, L, etc. Detailed instructions on how to use this package are available at L. In order to follow the steps in this HOW-TO you B obtain both executables. =item * You must have administrative rights on the target system. =back =head2 Preparation Please complete the following steps before starting the installation: =over =item * Copy B and B to c:\mrtg-2.17.10\bin\ (your MRTG bin directory). =item * Create a file called B anywhere on your system and paste the following content into it: Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MRTG\Parameters] "Application"="c:\\perl\\bin\\wperl.exe" "AppParameters"="c:\\mrtg-2.17.10\\bin\\mrtg --logging=eventlog c:\\mrtg-2.17.10\\bin\\mrtg.cfg" "AppDirectory"="c:\\mrtg-2.17.10\\bin\\" =back =head2 Service Installation Once again, assuming that MRTG is already fully installed and configured on the target system under c:\mrtg\ the following steps are necessary to setup MRTG as a service. Using the command prompt go into the temporary directory where you unzipped the package. When there type the following command to create a service named "MRTG" in the Windows Services management console: instsrv MRTG c:\mrtg\bin\srvany.exe Now you need to create the B entries required for the new service. You can do this by either right-clicking on the mrtg.reg file and selecting 'merge' or by running the following command: regedit /s mrtg.reg After setting up the registry entry it is time to point it to your MRTG installation. If you have installed MRTG under F, you can skip this step. Open your registry editor (Start -E Run -E regedt32), and locate the B<[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MRTG]> key. Make sure that the B variable is correctly pointing to B located in your MRTG bin directory (for example c:\mrtg\bin\srvany.exe). Next you have to expand the MRTG tree, and go to the B<[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MRTG\Parameters]> key. Under Parameters make sure that all the B variables are setup properly. At this point you are ready to run the service. The only thing left to do is to start the MRTG service in the Services management console. After you do this, you should see two new processes running on your system: srvany.exe and wperl.exe. Make sure to stop any previously running MRTG processes to avoid conflict. Note that it is imperative to set the B option or the service will stop after just one single run! =head1 EXAMPLE Now lets look at a config file to monitor what we wanted to on our mythical Cisco Cat 5000 -- utilization on ports 3, 5, 10, and 24, and the CPU Load, which will show us nonstandard mrtg configurations as well as more options.. WorkDir: c:\www\mrtg RunAsDaemon: yes ###################################################################### # Description: LCP SUWGB # Contact: Administrator # System Name: LC-Bridge # Location: Here #..................................................................... Target[10.10.10.1.1]: 3:public@10.10.10.1 MaxBytes[10.10.10.1.1]: 1250000 Title[10.10.10.1.1]: LC-Bridge (sample-device): ether0 PageTop[10.10.10.1.1]:

      Traffic Analysis for ether0

      System:LC-Bridge inAndover
      Maintainer:Administrator
      Interface:ether0(3)
      IP:sample-device(10.10.10.1)
      Max Speed: 1250.0 kBytes/s (ethernetCsmacd)
      #--------------------------------------------------------------- Target[10.10.10.1.2]: 5:public@10.10.10.1 MaxBytes[10.10.10.1.2]: 1250000 Title[10.10.10.1.2]: LC-Bridge (): ulink0 PageTop[10.10.10.1.2]:

      Traffic Analysis for ulink0

      System:LC-Bridge inAndover
      Maintainer:Administrator
      Interface:ulink0(5)
      IP:()
      Max Speed: 1250.0 kBytes/s (ethernetCsmacd)
      #--------------------------------------------------------------- Target[10.10.10.1.1]: 10:public@10.10.10.1 MaxBytes[10.10.10.1.1]: 1250000 Title[10.10.10.1.1]: LC-Bridge (sample-device): ether0 PageTop[10.10.10.1.1]:

      Traffic Analysis for ether0

      System:LC-Bridge inAndover
      Maintainer:Administrator
      Interface:ether0(10)
      IP:sample-device(10.10.10.1)
      Max Speed: 1250.0 kBytes/s (ethernetCsmacd)
      #--------------------------------------------------------------- Target[10.10.10.1.2]: 24:public@10.10.10.1 MaxBytes[10.10.10.1.2]: 1250000 Title[10.10.10.1.2]: LC-Bridge (): ulink0 PageTop[10.10.10.1.2]:

      Traffic Analysis for ulink0

      System:LC-Bridge inAndover
      Maintainer:Administrator
      Interface:ulink0(24)
      IP:()
      Max Speed: 1250.0 kBytes/s (ethernetCsmacd)
      #--------------------------------------------------------------- # Router CPU load % Target[cpu.1]:1.3.6.1.4.1.9.2.1.58.0&1.3.6.1.4.1.9.2.1.58.0:public@10.10.10.1 RouterUptime[cpu.1]: public@10.10.10.1 MaxBytes[cpu.1]: 100 Title[cpu.1]: CPU LOAD PageTop[cpu.1]:

      CPU Load %

      Unscaled[cpu.1]: ymwd ShortLegend[cpu.1]: % XSize[cpu.1]: 380 YSize[cpu.1]: 100 YLegend[cpu.1]: CPU Utilization Legend1[cpu.1]: CPU Utilization in % (Load) Legend2[cpu.1]: CPU Utilization in % (Load) Legend3[cpu.1]: Legend4[cpu.1]: LegendI[cpu.1]: LegendO[cpu.1]:  Usage Options[cpu.1]: gauge This is a nice example of how to monitor any SNMP device if you know what OID you want to use. Once again, for an explanation of the more advance features of mrtg, please see the rest of the documentation. =head1 AUTHORS Tobi Oetiker Etobi@oetiker.chE, David S. Divins Eddivins@moon.jic.comE, Steve Pierce EMRTG@HDL.comE, Artyom Adjemov Eone.bofh@gmail.comE, Ilja Ivanov Eivanov@bseu.byE Karel Fajkus Ehttp://fajkus.cz/E mrtg-2.17.10/doc/mrtg-nw-guide.pod0000644000175300017510000003132714171763414015623 0ustar oetikeroep=head1 NAME mrtg-nw-guide - MRTG for NetWare =head1 SYNOPSIS This guide is intended to aid in the installation and configuration of MRTG on a NetWare server. =head1 OVERVIEW MRTG is a relative newcomer to the NetWare platform. Earlier versions of NetWare could not run MRTG natively for several reasons: =over =item * Absence of NetWare OS support in the MRTG package. =item * A NetWare server commandline length limitation. =item * Absence of the Rateup executable (Rateup.nlm). =item * A standard installation method. =item * Problems with NetWare's implementation of Perl. =back Support for the NetWare OS has now been fully added into MRTG, beginning with MRTG release 2.12.2. Liberally minded operating systems support a commandline length approaching 1000 characters. In such environments it was an easy matter to pass the sometimes high number of parameters used by MRTG's Rateup executable directly on the commandline. Until NetWare 6.5, NetWare had a commandline limit of 512 characters. This limitation was also removed for NetWare 6.0 by Service Pack 5. For other NetWare versions and earlier Service Packs, this limitation remains. To permit a 'standard' interface for NetWare, the Rateup executable has been modified to also read its parameters from a file, and the MRTG script has been modified to support this method on a NetWare platform. (See New Rateup Switch) A Rateup NLM is now available, along with the necessary scripts to build it if required. See the NetWare Support section of this document for further details. Additionally, mrtg.pl has been revised because of the unique (to NetWare) name of executables (NLM). The absence of a specific installation procedure has caused MRTG to fail in the past because the Perl script could not find or load the Rateup executable. The installation method supplied here will solve this problem for now. The MRTG.pl script in the 2.12.2 (or later) version of MRTG has been configured to suit all likely versions of NetWare able to use Perl5, and bypasses all of the known problems with NetWare Perl running MRTG. =head1 PREREQUISITES You will need the following: =over =item * Perl 5.8.0 for NetWare with latest Perl Updates (February, 2005 or later; previous versions MAY work) =item * NetWare 5.1 w/ SP8, NetWare 6.0 w/ SP5 or NetWare 6.5 w/ SP2. =item * A copy of the MRTG Package (v2.12.2 at time of writing) =item * Three .ncf files to execute the Perl scripts at the NetWare server console. =item * A copy of the Rateup NLM (Pre-built or compiled) =item * Optionally, any NetWare supported Web Server (Netscape, Apache 1.3 or 2.0) =back For copies of the .ncf files and Rateup NLM, see NetWare Support in this document. =head1 INSTALLING MRTG =over =item 1. Install the latest Perl 5.8.x release on your server. See the Perl documentation for details. =item 2. Create the following directories: SYS:/Mrtg SYS:/Mrtg/bin SYS:/Mrtg/contrib (Optional for this document) SYS:/Mrtg/doc (Optional for this document) SYS:/Mrtg/html SYS:/Mrtg/html/images SYS:/Mrtg/html/work SYS:/Mrtg/lib SYS:/Mrtg/logs SYS:/Mrtg/translate =item 3. Copy from the MRTG package the following files: \bin\* to SYS:/Mrtg/bin All files. See Note 1. Note 1: Add a .pl extension to the mrtg, cfgmaker and indexmaker files. The rateup.exe will NOT be needed on the NetWare server. \contrib\* to SYS:/Mrtg/contrib/ Include sub-directories \doc\* to SYS:/Mrtg/doc/ All files \images\* to SYS:/Mrtg/html/images/ All files \translate\* to SYS:/Mrtg/translate/ All files. See Note 2. Note 2: For English-only language support, all \translate files EXCEPT Locales_mrtg may be deleted. \lib\* to SYS:/Mrtg/lib Include sub-directories. See Note 3. Note 3: This will create the SYS:/Mrtg/lib/mrtg2 and ./pod directories. =item 4. Create copies of the three .ncf files and install them: *.ncf to SYS:/Mrtg/bin See NetWare Support in this document for details on how to create copies of these files. =item 5. See Compiling Rateup.nlm"> in this document for details on compiling the Rateup NLM yourself if desired. A prebuit verion is available in the .\mrtg\bin directory where it must remain. =back =head1 CONFIGURING MRTG =over =item * Refer to Novell documentation on configuring and loading SNMP support on your server if this is the device to be monitored. =item * Edit sys:/mrtg/bin/MakeMrtgCfg.ncf: replace ccccc with the GET community name for the SNMP device (typically 'public'), replace ddddd with the DNS name or IP address of the device to be monitored. e.g public@www.myserver.com, public@10.202.65.180 Note 1: These are NOT mail addresses, they just look like one! Note 2: If multiple devices are to be monitored, add their entries to the same line: e.g perl cfgmaker.pl public@www.myserver.com public@10.202.65.180 > sys:/mrtg/bin/mrtg.cfg In this "Getting Started", it is 'suggested' to only monitor a single device. =item * At the server console, run: sys:/mrtg/bin/MakeMrtgCfg.ncf This will create Mrtg.cfg in sys:/mrtg/bin. =item * Edit the Mrtg.cfg configuration file created in the previous step. Note the following: It was found, when testing MRTG on a NetWare 6.5 server using a NIC Interface, that mrtg.cfg contained the following message: ### Interface 1 >> Descr: 'Intel(R)-8255x-based-Network-Connection'... ### The following interface is commented out because: ### * has a speed of 0 which makes no sense # ... If this occurs, edit MakeMrtgCfg.ncf and add the following parameter as shown: perl sys:\mrtg\bin\cfgmaker.pl --zero-speed=nnn public@10.202.65.180 > sys:\mrtg\bin\Mrtg.cfg where B is the interface speed in bits per second. For a 100 Megabit LAN NIC, nnn = 10000000. It will be necessary to re-execute the MakeMrtgCfg.ncf script before continuing with this section. Below line 16 (*** Global Defaults), add: HtmlDir: e.g HtmlDir: sys:/mrtg/html ImageDir: e.g ImageDir: sys:/mrtg/html/work LogDir: e.g LogDir: sys:/mrtg/logs IconDir: e.g IconDir: ./images Note 1. The HtmlDir entry specifies where MRTG will create its HTML pages. Note 2. The ImageDir entry specifies where the created graphic icons are placed. Note 3. The IconDir entry specifies where the supplied MRTG icons are located. It MUST be a relative path from HtmlDir or absolute URL. The value shown is recommended. =item * At the server console run: sys:/mrtg/bin/RunMrtg.ncf several times. By the third time it should run without showing error messages on the console screen. This should create. - A HTML page in the (HtmlDir) directory for each monitored device, - A .dat file in the (ImageDir) directory for each monitored device, - Several .png icons in the (ImageDir) directory, - Some log file entries in the (LogDir) directory. Note: If you experience a "Use of uninitialised value in split" error, it will be necessary to create a 'Path' environment variable at the server console; use the following example env path="SYS:\" (The actual value is immaterial, as long as the var itself exists.) =item * Edit sys:/mrtg/bin/MakeMrtgIndex.ncf. Change the indicated EpathE shown in the following example to match the value entered for (HtmlDir). perl --noscreen sys:/mrtg/bin/indexmaker.pl sys:/mrtg/bin/Mrtg.cfg > /index.html =item * Create an index.html page linking the separate device HTML page(s). At the server console, run: sys:/mrtg/bin/MakeMrtgIndex.ncf This will create index.html in the (HtmlDir) directory. =item * Optionally, configure a Web Server to permit access to the directory specified in (HtmlDir) to view the MRTG graphs remotely, at, for example: http://ip_or_dns/mrtg/index.html A sample configuration for an Apache Webserver is shown: Alias /mrtg/ "SYS:/mrtg/html/" AllowOverride None Order allow,deny Allow from all =item * Set the property of the directory pointed to by (ImageDir), to 'Purge Immediate'. =item * Finally, read the MRTG documentation for much more detailed configuration/usage information. =back Welcome to MRTG!! =head1 MAKE MRTG RUN ALL THE TIME MRTG can be made to run periodically by at least two means: =over =item * Using CRON Scheduling =item * Running MRTG in Daemon Mode =back =head2 CRON Scheduling To use CRON scheduling, create a CRON Scheduler entry to execute the RunMrtg.ncf file on a frequency appropriate for the server environment and information desired. The following entry in the sys:\etc\crontab file will execute MRTG every five minutes: 0,5,10,15,20,25,30,35,40,45,50,55 * * * * sys:\mrtg\bin\runmrtg.ncf The CRON Scheduler (cron.nlm) can be started automatically by adding it in AUTOEXEC.ncf or, manually loading it at the server console. =head2 MRTG in Daemon Mode Refer to the MRTG-Reference document for information about the 'RunAsDaemon' option. Its use is outside the scope of this document. =head1 TROUBLESHOOTING Read the MRTG documents, Perl documents or, finally, submit questions to the MRTG User forums. For NetWare specific issues, submit questions to the Perl forum at news://developer-forums.novell.com/novell.devsup.perl (Novell Developer Forums). =head1 COMPILING RATEUP.NLM In addition to the rateup.c and Makefile.Netware supplied with the MRTG release, you will also need: =over =item * Metrowerks CodeWarrior with NetWare Support OR GCC Compiler (v3.0.3 or later) with NlmConv Utility =item * Novell LibC NDK (February 2004 or later) =item * GD Graphics Library (v2.0.33 or later) =item * LibPNG Graphics Library (v1.2.8 or later) =item * ZLib Library (v1.2.3 or later) =item * The get_ver.awk script =item * A copy of the GNU build tools. (See http://sourceforge.net/projects/gnuwin32/) =back The auxiliary libraries can be obtained from: GD Graphics Library. (See http://www.boutell.com/gd/ ) PNG Graphics Library. (See http://libpng.sourceforge.net/ ) zLib Compression Library. (See http://www.gzip.org/zlib/ ) Edit the Makefile.Netware file as required to match your installation paths; search the file for the key word 'Edit'. =head1 NETWARE SUPPORT For copies of the NCF and get_ver.awk scripts, see Appendix. For NetWare specific issues, submit questions to the Perl forum at news://developer-forums.novell.com/novell.devsup.perl (Novell Developer Forums). To move the MRTG application to a volume other than SYS: you will need to edit the NCF scripts provided plus the MRTG[.pl] script itself in two places. =head1 NEW RATEUP SWITCH The MRTG[.pl] script, when used on a NetWare platform, uses Rateup[.nlm] with the new commandline switch: RATEUP -f filename where the filename parameter can include a leading path element. The file format is exactly the same as that used on the commandline by other operating systems, including the leading path and name of the Rateup NLM. =head1 APPENDIX The Appendix includes 'copies' of the following files: =over =item * The NCF files used during MRTG configuration, =back To create copies of these files, simply 'cut and paste' into your favourite 'B' and save under their respective names. You should remove the leading space from each line. =head3 MakeMrtgCfg.NCF # MakeMrtgCfg.NCF # Purpose : Create the MRTG Configuration File # Changed : 5/05/2005 New # Located : SYS:MRTG\BIN # Set For : # Params : # Edit this file and: # Replace ccccc with your device GET SNMP Community Name - If unsure try 'public'. # Replace ddddd with your device IP (n.n.n.n) or domain name. perl --noscreen sys:\mrtg\bin\cfgmaker.pl ccccc@ddddd > sys:\mrtg\bin\Mrtg.cfg # # End of MakeMrtgCfg.NCF =head3 RunMrtg.NCF # RunMrtg.NCF # Purpose : Run the MRTG Application # Changed : 5/05/2005 New # Located : SYS:MRTG\BIN # Set For : # Params : # The paths are as per the examples recommended in "Getting Started". perl --noscreen sys:\mrtg\bin\mrtg.pl sys:\mrtg\bin\mrtg.cfg # # End of RunMrtg.NCF =head3 MakeMrtgIndex.NCF # MakeMrtgIndex.NCF # Purpose : Create the HTML Index File for MRTG HTML data pages # Changed : 5/05/2005 New # Located : SYS:MRTG\BIN # Set For : # Params : # Note: Edit this file and change the redirected output to the location # specified for HtmlDir or WorkDir. The sys:\apache2\htdocs\mrtg\index.html # is based on the examples in "Getting Started". perl --noscreen sys:\mrtg\bin\indexmaker.pl sys:\mrtg\bin\Mrtg.cfg > sys:\mrtg\html\index.html # # End of MakeMrtgIndex.NCF =head1 LICENSE GNU General Public License =head1 CREDITS The MRTG for NetWare exists largely through the efforts of Guenter Knauf and feedback from beta testers. =head1 AUTHOR Norm W.. =cut mrtg-2.17.10/doc/mrtg.pod0000644000175300017510000001565514171763414014114 0ustar oetikeroep=head1 NAME mrtg - What is MRTG ? =head1 DESCRIPTION The Multi Router Traffic Grapher (MRTG) is a tool to monitor the traffic load on network links. MRTG generates HTML pages containing PNG images which provide a LIVE visual representation of this traffic. Go to http://oss.oetiker.ch/mrtg for all the details about mrtg. =head1 HIGHLIGHTS =over =item Portable MRTG works on most UNIX platforms and Windows NT. =item Perl MRTG is written in Perl and comes with full source. =item Portable SNMP MRTG Uses a highly portable SNMP implementation written entirely in Perl (thanks to Simon Leinen). There is no need to install any external SNMP package. =item SNMPv2c support MRTG can read the new SNMPv2c 64bit counters. No more counter wrapping. =item Reliable Interface Identification Router interfaces can be identified by IP address, description and ethernet address in addition to the normal interface number. =item Constant size Logfiles MRTG's logfiles do NOT grow thanks to the use of a unique data consolidation algorithm. =item Automatic Configuration MRTG comes with a set of configuration tools which make configuration and setup very simple. =item Performance Time critical routines are written in C (thanks to the initiative of Dave Rand my Co-Author). =item GIF free Graphics Graphics are generated directly in PNG format using the GD library by Thomas Boutell. =item Customizability The look of the webpages produced by MRTG is highly configurable. =item RRDtool MRTG has built-in hooks for using RRDtool. If you are strapped for performance this may help. =back =head1 DETAILS MRTG consists of a Perl script which uses SNMP to read the traffic counters of your routers and a fast C program which logs the traffic data and creates beautiful graphs representing the traffic on the monitored network connection. These graphs are embedded into webpages which can be viewed from any modern Web-browser. In addition to a detailed daily view, MRTG also creates visual representations of the traffic seen during the last seven days, the last five weeks and the last twelve months. This is possible because MRTG keeps a log of all the data it has pulled from the router. This log is automatically consolidated so that it does not grow over time, but still contains all the relevant data for all the traffic seen over the last two years. This is all performed in an efficient manner. Therefore you can monitor 200 or more network links from any halfway decent UNIX box. MRTG is not limited to monitoring traffic, though. It is possible to monitor any SNMP variable you choose. You can even use an external program to gather the data which should be monitored via MRTG. People are using MRTG, to monitor things such as System Load, Login Sessions, Modem availability and more. MRTG even allows you to accumulate two or more data sources into a single graph. =head1 HISTORY In 1994 I was working at a site where we had one 64kbit line to the outside world. Obviously, everybody was interested in knowing how the link was performing. So I wrote a quick hack which created a constantly updated graph on the web that showed the traffic load on our Internet link. This eventually evolved into a rather configurable Perl script called MRTG-1.0 which I released in spring 1995. After a few updates, I left my job at DMU to start work at the Swiss Federal Institute of Technology. Due to lack of time I had to put MRTG aside. One day in January of 1996, I received email from Dave Rand asking if I had any ideas why MRTG was so slow. Actually, I did. MRTG's programming was not very efficient and it was written entirely in Perl. After a week or so, Dave wrote back to me and said he had tried what I had suggested for improving MRTG's speed. Since the changes did not help much, he had decided to rewrite the time-critical sections of MRTG in C. The code was attached to his email. His tool increased the speed of MRTG by a factor of 40! This got me out of my 'MRTG ignorance' and I started to spend my spare time developing of MRTG-2. Soon after MRTG-2 development had begun I started to give beta copies to interested parties. In return I got many feature patches, a lot of user feedback and bug fixes. The product you are getting now wouldn't be in this state if it hadn't been for the great contributions and support I received from of many people. I would like to take this opportunity to thank them all. (See the files CHANGES for a long list of folk people who helped to make MRTG what it is today.) =head1 Command-line Mrtg is also the name of the script you have to run to poll data and generate the graphs. Most configuration is set through the configuration file; some command-line options exist all the same. =over =item B<--user> I and B<--group> I Run as the given user and/or group. (Unix Only) =item B<--lock-file> I Use an alternate lock-file (the default is to use the configuration-file appended with C<_l>). =item B<--confcache-file> I Use an alternate confcache-file (the default is to use the configuration-file appended with C<.ok>) =item B<--logging> I|B If this is set to writable filename, all output from mrtg (warnings, debug messages, errors) will go to I. If you are running on Win32 you can specify B instead of a filename which will send all error to the windows event log. BNote, there is no Message DLL for mrtg. This has the side effect that the windows event logger will display a nice message with every entry in the event log, complaining about the fact that mrtg has no message dll. If any of the Windows folks want to contribute one, they are welcome. =item B<--daemon> Put MRTG into the background, running as a daemon. This works the same way as the config file option, but the switch is required for proper FHS operation (because /var/run is writable only by root) =item B<--fhs> Configure all mrtg paths to conform to the FHS specification L. The following default values are assumed: confcachefile - /var/lib/mrtg/mrtg.ok pid-file - /run/mrtg/mrtg.pid lock-file - /var/lock/mrtg/mrtg.lck log-file - /var/log/mrtg/mrtg.log =item B<--check> Only check the cfg file for errors. Do not do anything. =item B<--pid-file=s> Define the name and path of the pid file for mrtg running as a daemon =item B<--log-only> Only update the logfile, do not produce graphics or html pages =item B<--debug=s> Enable debug options. The argument of the debug option is a comma separated list of debug values: cfg - watch the config file reading dir - directory mangeling base - basic program flow tarp - target parser snpo - snmp polling fork - forking view time - some timing info log - logging of data via rateup or rrdtool Example: --debug="cfg,snpo" =back =head1 READ ON Learn more about MRTG by going to the mrtg home page on: http://oss.oetiker.ch/mrtg =head1 AUTHOR Tobias Oetiker Etobi@oetiker.chE and many contributors mrtg-2.17.10/doc/mrtg-reference.pod0000644000175300017510000021147614171763414016047 0ustar oetikeroep=head1 NAME mrtg-reference - MRTG 2.17.10 configuration reference =head1 OVERVIEW The runtime behaviour of MRTG is governed by a configuration file. Run-of-the-mill configuration files can be generated with B. (Check L). But for more elaborate configurations some hand-tuning is required. This document describes all the configuration options understood by the mrtg software. =head1 SYNTAX MRTG configuration file syntax follows some simple rules: =over =item * Keywords must start at the beginning of a line. =item * Lines which follow a keyword line which start with a blank are appended to the keyword line =item * Empty Lines are ignored =item * Lines starting with a # sign are comments. =item * You can add other files into the configuration file using B I Example: Include: base-options.inc If included files are specified with relative paths, both the current working directory and the directory containing the main config file will be searched for the files. The current working directory will be searched first. If the included filename contains an asterisk, then this is taken as a wildcard for zero or more characters, and all matching files are included. Thus, you can use this statement to include all files in a specified subdirectory. Example: Include: servers/*.cfg In this case, you should be very careful that your wildcard pattern does not find a match relative to the current working directory if you mean it to be relative to the main config file directory, since the working directory is checked for a match first (as with a normal Include directive). Therefore, use of something like '*/*' is discouraged. =back =head1 GLOBAL KEYWORDS =head2 WorkDir WorkDir specifies where the logfiles and the webpages should be created. Example: WorkDir: /usr/tardis/pub/www/stats/mrtg =head1 OPTIONAL GLOBAL KEYWORDS =head2 HtmlDir HtmlDir specifies the directory where the html (or shtml, but we'll get on to those later) lives. NOTE: Workdir overrides the settings for htmldir, imagedir and logdir. Example: Htmldir: /www/mrtg/ =head2 ImageDir ImageDir specifies the directory where the images live. They should be under the html directory. Example: Imagedir: /www/mrtg/images =head2 LogDir LogDir specifies the directory where the logs are stored. This need not be under htmldir directive. Example: Logdir: /www/mrtg/logs =head2 Forks (UNIX only) With system that supports fork (UNIX for example), mrtg can fork itself into multiple instances while it is acquiring data via snmp. For situations with high latency or a great number of devices this will speed things up considerably. It will not make things faster, though, if you query a single switch sitting next door. As far as I know NT can not fork so this option is not available on NT. Example: Forks: 4 =head2 EnableIPv6 When set to yes, IPv6 support is enabled if the required libraries are present (see the L manpage). When IPv6 is enabled, mrtg can talk to routers using SNMP over IPv6 and targets may be specified by their numeric IPv6 addresses as well as by hostname or IPv4 address. If IPv6 is enabled and the target is a hostname, mrtg will try to resolve the hostname to an IPv6 address and, if this fails, to an IPv4 address. Note that mrtg will only use IPv4 if you specify an IPv4 address or a hostname with no corresponding IPv6 address; it will not fall back to IPv4 if it simply fails to communicate with the target using IPv6. This is by design. Note that many routers do not currently support SNMP over IPv6. Use the I per target option for these routers. IPv6 is disabled by default. Example: EnableIPv6: Yes =head2 EnableSnmpV3 When set to yes, uses the Net::SNMP module instead of the SNMP_SESSION module for generating snmp queries. This allows the use of SNMPv3 if other snmpv3 parameters are set. SNMPv3 is disabled by default. Example: EnableSnmpV3: yes =head2 Refresh How many seconds apart should the browser (Netscape) be instructed to reload the page? If this is not defined, the default is 300 seconds (5 minutes). Example: Refresh: 600 =head2 Interval How often do you call mrtg? The default is 5 minutes. If you call it less often, you should specify it here. This does two things: =over =item * The generated HTML page contains the right information about the calling interval ... =item * A META header in the generated HTML page will instruct caches about the time-to-live of this page ..... =back In this example, we tell mrtg that we will be calling it every 10 minutes. If you are calling mrtg every 5 minutes, you can leave this line commented out. Example: Interval: 10 Note that unless you are using rrdtool you can not set Interval to less than 5 minutes. If you are using rrdtool you can set interval in the format Interval: MM[:SS] Down to 1 second. Note though, setting the Interval for an rrdtool/mrtg setup will influence the initial creation of the database. If you change the interval later, all existing databases will remain at the resolution they were initially created with. Also note that you must make sure that your mrtg-rrd Web-frontend can deal with this kind of Interval setting. =head2 MaxAge MRTG relies heavily on the real time clock of your computer. If the time is set to a wrong value, especially if it is advanced far into the future, this will cause mrtg to expire lots of supposedly old data from the log files. To prevent this, you can add a 'reasonability' check by specifying a maximum age for log files. If a file seems to be older, mrtg will not touch it but complain instead, giving you a chance to investigate the cause. Example: MaxAge: 7200 The example above will make mrtg refuse to update log files older than 2 hours (7200 seconds). =head2 WriteExpires With this switch mrtg will generate .meta files for CERN and Apache servers which contain Expiration tags for the html and gif files. The *.meta files will be created in the same directory as the other files, so you will have to set "MetaDir ." and "MetaFiles on" in your apache.conf or .htaccess file for this to work NOTE: If you are running Apache-1.2 or later, you can use the mod_expire to achieve the same effect ... see the file htaccess.txt Example: WriteExpires: Yes =head2 NoMib2 Normally we ask the SNMP device for 'sysUptime' and 'sysName' properties. Some do not have these. If you want to avoid getting complaints from mrtg about these missing properties, specify the nomib2 option. An example of agents which do not implement base mib2 attributes are Computer Associates - Unicenter TNG Agents. CA relies on using the base OS SNMP agent in addition to its own agents to supplement the management of a system. Example: NoMib2: Yes =head2 SingleRequest Some SNMP implementations can not deal with requests asking for multiple snmp variables in one go. Set this in your cfg file to force mrtg to only ask for one variable per request. Examples SingleRequest: Yes =head2 SnmpOptions Apart from the per target timeout options, you can also configure the behaviour of the snmpget process on a more profound level. SnmpOptions accepts a hash of options. The following options are currently supported: timeout => $default_timeout, retries => $default_retries, backoff => $default_backoff, default_max_repetitions => $max_repetitions, use_16bit_request_ids => 1, lenient_source_port_matching => 0, lenient_source_address_matching => 1 The values behind the options indicate the current default value. Note that these settings OVERRIDE the per target timeout settings. A per-target SnmpOptions[] keyword will override the global settings. That keyword is primarily for SNMPv3. The 16bit request ids are the only way to query the broken SNMP implementation of SMC Barricade routers. Example: SnmpOptions: retries => 2, only_ip_address_matching => 0 Note that AS/400 snmp seems to be broken in a way which prevents mrtg from working with it unless SnmpOptions: lenient_source_port_matching => 1 is set. =head2 IconDir If you want to keep the mrtg icons in someplace other than the working (or imagedir) directory, use the I variable for defining the url of the icons directory. Example: IconDir: /mrtgicons/ =head2 LoadMIBs Load the MIB file(s) specified and make its OIDs available as symbolic names. For better efficiency, a cache of MIBs is maintained in the WorkDir. Example: LoadMIBs: /dept/net/mibs/netapp.mib,/usr/local/lib/ft100m.mib =head2 Language Switch output format to the selected Language (Check the F directory to see which languages are supported at the moment. In this directory you can also find instructions on how to create new translations). Currently the following languages are supported: big5 brazilian bulgarian catalan chinese croatian czech danish dutch eucjp french galician gb gb2312 german greek hungarian icelandic indonesia iso2022jp italian korean lithuanian malay norwegian polish portuguese romanian russian russian1251 serbian slovak slovenian spanish swedish turkish ukrainian Example: Language: danish =head2 LogFormat Setting LogFormat to 'rrdtool' in your mrtg.cfg file enables rrdtool mode. In rrdtool mode, mrtg relies on B to do its logging. See L. Example: LogFormat: rrdtool =head2 LibAdd If you are using rrdtool mode and your B Perl module (RRDs.pm) is not installed in a location where perl can find it on its own, you can use LibAdd to supply an appropriate path. Example: LibAdd: /usr/local/rrdtool/lib/perl/ =head2 PathAdd If the B executable can not be found in the normal C, you can use this keyword to add a suitable directory to your path. Example: PathAdd: /usr/local/rrdtool/bin/ =head2 RRDCached If you are running RRDTool 1.4 or later with B, then you can configure MRTG to take advantage of this for updates, either by using the RRDCACHED_ADDRESS environment variable, or by setting the RRDCached keyword in the configuration file. Note that, if both are set, the configuration file keyword will take precedence. Only UNIX domain sockets are fully supported prior to RRDTool v1.5, and you should note that using RRDCached mode will disable all Threshold checking normally done by MRTG. Appropriate warning messages will be printed if necessary. Examples: RRDCached: unix:/var/tmp/rrdcached.sock RRDCached: localhost:42217 =head2 RunAsDaemon The RunAsDaemon keyword enables daemon mode operation. The purpose of daemon mode is that MRTG is launched once and not repeatedly (as it is with cron). This behavior saves computing resources as loading and parsing of configuration files happens only once on startup, and if the configuration file is modified. Using daemon mode MRTG itself is responsible for timing the measurement intervals. Therefore its important to set the Interval keyword to an appropriate value. Note that when using daemon mode MRTG should no longer be started from cron as each new process runs forever. Instead MRTG should be started from the command prompt or by a system startup script. If you want mrtg to run under a particular user and group (it is not recommended to run MRTG as root) then you can use the B<--user=>I and B<--group=>I options on the mrtg commandline. mrtg --user=mrtg_user --group=mrtg_group mrtg.cfg Also note that in daemon mode restarting the process is required in order to activate changes in the config file. Under UNIX, the Daemon switch causes mrtg to fork into background after checking its config file. On Windows NT the MRTG process will detach from the console, but because the NT/2000 shell waits for its children you have to use this special start sequence when you launch the program: start /b perl mrtg mrtg.cfg You may have to add path information equal to what you add when you run mrtg from the commandline. Example RunAsDaemon: Yes Interval: 5 This makes MRTG run as a daemon beginning data collection every 5 minutes If you are daemontools and still want to run mrtg as a daemon you can additionally specify NoDetach: Yes this will make mrtg run but without detaching it from the terminal. If the modification date on the configuration file changes during operation, then MRTG will re-read the configuration on the next polling cycle. Note that sub-files which are included from the main configuration do not have their modification times monitored, only the top-level file is so checked. =head2 ConversionCode Some devices may produce non-numeric values that would nevertheless be useful to graph with MRTG if those values could be converted to numbers. The ConversionCode keyword specifies the path to a file containing Perl code to perform such conversions. The code in this file must consist of one or more Perl subroutines. Each subroutine must accept a single string argument and return a single numeric value. When RRDtool is in use, a decimal value may be returned. When the name of one of these subroutines is specified in a target definition (see below), MRTG calls it twice for that target, once to convert the the input value being monitored and a second time to convert the output value. The subroutine must return an undefined value if the conversion fails. In case of failure, a warning may be posted to the MRTG log file using Perl's warn function. MRTG imports the subroutines into a separate name space (package MRTGConversion), so the user need not worry about pollution of MRTG's global name space. MRTG automatically prepends this package declaration to the user-supplied code. Example: Suppose a particular OID returns a character string whose length is proportional to the value to be monitored. To convert this string to a number that can be graphed by MRTG, create a file arbitrarily named "MyConversions.pl" containing the following code: # Return the length of the string argument sub Length2Int { my $value = shift; return length( $value ); } Then include the following global keyword in the MRTG configuration file (assuming that the conversion code file is saved in the mrtg/bin directory along with mrtg itself): ConversionCode: MyConversions.pl This will cause MRTG to include the definition of the subroutine Length2Int in its execution environment. Length2Int can then be invoked on any target by appending "|Length2Int" to the target definition as follows: Target[myrouter]: 1.3.6.1.4.1.999.1&1.3.6.1.4.1.999.1:public@mydevice|Length2Int See "Extended Host Name Syntax" below for complete target definition syntax information. =head2 SendToGraphite If you want to send a copy of the collected data into a Graphite database in addition to storing it in the RRDfile, you can provide your Graphite database name/ip and port number here. This requires the Net::Graphite perl module which is available from CPAN. Examples: # If your Graphite receiver is running on the same host as the MRTG daemon and using the default port SendToGraphite: 127.0.0.1,2003 # If your Graphite receiver is running on 192.168.100.50 port 5000 SendToGraphite: 192.168.100.50,5000 # If your Graphite receiver is running on graphite.mydomain.com port 2003 SendToGraphite: graphite.mydomain.com,2003 Graphite's namespace has a number of restrictions on what characters are allowed. The SendToGraphite functionality makes an attempt to convert the MRTG target name and, if specified, the Legendi and Legendo values to Graphite namespace friendly values. Specifically, the following conversion rules apply: =over =item * Underscores in the target_name are converted to periods which are Graphite namespace delimiters. =item * Comma characters are not allowed so they are removed. =item * The string "m2g" for MRTG to Graphite is prepended onto the Graphite namespace variable. =back Example MRTG target to Graphite namespace conversion: # Our MRTG target name from mrtg.cfg is as follows Target[switch_GigabitEthernet0_5]: \GigabitEthernet0/5:public1@switch:::::2 After the conversion you will end up with these Graphite namespace values m2g.switch.gigabitethernet0.5.in m2g.switch.gigabitethernet0.5.out Next is a more complicated example because Legendi and Legendo are in use to denote min and max voltage values that pertain to some APC UPS SNMP OIDs # Target, Legendi, and Legendo are specified in mrtg.cfg as follows Target[apc_minmaxline]: 1.3.6.1.4.1.318.1.1.1.3.2.3.0&1.3.6.1.4.1.318.1.1.1.3.2.2.0:public@apc: LegendI[apc_minmaxline]: upsAdvInputMinLineVoltage LegendO[apc_minmaxline]: upsAdvInputMaxLineVoltage After the conversion you will end up with these Graphite namespace values m2g.apc.minmaxline.upsAdvInputMinLineVoltage m2g.apc.minmaxline.upsAdvInputMaxLineVoltage If you don't see the data showing up in Graphite, chances are there are invalid characters in the namespace. To debug this, use the DEBUG=qw(log) directive at the top of the MRTG script to find out what is happening with the MRTG to Graphite namespace conversion. DEBUG=qw(log) will generate some output similar to what appears below 2016-10-13 06:08:39 -- --log: RRDs::update(/var/www/mrtg/switch/switch_gigabitethernet0_5.rrd, '1476356919:2738746035:2927936327') 2016-10-13 06:08:39 -- --log: graphite->send(m2g.switch.gigabitethernet0.5.in,2738746035,1476356919) 2016-10-13 06:08:39 -- --log: graphite->send(m2g.switch.gigabitethernet0.5.out,2927936327,1476356919) 2016-10-13 06:09:25 -- --log: RRDs::update(/var/www/mrtg/apc/apc_minmaxline.rrd, '1476356965:122:123') 2016-10-13 06:09:25 -- --log: graphite->send(m2g.apc.minmaxline.upsAdvInputMinLineVoltage,122,1476356965) 2016-10-13 06:09:25 -- --log: graphite->send(m2g.apc.minmaxline.upsAdvInputMaxLineVoltage,123,1476356965) If the MRTG log output looks reasonable, then take a look at Graphite's carbon-cache logs. =head1 PER TARGET CONFIGURATION Each monitoring target must be identified by a unique name. This name must be appended to each parameter belonging to the same target. The name will also be used for naming the generated webpages, logfiles and images for this target. =head2 Target With the I keyword you tell mrtg what it should monitor. The I keyword takes arguments in a wide range of formats: =over =item Basic The most basic format is "port:community@router" This will generate a traffic graph for the interface 'port' of the host 'router' (dns name or IP address) and it will use the community 'community' (snmp password) for the snmp query. Example: Target[myrouter]: 2:public@wellfleet-fddi.domain If your community contains a "@" or a " " these characters must be escaped with a "\". Target[bla]: 2:stu\ pi\@d@router =item SNMPv2c If you have a fast router you might want to try to poll the ifHC* counters. This feature gets activated by switching to SNMPv2c. Unfortunately not all devices support SNMPv2c yet. If it works, this will prevent your counters from wrapping within the 5 minute polling interval, since we now use 64 bit instead of the normal 32 bit. Example: Target[myrouter]: 2:public@router1:::::2 =item SNMPv3 As an alternative to SNMPv2c, SNMPv3 provides access to the ifHC* counters, along with encryption. Not all devices support SNMPv3, and you will also need the perl Net::SNMP library in order to use it. It is recommended that cfgmaker be used to generate configurations involving SNMPv3, as it will check if the Net::SNMP library is loadable, and will switch to SNMPv2c if v3 is unavailable. SNMP v3 requires additional authentication parameters, passed using the SnmpOptions[] per-target keyword. Example: Target[myrouter]: 2:router1:::::3 SnmpOptions[myrouter]: username=>'user1' =item noHC Not all routers that support SNMPv2 or SNMPv3 provide the ifHC* counters on every interface. The noHC[] per-target keyword signals that the low-speed counters ifInOctets and ifOutOctets should be queried instead. cfgmaker will automatically insert this tag if SNMPv2 or SNMPv3 is specified but the ifHC* counters are unavailable. Example: Target[myrouter]: #Bri0:router1:::::3 SnmpOptions[myrouter]: username=>'user1' noHC[myrouter]: yes =item Reversing Sometimes you are sitting on the wrong side of the link, and you would like to have mrtg report Incoming traffic as Outgoing and vice versa. This can be achieved by adding the '-' sign in front of the "Target" description. It flips the incoming and outgoing traffic rates. Example: Target[ezci]: -1:public@ezci-ether.domain =item Explicit OIDs You can also explicitly define which OID to query by using the following syntax 'OID_1&OID_2:community@router' The following example will retrieve error counts for input and output on interface 1. MRTG needs to graph two variables, so you need to specify two OID's such as temperature and humidity or error input and error output. Example: Target[myrouter]: 1.3.6.1.2.1.2.2.1.14.1&1.3.6.1.2.1.2.2.1.20.1:public@myrouter =item MIB Variables MRTG knows a number of symbolic SNMP variable names. See the file mibhelp.txt for a list of known names. One example are the ifInErrors and ifOutErrors. This means you can specify the above as: Example: Target[myrouter]: ifInErrors.1&ifOutErrors.1:public@myrouter =item SnmpWalk It may be that you want to monitor an snmp object that is only reachable by 'walking'. You can get mrtg to walk by prepending the OID with the string B or if you want a particular entry from the table returned by the walk you can use BI where I is a number starting from 0 (!). Example: Target[myrouter]: WaLKstrangeOid.1&WaLKstrangeOid.2:public@myrouter Target[myrouter]: WaLK3strangeOid.1&WaLK4strangeOid.2:public@myrouter =item SnmpGetNext A special case of an snmp object that is only reachable by 'walking' occurs when a single snmpgetnext will return the correct value, but snmpwalk fails. This may occur with snmp V2 or V3, as the snmpgetbulk method is used in these versions. You can get mrtg to use getnext instead of getbulk by prepending the OID with the string B. Example: Target[myrouter]: GeTNEXTstrangeOid&GeTNEXTstrangeOid:public@myrouter =item Counted SNMP Walk In other situations, an snmpwalk is needed to count rows, but the actual data is uninteresting. For example, counting the number of mac-addresses in a CAM table, or the number of simultaneous dialup sessions. You can get MRTG to count the number of instances by prepending the OID with the string B. The following will retrieve the number of simultaneous VOIP calls on some routers: Example: Target[myrouter]: CnTWaLK1.3.6.1.4.1.9.10.55.1.1.1.1.3&CnTWaLK1.3.6.1.4.1.9.10.55.1.1.1.1.3:public@myrouter =item Interface by IP Sometimes SNMP interface index can change, like when new interfaces are added or removed. This can cause all Target entries in your config file to become offset, causing MRTG to graphs wrong instances etc. MRTG supports IP address instead of ifindex in target definition. Then MRTG will query snmp device and try to map IP address to the current ifindex. You can use IP addresses in every type of target definition by adding IP address of the numbered interface after OID and separation char '/'. Make sure that the given IP address is used on your same target router, especially when graphing two different OIDs and/or interface split by '&' delimiter. You can tell cfgmaker to generate such references with the option B<--ifref=ip>. Example: Target[myrouter]: /1.2.3.4:public@wellfleet-fddi.domain Target[ezci]: -/1.2.3.4:public@ezci-ether.domain Target[myrouter]: ifInErrors/1.2.3.4&ifOutErrors/1.2.3.4:public@myrouter =item Interface by Description If you can not use IP addresses you might want to use the interface names. This works similar to the IP address approach except that the prefix to use is a \ instead of a / You can tell cfgmaker to generate such references with the option B<--ifref=descr>. Example: Target[myrouter]: \My-Interface2:public@wellfleet-fddi.domain Target[ezci]: -\My-Interface2:public@ezci-ether.domain Target[myrouter]: ifInErrors\My-If2&ifOutErrors\My-If3:public@myrouter If your description contains a "&", a ":", a "@" or a " " you can include them but you must escape with a backlash: Target[myrouter]: \fun\:\ ney\&ddd:public@hello.router =item Interface by Name This is the only sensible way to reference the interfaces of your switches. You can tell cfgmaker to generate such references with the option B<--ifref=name>. Example: Target[myrouter]: #2/11:public@wellfleet-fddi.domain Target[ezci]: -#2/11:public@ezci-ether.domain Target[myrouter]: ifInErrors#3/7&ifOutErrors#3/7:public@myrouter If your description contains a "&", a ":", a "@" or a " " you can include them but you must escape with a backlash: Target[myrouter]: #\:\ fun:public@hello.router Note that the # sign will be interpreted as a comment character if it is the first non white-space character on the line. =item Interface by Ethernet Address When the SNMP interface index changes, you can key that interface by its 'Physical Address', sometimes called a 'hard address', which is the SNMP variable 'ifPhysAddress'. Internally, MRTG matches the Physical Address from the *.cfg file to its current index, and then uses that index for the rest of the session. You can use the Physical Address in every type of target definition by adding the Physical Address after the OID and the separation char '!' (analogous to the IP address option). The Physical address is specified as '-' delimited octets, such as "0a-0-f1-5-23-18" (omit the double quotes). Note that some routers use the same Hardware Ethernet Address for all of their Interfaces which prevents unique interface identification. Mrtg will notice such problems and alert you. You can tell cfgmaker to generate configuration files with hardware ethernet address references by using the option B<--ifref=eth>. Example: Target[myrouter]: !0a-0b-0c-0d:public@wellfleet-fddi.domain Target[ezci]: -!0-f-bb-05-71-22:public@ezci-ether.domain Target[myrouter]: 1.3.6.1.2.1.2.2.1.14!0a-00-10-23-44-51& *BREAK* 1.3.6.1.2.1.2.2.1.14!0a-00-10-23-44-51:public@myrouter Target[myrouter]: ifInErrors!0a-00-10-23-44-51& *BREAK* ifOutErrors!0a-00-10-23-44-51:public@myrouter Join the lines at *BREAK* ... =item Interface by Type It seems that there are devices that try to defy all monitoring efforts: the interesting interfaces have neither ifName nor a constant ifDescr not to mention a persistent ifIndex. The only way to get a constant mapping is by looking at the interface type, because the interface you are interested in is unique in the device you are looking at ... You can tell cfgmaker to generate such references with the option B<--ifref=type>. Example: Target[myrouter]: %13:public@wellfleet-fddi.domain Target[ezci]: -%13:public@ezci-ether.domain Target[myrouter]: ifInErrors%13&ifOutErrors%14:public@myrouter =item Extended positioning of ifIndex There are OIDs that contain the interface index at some inner position within the OID. To use the above mentioned Interface by IP/Description/Name/Type methods in the target definition the keyword 'IndexPOS' can be used to indicate the position of ifIndex. If 'IndexPOS' is not used the ifIndex will be appended at the end of the OID. Example: Target[myrouter]: OID.IndexPOS.1/1.2.3.4&OID.IndexPOS.1/1.2.3.4:public@myrouter Replace OID by your numeric OID. =item Extended Host Name Syntax In all places where ``community@router'' is accepted, you can add additional parameters for the SNMP communication using colon-separated suffixes. You can also append a pipe symbol ( | ) and the name of a numeric conversion subroutine as described under the global keyword "ConversionCode" above. The full syntax is as follows: community@router[:[port][:[timeout][:[retries][:[backoff][:[version]]]]][|name] where the meaning of each parameter is as follows: =over =item port the UDP port under which to contact the SNMP agent (default: 161) The complete syntax of the port parameter is remote_port[!local_address[!local_port]] Some machines have additional security features that only allow SNMP queries to come from certain IP addresses. If the host doing the query has multiple interface, it may be necessary to specify the interface the query should come from. The port parameter allows the specification of the port of the machine being queried. In addition, the IP address (or hostname) and port of the machine doing the query may be specified. Examples: somehost somehost:161 somehost:161!192.168.2.4!4000 use 192.168.2.4 and port 4000 as source somehost:!192.168.2.4 use 192.168.2.4 as source somehost:!!4000 use port 4000 as source =item timeout initial timeout for SNMP queries, in seconds (default: 2.0) =item retries number of times a timed-out request will be retried (default: 5) =item backoff factor by which the timeout is multiplied on every retry (default: 1.0). =item version for SNMP version. If you have a fast router you might want to put a '2' here. For authenticated or encrypted SNMP, you can try to put a '3' here. This will make mrtg try to poll the 64 bit counters and thus prevent excessive counter wrapping. Not all routers support this though. SNMP v3 requires additional setup, see SnmpOptions[] for full details. Example: 3:public@router1:::::2 =item name the name of the subroutine that MRTG will call to convert the input and output values to integers. See the complete example under the global keyword "ConversionCode" above. Example: 1.3.6.1.4.1.999.1&1.3.6.1.4.1.999.2:public@mydevice:161::::2|Length2Int This would retrieve values from the OID 1.3.6.1.4.1.999.1 for input and .2 for output on mydevice using UDP port 161 and SNMP version 2, and would execute the user-defined numeric conversion subroutine Length2Int to convert those values to integers. =back A value that equals the default value can be omitted. Trailing colons can be omitted, too. The pipe symbol followed by the name parameter, if present, must come at the end. There must be no spaces around the colons or pipe symbol. Example: Target[ezci]: 1:public@ezci-ether.domain:9161::4 This would refer to the input/output octet counters for the interface with I on I, as known by the SNMP agent listening on UDP port 9161. The standard initial timeout (2.0 seconds) is used, but the number of retries is set to four. The backoff value is the default. =item Numeric IPv6 addresses If IPv6 is enabled you may also specify a target using its IPv6 address. To avoid ambiguity with the port number, numeric IPv6 addresses must be placed in square brackets. Example: Target[IPv6test]: 2:public@[2001:760:4::]:6161::4 =item External Monitoring Scripts If you want to monitor something which does not provide data via snmp you can use some external program to do the data gathering. The external command must return 4 lines of output: =over =item Line 1 current state of the first variable, normally 'incoming bytes count' =item Line 2 current state of the second variable, normally 'outgoing bytes count' =item Line 3 string (in any human readable format), telling the uptime of the target. =item Line 4 string, telling the name of the target. =back Depending on the type of data your script returns you might want to use the 'gauge' or 'absolute' arguments for the I keyword. Example: Target[myrouter]: `/usr/local/bin/df2mrtg /dev/dsk/c0t2d0s0` Note the use of the backticks (`), not apostrophes (') around the command. If you want to use a backtick in the command name this can be done but you must escape it with a backslash ... If your script does not have any data to return but does not want mrtg to complain about invalid data, it can return 'UNKNOWN' instead of a number. Note though that only rrdtool is really equipped to handle unknown data well. =item Multi Target Syntax You can also combine several target definitions in a mathematical expression. Any syntactically correct expression that the Perl interpreter can evaluate to will work. An expression could be used, for example, to aggregate both B channels in an ISDN connection or to calculate the percentage hard disk utilization of a server from the absolute used space and total capacity. Examples: Target[myrouter]: 2:public@wellfleetA + 1:public@wellfleetA Target[myrouter]: .1.3.6.1.4.1.999.1&.1.3.6.1.4.1.999.2:public@mydevice / .1.3.6.1.4.1.999.3&.1.3.6.1.4.1.999.4:public@mydevice * 100 Note that whitespace must surround each target definition in the expression. Target definitions themselves must not contain whitespace, except in interface descriptions and interface names, where each whitespace character is escaped by a backslash. MRTG automatically rounds the result of the expression to an integer unless RRDTool logging is in use and the gauge option is in effect for the target. Internally MRTG uses Perl's Math::BigFloat package to calculate the result of the expression with 40 digits of precision. Even in extreme cases, where, for example, you take the difference of two 64-bit integers, the result of the expression should be accurate. =item SNMP Request Optimization MRTG is designed to economize on its SNMP requests. Where a target definition appears more than once in the configuration file, MRTG requests the data from the device only once per round of data collection and uses the collected data for each instance of a particular target. Recognition of two target definitions as being identical is based on a simple string match rather than any kind of deeper semantic analysis. Example: Target[Targ1]: 1:public@CiscoA Target[Targ2]: 2:public@CiscoA Target[Targ3]: 1:public@CiscoA + 2:public@CiscoA Target[Targ4]: 1:public@CISCOA This results in a total of three SNMP requests. Data for 1:public@CiscoA and 2:public@CiscoA are requested only once each, and used for Targ1, Targ2, and Targ3. Targ4 causes another SNMP request for 1:public@CISCOA, which is not recognized as being identical to 1:public@CiscoA. =back =head2 MaxBytes The maximum value either of the two variables monitored are allowed to reach. For monitoring router traffic this is normally the bytes per second this interface port can carry. If a number higher than I is returned, it is ignored. Also read the section on I for further info. The I value is also used in calculating the Y range for unscaled graphs (see the section on I). Since most links are rated in bits per second, you need to divide their maximum bandwidth (in bits) by eight (8) in order to get bytes per second. This is very important to make your unscaled graphs display realistic information. T1 = 193000, 56K = 7000, 10 MB Ethernet = 1250000, 100 MB Ethernet = 12500000. The I value will be used by mrtg to decide whether it got a valid response from the router. If you need two different MaxBytes values for the two monitored variables, you can use MaxBytes1 and MaxBytes2 instead of MaxBytes. Example: MaxBytes[myrouter]: 1250000 =head2 Title Title for the HTML page which gets generated for the graph. Example: Title[myrouter]: Traffic Analysis for Our Nice Company =head1 OPTIONAL PER TARGET KEYWORDS =head2 PageTop Things to add to the top of the generated HTML page. Note that you can have several lines of text as long as the first column is empty. Note that the continuation lines will all end up on the same line in the html page. If you want linebreaks in the generated html use the '\n' sequence. Example: PageTop[myrouter]:

      Traffic Analysis for ETZ C95.1

      Our Campus Backbone runs over an FDDI line\n with a maximum transfer rate of 12.5 megabytes per Second. =head2 RouterUptime In cases where you calculate the used bandwidth from several interfaces you normally don't get the router uptime and router name displayed on the web page. If these interfaces are on the same router and the uptime and name should be displayed you have to specify its community and address again with the I keyword. If you want to use a special OID for querying the router uptime, use prepend the oid. Example: Target[kacisco.comp.edu]: 1:public@194.64.66.250 + 2:public@194.64.66.250 RouterUptime[kacisco.comp.edu]: public@194.64.66.250 RouterUptime[kacisco.comp.edu]: hrSystemUptime.0:public@194.64.66.250 =head2 RouterName If the default name of the router is incorrect/uninformative, you can use RouterName to specify a different OID on either the same or a different host. A practical example: sysName on BayTech DS72 units always display "ds72", no matter what you set the Unit ID to be. Instead, the Unit ID is stored at 1.3.6.1.4.1.4779.1.1.3.0, so we can have MRTG display this instead of sysName. Example: RouterName[kacisco.comp.edu]: 1.3.6.1.4.1.4779.1.1.3.0 A different OID on a different host can also be specified: RouterName[kacisco.comp.edu]: 1.3.6.1.4.1.4779.1.1.3.0:public@194.64.66.251 =head2 MaxBytes1 Same as MaxBytes, for variable 1. =head2 MaxBytes2 Same as MaxBytes, for variable 2. =head2 IPv4Only Many IPv6 routers do not currently support SNMP over IPv6 and must be monitored using IPv4. The IPv4Only option forces mrtg to use IPv4 when communicating with the target, even if IPv6 is enabled. This is useful if the target is a hostname with both IPv4 and IPv6 addresses; without the IPv4Only keyword, monitoring such a router will not work if IPv6 is enabled. If set to no (the default), mrtg will use IPv6 unless the target has no IPv6 addresses, in which case it will use IPv4. If set to yes, mrtg will only use IPv4. Note that if this option is set to yes and the target does not have an IPv4 address, communication with the target will fail. This option has no effect if IPv6 is not enabled. Example: Target[v4onlyrouter_1]: 1:public@v4onlyrouter IPv4Only[v4onlyrouter_1]: Yes =head2 SnmpOptions (V3) SNMPv3 requires a fairly rich set of options. This per-target keyword allows access to the User Security Model of SNMPv3. Options are listed in the same syntax as a perl hash. =head3 Security Modes SNMPv3 has three security modes, defined on the device being polled. For example, on Cisco routers the security mode is defined by the snmp-server group global configuration command. =over =item NoAuthNoPriv Neither Authentication nor Privacy is defined. Only the Username option is specified for this mode. Example: SnmpOptions[myrouter]: username=>'user1' =item AuthNoPriv Uses a Username and a password. The password can be hashed using the snmpkey application, or passed in plain text along with the ContextEngineID Example: SnmpOptions[myrouter]: username=>'user1',authpassword=>'example', contextengineid=>'80000001110000004000000' =item Priv Both Authentication and Privacy is defined. The default privacy protocol is des. Example: SnmpOptions[myrouter]: authkey=>'0x1e93ab5a396e2af234c8920e61cfe2028072c0e2', authprotocol=>'sha',privprotocol=>'des',username=>'user1', privkey=>'0x498d74940c5872ed387201d74b9b25e2' =back =head3 snmp options The following option keywords are recognized: =over =item username The user associated with the User Security Model =item contextname An SNMP agent can define multiple contexts. This keyword allows them to be polled. =item contextengineid A unique 24-byte string identifying the snmp-agent. =item authpassword The plaintext password for a user in either AuthNoPriv or Priv mode. =item authkey A md5 or sha hash of the plain-text password, along with the engineid. Use the snmpkey commandline program to generate this hash, or use Net::SNMP::Security::USM in a script. =item authprotocol {sha|md5} The hashing algorithm defined on the SNMP client. Defaults to md5. =item privpassword A plaintext pre-shared key for encrypting snmp packets in Priv mode. =item privkey A hash of the plain-text pre-shared key, along with the engineid. Use the snmpkey commandline program to generate this hash, or use Net::SNMP::Security::USM in a script. =item privprotocol {des|3desede|aescfb128|aescfb192|aescfb256} Specifies the encryption method defined on the snmp agent. The default is des. =back =head2 PageFoot Things to add to the bottom of the generated HTML page. Note that you can have several lines of text as long as the first column is empty. Note that the continuation lines will all end up on the same line in the html page. If you want linebreaks in the generated html use the '\n' sequence. The material will be added just before the E/BODYE tag: Example: PageFoot[myrouter]: Contact
      Peter if you have questions regarding this page =head2 AddHead Use this tag like the I header, but its contents will be added between E/TITLEE and E/HEADE. Example: AddHead[myrouter]: =head2 BodyTag BodyTag lets you supply your very own Ebody ...E tag for the generated webpages. Example: BodyTag[myrouter]: =head2 AbsMax If you are monitoring a link which can handle more traffic than the I value. Eg, a line which uses compression or some frame relay link, you can use the I keyword to give the absolute maximum value ever to be reached. We need to know this in order to sort out unrealistic values returned by the routers. If you do not set I, rateup will ignore values higher than I. Example: AbsMax[myrouter]: 2500000 =head2 Unscaled By default each graph is scaled vertically to make the actual data visible even when it is much lower than I. With the I variable you can suppress this. It's argument is a string, containing one letter for each graph you don't want to be scaled: d=day w=week m=month y=year. There is also a special case to unset the variable completely: n=none. This could be useful in the event you need to override a global configuration. In the example scaling for the yearly and the monthly graph are suppressed. Example: Unscaled[myrouter]: ym =head2 WithPeak By default the graphs only contain the average values of the monitored variables - normally the transfer rates for incoming and outgoing traffic. The following option instructs mrtg to display the peak 5 minute values in the [w]eekly, [m]onthly and [y]early graph. In the example we define the monthly and the yearly graph to contain peak as well as average values. Examples: WithPeak[myrouter]: ym =head2 Suppress By default mrtg produces 4 graphs. With this option you can suppress the generation of selected graphs. The option value syntax is analogous to the above two options. In this example we suppress the yearly graph as it is quite empty in the beginning. Example: Suppress[myrouter]: y =head2 Extension By default, mrtg creates .html files. Use this option to tell mrtg to use a different extension. For example you could set the extension to php3, then you will be able to enclose PHP tags into the output (useful for getting a router name out of a database). Example: Extension[myrouter]: phtml =head2 Directory By default, mrtg puts all the files that it generates for each target (the GIFs, the HTML page, the log file, etc.) in I. If the I option is specified, the files are instead put into a directory under I or Log-, Image- and HtmlDir). (For example the I option below would cause all the files for a target myrouter to be put into directory /usr/tardis/pub/www/stats/mrtg/myrouter/ .) The directory must already exist; mrtg will not create it. Example: WorkDir: /usr/tardis/pub/www/stats/mrtg Directory[myrouter]: myrouter NOTE: the Directory option must always be 'relative' or bad things will happen. =head2 Clonedirectory If the I option is specified, the I option will copy all the contents of I to the I. Example: WorkDir: /usr/tardis/pub/www/stats/mrtg Directory[myrouter]: myrouter Clonedirectory[myrouter]: myclonedirectory Optionally the target name can be changed in the cloning process. Example: WorkDir: /usr/tardis/pub/www/stats/mrtg Directory[myrouter]: myrouter Clonedirectory[myrouter]: myclonedirectory mynewtarget NOTE1: The clone directory must already exist; mrtg will not create it. NOTE2: The Clonedirectory option must also always be 'relative' or bad things will happen. NOTE3: This requires the File::Copy module =head2 XSize and YSize By default mrtgs graphs are 100 by 400 pixels wide (plus some more for the labels. In the example we get almost square graphs ... Note: XSize must be between 20 and 600; YSize must be larger than 20 Example: XSize[myrouter]: 300 YSize[myrouter]: 300 =head2 XZoom and YZoom If you want your graphs to have larger pixels, you can "Zoom" them. Example: XZoom[myrouter]: 2.0 YZoom[myrouter]: 2.0 =head2 XScale and YScale If you want your graphs to be actually scaled use I and I. (Beware: while this works, the results look ugly (to be frank) so if someone wants to fix this: patches are welcome. Example: XScale[myrouter]: 1.5 YScale[myrouter]: 1.5 =head2 YTics and YTicsFactor If you want to show more than 4 lines per graph, use YTics. If you want to scale the value used for the YLegend of these tics, use YTicsFactor. The default value for YTics is 4 and the default value for YTicsFactor is 1.0 . Example: Suppose you get values ranging from 0 to 700. You want to plot 7 lines and want to show 0, 1, 2, 3, 4, 5, 6, 7 instead of 0, 100, 200, 300, 400, 500, 600, 700. You should write then: YTics[myrouter]: 7 YTicsFactor[myrouter]: 0.01 =head2 Factor If you want to multiply all numbers shown below the graph with a constant factor, use this directive to define it .. Example: Factor[as400]: 4096 =head2 Step Change the default step from 5 * 60 seconds to something else (I have not tested this much ...) Example: Step[myrouter]: 60 =head2 PNGTitle When using rateup for graph generation, this will print the given title in the graph it generates. Example: PNGTitle[myrouter]: WAN Link UK-US =head2 Options The I Keyword allows you to set some boolean switches: =over =item growright The graph grows to the left by default. This option flips the direction of growth causing the current time to be at the right edge of the graph and the history values to the left of it. =item bits All the monitored variable values are multiplied by 8 (i.e. shown in bits instead of bytes) ... looks much more impressive :-) It also affects the 'factory default' labeling and units for the given target. =item perminute All the monitored variable values are multiplied by 60 (i.e. shown in units per minute instead of units per second) in case of small values more accurate graphs are displayed. It also affects the 'factory default' labeling and units for the given target. =item perhour All the monitored variable values are multiplied by 3600 (i.e. shown in units per hour instead of units per second) in case of small values more accurate graphs are displayed. It also affects the 'factory default' labeling and units for the given target. =item noinfo Suppress the information about uptime and device name in the generated webpage. =item nopercent Don't print usage percentages. =item transparent Make the background of the generated gifs transparent. =item integer Print summary lines below graph as integers without commas. =item dorelpercent The relative percentage of IN-traffic to OUT-traffic is calculated and displayed in the graph as an additional line. Note: Only a fixed scale is available (from 0 to 100%). Therefore if IN-traffic is greater than OUT-traffic then 100% is displayed. If you suspect that your IN-traffic is not always less than or equal to your OUT-traffic you are urged to not use this options. Note: If you use this option in combination with the I options, a fifth colour-name colour-value pair is required there. =item avgpeak There are some ISPs who use the average Peak values to bill their customers. Using this option MRTG displays these values for each graph. The value is built by averaging the max 5 minute traffic average for each 'step' shown in the graph. For the Weekly graph this means that it builds the average of all 2 hour intervals 5 minute peak values. (Confused? Thought so!) =item gauge Treat the values gathered from target as 'current status' measurements and not as ever incrementing counters. This would be useful to monitor things like disk space, processor load, temperature, and the like ... In the absence of 'gauge' or 'absolute' options, MRTG treats variables as a counters and calculates the difference between the current and the previous value and divides that by the elapsed time between the last two readings to get the value to be plotted. =item absolute This is for counter type data sources which reset their value when they are read. This means that rateup does not have to build the difference between the current and the last value read from the data source. The value obtained is still divided by the elapsed time between the current and the last reading, which makes it different from the 'gauge' option. Useful for external data gatherers. =item derive If you are using rrdtool as logger/grapher you can use a third type of data source. Derive is like counter, except that it is not required to go UP all the time. It is useful for situations where the change of some value should be graphed. =item unknaszero Log unknown data as zero instead of the default behaviour of repeating the last value seen. Be careful with this, often a flat line in the graph is much more obvious than a line at 0. =item withzeroes Normally we ignore all values which are zero when calculating the average transfer rate on a line. If this is not desirable use this option. =item noborder If you are using rateup to log data, MRTG will create the graph images. Normally these images have a shaded border around them. If you do not want the border to be drawn, enable this option. This option has no effect if you are not using rateup. =item noarrow As with the option above, this effects rateup graph generation only. Normally rateup will generate graphs with a small arrow showing the direction of the data. If you do not want this arrow to be drawn, enable this option. This option has no effect if you are not using rateup. =item noi When using rateup for graph generation, you can use this option to stop rateup drawing a graph for the 'I' or first variable. This also removes entries for this variable in the HTML page MRTG generates, and will remove the peaks for this variable if they are enabled. This allows you to hide this data, or can be very useful if you are only graphing one line of data rather than two. This option is not destructive - any data received for the the variable continued to be logged, it just isn't shown. =item noo Same as above, except relating to the 'O' or second variable. =item nobanner When using rateup for graph generation, this option disables MRTG adding the MRTG banner to the HTML pages it generates. =item nolegend When using rateup for graph generation, this option will stop MRTG from creating a legend at the bottom of the HTML pages it generates. =item printrouter When using rateup for graph generation, this option will print the router name in the graph it generates. This option is overridden by the value of PNGTitle if one is given =item pngdate When using rateup for graph generation, this option will print a timestamp in the graph it generates, including a timezone if one is specified by the 'Timezone' parameter. This is equivalent to setting TimeStrPost[x]: RU =item logscale The B option causes rateup to display the data with the Y axis scaled logarithmically. Doing so allows the normal traffic to occupy the majority of the vertical range, while still showing any spikes at their full height. B displays all the available data and will always produce well-behaved graphs. People often consider a logarithmically scaled graph counterintuitive, however, and thus hard to interpret. =item expscale The B option causes rateup to display the data with the Y axis scaled exponentially. Doing so emphasizes small changes at the top of the scale; this can be useful when graphing values that fluctuate by a small amount near the top of the scale, such as line voltage. B is essentially the inverse of B. =item secondmean The B option sets the maximum value on the graph to the mean of the data greater than the mean of all data. This produces a graph that focuses more on the typical data, while clipping large peaks. Using B will give a more intuitive linearly scaled graph, but can result in a uselessly high or low scale in some rare situations (specifically, when the data includes a large portion of values far from the actual mean) If a target includes both B and B in the options, the B takes precedence. =back Example: Options[myrouter]: growright, bits =head2 kilo Use this option to change the multiplier value for building prefixes. Defaultvalue is 1000. This tag is for the special case that 1kB = 1024B, 1MB = 1024kB and so far. Example: kilo[myrouter]: 1024 =head2 kMG Change the default multiplier prefixes (,k,M,G,T,P). In the tag I define only the basic units. Format: Comma separated list of prefixed. Two consecutive commas or a comma at start or end of the line gives no prefix on this item. If you do not want prefixes, just put two consecutive commas. If you want to skip a magnitude select '-' as value. Example: velocity in nm/s (nanometers per second) displayed in nm/h. ShortLegend[myrouter]: m/h kMG[myrouter]: n,u,m,,k,M,G,T,P options[myrouter]: perhour =head2 Colours The I tag allows you to override the default colour scheme. Note: All 4 of the required colours must be specified here. The colour name ('Colourx' below) is the legend name displayed, while the RGB value is the real colour used for the display, both on the graph and in the html doc. Format is: Col1#RRGGBB,Col2#RRGGBB,Col3#RRGGBB,Col4#RRGGBB Important: If you use the I options tag a fifth colour name colour value pair is required: Col1#RRGGBB,Col2#RRGGBB,Col3#RRGGBB,Col4#RRGGBB,Col5#RRGGBB =over 4 =item Colour1 First variable (normally Input) on default graph. =item Colour2 Second variable (normally Output) on default graph. =item Colour3 Max first variable (input). =item Colour4 Max second variable (output). =item RRGGBB 2 digit hex values for Red, Green and Blue. =back Example: Colours[myrouter]: GREEN#00eb0c,BLUE#1000ff,DARK GREEN#006600,VIOLET#ff00ff =head2 Background With the I tag you can configure the background colour of the generated HTML page. Example: Background[myrouter]: #a0a0a0a =head2 TextColor With the I tag you can configure the text colour of the generated HTML page. Example: TextColor[myrouter]: #a0a0a0a =head2 YLegend, ShortLegend, Legend[1234] The following keywords allow you to override the text displayed for the various legends of the graph and in the HTML document: =over =item YLegend The Y-axis label of the graph. Note that a text which is too long to fit in the graph will be silently ignored. =item ShortLegend The units string (default 'b/s') used for Max, Average and Current =item Legend[1234IO] The strings for the colour legend. =back Example: YLegend[myrouter]: Bits per Second ShortLegend[myrouter]: b/s Legend1[myrouter]: Incoming Traffic in Bits per Second Legend2[myrouter]: Outgoing Traffic in Bits per Second Legend3[myrouter]: Maximal 5 Minute Incoming Traffic Legend4[myrouter]: Maximal 5 Minute Outgoing Traffic LegendI[myrouter]:  In: LegendO[myrouter]:  Out: Note, if I or I are set to an empty string with LegendO[myrouter]: The corresponding line below the graph will not be printed at all. =head2 Timezone If you live in an international world, you might want to generate the graphs in different timezones. This is set in the TZ variable. Under certain operating systems like Solaris, this will provoke the localtime call to give the time in the selected timezone. Example: Timezone[myrouter]: Japan The Timezone is the standard timezone of your system, ie Japan, Hongkong, GMT, GMT+1 etc etc. =head2 Weekformat By default, mrtg (actually rateup) uses the strftime(3) '%V' option to format week numbers in the monthly graphs. The exact semantics of this format option vary between systems. If you find that the week numbers are wrong, and your system's strftime(3) routine supports it, you can try another format option. The POSIX '%V' option correspond to the widely used ISO 8601 week numbering standard. The week format character should be specified as a single letter; either W, V, or U. The UNIX version of rateup uses the libc implementation of strftime. On Windows, the native strftime implementation does not know about %V. So there we use a different implementation of strftime that does support %V. Example: Weekformat[myrouter]: W =head2 RRDRowCount This affects the creation of new rrd files. By default rrds are created to hold about 1 day's worth of high resolution data. (plus 1 week of 30 minute data, 2 months of 2 hour data and 2 years of 1 day data). With this Keyword you can change the number of base interval entries configured for new rrds as they get created. Note that you must take the interval time into account. Example: RRDRowCount[myrouter]: 1600 =head2 RRDRowCount30m As per RRDRowCount, but for the RRA's -typically- used for 30 minute data. Even so, you must still take the base interval into account. Leaving out this keyword will force the old default of 800 rows. Example: RRDRowCount30m[myrouter]: 800 =head2 RRDRowCount2h As per RRDRowCount, but for the RRA's -typically- used for 2 hour data. Even so, you must still take the base interval into account. Leaving out this keyword will force the old default of 800 rows. Example: RRDRowCount2h[myrouter]: 400 =head2 RRDRowCount1d As per RRDRowCount, but for the RRA's -typically- used for 1 day data. Even so, you must still take the base interval into account. Leaving out this keyword will force the old default of 800 rows. Example: RRDRowCount1d[myrouter]: 200 =head2 RRDHWRRAs Normally the RRDs created by MRTG will just contain the information gathered directly from the respective target. With this option you can tap into rrdtools advanced aberrant behaviour detection module based on Holt-Winters forecasting. The RRDHWRRAs property specifies the Holt-Winters RRAs as described in the rrdcreate manual page. Note, this setting will only affect newly created RRDs (targets). Example: RRDHWRRAs[myrouter]: RRA:HWPREDICT:1440:0.1:0.0035:288 =head2 TimeStrPos This defines placement of the timestamp string on the image. Possible values are RU, LU, RL, LL (which stand, respectively, for RightUpper, LeftUpper, RightLower and LeftLower corner) and NO (for no timestamp). By default, no timestamp is placed on the image. Example: TimeStrPos[myrouter]: RU =head2 TimeStrFmt Using this keyword you may specify format of the timestamp to be placed on the image (if enabled by the TimeStrPos keyword). Specified string will be used by the strftime() function - see strftime(3) documentation for conversion specifiers available on your system. Default format: %Y-%m-%d %H:%M Example: TimeStrFmt[myrouter]: %H:%M:%S =head1 THRESHOLD CHECKING Through its threshold checking functionality mrtg is able to detect threshold problems for the various targets and can call external scripts to handle those problems (e.g. send email or a page to an administrator). Threshold checking is configured through the following parameters: =head2 ThreshDir (GLOBAL) By defining ThreshDir to point to a writable directory, MRTG will only alert you when a threshold boundary has been crossed. Example: ThreshDir: /var/mrtg/thresh =head2 ThreshHyst (GLOBAL) If a threshold is broken, and you have a threshdir defined, then mrtg will send mail once the threshold becomes 'unborken' to avoid situations where broken and unbroken messages get sent in close succession, we only send an unbroken message once the current value is 0.1 (10%) away from the threshold. using the ThreshHyst config variable you can customize this value. Example for 5%: ThreshHyst: 0.05 =head2 ThreshMailServer (GLOBAL) Address of an SMTP server which is going to accept mail about Thresholds being broken and unbroken. =head2 ThreshMailSender (GLOBAL) What is the sender address of the threshold mail. Example: ThreshMailSender: mrtg@example.com =head2 ThreshMailAddress (PER TARGET) Email address for Threshold related Mails. This will only work if a mailserver has been configured. Example: ThreshMailAddress[_]: admin@example.com ThreshMailAddress[router]: This would bring threshold released mail to all but the target called 'router'. =head2 ThreshMinI (PER TARGET) This is the minimum acceptable value for the Input (first) parameter. If the parameter falls below this value, the program specified in ThreshProgI will be run and a mail will be sent to the ThreshMailAddress if specified. If the value ends in '%' then the threshold is defined relative to MaxBytes. =head2 ThreshMaxI (PER TARGET) Works the same as TheshMinI but it acts when the value is higher than ThreshMaxI. =head2 ThreshDesc (PER TARGET) Its value will be assigned to the environment variable THRESH_DESC before any of the programs mentioned below are called. The programs can use the value of this variable to produce more user-friendly output. =head2 ThreshProgI (PER TARGET) This defines a program to be run if ThreshMinI or ThreshMaxI is broken. MRTG passes 3 arguments: the $router variable, the threshold value broken, and the current parameter value. =head2 ThreshProgOKI (PER TARGET) This defines a program to be run if the parameter is currently OK (based on ThreshMinI and ThreshMaxI), but wasn't OK on the previous running -- based on the files found in ThreshDir. MRTG passes 3 arguments: the $router variable the unbroken threshold value, and the current parameter value. =head2 ThreshMinO, ThreshMaxO, ThreshProgO, and ThreshProgOKO These work the same as their *I counterparts, except on the Output (second) parameter. =head2 SetEnv When calling threshold scripts from within your cfg file you might want to pass some data on to the script. This can be done with the SetEnv configuration option which takes a series of environment variable assignments. Note that the quotes are mandatory. This does not work for external scripts. It is not possible to set environment variables per target. Example: SetEnv[myrouter]: EMAIL="contact_email@someplace.net" HOST="www.some_server.net" =head2 HW Failure Based Threshold Checking When using rrd based logging with HW RRAs defined. You can use the confidence bounds violations stored in the FAILURES RRA for threshold based alerts. There the all target specific threshold variables have a Hold-Winters counterpart: ThreshMailAddress -> HWThreshMailAddress ThreshMinI -> HWThreshMinI ... The global variables for threshold checking are shared except for the ThreshHyst -> HWThreshHyst And HWThreshDesc sets the HWTHRESH_DESC variable. =head1 PER TARGET DEFAULT VALUES =head2 Pre- and Postfix To save yourself some typing you can define a target called '^'. The text of every Keyword you define for this target will be PREPENDED to the corresponding Keyword of all the targets defined below this line. The same goes for a Target called '$' but its text will be APPENDED. Note that a space is inserted between the prepended text and the Keyword value, as well as between the Keyword value and the appended text. This works well for text-valued Keywords, but is not very useful for other Keywords. See the "default" target description below. The example will make mrtg use a common header and a common contact person in all the pages generated from targets defined later in this file. Example: PageTop[^]:

      NoWhere Unis Traffic Stats


      PageTop[$]: Contact Peter Norton if you have any questions
      To remove the prepend/append value, specify an empty value, e.g.: PageTop[^]: PageTop[$]: =head2 NoSpaceChar With PREPEND and APPEND (see below) there is normally a space inserted between the local value and the PRE- or APPEND value. Sometimes this is not desirable. You can use the global option I to define a character which can be mentioned at the end of a $ or ^ definition in order to suppress the space. Example: NoSpaceChar: ~ Target[^]: 1.3.6.1.4.1.482.50.2.4.20.0&1.3.6.1.4.1.482.50.2.4.21.0:get@~ Target[a]: a.tolna.net Target[b]: b.tolna.net Target[c]: c.tolna.net Target[d]: d.tolna.net =head2 Default Values The target name '_' specifies a default value for that Keyword. In the absence of explicit Keyword value, the prepended and the appended keyword value, the default value will be used. Example: YSize[_]: 150 Options[_]: growright,bits,nopercent WithPeak[_]: ymw Suppress[_]: y MaxBytes[_]: 1250000 To remove the default value and return to the 'factory default', specify an empty value, e.g.: YLegend[_]: There can be several instances of setting the default/prepend/append values in the configuration file. The later setting replaces the previous one for the rest of the configuration file. The default/prepend/append values used for a given keyword/target pair are the ones that were in effect at the point in the configuration file where the target was mentioned for the first time. Example: MaxBytes[_]: 1250000 Target[myrouter.somplace.edu.2]: 2:public@myrouter.somplace.edu MaxBytes[_]: 8000 Title[myrouter.somplace.edu.2]: Traffic Analysis for myrouter.somplace.edu IF 2 The default I for the target myrouter.someplace.edu.2 in the above example will be 1250000, which was in effect where the target name myrouter.someplace.edu.2 first appeared in the config file. =head1 COMMAND LINE OPTIONS =over =item B<--user> I and B<--group> I Run as the given user and/or group. (Unix Only) =item B<--lock-file> I Use an alternate lock-file (the default is to use the configuration-file appended with C<_l>). =item B<--confcache-file> I Use an alternate confcache-file (the default is to use the configuration-file appended with C<.ok>) =item B<--logging> I|B If this is set to writable filename, all output from mrtg (warnings, debug messages, errors) will go to I. If you are running on Win32 you can specify B instead of a filename which will send all error to the windows event log. B Note, there is no Message DLL for mrtg included with mrtg. This has the side effect that the windows event logger will display a nice message with every entry in the event log, complaining about the fact that mrtg has no message dll. If you go to the mrtg contrib download area (on the website) you will find the mrtg-message-dll.zip which does contain such a thing. =item B<--daemon> Put MRTG into the background, running as a daemon. This works the same way as the config file option, but the switch is required for proper FHS operation (because /var/run is writable only by root) =item B<--fhs> Configure all mrtg paths to conform to the FHS specification; http://www.pathname.com/fhs/ =item B<--check> Only check the cfg file for errors. Do not do anything. =item B<--pid-file=s> Define the name and path of the pid file for mrtg running as a daemon =item B<--debug=s> Enable debug options. The argument of the debug option is a comma separated list of debug values: cfg - watch the config file reading dir - directory mangeling base - basic program flow tarp - target parser snpo - snmp polling coca - confcache operations fork - forking view time - some timing info log - logging of data via rateup or rrdtool eval - print eval strings before evaluating them prof - add hires timing info the rrd calls Example: --debug="cfg,snpo" =back =head1 EXIT CODES An exit code of 0 indicates that all targets were successful. Generally speaking, most codes greater than 0 indicate that there was an unrecoverable problem. One exception to this is code 91, which indicates that at least one of the targets was successful. A partial listing of the codes follows: 0: All targets successful 2: Config error (can't read, fatal error in config, etc) 17: Another MRTG process is processing config 91: At least one target successful 92: No targets were successful =head1 EXAMPLES =head2 Minimal mrtg.cfg WorkDir: /usr/tardis/pub/www/stats/mrtg Target[r1]: 2:public@myrouter.somplace.edu MaxBytes[r1]: 8000 Title[r1]: Traffic Analysis ISDN PageTop[r1]:

      Stats for our ISDN Line

      =head2 Cfg for several Routers. WorkDir: /usr/tardis/pub/www/stats/mrtg Title[^]: Traffic Analysis for PageTop[^]:

      Stats for PageTop[$]: Contact The Chief if you notice anybody
      MaxBytes[_]: 8000 Options[_]: growright Title[isdn]: our ISDN Line PageTop[isdn]: our ISDN Line

      Target[isdn]: 2:public@router.somplace.edu Title[backb]: our Campus Backbone PageTop[backb]: our Campus Backbone Target[backb]: 1:public@router.somplace.edu MaxBytes[backb]: 1250000 # the following line removes the default prepend value # defined above Title[^]: Title[isdn2]: Traffic for the Backup ISDN Line PageTop[isdn2]: our ISDN Line Target[isdn2]: 3:public@router.somplace.edu =head1 AUTHOR Tobias Oetiker Etobi@oetiker.chE and many contributors mrtg-2.17.10/doc/mrtg-rrd.pod0000644000175300017510000000744414171763414014676 0ustar oetikeroep=head1 NAME mrtg-rrd - How to use RRDtool with MRTG =head1 SYNOPSIS After using MRTG for some time you may find some limitations, mostly in the areas of performance and graphing flexibility. These are exactly the areas addressed by RRDtool. To learn more about RRDtool check out its website on http://oss.oetiker.ch/rrdtool =head1 RRDTOOL INTEGRATION When using mrtg with RRDtool you are replacing F with the RRDtool perl module F. To enable RRDtool support in mrtg you have to add the line LogFormat: rrdtool to your mrtg config file. MRTG needs access to both the RRDtool perl module B and to the B executable. If these two items are not installed in locations where perl can find them on its own, then you can use the following two parameters to supply the appropriate directories. For the location of the B executable you put PathAdd: /usr/local/rrdtool/bin/ or PathAdd: c:\rrdtool\bin For the location of the perl module it would be: LibAdd: /usr/local/rrdtool/lib/perl/ or LibAdd: c:\rrdtool\bin\lib\perl When you have made this modification to the configuration file, several things will happen when you run mrtg again with the new config file: =over =item 1. mrtg will take all your old C<.log> files and B them to C<.rrd> format. (The C<.log> files don't get touched in the process, so if things don't work out they are still there.) =item 2. mrtg will use B to update its databases. These will have a new format called I which is totally different than the native I format of the classic mrtg. =item 3. mrtg will B create any webpages of graphs anymore. It will only query the routers for traffic information and update its I databases. =back The advantage of whole thing is that the mrtg will become B faster. Expect the runtime to drop to 20% of the previous value. (I would like to get some feedback on this from folks with large installations.) Mind you, though, while the logging process of RRDtool is B fast, you are also gaining some time by neither creating graphs nor updating webpages. The idea behind this is that it is more efficient to create graphs and webpages on demand by using a cgi script. At the moment there is no B script to do this, but two contributors have created such scripts: =over =item One4All aka 14all.cgi This was the first program to take over the webpage creation and graphing task. It has been developed by Rainer Bawidamann rainer.bawidamann@web.de. You can find a copy on Rainers website: http://my14all.sourceforge.net/ The program comes with its own documentation =item B This is another CGI frontend for mrtg running with rrdtool. The main difference between this and 14all is that the web pages it creates are much more stylish than the ones from mrtg, plus they support User Defined summary graphs and different levels of Authentication and Authorisation. This has been written by Steve Shipway (steve@steveshipway.org). You obtain a copy, and find a forum and demonstration system at http://www.steveshipway.org/software/ The program comes with its own installation instructions and install script. =item B The mrtg-rrd script is a CGI/FastCGI application by Jan "Yenya" Kasprzak for displaying MRTG graphs from data in the RRDtool format. It is an intended replacement for the 14all.cgi script. It can make your monitoring system faster because MRTG does not have to generate all the PNG files with graphs every 5 minutes or so. Instead of this the graphs are generated on-demand when the user wants to see them. http://www.fi.muni.cz/~kas/mrtg-rrd/ =back =head1 FUTURE Just as a side note: MRTG-3 will be based entirely on rrdtool technology. But don't wait for it ... get going B! =head1 AUTHOR Tobias Oetiker Etobi@oetiker.chE mrtg-2.17.10/doc/mrtg-squid.pod0000644000175300017510000000671214171763414015231 0ustar oetikeroep=encoding utf8 =head1 NAME mrtg-squid - using mrtg to monitor Squid =head1 DESCRIPTION Squid 2.3 knows SNMP and you can therefore use mrtg to monitor it quite easily. I have made some modifications to mrtg which simplify this. My work is based on earlier modification made by: matija.grabnar@arnes.si and kostas@nlanr.net. =head1 MODIFICATIONS I added new code for displaying correct units to the previous patches "perminute" and "perhour" ("option" tokens), which allows other measurement in addition to "persecond". Then I created a new option token "dorelpercent" which allows the calculation of the percentage of IN-stream / OUT-stream on the fly and then displays it on a fixed scale from 0% to 100%. For my requirements, this does good work. Maybe someone wants a floating scale. It should not be a problem to implement it, too (but give me an option to keep my fixed scale). If IN-stream is always less than OUT-stream both lines (OUT-stream and relative percent) are always displayed on top of IN-stream bulk. Otherwise this option makes no sense. With this option you can display hitrates, errorrates (for router monitoring: rel. droprates) easily now. If you use this options please consider that you need a 5th colourname/value pair in your Colours statements! Due to some discussion on this list, I have implemented two tokens too: "kilo" and "kMG" "kilo" should contain the value of k (1000 or 1024), where 1000 is the default. "kMG" is a comma separated list of multiplier prefixes, used instead of "", "k", "M", "G", "T" on the MRTG display. Leave the place free, if you want no prefix. Also an incomplete list of OIDs for the new SQUID release is added. You may need to turn on snmp_port in squid.conf to as it is disabled by default. I hope you enjoy it. =head1 CONFIG EXAMPLE First load the squid mib LoadMIBs: /usr/share/squid/mib.txt You can measure responsetimes in ms and display it with MRTG correctly with: kMG[measure-ms]: m,,k,M,G,T short[measure-ms]: s You can display now MB/s as 1024*1024 B/s with: kilo[volume]: 1024 Assuming you're not running squid's SNMP on the default snmp port, you need to include a port number in your target line: Target[proxy-hit]: cacheHttpHits&cacheProtoClientHttpRequests:public@localhost:3401 A sample config for squid: Target[proxy-hit]: cacheHttpHits&cacheProtoClientHttpRequests:public@proxy Title[proxy-hit]: HTTP Hits PageTop[proxy-hit]:

      proxy Cache Statistics: HTTP Hits / Requests

      Suppress[proxy-hit]: y LegendI[proxy-hit]: HTTP hits LegendO[proxy-hit]: HTTP requests Legend1[proxy-hit]: HTTP hits Legend2[proxy-hit]: HTTP requests YLegend[proxy-hit]: perminute ShortLegend[proxy-hit]: req/min Options[proxy-hit]: nopercent, perminute, dorelpercent Target[proxy-srvkbinout]: cacheServerInKb&cacheServerOutKb:public@proxy Title[proxy-srvkbinout]: Cache Server Traffic In / Out PageTop[proxy-srvkbinout]:

      Cache Statistics: Server traffic volume (In/Out)

      Suppress[proxy-srvkbinout]: y LegendI[proxy-srvkbinout]: Traffic In LegendO[proxy-srvkbinout]: Traffic Out Legend1[proxy-srvkbinout]: Traffic In Legend2[proxy-srvkbinout]: Traffic Out YLegend[proxy-srvkbinout]: per minute ShortLegend[proxy-srvkbinout]: b/min kMG[proxy-srvkbinout]: k,M,G,T kilo[proxy-srvkbinout]: 1024 Options[proxy-srvkbinout]: nopercent, perminute =head1 AUTHOR Andreas Papst Eandreas.papst@univie.ac.atE Dirk-Lder Kreie Edeelkar@gmx.deE Chris Chiappa Echris+debian@chiappa.netE mrtg-2.17.10/doc/mrtg-traffic-sum.pod0000777000175300017510000000000014171763413022407 2../bin/mrtg-traffic-sumustar oetikeroepmrtg-2.17.10/doc/mrtg-unix-guide.pod0000644000175300017510000002306414171763414016161 0ustar oetikeroep=head1 NAME mrtg-unix-guide - The MRTG 2.17.10 Linux/Unix Installation Guide =head1 DESCRIPTION MRTG comes to you in Source Code. This means that you have to compile parts of it before you can use it on a Unix machine. These instructions help you to do so. =head1 PREPARATION In order to compile and use mrtg you need a C compiler and a copy of perl installed on your machine. In most cases this will already be available. In case it is not, here are some starting points. Below I'll give you a detailed run through the whole compilation process. =over =item GCC The GNU C compiler comes preinstalled on most of the free Unices out there. For commercial derivatives you may have to download and compile it first. If you have no compiler at all there is a chicken and egg problem, but there are also precompiled versions of gcc available for most operating systems. http://gcc.gnu.org/ =item Perl Large parts of the MRTG system are written in the Perl scripting language. Make sure there is a recent copy of perl on your machine (try perl -v). At least version 5.005 is required for mrtg to work well. If you use SNMPV3 and other new features you should use at least 5.8. You can get the latest perl from http://www.perl.com/ =back MRTG generates traffic graphs in the PNG format. To be able to do this it needs several 3rd party libraries. When compiling these libraries I urge you to make sure you compile them as B libraries. There is just much less trouble ahead if you are doing it like this. See the Instructions in the next section for inspiration. Note that many free unices have all the required libraries already in place so there is no need to install another copy. To check it is best to skip all the library instructions below and go straight into the mrtg compile. If the first attempt fails and you do not get a working version of mrtg, try compiling new copies of all libraries as explained below. Do this B you send email to me about problems compiling mrtg. =over =item gd This is a basic graph drawing library created by Thomas Boutell. Note that all releases after Version 1.3 only create PNG images. This is because a) Thomas got into trouble because the GIF format which it used to produce uses a compression technology patented by Unisys. b) PNG is more efficient and patent free. MRTG can work with old and new version of the GD library. You can get a recent copy of GD from: http://www.boutell.com/gd/ =item libpng Is required by gd in order to produce PNG graphics files. Get it from: http://www.libpng.org/pub/png/libpng.html =item zlib Is needed by libpng to compress the graphics files you create. Get a copy from http://www.gzip.org/zlib =back And last but not least you also need mrtg itself. In case you have not yet downloaded it, you can find a copy on my website: http://oss.oetiker.ch/mrtg/pub =head1 LIBRARY COMPILATION In this section I will give you step by step instructions on how to compile the various libraries required for the compilation of mrtg. Note that these libraries may already be installed if you have a I<*BSD> or I system so you can skip recompiling them. The B program used below is a simple web downloader. You can also enter the address into your B if you don't have B available. First let's create a directory for the compilation. Note that this may already exist on your system. No problem, just use it. mkdir -p /usr/local/src cd /usr/local/src If you do not have zlib installed: wget http://www.zlib.net/zlib-1.2.3.tar.gz gunzip -c zlib-*.tar.gz | tar xf - rm zlib-*.tar.gz mv zlib-* zlib cd zlib ./configure make cd .. If you don't have libpng installed wget ftp://ftp.simplesystems.org/pub/libpng/png/src/libpng-1.2.40.tar.gz gunzip -c libpng-1.2.34.tar.gz | tar xf - mv libpng-* libpng cd libpng env CFLAGS="-O3 -fPIC" ./configure --prefix=$INSTALL_DIR make rm *.so.* *.so cd .. And now you can compile gd For versions up to 1.8.4, try: wget http://www.boutell.com/gd/http/gd-1.8.4.tar.gz gunzip -c gd-*.tar.gz |tar xf - rm gd-*.tar.gz mv gd-* gd cd gd The \ characters at the end of the following lines mean that all the following material should actually be written on a single line. perl -i~ -p -e s/gd_jpeg.o//g Makefile make INCLUDEDIRS="-I. -I../zlib -I../libpng" \ LIBDIRS="-L../zlib -L. -L../libpng" \ LIBS="-lgd -lpng -lz -lm" \ CFLAGS="-O -DHAVE_LIBPNG" cd .. For versions starting around 2.0.11, try: wget http://www.boutell.com/gd/http/gd-2.0.33.tar.gz gunzip -c gd-2.0.33.tar.gz |tar xf - mv gd-2.0.33 gd cd gd env CPPFLAGS="-I../zlib -I../libpng" LDFLAGS="-L../zlib -L../libpng" \ ./configure --disable-shared --without-freetype --without-jpeg make cp .libs/* . =head1 MRTG COMPILATION Ok, now everything is ready for the mrtg compilation. cd /usr/local/src gunzip -c mrtg-2.17.10.tar.gz | tar xvf - cd mrtg-2.17.10 If all the libraries have been preinstalled on your system you can configure mrtg by doing a simple: ./configure --prefix=/usr/local/mrtg-2 Otherwise you may have to give some hints on where to find the various libraries required to compile mrtg: ./configure --prefix=/usr/local/mrtg-2 \ --with-gd=/usr/local/src/gd \ --with-z=/usr/local/src/zlib \ --with-png=/usr/local/src/libpng If you have RRDtool available you might want to tell mrtg about it so that you can opt to use rrdtool with mrtg. Check L. Configure will make sure your environment is fit for building mrtg. If it finds a problem, it will tell you so and it will also tell you what to do about it. If everything is OK, you will end up with a custom Makefile for your system. Now type: make This builds the rateup binary and edits all the perl pathnames in the scripts. You can now install mrtg by typing make install (requires gnu install) All the software required by MRTG is now installed under the F subdirectory. You can now safely delete the libraries we compiled above. Then again, you might want to keep them around so that you have them available when compiling the next version of mrtg. =head1 CONFIGURATION The next step is to configure mrtg for monitoring a network device. This is done by creating an F file which defines what you want to monitor. Luckily, you don't have to dive straight in and start writing your own configuration file all by yourself. Together with mrtg you also got a copy of B. This is a script you can point at a router of your choice; it will create a mrtg configuration file for you. You can find the script in the F subdirectory. cfgmaker --global 'WorkDir: /home/httpd/mrtg' \ --global 'Options[_]: bits,growright' \ --output /home/mrtg/cfg/mrtg.cfg \ community@router.abc.xyz This example above will create an mrtg config file in F assuming this is a directory visible on your webserver. You can read all about cfgmaker in L. One area you might want to look at is the possibility of using B<--ifref=ip> to prevent interface renumbering troubles from catching you. If you want to start rolling your own mrtg configuration files, make sure you read L to learn all about the possible configuration options. =head1 RUNNING MRTG Once you have created a configuration file, try the following: /usr/local/mrtg-2/bin/mrtg /home/mrtg/cfg/mrtg.cfg This will query your router and also create your first mrtg traffic graphs and webpages. When you run mrtg for the first time there will be a lot of complaints about missing log files. Don't worry, this is normal for the first 2 times you start mrtg. If it keeps complaining after this time you might want to look into the problem. Starting mrtg by hand is not ideal in the long run. So when you are satisfied with the results you can automate the process of running mrtg in regular intervals (this means every 5 minutes by default). You can either add mrtg to your crontab with a line like this: 0,5,10,15,20,25,30,35,40,45,50,55 * * * * \ /mrtg /mrtg.cfg \ --logging /var/log/mrtg.log or if you live in Linux Land the line may look like this if you are using C */5 * * * * /mrtg /mrtg.cfg \ --logging /var/log/mrtg.log or like this if you use F */5 * * * * mrtg-user /mrtg /mrtg.cfg \ --logging /var/log/mrtg.log You can also run mrtg as a daemon process by adding the line RunAsDaemon: Yes to your mrtg configuration file and then creating a startup script in your system startup sequence. Unfortunately, adding startup scripts differs widely amongst different unix systems. The modern ones normally have a directory called F or F where you put scripts which starts the process you want to run when the system boots. Further you must create a symbolic link in F or F called F (this is just a sample name ... it is just important that it starts with S followed by a two digit number). If you are not sure about this, make sure you consult the documentation of your system to make sure you get this right. A B script to put into F might look like this: #! /bin/sh cd /usr/local/mrtg-2.17.10/bin && ./mrtg --user=mrtg-user \ /home/httpd/mrtg/mrtg.cfg --logging /var/log/mrtg.log Note that this will only work with B in your mrtg.cfg file. =head1 AUTHOR Tobias Oetiker Etobi@oetiker.chE mrtg-2.17.10/doc/mrtg-webserver.pod0000644000175300017510000000320114171763414016076 0ustar oetikeroep=head1 NAME mrtg-webserver - hints for web server configuration =head1 SYNOPSIS If you want people to actually see the results of your network monitoring efforts you will need a webserver. This document lists some configuration hints for webservers. Contributions welcome. =head1 APACHE =head2 Configuring mod_expire A big issue with mrtg monitoring data is the expiry time. All these nice graphs you can create are only valid for a short time. If you do not take special action some webbrowsers will not notice this and you may end up with people seeing old data because of caching issues. The apache module mod_expire allows you to setup special expiry properties for individual file. Here is an example for how this may look for an mrtg web directory. The configuration directives can be stored into a F<.htaccess> file. ############################################################ # Example .htaccess for use with apache-1.2 and mod_expire. # (mod_expire come with apache-1.2 but you have to explicitly # activate it when compiling the httpd ...) ############################################################# # ExpiresActive On # enable expirations # five minutes ExpiresDefault M300 ExpiresActive On ExpiresDefault M1800 ExpiresActive On ExpiresDefault M7200 ExpiresActive On ExpiresDefault M86400 ExpiresActive On ExpiresDefault M300 # index.html is not automatically generated ExpiresActive Off =head1 AUTHOR Unknown mrtg-2.17.10/doc/rateup.pod0000644000175300017510000000253114171763414014430 0ustar oetikeroep=head1 NAME rateup - tool to generate images for MRTG =head1 SYNOPSIS rateup -f rateup directory basename [sampletime] [t sampletime] [-(t)ransparent] [-(b)order] [u|a|g|h|m in out abs_max] [i/p file maxvi maxvo maxx maxy growright step bits] =head1 DESCRIPTION rateup is a fast add-on to the great MRTG Traffic monitor. It makes the database file updates much faster, and creates the graphic image files, ready for processing by PPMTOGIF. It also reduces memory requirements by a factor of 10, and increases the speed of updates by a factor of at least 10. This makes it feasible to run mrtg every 5 minutes. rateup attempts to compensate for missed updates by repeating the last sample, and also tries to catch bad update times. The .log file stores real history every five minutes for 31 hours, then 'compresses' the history into 30 minute samples for a week, then 2-hour samples for 31 days, then daily samples for two years. This ensures that the log files don't grow in size. The log files are a slightly different format, but convert.perl will fix that for you. =head1 AUTHOR Dave Rand , Tobias Oetiker , Alexandre Steinberg =head1 SEE ALSO L, L, L, L, L, L mrtg-2.17.10/doc/cfgmaker.10000644000175300017510000017214714171763416014302 0ustar oetikeroep.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "CFGMAKER 1" .TH CFGMAKER 1 "2022-01-19" "2.17.10" "mrtg" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" cfgmaker \- Creates mrtg.cfg files (for mrtg\-2.17.10) .SH "SYNOPSIS" .IX Header "SYNOPSIS" cfgmaker [options] [community@]router [[options] [community@]router ...] .SH "OPTIONS" .IX Header "OPTIONS" .Vb 9 \& \-\-ifref=name interface references by Interface Name (default) \& \-\-ifref=ip ... by Ip Address \& \-\-ifref=eth ... by Ethernet Number \& \-\-ifref=descr ... by Interface Description \& \-\-ifref=nr ... by Interface Number \& \-\-ifref=type ... by Interface Type \& You may also use multiple options separated by commas, \& in which case the first available one is used: \& e.g. \-\-ifref=ip,name,nr \& \& \-\-ifdesc=nr interface description uses Interface Number (default) \& \-\-ifdesc=ip ... uses Ip Address \& \-\-ifdesc=eth ... uses Ethernet Number \& \-\-ifdesc=descr ... uses Interface Description \& \-\-ifdesc=name ... uses Interface Name \& \-\-ifdesc=catname ... uses CatOS Interface Name \& \-\-ifdesc=ppname ... uses Passport Port Name \& \-\-ifdesc=alias ... uses Interface Alias \& \-\-ifdesc=type ... uses Interface Type \& You may also use multiple options separated by commas, \& in which case the first available one is used: \& e.g. \-\-ifdesc=catname,ppname,descr,alias,ip,name,nr \& \& \-\-if\-filter=f Test every interface against filter f to decide whether \& or not to include that interface into the collection. \& Currently f is being evaluated as a Perl expression \& and it\*(Aqs truth value is used to reject or accept the \& interface. \& (Experimental, under development, might change) \& \& \-\-if\-template=templatefile \& Replace the normal target entries for the interfaces \& with an entry as specified by the contents in the file \& templatefile. The file is supposed to contain Perl \& code to be executed to generate the lines for the \& target in the configuration file. \& (Experimental, under development, might change) \& \& \-\-host\-template=templatefile \& In addition to creating targets for a host\*(Aqs interfaces \& do also create targets for the host itself as specified \& by the contents in the file templatefile. The file is \& supposed to contain Perl code to be executed to generate \& the lines for the host related targets (such as CPU, \& ping response time measurements etc.) in the config\- \& uration file. \& (Experimental, under development, might change) \& \& \-\-global "x: a" add global config entries \& \& \-\-nodefaultglobal do not include default global settings \& \& \-\-no\-down do not look at admin or opr status of interfaces \& \& \-\-show\-op\-down show interfaces which are operatively down \& \& \-\-zero\-speed=spd use this speed in bits\-per\-second as the interface \& speed for all interfaces that return a speed of 0 \& via ifSpeed/ifHighSpeed. 100Mbps = 100000000 \& \& \-\-subdirs=format give each router its own subdirectory, naming each per \& "format", in which HOSTNAME and SNMPNAME will be \& replaced by the values of those items \-\- for instance, \& \-\-subdirs=HOSTNAME or \-\-subdirs="HOSTNAME (SNMPNAME)" \& \& \-\-noreversedns do not reverse lookup ip numbers \& \& \-\-community=cmty Set the default community string to "cmty" instead of \& "public". \& \& \-\-enable\-ipv6 Enable IPv6 support, if the required libraries are \& present. Numeric IPv6 addresses must be enclosed \& in square brackets, e.g. public@[2001:760:4::1]:161 \& \& \-\-use\-16bit Use 16bit SNMP request IDs to query all routers. \& \& \-\-snmp\-options=:[][:[][:[][:[][:]]]] \& \& Specify default SNMP options to be appended to all \& routers following. Individual fields can be empty. \& Routers following might override some or all of the \& options given to \-\-snmp\-options. \& \& \-\-dns\-domain=domain \& Specifies a domain to append to the name of all \& routers following. \& \& \-\-nointerfaces Don\*(Aqt do generate any configuration lines for interfaces, \& skip the step of gathering interface information and \& don\*(Aqt run any interface template code. \& \& \-\-interfaces Generate configuration lines for interfaces (this is the \& default). The main purpose of this option is to negate \& an \-\-nointerfaces appearing earlier on the command line. \& \& \-\-help brief help message \& \-\-man full documentation \& \-\-version print the version of cfgmaker \& \& \-\-output=file output filename default is STDOUT .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" \&\fBCfgmaker\fR creates \s-1MRTG\s0 configuration files based on information pulled from a router or another \s-1SNMP\s0 manageable device. .PP [\fIcommunity\fR\fB@\fR]\fIrouter\fR .PP \&\fICommunity\fR is the community name of the device you want to create a configuration for. If not specified, it defaults to '\fBpublic\fR'; you might want to try this first if you do not know the community name of a device. If you are using the wrong community name you will get no response from the device. .PP \&\fIRouter\fR is the \s-1DNS\s0 name or the \s-1IP\s0 number of an SNMP-manageable device. Following the name you can specify 6 further options separated by colons. The full syntax looks like this: .PP \&\fBrouter\fR[:[\fBprt\fR][:[\fBtmout\fR][:[\fBretr\fR][:[\fBbackoff\fR][:\fBvers\fR]]]]] .PP Of special interest may be the last parameter, \fBvers\fR. If you set this to \&'2' then your device will be queried with \s-1SNMP\s0 version 2 requests. This allows you to poll the 64 bit traffic counters in the device and will thus work much better with fast interfaces (no more counter overrun). Note that the order in which the routers are specified on the command line do matter as the same order is used when the configuration file is generated. The first specified router has it's configuration lines generated first, followed by the lines belonging to the next router and so on. .PP Note that the first line of the generated cfg file will contain all the commandline options you used for generating it. This is to allow for the easy 'regeneration' in case you want to add newhosts or make some other global change. .SS "Configuration" .IX Subsection "Configuration" Except for the \fB\-\-output\fR and \fB\-\-global\fR options, all options affect only the routers following them on the command line. If an option specified earlier on the command line reappears later on the command line with another value, the new value overrides the old value as far as remaining routers are concerned. This way options might be tailored for groups of routers or for individual routers. .PP See \fB\-\-output\fR and \fB\-\-global\fR for how their behaviour is affected by where or how many times they appear on the command line. .PP See the \fBExamples\fR below on how to set an option differently for multiple routers. .IP "\fB\-\-help\fR" 4 .IX Item "--help" Print a brief help message and exit. .IP "\fB\-\-man\fR" 4 .IX Item "--man" Prints the manual page and exits. .IP "\fB\-\-version\fR" 4 .IX Item "--version" Print the version of cfgmaker. This should match the version of \s-1MRTG\s0 for which config files are being created. .IP "\fB\-\-ifref\fR \fBnr\fR|\fBip\fR|\fBeth\fR|\fBdescr\fR|\fBname\fR" 4 .IX Item "--ifref nr|ip|eth|descr|name" Select the interface identification method. Default is \fBnr\fR which identifies the router interfaces by their number. Unfortunately the interface numbering scheme in an \s-1SNMP\s0 tree can change. Some routers change their numbering when new interfaces are added, others change their numbering every full moon just for fun. .Sp To work around this sad problem \s-1MRTG\s0 can identify interfaces by 4 other properties. None of these works for all interfaces, but you should be able to find one which does fine for you. Note that especially ethernet addresses can be problematic as some routers have the same ethernet address on most of their interface cards. .Sp Select \fBip\fR to identify the interface by its \s-1IP\s0 number. Use \fBeth\fR to use the ethernet address for identification. Use \fBdescr\fR to use the Interface description. Or use \fBname\fR to use the Interface name. .Sp You can specify multiple properties if you wish, separated by commas. In this case, cfgmaker will use the first item in the list which can provide unique identification. This allows you to specify, for example, to use \s-1IP\s0 address and to use ifName if this is not defined: \-\-ifref ip,name .Sp If your chosen method does not allow unique interface identification on the device you are querying, \fBcfgmaker\fR will tell you about it. .IP "\fB\-\-ifdesc\fR \fBnr\fR|\fBip\fR|\fBeth\fR|\fBdescr\fR|\fBname\fR|\fBtype\fR|\fBalias\fR" 4 .IX Item "--ifdesc nr|ip|eth|descr|name|type|alias" Select what to use as the description of the interface. The description appears in the \f(CW\*(C`Title[]\*(C'\fR property for the target as well as the text header in the \s-1HTML\s0 code defined in the target's \f(CW\*(C`PageTop[]\*(C'\fR. Default is to use \&\fBnr\fR which is just the interface number which isn't always useful to the viewer of the graphs. .Sp There are 6 other properties which could be used. Use \fBip\fR if you want to use the interface's IP-address. Use \fBeth\fR if you want to use the interface's ethernet address. If you want a better description, you can use either \fBdescr\fR, \fBname\fR or \fBalias\fR. Exactly what each of these do varies between different equipment so you might need to experiment. For instance, for a serial interface on a Cisco router running \s-1IOS\s0 using \fBname\fR might result in \f(CW"S0"\fR being the interface description , \fBdescr\fR might result in \f(CW"Serial0"\fR and \fBalias\fR might result in \f(CW"Link to HQ"\fR (provided that is what is used as the interface's \f(CW\*(C`description\*(C'\fR in the router's configuration). .Sp Finally, if you want to describe the interface by it's Btype (i.e \f(CW"ethernetCSMA"\fR, \f(CW"propPointtoPoint"\fR etc) you can use \fBtype\fR. .Sp You can specify multiple properties if you wish, separated by commas. In this case, cfgmaker will use the first item in the list which is available for this interface. This allows you to specify, for example, to use any of the different aliases in order of preference. .IP "\fB\-\-if\-filter\fR '\fBfilter-expression\fR'" 4 .IX Item "--if-filter 'filter-expression'" First of all, this is under some development and is experimental. .Sp Use this if you want to have better control over what interfaces gets included into the configuration. The \fBfilter-expression\fR is evaluated as a piece of Perl code and is expected to return a truth value. If true, include the interface and if false, exclude the interface. .Sp For a further discussion on how these filters work, see the section \&\*(L"Details on Filters\*(R" below. .IP "\fB\-\-if\-template\fR \fBtemplate-file\fR" 4 .IX Item "--if-template template-file" First of all, this is under some development and is experimental. .Sp Use this if you want to control what the line for each target should look like in the configuration file. The contents of the file \fBtemplate-file\fR will be evaluated as a Perl program which generates the lines using certain variables for input and output. .Sp For a further discussion on how these templates work, see the section \&\*(L"Details on Templates\*(R" below. .IP "\fB\-\-host\-template\fR \fBtemplate-file\fR" 4 .IX Item "--host-template template-file" First of all, this is under some development and is experimental. .Sp Use this if you want to have some extra targets related to the host itself such as \s-1CPU\s0 utilization, ping response time to the host, number of busy modems etc. The contents of the file \fBtemplate-file\fR will be evaluated once per host as a Perl program which generates the lines using certain variables for input and output. .Sp For a further discussion on how these templates work, see the section \&\*(L"Details on Templates\*(R" below. .IP "\fB\-\-community\fR \fBcommunity-string\fR" 4 .IX Item "--community community-string" Use this to set the community for the routers following on the command line to \fBcommunity-string\fR. Individual routers might override this community string by using the syntax \fBcommunity\fR\fB@\fR\fBrouter\fR. .IP "\fB\-\-enable\-ipv6\fR" 4 .IX Item "--enable-ipv6" This option enables IPv6 support. It requires the appropriate perl modules; if they are not found then IPv6 is disabled (see the ipv6 documentation). .Sp cfgmaker will use IPv6 or IPv4 depending on the target. If the target is a numeric address, the protocol depends on the type of address. If the target is a hostname, cfgmaker will try to resolve the name first to an IPv6 address then to an IPv4 address. .Sp IPv6 numeric addresses must be specified between square braces. .Sp For example: .Sp .Vb 1 \& cfgmaker \-\-enable\-ipv6 [2001:760:4::1]:165:::2 .Ve .Sp If the target has both an IPv6 address and an IPv4 address with the same hostname, cfgmaker first queries the target using IPv6 and falls back to IPv4 if it fails. This is useful for targets which don't support \s-1SNMP\s0 over IPv6. .IP "\fB\-\-use\-16bit\fR" 4 .IX Item "--use-16bit" This option forces the use of 16bit \s-1SNMP\s0 request IDs. Some broken \s-1SNMP\s0 agents do not accept 32bit request IDs. Try to avoid this option as much as possible, complain to your agent vendor instead. .IP "\fB\-\-snmp\-options\fR :[\fBport\fR][:[\fBtimeout\fR][:[\fBretries\fR][:[\fBbackoff\fR][:\fBversion\fR]]]]" 4 .IX Item "--snmp-options :[port][:[timeout][:[retries][:[backoff][:version]]]]" Use this to set the default \s-1SNMP\s0 options for all routers following on the command line. Individual values might be omitted as well as trailing colons. Note that routers might override individual (or all) values specified by \fB\-\-snmp\-options\fR by using the syntax .Sp \&\fBrouter\fR[:[\fBport\fR][:[\fBtimeout\fR][:[\fBretries\fR][:[\fBbackoff\fR][:\fBversion\fR]]]]] .ie n .IP "\fB\-\-global\fR \fB""\fR\fIbla: abc\fR\fB""\fR" 4 .el .IP "\fB\-\-global\fR \fB``\fR\fIbla: abc\fR\fB''\fR" 4 .IX Item "--global ""bla: abc""" Use this to add global options to the generated config file. You can call \fB\-\-global\fR several times to add multiple options. The line will appear in the configuration just before the config for the next router appearing on the command line. .Sp .Vb 1 \& \-\-global "workdir: /home/mrtg" .Ve .Sp If you want some default Options you might want to put .Sp .Vb 1 \& \-\-global "options[_]: growright,bits" .Ve .Sp Specifying \fB\-\-global\fR after the last router on the command line will create a line in the configuration file which will appear after all the routers. .IP "\fB\-\-noreversedns\fR" 4 .IX Item "--noreversedns" Do not try to reverse lookup \s-1IP\s0 numbers ... a must for \s-1DNS\s0 free environments. .IP "\fB\-\-no\-down\fR" 4 .IX Item "--no-down" Normally cfgmaker will not include interfaces which are marked anything but administratively and operationally \s-1UP.\s0 With this switch you get them all. .IP "\fB\-\-show\-op\-down\fR" 4 .IX Item "--show-op-down" Include interfaces which are operatively down. .IP "\fB\-\-zero\-speed\fR \fIspeed\fR" 4 .IX Item "--zero-speed speed" Assign this speed in bits-per-second to all interfaces which return 0 for ifSpeed and ifHighSpeed. Some switches, notably Foundry equipment, return a speed of zero for some interfaces. For example, to have all interfaces reporting zero set to 100Mbps, use \&\-\-zero\-speed=100000000. .IP "\fB\-\-subdirs\fR \fIformat\fR" 4 .IX Item "--subdirs format" Give each router its own subdirectory for the \s-1HTML\s0 and graphics (or \&.rrd) files. The directory name is the given \fIformat\fR string with a couple of pattern replacements. The string \*(L"\s-1HOSTNAME\*(R"\s0 will be replaced by the hostname of the router (however you specified it on the \fBcfgmaker\fR commandline \*(-- it may be an actual hostname or just an \&\s-1IP\s0 address), and \*(L"\s-1SNMPNAME\*(R"\s0 will be replaced with the device's idea of its own name (the same name that appears on the right side of the \&\*(L"Title\*(R" lines). For instance, a call like: .Sp .Vb 1 \& cfgmaker \-\-subdirs=HOSTNAME_\|_SNMPNAME public@10.10.0.18 .Ve .Sp would result in the generation of lines looking something like: .Sp .Vb 1 \& Directory[10.10.0.18_1]: 10.10.0.18_\|_fp2200\-bothrip\-1.3 .Ve .IP "\fB\-\-output\fR \fIfile\fR" 4 .IX Item "--output file" Write the output from \fBcfgmaker\fR into the file \fIfile\fR. The default is to use \f(CW\*(C`STDOUT\*(C'\fR. \fB\-\-output\fR is expected to appear only once on the command line. If used multiple times, the file specified by the last \&\fB\-\-output\fR will be used. .IP "\fB\-\-nointerfaces\fR" 4 .IX Item "--nointerfaces" Don't generate configuration lines for interfaces. .Sp This makes cfgmaker skip all steps related to interfaces which means it will not do any polling of the router to retrieve interface information which speeds up the execution of cfgmaker and it will neither run any interface templates. .IP "\fB\-\-interfaces\fR" 4 .IX Item "--interfaces" This makes cfgmaker generate configuration lines for interfaces (the default behaviour). .Sp The main usage of this option is to negate an \-\-nointerfaces appearing earlier on the command line. .SS "\s-1SNMP V3\s0 Options" .IX Subsection "SNMP V3 Options" \&\fBCfgmaker\fR supports \s-1SNMP V3\s0 using the \fBNet:SNMP\fR perl module. There are optional parameters affecting \s-1SNMP\s0 operation. .IP "\-\-enablesnmpv3 {yes|no}" 4 .IX Item "--enablesnmpv3 {yes|no}" The \fB\-\-enablesnmpv3\fR option is an optional flag to check for the presence of the \fBNet::SNMP\fR libraries. \fBCfgmaker\fR will try to determine whether this flag is required and will set the values automatically. .PP \fISNMPv3 Arguments\fR .IX Subsection "SNMPv3 Arguments" .PP A \s-1SNMP\s0 context is a collection of management information accessible by a \s-1SNMP\s0 entity. An item of management information may exist in more than one context and a \s-1SNMP\s0 entity potentially has access to many contexts. The combination of a contextEngineID and a contextName unambiguously identifies a context within an administrative domain. In a SNMPv3 message, the contextEngineID and contextName are included as part of the scopedPDU. All methods that generate a \s-1SNMP\s0 message optionally take a \fB\-\-contextengineid\fR and \fB\-\-contextname\fR argument to configure these fields. .IP "Context Engine \s-1ID\s0" 4 .IX Item "Context Engine ID" The \fB\-\-contextengineid\fR argument expects a hexadecimal string representing the desired contextEngineID. The string must be 10 to 64 characters (5 to 32 octets) long and can be prefixed with an optional \*(L"0x\*(R". Once the \&\fB\-\-contextengineid\fR is specified it stays with the object until it is changed again or reset to default by passing in the undefined value. By default, the contextEngineID is set to match the authoritativeEngineID of the authoritative \&\s-1SNMP\s0 engine. .IP "Context Name" 4 .IX Item "Context Name" The contextName is passed as a string which must be 0 to 32 octets in length using the \fB\-\-contextname\fR argument. The contextName stays with the object until it is changed. The contextName defaults to an empty string which represents the \*(L"default\*(R" context. .PP \fIUser-based Security Model Arguments\fR .IX Subsection "User-based Security Model Arguments" .PP The User-based Security Model (\s-1USM\s0) used by SNMPv3 requires that a securityName be specified using the \fB\-\-username\fR argument. The creation of a Net::SNMP object with the version set to SNMPv3 will fail if the \fB\-\-username\fR argument is not present. The \fB\-\-username\fR argument expects a string 1 to 32 octets in length. .PP Different levels of security are allowed by the User-based Security Model which address authentication and privacy concerns. A SNMPv3 target will derive the security level (securityLevel) based on which of the following arguments are specified. .PP By default a securityLevel of 'noAuthNoPriv' is assumed. If the \fB\-\-authkey\fR or \fB\-\-authpassword\fR arguments are specified, the securityLevel becomes \&'authNoPriv'. The \fB\-\-authpassword\fR argument expects a string which is at least 1 octet in length. Optionally, the \fB\-\-authkey\fR argument can be used so that a plain text password does not have to be specified in a script. The \&\fB\-\-authkey\fR argument expects a hexadecimal string produced by localizing the password with the authoritativeEngineID for the specific destination device. The \f(CW\*(C`snmpkey\*(C'\fR utility included with the Net::SNMP distribution can be used to create the hexadecimal string (see snmpkey). .PP Two different hash algorithms are defined by SNMPv3 which can be used by the Security Model for authentication. These algorithms are \s-1HMAC\-MD5\-96 \*(L"MD5\*(R"\s0 (\s-1RFC 1321\s0) and \s-1HMAC\-SHA\-96 \*(L"SHA\-1\*(R"\s0 (\s-1NIST FIPS PUB 180\-1\s0). The default algorithm used by the module is \s-1HMAC\-MD5\-96.\s0 This behavior can be changed by using the \fB\-\-authprotocol\fR argument. This argument expects either the string \&'md5' or 'sha' to be passed to modify the hash algorithm. .PP By specifying the arguments \fB\-\-privkey\fR or \fB\-\-privpassword\fR the securityLevel associated with the object becomes 'authPriv'. According to SNMPv3, privacy requires the use of authentication. Therefore, if either of these two arguments are present and the \fB\-\-authkey\fR or \fB\-\-authpassword\fR arguments are missing, the creation of the object fails. The \fB\-\-privkey\fR and \&\fB\-\-privpassword\fR arguments expect the same input as the \fB\-\-authkey\fR and \&\fB\-\-authpassword\fR arguments respectively. .PP The User-based Security Model described in \s-1RFC 3414\s0 defines a single encryption protocol to be used for privacy. This protocol, CBC-DES \*(L"\s-1DES\*(R"\s0 (\s-1NIST FIPS PUB 46\-1\s0), is used by default or if the string 'des' is passed to the \&\fB\-\-privprotocol\fR argument. By working with the Extended Security Options Consortium http://www.snmp.com/eso/, the module also supports additional protocols which have been defined in draft specifications. The draft http://www.snmp.com/eso/draft\-reeder\-snmpv3\-usm\-3desede\-00.txt defines the support of \s-1CBC\-3DES\-EDE\s0 \*(L"Triple-DES\*(R" (\s-1NIST FIPS 46\-3\s0) in the User-based Security Model. This protocol can be selected using the \&\fB\-\-privprotocol\fR argument with the string '3desede'. The draft http://www.snmp.com/eso/draft\-blumenthal\-aes\-usm\-04.txt describes the use of \s-1CFB128\-AES\-128/192/256 \*(L"AES\*(R"\s0 (\s-1NIST FIPS PUB 197\s0) in the \&\s-1USM.\s0 The three \s-1AES\s0 encryption protocols, differentiated by their key sizes, can be selected by passing 'aescfb128', 'aescfb192', or 'aescfb256' to the \&\fB\-privprotocol\fR argument. .SS "Details on Filters" .IX Subsection "Details on Filters" The purpose of the filters is to decide which interfaces to accept and which interfaces to reject. This decision is done for each interface by evaluating the filter expression as a piece of Perl code and investigating the result of the evaluation. If true, accept the interface otherwise reject it. .PP When working with filters, remember that Perl has it's own idea of what truth and false is. The empty string "\*(L" and the string \*(R"0" are false, all other strings are true. This further implies that any integer value of 0 is false as well as any undef value. It also implies that all references are considered true. .PP As the filter is evaluated as a Perl expression, several useful constructs in Perl are worth mentioning: .PP Expressions might be grouped by using parentheses \*(L"()\*(R". Expressions might be combined using boolean operators such as the following: .ie n .IP """\fBand\fR"" (equivalent with ""\fB&&\fR"")" 4 .el .IP "``\fBand\fR'' (equivalent with ``\fB&&\fR'')" 4 .IX Item """and (equivalent with &&"")" Boolean \*(L"and\*(R" of the two expressions, is only true if both expressions are true. Example: \fIexpression1\fR \fBand\fR \fIexpression2\fR .ie n .IP """\fBor\fR"" (equivalent with ""\fB||\fR"")" 4 .el .IP "``\fBor\fR'' (equivalent with ``\fB||\fR'')" 4 .IX Item """or (equivalent with ||"")" Boolean \*(L"or\*(R" of the two expressions, is true if either or both expressions are true. Example: \fIexpression1\fR \fBor\fR \fIexpression2\fR .ie n .IP """\fBnot\fR"" (equivalent with ""\fB!\fR"")" 4 .el .IP "``\fBnot\fR'' (equivalent with ``\fB!\fR'')" 4 .IX Item """not (equivalent with !"")" Boolean negation of a single expression. Example: \fBnot\fR \fIexpression\fR . Yet another example: \fB!\fR\fIexpression\fR .PP (For more details on this I recommend a book on Perl) .PP \fIPredefined Filter Variables\fR .IX Subsection "Predefined Filter Variables" .PP To facilitate, there are a number of predefined values available to use in the filter. Note that these variables are also available when templates interfaces are evaluated (but not host templates). .PP Caveat: All these variables' names begin with a dollar sign ($), which is a syntactic requirement for scalar variables in Perl. The danger here is that the dollar sign in many shells is an active character (often used for shell variables exactly as in Perl variables) so it is important to ensure that the Perl expression isn't evaluated by the command line shell as shell code before being passed to cfgmaker as command line arguments. In shells like Bourne shell, ksh shell or bash shell, placing the entire expression within single quotes will avoid such accidental evaluation: .PP .Vb 1 \& \*(Aq\-\-if\-filter=($default_iftype && $if_admin)\*(Aq .Ve .IP "\fB\f(CB$if_type\fB\fR" 4 .IX Item "$if_type" This is an integer specifying the interface type as per the \s-1SNMP\s0 standards and as reported by the polled device. A complete list of interface types would be impractical for this document , but there are a number predefined variables below. Normally, cfgmaker puts in the target's PageTop this iftype value within parenthesis after the name of the interface type. (e.g \*(L"propPointToPointSerial (22)\*(R"). .Sp Here's a list of some of the most common interface types by number: .Sp .Vb 10 \& 6 ethernetCsmacd \& 7 iso88023Csmacd \& 9 iso88025TokenRing \& 15 fddi \& 19 E1 \& 20 basicISDN \& 21 primaryISDN \& 22 propPointToPointSerial \& 23 ppp \& 24 softwareLoopback \& 30 ds3 \& 32 frame\-relay \& 33 rs232 \& 37 atm \& 39 sonet \& 44 frameRelayService \& 46 hssi \& 49 aal5 \& 53 propVirtual \& 62 Fast Ethernet (100BaseT) \& 63 ISDN & X.25 \& 69 Full Duplex Fast Ethernet (100BaseFX) \& 94 Asymmetric Digital Subscriber Loop (ADSL) \& 117 Gigabit Ethernet \& 134 ATM Sub Interface .Ve .IP "\fB\f(CB$default\fB\fR" 4 .IX Item "$default" True if and only if cfgmaker normally should accepted the interface based on the interfaces administrative and operational state (taking the flags \fB\-\-no\-down\fR and \fB\-\-show\-op\-down\fR into account) and it's type (and a few other things). .IP "\fB\f(CB$default_ifstate\fB\fR" 4 .IX Item "$default_ifstate" True if and only if cfgmaker would have accepted the interface based on it's operational and administrative states (also taking into account the presence of the flags \fB\-\-no\-down\fR and \fB\-\-show\-op\-down\fR). .IP "\fB\f(CB$default_iftype\fB\fR" 4 .IX Item "$default_iftype" True if and only if cfgmaker would have accepted the interface based on it's type (and a few type specific details in addition). .IP "\fB\f(CB$if_admin\fB\fR" 4 .IX Item "$if_admin" True if and only if the interface is in an administrative up state. .IP "\fB\f(CB$if_oper\fB\fR" 4 .IX Item "$if_oper" True if and only if the interface is in an operational up state. .PP A number of variables are also predefined to easily decide if an interface belong to a certain category or not. Below is all those variables listed together with which if_type numbers each variable will be true for. Note that some variables refer to other variables as well. .IP "\fB\f(CB$if_is_ethernet\fB\fR" 4 .IX Item "$if_is_ethernet" True for ethernet interfaces (nr 6, 7, 26, 62, 69 and 117). .IP "\fB\f(CB$if_is_isdn\fB\fR" 4 .IX Item "$if_is_isdn" True for various \s-1ISDN\s0 interface types (nr 20, 21, 63, 75, 76 and 77) .IP "\fB\f(CB$if_is_dialup\fB\fR" 4 .IX Item "$if_is_dialup" True for dial-up interfaces such as \s-1PPP\s0 as well as \s-1ISDN.\s0 (nr 23, 81, 82 and 108 in addition to the numbers of \&\fB\f(CB$if_is_isdn\fB\fR). .IP "\fB\f(CB$if_is_atm\fB\fR" 4 .IX Item "$if_is_atm" True for miscellaneous \s-1ATM\s0 related interface types (nr 37, 49, 107, 105, 106, 114 and 134). .IP "\fB\f(CB$if_is_wan\fB\fR" 4 .IX Item "$if_is_wan" True for \s-1WAN\s0 interfaces point to point, Frame Relay and High Speed Serial ( 22,32,44,46) .IP "\fB\f(CB$if_is_lan\fB\fR" 4 .IX Item "$if_is_lan" True for \s-1LAN\s0 interfaces (8, 9, 11, 15, 26, 55, 59, 60 and 115 in addition to the numbers of \fB\f(CB$if_is_ethernet\fB\fR). .IP "\fB\f(CB$if_is_dsl\fB\fR" 4 .IX Item "$if_is_dsl" True for \s-1ADSL, RDSL, HDSL\s0 and \s-1SDSL\s0 (nr 94, 95, 96, 97) .IP "\fB\f(CB$if_is_loopback\fB\fR" 4 .IX Item "$if_is_loopback" True for software loopback interfaces (nr 24) .IP "\fB\f(CB$if_is_ciscovlan\fB\fR" 4 .IX Item "$if_is_ciscovlan" True for Cisco \s-1VLAN\s0 interfaces (interfaces with the word Vlan or \s-1VLAN\s0 in their ifdescs) .IP "\fB\f(CB$if_vlan_id\fB\fR" 4 .IX Item "$if_vlan_id" Returns the vlan id associated with a specific port on Cisco Catalyst switches under both Catalyst \s-1OS\s0 and \s-1IOS,\s0 and 3Com switches. If it is not a vlan interface, will return undef. .IP "\fB\f(CB$if_cisco_trunk\fB\fR" 4 .IX Item "$if_cisco_trunk" Returns the trunking state of a specific port on Cisco Catalyst switches under both Catalyst \s-1OS\s0 and \s-1IOS.\s0 Returns \*(L"1\*(R" if the interface is a trunk, undef otherwise. .IP "\fB\f(CB$if_MTU\fB\fR" 4 .IX Item "$if_MTU" Returns the Maximum Transfer Unit associated with a specific port. .PP Besides that, you can also use the variables defined for templates below. Further, all the variables available in cfgmaker is at the scripts disposal even if the use of such features is discouraged. More \*(L"shortcuts\*(R" in the form of variables and functions will be made available in the future instead. .PP \fIExamples on Filters\fR .IX Subsection "Examples on Filters" .PP The following filter will not affect which interfaces gets included or excluded, it will make cfgmaker behave as normally. .PP .Vb 1 \& \*(Aq\-\-if\-filter=$default\*(Aq .Ve .PP The following filter will make cfgmaker exclude \s-1PPP\s0 (23) interfaces: .PP .Vb 1 \& \*(Aq\-\-if\-filter=$default && $if_type!=23\*(Aq .Ve .PP The following filter will make cfgmaker behave as usual except that it will consider the operational state of an interface irrelevant but still reject all interfaces which are administratively down. .PP .Vb 1 \& \*(Aq\-\-if\-filter=$if_admin && $default_iftype\*(Aq .Ve .SS "Details on Templates" .IX Subsection "Details on Templates" The contents of the template files are evaluated as a Perl program. A number or Perl variables are available for the program to read and others are used to be written to. .PP As quite a few of the predefined variables has values which are are supposed to be used in \s-1HTML\s0 code some of them have an \*(L"HTML-escaped\*(R" variant, e.g \&\f(CW$html_syslocation\fR is the \s-1HTML\s0 escaped variant of \f(CW$syslocation\fR. The \s-1HTML\s0 escaping means that the chars \*(L"<\*(R", \*(L">\*(R" and \*(L"&\*(R" are replaced by \*(L"<\*(R", \&\*(L">\*(R" and \*(L"&\*(R" and that newlines embedded in the string are prepended with \*(L"<\s-1BR\s0>\*(R" and appended with a space character (if a newline is last in the string it is not touched). .PP \fIWritable Template Variables\fR .IX Subsection "Writable Template Variables" .PP These are the variables available to store the configuration lines in. Some of them are initialized prior to the evaluation of the template but such content normally is comments for inclusion in the final configuration file so those variables might be reset to the empty string in the template code to eliminate the comments. The other way around is also possible, the contents of these variables might be extended with further information for various reasons such as debugging etc. .PP Once the template has been evaluated, the following happens: if the template is a interface template and the actual interface for some reason is rejected and thus needs to be commented out, all the lines in the variable \fB\f(CB$target_lines\fB\fR are turned into comments by adding a hash mark (\*(L"#\*(R") at their beginning. Then all the variables \fB\f(CB$head_lines\fB\fR, \&\fB\f(CB$problem_lines\fB\fR , \fB\f(CB$target_lines\fB\fR and \fB\f(CB$separator_lines\fB\fR are concatenated together to form the lines to add to the configuration file. .IP "\fB\f(CB$target_lines\fB\fR" 4 .IX Item "$target_lines" This variable is the placeholder for the configuration lines created by the template. \fB\f(CB$target_lines\fB\fR is predefined to be empty when the template code is evaluated. .IP "\fB\f(CB$head_lines\fB\fR" 4 .IX Item "$head_lines" This variable is intended to be the placeholder for the comment line appearing just before the target in the configuration file. It is initialized with that comment line before the evaluation of the template code and if the template doesn't modify \fB\f(CB$head_lines\fB\fR during evaluation, the comment will look like usual in the config file. .IP "\fB\f(CB$problem_lines\fB\fR" 4 .IX Item "$problem_lines" This variable is intended to be the placholder for the comment lines describing any problems which might have been encountered when trying to add the target into the configuration. For host templates it's normally not used and for those it's predefined as the empty string. For interface templates \fB\f(CB$problem_lines\fB\fR is predefined with the error description comments which cfgmaker normally would use for rejected interfaces or as the empty string for accepted interfaces. .Sp It is possible to test against \fB\f(CB$problem_lines\fB\fR to find out if an interface will be included or rejected but this is not recommended. Test against \fB\f(CB$if_ok\fB\fR instead. .IP "\fB\f(CB$separator_lines\fB\fR" 4 .IX Item "$separator_lines" This variable is the placeholder for the string to use as the separator between the code for individual targets. The contents of this variable is put after each target (so the lines will appear after the end of the last target in the config as well). .PP \fIPredefined Template Variables\fR .IX Subsection "Predefined Template Variables" .PP All the variables below are available for interface templates to use. For host templates, only those listed under \*(L"Host and System Variables\*(R" are available. .PP For interface templates the variables listed under \&\*(L"Predefined Filter Variables\*(R" are also available. .PP \fIHost and System Variables\fR .IX Subsection "Host and System Variables" .IP "\fB\f(CB$router_name\fB\fR" 4 .IX Item "$router_name" This is the fully qualified name for the router. It is affected by the following items on the command line: the router name itself and \&\fB\-\-dns\-domain\fR. .IP "\fB\f(CB$router_connect\fB\fR" 4 .IX Item "$router_connect" This is the reference string for the router being polled. It is on the form community@router possibly followed by some snmp options. It is affected by the following items on the command line: the router name itself, \fB\-\-community\fR, \fB\-\-snmp\-options\fR and \fB\-\-dns\-domain\fR. (There's no \s-1HTML\s0 escaped variant available) .IP "\fB\f(CB$directory_name\fB\fR" 4 .IX Item "$directory_name" This variable should contain the directory name as cfgmaker normally would use as the value for the \*(L"Directory[]\*(R" directive. The value is determined by the \fB\-\-subdirs\fR command line option. If \fB\-\-subdirs\fR isn't specified \&\fB\f(CB$directory_name\fB\fR will be the empty string. (There's no \s-1HTML\s0 escaped variant available) .IP "\fB\f(CB$syscontact\fB\fR" 4 .IX Item "$syscontact" This variable is the router's \s-1SNMP\s0 sysContact value. (\s-1HTML\s0 escaped variant: \fB\f(CB$html_syscontact\fB\fR) .IP "\fB\f(CB$sysname\fB\fR" 4 .IX Item "$sysname" This variable is the router's \s-1SNMP\s0 sysName value. (No \s-1HTML\s0 escaped variant available) .IP "\fB\f(CB$syslocation\fB\fR" 4 .IX Item "$syslocation" This variable is the router's \s-1SNMP\s0 sysLocation value. (\s-1HTML\s0 escaped variant: \fB\f(CB$html_syslocation\fB\fR) .IP "\fB\f(CB$sysdescr\fB\fR" 4 .IX Item "$sysdescr" This variable is the router's \s-1SNMP\s0 sysDescr value. It is normally not used by cfgmaker but might be useful in a template. (\s-1HTML\s0 escaped variant: \&\fB\f(CB$html_sysdescr\fB\fR) .PP \fIInterface Target Related Variables\fR .IX Subsection "Interface Target Related Variables" .IP "\fB\f(CB$target_name\fB\fR" 4 .IX Item "$target_name" This is what cfgmaker normally would use as the the name of the target. The target name is what is found within the square brackets, \*(L"[]\*(R", for target directives. (There's no \s-1HTML\s0 escaped variant available) .IP "\fB\f(CB$if_ref\fB\fR" 4 .IX Item "$if_ref" This the reference string for the interface. It is expected to be used in the \*(L"Target[xyz]\*(R" directive to distinguish what interface to use. The value of this variable is affected by the \fB\-\-ifref\fR command line option. It is normally used together with \fB\f(CB$router_connect\fB\fR. (There's no \s-1HTML\s0 escaped variant available) .IP "\fB\f(CB$if_ok\fB\fR" 4 .IX Item "$if_ok" This variable is true if the interface is going to be included into the configuration file, otherwise false. Don't test against other variables such as \fB\f(CB$problem_lines\fB\fR to find out if an interface will be rejected or not, use this \fB\f(CB$if_ok\fB\fR instead. .IP "\fB\f(CB$default_target_lines\fB\fR" 4 .IX Item "$default_target_lines" This variable contains all the target lines which cfgmaker by default outputs for this interface. It's useful if you want to have the \*(L"standard target\*(R" but want to add some extra lines to it by using a template. .PP By default cfgmaker uses the following directives for each target it generates: Target[], SetEnv[], MaxBytes[], Title[], PageTop[] and if there is any directory specified also the Directory[] directive. .PP To facilitate the creation of templates which generates target configs which are similar to the default one, each of the above mentioned directive lines have a corresponding variable containing the line as cfgmaker would have output it by default. .PP Note that none of these have a \s-1HTML\s0 escaped variant, text in them is \&\s-1HTML\s0 escaped where needed. Also note that they do not have any newline at the end. .IP "\fB\f(CB$default_target_directive\fB\fR" 4 .IX Item "$default_target_directive" This variable contains the default string for the Target[] directive line. .IP "\fB\f(CB$default_setenv_directive\fB\fR" 4 .IX Item "$default_setenv_directive" This variable contains the default string for the SetEnv[] directive line. .IP "\fB\f(CB$default_directory_directive\fB\fR" 4 .IX Item "$default_directory_directive" This variable contains the default string for the Directory[] directive line which means it is an empty string (with no newline) if there's no directory. .IP "\fB\f(CB$default_maxbytes_directive\fB\fR" 4 .IX Item "$default_maxbytes_directive" This variable contains the default string for the MaxBytes[] directive line. .IP "\fB\f(CB$default_title_directive\fB\fR" 4 .IX Item "$default_title_directive" This variable contains the default string for the Title[] directive line. .IP "\fB\f(CB$default_pagetop_directive\fB\fR" 4 .IX Item "$default_pagetop_directive" This variable contains the default string for the PageTop[] directive lines. .PP \fIInterface Network Configuration Variables\fR .IX Subsection "Interface Network Configuration Variables" .IP "\fB\f(CB$if_ip\fB\fR" 4 .IX Item "$if_ip" This variable should contain the IP-address of the interface, if any has been assigned to it. (There's no \s-1HTML\s0 escaped variant available) .IP "\fB\f(CB$ifindex\fB\fR" 4 .IX Item "$ifindex" This variable is the \s-1SNMP\s0 ifIndex for the interface which per definition always is an integer. (There's no \s-1HTML\s0 escaped variant available) .IP "\fB\f(CB$if_index\fB\fR" 4 .IX Item "$if_index" Equivalent with \fB\f(CB$ifindex\fB\fR. .IP "\fB\f(CB$if_eth\fB\fR" 4 .IX Item "$if_eth" Contains the ethernet address of the interface, if any. (There's no \s-1HTML\s0 escaped variant available) .IP "\fB\f(CB$if_speed\fB\fR" 4 .IX Item "$if_speed" This variable is the speed in bytes/second (with prefixes). (There's no \&\s-1HTML\s0 escaped variant available) .IP "\fB\f(CB$if_speed_str\fB\fR" 4 .IX Item "$if_speed_str" This variable is a cooked speed description which is either in bits or bytes depending on whether or not the bits option is active and also with the proper prefix for the speed (k, M, G etc). (No \s-1HTML\s0 escaped variant available) .IP "\fB\f(CB$if_type_desc\fB\fR" 4 .IX Item "$if_type_desc" This variable is a textual description of the interface type. (\s-1HTML\s0 escaped variant: \fB\f(CB$html_if_type_desc\fB\fR) .IP "\fB\f(CB$if_type_num\fB\fR" 4 .IX Item "$if_type_num" This variable the integer value corresponding to the interface type (for a listing for the value for the more common interface types, see the section \&\s-1DETAILS ON FILTERS\s0 above). (No \s-1HTML\s0 escaped variant available) .IP "\fB\f(CB$if_dns_name\fB\fR" 4 .IX Item "$if_dns_name" This is the \s-1DNS\s0 name for the interface. (No \s-1HTML\s0 escaped variant available) .PP \fIInterface Name, Description and Alias Variables\fR .IX Subsection "Interface Name, Description and Alias Variables" .PP It might seem confusing with both \fIName\fR, \fIDescription\fR and \fIAlias\fR in this context and to some extent it is. \fIName\fR and \fIDescription\fR are usually supported on most equipment but how they are used varies, both between manufacturers as well as between different categories of equipment from the same manufacturer. The \fIAlias\fR is at least supported by Cisco \&\s-1IOS,\s0 and that variable contains whatever is used in the \s-1IOS\s0 statement called \*(L"description\*(R" for the interface (not to be confused with the \s-1SNMP\s0 variables for \fIDescription\fR). .PP For better control from the command line consider \fB\f(CB$if_title_desc\fB\fR which contents are controlled by the \fB\-\-if\-descr\fR command line option. .IP "\fB\f(CB$if_snmp_descr\fB\fR" 4 .IX Item "$if_snmp_descr" This variable should contain the \*(L"raw\*(R" description of the interface as determined by the \s-1SNMP\s0 polling of the router. (\s-1HTML\s0 escaped variant: \&\fB\f(CB$html_if_snmp_descr\fB\fR) .IP "\fB\f(CB$if_snmp_name\fB\fR" 4 .IX Item "$if_snmp_name" The \*(L"raw\*(R" name for the interface as provided by \s-1SNMP\s0 polling. (\s-1HTML\s0 escaped variant: \fB\f(CB$html_if_snmp_name\fB\fR) .IP "\fB\f(CB$if_snmp_alias\fB\fR" 4 .IX Item "$if_snmp_alias" The \*(L"raw\*(R" ifAlias for the interface as provided by \s-1SNMP\s0 polling. (\s-1HTML\s0 escaped variant: \fB\f(CB$html_if_snmp_alias\fB\fR) .IP "\fB\f(CB$if_cisco_descr\fB\fR" 4 .IX Item "$if_cisco_descr" The \*(L"raw\*(R" CiscolocIfDescr for the interface as provided by \s-1SNMP\s0 polling. (\s-1HTML\s0 escaped variant: \fB\f(CB$html_if_cisco_descr\fB\fR) .IP "\fB\f(CB$if_description\fB\fR" 4 .IX Item "$if_description" This is the \*(L"cooked\*(R" description string for the interface, taking into account the \s-1SNMP\s0 values found for the interface's RDescr, ifAlias and CiscolocIfDescr. (\s-1HTML\s0 escaped variant: \fB\f(CB$html_if_description\fB\fR) .IP "\fB\f(CB$if_title\fB\fR" 4 .IX Item "$if_title" The full string cfgmaker by default would have used for the Title[] directive in the configuration as well as the content of the topmost H1 tag in the PageTop[]. Is composed by the contents of \fB\f(CB$desc_prefix\fB\fR, \&\fB\f(CB$if_title_desc\fB\fR and \fB\f(CB$sysname\fB\fR. .Sp As \fB\f(CB$if_title\fB\fR depends on \fB\f(CB$if_title_desc\fB\fR, it is possible to indirectly control \fB\f(CB$if_title\fB\fR by using the command line option \fB\-\-if\-descr\fR. .Sp (\s-1HTML\s0 escaped variant: \fB\f(CB$html_if_title\fB\fR) .IP "\fB\f(CB$if_port_name\fB\fR" 4 .IX Item "$if_port_name" If the host is a Cisco Catalyst \s-1LAN\s0 switch, this variable is the name of that port. (No \s-1HTML\s0 escaped variant available) .IP "\fB\f(CB$if_pp_port_name\fB\fR" 4 .IX Item "$if_pp_port_name" If the host is a Nortel Passport \s-1LAN\s0 switch, this variable is the name of that port. (No \s-1HTML\s0 escaped variant available) .IP "\fB\f(CB$desc_prefix\fB\fR" 4 .IX Item "$desc_prefix" This variable is a prefix of the description of what the target is to use in the \*(L"Title[]\*(R" directive and in the H1 section of the \*(L"PageTop[]\*(R". Default is \&\*(L"Traffic analysis for \*(R". (\s-1HTML\s0 escaped variant: \fB\f(CB$html_desc_prefix\fB\fR) .IP "\fB\f(CB$if_title_desc\fB\fR" 4 .IX Item "$if_title_desc" This is the description of the interface normally used by cfgmaker as part of the variable \fB\f(CB$if_title\fB\fR. The latter is used as the full string in the \&\*(L"Title[]\*(R" directive and the H1 section in the PageTop[]. .Sp \&\fB\f(CB$if_title_desc\fB\fR is controlled by the command line option \fB\-\-if\-descr\fR which indirectly controls the contents of \fB\f(CB$if_title\fB\fR .Sp (\s-1HTML\s0 escaped variant: \fB\f(CB$html_if_title_desc\fB\fR) .PP \fIHelp Functions for Templates\fR .IX Subsection "Help Functions for Templates" .PP The following functions exists to facilitate the writing of host and interface templates. .IP "\fBhtml_escape(\f(BIstring\fB)\fR" 4 .IX Item "html_escape(string)" \&\fB\fBhtml_escape()\fB\fR takes a string as an argument and returns a new string where the following substitutions has been done: the chars \*(L"<\*(R", \*(L">\*(R" and \&\*(L"&\*(R" are replaced by \*(L"<\*(R", \*(L">\*(R" and \*(L"&\*(R" and that newlines embedded in the string are prepended with \*(L"<\s-1BR\s0>\*(R" and appended with a space character (newlines at the end of the string are not touched). .ie n .IP "\fBoid_pick($router_connect,$v3opt,""oid1"",""oid2""...)\fR" 4 .el .IP "\fBoid_pick($router_connect,$v3opt,``oid1'',``oid2''...)\fR" 4 .IX Item "oid_pick($router_connect,$v3opt,oid1,oid2...)" This function will try to poll each of the oids specified until it is successful or has run out of oids. It will return the name of the first oid that worked or undef if it is not successful .PP \fIExample Template Files\fR .IX Subsection "Example Template Files" .PP Template Example 1: Eliminating Rejected Targets From Appearing .IX Subsection "Template Example 1: Eliminating Rejected Targets From Appearing" .PP This template file generates exactly the same configuration code per interface as cfgmaker does by default, with the exception that it eliminates all lines (comments as well as config code) for an interface if the interface happens to be rejected. .PP .Vb 3 \& if(not $problem_lines) \& { \& $target_lines .= <$html_desc_prefix$html_if_title_desc \-\- $sysname \&
      \& \& \& \& \& \& \& \& \& \& \& \& \& \& \& \& \& \& \& \& \& \& ECHO \& \& $target_lines .= < \& \& \& \& ECHO \& \& $target_lines .= < \& \& \& \& ECHO \& \& $target_lines .= < \& \& \& \& ECHO \& \& $target_lines .= < \& \& \& \& ECHO \& \& $target_lines .= < \& \& ECHO \& } else { \& $head_lines=""; \& $problem_lines=""; \& $target_lines=""; \& $separator_lines=""; \& } .Ve .PP \fITemplate Example 2: Simpler Version of Example 1\fR .IX Subsection "Template Example 2: Simpler Version of Example 1" .PP Example 1 was partly intended to demonstrate how to customize the generation of interface targets but also to provide a hint of how the variables are used in the \*(L"default\*(R" template which one could consider that cfgmaker normally uses. .PP If you're only interested in the easiest way of entirely eliminating those reject interfaces, the template below would do the job as well by using \&\fB\f(CB$default_target_lines\fB\fR. .PP .Vb 8 \& if($if_ok) { \& $target_lines = $default_target_lines; \& } else { \& $head_lines=""; \& $problem_lines=""; \& $target_lines=""; \& $separator_lines=""; \& } .Ve .PP \fITemplate Example 3: Creating \s-1CPU\s0 Targets for Hosts\fR .IX Subsection "Template Example 3: Creating CPU Targets for Hosts" .PP Below is an example of a host template. .PP .Vb 3 \& $head_lines .= <$router_name CPU load \&
      \&
      System:$sysname in $html_syslocation
      Maintainer:$html_syscontact
      Description:$html_if_description
      ifType:$html_if_type_desc ($if_type_num)
      ifName:$html_if_snmp_name
      Port Name:$if_port_name
      Port Name:$if_pp_port_name
      Max Speed:$if_speed_str
      Ip:$if_ip ($if_dns_name)
      \& \& \& \& \& \& \& \& \& \& \& \& \& \& \& \& \&
      System:$router_name in $html_syslocation
      Maintainer:$html_syscontact
      Description:$html_sysdescr
      Resource:CPU.
      \&
      \& ECHO .Ve .SH "EXAMPLES" .IX Header "EXAMPLES" The first example creates a config file for \fIrouter.place.xyz\fR: the router has the community name \fIpublic\fR. Interfaces get identified by their \&\s-1IP\s0 number. Two global options get added to the config file. The config file gets redirected to \fImrtg.conf\fR. The '\e' signs at the end of the line mean that this command should be written on a single line. .PP .Vb 4 \& cfgmaker \-\-global "WorkDir: /home/tobi" \e \& \-\-global "Options[_]: growright,bits" \e \& \-\-ifref=ip \e \& public@router.place.xyz > mrtg.cfg .Ve .PP Note: if cfgmaker is not in your path, but you are in the directory where cfgmaker is stored, you can start it with ./cfgmaker .PP The next example creates a config file for four devices: \&\fIrouter1.place.xyz\fR, \fIrouter2.place.xyz\fR, \fIswitch1.place.xyz\fR and \&\fIswitch2.place.xyz\fR all with the community \fIpublic\fR. .PP The two routers will have \fB\-\-ifref\fR set to \fBdescr\fR whilst the two switches will use \fB\-\-ifref\fR set to \fBname\fR. Further the routers will use \fB\-\-ifdesc\fR set to \fBalias\fR and \fIswitch1.place.xyz\fR will use \&\fB\-\-ifdesc\fR set to \fBdescr\fR whilst \fIswitch2.place.xyz\fR use \fBname\fR instead. .PP Finally, there will be two Options lines inserted in the configuration: One will be in the beginning, whilst the other will be inserted after the lines related to the two routers but before those lines related to the switches. .PP .Vb 12 \& cfgmaker \-\-global "WorkDir: /home/tobi" \e \& \-\-global "Options[_]: growright,bits" \e \& \-\-ifref=descr \e \& \-\-ifdesc=alias \e \& public@router1.place.xyz \e \& public@router2.place.xyz \e \& \-\-global "Options[_]: growright" \e \& \-\-ifref=name \e \& \-\-ifdesc=descr \e \& public@switch1.place.xyz \e \& \-\-ifdesc=name \e \& public@switch2.place.xyz > mrtg.cfg .Ve .PP The next example demonstrates how to use the \fB\-\-community\fR, \&\fB\-\-snmp\-options\fR and \fB\-\-dns\-domain\fR to make the command line simpler. All the equipment will use the community \fIhidden\fR, except for the ppp-server which use community \fIaccess\fR. All equipment uses these \&\s-1SNMP\s0 options: \fB1s timeout\fR, \fB1 retry\fR and \fB\s-1SNMP\s0 version 2\fR (\fBbackoff\fR and \&\fBport\fR is unspecified which means they use the default values). The exception again is the ppp-server which uses \fB\s-1SNMP\s0 version 1\fR. Finally, all the equipment is part of the domain \fIplace.xyz\fR, except for the ppp-server which is part of the domain \fIremote.place.xyz\fR. Note that the latter is achieved simply by specifying the name of the ppp-server to be \fIppp-server.\f(BIremote\fI\fR . .PP .Vb 10 \& cfgmaker \-\-global "WorkDir: /home/tobi" \e \& \-\-global "Options[_]: growright,bits" \e \& \-\-dns\-domain=place.xyz \e \& \-\-community=hidden \e \& \-\-snmp\-options=::1:1::2 \e \& router1 \e \& router2 \e \& router3 \e \& router4 \e \& router5 \e \& switch1 \e \& switch2 \e \& switch3 \e \& switch4 \e \& switch5 \e \& switch6 \e \& switch7 \e \& access@ppp\-server.remote:::::1 > mrtg.cfg .Ve .SH "SEE ALSO" .IX Header "SEE ALSO" mrtg-reference .SH "AUTHOR" .IX Header "AUTHOR" Tobias Oetiker and Jakob Ilves .SH "LICENSE" .IX Header "LICENSE" \&\s-1GNU\s0 General Public License .SH "COPYRIGHT" .IX Header "COPYRIGHT" Cfgmaker is Copyright 2000 by Tobias Oetiker mrtg-2.17.10/doc/indexmaker.10000644000175300017510000002700314171763416014640 0ustar oetikeroep.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "INDEXMAKER 1" .TH INDEXMAKER 1 "2022-01-19" "2.17.10" "mrtg" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" indexmaker \- Creates index files for mrtg web sites (mrtg\-2.17.10) .SH "SYNOPSIS" .IX Header "SYNOPSIS" indexmaker [options] mrtg.cfg [other.cfg ...] .SH "OPTIONS" .IX Header "OPTIONS" .Vb 1 \& \-\-output=filename set output filename (default: stdout) \& \& \-\-filter title=~regexp select targets by matching regexp against titles \& \-\-filter pagetop=~regexp select targets by matching regexp against pagetop \& \-\-filter name=~regexp select targets by matching regexp against name \& \& \-\-addhead=text insert this text between and \& \-\-title=text set title of generated index file \& \-\-subtitle=text add a subtitle to the generated index file \& \-\-bodyopt=text set body tag options \& \-\-headlevel=number use at top of page (default: 1) \& \-\-pagetop=text insert this text between and

      ...

      \& \-\-pageend=text insert this text after the main body \& \-\-pagetopend=text use this text for pagetop or pageend if undefined \& \-\-nolegend do not add the Mrtg legend at the end of the page \& \& \-\-columns=number show graphs in a table with x columns (default: 2) \& \-\-perhost show graphs of the same host on a row \& \-\-compact try to make a vertically more compact page \& \-\-optlog log the used command line in the page (default: log) \& \& \-\-sort=title sort graphs by title \& \-\-sort=name sort graphs by their name \& \-\-sort=descr sort graphs by their description \& \-\-sort=original leave as is (default) \& \& \-\-enumerate add a sequence number to the title of each graph \& \& \-\-picfirst place pictures before text (default: text first) \& \-\-width=number set width of graphs (default: not set) \& \-\-height=number \& \-\-sidebyside place text / pictures side by side (default: above/below) \& \-\-bold use bold text (default: bold) \& \-\-clicktext make the text link to the inner page (like the image) \& \& \-\-show=day pick which graph to show in the index (default) \& \-\-show=week \& \-\-show=month \& \-\-show=year \& \-\-show=none \& \& \-\-section=h1 h1 tag from pagetop as section heading (default) \& \-\-section=title title as section headings for graphs \& \-\-section=name graph name as section heading \& \-\-section=descr graph description as section heading \& \-\-section=ifname interface name (ifName) as section heading \& \-\-section=portname port name entry in pagetop as section heading \& \-\-sectionhost Try to prepend the host to the section heading if missing \& \& \-\-rrdviewer=path path to rrdviewer (default: /cgi\-bin/14all.cgi) \& \-\-icondir=path path to icondir \& \-\-prefix=path path from the location of the index.html to the graphs \& \-\-headeradd=string add string to the html page header \& \-\-autoprefix try to set prefix automatically \& \& \-\-\-file=file read string argument for option from file .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" \&\fBIndexmaker\fR can create web pages which display the status of an array of mrtg interface status pages. .IP "\fB\-\-output\fR \fIfilename\fR" 4 .IX Item "--output filename" set output filename (default: stdout) .IP "\fB\-\-filter\fR (\fBtitle\fR|\fBpagetop\fR|\fBname\fR)(\fB=~\fR|\fB!~\fR)\fIregexp\fR" 4 .IX Item "--filter (title|pagetop|name)(=~|!~)regexp" Several filters may get set. Each filter can match against the contents of a specific section of the mrtg config file. \fBName\fR refers to the bit in square brackets (option[name]: bla). .Sp Depending on the match operator chosen (\fB=~\fR or \fB!~\fR) the match will be positive or negative. .Sp Note that some shells consider \fB!\fR a special character. It may be necessary to type \fB\e!~\fR instead. .IP "\fB\-\-title\fR \fItext\fR" 4 .IX Item "--title text" Set title of generated index file (default: regexp) .IP "\fB\-\-bodyopt\fR \fItext\fR" 4 .IX Item "--bodyopt text" The value of this argument gets appended to the <\s-1BODY\s0> tag. This allows you to set document colors. By default this option is set to .Sp .Vb 1 \& bgcolor="#ffffff" text="#000000" link="#000000" vlink="#000000" alink="#000000" .Ve .IP "\fB\-\-columns\fR \fInumber\fR" 4 .IX Item "--columns number" Display graphs in a table with \fInumber\fR columns (default: 2) .IP "\fB\-\-sort\fR \fBtitle\fR|\fBname\fR|\fBdescr\fR|\fBoriginal\fR" 4 .IX Item "--sort title|name|descr|original" Sort the graphs in the page either by \fBtitle\fR, by \fBname\fR, by interface \&\fBdescr\fRiption, or leave them as is. .IP "\fB\-\-enumerate\fR" 4 .IX Item "--enumerate" Add a sequence number to the title of each graph .IP "\fB\-\-width\fR \fInumber\fR" 4 .IX Item "--width number" Set width of graphs .IP "\fB\-\-height\fR \fInumber\fR" 4 .IX Item "--height number" Set the height of the graphs .IP "\fB\-\-show\fR \fBday\fR|\fBweek\fR|\fBmonth\fR|\fByear\fR|\fBnone\fR" 4 .IX Item "--show day|week|month|year|none" Select which graph to show in the index page. You can suppress images completely with \fB\-\-show=none\fR. .IP "\fB\-\-section\fR \fBh1\fR|\fBtitle\fR|\fBname\fR|\fBdescription\fR|\fBportname\fR" 4 .IX Item "--section h1|title|name|description|portname" Select what to use as the title for each graph in the page. \fBh1\fR is the H1 section from pagetop, \fBtitle\fR is the graph title, \fBname\fR is the bit in square brackets (option[name]: bla), and \fBdescr\fR or \&\fBdescription\fR is the text from the Description field of the PageTop (the Cisco description text if it's available, otherwise just the interface description). \fBportname\fR is the \f(CW\*(C`Port Name:\*(C'\fR from pagetop. .IP "\fB\-\-sectionhost\fR" 4 .IX Item "--sectionhost" Extract the hostname from the target line (this does not work if the target is a mathematical expression). Prepend the hostname (and a colon) to the section if not already present. .IP "\fB\-\-rrdviewer\fR \fIpath\fR" 4 .IX Item "--rrdviewer path" If you have set the \fBLogFormat: rrdtool\fR property in the mrtg.cfg file, the index will take this into account. The only thing you must tell it is the path to your grapher cgi. (default: /cgi\-bin/14all.cgi) .IP "\fB\-\-prefix\fR \fIpath\fR" 4 .IX Item "--prefix path" By default we assume that the file generated by indexmaker is stored in \&\fIWorkDir\fR. If you want to store it somewhere else, specify how to reach \&\fIWorkDir\fR from the place where the Index is stored. Note that you have to use '/' as path separator as this will be used in urls. Speaking of which, you can even enter a whole url. .IP "\fB\-\-autoprefix\fR \fIpath\fR" 4 .IX Item "--autoprefix path" Requires \-\-output. Try to generate the prefix automatically by comparison of the path to the output file set with \-\-output and the Htmldir set in the configuration files. Particularly useful when multiple configuration files are specified, with different Htmldir settings. .IP "\fB\-\-optlog\fR" 4 .IX Item "--optlog" Default is logging in the generated page the command line, suppress with \&\-\-nooptlog . Useful if the commandline contains a complex \-\-pagetop=string which could confuse simple browsers. .IP "\fB\-\-someoption\-file\fR \fIfilename\fR" 4 .IX Item "--someoption-file filename" For any someoption which takes a \fIstring\fR as parameter you can read the string from a file by adding <\-file> to the option keyword. The whole content of the file will be read and used as the \fIstring\fR. The file must exist. .SH "AUTHOR" .IX Header "AUTHOR" Tobias Oetiker .SH "LICENSE" .IX Header "LICENSE" \&\s-1GNU\s0 General Public License .SH "COPYRIGHT" .IX Header "COPYRIGHT" 2000\-2001 Tobias Oetiker mrtg-2.17.10/doc/mrtg-contrib.10000644000175300017510000001421414171763416015120 0ustar oetikeroep.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "MRTG-CONTRIB 1" .TH MRTG-CONTRIB 1 "2022-01-19" "2.17.10" "mrtg" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" mrtg\-contrib \- Contribution Guidelines for MRTG .SH "DESCRIPTION" .IX Header "DESCRIPTION" If you have written an extension to mrtg or created a bug fix, please consider contributing it to the project. As I get quite a number of contributions every week, here are a few guidelines which explain how to contribute so that I can use the contribution without too much additional work. .SS "Translations" .IX Subsection "Translations" \&\s-1MRTG\s0 messages have been translated to a number of languages but there are still many which have not been covered yet. If you want to add yours, go into the \fImrtg\-2.17.10/translate\fR directory and follow the instructions given in the \fI\s-1README\s0\fR file. .SS "Patches" .IX Subsection "Patches" When you have created your modification or extension to mrtg and want to submit it to me, please crate a patch for the files which you have modified. Do not send entire files unless they are new. .PP To create a patch, get hold of a copy of \s-1GNU\s0 diff (Many Unix systems will have this installed already. In the \s-1NT\s0 world you might want to get http://sources.redhat.com/cygwin/ to get all the nice \s-1GNU\s0 tools available.) and type .PP .Vb 1 \& diff \-\-unified \-\-ignore\-space\-change old\-file new\-file > simple.patch .Ve .PP or if you have modified several files do .PP .Vb 1 \& diff \-\-recursive \-\-unified \-\-ignore\-space\-change old\-dir/ new\-dir/ >long.patch .Ve .SS "Documentation" .IX Subsection "Documentation" All documentation of mrtg is done with the perl \fB\s-1POD\s0\fR system. If you want to learn about it, type .PP .Vb 1 \& perldoc perlpod .Ve .PP and read the instructions. If you have bugfixes or additions to the existing documents, make sure you modify the \fB\s-1POD\s0\fR files and not the html or txt versions. .PP I take documentation very seriously. Whenever you create a new feature for mrtg which you want to get included in the official release, your patch must also contain modifications for the relevant \fBpod\fR file in the \fIdoc\fR tree or for the documentation sections of \fIcfgmaker\fR and \fIindexmaker\fR. .SH "ADDRESS" .IX Header "ADDRESS" Send your patches, translations and contributions to Tobias Oetiker .SH "AUTHOR" .IX Header "AUTHOR" Tobias Oetiker mrtg-2.17.10/doc/mrtg-faq.10000644000175300017510000002064514171763414014232 0ustar oetikeroep.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "MRTG-FAQ 1" .TH MRTG-FAQ 1 "2022-01-19" "2.17.10" "mrtg" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" mrtg\-faq \- How to get help if you have problems with MRTG .SH "SYNOPSIS" .IX Header "SYNOPSIS" \&\s-1MRTG\s0 seems to raise a lot of questions. There are a number of resources apart from the documentation where you can find help for mrtg. .SH "FAQ" .IX Header "FAQ" In the following sections you'll find some additional Frequently Asked Questions, with Answers. .ie n .SS "Why is there no ""@#$%"" (my native language) version of \s-1MRTG\s0?" .el .SS "Why is there no ``@#$%'' (my native language) version of \s-1MRTG\s0?" .IX Subsection "Why is there no @#$% (my native language) version of MRTG?" Nobody has contributed a \fI@#$%.pmd\fR file yet. Go into the \&\fImrtg\-2.17.10/translate\fR directory and create your own translation file. When you are happy with it send it to me for inclusion with the next mrtg release. .SS "I need a script to make mrtg work with my xyz device." .IX Subsection "I need a script to make mrtg work with my xyz device." Probably this has already been done. Check the stuff in the \&\fImrtg\-2.17.10/contrib\fR directory. There is a file called \fI00INDEX\fR in that directory which tells what you can find in there. .SS "How does this \s-1SNMP\s0 thing work" .IX Subsection "How does this SNMP thing work" There are many resources on the net that explain \s-1SNMP.\s0 Take a look at this article from the Linux Journal by David Guerrero .PP .Vb 1 \& http://www.david\-guerrero.com/papers/snmp/ .Ve .PP And at this rather long document from \s-1CISCO.\s0 .PP .Vb 1 \& http://www.cisco.com/univercd/cc/td/doc/cisintwk/ito_doc/snmp.htm .Ve .SS "The images created by \s-1MRTG\s0 look very strange." .IX Subsection "The images created by MRTG look very strange." Remove the *\-{week,day,month,year}.png files and start \s-1MRTG\s0 again. Using \s-1MRTG\s0 for the first time, you might have to do this twice. This will also help when you introduce new routers into the cfg file. .SS "What is my Community Name?" .IX Subsection "What is my Community Name?" Ask the person in charge of your Router or try 'public', as this is the default Community Name. .SS "My graphs show a flat line during an outage. Why ?" .IX Subsection "My graphs show a flat line during an outage. Why ?" Well, the short answer is that when an \s-1SNMP\s0 query goes out and a response doesn't come back, \s-1MRTG\s0 has to assume something to put in the graph, and by default it assumes that the last answer we got back is probably closer to the truth than zero. This assumption is not perfect (as you have noticed). It's a trade-off that happens to fail during a total outage. .PP If this is an unacceptable trade-off, use the \fBunknaszero\fR option. .PP You may want to know what you're trading off, so in the spirit of trade-offs, here's the long answer: .PP The problem is that \s-1MRTG\s0 doesn't know *why* the data didn't come back, all it knows is that it didn't come back. It has to do something, and it assumes it's a stray lost packet rather than an outage. .PP Why don't we always assume the circuit is down and use zero, which will (we think) be more nearly right? Well, it turns out that you may be taking advantage of \s-1MRTG\s0's \*(L"assume last\*(R" behaviour without being aware of it. .PP \&\s-1MRTG\s0 uses \s-1SNMP\s0 (Simple Network Management Protocol) to collect data, and \&\s-1SNMP\s0 uses \s-1UDP\s0 (User Datagram Protocol) to ship packets around. \s-1UDP\s0 is connectionless (not guaranteed) unlike \s-1TCP\s0 where packets are tracked and acknowledged and, if needed, retransmitted. \s-1UDP\s0 just throws packets at the network and hopes they arrive. Sometimes they don't. .PP One likely cause of lost \s-1SNMP\s0 data is congestion; another is busy routers. Other possibilities include transient telecommunications problems, router buffer overflows (which may or may not be congestion-related), \*(L"dirty lines\*(R" (links with high error rates), and acts of God. These things happen all the time; we just don't notice because many interactive services are TCP-based and the lost packets get retransmitted automatically. .PP In the above cases where some \s-1SNMP\s0 packets are lost but traffic is flowing, assuming zero is the wrong thing to do \- you end up with a graph that looks like it's missing teeth whenever the link fills up. \s-1MRTG\s0 interpolates the lost data to produce a smoother graph which is more accurate in cases of intermittent packet loss. But with V2.8.4 and above, you can use the \*(L"unknaszero\*(R" option to produce whichever graph is best under the conditions typical for your network. .SH "AUTHOR" .IX Header "AUTHOR" Tobias Oetiker mrtg-2.17.10/doc/mrtg-forum.10000644000175300017510000001701414171763415014610 0ustar oetikeroep.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "MRTG-FORUM 1" .TH MRTG-FORUM 1 "2022-01-19" "2.17.10" "mrtg" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" mrtg\-forum \- Interactive Help for MRTG users .SH "SYNOPSIS" .IX Header "SYNOPSIS" There is a lot of written documentation for mrtg, but nevertheless you may have a problem where you can't find the solution. In this case some Human Help may be necessary. With \s-1MRTG\s0 there are several ways to get Humans to help you. .SH "MAILING-LIST" .IX Header "MAILING-LIST" There are three mailing lists for \s-1MRTG\s0 available. .IP "mrtg" 4 .IX Item "mrtg" for discussion among mrtg users. .IP "mrtg-announce" 4 .IX Item "mrtg-announce" for announcements regarding new versions of mrtg related software. .IP "mrtg-developers" 4 .IX Item "mrtg-developers" for discussion among people who write software in connection with mrtg or who hack mrtg itself. .SS "\s-1THE RULES\s0" .IX Subsection "THE RULES" Please note that the members of the mrtg mailinglist value politeness highly. This means behave in a way you would like others to behave towards you. .IP "\(bu" 4 No shouting. (\s-1NO CAPS\s0) .IP "\(bu" 4 No rude language .IP "\(bu" 4 No demands. everybody is on the list out of their own free will. If you do not get an answer to your question, chances are high that you did not give sufficient details about the nature of your problem or that the answer to your problem is in the documentation. .IP "\(bu" 4 If you do not follow the rules you will be unsubscribed from the list with no further questions asked. .IP "\(bu" 4 Decisions about your unsubscription from the list will be taken by .Sp .Vb 2 \& Alex van den Bogaerdt \& Paul C. Williamson .Ve .Sp If you feel that you have been treated unfairly, you may send mail to me and explain the situation. .Sp .Vb 1 \& Tobi Oetiker .Ve .SS "\s-1SUBSCRIBING\s0" .IX Subsection "SUBSCRIBING" These lists are managed by a mailing-list management program (listar). It allows you to subscribe to these lists by sending a message with the subject: \fBsubscribe\fR to the following address: .PP .Vb 1 \& listname\-request@lists.oetiker.ch .Ve .PP You will then get a message asking you to confirm your subscription. .PP For posting to the lists use the following address .PP .Vb 1 \& listname@lists.oetiker.ch .Ve .PP Note that only people who are subscribed to the list can post. .PP Further information about the usage of the mailing lists is available by sending a message with the subject line \fBhelp\fR to either one of the request addresses. .PP There is also a webinterface to the lists on .PP .Vb 1 \& http://lists.oetiker.ch .Ve .PP List archives are on .PP .Vb 1 \& http://www.mail\-archive.com/index.php?hunt=mrtg .Ve .PP and .PP .Vb 1 \& http://gmane.org/find.php?list=mrtg .Ve .SH "NEWSGROUP" .IX Header "NEWSGROUP" For discussion of \s-1MRTG\s0 or related topics on the Usenet, please send your posts to: .PP .Vb 1 \& news:comp.dcom.net\-management .Ve .PP Many \s-1MRTG\s0 users are in this forum and will help you. You can also find an archive of past activity from this Newsgroup on: .PP .Vb 1 \& http://groups.google.com/group/comp.dcom.net\-management .Ve .SH "IRC Channel" .IX Header "IRC Channel" For discussion of \s-1MRTG\s0 and related topics on \s-1IRC,\s0 the `#mrtg' channel on EFNet has been created. .PP More information can be found at .PP .Vb 1 \& http://mrtg.easymac.org .Ve .SH "MRTG Japan" .IX Header "MRTG Japan" There is a special Mailinglist for \s-1MRTG\s0 Users in Japan. It carries translations of the traffic from MRTG-ANNOUNCE as well as updates on the Japanese Translation of the \s-1MRTG\s0 documentation. Go to http://www.mrtg.jp/ for further Information. .SH "AUTHOR" .IX Header "AUTHOR" Tobias Oetiker and many contributors mrtg-2.17.10/doc/mrtg-ipv6.10000644000175300017510000001717014171763416014350 0ustar oetikeroep.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "MRTG-IPV6 1" .TH MRTG-IPV6 1 "2022-01-19" "2.17.10" "mrtg" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" mrtg\-ipv6 \- IPv6 support in MRTG .SH "OVERVIEW" .IX Header "OVERVIEW" \&\s-1MRTG\s0 and cfgmaker support \s-1SNMP\s0 over IPv6. IPv6 targets can be specified by hostname or IPv6 address, and if the required libraries are present (see below), queries will use IPv6. .SH "USAGE" .IX Header "USAGE" .SS "Enabling IPv6" .IX Subsection "Enabling IPv6" IPv6 is currently disabled by default and must be explicitly enabled. In \&\s-1MRTG\s0 this is done by turning on the \fBEnableIPv6\fR global option in the configuration file. In cfgmaker, it is enabled with the \fB\-\-enable\-ipv6\fR command-line option. .PP If IPv6 is disabled, \s-1MRTG\s0 and cfgmaker should behave in exactly the same way as previous versions. So the addition of IPv6 support should have no effect on existing \s-1MRTG\s0 setups unless IPv6 is enabled. .PP IPv6 support requires the Socket6 and \s-1INET6\s0 libraries (see below). If \s-1MRTG\s0 can't find them, IPv6 is disabled. .SS "Specifying IPv6 targets" .IX Subsection "Specifying IPv6 targets" IPv6 targets may be specified by name or IPv6 address. Numeric IPv6 addresses may be used with both cfgmaker and \s-1MRTG,\s0 but they must be enclosed in square brackets. .PP For example, a target could be specified as: .PP .Vb 1 \& public@[2001:760:4::]:161 .Ve .PP Hostnames work as expected: first an IPv6 name lookup is tried, then an IPv4 lookup. .SS "Targets that do not support \s-1SNMP\s0 over IPv6" .IX Subsection "Targets that do not support SNMP over IPv6" Many targets (this currently includes all Cisco routers) do not yet support \&\s-1SNMP\s0 over IPv6 and must be monitored over IPv4. This can cause problems if you specify a target through its \s-1DNS\s0 name and the name maps to both the IPv6 address and the IPv4 address of the target: \s-1MRTG\s0 will only try IPv6, and will fail. .PP To query these targets, use the \fBIPv4Only\fR per-target option, which tells \&\s-1MRTG\s0 not to use \s-1SNMP\s0 over IPv6 for the target. .PP \&\s-1MRTG\s0 does not fall back to IPv4 for performance and correctness reasons. If there are many routers to query, a timeout for every router would make \s-1MRTG\s0 take too long to query them all. And if, for some reason, IPv6 connectivity to the target is lost, \s-1MRTG\s0's error messages can help figure out what is wrong. .PP cfgmaker does fall back from IPv6 to IPv4. If IPv6 is enabled and cfgmaker is given a hostname that resolves to both an IPv6 and an IPv4 address, it first tries to query the target over IPv6. If it receives no answer, it tries again using IPv4. If the target answers, cfgmaker sets the IPv4Only option in the generated config file. .SH "IPv6 LIBRARIES" .IX Header "IPv6 LIBRARIES" .SS "Libraries required" .IX Subsection "Libraries required" IPv6 support requires the \fBSocket6\fR and \fB\s-1INET6\s0\fR Perl modules. Both can be downloaded from \s-1CPAN:\s0 .PP http://search.cpan.org/author/UMEMOTO/Socket6/ .PP http://search.cpan.org/author/MONDEJAR/INET6/ .PP If you use Debian, you will need the packages \fBlibsocket6\-perl\fR and \&\fBlibio\-socket\-inet6\-perl\fR, which are (or should soon be) in unstable. .PP So far, IPv6 support has been tested on Linux only, and only with Socket6 version 0.12. Also note that IPv6 won't work at all if you don't have \&\s-1INET6\s0.pm version 2.00 or newer. .SS "Installing the libraries" .IX Subsection "Installing the libraries" Building and installing Socket6 and \s-1INET6\s0 is very simple. For each module, just unpack the archive and then do: .PP .Vb 2 \& perl Makefile.PL \& make .Ve .PP and then: .PP .Vb 2 \& su \& make install .Ve .PP If you have installed the libraries successfully, cfgmaker and mrtg should automatically detect them and allow IPv6 support to be enabled. .SH "AUTHOR" .IX Header "AUTHOR" Lorenzo Colitti mrtg-2.17.10/doc/mrtglib.30000644000175300017510000003103614171763416014154 0ustar oetikeroep.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "doc::mrtglib 3" .TH doc::mrtglib 3 "2022-01-19" "2.17.10" "mrtg" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" MRTG_lib.pm \- Library for MRTG and support scripts .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 5 \& use MRTG_lib; \& my ($configfile, @target_names, %globalcfg, %targetcfg); \& readcfg($configfile, \e@target_names, \e%globalcfg, \e%targetcfg); \& my (@parsed_targets); \& cfgcheck(\e@target_names, \e%globalcfg, \e%targetcfg, \e@parsed_targets); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" MRTG_lib is part of \s-1MRTG,\s0 the Multi Router Traffic Grapher. It was separated from \s-1MRTG\s0 to allow other programs to easily use the same config files. The main part of MRTG_lib is the config file parser but some other functions are there too. .ie n .IP "$MRTG_lib::OS" 4 .el .IP "\f(CW$MRTG_lib::OS\fR" 4 .IX Item "$MRTG_lib::OS" Type of \s-1OS: WIN, UNIX, VMS\s0 .ie n .IP "$MRTG_lib::SL" 4 .el .IP "\f(CW$MRTG_lib::SL\fR" 4 .IX Item "$MRTG_lib::SL" \&\fISlash\fR in the current \s-1OS.\s0 .ie n .IP "$MRTG_lib::PS" 4 .el .IP "\f(CW$MRTG_lib::PS\fR" 4 .IX Item "$MRTG_lib::PS" Path separator in \s-1PATH\s0 variable .ie n .IP """readcfg""" 4 .el .IP "\f(CWreadcfg\fR" 4 .IX Item "readcfg" \&\f(CW\*(C`readcfg($file, \e@targets, \e%globalcfg, \e%targetcfg [, $prefix, \e%extrules])\*(C'\fR .Sp Reads a config file, parses it and fills some arrays and hashes. The mandatory arguments are: the name of the config file, a ref to an array which will be filled with a list of the target names, a hashref for the global configuration, a hashref for the target configuration. .Sp The configuration file syntax is: .Sp .Vb 4 \& globaloption: value \& targetoption[targetname]: value \& aprefix*extglobal: value \& aprefix*exttarget[target2]: value .Ve .Sp E.g. .Sp .Vb 3 \& workdir: /var/stat/mrtg \& target[router1]: 2:public@router1.local.net \& 14all*columns: 2 .Ve .Sp The global config hash has the structure .Sp .Vb 1 \& $globalcfg{configoption} = \*(Aqvalue\*(Aq .Ve .Sp The target config hash has the structure .Sp .Vb 1 \& $targetcfg{configoption}{targetname} = \*(Aqvalue\*(Aq .Ve .Sp See mrtg-reference for more information about the \s-1MRTG\s0 configuration syntax. .Sp \&\f(CW\*(C`readcfg\*(C'\fR can take two additional arguments to extend the config file syntax. This allows programs to put their configuration into the mrtg config file. The fifth argument is the prefix of the extension, the sixth argument is a hash with the checkrules for these extension settings. E.g. if the prefix is \*(L"14all\*(R" \f(CW\*(C`readcfg\*(C'\fR will check config lines that begin with \&\*(L"14all*\*(R", i.e. all lines like .Sp .Vb 2 \& 14all*columns: 2 \& 14all*graphsize[target3]: 500 200 .Ve .Sp against the rules in \f(CW%extrules\fR. The format of this hash is: .Sp .Vb 4 \& $extrules{option} = [sub{$_[0] =~ m/^\ed+$/}, sub{"Error message for $_[0]"}] \& i.e. \& $extrules{option}[0] \-> a test expression \& $extrules{option}[1] \-> error message if test fails .Ve .Sp The first part of the array is a perl expression to test the value of the option. The test can access this value in the variable \*(L"$arg\*(R". The second part of the array is an error message to display when the test fails. The failed value can be integrated by using the variable \*(L"$arg\*(R". .Sp Config settings with an different prefix than the one given in the \f(CW\*(C`readcfg\*(C'\fR call are not checked but inserted into \fI\f(CI%globalcfg\fI\fR and \fI\f(CI%targetcfg\fI\fR. Prefixed settings keep their prefix in the config hashes: .Sp .Vb 1 \& $targetcfg{\*(Aq14all*graphsize\*(Aq}{\*(Aqtarget3\*(Aq} = \*(Aq500 200\*(Aq .Ve .ie n .IP """cfgcheck""" 4 .el .IP "\f(CWcfgcheck\fR" 4 .IX Item "cfgcheck" \&\f(CW\*(C`cfgcheck(\e@target_names, \e%globalcfg, \e%targetcfg, \e@parsed_targets)\*(C'\fR .Sp Checks the configuration read by \f(CW\*(C`readcfg\*(C'\fR. Checks the values in the config for syntactical and/or semantical errors. Sets defaults for some options. Parses the \*(L"target[...]\*(R" options and files the array \f(CW@parsed_targets\fR ready for mrtg functions. .Sp The first three arguments are the same as for \f(CW\*(C`readcfg\*(C'\fR. The fourth argument is an arrayref which will be filled with the parsed target defs. .Sp \&\f(CW\*(C`cfgcheck\*(C'\fR converts the values of target settings \fIoptions\fR, e.g. .Sp .Vb 1 \& options[router1]: bits, growright .Ve .Sp to a hash: .Sp .Vb 2 \& $targetcfg{\*(Aqoption\*(Aq}{\*(Aqbits\*(Aq}{\*(Aqrouter1\*(Aq} = 1 \& $targetcfg{\*(Aqoption\*(Aq}{\*(Aqgrowright\*(Aq}{\*(Aqrouter1\*(Aq} = 1 .Ve .Sp This is not done by \f(CW\*(C`readcfg\*(C'\fR so if you don't use \f(CW\*(C`cfgcheck\*(C'\fR you have to check the scalar variable \fI\f(CI$targetcfg\fI{'option'}{'router1'}\fR (\s-1MRTG\s0 allows options to be separated by space or ','). .ie n .IP """ensureSL""" 4 .el .IP "\f(CWensureSL\fR" 4 .IX Item "ensureSL" \&\f(CW\*(C`ensureSL(\e$pathname)\*(C'\fR .Sp Checks that the \fIpathname\fR does not contain double path separators and ends with a path separator. It uses \f(CW$MRTG_lib::SL\fR as path separator which will be / or \e depending on the \s-1OS.\s0 .ie n .IP """log2rrd""" 4 .el .IP "\f(CWlog2rrd\fR" 4 .IX Item "log2rrd" \&\f(CW\*(C`log2rrd ($router,\e%globalcfg,\e%targetcfg)\*(C'\fR .Sp Convert log file to rrd format. Needs rrdtool. .ie n .IP """datestr""" 4 .el .IP "\f(CWdatestr\fR" 4 .IX Item "datestr" \&\f(CW\*(C`datestr(time)\*(C'\fR .Sp Returns the time given in the argument as a nicely formatted date string. The argument has to be in \s-1UNIX\s0 time format (seconds since 1970\-1\-1). .ie n .IP """timestamp""" 4 .el .IP "\f(CWtimestamp\fR" 4 .IX Item "timestamp" \&\f(CW\*(C`timestamp()\*(C'\fR .Sp Return a string representing the current time. .ie n .IP """setup_loghandlers""" 4 .el .IP "\f(CWsetup_loghandlers\fR" 4 .IX Item "setup_loghandlers" \&\f(CW\*(C`setup_loghandlers(filename)\*(C'\fR .Sp Install signalhandlers for _\|_DIE_\|_ and _\|_WARN_\|_ making the errors go the the specified destination. If filename is 'eventlog' mrtg will log to the windows event logger. .ie n .IP """expistr""" 4 .el .IP "\f(CWexpistr\fR" 4 .IX Item "expistr" \&\f(CW\*(C`expistr(time)\*(C'\fR .Sp Returns the time given in the argument formatted suitable for \s-1HTTP\s0 Expire-Headers. .ie n .IP """create_pid""" 4 .el .IP "\f(CWcreate_pid\fR" 4 .IX Item "create_pid" \&\f(CW\*(C`create_pid()\*(C'\fR .Sp Creates a pid file for the mrtg daemon .ie n .IP """demonize_me""" 4 .el .IP "\f(CWdemonize_me\fR" 4 .IX Item "demonize_me" \&\f(CW\*(C`demonize_me()\*(C'\fR .Sp Puts the running program into background, detaching it from the terminal. .ie n .IP """populatecache""" 4 .el .IP "\f(CWpopulatecache\fR" 4 .IX Item "populatecache" \&\f(CW\*(C`populatecache(\e%confcache, $host, $reread, $snmpoptshash)\*(C'\fR .Sp Reads the \s-1SNMP\s0 variables \fIifDescr\fR, \fIipAdEntIfIndex\fR, \fIifPhysAddress\fR, \fIifName\fR from the \fIhost\fR and stores the values in \fI\f(CI%confcache\fI\fR as follows: .Sp .Vb 5 \& $confcache{$host}{\*(AqDescr\*(Aq}{ifDescr}{oid} = (ifDescr or \*(AqDup\*(Aq) \& $confcache{$host}{\*(AqIP\*(Aq}{ipAdEntIfIndex}{oid} = (ipAdEntIfIndex or \*(AqDup\*(Aq) \& $confcache{$host}{\*(AqEth\*(Aq}{ifPhysAddress}{oid} = (ifPhysAddress or \*(AqDup\*(Aq) \& $confcache{$host}{\*(AqName\*(Aq}{ifName}{oid} = (ifName or \*(AqDup\*(Aq) \& $confcache{$host}{\*(AqType\*(Aq}{ifType}{oid} = (ifType or \*(AqDup\*(Aq) .Ve .Sp The value (at the right side of =) is 'Dup' if a value was retrieved multiple times, the retrieved value else. .ie n .IP """readconfcache""" 4 .el .IP "\f(CWreadconfcache\fR" 4 .IX Item "readconfcache" \&\f(CW\*(C`my $confcache = readconfcache($file)\*(C'\fR .Sp Preload the confcache from a file. .ie n .IP """readfromconfcache""" 4 .el .IP "\f(CWreadfromconfcache\fR" 4 .IX Item "readfromconfcache" \&\f(CW\*(C`writeconfcache($confcache,$file)\*(C'\fR .Sp Store the current confcache into a file. .ie n .IP """writeconfcache""" 4 .el .IP "\f(CWwriteconfcache\fR" 4 .IX Item "writeconfcache" \&\f(CW\*(C`writeconfcache($confcache,$file)\*(C'\fR .Sp Store the current confcache into a file. .ie n .IP """storeincache""" 4 .el .IP "\f(CWstoreincache\fR" 4 .IX Item "storeincache" \&\f(CW\*(C`storeincache($confcache,$host,$method,$key,$value)\*(C'\fR .ie n .IP """readfromcache""" 4 .el .IP "\f(CWreadfromcache\fR" 4 .IX Item "readfromcache" \&\f(CW\*(C`readfromcache($confcache,$host,$method,$key)\*(C'\fR .ie n .IP """clearfromcache""" 4 .el .IP "\f(CWclearfromcache\fR" 4 .IX Item "clearfromcache" \&\f(CW\*(C`clearfromcache($confcache,$host)\*(C'\fR .ie n .IP """debug""" 4 .el .IP "\f(CWdebug\fR" 4 .IX Item "debug" \&\f(CW\*(C`debug($type, $message)\*(C'\fR .Sp Prints the \fImessage\fR on \s-1STDERR\s0 if debugging is enabled for type \fItype\fR. A debug type is enabled if \fItype\fR is in array \f(CW@main::DEBUG\fR. .SH "AUTHORS" .IX Header "AUTHORS" Rainer Bawidamann .PP (This Manpage) mrtg-2.17.10/doc/mrtg-logfile.10000644000175300017510000001555214171763414015105 0ustar oetikeroep.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "MRTG-LOGFILE 1" .TH MRTG-LOGFILE 1 "2022-01-19" "2.17.10" "mrtg" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" mrtg\-logfile \- description of the mrtg\-2 logfile format .SH "SYNOPSIS" .IX Header "SYNOPSIS" This document provides a description of the contents of the mrtg\-2 logfile. .SH "OVERVIEW" .IX Header "OVERVIEW" The logfile consists of two main sections. .IP "The first Line" 4 .IX Item "The first Line" It stores the traffic counters from the most recent run of mrtg. .IP "The rest of the File" 4 .IX Item "The rest of the File" Stores past traffic rate averages and maximum at increasing intervals. .PP The first number on each line is a unix time stamp. It represents the number of seconds since 1970. .SH "DETAILS" .IX Header "DETAILS" .SS "The first Line" .IX Subsection "The first Line" The first line has 3 numbers which are: .IP "A (1st column)" 4 .IX Item "A (1st column)" A timestamp of when \s-1MRTG\s0 last ran for this interface. The timestamp is the number of non-skip seconds passed since the standard \s-1UNIX\s0 \*(L"epoch\*(R" of midnight on 1st of January 1970 \s-1GMT.\s0 .IP "B (2nd column)" 4 .IX Item "B (2nd column)" The \*(L"incoming bytes counter\*(R" value. .IP "C (3rd column)" 4 .IX Item "C (3rd column)" The \*(L"outgoing bytes counter\*(R" value. .SS "The rest of the File" .IX Subsection "The rest of the File" The second and remaining lines of the file contains 5 numbers which are: .IP "A (1st column)" 4 .IX Item "A (1st column)" The Unix timestamp for the point in time the data on this line is relevant. Note that the interval between timestamps increases as you progress through the file. At first it is 5 minutes and at the end it is one day between two lines. .Sp This timestamp may be converted in OpenOffice Calc or \s-1MS\s0 Excel by using the following formula .Sp .Vb 1 \& =(x+y)/86400+DATE(1970;1;1) .Ve .Sp (instead of \*(L";\*(R" it may be that you have to use \*(L",\*(R" this depends on the context and your locale settings) .Sp you can also ask perl to help by typing .Sp .Vb 1 \& perl \-e \*(Aqprint scalar localtime(x),"\en"\*(Aq .Ve .Sp \&\fBx\fR is the unix timestamp and \fBy\fR is the offset in seconds from \s-1UTC.\s0 (Perl knows \fBy\fR). .IP "B (2nd column)" 4 .IX Item "B (2nd column)" The average incoming transfer rate in bytes per second. This is valid for the time between the A value of the current line and the A value of the previous line. .IP "C (3rd column)" 4 .IX Item "C (3rd column)" The average outgoing transfer rate in bytes per second since the previous measurement. .IP "D (4th column)" 4 .IX Item "D (4th column)" The maximum incoming transfer rate in bytes per second for the current interval. This is calculated from all the updates which have occurred in the current interval. If the current interval is 1 hour, and updates have occurred every 5 minutes, it will be the biggest 5 minute transfer rate seen during the hour. .IP "E (5th column)" 4 .IX Item "E (5th column)" The maximum outgoing transfer rate in bytes per second for the current interval. .SH "AUTHOR" .IX Header "AUTHOR" Butch Kemper and Tobias Oetiker mrtg-2.17.10/doc/mrtg-mibhelp.10000644000175300017510000002352114171763415015100 0ustar oetikeroep.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "MRTG-MIBHELP 1" .TH MRTG-MIBHELP 1 "2022-01-19" "2.17.10" "mrtg" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" mrtg\-mibhelp \- A Table of some interesting OIDs .SH "OVERVIEW" .IX Header "OVERVIEW" This File Contains a collection of interesting \s-1MIB\s0 Entries ... mrtg knows about their names ... depending on the \s-1ASN.1\s0 Syntax you may have to put \fBgauge\fR into the \fBOptions[]:\fR parameter. .PP For information about how to create a \fBTarget[]:\fR parameter which references these \s-1MIB\s0 entries, please consult mrtg-reference. .SH "MIB LIST" .IX Header "MIB LIST" .SS "ifOperStatus" .IX Subsection "ifOperStatus" .Vb 4 \& Descriptor: ifOperStatus \& Identifier: 1.3.6.1.2.1.2.2.1.8 \& ASN.1 Syntax: INTEGER \& Enumeration: up 1, down 2, testing 3 .Ve .PP The current operational state of the interface. The \fBtesting\fR\|(3) state indicates that no operational packets can be passed. .SS "ifAdminStatus" .IX Subsection "ifAdminStatus" .Vb 4 \& Descriptor: ifAdminStatus \& Identifier: 1.3.6.1.2.1.2.2.1.7 \& ASN.1 Syntax: INTEGER \& Enumeration: up 1, down 2, testing 3 .Ve .PP The current administrative state of the interface. The \fBtesting\fR\|(3) state indicates that no operational packets can be passed. .SS "ifInOctets" .IX Subsection "ifInOctets" .Vb 3 \& Descriptor: ifInOctets \& Identifier: 1.3.6.1.2.1.2.2.1.10 \& ASN.1 Syntax: Counter32 .Ve .PP The total number of octets received on the interface, including framing characters. .SS "ifInUcastPkts" .IX Subsection "ifInUcastPkts" .Vb 3 \& Descriptor: ifInUcastPkts \& Identifier: 1.3.6.1.2.1.2.2.1.11 \& ASN.1 Syntax: Counter32 .Ve .PP The number of subnetwork-unicast packets delivered to a higher-layer protocol. .SS "ifInNUcastPkts" .IX Subsection "ifInNUcastPkts" .Vb 3 \& Descriptor: ifInNUcastPkts \& Identifier: 1.3.6.1.2.1.2.2.1.12 \& ASN.1 Syntax: Counter32 .Ve .PP The number of non-unicast (i.e., subnetwork\- broadcast or subnetwork-multicast) packets delivered to a higher-layer protocol. .SS "ifInDiscards" .IX Subsection "ifInDiscards" .Vb 3 \& Descriptor: ifInDiscards \& Identifier: 1.3.6.1.2.1.2.2.1.13 \& ASN.1 Syntax: Counter32 .Ve .PP The number of inbound packets which were chosen to be discarded even though no errors had been detected to prevent their being deliverable to a higher-layer protocol. One possible reason for discarding such a packet could be to free up buffer space. .SS "ifInErrors" .IX Subsection "ifInErrors" .Vb 3 \& Descriptor: ifInErrors \& Identifier: 1.3.6.1.2.1.2.2.1.14 \& ASN.1 Syntax: Counter32 .Ve .PP The number of inbound packets that contained errors preventing them from being deliverable to a higher-layer protocol. .SS "ifInUnknownProtos" .IX Subsection "ifInUnknownProtos" .Vb 3 \& Descriptor: ifInUnknownProtos \& Identifier: 1.3.6.1.2.1.2.2.1.15 \& ASN.1 Syntax: Counter32 .Ve .PP The number of packets received via the interface which were discarded because of an unknown or unsupported protocol. .SS "ifOutOctets" .IX Subsection "ifOutOctets" .Vb 3 \& Descriptor: ifOutOctets \& Identifier: 1.3.6.1.2.1.2.2.1.16 \& ASN.1 Syntax: Counter32 .Ve .PP The total number of octets transmitted out of the interface, including framing characters. .SS "ifOutUcastPkts" .IX Subsection "ifOutUcastPkts" .Vb 3 \& Descriptor: ifOutUcastPkts \& Identifier: 1.3.6.1.2.1.2.2.1.17 \& ASN.1 Syntax: Counter32 .Ve .PP The total number of packets that higher-level protocols requested be transmitted to a subnetwork-unicast address, including those that were discarded or not sent. .SS "ifOutNUcastPkts" .IX Subsection "ifOutNUcastPkts" .Vb 3 \& Descriptor: ifOutNUcastPkts \& Identifier: 1.3.6.1.2.1.2.2.1.18 \& ASN.1 Syntax: Counter32 .Ve .PP The total number of packets that higher-level protocols requested be transmitted to a non\- unicast (i.e., a subnetwork-broadcast or subnetwork-multicast) address, including those that were discarded or not sent. .SS "ifOutDiscards" .IX Subsection "ifOutDiscards" .Vb 3 \& Descriptor: ifOutDiscards \& Identifier: 1.3.6.1.2.1.2.2.1.19 \& ASN.1 Syntax: Counter32 .Ve .PP The number of outbound packets which were chosen to be discarded even though no errors had been detected to prevent their being transmitted. One possible reason for discarding such a packet could be to free up buffer space. .SS "ifOutErrors" .IX Subsection "ifOutErrors" .Vb 3 \& Descriptor: ifOutErrors \& Identifier: 1.3.6.1.2.1.2.2.1.20 \& ASN.1 Syntax: Counter32 .Ve .PP The number of outbound packets that could not be transmitted because of errors. .SS "ifOutQLen" .IX Subsection "ifOutQLen" .Vb 3 \& Descriptor: ifOutQLen \& Identifier: 1.3.6.1.2.1.2.2.1.21 \& ASN.1 Syntax: Unsigned32 .Ve .PP The length of the output packet queue (in packets). .SS "frInOctets" .IX Subsection "frInOctets" From: Simon Ferrett .PP .Vb 2 \& \*(AqfrInOctets\*(Aq => \*(Aq1.3.6.1.2.1.10.32.2.1.9\*(Aq \& \*(AqfrOutOctets\*(Aq => \*(Aq1.3.6.1.2.1.10.32.2.1.7\*(Aq .Ve .PP which when used in the form: .PP .Vb 1 \& frInOctets.pp.dd&frOutOctets.pp.dd:community@cisco.router .Ve .PP where pp is the physical port that the frame relay pvc is defined on and dd is the \s-1DLCI\s0 of the pvc gets you the in and out octets for just that pvc. .SS "ifAdminHack and ifOperHack" .IX Subsection "ifAdminHack and ifOperHack" The return values of ifAdminStatus and ifOperStatus are not very useful for graphing. Use ifOperHack and ifAdminHack instead. They return 1 for \&\s-1UP\s0 and 0 otherwise. .PP Note these are not real \s-1MIB\s0 entities but mrtg hacks .SS "PseudoZero and PseudoOne" .IX Subsection "PseudoZero and PseudoOne" will return 0 and 1 respectively .PP Note these are not real \s-1MIB\s0 entities but mrtg hacks .SH "AUTHOR" .IX Header "AUTHOR" Tobias Oetiker mrtg-2.17.10/doc/mrtg-nt-guide.10000644000175300017510000004607514171763414015204 0ustar oetikeroep.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "MRTG-NT-GUIDE 1" .TH MRTG-NT-GUIDE 1 "2022-01-19" "2.17.10" "mrtg" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" mrtg\-nt\-guide \- The MRTG 2.17.10 Windows Installation Guide .SH "SYNOPSIS" .IX Header "SYNOPSIS" Installing \s-1MRTG\s0 on a Windows box is not quite as \*(L"click and point\*(R" as some might want it to be. But then again, it is not all that difficult if you follow the instructions below. .SH "PREREQUISITES" .IX Header "PREREQUISITES" To get \s-1MRTG\s0 to work on Windows you need the following: .IP "\(bu" 4 A current copy of Perl. For Example ActivePerl 5.8.8 from ActiveState http://www.activestate.com/store/activeperl/download/ .IP "\(bu" 4 The latest version of \s-1MRTG\s0 from http://oss.oetiker.ch/mrtg/pub. Look for mrtg\-2.17.10.zip or better. The archive also contains a precompiled copy of rateup.exe for Win32. .SH "INSTALLING" .IX Header "INSTALLING" I suggest you do the following from the machine that will be running \s-1MRTG,\s0 which, in this case, is also a web server. All examples are for doing things to a \s-1LOCAL\s0 machine. .IP "First" 4 .IX Item "First" Unzip \s-1MRTG\s0 to C:\emrtg\-2.17.10 on the Windows machine of your choice. .IP "Next" 4 .IX Item "Next" Install Perl on the same Windows machine. You might want to make sure that the Perl binary directory is listed in your system path. .Sp .Vb 1 \& C:\ePerl\ebin;%SystemRoot%\esystem32;%SystemRoot%;... .Ve .Sp You can manually check this by going to [Control Panel]\->[System]\->[Environment] .PP To see if everything is installed properly you can open a Command Shell and go into \fIc:\emrtg\-2.17.10\ebin\fR. Type: .PP .Vb 1 \& perl mrtg .Ve .PP This should give you a friendly error message complaining about the missing \s-1MRTG\s0 configuration file. Now, you have successfully installed \s-1MRTG\s0 and Perl. .SH "CONFIGURING MRTG" .IX Header "CONFIGURING MRTG" Now it is time to create a configuration for \s-1MRTG.\s0 But before we begin you need to know a few things. Take an opportunity to gather the following information: .IP "\(bu" 4 The \s-1IP\s0 address or hostname and the \s-1SNMP\s0 port number, (if non standard), of the device you want to monitor. .IP "\(bu" 4 If you want to monitor something other than bytes in and out, you must also know the \s-1SNMPOID\s0 of what you want to monitor. .IP "\(bu" 4 Finally you need to know the read-only \s-1SNMP\s0 community string for your device. If you don't know it, try \fBpublic\fR, that is the default. .PP For the rest of this document we will be using device \fB10.10.10.1\fR ( a \s-1CISCO\s0 Catalyst 5000) with Community string \fBpublic\fR. We are interested in monitoring traffic, and the \s-1CPU\s0 load. Let's begin. .PP The first thing we do in setting up \s-1MRTG\s0 is making a default config file. Get to a cmd prompt and change to the \fIc:\emrtg\-2.17.10\ebin\fR directory. Type the following command: .PP .Vb 1 \& perl cfgmaker public@10.10.10.1 \-\-global "WorkDir: c:\ewww\emrtg" \-\-output mrtg.cfg .Ve .PP This creates an initial \s-1MRTG\s0 config file for you. Note that in this file all interfaces of your router will be stored by number. Unfortunately, these numbers are likely to change whenever you reconfigure your router. In order to work around this you can get \fIcfgmaker\fR to produce a configuration which is based on Ip numbers, or even Interface Descriptions. Check cfgmaker .PP If you get an error message complaining about \fBno such name\fR or \fBno response\fR, your community name is probably wrong. .PP Now, let's take a look at the mrtg.cfg file that was created. .PP In Perl, a \f(CW\*(C`#\*(C'\fR is a comment, synonymous with \f(CW\*(C`REM\*(C'\fR in \s-1DOS.\s0 .PP Add the following to the top of the mrtg.cfg file: .PP .Vb 1 \& WorkDir: c:\ewww\emrtg .Ve .PP This is where the web pages are created, usually a web root. .PP .Vb 6 \& ###################################################################### \& # Description: LCP SUWGB \& # Contact: Administrator \& # System Name: LC\-Bridge \& # Location: Here \& #..................................................................... .Ve .PP TargetDevice's \s-1IP\s0 Address:Interface Number:Community:IP Address .PP .Vb 1 \& Target[10.10.10.1.1]: 1:public@10.10.10.1 .Ve .PP This is the interface speed (Default is 10 megabits; for 100Mbit devices use 12500000 and so on...) .PP .Vb 1 \& MaxBytes[10.10.10.1.1]: 1250000 \& \& Title[10.10.10.1.1]: LC\-Bridge (sample.device): ether0 .Ve .PP This section determines how the web page headers will look .PP .Vb 9 \& PageTop[10.10.10.1.1]:

      Traffic Analysis for ether0

      \& \& \& \& \& \& \& \&
      System:LC\-Bridge inAndover
      Maintainer:Administrator
      Interface:ether0(1)
      IP:sample.device(10.10.10.1)
      Max Speed:1250.0 kBytes/s (ethernetCsmacd)
      \& \& Target[10.10.10.1.2]: 2:public@10.10.10.1 \& MaxBytes[10.10.10.1.2]: 1250000 \& Title[10.10.10.1.2]: LC\-Bridge (): ulink0 \& PageTop[10.10.10.1.2]:

      Traffic Analysis for ulink0

      \& \& \& \& \& \& \& \&
      System:LC\-Bridge inAndover
      Maintainer:Administrator
      Interface:ulink0(2)
      IP:()
      Max Speed:1250.0 kBytes/s (ethernetCsmacd)
      \& \& #\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- .Ve .PP And that's a very basic \s-1MRTG\s0 config file. You can run this and see your results by going into the \fIc:\emrtg\-2.17.10\ebin\fR directory and typing: .PP .Vb 1 \& perl mrtg mrtg.cfg .Ve .PP It is normal to get errors for the first two times you run this command. The errors will alert you about the fact that there have not been any log files in existence before. .PP If you take a look at those web pages they are not very exciting (yet). You need to have the \s-1MRTG\s0 files run every five minutes to produce the desired results. Just run it again after a few minutes. You should now be able to see the first lines in your graphs. .SH "MAKE MRTG RUN ALL THE TIME" .IX Header "MAKE MRTG RUN ALL THE TIME" Starting \s-1MRTG\s0 by hand every time you want to run it is not going to make you happy I guess. .PP There is a special option you can set in the \s-1MRTG\s0 configuration file so so that \s-1MRTG\s0 will not terminate after it was started. Instead it will wait for 5 minutes and then run again. .PP Add the option .PP .Vb 1 \& RunAsDaemon: yes .Ve .PP to your mrtg.cfg file and start it with: .PP .Vb 1 \& start /Dc:\emrtg\-2.17.10\ebin wperl mrtg \-\-logging=eventlog mrtg.cfg .Ve .PP If you use \fBwperl\fR instead of \fBperl\fR, no console window will show. \s-1MRTG\s0 is now running in the background. If it runs into problems it will tell you so over the EventLog. To stop \s-1MRTG,\s0 open the Task Manager and terminate the \&\fBwperl.exe\fR process. If mrtg has anything to tell you these messages can be found in the event log. .PP If you put a shortcut with .PP .Vb 2 \& Target: wperl mrtg \-\-logging=eventlog mrtg.cfg \& Start in: c:\emrtg\-2.17.10\ebin .Ve .PP into your start-up folder, \s-1MRTG\s0 will now start whenever you login to your \s-1NT\s0 box. .PP If you do not want to log into your box just to start \s-1MRTG.\s0 Have a look at http://www.firedaemon.com/mrtg\-howto.html which describes a free tool to start any program as a Service. The pages gives specific instructions for \&\s-1MRTG\s0 users. .SH "HOW TO SETUP MRTG AS A WINDOWS SERVICE" .IX Header "HOW TO SETUP MRTG AS A WINDOWS SERVICE" .SS "Additional Prerequisites" .IX Subsection "Additional Prerequisites" .IP "\(bu" 4 \&\s-1MRTG\s0 must be installed and fully configured on the target system. In the following exercise the assumption is that \s-1MRTG\s0 is installed under c:\emrtg\e and all the sample files use this location. .IP "\(bu" 4 Microsoft Tools \fB\s-1SRVANY\s0.exe\fR (Applications as Services Utility) and \&\fB\s-1INSTSRV\s0.exe\fR (Service Installer) \- Those files can be downloaded from Microsoft as a part of Windows 2000 Resource Kit at . They are also available from other locations such as , , etc. Detailed instructions on how to use this package are available at . In order to follow the steps in this HOW-TO you \fB\s-1MUST\s0\fR obtain both executables. .IP "\(bu" 4 You must have administrative rights on the target system. .SS "Preparation" .IX Subsection "Preparation" Please complete the following steps before starting the installation: .IP "\(bu" 4 Copy \fBsrvany.exe\fR and \fBinstsrv.exe\fR to c:\emrtg\-2.17.10\ebin\e (your \s-1MRTG\s0 bin directory). .IP "\(bu" 4 Create a file called \fBmrtg.reg\fR anywhere on your system and paste the following content into it: .Sp .Vb 1 \& Windows Registry Editor Version 5.00 \& \& [HKEY_LOCAL_MACHINE\eSYSTEM\eCurrentControlSet\eServices\eMRTG\eParameters] \& "Application"="c:\e\eperl\e\ebin\e\ewperl.exe" \& "AppParameters"="c:\e\emrtg\-2.17.10\e\ebin\e\emrtg \-\-logging=eventlog c:\e\emrtg\-2.17.10\e\ebin\e\emrtg.cfg" \& "AppDirectory"="c:\e\emrtg\-2.17.10\e\ebin\e\e" .Ve .SS "Service Installation" .IX Subsection "Service Installation" Once again, assuming that \s-1MRTG\s0 is already fully installed and configured on the target system under c:\emrtg\e the following steps are necessary to setup \&\s-1MRTG\s0 as a service. .PP Using the command prompt go into the temporary directory where you unzipped the package. When there type the following command to create a service named \*(L"\s-1MRTG\*(R"\s0 in the Windows Services management console: .PP .Vb 1 \& instsrv MRTG c:\emrtg\ebin\esrvany.exe .Ve .PP Now you need to create the \fBApp*\fR entries required for the new service. You can do this by either right-clicking on the mrtg.reg file and selecting \&'merge' or by running the following command: .PP .Vb 1 \& regedit /s mrtg.reg .Ve .PP After setting up the registry entry it is time to point it to your \s-1MRTG\s0 installation. If you have installed \s-1MRTG\s0 under \fIc:\emrtg\e\fR, you can skip this step. Open your registry editor (Start \-> Run \-> regedt32), and locate the \&\fB[HKEY_LOCAL_MACHINE\eSYSTEM\eCurrentControlSet\eServices\eMRTG]\fR key. Make sure that the \fBImagePath\fR variable is correctly pointing to \fBsrvany.exe\fR located in your \s-1MRTG\s0 bin directory (for example c:\emrtg\ebin\esrvany.exe). Next you have to expand the \s-1MRTG\s0 tree, and go to the \&\fB[HKEY_LOCAL_MACHINE\eSYSTEM\eCurrentControlSet\eServices\eMRTG\eParameters]\fR key. Under Parameters make sure that all the \fBApplication\fR variables are setup properly. .PP At this point you are ready to run the service. The only thing left to do is to start the \s-1MRTG\s0 service in the Services management console. After you do this, you should see two new processes running on your system: srvany.exe and wperl.exe. Make sure to stop any previously running \s-1MRTG\s0 processes to avoid conflict. .PP Note that it is imperative to set the \fBRunAsDaemon: yes\fR option or the service will stop after just one single run! .SH "EXAMPLE" .IX Header "EXAMPLE" Now lets look at a config file to monitor what we wanted to on our mythical Cisco Cat 5000 \*(-- utilization on ports 3, 5, 10, and 24, and the \s-1CPU\s0 Load, which will show us nonstandard mrtg configurations as well as more options.. .PP .Vb 2 \& WorkDir: c:\ewww\emrtg \& RunAsDaemon: yes \& \& ###################################################################### \& # Description: LCP SUWGB \& # Contact: Administrator \& # System Name: LC\-Bridge \& # Location: Here \& #..................................................................... \& \& Target[10.10.10.1.1]: 3:public@10.10.10.1 \& MaxBytes[10.10.10.1.1]: 1250000 \& Title[10.10.10.1.1]: LC\-Bridge (sample\-device): ether0 \& PageTop[10.10.10.1.1]:

      Traffic Analysis for ether0

      \& \& \& \& \& \& \& \&
      System:LC\-Bridge inAndover
      Maintainer:Administrator
      Interface:ether0(3)
      IP:sample\-device(10.10.10.1)
      Max Speed:1250.0 kBytes/s (ethernetCsmacd)
      \& \& #\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- \& \& Target[10.10.10.1.2]: 5:public@10.10.10.1 \& MaxBytes[10.10.10.1.2]: 1250000 \& Title[10.10.10.1.2]: LC\-Bridge (): ulink0 \& PageTop[10.10.10.1.2]:

      Traffic Analysis for ulink0

      \& \& \& \& \& \& \& \&
      System:LC\-Bridge inAndover
      Maintainer:Administrator
      Interface:ulink0(5)
      IP:()
      Max Speed:1250.0 kBytes/s (ethernetCsmacd)
      \& \& #\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- \& \& Target[10.10.10.1.1]: 10:public@10.10.10.1 \& MaxBytes[10.10.10.1.1]: 1250000 \& Title[10.10.10.1.1]: LC\-Bridge (sample\-device): ether0 \& PageTop[10.10.10.1.1]:

      Traffic Analysis for ether0

      \& \& \& \& \& \& \& \&
      System:LC\-Bridge inAndover
      Maintainer:Administrator
      Interface:ether0(10)
      IP:sample\-device(10.10.10.1)
      Max Speed:1250.0 kBytes/s (ethernetCsmacd)
      \& \& #\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- \& \& Target[10.10.10.1.2]: 24:public@10.10.10.1 \& MaxBytes[10.10.10.1.2]: 1250000 \& Title[10.10.10.1.2]: LC\-Bridge (): ulink0 \& PageTop[10.10.10.1.2]:

      Traffic Analysis for ulink0

      \& \& \& \& \& \& \& \&
      System:LC\-Bridge inAndover
      Maintainer:Administrator
      Interface:ulink0(24)
      IP:()
      Max Speed:1250.0 kBytes/s (ethernetCsmacd)
      \& \& #\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- \& \& # Router CPU load % \& Target[cpu.1]:1.3.6.1.4.1.9.2.1.58.0&1.3.6.1.4.1.9.2.1.58.0:public@10.10.10.1 \& RouterUptime[cpu.1]: public@10.10.10.1 \& MaxBytes[cpu.1]: 100 \& Title[cpu.1]: CPU LOAD \& PageTop[cpu.1]:

      CPU Load %

      \& Unscaled[cpu.1]: ymwd \& ShortLegend[cpu.1]: % \& XSize[cpu.1]: 380 \& YSize[cpu.1]: 100 \& YLegend[cpu.1]: CPU Utilization \& Legend1[cpu.1]: CPU Utilization in % (Load) \& Legend2[cpu.1]: CPU Utilization in % (Load) \& Legend3[cpu.1]: \& Legend4[cpu.1]: \& LegendI[cpu.1]: \& LegendO[cpu.1]:  Usage \& Options[cpu.1]: gauge .Ve .PP This is a nice example of how to monitor any \s-1SNMP\s0 device if you know what \s-1OID\s0 you want to use. Once again, for an explanation of the more advance features of mrtg, please see the rest of the documentation. .SH "AUTHORS" .IX Header "AUTHORS" Tobi Oetiker , David S. Divins , Steve Pierce , Artyom Adjemov , Ilja Ivanov Karel Fajkus mrtg-2.17.10/doc/mrtg-nw-guide.10000644000175300017510000004440614171763414015203 0ustar oetikeroep.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "MRTG-NW-GUIDE 1" .TH MRTG-NW-GUIDE 1 "2022-01-19" "2.17.10" "mrtg" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" mrtg\-nw\-guide \- MRTG for NetWare .SH "SYNOPSIS" .IX Header "SYNOPSIS" This guide is intended to aid in the installation and configuration of \s-1MRTG\s0 on a NetWare server. .SH "OVERVIEW" .IX Header "OVERVIEW" \&\s-1MRTG\s0 is a relative newcomer to the NetWare platform. Earlier versions of NetWare could not run \s-1MRTG\s0 natively for several reasons: .IP "\(bu" 4 Absence of NetWare \s-1OS\s0 support in the \s-1MRTG\s0 package. .IP "\(bu" 4 A NetWare server commandline length limitation. .IP "\(bu" 4 Absence of the Rateup executable (Rateup.nlm). .IP "\(bu" 4 A standard installation method. .IP "\(bu" 4 Problems with NetWare's implementation of Perl. .PP Support for the NetWare \s-1OS\s0 has now been fully added into \s-1MRTG,\s0 beginning with \s-1MRTG\s0 release 2.12.2. .PP Liberally minded operating systems support a commandline length approaching 1000 characters. In such environments it was an easy matter to pass the sometimes high number of parameters used by \s-1MRTG\s0's Rateup executable directly on the commandline. Until NetWare 6.5, NetWare had a commandline limit of 512 characters. This limitation was also removed for NetWare 6.0 by Service Pack 5. For other NetWare versions and earlier Service Packs, this limitation remains. To permit a 'standard' interface for NetWare, the Rateup executable has been modified to also read its parameters from a file, and the \s-1MRTG\s0 script has been modified to support this method on a NetWare platform. (See New Rateup Switch) .PP A Rateup \s-1NLM\s0 is now available, along with the necessary scripts to build it if required. See the NetWare Support section of this document for further details. Additionally, mrtg.pl has been revised because of the unique (to NetWare) name of executables (\s-1NLM\s0). .PP The absence of a specific installation procedure has caused \s-1MRTG\s0 to fail in the past because the Perl script could not find or load the Rateup executable. The installation method supplied here will solve this problem for now. .PP The \s-1MRTG\s0.pl script in the 2.12.2 (or later) version of \s-1MRTG\s0 has been configured to suit all likely versions of NetWare able to use Perl5, and bypasses all of the known problems with NetWare Perl running \s-1MRTG.\s0 .SH "PREREQUISITES" .IX Header "PREREQUISITES" You will need the following: .IP "\(bu" 4 Perl 5.8.0 for NetWare with latest Perl Updates (February, 2005 or later; previous versions \s-1MAY\s0 work) .IP "\(bu" 4 NetWare 5.1 w/ \s-1SP8,\s0 NetWare 6.0 w/ \s-1SP5\s0 or NetWare 6.5 w/ \s-1SP2.\s0 .IP "\(bu" 4 A copy of the \s-1MRTG\s0 Package (v2.12.2 at time of writing) .IP "\(bu" 4 Three .ncf files to execute the Perl scripts at the NetWare server console. .IP "\(bu" 4 A copy of the Rateup \s-1NLM\s0 (Pre-built or compiled) .IP "\(bu" 4 Optionally, any NetWare supported Web Server (Netscape, Apache 1.3 or 2.0) .PP For copies of the .ncf files and Rateup \s-1NLM,\s0 see NetWare Support in this document. .SH "INSTALLING MRTG" .IX Header "INSTALLING MRTG" .IP "1." 4 Install the latest Perl 5.8.x release on your server. See the Perl documentation for details. .IP "2." 4 Create the following directories: .Sp .Vb 10 \& SYS:/Mrtg \& SYS:/Mrtg/bin \& SYS:/Mrtg/contrib (Optional for this document) \& SYS:/Mrtg/doc (Optional for this document) \& SYS:/Mrtg/html \& SYS:/Mrtg/html/images \& SYS:/Mrtg/html/work \& SYS:/Mrtg/lib \& SYS:/Mrtg/logs \& SYS:/Mrtg/translate .Ve .IP "3." 4 Copy from the \s-1MRTG\s0 package the following files: .Sp .Vb 1 \& \ebin\e* to SYS:/Mrtg/bin All files. See Note 1. .Ve .Sp Note 1: Add a .pl extension to the mrtg, cfgmaker and indexmaker files. The rateup.exe will \s-1NOT\s0 be needed on the NetWare server. .Sp .Vb 4 \& \econtrib\e* to SYS:/Mrtg/contrib/ Include sub\-directories \& \edoc\e* to SYS:/Mrtg/doc/ All files \& \eimages\e* to SYS:/Mrtg/html/images/ All files \& \etranslate\e* to SYS:/Mrtg/translate/ All files. See Note 2. .Ve .Sp Note 2: For English-only language support, all \etranslate files \s-1EXCEPT\s0 Locales_mrtg may be deleted. .Sp .Vb 1 \& \elib\e* to SYS:/Mrtg/lib Include sub\-directories. See Note 3. .Ve .Sp Note 3: This will create the SYS:/Mrtg/lib/mrtg2 and ./pod directories. .IP "4." 4 Create copies of the three .ncf files and install them: .Sp .Vb 1 \& *.ncf to SYS:/Mrtg/bin .Ve .Sp See NetWare Support in this document for details on how to create copies of these files. .IP "5." 4 See Compiling Rateup.nlm"> in this document for details on compiling the Rateup \s-1NLM\s0 yourself if desired. A prebuit verion is available in the .\emrtg\ebin directory where it must remain. .SH "CONFIGURING MRTG" .IX Header "CONFIGURING MRTG" .IP "\(bu" 4 Refer to Novell documentation on configuring and loading \s-1SNMP\s0 support on your server if this is the device to be monitored. .IP "\(bu" 4 Edit sys:/mrtg/bin/MakeMrtgCfg.ncf: .Sp replace ccccc with the \s-1GET\s0 community name for the \s-1SNMP\s0 device (typically 'public'), .Sp replace ddddd with the \s-1DNS\s0 name or \s-1IP\s0 address of the device to be monitored. e.g public@www.myserver.com, public@10.202.65.180 .Sp Note 1: These are \s-1NOT\s0 mail addresses, they just look like one! .Sp Note 2: If multiple devices are to be monitored, add their entries to the same line: .Sp e.g perl cfgmaker.pl public@www.myserver.com public@10.202.65.180 > sys:/mrtg/bin/mrtg.cfg .Sp In this \*(L"Getting Started\*(R", it is 'suggested' to only monitor a single device. .IP "\(bu" 4 At the server console, run: .Sp .Vb 1 \& sys:/mrtg/bin/MakeMrtgCfg.ncf .Ve .Sp This will create Mrtg.cfg in sys:/mrtg/bin. .IP "\(bu" 4 Edit the Mrtg.cfg configuration file created in the previous step. Note the following: .Sp It was found, when testing \s-1MRTG\s0 on a NetWare 6.5 server using a \s-1NIC\s0 Interface, that mrtg.cfg contained the following message: .Sp .Vb 5 \& ### Interface 1 >> Descr: \*(AqIntel(R)\-8255x\-based\-Network\-Connection\*(Aq... \& ### The following interface is commented out because: \& ### * has a speed of 0 which makes no sense \& # \& ... .Ve .Sp If this occurs, edit MakeMrtgCfg.ncf and add the following parameter as shown: .Sp .Vb 1 \& perl sys:\emrtg\ebin\ecfgmaker.pl \-\-zero\-speed=nnn public@10.202.65.180 > sys:\emrtg\ebin\eMrtg.cfg .Ve .Sp where \fBnnn\fR is the interface speed in bits per second. For a 100 Megabit \s-1LAN NIC,\s0 nnn = 10000000. It will be necessary to re-execute the MakeMrtgCfg.ncf script before continuing with this section. .Sp Below line 16 (*** Global Defaults), add: .Sp .Vb 4 \& HtmlDir: e.g HtmlDir: sys:/mrtg/html \& ImageDir: e.g ImageDir: sys:/mrtg/html/work \& LogDir: e.g LogDir: sys:/mrtg/logs \& IconDir: e.g IconDir: ./images .Ve .Sp Note 1. The HtmlDir entry specifies where \s-1MRTG\s0 will create its \s-1HTML\s0 pages. .Sp Note 2. The ImageDir entry specifies where the created graphic icons are placed. .Sp Note 3. The IconDir entry specifies where the supplied \s-1MRTG\s0 icons are located. It \s-1MUST\s0 be a relative path from HtmlDir or absolute \s-1URL.\s0 The value shown is recommended. .IP "\(bu" 4 At the server console run: .Sp .Vb 1 \& sys:/mrtg/bin/RunMrtg.ncf .Ve .Sp several times. By the third time it should run without showing error messages on the console screen. .Sp This should create. .Sp \&\- A \s-1HTML\s0 page in the (HtmlDir) directory for each monitored device, .Sp \&\- A .dat file in the (ImageDir) directory for each monitored device, .Sp \&\- Several .png icons in the (ImageDir) directory, .Sp \&\- Some log file entries in the (LogDir) directory. .Sp Note: If you experience a \*(L"Use of uninitialised value in split\*(R" error, it will be necessary to create a 'Path' environment variable at the server console; use the following example .Sp .Vb 1 \& env path="SYS:\e" (The actual value is immaterial, as long as the var itself exists.) .Ve .IP "\(bu" 4 Edit sys:/mrtg/bin/MakeMrtgIndex.ncf. Change the indicated shown in the following example to match the value entered for (HtmlDir). .Sp .Vb 1 \& perl \-\-noscreen sys:/mrtg/bin/indexmaker.pl sys:/mrtg/bin/Mrtg.cfg > /index.html .Ve .IP "\(bu" 4 Create an index.html page linking the separate device \s-1HTML\s0 page(s). At the server console, run: .Sp .Vb 1 \& sys:/mrtg/bin/MakeMrtgIndex.ncf .Ve .Sp This will create index.html in the (HtmlDir) directory. .IP "\(bu" 4 Optionally, configure a Web Server to permit access to the directory specified in (HtmlDir) to view the \s-1MRTG\s0 graphs remotely, at, for example: .Sp .Vb 1 \& http://ip_or_dns/mrtg/index.html .Ve .Sp A sample configuration for an Apache Webserver is shown: .Sp .Vb 6 \& Alias /mrtg/ "SYS:/mrtg/html/" \& \& AllowOverride None \& Order allow,deny \& Allow from all \& .Ve .IP "\(bu" 4 Set the property of the directory pointed to by (ImageDir), to 'Purge Immediate'. .IP "\(bu" 4 Finally, read the \s-1MRTG\s0 documentation for much more detailed configuration/usage information. .PP Welcome to \s-1MRTG\s0!! .SH "MAKE MRTG RUN ALL THE TIME" .IX Header "MAKE MRTG RUN ALL THE TIME" \&\s-1MRTG\s0 can be made to run periodically by at least two means: .IP "\(bu" 4 Using \s-1CRON\s0 Scheduling .IP "\(bu" 4 Running \s-1MRTG\s0 in Daemon Mode .SS "\s-1CRON\s0 Scheduling" .IX Subsection "CRON Scheduling" To use \s-1CRON\s0 scheduling, create a \s-1CRON\s0 Scheduler entry to execute the RunMrtg.ncf file on a frequency appropriate for the server environment and information desired. The following entry in the sys:\eetc\ecrontab file will execute \s-1MRTG\s0 every five minutes: .PP .Vb 1 \& 0,5,10,15,20,25,30,35,40,45,50,55 * * * * sys:\emrtg\ebin\erunmrtg.ncf .Ve .PP The \s-1CRON\s0 Scheduler (cron.nlm) can be started automatically by adding it in \s-1AUTOEXEC\s0.ncf or, manually loading it at the server console. .SS "\s-1MRTG\s0 in Daemon Mode" .IX Subsection "MRTG in Daemon Mode" Refer to the MRTG-Reference document for information about the 'RunAsDaemon' option. Its use is outside the scope of this document. .SH "TROUBLESHOOTING" .IX Header "TROUBLESHOOTING" Read the \s-1MRTG\s0 documents, Perl documents or, finally, submit questions to the \s-1MRTG\s0 User forums. .PP For NetWare specific issues, submit questions to the Perl forum at news://developer\-forums.novell.com/novell.devsup.perl (Novell Developer Forums). .SH "COMPILING RATEUP.NLM" .IX Header "COMPILING RATEUP.NLM" In addition to the rateup.c and Makefile.Netware supplied with the \s-1MRTG\s0 release, you will also need: .IP "\(bu" 4 Metrowerks CodeWarrior with NetWare Support \s-1OR GCC\s0 Compiler (v3.0.3 or later) with NlmConv Utility .IP "\(bu" 4 Novell LibC \s-1NDK\s0 (February 2004 or later) .IP "\(bu" 4 \&\s-1GD\s0 Graphics Library (v2.0.33 or later) .IP "\(bu" 4 LibPNG Graphics Library (v1.2.8 or later) .IP "\(bu" 4 ZLib Library (v1.2.3 or later) .IP "\(bu" 4 The get_ver.awk script .IP "\(bu" 4 A copy of the \s-1GNU\s0 build tools. (See http://sourceforge.net/projects/gnuwin32/) .PP The auxiliary libraries can be obtained from: .PP \&\s-1GD\s0 Graphics Library. (See http://www.boutell.com/gd/ ) .PP \&\s-1PNG\s0 Graphics Library. (See http://libpng.sourceforge.net/ ) .PP zLib Compression Library. (See http://www.gzip.org/zlib/ ) .PP Edit the Makefile.Netware file as required to match your installation paths; search the file for the key word 'Edit'. .SH "NETWARE SUPPORT" .IX Header "NETWARE SUPPORT" For copies of the \s-1NCF\s0 and get_ver.awk scripts, see Appendix. .PP For NetWare specific issues, submit questions to the Perl forum at news://developer\-forums.novell.com/novell.devsup.perl (Novell Developer Forums). .PP To move the \s-1MRTG\s0 application to a volume other than \s-1SYS:\s0 you will need to edit the \s-1NCF\s0 scripts provided plus the MRTG[.pl] script itself in two places. .SH "NEW RATEUP SWITCH" .IX Header "NEW RATEUP SWITCH" The MRTG[.pl] script, when used on a NetWare platform, uses Rateup[.nlm] with the new commandline switch: .PP .Vb 1 \& RATEUP \-f filename .Ve .PP where the filename parameter can include a leading path element. .PP The file format is exactly the same as that used on the commandline by other operating systems, including the leading path and name of the Rateup \s-1NLM.\s0 .SH "APPENDIX" .IX Header "APPENDIX" The Appendix includes 'copies' of the following files: .IP "\(bu" 4 The \s-1NCF\s0 files used during \s-1MRTG\s0 configuration, .PP To create copies of these files, simply 'cut and paste' into your favourite '\fBtext editor\fR' and save under their respective names. You should remove the leading space from each line. .PP \fIMakeMrtgCfg.NCF\fR .IX Subsection "MakeMrtgCfg.NCF" .PP .Vb 6 \& # MakeMrtgCfg.NCF \& # Purpose : Create the MRTG Configuration File \& # Changed : 5/05/2005 New \& # Located : SYS:MRTG\eBIN \& # Set For : \& # Params : \& \& # Edit this file and: \& \& # Replace ccccc with your device GET SNMP Community Name \- If unsure try \*(Aqpublic\*(Aq. \& # Replace ddddd with your device IP (n.n.n.n) or domain name. \& \& perl \-\-noscreen sys:\emrtg\ebin\ecfgmaker.pl ccccc@ddddd > sys:\emrtg\ebin\eMrtg.cfg \& \& # \& # End of MakeMrtgCfg.NCF .Ve .PP \fIRunMrtg.NCF\fR .IX Subsection "RunMrtg.NCF" .PP .Vb 6 \& # RunMrtg.NCF \& # Purpose : Run the MRTG Application \& # Changed : 5/05/2005 New \& # Located : SYS:MRTG\eBIN \& # Set For : \& # Params : \& \& # The paths are as per the examples recommended in "Getting Started". \& \& perl \-\-noscreen sys:\emrtg\ebin\emrtg.pl sys:\emrtg\ebin\emrtg.cfg \& \& # \& # End of RunMrtg.NCF .Ve .PP \fIMakeMrtgIndex.NCF\fR .IX Subsection "MakeMrtgIndex.NCF" .PP .Vb 6 \& # MakeMrtgIndex.NCF \& # Purpose : Create the HTML Index File for MRTG HTML data pages \& # Changed : 5/05/2005 New \& # Located : SYS:MRTG\eBIN \& # Set For : \& # Params : \& \& # Note: Edit this file and change the redirected output to the location \& # specified for HtmlDir or WorkDir. The sys:\eapache2\ehtdocs\emrtg\eindex.html \& # is based on the examples in "Getting Started". \& \& perl \-\-noscreen sys:\emrtg\ebin\eindexmaker.pl sys:\emrtg\ebin\eMrtg.cfg > sys:\emrtg\ehtml\eindex.html \& \& # \& # End of MakeMrtgIndex.NCF .Ve .SH "LICENSE" .IX Header "LICENSE" \&\s-1GNU\s0 General Public License .SH "CREDITS" .IX Header "CREDITS" The \s-1MRTG\s0 for NetWare exists largely through the efforts of Guenter Knauf and feedback from beta testers. .SH "AUTHOR" .IX Header "AUTHOR" Norm W.. mrtg-2.17.10/doc/mrtg.10000644000175300017510000003004314171763415013457 0ustar oetikeroep.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "MRTG 1" .TH MRTG 1 "2022-01-19" "2.17.10" "mrtg" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" mrtg \- What is MRTG ? .SH "DESCRIPTION" .IX Header "DESCRIPTION" The Multi Router Traffic Grapher (\s-1MRTG\s0) is a tool to monitor the traffic load on network links. \s-1MRTG\s0 generates \s-1HTML\s0 pages containing \s-1PNG\s0 images which provide a \s-1LIVE\s0 visual representation of this traffic. .PP Go to http://oss.oetiker.ch/mrtg for all the details about mrtg. .SH "HIGHLIGHTS" .IX Header "HIGHLIGHTS" .IP "Portable" 4 .IX Item "Portable" \&\s-1MRTG\s0 works on most \s-1UNIX\s0 platforms and Windows \s-1NT.\s0 .IP "Perl" 4 .IX Item "Perl" \&\s-1MRTG\s0 is written in Perl and comes with full source. .IP "Portable \s-1SNMP\s0" 4 .IX Item "Portable SNMP" \&\s-1MRTG\s0 Uses a highly portable \s-1SNMP\s0 implementation written entirely in Perl (thanks to Simon Leinen). There is no need to install any external \s-1SNMP\s0 package. .IP "SNMPv2c support" 4 .IX Item "SNMPv2c support" \&\s-1MRTG\s0 can read the new SNMPv2c 64bit counters. No more counter wrapping. .IP "Reliable Interface Identification" 4 .IX Item "Reliable Interface Identification" Router interfaces can be identified by \s-1IP\s0 address, description and ethernet address in addition to the normal interface number. .IP "Constant size Logfiles" 4 .IX Item "Constant size Logfiles" \&\s-1MRTG\s0's logfiles do \s-1NOT\s0 grow thanks to the use of a unique data consolidation algorithm. .IP "Automatic Configuration" 4 .IX Item "Automatic Configuration" \&\s-1MRTG\s0 comes with a set of configuration tools which make configuration and setup very simple. .IP "Performance" 4 .IX Item "Performance" Time critical routines are written in C (thanks to the initiative of Dave Rand my Co-Author). .IP "\s-1GIF\s0 free Graphics" 4 .IX Item "GIF free Graphics" Graphics are generated directly in \s-1PNG\s0 format using the \&\s-1GD\s0 library by Thomas Boutell. .IP "Customizability" 4 .IX Item "Customizability" The look of the webpages produced by \s-1MRTG\s0 is highly configurable. .IP "RRDtool" 4 .IX Item "RRDtool" \&\s-1MRTG\s0 has built-in hooks for using RRDtool. If you are strapped for performance this may help. .SH "DETAILS" .IX Header "DETAILS" \&\s-1MRTG\s0 consists of a Perl script which uses \s-1SNMP\s0 to read the traffic counters of your routers and a fast C program which logs the traffic data and creates beautiful graphs representing the traffic on the monitored network connection. These graphs are embedded into webpages which can be viewed from any modern Web-browser. .PP In addition to a detailed daily view, \s-1MRTG\s0 also creates visual representations of the traffic seen during the last seven days, the last five weeks and the last twelve months. This is possible because \&\s-1MRTG\s0 keeps a log of all the data it has pulled from the router. This log is automatically consolidated so that it does not grow over time, but still contains all the relevant data for all the traffic seen over the last two years. This is all performed in an efficient manner. Therefore you can monitor 200 or more network links from any halfway decent \s-1UNIX\s0 box. .PP \&\s-1MRTG\s0 is not limited to monitoring traffic, though. It is possible to monitor any \s-1SNMP\s0 variable you choose. You can even use an external program to gather the data which should be monitored via \&\s-1MRTG.\s0 People are using \s-1MRTG,\s0 to monitor things such as System Load, Login Sessions, Modem availability and more. \s-1MRTG\s0 even allows you to accumulate two or more data sources into a single graph. .SH "HISTORY" .IX Header "HISTORY" In 1994 I was working at a site where we had one 64kbit line to the outside world. Obviously, everybody was interested in knowing how the link was performing. So I wrote a quick hack which created a constantly updated graph on the web that showed the traffic load on our Internet link. This eventually evolved into a rather configurable Perl script called \s-1MRTG\-1.0\s0 which I released in spring 1995. After a few updates, I left my job at \s-1DMU\s0 to start work at the Swiss Federal Institute of Technology. Due to lack of time I had to put \s-1MRTG\s0 aside. One day in January of 1996, I received email from Dave Rand asking if I had any ideas why \s-1MRTG\s0 was so slow. Actually, I did. \s-1MRTG\s0's programming was not very efficient and it was written entirely in Perl. After a week or so, Dave wrote back to me and said he had tried what I had suggested for improving \s-1MRTG\s0's speed. Since the changes did not help much, he had decided to rewrite the time-critical sections of \s-1MRTG\s0 in C. The code was attached to his email. His tool increased the speed of \s-1MRTG\s0 by a factor of 40! This got me out of my '\s-1MRTG\s0 ignorance' and I started to spend my spare time developing of \s-1MRTG\-2.\s0 .PP Soon after \s-1MRTG\-2\s0 development had begun I started to give beta copies to interested parties. In return I got many feature patches, a lot of user feedback and bug fixes. The product you are getting now wouldn't be in this state if it hadn't been for the great contributions and support I received from of many people. I would like to take this opportunity to thank them all. (See the files \s-1CHANGES\s0 for a long list of folk people who helped to make \s-1MRTG\s0 what it is today.) .SH "Command-line" .IX Header "Command-line" Mrtg is also the name of the script you have to run to poll data and generate the graphs. Most configuration is set through the configuration file; some command-line options exist all the same. .IP "\fB\-\-user\fR \fIusername\fR and \fB\-\-group\fR \fIgroupname\fR" 4 .IX Item "--user username and --group groupname" Run as the given user and/or group. (Unix Only) .IP "\fB\-\-lock\-file\fR \fIfilename\fR" 4 .IX Item "--lock-file filename" Use an alternate lock-file (the default is to use the configuration-file appended with \f(CW\*(C`_l\*(C'\fR). .IP "\fB\-\-confcache\-file\fR \fIfilename\fR" 4 .IX Item "--confcache-file filename" Use an alternate confcache-file (the default is to use the configuration-file appended with \f(CW\*(C`.ok\*(C'\fR) .IP "\fB\-\-logging\fR \fIfilename\fR|\fBeventlog\fR" 4 .IX Item "--logging filename|eventlog" If this is set to writable filename, all output from mrtg (warnings, debug messages, errors) will go to \fIfilename\fR. If you are running on Win32 you can specify \fBeventlog\fR instead of a filename which will send all error to the windows event log. .Sp \&\fB\s-1NOTE:\s0\fRNote, there is no Message \s-1DLL\s0 for mrtg. This has the side effect that the windows event logger will display a nice message with every entry in the event log, complaining about the fact that mrtg has no message dll. If any of the Windows folks want to contribute one, they are welcome. .IP "\fB\-\-daemon\fR" 4 .IX Item "--daemon" Put \s-1MRTG\s0 into the background, running as a daemon. This works the same way as the config file option, but the switch is required for proper \s-1FHS\s0 operation (because /var/run is writable only by root) .IP "\fB\-\-fhs\fR" 4 .IX Item "--fhs" Configure all mrtg paths to conform to the \s-1FHS\s0 specification . The following default values are assumed: .Sp .Vb 4 \& confcachefile \- /var/lib/mrtg/mrtg.ok \& pid\-file \- /run/mrtg/mrtg.pid \& lock\-file \- /var/lock/mrtg/mrtg.lck \& log\-file \- /var/log/mrtg/mrtg.log .Ve .IP "\fB\-\-check\fR" 4 .IX Item "--check" Only check the cfg file for errors. Do not do anything. .IP "\fB\-\-pid\-file=s\fR" 4 .IX Item "--pid-file=s" Define the name and path of the pid file for mrtg running as a daemon .IP "\fB\-\-log\-only\fR" 4 .IX Item "--log-only" Only update the logfile, do not produce graphics or html pages .IP "\fB\-\-debug=s\fR" 4 .IX Item "--debug=s" Enable debug options. The argument of the debug option is a comma separated list of debug values: .Sp .Vb 8 \& cfg \- watch the config file reading \& dir \- directory mangeling \& base \- basic program flow \& tarp \- target parser \& snpo \- snmp polling \& fork \- forking view \& time \- some timing info \& log \- logging of data via rateup or rrdtool .Ve .Sp Example: .Sp .Vb 1 \& \-\-debug="cfg,snpo" .Ve .SH "READ ON" .IX Header "READ ON" Learn more about \s-1MRTG\s0 by going to the mrtg home page on: http://oss.oetiker.ch/mrtg .SH "AUTHOR" .IX Header "AUTHOR" Tobias Oetiker and many contributors mrtg-2.17.10/doc/mrtg-reference.10000644000175300017510000024454114171763415015425 0ustar oetikeroep.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "MRTG-REFERENCE 1" .TH MRTG-REFERENCE 1 "2022-01-19" "2.17.10" "mrtg" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" mrtg\-reference \- MRTG 2.17.10 configuration reference .SH "OVERVIEW" .IX Header "OVERVIEW" The runtime behaviour of \s-1MRTG\s0 is governed by a configuration file. Run-of-the-mill configuration files can be generated with \fBcfgmaker\fR. (Check cfgmaker). But for more elaborate configurations some hand-tuning is required. .PP This document describes all the configuration options understood by the mrtg software. .SH "SYNTAX" .IX Header "SYNTAX" \&\s-1MRTG\s0 configuration file syntax follows some simple rules: .IP "\(bu" 4 Keywords must start at the beginning of a line. .IP "\(bu" 4 Lines which follow a keyword line which start with a blank are appended to the keyword line .IP "\(bu" 4 Empty Lines are ignored .IP "\(bu" 4 Lines starting with a # sign are comments. .IP "\(bu" 4 You can add other files into the configuration file using .Sp \&\fBInclude:\fR \fIfile\fR .Sp Example: .Sp .Vb 1 \& Include: base\-options.inc .Ve .Sp If included files are specified with relative paths, both the current working directory and the directory containing the main config file will be searched for the files. The current working directory will be searched first. .Sp If the included filename contains an asterisk, then this is taken as a wildcard for zero or more characters, and all matching files are included. Thus, you can use this statement to include all files in a specified subdirectory. .Sp Example: .Sp .Vb 1 \& Include: servers/*.cfg .Ve .Sp In this case, you should be very careful that your wildcard pattern does not find a match relative to the current working directory if you mean it to be relative to the main config file directory, since the working directory is checked for a match first (as with a normal Include directive). Therefore, use of something like '*/*' is discouraged. .SH "GLOBAL KEYWORDS" .IX Header "GLOBAL KEYWORDS" .SS "WorkDir" .IX Subsection "WorkDir" WorkDir specifies where the logfiles and the webpages should be created. .PP Example: .PP .Vb 1 \& WorkDir: /usr/tardis/pub/www/stats/mrtg .Ve .SH "OPTIONAL GLOBAL KEYWORDS" .IX Header "OPTIONAL GLOBAL KEYWORDS" .SS "HtmlDir" .IX Subsection "HtmlDir" HtmlDir specifies the directory where the html (or shtml, but we'll get on to those later) lives. .PP \&\s-1NOTE:\s0 Workdir overrides the settings for htmldir, imagedir and logdir. .PP Example: .PP .Vb 1 \& Htmldir: /www/mrtg/ .Ve .SS "ImageDir" .IX Subsection "ImageDir" ImageDir specifies the directory where the images live. They should be under the html directory. .PP Example: .PP .Vb 1 \& Imagedir: /www/mrtg/images .Ve .SS "LogDir" .IX Subsection "LogDir" LogDir specifies the directory where the logs are stored. This need not be under htmldir directive. .PP Example: .PP .Vb 1 \& Logdir: /www/mrtg/logs .Ve .SS "Forks (\s-1UNIX\s0 only)" .IX Subsection "Forks (UNIX only)" With system that supports fork (\s-1UNIX\s0 for example), mrtg can fork itself into multiple instances while it is acquiring data via snmp. .PP For situations with high latency or a great number of devices this will speed things up considerably. It will not make things faster, though, if you query a single switch sitting next door. .PP As far as I know \s-1NT\s0 can not fork so this option is not available on \s-1NT.\s0 .PP Example: .PP .Vb 1 \& Forks: 4 .Ve .SS "EnableIPv6" .IX Subsection "EnableIPv6" When set to yes, IPv6 support is enabled if the required libraries are present (see the mrtg\-ipv6 manpage). When IPv6 is enabled, mrtg can talk to routers using \s-1SNMP\s0 over IPv6 and targets may be specified by their numeric IPv6 addresses as well as by hostname or IPv4 address. .PP If IPv6 is enabled and the target is a hostname, mrtg will try to resolve the hostname to an IPv6 address and, if this fails, to an IPv4 address. Note that mrtg will only use IPv4 if you specify an IPv4 address or a hostname with no corresponding IPv6 address; it will not fall back to IPv4 if it simply fails to communicate with the target using IPv6. This is by design. .PP Note that many routers do not currently support \s-1SNMP\s0 over IPv6. Use the \&\fIIPv4Only\fR per target option for these routers. .PP IPv6 is disabled by default. .PP Example: .PP .Vb 1 \& EnableIPv6: Yes .Ve .SS "EnableSnmpV3" .IX Subsection "EnableSnmpV3" When set to yes, uses the Net::SNMP module instead of the \s-1SNMP_SESSION\s0 module for generating snmp queries. This allows the use of SNMPv3 if other snmpv3 parameters are set. .PP SNMPv3 is disabled by default. .PP Example: .PP .Vb 1 \& EnableSnmpV3: yes .Ve .SS "Refresh" .IX Subsection "Refresh" How many seconds apart should the browser (Netscape) be instructed to reload the page? If this is not defined, the default is 300 seconds (5 minutes). .PP Example: .PP .Vb 1 \& Refresh: 600 .Ve .SS "Interval" .IX Subsection "Interval" How often do you call mrtg? The default is 5 minutes. If you call it less often, you should specify it here. This does two things: .IP "\(bu" 4 The generated \s-1HTML\s0 page contains the right information about the calling interval ... .IP "\(bu" 4 A \s-1META\s0 header in the generated \s-1HTML\s0 page will instruct caches about the time-to-live of this page ..... .PP In this example, we tell mrtg that we will be calling it every 10 minutes. If you are calling mrtg every 5 minutes, you can leave this line commented out. .PP Example: .PP .Vb 1 \& Interval: 10 .Ve .PP Note that unless you are using rrdtool you can not set Interval to less than 5 minutes. If you are using rrdtool you can set interval in the format .PP .Vb 1 \& Interval: MM[:SS] .Ve .PP Down to 1 second. Note though, setting the Interval for an rrdtool/mrtg setup will influence the initial creation of the database. If you change the interval later, all existing databases will remain at the resolution they were initially created with. Also note that you must make sure that your mrtg-rrd Web-frontend can deal with this kind of Interval setting. .SS "MaxAge" .IX Subsection "MaxAge" \&\s-1MRTG\s0 relies heavily on the real time clock of your computer. If the time is set to a wrong value, especially if it is advanced far into the future, this will cause mrtg to expire lots of supposedly old data from the log files. .PP To prevent this, you can add a 'reasonability' check by specifying a maximum age for log files. If a file seems to be older, mrtg will not touch it but complain instead, giving you a chance to investigate the cause. .PP Example: .PP .Vb 1 \& MaxAge: 7200 .Ve .PP The example above will make mrtg refuse to update log files older than 2 hours (7200 seconds). .SS "WriteExpires" .IX Subsection "WriteExpires" With this switch mrtg will generate .meta files for \s-1CERN\s0 and Apache servers which contain Expiration tags for the html and gif files. The *.meta files will be created in the same directory as the other files, so you will have to set \*(L"MetaDir .\*(R" and \*(L"MetaFiles on\*(R" in your apache.conf or .htaccess file for this to work .PP \&\s-1NOTE:\s0 If you are running Apache\-1.2 or later, you can use the mod_expire to achieve the same effect ... see the file htaccess.txt .PP Example: .PP .Vb 1 \& WriteExpires: Yes .Ve .SS "NoMib2" .IX Subsection "NoMib2" Normally we ask the \s-1SNMP\s0 device for 'sysUptime' and 'sysName' properties. Some do not have these. If you want to avoid getting complaints from mrtg about these missing properties, specify the nomib2 option. .PP An example of agents which do not implement base mib2 attributes are Computer Associates \- Unicenter \s-1TNG\s0 Agents. \s-1CA\s0 relies on using the base \&\s-1OS SNMP\s0 agent in addition to its own agents to supplement the management of a system. .PP Example: .PP .Vb 1 \& NoMib2: Yes .Ve .SS "SingleRequest" .IX Subsection "SingleRequest" Some \s-1SNMP\s0 implementations can not deal with requests asking for multiple snmp variables in one go. Set this in your cfg file to force mrtg to only ask for one variable per request. .PP Examples .PP .Vb 1 \& SingleRequest: Yes .Ve .SS "SnmpOptions" .IX Subsection "SnmpOptions" Apart from the per target timeout options, you can also configure the behaviour of the snmpget process on a more profound level. SnmpOptions accepts a hash of options. The following options are currently supported: .PP .Vb 7 \& timeout => $default_timeout, \& retries => $default_retries, \& backoff => $default_backoff, \& default_max_repetitions => $max_repetitions, \& use_16bit_request_ids => 1, \& lenient_source_port_matching => 0, \& lenient_source_address_matching => 1 .Ve .PP The values behind the options indicate the current default value. Note that these settings \s-1OVERRIDE\s0 the per target timeout settings. .PP A per-target SnmpOptions[] keyword will override the global settings. That keyword is primarily for SNMPv3. .PP The 16bit request ids are the only way to query the broken \s-1SNMP\s0 implementation of \s-1SMC\s0 Barricade routers. .PP Example: .PP .Vb 1 \& SnmpOptions: retries => 2, only_ip_address_matching => 0 .Ve .PP Note that \s-1AS/400\s0 snmp seems to be broken in a way which prevents mrtg from working with it unless .PP .Vb 1 \& SnmpOptions: lenient_source_port_matching => 1 .Ve .PP is set. .SS "IconDir" .IX Subsection "IconDir" If you want to keep the mrtg icons in someplace other than the working (or imagedir) directory, use the \fIIconDir\fR variable for defining the url of the icons directory. .PP Example: .PP .Vb 1 \& IconDir: /mrtgicons/ .Ve .SS "LoadMIBs" .IX Subsection "LoadMIBs" Load the \s-1MIB\s0 file(s) specified and make its OIDs available as symbolic names. For better efficiency, a cache of MIBs is maintained in the WorkDir. .PP Example: .PP .Vb 1 \& LoadMIBs: /dept/net/mibs/netapp.mib,/usr/local/lib/ft100m.mib .Ve .SS "Language" .IX Subsection "Language" Switch output format to the selected Language (Check the \fItranslate\fR directory to see which languages are supported at the moment. In this directory you can also find instructions on how to create new translations). .PP Currently the following languages are supported: .PP big5 brazilian bulgarian catalan chinese croatian czech danish dutch eucjp french galician gb gb2312 german greek hungarian icelandic indonesia iso2022jp italian korean lithuanian malay norwegian polish portuguese romanian russian russian1251 serbian slovak slovenian spanish swedish turkish ukrainian .PP Example: .PP .Vb 1 \& Language: danish .Ve .SS "LogFormat" .IX Subsection "LogFormat" Setting LogFormat to 'rrdtool' in your mrtg.cfg file enables rrdtool mode. In rrdtool mode, mrtg relies on \fBrrdtool\fR to do its logging. See mrtg-rrd. .PP Example: .PP .Vb 1 \& LogFormat: rrdtool .Ve .SS "LibAdd" .IX Subsection "LibAdd" If you are using rrdtool mode and your \fBrrdtool\fR Perl module (RRDs.pm) is not installed in a location where perl can find it on its own, you can use LibAdd to supply an appropriate path. .PP Example: .PP .Vb 1 \& LibAdd: /usr/local/rrdtool/lib/perl/ .Ve .SS "PathAdd" .IX Subsection "PathAdd" If the \fBrrdtool\fR executable can not be found in the normal \f(CW\*(C`PATH\*(C'\fR, you can use this keyword to add a suitable directory to your path. .PP Example: .PP .Vb 1 \& PathAdd: /usr/local/rrdtool/bin/ .Ve .SS "RRDCached" .IX Subsection "RRDCached" If you are running RRDTool 1.4 or later with \fBrrdcached\fR, then you can configure \s-1MRTG\s0 to take advantage of this for updates, either by using the \&\s-1RRDCACHED_ADDRESS\s0 environment variable, or by setting the RRDCached keyword in the configuration file. Note that, if both are set, the configuration file keyword will take precedence. .PP Only \s-1UNIX\s0 domain sockets are fully supported prior to RRDTool v1.5, and you should note that using RRDCached mode will disable all Threshold checking normally done by \s-1MRTG.\s0 Appropriate warning messages will be printed if necessary. .PP Examples: .PP .Vb 1 \& RRDCached: unix:/var/tmp/rrdcached.sock \& \& RRDCached: localhost:42217 .Ve .SS "RunAsDaemon" .IX Subsection "RunAsDaemon" The RunAsDaemon keyword enables daemon mode operation. The purpose of daemon mode is that \s-1MRTG\s0 is launched once and not repeatedly (as it is with cron). This behavior saves computing resources as loading and parsing of configuration files happens only once on startup, and if the configuration file is modified. .PP Using daemon mode \s-1MRTG\s0 itself is responsible for timing the measurement intervals. Therefore its important to set the Interval keyword to an appropriate value. .PP Note that when using daemon mode \s-1MRTG\s0 should no longer be started from cron as each new process runs forever. Instead \s-1MRTG\s0 should be started from the command prompt or by a system startup script. .PP If you want mrtg to run under a particular user and group (it is not recommended to run \s-1MRTG\s0 as root) then you can use the \fB\-\-user=\fR\fIuser_name\fR and \fB\-\-group=\fR\fIgroup_name\fR options on the mrtg commandline. .PP .Vb 1 \& mrtg \-\-user=mrtg_user \-\-group=mrtg_group mrtg.cfg .Ve .PP Also note that in daemon mode restarting the process is required in order to activate changes in the config file. .PP Under \s-1UNIX,\s0 the Daemon switch causes mrtg to fork into background after checking its config file. On Windows \s-1NT\s0 the \s-1MRTG\s0 process will detach from the console, but because the \s-1NT/2000\s0 shell waits for its children you have to use this special start sequence when you launch the program: .PP .Vb 1 \& start /b perl mrtg mrtg.cfg .Ve .PP You may have to add path information equal to what you add when you run mrtg from the commandline. .PP Example .PP .Vb 2 \& RunAsDaemon: Yes \& Interval: 5 .Ve .PP This makes \s-1MRTG\s0 run as a daemon beginning data collection every 5 minutes .PP If you are daemontools and still want to run mrtg as a daemon you can additionally specify .PP .Vb 1 \& NoDetach: Yes .Ve .PP this will make mrtg run but without detaching it from the terminal. .PP If the modification date on the configuration file changes during operation, then \s-1MRTG\s0 will re-read the configuration on the next polling cycle. Note that sub-files which are included from the main configuration do not have their modification times monitored, only the top-level file is so checked. .SS "ConversionCode" .IX Subsection "ConversionCode" Some devices may produce non-numeric values that would nevertheless be useful to graph with \s-1MRTG\s0 if those values could be converted to numbers. The ConversionCode keyword specifies the path to a file containing Perl code to perform such conversions. The code in this file must consist of one or more Perl subroutines. Each subroutine must accept a single string argument and return a single numeric value. When RRDtool is in use, a decimal value may be returned. When the name of one of these subroutines is specified in a target definition (see below), \s-1MRTG\s0 calls it twice for that target, once to convert the the input value being monitored and a second time to convert the output value. The subroutine must return an undefined value if the conversion fails. In case of failure, a warning may be posted to the \s-1MRTG\s0 log file using Perl's warn function. \s-1MRTG\s0 imports the subroutines into a separate name space (package MRTGConversion), so the user need not worry about pollution of \s-1MRTG\s0's global name space. \s-1MRTG\s0 automatically prepends this package declaration to the user-supplied code. .PP Example: Suppose a particular \s-1OID\s0 returns a character string whose length is proportional to the value to be monitored. To convert this string to a number that can be graphed by \s-1MRTG,\s0 create a file arbitrarily named \&\*(L"MyConversions.pl\*(R" containing the following code: .PP .Vb 5 \& # Return the length of the string argument \& sub Length2Int { \& my $value = shift; \& return length( $value ); \& } .Ve .PP Then include the following global keyword in the \s-1MRTG\s0 configuration file (assuming that the conversion code file is saved in the mrtg/bin directory along with mrtg itself): .PP .Vb 1 \& ConversionCode: MyConversions.pl .Ve .PP This will cause \s-1MRTG\s0 to include the definition of the subroutine Length2Int in its execution environment. Length2Int can then be invoked on any target by appending \*(L"|Length2Int\*(R" to the target definition as follows: .PP .Vb 1 \& Target[myrouter]: 1.3.6.1.4.1.999.1&1.3.6.1.4.1.999.1:public@mydevice|Length2Int .Ve .PP See \*(L"Extended Host Name Syntax\*(R" below for complete target definition syntax information. .SS "SendToGraphite" .IX Subsection "SendToGraphite" If you want to send a copy of the collected data into a Graphite database in addition to storing it in the RRDfile, you can provide your Graphite database name/ip and port number here. .PP This requires the Net::Graphite perl module which is available from \s-1CPAN.\s0 .PP Examples: .PP .Vb 2 \& # If your Graphite receiver is running on the same host as the MRTG daemon and using the default port \& SendToGraphite: 127.0.0.1,2003 \& \& # If your Graphite receiver is running on 192.168.100.50 port 5000 \& SendToGraphite: 192.168.100.50,5000 \& \& # If your Graphite receiver is running on graphite.mydomain.com port 2003 \& SendToGraphite: graphite.mydomain.com,2003 .Ve .PP Graphite's namespace has a number of restrictions on what characters are allowed. The SendToGraphite functionality makes an attempt to convert the \s-1MRTG\s0 target name and, if specified, the Legendi and Legendo values to Graphite namespace friendly values. Specifically, the following conversion rules apply: .IP "\(bu" 4 Underscores in the target_name are converted to periods which are Graphite namespace delimiters. .IP "\(bu" 4 Comma characters are not allowed so they are removed. .IP "\(bu" 4 The string \*(L"m2g\*(R" for \s-1MRTG\s0 to Graphite is prepended onto the Graphite namespace variable. .PP Example \s-1MRTG\s0 target to Graphite namespace conversion: .PP .Vb 2 \& # Our MRTG target name from mrtg.cfg is as follows \& Target[switch_GigabitEthernet0_5]: \eGigabitEthernet0/5:public1@switch:::::2 .Ve .PP After the conversion you will end up with these Graphite namespace values .PP .Vb 2 \& m2g.switch.gigabitethernet0.5.in \& m2g.switch.gigabitethernet0.5.out .Ve .PP Next is a more complicated example because Legendi and Legendo are in use to denote min and max voltage values that pertain to some \s-1APC UPS SNMP\s0 OIDs .PP .Vb 4 \& # Target, Legendi, and Legendo are specified in mrtg.cfg as follows \& Target[apc_minmaxline]: 1.3.6.1.4.1.318.1.1.1.3.2.3.0&1.3.6.1.4.1.318.1.1.1.3.2.2.0:public@apc: \& LegendI[apc_minmaxline]: upsAdvInputMinLineVoltage \& LegendO[apc_minmaxline]: upsAdvInputMaxLineVoltage .Ve .PP After the conversion you will end up with these Graphite namespace values .PP .Vb 2 \& m2g.apc.minmaxline.upsAdvInputMinLineVoltage \& m2g.apc.minmaxline.upsAdvInputMaxLineVoltage .Ve .PP If you don't see the data showing up in Graphite, chances are there are invalid characters in the namespace. To debug this, use the DEBUG=qw(log) directive at the top of the \s-1MRTG\s0 script to find out what is happening with the \s-1MRTG\s0 to Graphite namespace conversion. .PP DEBUG=qw(log) will generate some output similar to what appears below .PP .Vb 2 \& 2016\-10\-13 06:08:39 \-\- \-\-log: RRDs::update(/var/www/mrtg/switch/switch_gigabitethernet0_5.rrd, \*(Aq1476356919:2738746035:2927936327\*(Aq) \& 2016\-10\-13 06:08:39 \-\- \-\-log: graphite\->send(m2g.switch.gigabitethernet0.5.in,2738746035,1476356919) \& \& 2016\-10\-13 06:08:39 \-\- \-\-log: graphite\->send(m2g.switch.gigabitethernet0.5.out,2927936327,1476356919) \& \& 2016\-10\-13 06:09:25 \-\- \-\-log: RRDs::update(/var/www/mrtg/apc/apc_minmaxline.rrd, \*(Aq1476356965:122:123\*(Aq) \& 2016\-10\-13 06:09:25 \-\- \-\-log: graphite\->send(m2g.apc.minmaxline.upsAdvInputMinLineVoltage,122,1476356965) \& \& 2016\-10\-13 06:09:25 \-\- \-\-log: graphite\->send(m2g.apc.minmaxline.upsAdvInputMaxLineVoltage,123,1476356965) .Ve .PP If the \s-1MRTG\s0 log output looks reasonable, then take a look at Graphite's carbon-cache logs. .SH "PER TARGET CONFIGURATION" .IX Header "PER TARGET CONFIGURATION" Each monitoring target must be identified by a unique name. This name must be appended to each parameter belonging to the same target. The name will also be used for naming the generated webpages, logfiles and images for this target. .SS "Target" .IX Subsection "Target" With the \fITarget\fR keyword you tell mrtg what it should monitor. The \fITarget\fR keyword takes arguments in a wide range of formats: .IP "Basic" 4 .IX Item "Basic" The most basic format is \*(L"port:community@router\*(R" This will generate a traffic graph for the interface 'port' of the host 'router' (dns name or \s-1IP\s0 address) and it will use the community 'community' (snmp password) for the snmp query. .Sp Example: .Sp .Vb 1 \& Target[myrouter]: 2:public@wellfleet\-fddi.domain .Ve .Sp If your community contains a \*(L"@\*(R" or a \*(L" \*(R" these characters must be escaped with a \*(L"\e\*(R". .Sp .Vb 1 \& Target[bla]: 2:stu\e pi\e@d@router .Ve .IP "SNMPv2c" 4 .IX Item "SNMPv2c" If you have a fast router you might want to try to poll the ifHC* counters. This feature gets activated by switching to SNMPv2c. Unfortunately not all devices support SNMPv2c yet. If it works, this will prevent your counters from wrapping within the 5 minute polling interval, since we now use 64 bit instead of the normal 32 bit. .Sp Example: .Sp .Vb 1 \& Target[myrouter]: 2:public@router1:::::2 .Ve .IP "SNMPv3" 4 .IX Item "SNMPv3" As an alternative to SNMPv2c, SNMPv3 provides access to the ifHC* counters, along with encryption. Not all devices support SNMPv3, and you will also need the perl Net::SNMP library in order to use it. It is recommended that cfgmaker be used to generate configurations involving SNMPv3, as it will check if the Net::SNMP library is loadable, and will switch to SNMPv2c if v3 is unavailable. .Sp \&\s-1SNMP\s0 v3 requires additional authentication parameters, passed using the SnmpOptions[] per-target keyword. .Sp Example: Target[myrouter]: 2:router1:::::3 SnmpOptions[myrouter]: username=>'user1' .IP "noHC" 4 .IX Item "noHC" Not all routers that support SNMPv2 or SNMPv3 provide the ifHC* counters on every interface. The noHC[] per-target keyword signals that the low-speed counters ifInOctets and ifOutOctets should be queried instead. cfgmaker will automatically insert this tag if SNMPv2 or SNMPv3 is specified but the ifHC* counters are unavailable. .Sp Example: Target[myrouter]: #Bri0:router1:::::3 SnmpOptions[myrouter]: username=>'user1' noHC[myrouter]: yes .IP "Reversing" 4 .IX Item "Reversing" Sometimes you are sitting on the wrong side of the link, and you would like to have mrtg report Incoming traffic as Outgoing and vice versa. This can be achieved by adding the '\-' sign in front of the \*(L"Target\*(R" description. It flips the incoming and outgoing traffic rates. .Sp Example: .Sp .Vb 1 \& Target[ezci]: \-1:public@ezci\-ether.domain .Ve .IP "Explicit OIDs" 4 .IX Item "Explicit OIDs" You can also explicitly define which \s-1OID\s0 to query by using the following syntax 'OID_1&OID_2:community@router' The following example will retrieve error counts for input and output on interface 1. \s-1MRTG\s0 needs to graph two variables, so you need to specify two \s-1OID\s0's such as temperature and humidity or error input and error output. .Sp Example: .Sp .Vb 1 \& Target[myrouter]: 1.3.6.1.2.1.2.2.1.14.1&1.3.6.1.2.1.2.2.1.20.1:public@myrouter .Ve .IP "\s-1MIB\s0 Variables" 4 .IX Item "MIB Variables" \&\s-1MRTG\s0 knows a number of symbolic \s-1SNMP\s0 variable names. See the file mibhelp.txt for a list of known names. One example are the ifInErrors and ifOutErrors. This means you can specify the above as: .Sp Example: .Sp .Vb 1 \& Target[myrouter]: ifInErrors.1&ifOutErrors.1:public@myrouter .Ve .IP "SnmpWalk" 4 .IX Item "SnmpWalk" It may be that you want to monitor an snmp object that is only reachable by \&'walking'. You can get mrtg to walk by prepending the \s-1OID\s0 with the string \&\fBWaLK\fR or if you want a particular entry from the table returned by the walk you can use \fBWaLK\fR\fIx\fR where \fIx\fR is a number starting from 0 (!). .Sp Example: .Sp .Vb 1 \& Target[myrouter]: WaLKstrangeOid.1&WaLKstrangeOid.2:public@myrouter \& \& Target[myrouter]: WaLK3strangeOid.1&WaLK4strangeOid.2:public@myrouter .Ve .IP "SnmpGetNext" 4 .IX Item "SnmpGetNext" A special case of an snmp object that is only reachable by 'walking' occurs when a single snmpgetnext will return the correct value, but snmpwalk fails. This may occur with snmp V2 or V3, as the snmpgetbulk method is used in these versions. You can get mrtg to use getnext instead of getbulk by prepending the \&\s-1OID\s0 with the string \fBGeTNEXT\fR. .Sp Example: .Sp .Vb 1 \& Target[myrouter]: GeTNEXTstrangeOid&GeTNEXTstrangeOid:public@myrouter .Ve .IP "Counted \s-1SNMP\s0 Walk" 4 .IX Item "Counted SNMP Walk" In other situations, an snmpwalk is needed to count rows, but the actual data is uninteresting. For example, counting the number of mac-addresses in a \s-1CAM\s0 table, or the number of simultaneous dialup sessions. You can get \s-1MRTG\s0 to count the number of instances by prepending the \s-1OID\s0 with the string \fBCnTWaLK\fR. The following will retrieve the number of simultaneous \s-1VOIP\s0 calls on some routers: .Sp Example: .Sp .Vb 1 \& Target[myrouter]: CnTWaLK1.3.6.1.4.1.9.10.55.1.1.1.1.3&CnTWaLK1.3.6.1.4.1.9.10.55.1.1.1.1.3:public@myrouter .Ve .IP "Interface by \s-1IP\s0" 4 .IX Item "Interface by IP" Sometimes \s-1SNMP\s0 interface index can change, like when new interfaces are added or removed. This can cause all Target entries in your config file to become offset, causing \s-1MRTG\s0 to graphs wrong instances etc. \&\s-1MRTG\s0 supports \s-1IP\s0 address instead of ifindex in target definition. Then \&\s-1MRTG\s0 will query snmp device and try to map \s-1IP\s0 address to the current ifindex. You can use \s-1IP\s0 addresses in every type of target definition by adding \&\s-1IP\s0 address of the numbered interface after \s-1OID\s0 and separation char '/'. .Sp Make sure that the given \s-1IP\s0 address is used on your same target router, especially when graphing two different OIDs and/or interface split by '&' delimiter. .Sp You can tell cfgmaker to generate such references with the option \&\fB\-\-ifref=ip\fR. .Sp Example: .Sp .Vb 3 \& Target[myrouter]: /1.2.3.4:public@wellfleet\-fddi.domain \& Target[ezci]: \-/1.2.3.4:public@ezci\-ether.domain \& Target[myrouter]: ifInErrors/1.2.3.4&ifOutErrors/1.2.3.4:public@myrouter .Ve .IP "Interface by Description" 4 .IX Item "Interface by Description" If you can not use \s-1IP\s0 addresses you might want to use the interface names. This works similar to the \s-1IP\s0 address approach except that the prefix to use is a \e instead of a / .Sp You can tell cfgmaker to generate such references with the option \&\fB\-\-ifref=descr\fR. .Sp Example: .Sp .Vb 3 \& Target[myrouter]: \eMy\-Interface2:public@wellfleet\-fddi.domain \& Target[ezci]: \-\eMy\-Interface2:public@ezci\-ether.domain \& Target[myrouter]: ifInErrors\eMy\-If2&ifOutErrors\eMy\-If3:public@myrouter .Ve .Sp If your description contains a \*(L"&\*(R", a \*(L":\*(R", a \*(L"@\*(R" or a \*(L" \*(R" you can include them but you must escape with a backlash: .Sp .Vb 1 \& Target[myrouter]: \efun\e:\e ney\e&ddd:public@hello.router .Ve .IP "Interface by Name" 4 .IX Item "Interface by Name" This is the only sensible way to reference the interfaces of your switches. .Sp You can tell cfgmaker to generate such references with the option \&\fB\-\-ifref=name\fR. .Sp Example: .Sp .Vb 3 \& Target[myrouter]: #2/11:public@wellfleet\-fddi.domain \& Target[ezci]: \-#2/11:public@ezci\-ether.domain \& Target[myrouter]: ifInErrors#3/7&ifOutErrors#3/7:public@myrouter .Ve .Sp If your description contains a \*(L"&\*(R", a \*(L":\*(R", a \*(L"@\*(R" or a \*(L" \*(R" you can include them but you must escape with a backlash: .Sp .Vb 1 \& Target[myrouter]: #\e:\e fun:public@hello.router .Ve .Sp Note that the # sign will be interpreted as a comment character if it is the first non white-space character on the line. .IP "Interface by Ethernet Address" 4 .IX Item "Interface by Ethernet Address" When the \s-1SNMP\s0 interface index changes, you can key that interface by its \&'Physical Address', sometimes called a 'hard address', which is the \s-1SNMP\s0 variable 'ifPhysAddress'. Internally, \s-1MRTG\s0 matches the Physical Address from the *.cfg file to its current index, and then uses that index for the rest of the session. .Sp You can use the Physical Address in every type of target definition by adding the Physical Address after the \s-1OID\s0 and the separation char '!' (analogous to the \s-1IP\s0 address option). The Physical address is specified as '\-' delimited octets, such as \*(L"0a\-0\-f1\-5\-23\-18\*(R" (omit the double quotes). Note that some routers use the same Hardware Ethernet Address for all of their Interfaces which prevents unique interface identification. Mrtg will notice such problems and alert you. .Sp You can tell cfgmaker to generate configuration files with hardware ethernet address references by using the option \fB\-\-ifref=eth\fR. .Sp Example: .Sp .Vb 6 \& Target[myrouter]: !0a\-0b\-0c\-0d:public@wellfleet\-fddi.domain \& Target[ezci]: \-!0\-f\-bb\-05\-71\-22:public@ezci\-ether.domain \& Target[myrouter]: 1.3.6.1.2.1.2.2.1.14!0a\-00\-10\-23\-44\-51& *BREAK* \& 1.3.6.1.2.1.2.2.1.14!0a\-00\-10\-23\-44\-51:public@myrouter \& Target[myrouter]: ifInErrors!0a\-00\-10\-23\-44\-51& *BREAK* \& ifOutErrors!0a\-00\-10\-23\-44\-51:public@myrouter .Ve .Sp Join the lines at *BREAK* ... .IP "Interface by Type" 4 .IX Item "Interface by Type" It seems that there are devices that try to defy all monitoring efforts: the interesting interfaces have neither ifName nor a constant ifDescr not to mention a persistent ifIndex. The only way to get a constant mapping is by looking at the interface type, because the interface you are interested in is unique in the device you are looking at ... .Sp You can tell cfgmaker to generate such references with the option \&\fB\-\-ifref=type\fR. .Sp Example: .Sp .Vb 3 \& Target[myrouter]: %13:public@wellfleet\-fddi.domain \& Target[ezci]: \-%13:public@ezci\-ether.domain \& Target[myrouter]: ifInErrors%13&ifOutErrors%14:public@myrouter .Ve .IP "Extended positioning of ifIndex" 4 .IX Item "Extended positioning of ifIndex" There are OIDs that contain the interface index at some inner position within the \s-1OID.\s0 To use the above mentioned Interface by IP/Description/Name/Type methods in the target definition the keyword 'IndexPOS' can be used to indicate the position of ifIndex. If 'IndexPOS' is not used the ifIndex will be appended at the end of the \s-1OID.\s0 .Sp Example: .Sp .Vb 1 \& Target[myrouter]: OID.IndexPOS.1/1.2.3.4&OID.IndexPOS.1/1.2.3.4:public@myrouter .Ve .Sp Replace \s-1OID\s0 by your numeric \s-1OID.\s0 .IP "Extended Host Name Syntax" 4 .IX Item "Extended Host Name Syntax" In all places where ``community@router'' is accepted, you can add additional parameters for the \s-1SNMP\s0 communication using colon-separated suffixes. You can also append a pipe symbol ( | ) and the name of a numeric conversion subroutine as described under the global keyword \*(L"ConversionCode\*(R" above. The full syntax is as follows: .Sp .Vb 1 \& community@router[:[port][:[timeout][:[retries][:[backoff][:[version]]]]][|name] .Ve .Sp where the meaning of each parameter is as follows: .RS 4 .IP "port" 4 .IX Item "port" the \s-1UDP\s0 port under which to contact the \s-1SNMP\s0 agent (default: 161) .Sp The complete syntax of the port parameter is .Sp .Vb 1 \& remote_port[!local_address[!local_port]] .Ve .Sp Some machines have additional security features that only allow \s-1SNMP\s0 queries to come from certain \s-1IP\s0 addresses. If the host doing the query has multiple interface, it may be necessary to specify the interface the query should come from. .Sp The port parameter allows the specification of the port of the machine being queried. In addition, the \s-1IP\s0 address (or hostname) and port of the machine doing the query may be specified. .Sp Examples: .Sp .Vb 5 \& somehost \& somehost:161 \& somehost:161!192.168.2.4!4000 use 192.168.2.4 and port 4000 as source \& somehost:!192.168.2.4 use 192.168.2.4 as source \& somehost:!!4000 use port 4000 as source .Ve .IP "timeout" 4 .IX Item "timeout" initial timeout for \s-1SNMP\s0 queries, in seconds (default: 2.0) .IP "retries" 4 .IX Item "retries" number of times a timed-out request will be retried (default: 5) .IP "backoff" 4 .IX Item "backoff" factor by which the timeout is multiplied on every retry (default: 1.0). .IP "version" 4 .IX Item "version" for \s-1SNMP\s0 version. If you have a fast router you might want to put a '2' here. For authenticated or encrypted \s-1SNMP,\s0 you can try to put a \&'3' here. This will make mrtg try to poll the 64 bit counters and thus prevent excessive counter wrapping. Not all routers support this though. \&\s-1SNMP\s0 v3 requires additional setup, see SnmpOptions[] for full details. .Sp Example: .Sp .Vb 1 \& 3:public@router1:::::2 .Ve .IP "name" 4 .IX Item "name" the name of the subroutine that \s-1MRTG\s0 will call to convert the input and output values to integers. See the complete example under the global keyword \&\*(L"ConversionCode\*(R" above. .Sp Example: .Sp .Vb 1 \& 1.3.6.1.4.1.999.1&1.3.6.1.4.1.999.2:public@mydevice:161::::2|Length2Int .Ve .Sp This would retrieve values from the \s-1OID 1.3.6.1.4.1.999.1\s0 for input and .2 for output on mydevice using \s-1UDP\s0 port 161 and \s-1SNMP\s0 version 2, and would execute the user-defined numeric conversion subroutine Length2Int to convert those values to integers. .RE .RS 4 .Sp A value that equals the default value can be omitted. Trailing colons can be omitted, too. The pipe symbol followed by the name parameter, if present, must come at the end. There must be no spaces around the colons or pipe symbol. .Sp Example: .Sp .Vb 1 \& Target[ezci]: 1:public@ezci\-ether.domain:9161::4 .Ve .Sp This would refer to the input/output octet counters for the interface with \fIifIndex 1\fR on \fIezci\-ether.domain\fR, as known by the \s-1SNMP\s0 agent listening on \s-1UDP\s0 port 9161. The standard initial timeout (2.0 seconds) is used, but the number of retries is set to four. The backoff value is the default. .RE .IP "Numeric IPv6 addresses" 4 .IX Item "Numeric IPv6 addresses" If IPv6 is enabled you may also specify a target using its IPv6 address. To avoid ambiguity with the port number, numeric IPv6 addresses must be placed in square brackets. .Sp Example: .Sp .Vb 1 \& Target[IPv6test]: 2:public@[2001:760:4::]:6161::4 .Ve .IP "External Monitoring Scripts" 4 .IX Item "External Monitoring Scripts" If you want to monitor something which does not provide data via snmp you can use some external program to do the data gathering. .Sp The external command must return 4 lines of output: .RS 4 .IP "Line 1" 4 .IX Item "Line 1" current state of the first variable, normally 'incoming bytes count' .IP "Line 2" 4 .IX Item "Line 2" current state of the second variable, normally 'outgoing bytes count' .IP "Line 3" 4 .IX Item "Line 3" string (in any human readable format), telling the uptime of the target. .IP "Line 4" 4 .IX Item "Line 4" string, telling the name of the target. .RE .RS 4 .Sp Depending on the type of data your script returns you might want to use the 'gauge' or 'absolute' arguments for the \fIOptions\fR keyword. .Sp Example: .Sp .Vb 1 \& Target[myrouter]: \`/usr/local/bin/df2mrtg /dev/dsk/c0t2d0s0\` .Ve .Sp Note the use of the backticks (`), not apostrophes (') around the command. .Sp If you want to use a backtick in the command name this can be done but you must escape it with a backslash ... .Sp If your script does not have any data to return but does not want mrtg to complain about invalid data, it can return '\s-1UNKNOWN\s0' instead of a number. Note though that only rrdtool is really equipped to handle unknown data well. .RE .IP "Multi Target Syntax" 4 .IX Item "Multi Target Syntax" You can also combine several target definitions in a mathematical expression. Any syntactically correct expression that the Perl interpreter can evaluate to will work. An expression could be used, for example, to aggregate both B channels in an \s-1ISDN\s0 connection or to calculate the percentage hard disk utilization of a server from the absolute used space and total capacity. .Sp Examples: .Sp .Vb 1 \& Target[myrouter]: 2:public@wellfleetA + 1:public@wellfleetA \& \& Target[myrouter]: .1.3.6.1.4.1.999.1&.1.3.6.1.4.1.999.2:public@mydevice / \& .1.3.6.1.4.1.999.3&.1.3.6.1.4.1.999.4:public@mydevice * 100 .Ve .Sp Note that whitespace must surround each target definition in the expression. Target definitions themselves must not contain whitespace, except in interface descriptions and interface names, where each whitespace character is escaped by a backslash. .Sp \&\s-1MRTG\s0 automatically rounds the result of the expression to an integer unless RRDTool logging is in use and the gauge option is in effect for the target. Internally \s-1MRTG\s0 uses Perl's Math::BigFloat package to calculate the result of the expression with 40 digits of precision. Even in extreme cases, where, for example, you take the difference of two 64\-bit integers, the result of the expression should be accurate. .IP "\s-1SNMP\s0 Request Optimization" 4 .IX Item "SNMP Request Optimization" \&\s-1MRTG\s0 is designed to economize on its \s-1SNMP\s0 requests. Where a target definition appears more than once in the configuration file, \s-1MRTG\s0 requests the data from the device only once per round of data collection and uses the collected data for each instance of a particular target. Recognition of two target definitions as being identical is based on a simple string match rather than any kind of deeper semantic analysis. .Sp Example: .Sp .Vb 4 \& Target[Targ1]: 1:public@CiscoA \& Target[Targ2]: 2:public@CiscoA \& Target[Targ3]: 1:public@CiscoA + 2:public@CiscoA \& Target[Targ4]: 1:public@CISCOA .Ve .Sp This results in a total of three \s-1SNMP\s0 requests. Data for 1:public@CiscoA and 2:public@CiscoA are requested only once each, and used for Targ1, Targ2, and Targ3. Targ4 causes another \s-1SNMP\s0 request for 1:public@CISCOA, which is not recognized as being identical to 1:public@CiscoA. .SS "MaxBytes" .IX Subsection "MaxBytes" The maximum value either of the two variables monitored are allowed to reach. For monitoring router traffic this is normally the bytes per second this interface port can carry. .PP If a number higher than \fIMaxBytes\fR is returned, it is ignored. Also read the section on \fIAbsMax\fR for further info. The \fIMaxBytes\fR value is also used in calculating the Y range for unscaled graphs (see the section on \fIUnscaled\fR). .PP Since most links are rated in bits per second, you need to divide their maximum bandwidth (in bits) by eight (8) in order to get bytes per second. This is very important to make your unscaled graphs display realistic information. T1 = 193000, 56K = 7000, 10 \s-1MB\s0 Ethernet = 1250000, 100 \s-1MB\s0 Ethernet = 12500000. The \fIMaxBytes\fR value will be used by mrtg to decide whether it got a valid response from the router. .PP If you need two different MaxBytes values for the two monitored variables, you can use MaxBytes1 and MaxBytes2 instead of MaxBytes. .PP Example: .PP .Vb 1 \& MaxBytes[myrouter]: 1250000 .Ve .SS "Title" .IX Subsection "Title" Title for the \s-1HTML\s0 page which gets generated for the graph. .PP Example: .PP .Vb 1 \& Title[myrouter]: Traffic Analysis for Our Nice Company .Ve .SH "OPTIONAL PER TARGET KEYWORDS" .IX Header "OPTIONAL PER TARGET KEYWORDS" .SS "PageTop" .IX Subsection "PageTop" Things to add to the top of the generated \s-1HTML\s0 page. Note that you can have several lines of text as long as the first column is empty. .PP Note that the continuation lines will all end up on the same line in the html page. If you want linebreaks in the generated html use the '\en' sequence. .PP Example: .PP .Vb 4 \& PageTop[myrouter]:

      Traffic Analysis for ETZ C95.1

      \& Our Campus Backbone runs over an FDDI line\en \& with a maximum transfer rate of 12.5 megabytes per \& Second. .Ve .SS "RouterUptime" .IX Subsection "RouterUptime" In cases where you calculate the used bandwidth from several interfaces you normally don't get the router uptime and router name displayed on the web page. .PP If these interfaces are on the same router and the uptime and name should be displayed you have to specify its community and address again with the \fIRouterUptime\fR keyword. .PP If you want to use a special \s-1OID\s0 for querying the router uptime, use prepend the oid. .PP Example: .PP .Vb 2 \& Target[kacisco.comp.edu]: 1:public@194.64.66.250 + 2:public@194.64.66.250 \& RouterUptime[kacisco.comp.edu]: public@194.64.66.250 \& \& RouterUptime[kacisco.comp.edu]: hrSystemUptime.0:public@194.64.66.250 .Ve .SS "RouterName" .IX Subsection "RouterName" If the default name of the router is incorrect/uninformative, you can use RouterName to specify a different \s-1OID\s0 on either the same or a different host. .PP A practical example: sysName on BayTech \s-1DS72\s0 units always display \&\*(L"ds72\*(R", no matter what you set the Unit \s-1ID\s0 to be. Instead, the Unit \s-1ID\s0 is stored at 1.3.6.1.4.1.4779.1.1.3.0, so we can have \&\s-1MRTG\s0 display this instead of sysName. .PP Example: .PP .Vb 1 \& RouterName[kacisco.comp.edu]: 1.3.6.1.4.1.4779.1.1.3.0 .Ve .PP A different \s-1OID\s0 on a different host can also be specified: .PP .Vb 1 \& RouterName[kacisco.comp.edu]: 1.3.6.1.4.1.4779.1.1.3.0:public@194.64.66.251 .Ve .SS "MaxBytes1" .IX Subsection "MaxBytes1" Same as MaxBytes, for variable 1. .SS "MaxBytes2" .IX Subsection "MaxBytes2" Same as MaxBytes, for variable 2. .SS "IPv4Only" .IX Subsection "IPv4Only" Many IPv6 routers do not currently support \s-1SNMP\s0 over IPv6 and must be monitored using IPv4. The IPv4Only option forces mrtg to use IPv4 when communicating with the target, even if IPv6 is enabled. This is useful if the target is a hostname with both IPv4 and IPv6 addresses; without the IPv4Only keyword, monitoring such a router will not work if IPv6 is enabled. .PP If set to no (the default), mrtg will use IPv6 unless the target has no IPv6 addresses, in which case it will use IPv4. If set to yes, mrtg will only use IPv4. .PP Note that if this option is set to yes and the target does not have an IPv4 address, communication with the target will fail. .PP This option has no effect if IPv6 is not enabled. .PP Example: .PP .Vb 2 \& Target[v4onlyrouter_1]: 1:public@v4onlyrouter \& IPv4Only[v4onlyrouter_1]: Yes .Ve .SS "SnmpOptions (V3)" .IX Subsection "SnmpOptions (V3)" SNMPv3 requires a fairly rich set of options. This per-target keyword allows access to the User Security Model of SNMPv3. Options are listed in the same syntax as a perl hash. .PP \fISecurity Modes\fR .IX Subsection "Security Modes" .PP SNMPv3 has three security modes, defined on the device being polled. For example, on Cisco routers the security mode is defined by the snmp-server group global configuration command. .IP "NoAuthNoPriv" 4 .IX Item "NoAuthNoPriv" Neither Authentication nor Privacy is defined. Only the Username option is specified for this mode. .Sp Example: .Sp .Vb 1 \& SnmpOptions[myrouter]: username=>\*(Aquser1\*(Aq .Ve .IP "AuthNoPriv" 4 .IX Item "AuthNoPriv" Uses a Username and a password. The password can be hashed using the snmpkey application, or passed in plain text along with the ContextEngineID .Sp Example: .Sp .Vb 2 \& SnmpOptions[myrouter]: username=>\*(Aquser1\*(Aq,authpassword=>\*(Aqexample\*(Aq, \& contextengineid=>\*(Aq80000001110000004000000\*(Aq .Ve .IP "Priv" 4 .IX Item "Priv" Both Authentication and Privacy is defined. The default privacy protocol is des. .Sp Example: SnmpOptions[myrouter]: authkey=>'0x1e93ab5a396e2af234c8920e61cfe2028072c0e2', authprotocol=>'sha',privprotocol=>'des',username=>'user1', privkey=>'0x498d74940c5872ed387201d74b9b25e2' .PP \fIsnmp options\fR .IX Subsection "snmp options" .PP The following option keywords are recognized: .IP "username" 4 .IX Item "username" The user associated with the User Security Model .IP "contextname" 4 .IX Item "contextname" An \s-1SNMP\s0 agent can define multiple contexts. This keyword allows them to be polled. .IP "contextengineid" 4 .IX Item "contextengineid" A unique 24\-byte string identifying the snmp-agent. .IP "authpassword" 4 .IX Item "authpassword" The plaintext password for a user in either AuthNoPriv or Priv mode. .IP "authkey" 4 .IX Item "authkey" A md5 or sha hash of the plain-text password, along with the engineid. Use the snmpkey commandline program to generate this hash, or use Net::SNMP::Security::USM in a script. .IP "authprotocol {sha|md5}" 4 .IX Item "authprotocol {sha|md5}" The hashing algorithm defined on the \s-1SNMP\s0 client. Defaults to md5. .IP "privpassword" 4 .IX Item "privpassword" A plaintext pre-shared key for encrypting snmp packets in Priv mode. .IP "privkey" 4 .IX Item "privkey" A hash of the plain-text pre-shared key, along with the engineid. Use the snmpkey commandline program to generate this hash, or use Net::SNMP::Security::USM in a script. .IP "privprotocol {des|3desede|aescfb128|aescfb192|aescfb256}" 4 .IX Item "privprotocol {des|3desede|aescfb128|aescfb192|aescfb256}" Specifies the encryption method defined on the snmp agent. The default is des. .SS "PageFoot" .IX Subsection "PageFoot" Things to add to the bottom of the generated \s-1HTML\s0 page. Note that you can have several lines of text as long as the first column is empty. .PP Note that the continuation lines will all end up on the same line in the html page. If you want linebreaks in the generated html use the '\en' sequence. .PP The material will be added just before the tag: .PP Example: .PP .Vb 2 \& PageFoot[myrouter]: Contact
      Peter \& if you have questions regarding this page .Ve .SS "AddHead" .IX Subsection "AddHead" Use this tag like the \fIPageTop\fR header, but its contents will be added between and . .PP Example: .PP .Vb 1 \& AddHead[myrouter]: .Ve .SS "BodyTag" .IX Subsection "BodyTag" BodyTag lets you supply your very own tag for the generated webpages. .PP Example: .PP .Vb 2 \& BodyTag[myrouter]: .Ve .SS "AbsMax" .IX Subsection "AbsMax" If you are monitoring a link which can handle more traffic than the \&\fIMaxBytes\fR value. Eg, a line which uses compression or some frame relay link, you can use the \fIAbsMax\fR keyword to give the absolute maximum value ever to be reached. We need to know this in order to sort out unrealistic values returned by the routers. If you do not set \fIAbsMax\fR, rateup will ignore values higher than \fIMaxBytes\fR. .PP Example: .PP .Vb 1 \& AbsMax[myrouter]: 2500000 .Ve .SS "Unscaled" .IX Subsection "Unscaled" By default each graph is scaled vertically to make the actual data visible even when it is much lower than \fIMaxBytes\fR. With the \fIUnscaled\fR variable you can suppress this. It's argument is a string, containing one letter for each graph you don't want to be scaled: d=day w=week m=month y=year. There is also a special case to unset the variable completely: n=none. This could be useful in the event you need to override a global configuration. In the example scaling for the yearly and the monthly graph are suppressed. .PP Example: .PP .Vb 1 \& Unscaled[myrouter]: ym .Ve .SS "WithPeak" .IX Subsection "WithPeak" By default the graphs only contain the average values of the monitored variables \- normally the transfer rates for incoming and outgoing traffic. The following option instructs mrtg to display the peak 5 minute values in the [w]eekly, [m]onthly and [y]early graph. In the example we define the monthly and the yearly graph to contain peak as well as average values. .PP Examples: .PP .Vb 1 \& WithPeak[myrouter]: ym .Ve .SS "Suppress" .IX Subsection "Suppress" By default mrtg produces 4 graphs. With this option you can suppress the generation of selected graphs. The option value syntax is analogous to the above two options. In this example we suppress the yearly graph as it is quite empty in the beginning. .PP Example: .PP .Vb 1 \& Suppress[myrouter]: y .Ve .SS "Extension" .IX Subsection "Extension" By default, mrtg creates .html files. Use this option to tell mrtg to use a different extension. For example you could set the extension to php3, then you will be able to enclose \s-1PHP\s0 tags into the output (useful for getting a router name out of a database). .PP Example: .PP .Vb 1 \& Extension[myrouter]: phtml .Ve .SS "Directory" .IX Subsection "Directory" By default, mrtg puts all the files that it generates for each target (the GIFs, the \s-1HTML\s0 page, the log file, etc.) in \fIWorkDir\fR. .PP If the \fIDirectory\fR option is specified, the files are instead put into a directory under \fIWorkDir\fR or Log\-, Image\- and HtmlDir). (For example the \fIDirectory\fR option below would cause all the files for a target myrouter to be put into directory /usr/tardis/pub/www/stats/mrtg/myrouter/ .) .PP The directory must already exist; mrtg will not create it. .PP Example: .PP .Vb 2 \& WorkDir: /usr/tardis/pub/www/stats/mrtg \& Directory[myrouter]: myrouter .Ve .PP \&\s-1NOTE:\s0 the Directory option must always be 'relative' or bad things will happen. .SS "Clonedirectory" .IX Subsection "Clonedirectory" If the \fIDirectory\fR option is specified, the \fIClonedirectory\fR option will copy all the contents of \fIDirectory\fR to the \fIClonedirectory\fR. .PP Example: .PP .Vb 3 \& WorkDir: /usr/tardis/pub/www/stats/mrtg \& Directory[myrouter]: myrouter \& Clonedirectory[myrouter]: myclonedirectory .Ve .PP Optionally the target name can be changed in the cloning process. .PP Example: .PP .Vb 3 \& WorkDir: /usr/tardis/pub/www/stats/mrtg \& Directory[myrouter]: myrouter \& Clonedirectory[myrouter]: myclonedirectory mynewtarget .Ve .PP \&\s-1NOTE1:\s0 The clone directory must already exist; mrtg will not create it. .PP \&\s-1NOTE2:\s0 The Clonedirectory option must also always be 'relative' or bad things will happen. .PP \&\s-1NOTE3:\s0 This requires the File::Copy module .SS "XSize and YSize" .IX Subsection "XSize and YSize" By default mrtgs graphs are 100 by 400 pixels wide (plus some more for the labels. In the example we get almost square graphs ... .PP Note: XSize must be between 20 and 600; YSize must be larger than 20 .PP Example: .PP .Vb 2 \& XSize[myrouter]: 300 \& YSize[myrouter]: 300 .Ve .SS "XZoom and YZoom" .IX Subsection "XZoom and YZoom" If you want your graphs to have larger pixels, you can \&\*(L"Zoom\*(R" them. .PP Example: .PP .Vb 2 \& XZoom[myrouter]: 2.0 \& YZoom[myrouter]: 2.0 .Ve .SS "XScale and YScale" .IX Subsection "XScale and YScale" If you want your graphs to be actually scaled use \fIXScale\fR and \fIYScale\fR. (Beware: while this works, the results look ugly (to be frank) so if someone wants to fix this: patches are welcome. .PP Example: .PP .Vb 2 \& XScale[myrouter]: 1.5 \& YScale[myrouter]: 1.5 .Ve .SS "YTics and YTicsFactor" .IX Subsection "YTics and YTicsFactor" If you want to show more than 4 lines per graph, use YTics. If you want to scale the value used for the YLegend of these tics, use YTicsFactor. The default value for YTics is 4 and the default value for YTicsFactor is 1.0 . .PP Example: .PP Suppose you get values ranging from 0 to 700. You want to plot 7 lines and want to show 0, 1, 2, 3, 4, 5, 6, 7 instead of 0, 100, 200, 300, 400, 500, 600, 700. You should write then: .PP .Vb 2 \& YTics[myrouter]: 7 \& YTicsFactor[myrouter]: 0.01 .Ve .SS "Factor" .IX Subsection "Factor" If you want to multiply all numbers shown below the graph with a constant factor, use this directive to define it .. .PP Example: .PP .Vb 1 \& Factor[as400]: 4096 .Ve .SS "Step" .IX Subsection "Step" Change the default step from 5 * 60 seconds to something else (I have not tested this much ...) .PP Example: .PP .Vb 1 \& Step[myrouter]: 60 .Ve .SS "PNGTitle" .IX Subsection "PNGTitle" When using rateup for graph generation, this will print the given title in the graph it generates. .PP Example: .PP .Vb 1 \& PNGTitle[myrouter]: WAN Link UK\-US .Ve .SS "Options" .IX Subsection "Options" The \fIOptions\fR Keyword allows you to set some boolean switches: .IP "growright" 4 .IX Item "growright" The graph grows to the left by default. This option flips the direction of growth causing the current time to be at the right edge of the graph and the history values to the left of it. .IP "bits" 4 .IX Item "bits" All the monitored variable values are multiplied by 8 (i.e. shown in bits instead of bytes) ... looks much more impressive :\-) It also affects the 'factory default' labeling and units for the given target. .IP "perminute" 4 .IX Item "perminute" All the monitored variable values are multiplied by 60 (i.e. shown in units per minute instead of units per second) in case of small values more accurate graphs are displayed. It also affects the 'factory default' labeling and units for the given target. .IP "perhour" 4 .IX Item "perhour" All the monitored variable values are multiplied by 3600 (i.e. shown in units per hour instead of units per second) in case of small values more accurate graphs are displayed. It also affects the 'factory default' labeling and units for the given target. .IP "noinfo" 4 .IX Item "noinfo" Suppress the information about uptime and device name in the generated webpage. .IP "nopercent" 4 .IX Item "nopercent" Don't print usage percentages. .IP "transparent" 4 .IX Item "transparent" Make the background of the generated gifs transparent. .IP "integer" 4 .IX Item "integer" Print summary lines below graph as integers without commas. .IP "dorelpercent" 4 .IX Item "dorelpercent" The relative percentage of IN-traffic to OUT-traffic is calculated and displayed in the graph as an additional line. Note: Only a fixed scale is available (from 0 to 100%). Therefore if IN-traffic is greater than OUT-traffic then 100% is displayed. If you suspect that your IN-traffic is not always less than or equal to your OUT-traffic you are urged to not use this options. Note: If you use this option in combination with the \fIColours\fR options, a fifth colour-name colour-value pair is required there. .IP "avgpeak" 4 .IX Item "avgpeak" There are some ISPs who use the average Peak values to bill their customers. Using this option \s-1MRTG\s0 displays these values for each graph. The value is built by averaging the max 5 minute traffic average for each 'step' shown in the graph. For the Weekly graph this means that it builds the average of all 2 hour intervals 5 minute peak values. (Confused? Thought so!) .IP "gauge" 4 .IX Item "gauge" Treat the values gathered from target as 'current status' measurements and not as ever incrementing counters. This would be useful to monitor things like disk space, processor load, temperature, and the like ... .Sp In the absence of 'gauge' or 'absolute' options, \&\s-1MRTG\s0 treats variables as a counters and calculates the difference between the current and the previous value and divides that by the elapsed time between the last two readings to get the value to be plotted. .IP "absolute" 4 .IX Item "absolute" This is for counter type data sources which reset their value when they are read. This means that rateup does not have to build the difference between the current and the last value read from the data source. The value obtained is still divided by the elapsed time between the current and the last reading, which makes it different from the 'gauge' option. Useful for external data gatherers. .IP "derive" 4 .IX Item "derive" If you are using rrdtool as logger/grapher you can use a third type of data source. Derive is like counter, except that it is not required to go \s-1UP\s0 all the time. It is useful for situations where the change of some value should be graphed. .IP "unknaszero" 4 .IX Item "unknaszero" Log unknown data as zero instead of the default behaviour of repeating the last value seen. Be careful with this, often a flat line in the graph is much more obvious than a line at 0. .IP "withzeroes" 4 .IX Item "withzeroes" Normally we ignore all values which are zero when calculating the average transfer rate on a line. If this is not desirable use this option. .IP "noborder" 4 .IX Item "noborder" If you are using rateup to log data, \s-1MRTG\s0 will create the graph images. Normally these images have a shaded border around them. If you do not want the border to be drawn, enable this option. This option has no effect if you are not using rateup. .IP "noarrow" 4 .IX Item "noarrow" As with the option above, this effects rateup graph generation only. Normally rateup will generate graphs with a small arrow showing the direction of the data. If you do not want this arrow to be drawn, enable this option. This option has no effect if you are not using rateup. .IP "noi" 4 .IX Item "noi" When using rateup for graph generation, you can use this option to stop rateup drawing a graph for the 'I' or first variable. This also removes entries for this variable in the \s-1HTML\s0 page \s-1MRTG\s0 generates, and will remove the peaks for this variable if they are enabled. This allows you to hide this data, or can be very useful if you are only graphing one line of data rather than two. This option is not destructive \- any data received for the the variable continued to be logged, it just isn't shown. .IP "noo" 4 .IX Item "noo" Same as above, except relating to the 'O' or second variable. .IP "nobanner" 4 .IX Item "nobanner" When using rateup for graph generation, this option disables \s-1MRTG\s0 adding the \&\s-1MRTG\s0 banner to the \s-1HTML\s0 pages it generates. .IP "nolegend" 4 .IX Item "nolegend" When using rateup for graph generation, this option will stop \s-1MRTG\s0 from creating a legend at the bottom of the \s-1HTML\s0 pages it generates. .IP "printrouter" 4 .IX Item "printrouter" When using rateup for graph generation, this option will print the router name in the graph it generates. This option is overridden by the value of PNGTitle if one is given .IP "pngdate" 4 .IX Item "pngdate" When using rateup for graph generation, this option will print a timestamp in the graph it generates, including a timezone if one is specified by the 'Timezone' parameter. This is equivalent to setting TimeStrPost[x]: \s-1RU\s0 .IP "logscale" 4 .IX Item "logscale" The \fBlogscale\fR option causes rateup to display the data with the Y axis scaled logarithmically. Doing so allows the normal traffic to occupy the majority of the vertical range, while still showing any spikes at their full height. .Sp \&\fBlogscale\fR displays all the available data and will always produce well-behaved graphs. People often consider a logarithmically scaled graph counterintuitive, however, and thus hard to interpret. .IP "expscale" 4 .IX Item "expscale" The \fBexpscale\fR option causes rateup to display the data with the Y axis scaled exponentially. Doing so emphasizes small changes at the top of the scale; this can be useful when graphing values that fluctuate by a small amount near the top of the scale, such as line voltage. .Sp \&\fBexpscale\fR is essentially the inverse of \fBlogscale\fR. .IP "secondmean" 4 .IX Item "secondmean" The \fBsecondmean\fR option sets the maximum value on the graph to the mean of the data greater than the mean of all data. This produces a graph that focuses more on the typical data, while clipping large peaks. .Sp Using \fBsecondmean\fR will give a more intuitive linearly scaled graph, but can result in a uselessly high or low scale in some rare situations (specifically, when the data includes a large portion of values far from the actual mean) .Sp If a target includes both \fBlogscale\fR and \fBsecondmean\fR in the options, the \&\fBsecondmean\fR takes precedence. .PP Example: .PP .Vb 1 \& Options[myrouter]: growright, bits .Ve .SS "kilo" .IX Subsection "kilo" Use this option to change the multiplier value for building prefixes. Defaultvalue is 1000. This tag is for the special case that 1kB = 1024B, 1MB = 1024kB and so far. .PP Example: .PP .Vb 1 \& kilo[myrouter]: 1024 .Ve .SS "kMG" .IX Subsection "kMG" Change the default multiplier prefixes (,k,M,G,T,P). In the tag \&\fIShortLegend\fR define only the basic units. Format: Comma separated list of prefixed. Two consecutive commas or a comma at start or end of the line gives no prefix on this item. If you do not want prefixes, just put two consecutive commas. If you want to skip a magnitude select '\-' as value. .PP Example: velocity in nm/s (nanometers per second) displayed in nm/h. .PP .Vb 3 \& ShortLegend[myrouter]: m/h \& kMG[myrouter]: n,u,m,,k,M,G,T,P \& options[myrouter]: perhour .Ve .SS "Colours" .IX Subsection "Colours" The \fIColours\fR tag allows you to override the default colour scheme. Note: All 4 of the required colours must be specified here. The colour name ('Colourx' below) is the legend name displayed, while the \s-1RGB\s0 value is the real colour used for the display, both on the graph and in the html doc. .PP Format is: Col1#RRGGBB,Col2#RRGGBB,Col3#RRGGBB,Col4#RRGGBB .PP Important: If you use the \fIdorelpercent\fR options tag a fifth colour name colour value pair is required: Col1#RRGGBB,Col2#RRGGBB,Col3#RRGGBB,Col4#RRGGBB,Col5#RRGGBB .IP "Colour1" 4 .IX Item "Colour1" First variable (normally Input) on default graph. .IP "Colour2" 4 .IX Item "Colour2" Second variable (normally Output) on default graph. .IP "Colour3" 4 .IX Item "Colour3" Max first variable (input). .IP "Colour4" 4 .IX Item "Colour4" Max second variable (output). .IP "\s-1RRGGBB\s0" 4 .IX Item "RRGGBB" 2 digit hex values for Red, Green and Blue. .PP Example: .PP .Vb 1 \& Colours[myrouter]: GREEN#00eb0c,BLUE#1000ff,DARK GREEN#006600,VIOLET#ff00ff .Ve .SS "Background" .IX Subsection "Background" With the \fIBackground\fR tag you can configure the background colour of the generated \s-1HTML\s0 page. .PP Example: .PP .Vb 1 \& Background[myrouter]: #a0a0a0a .Ve .SS "TextColor" .IX Subsection "TextColor" With the \fITextColor\fR tag you can configure the text colour of the generated \s-1HTML\s0 page. .PP Example: .PP .Vb 1 \& TextColor[myrouter]: #a0a0a0a .Ve .SS "YLegend, ShortLegend, Legend[1234]" .IX Subsection "YLegend, ShortLegend, Legend[1234]" The following keywords allow you to override the text displayed for the various legends of the graph and in the \&\s-1HTML\s0 document: .IP "YLegend" 4 .IX Item "YLegend" The Y\-axis label of the graph. Note that a text which is too long to fit in the graph will be silently ignored. .IP "ShortLegend" 4 .IX Item "ShortLegend" The units string (default 'b/s') used for Max, Average and Current .IP "Legend[1234IO]" 4 .IX Item "Legend[1234IO]" The strings for the colour legend. .PP Example: .PP .Vb 8 \& YLegend[myrouter]: Bits per Second \& ShortLegend[myrouter]: b/s \& Legend1[myrouter]: Incoming Traffic in Bits per Second \& Legend2[myrouter]: Outgoing Traffic in Bits per Second \& Legend3[myrouter]: Maximal 5 Minute Incoming Traffic \& Legend4[myrouter]: Maximal 5 Minute Outgoing Traffic \& LegendI[myrouter]:  In: \& LegendO[myrouter]:  Out: .Ve .PP Note, if \fILegendI\fR or \fILegendO\fR are set to an empty string with .PP .Vb 1 \& LegendO[myrouter]: .Ve .PP The corresponding line below the graph will not be printed at all. .SS "Timezone" .IX Subsection "Timezone" If you live in an international world, you might want to generate the graphs in different timezones. This is set in the \&\s-1TZ\s0 variable. Under certain operating systems like Solaris, this will provoke the localtime call to give the time in the selected timezone. .PP Example: .PP .Vb 1 \& Timezone[myrouter]: Japan .Ve .PP The Timezone is the standard timezone of your system, ie Japan, Hongkong, \&\s-1GMT, GMT+1\s0 etc etc. .SS "Weekformat" .IX Subsection "Weekformat" By default, mrtg (actually rateup) uses the \fBstrftime\fR\|(3) '%V' option to format week numbers in the monthly graphs. The exact semantics of this format option vary between systems. If you find that the week numbers are wrong, and your system's \fBstrftime\fR\|(3) routine supports it, you can try another format option. The \s-1POSIX\s0 '%V' option correspond to the widely used \&\s-1ISO 8601\s0 week numbering standard. The week format character should be specified as a single letter; either W, V, or U. .PP The \s-1UNIX\s0 version of rateup uses the libc implementation of strftime. On Windows, the native strftime implementation does not know about \&\f(CW%V\fR. So there we use a different implementation of strftime that does support \f(CW%V\fR. .PP Example: .PP .Vb 1 \& Weekformat[myrouter]: W .Ve .SS "RRDRowCount" .IX Subsection "RRDRowCount" This affects the creation of new rrd files. By default rrds are created to hold about 1 day's worth of high resolution data. (plus 1 week of 30 minute data, 2 months of 2 hour data and 2 years of 1 day data). With this Keyword you can change the number of base interval entries configured for new rrds as they get created. Note that you must take the interval time into account. .PP Example: .PP .Vb 1 \& RRDRowCount[myrouter]: 1600 .Ve .SS "RRDRowCount30m" .IX Subsection "RRDRowCount30m" As per RRDRowCount, but for the \s-1RRA\s0's \-typically\- used for 30 minute data. Even so, you must still take the base interval into account. Leaving out this keyword will force the old default of 800 rows. .PP Example: .PP .Vb 1 \& RRDRowCount30m[myrouter]: 800 .Ve .SS "RRDRowCount2h" .IX Subsection "RRDRowCount2h" As per RRDRowCount, but for the \s-1RRA\s0's \-typically\- used for 2 hour data. Even so, you must still take the base interval into account. Leaving out this keyword will force the old default of 800 rows. .PP Example: .PP .Vb 1 \& RRDRowCount2h[myrouter]: 400 .Ve .SS "RRDRowCount1d" .IX Subsection "RRDRowCount1d" As per RRDRowCount, but for the \s-1RRA\s0's \-typically\- used for 1 day data. Even so, you must still take the base interval into account. Leaving out this keyword will force the old default of 800 rows. .PP Example: .PP .Vb 1 \& RRDRowCount1d[myrouter]: 200 .Ve .SS "RRDHWRRAs" .IX Subsection "RRDHWRRAs" Normally the RRDs created by \s-1MRTG\s0 will just contain the information gathered directly from the respective target. With this option you can tap into rrdtools advanced aberrant behaviour detection module based on Holt-Winters forecasting. The RRDHWRRAs property specifies the Holt-Winters RRAs as described in the rrdcreate manual page. .PP Note, this setting will only affect newly created RRDs (targets). .PP Example: .PP .Vb 1 \& RRDHWRRAs[myrouter]: RRA:HWPREDICT:1440:0.1:0.0035:288 .Ve .SS "TimeStrPos" .IX Subsection "TimeStrPos" This defines placement of the timestamp string on the image. Possible values are \s-1RU, LU, RL, LL\s0 (which stand, respectively, for RightUpper, LeftUpper, RightLower and LeftLower corner) and \s-1NO\s0 (for no timestamp). By default, no timestamp is placed on the image. .PP Example: .PP .Vb 1 \& TimeStrPos[myrouter]: RU .Ve .SS "TimeStrFmt" .IX Subsection "TimeStrFmt" Using this keyword you may specify format of the timestamp to be placed on the image (if enabled by the TimeStrPos keyword). Specified string will be used by the \fBstrftime()\fR function \- see \fBstrftime\fR\|(3) documentation for conversion specifiers available on your system. Default format: \f(CW%Y\fR\-%m\-%d \f(CW%H:\fR%M .PP Example: .PP .Vb 1 \& TimeStrFmt[myrouter]: %H:%M:%S .Ve .SH "THRESHOLD CHECKING" .IX Header "THRESHOLD CHECKING" Through its threshold checking functionality mrtg is able to detect threshold problems for the various targets and can call external scripts to handle those problems (e.g. send email or a page to an administrator). .PP Threshold checking is configured through the following parameters: .SS "ThreshDir (\s-1GLOBAL\s0)" .IX Subsection "ThreshDir (GLOBAL)" By defining ThreshDir to point to a writable directory, \s-1MRTG\s0 will only alert you when a threshold boundary has been crossed. .PP Example: .PP .Vb 1 \& ThreshDir: /var/mrtg/thresh .Ve .SS "ThreshHyst (\s-1GLOBAL\s0)" .IX Subsection "ThreshHyst (GLOBAL)" If a threshold is broken, and you have a threshdir defined, then mrtg will send mail once the threshold becomes 'unborken' to avoid situations where broken and unbroken messages get sent in close succession, we only send an unbroken message once the current value is 0.1 (10%) away from the threshold. using the ThreshHyst config variable you can customize this value. .PP Example for 5%: .PP .Vb 1 \& ThreshHyst: 0.05 .Ve .SS "ThreshMailServer (\s-1GLOBAL\s0)" .IX Subsection "ThreshMailServer (GLOBAL)" Address of an \s-1SMTP\s0 server which is going to accept mail about Thresholds being broken and unbroken. .SS "ThreshMailSender (\s-1GLOBAL\s0)" .IX Subsection "ThreshMailSender (GLOBAL)" What is the sender address of the threshold mail. .PP Example: .PP .Vb 1 \& ThreshMailSender: mrtg@example.com .Ve .SS "ThreshMailAddress (\s-1PER TARGET\s0)" .IX Subsection "ThreshMailAddress (PER TARGET)" Email address for Threshold related Mails. This will only work if a mailserver has been configured. .PP Example: .PP .Vb 2 \& ThreshMailAddress[_]: admin@example.com \& ThreshMailAddress[router]: .Ve .PP This would bring threshold released mail to all but the target called 'router'. .SS "ThreshMinI (\s-1PER TARGET\s0)" .IX Subsection "ThreshMinI (PER TARGET)" This is the minimum acceptable value for the Input (first) parameter. If the parameter falls below this value, the program specified in ThreshProgI will be run and a mail will be sent to the ThreshMailAddress if specified. If the value ends in '%' then the threshold is defined relative to MaxBytes. .SS "ThreshMaxI (\s-1PER TARGET\s0)" .IX Subsection "ThreshMaxI (PER TARGET)" Works the same as TheshMinI but it acts when the value is higher than ThreshMaxI. .SS "ThreshDesc (\s-1PER TARGET\s0)" .IX Subsection "ThreshDesc (PER TARGET)" Its value will be assigned to the environment variable \s-1THRESH_DESC\s0 before any of the programs mentioned below are called. The programs can use the value of this variable to produce more user-friendly output. .SS "ThreshProgI (\s-1PER TARGET\s0)" .IX Subsection "ThreshProgI (PER TARGET)" This defines a program to be run if ThreshMinI or ThreshMaxI is broken. \&\s-1MRTG\s0 passes 3 arguments: the \f(CW$router\fR variable, the threshold value broken, and the current parameter value. .SS "ThreshProgOKI (\s-1PER TARGET\s0)" .IX Subsection "ThreshProgOKI (PER TARGET)" This defines a program to be run if the parameter is currently \s-1OK\s0 (based on ThreshMinI and ThreshMaxI), but wasn't \s-1OK\s0 on the previous running \*(-- based on the files found in ThreshDir. \s-1MRTG\s0 passes 3 arguments: the \f(CW$router\fR variable the unbroken threshold value, and the current parameter value. .SS "ThreshMinO, ThreshMaxO, ThreshProgO, and ThreshProgOKO" .IX Subsection "ThreshMinO, ThreshMaxO, ThreshProgO, and ThreshProgOKO" These work the same as their *I counterparts, except on the Output (second) parameter. .SS "SetEnv" .IX Subsection "SetEnv" When calling threshold scripts from within your cfg file you might want to pass some data on to the script. This can be done with the SetEnv configuration option which takes a series of environment variable assignments. Note that the quotes are mandatory. This does not work for external scripts. It is not possible to set environment variables per target. .PP Example: .PP .Vb 2 \& SetEnv[myrouter]: EMAIL="contact_email@someplace.net" \& HOST="www.some_server.net" .Ve .SS "\s-1HW\s0 Failure Based Threshold Checking" .IX Subsection "HW Failure Based Threshold Checking" When using rrd based logging with \s-1HW\s0 RRAs defined. You can use the confidence bounds violations stored in the \s-1FAILURES RRA\s0 for threshold based alerts. .PP There the all target specific threshold variables have a Hold-Winters counterpart: .PP .Vb 3 \& ThreshMailAddress \-> HWThreshMailAddress \& ThreshMinI \-> HWThreshMinI \& ... .Ve .PP The global variables for threshold checking are shared except for the .PP .Vb 1 \& ThreshHyst \-> HWThreshHyst .Ve .PP And HWThreshDesc sets the \s-1HWTHRESH_DESC\s0 variable. .SH "PER TARGET DEFAULT VALUES" .IX Header "PER TARGET DEFAULT VALUES" .SS "Pre\- and Postfix" .IX Subsection "Pre- and Postfix" To save yourself some typing you can define a target called '^'. The text of every Keyword you define for this target will be \s-1PREPENDED\s0 to the corresponding Keyword of all the targets defined below this line. The same goes for a Target called '$' but its text will be \s-1APPENDED.\s0 .PP Note that a space is inserted between the prepended text and the Keyword value, as well as between the Keyword value and the appended text. This works well for text-valued Keywords, but is not very useful for other Keywords. See the \*(L"default\*(R" target description below. .PP The example will make mrtg use a common header and a common contact person in all the pages generated from targets defined later in this file. .PP Example: .PP .Vb 2 \& PageTop[^]:

      NoWhere Unis Traffic Stats


      \& PageTop[$]: Contact Peter Norton if you have any questions
      .Ve .PP To remove the prepend/append value, specify an empty value, e.g.: .PP .Vb 2 \& PageTop[^]: \& PageTop[$]: .Ve .SS "NoSpaceChar" .IX Subsection "NoSpaceChar" With \s-1PREPEND\s0 and \s-1APPEND\s0 (see below) there is normally a space inserted between the local value and the \s-1PRE\-\s0 or \s-1APPEND\s0 value. Sometimes this is not desirable. You can use the global option \fINoSpaceChar\fR to define a character which can be mentioned at the end of a $ or ^ definition in order to suppress the space. .PP Example: .PP .Vb 6 \& NoSpaceChar: ~ \& Target[^]: 1.3.6.1.4.1.482.50.2.4.20.0&1.3.6.1.4.1.482.50.2.4.21.0:get@~ \& Target[a]: a.tolna.net \& Target[b]: b.tolna.net \& Target[c]: c.tolna.net \& Target[d]: d.tolna.net .Ve .SS "Default Values" .IX Subsection "Default Values" The target name '_' specifies a default value for that Keyword. In the absence of explicit Keyword value, the prepended and the appended keyword value, the default value will be used. .PP Example: .PP .Vb 5 \& YSize[_]: 150 \& Options[_]: growright,bits,nopercent \& WithPeak[_]: ymw \& Suppress[_]: y \& MaxBytes[_]: 1250000 .Ve .PP To remove the default value and return to the 'factory default', specify an empty value, e.g.: .PP .Vb 1 \& YLegend[_]: .Ve .PP There can be several instances of setting the default/prepend/append values in the configuration file. The later setting replaces the previous one for the rest of the configuration file. The default/prepend/append values used for a given keyword/target pair are the ones that were in effect at the point in the configuration file where the target was mentioned for the first time. .PP Example: .PP .Vb 4 \& MaxBytes[_]: 1250000 \& Target[myrouter.somplace.edu.2]: 2:public@myrouter.somplace.edu \& MaxBytes[_]: 8000 \& Title[myrouter.somplace.edu.2]: Traffic Analysis for myrouter.somplace.edu IF 2 .Ve .PP The default \fIMaxBytes\fR for the target myrouter.someplace.edu.2 in the above example will be 1250000, which was in effect where the target name myrouter.someplace.edu.2 first appeared in the config file. .SH "COMMAND LINE OPTIONS" .IX Header "COMMAND LINE OPTIONS" .IP "\fB\-\-user\fR \fIusername\fR and \fB\-\-group\fR \fIgroupname\fR" 4 .IX Item "--user username and --group groupname" Run as the given user and/or group. (Unix Only) .IP "\fB\-\-lock\-file\fR \fIfilename\fR" 4 .IX Item "--lock-file filename" Use an alternate lock-file (the default is to use the configuration-file appended with \f(CW\*(C`_l\*(C'\fR). .IP "\fB\-\-confcache\-file\fR \fIfilename\fR" 4 .IX Item "--confcache-file filename" Use an alternate confcache-file (the default is to use the configuration-file appended with \f(CW\*(C`.ok\*(C'\fR) .IP "\fB\-\-logging\fR \fIfilename\fR|\fBeventlog\fR" 4 .IX Item "--logging filename|eventlog" If this is set to writable filename, all output from mrtg (warnings, debug messages, errors) will go to \fIfilename\fR. If you are running on Win32 you can specify \fBeventlog\fR instead of a filename which will send all error to the windows event log. .Sp \&\fB\s-1NOTE:\s0\fR Note, there is no Message \s-1DLL\s0 for mrtg included with mrtg. This has the side effect that the windows event logger will display a nice message with every entry in the event log, complaining about the fact that mrtg has no message dll. If you go to the mrtg contrib download area (on the website) you will find the mrtg\-message\-dll.zip which does contain such a thing. .IP "\fB\-\-daemon\fR" 4 .IX Item "--daemon" Put \s-1MRTG\s0 into the background, running as a daemon. This works the same way as the config file option, but the switch is required for proper \s-1FHS\s0 operation (because /var/run is writable only by root) .IP "\fB\-\-fhs\fR" 4 .IX Item "--fhs" Configure all mrtg paths to conform to the \s-1FHS\s0 specification; http://www.pathname.com/fhs/ .IP "\fB\-\-check\fR" 4 .IX Item "--check" Only check the cfg file for errors. Do not do anything. .IP "\fB\-\-pid\-file=s\fR" 4 .IX Item "--pid-file=s" Define the name and path of the pid file for mrtg running as a daemon .IP "\fB\-\-debug=s\fR" 4 .IX Item "--debug=s" Enable debug options. The argument of the debug option is a comma separated list of debug values: .Sp .Vb 11 \& cfg \- watch the config file reading \& dir \- directory mangeling \& base \- basic program flow \& tarp \- target parser \& snpo \- snmp polling \& coca \- confcache operations \& fork \- forking view \& time \- some timing info \& log \- logging of data via rateup or rrdtool \& eval \- print eval strings before evaluating them \& prof \- add hires timing info the rrd calls .Ve .Sp Example: .Sp .Vb 1 \& \-\-debug="cfg,snpo" .Ve .SH "EXIT CODES" .IX Header "EXIT CODES" An exit code of 0 indicates that all targets were successful. Generally speaking, most codes greater than 0 indicate that there was an unrecoverable problem. One exception to this is code 91, which indicates that at least one of the targets was successful. A partial listing of the codes follows: .PP .Vb 1 \& 0: All targets successful \& \& 2: Config error (can\*(Aqt read, fatal error in config, etc) \& 17: Another MRTG process is processing config \& \& 91: At least one target successful \& 92: No targets were successful .Ve .SH "EXAMPLES" .IX Header "EXAMPLES" .SS "Minimal mrtg.cfg" .IX Subsection "Minimal mrtg.cfg" .Vb 5 \& WorkDir: /usr/tardis/pub/www/stats/mrtg \& Target[r1]: 2:public@myrouter.somplace.edu \& MaxBytes[r1]: 8000 \& Title[r1]: Traffic Analysis ISDN \& PageTop[r1]:

      Stats for our ISDN Line

      .Ve .SS "Cfg for several Routers." .IX Subsection "Cfg for several Routers." .Vb 6 \& WorkDir: /usr/tardis/pub/www/stats/mrtg \& Title[^]: Traffic Analysis for \& PageTop[^]:

      Stats for \& PageTop[$]: Contact The Chief if you notice anybody
      \& MaxBytes[_]: 8000 \& Options[_]: growright \& \& Title[isdn]: our ISDN Line \& PageTop[isdn]: our ISDN Line

      \& Target[isdn]: 2:public@router.somplace.edu \& \& Title[backb]: our Campus Backbone \& PageTop[backb]: our Campus Backbone \& Target[backb]: 1:public@router.somplace.edu \& MaxBytes[backb]: 1250000 \& \& # the following line removes the default prepend value \& # defined above \& \& Title[^]: \& \& Title[isdn2]: Traffic for the Backup ISDN Line \& PageTop[isdn2]: our ISDN Line \& Target[isdn2]: 3:public@router.somplace.edu .Ve .SH "AUTHOR" .IX Header "AUTHOR" Tobias Oetiker and many contributors mrtg-2.17.10/doc/mrtg-rrd.10000644000175300017510000002007214171763415014245 0ustar oetikeroep.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "MRTG-RRD 1" .TH MRTG-RRD 1 "2022-01-19" "2.17.10" "mrtg" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" mrtg\-rrd \- How to use RRDtool with MRTG .SH "SYNOPSIS" .IX Header "SYNOPSIS" After using \s-1MRTG\s0 for some time you may find some limitations, mostly in the areas of performance and graphing flexibility. These are exactly the areas addressed by RRDtool. To learn more about RRDtool check out its website on .PP .Vb 1 \& http://oss.oetiker.ch/rrdtool .Ve .SH "RRDTOOL INTEGRATION" .IX Header "RRDTOOL INTEGRATION" When using mrtg with RRDtool you are replacing \fIrateup\fR with the RRDtool perl module \fIRRDs.pm\fR. To enable RRDtool support in mrtg you have to add the line .PP .Vb 1 \& LogFormat: rrdtool .Ve .PP to your mrtg config file. .PP \&\s-1MRTG\s0 needs access to both the RRDtool perl module \fBRRDs.pm\fR and to the \&\fBrrdtool\fR executable. .PP If these two items are not installed in locations where perl can find them on its own, then you can use the following two parameters to supply the appropriate directories. .PP For the location of the \fBrrdtool\fR executable you put .PP .Vb 1 \& PathAdd: /usr/local/rrdtool/bin/ .Ve .PP or .PP .Vb 1 \& PathAdd: c:\errdtool\ebin .Ve .PP For the location of the perl module it would be: .PP .Vb 1 \& LibAdd: /usr/local/rrdtool/lib/perl/ .Ve .PP or .PP .Vb 1 \& LibAdd: c:\errdtool\ebin\elib\eperl .Ve .PP When you have made this modification to the configuration file, several things will happen when you run mrtg again with the new config file: .IP "1." 4 mrtg will take all your old \f(CW\*(C`.log\*(C'\fR files and \fBconvert\fR them to \f(CW\*(C`.rrd\*(C'\fR format. (The \f(CW\*(C`.log\*(C'\fR files don't get touched in the process, so if things don't work out they are still there.) .IP "2." 4 mrtg will use \fBrrdtool\fR to update its databases. These will have a new format called \fIrrd\fR which is totally different than the native \fIlog\fR format of the classic mrtg. .IP "3." 4 mrtg will \fBnot\fR create any webpages of graphs anymore. It will only query the routers for traffic information and update its \fIrrd\fR databases. .PP The advantage of whole thing is that the mrtg will become \fBmuch\fR faster. Expect the runtime to drop to 20% of the previous value. (I would like to get some feedback on this from folks with large installations.) .PP Mind you, though, while the logging process of RRDtool is \fBvery\fR fast, you are also gaining some time by neither creating graphs nor updating webpages. The idea behind this is that it is more efficient to create graphs and webpages on demand by using a cgi script. .PP At the moment there is no \fBofficial\fR script to do this, but two contributors have created such scripts: .IP "One4All aka 14all.cgi" 4 .IX Item "One4All aka 14all.cgi" This was the first program to take over the webpage creation and graphing task. It has been developed by Rainer Bawidamann rainer.bawidamann@web.de. You can find a copy on Rainers website: http://my14all.sourceforge.net/ The program comes with its own documentation .IP "\fBrouters2.cgi\fR" 4 .IX Item "routers2.cgi" This is another \s-1CGI\s0 frontend for mrtg running with rrdtool. The main difference between this and 14all is that the web pages it creates are much more stylish than the ones from mrtg, plus they support User Defined summary graphs and different levels of Authentication and Authorisation. This has been written by Steve Shipway (steve@steveshipway.org). You obtain a copy, and find a forum and demonstration system at http://www.steveshipway.org/software/ The program comes with its own installation instructions and install script. .IP "\fBmrtg-rrd\fR" 4 .IX Item "mrtg-rrd" The mrtg-rrd script is a CGI/FastCGI application by Jan \*(L"Yenya\*(R" Kasprzak for displaying \s-1MRTG\s0 graphs from data in the RRDtool format. It is an intended replacement for the 14all.cgi script. It can make your monitoring system faster because \s-1MRTG\s0 does not have to generate all the \s-1PNG\s0 files with graphs every 5 minutes or so. Instead of this the graphs are generated on-demand when the user wants to see them. http://www.fi.muni.cz/~kas/mrtg\-rrd/ .SH "FUTURE" .IX Header "FUTURE" Just as a side note: \s-1MRTG\-3\s0 will be based entirely on rrdtool technology. But don't wait for it ... get going \fBnow\fR! .SH "AUTHOR" .IX Header "AUTHOR" Tobias Oetiker mrtg-2.17.10/doc/mrtg-squid.10000644000175300017510000001731414171763415014610 0ustar oetikeroep.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "MRTG-SQUID 1" .TH MRTG-SQUID 1 "2022-01-19" "2.17.10" "mrtg" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" mrtg\-squid \- using mrtg to monitor Squid .SH "DESCRIPTION" .IX Header "DESCRIPTION" Squid 2.3 knows \s-1SNMP\s0 and you can therefore use mrtg to monitor it quite easily. .PP I have made some modifications to mrtg which simplify this. My work is based on earlier modification made by: matija.grabnar@arnes.si and kostas@nlanr.net. .SH "MODIFICATIONS" .IX Header "MODIFICATIONS" I added new code for displaying correct units to the previous patches \*(L"perminute\*(R" and \*(L"perhour\*(R" (\*(L"option\*(R" tokens), which allows other measurement in addition to \*(L"persecond\*(R". .PP Then I created a new option token \*(L"dorelpercent\*(R" which allows the calculation of the percentage of IN-stream / OUT-stream on the fly and then displays it on a fixed scale from 0% to 100%. For my requirements, this does good work. Maybe someone wants a floating scale. It should not be a problem to implement it, too (but give me an option to keep my fixed scale). If IN-stream is always less than OUT-stream both lines (OUT-stream and relative percent) are always displayed on top of IN-stream bulk. Otherwise this option makes no sense. With this option you can display hitrates, errorrates (for router monitoring: rel. droprates) easily now. .PP If you use this options please consider that you need a 5th colourname/value pair in your Colours statements! .PP Due to some discussion on this list, I have implemented two tokens too: .PP \&\*(L"kilo\*(R" and \*(L"kMG\*(R" .PP \&\*(L"kilo\*(R" should contain the value of k (1000 or 1024), where 1000 is the default. .PP \&\*(L"kMG\*(R" is a comma separated list of multiplier prefixes, used instead of "\*(L", \*(R"k\*(L", \*(R"M\*(L", \*(R"G\*(L", \*(R"T" on the \s-1MRTG\s0 display. Leave the place free, if you want no prefix. .PP Also an incomplete list of OIDs for the new \s-1SQUID\s0 release is added. .PP You may need to turn on snmp_port in squid.conf to as it is disabled by default. .PP I hope you enjoy it. .SH "CONFIG EXAMPLE" .IX Header "CONFIG EXAMPLE" First load the squid mib .PP .Vb 1 \& LoadMIBs: /usr/share/squid/mib.txt .Ve .PP You can measure responsetimes in ms and display it with \s-1MRTG\s0 correctly with: .PP .Vb 2 \& kMG[measure\-ms]: m,,k,M,G,T \& short[measure\-ms]: s .Ve .PP You can display now MB/s as 1024*1024 B/s with: .PP .Vb 1 \& kilo[volume]: 1024 .Ve .PP Assuming you're not running squid's \s-1SNMP\s0 on the default snmp port, you need to include a port number in your target line: .PP .Vb 1 \& Target[proxy\-hit]: cacheHttpHits&cacheProtoClientHttpRequests:public@localhost:3401 .Ve .PP A sample config for squid: .PP .Vb 11 \& Target[proxy\-hit]: cacheHttpHits&cacheProtoClientHttpRequests:public@proxy \& Title[proxy\-hit]: HTTP Hits \& PageTop[proxy\-hit]:

      proxy Cache Statistics: HTTP Hits / Requests

      \& Suppress[proxy\-hit]: y \& LegendI[proxy\-hit]: HTTP hits \& LegendO[proxy\-hit]: HTTP requests \& Legend1[proxy\-hit]: HTTP hits \& Legend2[proxy\-hit]: HTTP requests \& YLegend[proxy\-hit]: perminute \& ShortLegend[proxy\-hit]: req/min \& Options[proxy\-hit]: nopercent, perminute, dorelpercent \& \& Target[proxy\-srvkbinout]: cacheServerInKb&cacheServerOutKb:public@proxy \& Title[proxy\-srvkbinout]: Cache Server Traffic In / Out \& PageTop[proxy\-srvkbinout]:

      Cache Statistics: Server traffic volume (In/Out)

      \& Suppress[proxy\-srvkbinout]: y \& LegendI[proxy\-srvkbinout]: Traffic In \& LegendO[proxy\-srvkbinout]: Traffic Out \& Legend1[proxy\-srvkbinout]: Traffic In \& Legend2[proxy\-srvkbinout]: Traffic Out \& YLegend[proxy\-srvkbinout]: per minute \& ShortLegend[proxy\-srvkbinout]: b/min \& kMG[proxy\-srvkbinout]: k,M,G,T \& kilo[proxy\-srvkbinout]: 1024 \& Options[proxy\-srvkbinout]: nopercent, perminute .Ve .SH "AUTHOR" .IX Header "AUTHOR" Andreas Papst Dirk-LXder Kreie Chris Chiappa mrtg-2.17.10/doc/mrtg-traffic-sum.10000644000175300017510000001501314171763416015676 0ustar oetikeroep.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "MRTG-TRAFFIC-SUM 1" .TH MRTG-TRAFFIC-SUM 1 "2021-10-08" "2.17.10" "mrtg" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" mrtg\-traffic\-sum \- Builds monthly traffic summary from mrtg log files .SH "SYNOPSIS" .IX Header "SYNOPSIS" \&\fBmrtg-traffic-sum\fR [\fIoptions\fR...] \fBconfig-file\fR .PP .Vb 8 \& \-\-man show man\-page and exit \& \-h, \-\-help display this help and exit \& \-\-version output version information and exit \& \-\-catch=regexp filter out things that match this in PageTop \& \-\-email=address email the result \& \-\-min=gigabytes minimal number of gigabites required for report \& \-\-range= Specify "current" for month\-to\-date, "previous" for last complete month \& \-\-units=[GB|MB] Display results in gigabytes (default is MB) .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" The mrtg-traffic-sum goes through the mrtg logs for the targets in the the config file specified and builds the traffic total for the last month in Giga Bytes. (Note in communications Giga is 10^9). .PP The result of this analysis can be sent via email to an address of your choice using the \fB\-\-email\fR option. .PP With the \fB\-\-catch\fR option you can specify a regular expression which will be matched against the contents of the PageTop settings. The regular expression should return a value into \f(CW$1\fR and possibly into \&\f(CW$2\fR. This will then be used as description for the appropriate traffic sum. By default the catch is set to: .PP .Vb 1 \& (?:description|port name):\es*\es*([^< ]*?[^<]*?)\es*, Keith Dunnett .SH "HISTORY" .IX Header "HISTORY" .Vb 2 \& 2002\-07\-13 to Initial Version \& 2009\-12\-38 kd New features .Ve mrtg-2.17.10/doc/mrtg-unix-guide.10000644000175300017510000003472614171763415015547 0ustar oetikeroep.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "MRTG-UNIX-GUIDE 1" .TH MRTG-UNIX-GUIDE 1 "2022-01-19" "2.17.10" "mrtg" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" mrtg\-unix\-guide \- The MRTG 2.17.10 Linux/Unix Installation Guide .SH "DESCRIPTION" .IX Header "DESCRIPTION" \&\s-1MRTG\s0 comes to you in Source Code. This means that you have to compile parts of it before you can use it on a Unix machine. These instructions help you to do so. .SH "PREPARATION" .IX Header "PREPARATION" In order to compile and use mrtg you need a C compiler and a copy of perl installed on your machine. In most cases this will already be available. In case it is not, here are some starting points. Below I'll give you a detailed run through the whole compilation process. .IP "\s-1GCC\s0" 4 .IX Item "GCC" The \s-1GNU C\s0 compiler comes preinstalled on most of the free Unices out there. For commercial derivatives you may have to download and compile it first. If you have no compiler at all there is a chicken and egg problem, but there are also precompiled versions of gcc available for most operating systems. .Sp .Vb 1 \& http://gcc.gnu.org/ .Ve .IP "Perl" 4 .IX Item "Perl" Large parts of the \s-1MRTG\s0 system are written in the Perl scripting language. Make sure there is a recent copy of perl on your machine (try perl \-v). At least version 5.005 is required for mrtg to work well. If you use \s-1SNMPV3\s0 and other new features you should use at least 5.8. .Sp You can get the latest perl from .Sp .Vb 1 \& http://www.perl.com/ .Ve .PP \&\s-1MRTG\s0 generates traffic graphs in the \s-1PNG\s0 format. To be able to do this it needs several 3rd party libraries. When compiling these libraries I urge you to make sure you compile them as \fBstatic\fR libraries. There is just much less trouble ahead if you are doing it like this. See the Instructions in the next section for inspiration. Note that many free unices have all the required libraries already in place so there is no need to install another copy. To check it is best to skip all the library instructions below and go straight into the mrtg compile. .PP If the first attempt fails and you do not get a working version of mrtg, try compiling new copies of all libraries as explained below. Do this \&\fB\s-1BEFORE\s0\fR you send email to me about problems compiling mrtg. .IP "gd" 4 .IX Item "gd" This is a basic graph drawing library created by Thomas Boutell. Note that all releases after Version 1.3 only create \&\s-1PNG\s0 images. This is because a) Thomas got into trouble because the \s-1GIF\s0 format which it used to produce uses a compression technology patented by Unisys. b) \s-1PNG\s0 is more efficient and patent free. \s-1MRTG\s0 can work with old and new version of the \s-1GD\s0 library. You can get a recent copy of \s-1GD\s0 from: .Sp .Vb 1 \& http://www.boutell.com/gd/ .Ve .IP "libpng" 4 .IX Item "libpng" Is required by gd in order to produce \s-1PNG\s0 graphics files. Get it from: .Sp .Vb 1 \& http://www.libpng.org/pub/png/libpng.html .Ve .IP "zlib" 4 .IX Item "zlib" Is needed by libpng to compress the graphics files you create. Get a copy from .Sp .Vb 1 \& http://www.gzip.org/zlib .Ve .PP And last but not least you also need mrtg itself. In case you have not yet downloaded it, you can find a copy on my website: .PP .Vb 1 \& http://oss.oetiker.ch/mrtg/pub .Ve .SH "LIBRARY COMPILATION" .IX Header "LIBRARY COMPILATION" In this section I will give you step by step instructions on how to compile the various libraries required for the compilation of mrtg. Note that these libraries may already be installed if you have a \fI*BSD\fR or \fILinux\fR system so you can skip recompiling them. The \fBwget\fR program used below is a simple web downloader. You can also enter the address into your \fBnetscape\fR if you don't have \fBwget\fR available. .PP First let's create a directory for the compilation. Note that this may already exist on your system. No problem, just use it. .PP .Vb 2 \& mkdir \-p /usr/local/src \& cd /usr/local/src .Ve .PP If you do not have zlib installed: .PP .Vb 8 \& wget http://www.zlib.net/zlib\-1.2.3.tar.gz \& gunzip \-c zlib\-*.tar.gz | tar xf \- \& rm zlib\-*.tar.gz \& mv zlib\-* zlib \& cd zlib \& ./configure \& make \& cd .. .Ve .PP If you don't have libpng installed .PP .Vb 8 \& wget ftp://ftp.simplesystems.org/pub/libpng/png/src/libpng\-1.2.40.tar.gz \& gunzip \-c libpng\-1.2.34.tar.gz | tar xf \- \& mv libpng\-* libpng \& cd libpng \& env CFLAGS="\-O3 \-fPIC" ./configure \-\-prefix=$INSTALL_DIR \& make \& rm *.so.* *.so \& cd .. .Ve .PP And now you can compile gd .PP For versions up to 1.8.4, try: .PP .Vb 5 \& wget http://www.boutell.com/gd/http/gd\-1.8.4.tar.gz \& gunzip \-c gd\-*.tar.gz |tar xf \- \& rm gd\-*.tar.gz \& mv gd\-* gd \& cd gd .Ve .PP The \e characters at the end of the following lines mean that all the following material should actually be written on a single line. .PP .Vb 6 \& perl \-i~ \-p \-e s/gd_jpeg.o//g Makefile \& make INCLUDEDIRS="\-I. \-I../zlib \-I../libpng" \e \& LIBDIRS="\-L../zlib \-L. \-L../libpng" \e \& LIBS="\-lgd \-lpng \-lz \-lm" \e \& CFLAGS="\-O \-DHAVE_LIBPNG" \& cd .. .Ve .PP For versions starting around 2.0.11, try: .PP .Vb 8 \& wget http://www.boutell.com/gd/http/gd\-2.0.33.tar.gz \& gunzip \-c gd\-2.0.33.tar.gz |tar xf \- \& mv gd\-2.0.33 gd \& cd gd \& env CPPFLAGS="\-I../zlib \-I../libpng" LDFLAGS="\-L../zlib \-L../libpng" \e \& ./configure \-\-disable\-shared \-\-without\-freetype \-\-without\-jpeg \& make \& cp .libs/* . .Ve .SH "MRTG COMPILATION" .IX Header "MRTG COMPILATION" Ok, now everything is ready for the mrtg compilation. .PP .Vb 3 \& cd /usr/local/src \& gunzip \-c mrtg\-2.17.10.tar.gz | tar xvf \- \& cd mrtg\-2.17.10 .Ve .PP If all the libraries have been preinstalled on your system you can configure mrtg by doing a simple: .PP .Vb 1 \& ./configure \-\-prefix=/usr/local/mrtg\-2 .Ve .PP Otherwise you may have to give some hints on where to find the various libraries required to compile mrtg: .PP .Vb 4 \& ./configure \-\-prefix=/usr/local/mrtg\-2 \e \& \-\-with\-gd=/usr/local/src/gd \e \& \-\-with\-z=/usr/local/src/zlib \e \& \-\-with\-png=/usr/local/src/libpng .Ve .PP If you have RRDtool available you might want to tell mrtg about it so that you can opt to use rrdtool with mrtg. Check mrtg-rrd. .PP Configure will make sure your environment is fit for building mrtg. If it finds a problem, it will tell you so and it will also tell you what to do about it. If everything is \s-1OK,\s0 you will end up with a custom Makefile for your system. Now type: .PP .Vb 1 \& make .Ve .PP This builds the rateup binary and edits all the perl pathnames in the scripts. You can now install mrtg by typing .PP .Vb 1 \& make install (requires gnu install) .Ve .PP All the software required by \s-1MRTG\s0 is now installed under the \fI/usr/local/mrtg\-2\fR subdirectory. .PP You can now safely delete the libraries we compiled above. Then again, you might want to keep them around so that you have them available when compiling the next version of mrtg. .SH "CONFIGURATION" .IX Header "CONFIGURATION" The next step is to configure mrtg for monitoring a network device. This is done by creating an \fImrtg.cfg\fR file which defines what you want to monitor. Luckily, you don't have to dive straight in and start writing your own configuration file all by yourself. Together with mrtg you also got a copy of \fBcfgmaker\fR. This is a script you can point at a router of your choice; it will create a mrtg configuration file for you. You can find the script in the \fIbin\fR subdirectory. .PP .Vb 4 \& cfgmaker \-\-global \*(AqWorkDir: /home/httpd/mrtg\*(Aq \e \& \-\-global \*(AqOptions[_]: bits,growright\*(Aq \e \& \-\-output /home/mrtg/cfg/mrtg.cfg \e \& community@router.abc.xyz .Ve .PP This example above will create an mrtg config file in \&\fI/home/mrtg/cfg\fR assuming this is a directory visible on your webserver. You can read all about cfgmaker in cfgmaker. One area you might want to look at is the possibility of using \fB\-\-ifref=ip\fR to prevent interface renumbering troubles from catching you. .PP If you want to start rolling your own mrtg configuration files, make sure you read mrtg-reference to learn all about the possible configuration options. .SH "RUNNING MRTG" .IX Header "RUNNING MRTG" Once you have created a configuration file, try the following: .PP .Vb 1 \& /usr/local/mrtg\-2/bin/mrtg /home/mrtg/cfg/mrtg.cfg .Ve .PP This will query your router and also create your first mrtg traffic graphs and webpages. When you run mrtg for the first time there will be a lot of complaints about missing log files. Don't worry, this is normal for the first 2 times you start mrtg. If it keeps complaining after this time you might want to look into the problem. .PP Starting mrtg by hand is not ideal in the long run. So when you are satisfied with the results you can automate the process of running mrtg in regular intervals (this means every 5 minutes by default). .PP You can either add mrtg to your crontab with a line like this: .PP .Vb 3 \& 0,5,10,15,20,25,30,35,40,45,50,55 * * * * \e \& /mrtg /mrtg.cfg \e \& \-\-logging /var/log/mrtg.log .Ve .PP or if you live in Linux Land the line may look like this if you are using \f(CW\*(C`crontab \-e\*(C'\fR .PP .Vb 2 \& */5 * * * * /mrtg /mrtg.cfg \e \& \-\-logging /var/log/mrtg.log .Ve .PP or like this if you use \fI/etc/crontab\fR .PP .Vb 2 \& */5 * * * * mrtg\-user /mrtg /mrtg.cfg \e \& \-\-logging /var/log/mrtg.log .Ve .PP You can also run mrtg as a daemon process by adding the line .PP .Vb 1 \& RunAsDaemon: Yes .Ve .PP to your mrtg configuration file and then creating a startup script in your system startup sequence. Unfortunately, adding startup scripts differs widely amongst different unix systems. The modern ones normally have a directory called \fI/etc/init.d\fR or \fI/etc/rc.d/init.d\fR where you put scripts which starts the process you want to run when the system boots. Further you must create a symbolic link in \fI/etc/rc3.d\fR or \&\fI/etc/rc.d/rc?.d\fR called \fIS65mrtg\fR (this is just a sample name \&... it is just important that it starts with S followed by a two digit number). If you are not sure about this, make sure you consult the documentation of your system to make sure you get this right. .PP A \fBminimal\fR script to put into \fIinit.d\fR might look like this: .PP .Vb 3 \& #! /bin/sh \& cd /usr/local/mrtg\-2.17.10/bin && ./mrtg \-\-user=mrtg\-user \e \& /home/httpd/mrtg/mrtg.cfg \-\-logging /var/log/mrtg.log .Ve .PP Note that this will only work with \fBRunAsDaemon: Yes\fR in your mrtg.cfg file. .SH "AUTHOR" .IX Header "AUTHOR" Tobias Oetiker mrtg-2.17.10/doc/mrtg-webserver.10000644000175300017510000001331314171763415015462 0ustar oetikeroep.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "MRTG-WEBSERVER 1" .TH MRTG-WEBSERVER 1 "2022-01-19" "2.17.10" "mrtg" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" mrtg\-webserver \- hints for web server configuration .SH "SYNOPSIS" .IX Header "SYNOPSIS" If you want people to actually see the results of your network monitoring efforts you will need a webserver. .PP This document lists some configuration hints for webservers. Contributions welcome. .SH "APACHE" .IX Header "APACHE" .SS "Configuring mod_expire" .IX Subsection "Configuring mod_expire" A big issue with mrtg monitoring data is the expiry time. All these nice graphs you can create are only valid for a short time. If you do not take special action some webbrowsers will not notice this and you may end up with people seeing old data because of caching issues. .PP The apache module mod_expire allows you to setup special expiry properties for individual file. .PP Here is an example for how this may look for an mrtg web directory. The configuration directives can be stored into a \fI.htaccess\fR file. .PP .Vb 11 \& ############################################################ \& # Example .htaccess for use with apache\-1.2 and mod_expire. \& # (mod_expire come with apache\-1.2 but you have to explicitly \& # activate it when compiling the httpd ...) \& ############################################################# \& # \& \& ExpiresActive On # enable expirations \& # five minutes \& ExpiresDefault M300 \& \& \& \& ExpiresActive On \& ExpiresDefault M1800 \& \& \& \& ExpiresActive On \& ExpiresDefault M7200 \& \& \& \& ExpiresActive On \& ExpiresDefault M86400 \& \& \& \& ExpiresActive On \& ExpiresDefault M300 \& \& \& # index.html is not automatically generated \& \& ExpiresActive Off \& .Ve .SH "AUTHOR" .IX Header "AUTHOR" Unknown mrtg-2.17.10/doc/rateup.10000644000175300017510000001253314171763416014013 0ustar oetikeroep.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "RATEUP 1" .TH RATEUP 1 "2022-01-19" "2.17.10" "mrtg" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" rateup \- tool to generate images for MRTG .SH "SYNOPSIS" .IX Header "SYNOPSIS" rateup \-f .PP rateup directory basename [sampletime] [t sampletime] [\-(t)ransparent] [\-(b)order] [u|a|g|h|m in out abs_max] [i/p file maxvi maxvo maxx maxy growright step bits] .SH "DESCRIPTION" .IX Header "DESCRIPTION" rateup is a fast add-on to the great \s-1MRTG\s0 Traffic monitor. It makes the database file updates much faster, and creates the graphic image files, ready for processing by \s-1PPMTOGIF.\s0 It also reduces memory requirements by a factor of 10, and increases the speed of updates by a factor of at least 10. This makes it feasible to run mrtg every 5 minutes. .PP rateup attempts to compensate for missed updates by repeating the last sample, and also tries to catch bad update times. The .log file stores real history every five minutes for 31 hours, then 'compresses' the history into 30 minute samples for a week, then 2\-hour samples for 31 days, then daily samples for two years. This ensures that the log files don't grow in size. .PP The log files are a slightly different format, but convert.perl will fix that for you. .SH "AUTHOR" .IX Header "AUTHOR" Dave Rand , Tobias Oetiker , Alexandre Steinberg .SH "SEE ALSO" .IX Header "SEE ALSO" \&\fBmrtg\fR\|(1), \fBmrtg\-reference\fR\|(1), \fBmrtg\-logfile\fR\|(1), \fBmrtg\-traffic\-sum\fR\|(1), \fBcfgmaker\fR\|(1), \fBindexmaker\fR\|(1) mrtg-2.17.10/doc/cfgmaker.txt0000644000175300017510000017456614171763417014771 0ustar oetikeroepCFGMAKER(1) mrtg CFGMAKER(1) NNAAMMEE cfgmaker - Creates mrtg.cfg files (for mrtg-2.17.10) SSYYNNOOPPSSIISS cfgmaker [options] [community@]router [[options] [community@]router ...] OOPPTTIIOONNSS --ifref=name interface references by Interface Name (default) --ifref=ip ... by Ip Address --ifref=eth ... by Ethernet Number --ifref=descr ... by Interface Description --ifref=nr ... by Interface Number --ifref=type ... by Interface Type You may also use multiple options separated by commas, in which case the first available one is used: e.g. --ifref=ip,name,nr --ifdesc=nr interface description uses Interface Number (default) --ifdesc=ip ... uses Ip Address --ifdesc=eth ... uses Ethernet Number --ifdesc=descr ... uses Interface Description --ifdesc=name ... uses Interface Name --ifdesc=catname ... uses CatOS Interface Name --ifdesc=ppname ... uses Passport Port Name --ifdesc=alias ... uses Interface Alias --ifdesc=type ... uses Interface Type You may also use multiple options separated by commas, in which case the first available one is used: e.g. --ifdesc=catname,ppname,descr,alias,ip,name,nr --if-filter=f Test every interface against filter f to decide whether or not to include that interface into the collection. Currently f is being evaluated as a Perl expression and it's truth value is used to reject or accept the interface. (Experimental, under development, might change) --if-template=templatefile Replace the normal target entries for the interfaces with an entry as specified by the contents in the file templatefile. The file is supposed to contain Perl code to be executed to generate the lines for the target in the configuration file. (Experimental, under development, might change) --host-template=templatefile In addition to creating targets for a host's interfaces do also create targets for the host itself as specified by the contents in the file templatefile. The file is supposed to contain Perl code to be executed to generate the lines for the host related targets (such as CPU, ping response time measurements etc.) in the config- uration file. (Experimental, under development, might change) --global "x: a" add global config entries --nodefaultglobal do not include default global settings --no-down do not look at admin or opr status of interfaces --show-op-down show interfaces which are operatively down --zero-speed=spd use this speed in bits-per-second as the interface speed for all interfaces that return a speed of 0 via ifSpeed/ifHighSpeed. 100Mbps = 100000000 --subdirs=format give each router its own subdirectory, naming each per "format", in which HOSTNAME and SNMPNAME will be replaced by the values of those items -- for instance, --subdirs=HOSTNAME or --subdirs="HOSTNAME (SNMPNAME)" --noreversedns do not reverse lookup ip numbers --community=cmty Set the default community string to "cmty" instead of "public". --enable-ipv6 Enable IPv6 support, if the required libraries are present. Numeric IPv6 addresses must be enclosed in square brackets, e.g. public@[2001:760:4::1]:161 --use-16bit Use 16bit SNMP request IDs to query all routers. --snmp-options=:[][:[][:[][:[][:]]]] Specify default SNMP options to be appended to all routers following. Individual fields can be empty. Routers following might override some or all of the options given to --snmp-options. --dns-domain=domain Specifies a domain to append to the name of all routers following. --nointerfaces Don't do generate any configuration lines for interfaces, skip the step of gathering interface information and don't run any interface template code. --interfaces Generate configuration lines for interfaces (this is the default). The main purpose of this option is to negate an --nointerfaces appearing earlier on the command line. --help brief help message --man full documentation --version print the version of cfgmaker --output=file output filename default is STDOUT DDEESSCCRRIIPPTTIIOONN CCffggmmaakkeerr creates MRTG configuration files based on information pulled from a router or another SNMP manageable device. [_c_o_m_m_u_n_i_t_y@@]_r_o_u_t_e_r _C_o_m_m_u_n_i_t_y is the community name of the device you want to create a configuration for. If not specified, it defaults to 'ppuubblliicc'; you might want to try this first if you do not know the community name of a device. If you are using the wrong community name you will get no response from the device. _R_o_u_t_e_r is the DNS name or the IP number of an SNMP-manageable device. Following the name you can specify 6 further options separated by colons. The full syntax looks like this: rroouutteerr[:[pprrtt][:[ttmmoouutt][:[rreettrr][:[bbaacckkooffff][:vveerrss]]]]] Of special interest may be the last parameter, vveerrss. If you set this to '2' then your device will be queried with SNMP version 2 requests. This allows you to poll the 64 bit traffic counters in the device and will thus work much better with fast interfaces (no more counter overrun). Note that the order in which the routers are specified on the command line do matter as the same order is used when the configuration file is generated. The first specified router has it's configuration lines generated first, followed by the lines belonging to the next router and so on. Note that the first line of the generated cfg file will contain all the commandline options you used for generating it. This is to allow for the easy 'regeneration' in case you want to add newhosts or make some other global change. CCoonnffiigguurraattiioonn Except for the ----oouuttppuutt and ----gglloobbaall options, all options affect only the routers following them on the command line. If an option specified earlier on the command line reappears later on the command line with another value, the new value overrides the old value as far as remaining routers are concerned. This way options might be tailored for groups of routers or for individual routers. See ----oouuttppuutt and ----gglloobbaall for how their behaviour is affected by where or how many times they appear on the command line. See the EExxaammpplleess below on how to set an option differently for multiple routers. ----hheellpp Print a brief help message and exit. ----mmaann Prints the manual page and exits. ----vveerrssiioonn Print the version of cfgmaker. This should match the version of MRTG for which config files are being created. ----iiffrreeff nnrr|iipp|eetthh|ddeessccrr|nnaammee Select the interface identification method. Default is nnrr which identifies the router interfaces by their number. Unfortunately the interface numbering scheme in an SNMP tree can change. Some routers change their numbering when new interfaces are added, others change their numbering every full moon just for fun. To work around this sad problem MRTG can identify interfaces by 4 other properties. None of these works for all interfaces, but you should be able to find one which does fine for you. Note that especially ethernet addresses can be problematic as some routers have the same ethernet address on most of their interface cards. Select iipp to identify the interface by its IP number. Use eetthh to use the ethernet address for identification. Use ddeessccrr to use the Interface description. Or use nnaammee to use the Interface name. You can specify multiple properties if you wish, separated by commas. In this case, cfgmaker will use the first item in the list which can provide unique identification. This allows you to specify, for example, to use IP address and to use ifName if this is not defined: --ifref ip,name If your chosen method does not allow unique interface identification on the device you are querying, ccffggmmaakkeerr will tell you about it. ----iiffddeesscc nnrr|iipp|eetthh|ddeessccrr|nnaammee|ttyyppee|aalliiaass Select what to use as the description of the interface. The description appears in the "Title[]" property for the target as well as the text header in the HTML code defined in the target's "PageTop[]". Default is to use nnrr which is just the interface number which isn't always useful to the viewer of the graphs. There are 6 other properties which could be used. Use iipp if you want to use the interface's IP-address. Use eetthh if you want to use the interface's ethernet address. If you want a better description, you can use either ddeessccrr, nnaammee or aalliiaass. Exactly what each of these do varies between different equipment so you might need to experiment. For instance, for a serial interface on a Cisco router running IOS using nnaammee might result in "S0" being the interface description , ddeessccrr might result in "Serial0" and aalliiaass might result in "Link to HQ" (provided that is what is used as the interface's "description" in the router's configuration). Finally, if you want to describe the interface by it's Btype (i.e "ethernetCSMA", "propPointtoPoint" etc) you can use ttyyppee. You can specify multiple properties if you wish, separated by commas. In this case, cfgmaker will use the first item in the list which is available for this interface. This allows you to specify, for example, to use any of the different aliases in order of preference. ----iiff--ffiilltteerr 'ffiilltteerr--eexxpprreessssiioonn' First of all, this is under some development and is experimental. Use this if you want to have better control over what interfaces gets included into the configuration. The ffiilltteerr--eexxpprreessssiioonn is evaluated as a piece of Perl code and is expected to return a truth value. If true, include the interface and if false, exclude the interface. For a further discussion on how these filters work, see the section "Details on Filters" below. ----iiff--tteemmppllaattee tteemmppllaattee--ffiillee First of all, this is under some development and is experimental. Use this if you want to control what the line for each target should look like in the configuration file. The contents of the file tteemmppllaattee--ffiillee will be evaluated as a Perl program which generates the lines using certain variables for input and output. For a further discussion on how these templates work, see the section "Details on Templates" below. ----hhoosstt--tteemmppllaattee tteemmppllaattee--ffiillee First of all, this is under some development and is experimental. Use this if you want to have some extra targets related to the host itself such as CPU utilization, ping response time to the host, number of busy modems etc. The contents of the file tteemmppllaattee--ffiillee will be evaluated once per host as a Perl program which generates the lines using certain variables for input and output. For a further discussion on how these templates work, see the section "Details on Templates" below. ----ccoommmmuunniittyy ccoommmmuunniittyy--ssttrriinngg Use this to set the community for the routers following on the command line to ccoommmmuunniittyy--ssttrriinngg. Individual routers might override this community string by using the syntax ccoommmmuunniittyy@@rroouutteerr. ----eennaabbllee--iippvv66 This option enables IPv6 support. It requires the appropriate perl modules; if they are not found then IPv6 is disabled (see the ipv6 documentation). cfgmaker will use IPv6 or IPv4 depending on the target. If the target is a numeric address, the protocol depends on the type of address. If the target is a hostname, cfgmaker will try to resolve the name first to an IPv6 address then to an IPv4 address. IPv6 numeric addresses must be specified between square braces. For example: cfgmaker --enable-ipv6 [2001:760:4::1]:165:::2 If the target has both an IPv6 address and an IPv4 address with the same hostname, cfgmaker first queries the target using IPv6 and falls back to IPv4 if it fails. This is useful for targets which don't support SNMP over IPv6. ----uussee--1166bbiitt This option forces the use of 16bit SNMP request IDs. Some broken SNMP agents do not accept 32bit request IDs. Try to avoid this option as much as possible, complain to your agent vendor instead. ----ssnnmmpp--ooppttiioonnss :[ppoorrtt][:[ttiimmeeoouutt][:[rreettrriieess][:[bbaacckkooffff][:vveerrssiioonn]]]] Use this to set the default SNMP options for all routers following on the command line. Individual values might be omitted as well as trailing colons. Note that routers might override individual (or all) values specified by ----ssnnmmpp--ooppttiioonnss by using the syntax rroouutteerr[:[ppoorrtt][:[ttiimmeeoouutt][:[rreettrriieess][:[bbaacckkooffff][:vveerrssiioonn]]]]] ----gglloobbaall ""_b_l_a_: _a_b_c"" Use this to add global options to the generated config file. You can call ----gglloobbaall several times to add multiple options. The line will appear in the configuration just before the config for the next router appearing on the command line. --global "workdir: /home/mrtg" If you want some default Options you might want to put --global "options[_]: growright,bits" Specifying ----gglloobbaall after the last router on the command line will create a line in the configuration file which will appear after all the routers. ----nnoorreevveerrsseeddnnss Do not try to reverse lookup IP numbers ... a must for DNS free environments. ----nnoo--ddoowwnn Normally cfgmaker will not include interfaces which are marked anything but administratively and operationally UP. With this switch you get them all. ----sshhooww--oopp--ddoowwnn Include interfaces which are operatively down. ----zzeerroo--ssppeeeedd _s_p_e_e_d Assign this speed in bits-per-second to all interfaces which return 0 for ifSpeed and ifHighSpeed. Some switches, notably Foundry equipment, return a speed of zero for some interfaces. For example, to have all interfaces reporting zero set to 100Mbps, use --zero-speed=100000000. ----ssuubbddiirrss _f_o_r_m_a_t Give each router its own subdirectory for the HTML and graphics (or .rrd) files. The directory name is the given _f_o_r_m_a_t string with a couple of pattern replacements. The string "HOSTNAME" will be replaced by the hostname of the router (however you specified it on the ccffggmmaakkeerr commandline -- it may be an actual hostname or just an IP address), and "SNMPNAME" will be replaced with the device's idea of its own name (the same name that appears on the right side of the "Title" lines). For instance, a call like: cfgmaker --subdirs=HOSTNAME__SNMPNAME public@10.10.0.18 would result in the generation of lines looking something like: Directory[10.10.0.18_1]: 10.10.0.18__fp2200-bothrip-1.3 ----oouuttppuutt _f_i_l_e Write the output from ccffggmmaakkeerr into the file _f_i_l_e. The default is to use "STDOUT". ----oouuttppuutt is expected to appear only once on the command line. If used multiple times, the file specified by the last ----oouuttppuutt will be used. ----nnooiinntteerrffaacceess Don't generate configuration lines for interfaces. This makes cfgmaker skip all steps related to interfaces which means it will not do any polling of the router to retrieve interface information which speeds up the execution of cfgmaker and it will neither run any interface templates. ----iinntteerrffaacceess This makes cfgmaker generate configuration lines for interfaces (the default behaviour). The main usage of this option is to negate an --nointerfaces appearing earlier on the command line. SSNNMMPP VV33 OOppttiioonnss CCffggmmaakkeerr supports SNMP V3 using the NNeett::SSNNMMPP perl module. There are optional parameters affecting SNMP operation. --enablesnmpv3 {yes|no} The ----eennaabblleessnnmmppvv33 option is an optional flag to check for the presence of the NNeett::::SSNNMMPP libraries. CCffggmmaakkeerr will try to determine whether this flag is required and will set the values automatically. _S_N_M_P_v_3 _A_r_g_u_m_e_n_t_s A SNMP context is a collection of management information accessible by a SNMP entity. An item of management information may exist in more than one context and a SNMP entity potentially has access to many contexts. The combination of a contextEngineID and a contextName unambiguously identifies a context within an administrative domain. In a SNMPv3 message, the contextEngineID and contextName are included as part of the scopedPDU. All methods that generate a SNMP message optionally take a ----ccoonntteexxtteennggiinneeiidd and ----ccoonntteexxttnnaammee argument to configure these fields. Context Engine ID The ----ccoonntteexxtteennggiinneeiidd argument expects a hexadecimal string representing the desired contextEngineID. The string must be 10 to 64 characters (5 to 32 octets) long and can be prefixed with an optional "0x". Once the ----ccoonntteexxtteennggiinneeiidd is specified it stays with the object until it is changed again or reset to default by passing in the undefined value. By default, the contextEngineID is set to match the authoritativeEngineID of the authoritative SNMP engine. Context Name The contextName is passed as a string which must be 0 to 32 octets in length using the ----ccoonntteexxttnnaammee argument. The contextName stays with the object until it is changed. The contextName defaults to an empty string which represents the "default" context. _U_s_e_r_-_b_a_s_e_d _S_e_c_u_r_i_t_y _M_o_d_e_l _A_r_g_u_m_e_n_t_s The User-based Security Model (USM) used by SNMPv3 requires that a securityName be specified using the ----uusseerrnnaammee argument. The creation of a Net::SNMP object with the version set to SNMPv3 will fail if the ----uusseerrnnaammee argument is not present. The ----uusseerrnnaammee argument expects a string 1 to 32 octets in length. Different levels of security are allowed by the User-based Security Model which address authentication and privacy concerns. A SNMPv3 target will derive the security level (securityLevel) based on which of the following arguments are specified. By default a securityLevel of 'noAuthNoPriv' is assumed. If the ----aauutthhkkeeyy or ----aauutthhppaasssswwoorrdd arguments are specified, the securityLevel becomes 'authNoPriv'. The ----aauutthhppaasssswwoorrdd argument expects a string which is at least 1 octet in length. Optionally, the ----aauutthhkkeeyy argument can be used so that a plain text password does not have to be specified in a script. The ----aauutthhkkeeyy argument expects a hexadecimal string produced by localizing the password with the authoritativeEngineID for the specific destination device. The "snmpkey" utility included with the Net::SNMP distribution can be used to create the hexadecimal string (see snmpkey). Two different hash algorithms are defined by SNMPv3 which can be used by the Security Model for authentication. These algorithms are HMAC-MD5-96 "MD5" (RFC 1321) and HMAC-SHA-96 "SHA-1" (NIST FIPS PUB 180-1). The default algorithm used by the module is HMAC-MD5-96. This behavior can be changed by using the ----aauutthhpprroottooccooll argument. This argument expects either the string 'md5' or 'sha' to be passed to modify the hash algorithm. By specifying the arguments ----pprriivvkkeeyy or ----pprriivvppaasssswwoorrdd the securityLevel associated with the object becomes 'authPriv'. According to SNMPv3, privacy requires the use of authentication. Therefore, if either of these two arguments are present and the ----aauutthhkkeeyy or ----aauutthhppaasssswwoorrdd arguments are missing, the creation of the object fails. The ----pprriivvkkeeyy and ----pprriivvppaasssswwoorrdd arguments expect the same input as the ----aauutthhkkeeyy and ----aauutthhppaasssswwoorrdd arguments respectively. The User-based Security Model described in RFC 3414 defines a single encryption protocol to be used for privacy. This protocol, CBC-DES "DES" (NIST FIPS PUB 46-1), is used by default or if the string 'des' is passed to the ----pprriivvpprroottooccooll argument. By working with the Extended Security Options Consortium http://www.snmp.com/eso/, the module also supports additional protocols which have been defined in draft specifications. The draft http://www.snmp.com/eso/draft-reeder-snmpv3-usm-3desede-00.txt defines the support of CBC-3DES-EDE "Triple-DES" (NIST FIPS 46-3) in the User- based Security Model. This protocol can be selected using the ----pprriivvpprroottooccooll argument with the string '3desede'. The draft http://www.snmp.com/eso/draft-blumenthal-aes-usm-04.txt describes the use of CFB128-AES-128/192/256 "AES" (NIST FIPS PUB 197) in the USM. The three AES encryption protocols, differentiated by their key sizes, can be selected by passing 'aescfb128', 'aescfb192', or 'aescfb256' to the --pprriivvpprroottooccooll argument. DDeettaaiillss oonn FFiilltteerrss The purpose of the filters is to decide which interfaces to accept and which interfaces to reject. This decision is done for each interface by evaluating the filter expression as a piece of Perl code and investigating the result of the evaluation. If true, accept the interface otherwise reject it. When working with filters, remember that Perl has it's own idea of what truth and false is. The empty string "" and the string "0" are false, all other strings are true. This further implies that any integer value of 0 is false as well as any undef value. It also implies that all references are considered true. As the filter is evaluated as a Perl expression, several useful constructs in Perl are worth mentioning: Expressions might be grouped by using parentheses "()". Expressions might be combined using boolean operators such as the following: "aanndd" (equivalent with "&&&&") Boolean "and" of the two expressions, is only true if both expressions are true. Example: _e_x_p_r_e_s_s_i_o_n_1 aanndd _e_x_p_r_e_s_s_i_o_n_2 "oorr" (equivalent with "||||") Boolean "or" of the two expressions, is true if either or both expressions are true. Example: _e_x_p_r_e_s_s_i_o_n_1 oorr _e_x_p_r_e_s_s_i_o_n_2 "nnoott" (equivalent with "!!") Boolean negation of a single expression. Example: nnoott _e_x_p_r_e_s_s_i_o_n . Yet another example: !!_e_x_p_r_e_s_s_i_o_n (For more details on this I recommend a book on Perl) _P_r_e_d_e_f_i_n_e_d _F_i_l_t_e_r _V_a_r_i_a_b_l_e_s To facilitate, there are a number of predefined values available to use in the filter. Note that these variables are also available when templates interfaces are evaluated (but not host templates). Caveat: All these variables' names begin with a dollar sign ($), which is a syntactic requirement for scalar variables in Perl. The danger here is that the dollar sign in many shells is an active character (often used for shell variables exactly as in Perl variables) so it is important to ensure that the Perl expression isn't evaluated by the command line shell as shell code before being passed to cfgmaker as command line arguments. In shells like Bourne shell, ksh shell or bash shell, placing the entire expression within single quotes will avoid such accidental evaluation: '--if-filter=($default_iftype && $if_admin)' $$iiff__ttyyppee This is an integer specifying the interface type as per the SNMP standards and as reported by the polled device. A complete list of interface types would be impractical for this document , but there are a number predefined variables below. Normally, cfgmaker puts in the target's PageTop this iftype value within parenthesis after the name of the interface type. (e.g "propPointToPointSerial (22)"). Here's a list of some of the most common interface types by number: 6 ethernetCsmacd 7 iso88023Csmacd 9 iso88025TokenRing 15 fddi 19 E1 20 basicISDN 21 primaryISDN 22 propPointToPointSerial 23 ppp 24 softwareLoopback 30 ds3 32 frame-relay 33 rs232 37 atm 39 sonet 44 frameRelayService 46 hssi 49 aal5 53 propVirtual 62 Fast Ethernet (100BaseT) 63 ISDN & X.25 69 Full Duplex Fast Ethernet (100BaseFX) 94 Asymmetric Digital Subscriber Loop (ADSL) 117 Gigabit Ethernet 134 ATM Sub Interface $$ddeeffaauulltt True if and only if cfgmaker normally should accepted the interface based on the interfaces administrative and operational state (taking the flags ----nnoo--ddoowwnn and ----sshhooww--oopp--ddoowwnn into account) and it's type (and a few other things). $$ddeeffaauulltt__iiffssttaattee True if and only if cfgmaker would have accepted the interface based on it's operational and administrative states (also taking into account the presence of the flags ----nnoo--ddoowwnn and ----sshhooww--oopp--ddoowwnn). $$ddeeffaauulltt__iiffttyyppee True if and only if cfgmaker would have accepted the interface based on it's type (and a few type specific details in addition). $$iiff__aaddmmiinn True if and only if the interface is in an administrative up state. $$iiff__ooppeerr True if and only if the interface is in an operational up state. A number of variables are also predefined to easily decide if an interface belong to a certain category or not. Below is all those variables listed together with which if_type numbers each variable will be true for. Note that some variables refer to other variables as well. $$iiff__iiss__eetthheerrnneett True for ethernet interfaces (nr 6, 7, 26, 62, 69 and 117). $$iiff__iiss__iissddnn True for various ISDN interface types (nr 20, 21, 63, 75, 76 and 77) $$iiff__iiss__ddiiaalluupp True for dial-up interfaces such as PPP as well as ISDN. (nr 23, 81, 82 and 108 in addition to the numbers of $$iiff__iiss__iissddnn). $$iiff__iiss__aattmm True for miscellaneous ATM related interface types (nr 37, 49, 107, 105, 106, 114 and 134). $$iiff__iiss__wwaann True for WAN interfaces point to point, Frame Relay and High Speed Serial ( 22,32,44,46) $$iiff__iiss__llaann True for LAN interfaces (8, 9, 11, 15, 26, 55, 59, 60 and 115 in addition to the numbers of $$iiff__iiss__eetthheerrnneett). $$iiff__iiss__ddssll True for ADSL, RDSL, HDSL and SDSL (nr 94, 95, 96, 97) $$iiff__iiss__llooooppbbaacckk True for software loopback interfaces (nr 24) $$iiff__iiss__cciissccoovvllaann True for Cisco VLAN interfaces (interfaces with the word Vlan or VLAN in their ifdescs) $$iiff__vvllaann__iidd Returns the vlan id associated with a specific port on Cisco Catalyst switches under both Catalyst OS and IOS, and 3Com switches. If it is not a vlan interface, will return undef. $$iiff__cciissccoo__ttrruunnkk Returns the trunking state of a specific port on Cisco Catalyst switches under both Catalyst OS and IOS. Returns "1" if the interface is a trunk, undef otherwise. $$iiff__MMTTUU Returns the Maximum Transfer Unit associated with a specific port. Besides that, you can also use the variables defined for templates below. Further, all the variables available in cfgmaker is at the scripts disposal even if the use of such features is discouraged. More "shortcuts" in the form of variables and functions will be made available in the future instead. _E_x_a_m_p_l_e_s _o_n _F_i_l_t_e_r_s The following filter will not affect which interfaces gets included or excluded, it will make cfgmaker behave as normally. '--if-filter=$default' The following filter will make cfgmaker exclude PPP (23) interfaces: '--if-filter=$default && $if_type!=23' The following filter will make cfgmaker behave as usual except that it will consider the operational state of an interface irrelevant but still reject all interfaces which are administratively down. '--if-filter=$if_admin && $default_iftype' DDeettaaiillss oonn TTeemmppllaatteess The contents of the template files are evaluated as a Perl program. A number or Perl variables are available for the program to read and others are used to be written to. As quite a few of the predefined variables has values which are are supposed to be used in HTML code some of them have an "HTML-escaped" variant, e.g $html_syslocation is the HTML escaped variant of $syslocation. The HTML escaping means that the chars "<", ">" and "&" are replaced by "<", ">" and "&" and that newlines embedded in the string are prepended with "
      " and appended with a space character (if a newline is last in the string it is not touched). _W_r_i_t_a_b_l_e _T_e_m_p_l_a_t_e _V_a_r_i_a_b_l_e_s These are the variables available to store the configuration lines in. Some of them are initialized prior to the evaluation of the template but such content normally is comments for inclusion in the final configuration file so those variables might be reset to the empty string in the template code to eliminate the comments. The other way around is also possible, the contents of these variables might be extended with further information for various reasons such as debugging etc. Once the template has been evaluated, the following happens: if the template is a interface template and the actual interface for some reason is rejected and thus needs to be commented out, all the lines in the variable $$ttaarrggeett__lliinneess are turned into comments by adding a hash mark ("#") at their beginning. Then all the variables $$hheeaadd__lliinneess, $$pprroobblleemm__lliinneess , $$ttaarrggeett__lliinneess and $$sseeppaarraattoorr__lliinneess are concatenated together to form the lines to add to the configuration file. $$ttaarrggeett__lliinneess This variable is the placeholder for the configuration lines created by the template. $$ttaarrggeett__lliinneess is predefined to be empty when the template code is evaluated. $$hheeaadd__lliinneess This variable is intended to be the placeholder for the comment line appearing just before the target in the configuration file. It is initialized with that comment line before the evaluation of the template code and if the template doesn't modify $$hheeaadd__lliinneess during evaluation, the comment will look like usual in the config file. $$pprroobblleemm__lliinneess This variable is intended to be the placholder for the comment lines describing any problems which might have been encountered when trying to add the target into the configuration. For host templates it's normally not used and for those it's predefined as the empty string. For interface templates $$pprroobblleemm__lliinneess is predefined with the error description comments which cfgmaker normally would use for rejected interfaces or as the empty string for accepted interfaces. It is possible to test against $$pprroobblleemm__lliinneess to find out if an interface will be included or rejected but this is not recommended. Test against $$iiff__ookk instead. $$sseeppaarraattoorr__lliinneess This variable is the placeholder for the string to use as the separator between the code for individual targets. The contents of this variable is put after each target (so the lines will appear after the end of the last target in the config as well). _P_r_e_d_e_f_i_n_e_d _T_e_m_p_l_a_t_e _V_a_r_i_a_b_l_e_s All the variables below are available for interface templates to use. For host templates, only those listed under "Host and System Variables" are available. For interface templates the variables listed under "Predefined Filter Variables" are also available. _H_o_s_t _a_n_d _S_y_s_t_e_m _V_a_r_i_a_b_l_e_s $$rroouutteerr__nnaammee This is the fully qualified name for the router. It is affected by the following items on the command line: the router name itself and ----ddnnss--ddoommaaiinn. $$rroouutteerr__ccoonnnneecctt This is the reference string for the router being polled. It is on the form community@router possibly followed by some snmp options. It is affected by the following items on the command line: the router name itself, ----ccoommmmuunniittyy, ----ssnnmmpp--ooppttiioonnss and ----ddnnss--ddoommaaiinn. (There's no HTML escaped variant available) $$ddiirreeccttoorryy__nnaammee This variable should contain the directory name as cfgmaker normally would use as the value for the "Directory[]" directive. The value is determined by the ----ssuubbddiirrss command line option. If ----ssuubbddiirrss isn't specified $$ddiirreeccttoorryy__nnaammee will be the empty string. (There's no HTML escaped variant available) $$ssyyssccoonnttaacctt This variable is the router's SNMP sysContact value. (HTML escaped variant: $$hhttmmll__ssyyssccoonnttaacctt) $$ssyyssnnaammee This variable is the router's SNMP sysName value. (No HTML escaped variant available) $$ssyyssllooccaattiioonn This variable is the router's SNMP sysLocation value. (HTML escaped variant: $$hhttmmll__ssyyssllooccaattiioonn) $$ssyyssddeessccrr This variable is the router's SNMP sysDescr value. It is normally not used by cfgmaker but might be useful in a template. (HTML escaped variant: $$hhttmmll__ssyyssddeessccrr) _I_n_t_e_r_f_a_c_e _T_a_r_g_e_t _R_e_l_a_t_e_d _V_a_r_i_a_b_l_e_s $$ttaarrggeett__nnaammee This is what cfgmaker normally would use as the the name of the target. The target name is what is found within the square brackets, "[]", for target directives. (There's no HTML escaped variant available) $$iiff__rreeff This the reference string for the interface. It is expected to be used in the "Target[xyz]" directive to distinguish what interface to use. The value of this variable is affected by the ----iiffrreeff command line option. It is normally used together with $$rroouutteerr__ccoonnnneecctt. (There's no HTML escaped variant available) $$iiff__ookk This variable is true if the interface is going to be included into the configuration file, otherwise false. Don't test against other variables such as $$pprroobblleemm__lliinneess to find out if an interface will be rejected or not, use this $$iiff__ookk instead. $$ddeeffaauulltt__ttaarrggeett__lliinneess This variable contains all the target lines which cfgmaker by default outputs for this interface. It's useful if you want to have the "standard target" but want to add some extra lines to it by using a template. By default cfgmaker uses the following directives for each target it generates: Target[], SetEnv[], MaxBytes[], Title[], PageTop[] and if there is any directory specified also the Directory[] directive. To facilitate the creation of templates which generates target configs which are similar to the default one, each of the above mentioned directive lines have a corresponding variable containing the line as cfgmaker would have output it by default. Note that none of these have a HTML escaped variant, text in them is HTML escaped where needed. Also note that they do not have any newline at the end. $$ddeeffaauulltt__ttaarrggeett__ddiirreeccttiivvee This variable contains the default string for the Target[] directive line. $$ddeeffaauulltt__sseetteennvv__ddiirreeccttiivvee This variable contains the default string for the SetEnv[] directive line. $$ddeeffaauulltt__ddiirreeccttoorryy__ddiirreeccttiivvee This variable contains the default string for the Directory[] directive line which means it is an empty string (with no newline) if there's no directory. $$ddeeffaauulltt__mmaaxxbbyytteess__ddiirreeccttiivvee This variable contains the default string for the MaxBytes[] directive line. $$ddeeffaauulltt__ttiittllee__ddiirreeccttiivvee This variable contains the default string for the Title[] directive line. $$ddeeffaauulltt__ppaaggeettoopp__ddiirreeccttiivvee This variable contains the default string for the PageTop[] directive lines. _I_n_t_e_r_f_a_c_e _N_e_t_w_o_r_k _C_o_n_f_i_g_u_r_a_t_i_o_n _V_a_r_i_a_b_l_e_s $$iiff__iipp This variable should contain the IP-address of the interface, if any has been assigned to it. (There's no HTML escaped variant available) $$iiffiinnddeexx This variable is the SNMP ifIndex for the interface which per definition always is an integer. (There's no HTML escaped variant available) $$iiff__iinnddeexx Equivalent with $$iiffiinnddeexx. $$iiff__eetthh Contains the ethernet address of the interface, if any. (There's no HTML escaped variant available) $$iiff__ssppeeeedd This variable is the speed in bytes/second (with prefixes). (There's no HTML escaped variant available) $$iiff__ssppeeeedd__ssttrr This variable is a cooked speed description which is either in bits or bytes depending on whether or not the bits option is active and also with the proper prefix for the speed (k, M, G etc). (No HTML escaped variant available) $$iiff__ttyyppee__ddeesscc This variable is a textual description of the interface type. (HTML escaped variant: $$hhttmmll__iiff__ttyyppee__ddeesscc) $$iiff__ttyyppee__nnuumm This variable the integer value corresponding to the interface type (for a listing for the value for the more common interface types, see the section DETAILS ON FILTERS above). (No HTML escaped variant available) $$iiff__ddnnss__nnaammee This is the DNS name for the interface. (No HTML escaped variant available) _I_n_t_e_r_f_a_c_e _N_a_m_e_, _D_e_s_c_r_i_p_t_i_o_n _a_n_d _A_l_i_a_s _V_a_r_i_a_b_l_e_s It might seem confusing with both _N_a_m_e, _D_e_s_c_r_i_p_t_i_o_n and _A_l_i_a_s in this context and to some extent it is. _N_a_m_e and _D_e_s_c_r_i_p_t_i_o_n are usually supported on most equipment but how they are used varies, both between manufacturers as well as between different categories of equipment from the same manufacturer. The _A_l_i_a_s is at least supported by Cisco IOS, and that variable contains whatever is used in the IOS statement called "description" for the interface (not to be confused with the SNMP variables for _D_e_s_c_r_i_p_t_i_o_n). For better control from the command line consider $$iiff__ttiittllee__ddeesscc which contents are controlled by the ----iiff--ddeessccrr command line option. $$iiff__ssnnmmpp__ddeessccrr This variable should contain the "raw" description of the interface as determined by the SNMP polling of the router. (HTML escaped variant: $$hhttmmll__iiff__ssnnmmpp__ddeessccrr) $$iiff__ssnnmmpp__nnaammee The "raw" name for the interface as provided by SNMP polling. (HTML escaped variant: $$hhttmmll__iiff__ssnnmmpp__nnaammee) $$iiff__ssnnmmpp__aalliiaass The "raw" ifAlias for the interface as provided by SNMP polling. (HTML escaped variant: $$hhttmmll__iiff__ssnnmmpp__aalliiaass) $$iiff__cciissccoo__ddeessccrr The "raw" CiscolocIfDescr for the interface as provided by SNMP polling. (HTML escaped variant: $$hhttmmll__iiff__cciissccoo__ddeessccrr) $$iiff__ddeessccrriippttiioonn This is the "cooked" description string for the interface, taking into account the SNMP values found for the interface's RDescr, ifAlias and CiscolocIfDescr. (HTML escaped variant: $$hhttmmll__iiff__ddeessccrriippttiioonn) $$iiff__ttiittllee The full string cfgmaker by default would have used for the Title[] directive in the configuration as well as the content of the topmost H1 tag in the PageTop[]. Is composed by the contents of $$ddeesscc__pprreeffiixx, $$iiff__ttiittllee__ddeesscc and $$ssyyssnnaammee. As $$iiff__ttiittllee depends on $$iiff__ttiittllee__ddeesscc, it is possible to indirectly control $$iiff__ttiittllee by using the command line option ----iiff--ddeessccrr. (HTML escaped variant: $$hhttmmll__iiff__ttiittllee) $$iiff__ppoorrtt__nnaammee If the host is a Cisco Catalyst LAN switch, this variable is the name of that port. (No HTML escaped variant available) $$iiff__pppp__ppoorrtt__nnaammee If the host is a Nortel Passport LAN switch, this variable is the name of that port. (No HTML escaped variant available) $$ddeesscc__pprreeffiixx This variable is a prefix of the description of what the target is to use in the "Title[]" directive and in the H1 section of the "PageTop[]". Default is "Traffic analysis for ". (HTML escaped variant: $$hhttmmll__ddeesscc__pprreeffiixx) $$iiff__ttiittllee__ddeesscc This is the description of the interface normally used by cfgmaker as part of the variable $$iiff__ttiittllee. The latter is used as the full string in the "Title[]" directive and the H1 section in the PageTop[]. $$iiff__ttiittllee__ddeesscc is controlled by the command line option ----iiff--ddeessccrr which indirectly controls the contents of $$iiff__ttiittllee (HTML escaped variant: $$hhttmmll__iiff__ttiittllee__ddeesscc) _H_e_l_p _F_u_n_c_t_i_o_n_s _f_o_r _T_e_m_p_l_a_t_e_s The following functions exists to facilitate the writing of host and interface templates. hhttmmll__eessccaappee((_ss_tt_rr_ii_nn_gg)) hhttmmll__eessccaappee(()) takes a string as an argument and returns a new string where the following substitutions has been done: the chars "<", ">" and "&" are replaced by "<", ">" and "&" and that newlines embedded in the string are prepended with "
      " and appended with a space character (newlines at the end of the string are not touched). ooiidd__ppiicckk(($$rroouutteerr__ccoonnnneecctt,,$$vv33oopptt,,""ooiidd11"",,""ooiidd22""......)) This function will try to poll each of the oids specified until it is successful or has run out of oids. It will return the name of the first oid that worked or undef if it is not successful _E_x_a_m_p_l_e _T_e_m_p_l_a_t_e _F_i_l_e_s Template Example 1: Eliminating Rejected Targets From Appearing This template file generates exactly the same configuration code per interface as cfgmaker does by default, with the exception that it eliminates all lines (comments as well as config code) for an interface if the interface happens to be rejected. if(not $problem_lines) { $target_lines .= <$html_desc_prefix$html_if_title_desc -- $sysname
      ECHO $target_lines .= < ECHO $target_lines .= < ECHO $target_lines .= < ECHO $target_lines .= < ECHO $target_lines .= < ECHO } else { $head_lines=""; $problem_lines=""; $target_lines=""; $separator_lines=""; } _T_e_m_p_l_a_t_e _E_x_a_m_p_l_e _2_: _S_i_m_p_l_e_r _V_e_r_s_i_o_n _o_f _E_x_a_m_p_l_e _1 Example 1 was partly intended to demonstrate how to customize the generation of interface targets but also to provide a hint of how the variables are used in the "default" template which one could consider that cfgmaker normally uses. If you're only interested in the easiest way of entirely eliminating those reject interfaces, the template below would do the job as well by using $$ddeeffaauulltt__ttaarrggeett__lliinneess. if($if_ok) { $target_lines = $default_target_lines; } else { $head_lines=""; $problem_lines=""; $target_lines=""; $separator_lines=""; } _T_e_m_p_l_a_t_e _E_x_a_m_p_l_e _3_: _C_r_e_a_t_i_n_g _C_P_U _T_a_r_g_e_t_s _f_o_r _H_o_s_t_s Below is an example of a host template. $head_lines .= <$router_name CPU load
      System: $sysname in $html_syslocation
      Maintainer: $html_syscontact
      Description: $html_if_description
      ifType: $html_if_type_desc ($if_type_num)
      ifName: $html_if_snmp_name
      Port Name: $if_port_name
      Port Name: $if_pp_port_name
      Max Speed: $if_speed_str
      Ip: $if_ip ($if_dns_name)
      System: $router_name in $html_syslocation
      Maintainer: $html_syscontact
      Description: $html_sysdescr
      Resource: CPU.
      ECHO EEXXAAMMPPLLEESS The first example creates a config file for _r_o_u_t_e_r_._p_l_a_c_e_._x_y_z: the router has the community name _p_u_b_l_i_c. Interfaces get identified by their IP number. Two global options get added to the config file. The config file gets redirected to _m_r_t_g_._c_o_n_f. The '\' signs at the end of the line mean that this command should be written on a single line. cfgmaker --global "WorkDir: /home/tobi" \ --global "Options[_]: growright,bits" \ --ifref=ip \ public@router.place.xyz > mrtg.cfg Note: if cfgmaker is not in your path, but you are in the directory where cfgmaker is stored, you can start it with ./cfgmaker The next example creates a config file for four devices: _r_o_u_t_e_r_1_._p_l_a_c_e_._x_y_z, _r_o_u_t_e_r_2_._p_l_a_c_e_._x_y_z, _s_w_i_t_c_h_1_._p_l_a_c_e_._x_y_z and _s_w_i_t_c_h_2_._p_l_a_c_e_._x_y_z all with the community _p_u_b_l_i_c. The two routers will have ----iiffrreeff set to ddeessccrr whilst the two switches will use ----iiffrreeff set to nnaammee. Further the routers will use ----iiffddeesscc set to aalliiaass and _s_w_i_t_c_h_1_._p_l_a_c_e_._x_y_z will use ----iiffddeesscc set to ddeessccrr whilst _s_w_i_t_c_h_2_._p_l_a_c_e_._x_y_z use nnaammee instead. Finally, there will be two Options lines inserted in the configuration: One will be in the beginning, whilst the other will be inserted after the lines related to the two routers but before those lines related to the switches. cfgmaker --global "WorkDir: /home/tobi" \ --global "Options[_]: growright,bits" \ --ifref=descr \ --ifdesc=alias \ public@router1.place.xyz \ public@router2.place.xyz \ --global "Options[_]: growright" \ --ifref=name \ --ifdesc=descr \ public@switch1.place.xyz \ --ifdesc=name \ public@switch2.place.xyz > mrtg.cfg The next example demonstrates how to use the ----ccoommmmuunniittyy, ----ssnnmmpp--ooppttiioonnss and ----ddnnss--ddoommaaiinn to make the command line simpler. All the equipment will use the community _h_i_d_d_e_n, except for the ppp-server which use community _a_c_c_e_s_s. All equipment uses these SNMP options: 11ss ttiimmeeoouutt, 11 rreettrryy and SSNNMMPP vveerrssiioonn 22 (bbaacckkooffff and ppoorrtt is unspecified which means they use the default values). The exception again is the ppp-server which uses SSNNMMPP vveerrssiioonn 11. Finally, all the equipment is part of the domain _p_l_a_c_e_._x_y_z, except for the ppp-server which is part of the domain _r_e_m_o_t_e_._p_l_a_c_e_._x_y_z. Note that the latter is achieved simply by specifying the name of the ppp-server to be _p_p_p_-_s_e_r_v_e_r_._rr_ee_mm_oo_tt_ee . cfgmaker --global "WorkDir: /home/tobi" \ --global "Options[_]: growright,bits" \ --dns-domain=place.xyz \ --community=hidden \ --snmp-options=::1:1::2 \ router1 \ router2 \ router3 \ router4 \ router5 \ switch1 \ switch2 \ switch3 \ switch4 \ switch5 \ switch6 \ switch7 \ access@ppp-server.remote:::::1 > mrtg.cfg SSEEEE AALLSSOO mrtg-reference AAUUTTHHOORR Tobias Oetiker and Jakob Ilves LLIICCEENNSSEE GNU General Public License CCOOPPYYRRIIGGHHTT Cfgmaker is Copyright 2000 by Tobias Oetiker 2.17.10 2022-01-19 CFGMAKER(1) mrtg-2.17.10/doc/indexmaker.txt0000644000175300017510000002037414171763417015324 0ustar oetikeroepINDEXMAKER(1) mrtg INDEXMAKER(1) NNAAMMEE indexmaker - Creates index files for mrtg web sites (mrtg-2.17.10) SSYYNNOOPPSSIISS indexmaker [options] mrtg.cfg [other.cfg ...] OOPPTTIIOONNSS --output=filename set output filename (default: stdout) --filter title=~regexp select targets by matching regexp against titles --filter pagetop=~regexp select targets by matching regexp against pagetop --filter name=~regexp select targets by matching regexp against name --addhead=text insert this text between and --title=text set title of generated index file --subtitle=text add a subtitle to the generated index file --bodyopt=text set body tag options --headlevel=number use at top of page (default: 1) --pagetop=text insert this text between and

      ...

      --pageend=text insert this text after the main body --pagetopend=text use this text for pagetop or pageend if undefined --nolegend do not add the Mrtg legend at the end of the page --columns=number show graphs in a table with x columns (default: 2) --perhost show graphs of the same host on a row --compact try to make a vertically more compact page --optlog log the used command line in the page (default: log) --sort=title sort graphs by title --sort=name sort graphs by their name --sort=descr sort graphs by their description --sort=original leave as is (default) --enumerate add a sequence number to the title of each graph --picfirst place pictures before text (default: text first) --width=number set width of graphs (default: not set) --height=number --sidebyside place text / pictures side by side (default: above/below) --bold use bold text (default: bold) --clicktext make the text link to the inner page (like the image) --show=day pick which graph to show in the index (default) --show=week --show=month --show=year --show=none --section=h1 h1 tag from pagetop as section heading (default) --section=title title as section headings for graphs --section=name graph name as section heading --section=descr graph description as section heading --section=ifname interface name (ifName) as section heading --section=portname port name entry in pagetop as section heading --sectionhost Try to prepend the host to the section heading if missing --rrdviewer=path path to rrdviewer (default: /cgi-bin/14all.cgi) --icondir=path path to icondir --prefix=path path from the location of the index.html to the graphs --headeradd=string add string to the html page header --autoprefix try to set prefix automatically ---file=file read string argument for option from file DDEESSCCRRIIPPTTIIOONN IInnddeexxmmaakkeerr can create web pages which display the status of an array of mrtg interface status pages. ----oouuttppuutt _f_i_l_e_n_a_m_e set output filename (default: stdout) ----ffiilltteerr (ttiittllee|ppaaggeettoopp|nnaammee)(==~~|!!~~)_r_e_g_e_x_p Several filters may get set. Each filter can match against the contents of a specific section of the mrtg config file. NNaammee refers to the bit in square brackets (option[name]: bla). Depending on the match operator chosen (==~~ or !!~~) the match will be positive or negative. Note that some shells consider !! a special character. It may be necessary to type \\!!~~ instead. ----ttiittllee _t_e_x_t Set title of generated index file (default: regexp) ----bbooddyyoopptt _t_e_x_t The value of this argument gets appended to the tag. This allows you to set document colors. By default this option is set to bgcolor="#ffffff" text="#000000" link="#000000" vlink="#000000" alink="#000000" ----ccoolluummnnss _n_u_m_b_e_r Display graphs in a table with _n_u_m_b_e_r columns (default: 2) ----ssoorrtt ttiittllee|nnaammee|ddeessccrr|oorriiggiinnaall Sort the graphs in the page either by ttiittllee, by nnaammee, by interface ddeessccrription, or leave them as is. ----eennuummeerraattee Add a sequence number to the title of each graph ----wwiiddtthh _n_u_m_b_e_r Set width of graphs ----hheeiigghhtt _n_u_m_b_e_r Set the height of the graphs ----sshhooww ddaayy|wweeeekk|mmoonntthh|yyeeaarr|nnoonnee Select which graph to show in the index page. You can suppress images completely with ----sshhooww==nnoonnee. ----sseeccttiioonn hh11|ttiittllee|nnaammee|ddeessccrriippttiioonn|ppoorrttnnaammee Select what to use as the title for each graph in the page. hh11 is the H1 section from pagetop, ttiittllee is the graph title, nnaammee is the bit in square brackets (option[name]: bla), and ddeessccrr or ddeessccrriippttiioonn is the text from the Description field of the PageTop (the Cisco description text if it's available, otherwise just the interface description). ppoorrttnnaammee is the "Port Name:" from pagetop. ----sseeccttiioonnhhoosstt Extract the hostname from the target line (this does not work if the target is a mathematical expression). Prepend the hostname (and a colon) to the section if not already present. ----rrrrddvviieewweerr _p_a_t_h If you have set the LLooggFFoorrmmaatt:: rrrrddttooooll property in the mrtg.cfg file, the index will take this into account. The only thing you must tell it is the path to your grapher cgi. (default: /cgi-bin/14all.cgi) ----pprreeffiixx _p_a_t_h By default we assume that the file generated by indexmaker is stored in _W_o_r_k_D_i_r. If you want to store it somewhere else, specify how to reach _W_o_r_k_D_i_r from the place where the Index is stored. Note that you have to use '/' as path separator as this will be used in urls. Speaking of which, you can even enter a whole url. ----aauuttoopprreeffiixx _p_a_t_h Requires --output. Try to generate the prefix automatically by comparison of the path to the output file set with --output and the Htmldir set in the configuration files. Particularly useful when multiple configuration files are specified, with different Htmldir settings. ----ooppttlloogg Default is logging in the generated page the command line, suppress with --nooptlog . Useful if the commandline contains a complex --pagetop=string which could confuse simple browsers. ----ssoommeeooppttiioonn--ffiillee _f_i_l_e_n_a_m_e For any someoption which takes a _s_t_r_i_n_g as parameter you can read the string from a file by adding <-file> to the option keyword. The whole content of the file will be read and used as the _s_t_r_i_n_g. The file must exist. AAUUTTHHOORR Tobias Oetiker LLIICCEENNSSEE GNU General Public License CCOOPPYYRRIIGGHHTT 2000-2001 Tobias Oetiker 2.17.10 2022-01-19 INDEXMAKER(1) mrtg-2.17.10/doc/mrtg-contrib.txt0000644000175300017510000000503614171763417015602 0ustar oetikeroepMRTG-CONTRIB(1) mrtg MRTG-CONTRIB(1) NNAAMMEE mrtg-contrib - Contribution Guidelines for MRTG DDEESSCCRRIIPPTTIIOONN If you have written an extension to mrtg or created a bug fix, please consider contributing it to the project. As I get quite a number of contributions every week, here are a few guidelines which explain how to contribute so that I can use the contribution without too much additional work. TTrraannssllaattiioonnss MRTG messages have been translated to a number of languages but there are still many which have not been covered yet. If you want to add yours, go into the _m_r_t_g_-_2_._1_7_._1_0_/_t_r_a_n_s_l_a_t_e directory and follow the instructions given in the _R_E_A_D_M_E file. PPaattcchheess When you have created your modification or extension to mrtg and want to submit it to me, please crate a patch for the files which you have modified. Do not send entire files unless they are new. To create a patch, get hold of a copy of GNU diff (Many Unix systems will have this installed already. In the NT world you might want to get http://sources.redhat.com/cygwin/ to get all the nice GNU tools available.) and type diff --unified --ignore-space-change old-file new-file > simple.patch or if you have modified several files do diff --recursive --unified --ignore-space-change old-dir/ new-dir/ >long.patch DDooccuummeennttaattiioonn All documentation of mrtg is done with the perl PPOODD system. If you want to learn about it, type perldoc perlpod and read the instructions. If you have bugfixes or additions to the existing documents, make sure you modify the PPOODD files and not the html or txt versions. I take documentation very seriously. Whenever you create a new feature for mrtg which you want to get included in the official release, your patch must also contain modifications for the relevant ppoodd file in the _d_o_c tree or for the documentation sections of _c_f_g_m_a_k_e_r and _i_n_d_e_x_m_a_k_e_r. AADDDDRREESSSS Send your patches, translations and contributions to Tobias Oetiker AAUUTTHHOORR Tobias Oetiker 2.17.10 2022-01-19 MRTG-CONTRIB(1) mrtg-2.17.10/doc/mrtg-faq.txt0000644000175300017510000001161014171763416014703 0ustar oetikeroepMRTG-FAQ(1) mrtg MRTG-FAQ(1) NNAAMMEE mrtg-faq - How to get help if you have problems with MRTG SSYYNNOOPPSSIISS MRTG seems to raise a lot of questions. There are a number of resources apart from the documentation where you can find help for mrtg. FFAAQQ In the following sections you'll find some additional Frequently Asked Questions, with Answers. WWhhyy iiss tthheerree nnoo ""@@##$$%%"" ((mmyy nnaattiivvee llaanngguuaaggee)) vveerrssiioonn ooff MMRRTTGG?? Nobody has contributed a _@_#_$_%_._p_m_d file yet. Go into the _m_r_t_g_-_2_._1_7_._1_0_/_t_r_a_n_s_l_a_t_e directory and create your own translation file. When you are happy with it send it to me for inclusion with the next mrtg release. II nneeeedd aa ssccrriipptt ttoo mmaakkee mmrrttgg wwoorrkk wwiitthh mmyy xxyyzz ddeevviiccee.. Probably this has already been done. Check the stuff in the _m_r_t_g_-_2_._1_7_._1_0_/_c_o_n_t_r_i_b directory. There is a file called _0_0_I_N_D_E_X in that directory which tells what you can find in there. HHooww ddooeess tthhiiss SSNNMMPP tthhiinngg wwoorrkk There are many resources on the net that explain SNMP. Take a look at this article from the Linux Journal by David Guerrero http://www.david-guerrero.com/papers/snmp/ And at this rather long document from CISCO. http://www.cisco.com/univercd/cc/td/doc/cisintwk/ito_doc/snmp.htm TThhee iimmaaggeess ccrreeaatteedd bbyy MMRRTTGG llooookk vveerryy ssttrraannggee.. Remove the *-{week,day,month,year}.png files and start MRTG again. Using MRTG for the first time, you might have to do this twice. This will also help when you introduce new routers into the cfg file. WWhhaatt iiss mmyy CCoommmmuunniittyy NNaammee?? Ask the person in charge of your Router or try 'public', as this is the default Community Name. MMyy ggrraapphhss sshhooww aa ffllaatt lliinnee dduurriinngg aann oouuttaaggee.. WWhhyy ?? Well, the short answer is that when an SNMP query goes out and a response doesn't come back, MRTG has to assume something to put in the graph, and by default it assumes that the last answer we got back is probably closer to the truth than zero. This assumption is not perfect (as you have noticed). It's a trade-off that happens to fail during a total outage. If this is an unacceptable trade-off, use the uunnkknnaasszzeerroo option. You may want to know what you're trading off, so in the spirit of trade-offs, here's the long answer: The problem is that MRTG doesn't know *why* the data didn't come back, all it knows is that it didn't come back. It has to do something, and it assumes it's a stray lost packet rather than an outage. Why don't we always assume the circuit is down and use zero, which will (we think) be more nearly right? Well, it turns out that you may be taking advantage of MRTG's "assume last" behaviour without being aware of it. MRTG uses SNMP (Simple Network Management Protocol) to collect data, and SNMP uses UDP (User Datagram Protocol) to ship packets around. UDP is connectionless (not guaranteed) unlike TCP where packets are tracked and acknowledged and, if needed, retransmitted. UDP just throws packets at the network and hopes they arrive. Sometimes they don't. One likely cause of lost SNMP data is congestion; another is busy routers. Other possibilities include transient telecommunications problems, router buffer overflows (which may or may not be congestion- related), "dirty lines" (links with high error rates), and acts of God. These things happen all the time; we just don't notice because many interactive services are TCP-based and the lost packets get retransmitted automatically. In the above cases where some SNMP packets are lost but traffic is flowing, assuming zero is the wrong thing to do - you end up with a graph that looks like it's missing teeth whenever the link fills up. MRTG interpolates the lost data to produce a smoother graph which is more accurate in cases of intermittent packet loss. But with V2.8.4 and above, you can use the "unknaszero" option to produce whichever graph is best under the conditions typical for your network. AAUUTTHHOORR Tobias Oetiker 2.17.10 2022-01-19 MRTG-FAQ(1) mrtg-2.17.10/doc/mrtg-forum.txt0000644000175300017510000000752414171763416015275 0ustar oetikeroepMRTG-FORUM(1) mrtg MRTG-FORUM(1) NNAAMMEE mrtg-forum - Interactive Help for MRTG users SSYYNNOOPPSSIISS There is a lot of written documentation for mrtg, but nevertheless you may have a problem where you can't find the solution. In this case some Human Help may be necessary. With MRTG there are several ways to get Humans to help you. MMAAIILLIINNGG--LLIISSTT There are three mailing lists for MRTG available. mrtg for discussion among mrtg users. mrtg-announce for announcements regarding new versions of mrtg related software. mrtg-developers for discussion among people who write software in connection with mrtg or who hack mrtg itself. TTHHEE RRUULLEESS Please note that the members of the mrtg mailinglist value politeness highly. This means behave in a way you would like others to behave towards you. +o No shouting. (NO CAPS) +o No rude language +o No demands. everybody is on the list out of their own free will. If you do not get an answer to your question, chances are high that you did not give sufficient details about the nature of your problem or that the answer to your problem is in the documentation. +o If you do not follow the rules you will be unsubscribed from the list with no further questions asked. +o Decisions about your unsubscription from the list will be taken by Alex van den Bogaerdt Paul C. Williamson If you feel that you have been treated unfairly, you may send mail to me and explain the situation. Tobi Oetiker SSUUBBSSCCRRIIBBIINNGG These lists are managed by a mailing-list management program (listar). It allows you to subscribe to these lists by sending a message with the subject: ssuubbssccrriibbee to the following address: listname-request@lists.oetiker.ch You will then get a message asking you to confirm your subscription. For posting to the lists use the following address listname@lists.oetiker.ch Note that only people who are subscribed to the list can post. Further information about the usage of the mailing lists is available by sending a message with the subject line hheellpp to either one of the request addresses. There is also a webinterface to the lists on http://lists.oetiker.ch List archives are on http://www.mail-archive.com/index.php?hunt=mrtg and http://gmane.org/find.php?list=mrtg NNEEWWSSGGRROOUUPP For discussion of MRTG or related topics on the Usenet, please send your posts to: news:comp.dcom.net-management Many MRTG users are in this forum and will help you. You can also find an archive of past activity from this Newsgroup on: http://groups.google.com/group/comp.dcom.net-management IIRRCC CChhaannnneell For discussion of MRTG and related topics on IRC, the `#mrtg' channel on EFNet has been created. More information can be found at http://mrtg.easymac.org MMRRTTGG JJaappaann There is a special Mailinglist for MRTG Users in Japan. It carries translations of the traffic from MRTG-ANNOUNCE as well as updates on the Japanese Translation of the MRTG documentation. Go to http://www.mrtg.jp/ for further Information. AAUUTTHHOORR Tobias Oetiker and many contributors 2.17.10 2022-01-19 MRTG-FORUM(1) mrtg-2.17.10/doc/mrtg-ipv6.txt0000644000175300017510000001015214171763417015021 0ustar oetikeroepMRTG-IPV6(1) mrtg MRTG-IPV6(1) NNAAMMEE mrtg-ipv6 - IPv6 support in MRTG OOVVEERRVVIIEEWW MRTG and cfgmaker support SNMP over IPv6. IPv6 targets can be specified by hostname or IPv6 address, and if the required libraries are present (see below), queries will use IPv6. UUSSAAGGEE EEnnaabblliinngg IIPPvv66 IPv6 is currently disabled by default and must be explicitly enabled. In MRTG this is done by turning on the EEnnaabblleeIIPPvv66 global option in the configuration file. In cfgmaker, it is enabled with the ----eennaabbllee--iippvv66 command-line option. If IPv6 is disabled, MRTG and cfgmaker should behave in exactly the same way as previous versions. So the addition of IPv6 support should have no effect on existing MRTG setups unless IPv6 is enabled. IPv6 support requires the Socket6 and INET6 libraries (see below). If MRTG can't find them, IPv6 is disabled. SSppeecciiffyyiinngg IIPPvv66 ttaarrggeettss IPv6 targets may be specified by name or IPv6 address. Numeric IPv6 addresses may be used with both cfgmaker and MRTG, but they must be enclosed in square brackets. For example, a target could be specified as: public@[2001:760:4::]:161 Hostnames work as expected: first an IPv6 name lookup is tried, then an IPv4 lookup. TTaarrggeettss tthhaatt ddoo nnoott ssuuppppoorrtt SSNNMMPP oovveerr IIPPvv66 Many targets (this currently includes all Cisco routers) do not yet support SNMP over IPv6 and must be monitored over IPv4. This can cause problems if you specify a target through its DNS name and the name maps to both the IPv6 address and the IPv4 address of the target: MRTG will only try IPv6, and will fail. To query these targets, use the IIPPvv44OOnnllyy per-target option, which tells MRTG not to use SNMP over IPv6 for the target. MRTG does not fall back to IPv4 for performance and correctness reasons. If there are many routers to query, a timeout for every router would make MRTG take too long to query them all. And if, for some reason, IPv6 connectivity to the target is lost, MRTG's error messages can help figure out what is wrong. cfgmaker does fall back from IPv6 to IPv4. If IPv6 is enabled and cfgmaker is given a hostname that resolves to both an IPv6 and an IPv4 address, it first tries to query the target over IPv6. If it receives no answer, it tries again using IPv4. If the target answers, cfgmaker sets the IPv4Only option in the generated config file. IIPPvv66 LLIIBBRRAARRIIEESS LLiibbrraarriieess rreeqquuiirreedd IPv6 support requires the SSoocckkeett66 and IINNEETT66 Perl modules. Both can be downloaded from CPAN: http://search.cpan.org/author/UMEMOTO/Socket6/ http://search.cpan.org/author/MONDEJAR/INET6/ If you use Debian, you will need the packages lliibbssoocckkeett66--ppeerrll and lliibbiioo--ssoocckkeett--iinneett66--ppeerrll, which are (or should soon be) in unstable. So far, IPv6 support has been tested on Linux only, and only with Socket6 version 0.12. Also note that IPv6 won't work at all if you don't have INET6.pm version 2.00 or newer. IInnssttaalllliinngg tthhee lliibbrraarriieess Building and installing Socket6 and INET6 is very simple. For each module, just unpack the archive and then do: perl Makefile.PL make and then: su make install If you have installed the libraries successfully, cfgmaker and mrtg should automatically detect them and allow IPv6 support to be enabled. AAUUTTHHOORR Lorenzo Colitti 2.17.10 2022-01-19 MRTG-IPV6(1) mrtg-2.17.10/doc/mrtglib.txt0000644000175300017510000001757214171763417014643 0ustar oetikeroepdoc::mrtglib(3) mrtg doc::mrtglib(3) NNAAMMEE MRTG_lib.pm - Library for MRTG and support scripts SSYYNNOOPPSSIISS use MRTG_lib; my ($configfile, @target_names, %globalcfg, %targetcfg); readcfg($configfile, \@target_names, \%globalcfg, \%targetcfg); my (@parsed_targets); cfgcheck(\@target_names, \%globalcfg, \%targetcfg, \@parsed_targets); DDEESSCCRRIIPPTTIIOONN MRTG_lib is part of MRTG, the Multi Router Traffic Grapher. It was separated from MRTG to allow other programs to easily use the same config files. The main part of MRTG_lib is the config file parser but some other functions are there too. $MRTG_lib::OS Type of OS: WIN, UNIX, VMS $MRTG_lib::SL _S_l_a_s_h in the current OS. $MRTG_lib::PS Path separator in PATH variable "readcfg" "readcfg($file, \@targets, \%globalcfg, \%targetcfg [, $prefix, \%extrules])" Reads a config file, parses it and fills some arrays and hashes. The mandatory arguments are: the name of the config file, a ref to an array which will be filled with a list of the target names, a hashref for the global configuration, a hashref for the target configuration. The configuration file syntax is: globaloption: value targetoption[targetname]: value aprefix*extglobal: value aprefix*exttarget[target2]: value E.g. workdir: /var/stat/mrtg target[router1]: 2:public@router1.local.net 14all*columns: 2 The global config hash has the structure $globalcfg{configoption} = 'value' The target config hash has the structure $targetcfg{configoption}{targetname} = 'value' See mrtg-reference for more information about the MRTG configuration syntax. "readcfg" can take two additional arguments to extend the config file syntax. This allows programs to put their configuration into the mrtg config file. The fifth argument is the prefix of the extension, the sixth argument is a hash with the checkrules for these extension settings. E.g. if the prefix is "14all" "readcfg" will check config lines that begin with "14all*", i.e. all lines like 14all*columns: 2 14all*graphsize[target3]: 500 200 against the rules in %extrules. The format of this hash is: $extrules{option} = [sub{$_[0] =~ m/^\d+$/}, sub{"Error message for $_[0]"}] i.e. $extrules{option}[0] -> a test expression $extrules{option}[1] -> error message if test fails The first part of the array is a perl expression to test the value of the option. The test can access this value in the variable "$arg". The second part of the array is an error message to display when the test fails. The failed value can be integrated by using the variable "$arg". Config settings with an different prefix than the one given in the "readcfg" call are not checked but inserted into _%_g_l_o_b_a_l_c_f_g and _%_t_a_r_g_e_t_c_f_g. Prefixed settings keep their prefix in the config hashes: $targetcfg{'14all*graphsize'}{'target3'} = '500 200' "cfgcheck" "cfgcheck(\@target_names, \%globalcfg, \%targetcfg, \@parsed_targets)" Checks the configuration read by "readcfg". Checks the values in the config for syntactical and/or semantical errors. Sets defaults for some options. Parses the "target[...]" options and files the array @parsed_targets ready for mrtg functions. The first three arguments are the same as for "readcfg". The fourth argument is an arrayref which will be filled with the parsed target defs. "cfgcheck" converts the values of target settings _o_p_t_i_o_n_s, e.g. options[router1]: bits, growright to a hash: $targetcfg{'option'}{'bits'}{'router1'} = 1 $targetcfg{'option'}{'growright'}{'router1'} = 1 This is not done by "readcfg" so if you don't use "cfgcheck" you have to check the scalar variable _$_t_a_r_g_e_t_c_f_g_{_'_o_p_t_i_o_n_'_}_{_'_r_o_u_t_e_r_1_'_} (MRTG allows options to be separated by space or ','). "ensureSL" "ensureSL(\$pathname)" Checks that the _p_a_t_h_n_a_m_e does not contain double path separators and ends with a path separator. It uses $MRTG_lib::SL as path separator which will be / or \ depending on the OS. "log2rrd" "log2rrd ($router,\%globalcfg,\%targetcfg)" Convert log file to rrd format. Needs rrdtool. "datestr" "datestr(time)" Returns the time given in the argument as a nicely formatted date string. The argument has to be in UNIX time format (seconds since 1970-1-1). "timestamp" "timestamp()" Return a string representing the current time. "setup_loghandlers" "setup_loghandlers(filename)" Install signalhandlers for __DIE__ and __WARN__ making the errors go the the specified destination. If filename is 'eventlog' mrtg will log to the windows event logger. "expistr" "expistr(time)" Returns the time given in the argument formatted suitable for HTTP Expire-Headers. "create_pid" "create_pid()" Creates a pid file for the mrtg daemon "demonize_me" "demonize_me()" Puts the running program into background, detaching it from the terminal. "populatecache" "populatecache(\%confcache, $host, $reread, $snmpoptshash)" Reads the SNMP variables _i_f_D_e_s_c_r, _i_p_A_d_E_n_t_I_f_I_n_d_e_x, _i_f_P_h_y_s_A_d_d_r_e_s_s, _i_f_N_a_m_e from the _h_o_s_t and stores the values in _%_c_o_n_f_c_a_c_h_e as follows: $confcache{$host}{'Descr'}{ifDescr}{oid} = (ifDescr or 'Dup') $confcache{$host}{'IP'}{ipAdEntIfIndex}{oid} = (ipAdEntIfIndex or 'Dup') $confcache{$host}{'Eth'}{ifPhysAddress}{oid} = (ifPhysAddress or 'Dup') $confcache{$host}{'Name'}{ifName}{oid} = (ifName or 'Dup') $confcache{$host}{'Type'}{ifType}{oid} = (ifType or 'Dup') The value (at the right side of =) is 'Dup' if a value was retrieved multiple times, the retrieved value else. "readconfcache" "my $confcache = readconfcache($file)" Preload the confcache from a file. "readfromconfcache" "writeconfcache($confcache,$file)" Store the current confcache into a file. "writeconfcache" "writeconfcache($confcache,$file)" Store the current confcache into a file. "storeincache" "storeincache($confcache,$host,$method,$key,$value)" "readfromcache" "readfromcache($confcache,$host,$method,$key)" "clearfromcache" "clearfromcache($confcache,$host)" "debug" "debug($type, $message)" Prints the _m_e_s_s_a_g_e on STDERR if debugging is enabled for type _t_y_p_e. A debug type is enabled if _t_y_p_e is in array @main::DEBUG. AAUUTTHHOORRSS Rainer Bawidamann (This Manpage) 2.17.10 2022-01-19 doc::mrtglib(3) mrtg-2.17.10/doc/mrtg-logfile.txt0000644000175300017510000000613714171763416015565 0ustar oetikeroepMRTG-LOGFILE(1) mrtg MRTG-LOGFILE(1) NNAAMMEE mrtg-logfile - description of the mrtg-2 logfile format SSYYNNOOPPSSIISS This document provides a description of the contents of the mrtg-2 logfile. OOVVEERRVVIIEEWW The logfile consists of two main sections. The first Line It stores the traffic counters from the most recent run of mrtg. The rest of the File Stores past traffic rate averages and maximum at increasing intervals. The first number on each line is a unix time stamp. It represents the number of seconds since 1970. DDEETTAAIILLSS TThhee ffiirrsstt LLiinnee The first line has 3 numbers which are: A (1st column) A timestamp of when MRTG last ran for this interface. The timestamp is the number of non-skip seconds passed since the standard UNIX "epoch" of midnight on 1st of January 1970 GMT. B (2nd column) The "incoming bytes counter" value. C (3rd column) The "outgoing bytes counter" value. TThhee rreesstt ooff tthhee FFiillee The second and remaining lines of the file contains 5 numbers which are: A (1st column) The Unix timestamp for the point in time the data on this line is relevant. Note that the interval between timestamps increases as you progress through the file. At first it is 5 minutes and at the end it is one day between two lines. This timestamp may be converted in OpenOffice Calc or MS Excel by using the following formula =(x+y)/86400+DATE(1970;1;1) (instead of ";" it may be that you have to use "," this depends on the context and your locale settings) you can also ask perl to help by typing perl -e 'print scalar localtime(x),"\n"' xx is the unix timestamp and yy is the offset in seconds from UTC. (Perl knows yy). B (2nd column) The average incoming transfer rate in bytes per second. This is valid for the time between the A value of the current line and the A value of the previous line. C (3rd column) The average outgoing transfer rate in bytes per second since the previous measurement. D (4th column) The maximum incoming transfer rate in bytes per second for the current interval. This is calculated from all the updates which have occurred in the current interval. If the current interval is 1 hour, and updates have occurred every 5 minutes, it will be the biggest 5 minute transfer rate seen during the hour. E (5th column) The maximum outgoing transfer rate in bytes per second for the current interval. AAUUTTHHOORR Butch Kemper and Tobias Oetiker 2.17.10 2022-01-19 MRTG-LOGFILE(1) mrtg-2.17.10/doc/mrtg-mibhelp.txt0000644000175300017510000001445214171763417015564 0ustar oetikeroepMRTG-MIBHELP(1) mrtg MRTG-MIBHELP(1) NNAAMMEE mrtg-mibhelp - A Table of some interesting OIDs OOVVEERRVVIIEEWW This File Contains a collection of interesting MIB Entries ... mrtg knows about their names ... depending on the ASN.1 Syntax you may have to put ggaauuggee into the OOppttiioonnss[[]]:: parameter. For information about how to create a TTaarrggeett[[]]:: parameter which references these MIB entries, please consult mrtg-reference. MMIIBB LLIISSTT iiffOOppeerrSSttaattuuss Descriptor: ifOperStatus Identifier: 1.3.6.1.2.1.2.2.1.8 ASN.1 Syntax: INTEGER Enumeration: up 1, down 2, testing 3 The current operational state of the interface. The tteessttiinngg(3) state indicates that no operational packets can be passed. iiffAAddmmiinnSSttaattuuss Descriptor: ifAdminStatus Identifier: 1.3.6.1.2.1.2.2.1.7 ASN.1 Syntax: INTEGER Enumeration: up 1, down 2, testing 3 The current administrative state of the interface. The tteessttiinngg(3) state indicates that no operational packets can be passed. iiffIInnOOcctteettss Descriptor: ifInOctets Identifier: 1.3.6.1.2.1.2.2.1.10 ASN.1 Syntax: Counter32 The total number of octets received on the interface, including framing characters. iiffIInnUUccaassttPPkkttss Descriptor: ifInUcastPkts Identifier: 1.3.6.1.2.1.2.2.1.11 ASN.1 Syntax: Counter32 The number of subnetwork-unicast packets delivered to a higher-layer protocol. iiffIInnNNUUccaassttPPkkttss Descriptor: ifInNUcastPkts Identifier: 1.3.6.1.2.1.2.2.1.12 ASN.1 Syntax: Counter32 The number of non-unicast (i.e., subnetwork- broadcast or subnetwork- multicast) packets delivered to a higher-layer protocol. iiffIInnDDiissccaarrddss Descriptor: ifInDiscards Identifier: 1.3.6.1.2.1.2.2.1.13 ASN.1 Syntax: Counter32 The number of inbound packets which were chosen to be discarded even though no errors had been detected to prevent their being deliverable to a higher-layer protocol. One possible reason for discarding such a packet could be to free up buffer space. iiffIInnEErrrroorrss Descriptor: ifInErrors Identifier: 1.3.6.1.2.1.2.2.1.14 ASN.1 Syntax: Counter32 The number of inbound packets that contained errors preventing them from being deliverable to a higher-layer protocol. iiffIInnUUnnkknnoowwnnPPrroottooss Descriptor: ifInUnknownProtos Identifier: 1.3.6.1.2.1.2.2.1.15 ASN.1 Syntax: Counter32 The number of packets received via the interface which were discarded because of an unknown or unsupported protocol. iiffOOuuttOOcctteettss Descriptor: ifOutOctets Identifier: 1.3.6.1.2.1.2.2.1.16 ASN.1 Syntax: Counter32 The total number of octets transmitted out of the interface, including framing characters. iiffOOuuttUUccaassttPPkkttss Descriptor: ifOutUcastPkts Identifier: 1.3.6.1.2.1.2.2.1.17 ASN.1 Syntax: Counter32 The total number of packets that higher-level protocols requested be transmitted to a subnetwork-unicast address, including those that were discarded or not sent. iiffOOuuttNNUUccaassttPPkkttss Descriptor: ifOutNUcastPkts Identifier: 1.3.6.1.2.1.2.2.1.18 ASN.1 Syntax: Counter32 The total number of packets that higher-level protocols requested be transmitted to a non- unicast (i.e., a subnetwork-broadcast or subnetwork-multicast) address, including those that were discarded or not sent. iiffOOuuttDDiissccaarrddss Descriptor: ifOutDiscards Identifier: 1.3.6.1.2.1.2.2.1.19 ASN.1 Syntax: Counter32 The number of outbound packets which were chosen to be discarded even though no errors had been detected to prevent their being transmitted. One possible reason for discarding such a packet could be to free up buffer space. iiffOOuuttEErrrroorrss Descriptor: ifOutErrors Identifier: 1.3.6.1.2.1.2.2.1.20 ASN.1 Syntax: Counter32 The number of outbound packets that could not be transmitted because of errors. iiffOOuuttQQLLeenn Descriptor: ifOutQLen Identifier: 1.3.6.1.2.1.2.2.1.21 ASN.1 Syntax: Unsigned32 The length of the output packet queue (in packets). ffrrIInnOOcctteettss From: Simon Ferrett 'frInOctets' => '1.3.6.1.2.1.10.32.2.1.9' 'frOutOctets' => '1.3.6.1.2.1.10.32.2.1.7' which when used in the form: frInOctets.pp.dd&frOutOctets.pp.dd:community@cisco.router where pp is the physical port that the frame relay pvc is defined on and dd is the DLCI of the pvc gets you the in and out octets for just that pvc. iiffAAddmmiinnHHaacckk aanndd iiffOOppeerrHHaacckk The return values of ifAdminStatus and ifOperStatus are not very useful for graphing. Use ifOperHack and ifAdminHack instead. They return 1 for UP and 0 otherwise. Note these are not real MIB entities but mrtg hacks PPsseeuuddooZZeerroo aanndd PPsseeuuddooOOnnee will return 0 and 1 respectively Note these are not real MIB entities but mrtg hacks AAUUTTHHOORR Tobias Oetiker 2.17.10 2022-01-19 MRTG-MIBHELP(1) mrtg-2.17.10/doc/mrtg-nt-guide.txt0000644000175300017510000004045314171763416015657 0ustar oetikeroepMRTG-NT-GUIDE(1) mrtg MRTG-NT-GUIDE(1) NNAAMMEE mrtg-nt-guide - The MRTG 2.17.10 Windows Installation Guide SSYYNNOOPPSSIISS Installing MRTG on a Windows box is not quite as "click and point" as some might want it to be. But then again, it is not all that difficult if you follow the instructions below. PPRREERREEQQUUIISSIITTEESS To get MRTG to work on Windows you need the following: +o A current copy of Perl. For Example ActivePerl 5.8.8 from ActiveState http://www.activestate.com/store/activeperl/download/ +o The latest version of MRTG from http://oss.oetiker.ch/mrtg/pub. Look for mrtg-2.17.10.zip or better. The archive also contains a precompiled copy of rateup.exe for Win32. IINNSSTTAALLLLIINNGG I suggest you do the following from the machine that will be running MRTG, which, in this case, is also a web server. All examples are for doing things to a LOCAL machine. First Unzip MRTG to C:\mrtg-2.17.10 on the Windows machine of your choice. Next Install Perl on the same Windows machine. You might want to make sure that the Perl binary directory is listed in your system path. C:\Perl\bin;%SystemRoot%\system32;%SystemRoot%;... You can manually check this by going to [Control Panel]->[System]->[Environment] To see if everything is installed properly you can open a Command Shell and go into _c_:_\_m_r_t_g_-_2_._1_7_._1_0_\_b_i_n. Type: perl mrtg This should give you a friendly error message complaining about the missing MRTG configuration file. Now, you have successfully installed MRTG and Perl. CCOONNFFIIGGUURRIINNGG MMRRTTGG Now it is time to create a configuration for MRTG. But before we begin you need to know a few things. Take an opportunity to gather the following information: +o The IP address or hostname and the SNMP port number, (if non standard), of the device you want to monitor. +o If you want to monitor something other than bytes in and out, you must also know the SNMPOID of what you want to monitor. +o Finally you need to know the read-only SNMP community string for your device. If you don't know it, try ppuubblliicc, that is the default. For the rest of this document we will be using device 1100..1100..1100..11 ( a CISCO Catalyst 5000) with Community string ppuubblliicc. We are interested in monitoring traffic, and the CPU load. Let's begin. The first thing we do in setting up MRTG is making a default config file. Get to a cmd prompt and change to the _c_:_\_m_r_t_g_-_2_._1_7_._1_0_\_b_i_n directory. Type the following command: perl cfgmaker public@10.10.10.1 --global "WorkDir: c:\www\mrtg" --output mrtg.cfg This creates an initial MRTG config file for you. Note that in this file all interfaces of your router will be stored by number. Unfortunately, these numbers are likely to change whenever you reconfigure your router. In order to work around this you can get _c_f_g_m_a_k_e_r to produce a configuration which is based on Ip numbers, or even Interface Descriptions. Check cfgmaker If you get an error message complaining about nnoo ssuucchh nnaammee or nnoo rreessppoonnssee, your community name is probably wrong. Now, let's take a look at the mrtg.cfg file that was created. In Perl, a "#" is a comment, synonymous with "REM" in DOS. Add the following to the top of the mrtg.cfg file: WorkDir: c:\www\mrtg This is where the web pages are created, usually a web root. ###################################################################### # Description: LCP SUWGB # Contact: Administrator # System Name: LC-Bridge # Location: Here #..................................................................... TargetDevice's IP Address:Interface Number:Community:IP Address Target[10.10.10.1.1]: 1:public@10.10.10.1 This is the interface speed (Default is 10 megabits; for 100Mbit devices use 12500000 and so on...) MaxBytes[10.10.10.1.1]: 1250000 Title[10.10.10.1.1]: LC-Bridge (sample.device): ether0 This section determines how the web page headers will look PageTop[10.10.10.1.1]:

      Traffic Analysis for ether0

      System:LC-Bridge inAndover
      Maintainer:Administrator
      Interface:ether0(1)
      IP:sample.device(10.10.10.1)
      Max Speed: 1250.0 kBytes/s (ethernetCsmacd)
      Target[10.10.10.1.2]: 2:public@10.10.10.1 MaxBytes[10.10.10.1.2]: 1250000 Title[10.10.10.1.2]: LC-Bridge (): ulink0 PageTop[10.10.10.1.2]:

      Traffic Analysis for ulink0

      System:LC-Bridge inAndover
      Maintainer:Administrator
      Interface:ulink0(2)
      IP:()
      Max Speed: 1250.0 kBytes/s (ethernetCsmacd)
      #--------------------------------------------------------------- And that's a very basic MRTG config file. You can run this and see your results by going into the _c_:_\_m_r_t_g_-_2_._1_7_._1_0_\_b_i_n directory and typing: perl mrtg mrtg.cfg It is normal to get errors for the first two times you run this command. The errors will alert you about the fact that there have not been any log files in existence before. If you take a look at those web pages they are not very exciting (yet). You need to have the MRTG files run every five minutes to produce the desired results. Just run it again after a few minutes. You should now be able to see the first lines in your graphs. MMAAKKEE MMRRTTGG RRUUNN AALLLL TTHHEE TTIIMMEE Starting MRTG by hand every time you want to run it is not going to make you happy I guess. There is a special option you can set in the MRTG configuration file so so that MRTG will not terminate after it was started. Instead it will wait for 5 minutes and then run again. Add the option RunAsDaemon: yes to your mrtg.cfg file and start it with: start /Dc:\mrtg-2.17.10\bin wperl mrtg --logging=eventlog mrtg.cfg If you use wwppeerrll instead of ppeerrll, no console window will show. MRTG is now running in the background. If it runs into problems it will tell you so over the EventLog. To stop MRTG, open the Task Manager and terminate the wwppeerrll..eexxee process. If mrtg has anything to tell you these messages can be found in the event log. If you put a shortcut with Target: wperl mrtg --logging=eventlog mrtg.cfg Start in: c:\mrtg-2.17.10\bin into your start-up folder, MRTG will now start whenever you login to your NT box. If you do not want to log into your box just to start MRTG. Have a look at http://www.firedaemon.com/mrtg-howto.html which describes a free tool to start any program as a Service. The pages gives specific instructions for MRTG users. HHOOWW TTOO SSEETTUUPP MMRRTTGG AASS AA WWIINNDDOOWWSS SSEERRVVIICCEE AAddddiittiioonnaall PPrreerreeqquuiissiitteess +o MRTG must be installed and fully configured on the target system. In the following exercise the assumption is that MRTG is installed under c:\mrtg\ and all the sample files use this location. +o Microsoft Tools SSRRVVAANNYY..eexxee (Applications as Services Utility) and IINNSSTTSSRRVV..eexxee (Service Installer) - Those files can be downloaded from Microsoft as a part of Windows 2000 Resource Kit at . They are also available from other locations such as , , etc. Detailed instructions on how to use this package are available at . In order to follow the steps in this HOW-TO you MMUUSSTT obtain both executables. +o You must have administrative rights on the target system. PPrreeppaarraattiioonn Please complete the following steps before starting the installation: +o Copy ssrrvvaannyy..eexxee and iinnssttssrrvv..eexxee to c:\mrtg-2.17.10\bin\ (your MRTG bin directory). +o Create a file called mmrrttgg..rreegg anywhere on your system and paste the following content into it: Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MRTG\Parameters] "Application"="c:\\perl\\bin\\wperl.exe" "AppParameters"="c:\\mrtg-2.17.10\\bin\\mrtg --logging=eventlog c:\\mrtg-2.17.10\\bin\\mrtg.cfg" "AppDirectory"="c:\\mrtg-2.17.10\\bin\\" SSeerrvviiccee IInnssttaallllaattiioonn Once again, assuming that MRTG is already fully installed and configured on the target system under c:\mrtg\ the following steps are necessary to setup MRTG as a service. Using the command prompt go into the temporary directory where you unzipped the package. When there type the following command to create a service named "MRTG" in the Windows Services management console: instsrv MRTG c:\mrtg\bin\srvany.exe Now you need to create the AApppp** entries required for the new service. You can do this by either right-clicking on the mrtg.reg file and selecting 'merge' or by running the following command: regedit /s mrtg.reg After setting up the registry entry it is time to point it to your MRTG installation. If you have installed MRTG under _c_:_\_m_r_t_g_\, you can skip this step. Open your registry editor (Start -> Run -> regedt32), and locate the [[HHKKEEYY__LLOOCCAALL__MMAACCHHIINNEE\\SSYYSSTTEEMM\\CCuurrrreennttCCoonnttrroollSSeett\\SSeerrvviicceess\\MMRRTTGG]] key. Make sure that the IImmaaggeePPaatthh variable is correctly pointing to ssrrvvaannyy..eexxee located in your MRTG bin directory (for example c:\mrtg\bin\srvany.exe). Next you have to expand the MRTG tree, and go to the [[HHKKEEYY__LLOOCCAALL__MMAACCHHIINNEE\\SSYYSSTTEEMM\\CCuurrrreennttCCoonnttrroollSSeett\\SSeerrvviicceess\\MMRRTTGG\\PPaarraammeetteerrss]] key. Under Parameters make sure that all the AApppplliiccaattiioonn variables are setup properly. At this point you are ready to run the service. The only thing left to do is to start the MRTG service in the Services management console. After you do this, you should see two new processes running on your system: srvany.exe and wperl.exe. Make sure to stop any previously running MRTG processes to avoid conflict. Note that it is imperative to set the RRuunnAAssDDaaeemmoonn:: yyeess option or the service will stop after just one single run! EEXXAAMMPPLLEE Now lets look at a config file to monitor what we wanted to on our mythical Cisco Cat 5000 -- utilization on ports 3, 5, 10, and 24, and the CPU Load, which will show us nonstandard mrtg configurations as well as more options.. WorkDir: c:\www\mrtg RunAsDaemon: yes ###################################################################### # Description: LCP SUWGB # Contact: Administrator # System Name: LC-Bridge # Location: Here #..................................................................... Target[10.10.10.1.1]: 3:public@10.10.10.1 MaxBytes[10.10.10.1.1]: 1250000 Title[10.10.10.1.1]: LC-Bridge (sample-device): ether0 PageTop[10.10.10.1.1]:

      Traffic Analysis for ether0

      System:LC-Bridge inAndover
      Maintainer:Administrator
      Interface:ether0(3)
      IP:sample-device(10.10.10.1)
      Max Speed: 1250.0 kBytes/s (ethernetCsmacd)
      #--------------------------------------------------------------- Target[10.10.10.1.2]: 5:public@10.10.10.1 MaxBytes[10.10.10.1.2]: 1250000 Title[10.10.10.1.2]: LC-Bridge (): ulink0 PageTop[10.10.10.1.2]:

      Traffic Analysis for ulink0

      System:LC-Bridge inAndover
      Maintainer:Administrator
      Interface:ulink0(5)
      IP:()
      Max Speed: 1250.0 kBytes/s (ethernetCsmacd)
      #--------------------------------------------------------------- Target[10.10.10.1.1]: 10:public@10.10.10.1 MaxBytes[10.10.10.1.1]: 1250000 Title[10.10.10.1.1]: LC-Bridge (sample-device): ether0 PageTop[10.10.10.1.1]:

      Traffic Analysis for ether0

      System:LC-Bridge inAndover
      Maintainer:Administrator
      Interface:ether0(10)
      IP:sample-device(10.10.10.1)
      Max Speed: 1250.0 kBytes/s (ethernetCsmacd)
      #--------------------------------------------------------------- Target[10.10.10.1.2]: 24:public@10.10.10.1 MaxBytes[10.10.10.1.2]: 1250000 Title[10.10.10.1.2]: LC-Bridge (): ulink0 PageTop[10.10.10.1.2]:

      Traffic Analysis for ulink0

      System:LC-Bridge inAndover
      Maintainer:Administrator
      Interface:ulink0(24)
      IP:()
      Max Speed: 1250.0 kBytes/s (ethernetCsmacd)
      #--------------------------------------------------------------- # Router CPU load % Target[cpu.1]:1.3.6.1.4.1.9.2.1.58.0&1.3.6.1.4.1.9.2.1.58.0:public@10.10.10.1 RouterUptime[cpu.1]: public@10.10.10.1 MaxBytes[cpu.1]: 100 Title[cpu.1]: CPU LOAD PageTop[cpu.1]:

      CPU Load %

      Unscaled[cpu.1]: ymwd ShortLegend[cpu.1]: % XSize[cpu.1]: 380 YSize[cpu.1]: 100 YLegend[cpu.1]: CPU Utilization Legend1[cpu.1]: CPU Utilization in % (Load) Legend2[cpu.1]: CPU Utilization in % (Load) Legend3[cpu.1]: Legend4[cpu.1]: LegendI[cpu.1]: LegendO[cpu.1]:  Usage Options[cpu.1]: gauge This is a nice example of how to monitor any SNMP device if you know what OID you want to use. Once again, for an explanation of the more advance features of mrtg, please see the rest of the documentation. AAUUTTHHOORRSS Tobi Oetiker , David S. Divins , Steve Pierce , Artyom Adjemov , Ilja Ivanov Karel Fajkus 2.17.10 2022-01-19 MRTG-NT-GUIDE(1) mrtg-2.17.10/doc/mrtg-nw-guide.txt0000644000175300017510000003620214171763416015657 0ustar oetikeroepMRTG-NW-GUIDE(1) mrtg MRTG-NW-GUIDE(1) NNAAMMEE mrtg-nw-guide - MRTG for NetWare SSYYNNOOPPSSIISS This guide is intended to aid in the installation and configuration of MRTG on a NetWare server. OOVVEERRVVIIEEWW MRTG is a relative newcomer to the NetWare platform. Earlier versions of NetWare could not run MRTG natively for several reasons: +o Absence of NetWare OS support in the MRTG package. +o A NetWare server commandline length limitation. +o Absence of the Rateup executable (Rateup.nlm). +o A standard installation method. +o Problems with NetWare's implementation of Perl. Support for the NetWare OS has now been fully added into MRTG, beginning with MRTG release 2.12.2. Liberally minded operating systems support a commandline length approaching 1000 characters. In such environments it was an easy matter to pass the sometimes high number of parameters used by MRTG's Rateup executable directly on the commandline. Until NetWare 6.5, NetWare had a commandline limit of 512 characters. This limitation was also removed for NetWare 6.0 by Service Pack 5. For other NetWare versions and earlier Service Packs, this limitation remains. To permit a 'standard' interface for NetWare, the Rateup executable has been modified to also read its parameters from a file, and the MRTG script has been modified to support this method on a NetWare platform. (See New Rateup Switch) A Rateup NLM is now available, along with the necessary scripts to build it if required. See the NetWare Support section of this document for further details. Additionally, mrtg.pl has been revised because of the unique (to NetWare) name of executables (NLM). The absence of a specific installation procedure has caused MRTG to fail in the past because the Perl script could not find or load the Rateup executable. The installation method supplied here will solve this problem for now. The MRTG.pl script in the 2.12.2 (or later) version of MRTG has been configured to suit all likely versions of NetWare able to use Perl5, and bypasses all of the known problems with NetWare Perl running MRTG. PPRREERREEQQUUIISSIITTEESS You will need the following: +o Perl 5.8.0 for NetWare with latest Perl Updates (February, 2005 or later; previous versions MAY work) +o NetWare 5.1 w/ SP8, NetWare 6.0 w/ SP5 or NetWare 6.5 w/ SP2. +o A copy of the MRTG Package (v2.12.2 at time of writing) +o Three .ncf files to execute the Perl scripts at the NetWare server console. +o A copy of the Rateup NLM (Pre-built or compiled) +o Optionally, any NetWare supported Web Server (Netscape, Apache 1.3 or 2.0) For copies of the .ncf files and Rateup NLM, see NetWare Support in this document. IINNSSTTAALLLLIINNGG MMRRTTGG 1. Install the latest Perl 5.8.x release on your server. See the Perl documentation for details. 2. Create the following directories: SYS:/Mrtg SYS:/Mrtg/bin SYS:/Mrtg/contrib (Optional for this document) SYS:/Mrtg/doc (Optional for this document) SYS:/Mrtg/html SYS:/Mrtg/html/images SYS:/Mrtg/html/work SYS:/Mrtg/lib SYS:/Mrtg/logs SYS:/Mrtg/translate 3. Copy from the MRTG package the following files: \bin\* to SYS:/Mrtg/bin All files. See Note 1. Note 1: Add a .pl extension to the mrtg, cfgmaker and indexmaker files. The rateup.exe will NOT be needed on the NetWare server. \contrib\* to SYS:/Mrtg/contrib/ Include sub-directories \doc\* to SYS:/Mrtg/doc/ All files \images\* to SYS:/Mrtg/html/images/ All files \translate\* to SYS:/Mrtg/translate/ All files. See Note 2. Note 2: For English-only language support, all \translate files EXCEPT Locales_mrtg may be deleted. \lib\* to SYS:/Mrtg/lib Include sub-directories. See Note 3. Note 3: This will create the SYS:/Mrtg/lib/mrtg2 and ./pod directories. 4. Create copies of the three .ncf files and install them: *.ncf to SYS:/Mrtg/bin See NetWare Support in this document for details on how to create copies of these files. 5. See Compiling Rateup.nlm"> in this document for details on compiling the Rateup NLM yourself if desired. A prebuit verion is available in the .\mrtg\bin directory where it must remain. CCOONNFFIIGGUURRIINNGG MMRRTTGG +o Refer to Novell documentation on configuring and loading SNMP support on your server if this is the device to be monitored. +o Edit sys:/mrtg/bin/MakeMrtgCfg.ncf: replace ccccc with the GET community name for the SNMP device (typically 'public'), replace ddddd with the DNS name or IP address of the device to be monitored. e.g public@www.myserver.com, public@10.202.65.180 Note 1: These are NOT mail addresses, they just look like one! Note 2: If multiple devices are to be monitored, add their entries to the same line: e.g perl cfgmaker.pl public@www.myserver.com public@10.202.65.180 > sys:/mrtg/bin/mrtg.cfg In this "Getting Started", it is 'suggested' to only monitor a single device. +o At the server console, run: sys:/mrtg/bin/MakeMrtgCfg.ncf This will create Mrtg.cfg in sys:/mrtg/bin. +o Edit the Mrtg.cfg configuration file created in the previous step. Note the following: It was found, when testing MRTG on a NetWare 6.5 server using a NIC Interface, that mrtg.cfg contained the following message: ### Interface 1 >> Descr: 'Intel(R)-8255x-based-Network-Connection'... ### The following interface is commented out because: ### * has a speed of 0 which makes no sense # ... If this occurs, edit MakeMrtgCfg.ncf and add the following parameter as shown: perl sys:\mrtg\bin\cfgmaker.pl --zero-speed=nnn public@10.202.65.180 > sys:\mrtg\bin\Mrtg.cfg where nnnnnn is the interface speed in bits per second. For a 100 Megabit LAN NIC, nnn = 10000000. It will be necessary to re-execute the MakeMrtgCfg.ncf script before continuing with this section. Below line 16 (*** Global Defaults), add: HtmlDir: e.g HtmlDir: sys:/mrtg/html ImageDir: e.g ImageDir: sys:/mrtg/html/work LogDir: e.g LogDir: sys:/mrtg/logs IconDir: e.g IconDir: ./images Note 1. The HtmlDir entry specifies where MRTG will create its HTML pages. Note 2. The ImageDir entry specifies where the created graphic icons are placed. Note 3. The IconDir entry specifies where the supplied MRTG icons are located. It MUST be a relative path from HtmlDir or absolute URL. The value shown is recommended. +o At the server console run: sys:/mrtg/bin/RunMrtg.ncf several times. By the third time it should run without showing error messages on the console screen. This should create. - A HTML page in the (HtmlDir) directory for each monitored device, - A .dat file in the (ImageDir) directory for each monitored device, - Several .png icons in the (ImageDir) directory, - Some log file entries in the (LogDir) directory. Note: If you experience a "Use of uninitialised value in split" error, it will be necessary to create a 'Path' environment variable at the server console; use the following example env path="SYS:\" (The actual value is immaterial, as long as the var itself exists.) +o Edit sys:/mrtg/bin/MakeMrtgIndex.ncf. Change the indicated shown in the following example to match the value entered for (HtmlDir). perl --noscreen sys:/mrtg/bin/indexmaker.pl sys:/mrtg/bin/Mrtg.cfg > /index.html +o Create an index.html page linking the separate device HTML page(s). At the server console, run: sys:/mrtg/bin/MakeMrtgIndex.ncf This will create index.html in the (HtmlDir) directory. +o Optionally, configure a Web Server to permit access to the directory specified in (HtmlDir) to view the MRTG graphs remotely, at, for example: http://ip_or_dns/mrtg/index.html A sample configuration for an Apache Webserver is shown: Alias /mrtg/ "SYS:/mrtg/html/" AllowOverride None Order allow,deny Allow from all +o Set the property of the directory pointed to by (ImageDir), to 'Purge Immediate'. +o Finally, read the MRTG documentation for much more detailed configuration/usage information. Welcome to MRTG!! MMAAKKEE MMRRTTGG RRUUNN AALLLL TTHHEE TTIIMMEE MRTG can be made to run periodically by at least two means: +o Using CRON Scheduling +o Running MRTG in Daemon Mode CCRROONN SScchheedduulliinngg To use CRON scheduling, create a CRON Scheduler entry to execute the RunMrtg.ncf file on a frequency appropriate for the server environment and information desired. The following entry in the sys:\etc\crontab file will execute MRTG every five minutes: 0,5,10,15,20,25,30,35,40,45,50,55 * * * * sys:\mrtg\bin\runmrtg.ncf The CRON Scheduler (cron.nlm) can be started automatically by adding it in AUTOEXEC.ncf or, manually loading it at the server console. MMRRTTGG iinn DDaaeemmoonn MMooddee Refer to the MRTG-Reference document for information about the 'RunAsDaemon' option. Its use is outside the scope of this document. TTRROOUUBBLLEESSHHOOOOTTIINNGG Read the MRTG documents, Perl documents or, finally, submit questions to the MRTG User forums. For NetWare specific issues, submit questions to the Perl forum at news://developer-forums.novell.com/novell.devsup.perl (Novell Developer Forums). CCOOMMPPIILLIINNGG RRAATTEEUUPP..NNLLMM In addition to the rateup.c and Makefile.Netware supplied with the MRTG release, you will also need: +o Metrowerks CodeWarrior with NetWare Support OR GCC Compiler (v3.0.3 or later) with NlmConv Utility +o Novell LibC NDK (February 2004 or later) +o GD Graphics Library (v2.0.33 or later) +o LibPNG Graphics Library (v1.2.8 or later) +o ZLib Library (v1.2.3 or later) +o The get_ver.awk script +o A copy of the GNU build tools. (See http://sourceforge.net/projects/gnuwin32/) The auxiliary libraries can be obtained from: GD Graphics Library. (See http://www.boutell.com/gd/ ) PNG Graphics Library. (See http://libpng.sourceforge.net/ ) zLib Compression Library. (See http://www.gzip.org/zlib/ ) Edit the Makefile.Netware file as required to match your installation paths; search the file for the key word 'Edit'. NNEETTWWAARREE SSUUPPPPOORRTT For copies of the NCF and get_ver.awk scripts, see Appendix. For NetWare specific issues, submit questions to the Perl forum at news://developer-forums.novell.com/novell.devsup.perl (Novell Developer Forums). To move the MRTG application to a volume other than SYS: you will need to edit the NCF scripts provided plus the MRTG[.pl] script itself in two places. NNEEWW RRAATTEEUUPP SSWWIITTCCHH The MRTG[.pl] script, when used on a NetWare platform, uses Rateup[.nlm] with the new commandline switch: RATEUP -f filename where the filename parameter can include a leading path element. The file format is exactly the same as that used on the commandline by other operating systems, including the leading path and name of the Rateup NLM. AAPPPPEENNDDIIXX The Appendix includes 'copies' of the following files: +o The NCF files used during MRTG configuration, To create copies of these files, simply 'cut and paste' into your favourite 'tteexxtt eeddiittoorr' and save under their respective names. You should remove the leading space from each line. _M_a_k_e_M_r_t_g_C_f_g_._N_C_F # MakeMrtgCfg.NCF # Purpose : Create the MRTG Configuration File # Changed : 5/05/2005 New # Located : SYS:MRTG\BIN # Set For : # Params : # Edit this file and: # Replace ccccc with your device GET SNMP Community Name - If unsure try 'public'. # Replace ddddd with your device IP (n.n.n.n) or domain name. perl --noscreen sys:\mrtg\bin\cfgmaker.pl ccccc@ddddd > sys:\mrtg\bin\Mrtg.cfg # # End of MakeMrtgCfg.NCF _R_u_n_M_r_t_g_._N_C_F # RunMrtg.NCF # Purpose : Run the MRTG Application # Changed : 5/05/2005 New # Located : SYS:MRTG\BIN # Set For : # Params : # The paths are as per the examples recommended in "Getting Started". perl --noscreen sys:\mrtg\bin\mrtg.pl sys:\mrtg\bin\mrtg.cfg # # End of RunMrtg.NCF _M_a_k_e_M_r_t_g_I_n_d_e_x_._N_C_F # MakeMrtgIndex.NCF # Purpose : Create the HTML Index File for MRTG HTML data pages # Changed : 5/05/2005 New # Located : SYS:MRTG\BIN # Set For : # Params : # Note: Edit this file and change the redirected output to the location # specified for HtmlDir or WorkDir. The sys:\apache2\htdocs\mrtg\index.html # is based on the examples in "Getting Started". perl --noscreen sys:\mrtg\bin\indexmaker.pl sys:\mrtg\bin\Mrtg.cfg > sys:\mrtg\html\index.html # # End of MakeMrtgIndex.NCF LLIICCEENNSSEE GNU General Public License CCRREEDDIITTSS The MRTG for NetWare exists largely through the efforts of Guenter Knauf and feedback from beta testers. AAUUTTHHOORR Norm W.. 2.17.10 2022-01-19 MRTG-NW-GUIDE(1) mrtg-2.17.10/doc/mrtg.txt0000644000175300017510000002061214171763417014141 0ustar oetikeroepMRTG(1) mrtg MRTG(1) NNAAMMEE mrtg - What is MRTG ? DDEESSCCRRIIPPTTIIOONN The Multi Router Traffic Grapher (MRTG) is a tool to monitor the traffic load on network links. MRTG generates HTML pages containing PNG images which provide a LIVE visual representation of this traffic. Go to http://oss.oetiker.ch/mrtg for all the details about mrtg. HHIIGGHHLLIIGGHHTTSS Portable MRTG works on most UNIX platforms and Windows NT. Perl MRTG is written in Perl and comes with full source. Portable SNMP MRTG Uses a highly portable SNMP implementation written entirely in Perl (thanks to Simon Leinen). There is no need to install any external SNMP package. SNMPv2c support MRTG can read the new SNMPv2c 64bit counters. No more counter wrapping. Reliable Interface Identification Router interfaces can be identified by IP address, description and ethernet address in addition to the normal interface number. Constant size Logfiles MRTG's logfiles do NOT grow thanks to the use of a unique data consolidation algorithm. Automatic Configuration MRTG comes with a set of configuration tools which make configuration and setup very simple. Performance Time critical routines are written in C (thanks to the initiative of Dave Rand my Co-Author). GIF free Graphics Graphics are generated directly in PNG format using the GD library by Thomas Boutell. Customizability The look of the webpages produced by MRTG is highly configurable. RRDtool MRTG has built-in hooks for using RRDtool. If you are strapped for performance this may help. DDEETTAAIILLSS MRTG consists of a Perl script which uses SNMP to read the traffic counters of your routers and a fast C program which logs the traffic data and creates beautiful graphs representing the traffic on the monitored network connection. These graphs are embedded into webpages which can be viewed from any modern Web-browser. In addition to a detailed daily view, MRTG also creates visual representations of the traffic seen during the last seven days, the last five weeks and the last twelve months. This is possible because MRTG keeps a log of all the data it has pulled from the router. This log is automatically consolidated so that it does not grow over time, but still contains all the relevant data for all the traffic seen over the last two years. This is all performed in an efficient manner. Therefore you can monitor 200 or more network links from any halfway decent UNIX box. MRTG is not limited to monitoring traffic, though. It is possible to monitor any SNMP variable you choose. You can even use an external program to gather the data which should be monitored via MRTG. People are using MRTG, to monitor things such as System Load, Login Sessions, Modem availability and more. MRTG even allows you to accumulate two or more data sources into a single graph. HHIISSTTOORRYY In 1994 I was working at a site where we had one 64kbit line to the outside world. Obviously, everybody was interested in knowing how the link was performing. So I wrote a quick hack which created a constantly updated graph on the web that showed the traffic load on our Internet link. This eventually evolved into a rather configurable Perl script called MRTG-1.0 which I released in spring 1995. After a few updates, I left my job at DMU to start work at the Swiss Federal Institute of Technology. Due to lack of time I had to put MRTG aside. One day in January of 1996, I received email from Dave Rand asking if I had any ideas why MRTG was so slow. Actually, I did. MRTG's programming was not very efficient and it was written entirely in Perl. After a week or so, Dave wrote back to me and said he had tried what I had suggested for improving MRTG's speed. Since the changes did not help much, he had decided to rewrite the time-critical sections of MRTG in C. The code was attached to his email. His tool increased the speed of MRTG by a factor of 40! This got me out of my 'MRTG ignorance' and I started to spend my spare time developing of MRTG-2. Soon after MRTG-2 development had begun I started to give beta copies to interested parties. In return I got many feature patches, a lot of user feedback and bug fixes. The product you are getting now wouldn't be in this state if it hadn't been for the great contributions and support I received from of many people. I would like to take this opportunity to thank them all. (See the files CHANGES for a long list of folk people who helped to make MRTG what it is today.) CCoommmmaanndd--lliinnee Mrtg is also the name of the script you have to run to poll data and generate the graphs. Most configuration is set through the configuration file; some command-line options exist all the same. ----uusseerr _u_s_e_r_n_a_m_e and ----ggrroouupp _g_r_o_u_p_n_a_m_e Run as the given user and/or group. (Unix Only) ----lloocckk--ffiillee _f_i_l_e_n_a_m_e Use an alternate lock-file (the default is to use the configuration-file appended with "_l"). ----ccoonnffccaacchhee--ffiillee _f_i_l_e_n_a_m_e Use an alternate confcache-file (the default is to use the configuration-file appended with ".ok") ----llooggggiinngg _f_i_l_e_n_a_m_e|eevveennttlloogg If this is set to writable filename, all output from mrtg (warnings, debug messages, errors) will go to _f_i_l_e_n_a_m_e. If you are running on Win32 you can specify eevveennttlloogg instead of a filename which will send all error to the windows event log. NNOOTTEE::Note, there is no Message DLL for mrtg. This has the side effect that the windows event logger will display a nice message with every entry in the event log, complaining about the fact that mrtg has no message dll. If any of the Windows folks want to contribute one, they are welcome. ----ddaaeemmoonn Put MRTG into the background, running as a daemon. This works the same way as the config file option, but the switch is required for proper FHS operation (because /var/run is writable only by root) ----ffhhss Configure all mrtg paths to conform to the FHS specification . The following default values are assumed: confcachefile - /var/lib/mrtg/mrtg.ok pid-file - /run/mrtg/mrtg.pid lock-file - /var/lock/mrtg/mrtg.lck log-file - /var/log/mrtg/mrtg.log ----cchheecckk Only check the cfg file for errors. Do not do anything. ----ppiidd--ffiillee==ss Define the name and path of the pid file for mrtg running as a daemon ----lloogg--oonnllyy Only update the logfile, do not produce graphics or html pages ----ddeebbuugg==ss Enable debug options. The argument of the debug option is a comma separated list of debug values: cfg - watch the config file reading dir - directory mangeling base - basic program flow tarp - target parser snpo - snmp polling fork - forking view time - some timing info log - logging of data via rateup or rrdtool Example: --debug="cfg,snpo" RREEAADD OONN Learn more about MRTG by going to the mrtg home page on: http://oss.oetiker.ch/mrtg AAUUTTHHOORR Tobias Oetiker and many contributors 2.17.10 2022-01-19 MRTG(1) mrtg-2.17.10/doc/mrtg-reference.txt0000644000175300017510000024601214171763417016101 0ustar oetikeroepMRTG-REFERENCE(1) mrtg MRTG-REFERENCE(1) NNAAMMEE mrtg-reference - MRTG 2.17.10 configuration reference OOVVEERRVVIIEEWW The runtime behaviour of MRTG is governed by a configuration file. Run-of-the-mill configuration files can be generated with ccffggmmaakkeerr. (Check cfgmaker). But for more elaborate configurations some hand- tuning is required. This document describes all the configuration options understood by the mrtg software. SSYYNNTTAAXX MRTG configuration file syntax follows some simple rules: +o Keywords must start at the beginning of a line. +o Lines which follow a keyword line which start with a blank are appended to the keyword line +o Empty Lines are ignored +o Lines starting with a # sign are comments. +o You can add other files into the configuration file using IInncclluuddee:: _f_i_l_e Example: Include: base-options.inc If included files are specified with relative paths, both the current working directory and the directory containing the main config file will be searched for the files. The current working directory will be searched first. If the included filename contains an asterisk, then this is taken as a wildcard for zero or more characters, and all matching files are included. Thus, you can use this statement to include all files in a specified subdirectory. Example: Include: servers/*.cfg In this case, you should be very careful that your wildcard pattern does not find a match relative to the current working directory if you mean it to be relative to the main config file directory, since the working directory is checked for a match first (as with a normal Include directive). Therefore, use of something like '*/*' is discouraged. GGLLOOBBAALL KKEEYYWWOORRDDSS WWoorrkkDDiirr WorkDir specifies where the logfiles and the webpages should be created. Example: WorkDir: /usr/tardis/pub/www/stats/mrtg OOPPTTIIOONNAALL GGLLOOBBAALL KKEEYYWWOORRDDSS HHttmmllDDiirr HtmlDir specifies the directory where the html (or shtml, but we'll get on to those later) lives. NOTE: Workdir overrides the settings for htmldir, imagedir and logdir. Example: Htmldir: /www/mrtg/ IImmaaggeeDDiirr ImageDir specifies the directory where the images live. They should be under the html directory. Example: Imagedir: /www/mrtg/images LLooggDDiirr LogDir specifies the directory where the logs are stored. This need not be under htmldir directive. Example: Logdir: /www/mrtg/logs FFoorrkkss ((UUNNIIXX oonnllyy)) With system that supports fork (UNIX for example), mrtg can fork itself into multiple instances while it is acquiring data via snmp. For situations with high latency or a great number of devices this will speed things up considerably. It will not make things faster, though, if you query a single switch sitting next door. As far as I know NT can not fork so this option is not available on NT. Example: Forks: 4 EEnnaabblleeIIPPvv66 When set to yes, IPv6 support is enabled if the required libraries are present (see the mrtg-ipv6 manpage). When IPv6 is enabled, mrtg can talk to routers using SNMP over IPv6 and targets may be specified by their numeric IPv6 addresses as well as by hostname or IPv4 address. If IPv6 is enabled and the target is a hostname, mrtg will try to resolve the hostname to an IPv6 address and, if this fails, to an IPv4 address. Note that mrtg will only use IPv4 if you specify an IPv4 address or a hostname with no corresponding IPv6 address; it will not fall back to IPv4 if it simply fails to communicate with the target using IPv6. This is by design. Note that many routers do not currently support SNMP over IPv6. Use the _I_P_v_4_O_n_l_y per target option for these routers. IPv6 is disabled by default. Example: EnableIPv6: Yes EEnnaabblleeSSnnmmppVV33 When set to yes, uses the Net::SNMP module instead of the SNMP_SESSION module for generating snmp queries. This allows the use of SNMPv3 if other snmpv3 parameters are set. SNMPv3 is disabled by default. Example: EnableSnmpV3: yes RReeffrreesshh How many seconds apart should the browser (Netscape) be instructed to reload the page? If this is not defined, the default is 300 seconds (5 minutes). Example: Refresh: 600 IInntteerrvvaall How often do you call mrtg? The default is 5 minutes. If you call it less often, you should specify it here. This does two things: +o The generated HTML page contains the right information about the calling interval ... +o A META header in the generated HTML page will instruct caches about the time-to-live of this page ..... In this example, we tell mrtg that we will be calling it every 10 minutes. If you are calling mrtg every 5 minutes, you can leave this line commented out. Example: Interval: 10 Note that unless you are using rrdtool you can not set Interval to less than 5 minutes. If you are using rrdtool you can set interval in the format Interval: MM[:SS] Down to 1 second. Note though, setting the Interval for an rrdtool/mrtg setup will influence the initial creation of the database. If you change the interval later, all existing databases will remain at the resolution they were initially created with. Also note that you must make sure that your mrtg-rrd Web-frontend can deal with this kind of Interval setting. MMaaxxAAggee MRTG relies heavily on the real time clock of your computer. If the time is set to a wrong value, especially if it is advanced far into the future, this will cause mrtg to expire lots of supposedly old data from the log files. To prevent this, you can add a 'reasonability' check by specifying a maximum age for log files. If a file seems to be older, mrtg will not touch it but complain instead, giving you a chance to investigate the cause. Example: MaxAge: 7200 The example above will make mrtg refuse to update log files older than 2 hours (7200 seconds). WWrriitteeEExxppiirreess With this switch mrtg will generate .meta files for CERN and Apache servers which contain Expiration tags for the html and gif files. The *.meta files will be created in the same directory as the other files, so you will have to set "MetaDir ." and "MetaFiles on" in your apache.conf or .htaccess file for this to work NOTE: If you are running Apache-1.2 or later, you can use the mod_expire to achieve the same effect ... see the file htaccess.txt Example: WriteExpires: Yes NNooMMiibb22 Normally we ask the SNMP device for 'sysUptime' and 'sysName' properties. Some do not have these. If you want to avoid getting complaints from mrtg about these missing properties, specify the nomib2 option. An example of agents which do not implement base mib2 attributes are Computer Associates - Unicenter TNG Agents. CA relies on using the base OS SNMP agent in addition to its own agents to supplement the management of a system. Example: NoMib2: Yes SSiinngglleeRReeqquueesstt Some SNMP implementations can not deal with requests asking for multiple snmp variables in one go. Set this in your cfg file to force mrtg to only ask for one variable per request. Examples SingleRequest: Yes SSnnmmppOOppttiioonnss Apart from the per target timeout options, you can also configure the behaviour of the snmpget process on a more profound level. SnmpOptions accepts a hash of options. The following options are currently supported: timeout => $default_timeout, retries => $default_retries, backoff => $default_backoff, default_max_repetitions => $max_repetitions, use_16bit_request_ids => 1, lenient_source_port_matching => 0, lenient_source_address_matching => 1 The values behind the options indicate the current default value. Note that these settings OVERRIDE the per target timeout settings. A per-target SnmpOptions[] keyword will override the global settings. That keyword is primarily for SNMPv3. The 16bit request ids are the only way to query the broken SNMP implementation of SMC Barricade routers. Example: SnmpOptions: retries => 2, only_ip_address_matching => 0 Note that AS/400 snmp seems to be broken in a way which prevents mrtg from working with it unless SnmpOptions: lenient_source_port_matching => 1 is set. IIccoonnDDiirr If you want to keep the mrtg icons in someplace other than the working (or imagedir) directory, use the _I_c_o_n_D_i_r variable for defining the url of the icons directory. Example: IconDir: /mrtgicons/ LLooaaddMMIIBBss Load the MIB file(s) specified and make its OIDs available as symbolic names. For better efficiency, a cache of MIBs is maintained in the WorkDir. Example: LoadMIBs: /dept/net/mibs/netapp.mib,/usr/local/lib/ft100m.mib LLaanngguuaaggee Switch output format to the selected Language (Check the _t_r_a_n_s_l_a_t_e directory to see which languages are supported at the moment. In this directory you can also find instructions on how to create new translations). Currently the following languages are supported: big5 brazilian bulgarian catalan chinese croatian czech danish dutch eucjp french galician gb gb2312 german greek hungarian icelandic indonesia iso2022jp italian korean lithuanian malay norwegian polish portuguese romanian russian russian1251 serbian slovak slovenian spanish swedish turkish ukrainian Example: Language: danish LLooggFFoorrmmaatt Setting LogFormat to 'rrdtool' in your mrtg.cfg file enables rrdtool mode. In rrdtool mode, mrtg relies on rrrrddttooooll to do its logging. See mrtg-rrd. Example: LogFormat: rrdtool LLiibbAAdddd If you are using rrdtool mode and your rrrrddttooooll Perl module (RRDs.pm) is not installed in a location where perl can find it on its own, you can use LibAdd to supply an appropriate path. Example: LibAdd: /usr/local/rrdtool/lib/perl/ PPaatthhAAdddd If the rrrrddttooooll executable can not be found in the normal "PATH", you can use this keyword to add a suitable directory to your path. Example: PathAdd: /usr/local/rrdtool/bin/ RRRRDDCCaacchheedd If you are running RRDTool 1.4 or later with rrrrddccaacchheedd, then you can configure MRTG to take advantage of this for updates, either by using the RRDCACHED_ADDRESS environment variable, or by setting the RRDCached keyword in the configuration file. Note that, if both are set, the configuration file keyword will take precedence. Only UNIX domain sockets are fully supported prior to RRDTool v1.5, and you should note that using RRDCached mode will disable all Threshold checking normally done by MRTG. Appropriate warning messages will be printed if necessary. Examples: RRDCached: unix:/var/tmp/rrdcached.sock RRDCached: localhost:42217 RRuunnAAssDDaaeemmoonn The RunAsDaemon keyword enables daemon mode operation. The purpose of daemon mode is that MRTG is launched once and not repeatedly (as it is with cron). This behavior saves computing resources as loading and parsing of configuration files happens only once on startup, and if the configuration file is modified. Using daemon mode MRTG itself is responsible for timing the measurement intervals. Therefore its important to set the Interval keyword to an appropriate value. Note that when using daemon mode MRTG should no longer be started from cron as each new process runs forever. Instead MRTG should be started from the command prompt or by a system startup script. If you want mrtg to run under a particular user and group (it is not recommended to run MRTG as root) then you can use the ----uusseerr==_u_s_e_r___n_a_m_e and ----ggrroouupp==_g_r_o_u_p___n_a_m_e options on the mrtg commandline. mrtg --user=mrtg_user --group=mrtg_group mrtg.cfg Also note that in daemon mode restarting the process is required in order to activate changes in the config file. Under UNIX, the Daemon switch causes mrtg to fork into background after checking its config file. On Windows NT the MRTG process will detach from the console, but because the NT/2000 shell waits for its children you have to use this special start sequence when you launch the program: start /b perl mrtg mrtg.cfg You may have to add path information equal to what you add when you run mrtg from the commandline. Example RunAsDaemon: Yes Interval: 5 This makes MRTG run as a daemon beginning data collection every 5 minutes If you are daemontools and still want to run mrtg as a daemon you can additionally specify NoDetach: Yes this will make mrtg run but without detaching it from the terminal. If the modification date on the configuration file changes during operation, then MRTG will re-read the configuration on the next polling cycle. Note that sub-files which are included from the main configuration do not have their modification times monitored, only the top-level file is so checked. CCoonnvveerrssiioonnCCooddee Some devices may produce non-numeric values that would nevertheless be useful to graph with MRTG if those values could be converted to numbers. The ConversionCode keyword specifies the path to a file containing Perl code to perform such conversions. The code in this file must consist of one or more Perl subroutines. Each subroutine must accept a single string argument and return a single numeric value. When RRDtool is in use, a decimal value may be returned. When the name of one of these subroutines is specified in a target definition (see below), MRTG calls it twice for that target, once to convert the the input value being monitored and a second time to convert the output value. The subroutine must return an undefined value if the conversion fails. In case of failure, a warning may be posted to the MRTG log file using Perl's warn function. MRTG imports the subroutines into a separate name space (package MRTGConversion), so the user need not worry about pollution of MRTG's global name space. MRTG automatically prepends this package declaration to the user-supplied code. Example: Suppose a particular OID returns a character string whose length is proportional to the value to be monitored. To convert this string to a number that can be graphed by MRTG, create a file arbitrarily named "MyConversions.pl" containing the following code: # Return the length of the string argument sub Length2Int { my $value = shift; return length( $value ); } Then include the following global keyword in the MRTG configuration file (assuming that the conversion code file is saved in the mrtg/bin directory along with mrtg itself): ConversionCode: MyConversions.pl This will cause MRTG to include the definition of the subroutine Length2Int in its execution environment. Length2Int can then be invoked on any target by appending "|Length2Int" to the target definition as follows: Target[myrouter]: 1.3.6.1.4.1.999.1&1.3.6.1.4.1.999.1:public@mydevice|Length2Int See "Extended Host Name Syntax" below for complete target definition syntax information. SSeennddTTooGGrraapphhiittee If you want to send a copy of the collected data into a Graphite database in addition to storing it in the RRDfile, you can provide your Graphite database name/ip and port number here. This requires the Net::Graphite perl module which is available from CPAN. Examples: # If your Graphite receiver is running on the same host as the MRTG daemon and using the default port SendToGraphite: 127.0.0.1,2003 # If your Graphite receiver is running on 192.168.100.50 port 5000 SendToGraphite: 192.168.100.50,5000 # If your Graphite receiver is running on graphite.mydomain.com port 2003 SendToGraphite: graphite.mydomain.com,2003 Graphite's namespace has a number of restrictions on what characters are allowed. The SendToGraphite functionality makes an attempt to convert the MRTG target name and, if specified, the Legendi and Legendo values to Graphite namespace friendly values. Specifically, the following conversion rules apply: +o Underscores in the target_name are converted to periods which are Graphite namespace delimiters. +o Comma characters are not allowed so they are removed. +o The string "m2g" for MRTG to Graphite is prepended onto the Graphite namespace variable. Example MRTG target to Graphite namespace conversion: # Our MRTG target name from mrtg.cfg is as follows Target[switch_GigabitEthernet0_5]: \GigabitEthernet0/5:public1@switch:::::2 After the conversion you will end up with these Graphite namespace values m2g.switch.gigabitethernet0.5.in m2g.switch.gigabitethernet0.5.out Next is a more complicated example because Legendi and Legendo are in use to denote min and max voltage values that pertain to some APC UPS SNMP OIDs # Target, Legendi, and Legendo are specified in mrtg.cfg as follows Target[apc_minmaxline]: 1.3.6.1.4.1.318.1.1.1.3.2.3.0&1.3.6.1.4.1.318.1.1.1.3.2.2.0:public@apc: LegendI[apc_minmaxline]: upsAdvInputMinLineVoltage LegendO[apc_minmaxline]: upsAdvInputMaxLineVoltage After the conversion you will end up with these Graphite namespace values m2g.apc.minmaxline.upsAdvInputMinLineVoltage m2g.apc.minmaxline.upsAdvInputMaxLineVoltage If you don't see the data showing up in Graphite, chances are there are invalid characters in the namespace. To debug this, use the DEBUG=qw(log) directive at the top of the MRTG script to find out what is happening with the MRTG to Graphite namespace conversion. DEBUG=qw(log) will generate some output similar to what appears below 2016-10-13 06:08:39 -- --log: RRDs::update(/var/www/mrtg/switch/switch_gigabitethernet0_5.rrd, '1476356919:2738746035:2927936327') 2016-10-13 06:08:39 -- --log: graphite->send(m2g.switch.gigabitethernet0.5.in,2738746035,1476356919) 2016-10-13 06:08:39 -- --log: graphite->send(m2g.switch.gigabitethernet0.5.out,2927936327,1476356919) 2016-10-13 06:09:25 -- --log: RRDs::update(/var/www/mrtg/apc/apc_minmaxline.rrd, '1476356965:122:123') 2016-10-13 06:09:25 -- --log: graphite->send(m2g.apc.minmaxline.upsAdvInputMinLineVoltage,122,1476356965) 2016-10-13 06:09:25 -- --log: graphite->send(m2g.apc.minmaxline.upsAdvInputMaxLineVoltage,123,1476356965) If the MRTG log output looks reasonable, then take a look at Graphite's carbon-cache logs. PPEERR TTAARRGGEETT CCOONNFFIIGGUURRAATTIIOONN Each monitoring target must be identified by a unique name. This name must be appended to each parameter belonging to the same target. The name will also be used for naming the generated webpages, logfiles and images for this target. TTaarrggeett With the _T_a_r_g_e_t keyword you tell mrtg what it should monitor. The _T_a_r_g_e_t keyword takes arguments in a wide range of formats: Basic The most basic format is "port:community@router" This will generate a traffic graph for the interface 'port' of the host 'router' (dns name or IP address) and it will use the community 'community' (snmp password) for the snmp query. Example: Target[myrouter]: 2:public@wellfleet-fddi.domain If your community contains a "@" or a " " these characters must be escaped with a "\". Target[bla]: 2:stu\ pi\@d@router SNMPv2c If you have a fast router you might want to try to poll the ifHC* counters. This feature gets activated by switching to SNMPv2c. Unfortunately not all devices support SNMPv2c yet. If it works, this will prevent your counters from wrapping within the 5 minute polling interval, since we now use 64 bit instead of the normal 32 bit. Example: Target[myrouter]: 2:public@router1:::::2 SNMPv3 As an alternative to SNMPv2c, SNMPv3 provides access to the ifHC* counters, along with encryption. Not all devices support SNMPv3, and you will also need the perl Net::SNMP library in order to use it. It is recommended that cfgmaker be used to generate configurations involving SNMPv3, as it will check if the Net::SNMP library is loadable, and will switch to SNMPv2c if v3 is unavailable. SNMP v3 requires additional authentication parameters, passed using the SnmpOptions[] per-target keyword. Example: Target[myrouter]: 2:router1:::::3 SnmpOptions[myrouter]: username=>'user1' noHC Not all routers that support SNMPv2 or SNMPv3 provide the ifHC* counters on every interface. The noHC[] per-target keyword signals that the low-speed counters ifInOctets and ifOutOctets should be queried instead. cfgmaker will automatically insert this tag if SNMPv2 or SNMPv3 is specified but the ifHC* counters are unavailable. Example: Target[myrouter]: #Bri0:router1:::::3 SnmpOptions[myrouter]: username=>'user1' noHC[myrouter]: yes Reversing Sometimes you are sitting on the wrong side of the link, and you would like to have mrtg report Incoming traffic as Outgoing and vice versa. This can be achieved by adding the '-' sign in front of the "Target" description. It flips the incoming and outgoing traffic rates. Example: Target[ezci]: -1:public@ezci-ether.domain Explicit OIDs You can also explicitly define which OID to query by using the following syntax 'OID_1&OID_2:community@router' The following example will retrieve error counts for input and output on interface 1. MRTG needs to graph two variables, so you need to specify two OID's such as temperature and humidity or error input and error output. Example: Target[myrouter]: 1.3.6.1.2.1.2.2.1.14.1&1.3.6.1.2.1.2.2.1.20.1:public@myrouter MIB Variables MRTG knows a number of symbolic SNMP variable names. See the file mibhelp.txt for a list of known names. One example are the ifInErrors and ifOutErrors. This means you can specify the above as: Example: Target[myrouter]: ifInErrors.1&ifOutErrors.1:public@myrouter SnmpWalk It may be that you want to monitor an snmp object that is only reachable by 'walking'. You can get mrtg to walk by prepending the OID with the string WWaaLLKK or if you want a particular entry from the table returned by the walk you can use WWaaLLKK_x where _x is a number starting from 0 (!). Example: Target[myrouter]: WaLKstrangeOid.1&WaLKstrangeOid.2:public@myrouter Target[myrouter]: WaLK3strangeOid.1&WaLK4strangeOid.2:public@myrouter SnmpGetNext A special case of an snmp object that is only reachable by 'walking' occurs when a single snmpgetnext will return the correct value, but snmpwalk fails. This may occur with snmp V2 or V3, as the snmpgetbulk method is used in these versions. You can get mrtg to use getnext instead of getbulk by prepending the OID with the string GGeeTTNNEEXXTT. Example: Target[myrouter]: GeTNEXTstrangeOid&GeTNEXTstrangeOid:public@myrouter Counted SNMP Walk In other situations, an snmpwalk is needed to count rows, but the actual data is uninteresting. For example, counting the number of mac-addresses in a CAM table, or the number of simultaneous dialup sessions. You can get MRTG to count the number of instances by prepending the OID with the string CCnnTTWWaaLLKK. The following will retrieve the number of simultaneous VOIP calls on some routers: Example: Target[myrouter]: CnTWaLK1.3.6.1.4.1.9.10.55.1.1.1.1.3&CnTWaLK1.3.6.1.4.1.9.10.55.1.1.1.1.3:public@myrouter Interface by IP Sometimes SNMP interface index can change, like when new interfaces are added or removed. This can cause all Target entries in your config file to become offset, causing MRTG to graphs wrong instances etc. MRTG supports IP address instead of ifindex in target definition. Then MRTG will query snmp device and try to map IP address to the current ifindex. You can use IP addresses in every type of target definition by adding IP address of the numbered interface after OID and separation char '/'. Make sure that the given IP address is used on your same target router, especially when graphing two different OIDs and/or interface split by '&' delimiter. You can tell cfgmaker to generate such references with the option ----iiffrreeff==iipp. Example: Target[myrouter]: /1.2.3.4:public@wellfleet-fddi.domain Target[ezci]: -/1.2.3.4:public@ezci-ether.domain Target[myrouter]: ifInErrors/1.2.3.4&ifOutErrors/1.2.3.4:public@myrouter Interface by Description If you can not use IP addresses you might want to use the interface names. This works similar to the IP address approach except that the prefix to use is a \ instead of a / You can tell cfgmaker to generate such references with the option ----iiffrreeff==ddeessccrr. Example: Target[myrouter]: \My-Interface2:public@wellfleet-fddi.domain Target[ezci]: -\My-Interface2:public@ezci-ether.domain Target[myrouter]: ifInErrors\My-If2&ifOutErrors\My-If3:public@myrouter If your description contains a "&", a ":", a "@" or a " " you can include them but you must escape with a backlash: Target[myrouter]: \fun\:\ ney\&ddd:public@hello.router Interface by Name This is the only sensible way to reference the interfaces of your switches. You can tell cfgmaker to generate such references with the option ----iiffrreeff==nnaammee. Example: Target[myrouter]: #2/11:public@wellfleet-fddi.domain Target[ezci]: -#2/11:public@ezci-ether.domain Target[myrouter]: ifInErrors#3/7&ifOutErrors#3/7:public@myrouter If your description contains a "&", a ":", a "@" or a " " you can include them but you must escape with a backlash: Target[myrouter]: #\:\ fun:public@hello.router Note that the # sign will be interpreted as a comment character if it is the first non white-space character on the line. Interface by Ethernet Address When the SNMP interface index changes, you can key that interface by its 'Physical Address', sometimes called a 'hard address', which is the SNMP variable 'ifPhysAddress'. Internally, MRTG matches the Physical Address from the *.cfg file to its current index, and then uses that index for the rest of the session. You can use the Physical Address in every type of target definition by adding the Physical Address after the OID and the separation char '!' (analogous to the IP address option). The Physical address is specified as '-' delimited octets, such as "0a-0-f1-5-23-18" (omit the double quotes). Note that some routers use the same Hardware Ethernet Address for all of their Interfaces which prevents unique interface identification. Mrtg will notice such problems and alert you. You can tell cfgmaker to generate configuration files with hardware ethernet address references by using the option ----iiffrreeff==eetthh. Example: Target[myrouter]: !0a-0b-0c-0d:public@wellfleet-fddi.domain Target[ezci]: -!0-f-bb-05-71-22:public@ezci-ether.domain Target[myrouter]: 1.3.6.1.2.1.2.2.1.14!0a-00-10-23-44-51& *BREAK* 1.3.6.1.2.1.2.2.1.14!0a-00-10-23-44-51:public@myrouter Target[myrouter]: ifInErrors!0a-00-10-23-44-51& *BREAK* ifOutErrors!0a-00-10-23-44-51:public@myrouter Join the lines at *BREAK* ... Interface by Type It seems that there are devices that try to defy all monitoring efforts: the interesting interfaces have neither ifName nor a constant ifDescr not to mention a persistent ifIndex. The only way to get a constant mapping is by looking at the interface type, because the interface you are interested in is unique in the device you are looking at ... You can tell cfgmaker to generate such references with the option ----iiffrreeff==ttyyppee. Example: Target[myrouter]: %13:public@wellfleet-fddi.domain Target[ezci]: -%13:public@ezci-ether.domain Target[myrouter]: ifInErrors%13&ifOutErrors%14:public@myrouter Extended positioning of ifIndex There are OIDs that contain the interface index at some inner position within the OID. To use the above mentioned Interface by IP/Description/Name/Type methods in the target definition the keyword 'IndexPOS' can be used to indicate the position of ifIndex. If 'IndexPOS' is not used the ifIndex will be appended at the end of the OID. Example: Target[myrouter]: OID.IndexPOS.1/1.2.3.4&OID.IndexPOS.1/1.2.3.4:public@myrouter Replace OID by your numeric OID. Extended Host Name Syntax In all places where ``community@router'' is accepted, you can add additional parameters for the SNMP communication using colon- separated suffixes. You can also append a pipe symbol ( | ) and the name of a numeric conversion subroutine as described under the global keyword "ConversionCode" above. The full syntax is as follows: community@router[:[port][:[timeout][:[retries][:[backoff][:[version]]]]][|name] where the meaning of each parameter is as follows: port the UDP port under which to contact the SNMP agent (default: 161) The complete syntax of the port parameter is remote_port[!local_address[!local_port]] Some machines have additional security features that only allow SNMP queries to come from certain IP addresses. If the host doing the query has multiple interface, it may be necessary to specify the interface the query should come from. The port parameter allows the specification of the port of the machine being queried. In addition, the IP address (or hostname) and port of the machine doing the query may be specified. Examples: somehost somehost:161 somehost:161!192.168.2.4!4000 use 192.168.2.4 and port 4000 as source somehost:!192.168.2.4 use 192.168.2.4 as source somehost:!!4000 use port 4000 as source timeout initial timeout for SNMP queries, in seconds (default: 2.0) retries number of times a timed-out request will be retried (default: 5) backoff factor by which the timeout is multiplied on every retry (default: 1.0). version for SNMP version. If you have a fast router you might want to put a '2' here. For authenticated or encrypted SNMP, you can try to put a '3' here. This will make mrtg try to poll the 64 bit counters and thus prevent excessive counter wrapping. Not all routers support this though. SNMP v3 requires additional setup, see SnmpOptions[] for full details. Example: 3:public@router1:::::2 name the name of the subroutine that MRTG will call to convert the input and output values to integers. See the complete example under the global keyword "ConversionCode" above. Example: 1.3.6.1.4.1.999.1&1.3.6.1.4.1.999.2:public@mydevice:161::::2|Length2Int This would retrieve values from the OID 1.3.6.1.4.1.999.1 for input and .2 for output on mydevice using UDP port 161 and SNMP version 2, and would execute the user-defined numeric conversion subroutine Length2Int to convert those values to integers. A value that equals the default value can be omitted. Trailing colons can be omitted, too. The pipe symbol followed by the name parameter, if present, must come at the end. There must be no spaces around the colons or pipe symbol. Example: Target[ezci]: 1:public@ezci-ether.domain:9161::4 This would refer to the input/output octet counters for the interface with _i_f_I_n_d_e_x _1 on _e_z_c_i_-_e_t_h_e_r_._d_o_m_a_i_n, as known by the SNMP agent listening on UDP port 9161. The standard initial timeout (2.0 seconds) is used, but the number of retries is set to four. The backoff value is the default. Numeric IPv6 addresses If IPv6 is enabled you may also specify a target using its IPv6 address. To avoid ambiguity with the port number, numeric IPv6 addresses must be placed in square brackets. Example: Target[IPv6test]: 2:public@[2001:760:4::]:6161::4 External Monitoring Scripts If you want to monitor something which does not provide data via snmp you can use some external program to do the data gathering. The external command must return 4 lines of output: Line 1 current state of the first variable, normally 'incoming bytes count' Line 2 current state of the second variable, normally 'outgoing bytes count' Line 3 string (in any human readable format), telling the uptime of the target. Line 4 string, telling the name of the target. Depending on the type of data your script returns you might want to use the 'gauge' or 'absolute' arguments for the _O_p_t_i_o_n_s keyword. Example: Target[myrouter]: `/usr/local/bin/df2mrtg /dev/dsk/c0t2d0s0` Note the use of the backticks (`), not apostrophes (') around the command. If you want to use a backtick in the command name this can be done but you must escape it with a backslash ... If your script does not have any data to return but does not want mrtg to complain about invalid data, it can return 'UNKNOWN' instead of a number. Note though that only rrdtool is really equipped to handle unknown data well. Multi Target Syntax You can also combine several target definitions in a mathematical expression. Any syntactically correct expression that the Perl interpreter can evaluate to will work. An expression could be used, for example, to aggregate both B channels in an ISDN connection or to calculate the percentage hard disk utilization of a server from the absolute used space and total capacity. Examples: Target[myrouter]: 2:public@wellfleetA + 1:public@wellfleetA Target[myrouter]: .1.3.6.1.4.1.999.1&.1.3.6.1.4.1.999.2:public@mydevice / .1.3.6.1.4.1.999.3&.1.3.6.1.4.1.999.4:public@mydevice * 100 Note that whitespace must surround each target definition in the expression. Target definitions themselves must not contain whitespace, except in interface descriptions and interface names, where each whitespace character is escaped by a backslash. MRTG automatically rounds the result of the expression to an integer unless RRDTool logging is in use and the gauge option is in effect for the target. Internally MRTG uses Perl's Math::BigFloat package to calculate the result of the expression with 40 digits of precision. Even in extreme cases, where, for example, you take the difference of two 64-bit integers, the result of the expression should be accurate. SNMP Request Optimization MRTG is designed to economize on its SNMP requests. Where a target definition appears more than once in the configuration file, MRTG requests the data from the device only once per round of data collection and uses the collected data for each instance of a particular target. Recognition of two target definitions as being identical is based on a simple string match rather than any kind of deeper semantic analysis. Example: Target[Targ1]: 1:public@CiscoA Target[Targ2]: 2:public@CiscoA Target[Targ3]: 1:public@CiscoA + 2:public@CiscoA Target[Targ4]: 1:public@CISCOA This results in a total of three SNMP requests. Data for 1:public@CiscoA and 2:public@CiscoA are requested only once each, and used for Targ1, Targ2, and Targ3. Targ4 causes another SNMP request for 1:public@CISCOA, which is not recognized as being identical to 1:public@CiscoA. MMaaxxBByytteess The maximum value either of the two variables monitored are allowed to reach. For monitoring router traffic this is normally the bytes per second this interface port can carry. If a number higher than _M_a_x_B_y_t_e_s is returned, it is ignored. Also read the section on _A_b_s_M_a_x for further info. The _M_a_x_B_y_t_e_s value is also used in calculating the Y range for unscaled graphs (see the section on _U_n_s_c_a_l_e_d). Since most links are rated in bits per second, you need to divide their maximum bandwidth (in bits) by eight (8) in order to get bytes per second. This is very important to make your unscaled graphs display realistic information. T1 = 193000, 56K = 7000, 10 MB Ethernet = 1250000, 100 MB Ethernet = 12500000. The _M_a_x_B_y_t_e_s value will be used by mrtg to decide whether it got a valid response from the router. If you need two different MaxBytes values for the two monitored variables, you can use MaxBytes1 and MaxBytes2 instead of MaxBytes. Example: MaxBytes[myrouter]: 1250000 TTiittllee Title for the HTML page which gets generated for the graph. Example: Title[myrouter]: Traffic Analysis for Our Nice Company OOPPTTIIOONNAALL PPEERR TTAARRGGEETT KKEEYYWWOORRDDSS PPaaggeeTToopp Things to add to the top of the generated HTML page. Note that you can have several lines of text as long as the first column is empty. Note that the continuation lines will all end up on the same line in the html page. If you want linebreaks in the generated html use the '\n' sequence. Example: PageTop[myrouter]:

      Traffic Analysis for ETZ C95.1

      Our Campus Backbone runs over an FDDI line\n with a maximum transfer rate of 12.5 megabytes per Second. RRoouutteerrUUppttiimmee In cases where you calculate the used bandwidth from several interfaces you normally don't get the router uptime and router name displayed on the web page. If these interfaces are on the same router and the uptime and name should be displayed you have to specify its community and address again with the _R_o_u_t_e_r_U_p_t_i_m_e keyword. If you want to use a special OID for querying the router uptime, use prepend the oid. Example: Target[kacisco.comp.edu]: 1:public@194.64.66.250 + 2:public@194.64.66.250 RouterUptime[kacisco.comp.edu]: public@194.64.66.250 RouterUptime[kacisco.comp.edu]: hrSystemUptime.0:public@194.64.66.250 RRoouutteerrNNaammee If the default name of the router is incorrect/uninformative, you can use RouterName to specify a different OID on either the same or a different host. A practical example: sysName on BayTech DS72 units always display "ds72", no matter what you set the Unit ID to be. Instead, the Unit ID is stored at 1.3.6.1.4.1.4779.1.1.3.0, so we can have MRTG display this instead of sysName. Example: RouterName[kacisco.comp.edu]: 1.3.6.1.4.1.4779.1.1.3.0 A different OID on a different host can also be specified: RouterName[kacisco.comp.edu]: 1.3.6.1.4.1.4779.1.1.3.0:public@194.64.66.251 MMaaxxBByytteess11 Same as MaxBytes, for variable 1. MMaaxxBByytteess22 Same as MaxBytes, for variable 2. IIPPvv44OOnnllyy Many IPv6 routers do not currently support SNMP over IPv6 and must be monitored using IPv4. The IPv4Only option forces mrtg to use IPv4 when communicating with the target, even if IPv6 is enabled. This is useful if the target is a hostname with both IPv4 and IPv6 addresses; without the IPv4Only keyword, monitoring such a router will not work if IPv6 is enabled. If set to no (the default), mrtg will use IPv6 unless the target has no IPv6 addresses, in which case it will use IPv4. If set to yes, mrtg will only use IPv4. Note that if this option is set to yes and the target does not have an IPv4 address, communication with the target will fail. This option has no effect if IPv6 is not enabled. Example: Target[v4onlyrouter_1]: 1:public@v4onlyrouter IPv4Only[v4onlyrouter_1]: Yes SSnnmmppOOppttiioonnss ((VV33)) SNMPv3 requires a fairly rich set of options. This per-target keyword allows access to the User Security Model of SNMPv3. Options are listed in the same syntax as a perl hash. _S_e_c_u_r_i_t_y _M_o_d_e_s SNMPv3 has three security modes, defined on the device being polled. For example, on Cisco routers the security mode is defined by the snmp- server group global configuration command. NoAuthNoPriv Neither Authentication nor Privacy is defined. Only the Username option is specified for this mode. Example: SnmpOptions[myrouter]: username=>'user1' AuthNoPriv Uses a Username and a password. The password can be hashed using the snmpkey application, or passed in plain text along with the ContextEngineID Example: SnmpOptions[myrouter]: username=>'user1',authpassword=>'example', contextengineid=>'80000001110000004000000' Priv Both Authentication and Privacy is defined. The default privacy protocol is des. Example: SnmpOptions[myrouter]: authkey=>'0x1e93ab5a396e2af234c8920e61cfe2028072c0e2', authprotocol=>'sha',privprotocol=>'des',username=>'user1', privkey=>'0x498d74940c5872ed387201d74b9b25e2' _s_n_m_p _o_p_t_i_o_n_s The following option keywords are recognized: username The user associated with the User Security Model contextname An SNMP agent can define multiple contexts. This keyword allows them to be polled. contextengineid A unique 24-byte string identifying the snmp-agent. authpassword The plaintext password for a user in either AuthNoPriv or Priv mode. authkey A md5 or sha hash of the plain-text password, along with the engineid. Use the snmpkey commandline program to generate this hash, or use Net::SNMP::Security::USM in a script. authprotocol {sha|md5} The hashing algorithm defined on the SNMP client. Defaults to md5. privpassword A plaintext pre-shared key for encrypting snmp packets in Priv mode. privkey A hash of the plain-text pre-shared key, along with the engineid. Use the snmpkey commandline program to generate this hash, or use Net::SNMP::Security::USM in a script. privprotocol {des|3desede|aescfb128|aescfb192|aescfb256} Specifies the encryption method defined on the snmp agent. The default is des. PPaaggeeFFoooott Things to add to the bottom of the generated HTML page. Note that you can have several lines of text as long as the first column is empty. Note that the continuation lines will all end up on the same line in the html page. If you want linebreaks in the generated html use the '\n' sequence. The material will be added just before the tag: Example: PageFoot[myrouter]: Contact
      Peter if you have questions regarding this page AAddddHHeeaadd Use this tag like the _P_a_g_e_T_o_p header, but its contents will be added between and . Example: AddHead[myrouter]: BBooddyyTTaagg BodyTag lets you supply your very own tag for the generated webpages. Example: BodyTag[myrouter]: AAbbssMMaaxx If you are monitoring a link which can handle more traffic than the _M_a_x_B_y_t_e_s value. Eg, a line which uses compression or some frame relay link, you can use the _A_b_s_M_a_x keyword to give the absolute maximum value ever to be reached. We need to know this in order to sort out unrealistic values returned by the routers. If you do not set _A_b_s_M_a_x, rateup will ignore values higher than _M_a_x_B_y_t_e_s. Example: AbsMax[myrouter]: 2500000 UUnnssccaalleedd By default each graph is scaled vertically to make the actual data visible even when it is much lower than _M_a_x_B_y_t_e_s. With the _U_n_s_c_a_l_e_d variable you can suppress this. It's argument is a string, containing one letter for each graph you don't want to be scaled: d=day w=week m=month y=year. There is also a special case to unset the variable completely: n=none. This could be useful in the event you need to override a global configuration. In the example scaling for the yearly and the monthly graph are suppressed. Example: Unscaled[myrouter]: ym WWiitthhPPeeaakk By default the graphs only contain the average values of the monitored variables - normally the transfer rates for incoming and outgoing traffic. The following option instructs mrtg to display the peak 5 minute values in the [w]eekly, [m]onthly and [y]early graph. In the example we define the monthly and the yearly graph to contain peak as well as average values. Examples: WithPeak[myrouter]: ym SSuupppprreessss By default mrtg produces 4 graphs. With this option you can suppress the generation of selected graphs. The option value syntax is analogous to the above two options. In this example we suppress the yearly graph as it is quite empty in the beginning. Example: Suppress[myrouter]: y EExxtteennssiioonn By default, mrtg creates .html files. Use this option to tell mrtg to use a different extension. For example you could set the extension to php3, then you will be able to enclose PHP tags into the output (useful for getting a router name out of a database). Example: Extension[myrouter]: phtml DDiirreeccttoorryy By default, mrtg puts all the files that it generates for each target (the GIFs, the HTML page, the log file, etc.) in _W_o_r_k_D_i_r. If the _D_i_r_e_c_t_o_r_y option is specified, the files are instead put into a directory under _W_o_r_k_D_i_r or Log-, Image- and HtmlDir). (For example the _D_i_r_e_c_t_o_r_y option below would cause all the files for a target myrouter to be put into directory /usr/tardis/pub/www/stats/mrtg/myrouter/ .) The directory must already exist; mrtg will not create it. Example: WorkDir: /usr/tardis/pub/www/stats/mrtg Directory[myrouter]: myrouter NOTE: the Directory option must always be 'relative' or bad things will happen. CClloonneeddiirreeccttoorryy If the _D_i_r_e_c_t_o_r_y option is specified, the _C_l_o_n_e_d_i_r_e_c_t_o_r_y option will copy all the contents of _D_i_r_e_c_t_o_r_y to the _C_l_o_n_e_d_i_r_e_c_t_o_r_y. Example: WorkDir: /usr/tardis/pub/www/stats/mrtg Directory[myrouter]: myrouter Clonedirectory[myrouter]: myclonedirectory Optionally the target name can be changed in the cloning process. Example: WorkDir: /usr/tardis/pub/www/stats/mrtg Directory[myrouter]: myrouter Clonedirectory[myrouter]: myclonedirectory mynewtarget NOTE1: The clone directory must already exist; mrtg will not create it. NOTE2: The Clonedirectory option must also always be 'relative' or bad things will happen. NOTE3: This requires the File::Copy module XXSSiizzee aanndd YYSSiizzee By default mrtgs graphs are 100 by 400 pixels wide (plus some more for the labels. In the example we get almost square graphs ... Note: XSize must be between 20 and 600; YSize must be larger than 20 Example: XSize[myrouter]: 300 YSize[myrouter]: 300 XXZZoooomm aanndd YYZZoooomm If you want your graphs to have larger pixels, you can "Zoom" them. Example: XZoom[myrouter]: 2.0 YZoom[myrouter]: 2.0 XXSSccaallee aanndd YYSSccaallee If you want your graphs to be actually scaled use _X_S_c_a_l_e and _Y_S_c_a_l_e. (Beware: while this works, the results look ugly (to be frank) so if someone wants to fix this: patches are welcome. Example: XScale[myrouter]: 1.5 YScale[myrouter]: 1.5 YYTTiiccss aanndd YYTTiiccssFFaaccttoorr If you want to show more than 4 lines per graph, use YTics. If you want to scale the value used for the YLegend of these tics, use YTicsFactor. The default value for YTics is 4 and the default value for YTicsFactor is 1.0 . Example: Suppose you get values ranging from 0 to 700. You want to plot 7 lines and want to show 0, 1, 2, 3, 4, 5, 6, 7 instead of 0, 100, 200, 300, 400, 500, 600, 700. You should write then: YTics[myrouter]: 7 YTicsFactor[myrouter]: 0.01 FFaaccttoorr If you want to multiply all numbers shown below the graph with a constant factor, use this directive to define it .. Example: Factor[as400]: 4096 SStteepp Change the default step from 5 * 60 seconds to something else (I have not tested this much ...) Example: Step[myrouter]: 60 PPNNGGTTiittllee When using rateup for graph generation, this will print the given title in the graph it generates. Example: PNGTitle[myrouter]: WAN Link UK-US OOppttiioonnss The _O_p_t_i_o_n_s Keyword allows you to set some boolean switches: growright The graph grows to the left by default. This option flips the direction of growth causing the current time to be at the right edge of the graph and the history values to the left of it. bits All the monitored variable values are multiplied by 8 (i.e. shown in bits instead of bytes) ... looks much more impressive :-) It also affects the 'factory default' labeling and units for the given target. perminute All the monitored variable values are multiplied by 60 (i.e. shown in units per minute instead of units per second) in case of small values more accurate graphs are displayed. It also affects the 'factory default' labeling and units for the given target. perhour All the monitored variable values are multiplied by 3600 (i.e. shown in units per hour instead of units per second) in case of small values more accurate graphs are displayed. It also affects the 'factory default' labeling and units for the given target. noinfo Suppress the information about uptime and device name in the generated webpage. nopercent Don't print usage percentages. transparent Make the background of the generated gifs transparent. integer Print summary lines below graph as integers without commas. dorelpercent The relative percentage of IN-traffic to OUT-traffic is calculated and displayed in the graph as an additional line. Note: Only a fixed scale is available (from 0 to 100%). Therefore if IN-traffic is greater than OUT-traffic then 100% is displayed. If you suspect that your IN-traffic is not always less than or equal to your OUT- traffic you are urged to not use this options. Note: If you use this option in combination with the _C_o_l_o_u_r_s options, a fifth colour-name colour-value pair is required there. avgpeak There are some ISPs who use the average Peak values to bill their customers. Using this option MRTG displays these values for each graph. The value is built by averaging the max 5 minute traffic average for each 'step' shown in the graph. For the Weekly graph this means that it builds the average of all 2 hour intervals 5 minute peak values. (Confused? Thought so!) gauge Treat the values gathered from target as 'current status' measurements and not as ever incrementing counters. This would be useful to monitor things like disk space, processor load, temperature, and the like ... In the absence of 'gauge' or 'absolute' options, MRTG treats variables as a counters and calculates the difference between the current and the previous value and divides that by the elapsed time between the last two readings to get the value to be plotted. absolute This is for counter type data sources which reset their value when they are read. This means that rateup does not have to build the difference between the current and the last value read from the data source. The value obtained is still divided by the elapsed time between the current and the last reading, which makes it different from the 'gauge' option. Useful for external data gatherers. derive If you are using rrdtool as logger/grapher you can use a third type of data source. Derive is like counter, except that it is not required to go UP all the time. It is useful for situations where the change of some value should be graphed. unknaszero Log unknown data as zero instead of the default behaviour of repeating the last value seen. Be careful with this, often a flat line in the graph is much more obvious than a line at 0. withzeroes Normally we ignore all values which are zero when calculating the average transfer rate on a line. If this is not desirable use this option. noborder If you are using rateup to log data, MRTG will create the graph images. Normally these images have a shaded border around them. If you do not want the border to be drawn, enable this option. This option has no effect if you are not using rateup. noarrow As with the option above, this effects rateup graph generation only. Normally rateup will generate graphs with a small arrow showing the direction of the data. If you do not want this arrow to be drawn, enable this option. This option has no effect if you are not using rateup. noi When using rateup for graph generation, you can use this option to stop rateup drawing a graph for the 'I' or first variable. This also removes entries for this variable in the HTML page MRTG generates, and will remove the peaks for this variable if they are enabled. This allows you to hide this data, or can be very useful if you are only graphing one line of data rather than two. This option is not destructive - any data received for the the variable continued to be logged, it just isn't shown. noo Same as above, except relating to the 'O' or second variable. nobanner When using rateup for graph generation, this option disables MRTG adding the MRTG banner to the HTML pages it generates. nolegend When using rateup for graph generation, this option will stop MRTG from creating a legend at the bottom of the HTML pages it generates. printrouter When using rateup for graph generation, this option will print the router name in the graph it generates. This option is overridden by the value of PNGTitle if one is given pngdate When using rateup for graph generation, this option will print a timestamp in the graph it generates, including a timezone if one is specified by the 'Timezone' parameter. This is equivalent to setting TimeStrPost[x]: RU logscale The llooggssccaallee option causes rateup to display the data with the Y axis scaled logarithmically. Doing so allows the normal traffic to occupy the majority of the vertical range, while still showing any spikes at their full height. llooggssccaallee displays all the available data and will always produce well-behaved graphs. People often consider a logarithmically scaled graph counterintuitive, however, and thus hard to interpret. expscale The eexxppssccaallee option causes rateup to display the data with the Y axis scaled exponentially. Doing so emphasizes small changes at the top of the scale; this can be useful when graphing values that fluctuate by a small amount near the top of the scale, such as line voltage. eexxppssccaallee is essentially the inverse of llooggssccaallee. secondmean The sseeccoonnddmmeeaann option sets the maximum value on the graph to the mean of the data greater than the mean of all data. This produces a graph that focuses more on the typical data, while clipping large peaks. Using sseeccoonnddmmeeaann will give a more intuitive linearly scaled graph, but can result in a uselessly high or low scale in some rare situations (specifically, when the data includes a large portion of values far from the actual mean) If a target includes both llooggssccaallee and sseeccoonnddmmeeaann in the options, the sseeccoonnddmmeeaann takes precedence. Example: Options[myrouter]: growright, bits kkiilloo Use this option to change the multiplier value for building prefixes. Defaultvalue is 1000. This tag is for the special case that 1kB = 1024B, 1MB = 1024kB and so far. Example: kilo[myrouter]: 1024 kkMMGG Change the default multiplier prefixes (,k,M,G,T,P). In the tag _S_h_o_r_t_L_e_g_e_n_d define only the basic units. Format: Comma separated list of prefixed. Two consecutive commas or a comma at start or end of the line gives no prefix on this item. If you do not want prefixes, just put two consecutive commas. If you want to skip a magnitude select '-' as value. Example: velocity in nm/s (nanometers per second) displayed in nm/h. ShortLegend[myrouter]: m/h kMG[myrouter]: n,u,m,,k,M,G,T,P options[myrouter]: perhour CCoolloouurrss The _C_o_l_o_u_r_s tag allows you to override the default colour scheme. Note: All 4 of the required colours must be specified here. The colour name ('Colourx' below) is the legend name displayed, while the RGB value is the real colour used for the display, both on the graph and in the html doc. Format is: Col1#RRGGBB,Col2#RRGGBB,Col3#RRGGBB,Col4#RRGGBB Important: If you use the _d_o_r_e_l_p_e_r_c_e_n_t options tag a fifth colour name colour value pair is required: Col1#RRGGBB,Col2#RRGGBB,Col3#RRGGBB,Col4#RRGGBB,Col5#RRGGBB Colour1 First variable (normally Input) on default graph. Colour2 Second variable (normally Output) on default graph. Colour3 Max first variable (input). Colour4 Max second variable (output). RRGGBB 2 digit hex values for Red, Green and Blue. Example: Colours[myrouter]: GREEN#00eb0c,BLUE#1000ff,DARK GREEN#006600,VIOLET#ff00ff BBaacckkggrroouunndd With the _B_a_c_k_g_r_o_u_n_d tag you can configure the background colour of the generated HTML page. Example: Background[myrouter]: #a0a0a0a TTeexxttCCoolloorr With the _T_e_x_t_C_o_l_o_r tag you can configure the text colour of the generated HTML page. Example: TextColor[myrouter]: #a0a0a0a YYLLeeggeenndd,, SShhoorrttLLeeggeenndd,, LLeeggeenndd[[11223344]] The following keywords allow you to override the text displayed for the various legends of the graph and in the HTML document: YLegend The Y-axis label of the graph. Note that a text which is too long to fit in the graph will be silently ignored. ShortLegend The units string (default 'b/s') used for Max, Average and Current Legend[1234IO] The strings for the colour legend. Example: YLegend[myrouter]: Bits per Second ShortLegend[myrouter]: b/s Legend1[myrouter]: Incoming Traffic in Bits per Second Legend2[myrouter]: Outgoing Traffic in Bits per Second Legend3[myrouter]: Maximal 5 Minute Incoming Traffic Legend4[myrouter]: Maximal 5 Minute Outgoing Traffic LegendI[myrouter]:  In: LegendO[myrouter]:  Out: Note, if _L_e_g_e_n_d_I or _L_e_g_e_n_d_O are set to an empty string with LegendO[myrouter]: The corresponding line below the graph will not be printed at all. TTiimmeezzoonnee If you live in an international world, you might want to generate the graphs in different timezones. This is set in the TZ variable. Under certain operating systems like Solaris, this will provoke the localtime call to give the time in the selected timezone. Example: Timezone[myrouter]: Japan The Timezone is the standard timezone of your system, ie Japan, Hongkong, GMT, GMT+1 etc etc. WWeeeekkffoorrmmaatt By default, mrtg (actually rateup) uses the ssttrrffttiimmee(3) '%V' option to format week numbers in the monthly graphs. The exact semantics of this format option vary between systems. If you find that the week numbers are wrong, and your system's ssttrrffttiimmee(3) routine supports it, you can try another format option. The POSIX '%V' option correspond to the widely used ISO 8601 week numbering standard. The week format character should be specified as a single letter; either W, V, or U. The UNIX version of rateup uses the libc implementation of strftime. On Windows, the native strftime implementation does not know about %V. So there we use a different implementation of strftime that does support %V. Example: Weekformat[myrouter]: W RRRRDDRRoowwCCoouunntt This affects the creation of new rrd files. By default rrds are created to hold about 1 day's worth of high resolution data. (plus 1 week of 30 minute data, 2 months of 2 hour data and 2 years of 1 day data). With this Keyword you can change the number of base interval entries configured for new rrds as they get created. Note that you must take the interval time into account. Example: RRDRowCount[myrouter]: 1600 RRRRDDRRoowwCCoouunntt3300mm As per RRDRowCount, but for the RRA's -typically- used for 30 minute data. Even so, you must still take the base interval into account. Leaving out this keyword will force the old default of 800 rows. Example: RRDRowCount30m[myrouter]: 800 RRRRDDRRoowwCCoouunntt22hh As per RRDRowCount, but for the RRA's -typically- used for 2 hour data. Even so, you must still take the base interval into account. Leaving out this keyword will force the old default of 800 rows. Example: RRDRowCount2h[myrouter]: 400 RRRRDDRRoowwCCoouunntt11dd As per RRDRowCount, but for the RRA's -typically- used for 1 day data. Even so, you must still take the base interval into account. Leaving out this keyword will force the old default of 800 rows. Example: RRDRowCount1d[myrouter]: 200 RRRRDDHHWWRRRRAAss Normally the RRDs created by MRTG will just contain the information gathered directly from the respective target. With this option you can tap into rrdtools advanced aberrant behaviour detection module based on Holt-Winters forecasting. The RRDHWRRAs property specifies the Holt- Winters RRAs as described in the rrdcreate manual page. Note, this setting will only affect newly created RRDs (targets). Example: RRDHWRRAs[myrouter]: RRA:HWPREDICT:1440:0.1:0.0035:288 TTiimmeeSSttrrPPooss This defines placement of the timestamp string on the image. Possible values are RU, LU, RL, LL (which stand, respectively, for RightUpper, LeftUpper, RightLower and LeftLower corner) and NO (for no timestamp). By default, no timestamp is placed on the image. Example: TimeStrPos[myrouter]: RU TTiimmeeSSttrrFFmmtt Using this keyword you may specify format of the timestamp to be placed on the image (if enabled by the TimeStrPos keyword). Specified string will be used by the ssttrrffttiimmee(()) function - see ssttrrffttiimmee(3) documentation for conversion specifiers available on your system. Default format: %Y-%m-%d %H:%M Example: TimeStrFmt[myrouter]: %H:%M:%S TTHHRREESSHHOOLLDD CCHHEECCKKIINNGG Through its threshold checking functionality mrtg is able to detect threshold problems for the various targets and can call external scripts to handle those problems (e.g. send email or a page to an administrator). Threshold checking is configured through the following parameters: TThhrreesshhDDiirr ((GGLLOOBBAALL)) By defining ThreshDir to point to a writable directory, MRTG will only alert you when a threshold boundary has been crossed. Example: ThreshDir: /var/mrtg/thresh TThhrreesshhHHyysstt ((GGLLOOBBAALL)) If a threshold is broken, and you have a threshdir defined, then mrtg will send mail once the threshold becomes 'unborken' to avoid situations where broken and unbroken messages get sent in close succession, we only send an unbroken message once the current value is 0.1 (10%) away from the threshold. using the ThreshHyst config variable you can customize this value. Example for 5%: ThreshHyst: 0.05 TThhrreesshhMMaaiillSSeerrvveerr ((GGLLOOBBAALL)) Address of an SMTP server which is going to accept mail about Thresholds being broken and unbroken. TThhrreesshhMMaaiillSSeennddeerr ((GGLLOOBBAALL)) What is the sender address of the threshold mail. Example: ThreshMailSender: mrtg@example.com TThhrreesshhMMaaiillAAddddrreessss ((PPEERR TTAARRGGEETT)) Email address for Threshold related Mails. This will only work if a mailserver has been configured. Example: ThreshMailAddress[_]: admin@example.com ThreshMailAddress[router]: This would bring threshold released mail to all but the target called 'router'. TThhrreesshhMMiinnII ((PPEERR TTAARRGGEETT)) This is the minimum acceptable value for the Input (first) parameter. If the parameter falls below this value, the program specified in ThreshProgI will be run and a mail will be sent to the ThreshMailAddress if specified. If the value ends in '%' then the threshold is defined relative to MaxBytes. TThhrreesshhMMaaxxII ((PPEERR TTAARRGGEETT)) Works the same as TheshMinI but it acts when the value is higher than ThreshMaxI. TThhrreesshhDDeesscc ((PPEERR TTAARRGGEETT)) Its value will be assigned to the environment variable THRESH_DESC before any of the programs mentioned below are called. The programs can use the value of this variable to produce more user-friendly output. TThhrreesshhPPrrooggII ((PPEERR TTAARRGGEETT)) This defines a program to be run if ThreshMinI or ThreshMaxI is broken. MRTG passes 3 arguments: the $router variable, the threshold value broken, and the current parameter value. TThhrreesshhPPrrooggOOKKII ((PPEERR TTAARRGGEETT)) This defines a program to be run if the parameter is currently OK (based on ThreshMinI and ThreshMaxI), but wasn't OK on the previous running -- based on the files found in ThreshDir. MRTG passes 3 arguments: the $router variable the unbroken threshold value, and the current parameter value. TThhrreesshhMMiinnOO,, TThhrreesshhMMaaxxOO,, TThhrreesshhPPrrooggOO,, aanndd TThhrreesshhPPrrooggOOKKOO These work the same as their *I counterparts, except on the Output (second) parameter. SSeettEEnnvv When calling threshold scripts from within your cfg file you might want to pass some data on to the script. This can be done with the SetEnv configuration option which takes a series of environment variable assignments. Note that the quotes are mandatory. This does not work for external scripts. It is not possible to set environment variables per target. Example: SetEnv[myrouter]: EMAIL="contact_email@someplace.net" HOST="www.some_server.net" HHWW FFaaiilluurree BBaasseedd TThhrreesshhoolldd CChheecckkiinngg When using rrd based logging with HW RRAs defined. You can use the confidence bounds violations stored in the FAILURES RRA for threshold based alerts. There the all target specific threshold variables have a Hold-Winters counterpart: ThreshMailAddress -> HWThreshMailAddress ThreshMinI -> HWThreshMinI ... The global variables for threshold checking are shared except for the ThreshHyst -> HWThreshHyst And HWThreshDesc sets the HWTHRESH_DESC variable. PPEERR TTAARRGGEETT DDEEFFAAUULLTT VVAALLUUEESS PPrree-- aanndd PPoossttffiixx To save yourself some typing you can define a target called '^'. The text of every Keyword you define for this target will be PREPENDED to the corresponding Keyword of all the targets defined below this line. The same goes for a Target called '$' but its text will be APPENDED. Note that a space is inserted between the prepended text and the Keyword value, as well as between the Keyword value and the appended text. This works well for text-valued Keywords, but is not very useful for other Keywords. See the "default" target description below. The example will make mrtg use a common header and a common contact person in all the pages generated from targets defined later in this file. Example: PageTop[^]:

      NoWhere Unis Traffic Stats


      PageTop[$]: Contact Peter Norton if you have any questions
      To remove the prepend/append value, specify an empty value, e.g.: PageTop[^]: PageTop[$]: NNooSSppaacceeCChhaarr With PREPEND and APPEND (see below) there is normally a space inserted between the local value and the PRE- or APPEND value. Sometimes this is not desirable. You can use the global option _N_o_S_p_a_c_e_C_h_a_r to define a character which can be mentioned at the end of a $ or ^ definition in order to suppress the space. Example: NoSpaceChar: ~ Target[^]: 1.3.6.1.4.1.482.50.2.4.20.0&1.3.6.1.4.1.482.50.2.4.21.0:get@~ Target[a]: a.tolna.net Target[b]: b.tolna.net Target[c]: c.tolna.net Target[d]: d.tolna.net DDeeffaauulltt VVaalluueess The target name '_' specifies a default value for that Keyword. In the absence of explicit Keyword value, the prepended and the appended keyword value, the default value will be used. Example: YSize[_]: 150 Options[_]: growright,bits,nopercent WithPeak[_]: ymw Suppress[_]: y MaxBytes[_]: 1250000 To remove the default value and return to the 'factory default', specify an empty value, e.g.: YLegend[_]: There can be several instances of setting the default/prepend/append values in the configuration file. The later setting replaces the previous one for the rest of the configuration file. The default/prepend/append values used for a given keyword/target pair are the ones that were in effect at the point in the configuration file where the target was mentioned for the first time. Example: MaxBytes[_]: 1250000 Target[myrouter.somplace.edu.2]: 2:public@myrouter.somplace.edu MaxBytes[_]: 8000 Title[myrouter.somplace.edu.2]: Traffic Analysis for myrouter.somplace.edu IF 2 The default _M_a_x_B_y_t_e_s for the target myrouter.someplace.edu.2 in the above example will be 1250000, which was in effect where the target name myrouter.someplace.edu.2 first appeared in the config file. CCOOMMMMAANNDD LLIINNEE OOPPTTIIOONNSS ----uusseerr _u_s_e_r_n_a_m_e and ----ggrroouupp _g_r_o_u_p_n_a_m_e Run as the given user and/or group. (Unix Only) ----lloocckk--ffiillee _f_i_l_e_n_a_m_e Use an alternate lock-file (the default is to use the configuration-file appended with "_l"). ----ccoonnffccaacchhee--ffiillee _f_i_l_e_n_a_m_e Use an alternate confcache-file (the default is to use the configuration-file appended with ".ok") ----llooggggiinngg _f_i_l_e_n_a_m_e|eevveennttlloogg If this is set to writable filename, all output from mrtg (warnings, debug messages, errors) will go to _f_i_l_e_n_a_m_e. If you are running on Win32 you can specify eevveennttlloogg instead of a filename which will send all error to the windows event log. NNOOTTEE:: Note, there is no Message DLL for mrtg included with mrtg. This has the side effect that the windows event logger will display a nice message with every entry in the event log, complaining about the fact that mrtg has no message dll. If you go to the mrtg contrib download area (on the website) you will find the mrtg-message-dll.zip which does contain such a thing. ----ddaaeemmoonn Put MRTG into the background, running as a daemon. This works the same way as the config file option, but the switch is required for proper FHS operation (because /var/run is writable only by root) ----ffhhss Configure all mrtg paths to conform to the FHS specification; http://www.pathname.com/fhs/ ----cchheecckk Only check the cfg file for errors. Do not do anything. ----ppiidd--ffiillee==ss Define the name and path of the pid file for mrtg running as a daemon ----ddeebbuugg==ss Enable debug options. The argument of the debug option is a comma separated list of debug values: cfg - watch the config file reading dir - directory mangeling base - basic program flow tarp - target parser snpo - snmp polling coca - confcache operations fork - forking view time - some timing info log - logging of data via rateup or rrdtool eval - print eval strings before evaluating them prof - add hires timing info the rrd calls Example: --debug="cfg,snpo" EEXXIITT CCOODDEESS An exit code of 0 indicates that all targets were successful. Generally speaking, most codes greater than 0 indicate that there was an unrecoverable problem. One exception to this is code 91, which indicates that at least one of the targets was successful. A partial listing of the codes follows: 0: All targets successful 2: Config error (can't read, fatal error in config, etc) 17: Another MRTG process is processing config 91: At least one target successful 92: No targets were successful EEXXAAMMPPLLEESS MMiinniimmaall mmrrttgg..ccffgg WorkDir: /usr/tardis/pub/www/stats/mrtg Target[r1]: 2:public@myrouter.somplace.edu MaxBytes[r1]: 8000 Title[r1]: Traffic Analysis ISDN PageTop[r1]:

      Stats for our ISDN Line

      CCffgg ffoorr sseevveerraall RRoouutteerrss.. WorkDir: /usr/tardis/pub/www/stats/mrtg Title[^]: Traffic Analysis for PageTop[^]:

      Stats for PageTop[$]: Contact The Chief if you notice anybody
      MaxBytes[_]: 8000 Options[_]: growright Title[isdn]: our ISDN Line PageTop[isdn]: our ISDN Line

      Target[isdn]: 2:public@router.somplace.edu Title[backb]: our Campus Backbone PageTop[backb]: our Campus Backbone Target[backb]: 1:public@router.somplace.edu MaxBytes[backb]: 1250000 # the following line removes the default prepend value # defined above Title[^]: Title[isdn2]: Traffic for the Backup ISDN Line PageTop[isdn2]: our ISDN Line Target[isdn2]: 3:public@router.somplace.edu AAUUTTHHOORR Tobias Oetiker and many contributors 2.17.10 2022-01-19 MRTG-REFERENCE(1) mrtg-2.17.10/doc/mrtg-rrd.txt0000644000175300017510000001123014171763417014722 0ustar oetikeroepMRTG-RRD(1) mrtg MRTG-RRD(1) NNAAMMEE mrtg-rrd - How to use RRDtool with MRTG SSYYNNOOPPSSIISS After using MRTG for some time you may find some limitations, mostly in the areas of performance and graphing flexibility. These are exactly the areas addressed by RRDtool. To learn more about RRDtool check out its website on http://oss.oetiker.ch/rrdtool RRRRDDTTOOOOLL IINNTTEEGGRRAATTIIOONN When using mrtg with RRDtool you are replacing _r_a_t_e_u_p with the RRDtool perl module _R_R_D_s_._p_m. To enable RRDtool support in mrtg you have to add the line LogFormat: rrdtool to your mrtg config file. MRTG needs access to both the RRDtool perl module RRRRDDss..ppmm and to the rrrrddttooooll executable. If these two items are not installed in locations where perl can find them on its own, then you can use the following two parameters to supply the appropriate directories. For the location of the rrrrddttooooll executable you put PathAdd: /usr/local/rrdtool/bin/ or PathAdd: c:\rrdtool\bin For the location of the perl module it would be: LibAdd: /usr/local/rrdtool/lib/perl/ or LibAdd: c:\rrdtool\bin\lib\perl When you have made this modification to the configuration file, several things will happen when you run mrtg again with the new config file: 1. mrtg will take all your old ".log" files and ccoonnvveerrtt them to ".rrd" format. (The ".log" files don't get touched in the process, so if things don't work out they are still there.) 2. mrtg will use rrrrddttooooll to update its databases. These will have a new format called _r_r_d which is totally different than the native _l_o_g format of the classic mrtg. 3. mrtg will nnoott create any webpages of graphs anymore. It will only query the routers for traffic information and update its _r_r_d databases. The advantage of whole thing is that the mrtg will become mmuucchh faster. Expect the runtime to drop to 20% of the previous value. (I would like to get some feedback on this from folks with large installations.) Mind you, though, while the logging process of RRDtool is vveerryy fast, you are also gaining some time by neither creating graphs nor updating webpages. The idea behind this is that it is more efficient to create graphs and webpages on demand by using a cgi script. At the moment there is no ooffffiicciiaall script to do this, but two contributors have created such scripts: One4All aka 14all.cgi This was the first program to take over the webpage creation and graphing task. It has been developed by Rainer Bawidamann rainer.bawidamann@web.de. You can find a copy on Rainers website: http://my14all.sourceforge.net/ The program comes with its own documentation rroouutteerrss22..ccggii This is another CGI frontend for mrtg running with rrdtool. The main difference between this and 14all is that the web pages it creates are much more stylish than the ones from mrtg, plus they support User Defined summary graphs and different levels of Authentication and Authorisation. This has been written by Steve Shipway (steve@steveshipway.org). You obtain a copy, and find a forum and demonstration system at http://www.steveshipway.org/software/ The program comes with its own installation instructions and install script. mmrrttgg--rrrrdd The mrtg-rrd script is a CGI/FastCGI application by Jan "Yenya" Kasprzak for displaying MRTG graphs from data in the RRDtool format. It is an intended replacement for the 14all.cgi script. It can make your monitoring system faster because MRTG does not have to generate all the PNG files with graphs every 5 minutes or so. Instead of this the graphs are generated on-demand when the user wants to see them. http://www.fi.muni.cz/~kas/mrtg-rrd/ FFUUTTUURREE Just as a side note: MRTG-3 will be based entirely on rrdtool technology. But don't wait for it ... get going nnooww! AAUUTTHHOORR Tobias Oetiker 2.17.10 2022-01-19 MRTG-RRD(1) mrtg-2.17.10/doc/mrtg-squid.txt0000644000175300017510000001014614171763417015265 0ustar oetikeroepMRTG-SQUID(1) mrtg MRTG-SQUID(1) NNAAMMEE mrtg-squid - using mrtg to monitor Squid DDEESSCCRRIIPPTTIIOONN Squid 2.3 knows SNMP and you can therefore use mrtg to monitor it quite easily. I have made some modifications to mrtg which simplify this. My work is based on earlier modification made by: matija.grabnar@arnes.si and kostas@nlanr.net. MMOODDIIFFIICCAATTIIOONNSS I added new code for displaying correct units to the previous patches "perminute" and "perhour" ("option" tokens), which allows other measurement in addition to "persecond". Then I created a new option token "dorelpercent" which allows the calculation of the percentage of IN-stream / OUT-stream on the fly and then displays it on a fixed scale from 0% to 100%. For my requirements, this does good work. Maybe someone wants a floating scale. It should not be a problem to implement it, too (but give me an option to keep my fixed scale). If IN-stream is always less than OUT-stream both lines (OUT-stream and relative percent) are always displayed on top of IN- stream bulk. Otherwise this option makes no sense. With this option you can display hitrates, errorrates (for router monitoring: rel. droprates) easily now. If you use this options please consider that you need a 5th colourname/value pair in your Colours statements! Due to some discussion on this list, I have implemented two tokens too: "kilo" and "kMG" "kilo" should contain the value of k (1000 or 1024), where 1000 is the default. "kMG" is a comma separated list of multiplier prefixes, used instead of "", "k", "M", "G", "T" on the MRTG display. Leave the place free, if you want no prefix. Also an incomplete list of OIDs for the new SQUID release is added. You may need to turn on snmp_port in squid.conf to as it is disabled by default. I hope you enjoy it. CCOONNFFIIGG EEXXAAMMPPLLEE First load the squid mib LoadMIBs: /usr/share/squid/mib.txt You can measure responsetimes in ms and display it with MRTG correctly with: kMG[measure-ms]: m,,k,M,G,T short[measure-ms]: s You can display now MB/s as 1024*1024 B/s with: kilo[volume]: 1024 Assuming you're not running squid's SNMP on the default snmp port, you need to include a port number in your target line: Target[proxy-hit]: cacheHttpHits&cacheProtoClientHttpRequests:public@localhost:3401 A sample config for squid: Target[proxy-hit]: cacheHttpHits&cacheProtoClientHttpRequests:public@proxy Title[proxy-hit]: HTTP Hits PageTop[proxy-hit]:

      proxy Cache Statistics: HTTP Hits / Requests

      Suppress[proxy-hit]: y LegendI[proxy-hit]: HTTP hits LegendO[proxy-hit]: HTTP requests Legend1[proxy-hit]: HTTP hits Legend2[proxy-hit]: HTTP requests YLegend[proxy-hit]: perminute ShortLegend[proxy-hit]: req/min Options[proxy-hit]: nopercent, perminute, dorelpercent Target[proxy-srvkbinout]: cacheServerInKb&cacheServerOutKb:public@proxy Title[proxy-srvkbinout]: Cache Server Traffic In / Out PageTop[proxy-srvkbinout]:

      Cache Statistics: Server traffic volume (In/Out)

      Suppress[proxy-srvkbinout]: y LegendI[proxy-srvkbinout]: Traffic In LegendO[proxy-srvkbinout]: Traffic Out Legend1[proxy-srvkbinout]: Traffic In Legend2[proxy-srvkbinout]: Traffic Out YLegend[proxy-srvkbinout]: per minute ShortLegend[proxy-srvkbinout]: b/min kMG[proxy-srvkbinout]: k,M,G,T kilo[proxy-srvkbinout]: 1024 Options[proxy-srvkbinout]: nopercent, perminute AAUUTTHHOORR Andreas Papst Dirk-LXder Kreie Chris Chiappa 2.17.10 2022-01-19 MRTG-SQUID(1) mrtg-2.17.10/doc/mrtg-traffic-sum.txt0000644000175300017510000000557014171763417016365 0ustar oetikeroepMRTG-TRAFFIC-SUM(1) mrtg MRTG-TRAFFIC-SUM(1) NNAAMMEE mrtg-traffic-sum - Builds monthly traffic summary from mrtg log files SSYYNNOOPPSSIISS mmrrttgg--ttrraaffffiicc--ssuumm [_o_p_t_i_o_n_s...] ccoonnffiigg--ffiillee --man show man-page and exit -h, --help display this help and exit --version output version information and exit --catch=regexp filter out things that match this in PageTop --email=address email the result --min=gigabytes minimal number of gigabites required for report --range= Specify "current" for month-to-date, "previous" for last complete month --units=[GB|MB] Display results in gigabytes (default is MB) DDEESSCCRRIIPPTTIIOONN The mrtg-traffic-sum goes through the mrtg logs for the targets in the the config file specified and builds the traffic total for the last month in Giga Bytes. (Note in communications Giga is 10^9). The result of this analysis can be sent via email to an address of your choice using the ----eemmaaiill option. With the ----ccaattcchh option you can specify a regular expression which will be matched against the contents of the PageTop settings. The regular expression should return a value into $1 and possibly into $2. This will then be used as description for the appropriate traffic sum. By default the catch is set to: (?:description|port name):\s*\s*([^< ]*?[^<]*?)\s*, Keith Dunnett HHIISSTTOORRYY 2002-07-13 to Initial Version 2009-12-38 kd New features 2.17.10 2021-10-08 MRTG-TRAFFIC-SUM(1) mrtg-2.17.10/doc/mrtg-unix-guide.txt0000644000175300017510000002665414171763416016230 0ustar oetikeroepMRTG-UNIX-GUIDE(1) mrtg MRTG-UNIX-GUIDE(1) NNAAMMEE mrtg-unix-guide - The MRTG 2.17.10 Linux/Unix Installation Guide DDEESSCCRRIIPPTTIIOONN MRTG comes to you in Source Code. This means that you have to compile parts of it before you can use it on a Unix machine. These instructions help you to do so. PPRREEPPAARRAATTIIOONN In order to compile and use mrtg you need a C compiler and a copy of perl installed on your machine. In most cases this will already be available. In case it is not, here are some starting points. Below I'll give you a detailed run through the whole compilation process. GCC The GNU C compiler comes preinstalled on most of the free Unices out there. For commercial derivatives you may have to download and compile it first. If you have no compiler at all there is a chicken and egg problem, but there are also precompiled versions of gcc available for most operating systems. http://gcc.gnu.org/ Perl Large parts of the MRTG system are written in the Perl scripting language. Make sure there is a recent copy of perl on your machine (try perl -v). At least version 5.005 is required for mrtg to work well. If you use SNMPV3 and other new features you should use at least 5.8. You can get the latest perl from http://www.perl.com/ MRTG generates traffic graphs in the PNG format. To be able to do this it needs several 3rd party libraries. When compiling these libraries I urge you to make sure you compile them as ssttaattiicc libraries. There is just much less trouble ahead if you are doing it like this. See the Instructions in the next section for inspiration. Note that many free unices have all the required libraries already in place so there is no need to install another copy. To check it is best to skip all the library instructions below and go straight into the mrtg compile. If the first attempt fails and you do not get a working version of mrtg, try compiling new copies of all libraries as explained below. Do this BBEEFFOORREE you send email to me about problems compiling mrtg. gd This is a basic graph drawing library created by Thomas Boutell. Note that all releases after Version 1.3 only create PNG images. This is because a) Thomas got into trouble because the GIF format which it used to produce uses a compression technology patented by Unisys. b) PNG is more efficient and patent free. MRTG can work with old and new version of the GD library. You can get a recent copy of GD from: http://www.boutell.com/gd/ libpng Is required by gd in order to produce PNG graphics files. Get it from: http://www.libpng.org/pub/png/libpng.html zlib Is needed by libpng to compress the graphics files you create. Get a copy from http://www.gzip.org/zlib And last but not least you also need mrtg itself. In case you have not yet downloaded it, you can find a copy on my website: http://oss.oetiker.ch/mrtg/pub LLIIBBRRAARRYY CCOOMMPPIILLAATTIIOONN In this section I will give you step by step instructions on how to compile the various libraries required for the compilation of mrtg. Note that these libraries may already be installed if you have a _*_B_S_D or _L_i_n_u_x system so you can skip recompiling them. The wwggeett program used below is a simple web downloader. You can also enter the address into your nneettssccaappee if you don't have wwggeett available. First let's create a directory for the compilation. Note that this may already exist on your system. No problem, just use it. mkdir -p /usr/local/src cd /usr/local/src If you do not have zlib installed: wget http://www.zlib.net/zlib-1.2.3.tar.gz gunzip -c zlib-*.tar.gz | tar xf - rm zlib-*.tar.gz mv zlib-* zlib cd zlib ./configure make cd .. If you don't have libpng installed wget ftp://ftp.simplesystems.org/pub/libpng/png/src/libpng-1.2.40.tar.gz gunzip -c libpng-1.2.34.tar.gz | tar xf - mv libpng-* libpng cd libpng env CFLAGS="-O3 -fPIC" ./configure --prefix=$INSTALL_DIR make rm *.so.* *.so cd .. And now you can compile gd For versions up to 1.8.4, try: wget http://www.boutell.com/gd/http/gd-1.8.4.tar.gz gunzip -c gd-*.tar.gz |tar xf - rm gd-*.tar.gz mv gd-* gd cd gd The \ characters at the end of the following lines mean that all the following material should actually be written on a single line. perl -i~ -p -e s/gd_jpeg.o//g Makefile make INCLUDEDIRS="-I. -I../zlib -I../libpng" \ LIBDIRS="-L../zlib -L. -L../libpng" \ LIBS="-lgd -lpng -lz -lm" \ CFLAGS="-O -DHAVE_LIBPNG" cd .. For versions starting around 2.0.11, try: wget http://www.boutell.com/gd/http/gd-2.0.33.tar.gz gunzip -c gd-2.0.33.tar.gz |tar xf - mv gd-2.0.33 gd cd gd env CPPFLAGS="-I../zlib -I../libpng" LDFLAGS="-L../zlib -L../libpng" \ ./configure --disable-shared --without-freetype --without-jpeg make cp .libs/* . MMRRTTGG CCOOMMPPIILLAATTIIOONN Ok, now everything is ready for the mrtg compilation. cd /usr/local/src gunzip -c mrtg-2.17.10.tar.gz | tar xvf - cd mrtg-2.17.10 If all the libraries have been preinstalled on your system you can configure mrtg by doing a simple: ./configure --prefix=/usr/local/mrtg-2 Otherwise you may have to give some hints on where to find the various libraries required to compile mrtg: ./configure --prefix=/usr/local/mrtg-2 \ --with-gd=/usr/local/src/gd \ --with-z=/usr/local/src/zlib \ --with-png=/usr/local/src/libpng If you have RRDtool available you might want to tell mrtg about it so that you can opt to use rrdtool with mrtg. Check mrtg-rrd. Configure will make sure your environment is fit for building mrtg. If it finds a problem, it will tell you so and it will also tell you what to do about it. If everything is OK, you will end up with a custom Makefile for your system. Now type: make This builds the rateup binary and edits all the perl pathnames in the scripts. You can now install mrtg by typing make install (requires gnu install) All the software required by MRTG is now installed under the _/_u_s_r_/_l_o_c_a_l_/_m_r_t_g_-_2 subdirectory. You can now safely delete the libraries we compiled above. Then again, you might want to keep them around so that you have them available when compiling the next version of mrtg. CCOONNFFIIGGUURRAATTIIOONN The next step is to configure mrtg for monitoring a network device. This is done by creating an _m_r_t_g_._c_f_g file which defines what you want to monitor. Luckily, you don't have to dive straight in and start writing your own configuration file all by yourself. Together with mrtg you also got a copy of ccffggmmaakkeerr. This is a script you can point at a router of your choice; it will create a mrtg configuration file for you. You can find the script in the _b_i_n subdirectory. cfgmaker --global 'WorkDir: /home/httpd/mrtg' \ --global 'Options[_]: bits,growright' \ --output /home/mrtg/cfg/mrtg.cfg \ community@router.abc.xyz This example above will create an mrtg config file in _/_h_o_m_e_/_m_r_t_g_/_c_f_g assuming this is a directory visible on your webserver. You can read all about cfgmaker in cfgmaker. One area you might want to look at is the possibility of using ----iiffrreeff==iipp to prevent interface renumbering troubles from catching you. If you want to start rolling your own mrtg configuration files, make sure you read mrtg-reference to learn all about the possible configuration options. RRUUNNNNIINNGG MMRRTTGG Once you have created a configuration file, try the following: /usr/local/mrtg-2/bin/mrtg /home/mrtg/cfg/mrtg.cfg This will query your router and also create your first mrtg traffic graphs and webpages. When you run mrtg for the first time there will be a lot of complaints about missing log files. Don't worry, this is normal for the first 2 times you start mrtg. If it keeps complaining after this time you might want to look into the problem. Starting mrtg by hand is not ideal in the long run. So when you are satisfied with the results you can automate the process of running mrtg in regular intervals (this means every 5 minutes by default). You can either add mrtg to your crontab with a line like this: 0,5,10,15,20,25,30,35,40,45,50,55 * * * * \ /mrtg /mrtg.cfg \ --logging /var/log/mrtg.log or if you live in Linux Land the line may look like this if you are using "crontab -e" */5 * * * * /mrtg /mrtg.cfg \ --logging /var/log/mrtg.log or like this if you use _/_e_t_c_/_c_r_o_n_t_a_b */5 * * * * mrtg-user /mrtg /mrtg.cfg \ --logging /var/log/mrtg.log You can also run mrtg as a daemon process by adding the line RunAsDaemon: Yes to your mrtg configuration file and then creating a startup script in your system startup sequence. Unfortunately, adding startup scripts differs widely amongst different unix systems. The modern ones normally have a directory called _/_e_t_c_/_i_n_i_t_._d or _/_e_t_c_/_r_c_._d_/_i_n_i_t_._d where you put scripts which starts the process you want to run when the system boots. Further you must create a symbolic link in _/_e_t_c_/_r_c_3_._d or _/_e_t_c_/_r_c_._d_/_r_c_?_._d called _S_6_5_m_r_t_g (this is just a sample name ... it is just important that it starts with S followed by a two digit number). If you are not sure about this, make sure you consult the documentation of your system to make sure you get this right. A mmiinniimmaall script to put into _i_n_i_t_._d might look like this: #! /bin/sh cd /usr/local/mrtg-2.17.10/bin && ./mrtg --user=mrtg-user \ /home/httpd/mrtg/mrtg.cfg --logging /var/log/mrtg.log Note that this will only work with RRuunnAAssDDaaeemmoonn:: YYeess in your mrtg.cfg file. AAUUTTHHOORR Tobias Oetiker 2.17.10 2022-01-19 MRTG-UNIX-GUIDE(1) mrtg-2.17.10/doc/mrtg-webserver.txt0000644000175300017510000000424614171763417016150 0ustar oetikeroepMRTG-WEBSERVER(1) mrtg MRTG-WEBSERVER(1) NNAAMMEE mrtg-webserver - hints for web server configuration SSYYNNOOPPSSIISS If you want people to actually see the results of your network monitoring efforts you will need a webserver. This document lists some configuration hints for webservers. Contributions welcome. AAPPAACCHHEE CCoonnffiigguurriinngg mmoodd__eexxppiirree A big issue with mrtg monitoring data is the expiry time. All these nice graphs you can create are only valid for a short time. If you do not take special action some webbrowsers will not notice this and you may end up with people seeing old data because of caching issues. The apache module mod_expire allows you to setup special expiry properties for individual file. Here is an example for how this may look for an mrtg web directory. The configuration directives can be stored into a _._h_t_a_c_c_e_s_s file. ############################################################ # Example .htaccess for use with apache-1.2 and mod_expire. # (mod_expire come with apache-1.2 but you have to explicitly # activate it when compiling the httpd ...) ############################################################# # ExpiresActive On # enable expirations # five minutes ExpiresDefault M300 ExpiresActive On ExpiresDefault M1800 ExpiresActive On ExpiresDefault M7200 ExpiresActive On ExpiresDefault M86400 ExpiresActive On ExpiresDefault M300 # index.html is not automatically generated ExpiresActive Off AAUUTTHHOORR Unknown 2.17.10 2022-01-19 MRTG-WEBSERVER(1) mrtg-2.17.10/doc/rateup.txt0000644000175300017510000000345414171763417014475 0ustar oetikeroepRATEUP(1) mrtg RATEUP(1) NNAAMMEE rateup - tool to generate images for MRTG SSYYNNOOPPSSIISS rateup -f rateup directory basename [sampletime] [t sampletime] [-(t)ransparent] [-(b)order] [u|a|g|h|m in out abs_max] [i/p file maxvi maxvo maxx maxy growright step bits] DDEESSCCRRIIPPTTIIOONN rateup is a fast add-on to the great MRTG Traffic monitor. It makes the database file updates much faster, and creates the graphic image files, ready for processing by PPMTOGIF. It also reduces memory requirements by a factor of 10, and increases the speed of updates by a factor of at least 10. This makes it feasible to run mrtg every 5 minutes. rateup attempts to compensate for missed updates by repeating the last sample, and also tries to catch bad update times. The .log file stores real history every five minutes for 31 hours, then 'compresses' the history into 30 minute samples for a week, then 2-hour samples for 31 days, then daily samples for two years. This ensures that the log files don't grow in size. The log files are a slightly different format, but convert.perl will fix that for you. AAUUTTHHOORR Dave Rand , Tobias Oetiker , Alexandre Steinberg SSEEEE AALLSSOO mmrrttgg(1), mmrrttgg--rreeffeerreennccee(1), mmrrttgg--llooggffiillee(1), mmrrttgg--ttrraaffffiicc--ssuumm(1), ccffggmmaakkeerr(1), iinnddeexxmmaakkeerr(1) 2.17.10 2022-01-19 RATEUP(1)