tcf03 has asked for the wisdom of the Perl Monks concerning the following question:

I am testing the running of a script which depending on the OS will run according to the rules of the OS it is run on ( ie commands, etc...). I chose to test this using user maintenance as my test bed.
The code is here
#!/usr/bin/perl -w use strict; # use diagnostics; use POSIX qw/uname/; use POSIX qw/strftime/; my ($os, $hostname, undef)=POSIX::uname(); my ($host, undef)=split(/\./, $hostname); my $OS = lc($os); my ( $MODE, $USERNAME, $NEWPASS, $APACHECONF, @THINGS ); $MODE = $USERNAME = $NEWPASS = $APACHECONF = "UNDEFINED"; unless ( $ARGV[0] =~ m/-(p|a|d|ha|hd)/ ) { print "500 - DONE - $host - Missing or bad mode\n"; exit; } if ( defined $ARGV[0] ) { $MODE = $ARGV[0] } if ( defined $ARGV[1] ) { $USERNAME = $ARGV[1] } if ( defined $ARGV[2] ) { $NEWPASS = $ARGV[2] } #print "MODE = $MODE\nUSERNAME = $USERNAME\nNEWPASS = $NEWPASS\n"; # Format: MODE => ( COMMAND, ACTION TAKEN, CHECKMODES, ERRORS ) my %cmd=( "-p" => { "COMMAND" => { "linux" => "/usr/local/bin/setp +ass.expect $USERNAME $NEWPASS", "aix" => "" }, "ACTION" => "Password Changed", "CHECKMODES" => &checkparms(), "ERRORS" => { "$OS:256" => "$USERNAME Does +not exist" } }, "-d" => { "COMMAND" => { "linux" => "/usr/sbin/userdel - +r $USERNAME", "aix" => "" }, "ACTION" => "Deleted", "CHECKMODES" => &checkparms(),\ "ERRORS" => { "$OS:1536" => "$USERNAME Does n +ot exist" } }, "-a" => { "COMMAND" => { "linux" => "/usr/sbin/useradd $ +USERNAME && /usr/local/bin/setp +ass.expect $USERNAME $NEWPASS", "aix" => "" }, "ACTION" => "Added", "CHECKMODES" => &checkparms(), "ERRORS" => { "$OS:2304" => "$USERNAME exists +" } }, "-ha" => { "COMMAND" => { "linux" => "/usr/bin/htpasswd - +bd $APACHECONF $USERNAME $NEWPASS", "aix" => "" }, "ACTION" => "Added", "CHECKMODES" => &checkparms() }, "-hd" => { "COMMAND" => { "linux" => "/usr/bin/htpasswd - +D $APACHECONF $USERNAME", "aix" => "" }, "ACTION" => "Deleted", "CHECKMODES" => &checkparms() } ); if ( $cmd{$MODE}{'CHECKMODES'} == 0 ) { #qx/$cmd{$MODE}{'COMMAND'}/; print "$cmd{$MODE}{'COMMAND'}{$OS}\n"; check_error($?); } else { print "500 - DONE - $host - @THINGS not defined"; } exit; ############### sub check_error ############### { $_=shift; my $err="$OS:$_"; my $msg = "$USERNAME $cmd{$MODE}{'ACTION'}"; $msg = $cmd{$MODE}{'ERRORS'}{$err} if ( defined ($cmd{$MODE}{'ERRO +RS'}{$err}) ); open (LOGFILE, ">>/var/log/usermaint_.log") or warn "Unable to ope +n logfile\n"; ( $_ == 0 ) ? print "200 - DONE - $host - Sucess ($_) - $msg\n" : print "500 - DONE - $host - Failure ($_) - $msg\n"; my $now = strftime "%m/%d/%Y %H:%M:%S", (localtime); print LOGFILE "$now - $_ - $USERNAME - $msg\n"; close (LOGFILE) or warn "Unable to close logfile\n"; return 1; } ############## sub checkparms ############## { push (@THINGS, "Username") if ( $USERNAME eq "UNDEFINED" ); push (@THINGS, "Password") if ( $NEWPASS eq "UNDEFINED" and $MODE eq "-a" or $MODE eq "-p" or $MODE eq "-ha"); push (@THINGS, "httpd.conf") if ( $MODE eq "-ha" or $MODE eq "-hd" and $APACHECONF eq "UNDEFINED" ); my $return_val = ( scalar(@THINGS) == 0 ) ? return 0 : return 1; } __END__
The script runs fine except when I pass incorrect parameters it prints the incorrect parameters five times. I see what it its doing, its iterating through my hash $cmd{$MODE}{'CHECKMODES'} five times, Im just not sure why. I have tried using  defined ($cmd{$MODE}{'CHECKMODES'}) but that does not produce desireable results either.
When run incorrectly I get the results
500 - DONE - SERVER - Username Username Username Username Username not + defined
or if the script expects more than one parameter such as when run with the parameter -ha alone.
500 - DONE - SERVER - Username Password httpd.conf Username Password h +ttpd.conf Username Password httpd.conf Username Password httpd.conf U +sername Password httpd.conf not defined
Any suggestions are greatly appreciated.

