User and group info

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 $change or $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 getpwent advances the one shared cursor.

  • setpwent rewinds that cursor to the beginning.

  • endpwent closes the database and drops any resources (open file descriptors, NSS module state) the library was holding.

  • Threads share the cursor too. getpwent is 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 undef in scalar context. while (my @pw = getpwent) and while (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 $passwd and must call the shadow-aware routines (outside of core Perl) to get the hash.

  • NSS surprises: the database is whatever /etc/nsswitch.conf says it is. On a host bound to LDAP or SSSD, getpwent may 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 with getpwnam when you know which one you want.

  • Tainting under -T: $passwd, $gcos, and $shell come 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 getpwnam and getpwuid, there is no getpwent_r in POSIX that Perl can transparently substitute. Concurrent iteration from multiple threads is unsafe.

  • By-name interface: User::pwent overrides getpwent with 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 want

  • getpwuid — look up one account by numeric uid

  • setpwent — rewind the getpwent cursor to the first entry

  • endpwent — close the password database and release library resources; call it when the walk is done

  • getgrent — the group-database counterpart, same iteration model

  • User::pwent — by-name interface that returns an object with named accessors instead of a 10-element list