Complex Records help

T

Traveller2003

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.
 
J

Josef Moellers

Traveller2003 said:
#!/usr/bin/perl -w

##### User Info Structure #######
$UserInfoRec = {

You define a reference to an anonymous hash ...
print $UserInfoRec{PASSWDINFO};

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
 
G

Glenn Jackman

At 2004-09-01 06:47AM said:
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.

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

[...]
$UserInfoRec = {
PASSWDINFO => { LOGINNAME => "", [...]
}; # End user record

Now, $UserInfoRec is a reference to a hash

sub setenv {
$UserInfoRec = () ; # Initialise the Record

Now, $UserInfoRec is undefined.
while (<PASSWD>) { [...]
print $UserInfoRec{PASSWDINFO};

As mentioned earlier, the hash variable %UserInfoRec does not exist.
==============> 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} } ) {

See 'perldoc -f each' and 'perldoc -f keys'
 
T

Tore Aursand

#!/usr/bin/perl -w

Use this instead:

#!/usr/bin/perl
#
use strict;
use warnings;
##### User Info Structure #######
$UserInfoRec = {
PASSWDINFO => { LOGINNAME => "",
PASSWORD => "",
USERID => "",
USERGRP => "",
RESERVED => "",
WORKINGDIR=> "",
SHELL => "" },
DATABASEINFO => {%DBEnv}
}; # End user record

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,
}
open(PASSWD,"/etc/passwd") or die "Cannot read passwd file ? ($?)";

Needless use of double quotes (again), and why do you use the '$?'
variable?

open( PASSWD, '/etc/passwd' ) or die "Cannot read passwd file; $!\n";
$UserInfoRec = () ; # Initialise the Record

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.
print $UserInfoRec{PASSWDINFO};

$UserInfoRec is a hash _reference_, so you have to treat it like that, not
as a normal hash;

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

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";
}

while ( ( $pwinfo ) = each %{$UserInfoRec{PASSWDINFO}} ) {
print "$pwinfo = $UserInfoRec{PASSWDINFO}{$pwinfo} \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";
}
 
K

Karel Kubat

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 <[email protected], (e-mail address removed)>
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.
 
T

Tad McClellan

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

You have the wrong variable there.

You want "$!" instead.
 

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. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,540
Members
45,024
Latest member
ARDU_PROgrammER

Latest Threads

Top