When run without root privileges, getpwent(), getpwnam() and friends always set errno, even if they succeed. Because of this, it is impossible to distinguish between true errors (for which errno should be set) and conditions like "end of database" and "no such user" (for which errno should not be set).
The problem is caused by __initdb() in lib/libc/gen/getpwent.c. It first tries to open /etc/spwd.db. If that fails, it tries /etc/pwd.db. Opening /etc/spwd.db always fails for non-root users and this causes errno to be set. The simplest solution is to save the original errno value before attempting to open the password databases and then restore it when either database has been opened successfully. Regards, Tim Index: getpwent.c =================================================================== RCS file: /cvs/src/lib/libc/gen/getpwent.c,v retrieving revision 1.42 diff -p -u -r1.42 getpwent.c --- getpwent.c 21 Nov 2009 10:24:59 -0000 1.42 +++ getpwent.c 12 Aug 2011 23:30:07 -0000 @@ -844,14 +844,18 @@ static int __initdb(void) { static int warned; + int oerrno; #ifdef YP __ypmode = YPMODE_NONE; __getpwent_has_yppw = -1; #endif + oerrno = errno; if ((_pw_db = dbopen(_PATH_SMP_DB, O_RDONLY, 0, DB_HASH, NULL)) || - (_pw_db = dbopen(_PATH_MP_DB, O_RDONLY, 0, DB_HASH, NULL))) + (_pw_db = dbopen(_PATH_MP_DB, O_RDONLY, 0, DB_HASH, NULL))) { + errno = oerrno; return (1); + } if (!warned) syslog(LOG_ERR, "%s: %m", _PATH_MP_DB); warned = 1;