During an email exchange, I did a Google search for “hundreds of frameworks and languages” and got an unexpected result; a link to this list of computer programing language. I like Bradley’s breakdown of the list into categories. Looking at that list, I felt a bit of nostalgia.

I learned and developed in the following programming computer languages over my lifetime.

  • BASIC
  • Pascal
  • C
  • Perl
  • PHP
  • JavaScript

I learned the following computer languages but I have not developed anything meaningful in those languages.

  • C++
  • Java
  • Objective-C
  • Python

And according to this article, I can claim to know the following scripting languages and markup languages.

  • Awk
  • Tcl
  • HTML
  • XML
  • XHTML

Wow! That’s already too many.

I have forgotten how to use most of these. I think that if I had a project to work on, I could reprise my proficiency in Perl, PHP, and Javascript for web development as well as systems management and systems integration. But I think my favourite language had been and maybe always will be Perl. When I coded, Perl let me be me. It didn’t get in the way. It didn’t enforce rules dictated by computer science theory. It was said of Perl, that “there is more than one way to do it”. I love the subtitle of the book Learning Perl, “Making Easy Things Easy and Hard Things Possible”.

Why Perl Didn’t Win by an author (Outspeaking)

With every year that passed, as Perl 6 produced more press releases than actual code, the attractiveness of Perl as a platform declined. Sure, it still had users. Sure, it still had people starting new projects. (The Modern Perl movement was a decent attempt to bring wider enthusiasm back into the ecosystem by dispelling some of the worst myths of the language. It modeled itself after JavaScript: The Good Parts without realizing that Perl lacked JavaScript’s insurmountable advantage of ubiquity. Who could have predicted that Objective-C would be interesting again a year before the iPhone came out?)

What it didn’t have was a clearly defined future, let alone an articulated one.

Programming, Code, Coding, Programmer, Javascript

Usage

ftp.pl [-netrc] [-u <i>user</i>] [-p <i>passwd</i>] -m server -s source_dir -t target_dir [-log_dir <i>/path/to/logs/file</i>] file1 file2 ...

# Copyright 2000 Williams Interactive, Inc.
# Programmer: Khurt Williams, 2000.10.18
# command switches are
# -netrc : uses .netrc file to find user/passwd for the destination server 
# -u <i>user</i> : specify the user id
# -p <i>passwd</i> :specify the passwd for user id
# -m server : server ip or name
# -s source_dir : source dir
# -t target_dir : target dir
# -log_dir <i>/path/to/logs/file</i> : location of log file

Code

#!/usr/local/bin/perl -w
# Copyright 2000 Williams Interactive, Inc.
# Programmer: Khurt Williams, 2000.10.18
# command switches are
# [-netrc] : uses .netrc file to find user/passwd for the destination server 
# [-u user] : specify the user id
# [-p passwd] :specify the passwd for user id
# -m server : server ip or name
# -s source_dir : source dir
# -t target_dir : target dir
# [-log_dir /path/to/log] : location of log file

use strict;
use Getopt::Long;
use Net::FTP;
use Net::Netrc;
use Log::ErrLogger;

my ($log_file,@file_list,$file,$return_code);
my ($netrc,$server,$source,$target,$user,$passwd,$log_dir,$ftp);
my ($machine,$login,$password);
my $options = { netrc => \$netrc, m => \$server, s => \$source, t => \$target, u => \$user, p => \$passwd, log_dir => \$log_dir };

GetOptions($options, "netrc","m=s","s=s","t=s","u:s","p:s","log_dir:s");

@file_list = @ARGV;

#make sure we have some filename
usage() if( !defined(@file_list) );

#use netrc
if( $netrc ) {
#exit if not server specified
 usage () if( !defined($server) );
#make sure we use the correct userid
 if( !defined($user) ) {
  $machine = Net::Netrc->lookup($server);
 }
 else {
  $machine = Net::Netrc->lookup($server,$user);
 }
#get login id and password for that server
 $login = $machine->login();
 $password = $machine->password();

 $user = $login;
 $passwd = $password;
}

#check that command line switches are set
usage() if( !defined($user) || !defined($passwd) || !defined($server));
usage() if( !defined($source) || !defined($target));

