--- name: getpwent signature: 'getpwent' since: 5.0 status: documented categories: ["User and group info"] --- ```{index} single: getpwent; Perl built-in ``` *[User and group info](../perlfunc-by-category)* # 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`](undef) in scalar context. Pair it with [`setpwent`](setpwent) to rewind and [`endpwent`](endpwent) to release any resources the database library is holding. ## Synopsis ```perl 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: ```perl 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`](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`](../../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`](setpwent) rewinds that cursor to the beginning. - [`endpwent`](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: ```perl while ( my @pw = getpwent ) { print "$pw[0]\t$pw[7]\n"; } endpwent; ``` Named-field destructuring reads more clearly than numeric indexing: ```perl 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: ```perl my @users; while ( defined( my $name = getpwent ) ) { push @users, $name; } endpwent; ``` Rewind in the middle of a walk with [`setpwent`](setpwent): ```perl 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: ```perl 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`](undef) in scalar context. `while (my @pw = getpwent)` and `while (defined(my $name = getpwent))` are the idiomatic loop forms. - **Forgetting [`endpwent`](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`](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`](getpwnam) and [`getpwuid`](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`](getpwnam) — look up one account by login name; the right call when you know which user you want - [`getpwuid`](getpwuid) — look up one account by numeric uid - [`setpwent`](setpwent) — rewind the `getpwent` cursor to the first entry - [`endpwent`](endpwent) — close the password database and release library resources; call it when the walk is done - [`getgrent`](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