[comp.lang.perl] passwd/$home/who

frech@mwraaa.army.mil (Norman R. Frech CPLS) (11/21/90)

I am having problems with the following code.  What I am trying to do
is slurp the password file fields $login,$home into a varible,
run who, and then grep the $home out of my variable for each person
logged on.  I figured it would be faster to grab the password file
one time in the beginning instead of opening it for each person
out of the who.  I have tried various search approaches and they
either return a 1 or something completely erroneous.  It is evident
I do not have a clue. Help.

*** cut here ***

eval "exec /usr/local/bin/perl -S $0 $*"
    if $running_under_some_shell;
			# this emulates #! processing on NIH machines.
			# (remove #! line above if indigestible)

open(HOME, "/etc/passwd") || die "Can't access passwork file: $!\n";

while (<HOME>) {
($login,$passwd,$uid,$gid,$gcos,$home,$shell) = split(/:/);
$pass .= "$login:$home\n";
}
close HOME;
print $pass;
print "\n";
# open an input pipe to run who

open(WHO, "who |") || die "Can't run who: $!\n";

($wday, $mo, $today) = split(' ', `date`);

while (<WHO>) {
    chop;
    ($user, $tty, $month, $mday, $time) = split;
    print $user; 
    print "\n";
# grab the home directory from $pass
    @foo = grep($pass,$user);
    print @foo;
    print "\n";

}

tchrist@convex.COM (Tom Christiansen) (11/22/90)

In article <1990Nov20.164319.7326@uvaarpa.Virginia.EDU> frech@mwraaa.army.mil writes:
|I am having problems with the following code.  What I am trying to do
|is slurp the password file fields $login,$home into a varible,
|run who, and then grep the $home out of my variable for each person
|logged on.  I figured it would be faster to grab the password file
|one time in the beginning instead of opening it for each person
|out of the who.  I have tried various search approaches and they
|either return a 1 or something completely erroneous.  It is evident
|I do not have a clue. Help.
|
|*** cut here ***
|
|eval "exec /usr/local/bin/perl -S $0 $*"
|    if $running_under_some_shell;
|			# this emulates #! processing on NIH machines.
|			# (remove #! line above if indigestible)
|
|open(HOME, "/etc/passwd") || die "Can't access passwork file: $!\n";
|
|while (<HOME>) {
|($login,$passwd,$uid,$gid,$gcos,$home,$shell) = split(/:/);
|$pass .= "$login:$home\n";
|}
|close HOME;
|print $pass;
|print "\n";
|# open an input pipe to run who
|
|open(WHO, "who |") || die "Can't run who: $!\n";
|
|($wday, $mo, $today) = split(' ', `date`);
|
|while (<WHO>) {
|    chop;
|    ($user, $tty, $month, $mday, $time) = split;
|    print $user; 
|    print "\n";
|# grab the home directory from $pass
|    @foo = grep($pass,$user);
|    print @foo;
|    print "\n";
|
|}


This is another case where you would like to use an associative
array.  Hashded arrays and regular expressions are your
two greatest friends in perl.

I think I would write that more code more like this:


    open(WHO, "who |"); # this isn't going to fail
    while (<WHO>) {
	($user) = /^(\w+)\b/;
	print $user, ' ', &home($user), "\n";

    }
    ##> BUG WORK-AROUND HERE: CLOSE STILL DOESN'T FAIL iff $?
    close(WHO); die "can't run who command: $!" if $?;

    sub home {
	local($who);
	$who = $_[0] || $ENV{'USER'} || getlogin || (getpwuid($<))[0]
	    || die "Intruder alert, bailing out";

	unless(defined $Homes{$who}) {
	    $Homes{$who} = (getpwnam($who))[7] || '/';
	}
	$Homes{$who};
    }


I don't know why if a open "bogus|" fails to get something,
the close doesn't fail.  "close foo || die" doesn't do it.

--tom