#append to log file if it already exist
$log_dir = "/tmp" if( !defined($log_dir) );
#log all event to file including die and warn
$log_file = new Log::ErrLogger::File( FILE => ">$log_dir/SendToML.log",SENSITVITY => Log::ErrLogger::ALL );

#connect to server
$ftp = new Net::FTP($server);
Log::ErrLogger::log_error(Log::ErrLogger::INFORMATIONAL,__FILE__." ftp started.\n");
Log::ErrLogger::log_error(Log::ErrLogger::INFORMATIONAL,"ftp $server\n");
#exit and log message on failure
die($ftp->message()) if( !($ftp->login($user,$passwd)) );

#set mode to binary
Log::ErrLogger::log_error(Log::ErrLogger::INFORMATIONAL,"bin\n");
#exit and log message on failure
die($ftp->message()) if( !($ftp->binary()) );

 local directory
chdir($source);
Log::ErrLogger::log_error(Log::ErrLogger::INFORMATIONAL,"lcd $source\n");

 remote directory
Log::ErrLogger::log_error(Log::ErrLogger::INFORMATIONAL,"cd $target\n");
#exit and log message on failure
die($ftp->message()) if( !($ftp->cwd($target)) );

foreach $file (@file_list) {
#send files to server
 Log::ErrLogger::log_error(Log::ErrLogger::INFORMATIONAL,"put $file $file\n");
 retry_put($file) if( !($ftp->put($file,$file)) );
}

#close connection
$return_code = $ftp->quit();
Log::ErrLogger::log_error(Log::ErrLogger::INFORMATIONAL,"quit\n");
Log::ErrLogger::log_error(Log::ErrLogger::INFORMATIONAL,__FILE__." ftp ended.\n");

#end logging
$log_file->close();

exit(0);

sub usage {
 die "$0 [-netrc] [-u user] [-p passwd] -m [server]  -s [source_dir] -t [target_dir] [-log_dir [/path/to/logs/file]] file1 file2 ...\n";
}

#resend file if first attempt fails
#remove file if second attemp also fails.
sub retry_put {
 my ($file) = @_;

 warn($ftp->message());
 Log::ErrLogger::log_error(Log::ErrLogger::INFORMATIONAL,"Will attempt to resend file %s.\n",$file);

 warn($ftp->message()) if( !($ftp->quit()) );
 Log::ErrLogger::log_error(Log::ErrLogger::INFORMATIONAL,"quit\n");

 $ftp = new Net::FTP($server);
 Log::ErrLogger::log_error(Log::ErrLogger::INFORMATIONAL,"ftp $server\n");
 die($ftp->message()) if( !($ftp->login($user,$passwd)) );

 Log::ErrLogger::log_error(Log::ErrLogger::INFORMATIONAL,"cd $target\n");
 die($ftp->message()) if( !($ftp->cwd($target)) );

 Log::ErrLogger::log_error(Log::ErrLogger::INFORMATIONAL,"put $file $file\n");
 remove_file($file) if( !($ftp->put($file,$file)) );
}

sub remove_file {
 my ($file) = @_;

 warn($ftp->message());
 Log::ErrLogger::log_error(Log::ErrLogger::INFORMATIONAL,"Resend of $file failed.\n");
 Log::ErrLogger::log_error(Log::ErrLogger::INFORMATIONAL,"Will attempt to remove half baked file $file.\n");

 warn($ftp->message()) if( !($ftp->quit()) );
 Log::ErrLogger::log_error(Log::ErrLogger::INFORMATIONAL,"quit\n");

 $ftp = new Net::FTP($server);
 Log::ErrLogger::log_error(Log::ErrLogger::INFORMATIONAL,"ftp $server\n");
 die($ftp->message()) if( !($ftp->login($user,$passwd)) );

 Log::ErrLogger::log_error(Log::ErrLogger::INFORMATIONAL,"cd $target\n");
 die($ftp->message()) if( !($ftp->cwd($target)) );

 Log::ErrLogger::log_error(Log::ErrLogger::INFORMATIONAL,"delete $file\n");
 warn($ftp->message()) if( !($ftp->delete($file)) );
}