Autoftp Perl Code

This page contains the Perl code that is used to determine what files need to be uploaded to the web server site.
# Automatically FTP files to the web site.
#
# The idea is that the newfiles.txt file indicates which files have been
# updated by the makefile. This approach is more accurate and requires less
# maintenance than the older version of autoftp.pl. Nothing needs to be done
# for new files except update the makefile. Changes to the primary and mirror
# sites only require their information files to be updated.
#
# After successful downloading to the primary and mirror FTP sites the
# newfiles.txt file is removed.
#
#------------------------------------------------------------------------------

require 5.004;

use English;
use strict;
use Time::Local;
use Net::FTP;

my $log_file;
my $primary_info;
my $mirror_info;
my %times;
my @ftp_commands; # List of commands to send to FTP.
my @raw_files; # contents of newfiles.txt
my @files;
my $debug = 0;
my $primary_web;
my $primary_directory;
my $primary_username;
my $primary_password;
my $mirror_web;
my $mirror_directory;
my $mirror_username;
my $mirror_password;

$log_file = "/home/tom/ALL/WWW/newfiles.txt";
$primary_info = "/home/tom/ALL/WWW/primary.inf";
$mirror_info = "/home/tom/ALL/WWW/mirror.inf";

# Only have something to do if there is a list of new files.
if (-f "$log_file") {
 ($mirror_web, $mirror_directory, $mirror_username, $mirror_password) =
 parse_information_file($mirror_info);

 ($primary_web, $primary_directory, $primary_username, $primary_password) =
 parse_information_file($primary_info);

 open FILES, "$log_file" || die "Unable to open file $log_file";
 @raw_files = <FILES>;
 @files = remove_duplicates(@raw_files);
 close(FILES);

 if (put_files($primary_web, $primary_directory, $primary_username,
 $primary_password, @files) &&
 put_files($mirror_web, $mirror_directory, $mirror_username,
 $mirror_password, @files)) {
 unlink($log_file);
 }
}
else {
 print "Unable to find $log_file\n";
}

#------------------------------------------------------------------------------
# Write a file via FTP using the specified user information.
# Parameters:
# hostname - name of the host that contains the file.
# directory - the directory that contains the file.
# username - log in name
# password - duh
# files - the name of the files to get.
# Return value:
# boolean - true if the FTP was successful, false if not.
# Note: the FTP command results are written to archftp.log.
#------------------------------------------------------------------------------
sub put_files {
 my $hostname = shift @_;
 my $directory = shift @_;
 my $username = shift @_;
 my $password = shift @_;
 my @files = @_;
 my $n_files;
 my $file;
 my $base_file;
 my $last_line;
 my $ret;
 my $ftp;

 $n_files = @files;

 clear_ftp();
 if ($n_files > 0) {
 print "FTP to $hostname - ";
 $ftp = Net::FTP->new($hostname, Timeout => 30, $debug => 1) or
 die "Can't connect to $hostname: $ERRNO";
 $ftp->login($username, $password) or
 die "Can't login with <$username> <$password>";
 if ($directory ne "") {
 $ftp->cwd($directory) or
 die "Can't cwd to <$directory>";
 }
 $ftp->type("I"); # binary mode
 foreach $file (@files) {
 $base_file = basename($file);
 if ($base_file eq "index.htm") {
 $ftp->put($base_file, "index.html") or
 die "Can't put $base_file";
 }
 else {
 $ftp->put($base_file) or
 die "Can't put $base_file";
 }
 }
 $ftp->quit() or
 warn "Couldn't quit. Oh well.\n";

 $ret = 1;
 print ($ret ? "succeeded\n" : "failed\n");
 }
 return $ret;
} #put_files


#------------------------------------------------------------------------------
# basename - parallel to the Unix basename command.
# Parameters:
# $file - a file name, potentially with a directory.
# Return value:
# string - just the file part, without the directory.
#------------------------------------------------------------------------------
sub basename {
 my $file = $_[0];
 $file =~ /([^\\\/]*)$/;
 return $1;
} #basename


#------------------------------------------------------------------------------
# Collect commands to send to FTP.
# Parameters:
# line - a new line to send
# Return value:
# none
#------------------------------------------------------------------------------
sub collect_ftp {
 my $line = @_[0];

 push @ftp_commands, $line;
} # collect_ftp


#------------------------------------------------------------------------------
# Clear out list of commands to send to FTP.
# Parameters:
# none
# Return value:
# none
#------------------------------------------------------------------------------
sub clear_ftp {

 @ftp_commands = ();
} # clear_ftp


#------------------------------------------------------------------------------
# Send commands to FTP.
# Parameters:
# args - list of FTP commands
# Return value:
# none
# Note: the FTP command results are written to archftp.log.
#------------------------------------------------------------------------------
sub send_ftp {
 my $line;
 my $command_line;

 if ($debug) {
 print "Entering send_ftp\n";
 }
 $command_line = shift(@_);
 if ($debug) {
 print "send_ftp: command_line=$command_line\n";
 }
 if (open(FTP, "|$command_line>>archftp.log")) {
 for $line (@_) {
 print FTP "$line\n";
 }
 print FTP "disconnect\n";
 print FTP "bye\n";
 close(FTP);
 }
 if ($debug) {
 for $line (@_) {
 print "$line\n";
 }
 print "disconnect\n";
 print "bye\n";
 print "Exiting send_ftp\n";
 }
} # send_ftp


#------------------------------------------------------------------------------
# Scan a site information file and return the site, directory, username and
# password entries.
#
# Parameters:
# file - name of the information file.
# Return value:
# list - site, directory, username, password.
#------------------------------------------------------------------------------
sub parse_information_file {
 my $file = $_[0];
 my $site = "";
 my $directory = "";
 my $username = "";
 my $password = "";
 my $keyword;
 my $value;

 open INFO, "$file" || die "Unable to open FTP site information file $file";
 while (<INFO>) {
 ($keyword, $value) = split;
 if ($keyword eq "site") {
 $site = $value;
 }
 elsif ($keyword eq "directory") {
 $directory = $value;
 }
 elsif ($keyword eq "username") {
 $username = $value;
 }
 elsif ($keyword eq "password") {
 $password = $value;
 }
 else {
 print "Unknown keyword in FTP site information file $file: ";
 print "$keyword\n";
 }
 }

 return ($site, $directory, $username, $password);
} # parse_information_file


#------------------------------------------------------------------------------
# Remove duplicates from a list. A side-effect is that the return values are
# sorted.
#
# Parameters:
# in_list - list which may have duplicate entries.
# Return value:
# out_list - in_list, sorted with duplicates removed.
#------------------------------------------------------------------------------
sub remove_duplicates {
 my @unsorted_in_list = @_;
 my @in_list;
 my @out_list;
 my $element;
 my $last_element;

 @in_list = sort @unsorted_in_list;

 # Prime the pump.
 $element = shift(@in_list);
 chop $element;
 @out_list = ($element);
 $last_element = $element;
 foreach $element (@in_list) {
 chop $element;
 if ($element eq $last_element) {
 next;
 }
 $last_element = $element;
 push(@out_list, $element);
 }
 return @out_list;
} #remove_duplicates

Back to The Information Cave home page

Last modified Mon Apr 26 20:58:57 1999.