#!/usr/bin/perl # # Program to check a SAS job log for various character strings that # indicate problems of various types # $| = 1; # get user info my $username = getpwuid( $< ); ($name, $pass, $uid, $gid, $quota, $comment, $gcos, $dir, $shell, $expire) = getpwnam($username); # # The scalar variable '$processingNotices' functions as a boolean flag that # indicates whether lines of text containing the pattern 'NOTICE' are to be # treated as hits. # $processingNotices = 0; # # The following is the apparent file count on the command line # $totalFileCount = 0; # # The main body of this program consists of nothing more than two calls to a # subroutine called processParms. The processParms subroutine does the main # work of the program by parsing the parameter list of SAS log file names and # optional interspersed control flags and taking action accordingly. It is # desired that the script not process the initial entries in the list of files # and then discover that a subsequent control flag is syntactically incorrect. # This is the reason for the two calls to processParms. When called the first # time, processParms does nothing more than check the syntactical correctness # of the entire parameter list. If any problems are found an appropriate error # message is immediately put out the program exits without doing any checking. # Otherwise the second call to processParms takes place, in which the parameter # list is parsed and acted upon systematically from left to right. # # The first call to processParms is made with a subroutine parameter value of 0 # to signal that the only action the subroutine is to take is to scan and parse # the entire program parameter list for syntactical correctness. &processParms (0); # The second call to processParms is made with a subroutine parameter value of 1 # to signal that the subroutine is not only to scan and parse the entire program # parameter list but to take action immediately after encountering each element # of the list in sequence. &processParms (1); # END OF MAIN PROGRAM # The following is the processParms subroutine. It scans and parses the program # parameter list. If it is invoked with a subroutine parameter value of zero it # does nothing more than scan and parse the program parameter list and report any # errors it finds, causing the program as a whole to exit after error reporting is # completed. Otherwise, i.e. if it is invoked with a subroutine parameter value # of 1, the program parameter list is known already to be syntactically correct, # so the subroutine takes action immediately after parsing each list element. sub processParms { foreach (@ARGV) { if (/^-/) { # section to process dashed parms if (/^-s$/) { $processingNotices = 1; } elsif (/^-S$/) { $processingNotices = 0; } else { print "\nSorry, $gcos, the parameter \"$_\" is not recognized.\n"; print "Exiting, no action taken on any files.\n\n"; exit; } } # the current token is not a dashed parm, so it is assumed # to be a file name. elsif ($_[0]) { if (! -e) { print "\nSorry, $gcos, the file \"$_\" does not exist.\n\n"; } elsif (! -f) { print "\nSorry, $gcos, \"$_\" is not a plain file.\n\n"; } elsif (! -r) { print "\nSorry, $gcos, you do not have system permission to read\n"; print "the following file:\n\n"; print $_, "\n"; print "This file is owned by "; $owner = (getpwuid((stat $_)[4]))[6]; $owner = "root" if $owner eq "Operator"; print "$owner.\n\n"; } elsif (! -T) { print "\nSorry, $gcos, \"$_\" is not a text file.\n\n"; } else { &checkFile ($_); } } else { $totalFileCount++; } } } sub checkFile { my ($file) = $_[0]; $firstMessageInFile = 0; open STDIN, $file if $file; while () { if (! /^\s*[^\!]+[\!]/) # if this is not part of a !!!!! error message embedded in the code { if ( (/ERROR\s*\d*\-?\d*\s*:/ && ! /\b[Pp][Uu][Tt]\b.+ERROR:/) || /ERROR DETECTED/ || (/WARNING/ && ! (/Compression was disabled/ || /expire/ || /\b[Pp][Uu][Tt]\b.+WARNING/ || /(\'|\")\s*WARNING/)) || /values have been converted/ || /Missing values were gen/ || /uninitialized/ || /more than one data set with repeats of BY values/ || /Invalid/ || /Mathematical/ || /At least/ || /misspelled/ || /ignored/ || /is not valid or it is used out of proper order/ || /roups are not created/ || /nreferenced label/ || /pparent/ || /stopped due to looping/ || /already sorted/ || /already on the library/ || /Message\(s\) received/ || /appears on a DELETE/ || /went to a new line/ || /ivision by zero/ || /has no effect/ || /requires remerging/ || /\!/ || /outside the axis range/ || /Cartesian product joins/ || /The query as specified involves/ || /because of missing values/ || /overwritten/ || /\*W\*A\*R\*N\*I\*N\*G/ || ( $processingNotices && /NOTICE/ ) ) { if ($totalFileCount > 1 && ! $firstMessageInFile) { print "\n$file:\n"; $firstMessageInFile = 1; } s/^\s*([^\r]+).*/$1/; print "[line $.] $_"; } } } close STDIN; }