Complex Records help

Discussion in 'Perl Misc' started by Traveller2003, Sep 1, 2004.

  1. Hi All ,

    I am a bit stuck. I have only recently started using perl and trying
    to get to grips with the references , scalar and list contexts. I
    realise if I can understand these and spot them than I am on my way to
    learning perl.

    The following is the script I am using and need help as to what I am
    doing wrong or better still a perl way of writing it.

    I have defined a Record sturcture and would like to use it through my
    whole program. As such I am getting all the details I require into the
    record structure "UserInfoRec".


    #!/usr/bin/perl -w

    ##### User Info Structure #######
    $UserInfoRec = {
    PASSWDINFO => { LOGINNAME => "",
    PASSWORD => "",
    USERID => "",
    USERGRP => "",
    RESERVED => "",
    WORKINGDIR=> "",
    SHELL => "" },
    DATABASEINFO => {%DBEnv}
    }; # End user record

    ######################################################################################
    # sets up the Var used within program.
    ######################################################################################
    sub setenv {


    open(PASSWD,"/etc/passwd") or die "Cannot read passwd file ? ($?)";

    $UserInfoRec = () ; # Initialise the Record
    while (<PASSWD>) {
    chomp;
    if (/^root:/) { # Found root entry user entry
    @UserInfo = split(/\:/,$_);
    $counter=0;

    print $UserInfoRec{PASSWDINFO};

    ==============> My comment <===============
    Never enters the while loop. I have a feeling I am looking at the
    reference as opposed to what I really want to get. i.e LOGINNAME,
    PASSWORD etc. I want to populate the values in the while loop but not
    sure how to do it.
    ==============> End my Comment <===============

    while ( ($param ) = each %{$UserInfoRec{PASSWDINFO} } ) {
    print "PARAM = $param \n";
    $UserInfoRec{PASSWDINFO}{$param}= $UserInfo[$counter];
    ++$counter;
    print "Counter = $counter param = $param \n";
    } # While each
    } # End if

    } # End While


    while ( ( $pwinfo ) = each %{$UserInfoRec{PASSWDINFO}} ) {
    print "$pwinfo = $UserInfoRec{PASSWDINFO}{$pwinfo} \n";
    }

    } #=======(End setenv)=======#




    TIA.

    Traveller2003.
     
    Traveller2003, Sep 1, 2004
    #1
    1. Advertisements

  2. You define a reference to an anonymous hash ...
    You reference the PASSWDINFO of the (non-existent) hash %UserInfoRec.

    Since $UserInfoRec is a reference, use $UserInfoRec->{PASSWDINFO} to
    access the PASSWDINFO field.

    There's probably more, but as I've just BTDT ...

    Josef
     
    Josef Moellers, Sep 1, 2004
    #2
    1. Advertisements

  3. In 'perldoc perlref', refer to #3 of section "Making References", and the
    section "Using References", or get the "Programming Perl" book. Or both.

    [...]
    Now, $UserInfoRec is a reference to a hash

    Now, $UserInfoRec is undefined.
    As mentioned earlier, the hash variable %UserInfoRec does not exist.
    See 'perldoc -f each' and 'perldoc -f keys'
     
    Glenn Jackman, Sep 1, 2004
    #3
  4. Traveller2003

    Tore Aursand Guest

    Use this instead:

    #!/usr/bin/perl
    #
    use strict;
    use warnings;
    Here you define a hash reference. You might want to use single quotes
    instead of double quotes, and you might want to reference to %DBEnv;

    my $UserInfoRec = {
    PASSWDINFO => {
    LOGINNAME => '',
    PASSWORD => '',
    USERID => '',
    USERGRP => '',
    RESERVED => '',
    WORKINGDIR => '',
    SHELL => '',
    },
    DATABASEINFO => \%DBEnv,
    }
    Needless use of double quotes (again), and why do you use the '$?'
    variable?

    open( PASSWD, '/etc/passwd' ) or die "Cannot read passwd file; $!\n";
    Again? Or do you want to have a record local to the current subroutine?
    If so, you could do this;

    local $UserInfoRec = {};

    I would, however, use a different name for it. Makes your code a bit
    easier to read, IMO.
    $UserInfoRec is a hash _reference_, so you have to treat it like that, not
    as a normal hash;

    print $UserInfoRec->{PASSWDINFO};
    First of all, 'each' always returns two elements (ie. the key/value pair
    from the hash). See 'perldoc -f each' for more information.

    In this context, however, I think you want to extract only the keys from
    the hash reference, right?

    Secondly, you're still not treating your hash reference for what it is; a
    hash reference;

    foreach my $param ( keys %{$UserInfoRec->{PASSWDINFO}} ) {
    $UserInfoRec->{PASSWDINFO}->{$param} = $UserInfo[$counter];
    $counter++;
    print "COUNTER = $counter / PARAM = $param\n";
    }

    Once again, I don't think that 'each' will do you what you expect here;

    foreach my $pwinfo ( keys %{$UserInfoRec->{PASSWDINFO}} ) {
    print "$pwinfo = " . $UserInfoRec->{PASSWDINFO}->{$pwinfo} . "\n";
    }
     
    Tore Aursand, Sep 1, 2004
    #4
  5. Traveller2003

    Karel Kubat Guest

    Hi,

    I've looked at your code snippet and here's a slightly alternative form.
    Comments are in my code. It's a somewhat different approach to your
    program, but I think that it illustrates hash refs and so on. Also, it
    parses the full /etc/passwd and not only the root entry.

    Luck, Karel

    -- SNIP
    !/usr/bin/perl -w

    # Always do:
    use strict;

    # We don't need this one.. see below.
    # $UserInfoRec = {
    # PASSWDINFO => { LOGINNAME => "",
    # PASSWORD => "",
    # USERID => "",
    # USERGRP => "",
    # RESERVED => "",
    # WORKINGDIR=> "",
    # SHELL => "" },
    # DATABASEINFO => {%DBEnv}
    # };
    # Instead we do:
    my $UserInfoRec;

    # We will use this anonymous hash as follows:
    # $userinfo->{root} ==> entry for 'root' and so on, which is a ref to
    # another anon hash
    # $userinfo->{root}->{home} ==> value of the homedir etc..

    # read the passwd db function. Suggested: () to show the prototype
    sub readpasswd () {
    open(PASSWD,"/etc/passwd")
    or die "Cannot read passwd file ? ($?)";

    while (<PASSWD>) {
    chomp;
    my ($uname, undef, $uid, $gid, $name, $home, $shell) =
    split (/:/);

    $UserInfoRec->{$uname}->{uid} = $uid;
    $UserInfoRec->{$uname}->{gid} = $gid;
    $UserInfoRec->{$uname}->{name} = $name;
    $UserInfoRec->{$uname}->{home} = $home;
    $UserInfoRec->{$uname}->{shell} = $shell;
    }
    close (PASSWD);
    }

    # Another function to show traversal
    sub printpasswd () {
    foreach my $uname (sort (keys (%$UserInfoRec))) {
    printf ("\n" .
    "User: %s\n" .
    "Uid / gid: %s %s\n" .
    "Full name: %s\n" .
    "Home dir: %s\n" .
    "Login shell: %s\n",
    $uname,
    $UserInfoRec->{$uname}->{uid},
    $UserInfoRec->{$uname}->{gid},
    $UserInfoRec->{$uname}->{name},
    $UserInfoRec->{$uname}->{home},
    $UserInfoRec->{$uname}->{shell});
    }
    }


    # Main..
    readpasswd();
    printpasswd();
    -- SNIP

    --
    Karel Kubat <, >
    Phone: mobile (+31) 6 2956 4861, office (+31) (0)38 46 06 125
    PGP fingerprint: D76E 86EC B457 627A 0A87 0B8D DB71 6BCD 1CF2 6CD5

    What is it that makes a complete stranger dive into an icy river
    to save a solid gold baby? Maybe we'll never know.
     
    Karel Kubat, Sep 1, 2004
    #5
  6. ^^
    ^^

    You have the wrong variable there.

    You want "$!" instead.
     
    Tad McClellan, Sep 1, 2004
    #6
  7. Thanks all for the Help. Much appericated.


    Traveller
     
    Traveller2003, Sep 2, 2004
    #7
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.