views:

154

answers:

2

I am trying to setup a basic error checking system where it will catch shell errors run by a system call. execute_command is a webmin function that runs a system call and then sets an error message to its 4th parameter. I basically call execute_command_error("adduser test"), knowing that I already have a user called test created and based on my predefined arrays, id expect it to print

Unable to add user
Unable to add that user because it already exists on the system.

but instead I get:

Uhhhhhhhhh?
Uhhhhhhhhh?

I have verified that $exe and $return are "adduser" and 1, respectifully. What am I not understanding about arrays? It seems to ignore the string and or number and just go by the last definition with 3 elements. What is a solution to this, or a better solution?

Here is ths code:

$ErrorMsg['adduser',1,'title']  = "Unable to add user";
$ErrorMsg['adduser',1,'msg']    = "Unable to add that user because it already exists on the system.";
$ErrorMsg['random',2,'duaisdhai']  = "Uhhhhhhhhh?";

sub execute_command_error
{
    my $error = "";
    my $cmd = $_[0];

    $return = execute_command($cmd, undef, undef, \$error)>>8;
    if ($error) {
     my ($exe) = $cmd =~ m|^(.*?)[ ]|;

     $exe_title = $ErrorMsg[$exe,$return,'title'];
     $exe_msg = $ErrorMsg[$exe,$return,'msg'];


     print $exe_title."<br>";
     print $exe_msg ."<br>";
    }
}


Update:

I am thinking that I need to use hashes, I have no idea why I thought I could use strings in indices. With that said, little research has led me to something like this:

%ErrorMsgs =    ('adduser' => {
       '1' => {
        'title' => 'Unable to add user',
        'msg' => 'Unable to add that user because it already exists on the system.',
       },
      },
      );

Now how would I reference it using a variable? because neither of these work:

 $exe_title = $ErrorMsgs{"$exe"}{"$return"}{"title"};
 $exe_title = $ErrorMsgs{$exe}{$return}{title};
+2  A: 

First, see perldsc for the proper syntax for doing multidimensional structures. Your arrays don't make any sense.

If you had warnings turned on, you would have seen a "Argument isn't numeric" warning to tell you that you can't use strings in any meaningful way in an array index.

But the hash you posted in your update should work fine.

#!/usr/bin/perl

use strict;
use warnings;
## ^^ these things are your friends

my %ErrorMsgs =    ('adduser' =>   {
                        '1' =>  {
                                'title' =>      'Unable to add user',
                                'msg'   =>      'Unable to add that user because it already exists on the system.',
                        },
                },
                );

my $exe = 'adduser';
my $return = 1;

print $ErrorMsgs{$exe}{$return}{title};    # works

If you're not getting the output you expect, it's because there's something wrong with $exe or $return -- they might not be defined in the scope where you're trying to use them. Turning on strict and warnings will help track the issue down.

friedo
+1  A: 

{ 'key' => 'val' } creates a hash reference, so you dereference before looking up a key.

$exe_title = $ErrorMsgs{$exe}->{$return}->{"title"};

You also don't need to quote $exe or $return, since these already hold strings.

Note that Perl doesn't support multidimensional indices; a multidimensional array is just an array of arrays, so you need to use [] for each index. In scalar context, the comma operator returns the value of the rightmost expression, so the following lines are equivalent:

$ErrorMsg[0,1,2]  = "foo";
$ErrorMsg[2]  = "foo";

Note that in list context, the comma operator returns a list of values, which gives us slices:

@a=qw(f o o);
@a[3,4,5] = qw(b a r);
print join(',', @a), "\n";
# output: f,o,o,b,a,r 
@ErrMsg{qw(title msg)} = ('Unable to add user', 'Unable to add that user because it already exists on the system.')
outis