summaryrefslogtreecommitdiff
path: root/src/libnsss
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2018-06-26 00:25:28 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2018-06-26 00:25:28 +0000
commit633445be1a9be37ae727c044417f5607706cf4ae (patch)
tree3c037459f5249e5c18ee5b9e41802c5964364f95 /src/libnsss
downloadnsss-633445be1a9be37ae727c044417f5607706cf4ae.tar.xz
Initial commit
Diffstat (limited to 'src/libnsss')
-rw-r--r--src/libnsss/deps-lib/nsss111
-rw-r--r--src/libnsss/nsss-all-internal.h8
-rw-r--r--src/libnsss/nsss-internal.h35
-rw-r--r--src/libnsss/nsss-switch-internal.h21
-rw-r--r--src/libnsss/nsss-unix-internal.h13
-rw-r--r--src/libnsss/nsss_all_endgrent.c17
-rw-r--r--src/libnsss/nsss_all_endpwent.c17
-rw-r--r--src/libnsss/nsss_all_endspent.c17
-rw-r--r--src/libnsss/nsss_all_errno.c5
-rw-r--r--src/libnsss/nsss_all_getgrent.c28
-rw-r--r--src/libnsss/nsss_all_getgrent_r.c44
-rw-r--r--src/libnsss/nsss_all_getgrgid.c29
-rw-r--r--src/libnsss/nsss_all_getgrgid_r.c41
-rw-r--r--src/libnsss/nsss_all_getgrnam.c29
-rw-r--r--src/libnsss/nsss_all_getgrnam_r.c41
-rw-r--r--src/libnsss/nsss_all_getpwent.c26
-rw-r--r--src/libnsss/nsss_all_getpwent_r.c42
-rw-r--r--src/libnsss/nsss_all_getpwnam.c27
-rw-r--r--src/libnsss/nsss_all_getpwnam_r.c39
-rw-r--r--src/libnsss/nsss_all_getpwuid.c27
-rw-r--r--src/libnsss/nsss_all_getpwuid_r.c39
-rw-r--r--src/libnsss/nsss_all_getspent.c26
-rw-r--r--src/libnsss/nsss_all_getspent_r.c42
-rw-r--r--src/libnsss/nsss_all_getspnam.c27
-rw-r--r--src/libnsss/nsss_all_getspnam_r.c39
-rw-r--r--src/libnsss/nsss_all_setgrent.c22
-rw-r--r--src/libnsss/nsss_all_setpwent.c22
-rw-r--r--src/libnsss/nsss_all_setspent.c22
-rw-r--r--src/libnsss/nsss_grp_copy.c27
-rw-r--r--src/libnsss/nsss_grp_here.c10
-rw-r--r--src/libnsss/nsss_pwd_copy.c19
-rw-r--r--src/libnsss/nsss_pwd_here.c8
-rw-r--r--src/libnsss/nsss_shadow_copy.c21
-rw-r--r--src/libnsss/nsss_shadow_here.c8
-rw-r--r--src/libnsss/nsss_switch_end.c17
-rw-r--r--src/libnsss/nsss_switch_endgrent.c10
-rw-r--r--src/libnsss/nsss_switch_endpwent.c10
-rw-r--r--src/libnsss/nsss_switch_endspent.c10
-rw-r--r--src/libnsss/nsss_switch_getgrent.c17
-rw-r--r--src/libnsss/nsss_switch_getgrent_r.c36
-rw-r--r--src/libnsss/nsss_switch_getgrgid.c22
-rw-r--r--src/libnsss/nsss_switch_getgrgid_r.c36
-rw-r--r--src/libnsss/nsss_switch_getgrnam.c22
-rw-r--r--src/libnsss/nsss_switch_getgrnam_r.c36
-rw-r--r--src/libnsss/nsss_switch_getpwent.c15
-rw-r--r--src/libnsss/nsss_switch_getpwent_r.c34
-rw-r--r--src/libnsss/nsss_switch_getpwnam.c20
-rw-r--r--src/libnsss/nsss_switch_getpwnam_r.c34
-rw-r--r--src/libnsss/nsss_switch_getpwuid.c20
-rw-r--r--src/libnsss/nsss_switch_getpwuid_r.c34
-rw-r--r--src/libnsss/nsss_switch_getspent.c15
-rw-r--r--src/libnsss/nsss_switch_getspent_r.c34
-rw-r--r--src/libnsss/nsss_switch_getspnam.c20
-rw-r--r--src/libnsss/nsss_switch_getspnam_r.c34
-rw-r--r--src/libnsss/nsss_switch_grp_end.c9
-rw-r--r--src/libnsss/nsss_switch_grp_get.c17
-rw-r--r--src/libnsss/nsss_switch_grp_getbygid.c19
-rw-r--r--src/libnsss/nsss_switch_grp_getbyname.c24
-rw-r--r--src/libnsss/nsss_switch_grp_read.c58
-rw-r--r--src/libnsss/nsss_switch_grp_rewind.c9
-rw-r--r--src/libnsss/nsss_switch_here.c6
-rw-r--r--src/libnsss/nsss_switch_op.c16
-rw-r--r--src/libnsss/nsss_switch_pwd_end.c9
-rw-r--r--src/libnsss/nsss_switch_pwd_get.c17
-rw-r--r--src/libnsss/nsss_switch_pwd_getbyname.c24
-rw-r--r--src/libnsss/nsss_switch_pwd_getbyuid.c19
-rw-r--r--src/libnsss/nsss_switch_pwd_read.c53
-rw-r--r--src/libnsss/nsss_switch_pwd_rewind.c9
-rw-r--r--src/libnsss/nsss_switch_setgrent.c12
-rw-r--r--src/libnsss/nsss_switch_setpwent.c12
-rw-r--r--src/libnsss/nsss_switch_setspent.c12
-rw-r--r--src/libnsss/nsss_switch_shadow_end.c9
-rw-r--r--src/libnsss/nsss_switch_shadow_get.c17
-rw-r--r--src/libnsss/nsss_switch_shadow_getbyname.c24
-rw-r--r--src/libnsss/nsss_switch_shadow_read.c56
-rw-r--r--src/libnsss/nsss_switch_shadow_rewind.c9
-rw-r--r--src/libnsss/nsss_switch_start.c26
-rw-r--r--src/libnsss/nsss_unix_end.c11
-rw-r--r--src/libnsss/nsss_unix_endgrent.c9
-rw-r--r--src/libnsss/nsss_unix_endpwent.c9
-rw-r--r--src/libnsss/nsss_unix_endspent.c9
-rw-r--r--src/libnsss/nsss_unix_field.c14
-rw-r--r--src/libnsss/nsss_unix_getgrent.c16
-rw-r--r--src/libnsss/nsss_unix_getgrent_r.c35
-rw-r--r--src/libnsss/nsss_unix_getgrgid.c21
-rw-r--r--src/libnsss/nsss_unix_getgrgid_r.c35
-rw-r--r--src/libnsss/nsss_unix_getgrnam.c21
-rw-r--r--src/libnsss/nsss_unix_getgrnam_r.c35
-rw-r--r--src/libnsss/nsss_unix_getpwent.c14
-rw-r--r--src/libnsss/nsss_unix_getpwent_r.c33
-rw-r--r--src/libnsss/nsss_unix_getpwnam.c19
-rw-r--r--src/libnsss/nsss_unix_getpwnam_r.c33
-rw-r--r--src/libnsss/nsss_unix_getpwuid.c19
-rw-r--r--src/libnsss/nsss_unix_getpwuid_r.c33
-rw-r--r--src/libnsss/nsss_unix_getspent.c14
-rw-r--r--src/libnsss/nsss_unix_getspent_r.c33
-rw-r--r--src/libnsss/nsss_unix_getspnam.c19
-rw-r--r--src/libnsss/nsss_unix_getspnam_r.c33
-rw-r--r--src/libnsss/nsss_unix_grp_get.c62
-rw-r--r--src/libnsss/nsss_unix_grp_getbygid.c22
-rw-r--r--src/libnsss/nsss_unix_grp_getbyname.c22
-rw-r--r--src/libnsss/nsss_unix_grp_here.c5
-rw-r--r--src/libnsss/nsss_unix_maybe_start.c9
-rw-r--r--src/libnsss/nsss_unix_pwd_get.c45
-rw-r--r--src/libnsss/nsss_unix_pwd_getbyname.c19
-rw-r--r--src/libnsss/nsss_unix_pwd_getbyuid.c19
-rw-r--r--src/libnsss/nsss_unix_pwd_here.c5
-rw-r--r--src/libnsss/nsss_unix_rewind.c13
-rw-r--r--src/libnsss/nsss_unix_setgrent.c11
-rw-r--r--src/libnsss/nsss_unix_setpwent.c11
-rw-r--r--src/libnsss/nsss_unix_setspent.c11
-rw-r--r--src/libnsss/nsss_unix_shadow_get.c52
-rw-r--r--src/libnsss/nsss_unix_shadow_getbyname.c19
-rw-r--r--src/libnsss/nsss_unix_shadow_here.c5
-rw-r--r--src/libnsss/nsss_unix_start.c13
115 files changed, 2699 insertions, 0 deletions
diff --git a/src/libnsss/deps-lib/nsss b/src/libnsss/deps-lib/nsss
new file mode 100644
index 0000000..6a51e6a
--- /dev/null
+++ b/src/libnsss/deps-lib/nsss
@@ -0,0 +1,111 @@
+nsss_all_endgrent.o
+nsss_all_endpwent.o
+nsss_all_endspent.o
+nsss_all_errno.o
+nsss_all_getgrent.o
+nsss_all_getgrent_r.o
+nsss_all_getgrgid.o
+nsss_all_getgrgid_r.o
+nsss_all_getgrnam.o
+nsss_all_getgrnam_r.o
+nsss_all_getpwent.o
+nsss_all_getpwent_r.o
+nsss_all_getpwnam.o
+nsss_all_getpwnam_r.o
+nsss_all_getpwuid.o
+nsss_all_getpwuid_r.o
+nsss_all_getspent.o
+nsss_all_getspent_r.o
+nsss_all_getspnam.o
+nsss_all_getspnam_r.o
+nsss_all_setgrent.o
+nsss_all_setpwent.o
+nsss_all_setspent.o
+nsss_grp_copy.o
+nsss_grp_here.o
+nsss_pwd_copy.o
+nsss_pwd_here.o
+nsss_shadow_copy.o
+nsss_shadow_here.o
+nsss_switch_end.o
+nsss_switch_endgrent.o
+nsss_switch_endpwent.o
+nsss_switch_endspent.o
+nsss_switch_getgrent.o
+nsss_switch_getgrent_r.o
+nsss_switch_getgrgid.o
+nsss_switch_getgrgid_r.o
+nsss_switch_getgrnam.o
+nsss_switch_getgrnam_r.o
+nsss_switch_getpwent.o
+nsss_switch_getpwent_r.o
+nsss_switch_getpwnam.o
+nsss_switch_getpwnam_r.o
+nsss_switch_getpwuid.o
+nsss_switch_getpwuid_r.o
+nsss_switch_getspent.o
+nsss_switch_getspent_r.o
+nsss_switch_getspnam.o
+nsss_switch_getspnam_r.o
+nsss_switch_grp_end.o
+nsss_switch_grp_get.o
+nsss_switch_grp_getbygid.o
+nsss_switch_grp_getbyname.o
+nsss_switch_grp_read.o
+nsss_switch_grp_rewind.o
+nsss_switch_here.o
+nsss_switch_op.o
+nsss_switch_pwd_end.o
+nsss_switch_pwd_get.o
+nsss_switch_pwd_getbyname.o
+nsss_switch_pwd_getbyuid.o
+nsss_switch_pwd_read.o
+nsss_switch_pwd_rewind.o
+nsss_switch_setgrent.o
+nsss_switch_setpwent.o
+nsss_switch_setspent.o
+nsss_switch_shadow_end.o
+nsss_switch_shadow_get.o
+nsss_switch_shadow_getbyname.o
+nsss_switch_shadow_read.o
+nsss_switch_shadow_rewind.o
+nsss_switch_start.o
+nsss_unix_end.o
+nsss_unix_endgrent.o
+nsss_unix_endpwent.o
+nsss_unix_endspent.o
+nsss_unix_field.o
+nsss_unix_getgrent.o
+nsss_unix_getgrent_r.o
+nsss_unix_getgrgid.o
+nsss_unix_getgrgid_r.o
+nsss_unix_getgrnam.o
+nsss_unix_getgrnam_r.o
+nsss_unix_getpwent.o
+nsss_unix_getpwent_r.o
+nsss_unix_getpwnam.o
+nsss_unix_getpwnam_r.o
+nsss_unix_getpwuid.o
+nsss_unix_getpwuid_r.o
+nsss_unix_getspent.o
+nsss_unix_getspent_r.o
+nsss_unix_getspnam.o
+nsss_unix_getspnam_r.o
+nsss_unix_grp_get.o
+nsss_unix_grp_getbygid.o
+nsss_unix_grp_getbyname.o
+nsss_unix_grp_here.o
+nsss_unix_maybe_start.o
+nsss_unix_pwd_get.o
+nsss_unix_pwd_getbyname.o
+nsss_unix_pwd_getbyuid.o
+nsss_unix_pwd_here.o
+nsss_unix_rewind.o
+nsss_unix_setgrent.o
+nsss_unix_setpwent.o
+nsss_unix_setspent.o
+nsss_unix_shadow_get.o
+nsss_unix_shadow_getbyname.o
+nsss_unix_shadow_here.o
+nsss_unix_start.o
+-lskarnet
diff --git a/src/libnsss/nsss-all-internal.h b/src/libnsss/nsss-all-internal.h
new file mode 100644
index 0000000..91bd552
--- /dev/null
+++ b/src/libnsss/nsss-all-internal.h
@@ -0,0 +1,8 @@
+/* ISC license. */
+
+#ifndef NSSS_ALL_INTERNAL_H
+#define NSSS_ALL_INTERNAL_H
+
+extern int nsss_all_errno ;
+
+#endif
diff --git a/src/libnsss/nsss-internal.h b/src/libnsss/nsss-internal.h
new file mode 100644
index 0000000..f9dbeb3
--- /dev/null
+++ b/src/libnsss/nsss-internal.h
@@ -0,0 +1,35 @@
+/* ISC license. */
+
+#ifndef NSSS_INTERNAL_H
+#define NSSS_INTERNAL_H
+
+#include <sys/types.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/genalloc.h>
+#include <nsss/pwd-def.h>
+#include <nsss/grp-def.h>
+#include <nsss/shadow-def.h>
+
+
+ /* Password */
+
+extern struct passwd nsss_pwd_here ;
+extern stralloc nsss_pwd_sa_here ;
+extern int nsss_pwd_copy (struct passwd *, char *, size_t, struct passwd const *, char const *, size_t) ;
+
+
+ /* Group */
+
+extern struct group nsss_grp_here ;
+extern stralloc nsss_grp_sa_here ;
+extern genalloc nsss_grp_ga_here ;
+extern int nsss_grp_copy (struct group *, char *, size_t, struct group const *, char const *, size_t, char *const *, size_t) ;
+
+
+ /* Shadow */
+
+extern struct spwd nsss_shadow_here ;
+extern stralloc nsss_shadow_sa_here ;
+extern int nsss_shadow_copy (struct spwd *, char *, size_t, struct spwd const *, char const *, size_t) ;
+
+#endif
diff --git a/src/libnsss/nsss-switch-internal.h b/src/libnsss/nsss-switch-internal.h
new file mode 100644
index 0000000..e005ffc
--- /dev/null
+++ b/src/libnsss/nsss-switch-internal.h
@@ -0,0 +1,21 @@
+/* ISC license. */
+
+#ifndef NSSS_SWITCH_INTERNAL_H
+#define NSSS_SWITCH_INTERNAL_H
+
+#include <skalibs/tai.h>
+#include <skalibs/buffer.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/genalloc.h>
+#include <nsss/pwd-def.h>
+#include <nsss/grp-def.h>
+#include <nsss/shadow-def.h>
+#include <nsss/nsss-switch.h>
+
+extern nsss_switch_t nsss_switch_here ;
+extern int nsss_switch_op (nsss_switch_t *, char, tain_t const *, tain_t *) ;
+extern int nsss_switch_pwd_read (buffer *, struct passwd *, stralloc *, tain_t const *, tain_t *) ;
+extern int nsss_switch_grp_read (buffer *, struct group *, stralloc *, genalloc *, tain_t const *, tain_t *) ;
+extern int nsss_switch_shadow_read (buffer *, struct spwd *, stralloc *, tain_t const *, tain_t *) ;
+
+#endif
diff --git a/src/libnsss/nsss-unix-internal.h b/src/libnsss/nsss-unix-internal.h
new file mode 100644
index 0000000..9413a3b
--- /dev/null
+++ b/src/libnsss/nsss-unix-internal.h
@@ -0,0 +1,13 @@
+/* ISC license. */
+
+#ifndef NSSS_UNIX_INTERNAL_H
+#define NSSS_UNIX_INTERNAL_H
+
+#include <nsss/nsss-unix.h>
+
+extern int nsss_unix_field (char **, char **) ;
+extern nsss_unix_t nsss_unix_pwd_here ;
+extern nsss_unix_t nsss_unix_grp_here ;
+extern nsss_unix_t nsss_unix_shadow_here ;
+
+#endif
diff --git a/src/libnsss/nsss_all_endgrent.c b/src/libnsss/nsss_all_endgrent.c
new file mode 100644
index 0000000..059eca4
--- /dev/null
+++ b/src/libnsss/nsss_all_endgrent.c
@@ -0,0 +1,17 @@
+/* ISC license. */
+
+#include <nsss/grp-unix.h>
+#include <nsss/grp-switch.h>
+#include <nsss/grp-all.h>
+#include "nsss-all-internal.h"
+
+void nsss_all_endgrent (void)
+{
+ if (nsss_all_errno) goto fallback ;
+ nsss_switch_endgrent() ;
+ return ;
+
+ fallback:
+ nsss_unix_endgrent() ;
+ nsss_all_errno = 0 ;
+}
diff --git a/src/libnsss/nsss_all_endpwent.c b/src/libnsss/nsss_all_endpwent.c
new file mode 100644
index 0000000..c3ce953
--- /dev/null
+++ b/src/libnsss/nsss_all_endpwent.c
@@ -0,0 +1,17 @@
+/* ISC license. */
+
+#include <nsss/pwd-unix.h>
+#include <nsss/pwd-switch.h>
+#include <nsss/pwd-all.h>
+#include "nsss-all-internal.h"
+
+void nsss_all_endpwent (void)
+{
+ if (nsss_all_errno) goto fallback ;
+ nsss_switch_endpwent() ;
+ return ;
+
+ fallback:
+ nsss_unix_endpwent() ;
+ nsss_all_errno = 0 ;
+}
diff --git a/src/libnsss/nsss_all_endspent.c b/src/libnsss/nsss_all_endspent.c
new file mode 100644
index 0000000..c5587cb
--- /dev/null
+++ b/src/libnsss/nsss_all_endspent.c
@@ -0,0 +1,17 @@
+/* ISC license. */
+
+#include <nsss/shadow-unix.h>
+#include <nsss/shadow-switch.h>
+#include <nsss/shadow-all.h>
+#include "nsss-all-internal.h"
+
+void nsss_all_endspent (void)
+{
+ if (nsss_all_errno) goto fallback ;
+ nsss_switch_endspent() ;
+ return ;
+
+ fallback:
+ nsss_unix_endspent() ;
+ nsss_all_errno = 0 ;
+}
diff --git a/src/libnsss/nsss_all_errno.c b/src/libnsss/nsss_all_errno.c
new file mode 100644
index 0000000..8c50835
--- /dev/null
+++ b/src/libnsss/nsss_all_errno.c
@@ -0,0 +1,5 @@
+/* ISC license. */
+
+#include "nsss-all-internal.h"
+
+int nsss_all_errno = 0 ;
diff --git a/src/libnsss/nsss_all_getgrent.c b/src/libnsss/nsss_all_getgrent.c
new file mode 100644
index 0000000..15b5894
--- /dev/null
+++ b/src/libnsss/nsss_all_getgrent.c
@@ -0,0 +1,28 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/genalloc.h>
+#include <nsss/config.h>
+#include <nsss/grp-unix.h>
+#include <nsss/grp-all.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+#include "nsss-switch-internal.h"
+#include "nsss-all-internal.h"
+
+struct group *nsss_all_getgrent (void)
+{
+ int e = errno ;
+ if (nsss_all_errno) goto fallback ;
+ if (!nsss_switch_start(&nsss_switch_here, NSSS_SWITCH_GRP, NSSS_NSSSD_PATH, 0, 0)) goto efallback ;
+ nsss_grp_sa_here.len = 0 ;
+ genalloc_setlen(char *, &nsss_grp_ga_here, 0) ;
+ if (!nsss_switch_grp_get(&nsss_switch_here, &nsss_grp_here, &nsss_grp_sa_here, &nsss_grp_ga_here, 0, 0)) return 0 ;
+ return &nsss_grp_here ;
+
+ efallback:
+ nsss_all_errno = errno ;
+ errno = e ;
+ fallback:
+ return nsss_unix_getgrent() ;
+}
diff --git a/src/libnsss/nsss_all_getgrent_r.c b/src/libnsss/nsss_all_getgrent_r.c
new file mode 100644
index 0000000..8cdcad6
--- /dev/null
+++ b/src/libnsss/nsss_all_getgrent_r.c
@@ -0,0 +1,44 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/genalloc.h>
+#include <nsss/config.h>
+#include <nsss/grp-unix.h>
+#include <nsss/grp-all.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+#include "nsss-switch-internal.h"
+#include "nsss-all-internal.h"
+
+int nsss_all_getgrent_r (struct group *gr, char *buf, size_t buflen, struct group **grp)
+{
+ struct group gr2 ;
+ stralloc sa = STRALLOC_ZERO ;
+ genalloc ga = GENALLOC_ZERO ;
+ int e = errno ;
+ if (nsss_all_errno) goto fallback ;
+ if (!nsss_switch_start(&nsss_switch_here, NSSS_SWITCH_GRP, NSSS_NSSSD_PATH, 0, 0)) goto efallback ;
+ errno = 0 ;
+ if (!nsss_switch_grp_get(&nsss_switch_here, &gr2, &sa, &ga, 0, 0))
+ {
+ *grp = 0 ;
+ if (!errno) errno = ENOENT ;
+ return errno ;
+ }
+ if (!nsss_grp_copy(gr, buf, buflen, &gr2, sa.s, sa.len, genalloc_s(char *, &ga), genalloc_len(char *, &ga)))
+ {
+ stralloc_free(&sa) ;
+ *grp = 0 ;
+ return errno ;
+ }
+ stralloc_free(&sa) ;
+ *grp = gr ;
+ return (errno = e, 0) ;
+
+ efallback:
+ nsss_all_errno = errno ;
+ errno = e ;
+ fallback:
+ return nsss_unix_getgrent_r(gr, buf, buflen, grp) ;
+}
diff --git a/src/libnsss/nsss_all_getgrgid.c b/src/libnsss/nsss_all_getgrgid.c
new file mode 100644
index 0000000..da67518
--- /dev/null
+++ b/src/libnsss/nsss_all_getgrgid.c
@@ -0,0 +1,29 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/genalloc.h>
+#include <nsss/config.h>
+#include <nsss/grp-unix.h>
+#include <nsss/grp-all.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+
+struct group *nsss_all_getgrgid (gid_t gid)
+{
+ nsss_switch_t a = NSSS_SWITCH_ZERO ;
+ int e = errno ;
+ if (!nsss_switch_start(&a, NSSS_SWITCH_GRP, NSSS_NSSSD_PATH, 0, 0)) goto fallback ;
+ nsss_grp_sa_here.len = 0 ;
+ genalloc_setlen(char *, &nsss_grp_ga_here, 0) ;
+ if (!nsss_switch_grp_getbygid(&a, &nsss_grp_here, &nsss_grp_sa_here, &nsss_grp_ga_here, gid, 0, 0))
+ {
+ nsss_switch_end(&a, NSSS_SWITCH_GRP) ;
+ return 0 ;
+ }
+ nsss_switch_end(&a, NSSS_SWITCH_GRP) ;
+ return &nsss_grp_here ;
+
+ fallback:
+ errno = e ;
+ return nsss_unix_getgrgid(gid) ;
+}
diff --git a/src/libnsss/nsss_all_getgrgid_r.c b/src/libnsss/nsss_all_getgrgid_r.c
new file mode 100644
index 0000000..bd48322
--- /dev/null
+++ b/src/libnsss/nsss_all_getgrgid_r.c
@@ -0,0 +1,41 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/genalloc.h>
+#include <nsss/config.h>
+#include <nsss/grp-unix.h>
+#include <nsss/grp-all.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+
+int nsss_all_getgrgid_r (gid_t gid, struct group *gr, char *buf, size_t buflen, struct group **grp)
+{
+ struct group gr2 ;
+ stralloc sa = STRALLOC_ZERO ;
+ genalloc ga = GENALLOC_ZERO ;
+ nsss_switch_t a = NSSS_SWITCH_ZERO ;
+ int e = errno ;
+ if (!nsss_switch_start(&a, NSSS_SWITCH_GRP, NSSS_NSSSD_PATH, 0, 0)) goto fallback ;
+ errno = 0 ;
+ if (!nsss_switch_grp_getbygid(&a, &gr2, &sa, &ga, gid, 0, 0))
+ {
+ nsss_switch_end(&a, NSSS_SWITCH_GRP) ;
+ *grp = 0 ;
+ return errno ? errno : (errno = e, 0) ;
+ }
+ nsss_switch_end(&a, NSSS_SWITCH_GRP) ;
+ if (!nsss_grp_copy(gr, buf, buflen, &gr2, sa.s, sa.len, genalloc_s(char *, &ga), genalloc_len(char *, &ga)))
+ {
+ stralloc_free(&sa) ;
+ *grp = 0 ;
+ return errno ;
+ }
+ stralloc_free(&sa) ;
+ *grp = gr ;
+ return (errno = e, 0) ;
+
+ fallback:
+ errno = e ;
+ return nsss_unix_getgrgid_r(gid, gr, buf, buflen, grp) ;
+}
diff --git a/src/libnsss/nsss_all_getgrnam.c b/src/libnsss/nsss_all_getgrnam.c
new file mode 100644
index 0000000..a729bff
--- /dev/null
+++ b/src/libnsss/nsss_all_getgrnam.c
@@ -0,0 +1,29 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/genalloc.h>
+#include <nsss/config.h>
+#include <nsss/grp-unix.h>
+#include <nsss/grp-all.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+
+struct group *nsss_all_getgrnam (char const *name)
+{
+ nsss_switch_t a = NSSS_SWITCH_ZERO ;
+ int e = errno ;
+ if (!nsss_switch_start(&a, NSSS_SWITCH_GRP, NSSS_NSSSD_PATH, 0, 0)) goto fallback ;
+ nsss_grp_sa_here.len = 0 ;
+ genalloc_setlen(char *, &nsss_grp_ga_here, 0) ;
+ if (!nsss_switch_grp_getbyname(&a, &nsss_grp_here, &nsss_grp_sa_here, &nsss_grp_ga_here, name, 0, 0))
+ {
+ nsss_switch_end(&a, NSSS_SWITCH_GRP) ;
+ return 0 ;
+ }
+ nsss_switch_end(&a, NSSS_SWITCH_GRP) ;
+ return &nsss_grp_here ;
+
+ fallback:
+ errno = e ;
+ return nsss_unix_getgrnam(name) ;
+}
diff --git a/src/libnsss/nsss_all_getgrnam_r.c b/src/libnsss/nsss_all_getgrnam_r.c
new file mode 100644
index 0000000..d129d3c
--- /dev/null
+++ b/src/libnsss/nsss_all_getgrnam_r.c
@@ -0,0 +1,41 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/genalloc.h>
+#include <nsss/config.h>
+#include <nsss/grp-unix.h>
+#include <nsss/grp-all.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+
+int nsss_all_getgrnam_r (char const *name, struct group *gr, char *buf, size_t buflen, struct group **grp)
+{
+ struct group gr2 ;
+ stralloc sa = STRALLOC_ZERO ;
+ genalloc ga = GENALLOC_ZERO ;
+ nsss_switch_t a = NSSS_SWITCH_ZERO ;
+ int e = errno ;
+ if (!nsss_switch_start(&a, NSSS_SWITCH_GRP, NSSS_NSSSD_PATH, 0, 0)) goto fallback ;
+ errno = 0 ;
+ if (!nsss_switch_grp_getbyname(&a, &gr2, &sa, &ga, name, 0, 0))
+ {
+ nsss_switch_end(&a, NSSS_SWITCH_GRP) ;
+ *grp = 0 ;
+ return errno ? errno : (errno = e, 0) ;
+ }
+ nsss_switch_end(&a, NSSS_SWITCH_GRP) ;
+ if (!nsss_grp_copy(gr, buf, buflen, &gr2, sa.s, sa.len, genalloc_s(char *, &ga), genalloc_len(char *, &ga)))
+ {
+ stralloc_free(&sa) ;
+ *grp = 0 ;
+ return errno ;
+ }
+ stralloc_free(&sa) ;
+ *grp = gr ;
+ return (errno = e, 0) ;
+
+ fallback:
+ errno = e ;
+ return nsss_unix_getgrnam_r(name, gr, buf, buflen, grp) ;
+}
diff --git a/src/libnsss/nsss_all_getpwent.c b/src/libnsss/nsss_all_getpwent.c
new file mode 100644
index 0000000..b68a4b3
--- /dev/null
+++ b/src/libnsss/nsss_all_getpwent.c
@@ -0,0 +1,26 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <nsss/config.h>
+#include <nsss/pwd-unix.h>
+#include <nsss/pwd-all.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+#include "nsss-switch-internal.h"
+#include "nsss-all-internal.h"
+
+struct passwd *nsss_all_getpwent (void)
+{
+ int e = errno ;
+ if (nsss_all_errno) goto fallback ;
+ if (!nsss_switch_start(&nsss_switch_here, NSSS_SWITCH_PWD, NSSS_NSSSD_PATH, 0, 0)) goto efallback ;
+ nsss_pwd_sa_here.len = 0 ;
+ if (!nsss_switch_pwd_get(&nsss_switch_here, &nsss_pwd_here, &nsss_pwd_sa_here, 0, 0)) return 0 ;
+ return &nsss_pwd_here ;
+
+ efallback:
+ nsss_all_errno = errno ;
+ errno = e ;
+ fallback:
+ return nsss_unix_getpwent() ;
+}
diff --git a/src/libnsss/nsss_all_getpwent_r.c b/src/libnsss/nsss_all_getpwent_r.c
new file mode 100644
index 0000000..08e69dc
--- /dev/null
+++ b/src/libnsss/nsss_all_getpwent_r.c
@@ -0,0 +1,42 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/stralloc.h>
+#include <nsss/config.h>
+#include <nsss/pwd-unix.h>
+#include <nsss/pwd-all.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+#include "nsss-switch-internal.h"
+#include "nsss-all-internal.h"
+
+int nsss_all_getpwent_r (struct passwd *pw, char *buf, size_t buflen, struct passwd **pwp)
+{
+ struct passwd pw2 ;
+ stralloc sa = STRALLOC_ZERO ;
+ int e = errno ;
+ if (nsss_all_errno) goto fallback ;
+ if (!nsss_switch_start(&nsss_switch_here, NSSS_SWITCH_PWD, NSSS_NSSSD_PATH, 0, 0)) goto efallback ;
+ errno = 0 ;
+ if (!nsss_switch_pwd_get(&nsss_switch_here, &pw2, &sa, 0, 0))
+ {
+ *pwp = 0 ;
+ if (!errno) errno = ENOENT ;
+ return errno ;
+ }
+ if (!nsss_pwd_copy(pw, buf, buflen, &pw2, sa.s, sa.len))
+ {
+ stralloc_free(&sa) ;
+ *pwp = 0 ;
+ return errno ;
+ }
+ stralloc_free(&sa) ;
+ *pwp = pw ;
+ return (errno = e, 0) ;
+
+ efallback:
+ nsss_all_errno = errno ;
+ errno = e ;
+ fallback:
+ return nsss_unix_getpwent_r(pw, buf, buflen, pwp) ;
+}
diff --git a/src/libnsss/nsss_all_getpwnam.c b/src/libnsss/nsss_all_getpwnam.c
new file mode 100644
index 0000000..db855d7
--- /dev/null
+++ b/src/libnsss/nsss_all_getpwnam.c
@@ -0,0 +1,27 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <nsss/config.h>
+#include <nsss/pwd-unix.h>
+#include <nsss/pwd-all.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+
+struct passwd *nsss_all_getpwnam (char const *name)
+{
+ nsss_switch_t a = NSSS_SWITCH_ZERO ;
+ int e = errno ;
+ if (!nsss_switch_start(&a, NSSS_SWITCH_PWD, NSSS_NSSSD_PATH, 0, 0)) goto fallback ;
+ nsss_pwd_sa_here.len = 0 ;
+ if (!nsss_switch_pwd_getbyname(&a, &nsss_pwd_here, &nsss_pwd_sa_here, name, 0, 0))
+ {
+ nsss_switch_end(&a, NSSS_SWITCH_PWD) ;
+ return 0 ;
+ }
+ nsss_switch_end(&a, NSSS_SWITCH_PWD) ;
+ return &nsss_pwd_here ;
+
+ fallback:
+ errno = e ;
+ return nsss_unix_getpwnam(name) ;
+}
diff --git a/src/libnsss/nsss_all_getpwnam_r.c b/src/libnsss/nsss_all_getpwnam_r.c
new file mode 100644
index 0000000..e3169b1
--- /dev/null
+++ b/src/libnsss/nsss_all_getpwnam_r.c
@@ -0,0 +1,39 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/stralloc.h>
+#include <nsss/config.h>
+#include <nsss/pwd-unix.h>
+#include <nsss/pwd-all.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+
+int nsss_all_getpwnam_r (char const *name, struct passwd *pw, char *buf, size_t buflen, struct passwd **pwp)
+{
+ struct passwd pw2 ;
+ stralloc sa = STRALLOC_ZERO ;
+ nsss_switch_t a = NSSS_SWITCH_ZERO ;
+ int e = errno ;
+ if (!nsss_switch_start(&a, NSSS_SWITCH_PWD, NSSS_NSSSD_PATH, 0, 0)) goto fallback ;
+ errno = 0 ;
+ if (!nsss_switch_pwd_getbyname(&a, &pw2, &sa, name, 0, 0))
+ {
+ nsss_switch_end(&a, NSSS_SWITCH_PWD) ;
+ *pwp = 0 ;
+ return errno ? errno : (errno = e, 0) ;
+ }
+ nsss_switch_end(&a, NSSS_SWITCH_PWD) ;
+ if (!nsss_pwd_copy(pw, buf, buflen, &pw2, sa.s, sa.len))
+ {
+ stralloc_free(&sa) ;
+ *pwp = 0 ;
+ return errno ;
+ }
+ stralloc_free(&sa) ;
+ *pwp = pw ;
+ return (errno = e, 0) ;
+
+ fallback:
+ errno = e ;
+ return nsss_unix_getpwnam_r(name, pw, buf, buflen, pwp) ;
+}
diff --git a/src/libnsss/nsss_all_getpwuid.c b/src/libnsss/nsss_all_getpwuid.c
new file mode 100644
index 0000000..26f0e21
--- /dev/null
+++ b/src/libnsss/nsss_all_getpwuid.c
@@ -0,0 +1,27 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <nsss/config.h>
+#include <nsss/pwd-unix.h>
+#include <nsss/pwd-all.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+
+struct passwd *nsss_all_getpwuid (uid_t uid)
+{
+ nsss_switch_t a = NSSS_SWITCH_ZERO ;
+ int e = errno ;
+ if (!nsss_switch_start(&a, NSSS_SWITCH_PWD, NSSS_NSSSD_PATH, 0, 0)) goto fallback ;
+ nsss_pwd_sa_here.len = 0 ;
+ if (!nsss_switch_pwd_getbyuid(&a, &nsss_pwd_here, &nsss_pwd_sa_here, uid, 0, 0))
+ {
+ nsss_switch_end(&a, NSSS_SWITCH_PWD) ;
+ return 0 ;
+ }
+ nsss_switch_end(&a, NSSS_SWITCH_PWD) ;
+ return &nsss_pwd_here ;
+
+ fallback:
+ errno = e ;
+ return nsss_unix_getpwuid(uid) ;
+}
diff --git a/src/libnsss/nsss_all_getpwuid_r.c b/src/libnsss/nsss_all_getpwuid_r.c
new file mode 100644
index 0000000..2da32e1
--- /dev/null
+++ b/src/libnsss/nsss_all_getpwuid_r.c
@@ -0,0 +1,39 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/stralloc.h>
+#include <nsss/config.h>
+#include <nsss/pwd-unix.h>
+#include <nsss/pwd-all.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+
+int nsss_all_getpwuid_r (uid_t uid, struct passwd *pw, char *buf, size_t buflen, struct passwd **pwp)
+{
+ struct passwd pw2 ;
+ stralloc sa = STRALLOC_ZERO ;
+ nsss_switch_t a = NSSS_SWITCH_ZERO ;
+ int e = errno ;
+ if (!nsss_switch_start(&a, NSSS_SWITCH_PWD, NSSS_NSSSD_PATH, 0, 0)) goto fallback ;
+ errno = 0 ;
+ if (!nsss_switch_pwd_getbyuid(&a, &pw2, &sa, uid, 0, 0))
+ {
+ nsss_switch_end(&a, NSSS_SWITCH_PWD) ;
+ *pwp = 0 ;
+ return errno ? errno : (errno = e, 0) ;
+ }
+ nsss_switch_end(&a, NSSS_SWITCH_PWD) ;
+ if (!nsss_pwd_copy(pw, buf, buflen, &pw2, sa.s, sa.len))
+ {
+ stralloc_free(&sa) ;
+ *pwp = 0 ;
+ return errno ;
+ }
+ stralloc_free(&sa) ;
+ *pwp = pw ;
+ return (errno = e, 0) ;
+
+ fallback:
+ errno = e ;
+ return nsss_unix_getpwuid_r(uid, pw, buf, buflen, pwp) ;
+}
diff --git a/src/libnsss/nsss_all_getspent.c b/src/libnsss/nsss_all_getspent.c
new file mode 100644
index 0000000..7ca5048
--- /dev/null
+++ b/src/libnsss/nsss_all_getspent.c
@@ -0,0 +1,26 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <nsss/config.h>
+#include <nsss/shadow-unix.h>
+#include <nsss/shadow-all.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+#include "nsss-switch-internal.h"
+#include "nsss-all-internal.h"
+
+struct spwd *nsss_all_getspent (void)
+{
+ int e = errno ;
+ if (nsss_all_errno) goto fallback ;
+ if (!nsss_switch_start(&nsss_switch_here, NSSS_SWITCH_SHADOW, NSSS_NSSSD_PATH, 0, 0)) goto efallback ;
+ nsss_shadow_sa_here.len = 0 ;
+ if (!nsss_switch_shadow_get(&nsss_switch_here, &nsss_shadow_here, &nsss_shadow_sa_here, 0, 0)) return 0 ;
+ return &nsss_shadow_here ;
+
+ efallback:
+ nsss_all_errno = errno ;
+ errno = e ;
+ fallback:
+ return nsss_unix_getspent() ;
+}
diff --git a/src/libnsss/nsss_all_getspent_r.c b/src/libnsss/nsss_all_getspent_r.c
new file mode 100644
index 0000000..ab3e531
--- /dev/null
+++ b/src/libnsss/nsss_all_getspent_r.c
@@ -0,0 +1,42 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/stralloc.h>
+#include <nsss/config.h>
+#include <nsss/shadow-unix.h>
+#include <nsss/shadow-all.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+#include "nsss-switch-internal.h"
+#include "nsss-all-internal.h"
+
+int nsss_all_getspent_r (struct spwd *sp, char *buf, size_t buflen, struct spwd **spp)
+{
+ struct spwd sp2 ;
+ stralloc sa = STRALLOC_ZERO ;
+ int e = errno ;
+ if (nsss_all_errno) goto fallback ;
+ if (!nsss_switch_start(&nsss_switch_here, NSSS_SWITCH_SHADOW, NSSS_NSSSD_PATH, 0, 0)) goto efallback ;
+ errno = 0 ;
+ if (!nsss_switch_shadow_get(&nsss_switch_here, &sp2, &sa, 0, 0))
+ {
+ *spp = 0 ;
+ if (!errno) errno = ENOENT ;
+ return errno ;
+ }
+ if (!nsss_shadow_copy(sp, buf, buflen, &sp2, sa.s, sa.len))
+ {
+ stralloc_free(&sa) ;
+ *spp = 0 ;
+ return errno ;
+ }
+ stralloc_free(&sa) ;
+ *spp = sp ;
+ return (errno = e, 0) ;
+
+ efallback:
+ nsss_all_errno = errno ;
+ errno = e ;
+ fallback:
+ return nsss_unix_getspent_r(sp, buf, buflen, spp) ;
+}
diff --git a/src/libnsss/nsss_all_getspnam.c b/src/libnsss/nsss_all_getspnam.c
new file mode 100644
index 0000000..040d5e4
--- /dev/null
+++ b/src/libnsss/nsss_all_getspnam.c
@@ -0,0 +1,27 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <nsss/config.h>
+#include <nsss/shadow-unix.h>
+#include <nsss/shadow-all.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+
+struct spwd *nsss_all_getspnam (char const *name)
+{
+ nsss_switch_t a = NSSS_SWITCH_ZERO ;
+ int e = errno ;
+ if (!nsss_switch_start(&a, NSSS_SWITCH_SHADOW, NSSS_NSSSD_PATH, 0, 0)) goto fallback ;
+ nsss_shadow_sa_here.len = 0 ;
+ if (!nsss_switch_shadow_getbyname(&a, &nsss_shadow_here, &nsss_shadow_sa_here, name, 0, 0))
+ {
+ nsss_switch_end(&a, NSSS_SWITCH_SHADOW) ;
+ return 0 ;
+ }
+ nsss_switch_end(&a, NSSS_SWITCH_SHADOW) ;
+ return &nsss_shadow_here ;
+
+ fallback:
+ errno = e ;
+ return nsss_unix_getspnam(name) ;
+}
diff --git a/src/libnsss/nsss_all_getspnam_r.c b/src/libnsss/nsss_all_getspnam_r.c
new file mode 100644
index 0000000..0cee461
--- /dev/null
+++ b/src/libnsss/nsss_all_getspnam_r.c
@@ -0,0 +1,39 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/stralloc.h>
+#include <nsss/config.h>
+#include <nsss/shadow-unix.h>
+#include <nsss/shadow-all.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+
+int nsss_all_getspnam_r (char const *name, struct spwd *sp, char *buf, size_t buflen, struct spwd **spp)
+{
+ struct spwd sp2 ;
+ stralloc sa = STRALLOC_ZERO ;
+ nsss_switch_t a = NSSS_SWITCH_ZERO ;
+ int e = errno ;
+ if (!nsss_switch_start(&a, NSSS_SWITCH_SHADOW, NSSS_NSSSD_PATH, 0, 0)) goto fallback ;
+ errno = 0 ;
+ if (!nsss_switch_shadow_getbyname(&a, &sp2, &sa, name, 0, 0))
+ {
+ nsss_switch_end(&a, NSSS_SWITCH_SHADOW) ;
+ *spp = 0 ;
+ return errno ? errno : (errno = e, 0) ;
+ }
+ nsss_switch_end(&a, NSSS_SWITCH_SHADOW) ;
+ if (!nsss_shadow_copy(sp, buf, buflen, &sp2, sa.s, sa.len))
+ {
+ stralloc_free(&sa) ;
+ *spp = 0 ;
+ return errno ;
+ }
+ stralloc_free(&sa) ;
+ *spp = sp ;
+ return (errno = e, 0) ;
+
+ fallback:
+ errno = e ;
+ return nsss_unix_getspnam_r(name, sp, buf, buflen, spp) ;
+}
diff --git a/src/libnsss/nsss_all_setgrent.c b/src/libnsss/nsss_all_setgrent.c
new file mode 100644
index 0000000..78fee56
--- /dev/null
+++ b/src/libnsss/nsss_all_setgrent.c
@@ -0,0 +1,22 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <nsss/config.h>
+#include <nsss/grp-unix.h>
+#include <nsss/grp-all.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-switch-internal.h"
+#include "nsss-all-internal.h"
+
+void nsss_all_setgrent (void)
+{
+ int e = errno ;
+ if (!nsss_switch_start(&nsss_switch_here, NSSS_SWITCH_GRP, NSSS_NSSSD_PATH, 0, 0)) goto fallback ;
+ nsss_switch_grp_rewind(&nsss_switch_here, 0, 0) ;
+ return ;
+
+ fallback:
+ nsss_all_errno = errno ;
+ errno = e ;
+ nsss_unix_setgrent() ;
+}
diff --git a/src/libnsss/nsss_all_setpwent.c b/src/libnsss/nsss_all_setpwent.c
new file mode 100644
index 0000000..e22411a
--- /dev/null
+++ b/src/libnsss/nsss_all_setpwent.c
@@ -0,0 +1,22 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <nsss/config.h>
+#include <nsss/pwd-unix.h>
+#include <nsss/pwd-all.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-switch-internal.h"
+#include "nsss-all-internal.h"
+
+void nsss_all_setpwent (void)
+{
+ int e = errno ;
+ if (!nsss_switch_start(&nsss_switch_here, NSSS_SWITCH_PWD, NSSS_NSSSD_PATH, 0, 0)) goto fallback ;
+ nsss_switch_pwd_rewind(&nsss_switch_here, 0, 0) ;
+ return ;
+
+ fallback:
+ nsss_all_errno = errno ;
+ errno = e ;
+ nsss_unix_setpwent() ;
+}
diff --git a/src/libnsss/nsss_all_setspent.c b/src/libnsss/nsss_all_setspent.c
new file mode 100644
index 0000000..ab6c456
--- /dev/null
+++ b/src/libnsss/nsss_all_setspent.c
@@ -0,0 +1,22 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <nsss/config.h>
+#include <nsss/shadow-unix.h>
+#include <nsss/shadow-all.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-switch-internal.h"
+#include "nsss-all-internal.h"
+
+void nsss_all_setspent (void)
+{
+ int e = errno ;
+ if (!nsss_switch_start(&nsss_switch_here, NSSS_SWITCH_SHADOW, NSSS_NSSSD_PATH, 0, 0)) goto fallback ;
+ nsss_switch_shadow_rewind(&nsss_switch_here, 0, 0) ;
+ return ;
+
+ fallback:
+ nsss_all_errno = errno ;
+ errno = e ;
+ nsss_unix_setspent() ;
+}
diff --git a/src/libnsss/nsss_grp_copy.c b/src/libnsss/nsss_grp_copy.c
new file mode 100644
index 0000000..684996e
--- /dev/null
+++ b/src/libnsss/nsss_grp_copy.c
@@ -0,0 +1,27 @@
+/* ISC license. */
+
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include "nsss-internal.h"
+
+int nsss_grp_copy (struct group *gr, char *buf, size_t buflen, struct group const *gr2, char const *s, size_t len, char *const *p, size_t n)
+{
+ char **q ;
+ size_t offset = (uintptr_t)buf % 16 ;
+ offset = offset ? 16 - offset : 0 ;
+ if (buflen < offset) return (errno = ERANGE, 0) ;
+ buf += offset ; buflen -= offset ;
+ offset = (n+1) * sizeof(char *) ;
+ if (buflen < offset || buflen - offset < len) return (errno = ERANGE, 0) ;
+ q = (char **)buf ;
+ gr->gr_mem = q ;
+ buf += offset ;
+ memcpy(buf, s, len) ;
+ for (size_t i = 0 ; i < n ; i++) q[i] = buf + (p[i] - s) ;
+ q[n] = 0 ;
+ gr->gr_name = buf + (gr2->gr_name - s) ;
+ gr->gr_passwd = buf + (gr2->gr_passwd - s) ;
+ gr->gr_gid = gr2->gr_gid ;
+ return 1 ;
+}
diff --git a/src/libnsss/nsss_grp_here.c b/src/libnsss/nsss_grp_here.c
new file mode 100644
index 0000000..9b64ffd
--- /dev/null
+++ b/src/libnsss/nsss_grp_here.c
@@ -0,0 +1,10 @@
+/* ISC license. */
+
+#include <skalibs/stralloc.h>
+#include <skalibs/genalloc.h>
+#include <nsss/grp-def.h>
+#include "nsss-internal.h"
+
+struct group nsss_grp_here ;
+stralloc nsss_grp_sa_here = STRALLOC_ZERO ;
+genalloc nsss_grp_ga_here = GENALLOC_ZERO ;
diff --git a/src/libnsss/nsss_pwd_copy.c b/src/libnsss/nsss_pwd_copy.c
new file mode 100644
index 0000000..e163cf2
--- /dev/null
+++ b/src/libnsss/nsss_pwd_copy.c
@@ -0,0 +1,19 @@
+/* ISC license. */
+
+#include <string.h>
+#include <errno.h>
+#include "nsss-internal.h"
+
+int nsss_pwd_copy (struct passwd *pw, char *buf, size_t buflen, struct passwd const *pw2, char const *s, size_t len)
+{
+ if (len > buflen) return (errno = ERANGE, 0) ;
+ memcpy(buf, s, len) ;
+ pw->pw_name = buf + (pw2->pw_name - s) ;
+ pw->pw_passwd = buf + (pw2->pw_passwd - s) ;
+ pw->pw_uid = pw2->pw_uid ;
+ pw->pw_gid = pw2->pw_gid ;
+ pw->pw_gecos = buf + (pw2->pw_gecos - s) ;
+ pw->pw_dir = buf + (pw2->pw_dir - s) ;
+ pw->pw_shell = buf + (pw2->pw_shell - s) ;
+ return 1 ;
+}
diff --git a/src/libnsss/nsss_pwd_here.c b/src/libnsss/nsss_pwd_here.c
new file mode 100644
index 0000000..fdb95a4
--- /dev/null
+++ b/src/libnsss/nsss_pwd_here.c
@@ -0,0 +1,8 @@
+/* ISC license. */
+
+#include <skalibs/stralloc.h>
+#include <nsss/pwd-def.h>
+#include "nsss-internal.h"
+
+struct passwd nsss_pwd_here ;
+stralloc nsss_pwd_sa_here = STRALLOC_ZERO ;
diff --git a/src/libnsss/nsss_shadow_copy.c b/src/libnsss/nsss_shadow_copy.c
new file mode 100644
index 0000000..bb629db
--- /dev/null
+++ b/src/libnsss/nsss_shadow_copy.c
@@ -0,0 +1,21 @@
+/* ISC license. */
+
+#include <string.h>
+#include <errno.h>
+#include "nsss-internal.h"
+
+int nsss_shadow_copy (struct spwd *sp, char *buf, size_t buflen, struct spwd const *sp2, char const *s, size_t len)
+{
+ if (len > buflen) return (errno = ERANGE, 0) ;
+ memcpy(buf, s, len) ;
+ sp->sp_namp = buf + (sp2->sp_namp - s) ;
+ sp->sp_pwdp = buf + (sp2->sp_pwdp - s) ;
+ sp->sp_lstchg = sp2->sp_lstchg ;
+ sp->sp_min = sp2->sp_min ;
+ sp->sp_max = sp2->sp_max ;
+ sp->sp_warn = sp2->sp_warn ;
+ sp->sp_inact = sp2->sp_inact ;
+ sp->sp_expire = sp2->sp_expire ;
+ sp->sp_flag = sp2->sp_flag ;
+ return 1 ;
+}
diff --git a/src/libnsss/nsss_shadow_here.c b/src/libnsss/nsss_shadow_here.c
new file mode 100644
index 0000000..ecf83c9
--- /dev/null
+++ b/src/libnsss/nsss_shadow_here.c
@@ -0,0 +1,8 @@
+/* ISC license. */
+
+#include <skalibs/stralloc.h>
+#include <nsss/shadow-def.h>
+#include "nsss-internal.h"
+
+struct spwd nsss_shadow_here ;
+stralloc nsss_shadow_sa_here = STRALLOC_ZERO ;
diff --git a/src/libnsss/nsss_switch_end.c b/src/libnsss/nsss_switch_end.c
new file mode 100644
index 0000000..3922721
--- /dev/null
+++ b/src/libnsss/nsss_switch_end.c
@@ -0,0 +1,17 @@
+/* ISC license. */
+
+#include <skalibs/buffer.h>
+#include <skalibs/djbunix.h>
+#include <nsss/nsss-switch.h>
+
+static inline void nsss_switch_disconnect (nsss_switch_t *a)
+{
+ fd_close(buffer_fd(&a->b)) ;
+ a->b.fd = -1 ;
+}
+
+void nsss_switch_end (nsss_switch_t *a, unsigned int what)
+{
+ a->held &= ~(1U << what) ;
+ if (!a->held) nsss_switch_disconnect(a) ;
+}
diff --git a/src/libnsss/nsss_switch_endgrent.c b/src/libnsss/nsss_switch_endgrent.c
new file mode 100644
index 0000000..8ae43ea
--- /dev/null
+++ b/src/libnsss/nsss_switch_endgrent.c
@@ -0,0 +1,10 @@
+/* ISC license. */
+
+#include <nsss/grp-switch.h>
+#include "nsss-switch-internal.h"
+
+void nsss_switch_endgrent (void)
+{
+ nsss_switch_grp_end(&nsss_switch_here, 0, 0) ;
+ nsss_switch_end(&nsss_switch_here, NSSS_SWITCH_GRP) ;
+}
diff --git a/src/libnsss/nsss_switch_endpwent.c b/src/libnsss/nsss_switch_endpwent.c
new file mode 100644
index 0000000..8dbec92
--- /dev/null
+++ b/src/libnsss/nsss_switch_endpwent.c
@@ -0,0 +1,10 @@
+/* ISC license. */
+
+#include <nsss/pwd-switch.h>
+#include "nsss-switch-internal.h"
+
+void nsss_switch_endpwent (void)
+{
+ nsss_switch_pwd_end(&nsss_switch_here, 0, 0) ;
+ nsss_switch_end(&nsss_switch_here, NSSS_SWITCH_PWD) ;
+}
diff --git a/src/libnsss/nsss_switch_endspent.c b/src/libnsss/nsss_switch_endspent.c
new file mode 100644
index 0000000..8527072
--- /dev/null
+++ b/src/libnsss/nsss_switch_endspent.c
@@ -0,0 +1,10 @@
+/* ISC license. */
+
+#include <nsss/shadow-switch.h>
+#include "nsss-switch-internal.h"
+
+void nsss_switch_endspent (void)
+{
+ nsss_switch_shadow_end(&nsss_switch_here, 0, 0) ;
+ nsss_switch_end(&nsss_switch_here, NSSS_SWITCH_SHADOW) ;
+}
diff --git a/src/libnsss/nsss_switch_getgrent.c b/src/libnsss/nsss_switch_getgrent.c
new file mode 100644
index 0000000..6a6c8dc
--- /dev/null
+++ b/src/libnsss/nsss_switch_getgrent.c
@@ -0,0 +1,17 @@
+/* ISC license. */
+
+#include <skalibs/genalloc.h>
+#include <nsss/config.h>
+#include <nsss/grp-switch.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+#include "nsss-switch-internal.h"
+
+struct group *nsss_switch_getgrent (void)
+{
+ if (!nsss_switch_start(&nsss_switch_here, NSSS_SWITCH_GRP, NSSS_NSSSD_PATH, 0, 0)) return 0 ;
+ nsss_grp_sa_here.len = 0 ;
+ genalloc_setlen(char *, &nsss_grp_ga_here, 0) ;
+ if (!nsss_switch_grp_get(&nsss_switch_here, &nsss_grp_here, &nsss_grp_sa_here, &nsss_grp_ga_here, 0, 0)) return 0 ;
+ return &nsss_grp_here ;
+}
diff --git a/src/libnsss/nsss_switch_getgrent_r.c b/src/libnsss/nsss_switch_getgrent_r.c
new file mode 100644
index 0000000..97a7bbd
--- /dev/null
+++ b/src/libnsss/nsss_switch_getgrent_r.c
@@ -0,0 +1,36 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/genalloc.h>
+#include <nsss/config.h>
+#include <nsss/grp-switch.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+#include "nsss-switch-internal.h"
+
+int nsss_switch_getgrent_r (struct group *gr, char *buf, size_t buflen, struct group **grp)
+{
+ struct group gr2 ;
+ stralloc sa = STRALLOC_ZERO ;
+ genalloc ga = GENALLOC_ZERO ;
+ int e ;
+ if (!nsss_switch_start(&nsss_switch_here, NSSS_SWITCH_GRP, NSSS_NSSSD_PATH, 0, 0)) return errno ;
+ e = errno ;
+ errno = 0 ;
+ if (!nsss_switch_grp_get(&nsss_switch_here, &gr2, &sa, &ga, 0, 0))
+ {
+ *grp = 0 ;
+ if (!errno) errno = ENOENT ;
+ return errno ;
+ }
+ if (!nsss_grp_copy(gr, buf, buflen, &gr2, sa.s, sa.len, genalloc_s(char *, &ga), genalloc_len(char *, &ga)))
+ {
+ stralloc_free(&sa) ;
+ *grp = 0 ;
+ return errno ;
+ }
+ stralloc_free(&sa) ;
+ *grp = gr ;
+ return (errno = e, 0) ;
+}
diff --git a/src/libnsss/nsss_switch_getgrgid.c b/src/libnsss/nsss_switch_getgrgid.c
new file mode 100644
index 0000000..65dbeef
--- /dev/null
+++ b/src/libnsss/nsss_switch_getgrgid.c
@@ -0,0 +1,22 @@
+/* ISC license. */
+
+#include <skalibs/genalloc.h>
+#include <nsss/config.h>
+#include <nsss/grp-switch.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+
+struct group *nsss_switch_getgrgid (gid_t gid)
+{
+ nsss_switch_t a = NSSS_SWITCH_ZERO ;
+ if (!nsss_switch_start(&a, NSSS_SWITCH_GRP, NSSS_NSSSD_PATH, 0, 0)) return 0 ;
+ nsss_grp_sa_here.len = 0 ;
+ genalloc_setlen(char *, &nsss_grp_ga_here, 0) ;
+ if (!nsss_switch_grp_getbygid(&a, &nsss_grp_here, &nsss_grp_sa_here, &nsss_grp_ga_here, gid, 0, 0))
+ {
+ nsss_switch_end(&a, NSSS_SWITCH_GRP) ;
+ return 0 ;
+ }
+ nsss_switch_end(&a, NSSS_SWITCH_GRP) ;
+ return &nsss_grp_here ;
+}
diff --git a/src/libnsss/nsss_switch_getgrgid_r.c b/src/libnsss/nsss_switch_getgrgid_r.c
new file mode 100644
index 0000000..c87b57d
--- /dev/null
+++ b/src/libnsss/nsss_switch_getgrgid_r.c
@@ -0,0 +1,36 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/genalloc.h>
+#include <nsss/config.h>
+#include <nsss/grp-switch.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+
+int nsss_switch_getgrgid_r (gid_t gid, struct group *gr, char *buf, size_t buflen, struct group **grp)
+{
+ struct group gr2 ;
+ stralloc sa = STRALLOC_ZERO ;
+ genalloc ga = GENALLOC_ZERO ;
+ nsss_switch_t a = NSSS_SWITCH_ZERO ;
+ int e = errno ;
+ if (!nsss_switch_start(&a, NSSS_SWITCH_GRP, NSSS_NSSSD_PATH, 0, 0)) return errno ;
+ errno = 0 ;
+ if (!nsss_switch_grp_getbygid(&a, &gr2, &sa, &ga, gid, 0, 0))
+ {
+ nsss_switch_end(&a, NSSS_SWITCH_GRP) ;
+ *grp = 0 ;
+ return errno ? errno : (errno = e, 0) ;
+ }
+ nsss_switch_end(&a, NSSS_SWITCH_GRP) ;
+ if (!nsss_grp_copy(gr, buf, buflen, &gr2, sa.s, sa.len, genalloc_s(char *, &ga), genalloc_len(char *, &ga)))
+ {
+ stralloc_free(&sa) ;
+ *grp = 0 ;
+ return errno ;
+ }
+ stralloc_free(&sa) ;
+ *grp = gr ;
+ return (errno = e, 0) ;
+}
diff --git a/src/libnsss/nsss_switch_getgrnam.c b/src/libnsss/nsss_switch_getgrnam.c
new file mode 100644
index 0000000..396f44e
--- /dev/null
+++ b/src/libnsss/nsss_switch_getgrnam.c
@@ -0,0 +1,22 @@
+/* ISC license. */
+
+#include <skalibs/genalloc.h>
+#include <nsss/config.h>
+#include <nsss/grp-switch.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+
+struct group *nsss_switch_getgrnam (char const *name)
+{
+ nsss_switch_t a = NSSS_SWITCH_ZERO ;
+ if (!nsss_switch_start(&a, NSSS_SWITCH_GRP, NSSS_NSSSD_PATH, 0, 0)) return 0 ;
+ nsss_grp_sa_here.len = 0 ;
+ genalloc_setlen(char *, &nsss_grp_ga_here, 0) ;
+ if (!nsss_switch_grp_getbyname(&a, &nsss_grp_here, &nsss_grp_sa_here, &nsss_grp_ga_here, name, 0, 0))
+ {
+ nsss_switch_end(&a, NSSS_SWITCH_GRP) ;
+ return 0 ;
+ }
+ nsss_switch_end(&a, NSSS_SWITCH_GRP) ;
+ return &nsss_grp_here ;
+}
diff --git a/src/libnsss/nsss_switch_getgrnam_r.c b/src/libnsss/nsss_switch_getgrnam_r.c
new file mode 100644
index 0000000..e6d00ec
--- /dev/null
+++ b/src/libnsss/nsss_switch_getgrnam_r.c
@@ -0,0 +1,36 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/genalloc.h>
+#include <nsss/config.h>
+#include <nsss/grp-switch.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+
+int nsss_switch_getgrnam_r (char const *name, struct group *gr, char *buf, size_t buflen, struct group **grp)
+{
+ struct group gr2 ;
+ stralloc sa = STRALLOC_ZERO ;
+ genalloc ga = GENALLOC_ZERO ;
+ nsss_switch_t a = NSSS_SWITCH_ZERO ;
+ int e = errno ;
+ if (!nsss_switch_start(&a, NSSS_SWITCH_GRP, NSSS_NSSSD_PATH, 0, 0)) return errno ;
+ errno = 0 ;
+ if (!nsss_switch_grp_getbyname(&a, &gr2, &sa, &ga, name, 0, 0))
+ {
+ nsss_switch_end(&a, NSSS_SWITCH_GRP) ;
+ *grp = 0 ;
+ return errno ? errno : (errno = e, 0) ;
+ }
+ nsss_switch_end(&a, NSSS_SWITCH_GRP) ;
+ if (!nsss_grp_copy(gr, buf, buflen, &gr2, sa.s, sa.len, genalloc_s(char *, &ga), genalloc_len(char *, &ga)))
+ {
+ stralloc_free(&sa) ;
+ *grp = 0 ;
+ return errno ;
+ }
+ stralloc_free(&sa) ;
+ *grp = gr ;
+ return (errno = e, 0) ;
+}
diff --git a/src/libnsss/nsss_switch_getpwent.c b/src/libnsss/nsss_switch_getpwent.c
new file mode 100644
index 0000000..89cabfd
--- /dev/null
+++ b/src/libnsss/nsss_switch_getpwent.c
@@ -0,0 +1,15 @@
+/* ISC license. */
+
+#include <nsss/config.h>
+#include <nsss/pwd-switch.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+#include "nsss-switch-internal.h"
+
+struct passwd *nsss_switch_getpwent (void)
+{
+ if (!nsss_switch_start(&nsss_switch_here, NSSS_SWITCH_PWD, NSSS_NSSSD_PATH, 0, 0)) return 0 ;
+ nsss_pwd_sa_here.len = 0 ;
+ if (!nsss_switch_pwd_get(&nsss_switch_here, &nsss_pwd_here, &nsss_pwd_sa_here, 0, 0)) return 0 ;
+ return &nsss_pwd_here ;
+}
diff --git a/src/libnsss/nsss_switch_getpwent_r.c b/src/libnsss/nsss_switch_getpwent_r.c
new file mode 100644
index 0000000..7795af0
--- /dev/null
+++ b/src/libnsss/nsss_switch_getpwent_r.c
@@ -0,0 +1,34 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/stralloc.h>
+#include <nsss/config.h>
+#include <nsss/pwd-switch.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+#include "nsss-switch-internal.h"
+
+int nsss_switch_getpwent_r (struct passwd *pw, char *buf, size_t buflen, struct passwd **pwp)
+{
+ struct passwd pw2 ;
+ stralloc sa = STRALLOC_ZERO ;
+ int e ;
+ if (!nsss_switch_start(&nsss_switch_here, NSSS_SWITCH_PWD, NSSS_NSSSD_PATH, 0, 0)) return errno ;
+ e = errno ;
+ errno = 0 ;
+ if (!nsss_switch_pwd_get(&nsss_switch_here, &pw2, &sa, 0, 0))
+ {
+ *pwp = 0 ;
+ if (!errno) errno = ENOENT ;
+ return errno ;
+ }
+ if (!nsss_pwd_copy(pw, buf, buflen, &pw2, sa.s, sa.len))
+ {
+ stralloc_free(&sa) ;
+ *pwp = 0 ;
+ return errno ;
+ }
+ stralloc_free(&sa) ;
+ *pwp = pw ;
+ return (errno = e, 0) ;
+}
diff --git a/src/libnsss/nsss_switch_getpwnam.c b/src/libnsss/nsss_switch_getpwnam.c
new file mode 100644
index 0000000..393503d
--- /dev/null
+++ b/src/libnsss/nsss_switch_getpwnam.c
@@ -0,0 +1,20 @@
+/* ISC license. */
+
+#include <nsss/config.h>
+#include <nsss/pwd-switch.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+
+struct passwd *nsss_switch_getpwnam (char const *name)
+{
+ nsss_switch_t a = NSSS_SWITCH_ZERO ;
+ if (!nsss_switch_start(&a, NSSS_SWITCH_PWD, NSSS_NSSSD_PATH, 0, 0)) return 0 ;
+ nsss_pwd_sa_here.len = 0 ;
+ if (!nsss_switch_pwd_getbyname(&a, &nsss_pwd_here, &nsss_pwd_sa_here, name, 0, 0))
+ {
+ nsss_switch_end(&a, NSSS_SWITCH_PWD) ;
+ return 0 ;
+ }
+ nsss_switch_end(&a, NSSS_SWITCH_PWD) ;
+ return &nsss_pwd_here ;
+}
diff --git a/src/libnsss/nsss_switch_getpwnam_r.c b/src/libnsss/nsss_switch_getpwnam_r.c
new file mode 100644
index 0000000..e1c1e71
--- /dev/null
+++ b/src/libnsss/nsss_switch_getpwnam_r.c
@@ -0,0 +1,34 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/stralloc.h>
+#include <nsss/config.h>
+#include <nsss/pwd-switch.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+
+int nsss_switch_getpwnam_r (char const *name, struct passwd *pw, char *buf, size_t buflen, struct passwd **pwp)
+{
+ struct passwd pw2 ;
+ stralloc sa = STRALLOC_ZERO ;
+ nsss_switch_t a = NSSS_SWITCH_ZERO ;
+ int e = errno ;
+ if (!nsss_switch_start(&a, NSSS_SWITCH_PWD, NSSS_NSSSD_PATH, 0, 0)) return errno ;
+ errno = 0 ;
+ if (!nsss_switch_pwd_getbyname(&a, &pw2, &sa, name, 0, 0))
+ {
+ nsss_switch_end(&a, NSSS_SWITCH_PWD) ;
+ *pwp = 0 ;
+ return errno ? errno : (errno = e, 0) ;
+ }
+ nsss_switch_end(&a, NSSS_SWITCH_PWD) ;
+ if (!nsss_pwd_copy(pw, buf, buflen, &pw2, sa.s, sa.len))
+ {
+ stralloc_free(&sa) ;
+ *pwp = 0 ;
+ return errno ;
+ }
+ stralloc_free(&sa) ;
+ *pwp = pw ;
+ return (errno = e, 0) ;
+}
diff --git a/src/libnsss/nsss_switch_getpwuid.c b/src/libnsss/nsss_switch_getpwuid.c
new file mode 100644
index 0000000..3d765bf
--- /dev/null
+++ b/src/libnsss/nsss_switch_getpwuid.c
@@ -0,0 +1,20 @@
+/* ISC license. */
+
+#include <nsss/config.h>
+#include <nsss/pwd-switch.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+
+struct passwd *nsss_switch_getpwuid (uid_t uid)
+{
+ nsss_switch_t a = NSSS_SWITCH_ZERO ;
+ if (!nsss_switch_start(&a, NSSS_SWITCH_PWD, NSSS_NSSSD_PATH, 0, 0)) return 0 ;
+ nsss_pwd_sa_here.len = 0 ;
+ if (!nsss_switch_pwd_getbyuid(&a, &nsss_pwd_here, &nsss_pwd_sa_here, uid, 0, 0))
+ {
+ nsss_switch_end(&a, NSSS_SWITCH_PWD) ;
+ return 0 ;
+ }
+ nsss_switch_end(&a, NSSS_SWITCH_PWD) ;
+ return &nsss_pwd_here ;
+}
diff --git a/src/libnsss/nsss_switch_getpwuid_r.c b/src/libnsss/nsss_switch_getpwuid_r.c
new file mode 100644
index 0000000..8e63a75
--- /dev/null
+++ b/src/libnsss/nsss_switch_getpwuid_r.c
@@ -0,0 +1,34 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/stralloc.h>
+#include <nsss/config.h>
+#include <nsss/pwd-switch.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+
+int nsss_switch_getpwuid_r (uid_t uid, struct passwd *pw, char *buf, size_t buflen, struct passwd **pwp)
+{
+ struct passwd pw2 ;
+ stralloc sa = STRALLOC_ZERO ;
+ nsss_switch_t a = NSSS_SWITCH_ZERO ;
+ int e = errno ;
+ if (!nsss_switch_start(&a, NSSS_SWITCH_PWD, NSSS_NSSSD_PATH, 0, 0)) return errno ;
+ errno = 0 ;
+ if (!nsss_switch_pwd_getbyuid(&a, &pw2, &sa, uid, 0, 0))
+ {
+ nsss_switch_end(&a, NSSS_SWITCH_PWD) ;
+ *pwp = 0 ;
+ return errno ? errno : (errno = e, 0) ;
+ }
+ nsss_switch_end(&a, NSSS_SWITCH_PWD) ;
+ if (!nsss_pwd_copy(pw, buf, buflen, &pw2, sa.s, sa.len))
+ {
+ stralloc_free(&sa) ;
+ *pwp = 0 ;
+ return errno ;
+ }
+ stralloc_free(&sa) ;
+ *pwp = pw ;
+ return (errno = e, 0) ;
+}
diff --git a/src/libnsss/nsss_switch_getspent.c b/src/libnsss/nsss_switch_getspent.c
new file mode 100644
index 0000000..65064a1
--- /dev/null
+++ b/src/libnsss/nsss_switch_getspent.c
@@ -0,0 +1,15 @@
+/* ISC license. */
+
+#include <nsss/config.h>
+#include <nsss/shadow-switch.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+#include "nsss-switch-internal.h"
+
+struct spwd *nsss_switch_getspent (void)
+{
+ if (!nsss_switch_start(&nsss_switch_here, NSSS_SWITCH_SHADOW, NSSS_NSSSD_PATH, 0, 0)) return 0 ;
+ nsss_shadow_sa_here.len = 0 ;
+ if (!nsss_switch_shadow_get(&nsss_switch_here, &nsss_shadow_here, &nsss_shadow_sa_here, 0, 0)) return 0 ;
+ return &nsss_shadow_here ;
+}
diff --git a/src/libnsss/nsss_switch_getspent_r.c b/src/libnsss/nsss_switch_getspent_r.c
new file mode 100644
index 0000000..118e095
--- /dev/null
+++ b/src/libnsss/nsss_switch_getspent_r.c
@@ -0,0 +1,34 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/stralloc.h>
+#include <nsss/config.h>
+#include <nsss/shadow-switch.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+#include "nsss-switch-internal.h"
+
+int nsss_switch_getspent_r (struct spwd *sp, char *buf, size_t buflen, struct spwd **spp)
+{
+ struct spwd sp2 ;
+ stralloc sa = STRALLOC_ZERO ;
+ int e ;
+ if (!nsss_switch_start(&nsss_switch_here, NSSS_SWITCH_SHADOW, NSSS_NSSSD_PATH, 0, 0)) return errno ;
+ e = errno ;
+ errno = 0 ;
+ if (!nsss_switch_shadow_get(&nsss_switch_here, &sp2, &sa, 0, 0))
+ {
+ *spp = 0 ;
+ if (!errno) errno = ENOENT ;
+ return errno ;
+ }
+ if (!nsss_shadow_copy(sp, buf, buflen, &sp2, sa.s, sa.len))
+ {
+ stralloc_free(&sa) ;
+ *spp = 0 ;
+ return errno ;
+ }
+ stralloc_free(&sa) ;
+ *spp = sp ;
+ return (errno = e, 0) ;
+}
diff --git a/src/libnsss/nsss_switch_getspnam.c b/src/libnsss/nsss_switch_getspnam.c
new file mode 100644
index 0000000..01184ec
--- /dev/null
+++ b/src/libnsss/nsss_switch_getspnam.c
@@ -0,0 +1,20 @@
+/* ISC license. */
+
+#include <nsss/config.h>
+#include <nsss/shadow-switch.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+
+struct spwd *nsss_switch_getspnam (char const *name)
+{
+ nsss_switch_t a = NSSS_SWITCH_ZERO ;
+ if (!nsss_switch_start(&a, NSSS_SWITCH_SHADOW, NSSS_NSSSD_PATH, 0, 0)) return 0 ;
+ nsss_shadow_sa_here.len = 0 ;
+ if (!nsss_switch_shadow_getbyname(&a, &nsss_shadow_here, &nsss_shadow_sa_here, name, 0, 0))
+ {
+ nsss_switch_end(&a, NSSS_SWITCH_SHADOW) ;
+ return 0 ;
+ }
+ nsss_switch_end(&a, NSSS_SWITCH_SHADOW) ;
+ return &nsss_shadow_here ;
+}
diff --git a/src/libnsss/nsss_switch_getspnam_r.c b/src/libnsss/nsss_switch_getspnam_r.c
new file mode 100644
index 0000000..9c6b86f
--- /dev/null
+++ b/src/libnsss/nsss_switch_getspnam_r.c
@@ -0,0 +1,34 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/stralloc.h>
+#include <nsss/config.h>
+#include <nsss/shadow-switch.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-internal.h"
+
+int nsss_switch_getspnam_r (char const *name, struct spwd *sp, char *buf, size_t buflen, struct spwd **spp)
+{
+ struct spwd sp2 ;
+ stralloc sa = STRALLOC_ZERO ;
+ nsss_switch_t a = NSSS_SWITCH_ZERO ;
+ int e = errno ;
+ if (!nsss_switch_start(&a, NSSS_SWITCH_SHADOW, NSSS_NSSSD_PATH, 0, 0)) return errno ;
+ errno = 0 ;
+ if (!nsss_switch_shadow_getbyname(&a, &sp2, &sa, name, 0, 0))
+ {
+ nsss_switch_end(&a, NSSS_SWITCH_SHADOW) ;
+ *spp = 0 ;
+ return errno ? errno : (errno = e, 0) ;
+ }
+ nsss_switch_end(&a, NSSS_SWITCH_SHADOW) ;
+ if (!nsss_shadow_copy(sp, buf, buflen, &sp2, sa.s, sa.len))
+ {
+ stralloc_free(&sa) ;
+ *spp = 0 ;
+ return errno ;
+ }
+ stralloc_free(&sa) ;
+ *spp = sp ;
+ return (errno = e, 0) ;
+}
diff --git a/src/libnsss/nsss_switch_grp_end.c b/src/libnsss/nsss_switch_grp_end.c
new file mode 100644
index 0000000..3b25cdf
--- /dev/null
+++ b/src/libnsss/nsss_switch_grp_end.c
@@ -0,0 +1,9 @@
+/* ISC license. */
+
+#include <nsss/nsss-switch.h>
+#include "nsss-switch-internal.h"
+
+int nsss_grent_end (nsss_switch_t *a, tain_t const *deadline, tain_t *stamp)
+{
+ return nsss_switch_op(a, NSSS_SWITCH_GRP_END, deadline, stamp) ;
+}
diff --git a/src/libnsss/nsss_switch_grp_get.c b/src/libnsss/nsss_switch_grp_get.c
new file mode 100644
index 0000000..4cfb67e
--- /dev/null
+++ b/src/libnsss/nsss_switch_grp_get.c
@@ -0,0 +1,17 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/buffer.h>
+#include <skalibs/unix-timed.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-switch-internal.h"
+
+int nsss_switch_grp_get (nsss_switch_t *a, struct group *gr, stralloc *sa, genalloc *ga, tain_t const *deadline, tain_t *stamp)
+{
+ char c = NSSS_SWITCH_GRP_GET ;
+ if (!ipc_timed_send(buffer_fd(&a->b), &c, 1, deadline, stamp)) return 0 ;
+ if (!buffer_timed_get(&a->b, &c, 1, deadline, stamp)) return 0 ;
+ if ((unsigned char)c == 255) return 0 ;
+ if (c) return (errno = c, 0) ;
+ return nsss_switch_grp_read(&a->b, gr, sa, ga, deadline, stamp) ;
+}
diff --git a/src/libnsss/nsss_switch_grp_getbygid.c b/src/libnsss/nsss_switch_grp_getbygid.c
new file mode 100644
index 0000000..3b9802b
--- /dev/null
+++ b/src/libnsss/nsss_switch_grp_getbygid.c
@@ -0,0 +1,19 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/uint32.h>
+#include <skalibs/buffer.h>
+#include <skalibs/unix-timed.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-switch-internal.h"
+
+int nsss_switch_grp_getbygid (nsss_switch_t *a, struct group *gr, stralloc *sa, genalloc *ga, gid_t gid, tain_t const *deadline, tain_t *stamp)
+{
+ char buf[5] = { NSSS_SWITCH_GRP_GETBYGID } ;
+ uint32_pack_big(buf + 1, gid) ;
+ if (!ipc_timed_send(buffer_fd(&a->b), buf, 5, deadline, stamp)) return 0 ;
+ if (!buffer_timed_get(&a->b, &buf[0], 1, deadline, stamp)) return 0 ;
+ if ((unsigned char)buf[0] == 255) return 0 ;
+ if (buf[0]) return (errno = buf[0], 0) ;
+ return nsss_switch_grp_read(&a->b, gr, sa, ga, deadline, stamp) ;
+}
diff --git a/src/libnsss/nsss_switch_grp_getbyname.c b/src/libnsss/nsss_switch_grp_getbyname.c
new file mode 100644
index 0000000..2ece9d2
--- /dev/null
+++ b/src/libnsss/nsss_switch_grp_getbyname.c
@@ -0,0 +1,24 @@
+/* ISC license. */
+
+#include <string.h>
+#include <sys/uio.h>
+#include <errno.h>
+#include <skalibs/uint32.h>
+#include <skalibs/buffer.h>
+#include <skalibs/unix-timed.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-switch-internal.h"
+
+int nsss_switch_grp_getbyname (nsss_switch_t *a, struct group *gr, stralloc *sa, genalloc *ga, char const *name, tain_t const *deadline, tain_t *stamp)
+{
+ char buf[5] = { NSSS_SWITCH_GRP_GETBYNAME } ;
+ size_t len = strlen(name) ;
+ struct iovec v[2] = { { .iov_base = buf, .iov_len = 5 }, { .iov_base = (char *)name, .iov_len = len + 1 } } ;
+ if (len > NSSS_SWITCH_NAME_MAXLEN - 1) return (errno = EINVAL, 0) ;
+ uint32_pack_big(buf + 1, len + 1) ;
+ if (!ipc_timed_sendv(buffer_fd(&a->b), v, 2, deadline, stamp)) return 0 ;
+ if (!buffer_timed_get(&a->b, &buf[0], 1, deadline, stamp)) return 0 ;
+ if ((unsigned char)buf[0] == 255) return 0 ;
+ if (buf[0]) return (errno = buf[0], 0) ;
+ return nsss_switch_grp_read(&a->b, gr, sa, ga, deadline, stamp) ;
+}
diff --git a/src/libnsss/nsss_switch_grp_read.c b/src/libnsss/nsss_switch_grp_read.c
new file mode 100644
index 0000000..6152484
--- /dev/null
+++ b/src/libnsss/nsss_switch_grp_read.c
@@ -0,0 +1,58 @@
+/* ISC license. */
+
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <skalibs/posixplz.h>
+#include <skalibs/uint32.h>
+#include <skalibs/error.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/genalloc.h>
+#include <skalibs/unix-timed.h>
+#include <nsss/grp-def.h>
+#include "nsss-switch-internal.h"
+
+/*
+ Expects:
+ 4 bytes gr_gid
+ 4 bytes total length of strings (including \0's)
+ 4 bytes number of strings in gr_mem (n)
+ \0-terminated gr_name
+ \0-terminated gr_passwd
+ sequence of n \0-terminated elements in gr_mem
+*/
+
+int nsss_switch_grp_read (buffer *b, struct group *gr, stralloc *sa, genalloc *ga, tain_t const *deadline, tain_t *stamp)
+{
+ struct group grtmp ;
+ uint32_t total, len, n, x ;
+ char **q ;
+ char *p ;
+ char buf[12] ;
+ if (!buffer_timed_get(b, buf, 12, deadline, stamp)) return 0 ;
+ uint32_unpack_big(buf, &x) ; grtmp.gr_gid = x ;
+ uint32_unpack_big(buf + 4, &total) ;
+ uint32_unpack_big(buf + 8, &n) ;
+ if (n >= 0x30000000u) return (errno = EPROTO, 0) ;
+ if (!stralloc_readyplus(sa, total)) return 0 ;
+ if (!genalloc_readyplus(char *, ga, n+1)) return 0 ;
+ if (!buffer_timed_get(b, sa->s + sa->len, total, deadline, stamp)) return 0 ;
+ if (sa->s[sa->len + total - 1]) return (errno = EPROTO, 0) ;
+ p = sa->s + sa->len ; len = total ;
+ q = genalloc_s(char *, ga) + genalloc_len(char *, ga) ;
+ grtmp.gr_mem = q ;
+ grtmp.gr_name = p ; x = strnlen(p, len) + 1 ; p += x ; len -= x ;
+ if (!len) return (errno = EPROTO, 0) ;
+ grtmp.gr_passwd = p ; x = strnlen(p, len) + 1 ; p += x ; len -= x ;
+ for (uint32_t i = 0 ; i < n ; i++)
+ {
+ if (!len) return (errno = EPROTO, 0) ;
+ q[i] = p ; x = strnlen(p, len) + 1 ; p += x ; len -= x ;
+ }
+ if (len) return (errno = EPROTO, 0) ;
+ q[n] = 0 ;
+ sa->len += total ;
+ genalloc_setlen(char *, ga, genalloc_len(char *, ga) + n + 1) ;
+ *gr = grtmp ;
+ return 1 ;
+}
diff --git a/src/libnsss/nsss_switch_grp_rewind.c b/src/libnsss/nsss_switch_grp_rewind.c
new file mode 100644
index 0000000..347b071
--- /dev/null
+++ b/src/libnsss/nsss_switch_grp_rewind.c
@@ -0,0 +1,9 @@
+/* ISC license. */
+
+#include <nsss/nsss-switch.h>
+#include "nsss-switch-internal.h"
+
+int nsss_switch_grp_rewind (nsss_switch_t *a, tain_t const *deadline, tain_t *stamp)
+{
+ return nsss_switch_op(a, NSSS_SWITCH_GRP_REWIND, deadline, stamp) ;
+}
diff --git a/src/libnsss/nsss_switch_here.c b/src/libnsss/nsss_switch_here.c
new file mode 100644
index 0000000..994974b
--- /dev/null
+++ b/src/libnsss/nsss_switch_here.c
@@ -0,0 +1,6 @@
+/* ISC license. */
+
+#include <nsss/nsss-switch.h>
+#include "nsss-switch-internal.h"
+
+nsss_switch_t nsss_switch_here = NSSS_SWITCH_ZERO ;
diff --git a/src/libnsss/nsss_switch_op.c b/src/libnsss/nsss_switch_op.c
new file mode 100644
index 0000000..8b5bee3
--- /dev/null
+++ b/src/libnsss/nsss_switch_op.c
@@ -0,0 +1,16 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/buffer.h>
+#include <skalibs/unix-timed.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-switch-internal.h"
+
+int nsss_switch_op (nsss_switch_t *a, char op, tain_t const *deadline, tain_t *stamp)
+{
+ char c ;
+ if (!ipc_timed_send(buffer_fd(&a->b), &op, 1, deadline, stamp)) return 0 ;
+ if (!buffer_timed_get(&a->b, &c, 1, deadline, stamp)) return 0 ;
+ if (c) return (errno = c, 0) ;
+ return 1 ;
+}
diff --git a/src/libnsss/nsss_switch_pwd_end.c b/src/libnsss/nsss_switch_pwd_end.c
new file mode 100644
index 0000000..a082474
--- /dev/null
+++ b/src/libnsss/nsss_switch_pwd_end.c
@@ -0,0 +1,9 @@
+/* ISC license. */
+
+#include <nsss/nsss-switch.h>
+#include "nsss-switch-internal.h"
+
+int nsss_switch_pwd_end (nsss_switch_t *a, tain_t const *deadline, tain_t *stamp)
+{
+ return nsss_switch_op(a, NSSS_SWITCH_PWD_END, deadline, stamp) ;
+}
diff --git a/src/libnsss/nsss_switch_pwd_get.c b/src/libnsss/nsss_switch_pwd_get.c
new file mode 100644
index 0000000..0c630f8
--- /dev/null
+++ b/src/libnsss/nsss_switch_pwd_get.c
@@ -0,0 +1,17 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/buffer.h>
+#include <skalibs/unix-timed.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-switch-internal.h"
+
+int nsss_switch_pwd_get (nsss_switch_t *a, struct passwd *pw, stralloc *sa, tain_t const *deadline, tain_t *stamp)
+{
+ char c = NSSS_SWITCH_PWD_GET ;
+ if (!ipc_timed_send(buffer_fd(&a->b), &c, 1, deadline, stamp)) return 0 ;
+ if (!buffer_timed_get(&a->b, &c, 1, deadline, stamp)) return 0 ;
+ if ((unsigned char)c == 255) return 0 ;
+ if (c) return (errno = c, 0) ;
+ return nsss_switch_pwd_read(&a->b, pw, sa, deadline, stamp) ;
+}
diff --git a/src/libnsss/nsss_switch_pwd_getbyname.c b/src/libnsss/nsss_switch_pwd_getbyname.c
new file mode 100644
index 0000000..a10d129
--- /dev/null
+++ b/src/libnsss/nsss_switch_pwd_getbyname.c
@@ -0,0 +1,24 @@
+/* ISC license. */
+
+#include <string.h>
+#include <sys/uio.h>
+#include <errno.h>
+#include <skalibs/uint32.h>
+#include <skalibs/buffer.h>
+#include <skalibs/unix-timed.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-switch-internal.h"
+
+int nsss_switch_pwd_getbyname (nsss_switch_t *a, struct passwd *pw, stralloc *sa, char const *name, tain_t const *deadline, tain_t *stamp)
+{
+ char buf[5] = { NSSS_SWITCH_PWD_GETBYNAME } ;
+ size_t len = strlen(name) ;
+ struct iovec v[2] = { { .iov_base = buf, .iov_len = 5 }, { .iov_base = (char *)name, .iov_len = len + 1 } } ;
+ if (len > NSSS_SWITCH_NAME_MAXLEN - 1) return (errno = EINVAL, 0) ;
+ uint32_pack_big(buf + 1, len + 1) ;
+ if (!ipc_timed_sendv(buffer_fd(&a->b), v, 2, deadline, stamp)) return 0 ;
+ if (!buffer_timed_get(&a->b, &buf[0], 1, deadline, stamp)) return 0 ;
+ if ((unsigned char)buf[0] == 255) return 0 ;
+ if (buf[0]) return (errno = buf[0], 0) ;
+ return nsss_switch_pwd_read(&a->b, pw, sa, deadline, stamp) ;
+}
diff --git a/src/libnsss/nsss_switch_pwd_getbyuid.c b/src/libnsss/nsss_switch_pwd_getbyuid.c
new file mode 100644
index 0000000..b1d98cf
--- /dev/null
+++ b/src/libnsss/nsss_switch_pwd_getbyuid.c
@@ -0,0 +1,19 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/uint32.h>
+#include <skalibs/buffer.h>
+#include <skalibs/unix-timed.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-switch-internal.h"
+
+int nsss_switch_pwd_getbyuid (nsss_switch_t *a, struct passwd *pw, stralloc *sa, uid_t uid, tain_t const *deadline, tain_t *stamp)
+{
+ char buf[5] = { NSSS_SWITCH_PWD_GETBYUID } ;
+ uint32_pack_big(buf + 1, uid) ;
+ if (!ipc_timed_send(buffer_fd(&a->b), buf, 5, deadline, stamp)) return 0 ;
+ if (!buffer_timed_get(&a->b, &buf[0], 1, deadline, stamp)) return 0 ;
+ if ((unsigned char)buf[0] == 255) return 0 ;
+ if (buf[0]) return (errno = buf[0], 0) ;
+ return nsss_switch_pwd_read(&a->b, pw, sa, deadline, stamp) ;
+}
diff --git a/src/libnsss/nsss_switch_pwd_read.c b/src/libnsss/nsss_switch_pwd_read.c
new file mode 100644
index 0000000..936b0f4
--- /dev/null
+++ b/src/libnsss/nsss_switch_pwd_read.c
@@ -0,0 +1,53 @@
+/* ISC license. */
+
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <skalibs/posixplz.h>
+#include <skalibs/uint32.h>
+#include <skalibs/error.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/unix-timed.h>
+#include <nsss/pwd-def.h>
+#include "nsss-switch-internal.h"
+
+/*
+ Expects:
+ 4 bytes pw_uid
+ 4 bytes pw_gid
+ 4 bytes total length of strings (including \0's)
+ \0-terminated pw_name
+ \0-terminated pw_passwd
+ \0-terminated pw_gecos
+ \0-terminated pw_dir
+ \0-terminated pw_shell
+*/
+
+int nsss_switch_pwd_read (buffer *b, struct passwd *pw, stralloc *sa, tain_t const *deadline, tain_t *stamp)
+{
+ struct passwd pwtmp ;
+ uint32_t total, len, x ;
+ char *p ;
+ char buf[12] ;
+ if (!buffer_timed_get(b, buf, 12, deadline, stamp)) return 0 ;
+ uint32_unpack_big(buf, &x) ; pwtmp.pw_uid = x ;
+ uint32_unpack_big(buf + 4, &x) ; pwtmp.pw_gid = x ;
+ uint32_unpack_big(buf + 8, &total) ;
+ if (!stralloc_readyplus(sa, total)) return 0 ;
+ if (!buffer_timed_get(b, sa->s + sa->len, total, deadline, stamp)) return 0 ;
+ if (sa->s[sa->len + total - 1]) return (errno = EPROTO, 0) ;
+ p = sa->s + sa->len ; len = total ;
+ pwtmp.pw_name = p ; x = strnlen(p, len) + 1 ; p += x ; len -= x ;
+ if (!len) return (errno = EPROTO, 0) ;
+ pwtmp.pw_passwd = p ; x = strnlen(p, len) + 1 ; p += x ; len -= x ;
+ if (!len) return (errno = EPROTO, 0) ;
+ pwtmp.pw_gecos = p ; x = strnlen(p, len) + 1 ; p += x ; len -= x ;
+ if (!len) return (errno = EPROTO, 0) ;
+ pwtmp.pw_dir = p ; x = strnlen(p, len) + 1 ; p += x ; len -= x ;
+ if (!len) return (errno = EPROTO, 0) ;
+ pwtmp.pw_shell = p ; x = strnlen(p, len) + 1 ; p += x ; len -= x ;
+ if (len) return (errno = EPROTO, 0) ;
+ sa->len += total ;
+ *pw = pwtmp ;
+ return 1 ;
+}
diff --git a/src/libnsss/nsss_switch_pwd_rewind.c b/src/libnsss/nsss_switch_pwd_rewind.c
new file mode 100644
index 0000000..9920760
--- /dev/null
+++ b/src/libnsss/nsss_switch_pwd_rewind.c
@@ -0,0 +1,9 @@
+/* ISC license. */
+
+#include <nsss/nsss-switch.h>
+#include "nsss-switch-internal.h"
+
+int nsss_switch_pwd_rewind (nsss_switch_t *a, tain_t const *deadline, tain_t *stamp)
+{
+ return nsss_switch_op(a, NSSS_SWITCH_PWD_REWIND, deadline, stamp) ;
+}
diff --git a/src/libnsss/nsss_switch_setgrent.c b/src/libnsss/nsss_switch_setgrent.c
new file mode 100644
index 0000000..a930568
--- /dev/null
+++ b/src/libnsss/nsss_switch_setgrent.c
@@ -0,0 +1,12 @@
+/* ISC license. */
+
+#include <nsss/config.h>
+#include <nsss/grp-switch.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-switch-internal.h"
+
+void nsss_switch_setgrent (void)
+{
+ if (!nsss_switch_start(&nsss_switch_here, NSSS_SWITCH_GRP, NSSS_NSSSD_PATH, 0, 0)) return ;
+ nsss_switch_grp_rewind(&nsss_switch_here, 0, 0) ;
+}
diff --git a/src/libnsss/nsss_switch_setpwent.c b/src/libnsss/nsss_switch_setpwent.c
new file mode 100644
index 0000000..371423e
--- /dev/null
+++ b/src/libnsss/nsss_switch_setpwent.c
@@ -0,0 +1,12 @@
+/* ISC license. */
+
+#include <nsss/config.h>
+#include <nsss/pwd-switch.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-switch-internal.h"
+
+void nsss_switch_setpwent (void)
+{
+ if (!nsss_switch_start(&nsss_switch_here, NSSS_SWITCH_PWD, NSSS_NSSSD_PATH, 0, 0)) return ;
+ nsss_switch_pwd_rewind(&nsss_switch_here, 0, 0) ;
+}
diff --git a/src/libnsss/nsss_switch_setspent.c b/src/libnsss/nsss_switch_setspent.c
new file mode 100644
index 0000000..5f5ed8a
--- /dev/null
+++ b/src/libnsss/nsss_switch_setspent.c
@@ -0,0 +1,12 @@
+/* ISC license. */
+
+#include <nsss/config.h>
+#include <nsss/shadow-switch.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-switch-internal.h"
+
+void nsss_switch_setspent (void)
+{
+ if (!nsss_switch_start(&nsss_switch_here, NSSS_SWITCH_SHADOW, NSSS_NSSSD_PATH, 0, 0)) return ;
+ nsss_switch_shadow_rewind(&nsss_switch_here, 0, 0) ;
+}
diff --git a/src/libnsss/nsss_switch_shadow_end.c b/src/libnsss/nsss_switch_shadow_end.c
new file mode 100644
index 0000000..eb3454d
--- /dev/null
+++ b/src/libnsss/nsss_switch_shadow_end.c
@@ -0,0 +1,9 @@
+/* ISC license. */
+
+#include <nsss/nsss-switch.h>
+#include "nsss-switch-internal.h"
+
+int nsss_switch_shadow_end (nsss_switch_t *a, tain_t const *deadline, tain_t *stamp)
+{
+ return nsss_switch_op(a, NSSS_SWITCH_SHADOW_END, deadline, stamp) ;
+}
diff --git a/src/libnsss/nsss_switch_shadow_get.c b/src/libnsss/nsss_switch_shadow_get.c
new file mode 100644
index 0000000..e510232
--- /dev/null
+++ b/src/libnsss/nsss_switch_shadow_get.c
@@ -0,0 +1,17 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/buffer.h>
+#include <skalibs/unix-timed.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-switch-internal.h"
+
+int nsss_switch_shadow_get (nsss_switch_t *a, struct spwd *sp, stralloc *sa, tain_t const *deadline, tain_t *stamp)
+{
+ char c = NSSS_SWITCH_SHADOW_GET ;
+ if (!ipc_timed_send(buffer_fd(&a->b), &c, 1, deadline, stamp)) return 0 ;
+ if (!buffer_timed_get(&a->b, &c, 1, deadline, stamp)) return 0 ;
+ if ((unsigned char)c == 255) return 0 ;
+ if (c) return (errno = c, 0) ;
+ return nsss_switch_shadow_read(&a->b, sp, sa, deadline, stamp) ;
+}
diff --git a/src/libnsss/nsss_switch_shadow_getbyname.c b/src/libnsss/nsss_switch_shadow_getbyname.c
new file mode 100644
index 0000000..33fa426
--- /dev/null
+++ b/src/libnsss/nsss_switch_shadow_getbyname.c
@@ -0,0 +1,24 @@
+/* ISC license. */
+
+#include <string.h>
+#include <sys/uio.h>
+#include <errno.h>
+#include <skalibs/uint32.h>
+#include <skalibs/buffer.h>
+#include <skalibs/unix-timed.h>
+#include <nsss/nsss-switch.h>
+#include "nsss-switch-internal.h"
+
+int nsss_switch_shadow_getbyname (nsss_switch_t *a, struct spwd *sp, stralloc *sa, char const *name, tain_t const *deadline, tain_t *stamp)
+{
+ char buf[5] = { NSSS_SWITCH_SHADOW_GETBYNAME } ;
+ size_t len = strlen(name) ;
+ struct iovec v[2] = { { .iov_base = buf, .iov_len = 5 }, { .iov_base = (char *)name, .iov_len = len + 1 } } ;
+ if (len > NSSS_SWITCH_NAME_MAXLEN - 1) return (errno = EINVAL, 0) ;
+ uint32_pack_big(buf + 1, len + 1) ;
+ if (!ipc_timed_sendv(buffer_fd(&a->b), v, 2, deadline, stamp)) return 0 ;
+ if (!buffer_timed_get(&a->b, &buf[0], 1, deadline, stamp)) return 0 ;
+ if ((unsigned char)buf[0] == 255) return 0 ;
+ if (buf[0]) return (errno = buf[0], 0) ;
+ return nsss_switch_shadow_read(&a->b, sp, sa, deadline, stamp) ;
+}
diff --git a/src/libnsss/nsss_switch_shadow_read.c b/src/libnsss/nsss_switch_shadow_read.c
new file mode 100644
index 0000000..1806c6d
--- /dev/null
+++ b/src/libnsss/nsss_switch_shadow_read.c
@@ -0,0 +1,56 @@
+/* ISC license. */
+
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <skalibs/posixplz.h>
+#include <skalibs/uint32.h>
+#include <skalibs/uint64.h>
+#include <skalibs/error.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/unix-timed.h>
+#include <nsss/shadow-def.h>
+#include "nsss-switch-internal.h"
+
+/*
+ Expects:
+ 8 bytes sp_lstchg
+ 8 bytes sp_min
+ 8 bytes sp_max
+ 8 bytes sp_warn
+ 8 bytes sp_inact
+ 8 bytes sp_expire
+ 8 bytes sp_flag
+ 4 bytes total length of strings (including \0's)
+ \0-terminated sp_namp
+ \0-terminated sp_pwdp
+*/
+
+int nsss_switch_shadow_read (buffer *b, struct spwd *sp, stralloc *sa, tain_t const *deadline, tain_t *stamp)
+{
+ struct spwd sptmp ;
+ uint64_t x ;
+ uint32_t total, len ;
+ char *p ;
+ char buf[60] ;
+ if (!buffer_timed_get(b, buf, 60, deadline, stamp)) return 0 ;
+ uint64_unpack_big(buf, &x) ; sptmp.sp_lstchg = x ;
+ uint64_unpack_big(buf + 8, &x) ; sptmp.sp_min = x ;
+ uint64_unpack_big(buf + 16, &x) ; sptmp.sp_max = x ;
+ uint64_unpack_big(buf + 24, &x) ; sptmp.sp_warn = x ;
+ uint64_unpack_big(buf + 32, &x) ; sptmp.sp_inact = x ;
+ uint64_unpack_big(buf + 40, &x) ; sptmp.sp_expire = x ;
+ uint64_unpack_big(buf + 48, &x) ; sptmp.sp_flag = x ;
+ uint32_unpack_big(buf + 56, &total) ;
+ if (!stralloc_readyplus(sa, total)) return 0 ;
+ if (!buffer_timed_get(b, sa->s + sa->len, total, deadline, stamp)) return 0 ;
+ if (sa->s[sa->len + total - 1]) return (errno = EPROTO, 0) ;
+ p = sa->s + sa->len ; len = total ;
+ sptmp.sp_namp = p ; x = strnlen(p, len) + 1 ; p += x ; len -= x ;
+ if (!len) return (errno = EPROTO, 0) ;
+ sptmp.sp_pwdp = p ; x = strnlen(p, len) + 1 ; p += x ; len -= x ;
+ if (len) return (errno = EPROTO, 0) ;
+ sa->len += total ;
+ *sp = sptmp ;
+ return 1 ;
+}
diff --git a/src/libnsss/nsss_switch_shadow_rewind.c b/src/libnsss/nsss_switch_shadow_rewind.c
new file mode 100644
index 0000000..449f25c
--- /dev/null
+++ b/src/libnsss/nsss_switch_shadow_rewind.c
@@ -0,0 +1,9 @@
+/* ISC license. */
+
+#include <nsss/nsss-switch.h>
+#include "nsss-switch-internal.h"
+
+int nsss_switch_shadow_rewind (nsss_switch_t *a, tain_t const *deadline, tain_t *stamp)
+{
+ return nsss_switch_op(a, NSSS_SWITCH_SHADOW_REWIND, deadline, stamp) ;
+}
diff --git a/src/libnsss/nsss_switch_start.c b/src/libnsss/nsss_switch_start.c
new file mode 100644
index 0000000..5d7a183
--- /dev/null
+++ b/src/libnsss/nsss_switch_start.c
@@ -0,0 +1,26 @@
+/* ISC license. */
+
+#include <skalibs/buffer.h>
+#include <skalibs/djbunix.h>
+#include <skalibs/webipc.h>
+#include <nsss/nsss-switch.h>
+
+static inline int nsss_switch_connect (nsss_switch_t *a, char const *path, tain_t const *deadline, tain_t *stamp)
+{
+ int fd = ipc_stream_nbcoe() ;
+ if (fd < 0) return 0 ;
+ if (!ipc_timed_connect(fd, path, deadline, stamp))
+ {
+ fd_close(fd) ;
+ return 0 ;
+ }
+ buffer_init(&a->b, &buffer_read, fd, a->buf, NSSS_SWITCH_BUFSIZE) ;
+ return 1 ;
+}
+
+int nsss_switch_start (nsss_switch_t *a, unsigned int what, char const *path, tain_t const *deadline, tain_t *stamp)
+{
+ if (!a->held && !nsss_switch_connect(a, path, deadline, stamp)) return 0 ;
+ a->held |= (1U << what) ;
+ return 1 ;
+}
diff --git a/src/libnsss/nsss_unix_end.c b/src/libnsss/nsss_unix_end.c
new file mode 100644
index 0000000..1d6b867
--- /dev/null
+++ b/src/libnsss/nsss_unix_end.c
@@ -0,0 +1,11 @@
+/* ISC license. */
+
+#include <skalibs/buffer.h>
+#include <skalibs/djbunix.h>
+#include <nsss/nsss-unix.h>
+
+void nsss_unix_end (nsss_unix_t *a)
+{
+ fd_close(buffer_fd(&a->b)) ;
+ a->b.fd = -1 ;
+}
diff --git a/src/libnsss/nsss_unix_endgrent.c b/src/libnsss/nsss_unix_endgrent.c
new file mode 100644
index 0000000..58c2422
--- /dev/null
+++ b/src/libnsss/nsss_unix_endgrent.c
@@ -0,0 +1,9 @@
+/* ISC license. */
+
+#include <nsss/grp-unix.h>
+#include "nsss-unix-internal.h"
+
+void nsss_unix_endgrent (void)
+{
+ nsss_unix_grp_end(&nsss_unix_grp_here) ;
+}
diff --git a/src/libnsss/nsss_unix_endpwent.c b/src/libnsss/nsss_unix_endpwent.c
new file mode 100644
index 0000000..c7d87af
--- /dev/null
+++ b/src/libnsss/nsss_unix_endpwent.c
@@ -0,0 +1,9 @@
+/* ISC license. */
+
+#include <nsss/pwd-unix.h>
+#include "nsss-unix-internal.h"
+
+void nsss_unix_endpwent (void)
+{
+ nsss_unix_pwd_end(&nsss_unix_pwd_here) ;
+}
diff --git a/src/libnsss/nsss_unix_endspent.c b/src/libnsss/nsss_unix_endspent.c
new file mode 100644
index 0000000..3e28e75
--- /dev/null
+++ b/src/libnsss/nsss_unix_endspent.c
@@ -0,0 +1,9 @@
+/* ISC license. */
+
+#include <nsss/shadow-unix.h>
+#include "nsss-unix-internal.h"
+
+void nsss_unix_endspent (void)
+{
+ nsss_unix_shadow_end(&nsss_unix_shadow_here) ;
+}
diff --git a/src/libnsss/nsss_unix_field.c b/src/libnsss/nsss_unix_field.c
new file mode 100644
index 0000000..b77bb04
--- /dev/null
+++ b/src/libnsss/nsss_unix_field.c
@@ -0,0 +1,14 @@
+/* ISC license. */
+
+#include <string.h>
+#include "nsss-unix-internal.h"
+
+int nsss_unix_field (char **field, char **s)
+{
+ char *p = strchr(*s, ':') ;
+ if (!p) return 0 ;
+ *p++ = 0 ;
+ *field = *s ;
+ *s = p ;
+ return 1 ;
+}
diff --git a/src/libnsss/nsss_unix_getgrent.c b/src/libnsss/nsss_unix_getgrent.c
new file mode 100644
index 0000000..e531510
--- /dev/null
+++ b/src/libnsss/nsss_unix_getgrent.c
@@ -0,0 +1,16 @@
+/* ISC license. */
+
+#include <skalibs/genalloc.h>
+#include <nsss/grp-unix.h>
+#include <nsss/nsss-unix.h>
+#include "nsss-internal.h"
+#include "nsss-unix-internal.h"
+
+struct group *nsss_unix_getgrent (void)
+{
+ if (!nsss_unix_grp_maybe_start(&nsss_unix_grp_here)) return 0 ;
+ nsss_grp_sa_here.len = 0 ;
+ genalloc_setlen(char *, &nsss_grp_ga_here, 0) ;
+ if (!nsss_unix_grp_get(&nsss_unix_grp_here, &nsss_grp_here, &nsss_grp_sa_here, &nsss_grp_ga_here)) return 0 ;
+ return &nsss_grp_here ;
+}
diff --git a/src/libnsss/nsss_unix_getgrent_r.c b/src/libnsss/nsss_unix_getgrent_r.c
new file mode 100644
index 0000000..5ddc526
--- /dev/null
+++ b/src/libnsss/nsss_unix_getgrent_r.c
@@ -0,0 +1,35 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/genalloc.h>
+#include <nsss/grp-unix.h>
+#include <nsss/nsss-unix.h>
+#include "nsss-internal.h"
+#include "nsss-unix-internal.h"
+
+int nsss_unix_getgrent_r (struct group *gr, char *buf, size_t buflen, struct group **grp)
+{
+ struct group gr2 ;
+ stralloc sa = STRALLOC_ZERO ;
+ genalloc ga = GENALLOC_ZERO ;
+ int e ;
+ if (!nsss_unix_grp_maybe_start(&nsss_unix_grp_here)) return errno ;
+ e = errno ;
+ errno = 0 ;
+ if (!nsss_unix_grp_get(&nsss_unix_grp_here, &gr2, &sa, &ga))
+ {
+ *grp = 0 ;
+ if (!errno) errno = ENOENT ;
+ return errno ;
+ }
+ if (!nsss_grp_copy(gr, buf, buflen, &gr2, sa.s, sa.len, genalloc_s(char *, &ga), genalloc_len(char *, &ga)))
+ {
+ stralloc_free(&sa) ;
+ *grp = 0 ;
+ return errno ;
+ }
+ stralloc_free(&sa) ;
+ *grp = gr ;
+ return (errno = e, 0) ;
+}
diff --git a/src/libnsss/nsss_unix_getgrgid.c b/src/libnsss/nsss_unix_getgrgid.c
new file mode 100644
index 0000000..e6d8979
--- /dev/null
+++ b/src/libnsss/nsss_unix_getgrgid.c
@@ -0,0 +1,21 @@
+/* ISC license. */
+
+#include <skalibs/genalloc.h>
+#include <nsss/grp-unix.h>
+#include <nsss/nsss-unix.h>
+#include "nsss-internal.h"
+
+struct group *nsss_unix_getgrgid (gid_t gid)
+{
+ nsss_unix_t a = NSSS_UNIX_ZERO ;
+ if (!nsss_unix_grp_start(&a)) return 0 ;
+ nsss_grp_sa_here.len = 0 ;
+ genalloc_setlen(char *, &nsss_grp_ga_here, 0) ;
+ if (!nsss_unix_grp_getbygid(&a, &nsss_grp_here, &nsss_grp_sa_here, &nsss_grp_ga_here, gid))
+ {
+ nsss_unix_grp_end(&a) ;
+ return 0 ;
+ }
+ nsss_unix_grp_end(&a) ;
+ return &nsss_grp_here ;
+}
diff --git a/src/libnsss/nsss_unix_getgrgid_r.c b/src/libnsss/nsss_unix_getgrgid_r.c
new file mode 100644
index 0000000..5d3dbe5
--- /dev/null
+++ b/src/libnsss/nsss_unix_getgrgid_r.c
@@ -0,0 +1,35 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/genalloc.h>
+#include <nsss/grp-unix.h>
+#include <nsss/nsss-unix.h>
+#include "nsss-internal.h"
+
+int nsss_unix_getgrgid_r (gid_t gid, struct group *gr, char *buf, size_t buflen, struct group **grp)
+{
+ struct group gr2 ;
+ stralloc sa = STRALLOC_ZERO ;
+ genalloc ga = GENALLOC_ZERO ;
+ nsss_unix_t a = NSSS_UNIX_ZERO ;
+ int e = errno ;
+ if (!nsss_unix_grp_start(&a)) return errno ;
+ errno = 0 ;
+ if (!nsss_unix_grp_getbygid(&a, &gr2, &sa, &ga, gid))
+ {
+ nsss_unix_grp_end(&a) ;
+ *grp = 0 ;
+ return errno ? errno : (errno = e, 0) ;
+ }
+ nsss_unix_grp_end(&a) ;
+ if (!nsss_grp_copy(gr, buf, buflen, &gr2, sa.s, sa.len, genalloc_s(char *, &ga), genalloc_len(char *, &ga)))
+ {
+ stralloc_free(&sa) ;
+ *grp = 0 ;
+ return errno ;
+ }
+ stralloc_free(&sa) ;
+ *grp = gr ;
+ return (errno = e, 0) ;
+}
diff --git a/src/libnsss/nsss_unix_getgrnam.c b/src/libnsss/nsss_unix_getgrnam.c
new file mode 100644
index 0000000..ca9d9b9
--- /dev/null
+++ b/src/libnsss/nsss_unix_getgrnam.c
@@ -0,0 +1,21 @@
+/* ISC license. */
+
+#include <skalibs/genalloc.h>
+#include <nsss/grp-unix.h>
+#include <nsss/nsss-unix.h>
+#include "nsss-internal.h"
+
+struct group *nsss_unix_getgrnam (char const *name)
+{
+ nsss_unix_t a = NSSS_UNIX_ZERO ;
+ if (!nsss_unix_grp_start(&a)) return 0 ;
+ nsss_grp_sa_here.len = 0 ;
+ genalloc_setlen(char *, &nsss_grp_ga_here, 0) ;
+ if (!nsss_unix_grp_getbyname(&a, &nsss_grp_here, &nsss_grp_sa_here, &nsss_grp_ga_here, name))
+ {
+ nsss_unix_grp_end(&a) ;
+ return 0 ;
+ }
+ nsss_unix_grp_end(&a) ;
+ return &nsss_grp_here ;
+}
diff --git a/src/libnsss/nsss_unix_getgrnam_r.c b/src/libnsss/nsss_unix_getgrnam_r.c
new file mode 100644
index 0000000..bc63d78
--- /dev/null
+++ b/src/libnsss/nsss_unix_getgrnam_r.c
@@ -0,0 +1,35 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/genalloc.h>
+#include <nsss/grp-unix.h>
+#include <nsss/nsss-unix.h>
+#include "nsss-internal.h"
+
+int nsss_unix_getgrnam_r (char const *name, struct group *gr, char *buf, size_t buflen, struct group **grp)
+{
+ struct group gr2 ;
+ stralloc sa = STRALLOC_ZERO ;
+ genalloc ga = GENALLOC_ZERO ;
+ nsss_unix_t a = NSSS_UNIX_ZERO ;
+ int e = errno ;
+ if (!nsss_unix_grp_start(&a)) return errno ;
+ errno = 0 ;
+ if (!nsss_unix_grp_getbyname(&a, &gr2, &sa, &ga, name))
+ {
+ nsss_unix_grp_end(&a) ;
+ *grp = 0 ;
+ return errno ? errno : (errno = e, 0) ;
+ }
+ nsss_unix_grp_end(&a) ;
+ if (!nsss_grp_copy(gr, buf, buflen, &gr2, sa.s, sa.len, genalloc_s(char *, &ga), genalloc_len(char *, &ga)))
+ {
+ stralloc_free(&sa) ;
+ *grp = 0 ;
+ return errno ;
+ }
+ stralloc_free(&sa) ;
+ *grp = gr ;
+ return (errno = e, 0) ;
+}
diff --git a/src/libnsss/nsss_unix_getpwent.c b/src/libnsss/nsss_unix_getpwent.c
new file mode 100644
index 0000000..4271f0b
--- /dev/null
+++ b/src/libnsss/nsss_unix_getpwent.c
@@ -0,0 +1,14 @@
+/* ISC license. */
+
+#include <nsss/pwd-unix.h>
+#include <nsss/nsss-unix.h>
+#include "nsss-internal.h"
+#include "nsss-unix-internal.h"
+
+struct passwd *nsss_unix_getpwent (void)
+{
+ if (!nsss_unix_pwd_maybe_start(&nsss_unix_pwd_here)) return 0 ;
+ nsss_pwd_sa_here.len = 0 ;
+ if (!nsss_unix_pwd_get(&nsss_unix_pwd_here, &nsss_pwd_here, &nsss_pwd_sa_here)) return 0 ;
+ return &nsss_pwd_here ;
+}
diff --git a/src/libnsss/nsss_unix_getpwent_r.c b/src/libnsss/nsss_unix_getpwent_r.c
new file mode 100644
index 0000000..183bfd7
--- /dev/null
+++ b/src/libnsss/nsss_unix_getpwent_r.c
@@ -0,0 +1,33 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/stralloc.h>
+#include <nsss/pwd-unix.h>
+#include <nsss/nsss-unix.h>
+#include "nsss-internal.h"
+#include "nsss-unix-internal.h"
+
+int nsss_unix_getpwent_r (struct passwd *pw, char *buf, size_t buflen, struct passwd **pwp)
+{
+ struct passwd pw2 ;
+ stralloc sa = STRALLOC_ZERO ;
+ int e ;
+ if (!nsss_unix_pwd_maybe_start(&nsss_unix_pwd_here)) return errno ;
+ e = errno ;
+ errno = 0 ;
+ if (!nsss_unix_pwd_get(&nsss_unix_pwd_here, &pw2, &sa))
+ {
+ *pwp = 0 ;
+ if (!errno) errno = ENOENT ;
+ return errno ;
+ }
+ if (!nsss_pwd_copy(pw, buf, buflen, &pw2, sa.s, sa.len))
+ {
+ stralloc_free(&sa) ;
+ *pwp = 0 ;
+ return errno ;
+ }
+ stralloc_free(&sa) ;
+ *pwp = pw ;
+ return (errno = e, 0) ;
+}
diff --git a/src/libnsss/nsss_unix_getpwnam.c b/src/libnsss/nsss_unix_getpwnam.c
new file mode 100644
index 0000000..eb5d6b1
--- /dev/null
+++ b/src/libnsss/nsss_unix_getpwnam.c
@@ -0,0 +1,19 @@
+/* ISC license. */
+
+#include <nsss/pwd-unix.h>
+#include <nsss/nsss-unix.h>
+#include "nsss-internal.h"
+
+struct passwd *nsss_unix_getpwnam (char const *name)
+{
+ nsss_unix_t a = NSSS_UNIX_ZERO ;
+ if (!nsss_unix_pwd_start(&a)) return 0 ;
+ nsss_pwd_sa_here.len = 0 ;
+ if (!nsss_unix_pwd_getbyname(&a, &nsss_pwd_here, &nsss_pwd_sa_here, name))
+ {
+ nsss_unix_pwd_end(&a) ;
+ return 0 ;
+ }
+ nsss_unix_pwd_end(&a) ;
+ return &nsss_pwd_here ;
+}
diff --git a/src/libnsss/nsss_unix_getpwnam_r.c b/src/libnsss/nsss_unix_getpwnam_r.c
new file mode 100644
index 0000000..b41ce70
--- /dev/null
+++ b/src/libnsss/nsss_unix_getpwnam_r.c
@@ -0,0 +1,33 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/stralloc.h>
+#include <nsss/pwd-unix.h>
+#include <nsss/nsss-unix.h>
+#include "nsss-internal.h"
+
+int nsss_unix_getpwnam_r (char const *name, struct passwd *pw, char *buf, size_t buflen, struct passwd **pwp)
+{
+ struct passwd pw2 ;
+ stralloc sa = STRALLOC_ZERO ;
+ nsss_unix_t a = NSSS_UNIX_ZERO ;
+ int e = errno ;
+ if (!nsss_unix_pwd_start(&a)) return errno ;
+ errno = 0 ;
+ if (!nsss_unix_pwd_getbyname(&a, &pw2, &sa, name))
+ {
+ nsss_unix_pwd_end(&a) ;
+ *pwp = 0 ;
+ return errno ? errno : (errno = e, 0) ;
+ }
+ nsss_unix_pwd_end(&a) ;
+ if (!nsss_pwd_copy(pw, buf, buflen, &pw2, sa.s, sa.len))
+ {
+ stralloc_free(&sa) ;
+ *pwp = 0 ;
+ return errno ;
+ }
+ stralloc_free(&sa) ;
+ *pwp = pw ;
+ return (errno = e, 0) ;
+}
diff --git a/src/libnsss/nsss_unix_getpwuid.c b/src/libnsss/nsss_unix_getpwuid.c
new file mode 100644
index 0000000..35f019d
--- /dev/null
+++ b/src/libnsss/nsss_unix_getpwuid.c
@@ -0,0 +1,19 @@
+/* ISC license. */
+
+#include <nsss/pwd-unix.h>
+#include <nsss/nsss-unix.h>
+#include "nsss-internal.h"
+
+struct passwd *nsss_unix_getpwuid (uid_t uid)
+{
+ nsss_unix_t a = NSSS_UNIX_ZERO ;
+ if (!nsss_unix_pwd_start(&a)) return 0 ;
+ nsss_pwd_sa_here.len = 0 ;
+ if (!nsss_unix_pwd_getbyuid(&a, &nsss_pwd_here, &nsss_pwd_sa_here, uid))
+ {
+ nsss_unix_pwd_end(&a) ;
+ return 0 ;
+ }
+ nsss_unix_pwd_end(&a) ;
+ return &nsss_pwd_here ;
+}
diff --git a/src/libnsss/nsss_unix_getpwuid_r.c b/src/libnsss/nsss_unix_getpwuid_r.c
new file mode 100644
index 0000000..0601008
--- /dev/null
+++ b/src/libnsss/nsss_unix_getpwuid_r.c
@@ -0,0 +1,33 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/stralloc.h>
+#include <nsss/pwd-unix.h>
+#include <nsss/nsss-unix.h>
+#include "nsss-internal.h"
+
+int nsss_unix_getpwuid_r (uid_t uid, struct passwd *pw, char *buf, size_t buflen, struct passwd **pwp)
+{
+ struct passwd pw2 ;
+ stralloc sa = STRALLOC_ZERO ;
+ nsss_unix_t a = NSSS_UNIX_ZERO ;
+ int e = errno ;
+ if (!nsss_unix_pwd_start(&a)) return errno ;
+ errno = 0 ;
+ if (!nsss_unix_pwd_getbyuid(&a, &pw2, &sa, uid))
+ {
+ nsss_unix_pwd_end(&a) ;
+ *pwp = 0 ;
+ return errno ? errno : (errno = e, 0) ;
+ }
+ nsss_unix_pwd_end(&a) ;
+ if (!nsss_pwd_copy(pw, buf, buflen, &pw2, sa.s, sa.len))
+ {
+ stralloc_free(&sa) ;
+ *pwp = 0 ;
+ return errno ;
+ }
+ stralloc_free(&sa) ;
+ *pwp = pw ;
+ return (errno = e, 0) ;
+}
diff --git a/src/libnsss/nsss_unix_getspent.c b/src/libnsss/nsss_unix_getspent.c
new file mode 100644
index 0000000..f442a40
--- /dev/null
+++ b/src/libnsss/nsss_unix_getspent.c
@@ -0,0 +1,14 @@
+/* ISC license. */
+
+#include <nsss/shadow-unix.h>
+#include <nsss/nsss-unix.h>
+#include "nsss-internal.h"
+#include "nsss-unix-internal.h"
+
+struct spwd *nsss_unix_getspent (void)
+{
+ if (!nsss_unix_shadow_maybe_start(&nsss_unix_shadow_here)) return 0 ;
+ nsss_shadow_sa_here.len = 0 ;
+ if (!nsss_unix_shadow_get(&nsss_unix_shadow_here, &nsss_shadow_here, &nsss_shadow_sa_here)) return 0 ;
+ return &nsss_shadow_here ;
+}
diff --git a/src/libnsss/nsss_unix_getspent_r.c b/src/libnsss/nsss_unix_getspent_r.c
new file mode 100644
index 0000000..6ae4f8a
--- /dev/null
+++ b/src/libnsss/nsss_unix_getspent_r.c
@@ -0,0 +1,33 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/stralloc.h>
+#include <nsss/shadow-unix.h>
+#include <nsss/nsss-unix.h>
+#include "nsss-internal.h"
+#include "nsss-unix-internal.h"
+
+int nsss_unix_getspent_r (struct spwd *sp, char *buf, size_t buflen, struct spwd **spp)
+{
+ struct spwd sp2 ;
+ stralloc sa = STRALLOC_ZERO ;
+ int e ;
+ if (!nsss_unix_shadow_maybe_start(&nsss_unix_shadow_here)) return errno ;
+ e = errno ;
+ errno = 0 ;
+ if (!nsss_unix_shadow_get(&nsss_unix_shadow_here, &sp2, &sa))
+ {
+ *spp = 0 ;
+ if (!errno) errno = ENOENT ;
+ return errno ;
+ }
+ if (!nsss_shadow_copy(sp, buf, buflen, &sp2, sa.s, sa.len))
+ {
+ stralloc_free(&sa) ;
+ *spp = 0 ;
+ return errno ;
+ }
+ stralloc_free(&sa) ;
+ *spp = sp ;
+ return (errno = e, 0) ;
+}
diff --git a/src/libnsss/nsss_unix_getspnam.c b/src/libnsss/nsss_unix_getspnam.c
new file mode 100644
index 0000000..810d45f
--- /dev/null
+++ b/src/libnsss/nsss_unix_getspnam.c
@@ -0,0 +1,19 @@
+/* ISC license. */
+
+#include <nsss/shadow-unix.h>
+#include <nsss/nsss-unix.h>
+#include "nsss-internal.h"
+
+struct spwd *nsss_unix_getspnam (char const *name)
+{
+ nsss_unix_t a = NSSS_UNIX_ZERO ;
+ if (!nsss_unix_shadow_start(&a)) return 0 ;
+ nsss_shadow_sa_here.len = 0 ;
+ if (!nsss_unix_shadow_getbyname(&a, &nsss_shadow_here, &nsss_shadow_sa_here, name))
+ {
+ nsss_unix_shadow_end(&a) ;
+ return 0 ;
+ }
+ nsss_unix_shadow_end(&a) ;
+ return &nsss_shadow_here ;
+}
diff --git a/src/libnsss/nsss_unix_getspnam_r.c b/src/libnsss/nsss_unix_getspnam_r.c
new file mode 100644
index 0000000..f0bfed4
--- /dev/null
+++ b/src/libnsss/nsss_unix_getspnam_r.c
@@ -0,0 +1,33 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/stralloc.h>
+#include <nsss/shadow-unix.h>
+#include <nsss/nsss-unix.h>
+#include "nsss-internal.h"
+
+int nsss_unix_getspnam_r (char const *name, struct spwd *sp, char *buf, size_t buflen, struct spwd **spp)
+{
+ struct spwd sp2 ;
+ stralloc sa = STRALLOC_ZERO ;
+ nsss_unix_t a = NSSS_UNIX_ZERO ;
+ int e = errno ;
+ if (!nsss_unix_shadow_start(&a)) return errno ;
+ errno = 0 ;
+ if (!nsss_unix_shadow_getbyname(&a, &sp2, &sa, name))
+ {
+ nsss_unix_shadow_end(&a) ;
+ *spp = 0 ;
+ return errno ? errno : (errno = e, 0) ;
+ }
+ nsss_unix_shadow_end(&a) ;
+ if (!nsss_shadow_copy(sp, buf, buflen, &sp2, sa.s, sa.len))
+ {
+ stralloc_free(&sa) ;
+ *spp = 0 ;
+ return errno ;
+ }
+ stralloc_free(&sa) ;
+ *spp = sp ;
+ return (errno = e, 0) ;
+}
diff --git a/src/libnsss/nsss_unix_grp_get.c b/src/libnsss/nsss_unix_grp_get.c
new file mode 100644
index 0000000..f7984a4
--- /dev/null
+++ b/src/libnsss/nsss_unix_grp_get.c
@@ -0,0 +1,62 @@
+/* ISC license. */
+
+#include <string.h>
+#include <pthread.h>
+#include <skalibs/types.h>
+#include <skalibs/genalloc.h>
+#include <skalibs/skamisc.h>
+#include <nsss/grp-def.h>
+#include <nsss/nsss-unix.h>
+#include "nsss-unix-internal.h"
+
+static inline char **grp_parsemem (char *s, genalloc *ga)
+{
+ char **grmem ;
+ char **p ;
+ size_t n = 0 ;
+ for (char *t = s ; *t ; t++) if (*t == ',') { n++ ; *t = 0 ; } ;
+ if (*s) n++ ;
+ if (!genalloc_readyplus(char *, ga, n+1)) return 0 ;
+ p = genalloc_s(char *, ga) + genalloc_len(char *, ga) ;
+ grmem = p ;
+ for (size_t i = 0 ; i < n ; i++) { *p++ = s ; s += strlen(s) + 1 ; }
+ *p++ = 0 ;
+ genalloc_setlen(char *, ga, genalloc_len(char *, ga) + n+1) ;
+ return grmem ;
+}
+
+static inline int grp_parseline (struct group *gr, char *s, size_t max, genalloc *ga)
+{
+ struct group gr2 ;
+ char *p ;
+ s[max-1] = 0 ;
+ if (!nsss_unix_field(&gr2.gr_name, &s)) return 0 ;
+ if (!nsss_unix_field(&gr2.gr_passwd, &s)) return 0 ;
+ if (!nsss_unix_field(&p, &s)) return 0 ;
+ if (!gid0_scan(p, &gr2.gr_gid)) return 0 ;
+ gr2.gr_mem = grp_parsemem(s, ga) ;
+ if (!gr2.gr_mem) return 0 ;
+ *gr = gr2 ;
+ return 1 ;
+}
+
+int nsss_unix_grp_get (nsss_unix_t *a, struct group *gr, stralloc *sa, genalloc *ga)
+{
+ int cs ;
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs) ;
+ for (;;)
+ {
+ size_t sabase = sa->len ;
+ size_t gabase = genalloc_len(char *, ga) ;
+ if (skagetln_loose(&a->b, sa, '\n') <= 0) goto err ;
+ if (grp_parseline(gr, sa->s + sabase, sa->len - sabase, ga)) break ;
+ sa->len = sabase ;
+ genalloc_setlen(char *, ga, gabase) ;
+ }
+ pthread_setcancelstate(cs, 0) ;
+ return 1 ;
+
+ err:
+ pthread_setcancelstate(cs, 0) ;
+ return 0 ;
+}
diff --git a/src/libnsss/nsss_unix_grp_getbygid.c b/src/libnsss/nsss_unix_grp_getbygid.c
new file mode 100644
index 0000000..48cfecf
--- /dev/null
+++ b/src/libnsss/nsss_unix_grp_getbygid.c
@@ -0,0 +1,22 @@
+/* ISC license. */
+
+#include <sys/types.h>
+#include <skalibs/genalloc.h>
+#include <nsss/grp-def.h>
+#include <nsss/nsss-unix.h>
+
+int nsss_unix_grp_getbygid (nsss_unix_t *a, struct group *gr, stralloc *sa, genalloc *ga, gid_t gid)
+{
+ struct group gr2 ;
+ for (;;)
+ {
+ size_t sabase = sa->len ;
+ size_t gabase = genalloc_len(char *, ga) ;
+ if (!nsss_unix_grp_get(a, &gr2, sa, ga)) return 0 ;
+ if (gid == gr2.gr_gid) break ;
+ sa->len = sabase ;
+ genalloc_setlen(char *, ga, gabase) ;
+ }
+ *gr = gr2 ;
+ return 1 ;
+}
diff --git a/src/libnsss/nsss_unix_grp_getbyname.c b/src/libnsss/nsss_unix_grp_getbyname.c
new file mode 100644
index 0000000..0b8e3b8
--- /dev/null
+++ b/src/libnsss/nsss_unix_grp_getbyname.c
@@ -0,0 +1,22 @@
+/* ISC license. */
+
+#include <string.h>
+#include <skalibs/genalloc.h>
+#include <nsss/grp-def.h>
+#include <nsss/nsss-unix.h>
+
+int nsss_unix_grp_getbyname (nsss_unix_t *a, struct group *gr, stralloc *sa, genalloc *ga, char const *name)
+{
+ struct group gr2 ;
+ for (;;)
+ {
+ size_t sabase = sa->len ;
+ size_t gabase = genalloc_len(char *, ga) ;
+ if (!nsss_unix_grp_get(a, &gr2, sa, ga)) return 0 ;
+ if (!strcmp(name, gr2.gr_name)) break ;
+ sa->len = sabase ;
+ genalloc_setlen(char *, ga, gabase) ;
+ }
+ *gr = gr2 ;
+ return 1 ;
+}
diff --git a/src/libnsss/nsss_unix_grp_here.c b/src/libnsss/nsss_unix_grp_here.c
new file mode 100644
index 0000000..b2adfe9
--- /dev/null
+++ b/src/libnsss/nsss_unix_grp_here.c
@@ -0,0 +1,5 @@
+/* ISC license. */
+
+#include "nsss-unix-internal.h"
+
+nsss_unix_t nsss_unix_grp_here = NSSS_UNIX_ZERO ;
diff --git a/src/libnsss/nsss_unix_maybe_start.c b/src/libnsss/nsss_unix_maybe_start.c
new file mode 100644
index 0000000..9aad8d4
--- /dev/null
+++ b/src/libnsss/nsss_unix_maybe_start.c
@@ -0,0 +1,9 @@
+/* ISC license. */
+
+#include <skalibs/buffer.h>
+#include <nsss/nsss-unix.h>
+
+int nsss_unix_maybe_start (nsss_unix_t *a, char const *path)
+{
+ return buffer_fd(&a->b) >= 0 || nsss_unix_start(a, path) ;
+}
diff --git a/src/libnsss/nsss_unix_pwd_get.c b/src/libnsss/nsss_unix_pwd_get.c
new file mode 100644
index 0000000..b0c1200
--- /dev/null
+++ b/src/libnsss/nsss_unix_pwd_get.c
@@ -0,0 +1,45 @@
+/* ISC license. */
+
+#include <pthread.h>
+#include <skalibs/types.h>
+#include <skalibs/skamisc.h>
+#include <nsss/pwd-def.h>
+#include <nsss/nsss-unix.h>
+#include "nsss-unix-internal.h"
+
+static inline int pwd_parseline (struct passwd *pw, char *s, size_t max)
+{
+ struct passwd pw2 ;
+ char *p ;
+ s[max-1] = 0 ;
+ if (!nsss_unix_field(&pw2.pw_name, &s)) return 0 ;
+ if (!nsss_unix_field(&pw2.pw_passwd, &s)) return 0 ;
+ if (!nsss_unix_field(&p, &s)) return 0 ;
+ if (!uid0_scan(p, &pw2.pw_uid)) return 0 ;
+ if (!nsss_unix_field(&p, &s)) return 0 ;
+ if (!gid0_scan(p, &pw2.pw_gid)) return 0 ;
+ if (!nsss_unix_field(&pw2.pw_gecos, &s)) return 0 ;
+ if (!nsss_unix_field(&pw2.pw_dir, &s)) return 0 ;
+ pw2.pw_shell = s ;
+ *pw = pw2 ;
+ return 1 ;
+}
+
+int nsss_unix_pwd_get (nsss_unix_t *a, struct passwd *pw, stralloc *sa)
+{
+ int cs ;
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs) ;
+ for (;;)
+ {
+ size_t base = sa->len ;
+ if (skagetln_loose(&a->b, sa, '\n') <= 0) goto err ;
+ if (pwd_parseline(pw, sa->s + base, sa->len - base)) break ;
+ sa->len = base ;
+ }
+ pthread_setcancelstate(cs, 0) ;
+ return 1 ;
+
+ err:
+ pthread_setcancelstate(cs, 0) ;
+ return 0 ;
+}
diff --git a/src/libnsss/nsss_unix_pwd_getbyname.c b/src/libnsss/nsss_unix_pwd_getbyname.c
new file mode 100644
index 0000000..4d60e8c
--- /dev/null
+++ b/src/libnsss/nsss_unix_pwd_getbyname.c
@@ -0,0 +1,19 @@
+/* ISC license. */
+
+#include <string.h>
+#include <nsss/pwd-def.h>
+#include <nsss/nsss-unix.h>
+
+int nsss_unix_pwd_getbyname (nsss_unix_t *a, struct passwd *pw, stralloc *sa, char const *name)
+{
+ struct passwd pw2 ;
+ for (;;)
+ {
+ size_t base = sa->len ;
+ if (!nsss_unix_pwd_get(a, &pw2, sa)) return 0 ;
+ if (!strcmp(name, pw2.pw_name)) break ;
+ sa->len = base ;
+ }
+ *pw = pw2 ;
+ return 1 ;
+}
diff --git a/src/libnsss/nsss_unix_pwd_getbyuid.c b/src/libnsss/nsss_unix_pwd_getbyuid.c
new file mode 100644
index 0000000..4964cdd
--- /dev/null
+++ b/src/libnsss/nsss_unix_pwd_getbyuid.c
@@ -0,0 +1,19 @@
+/* ISC license. */
+
+#include <sys/types.h>
+#include <nsss/pwd-def.h>
+#include <nsss/nsss-unix.h>
+
+int nsss_unix_pwd_getbyuid (nsss_unix_t *a, struct passwd *pw, stralloc *sa, uid_t uid)
+{
+ struct passwd pw2 ;
+ for (;;)
+ {
+ size_t base = sa->len ;
+ if (!nsss_unix_pwd_get(a, &pw2, sa)) return 0 ;
+ if (uid == pw2.pw_uid) break ;
+ sa->len = base ;
+ }
+ *pw = pw2 ;
+ return 1 ;
+}
diff --git a/src/libnsss/nsss_unix_pwd_here.c b/src/libnsss/nsss_unix_pwd_here.c
new file mode 100644
index 0000000..33aa911
--- /dev/null
+++ b/src/libnsss/nsss_unix_pwd_here.c
@@ -0,0 +1,5 @@
+/* ISC license. */
+
+#include "nsss-unix-internal.h"
+
+nsss_unix_t nsss_unix_pwd_here = NSSS_UNIX_ZERO ;
diff --git a/src/libnsss/nsss_unix_rewind.c b/src/libnsss/nsss_unix_rewind.c
new file mode 100644
index 0000000..2b8c6b3
--- /dev/null
+++ b/src/libnsss/nsss_unix_rewind.c
@@ -0,0 +1,13 @@
+/* ISC license. */
+
+#include <unistd.h>
+#include <skalibs/buffer.h>
+#include <nsss/nsss-unix.h>
+
+int nsss_unix_rewind (nsss_unix_t *a)
+{
+ int fd = buffer_fd(&a->b) ;
+ if (lseek(fd, 0, SEEK_SET) < 0) return 0 ;
+ buffer_init(&a->b, &buffer_read, fd, a->buf, NSSS_UNIX_BUFSIZE) ;
+ return 1 ;
+}
diff --git a/src/libnsss/nsss_unix_setgrent.c b/src/libnsss/nsss_unix_setgrent.c
new file mode 100644
index 0000000..e01744f
--- /dev/null
+++ b/src/libnsss/nsss_unix_setgrent.c
@@ -0,0 +1,11 @@
+/* ISC license. */
+
+#include <nsss/grp-unix.h>
+#include <nsss/nsss-unix.h>
+#include "nsss-unix-internal.h"
+
+void nsss_unix_setgrent (void)
+{
+ if (!nsss_unix_grp_maybe_start(&nsss_unix_grp_here)) return ;
+ nsss_unix_grp_rewind(&nsss_unix_grp_here) ;
+}
diff --git a/src/libnsss/nsss_unix_setpwent.c b/src/libnsss/nsss_unix_setpwent.c
new file mode 100644
index 0000000..666680b
--- /dev/null
+++ b/src/libnsss/nsss_unix_setpwent.c
@@ -0,0 +1,11 @@
+/* ISC license. */
+
+#include <nsss/pwd-unix.h>
+#include <nsss/nsss-unix.h>
+#include "nsss-unix-internal.h"
+
+void nsss_unix_setpwent (void)
+{
+ if (!nsss_unix_pwd_maybe_start(&nsss_unix_pwd_here)) return ;
+ nsss_unix_pwd_rewind(&nsss_unix_pwd_here) ;
+}
diff --git a/src/libnsss/nsss_unix_setspent.c b/src/libnsss/nsss_unix_setspent.c
new file mode 100644
index 0000000..2b38e8d
--- /dev/null
+++ b/src/libnsss/nsss_unix_setspent.c
@@ -0,0 +1,11 @@
+/* ISC license. */
+
+#include <nsss/shadow-unix.h>
+#include <nsss/nsss-unix.h>
+#include "nsss-unix-internal.h"
+
+void nsss_unix_setspent (void)
+{
+ if (!nsss_unix_shadow_maybe_start(&nsss_unix_shadow_here)) return ;
+ nsss_unix_shadow_rewind(&nsss_unix_shadow_here) ;
+}
diff --git a/src/libnsss/nsss_unix_shadow_get.c b/src/libnsss/nsss_unix_shadow_get.c
new file mode 100644
index 0000000..0d87088
--- /dev/null
+++ b/src/libnsss/nsss_unix_shadow_get.c
@@ -0,0 +1,52 @@
+/* ISC license. */
+
+#include <pthread.h>
+#include <skalibs/types.h>
+#include <skalibs/skamisc.h>
+#include <nsss/shadow-def.h>
+#include <nsss/nsss-unix.h>
+#include "nsss-unix-internal.h"
+
+static inline int shadow_parseline (struct spwd *sp, char *s, size_t max)
+{
+ struct spwd sp2 ;
+ char *p ;
+ s[max-1] = 0 ;
+ if (!nsss_unix_field(&sp2.sp_namp, &s)) return 0 ;
+ if (!nsss_unix_field(&sp2.sp_pwdp, &s)) return 0 ;
+ if (!nsss_unix_field(&p, &s)) return 0 ;
+ if (!ulong0_scan(p, (unsigned long *)&sp2.sp_lstchg)) return 0 ;
+ if (!nsss_unix_field(&p, &s)) return 0 ;
+ if (!ulong0_scan(p, (unsigned long *)&sp2.sp_min)) return 0 ;
+ if (!nsss_unix_field(&p, &s)) return 0 ;
+ if (!ulong0_scan(p, (unsigned long *)&sp2.sp_max)) return 0 ;
+ if (!nsss_unix_field(&p, &s)) return 0 ;
+ if (!ulong0_scan(p, (unsigned long *)&sp2.sp_warn)) return 0 ;
+ if (!nsss_unix_field(&p, &s)) return 0 ;
+ if (!ulong0_scan(p, (unsigned long *)&sp2.sp_inact)) return 0 ;
+ if (!nsss_unix_field(&p, &s)) return 0 ;
+ if (!ulong0_scan(p, (unsigned long *)&sp2.sp_expire)) return 0 ;
+ if (!nsss_unix_field(&p, &s)) return 0 ;
+ if (!ulong0_scan(p, &sp2.sp_flag)) return 0 ;
+ *sp = sp2 ;
+ return 1 ;
+}
+
+int nsss_unix_shadow_get (nsss_unix_t *a, struct spwd *sp, stralloc *sa)
+{
+ int cs ;
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs) ;
+ for (;;)
+ {
+ size_t base = sa->len ;
+ if (skagetln_loose(&a->b, sa, '\n') <= 0) goto err ;
+ if (shadow_parseline(sp, sa->s + base, sa->len - base)) break ;
+ sa->len = base ;
+ }
+ pthread_setcancelstate(cs, 0) ;
+ return 1 ;
+
+ err:
+ pthread_setcancelstate(cs, 0) ;
+ return 0 ;
+}
diff --git a/src/libnsss/nsss_unix_shadow_getbyname.c b/src/libnsss/nsss_unix_shadow_getbyname.c
new file mode 100644
index 0000000..154e5ec
--- /dev/null
+++ b/src/libnsss/nsss_unix_shadow_getbyname.c
@@ -0,0 +1,19 @@
+/* ISC license. */
+
+#include <string.h>
+#include <nsss/shadow-def.h>
+#include <nsss/nsss-unix.h>
+
+int nsss_unix_shadow_getbyname (nsss_unix_t *a, struct spwd *sp, stralloc *sa, char const *name)
+{
+ struct spwd sp2 ;
+ for (;;)
+ {
+ size_t base = sa->len ;
+ if (!nsss_unix_shadow_get(a, &sp2, sa)) return 0 ;
+ if (!strcmp(name, sp2.sp_namp)) break ;
+ sa->len = base ;
+ }
+ *sp = sp2 ;
+ return 1 ;
+}
diff --git a/src/libnsss/nsss_unix_shadow_here.c b/src/libnsss/nsss_unix_shadow_here.c
new file mode 100644
index 0000000..2f500f4
--- /dev/null
+++ b/src/libnsss/nsss_unix_shadow_here.c
@@ -0,0 +1,5 @@
+/* ISC license. */
+
+#include "nsss-unix-internal.h"
+
+nsss_unix_t nsss_unix_shadow_here = NSSS_UNIX_ZERO ;
diff --git a/src/libnsss/nsss_unix_start.c b/src/libnsss/nsss_unix_start.c
new file mode 100644
index 0000000..1f6c5df
--- /dev/null
+++ b/src/libnsss/nsss_unix_start.c
@@ -0,0 +1,13 @@
+/* ISC license. */
+
+#include <skalibs/buffer.h>
+#include <skalibs/djbunix.h>
+#include <nsss/nsss-unix.h>
+
+int nsss_unix_start (nsss_unix_t *a, char const *path)
+{
+ int fd = open_readb(path) ;
+ if (fd < 0) return 0 ;
+ buffer_init(&a->b, &buffer_read, fd, a->buf, NSSS_UNIX_BUFSIZE) ;
+ return 1 ;
+}