#!/usr/bin/perl -wT
my $contentOut = 'false';
my $errLog="";
$ENV{PATH} = '/usr/local/bin:/bin:/usr/bin';#Untaint the path
########################################################
#Get the local host name
use Sys::Hostname;
my $ipaddr=gethostbyname(hostname());
my ($a, $b, $c, $d)=unpack('C4',$ipaddr);
my ($hostname,$aliases, $addrtype, $length, @addrs)=gethostbyaddr($ipaddr,2);
my $user=scalar(getpwuid($<));
sub TestFiles{
my $filename = shift;
my $writeableCheck = shift;
if(!defined($filename) || $filename eq "" ){
return "false";
}
if($filename =~/^([-\w.\/]+)$/) {#untaint
$filename=$1;
}
else {
$errLog ="Invalid filename = $filename
";
return "false";
}
if(!(-e $filename)){
$errLog .= "file: $filename, does not exist.
";
return "false";
}
if(-z $filename){
$errLog .= "file: $filename, has a size of 0.
";
#return "false";
}
#my $filePermissionCmd = "ls -alh $filename";
if(!(-r $filename)){
$errLog .= "file: $filename, is not readable
";#.`$filePermissionCmd`."
";
return "false";
}
if(defined($writeableCheck) && $writeableCheck!=0 && !(-w $filename)){
$errLog .= "file: $filename, is not writeable
";#.`$filePermissionCmd`."
";
return "false";
}
my %filemodes;
$filemodes{'cgi-lib.pl'} = 493;
$filemodes{'data'} = 493;
$filemodes{'beacons.txt'} = 420;
$filemodes{'pinger.xml'} = 420;
$filemodes{'offsite.nodes'} = 420;
$filemodes{'pingerCronStat.stderr'} = 420;
$filemodes{'pingerCronStat.stdout'} = 420;
$filemodes{'lynx'} = 493;
my $mode=(stat($filename)) [2] & 07777;
#(my $fn = $filename) =~ s'^.*/'';
$errLog .= "file: $filename found\n
";
foreach my $key (keys %filemodes) {
if($filename =~ /$key/) {
my $octmode=sprintf("%lo", $mode & 07777);
unless ($mode eq $filemodes{$key}) {
my $octfilemode=sprintf("%lo", $filemodes{$key} & 07777);
$errLog .= "Mode: $mode/0$octmode, "
. "should be $filemodes{$key}/0$octfilemode!\n
";
}
else {
$errLog .= "Mode: ". ((stat($filename))[2] & 07777) . "/0$octmode are required permissions\n
";
}
}
}
$errLog .= "Bytes: ". (stat($filename))[7] . "\n
";
$errLog .= "Modified Time: ". localtime((stat($filename))[9]) . "\n
";
#Find the free space
my $cmd = "df -h $filename";
if($cmd =~ /^(df $filename$)/) {$cmd=$1;} #untaint
my @df = `$cmd`;
$errLog .= "$cmd\n
";
foreach my $line (@df) {
$line=~ s/\s+$//;
$errLog .= "$line\n";
}
$errLog .= "\n";
return "true";
} # End TestFiles
########################################################
# TAILORING SECTION for NEW Hosts, change these to the right locations
#See http://www-iepm.slac.stanford.edu/pinger/tools/install2.html.
#If you use the standard PingER2 installation then nothing should need changing.
my $error = "";
my $cgi_lib = "";#If none of our guesses below work then add the location for
#for cgi-lib.pl for your host
if(&TestFiles($cgi_lib,0)=~/^true/i){
require $cgi_lib;
}
elsif(&TestFiles("/afs/slac/g/www/cgi-lib/cgi-lib.pl",0)=~/^true/i){
require "/afs/slac/g/www/cgi-lib/cgi-lib.pl";
}
elsif(&TestFiles("/usr/local/cgi-bin/cgi-lib.pl",0)=~/^true/i){
require "/usr/local/cgi-bin/cgi-lib.pl";
}
elsif(&TestFiles("/usr/lib/cgi-bin/cgi-lib.pl",0)=~/^true/i) {
require "/usr/lib/cgi-bin/cgi-lib.pl";
}
elsif(&TestFiles("/usr/bin/cgi-bin/cgi-lib.pl",0)=~/^true/i) {
require "/usr/bin/cgi-bin/cgi-lib.pl";
}
elsif(&TestFiles("/var/www/cgi-bin/cgi-lib.pl",0)=~/^true/i) {
require "/var/www/cgi-bin/cgi-lib.pl";
}
else{
print "Status: 200 OK\nContent-type: text/html\n\n"
. "Output from: $1$opt\n".`$1$opt`."\n"; } else { $errLog.="
$cmd $opt: Command not found\n"; } } } ################Done with changes####################### use strict; ######################################################## #Set up USAGE (my $progname = $0) =~ s'^.*/'';#strip path components, if any #my $version="3.6; 30-Aug-2010; Fahad Satti and Les Cottrell"; #See beyond __END__ for more #my $version="3.7; 17-Nov-2010; Fahad Satti and Les Cottrell"; #See beyond __END__ for more #my $version="3.8; 11-30-2010; Les Cottrell"; #See beyond __END__ for more #my $version="3.81; 12-20-2010; Les Cottrell"; #See beyond __END__ for more #my $version="3.82; 01-02-2011; Les Cottrell"; #See beyond __END__ for more #my $version="3.83; 01-07-2011; Les Cottrell"; #See beyond __END__ for more #my $version="3.84; 01-07-2011; Les Cottrell"; #See beyond __END__ for more #my $version="3.9; 03-24-2011; Les Cottrell"; #See beyond __END__ for more my $version="3.91; 03-24-2011; Les Cottrell"; #See beyond __END__ for more my $USAGE = " $progname is a CGI script that enables one to gather the pingER data for a user specified time window for user specified remote sites(). It is acccessed via a URL. The default by accessing http://
$USAGE\n"; exit 100; } if (defined($in{'admin_func'}) && ($in{'admin_func'} eq 'fileLog')) { if($contentOut eq 'false'){ print "Status: 200 OK\nContent-type: text/html\n\n"; } print "
\n";
while(){
print "$_\n";
}
print "--------------Output complete---------------------\n";
}
else{
print "Can't open Apache configuration file [$httpd]\n";
last;
}
}
else{
print "Aapche configration file [$httpd]: No such File Found\n";
last;
}
exit 102;
}
if(defined($in{'admin_func'}) && ($in{'admin_func'} eq 'pinger_xml')){
if($contentOut eq 'false'){
print "Status: 200 OK\nContent-type: text/plain\n\n";
}
if(-e $pinger_xml_file){
if(open(PINGERXML,$pinger_xml_file)){
print "Starting Output of PingER Landmarks file[$pinger_xml_file]\n\n";
while(){
print "$_\n";
}
print "--------------Output complete---------------------\n";
}
else{
print "Can't open $pinger_xml_file error \n";
last;
}
}
else{
print "pinger.xml[$pinger_xml_file]: No such File Found\n";
last;
}
exit 5;
}
if(defined($in{'admin_func'}) && ($in{'admin_func'} eq 'std_cron_out')){
if($contentOut eq 'false'){
print "Status: 200 OK\nContent-type: text/html\n\n";
}
if(-e $std_cron_out_file){
if(open(CRONOUT,$std_cron_out_file)){
print "";
print "Starting Output of Standard Cron Out[$std_cron_out_file]
\n\n";
while(){
print "$_
";
}
print "--------------Output complete---------------------
\n ";
}
else{
print "Can't open $std_cron_out_file fatal error
\n";
last;
}
}
else{
print "Cron Output File[$std_cron_out_file]: No such File Found
\n";
last;
}
exit 6;
}
if(defined($in{'admin_func'}) && ($in{'admin_func'} eq 'std_cron_err')){
if($contentOut eq 'false'){
print "Status: 200 OK\nContent-type: text/html\n\n";
}
if(-e $std_cron_err_file){
if(open(CRONERR,$std_cron_err_file)){
print "";
print "Starting Output of Cron Errors for PingER2[$std_cron_err_file]
\n\n";
while(){
print "$_
";
}
print "--------------Output complete---------------------
\n ";
}
else{
print "Can't open $std_cron_err_file FATAL ERROR
\n";
last;
}
}
else{
print "Cron Error File [$std_cron_err_file]: No such File Found
\n";
last;
}
exit 7;
}
if(defined($in{'admin_func'}) && ($in{'admin_func'} eq 'beacons')){
if($contentOut eq 'false'){
print "Status: 200 OK\nContent-type: text/html\n\n";
}
if(-e $std_beacons_file){
if(open(BEACONS,$std_beacons_file)){
print "";
print "Starting Output of beacons.txt file for PingER2[$std_beacons_file]
\n\n";
while(){
print "$_
";
}
print "--------------Output complete---------------------
\n ";
}
else{
print "Can't open $std_beacons_file FATAL ERROR
\n";
last;
}
}
else{
print "Beacons.txt File [$std_beacons_file]: No such File Found
\n";
last;
}
exit 8;
}
#############################################################################
# if in_form not defined then return the form.
if (!defined $in{'in_form'}) {
if($contentOut eq 'false'){
print "Status: 200 OK\nContent-type: text/html\n\n";
}
print " ";
print " \n";
print "";
print "Get Ping Data from $hostname \n"
. "\n";
print "$errorGet Ping Data from $hostname
"
. "";
print "
This is a test form to retrieve ping data from $hostname "
. "using $progname version=$version.\n";
print <<'EOM1';
There are similar retrieval scripts running
elsewhere.
Most of the time the data will be retrieved by automated scripts.
This form
is a good way of testing
installations (see
Verify XML Syntax
for how to verify the PingER.xml file) and looking at up-to-the-minute data.
Please note SLAC only
provides the most recent data available via
this web page.
For older data please refer to the following archive(anonymous FTP).
EOM1
print ""
. "
EXECUTE
my $time=scalar(localtime());
print "Form created by $0 for $user on $hostname($a.$b.$c.$d). \n"
. "Local time=$time.\n "
. "Raw PingER data obtained from $stats_dir. "
. "Remote sites obtained from $sites_fn. \n"
. "The most current version of this script and instructions to install can be found at: "
. ""
. "Installing ping_data.pl and traceroute.pl for PingER2. "
. "The "
. "master template pinger.xml is available from SLAC. "
. "There is USAGE "
. "information on the script.\n";
exit;
}
#############################################################################
#Not requesting help or a form so provide results
else {
if($contentOut eq 'false'){
print "Status: 200 OK\nContent-type: text/plain\n\n";
}
}
my ($begin, $end);
if (defined $in{'begin_hour'}) {
$begin = &timegm($in{'begin_sec'},$in{'begin_min'},$in{'begin_hour'},$in{'begin_day'}, ($in{'begin_month'} -1), ($in{'begin_year'} -1900));
$begin = $begin - ($in{'begin_offset'} *3600);
$end = &timegm($in{'end_sec'},$in{'end_min'},$in{'end_hour'},$in{'end_day'}, ($in{'end_month'} -1), $in{'end_year'} -1900);
$end = $end - ($in{'end_offset'} *3600);
}
elsif (defined $in{'begin'}) {
$begin = $in{'begin'};
$end = $in{'end'};
}
else {
print "No begin and end times\n";
exit;
}
# if no sites specified, return all sites
my $all_sites;
my %site_list;
if (!defined $in{'sites'}) {
$all_sites = 1;
}
else {
$all_sites = 0;
# put (lower-cased) site names in associate array for easy checking
for (split(/\0/, $in{'sites'})) {
tr/A-Z/a-z/;
$site_list{$_} = 1;
}
}
# Exclude the end points unless begin_point (or end_point) is specfied.
if ($in{'begin_point'} ne 'y') { ++$begin }
if ($in{'end_point'} ne 'y') { --$end }
if ($end < $begin) {
print "End < Begin\n";
exit;
}
my ($begin_sec, $begin_min, $begin_hour, $begin_mday, $begin_mon, $begin_year, $begin_wday, $begin_yday, $begin_isdst) = gmtime($begin);
my ($end_sec, $end_min, $end_hour, $end_mday, $end_mon, $end_year, $end_wday, $end_yday, $end_isdst) = gmtime($end);
# Add 2 minutes of "fuzz" to the timestamp search limits to allow for
# the timestamps' being a little out of strict sort order.
my $begin_search = $begin - 120;
my $end_search = $end + 120;
my $fn;
# for $month ((($begin_year +1900) * 12 + $begin_mon +1)..
# (($end_year+1900) * 12 + $end_mon +1)) {
# $fn = sprintf("%s/%s%4.4d-%2.2d.txt", $stats_dir,
# $stats_base_fn, int($month / 12), $month % 12)
#
# for $month ((($begin_year +1900) * 12 + $begin_mon )..
# (($end_year+1900) * 12 + $end_mon )) {
# $fn = sprintf("%s/%s%4.4d-%2.2d.txt", $stats_dir,
# $stats_base_fn, int($month / 12), ($month % 12) +1);
my $nline=0;
for my $month ((($begin_year +1900) * 12 + $begin_mon )..(($end_year+1900) * 12 + $end_mon)) {
$fn = sprintf("%s/%s%4.4d-%2.2d.txt", $stats_dir, $stats_base_fn, int($month / 12), ($month % 12) +1);
if (!open(PINGDATA, $fn)) {
if(!(-d $stats_dir)){
print "Unable to locate Data Dir = ".$stats_dir."\n";
}
if(!(-e $fn)){
print "Unable to locate Data File = ".$fn."\n";
}
print "#Warning $progname can't open $fn: $!\n";
next;
}
# print "Opened $fn\n";
# Use a binary search to quickly position the PINGDATA file to a little
# before the $begin timestamp data.
&SeekBinSrch(*PINGDATA, $begin_search, 1500);
while () {
my ($src_name, $src_ip, $dest_name, $dest_ip, $pingsize, $ctime) = split(/\s+/, $_);
# The following 5 lines are optimized for speed at the expense of beauty.
next if ($ctime < $begin);
if ($ctime > $end) {
if ($ctime < $end_search) {next;}
last;
}
$nline++;
$dest_name =~ tr/A-Z/a-z/;
print if (defined $site_list{$dest_name} || $all_sites);
} # while ()
close (PINGDATA);
} # for $month
if($nline<=0) {
print "#No data found in $nline lines of data between dates specified in $fn.\n"
. "#Dates: "
. ($begin_year+1900)."/".($begin_mon+1).".."
. ($end_year +1900)."/".($end_mon +1).". "
. "Epoch time searched from $begin-120 secs to $end+120 secs\n";
my $n=20;
my @tails=("/usr/bin/tail", "/bin/tail");
foreach my $tail (@tails) {
if(-e $tail){
if($tail=~/([\w\/]+)/){$tail=$1;}
else {print "#Command $tail is tainted\n"; next;}
if($n=~/(\d+)/) {$n=$1;}
else {print "#Line count $n is tainted\n"; next;}
if($fn=~/([\w\/\-\.]+)/) {$fn=$1;}
else {print "#File name $fn is tainted\n"; next;}
my $cmd="$tail -$n $fn";
my @ans=`$cmd`;
print "#Results (".scalar(@ans)." lines) from $cmd are:\n";
if(scalar(@ans)<=0) {print "$cmd returned ?=$? !=$!\n";}
else {
foreach my $line (@ans) {print "#$line\n";}
}
}
}
}
#############################################################################
sub SeekBinSrch # ( *FH, $key, $close_enough )
# Subroutine to seek to the vicinity of the $begin data records in the
# ping_data file using a binary search. The binary search only attempts
# to get within $close_enough bytes of the "exact" position in the sorted
# file which contains the search key (or, if no such record exists in the
# file, then to where such a record would be placed if it existed).
# More precisely, the binary search finds a region of the file such that
# (1) the size of the region is less than or equal to $close_enough bytes;
# (2) the beginning of the region is the beginning of a record whose key is
# less than or equal to the search key if such a record exists, otherwise
# the start of the region is the start of the file; and
# (3) the first record that begins after the end of the region has a key
# which is greater than or equal to the search key if such a record
# exists, otherwise the end of the region is the end of the file.
# The file is left positioned to the beginning of the region.
#
# Author: John Halperin 6 June 1997.
{
local(*FH) = $_[0];
my($key, $close_enough) = @_[1..2];
my($lo_posn, $hi_posn);
# return unless (defined());#remove warning "Value of construct can be "0"; test with defined()"
return unless (-f FH); # can't handle pipes or other oddities
$lo_posn = 0;
$hi_posn = (-s FH) or die "BinSrchFile: error stat'ing FH: $!\n";
my $loop_ct = 0;
my($mid_posn, $rec_start, $rec, $rec_key, $lt_eq_gt, $errct);
BinSrch:
while (($hi_posn - $lo_posn) > $close_enough && ++$loop_ct < 40) {
$mid_posn = ($lo_posn + $hi_posn) >> 1;
seek(FH, $mid_posn, 0) or
die "BinSrchFile: seek($mid_posn) failed: $!\n";
; # skip to start of next record
for ($errct = 0; ; ) {
$rec_start = (tell);
last BinSrch if ($rec_start >= $hi_posn);
if(!defined($rec = )){
die "SeekBinSrch: error reading file: $!\n";
}
$rec_key = (split(/ /, $rec, 7))[5];
last if (defined($rec_key) && $rec_key =~ m/^\d+$/);
warn "BinSrchFile: record at posn $rec_start has a bad timestamp\n",
"*** $rec";
die "BinSrchFile terminating\n" if (++$errct > 10);
}
$lt_eq_gt = $key - $rec_key;
if ($lt_eq_gt < 0) {
$hi_posn = $mid_posn; # srch key < rec, so drop ceiling
}
elsif ($lt_eq_gt > 0) {
$lo_posn = $rec_start; # srch key > rec, so raise floor
}
else {
$hi_posn = $lo_posn = $rec_start; # key == rec; found.
}
} # BinSrch: while ()
die "BinSrchFile failed; looping?\n"
if (($hi_posn - $lo_posn) > $close_enough);
seek(FH, $lo_posn, 0) or
die "BinSrchFile: seek($lo_posn) failed: $!\n";
} # &SeekBinSrch()
__END__
########################### Copyright Notice ###################################
# Copyright (c)1996 Universities Research Association, Inc. #
# All Rights Reserved #
# /*---------------------------------------------------------------*/
# /* STANFORD UNIVERSITY NOTICES FOR SLAC SOFTWARE */
# /* ON WHICH COPYRIGHT IS DISCLAIMED */
# /* */
# /* AUTHORSHIP */
# /* This software was created by , Stanford Linear */
# /* Accelerator Center, Stanford University. */
# /* */
# /* ACKNOWLEDGEMENT OF SPONSORSHIP */
# /* This software was produced by the Stanford Linear Accelerator */
# /* Center, Stanford University, under Contract DE-AC03-76SFO0515 */
# /* with the Department of Energy. */
# /* */
# /* GOVERNMENT DISCLAIMER OF LIABILITY */
# /* Neither the United States nor the United States Department of */
# /* Energy, nor any of their employees, makes any warranty, */
# /* express or implied, or assumes any legal liability or */
# /* responsibility for the accuracy, completeness, or usefulness */
# /* of any data, apparatus, product, or process disclosed, or */
# /* represents that its use would not infringe privately owned */
# /* rights. */
# /* */
# /* STANFORD DISCLAIMER OF LIABILITY */
# /* Stanford University makes no representations or warranties, */
# /* express or implied, nor assumes any liability for the use of */
# /* this software. */
# /* */
# /* STANFORD DISCLAIMER OF COPYRIGHT */
# /* Stanford University, owner of the copyright, hereby disclaims */
# /* its copyright and all other rights in this software. Hence, */
# /* anyone may freely use it for any purpose without restriction. */
# /* */
# /* MAINTENANCE OF NOTICES */
# /* In the interest of clarity regarding the origin and status of */
# /* this SLAC software, this and all the preceding Stanford */
# /* University notices are to remain affixed to any copy or */
# /* derivative of this software made or distributed by the */
# /* recipient and are to be affixed to any copy of software made */
# /* or distributed by the recipient that contains a copy or */
# /* derivative of this software. */
# /* */
# /* SLAC Software Notices, Set 4 (OTT.002a, 2004 FEB 03) */
# /*---------------------------------------------------------------*/
# Copyright (c) 2006, 2007, 2008, 2009, 2010
# The Board of Trustees of
# the Leland Stanford Junior University. All Rights Reserved.
#
# *** changes in version 1.1.1
# - selecting no sites returns all sites
# - refer to /usr/local/netmon
# *** changes in version 1.1.2
# - fast skip to starting time, and exit after ending time
# *** changes in version 1.1.4, June 24, 2006
# - Provide default dates and times in form boxes
# - Sort the sites, increase the size of box, compress output
# *** changes in version 1.1.5, July 20, 2006
# - Automate getting the hostname and add version number output.
# - Correct URL for getting FTP data.
# *** changes in version 1.1.6 August 18, 2006, Les Cottrell
# Check if running on host at slac.stanford.edu, if so use cgi-wrap, else use cgi-bin
# Add warning if can't open file
# *** changes in version 1.1.7 March 29, 2007, Les Cottrell
# use #!/usr/bin/perl -- rather than #!/usr/local/bin/perl5
# *** changes in version 1.1.8 May 30, 2007
# Report no data found in file.
# Prevent $yday going < 01
#my $version="1.1.8, 5/30/07, Cottrell.";
# *** changes in version 2.0 8/6/07, add help, use strict -T
# *** changes in version 3.1 2/17/10, provide access to help, pinger.xml,
# error and log. Get file locations automatically.
# Allow target node selection.
# *** changes in version 3.2 2/23/10, added require "/usr/lib/cgi-bin/cgi-lib.pl";
#Below is an example of the data format
minos.slac.stanford.edu 134.79.196.100 dukhet.phy.duke.edu 152.3.57.20 100 862526343 10 10 90 106 133
# *** changes in version 3.3 2/23/10,
# * Added a subroutine(TestFiles) at the top, to check required files for
# ** existance
# ** size > 0
# ** is readable
# ** is writeable(except in case of cgi-lib)
# * Added, checks to look for the most important files, like
# pinger.xml, cgi-lib.pl and pinger data dir in most obvious locations.
# This should help remove the need to make any changes to this script.
# *** changes in version 3.4 2/24/10,
# * Added the ability to output PingER2 FAQ
# * Added the ability to output beacons.txt file
# *** changes in version 3.5 2/24/10,
# * Added, search capability.
# *** changes in version 3.5.1 2/27/10,
# * Added, mode and Last modified output for files.
# *** Changes in version 3.6 8/30/2010,
# * Added octal display of permissions, space check,
# * info on checking the pinger.xml file
# *** Changes in version 3.7 11/17/2010
# * Provided date stamp of cronStat files.
# * Added test to see if lynx, mail, dig, ping, ping6 present
# *** Changes in version 3.8 11/30/10,
# * Added ability to list httpd.conf file.
# *** Changes in version 3.81 12/20/2010,
# * Added selinux check.
# *** Changes in version 3.82 01/02/2011,
# * Added "/usr/local/apache2/conf/httpd.conf" to possible httpd.conf locations
# * Added pwd, whoami and list of httpd processes
# *** Changes in version 3.83 01/07/2011,
# * Added /etc/hosts and /etc/resolv.conf, ip addr, local time,
# * location of master template for pinger.xml
# *** Changes in version 3.84 02/18/2011,
# * Added /bin/hostname, /bin/domainname.
# *** Changes in version 3.9 3/24/2011,
# * Added ps -efl | grep pinger2, ls -lt $stats_dir, added more
# * diagnostics for No data found.
# *** Changes in version 3.91 12/21/2011
# * Added look for $httpd in /etc/apache2/apache2.conf for acmesecurity