--- name: getpwuid signature: 'getpwuid UID' since: 5.0 status: documented categories: ["User and group info"] --- ```{index} single: getpwuid; Perl built-in ``` *[User and group info](../perlfunc-by-category)* # getpwuid Look up a user's passwd record by numeric UID. `getpwuid` wraps the system C library's `getpwuid(3)` call. Pass a numeric user ID like `0` or `$<`; you get back the passwd entry for that user, or an empty list / [`undef`](undef) if no such UID exists. The return shape depends on context: list context gives every field of the record; scalar context gives a single useful value — for `getpwuid` specifically, the login name. ## Synopsis ```perl getpwuid UID ``` ## What you get back **List context** returns a 10-element list mirroring `struct passwd` augmented with the BSD extras — the same shape [`getpwnam`](getpwnam) returns: ```perl my ($name, $passwd, $uid, $gid, $quota, $comment, $gcos, $dir, $shell, $expire) = getpwuid($uid); ``` - `$name` — login name - `$passwd` — encrypted password, or `"x"` / `"*"` on shadow-password systems. Tainted under `-T`. - `$uid` — numeric user ID (same number you passed in) - `$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 `$name` (the login name). For `getpwuid` — a lookup *by UID* — 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 — "UID not found" is not a failure, it's an empty return). - Reads `$<` and `$>` implicitly only when you pass them in, but the common idiom `getpwuid($<)` is what turns the real-UID special variable into a useful record. - 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 `getpwuid` call does **not** disturb an in-progress [`getpwent`](getpwent) loop on glibc, but portable code should not assume that. ## Examples Basic UID-to-name lookup in scalar context: ```perl my $name = getpwuid(0); # "root" ``` "Who am I running as" — the canonical `getpwuid` idiom, resolving the real UID to a login name: ```perl my $me = getpwuid($<); # e.g. "alice" ``` Pair with [`getlogin`](getlogin) for a reliable fallback chain that survives detached processes and `su` sessions: ```perl my $login = getlogin() || getpwuid($<) || "unknown"; ``` [`getlogin`](getlogin) reads the controlling-tty record and can lie (or return empty) when there is no tty; `getpwuid($<)` answers from the kernel's recorded UID and always works. Full record in list context, with a defensive check: ```perl my @pw = getpwuid($uid) or die "uid $uid: not in passwd database"; my ($name, undef, undef, $gid, undef, undef, $gcos, $home, $shell) = @pw; print "$name ($uid) -> $home, shell $shell\n"; ``` Go UID → group name via the `$gid` field: ```perl my $gid = (getpwuid($<))[3]; my $groupnam = getgrgid($gid); ``` Object-style access via the `User::pwent` override, useful when you want named accessors instead of counting list positions: ```perl use User::pwent; my $pw = getpwuid($<); printf "%s lives in %s, runs %s\n", $pw->name, $pw->dir, $pw->shell; ``` `use User::pwent` replaces `getpwuid` with a version returning a blessed object with `->name`, `->uid`, `->gid`, `->dir`, `->shell` accessors. The two forms do not mix: inside one scope either use the override or the built-in, not both. ## Edge cases - **No such UID** returns the empty list in list context and [`undef`](undef) in scalar context. This is not an error — [`$!`](../perlvar) is not set. Distinguish "UID missing" from "lookup failed" by checking [`$!`](../perlvar) only when you want to report an unexpected failure, not when deciding whether the UID 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. - **Scalar-return on UID 0 is never false.** Unlike [`getpwnam`](getpwnam), whose scalar return for `root` is the UID `0` (a false value), `getpwuid`'s scalar return is the *name* `"root"` — always a true string for existing users. `if (getpwuid($uid)) { ... }` therefore works as you would expect, but reach for `defined` anyway if you care about the distinction between "missing" and "empty name": ```perl if (defined getpwuid($uid)) { ... } # unambiguous if (my @pw = getpwuid($uid)) { ... } # also correct ``` - **UID is a number, not a name.** `getpwuid("root")` stringifies `"root"` to `0` (with a warning under `use warnings`) and looks up UID `0`. Use [`getpwnam`](getpwnam) for name lookups. - **Negative / oversized UIDs.** The system call accepts whatever `uid_t` accepts on the platform (typically 32-bit unsigned). Perl converts negative values via two's-complement on the way in; the result is platform-specific and almost never what you want. - **Large directories (LDAP / NIS / SSSD).** `getpwuid` 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 resolving many UIDs in a tight loop (e.g. annotating `ls -l`-style output). - **Threads.** Upstream notes that `getpwuid_r` is used automatically where the platform provides it; [`getpwent`](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 - [`getpwnam`](getpwnam) — same record, looked up by login name; pair with `getpwuid` when you need to go name → UID - [`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) - [`getgrgid`](getgrgid) — 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 `getpwuid($<)` when it returns empty - `User::pwent` — object wrapper with named accessors; reach for it when you want `->name` instead of counting list positions