getpwent#
Return the next entry from the system password database.
getpwent walks the password database one record at a time. The first
call opens the database (typically /etc/passwd, possibly augmented by
NSS with LDAP, SSSD, or similar); each subsequent call returns the next
entry. When the iteration is exhausted the call returns an empty list
in list context or undef in scalar context. Pair it with
setpwent to rewind and endpwent to release
any resources the database library is holding.
Synopsis#
my @fields = getpwent;
my $name = getpwent; # scalar context: login name only
What you get back#
In list context, a 10-element list describing one account:
my ( $name, $passwd, $uid, $gid, $quota,
$comment, $gcos, $dir, $shell, $expire ) = getpwent;
# 0 1 2 3 4
# 5 6 7 8 9
$name— login name.$passwd— the encrypted password field. On systems with shadow passwords this is usually"x"or"*"unless the process is privileged; the real hash lives in/etc/shadow. Tainted under-T.$uid,$gid— numeric user and primary group ids.$quota— disk quota on systems that support it, otherwise an empty string. On some systems this slot carries$changeor$age(password-aging data).$comment— administrative comment on systems that support it, otherwise empty. On some systems this slot carries$class.$gcos— the GECOS field, conventionally the user’s real name. User-writable on many systems, therefore tainted under-T.$dir— home directory.$shell— login shell. Tainted under-T.$expire— account or password expiration on systems that support it, otherwise absent.
In scalar context, only the login name is returned. When the
iteration is exhausted the scalar value is undef and the
list value is empty.
Whether $quota, $comment, and $expire carry meaningful data on
the current build depends on how Perl was configured; inspect
Config values d_pwquota, d_pwage, d_pwchange,
d_pwcomment, and d_pwexpire to find out.
Global state it touches#
getpwent keeps its cursor in a process-wide, library-owned state
block inside the C library’s pwd routines. Consequences:
Two independent loops over the database in the same process interfere with each other. Each
getpwentadvances the one shared cursor.setpwentrewinds that cursor to the beginning.endpwentcloses the database and drops any resources (open file descriptors, NSS module state) the library was holding.Threads share the cursor too.
getpwentis not safe to call concurrently from multiple threads; if two threads iterate in parallel, neither sees every record.
getpwent does not read or write any Perl special variables.
Examples#
Dump every account name and home directory:
while ( my @pw = getpwent ) {
print "$pw[0]\t$pw[7]\n";
}
endpwent;
Named-field destructuring reads more clearly than numeric indexing:
while ( my ($name, undef, $uid, $gid, undef, undef, $gcos, $dir) = getpwent ) {
next if $uid < 1000; # skip system accounts
print "$name ($gcos) uid=$uid home=$dir\n";
}
endpwent;
Scalar context yields the login name, useful for enumerating users without unpacking the rest:
my @users;
while ( defined( my $name = getpwent ) ) {
push @users, $name;
}
endpwent;
Rewind in the middle of a walk with setpwent:
my @first_pass = (getpwent)[0];
setpwent; # back to the top
while ( my @pw = getpwent ) { ... }
endpwent;
Collect all entries into a hash keyed by uid, then release the database:
my %by_uid;
while ( my @pw = getpwent ) {
$by_uid{ $pw[2] } = \@pw;
}
endpwent;
Edge cases#
End of iteration: returns an empty list in list context and
undefin scalar context.while (my @pw = getpwent)andwhile (defined(my $name = getpwent))are the idiomatic loop forms.Forgetting
endpwent: leaks whatever file descriptors or NSS state the library opened until the process exits. Not a correctness bug, but noticeable in long-lived programs and in test harnesses.Nested iteration is broken: two loops in the same process share the library’s single cursor. Collect one walk into a data structure before starting the next.
Shadow passwords: on Linux and Solaris the real password hash is in
/etc/shadow, readable only by root. Non-privileged processes see"x"or"*"in$passwdand must call the shadow-aware routines (outside of core Perl) to get the hash.NSS surprises: the database is whatever
/etc/nsswitch.confsays it is. On a host bound to LDAP or SSSD,getpwentmay return thousands of directory accounts, take a noticeable amount of time, and fail intermittently if the network is flaky. Consider looking accounts up by name withgetpwnamwhen you know which one you want.Tainting under
-T:$passwd,$gcos, and$shellcome back tainted because users can influence them. Untaint with a deliberate regex match if you need to use them in sensitive operations.Thread safety: unlike
getpwnamandgetpwuid, there is nogetpwent_rin POSIX that Perl can transparently substitute. Concurrent iteration from multiple threads is unsafe.By-name interface:
User::pwentoverridesgetpwentwith a version that returns an object exposing fields as methods ($pw->name,$pw->uid, …). Use it when the numeric-slot unpacking gets unwieldy.
Differences from upstream#
Fully compatible with upstream Perl 5.42.
See also#
getpwnam— look up one account by login name; the right call when you know which user you wantgetpwuid— look up one account by numeric uidsetpwent— rewind thegetpwentcursor to the first entryendpwent— close the password database and release library resources; call it when the walk is donegetgrent— the group-database counterpart, same iteration modelUser::pwent— by-name interface that returns an object with named accessors instead of a 10-element list