Resending.
On Fri, 19 Aug 2011 00:36:51 +0200, Tim van der Molen wrote:
> 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;