Subject: nsswitch / nsdispatch(3) cleanup ...
To: None <tech-userlevel@NetBSD.org>
From: Luke Mewburn <lukem@NetBSD.org>
List: tech-userlevel
Date: 09/27/2004 19:31:58
--sHrvAb52M6C8blB9
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable
Hi all.
We now have generic support for dynamic nsswitch back-ends,
based on work in FreeBSD by Jacques A. Vidrine, and
integrated by Jason Thorpe.
I've been working on a winbind nsswitch backend (for Samba 3),
and realised that the use of nsdispatch(3) in libc/gen/getpwent.c
and libc/gen/getgrent.c is ... suboptimal. We currently
nsdispatch to internal methods with an internal API that is not
suited to make publically available for use in dynamic modules.=20
(E.g, look at nsdispatch(3)'s use within getgrent.c)
To recap, an nsswitch method has the API:
typedef int (*nss_method)(void *retval, void *cb_data, va_list ap);
(See nsdispatch(3) for more details).
We need to standardize the API used between the "standard"
functions and the nsswitch methods invoked via nsdispatch(3).
I intend to use the following convention within each method:
1. void *retval is a pointer to the actual return
value for the external function.
The method should set this as necessary.
2. `va_list ap' has the same layout as the external
function's calling convention.
E.g., for getgrgid_r(3);
static int
dns_getgrgid_r(void *retval, void *cb_data, va_list ap)
{
/* int *retval */
gid_t gid =3D va_arg(ap, gid_t);
struct group *grp =3D va_arg(ap, struct group *);
char *buffer =3D va_arg(ap, char *);
size_t buflen =3D va_arg(ap, size_t);
struct group **result =3D va_arg(ap, struct group **);
*(int *)retval =3D 0;
/* do the work */
return NS_SUCCESS;
}
int
getgrgid_r(gid_t gid, struct group *grp, char *buffer, size_t
buflen, struct group **result)
{
int r, retval;
static const ns_dtab dtab[] =3D {
NS_DNS_CB(dns_getgrgid_r, NULL)
{ 0 }
};
*result =3D NULL;
r =3D nsdispatch(&retval, dtab, NSDB_GROUP,
"getgrgid_r", __nsdefaultsrc,=20
gid, grp, buffer, buflen, result);
return (r =3D=3D NS_SUCCESS) ? 0 : retval;
}
This simplifies the work of an implementer of a third party
libnss_foo.so module because the API of the method's va_list
is directly derived from the API of standard function that
invokes it.
I'm in the process of cleaning up getgrent(3) (et al); it's almost
ready to commit, and I have implemented getgrgid_r() and getgrnam_r()
as well. I'll be working on getpwent(3) et all) next.
This should not have any adverse affect on backward compatibility,
because I don't envisage that anyway has yet implemented backend
methods for these functions (e.g, "grscan", "getpwcompat", ...).
As a future project I'll be provide a build framework for building
libnss_{files,dns,nis,compat}.so from the libc sources, allowing us
to not have to compile in the "static" methods by default.
Cheers,
Luke.
--sHrvAb52M6C8blB9
Content-Type: application/pgp-signature
Content-Disposition: inline
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.6 (NetBSD)
iD8DBQFBV94OpBhtmn8zJHIRAl9MAKDUHIfvYaTGyMMh1dn0mEBg0WqXOgCgsWf5
7SCDe6GP5eZISDod1Jwzm0I=
=d0YY
-----END PGP SIGNATURE-----
--sHrvAb52M6C8blB9--