UPDATE - Ive only tested this on Linux thus far

UPDATE 2
Thanks transient! Re: Unexpected results returned from a hash
Ted
--
"That which we persist in doing becomes easier, not that the task itself has become easier, but that our ability to perform it has improved."
  --Ralph Waldo Emerson

Replies are listed 'Best First'.
Re: Unexpected results returned from a hash
by Zaxo (Archbishop) on Jun 21, 2005 at 19:04 UTC

    Have you tried Getopt::Long for this? The command line options will be much less fragile if you do.

    After Compline,
    Zaxo

      I have to agree with Zaxo on this. For a while I thought it was easier to just hand-role option code & errors for simple scripts like this. Then I found GetOpt::Long and Pod::Usage, and never looked back.


      Xaositect - Whitepages.com
Re: Unexpected results returned from a hash
by Transient (Hermit) on Jun 21, 2005 at 19:08 UTC
    Your checkparms are ALWAYS running 5 times (for the 5 commands you have listed).

    You have included the RESULTS of &checkparms in your %cmd hash... what I think you want is the ref (\&checkparms), which would change how you call it.
      Thanks, that was the problem. I changed %cmd to look like this
      my %cmd=( "-p" => { "COMMAND" => { "linux" => "/usr/local/bin/setp +ass.expect $USERNAME $NEWPASS", "aix" => "" }, "ACTION" => "Password Changed", "CHECKMODES" => \&checkparms($MODE), "ERRORS" => { "$OS:256" => "$USERNAME Does +not exist" } }, "-d" => { "COMMAND" => { "linux" => "/usr/sbin/userdel - +r $USERNAME", "aix" => "" }, "ACTION" => "Deleted", "CHECKMODES" => \&checkparms, "ERRORS" => { "$OS:1536" => "$USERNAME Does n +ot exist" } }, "-a" => { "COMMAND" => { "linux" => "/usr/sbin/useradd $ +USERNAME && /usr/local/bin/setp +ass.expect $USERNAME $NEWPASS", "aix" => "" }, "ACTION" => "Added", "CHECKMODES" => \&checkparms, "ERRORS" => { "$OS:2304" => "$USERNAME exists +" } }, "-ha" => { "COMMAND" => { "linux" => "/usr/bin/htpasswd - +bd $APACHECONF $USERNAME $NEWPASS", "aix" => "" }, "ACTION" => "Added", "CHECKMODES" => \&checkparms }, "-hd" => { "COMMAND" => { "linux" => "/usr/bin/htpasswd - +D $APACHECONF $USERNAME", "aix" => "" }, "ACTION" => "Deleted", "CHECKMODES" => \&checkparms } );


      and the checkparms sub to look like this

      ############## sub checkparms ############## { push (@THINGS, "Username") if ( $USERNAME eq "UNDEFINED" ); push (@THINGS, "Password") if ( $NEWPASS eq "UNDEFINED" and $MODE eq "-a" or $MODE eq "-p" or $MODE eq "-ha"); push (@THINGS, "httpd.conf") if ( $MODE eq "-ha" or $MODE eq "-hd" and $APACHECONF eq "UNDEFINED" ); my $return_val = ( scalar(@THINGS) == 0 ) ? "0" : "1"; return $return_val; }


      Ted
      --
      "That which we persist in doing becomes easier, not that the task itself has become easier, but that our ability to perform it has improved."
        --Ralph Waldo Emerson
Re: Unexpected results returned from a hash
by tlm (Prior) on Jun 21, 2005 at 19:08 UTC

    Every time you invoke &checkparms() as you initialize your %cmd hash, it basically pushes the same info into @THINGS, which then gets printed out when the program gets bad input.

    the lowliest monk