#!/usr/bin/perl -w # # SCCS information: # @(#) File: ftpuploads.pl # @(#) Version: 1.18 # @(#) SCCS Base: ./SCCS/s.ftpuploads.pl # @(#) Updated on: 06/04/22 at 11:08:44 # @(#) Obtained on: 06/04/22 at 11:14:55 # # Purpose: # Monitor the incoming ftp traffic and transmit the files of inter +est # to the relevant production server. Direct access to production # servers is not given to outsiders. # # Description: # Monitor the ftplog which is in wuftp format. Ignore files that # are outgoing, done by anonymous login, incomplete transfers, or # in directories not of interest. For the directories of interest +, # transmit the file to the mapped production server using ftp and # on successful ftp, move the file to an archive directory. # Log the actions in a log file per purpose. # The log files and archive directories are created per day, so # that their cleanup is easy. # This program replaces a host of cron jobs running earlier, # improves the reaction time, and processes only completely # transferred files. # # How to Use: # Define parameters in /opt/TouchBase/config/ftptargets.txt and # /opt/TouchBase/config/ftpdirmap.txt files. # Run the program as a background job, redirecting its output. # This job is a daemon. It does not exit. It must always be # running. # use strict ; use Env ; # To access environment variab +les use File::Path ; # To run 'mkpath' use Getopt::EvaP; # For processing command line +parameters use Data::Dumper ; # Used only for debugging statements use Net::FTP; # Perl Ftp Module for transferring fi +le use Shell qw(mv) ; # Invoke shell command seamlessly use sigtrap qw(die normal-signals) ; # Signal handling use XML::Simple ; # XML parsing sub main() ; # Main sub funcCommand($$) ; # Run specified commands sub funcLHOpush($$$) ; # Process files at the LHO servers sub funcTransmit($$$) ; # Ftp files from one server to another sub getLine($$) ; # Get line number to read from ftp log sub initialize() ; # Initialization sub logError($) ; # Log error sub mainloop() ; # The main loop. sub move($$$) ; # To archive the process files sub openConnection($) ; # Open an ftp connection sub processFile($$) ; # Process one incoming file sub processArgv() ; # To process the command line argument +s sub readDirMap($$) ; # Gead file which holds directory mapp +ing sub readNoProcess($) ; # Read file that hold patterns sub readTargets($$) ; # Read file which holds targets inform +ation sub readUserDetails($) ; # To determine 'ftparea' of user sub sigHandler() ; # Interrupt handler sub timestamp() ; # Nicely formatted date and time stamp sub today() ; # Today's date in YYYYMMDD format sub validConnection($) ; # Checks that a ftp connection is still va +lid sub windup() ; # Clean up routine sub writeRestart() ; # write in restart file sub ERROR { -1 } ; sub FALSE { 0 } ; # This is like #define of C sub TRUE { 1 } ; # TRUE and FALSE are used for booleans sub RESTARTMAIN { 2 } ; sub REREADLOG { 3 } ; my %cmdarg ; # Hash which stores the command line a +rguments my $currPos ; # Current line number in logfile my $debug = 1 ; # Debug level my $debugFile ; # Debug file name my %dirinfo = () ; # Information about directory mapping my $error = FALSE ; # Global flag that error has occurred my $errorFile = "PROGRAM.error.txt" ; my $ftpLog ; # Path of the ftp log file to monitor my $ftpDirMap ; # Holds path of file which maps target +s to directories my $ftpTargets ; # Holds path of file which has info on + target my $host ; # Holds hostname of user machine my $lastReadDatetime ; # Date of last incoming file processed + by program my $lastReadDatetimeSno ; # Serial numbser of file with the same + last date my %log ; # Information about log files my $noProcess ; # File with patterns my @MM ; # Holds info on command line parameter +s my %month ; # Translates month name to month number my @months = qw( jan feb mar apr may jun jul aug sep oct nov dec) ; my @PDT ; # Holds default values of command line + parameters my $osType ; # The operating system on which the pr +ogram is run my $openLog ; # Flag set when log is to be opened my @pattern = () ; # Hash with patterns of directories no +t to processed my $prodMode ; # Indicates mode of running of program + my $resetInterval ; # Idle interval my $restartFile = "PROGRAM.restart" ; my $runMode ; # Holds the program execution mode my %target = () ; # Information about ftp target machines my $tempPath ; # Holds the path of the temporary file +s my $user ; # Holds logname of user my %failed = () ; # Hash for holding info abt targets wi +th which ftp # connection is failed. my $failedtarget=''; # target name with which ftp connectio +n is failed my @weekdays # Name for weekday. Used for logs = qw( Sun Mon Tue Wed Thu Fri Sat ) ; my %notArchived ; # Hash to store inforamation on files +that # have been processed but not archived @PDT = split /\n/, <<end_of_PDT ; PDT debug, d: key 0,1,2,3 keyend = 1 debugfile, df: string = "PROGRAM.debug.txt" ftpdirmap, fd: string = "/opt/TouchBase/config/ftpdirmap.txt" ftptargets, ft: string = "/opt/TouchBase/config/ftptargets.txt" noprocess, np: string = "/home/scripts/data/noProcess.txt" prodmode, p: switch 0,1, keyend = 0 PDTEND no_file_list end_of_PDT @MM = split /\n/, <<end_of_MM ; Monitor the incoming ftp traffic and transmit the files of intere +st to the relevant production server. Direct access to production servers is not given to outsiders. .debug Switch which decides if debug messages are to be generated. .ftpdirmap Name of the file that maps the incoming file directories to the target servers. .ftptargets Name of the file that holds the information necessary to connect to the target servers. .noprocess Name of the file that holds the patterns of directories that are not to be processed. .prodmode Switch, when runs, executes the program in production mode. end_of_MM #-------------------------------------------------------------------- # The main entry point # sub main() { $SIG{'HUP'} = 'IGNORE' ; $SIG{'INT'} = 'sigHandler' ; $SIG{'TERM'} = 'sigHandler' ; $| = 1 ; *STDERR = *STDOUT ; # Let errors also come to stdout initialize() ; print DEBUGFILE "Initialization complete.\n" if $debug ; $currPos = undef ; while ( TRUE ) { my $status = mainloop() ; # This will return when it ne +eds to be restarted . print DEBUGFILE "Received \'$status\' from mainloop.\n" if $de +bug ; } } #-------------------------------------------------------------------- # Initialization # Read the input parameter files and store in memory # sub initialize() { processArgv() ; $host = `hostname` ; chomp $host ; $user = $LOGNAME ; if ( ! -d "/tmp/$LOGNAME" ) { mkdir "/tmp/$LOGNAME" ; } $tempPath = "/tmp/$LOGNAME" ; # Extracting the name of the program # Directory name and extension removed my $progName = $0 ; $progName =~ /^.*(?:(\/))(?(1)(.*))$/ ; if ( $2 ) { $progName = $2 ; } $progName =~ /^(.*)(?:(\.))(?(2)(.*))$/ ; if ( $3 ) { $progName = $1 ; } # Prefix the name of the program to the # debugfile name, errorfile name and # the restart file. # The present working directory is the # path in which restart file is present. $debugFile =~ s/PROGRAM/$progName/ ; $errorFile =~ s/PROGRAM/$progName/ ; $restartFile =~ s/PROGRAM/$progName/ ; $debugFile = "$tempPath/$debugFile" ; if ($debug) { open (DEBUGFILE, ">$debugFile") || die "Unable to open debug fi +le.\n" ; select DEBUGFILE ; $| = 1 ; select STDOUT ; } $errorFile = "$tempPath/$errorFile" ; open (ERRORFILE, ">$errorFile") || die "Unable to open error file. +\n" ; select ERRORFILE; $| = 1 ; select STDOUT ; ($prodMode == 0) ? ($runMode = "TEST") : ($runMode = "PROD") ; print DEBUGFILE "Program is running in $runMode mode.\n" if $debug + ; print "Program running in $runMode mode.\n" ; print DEBUGFILE "Restart file = $restartFile\n" if $debug ; print DEBUGFILE "Ftp DirMap file = $ftpDirMap\n" if $debug ; print DEBUGFILE "Ftp Targets file = $ftpTargets\n" if $debug ; print DEBUGFILE "No Process file = $noProcess\n" if $debug ; # Checking the OS type to decide # the ftp log file to use $osType = $^O ; chomp $osType ; if ( $osType =~ /^hpux$/i ) { $ftpLog = "/var/adm/syslog/xferlog" ; } elsif ( $osType =~ /^aix$/i ) { $ftpLog = "/var/adm/syslog/ftp.log" ; } else { print DEBUGFILE "OS type ($osType) no recognized. Quitting.\n" + if $debug ; print "OS type ($osType) not recognized\n" ; exit 1 ; } print DEBUGFILE "OS Type = $osType\n" if $debug ; print DEBUGFILE "FTP Log = $ftpLog\n" if $debug ; my $mm = 1 ; for my $mon (@months) { # Populate hash to get month number $month{lc $mon} = sprintf "%02d", $mm ; # from 3-letter month +name $mm++ ; } # Set log open flag to false $openLog = TRUE ; # Set reset interval to 10 min $resetInterval = 600 ; # Read data file and populate %target readTargets($ftpTargets, "all") ; print DEBUGFILE "Targets ($ftpTargets) read.\n" if $debug > 1 ; # Read data file and populate %dirinfo readDirmap($ftpDirMap, "all") ; print DEBUGFILE "Dirmap ($ftpDirMap) read.\n" if $debug > 1 ; # Read no process file readNoProcess($noProcess) ; print DEBUGFILE "File with directories ($noProcess), that are not +to be processed, read.\n" if $debug > 1 ; # Resetting notArchived flag $notArchived{'FLAG'} = FALSE ; # Check the restart point if ( ! -e $restartFile ) { # No last restart point print STDERR "Restart file, $restartFile, does not exist\n" ; exit 1 ; } elsif ( ! -r $restartFile ) { print STDERR "Can't read $restartFile\n" ; } # Entry in the restart file is in the format # # YYYYMMDD_HHMMSS dd # '--'\/\/ \/\/\/ \/ # | ' ' ' ' ' '-----> Count of files with same timestam +p # ' ' ' ' ' '-----------> Seconds # ' ' ' ' '-------------> Minutes # ' ' ' '---------------> Hours (24 Hrs) # ' ' '------------------> Day # ' '--------------------> Month # '----------------------> Year # open( RESTART, "$restartFile" ) or die "Can't open $restartFile" ; my $restartPoint = <RESTART> ; close RESTART ; if ( ! defined $restartPoint || $restartPoint !~ /\S/ ) { $restartPoint = '' ; $lastReadDatetime = '' ; $lastReadDatetimeSno = '' ; } if ( $restartPoint !~ /^(\d{8}_\d{6})\s+(\d+)/ ) { print STDERR "Restart file is not in proper format\n" ; exit 1 ; } else { $lastReadDatetime = $1 ; $lastReadDatetimeSno = $2 ; } print DEBUGFILE "From restart file [$lastReadDatetime][$lastReadDa +tetimeSno]\n" if $debug ; open( RESTART, ">$restartFile" ) or die "Can't open $restartFile" +; select RESTART ; $| = 1 ; select STDOUT ; seek RESTART, 0, 0 ; # Rewrite the file. printf RESTART "$lastReadDatetime\t%5d\n", $lastReadDatetimeSno ; # Write the last read date and time. The length must be constant. } #-------------------------------------------------------------------- # Trnsmit the required file. # Input: # Output: None # sub funcTransmit($$$) { my $file = $_[0] ; my $filesize = $_[1] ; my $d = $_[2] ; my $result = FALSE ; my $dir = $d->{DIR} ; my $tname = $d->{TARGET} ; # Target name, e.g. sbib24 my $t = $target{$tname} if defined $target{$tname} ; # Hash refe +rence for target information my $s = $t->{SESSION} if defined $t ; # Reference to ftp sessi +on created for target my $logfile = $d->{LOGFILE} ; if ( ! defined $t ) { print DEBUGFILE "\tTarget not defined for $dir/$file .\n" if $debu +g ; logError "Target not defined" ; return ERROR ; } $s = openConnection($t) unless ( $s && validConnection($s) ) ; if ( $failed{$tname} && $s ) { $failedtarget = $tname ; return RESTARTMAIN ; } unless ( $s ) { logError( "Can't open ftp session with $tname this time" ) ; print {$log{$logfile}{FH}} timestamp() . "\t$runMode\tFailed\t +$file\tCould not open ftp session for $tname\n" if ( $log{$logfile}{F +H} ) ; if( ! defined $failed{$tname} ) { $failedtarget = $tname ; $failed{uc $failedtarget} = $failedtarget ; $failed{$failedtarget}{TIME} = $lastReadDatetime ; $failed{$failedtarget}{SNO} = ($lastReadDatetimeSno-1) ; $failedtarget = undef ; } return ERROR ; } print DEBUGFILE "\tHave ftp connection to $tname\n" if $debug ; # Check that target directory exists and is reachable my $targetDir = $d->{TARGET_DIR} ; if ( ! $s->cwd( $targetDir ) ) { logError "Target directory $targetDir is not reachable" ; print {$log{$logfile}{FH}} timestamp() . "\t$runMode\tFailed\t +$file\tCan't go to $targetDir on $tname\n" if ( $log{$logfile}{FH} ) +; return ERROR ; } print DEBUGFILE "\tChanged dir to $targetDir\n" if $debug > 1; # Moving file to required target. if ( ! $s->put( "$dir/$file" ) ) { logError "Error in putting file $dir/$file to $tname at $targe +tDir" ; print {$log{$logfile}{FH}} timestamp() . "\t$runMode\tFailed\t +$file\tFTP transfer failed midway\n" if ( $log{$logfile}{FH} ) ; return ERROR ; } print DEBUGFILE "\tTransferred $file to $targetDir\n" if $debug ; print {$log{$logfile}{FH}} timestamp() . "\t$runMode\tSent\t$file\ +t$filesize\n" if ( $log{$logfile}{FH} ) ; # Passed all error checks. Must be successful. $result = TRUE ; writeRestart() ; if ( $t->{CHMOD} ) { print DEBUGFILE "\tGoing to execute chmod $t->{CHMOD} $file\n" + if $debug > 1 ; my $retval = $s->site("chmod $t->{CHMOD} $file") ; print DEBUGFILE "\tchmod returned $retval\n" if $debug > 1 ; # Return value is not predictable here. Hope for the best. } return $result ; } #------------------------------------------------------------------ # Run the command in the file # Input: # Output: None # sub funcCommand($$) { my $file = $_[0] ; my $d = $_[1] ; my $result = FALSE ; my $arg1 = '' ; my $arg2 = '' ; print DEBUGFILE "Processing command file [$file]\n" if $debug ; my $dir = $d->{DIR} ; my $logfile = $d->{LOGFILE} ; my $today = today() ; open( CMDFILE, "$dir/$file" ) || die "Unable to open $file for rea +ding.\n" ; my $cmd = <CMDFILE> ; chomp $cmd ; close CMDFILE ; if ( $cmd !~ /^\s*(\S+)\s+(.+)\s*$/ ) { print STDERR "Command file is not in proper format.\n" ; return ERROR ; } else { $arg1 = $1 ; $arg2 = $2 ; } print DEBUGFILE "Command arguments are [$arg1][$arg2]\n" if $debug + > 1 ; if ( $arg1 =~ /^READTARGETS$/i ) { print "Re-reading Target file [$ftpTargets]\n" ; readTargets($ftpTargets,$arg2) ; writeRestart() ; $result = TRUE ; } elsif ( $arg1 =~ /^READDIRMAP$/i ) { print "Re-reading Dirmap file [$ftpDirMap]\n" ; readDirmap($ftpDirMap,$arg2) ; writeRestart() ; $result = TRUE ; } elsif ( $arg1 =~ /^RESTART$/i ) { if ( $arg2 =~ /^(\d{8}_\d{6})$/ ) { print "Restart command valiadated. Restarting..\n" ; $lastReadDatetime = $1 ; $lastReadDatetimeSno = 1 ; my $archiveDir = $d->{ARCHIVE_DIR} ; $archiveDir =~ s/YYYYMMDD/$today/ ; mkdir $archiveDir unless -d $archiveDir ; move( $file, $archiveDir, $d ) ; # status not important. restart mandatory. return RESTARTMAIN ; } else { print DEBUGFILE "\tArguments specified are incorrect.\n" i +f $debug ; logError "Second argument is not correct. Cannot execute [ +$cmd]" ; return ERROR ; } } elsif ( $arg1 =~ /^READNOPROCESS$/i ) { if ( $arg2 =~ /^reset$/i ) { print "Resetting patterns.Re-reading NoProcess file [$noPr +ocess]\n" ; @pattern = () ; print DEBUGFILE "\tPatterns (\@pattern) reset.\n" if $debu +g > 1 ; readNoProcess($noProcess) ; } elsif ( (-e $arg2) and (-r $arg2) ) { print DEBUGFILE "\t[$arg2] is the noProcess file.\n" if $d +ebug > 1 ; print "Re-reading NoProcess file [$arg2]\n" ; readNoProcess($arg2) ; } else { print DEBUGFILE "\tArgument [$arg2] is invalid.\n" if $deb +ug ; logError "Second argument is incorrect. Cannot execute [$c +md]" ; return ERROR ; } writeRestart() ; $result = TRUE ; } return $result ; } #------------------------------------------------------------------ # Process file (at the LHO) and push to branch # Input: # Output: None # sub funcLHOpush($$$) { my $dir = $_[0] ; my $file = $_[1] ; my $d = $_[2] ; my $sendLine ; print DEBUGFILE "\tProcessing file for LHO [$dir/$file].\n" if $de +bug > 1 ; my $logfile = $d->{LOGFILE} ; my $spool = $d->{SPOOL_DIR} ; my $spoolFile = "$spool/ftplist.due" ; my $ftparea = $d->{FTPAREA} ; my ($branchCode, $relPath) ; if ( $dir =~ /^($ftparea)\/locations\/(b[^\/]+)\/(.*)$/ ) { $branchCode = $2 ; $relPath = $3 ; } else { print DEBUGFILE "\tDir pattern [$dir] is not in the correct fo +rmat.\n" if $debug ; return FALSE ; } my $source = "$relPath/$file" ; my $target = "$relPath/$file" ; $sendLine = "$branchCode\t$source\t$target" ; print DEBUGFILE "\tOpening spool file [$spoolFile].\n" if $debug > + 1 ; if ( !(open (FTPLIST, ">>$spoolFile")) ) { print DEBUGFILE "\tUnable to open spoolfile [$spoolFile].\n" i +f $debug ; logError "Unable to open spoolfile \'$spoolFile\'" ; print {$log{$logfile}{FH}} timestamp() . "\t$runMode\tError\t$ +file\t$spoolFile not accessible for $branchCode\n" if ( $log{$logfile +}{FH} ) ; return ERROR ; } select FTPLIST ; $| = 1 ; select STDOUT ; print DEBUGFILE "\tEntry in spoolFile [$sendLine].\n" if $debug > +1 ; if ( ! print FTPLIST "$sendLine\n" ) { print DEBUGFILE "\tUnable to write into file [$spoolFile].\n" +if $debug > 1 ; logError "Unable to write into '\$spoolFile\'" ; print {$log{$logfile}{FH}} timestamp() . "\t$runMode\tError\t$ +file\t$spoolFile not writable for $branchCode\n" if ( $log{$logfile}{ +FH} ) ; close FTPLIST ; return ERROR ; } close FTPLIST ; writeRestart() ; print {$log{$logfile}{FH}} timestamp() . "\t$runMode\tDone\t$file\ +tReport processed for $branchCode\n" if ( $log{$logfile}{FH} ) ; return TRUE ; } #-------------------------------------------------------------------- # Read line fron ftp log file # Input : Date-Time, Count # Output : Position in bytes # sub getLine($$) { my $datetime = $_[0] ; my $datetimeSno = $_[1] ; # For the format of the entry made in the log file, look at th +e # example in 'mainloop' # datetime is in the format 'yyyymmdd_hhmmss' $datetime =~ /(\d{4})(\d{2})(\d{2})_(\d{2})(\d{2})(\d{2})/ ; # preDate = 'Month' # date = date, single or double digit # postDate = 'Time Year' my $preDate = $months[($2)-1] ; my $date = 0 + $3 ; my $postDate = "$4:$5:$6 $1" ; print DEBUGFILE "Comparing in log file for [$preDate $date $postDa +te]\n" if $debug ; my $lineCount = 0 ; my $byteCount = 0 ; seek (FTPLOG, 0, 0) ; while (<FTPLOG>) { $lineCount++ ; $byteCount += length($_) ; if ( grep / $preDate ($date|0$date| $date) $postDate /i, $_ ) + { my $offset = 1 ; my $logEntry ; while ( $offset < $datetimeSno ) { $logEntry = <FTPLOG> ; if ( grep / $preDate ($date|0$date| $date) $postDate / +i, $logEntry ) { $byteCount += length($logEntry) ; $offset++ ; $lineCount++ ; } else { $datetimeSno = $offset ; last ; } } last ; } else { next ; } } my $lineToRead = $lineCount ; print DEBUGFILE "Line number from which program is reading [$lineT +oRead]\n" if $debug ; print DEBUGFILE "Position in file is [$byteCount].\n" if $debug > +1 ; return $byteCount ; } #-------------------------------------------------------------------- # Log error in the log file # Input: Error message # Output: None # sub logError($) { my $msg = $_[0] ; if ( ! $error ) { print ERRORFILE timestamp()."\tProgram is running in $runMode +mode.\n" ; $error = TRUE ; } print ERRORFILE timestamp()."\t$msg\n" ; } #-------------------------------------------------------------------- # This is the main processing loop. # It waits for files to come into the server through ftp and immediate +ly # moves them to the target server. # It does not return from this function. # sub mainloop() { # Open file and use the filehandle in getline my $logInode = (stat($ftpLog))[1] ; print DEBUGFILE "Inode of ftplog ($ftpLog) is [$logInode]\n" if $d +ebug > 1 ; if ( $openLog ) { print DEBUGFILE "Opening log ($ftpLog).\n" if $debug > 2 ; open( FTPLOG, "$ftpLog") or die "Can not open ftplog" ; $openLog = FALSE ; } if ( ! defined $currPos ) { $currPos = getLine($lastReadDatetime, $lastReadDatetimeSno) ; } seek (FTPLOG, $currPos, 0) ; my $retVal ; my $lastProcessed = time ; print DEBUGFILE "Reading log (from $currPos) for incoming files vi +a ftp\n" if $debug ; while ( (time - $lastProcessed) < $resetInterval ) { while ( <FTPLOG> ) { $currPos += length($_) ; $lastProcessed = time ; my ($weekday, $mon, $dd, $hms, $yyyy, $duration, $fromIp, +$filesize, $dirfile, $xferMode, $splActionFlag, $direction, $real +Anon, $user, $service, $authMethod, $authUserId, $lastField +) = split ; # Sample line read from the log file # Mon Apr 18 17:10:47 2005 1 10.0.20.23 1068 /INTERFACES +/STEPS/STEPS-OUTGOING-ENCRYPTED/001921000000249210000000024 b _ i r w +inftpuser ftp 0 * c/60 # Explanation of fields in the log line # Fields unused by ftpd, hence can be ignored # $splActionFlag (always '_') # $service (always 'ftp' ) # $authMethod (always '0' ) # $authUserId (always '*' ) # Obvious fields - One can figure out by looking at sample + line # $weekday = Day of the week, 3 character # $mon = Month, 3 character # $dd = Day of the month # $hms = Time, in hour:minute:seconds # $yyyy = Year, 4 digit # $fromIp = IP address of client machine # $filesize = Size of the file in bytes # $dirfile = Full name of the file with absolute path # $user = ftp user id # Other fields # $duration = Duration of transfer in seconds, minimum 1 # $xferMode = 'a' for Ascii, 'b' for Binary # $direction = 'i' for incoming file, 'o' for outgoing f +ile # $realAnon = 'r' for real user, 'a' for anonymous user # $lastField varies depending on OS. # on hpux : $lastFiled indicates the current time i +n seconds # in linux : 'c' for complete transfer, 'i' for inco +mplete transfer # However, it is found to be 'c' even whe +n ^C is # pressed in ftp client session and trans +fer aborted. # May not be reliable. # next unless $direction eq 'i' ; # Consider only incomi +ng files next unless $realAnon eq 'r' ; # Consider only real u +sers if ( $osType =~ /linux/i ) { # Consider only complete transfers # Check valid while running on Linux next unless $lastField eq 'c' ; } $hms =~ s/://g ; # Change from HH:MM:SS to HHMMSS my $mm = $month{lc $mon} ; my $day = sprintf "%02d", $dd ; my $datetime = "$yyyy$mm$day" . "_$hms" ; if ( $datetime eq $lastReadDatetime ) { $lastReadDatetimeSno++ ; } else { $lastReadDatetime = $datetime ; $lastReadDatetimeSno = 1 ; } print DEBUGFILE "Read \'$_" if $debug > 1 ; print DEBUGFILE "Values reset : BytesRead [$currPos] Time + [$lastProcessed].\n" if $debug > 2 ; $retVal = processFile($dirfile, $filesize) ; if ( $retVal == ERROR ) { print DEBUGFILE "Error while processing $dirfile\n" if + $debug ; logError "Error while processing $dirfile" ; } elsif ( $retVal == FALSE ) { print DEBUGFILE "Not processing $dirfile\n" if $debug +; } elsif ( $retVal == RESTARTMAIN ) { if ( defined $failed{$failedtarget} ) { $lastReadDatetime=$failed{$failedtarget}->{TIME} ; $lastReadDatetimeSno=$failed{$failedtarget}->{SNO} + ; $failed{$failedtarget} = undef ; $failedtarget = undef ; } print DEBUGFILE "RESTARTING with [$lastReadDatetime][$ +lastReadDatetimeSno].\n" if $debug ; return $retVal ; } print DEBUGFILE "Waiting for incoming file via FTP\n" if $ +debug ; } sleep 1 ; print DEBUGFILE "Checking program idle time.\n" if $debug > 2 +; } print DEBUGFILE "Checking if \'$ftpLog\' is valid.\n" if $debug > +2 ; my $inodeNow = (stat($ftpLog))[1] ; if ( $logInode != $inodeNow ) { $currPos = 0 ; $openLog = TRUE ; print DEBUGFILE "Changed inode value = [$inodeNow]\n" if $debu +g > 1 ; print DEBUGFILE "Rereading ftp log ($ftpLog) from [$currPos]. +Inode value changed.\n" if $debug ; } else { $openLog = FALSE ; } return REREADLOG ; } #-------------------------------------------------------------------- # To archive the processed files # sub move($$$) { my $file = $_[0] ; my $destination = $_[1] ; my $d = $_[2] ; my $result = FALSE ; my $dir = $d->{DIR} ; my $logfile = $d->{LOGFILE} ; mv ( "$dir/$file" , $destination ) ; if ( $? != 0 ) { # Error in move logError "Failed to move $dir/$file to $destination" ; print {$log{$logfile}{FH}} timestamp() . "\t$runMode\tNoArch\t +$file\tCould not archive to $destination\n" if ( $log{$logfile}{FH} ) + ; print DEBUGFILE "Unable to archive $dir/$file to $destination\ +n" if $debug ; $result = ERROR ; $notArchived{'FLAG'} = TRUE ; push @{$notArchived{$dir}}, $file ; print DEBUGFILE " Files not archived : " . Dumper(%notArchived +) ."\n" if $debug > 1 ; } else { print DEBUGFILE "\tArchived $file to $destination\n" if $debug + ; $result=TRUE ; } return $result ; } #-------------------------------------------------------------------- # Open ftp connection for the given target. # Fill the session id in the target structure. # Return session id. # Input: Reference to target hash # Output: Reference to session if opened # undef in cases of any error # sub openConnection($) { my $t = $_[0] ; print DEBUGFILE "\tOpening ftp connection with $t->{IPADDR}:$t->{P +ORT}\n" if $debug ; #open the Ftp connection to HOST my $ftpSession = Net::FTP->new( $t->{IPADDR}, Port => $t->{PORT}) +; $t->{SESSION} = $ftpSession ; if ( ! $ftpSession ) { logError "Can not open ftp session with $t->{IPADDR}" ; return FALSE ; } # Login as ftp user/password unless ( $ftpSession->login( $t->{USER}, $t->{PWD} ) ) { logError "FTP login failed for $t->{IPADDR} with user = $t->{U +SER} and password = $t->{PWD}\n" ; return FALSE ; } $ftpSession->binary() ; # Set transfer mode to binary return $ftpSession ; # Return the session } #-------------------------------------------------------------------- # Function to process the command line arguments. # Input: None # Output: None # sub processArgv() { &EvaP( \@PDT, \@MM, \%cmdarg ) ; $debug = $cmdarg{'debug'} ; $debugFile = $cmdarg{'debugfile'} ; $ftpDirMap = $cmdarg{'ftpdirmap'} ; $ftpTargets = $cmdarg{'ftptargets'} ; $noProcess = $cmdarg{'noprocess'} ; $prodMode = $cmdarg{'prodmode'} ; } #-------------------------------------------------------------------- # Process one file that has arrived into the ftp server # Transfer the file to its target ftp server into appropriate director +y # Log the action # Input: Incoming filename with absolute path # Size of the file in bytes # Output: TRUE for success # FALSE for failure # sub processFile($$) { my $dirfile = $_[0] ; my $filesize = $_[1] ; my $result = FALSE ; my @actions = () ; # Separate the directory name and the file name $dirfile =~ /(.*)\/(.*)/ ; # Search is greedy. First pattern gets + till last slash my $dir = $1 ; my $file = $2 ; my $ext = '' ; $ext = $1 if ( $file =~ /.*\.(.*)/ ) ; # Extract extension from + file name my $dirkey = $dir . ":" . $ext ; # Check if dir matches with patterns of directories if ( $#pattern >= 0 ) { foreach ( @pattern ) { if ( $dirkey =~ /.*$_.*/ ) { print DEBUGFILE "Directory [$dir] matches [$_] in \'no +Process\' file.\n" if $debug ; return FALSE ; } } } # Check if dirkey is present. If not, then # check if dirkey without extension exists. # # Also if BASE_DIR is set, check if the directory # specified in the dirmap matches the incoming directory. my $ignoreDir = TRUE ; if (! $dirinfo{$dirkey} ) { # Remove 'ext' $dirkey =~ s/(.*)\:(.*)/$1\:/ ; if (! $dirinfo{$dirkey} ) { # If the BASE_DIR flag is set for any of the valid # directories, check with and without 'ext' for my $dirs ( keys %dirinfo ) { if ( $dirinfo{$dirs}{BASE_DIR} eq "Y" ) { if ( $dir =~ /^$dirinfo{$dirs}{DIR}\/.*$/ ) { $dirkey = $dirinfo{$dirs}{DIR}.":".$ext ; if (! $dirinfo{$dirkey} ) { $dirkey =~ s/(.*)\:(.*)/$1\:/ ; if ( $dirinfo{$dirkey} ) { $ignoreDir = FALSE ; last ; } } else { $ignoreDir = FALSE ; } } } } } else { $ignoreDir = FALSE ; } } else { $ignoreDir = FALSE ; } if ($ignoreDir == TRUE) { print DEBUGFILE "Unexpected incoming ftp $dir/$file\n" if $deb +ug ; return FALSE ; } print DEBUGFILE "DirKey used is [$dirkey].\n" if $debug > 1 ; my $d = $dirinfo{$dirkey} ; # Hash reference for directory inform +tion print DEBUGFILE "Noticed $dir/$file\n" if $debug ; if ( $d->{ACTION} eq 'IGNORE' ) { print DEBUGFILE "\t$dir/$file to be ignored.\n" if $debug > 1 +; return FALSE ; } print DEBUGFILE "\tProcessing $dir/$file\n" if $debug ; if ( ($notArchived{'FLAG'} == TRUE) && (defined $notArchived{$dir} +) ) { if ( grep /$file/, @{$notArchived{$dir}} ) { print DEBUGFILE "\t\'$dir/$file\' processed earlier but no +t archived.\n" if $debug > 1 ; print DEBUGFILE "\tNot processing in current run.\n" if $d +ebug ; logError "File [$dir/$file] processed earlier but not arch +ived." ; return FALSE ; } } my $today = today() ; # Open a new log file every day my $logfile = $d->{LOGFILE} ; $log{$logfile}{DATE} = "00000000" if (! defined $log{$logfile}{DAT +E}) ; if ( $log{$logfile}{DATE} ne $today ) { # Date has changedi close $log{$logfile}{FH} if defined $log{$logfile}{FH} ; $log{$logfile}{FILENAME} = $logfile ; $log{$logfile}{FILENAME} =~ s/YYYYMMDD/$today/ ; # Fill to +day's date at appropriate place # Open the log file for writing if ( ! open( $log{$logfile}{FH}, ">>$log{$logfile}{FILENAME}" +) ) { print STDERR "Can not open log file $log{$logfile}{FILENAM +E}\n" ; $log{$logfile}{FH} = undef ; $log{$logfile}{DATE} = undef ; } else { select $log{$logfile}{FH} ; $| = 1 ; select STDOUT ; $log{$logfile}{DATE} = $today ; } } push @actions, $d->{ACTION} ; # Checking for existence of file before carrying on. if ( ! -e "$dir/$file" ) { logError "Incoming file not found in directory ($dir/$file)" ; print {$log{$logfile}{FH}} timestamp() . "\t$runMode\tFailed\t +$file\tIncoming file not present in directory\n" if ( $log{$logfile}{ +FH} ) ; return ERROR ; } while (@actions) { my $todo = pop @actions ; if ( $todo =~ /^TRANSMIT$/i) { $result = funcTransmit($file, $filesize, $d) ; return $result if ( $result != TRUE ) ; } elsif ( $todo =~ /^COMMAND$/i) { $result = funcCommand($file, $d) ; return $result if ( $result != TRUE ) ; } elsif ( $todo =~ /^LHOPUSH$/i ) { $result = funcLHOpush($dir, $file, $d) ; return $result if ( $result != TRUE ) ; } else { print DEBUGFILE "Action \'$todo\' not recognized.\n" if $d +ebug ; logError "Action \'$todo\' not recognized" ; return ERROR ; } } if ( ($prodMode == 1) && (defined $d->{ARCHIVE_DIR}) ) { # 1 in +dicates PROD my $archiveDir = $d->{ARCHIVE_DIR} ; $archiveDir =~ s/YYYYMMDD/$today/ ; # Fill today's date in dir +ectory name mkdir $archiveDir unless -d $archiveDir ; # Check if file is alreading present in archive directory. # If file is present, delete file, because 'mv' fails # due to permission conflict. if ( -e "$archiveDir/$file" ) { print DEBUGFILE "\tFile ($file) present in archive directo +ry. Removing old file.\n" if $debug > 1; unlink ("$archiveDir/$file") ; } # Transfer is successful. Now move the file to archive fo +lder $result = move( $file, $archiveDir, $d ) ; } return $result ; } #-------------------------------------------------------------------- # Read the dirmap file # sub readDirmap($) { my $fileDirMap = $_[0] ; my $dirToRead = $_[1] ; # Check if file exists print DEBUGFILE "Checking for file [$fileDirMap]\n" if $debug > 1 +; if ( ! -e $fileDirMap ) { print DEBUGFILE "File \'$fileDirMap\' does not exist.\n" if $d +ebug ; return ; } print DEBUGFILE "Reading directory information from $fileDirMap fo +r \'$dirToRead\'.\n" if $debug > 1 ; unless ( open( DIRMAP, $fileDirMap ) ) { print DEBUGFILE "Can not open $fileDirMap for reading\n" if $d +ebug ; return ; } # Checks for specified action are against the vales # specified below. All actions must have atleast one # value to check for. my %allowedActions = ( transmit => [ "target", "target_dir", " +archive_dir" ] , tbpush => [ "client", "appl", "archiv +e_dir" ] , transfer => [ "client", "appl", "archiv +e_dir" ] , command => [ "archive_dir" ] , lhopush => [ "spool_dir", "user_detail +s" ] , ) ; my @validParams = qw( dir ext action target target_dir client appl archive_dir logfile spool_dir user_details base_dir ) ; print DEBUGFILE "Allowed actions are : " . Dumper(%allowedActions) + ."\n" if $debug > 1 ; print DEBUGFILE "Valid parameters are : [ @validParams ]\n" if $de +bug > 1 ; while ( <DIRMAP> ) { next if /^\s*#/ ; # Skip comment lines next unless /\S/ ; # Skip blank lines chomp ; my $dirError = FALSE ; my @paramLine = split(/\s*\|\s*/); # Separated by pipe charact +er my @checkDir = () ; my %p = () ; # Value of parameters read from a line for my $param (@paramLine) { $param =~ s/\s*$// ; if ( $param =~ /^\s*([A-Za-z0-9_]+)\s*=\s*(.*)/ ) { if ( grep /^$1$/i, @validParams ) { eval '$p{' . uc $1 . '} =' . '$2;' ; print DEBUGFILE "Parameter $1 = $2\n" if $debug > 1 ; } else { print DEBUGFILE "Unrecognised Parameter \'$1\'\n" if $debu +g ; } } else { logError "Input syntax error in Parameter \'$param\'. It must +be in the form key=value" ; die ("Terminating due to syntax error in parameter file"); } } if ( defined $p{DIR} ) { # Continue if expected to read present target next unless ( ($dirToRead =~ /^all$/i) || ($p{DIR} =~ /^$d +irToRead$/i) ) ; if ( (defined $p{ACTION}) && (grep /$p{ACTION}/i, keys (%a +llowedActions)) ) { $p{ACTION} = lc $p{ACTION} ; if (! defined $allowedActions{$p{ACTION}} ) { print DEBUGFILE "\tNo checks specified for action +\'$p{ACTION}\'\n." if $debug ; print DEBUGFILE "\tNot reading other values for $p +{DIR}.\n" if $debug > 1 ; next ; } @checkDir = @{$allowedActions{$p{ACTION}}} ; print DEBUGFILE "\tChecks for \'$p{ACTION}\' are [@che +ckDir].\n" if $debug > 1 ; } else { $p{ACTION} = 'IGNORE' ; print DEBUGFILE "\tAction set to \'IGNORE\' for $p{DIR +}.\n" if $debug ; print DEBUGFILE "\tNot reading other values for $p{DIR +}.\n" if $debug > 1 ; next ; } my $tempVal ; foreach (@checkDir) { $tempVal = uc $_ ; if (! defined $p{$tempVal}) { print DEBUGFILE "\t\'$tempVal\' entry for $p{DIR} +not available. Ignoring $p{DIR}\n" if $debug ; $dirError = TRUE ; } } } else { $dirError = TRUE ; } if ( $dirError == TRUE ) { logError "\'$p{DIR}\' did not clear initial checks" ; next ; } unless ($p{LOGFILE}) { # Setting default logfile if not defined print DEBUGFILE "\t Setting default logfile for $p{DIR}\n" + if $debug ; $p{LOGFILE} = "$tempPath/default.YYYYMMDD" unless $p{LOGFI +LE} ; } $p{EXT} = '' unless $p{EXT} ; # Set default valu +e $p{TARGET} = lc $p{TARGET} if defined $p{TARGET} ; $p{BASE_DIR} = "N" if ( ! defined $p{BASE_DIR} ) ; my $dirkey = ( $p{DIR} . ":" . $p{EXT} ) ; # Ignore case in inp +ut file # TBD this is not required. Bad case is error anyway $dirinfo{$dirkey} = {} ; $dirinfo{$dirkey}{DIR} = $p{DIR} ; $dirinfo{$dirkey}{EXT} = $p{EXT} ; $dirinfo{$dirkey}{ACTION} = $p{ACTION} ; $dirinfo{$dirkey}{TARGET} = $p{TARGET} ; $dirinfo{$dirkey}{TARGET_DIR} = $p{TARGET_DIR} ; $dirinfo{$dirkey}{ARCHIVE_DIR} = $p{ARCHIVE_DIR} ; $dirinfo{$dirkey}{LOGFILE} = $p{LOGFILE} ; $dirinfo{$dirkey}{SPOOL_DIR} = $p{SPOOL_DIR} ; $dirinfo{$dirkey}{USER_DETAILS} = $p{USER_DETAILS} ; $dirinfo{$dirkey}{BASE_DIR} = $p{BASE_DIR} ; print DEBUGFILE " Values for $dirkey are " . Dumper($dirinfo{$ +dirkey}) ."\n" if $debug > 1 ; # Cheking if directory information is accurate # Incoming and archive directory are necessary for any act +ion, hence # we dont have to check if they are defined. my $dirCheck = TRUE ; print DEBUGFILE " Checking directory ($dirkey).\n" if $debug ; if ( -d $dirinfo{$dirkey}{DIR} ) { # Check if archive-dir is defined. # And then check for presence if ( defined $dirinfo{$dirkey}{ARCHIVE_DIR} ) { print DEBUGFILE " Checking archive directory \'$dirin +fo{$dirkey}{ARCHIVE_DIR}\'\n" if $debug > 1 ; my $archiveDir = $dirinfo{$dirkey}{ARCHIVE_DIR} ; $archiveDir =~ s/\/YYYYMMDD$// ; # Remove the variable + date part if (! -d $archiveDir ) { print DEBUGFILE "\tArchive directory \'$dirinfo{$d +irkey}{ARCHIVE_DIR}\' not present.\n" if $debug ; mkpath ($archiveDir, 0, 0755) ; print DEBUGFILE "\t Created $archiveDir\n" if $deb +ug > 1 ; } } # Similar check for spool-dir if ( defined $dirinfo{$dirkey}{SPOOL_DIR} ) { print DEBUGFILE " Checking spool directory \'$dirinfo +{$dirkey}{SPOOL_DIR}\'\n" if $debug > 1 ; my $spoolDir = $dirinfo{$dirkey}{SPOOL_DIR} ; if (! -d $spoolDir ) { print DEBUGFILE "\tSpool directory \'$spoolDir' no +t present.\n" if $debug ; logError "Directory $spoolDir not present" ; $dirCheck = FALSE ; } } } else { print DEBUGFILE "\tIncoming directory \'$dirinfo{$dirkey}{ +DIR}\' not present.\n" if $debug ; logError "Directory $dirinfo{$dirkey}{DIR} not present" ; $dirCheck = FALSE ; } # Reading userdetails, required for TBpush if ( ($dirCheck != FALSE) && (defined $dirinfo{$dirkey}{USER_D +ETAILS}) ) { print DEBUGFILE " Reading '\$dirinfo{$dirkey}{USER_DETAIL +S}\'\n" if $debug > 1 ; ($dirCheck, $dirinfo{$dirkey}{FTPAREA}) = readUserDetails( +$dirinfo{$dirkey}{USER_DETAILS}) ; # Check if the directory is present if ( $dirCheck != FALSE ) { print DEBUGFILE " Checking ftparea \'$dirinfo{$dirke +y}{FTPAREA}\'\n" if $debug > 1 ; if ( ! -d $dirinfo{$dirkey}{FTPAREA} ) { print DEBUGFILE "\tFtparea specified \'$dirinfo{$d +irkey}{FTPAREA}\' does not exist.\n" if $debug ; logError "Directory $dirinfo{$dirkey}{FTPAREA} not + present." ; $dirCheck = FALSE ; } } else { print DEBUGFILE "\tError while reading $dirinfo{$dirke +y}{USER_DETAILS}.\n" if $debug ; logError "Error while reading config file \'$dirinfo{$ +dirkey}{USER_DETAILS}\'" ; $dirCheck = FALSE ; } } if ( $dirCheck == FALSE ) { print DEBUGFILE "REMOVING information relating to $dirkey. +\n" if $debug ; delete $dirinfo{$dirkey} ; } else { print DEBUGFILE " Directory \'$dirkey\' validated.\n" if $ +debug ; } } close DIRMAP ; } #-------------------------------------------------------------------- # Read the noProcess file. # sub readNoProcess($) { my $fileNoProcess = $_[0] ; # Check if file exists. print DEBUGFILE "Checking for file [$fileNoProcess]\n" if $debug > + 1 ; if ( ! -e $noProcess ) { print DEBUGFILE " File \'$fileNoProcess\' does not exist.\n" i +f $debug ; return ; } unless ( open( NOPROCESS, "$fileNoProcess" ) ) { print DEBUGFILE "Can not open $fileNoProcess for reading\n" if + $debug ; return ; } print DEBUGFILE "Reading patterns from $fileNoProcess.\n" if $debu +g > 1 ; unless ( open ( NOPROCESS, "$fileNoProcess" ) ) { print DEBUGFILE "Unable to read $fileNoProcess\n" if $debug ; return ; } while ( <NOPROCESS> ) { next if /^\s*#/ ; # Skip comment lines next unless /\S/ ; # Skip blank lines my $inParamLine = $_ ; s/\s*$// ; # Remove trailing blanks chomp ; $_ =~ /^\s*(.*)\s*$/ ; push @pattern, $1 ; } close NOPROCESS ; print DEBUGFILE "Patterns specified are : [ @pattern ]\n" if $debu +g ; } #-------------------------------------------------------------------- # Read the ftp targets file. # sub readTargets($$) { my $fileTargets = $_[0] ; my $targetToRead = $_[1] ; # Check if file exists print DEBUGFILE "Checking for file [$fileTargets]\n" if $debug > 1 + ; if ( ! -e $fileTargets ) { print DEBUGFILE "File \'$fileTargets\' does not exist.\n" if $ +debug ; return ; } print DEBUGFILE "Reading target information from $fileTargets for +\'$targetToRead\'.\n" if $debug > 1 ; unless ( open( TARGETS, $fileTargets ) ) { print DEBUGFILE "Can not open $fileTargets for reading\n" if $ +debug ; return ; } my @validParams = qw( target ipaddr port user pwd chmod chown ) ; my @checkTarget = qw ( ipaddr user pwd ) ; print DEBUGFILE "Valid parameters are : [ @validParams ]\n" if $de +bug > 1 ; print DEBUGFILE "Checks are : [ @checkTarget ]\n" if $debug > 1 ; + while ( <TARGETS> ) { next if /^\s*#/ ; # Skip comment lines next unless /\S/ ; # Skip blank lines my $inParamLine = $_ ; s/\s*$// ; # Remove trailing blanks chomp ; my $targetError = FALSE ; my @paramLine = split(/\s*\|\s*/); # Separated by pipe charact +er my %p = () ; # Value of parameters read from a line for my $param (@paramLine) { $param =~ s/\s*$// ; if ( $param =~ /^\s*([A-Za-z0-9_]+)\s*=\s*(.*)/ ) { if ( grep /^$1$/i, @validParams ) { eval '$p{' . uc $1 . '} =' . '$2;' ; print DEBUGFILE "Parameter $1 = $2\n" if $debug > 1 ; } else { print DEBUGFILE "Unrecognised Parameter \'$1\'\n" if $debu +g ; } } else { logError "Input syntax error in Parameter \'$param\'. It must +be in the form key=value" ; die ("Terminating due to syntax error in parameter file"); } } if ( defined $p{TARGET} ) { # Continue if expected to read present target next unless ( ($targetToRead =~ /^all$/i) || ($p{TARGET} = +~ /^$targetToRead$/i) ) ; # Checking if required fields are # specified. my $tempVal ; foreach (@checkTarget) { $tempVal = uc $_ ; if (! defined $p{$tempVal} ) { print DEBUGFILE "\t\'$tempVal\' entry for $p{TARGE +T} not available. Ignoring $p{TARGET}\n" if $debug ; $targetError = TRUE ; last ; } } } else { $targetError = TRUE ; } if ( $targetError == TRUE ) { next ; } $p{PORT} = 21 unless $p{PORT} ; # Set default value $p{TARGET} = lc $p{TARGET} ; # Ignore case in input if ( defined $target{$p{TARGET}} ) { print DEBUGFILE "\tResetting the values for \'$p{TARGET}\' +.\n" if $debug ; } $target{$p{TARGET}} = {} ; $target{$p{TARGET}}{IPADDR} = $p{IPADDR} ; $target{$p{TARGET}}{PORT} = $p{PORT} ; $target{$p{TARGET}}{USER} = $p{USER} ; $target{$p{TARGET}}{PWD} = $p{PWD} ; $target{$p{TARGET}}{CHMOD} = $p{CHMOD} if $p{CHMOD} ; $target{$p{TARGET}}{CHOWN} = $p{CHOWN} if $p{CHOWN} ; print DEBUGFILE " Values for $p{TARGET} are " . Dumper($target +{$p{TARGET}}) ."\n" if $debug > 1 ; # Checking if target information is accurate. my $tname = $p{TARGET} ; print DEBUGFILE " Checking connection for $tname.\n" ; if ( (defined $target{$tname}->{SESSION}) && (validConnection( +$target{$tname}->{SESSION})) ) { print DEBUGFILE "\tConnection exists for $tname.\n" if $de +bug ; } else { unless ( openConnection($target{$tname}) ) { print DEBUGFILE "\tUnable to open connection with $tna +me.\n" if $debug ; print DEBUGFILE "REMOVING information on $tname.\n" if + $debug ; delete $target{$tname} ; } } print DEBUGFILE " Target \'$tname\' validated.\n" if $debug ; } close TARGETS ; } #-------------------------------------------------------------------- # sub sigHandler() { print DEBUGFILE "Ctrl+C or Kill caught.\n" if $debug ; exit ; } #-------------------------------------------------------------------- # Read user details. # sub readUserDetails($) { my $detailsFile = $_[0] ; print DEBUGFILE "\tReading config file \'$detailsFile\' for \'$hos +t\' .\n" if $debug > 2 ; if ( (! -e $detailsFile) || (! -r $detailsFile) ) { print DEBUGFILE "\tUnable to read [$detailsFile].\n" if $debug + ; return (FALSE, " ") ; } my $config = XMLin($detailsFile) ; my $hostInfo = $config->{$host} ; if (! $hostInfo) { print DEBUGFILE "\tHostInfo for \'$host\' no available in [$de +tailsFile].\n" if $debug ; return (FALSE, " ") ; } my $ftparea = undef ; # Parse file for ftparea details my $regions = $hostInfo->{REGION} ; foreach my $rgnInfo (@{$regions}) { if ( $rgnInfo->{USER} eq $user ) { $ftparea = $rgnInfo->{FTPAREA} ; print DEBUGFILE " Ftparea read is '\$ftparea\'\n" if $de +bug > 1 ; last ; } } return (TRUE, $ftparea) ; } #-------------------------------------------------------------------- # Form time stamp for log file # Return timestamp as a text sting. # sub timestamp() { my ( $sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localt +ime ; $year += 1900 ; $mon += 1 ; my $timeStamp = sprintf "%04d-%02d-%02d %3s %02d:%02d:%02d", $year, $mon, $mday, $weekdays[$wday], $hour, $min, $s +ec ; return $timeStamp ; } #-------------------------------------------------------------------- # Return today's date as YYYYMMDD # sub today() { my ( $sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localt +ime ; $year += 1900 ; $mon += 1 ; return sprintf "%04d%02d%02d", $year, $mon, $mday ; } #-------------------------------------------------------------------- # Check if a given ftp session is valid or not. The session times out # if not used for a long time. # Input: Reference to ftp session # Output: TRUE if ftp session is valid # FALSE if it is not valid # sub validConnection($) { my $s = $_[0] ; print DEBUGFILE "\tChecking if ftp connection is still valid\n" if + $debug > 1 ; # Carry out a simple command to test whether session is valid +or not # Change session mode to binary return $s->binary() ; } #-------------------------------------------------------------------- # Builds the restart file. Writes the date and time of the last # successfully process file. (Before chmod and archive.) # sub writeRestart() { seek RESTART, 0, 0 ; # Rewrite the file. printf RESTART "$lastReadDatetime\t%5d\n", $lastReadDatetimeSno ; print DEBUGFILE "\tEntry made into restart file: [$lastReadDatetim +e $lastReadDatetimeSno]\n" if $debug ; } #-------------------------------------------------------------------- # Executed when the program winds up. # sub windup() { print DEBUGFILE "Winding up.\n" if $debug ; close RESTART ; close FTPLOG ; close DEBUGFILE if $debug ; close ERRORFILE ; unlink($errorFile) if (! $error) ; } #-------------------------------------------------------------------- END { windup() ; } #-------------------------------------------------------------------- main ; # Don't forget to invoke the main
In reply to perl script not writing to mentioned ftplog by teja402000
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |