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;

Reply via email to