--- name: getpwnam signature: 'getpwnam NAME' since: 5.0 status: documented categories: ["User and group info"] --- ```{index} single: getpwnam; Perl built-in ``` *[User and group info](../perlfunc-by-category)* # getpwnam Look up a user's passwd record by login name. `getpwnam` wraps the system C library's `getpwnam(3)` call. Pass a login name like `"root"` or `"alice"`; you get back the passwd entry for that user, or an empty list / [`undef`](undef) if no such user exists. The return shape depends on context: list context gives every field of the record; scalar context gives a single useful value — for `getpwnam` specifically, the numeric UID. ## Synopsis ```perl getpwnam NAME ``` ## What you get back **List context** returns a 10-element list mirroring `struct passwd` augmented with the BSD extras: ```perl my ($name, $passwd, $uid, $gid, $quota, $comment, $gcos, $dir, $shell, $expire) = getpwnam($login); ``` - `$name` — login name (same string you passed in) - `$passwd` — encrypted password, or `"x"` / `"*"` on shadow-password systems. Tainted under `-T`. - `$uid` — numeric user ID - `$gid` — numeric primary group ID - `$quota` — disk quota, or `$change` / `$age` on some systems. Empty string when unsupported. - `$comment` — administrative comment, sometimes `$class`. Empty string when unsupported. - `$gcos` — GECOS field (usually the real name plus other user info). Tainted under `-T` because users can edit it. - `$dir` — home directory - `$shell` — login shell. Tainted under `-T`. - `$expire` — account / password expiration, when supported. **Scalar context** returns just `$uid`. For `getpwnam` — a lookup *by name* — scalar context gives you "the other thing," matching the rule upstream documents for all `getpw*` / `getgr*` / `gethost*` / `getnet*` / `getproto*` / `getserv*` functions. **On lookup failure** both contexts return the empty list / [`undef`](undef). Always check the return before unpacking. ## Global state it touches - Sets [`$!`](../perlvar) on system-call failure (rare — "user not found" is not a failure, it's an empty return). - Under `-T` (taint mode), `$passwd`, `$gcos`, and `$shell` come back tainted. See `perlsec` for how to launder them. - Shares the same underlying iterator state as [`getpwent`](getpwent), [`setpwent`](setpwent), and [`endpwent`](endpwent). A `getpwnam` call does **not** disturb an in-progress [`getpwent`](getpwent) loop on glibc, but portable code should not assume that. ## Examples Basic name-to-UID lookup in scalar context: ```perl my $uid = getpwnam("root"); # 0 ``` Full record in list context, with a defensive check: ```perl my @pw = getpwnam($user) or die "$user: not in passwd database"; my ($name, undef, $uid, $gid, undef, undef, $gcos, $home, $shell) = @pw; print "$name ($uid) -> $home, shell $shell\n"; ``` Assignment pattern from upstream — unpacking directly with `or die`: ```perl my ($login, $pass, $uid, $gid) = getpwnam($user) or die "$user not in passwd file"; ``` Comparing file ownership against a named user without hand-written field indexing, via the `User::pwent` override: ```perl use User::pwent; use File::stat; my $is_theirs = (stat($filename)->uid == getpwnam($whoever)->uid); ``` `use User::pwent` replaces `getpwnam` with a version returning a blessed object with `->name`, `->uid`, `->gid`, `->dir`, `->shell` accessors — handy when you want one field and don't want to count commas. The two forms do not mix: inside one scope either use the override or the built-in, not both. Fallback chain for "who am I running as": ```perl my $login = getlogin() || getpwuid($<) || "unknown"; ``` [`getpwuid`](getpwuid) is the by-UID counterpart; [`getlogin`](getlogin) reads the controlling-tty record and can lie on detached processes, so it's the first choice, not the only one. ## Edge cases - **No such user** returns the empty list in list context and [`undef`](undef) in scalar context. This is not an error — [`$!`](../perlvar) is not set. Distinguish "user missing" from "lookup failed" by checking [`$!`](../perlvar) only when you want to report an unexpected failure, not when deciding whether the user exists. - **`$passwd` is rarely useful.** On modern Linux and BSD systems the real hash lives in `/etc/shadow`, readable only by root. You get `"x"` or `"*"` here. Use PAM or the `Authen::PAM` module for authentication rather than comparing against this field. - **`$quota`, `$comment`, `$expire` portability.** These fields are empty or meaningless on Linux. The upstream POD lists `Config` values (`d_pwquota`, `d_pwage`, `d_pwchange`, `d_pwcomment`, `d_pwexpire`) you can check if you need to know at runtime whether the platform populates them. - **Tainted fields under `-T`.** `$passwd`, `$gcos`, `$shell` are tainted because users can modify them (via `chsh`, `chfn`, or direct `/etc/passwd` edits in privileged contexts). Pass them through a regex capture to launder before using in a system call. - **Return value is a "single meaningless true value"** in Boolean-ish scalar context *when the entry exists but you wanted list context.* The scalar-context documented return for `getpwnam` is the UID, which for `root` is `0` — a false value. `if (getpwnam("root")) { ... }` therefore fails for root. Use `defined` or list context: ```perl if (defined getpwnam("root")) { ... } # correct if (my @pw = getpwnam("root")) { ... } # also correct ``` - **Name is a string, not a UID.** `getpwnam(0)` stringifies `0` and looks up the literal user named `"0"`, which almost never exists. Use [`getpwuid`](getpwuid) for numeric lookups. - **Large directories (LDAP / NIS / SSSD).** `getpwnam` goes through NSS, so the cost scales with however the local resolver answers. A miss against a misconfigured LDAP server can block for seconds. Cache results in a hash if you are looking up many users in a tight loop. - **Threads.** Upstream notes that `getpwnam_r` is used automatically where the platform provides it; `getpwent` iteration, by contrast, remains per-process. Not a concern under pperl (no ithreads), but worth knowing if you share code with perl5. ## Differences from upstream Fully compatible with upstream Perl 5.42. ## See also - [`getpwuid`](getpwuid) — same record, looked up by numeric UID; pair with `getpwnam` when you need to go UID → name - [`getpwent`](getpwent) — iterate the whole passwd database; use when you need every user, not a specific one - [`endpwent`](endpwent) — close the passwd iterator after [`getpwent`](getpwent) - [`getgrnam`](getgrnam) — group-database counterpart; needed to resolve the `$gid` field from this record back to a group name - [`getlogin`](getlogin) — cheap "who is on this tty" lookup; fall back to `getpwnam`/[`getpwuid`](getpwuid) when it returns empty - `User::pwent` — object wrapper with named accessors; reach for it when you want `->uid` instead of counting list positions