Karyn Stump wrote:
I am trying to learn subroutines. I have seen refernces to using my and
local for passing variables so I am playing with them to try to understand
better how this all works.
http://perl.plover.com/FAQs/Namespaces.html
There is also some information in:
perldoc perlsub
I have a subroutine in the script below, printsub that errors when it is
run with
Global symbol "$name" requires explicit package name at ./user-sub.pl line
143.
Global symbol "$name" requires explicit package name at ./user-sub.pl line
144.
Execution of ./user-sub.pl aborted due to compilation error
This is the code pulled out of easy viewing:
sub printsub
{
local($name) = $_[0];
print "This is the value of $name in the subroutine.\n";
}
The second sub in this script works using:
my $name = shift(@_);
another example I found online.
I would appreciate some help understanding if or how local can be used in
this context. Also if there is a better/preferred way to pass this var to
the sub.
TIA,
Karyn
Here is the whole script:
#!/usr/bin/perl
use strict;
use warnings;
# Open passwd file to compare arguments to to make sure they are valid
usernames
my $pwfile = "/etc/passwd";
To access this file Perl provides the functions getpwnam, getpwuid,
getpwent, setpwent and endpwent.
perldoc -f getpwnam
perldoc -f getpwuid
perldoc -f getpwent
perldoc -f setpwent
perldoc -f endpwent
open (PW, "<$pwfile") or die "Can't open PW $pwfile : $!";
# Create extenions for log files as the older ones have a bz2 extension.
They will also need
# a different command to grep them than the current log file.
my @extension;
push @extension, ''; # Place null in [0] so that it will be
false the first loop for $log
my $increment = 0;
my $ext = ".bz2";
while (@extension < 6)
{
push @extension, ".$increment$ext";
$increment++;
}
Or simply:
my @extension = ( '', map ".$_$ext", 0 .. 4 );
my $pwf = do { local $/; <PW> };
close PW or warn "Error closing PW $!";
foreach my $user (@ARGV)
{
print "Checking $user\n";
if ($pwf !~ /\b$user\b/)
{
print "$user is not a valid login name.\n\n";
next;
}
if (-e "/usr/home/$user/.forward")
{
print "User $user has a forward file.\n\n";
my $forward = "/usr/home/$user/.forward";
open (INFO, "<$forward") or die "Can't open INFO $forward : $!";
my @lines = <INFO>;
close(INFO);
print @lines;
my $quota = `quota -v $user`;
print "User $user quota is $quota\n";
next;
}
my $count;
my $log;
my $bzcat = "/usr/bin/bzcat";
foreach my $end (@extension)
{
$log = "/var/log/maillog$end";
if ($end =~ /bz2/)
{
open (MAILLOG, '-|', "$bzcat $log") or warn "Couldn't run '$bzcat
$log': $!";
#print "That worked - Opened file with bzcat\n";
}
else
{
open (MAILLOG, $log) or warn "Couldn't open maillog $log: $!";
#print "Opened file without bzcat\n";
}
$count = 0;
while (<MAILLOG>)
{
#$count++ if /user=$user /;
$count++ if /user=\<$user/;
}
last if $count;
close MAILLOG or warn $! ? "error closing $log: $!" : "Exit status $?
from $$bzcat";
#print "Closing MAILLOG here\n";
}
if ($count)
{
$log =~ s|.*archives/||; # Strip out path before filename
print "$user checked mail $count times in $log.\n";
my $quota = `quota -v $user`;
print "User $user quota is $quota\n";
}
else
{
print "$user is not in the maillog for the last 6 months.\n";
my @directories = ("/usr/home/$user/public_html", "/usr/home/$user");
foreach my $directory (@directories)
{
if (-d $directory)
{
my @files =();
opendir DIR, $directory or die "Error reading $directory: $!n";
my @sorted = sort {-M "$directory/$a" <=> -M "$directory/$b"}
readdir(DIR);
closedir DIR;
foreach my $item (@sorted)
{
push(@files,$item) unless $item eq "." or $item eq "..";
}
my $count = @files;
if ($count > 0)
{
my $age = sprintf("%.1f",(-M "$directory/$files[0]"));
print "Newest file in $directory is $files[0] and it is $age
days old.\n";
}
else
{
print "User $user has no files in their $directory
directory.\n";
}
If all you want is the newest file in the directory then you don't have
to store all the file names, just the one that is newest:
my @directories = ("/usr/home/$user/public_html", "/usr/home/$user");
foreach my $directory ( @directories )
{
if ( -d $directory )
{
my @file = ( ~0, '' );
opendir DIR, $directory or die "Error reading $directory: $!n";
while ( my $file = readdir D ) {
next unless -f "$directory/$file";
@file = ( -M _, "$directory/$file" ) if $file[ 0 ] > -M _;
}
if ( length $file[ 1 ] )
{
my $age = sprintf '%.1f', $file[ 0 ];
print "Newest file in $directory is $file[1] and it is $age
days old.\n";
}
else
{
print "User $user has no files in their $directory
directory.\n";
}
}
else
{
print "No $directory found.\n";
}
}
}
else
{
print "No $directory found.\n";
}
}
# end of directory search
}
&printsub($user);
&lastsub($user);
print "\n";
}
sub printsub
{
local($name) = $_[0];
You shouldn't use local. It doesn't create variables like my does.
Please read the web page referenced at the top pf this post.
print "This is the value of $name in the subroutine.\n";
}
sub lastsub
{
# Check for logins with last
my $name = shift(@_);
my @command1 = `last -n 1 $name`;
chomp(@command1);
if ($command1[0] eq '')
{
print "$name has not logged in since $command1[1].\n";
}
else
{
print "$command1[0].\n";
}
}
John
--
Those people who think they know everything are a great
annoyance to those of us who do. -- Isaac Asimov
--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/