tags:

views:

164

answers:

4

I want to scan the passwd file and print only lines if the user is not locked. That is, passwd -S $user does not return "Password: locked." I can do easily in ksh. What is the best way to do this in Perl?

+1  A: 

Previously, this answer reported how to print only locked users. Mistake corrected.

On Linux, a locked user account has a password which begins whith '!'. You can parse the colon-separated /etc/shadow file yourself with:

# Run as root with /etc/shadow as program argument
while (<>) {
    chomp;
    my ($user, $password, $remainder) = split /:/, $_, 3;
    print $user."\n" unless $password =~ /^!/;
}

Edit: Another, portable, way is to use the getpwent function:

# Must run as root
while (my ($user, $password) = getpwent) {
    print $user."\n" unless $password =~ /^!/;
}

Note: You need to be root to read users' passwords from /etc/shadow and to find out whether a user is locked or not.

Danilo Piazzalunga
thanks guys - I think I've worked it out now.
paul44
You're welcome! :) Please vote up the helpful answers and choose the most helpful (if any) as the accepted answer.
Danilo Piazzalunga
A: 

I'm not sure if you're looking for a command-line way to do it or not, and the following code assumes that the output of passwd -S is exactly how you specified it (which probably won't work in practice), but this is one approach:

cat /etc/passwd | perl -ne '$user = (split /:/)[0]; print "$user\n" if `passwd -S $user` ne "Password: locked"'

In practice, you'd probably need some kind of hairy regex at the end, like:

`passwd -S $user` !~ /^\s*Password\s*:\s*locked\s*$/im'

Where the 'i' at the end makes it case insensitive (which probably isn't necessary), and the 'm' allows matching multiple lines of output [from passwd -S]. It's hard to say exactly what you'd need without seeing the exact output you're matching (on your *nix).

For example, on cygwin, I think the equivalent would be this:

`passwd -S $user` !~ /^\s*Account\s+disabled\s+:\s+yes\s*$/im'
datageist
+2  A: 

The same as one-liner.

sudo perl -F: -lane 'print $F[0] if $F[1]!~/^!/' /etc/shadow
codeholic
He is asking to print users which are NOT locked. I made the same mistake myself ;)
Danilo Piazzalunga
Thank you for pointing out my mistake.
codeholic
A: 
open(F,"<","/etc/shadow") or die "Cannot open shadow file:$!\n";
while(<F>){
    chomp;
    @s = split /:/;
    if ( $s[1] !~ /!/){
        print "user: $s[0] not locked \n";
    }
}
close(F);

use as root.

ghostdog74