Say I made a custom nss module called foo
which defines abides by the required API:
#include <nss.h>
enum nss_status _nss_foo_getpwnam(const char *name, struct passwd *result, char *buf, size_t buflen, int *errnop);
enum nss_status _nss_foo_getpwuid(uid_t uid, struct passwd *result, char *buf, size_t buflen, int *errnop);
enum nss_status _nss_foo_setpwent(void);
enum nss_status _nss_foo_getpwent(struct passwd *result, char *buf, size_t buflen, int *errnop);
enum nss_status _nss_foo_endpwent(void);
Assuming I have my nsswitch.conf setup like so:
passwd: foo files
It is clear from the standard that getpwnam()
for user bar
would first call my _nss_foo_getpwnam()
and then if that returns NSS_STATUS_NOTFOUND
, check /etc/passwd
. However, the standard and behavior for [set|get|end]pwent()
is a bit less clear to me. If I understand man 5 nsswitch.conf
correctly, it sounds like this would first call my _nss_foo_setpwent()
and if that returned NSS_STATUS_SUCCESS
then it would only enumerate users from my module (because by default the action for success is to "immediately return" according to the man page). Is this interpretation correct?
Ideally, I'd like this use my module first and fallback approach for getpwnam
/getpwuid
, but for enuemrating users, I really need to merge the enumeration between all sources. Is there a way to accomplish this that isn't a total hack (the best I can think of is to manually read and parse /etc/passwd
myself, because I obviously can't use setpwent()
, because that would recursively invoke my foo
module)?
Digging into the libc source, I discovered ACTION=merge
, which seems to do what I want for setpwent()
and friends. However, it seems like from the glibc >=2.24 man page for nsswitch.conf that this isn't supported for getgrent()
and friends. Does this mean I'm stuck with a hacky solution for groups (like parsing /etc/groups
myself)?