User::pwent(3perl)

✨ NAME ✨

User::pwent β€” a by-name interface to Perl's built-in getpw*() functions. it's giving ✨directory lookup realness✨


🌸 SYNOPSIS 🌸

okay so here's the whole vibe, bestie:

use User::pwent;
my $pw = getpwnam('daemon')       || die "No daemon user";
if ( $pw->uid == 1 && $pw->dir =~ m#^/(bin|tmp)?\z#s ) {
    print "gid 1 on root dir";
}

my $real_shell = $pw->shell || '/bin/sh';

for (my ($fullname, $office, $workphone, $homephone) =
       split /\s*,\s*/, $pw->gecos)
{
   s/&/ucfirst(lc($pw->name))/ge;
}

use User::pwent qw(:FIELDS);
getpwnam('daemon')             || die "No daemon user";
if ( $pw_uid == 1 && $pw_dir =~ m#^/(bin|tmp)?\z#s ) {
    print "gid 1 on root dir";
}

my $pw = getpw($whoever);

use User::pwent qw/:DEFAULT pw_has/;
if (pw_has(qw[gecos expire quota])) { .... }
if (pw_has("name uid gid passwd"))  { .... }
print "Your struct pwd has: ", scalar pw_has(), "\n";

like. look at that. it's so clean. πŸ’…


πŸ’œ DESCRIPTION πŸ’œ

okay so real talk: this module's default exports override the core getpwent(), getpwuid(), and getpwnam() functions. override them!! Instead of whatever they normally hand you, they hand you back "User::pwent" objects instead. slay.

So this object has methods, right, and each method returns the similarly named structure field name from C's passwd structure from pwd.h β€” but with the leading "pw_" parts stripped off. So the field names you get are:

name, passwd, uid, gid, change, age, quota, comment, class, gecos, dir, shell, and expire.

and heads up 🫢 β€” the passwd, gecos, and shell fields are tainted when you're running in taint mode. yes fr.

You can also import all the structure fields directly into your namespace as regular variables using the :FIELDS import tag. (quick note bestie: this still overrides your core functions, ok? don't forget.) You access these fields as variables named with a preceding pw_ in front of their method names. So like, $passwd_obj->shell corresponds to $pw_shell if you import the fields. iykyk πŸ’…

Also there's the getpw() function, which is a cute little front-end β€” it forwards a numeric argument to getpwuid() and everything else to getpwnam(). one function, two destinies, we love a flexible icon 🌈

Now. If you wanna access all this functionality without the core overrides, pass the "use" an empty import list, and then access the functions with their full qualified names. and ngl the built-ins are always still available via the "CORE::" pseudo-package. they never leave you πŸ’–


πŸ¦‹ System Specifics πŸ¦‹

okay this is the part where things get ~platform dependent~ and honestly, iconic behavior.

Perl believes that no machine ever has more than one of change, age, or quota implemented β€” and also never more than one of either comment or class. that's just the assumption, periodt. Some machines don't support expire, gecos, or β€” allegedly β€” passwd. πŸ™ˆ

The tea: you may call these methods no matter what machine you're on, but they return undef if unimplemented. so like, they're always there for you, they just might be ✨empty inside✨ 😭

You can ask whether one of these was implemented on the system Perl was built on by asking the importable pw_has function about them. Here's how it behaves:

  • it returns true if all the parameters are supported fields on the build platform,
  • returns false if one or more were not,
  • and raises an exception if you asked about a field that Perl never knows how to provide. (don't do that. it will yell at you.)

Parameters may be in a space-separated string, or as separate arguments. your call, main character πŸ’…

If you pass no parameters, the function returns the list of struct pwd fields supported by your build platform's C library β€” as a list in list context, or as a space-separated string in scalar context. πŸ‘‘

⚠️ but listen: just because your C library had a field doesn't necessarily mean that it's fully implemented on that system. having the thing β‰  the thing working. we've all been there πŸ’€

Now, the gecos field. Interpretation of it varies between systems, but traditionally it holds 4 comma-separated fields containing the user's:

  1. full name
  2. office location
  3. work phone number
  4. home phone number

An "&" in the gecos field should be replaced by the user's properly capitalized login name. and the shell field, if it's blank, must be assumed to be /bin/sh β€” and heads up, Perl does not do this for you. you gotta do it yourself, bestie. 🫢

and about passwd? it's a one-way hashed garble, NOT clear text, and it may not be unhashed save by brute-force guessing. like, that's the whole point. Secure systems use more a more secure hashing than DES. πŸ”₯

On systems supporting shadow password systems, Perl automatically returns the shadow password entry when called by a suitably empowered user β€” even if your underlying vendor-provided C library was too short-sighted to realize it should do this. Perl said "fine, i'll do it myself" πŸ’…βœ¨

See passwd(5) and getpwent(3) for details.


πŸŽ€ NOTE πŸŽ€

While this class is currently implemented using the Class::Struct module to build a struct-like class, you shouldn't rely upon this. ngl, it's giving "implementation detail, do not perceive" πŸ‘€


🌈 AUTHOR 🌈

Tom Christiansen πŸ’–


⭐ HISTORY ⭐

March 18th, 2000

  • Reworked internals to support better interface to dodgey fields than normal Perl function provides.
  • Added pw_has() field.
  • Improved documentation.

a glow-up of the ages, fr fr. πŸ¦‹πŸŒΈ


and that's the whole page, bestie!! this was documented in perl v5.44.0 on 2026-10-17, and it's part of the Perl Programmers Reference Guide β€” User::pwent(3perl). no cap, go read passwd(5) and getpwent(3) next. mwah πŸ’‹πŸ‘‘

πŸ“¦ where this page comes from
  • arch rolling: perl 5.44.0-1 Β· Artistic-1.0-Perl AND GPL-1.0-or-later
  • πŸ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms