summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--NEWS2
-rw-r--r--doc/index.html3
-rw-r--r--doc/libnsssd/index.html8
-rw-r--r--doc/nsssd-switch.html105
-rw-r--r--doc/upgrade.html3
-rwxr-xr-xexamples/openrc/nsssd2
-rw-r--r--examples/s6-rc/nsssd-log/pipeline-name (renamed from examples/s6-rc/nsssd/pipeline-name)0
-rw-r--r--examples/s6-rc/nsssd/dependencies1
-rw-r--r--examples/s6-rc/nsssd/run4
-rwxr-xr-xexamples/s6/nsssd/run4
-rw-r--r--package/deps.mak43
-rw-r--r--package/info2
-rw-r--r--package/modes1
-rw-r--r--package/targets.mak3
-rw-r--r--src/include/nsss/nsss-switch.h31
-rw-r--r--src/include/nsss/nsssd.h4
-rw-r--r--src/libnsss/deps-lib/nsss9
-rw-r--r--src/libnsss/nsss-switch-internal.h17
-rw-r--r--src/libnsss/nsss_all_getgrent.c4
-rw-r--r--src/libnsss/nsss_all_getgrent_r.c4
-rw-r--r--src/libnsss/nsss_all_getpwent.c4
-rw-r--r--src/libnsss/nsss_all_getpwent_r.c4
-rw-r--r--src/libnsss/nsss_all_getspent.c4
-rw-r--r--src/libnsss/nsss_all_getspent_r.c4
-rw-r--r--src/libnsss/nsss_all_setgrent.c4
-rw-r--r--src/libnsss/nsss_all_setpwent.c4
-rw-r--r--src/libnsss/nsss_all_setspent.c4
-rw-r--r--src/libnsss/nsss_switch_end.c3
-rw-r--r--src/libnsss/nsss_switch_endgrent.c8
-rw-r--r--src/libnsss/nsss_switch_endpwent.c8
-rw-r--r--src/libnsss/nsss_switch_endspent.c8
-rw-r--r--src/libnsss/nsss_switch_enumerator.c9
-rw-r--r--src/libnsss/nsss_switch_getgrent.c4
-rw-r--r--src/libnsss/nsss_switch_getgrent_r.c17
-rw-r--r--src/libnsss/nsss_switch_getgrgid.c13
-rw-r--r--src/libnsss/nsss_switch_getgrgid_r.c21
-rw-r--r--src/libnsss/nsss_switch_getgrnam.c13
-rw-r--r--src/libnsss/nsss_switch_getgrnam_r.c21
-rw-r--r--src/libnsss/nsss_switch_getgrouplist.c16
-rw-r--r--src/libnsss/nsss_switch_getpwent.c4
-rw-r--r--src/libnsss/nsss_switch_getpwent_r.c17
-rw-r--r--src/libnsss/nsss_switch_getpwnam.c12
-rw-r--r--src/libnsss/nsss_switch_getpwnam_r.c21
-rw-r--r--src/libnsss/nsss_switch_getpwuid.c12
-rw-r--r--src/libnsss/nsss_switch_getpwuid_r.c21
-rw-r--r--src/libnsss/nsss_switch_getspent.c4
-rw-r--r--src/libnsss/nsss_switch_getspent_r.c17
-rw-r--r--src/libnsss/nsss_switch_getspnam.c12
-rw-r--r--src/libnsss/nsss_switch_getspnam_r.c21
-rw-r--r--src/libnsss/nsss_switch_grp_get.c5
-rw-r--r--src/libnsss/nsss_switch_grp_getbygid.c5
-rw-r--r--src/libnsss/nsss_switch_grp_getbyname.c5
-rw-r--r--src/libnsss/nsss_switch_grp_getlist.c3
-rw-r--r--src/libnsss/nsss_switch_op.c5
-rw-r--r--src/libnsss/nsss_switch_pwd_get.c5
-rw-r--r--src/libnsss/nsss_switch_pwd_getbyname.c5
-rw-r--r--src/libnsss/nsss_switch_pwd_getbyuid.c5
-rw-r--r--src/libnsss/nsss_switch_query.c (renamed from src/libnsss/nsss_switch_here.c)4
-rw-r--r--src/libnsss/nsss_switch_query_mutex.c7
-rw-r--r--src/libnsss/nsss_switch_query_start.c12
-rw-r--r--src/libnsss/nsss_switch_send.c25
-rw-r--r--src/libnsss/nsss_switch_sendv.c25
-rw-r--r--src/libnsss/nsss_switch_set_timeout.c21
-rw-r--r--src/libnsss/nsss_switch_setgrent.c4
-rw-r--r--src/libnsss/nsss_switch_setpwent.c4
-rw-r--r--src/libnsss/nsss_switch_setspent.c4
-rw-r--r--src/libnsss/nsss_switch_shadow_get.c5
-rw-r--r--src/libnsss/nsss_switch_shadow_getbyname.c5
-rw-r--r--src/libnsss/nsss_switch_start.c3
-rw-r--r--src/libnsss/nsss_switch_startf.c26
-rw-r--r--src/nsssd/deps-exe/nsssd-switch5
-rw-r--r--src/nsssd/deps-exe/nsssd-unix2
-rw-r--r--src/nsssd/nsssd-nslcd.c9
-rw-r--r--src/nsssd/nsssd-switch.c292
-rw-r--r--src/nsssd/nsssd-unix.c9
-rw-r--r--src/nsssd/nsssd_main.c41
77 files changed, 891 insertions, 211 deletions
diff --git a/.gitignore b/.gitignore
index 85df6b0..4fb2d9b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,4 +8,5 @@
 /libnsssd.so.xyzzy
 /nsssd-unix
 /nsssd-nslcd
+/nsssd-switch
 /test-*
diff --git a/NEWS b/NEWS
index 161e779..5c7aa75 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,6 @@
 Changelog for nsss.
 
-In 0.1.0.2
+In 0.2.0.0
 ----------
 
  - Adaptation to skalibs-2.11.0.0.
diff --git a/doc/index.html b/doc/index.html
index 6af20c4..c774b03 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -100,7 +100,7 @@ for <a href="//skarnet.org/software/s6/s6-ipcserver">s6-ipcserver</a>). </li>
 <h3> Download </h3>
 
 <ul>
- <li> The current released version of nsss is <a href="nsss-0.1.0.2.tar.gz">0.1.0.2</a>. </li>
+ <li> The current released version of nsss is <a href="nsss-0.2.0.0.tar.gz">0.2.0.0</a>. </li>
  <li> Alternatively, you can checkout a copy of the
 <a href="//git.skarnet.org/cgi-bin/cgit.cgi/nsss/">nsss
 git repository</a>:
@@ -143,6 +143,7 @@ backend to the name service.
 <ul>
  <li> The <a href="nsssd-unix.html"><tt>nsssd-unix</tt></a> program </li>
  <li> The <a href="nsssd-nslcd.html"><tt>nsssd-nslcd</tt></a> program </li>
+ <li> The <a href="nsssd-switch.html"><tt>nsssd-switch</tt></a> program </li>
 </ul>
 
 <p>
diff --git a/doc/libnsssd/index.html b/doc/libnsssd/index.html
index 4cbff45..7e0cd82 100644
--- a/doc/libnsssd/index.html
+++ b/doc/libnsssd/index.html
@@ -57,8 +57,8 @@ the name of your program to the PROG variable. Example:
  <li> Your <tt>main()</tt> function can parse options and
 take command line arguments as it sees fit. But once it's done
 parsing options, give control to the <tt>nsssd_main()</tt>
-function, using your <em>argv</em> and <em>envp</em> as
-arguments: <tt>return nsssd_main(argv, envp);</tt> </li>
+function, using your <em>argv</em> as an argument:
+<tt>return nsssd_main(argv);</tt> </li>
 </ul>
 
 <p>
@@ -74,10 +74,10 @@ backend; the pointer to your handle will be passed to every
 subsequent function. The function must not return NULL.
 </p>
 
-<h4><code>int nsssd_handle_start (void *handle, char const *const *argv, char const *const *envp)</code></h4>
+<h4><code>int nsssd_handle_start (void *handle, char const *const *argv)</code></h4>
 <p>
 This function must <em>initialize the handle</em>. The arguments
-it receives are the <em>argv</em> and <em>envp</em> that have been
+it takes are a pointer to the handle and the <em>argv</em> that has been
 passed to <tt>nsssd_main()</tt>. This allows you to write daemons
 that can be somewhat configured via the command line: it is how
 <a href="../nsssd-nslcd.html">nsssd-nslcd</a> takes an argument
diff --git a/doc/nsssd-switch.html b/doc/nsssd-switch.html
new file mode 100644
index 0000000..9f5672c
--- /dev/null
+++ b/doc/nsssd-switch.html
@@ -0,0 +1,105 @@
+<html>
+  <head>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+    <meta http-equiv="Content-Language" content="en" />
+    <title>nsss: the nsssd-switch program</title>
+    <meta name="Description" content="nsss: the nsssd-switch program" />
+    <meta name="Keywords" content="nsss name service switch nsssd unix daemon service nsssd-switch" />
+    <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
+  </head>
+<body>
+
+<p>
+<a href="index.html">nsss</a><br />
+<a href="//skarnet.org/software/">Software</a><br />
+<a href="//skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> The nsssd-switch program </h1>
+
+<p>
+<tt>nsssd-switch</tt> is a daemon providing a backend for clients using the
+<a href="libnsss/">nsss library</a> - more precisely, clients using
+the <a href="libnsss/nsss-all.html">nsss-all</a> or
+the <a href="libnsss/nsss-switch.html">nsss-switch</a> functions.
+</p>
+
+<p>
+ The <tt>nsssd-switch</tt> backend is the real point of the <a href="index.html">nsss</a>
+package: it allows a complex configuration using different other backends,
+similarly to the <a href="nsswitch.html">/etc/nsswitch.conf</a> mechanism
+but without its drawbacks. It accomplishes this by reading its backend
+configuration on the command line.
+</p>
+
+<h2> Interface </h2>
+
+<pre>
+     s6-ipcserver -l0 /run/service/nsssd/s nsssd-switch <em>bitfield1</em> <em>backend1...</em> "" <em>bitfield2</em> <em>backend2...</em> "" ...
+</pre>
+
+<p>
+ or, in an <a href="//skarnet.org/software/execline/">execline</a> script:
+</p>
+
+<pre>
+     s6-ipcserver -l0 /run/service/nsssd/s
+     nsssd-switch
+       <em>bitfield1</em> { <em>backend1...</em> }
+       <em>bitfield2</em> { <em>backend2...</em> }
+       ...
+</pre>
+
+<ul>
+ <li> <tt>nsssd-switch</tt>
+</ul>
+
+
+<h2> Notes </h2>
+
+<p>
+ nsssd-switch is not meant to be called directly; instead, it is expected to be run from
+a script as a part of a "nsssd"
+<a href="//skarnet.org/software/s6/localservice.html">local service</a>.
+</p>
+
+<p>
+ The <tt>examples/</tt> subdirectory of the nsss package provides examples
+on how to run such a service.
+ The simplest way to do so, for testing purposes, is a command line such as:
+</p>
+<pre>s6-ipcserver -l0 /run/service/nsssd/s nsssd-switch 0 nsssd-unix "" </pre>
+
+<p>
+<tt>/run/service/nsssd/s</tt> is the default place where nsss's
+implementation of the <tt>pwd.h</tt>, <tt>grp.h</tt> and <tt>shadow.h</tt>
+functions expects the nsssd
+service to be. It can be changed at nsss build time by giving the
+<tt>--with-nsssd-socket=PATH</tt> option to configure.
+</p>
+
+<p>
+ nsssd-switch does not listen to the socket itself: it reads from its
+standard input and writes to its standard output. It relies
+on a superserver such as
+<a href="//skarnet.org/software/s6/s6-ipcserver.html">s6-ipcserver</a>
+to manage connections to the socket. An instance of nsssd-switch is run
+for every client connection.
+</p>
+
+<p>
+ If fine-grained authorizations are required (only allowing
+certain users and groups to connect to the service), the superserver
+can be configured to enforce them.
+</p>
+
+<p>
+ nsssd-switch does not need to run as root, provided it has all the
+permissions needed by the backends it spawns.
+It is recommended to create a <em>nsss</em> user and group, dedicated to
+the nsssd service, and run the superserver as this user and group.
+</p>
+
+</body>
+</html>
diff --git a/doc/upgrade.html b/doc/upgrade.html
index fa22bcb..d580203 100644
--- a/doc/upgrade.html
+++ b/doc/upgrade.html
@@ -18,13 +18,14 @@
 
 <h1> What has changed in nsss </h1>
 
-<h2> In 0.1.0.2 </h2>
+<h2> In 0.2.0.0 </h2>
 
 <ul>
  <li> <a href="//skarnet.org/software/skalibs/">skalibs</a> dependency bumped to
 2.11.0.0. </li>
  <li> <a href="//skarnet.org/software/s6/">s6</a> optional dependency bumped to
 2.11.0.0. </li>
+ <li> New binary: <a href="nsssd-switch.html">nsssd-switch</a>. </li>
 </ul>
 
 <h2> In 0.1.0.1 </h2>
diff --git a/examples/openrc/nsssd b/examples/openrc/nsssd
index 1221f89..8789f3b 100755
--- a/examples/openrc/nsssd
+++ b/examples/openrc/nsssd
@@ -2,7 +2,7 @@
 
 name="nsssd"
 command="s6-envuidgid"
-command_args="nsss s6-ipcserver -U -- /run/service/nsssd/s nsssd-unix"
+command_args="nsss s6-ipcserver -U -- /run/service/nsssd/s nsssd-switch 0 nsssd-nslcd '' 0 nsssd-unix ''"
 command_background=yes
 pidfile="/run/service/nsssd/nsssd.pid"
 start_stop_daemon_args="-d /run/service/nsssd"
diff --git a/examples/s6-rc/nsssd/pipeline-name b/examples/s6-rc/nsssd-log/pipeline-name
index 84fdc32..84fdc32 100644
--- a/examples/s6-rc/nsssd/pipeline-name
+++ b/examples/s6-rc/nsssd-log/pipeline-name
diff --git a/examples/s6-rc/nsssd/dependencies b/examples/s6-rc/nsssd/dependencies
deleted file mode 100644
index 8b13789..0000000
--- a/examples/s6-rc/nsssd/dependencies
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/examples/s6-rc/nsssd/run b/examples/s6-rc/nsssd/run
index 626edd4..458e632 100644
--- a/examples/s6-rc/nsssd/run
+++ b/examples/s6-rc/nsssd/run
@@ -4,4 +4,6 @@ fdmove -c 2 1
 s6-envuidgid nsss
 fdmove 1 3
 s6-ipcserver -1 -U -- s
-nsssd-unix
+nsssd-switch
+  0 { nsssd-nslcd }
+  0 { nsssd-unix }
diff --git a/examples/s6/nsssd/run b/examples/s6/nsssd/run
index 626edd4..458e632 100755
--- a/examples/s6/nsssd/run
+++ b/examples/s6/nsssd/run
@@ -4,4 +4,6 @@ fdmove -c 2 1
 s6-envuidgid nsss
 fdmove 1 3
 s6-ipcserver -1 -U -- s
-nsssd-unix
+nsssd-switch
+  0 { nsssd-nslcd }
+  0 { nsssd-unix }
diff --git a/package/deps.mak b/package/deps.mak
index 96b6953..bde2f68 100644
--- a/package/deps.mak
+++ b/package/deps.mak
@@ -60,31 +60,31 @@ src/libnsss/nsss_switch_end.o src/libnsss/nsss_switch_end.lo: src/libnsss/nsss_s
 src/libnsss/nsss_switch_endgrent.o src/libnsss/nsss_switch_endgrent.lo: src/libnsss/nsss_switch_endgrent.c src/libnsss/nsss-switch-internal.h src/include/nsss/grp-switch.h
 src/libnsss/nsss_switch_endpwent.o src/libnsss/nsss_switch_endpwent.lo: src/libnsss/nsss_switch_endpwent.c src/libnsss/nsss-switch-internal.h src/include/nsss/pwd-switch.h
 src/libnsss/nsss_switch_endspent.o src/libnsss/nsss_switch_endspent.lo: src/libnsss/nsss_switch_endspent.c src/libnsss/nsss-switch-internal.h src/include/nsss/shadow-switch.h
+src/libnsss/nsss_switch_enumerator.o src/libnsss/nsss_switch_enumerator.lo: src/libnsss/nsss_switch_enumerator.c src/libnsss/nsss-switch-internal.h src/include/nsss/nsss-switch.h
 src/libnsss/nsss_switch_getgrent.o src/libnsss/nsss_switch_getgrent.lo: src/libnsss/nsss_switch_getgrent.c src/libnsss/nsss-internal.h src/libnsss/nsss-switch-internal.h src/include/nsss/config.h src/include/nsss/grp-switch.h src/include/nsss/nsss-switch.h
 src/libnsss/nsss_switch_getgrent_r.o src/libnsss/nsss_switch_getgrent_r.lo: src/libnsss/nsss_switch_getgrent_r.c src/libnsss/nsss-internal.h src/libnsss/nsss-switch-internal.h src/include/nsss/config.h src/include/nsss/grp-switch.h src/include/nsss/nsss-switch.h
-src/libnsss/nsss_switch_getgrgid.o src/libnsss/nsss_switch_getgrgid.lo: src/libnsss/nsss_switch_getgrgid.c src/libnsss/nsss-internal.h src/include/nsss/config.h src/include/nsss/grp-switch.h src/include/nsss/nsss-switch.h
-src/libnsss/nsss_switch_getgrgid_r.o src/libnsss/nsss_switch_getgrgid_r.lo: src/libnsss/nsss_switch_getgrgid_r.c src/libnsss/nsss-internal.h src/include/nsss/config.h src/include/nsss/grp-switch.h src/include/nsss/nsss-switch.h
-src/libnsss/nsss_switch_getgrnam.o src/libnsss/nsss_switch_getgrnam.lo: src/libnsss/nsss_switch_getgrnam.c src/libnsss/nsss-internal.h src/include/nsss/config.h src/include/nsss/grp-switch.h src/include/nsss/nsss-switch.h
-src/libnsss/nsss_switch_getgrnam_r.o src/libnsss/nsss_switch_getgrnam_r.lo: src/libnsss/nsss_switch_getgrnam_r.c src/libnsss/nsss-internal.h src/include/nsss/config.h src/include/nsss/grp-switch.h src/include/nsss/nsss-switch.h
-src/libnsss/nsss_switch_getgrouplist.o src/libnsss/nsss_switch_getgrouplist.lo: src/libnsss/nsss_switch_getgrouplist.c src/libnsss/nsss-internal.h src/include/nsss/config.h src/include/nsss/grp-switch.h src/include/nsss/nsss-switch.h
+src/libnsss/nsss_switch_getgrgid.o src/libnsss/nsss_switch_getgrgid.lo: src/libnsss/nsss_switch_getgrgid.c src/libnsss/nsss-internal.h src/libnsss/nsss-switch-internal.h src/include/nsss/config.h src/include/nsss/grp-switch.h src/include/nsss/nsss-switch.h
+src/libnsss/nsss_switch_getgrgid_r.o src/libnsss/nsss_switch_getgrgid_r.lo: src/libnsss/nsss_switch_getgrgid_r.c src/libnsss/nsss-internal.h src/libnsss/nsss-switch-internal.h src/include/nsss/config.h src/include/nsss/grp-switch.h src/include/nsss/nsss-switch.h
+src/libnsss/nsss_switch_getgrnam.o src/libnsss/nsss_switch_getgrnam.lo: src/libnsss/nsss_switch_getgrnam.c src/libnsss/nsss-internal.h src/libnsss/nsss-switch-internal.h src/include/nsss/config.h src/include/nsss/grp-switch.h src/include/nsss/nsss-switch.h
+src/libnsss/nsss_switch_getgrnam_r.o src/libnsss/nsss_switch_getgrnam_r.lo: src/libnsss/nsss_switch_getgrnam_r.c src/libnsss/nsss-internal.h src/libnsss/nsss-switch-internal.h src/include/nsss/config.h src/include/nsss/grp-switch.h src/include/nsss/nsss-switch.h
+src/libnsss/nsss_switch_getgrouplist.o src/libnsss/nsss_switch_getgrouplist.lo: src/libnsss/nsss_switch_getgrouplist.c src/libnsss/nsss-internal.h src/libnsss/nsss-switch-internal.h src/include/nsss/config.h src/include/nsss/grp-switch.h src/include/nsss/nsss-switch.h
 src/libnsss/nsss_switch_getpwent.o src/libnsss/nsss_switch_getpwent.lo: src/libnsss/nsss_switch_getpwent.c src/libnsss/nsss-internal.h src/libnsss/nsss-switch-internal.h src/include/nsss/config.h src/include/nsss/nsss-switch.h src/include/nsss/pwd-switch.h
 src/libnsss/nsss_switch_getpwent_r.o src/libnsss/nsss_switch_getpwent_r.lo: src/libnsss/nsss_switch_getpwent_r.c src/libnsss/nsss-internal.h src/libnsss/nsss-switch-internal.h src/include/nsss/config.h src/include/nsss/nsss-switch.h src/include/nsss/pwd-switch.h
-src/libnsss/nsss_switch_getpwnam.o src/libnsss/nsss_switch_getpwnam.lo: src/libnsss/nsss_switch_getpwnam.c src/libnsss/nsss-internal.h src/include/nsss/config.h src/include/nsss/nsss-switch.h src/include/nsss/pwd-switch.h
-src/libnsss/nsss_switch_getpwnam_r.o src/libnsss/nsss_switch_getpwnam_r.lo: src/libnsss/nsss_switch_getpwnam_r.c src/libnsss/nsss-internal.h src/include/nsss/config.h src/include/nsss/nsss-switch.h src/include/nsss/pwd-switch.h
-src/libnsss/nsss_switch_getpwuid.o src/libnsss/nsss_switch_getpwuid.lo: src/libnsss/nsss_switch_getpwuid.c src/libnsss/nsss-internal.h src/include/nsss/config.h src/include/nsss/nsss-switch.h src/include/nsss/pwd-switch.h
-src/libnsss/nsss_switch_getpwuid_r.o src/libnsss/nsss_switch_getpwuid_r.lo: src/libnsss/nsss_switch_getpwuid_r.c src/libnsss/nsss-internal.h src/include/nsss/config.h src/include/nsss/nsss-switch.h src/include/nsss/pwd-switch.h
+src/libnsss/nsss_switch_getpwnam.o src/libnsss/nsss_switch_getpwnam.lo: src/libnsss/nsss_switch_getpwnam.c src/libnsss/nsss-internal.h src/libnsss/nsss-switch-internal.h src/include/nsss/config.h src/include/nsss/nsss-switch.h src/include/nsss/pwd-switch.h
+src/libnsss/nsss_switch_getpwnam_r.o src/libnsss/nsss_switch_getpwnam_r.lo: src/libnsss/nsss_switch_getpwnam_r.c src/libnsss/nsss-internal.h src/libnsss/nsss-switch-internal.h src/include/nsss/config.h src/include/nsss/nsss-switch.h src/include/nsss/pwd-switch.h
+src/libnsss/nsss_switch_getpwuid.o src/libnsss/nsss_switch_getpwuid.lo: src/libnsss/nsss_switch_getpwuid.c src/libnsss/nsss-internal.h src/libnsss/nsss-switch-internal.h src/include/nsss/config.h src/include/nsss/nsss-switch.h src/include/nsss/pwd-switch.h
+src/libnsss/nsss_switch_getpwuid_r.o src/libnsss/nsss_switch_getpwuid_r.lo: src/libnsss/nsss_switch_getpwuid_r.c src/libnsss/nsss-internal.h src/libnsss/nsss-switch-internal.h src/include/nsss/config.h src/include/nsss/nsss-switch.h src/include/nsss/pwd-switch.h
 src/libnsss/nsss_switch_getspent.o src/libnsss/nsss_switch_getspent.lo: src/libnsss/nsss_switch_getspent.c src/libnsss/nsss-internal.h src/libnsss/nsss-switch-internal.h src/include/nsss/config.h src/include/nsss/nsss-switch.h src/include/nsss/shadow-switch.h
 src/libnsss/nsss_switch_getspent_r.o src/libnsss/nsss_switch_getspent_r.lo: src/libnsss/nsss_switch_getspent_r.c src/libnsss/nsss-internal.h src/libnsss/nsss-switch-internal.h src/include/nsss/config.h src/include/nsss/nsss-switch.h src/include/nsss/shadow-switch.h
-src/libnsss/nsss_switch_getspnam.o src/libnsss/nsss_switch_getspnam.lo: src/libnsss/nsss_switch_getspnam.c src/libnsss/nsss-internal.h src/include/nsss/config.h src/include/nsss/nsss-switch.h src/include/nsss/shadow-switch.h
-src/libnsss/nsss_switch_getspnam_r.o src/libnsss/nsss_switch_getspnam_r.lo: src/libnsss/nsss_switch_getspnam_r.c src/libnsss/nsss-internal.h src/include/nsss/config.h src/include/nsss/nsss-switch.h src/include/nsss/shadow-switch.h
+src/libnsss/nsss_switch_getspnam.o src/libnsss/nsss_switch_getspnam.lo: src/libnsss/nsss_switch_getspnam.c src/libnsss/nsss-internal.h src/libnsss/nsss-switch-internal.h src/include/nsss/config.h src/include/nsss/nsss-switch.h src/include/nsss/shadow-switch.h
+src/libnsss/nsss_switch_getspnam_r.o src/libnsss/nsss_switch_getspnam_r.lo: src/libnsss/nsss_switch_getspnam_r.c src/libnsss/nsss-internal.h src/libnsss/nsss-switch-internal.h src/include/nsss/config.h src/include/nsss/nsss-switch.h src/include/nsss/shadow-switch.h
 src/libnsss/nsss_switch_grp_end.o src/libnsss/nsss_switch_grp_end.lo: src/libnsss/nsss_switch_grp_end.c src/libnsss/nsss-switch-internal.h src/include/nsss/nsss-switch.h
 src/libnsss/nsss_switch_grp_get.o src/libnsss/nsss_switch_grp_get.lo: src/libnsss/nsss_switch_grp_get.c src/libnsss/nsss-switch-internal.h src/include/nsss/nsss-switch.h
 src/libnsss/nsss_switch_grp_getbygid.o src/libnsss/nsss_switch_grp_getbygid.lo: src/libnsss/nsss_switch_grp_getbygid.c src/libnsss/nsss-switch-internal.h src/include/nsss/nsss-switch.h
 src/libnsss/nsss_switch_grp_getbyname.o src/libnsss/nsss_switch_grp_getbyname.lo: src/libnsss/nsss_switch_grp_getbyname.c src/libnsss/nsss-switch-internal.h src/include/nsss/nsss-switch.h
-src/libnsss/nsss_switch_grp_getlist.o src/libnsss/nsss_switch_grp_getlist.lo: src/libnsss/nsss_switch_grp_getlist.c src/include/nsss/nsss-switch.h
+src/libnsss/nsss_switch_grp_getlist.o src/libnsss/nsss_switch_grp_getlist.lo: src/libnsss/nsss_switch_grp_getlist.c src/libnsss/nsss-switch-internal.h src/include/nsss/nsss-switch.h
 src/libnsss/nsss_switch_grp_read.o src/libnsss/nsss_switch_grp_read.lo: src/libnsss/nsss_switch_grp_read.c src/libnsss/nsss-switch-internal.h src/include/nsss/grp-def.h
 src/libnsss/nsss_switch_grp_rewind.o src/libnsss/nsss_switch_grp_rewind.lo: src/libnsss/nsss_switch_grp_rewind.c src/libnsss/nsss-switch-internal.h src/include/nsss/nsss-switch.h
-src/libnsss/nsss_switch_here.o src/libnsss/nsss_switch_here.lo: src/libnsss/nsss_switch_here.c src/libnsss/nsss-switch-internal.h src/include/nsss/nsss-switch.h
 src/libnsss/nsss_switch_op.o src/libnsss/nsss_switch_op.lo: src/libnsss/nsss_switch_op.c src/libnsss/nsss-switch-internal.h src/include/nsss/nsss-switch.h
 src/libnsss/nsss_switch_pwd_end.o src/libnsss/nsss_switch_pwd_end.lo: src/libnsss/nsss_switch_pwd_end.c src/libnsss/nsss-switch-internal.h src/include/nsss/nsss-switch.h
 src/libnsss/nsss_switch_pwd_get.o src/libnsss/nsss_switch_pwd_get.lo: src/libnsss/nsss_switch_pwd_get.c src/libnsss/nsss-switch-internal.h src/include/nsss/nsss-switch.h
@@ -92,6 +92,12 @@ src/libnsss/nsss_switch_pwd_getbyname.o src/libnsss/nsss_switch_pwd_getbyname.lo
 src/libnsss/nsss_switch_pwd_getbyuid.o src/libnsss/nsss_switch_pwd_getbyuid.lo: src/libnsss/nsss_switch_pwd_getbyuid.c src/libnsss/nsss-switch-internal.h src/include/nsss/nsss-switch.h
 src/libnsss/nsss_switch_pwd_read.o src/libnsss/nsss_switch_pwd_read.lo: src/libnsss/nsss_switch_pwd_read.c src/libnsss/nsss-switch-internal.h src/include/nsss/pwd-def.h
 src/libnsss/nsss_switch_pwd_rewind.o src/libnsss/nsss_switch_pwd_rewind.lo: src/libnsss/nsss_switch_pwd_rewind.c src/libnsss/nsss-switch-internal.h src/include/nsss/nsss-switch.h
+src/libnsss/nsss_switch_query.o src/libnsss/nsss_switch_query.lo: src/libnsss/nsss_switch_query.c src/libnsss/nsss-switch-internal.h src/include/nsss/nsss-switch.h
+src/libnsss/nsss_switch_query_mutex.o src/libnsss/nsss_switch_query_mutex.lo: src/libnsss/nsss_switch_query_mutex.c src/libnsss/nsss-switch-internal.h
+src/libnsss/nsss_switch_query_start.o src/libnsss/nsss_switch_query_start.lo: src/libnsss/nsss_switch_query_start.c src/libnsss/nsss-switch-internal.h src/include/nsss/nsss-switch.h
+src/libnsss/nsss_switch_send.o src/libnsss/nsss_switch_send.lo: src/libnsss/nsss_switch_send.c src/libnsss/nsss-switch-internal.h src/include/nsss/nsss-switch.h
+src/libnsss/nsss_switch_sendv.o src/libnsss/nsss_switch_sendv.lo: src/libnsss/nsss_switch_sendv.c src/libnsss/nsss-switch-internal.h src/include/nsss/nsss-switch.h
+src/libnsss/nsss_switch_set_timeout.o src/libnsss/nsss_switch_set_timeout.lo: src/libnsss/nsss_switch_set_timeout.c src/libnsss/nsss-switch-internal.h src/include/nsss/nsss-switch.h
 src/libnsss/nsss_switch_setgrent.o src/libnsss/nsss_switch_setgrent.lo: src/libnsss/nsss_switch_setgrent.c src/libnsss/nsss-switch-internal.h src/include/nsss/config.h src/include/nsss/grp-switch.h src/include/nsss/nsss-switch.h
 src/libnsss/nsss_switch_setpwent.o src/libnsss/nsss_switch_setpwent.lo: src/libnsss/nsss_switch_setpwent.c src/libnsss/nsss-switch-internal.h src/include/nsss/config.h src/include/nsss/nsss-switch.h src/include/nsss/pwd-switch.h
 src/libnsss/nsss_switch_setspent.o src/libnsss/nsss_switch_setspent.lo: src/libnsss/nsss_switch_setspent.c src/libnsss/nsss-switch-internal.h src/include/nsss/config.h src/include/nsss/nsss-switch.h src/include/nsss/shadow-switch.h
@@ -101,6 +107,7 @@ src/libnsss/nsss_switch_shadow_getbyname.o src/libnsss/nsss_switch_shadow_getbyn
 src/libnsss/nsss_switch_shadow_read.o src/libnsss/nsss_switch_shadow_read.lo: src/libnsss/nsss_switch_shadow_read.c src/libnsss/nsss-switch-internal.h src/include/nsss/shadow-def.h
 src/libnsss/nsss_switch_shadow_rewind.o src/libnsss/nsss_switch_shadow_rewind.lo: src/libnsss/nsss_switch_shadow_rewind.c src/libnsss/nsss-switch-internal.h src/include/nsss/nsss-switch.h
 src/libnsss/nsss_switch_start.o src/libnsss/nsss_switch_start.lo: src/libnsss/nsss_switch_start.c src/include/nsss/nsss-switch.h
+src/libnsss/nsss_switch_startf.o src/libnsss/nsss_switch_startf.lo: src/libnsss/nsss_switch_startf.c src/include/nsss/nsss-switch.h
 src/libnsss/nsss_unix_end.o src/libnsss/nsss_unix_end.lo: src/libnsss/nsss_unix_end.c src/include/nsss/nsss-unix.h
 src/libnsss/nsss_unix_endgrent.o src/libnsss/nsss_unix_endgrent.lo: src/libnsss/nsss_unix_endgrent.c src/libnsss/nsss-unix-internal.h src/include/nsss/grp-unix.h
 src/libnsss/nsss_unix_endpwent.o src/libnsss/nsss_unix_endpwent.lo: src/libnsss/nsss_unix_endpwent.c src/libnsss/nsss-unix-internal.h src/include/nsss/pwd-unix.h
@@ -152,12 +159,12 @@ src/tests/test-switch.o src/tests/test-switch.lo: src/tests/test-switch.c src/in
 src/tests/test-unix.o src/tests/test-unix.lo: src/tests/test-unix.c src/include/nsss/grp-def.h src/include/nsss/nsss-unix.h src/include/nsss/pwd-def.h
 
 ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),)
-libnsss.a.xyzzy: src/libnsss/nsss_all_endgrent.o src/libnsss/nsss_all_endpwent.o src/libnsss/nsss_all_endspent.o src/libnsss/nsss_all_errno.o src/libnsss/nsss_all_getgrent.o src/libnsss/nsss_all_getgrent_r.o src/libnsss/nsss_all_getgrgid.o src/libnsss/nsss_all_getgrgid_r.o src/libnsss/nsss_all_getgrnam.o src/libnsss/nsss_all_getgrnam_r.o src/libnsss/nsss_all_getgrouplist.o src/libnsss/nsss_all_getpwent.o src/libnsss/nsss_all_getpwent_r.o src/libnsss/nsss_all_getpwnam.o src/libnsss/nsss_all_getpwnam_r.o src/libnsss/nsss_all_getpwuid.o src/libnsss/nsss_all_getpwuid_r.o src/libnsss/nsss_all_getspent.o src/libnsss/nsss_all_getspent_r.o src/libnsss/nsss_all_getspnam.o src/libnsss/nsss_all_getspnam_r.o src/libnsss/nsss_all_setgrent.o src/libnsss/nsss_all_setpwent.o src/libnsss/nsss_all_setspent.o src/libnsss/nsss_grp_copy.o src/libnsss/nsss_grp_here.o src/libnsss/nsss_grouplist_adjust.o src/libnsss/nsss_pwd_copy.o src/libnsss/nsss_pwd_here.o src/libnsss/nsss_shadow_copy.o src/libnsss/nsss_shadow_here.o src/libnsss/nsss_switch_end.o src/libnsss/nsss_switch_endgrent.o src/libnsss/nsss_switch_endpwent.o src/libnsss/nsss_switch_endspent.o src/libnsss/nsss_switch_getgrent.o src/libnsss/nsss_switch_getgrent_r.o src/libnsss/nsss_switch_getgrgid.o src/libnsss/nsss_switch_getgrgid_r.o src/libnsss/nsss_switch_getgrnam.o src/libnsss/nsss_switch_getgrnam_r.o src/libnsss/nsss_switch_getgrouplist.o src/libnsss/nsss_switch_getpwent.o src/libnsss/nsss_switch_getpwent_r.o src/libnsss/nsss_switch_getpwnam.o src/libnsss/nsss_switch_getpwnam_r.o src/libnsss/nsss_switch_getpwuid.o src/libnsss/nsss_switch_getpwuid_r.o src/libnsss/nsss_switch_getspent.o src/libnsss/nsss_switch_getspent_r.o src/libnsss/nsss_switch_getspnam.o src/libnsss/nsss_switch_getspnam_r.o src/libnsss/nsss_switch_grp_end.o src/libnsss/nsss_switch_grp_get.o src/libnsss/nsss_switch_grp_getbygid.o src/libnsss/nsss_switch_grp_getbyname.o src/libnsss/nsss_switch_grp_getlist.o src/libnsss/nsss_switch_grp_read.o src/libnsss/nsss_switch_grp_rewind.o src/libnsss/nsss_switch_here.o src/libnsss/nsss_switch_op.o src/libnsss/nsss_switch_pwd_end.o src/libnsss/nsss_switch_pwd_get.o src/libnsss/nsss_switch_pwd_getbyname.o src/libnsss/nsss_switch_pwd_getbyuid.o src/libnsss/nsss_switch_pwd_read.o src/libnsss/nsss_switch_pwd_rewind.o src/libnsss/nsss_switch_setgrent.o src/libnsss/nsss_switch_setpwent.o src/libnsss/nsss_switch_setspent.o src/libnsss/nsss_switch_shadow_end.o src/libnsss/nsss_switch_shadow_get.o src/libnsss/nsss_switch_shadow_getbyname.o src/libnsss/nsss_switch_shadow_read.o src/libnsss/nsss_switch_shadow_rewind.o src/libnsss/nsss_switch_start.o src/libnsss/nsss_unix_end.o src/libnsss/nsss_unix_endgrent.o src/libnsss/nsss_unix_endpwent.o src/libnsss/nsss_unix_endspent.o src/libnsss/nsss_unix_field.o src/libnsss/nsss_unix_getgrent.o src/libnsss/nsss_unix_getgrent_r.o src/libnsss/nsss_unix_getgrgid.o src/libnsss/nsss_unix_getgrgid_r.o src/libnsss/nsss_unix_getgrnam.o src/libnsss/nsss_unix_getgrnam_r.o src/libnsss/nsss_unix_getgrouplist.o src/libnsss/nsss_unix_getgrouplist_preadjust.o src/libnsss/nsss_unix_getpwent.o src/libnsss/nsss_unix_getpwent_r.o src/libnsss/nsss_unix_getpwnam.o src/libnsss/nsss_unix_getpwnam_r.o src/libnsss/nsss_unix_getpwuid.o src/libnsss/nsss_unix_getpwuid_r.o src/libnsss/nsss_unix_getspent.o src/libnsss/nsss_unix_getspent_r.o src/libnsss/nsss_unix_getspnam.o src/libnsss/nsss_unix_getspnam_r.o src/libnsss/nsss_unix_grp_get.o src/libnsss/nsss_unix_grp_getbygid.o src/libnsss/nsss_unix_grp_getbyname.o src/libnsss/nsss_unix_grp_getlist.o src/libnsss/nsss_unix_grp_here.o src/libnsss/nsss_unix_maybe_start.o src/libnsss/nsss_unix_pwd_get.o src/libnsss/nsss_unix_pwd_getbyname.o src/libnsss/nsss_unix_pwd_getbyuid.o src/libnsss/nsss_unix_pwd_here.o src/libnsss/nsss_unix_rewind.o src/libnsss/nsss_unix_setgrent.o src/libnsss/nsss_unix_setpwent.o src/libnsss/nsss_unix_setspent.o src/libnsss/nsss_unix_shadow_get.o src/libnsss/nsss_unix_shadow_getbyname.o src/libnsss/nsss_unix_shadow_here.o src/libnsss/nsss_unix_start.o
+libnsss.a.xyzzy: src/libnsss/nsss_all_endgrent.o src/libnsss/nsss_all_endpwent.o src/libnsss/nsss_all_endspent.o src/libnsss/nsss_all_errno.o src/libnsss/nsss_all_getgrent.o src/libnsss/nsss_all_getgrent_r.o src/libnsss/nsss_all_getgrgid.o src/libnsss/nsss_all_getgrgid_r.o src/libnsss/nsss_all_getgrnam.o src/libnsss/nsss_all_getgrnam_r.o src/libnsss/nsss_all_getgrouplist.o src/libnsss/nsss_all_getpwent.o src/libnsss/nsss_all_getpwent_r.o src/libnsss/nsss_all_getpwnam.o src/libnsss/nsss_all_getpwnam_r.o src/libnsss/nsss_all_getpwuid.o src/libnsss/nsss_all_getpwuid_r.o src/libnsss/nsss_all_getspent.o src/libnsss/nsss_all_getspent_r.o src/libnsss/nsss_all_getspnam.o src/libnsss/nsss_all_getspnam_r.o src/libnsss/nsss_all_setgrent.o src/libnsss/nsss_all_setpwent.o src/libnsss/nsss_all_setspent.o src/libnsss/nsss_grp_copy.o src/libnsss/nsss_grp_here.o src/libnsss/nsss_grouplist_adjust.o src/libnsss/nsss_pwd_copy.o src/libnsss/nsss_pwd_here.o src/libnsss/nsss_shadow_copy.o src/libnsss/nsss_shadow_here.o src/libnsss/nsss_switch_end.o src/libnsss/nsss_switch_endgrent.o src/libnsss/nsss_switch_endpwent.o src/libnsss/nsss_switch_endspent.o src/libnsss/nsss_switch_enumerator.o src/libnsss/nsss_switch_getgrent.o src/libnsss/nsss_switch_getgrent_r.o src/libnsss/nsss_switch_getgrgid.o src/libnsss/nsss_switch_getgrgid_r.o src/libnsss/nsss_switch_getgrnam.o src/libnsss/nsss_switch_getgrnam_r.o src/libnsss/nsss_switch_getgrouplist.o src/libnsss/nsss_switch_getpwent.o src/libnsss/nsss_switch_getpwent_r.o src/libnsss/nsss_switch_getpwnam.o src/libnsss/nsss_switch_getpwnam_r.o src/libnsss/nsss_switch_getpwuid.o src/libnsss/nsss_switch_getpwuid_r.o src/libnsss/nsss_switch_getspent.o src/libnsss/nsss_switch_getspent_r.o src/libnsss/nsss_switch_getspnam.o src/libnsss/nsss_switch_getspnam_r.o src/libnsss/nsss_switch_grp_end.o src/libnsss/nsss_switch_grp_get.o src/libnsss/nsss_switch_grp_getbygid.o src/libnsss/nsss_switch_grp_getbyname.o src/libnsss/nsss_switch_grp_getlist.o src/libnsss/nsss_switch_grp_read.o src/libnsss/nsss_switch_grp_rewind.o src/libnsss/nsss_switch_op.o src/libnsss/nsss_switch_pwd_end.o src/libnsss/nsss_switch_pwd_get.o src/libnsss/nsss_switch_pwd_getbyname.o src/libnsss/nsss_switch_pwd_getbyuid.o src/libnsss/nsss_switch_pwd_read.o src/libnsss/nsss_switch_pwd_rewind.o src/libnsss/nsss_switch_query.o src/libnsss/nsss_switch_query_mutex.o src/libnsss/nsss_switch_query_start.o src/libnsss/nsss_switch_send.o src/libnsss/nsss_switch_sendv.o src/libnsss/nsss_switch_setgrent.o src/libnsss/nsss_switch_setpwent.o src/libnsss/nsss_switch_setspent.o src/libnsss/nsss_switch_shadow_end.o src/libnsss/nsss_switch_shadow_get.o src/libnsss/nsss_switch_shadow_getbyname.o src/libnsss/nsss_switch_shadow_read.o src/libnsss/nsss_switch_shadow_rewind.o src/libnsss/nsss_switch_set_timeout.o src/libnsss/nsss_switch_start.o src/libnsss/nsss_switch_startf.o src/libnsss/nsss_unix_end.o src/libnsss/nsss_unix_endgrent.o src/libnsss/nsss_unix_endpwent.o src/libnsss/nsss_unix_endspent.o src/libnsss/nsss_unix_field.o src/libnsss/nsss_unix_getgrent.o src/libnsss/nsss_unix_getgrent_r.o src/libnsss/nsss_unix_getgrgid.o src/libnsss/nsss_unix_getgrgid_r.o src/libnsss/nsss_unix_getgrnam.o src/libnsss/nsss_unix_getgrnam_r.o src/libnsss/nsss_unix_getgrouplist.o src/libnsss/nsss_unix_getgrouplist_preadjust.o src/libnsss/nsss_unix_getpwent.o src/libnsss/nsss_unix_getpwent_r.o src/libnsss/nsss_unix_getpwnam.o src/libnsss/nsss_unix_getpwnam_r.o src/libnsss/nsss_unix_getpwuid.o src/libnsss/nsss_unix_getpwuid_r.o src/libnsss/nsss_unix_getspent.o src/libnsss/nsss_unix_getspent_r.o src/libnsss/nsss_unix_getspnam.o src/libnsss/nsss_unix_getspnam_r.o src/libnsss/nsss_unix_grp_get.o src/libnsss/nsss_unix_grp_getbygid.o src/libnsss/nsss_unix_grp_getbyname.o src/libnsss/nsss_unix_grp_getlist.o src/libnsss/nsss_unix_grp_here.o src/libnsss/nsss_unix_maybe_start.o src/libnsss/nsss_unix_pwd_get.o src/libnsss/nsss_unix_pwd_getbyname.o src/libnsss/nsss_unix_pwd_getbyuid.o src/libnsss/nsss_unix_pwd_here.o src/libnsss/nsss_unix_rewind.o src/libnsss/nsss_unix_setgrent.o src/libnsss/nsss_unix_setpwent.o src/libnsss/nsss_unix_setspent.o src/libnsss/nsss_unix_shadow_get.o src/libnsss/nsss_unix_shadow_getbyname.o src/libnsss/nsss_unix_shadow_here.o src/libnsss/nsss_unix_start.o
 else
-libnsss.a.xyzzy: src/libnsss/nsss_all_endgrent.lo src/libnsss/nsss_all_endpwent.lo src/libnsss/nsss_all_endspent.lo src/libnsss/nsss_all_errno.lo src/libnsss/nsss_all_getgrent.lo src/libnsss/nsss_all_getgrent_r.lo src/libnsss/nsss_all_getgrgid.lo src/libnsss/nsss_all_getgrgid_r.lo src/libnsss/nsss_all_getgrnam.lo src/libnsss/nsss_all_getgrnam_r.lo src/libnsss/nsss_all_getgrouplist.lo src/libnsss/nsss_all_getpwent.lo src/libnsss/nsss_all_getpwent_r.lo src/libnsss/nsss_all_getpwnam.lo src/libnsss/nsss_all_getpwnam_r.lo src/libnsss/nsss_all_getpwuid.lo src/libnsss/nsss_all_getpwuid_r.lo src/libnsss/nsss_all_getspent.lo src/libnsss/nsss_all_getspent_r.lo src/libnsss/nsss_all_getspnam.lo src/libnsss/nsss_all_getspnam_r.lo src/libnsss/nsss_all_setgrent.lo src/libnsss/nsss_all_setpwent.lo src/libnsss/nsss_all_setspent.lo src/libnsss/nsss_grp_copy.lo src/libnsss/nsss_grp_here.lo src/libnsss/nsss_grouplist_adjust.lo src/libnsss/nsss_pwd_copy.lo src/libnsss/nsss_pwd_here.lo src/libnsss/nsss_shadow_copy.lo src/libnsss/nsss_shadow_here.lo src/libnsss/nsss_switch_end.lo src/libnsss/nsss_switch_endgrent.lo src/libnsss/nsss_switch_endpwent.lo src/libnsss/nsss_switch_endspent.lo src/libnsss/nsss_switch_getgrent.lo src/libnsss/nsss_switch_getgrent_r.lo src/libnsss/nsss_switch_getgrgid.lo src/libnsss/nsss_switch_getgrgid_r.lo src/libnsss/nsss_switch_getgrnam.lo src/libnsss/nsss_switch_getgrnam_r.lo src/libnsss/nsss_switch_getgrouplist.lo src/libnsss/nsss_switch_getpwent.lo src/libnsss/nsss_switch_getpwent_r.lo src/libnsss/nsss_switch_getpwnam.lo src/libnsss/nsss_switch_getpwnam_r.lo src/libnsss/nsss_switch_getpwuid.lo src/libnsss/nsss_switch_getpwuid_r.lo src/libnsss/nsss_switch_getspent.lo src/libnsss/nsss_switch_getspent_r.lo src/libnsss/nsss_switch_getspnam.lo src/libnsss/nsss_switch_getspnam_r.lo src/libnsss/nsss_switch_grp_end.lo src/libnsss/nsss_switch_grp_get.lo src/libnsss/nsss_switch_grp_getbygid.lo src/libnsss/nsss_switch_grp_getbyname.lo src/libnsss/nsss_switch_grp_getlist.lo src/libnsss/nsss_switch_grp_read.lo src/libnsss/nsss_switch_grp_rewind.lo src/libnsss/nsss_switch_here.lo src/libnsss/nsss_switch_op.lo src/libnsss/nsss_switch_pwd_end.lo src/libnsss/nsss_switch_pwd_get.lo src/libnsss/nsss_switch_pwd_getbyname.lo src/libnsss/nsss_switch_pwd_getbyuid.lo src/libnsss/nsss_switch_pwd_read.lo src/libnsss/nsss_switch_pwd_rewind.lo src/libnsss/nsss_switch_setgrent.lo src/libnsss/nsss_switch_setpwent.lo src/libnsss/nsss_switch_setspent.lo src/libnsss/nsss_switch_shadow_end.lo src/libnsss/nsss_switch_shadow_get.lo src/libnsss/nsss_switch_shadow_getbyname.lo src/libnsss/nsss_switch_shadow_read.lo src/libnsss/nsss_switch_shadow_rewind.lo src/libnsss/nsss_switch_start.lo src/libnsss/nsss_unix_end.lo src/libnsss/nsss_unix_endgrent.lo src/libnsss/nsss_unix_endpwent.lo src/libnsss/nsss_unix_endspent.lo src/libnsss/nsss_unix_field.lo src/libnsss/nsss_unix_getgrent.lo src/libnsss/nsss_unix_getgrent_r.lo src/libnsss/nsss_unix_getgrgid.lo src/libnsss/nsss_unix_getgrgid_r.lo src/libnsss/nsss_unix_getgrnam.lo src/libnsss/nsss_unix_getgrnam_r.lo src/libnsss/nsss_unix_getgrouplist.lo src/libnsss/nsss_unix_getgrouplist_preadjust.lo src/libnsss/nsss_unix_getpwent.lo src/libnsss/nsss_unix_getpwent_r.lo src/libnsss/nsss_unix_getpwnam.lo src/libnsss/nsss_unix_getpwnam_r.lo src/libnsss/nsss_unix_getpwuid.lo src/libnsss/nsss_unix_getpwuid_r.lo src/libnsss/nsss_unix_getspent.lo src/libnsss/nsss_unix_getspent_r.lo src/libnsss/nsss_unix_getspnam.lo src/libnsss/nsss_unix_getspnam_r.lo src/libnsss/nsss_unix_grp_get.lo src/libnsss/nsss_unix_grp_getbygid.lo src/libnsss/nsss_unix_grp_getbyname.lo src/libnsss/nsss_unix_grp_getlist.lo src/libnsss/nsss_unix_grp_here.lo src/libnsss/nsss_unix_maybe_start.lo src/libnsss/nsss_unix_pwd_get.lo src/libnsss/nsss_unix_pwd_getbyname.lo src/libnsss/nsss_unix_pwd_getbyuid.lo src/libnsss/nsss_unix_pwd_here.lo src/libnsss/nsss_unix_rewind.lo src/libnsss/nsss_unix_setgrent.lo src/libnsss/nsss_unix_setpwent.lo src/libnsss/nsss_unix_setspent.lo src/libnsss/nsss_unix_shadow_get.lo src/libnsss/nsss_unix_shadow_getbyname.lo src/libnsss/nsss_unix_shadow_here.lo src/libnsss/nsss_unix_start.lo
+libnsss.a.xyzzy: src/libnsss/nsss_all_endgrent.lo src/libnsss/nsss_all_endpwent.lo src/libnsss/nsss_all_endspent.lo src/libnsss/nsss_all_errno.lo src/libnsss/nsss_all_getgrent.lo src/libnsss/nsss_all_getgrent_r.lo src/libnsss/nsss_all_getgrgid.lo src/libnsss/nsss_all_getgrgid_r.lo src/libnsss/nsss_all_getgrnam.lo src/libnsss/nsss_all_getgrnam_r.lo src/libnsss/nsss_all_getgrouplist.lo src/libnsss/nsss_all_getpwent.lo src/libnsss/nsss_all_getpwent_r.lo src/libnsss/nsss_all_getpwnam.lo src/libnsss/nsss_all_getpwnam_r.lo src/libnsss/nsss_all_getpwuid.lo src/libnsss/nsss_all_getpwuid_r.lo src/libnsss/nsss_all_getspent.lo src/libnsss/nsss_all_getspent_r.lo src/libnsss/nsss_all_getspnam.lo src/libnsss/nsss_all_getspnam_r.lo src/libnsss/nsss_all_setgrent.lo src/libnsss/nsss_all_setpwent.lo src/libnsss/nsss_all_setspent.lo src/libnsss/nsss_grp_copy.lo src/libnsss/nsss_grp_here.lo src/libnsss/nsss_grouplist_adjust.lo src/libnsss/nsss_pwd_copy.lo src/libnsss/nsss_pwd_here.lo src/libnsss/nsss_shadow_copy.lo src/libnsss/nsss_shadow_here.lo src/libnsss/nsss_switch_end.lo src/libnsss/nsss_switch_endgrent.lo src/libnsss/nsss_switch_endpwent.lo src/libnsss/nsss_switch_endspent.lo src/libnsss/nsss_switch_enumerator.lo src/libnsss/nsss_switch_getgrent.lo src/libnsss/nsss_switch_getgrent_r.lo src/libnsss/nsss_switch_getgrgid.lo src/libnsss/nsss_switch_getgrgid_r.lo src/libnsss/nsss_switch_getgrnam.lo src/libnsss/nsss_switch_getgrnam_r.lo src/libnsss/nsss_switch_getgrouplist.lo src/libnsss/nsss_switch_getpwent.lo src/libnsss/nsss_switch_getpwent_r.lo src/libnsss/nsss_switch_getpwnam.lo src/libnsss/nsss_switch_getpwnam_r.lo src/libnsss/nsss_switch_getpwuid.lo src/libnsss/nsss_switch_getpwuid_r.lo src/libnsss/nsss_switch_getspent.lo src/libnsss/nsss_switch_getspent_r.lo src/libnsss/nsss_switch_getspnam.lo src/libnsss/nsss_switch_getspnam_r.lo src/libnsss/nsss_switch_grp_end.lo src/libnsss/nsss_switch_grp_get.lo src/libnsss/nsss_switch_grp_getbygid.lo src/libnsss/nsss_switch_grp_getbyname.lo src/libnsss/nsss_switch_grp_getlist.lo src/libnsss/nsss_switch_grp_read.lo src/libnsss/nsss_switch_grp_rewind.lo src/libnsss/nsss_switch_op.lo src/libnsss/nsss_switch_pwd_end.lo src/libnsss/nsss_switch_pwd_get.lo src/libnsss/nsss_switch_pwd_getbyname.lo src/libnsss/nsss_switch_pwd_getbyuid.lo src/libnsss/nsss_switch_pwd_read.lo src/libnsss/nsss_switch_pwd_rewind.lo src/libnsss/nsss_switch_query.lo src/libnsss/nsss_switch_query_mutex.lo src/libnsss/nsss_switch_query_start.lo src/libnsss/nsss_switch_send.lo src/libnsss/nsss_switch_sendv.lo src/libnsss/nsss_switch_setgrent.lo src/libnsss/nsss_switch_setpwent.lo src/libnsss/nsss_switch_setspent.lo src/libnsss/nsss_switch_shadow_end.lo src/libnsss/nsss_switch_shadow_get.lo src/libnsss/nsss_switch_shadow_getbyname.lo src/libnsss/nsss_switch_shadow_read.lo src/libnsss/nsss_switch_shadow_rewind.lo src/libnsss/nsss_switch_set_timeout.lo src/libnsss/nsss_switch_start.lo src/libnsss/nsss_switch_startf.lo src/libnsss/nsss_unix_end.lo src/libnsss/nsss_unix_endgrent.lo src/libnsss/nsss_unix_endpwent.lo src/libnsss/nsss_unix_endspent.lo src/libnsss/nsss_unix_field.lo src/libnsss/nsss_unix_getgrent.lo src/libnsss/nsss_unix_getgrent_r.lo src/libnsss/nsss_unix_getgrgid.lo src/libnsss/nsss_unix_getgrgid_r.lo src/libnsss/nsss_unix_getgrnam.lo src/libnsss/nsss_unix_getgrnam_r.lo src/libnsss/nsss_unix_getgrouplist.lo src/libnsss/nsss_unix_getgrouplist_preadjust.lo src/libnsss/nsss_unix_getpwent.lo src/libnsss/nsss_unix_getpwent_r.lo src/libnsss/nsss_unix_getpwnam.lo src/libnsss/nsss_unix_getpwnam_r.lo src/libnsss/nsss_unix_getpwuid.lo src/libnsss/nsss_unix_getpwuid_r.lo src/libnsss/nsss_unix_getspent.lo src/libnsss/nsss_unix_getspent_r.lo src/libnsss/nsss_unix_getspnam.lo src/libnsss/nsss_unix_getspnam_r.lo src/libnsss/nsss_unix_grp_get.lo src/libnsss/nsss_unix_grp_getbygid.lo src/libnsss/nsss_unix_grp_getbyname.lo src/libnsss/nsss_unix_grp_getlist.lo src/libnsss/nsss_unix_grp_here.lo src/libnsss/nsss_unix_maybe_start.lo src/libnsss/nsss_unix_pwd_get.lo src/libnsss/nsss_unix_pwd_getbyname.lo src/libnsss/nsss_unix_pwd_getbyuid.lo src/libnsss/nsss_unix_pwd_here.lo src/libnsss/nsss_unix_rewind.lo src/libnsss/nsss_unix_setgrent.lo src/libnsss/nsss_unix_setpwent.lo src/libnsss/nsss_unix_setspent.lo src/libnsss/nsss_unix_shadow_get.lo src/libnsss/nsss_unix_shadow_getbyname.lo src/libnsss/nsss_unix_shadow_here.lo src/libnsss/nsss_unix_start.lo
 endif
 libnsss.so.xyzzy: EXTRA_LIBS := -lskarnet -lpthread
-libnsss.so.xyzzy: src/libnsss/nsss_all_endgrent.lo src/libnsss/nsss_all_endpwent.lo src/libnsss/nsss_all_endspent.lo src/libnsss/nsss_all_errno.lo src/libnsss/nsss_all_getgrent.lo src/libnsss/nsss_all_getgrent_r.lo src/libnsss/nsss_all_getgrgid.lo src/libnsss/nsss_all_getgrgid_r.lo src/libnsss/nsss_all_getgrnam.lo src/libnsss/nsss_all_getgrnam_r.lo src/libnsss/nsss_all_getgrouplist.lo src/libnsss/nsss_all_getpwent.lo src/libnsss/nsss_all_getpwent_r.lo src/libnsss/nsss_all_getpwnam.lo src/libnsss/nsss_all_getpwnam_r.lo src/libnsss/nsss_all_getpwuid.lo src/libnsss/nsss_all_getpwuid_r.lo src/libnsss/nsss_all_getspent.lo src/libnsss/nsss_all_getspent_r.lo src/libnsss/nsss_all_getspnam.lo src/libnsss/nsss_all_getspnam_r.lo src/libnsss/nsss_all_setgrent.lo src/libnsss/nsss_all_setpwent.lo src/libnsss/nsss_all_setspent.lo src/libnsss/nsss_grp_copy.lo src/libnsss/nsss_grp_here.lo src/libnsss/nsss_grouplist_adjust.lo src/libnsss/nsss_pwd_copy.lo src/libnsss/nsss_pwd_here.lo src/libnsss/nsss_shadow_copy.lo src/libnsss/nsss_shadow_here.lo src/libnsss/nsss_switch_end.lo src/libnsss/nsss_switch_endgrent.lo src/libnsss/nsss_switch_endpwent.lo src/libnsss/nsss_switch_endspent.lo src/libnsss/nsss_switch_getgrent.lo src/libnsss/nsss_switch_getgrent_r.lo src/libnsss/nsss_switch_getgrgid.lo src/libnsss/nsss_switch_getgrgid_r.lo src/libnsss/nsss_switch_getgrnam.lo src/libnsss/nsss_switch_getgrnam_r.lo src/libnsss/nsss_switch_getgrouplist.lo src/libnsss/nsss_switch_getpwent.lo src/libnsss/nsss_switch_getpwent_r.lo src/libnsss/nsss_switch_getpwnam.lo src/libnsss/nsss_switch_getpwnam_r.lo src/libnsss/nsss_switch_getpwuid.lo src/libnsss/nsss_switch_getpwuid_r.lo src/libnsss/nsss_switch_getspent.lo src/libnsss/nsss_switch_getspent_r.lo src/libnsss/nsss_switch_getspnam.lo src/libnsss/nsss_switch_getspnam_r.lo src/libnsss/nsss_switch_grp_end.lo src/libnsss/nsss_switch_grp_get.lo src/libnsss/nsss_switch_grp_getbygid.lo src/libnsss/nsss_switch_grp_getbyname.lo src/libnsss/nsss_switch_grp_getlist.lo src/libnsss/nsss_switch_grp_read.lo src/libnsss/nsss_switch_grp_rewind.lo src/libnsss/nsss_switch_here.lo src/libnsss/nsss_switch_op.lo src/libnsss/nsss_switch_pwd_end.lo src/libnsss/nsss_switch_pwd_get.lo src/libnsss/nsss_switch_pwd_getbyname.lo src/libnsss/nsss_switch_pwd_getbyuid.lo src/libnsss/nsss_switch_pwd_read.lo src/libnsss/nsss_switch_pwd_rewind.lo src/libnsss/nsss_switch_setgrent.lo src/libnsss/nsss_switch_setpwent.lo src/libnsss/nsss_switch_setspent.lo src/libnsss/nsss_switch_shadow_end.lo src/libnsss/nsss_switch_shadow_get.lo src/libnsss/nsss_switch_shadow_getbyname.lo src/libnsss/nsss_switch_shadow_read.lo src/libnsss/nsss_switch_shadow_rewind.lo src/libnsss/nsss_switch_start.lo src/libnsss/nsss_unix_end.lo src/libnsss/nsss_unix_endgrent.lo src/libnsss/nsss_unix_endpwent.lo src/libnsss/nsss_unix_endspent.lo src/libnsss/nsss_unix_field.lo src/libnsss/nsss_unix_getgrent.lo src/libnsss/nsss_unix_getgrent_r.lo src/libnsss/nsss_unix_getgrgid.lo src/libnsss/nsss_unix_getgrgid_r.lo src/libnsss/nsss_unix_getgrnam.lo src/libnsss/nsss_unix_getgrnam_r.lo src/libnsss/nsss_unix_getgrouplist.lo src/libnsss/nsss_unix_getgrouplist_preadjust.lo src/libnsss/nsss_unix_getpwent.lo src/libnsss/nsss_unix_getpwent_r.lo src/libnsss/nsss_unix_getpwnam.lo src/libnsss/nsss_unix_getpwnam_r.lo src/libnsss/nsss_unix_getpwuid.lo src/libnsss/nsss_unix_getpwuid_r.lo src/libnsss/nsss_unix_getspent.lo src/libnsss/nsss_unix_getspent_r.lo src/libnsss/nsss_unix_getspnam.lo src/libnsss/nsss_unix_getspnam_r.lo src/libnsss/nsss_unix_grp_get.lo src/libnsss/nsss_unix_grp_getbygid.lo src/libnsss/nsss_unix_grp_getbyname.lo src/libnsss/nsss_unix_grp_getlist.lo src/libnsss/nsss_unix_grp_here.lo src/libnsss/nsss_unix_maybe_start.lo src/libnsss/nsss_unix_pwd_get.lo src/libnsss/nsss_unix_pwd_getbyname.lo src/libnsss/nsss_unix_pwd_getbyuid.lo src/libnsss/nsss_unix_pwd_here.lo src/libnsss/nsss_unix_rewind.lo src/libnsss/nsss_unix_setgrent.lo src/libnsss/nsss_unix_setpwent.lo src/libnsss/nsss_unix_setspent.lo src/libnsss/nsss_unix_shadow_get.lo src/libnsss/nsss_unix_shadow_getbyname.lo src/libnsss/nsss_unix_shadow_here.lo src/libnsss/nsss_unix_start.lo
+libnsss.so.xyzzy: src/libnsss/nsss_all_endgrent.lo src/libnsss/nsss_all_endpwent.lo src/libnsss/nsss_all_endspent.lo src/libnsss/nsss_all_errno.lo src/libnsss/nsss_all_getgrent.lo src/libnsss/nsss_all_getgrent_r.lo src/libnsss/nsss_all_getgrgid.lo src/libnsss/nsss_all_getgrgid_r.lo src/libnsss/nsss_all_getgrnam.lo src/libnsss/nsss_all_getgrnam_r.lo src/libnsss/nsss_all_getgrouplist.lo src/libnsss/nsss_all_getpwent.lo src/libnsss/nsss_all_getpwent_r.lo src/libnsss/nsss_all_getpwnam.lo src/libnsss/nsss_all_getpwnam_r.lo src/libnsss/nsss_all_getpwuid.lo src/libnsss/nsss_all_getpwuid_r.lo src/libnsss/nsss_all_getspent.lo src/libnsss/nsss_all_getspent_r.lo src/libnsss/nsss_all_getspnam.lo src/libnsss/nsss_all_getspnam_r.lo src/libnsss/nsss_all_setgrent.lo src/libnsss/nsss_all_setpwent.lo src/libnsss/nsss_all_setspent.lo src/libnsss/nsss_grp_copy.lo src/libnsss/nsss_grp_here.lo src/libnsss/nsss_grouplist_adjust.lo src/libnsss/nsss_pwd_copy.lo src/libnsss/nsss_pwd_here.lo src/libnsss/nsss_shadow_copy.lo src/libnsss/nsss_shadow_here.lo src/libnsss/nsss_switch_end.lo src/libnsss/nsss_switch_endgrent.lo src/libnsss/nsss_switch_endpwent.lo src/libnsss/nsss_switch_endspent.lo src/libnsss/nsss_switch_enumerator.lo src/libnsss/nsss_switch_getgrent.lo src/libnsss/nsss_switch_getgrent_r.lo src/libnsss/nsss_switch_getgrgid.lo src/libnsss/nsss_switch_getgrgid_r.lo src/libnsss/nsss_switch_getgrnam.lo src/libnsss/nsss_switch_getgrnam_r.lo src/libnsss/nsss_switch_getgrouplist.lo src/libnsss/nsss_switch_getpwent.lo src/libnsss/nsss_switch_getpwent_r.lo src/libnsss/nsss_switch_getpwnam.lo src/libnsss/nsss_switch_getpwnam_r.lo src/libnsss/nsss_switch_getpwuid.lo src/libnsss/nsss_switch_getpwuid_r.lo src/libnsss/nsss_switch_getspent.lo src/libnsss/nsss_switch_getspent_r.lo src/libnsss/nsss_switch_getspnam.lo src/libnsss/nsss_switch_getspnam_r.lo src/libnsss/nsss_switch_grp_end.lo src/libnsss/nsss_switch_grp_get.lo src/libnsss/nsss_switch_grp_getbygid.lo src/libnsss/nsss_switch_grp_getbyname.lo src/libnsss/nsss_switch_grp_getlist.lo src/libnsss/nsss_switch_grp_read.lo src/libnsss/nsss_switch_grp_rewind.lo src/libnsss/nsss_switch_op.lo src/libnsss/nsss_switch_pwd_end.lo src/libnsss/nsss_switch_pwd_get.lo src/libnsss/nsss_switch_pwd_getbyname.lo src/libnsss/nsss_switch_pwd_getbyuid.lo src/libnsss/nsss_switch_pwd_read.lo src/libnsss/nsss_switch_pwd_rewind.lo src/libnsss/nsss_switch_query.lo src/libnsss/nsss_switch_query_mutex.lo src/libnsss/nsss_switch_query_start.lo src/libnsss/nsss_switch_send.lo src/libnsss/nsss_switch_sendv.lo src/libnsss/nsss_switch_setgrent.lo src/libnsss/nsss_switch_setpwent.lo src/libnsss/nsss_switch_setspent.lo src/libnsss/nsss_switch_shadow_end.lo src/libnsss/nsss_switch_shadow_get.lo src/libnsss/nsss_switch_shadow_getbyname.lo src/libnsss/nsss_switch_shadow_read.lo src/libnsss/nsss_switch_shadow_rewind.lo src/libnsss/nsss_switch_set_timeout.lo src/libnsss/nsss_switch_start.lo src/libnsss/nsss_switch_startf.lo src/libnsss/nsss_unix_end.lo src/libnsss/nsss_unix_endgrent.lo src/libnsss/nsss_unix_endpwent.lo src/libnsss/nsss_unix_endspent.lo src/libnsss/nsss_unix_field.lo src/libnsss/nsss_unix_getgrent.lo src/libnsss/nsss_unix_getgrent_r.lo src/libnsss/nsss_unix_getgrgid.lo src/libnsss/nsss_unix_getgrgid_r.lo src/libnsss/nsss_unix_getgrnam.lo src/libnsss/nsss_unix_getgrnam_r.lo src/libnsss/nsss_unix_getgrouplist.lo src/libnsss/nsss_unix_getgrouplist_preadjust.lo src/libnsss/nsss_unix_getpwent.lo src/libnsss/nsss_unix_getpwent_r.lo src/libnsss/nsss_unix_getpwnam.lo src/libnsss/nsss_unix_getpwnam_r.lo src/libnsss/nsss_unix_getpwuid.lo src/libnsss/nsss_unix_getpwuid_r.lo src/libnsss/nsss_unix_getspent.lo src/libnsss/nsss_unix_getspent_r.lo src/libnsss/nsss_unix_getspnam.lo src/libnsss/nsss_unix_getspnam_r.lo src/libnsss/nsss_unix_grp_get.lo src/libnsss/nsss_unix_grp_getbygid.lo src/libnsss/nsss_unix_grp_getbyname.lo src/libnsss/nsss_unix_grp_getlist.lo src/libnsss/nsss_unix_grp_here.lo src/libnsss/nsss_unix_maybe_start.lo src/libnsss/nsss_unix_pwd_get.lo src/libnsss/nsss_unix_pwd_getbyname.lo src/libnsss/nsss_unix_pwd_getbyuid.lo src/libnsss/nsss_unix_pwd_here.lo src/libnsss/nsss_unix_rewind.lo src/libnsss/nsss_unix_setgrent.lo src/libnsss/nsss_unix_setpwent.lo src/libnsss/nsss_unix_setspent.lo src/libnsss/nsss_unix_shadow_get.lo src/libnsss/nsss_unix_shadow_getbyname.lo src/libnsss/nsss_unix_shadow_here.lo src/libnsss/nsss_unix_start.lo
 ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),)
 libnsssd.a.xyzzy: src/nsssd/nsssd_main.o src/nsssd/nsssd_convert.o
 else
@@ -167,8 +174,10 @@ libnsssd.so.xyzzy: EXTRA_LIBS := -lskarnet
 libnsssd.so.xyzzy: src/nsssd/nsssd_main.lo src/nsssd/nsssd_convert.lo
 nsssd-nslcd: EXTRA_LIBS := -lskarnet ${SOCKET_LIB} ${SYSCLOCK_LIB}
 nsssd-nslcd: src/nsssd/nsssd-nslcd.o ${LIBNSSSD}
+nsssd-switch: EXTRA_LIBS := -lskarnet ${SOCKET_LIB} ${SYSCLOCK_LIB}
+nsssd-switch: src/nsssd/nsssd-switch.o ${LIBNSSSD} ${LIBNSSS}
 nsssd-unix: EXTRA_LIBS := -lskarnet
-nsssd-unix: src/nsssd/nsssd-unix.o ${LIBNSSS} ${LIBNSSSD}
+nsssd-unix: src/nsssd/nsssd-unix.o ${LIBNSSSD} ${LIBNSSS}
 test-all-fallback: EXTRA_LIBS := -lskarnet ${SOCKET_LIB} ${SYSCLOCK_LIB}
 test-all-fallback: src/tests/test-all-fallback.o ${LIBNSSS}
 test-switch: EXTRA_LIBS := -lskarnet ${SOCKET_LIB} ${SYSCLOCK_LIB}
diff --git a/package/info b/package/info
index 500ef4c..6517438 100644
--- a/package/info
+++ b/package/info
@@ -1,4 +1,4 @@
 package=nsss
-version=0.1.0.2
+version=0.2.0.0
 category=admin
 package_macro_name=NSSS
diff --git a/package/modes b/package/modes
index 013611d..8595155 100644
--- a/package/modes
+++ b/package/modes
@@ -1,2 +1,3 @@
 nsssd-unix	0755
 nsssd-nslcd	0755
+nsssd-switch	0755
diff --git a/package/targets.mak b/package/targets.mak
index bc1f9c0..653db32 100644
--- a/package/targets.mak
+++ b/package/targets.mak
@@ -1,6 +1,7 @@
 BIN_TARGETS := \
 nsssd-unix \
-nsssd-nslcd
+nsssd-nslcd \
+nsssd-switch
 
 LIBEXEC_TARGETS :=
 
diff --git a/src/include/nsss/nsss-switch.h b/src/include/nsss/nsss-switch.h
index e0ce2dc..9110b13 100644
--- a/src/include/nsss/nsss-switch.h
+++ b/src/include/nsss/nsss-switch.h
@@ -6,10 +6,12 @@
 #include <sys/types.h>
 #include <limits.h>
 #include <unistd.h>
+
 #include <skalibs/tai.h>
 #include <skalibs/buffer.h>
 #include <skalibs/stralloc.h>
 #include <skalibs/genalloc.h>
+
 #include <nsss/pwd-switch.h>
 #include <nsss/grp-switch.h>
 #include <nsss/shadow-switch.h>
@@ -26,27 +28,38 @@ typedef struct nsss_switch_s nsss_switch_t, *nsss_switch_t_ref ;
 struct nsss_switch_s
 {
   unsigned int held ;
+  char const *path ;
   buffer b ;
   char buf[NSSS_SWITCH_BUFSIZE] ;
 } ;
-#define NSSS_SWITCH_ZERO { .held = 0, .b = BUFFER_ZERO }
+#define NSSS_SWITCH_ZERO { .held = 0, .path = 0, .b = BUFFER_ZERO }
 
-#define NSSS_SWITCH_PWD 0
-#define NSSS_SWITCH_GRP 1
-#define NSSS_SWITCH_SHADOW 2
+#define NSSS_SWITCH_PWD 1
+#define NSSS_SWITCH_GRP 2
+#define NSSS_SWITCH_SHADOW 4
 
 extern int nsss_switch_start (nsss_switch_t *, unsigned int, char const *, tain const *, tain *) ;
 #define nsss_switch_start_g(a, what, s, deadline) nsss_switch_start(a, what, s, (deadline), &STAMP)
+extern int nsss_switch_startf (nsss_switch_t *, unsigned int, char const *const *, tain const *, tain *) ;
+#define nsss_switch_startf_g(a, what, argv, deadline) nsss_switch_startf(a, what, argv, (deadline), &STAMP)
 extern void nsss_switch_end (nsss_switch_t *, unsigned int) ;
 
 
+ /* Internal management */
+
+#define NSSS_SWITCH_SET_TIMEOUT '\001'
+
+extern int nsss_switch_set_timeout (nsss_switch_t *, unsigned int, tain const *, tain *) ;
+#define nsss_switch_set_timeout_g(a, timeout, deadline) nsss_switch_set_timeout(a, timeout, (deadline), &STAMP)
+
+
  /* Password */
 
-#define NSSS_SWITCH_PWD_END '\0'
-#define NSSS_SWITCH_PWD_REWIND '\001'
-#define NSSS_SWITCH_PWD_GET '\002'
-#define NSSS_SWITCH_PWD_GETBYNAME '\003'
-#define NSSS_SWITCH_PWD_GETBYUID '\004'
+#define NSSS_SWITCH_PWD_END '\010'
+#define NSSS_SWITCH_PWD_REWIND '\011'
+#define NSSS_SWITCH_PWD_GET '\012'
+#define NSSS_SWITCH_PWD_GETBYNAME '\013'
+#define NSSS_SWITCH_PWD_GETBYUID '\014'
 
 extern int nsss_switch_pwd_end (nsss_switch_t *, tain const *, tain *) ;
 #define nsss_switch_pwd_end_g(a, deadline) nsss_switch_pwd_end(a, (deadline), &STAMP)
diff --git a/src/include/nsss/nsssd.h b/src/include/nsss/nsssd.h
index b21e6d2..99e93f8 100644
--- a/src/include/nsss/nsssd.h
+++ b/src/include/nsss/nsssd.h
@@ -49,7 +49,7 @@ struct nsssd_spwd_s
 
 /* Functions provided by libnsssd */
 
-extern int nsssd_main (char const *const *, char const *const *) ;
+extern int nsssd_main (char const *const *) ;
 extern void nsssd_passwd_convert (struct passwd *, nsssd_passwd_t const *, char const *) ;
 extern void nsssd_group_convert (struct group *, char **, nsssd_group_t const *, char const *, size_t const *) ;
 extern void nsssd_spwd_convert (struct spwd *, nsssd_spwd_t const *, char const *) ;
@@ -58,7 +58,7 @@ extern void nsssd_spwd_convert (struct spwd *, nsssd_spwd_t const *, char const
 /* Functions that must be provided by the backend */
 
 extern void *nsssd_handle_init (void) ;
-extern int nsssd_handle_start (void *, char const *const *, char const *const *) ;
+extern int nsssd_handle_start (void *, char const *const *) ;
 extern void nsssd_handle_end (void *) ;
 
 extern int nsssd_pwd_start (void *) ;
diff --git a/src/libnsss/deps-lib/nsss b/src/libnsss/deps-lib/nsss
index e00084e..56764bf 100644
--- a/src/libnsss/deps-lib/nsss
+++ b/src/libnsss/deps-lib/nsss
@@ -33,6 +33,7 @@ nsss_switch_end.o
 nsss_switch_endgrent.o
 nsss_switch_endpwent.o
 nsss_switch_endspent.o
+nsss_switch_enumerator.o
 nsss_switch_getgrent.o
 nsss_switch_getgrent_r.o
 nsss_switch_getgrgid.o
@@ -57,7 +58,6 @@ nsss_switch_grp_getbyname.o
 nsss_switch_grp_getlist.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
@@ -65,6 +65,11 @@ nsss_switch_pwd_getbyname.o
 nsss_switch_pwd_getbyuid.o
 nsss_switch_pwd_read.o
 nsss_switch_pwd_rewind.o
+nsss_switch_query.o
+nsss_switch_query_mutex.o
+nsss_switch_query_start.o
+nsss_switch_send.o
+nsss_switch_sendv.o
 nsss_switch_setgrent.o
 nsss_switch_setpwent.o
 nsss_switch_setspent.o
@@ -73,7 +78,9 @@ nsss_switch_shadow_get.o
 nsss_switch_shadow_getbyname.o
 nsss_switch_shadow_read.o
 nsss_switch_shadow_rewind.o
+nsss_switch_set_timeout.o
 nsss_switch_start.o
+nsss_switch_startf.o
 nsss_unix_end.o
 nsss_unix_endgrent.o
 nsss_unix_endpwent.o
diff --git a/src/libnsss/nsss-switch-internal.h b/src/libnsss/nsss-switch-internal.h
index 2b93434..50615d8 100644
--- a/src/libnsss/nsss-switch-internal.h
+++ b/src/libnsss/nsss-switch-internal.h
@@ -3,19 +3,34 @@
 #ifndef NSSS_SWITCH_INTERNAL_H
 #define NSSS_SWITCH_INTERNAL_H
 
+#include <stddef.h>
+#include <sys/uio.h>
+#include <pthread.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 nsss_switch_t nsss_switch_enumerator ;
+extern pthread_mutex_t nsss_switch_enumerator_mutex ;
+
+extern nsss_switch_t nsss_switch_query ;
+extern pthread_mutex_t nsss_switch_query_mutex ;
+
+extern int nsss_switch_query_start (char const *, unsigned int, unsigned int, tain const *, tain *) ;
+
 extern int nsss_switch_op (nsss_switch_t *, char, tain const *, tain *) ;
 extern int nsss_switch_pwd_read (buffer *, struct passwd *, stralloc *, tain const *, tain *) ;
 extern int nsss_switch_grp_read (buffer *, struct group *, stralloc *, genalloc *, tain const *, tain *) ;
 extern int nsss_switch_shadow_read (buffer *, struct spwd *, stralloc *, tain const *, tain *) ;
 
+extern int nsss_switch_send (nsss_switch_t *, char const *, size_t, tain const *, tain *) ;
+extern int nsss_switch_sendv (nsss_switch_t *, struct iovec const *, unsigned int, tain const *, tain *) ;
+
 #endif
diff --git a/src/libnsss/nsss_all_getgrent.c b/src/libnsss/nsss_all_getgrent.c
index 15b5894..d6c5e1a 100644
--- a/src/libnsss/nsss_all_getgrent.c
+++ b/src/libnsss/nsss_all_getgrent.c
@@ -14,10 +14,10 @@ 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 ;
+  if (!nsss_switch_start(&nsss_switch_enumerator, 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 ;
+  if (!nsss_switch_grp_get(&nsss_switch_enumerator, &nsss_grp_here, &nsss_grp_sa_here, &nsss_grp_ga_here, 0, 0)) return 0 ;
   return &nsss_grp_here ;
 
  efallback:
diff --git a/src/libnsss/nsss_all_getgrent_r.c b/src/libnsss/nsss_all_getgrent_r.c
index 3e0557d..c4e5f7a 100644
--- a/src/libnsss/nsss_all_getgrent_r.c
+++ b/src/libnsss/nsss_all_getgrent_r.c
@@ -18,9 +18,9 @@ int nsss_all_getgrent_r (struct group *gr, char *buf, size_t buflen, struct grou
   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 ;
+  if (!nsss_switch_start(&nsss_switch_enumerator, 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))
+  if (!nsss_switch_grp_get(&nsss_switch_enumerator, &gr2, &sa, &ga, 0, 0))
   {
     *grp = 0 ;
     if (!errno) errno = ENOENT ;
diff --git a/src/libnsss/nsss_all_getpwent.c b/src/libnsss/nsss_all_getpwent.c
index b68a4b3..edb8a9f 100644
--- a/src/libnsss/nsss_all_getpwent.c
+++ b/src/libnsss/nsss_all_getpwent.c
@@ -13,9 +13,9 @@ 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 ;
+  if (!nsss_switch_start(&nsss_switch_enumerator, 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 ;
+  if (!nsss_switch_pwd_get(&nsss_switch_enumerator, &nsss_pwd_here, &nsss_pwd_sa_here, 0, 0)) return 0 ;
   return &nsss_pwd_here ;
 
  efallback:
diff --git a/src/libnsss/nsss_all_getpwent_r.c b/src/libnsss/nsss_all_getpwent_r.c
index 08e69dc..c08194a 100644
--- a/src/libnsss/nsss_all_getpwent_r.c
+++ b/src/libnsss/nsss_all_getpwent_r.c
@@ -16,9 +16,9 @@ int nsss_all_getpwent_r (struct passwd *pw, char *buf, size_t buflen, struct pas
   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 ;
+  if (!nsss_switch_start(&nsss_switch_enumerator, NSSS_SWITCH_PWD, NSSS_NSSSD_PATH, 0, 0)) goto efallback ;
   errno = 0 ;
-  if (!nsss_switch_pwd_get(&nsss_switch_here, &pw2, &sa, 0, 0))
+  if (!nsss_switch_pwd_get(&nsss_switch_enumerator, &pw2, &sa, 0, 0))
   {
     *pwp = 0 ;
     if (!errno) errno = ENOENT ;
diff --git a/src/libnsss/nsss_all_getspent.c b/src/libnsss/nsss_all_getspent.c
index 7ca5048..57d356b 100644
--- a/src/libnsss/nsss_all_getspent.c
+++ b/src/libnsss/nsss_all_getspent.c
@@ -13,9 +13,9 @@ 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 ;
+  if (!nsss_switch_start(&nsss_switch_enumerator, 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 ;
+  if (!nsss_switch_shadow_get(&nsss_switch_enumerator, &nsss_shadow_here, &nsss_shadow_sa_here, 0, 0)) return 0 ;
   return &nsss_shadow_here ;
 
  efallback:
diff --git a/src/libnsss/nsss_all_getspent_r.c b/src/libnsss/nsss_all_getspent_r.c
index ab3e531..e6df40e 100644
--- a/src/libnsss/nsss_all_getspent_r.c
+++ b/src/libnsss/nsss_all_getspent_r.c
@@ -16,9 +16,9 @@ int nsss_all_getspent_r (struct spwd *sp, char *buf, size_t buflen, struct spwd
   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 ;
+  if (!nsss_switch_start(&nsss_switch_enumerator, NSSS_SWITCH_SHADOW, NSSS_NSSSD_PATH, 0, 0)) goto efallback ;
   errno = 0 ;
-  if (!nsss_switch_shadow_get(&nsss_switch_here, &sp2, &sa, 0, 0))
+  if (!nsss_switch_shadow_get(&nsss_switch_enumerator, &sp2, &sa, 0, 0))
   {
     *spp = 0 ;
     if (!errno) errno = ENOENT ;
diff --git a/src/libnsss/nsss_all_setgrent.c b/src/libnsss/nsss_all_setgrent.c
index 78fee56..993d2fc 100644
--- a/src/libnsss/nsss_all_setgrent.c
+++ b/src/libnsss/nsss_all_setgrent.c
@@ -11,8 +11,8 @@
 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) ;
+  if (!nsss_switch_start(&nsss_switch_enumerator, NSSS_SWITCH_GRP, NSSS_NSSSD_PATH, 0, 0)) goto fallback ;
+  nsss_switch_grp_rewind(&nsss_switch_enumerator, 0, 0) ;
   return ;
 
  fallback:
diff --git a/src/libnsss/nsss_all_setpwent.c b/src/libnsss/nsss_all_setpwent.c
index e22411a..34f4c7f 100644
--- a/src/libnsss/nsss_all_setpwent.c
+++ b/src/libnsss/nsss_all_setpwent.c
@@ -11,8 +11,8 @@
 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) ;
+  if (!nsss_switch_start(&nsss_switch_enumerator, NSSS_SWITCH_PWD, NSSS_NSSSD_PATH, 0, 0)) goto fallback ;
+  nsss_switch_pwd_rewind(&nsss_switch_enumerator, 0, 0) ;
   return ;
 
  fallback:
diff --git a/src/libnsss/nsss_all_setspent.c b/src/libnsss/nsss_all_setspent.c
index ab6c456..437ffcc 100644
--- a/src/libnsss/nsss_all_setspent.c
+++ b/src/libnsss/nsss_all_setspent.c
@@ -11,8 +11,8 @@
 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) ;
+  if (!nsss_switch_start(&nsss_switch_enumerator, NSSS_SWITCH_SHADOW, NSSS_NSSSD_PATH, 0, 0)) goto fallback ;
+  nsss_switch_shadow_rewind(&nsss_switch_enumerator, 0, 0) ;
   return ;
 
  fallback:
diff --git a/src/libnsss/nsss_switch_end.c b/src/libnsss/nsss_switch_end.c
index 3922721..6895dd6 100644
--- a/src/libnsss/nsss_switch_end.c
+++ b/src/libnsss/nsss_switch_end.c
@@ -8,10 +8,11 @@ static inline void nsss_switch_disconnect (nsss_switch_t *a)
 {
   fd_close(buffer_fd(&a->b)) ;
   a->b.fd = -1 ;
+  a->path = 0 ;
 }
 
 void nsss_switch_end (nsss_switch_t *a, unsigned int what)
 {
-  a->held &= ~(1U << what) ;
+  a->held &= ~(what & 0x7u) ;
   if (!a->held) nsss_switch_disconnect(a) ;
 }
diff --git a/src/libnsss/nsss_switch_endgrent.c b/src/libnsss/nsss_switch_endgrent.c
index 8ae43ea..0a9e1e4 100644
--- a/src/libnsss/nsss_switch_endgrent.c
+++ b/src/libnsss/nsss_switch_endgrent.c
@@ -1,10 +1,14 @@
 /* ISC license. */
 
+#include <pthread.h>
+
 #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) ;
+  pthread_mutex_lock(&nsss_switch_enumerator_mutex) ;
+  nsss_switch_grp_end(&nsss_switch_enumerator, 0, 0) ;
+  nsss_switch_end(&nsss_switch_enumerator, NSSS_SWITCH_GRP) ;
+  pthread_mutex_unlock(&nsss_switch_enumerator_mutex) ;
 }
diff --git a/src/libnsss/nsss_switch_endpwent.c b/src/libnsss/nsss_switch_endpwent.c
index 8dbec92..501848f 100644
--- a/src/libnsss/nsss_switch_endpwent.c
+++ b/src/libnsss/nsss_switch_endpwent.c
@@ -1,10 +1,14 @@
 /* ISC license. */
 
+#include <pthread.h>
+
 #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) ;
+  pthread_mutex_lock(&nsss_switch_enumerator_mutex) ;
+  nsss_switch_pwd_end(&nsss_switch_enumerator, 0, 0) ;
+  nsss_switch_end(&nsss_switch_enumerator, NSSS_SWITCH_PWD) ;
+  pthread_mutex_unlock(&nsss_switch_enumerator_mutex) ;
 }
diff --git a/src/libnsss/nsss_switch_endspent.c b/src/libnsss/nsss_switch_endspent.c
index 8527072..0bf5b92 100644
--- a/src/libnsss/nsss_switch_endspent.c
+++ b/src/libnsss/nsss_switch_endspent.c
@@ -1,10 +1,14 @@
 /* ISC license. */
 
+#include <pthread.h>
+
 #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) ;
+  pthread_mutex_lock(&nsss_switch_enumerator_mutex) ;
+  nsss_switch_shadow_end(&nsss_switch_enumerator, 0, 0) ;
+  nsss_switch_end(&nsss_switch_enumerator, NSSS_SWITCH_SHADOW) ;
+  pthread_mutex_unlock(&nsss_switch_enumerator_mutex) ;
 }
diff --git a/src/libnsss/nsss_switch_enumerator.c b/src/libnsss/nsss_switch_enumerator.c
new file mode 100644
index 0000000..ca7d127
--- /dev/null
+++ b/src/libnsss/nsss_switch_enumerator.c
@@ -0,0 +1,9 @@
+/* ISC license. */
+
+#include <pthread.h>
+
+#include <nsss/nsss-switch.h>
+#include "nsss-switch-internal.h"
+
+nsss_switch_t nsss_switch_enumerator = NSSS_SWITCH_ZERO ;
+pthread_mutex_t nsss_switch_enumerator_mutex = PTHREAD_MUTEX_INITIALIZER ;
diff --git a/src/libnsss/nsss_switch_getgrent.c b/src/libnsss/nsss_switch_getgrent.c
index 6a6c8dc..cedcf8c 100644
--- a/src/libnsss/nsss_switch_getgrent.c
+++ b/src/libnsss/nsss_switch_getgrent.c
@@ -9,9 +9,9 @@
 
 struct group *nsss_switch_getgrent (void)
 {
-  if (!nsss_switch_start(&nsss_switch_here, NSSS_SWITCH_GRP, NSSS_NSSSD_PATH, 0, 0)) return 0 ;
+  if (!nsss_switch_start(&nsss_switch_enumerator, 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 ;
+  if (!nsss_switch_grp_get(&nsss_switch_enumerator, &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
index 92a4264..f13445c 100644
--- a/src/libnsss/nsss_switch_getgrent_r.c
+++ b/src/libnsss/nsss_switch_getgrent_r.c
@@ -1,8 +1,11 @@
 /* ISC license. */
 
 #include <errno.h>
+#include <pthread.h>
+
 #include <skalibs/stralloc.h>
 #include <skalibs/genalloc.h>
+
 #include <nsss/config.h>
 #include <nsss/grp-switch.h>
 #include <nsss/nsss-switch.h>
@@ -14,16 +17,18 @@ int nsss_switch_getgrent_r (struct group *gr, char *buf, size_t buflen, struct g
   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 ;
+  int e = pthread_mutex_lock(&nsss_switch_enumerator_mutex) ;
+  if (e) return e ;
+  if (!nsss_switch_start(&nsss_switch_enumerator, 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))
+  if (!nsss_switch_grp_get(&nsss_switch_enumerator, &gr2, &sa, &ga, 0, 0))
   {
     *grp = 0 ;
     if (!errno) errno = ENOENT ;
-    return errno ;
+    goto err ;
   }
+  pthread_mutex_unlock(&nsss_switch_enumerator_mutex) ;
   if (!nsss_grp_copy(gr, buf, buflen, &gr2, sa.s, sa.len, genalloc_s(char *, &ga), genalloc_len(char *, &ga)))
   {
     genalloc_free(char *, &ga) ;
@@ -35,4 +40,8 @@ int nsss_switch_getgrent_r (struct group *gr, char *buf, size_t buflen, struct g
   stralloc_free(&sa) ;
   *grp = gr ;
   return (errno = e, 0) ;
+
+ err:
+  pthread_mutex_unlock(&nsss_switch_enumerator_mutex) ;
+  return errno ;
 }
diff --git a/src/libnsss/nsss_switch_getgrgid.c b/src/libnsss/nsss_switch_getgrgid.c
index 65dbeef..57b71fc 100644
--- a/src/libnsss/nsss_switch_getgrgid.c
+++ b/src/libnsss/nsss_switch_getgrgid.c
@@ -1,22 +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_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 ;
+  if (!nsss_switch_query_start(NSSS_NSSSD_PATH, NSSS_SWITCH_GRP, 30000, 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 ;
+  return nsss_switch_grp_getbygid(&nsss_switch_query, &nsss_grp_here, &nsss_grp_sa_here, &nsss_grp_ga_here, gid, 0, 0) ? &nsss_grp_here : 0 ;
 }
diff --git a/src/libnsss/nsss_switch_getgrgid_r.c b/src/libnsss/nsss_switch_getgrgid_r.c
index 2eb4855..4113703 100644
--- a/src/libnsss/nsss_switch_getgrgid_r.c
+++ b/src/libnsss/nsss_switch_getgrgid_r.c
@@ -1,29 +1,38 @@
 /* ISC license. */
 
 #include <errno.h>
+#include <pthread.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_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 ;
+  int e = pthread_mutex_lock(&nsss_switch_query_mutex) ;
+  if (e) return e ;
+  e = errno ;
+  if (!nsss_switch_query_start(NSSS_NSSSD_PATH, NSSS_SWITCH_GRP, 30000, 0, 0))
+  {
+    pthread_mutex_unlock(&nsss_switch_query_mutex) ;
+    return errno ;
+  }
   errno = 0 ;
-  if (!nsss_switch_grp_getbygid(&a, &gr2, &sa, &ga, gid, 0, 0))
+  if (!nsss_switch_grp_getbygid(&nsss_switch_query, &gr2, &sa, &ga, gid, 0, 0))
   {
-    nsss_switch_end(&a, NSSS_SWITCH_GRP) ;
+    pthread_mutex_unlock(&nsss_switch_query_mutex) ;
     *grp = 0 ;
     return errno ? errno : (errno = e, 0) ;
   }
-  nsss_switch_end(&a, NSSS_SWITCH_GRP) ;
+  pthread_mutex_unlock(&nsss_switch_query_mutex) ;
   if (!nsss_grp_copy(gr, buf, buflen, &gr2, sa.s, sa.len, genalloc_s(char *, &ga), genalloc_len(char *, &ga)))
   {
     genalloc_free(char *, &ga) ;
diff --git a/src/libnsss/nsss_switch_getgrnam.c b/src/libnsss/nsss_switch_getgrnam.c
index 396f44e..9be1e18 100644
--- a/src/libnsss/nsss_switch_getgrnam.c
+++ b/src/libnsss/nsss_switch_getgrnam.c
@@ -1,22 +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_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 ;
+  if (!nsss_switch_query_start(NSSS_NSSSD_PATH, NSSS_SWITCH_GRP, 30000, 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 ;
+  return nsss_switch_grp_getbyname(&nsss_switch_query, &nsss_grp_here, &nsss_grp_sa_here, &nsss_grp_ga_here, name, 0, 0) ? &nsss_grp_here : 0 ;
 }
diff --git a/src/libnsss/nsss_switch_getgrnam_r.c b/src/libnsss/nsss_switch_getgrnam_r.c
index c35b8ef..b09484e 100644
--- a/src/libnsss/nsss_switch_getgrnam_r.c
+++ b/src/libnsss/nsss_switch_getgrnam_r.c
@@ -1,29 +1,38 @@
 /* ISC license. */
 
 #include <errno.h>
+#include <pthread.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_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 ;
+  int e = pthread_mutex_lock(&nsss_switch_query_mutex) ;
+  if (e) return (errno = e, 0) ;
+  e = errno ;
+  if (!nsss_switch_query_start(NSSS_NSSSD_PATH, NSSS_SWITCH_GRP, 30000, 0, 0))
+  {
+    pthread_mutex_unlock(&nsss_switch_query_mutex) ;
+    return errno ;
+  }
   errno = 0 ;
-  if (!nsss_switch_grp_getbyname(&a, &gr2, &sa, &ga, name, 0, 0))
+  if (!nsss_switch_grp_getbyname(&nsss_switch_query, &gr2, &sa, &ga, name, 0, 0))
   {
-    nsss_switch_end(&a, NSSS_SWITCH_GRP) ;
+    pthread_mutex_unlock(&nsss_switch_query_mutex) ;
     *grp = 0 ;
     return errno ? errno : (errno = e, 0) ;
   }
-  nsss_switch_end(&a, NSSS_SWITCH_GRP) ;
+  pthread_mutex_unlock(&nsss_switch_query_mutex) ;
   if (!nsss_grp_copy(gr, buf, buflen, &gr2, sa.s, sa.len, genalloc_s(char *, &ga), genalloc_len(char *, &ga)))
   {
     genalloc_free(char *, &ga) ;
diff --git a/src/libnsss/nsss_switch_getgrouplist.c b/src/libnsss/nsss_switch_getgrouplist.c
index 73d3fe0..868b463 100644
--- a/src/libnsss/nsss_switch_getgrouplist.c
+++ b/src/libnsss/nsss_switch_getgrouplist.c
@@ -2,6 +2,7 @@
 
 #include <stddef.h>
 #include <errno.h>
+#include <pthread.h>
 
 #include <skalibs/stralloc.h>
 
@@ -9,22 +10,25 @@
 #include <nsss/nsss-switch.h>
 #include <nsss/grp-switch.h>
 #include "nsss-internal.h"
+#include "nsss-switch-internal.h"
 
 int nsss_switch_getgrouplist (char const *user, gid_t gid, gid_t *gids, int *ngids)
 {
   stralloc sa = STRALLOC_ZERO ;
-  int e = errno ;
   size_t r = 0 ;
   size_t n ;
-  nsss_switch_t a = NSSS_SWITCH_ZERO ;
+  int e ;
   if (*ngids < 0) return (errno = EINVAL, -1) ;
   n = *ngids ;
-  if (!nsss_switch_start(&a, NSSS_SWITCH_GRP, NSSS_NSSSD_PATH, 0, 0)) return -1 ;
-  if (!nsss_switch_grp_getlist(&a, user, gids, n, &r, &sa, 0, 0))
+  e = pthread_mutex_lock(&nsss_switch_query_mutex) ;
+  if (e) return (errno = e, -1) ; 
+  e = errno ;
+  if (!nsss_switch_query_start(NSSS_NSSSD_PATH, NSSS_SWITCH_GRP, 30000, 0, 0)
+   || !nsss_switch_grp_getlist(&nsss_switch_query, user, gids, n, &r, &sa, 0, 0))
   {
-    nsss_switch_end(&a, NSSS_SWITCH_GRP) ;
+    pthread_mutex_unlock(&nsss_switch_query_mutex) ;
     return -1 ;
   }
-  nsss_switch_end(&a, NSSS_SWITCH_GRP) ;
+  pthread_mutex_unlock(&nsss_switch_query_mutex) ;
   return nsss_grouplist_adjust(n, r, gid, gids, ngids, e) ;
 }
diff --git a/src/libnsss/nsss_switch_getpwent.c b/src/libnsss/nsss_switch_getpwent.c
index 89cabfd..a339716 100644
--- a/src/libnsss/nsss_switch_getpwent.c
+++ b/src/libnsss/nsss_switch_getpwent.c
@@ -8,8 +8,8 @@
 
 struct passwd *nsss_switch_getpwent (void)
 {
-  if (!nsss_switch_start(&nsss_switch_here, NSSS_SWITCH_PWD, NSSS_NSSSD_PATH, 0, 0)) return 0 ;
+  if (!nsss_switch_start(&nsss_switch_enumerator, 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 ;
+  if (!nsss_switch_pwd_get(&nsss_switch_enumerator, &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
index 7795af0..e982f11 100644
--- a/src/libnsss/nsss_switch_getpwent_r.c
+++ b/src/libnsss/nsss_switch_getpwent_r.c
@@ -1,7 +1,10 @@
 /* ISC license. */
 
 #include <errno.h>
+#include <pthread.h>
+
 #include <skalibs/stralloc.h>
+
 #include <nsss/config.h>
 #include <nsss/pwd-switch.h>
 #include <nsss/nsss-switch.h>
@@ -12,16 +15,18 @@ int nsss_switch_getpwent_r (struct passwd *pw, char *buf, size_t buflen, struct
 {
   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 ;
+  int e = pthread_mutex_lock(&nsss_switch_enumerator_mutex) ;
+  if (e) return e ;
+  if (!nsss_switch_start(&nsss_switch_enumerator, NSSS_SWITCH_PWD, NSSS_NSSSD_PATH, 0, 0)) goto err ;
   e = errno ;
   errno = 0 ;
-  if (!nsss_switch_pwd_get(&nsss_switch_here, &pw2, &sa, 0, 0))
+  if (!nsss_switch_pwd_get(&nsss_switch_enumerator, &pw2, &sa, 0, 0))
   {
     *pwp = 0 ;
     if (!errno) errno = ENOENT ;
-    return errno ;
+    goto err ;
   }
+  pthread_mutex_unlock(&nsss_switch_enumerator_mutex) ;
   if (!nsss_pwd_copy(pw, buf, buflen, &pw2, sa.s, sa.len))
   {
     stralloc_free(&sa) ;
@@ -31,4 +36,8 @@ int nsss_switch_getpwent_r (struct passwd *pw, char *buf, size_t buflen, struct
   stralloc_free(&sa) ;
   *pwp = pw ;
   return (errno = e, 0) ;
+
+ err:
+  pthread_mutex_unlock(&nsss_switch_enumerator_mutex) ;
+  return errno ;
 }
diff --git a/src/libnsss/nsss_switch_getpwnam.c b/src/libnsss/nsss_switch_getpwnam.c
index 393503d..722e556 100644
--- a/src/libnsss/nsss_switch_getpwnam.c
+++ b/src/libnsss/nsss_switch_getpwnam.c
@@ -4,17 +4,11 @@
 #include <nsss/pwd-switch.h>
 #include <nsss/nsss-switch.h>
 #include "nsss-internal.h"
+#include "nsss-switch-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 ;
+  if (!nsss_switch_query_start(NSSS_NSSSD_PATH, NSSS_SWITCH_PWD, 30000, 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 ;
+  return nsss_switch_pwd_getbyname(&nsss_switch_query, &nsss_pwd_here, &nsss_pwd_sa_here, name, 0, 0) ? &nsss_pwd_here : 0 ;
 }
diff --git a/src/libnsss/nsss_switch_getpwnam_r.c b/src/libnsss/nsss_switch_getpwnam_r.c
index e1c1e71..53ab665 100644
--- a/src/libnsss/nsss_switch_getpwnam_r.c
+++ b/src/libnsss/nsss_switch_getpwnam_r.c
@@ -1,27 +1,36 @@
 /* ISC license. */
 
 #include <errno.h>
+#include <pthread.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_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 ;
+  int e = pthread_mutex_lock(&nsss_switch_query_mutex) ;
+  if (e) return e ;
+  e = errno ;
+  if (!nsss_switch_query_start(NSSS_NSSSD_PATH, NSSS_SWITCH_PWD, 30000, 0, 0))
+  {
+    pthread_mutex_unlock(&nsss_switch_query_mutex) ;
+    return errno ;
+  }
   errno = 0 ;
-  if (!nsss_switch_pwd_getbyname(&a, &pw2, &sa, name, 0, 0))
+  if (!nsss_switch_pwd_getbyname(&nsss_switch_query, &pw2, &sa, name, 0, 0))
   {
-    nsss_switch_end(&a, NSSS_SWITCH_PWD) ;
+    pthread_mutex_unlock(&nsss_switch_query_mutex) ;
     *pwp = 0 ;
     return errno ? errno : (errno = e, 0) ;
   }
-  nsss_switch_end(&a, NSSS_SWITCH_PWD) ;
+  pthread_mutex_unlock(&nsss_switch_query_mutex) ;
   if (!nsss_pwd_copy(pw, buf, buflen, &pw2, sa.s, sa.len))
   {
     stralloc_free(&sa) ;
diff --git a/src/libnsss/nsss_switch_getpwuid.c b/src/libnsss/nsss_switch_getpwuid.c
index 3d765bf..004e93c 100644
--- a/src/libnsss/nsss_switch_getpwuid.c
+++ b/src/libnsss/nsss_switch_getpwuid.c
@@ -4,17 +4,11 @@
 #include <nsss/pwd-switch.h>
 #include <nsss/nsss-switch.h>
 #include "nsss-internal.h"
+#include "nsss-switch-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 ;
+  if (!nsss_switch_query_start(NSSS_NSSSD_PATH, NSSS_SWITCH_PWD, 30000, 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 ;
+  return nsss_switch_pwd_getbyuid(&nsss_switch_query, &nsss_pwd_here, &nsss_pwd_sa_here, uid, 0, 0) ? &nsss_pwd_here : 0 ;
 }
diff --git a/src/libnsss/nsss_switch_getpwuid_r.c b/src/libnsss/nsss_switch_getpwuid_r.c
index 8e63a75..3eb17a6 100644
--- a/src/libnsss/nsss_switch_getpwuid_r.c
+++ b/src/libnsss/nsss_switch_getpwuid_r.c
@@ -1,27 +1,36 @@
 /* ISC license. */
 
 #include <errno.h>
+#include <pthread.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_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 ;
+  int e = pthread_mutex_lock(&nsss_switch_query_mutex) ;
+  if (e) return e ;
+  e = errno ;
+  if (!nsss_switch_query_start(NSSS_NSSSD_PATH, NSSS_SWITCH_PWD, 30000, 0, 0))
+  {
+    pthread_mutex_unlock(&nsss_switch_query_mutex) ;
+    return errno ;
+  }
   errno = 0 ;
-  if (!nsss_switch_pwd_getbyuid(&a, &pw2, &sa, uid, 0, 0))
+  if (!nsss_switch_pwd_getbyuid(&nsss_switch_query, &pw2, &sa, uid, 0, 0))
   {
-    nsss_switch_end(&a, NSSS_SWITCH_PWD) ;
+    pthread_mutex_unlock(&nsss_switch_query_mutex) ;
     *pwp = 0 ;
     return errno ? errno : (errno = e, 0) ;
   }
-  nsss_switch_end(&a, NSSS_SWITCH_PWD) ;
+  pthread_mutex_unlock(&nsss_switch_query_mutex) ;
   if (!nsss_pwd_copy(pw, buf, buflen, &pw2, sa.s, sa.len))
   {
     stralloc_free(&sa) ;
diff --git a/src/libnsss/nsss_switch_getspent.c b/src/libnsss/nsss_switch_getspent.c
index 65064a1..270737c 100644
--- a/src/libnsss/nsss_switch_getspent.c
+++ b/src/libnsss/nsss_switch_getspent.c
@@ -8,8 +8,8 @@
 
 struct spwd *nsss_switch_getspent (void)
 {
-  if (!nsss_switch_start(&nsss_switch_here, NSSS_SWITCH_SHADOW, NSSS_NSSSD_PATH, 0, 0)) return 0 ;
+  if (!nsss_switch_start(&nsss_switch_enumerator, 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 ;
+  if (!nsss_switch_shadow_get(&nsss_switch_enumerator, &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
index 118e095..25cebae 100644
--- a/src/libnsss/nsss_switch_getspent_r.c
+++ b/src/libnsss/nsss_switch_getspent_r.c
@@ -1,7 +1,10 @@
 /* ISC license. */
 
 #include <errno.h>
+#include <pthread.h>
+
 #include <skalibs/stralloc.h>
+
 #include <nsss/config.h>
 #include <nsss/shadow-switch.h>
 #include <nsss/nsss-switch.h>
@@ -12,16 +15,18 @@ int nsss_switch_getspent_r (struct spwd *sp, char *buf, size_t buflen, struct sp
 {
   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 ;
+  int e = pthread_mutex_lock(&nsss_switch_enumerator_mutex) ;
+  if (e) return e ;
+  if (!nsss_switch_start(&nsss_switch_enumerator, NSSS_SWITCH_SHADOW, NSSS_NSSSD_PATH, 0, 0)) goto err ;
   e = errno ;
   errno = 0 ;
-  if (!nsss_switch_shadow_get(&nsss_switch_here, &sp2, &sa, 0, 0))
+  if (!nsss_switch_shadow_get(&nsss_switch_enumerator, &sp2, &sa, 0, 0))
   {
     *spp = 0 ;
     if (!errno) errno = ENOENT ;
-    return errno ;
+    goto err ;
   }
+  pthread_mutex_unlock(&nsss_switch_enumerator_mutex) ;
   if (!nsss_shadow_copy(sp, buf, buflen, &sp2, sa.s, sa.len))
   {
     stralloc_free(&sa) ;
@@ -31,4 +36,8 @@ int nsss_switch_getspent_r (struct spwd *sp, char *buf, size_t buflen, struct sp
   stralloc_free(&sa) ;
   *spp = sp ;
   return (errno = e, 0) ;
+
+ err:
+  pthread_mutex_unlock(&nsss_switch_enumerator_mutex) ;
+  return errno ;
 }
diff --git a/src/libnsss/nsss_switch_getspnam.c b/src/libnsss/nsss_switch_getspnam.c
index 01184ec..af2f8da 100644
--- a/src/libnsss/nsss_switch_getspnam.c
+++ b/src/libnsss/nsss_switch_getspnam.c
@@ -4,17 +4,11 @@
 #include <nsss/shadow-switch.h>
 #include <nsss/nsss-switch.h>
 #include "nsss-internal.h"
+#include "nsss-switch-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 ;
+  if (!nsss_switch_query_start(NSSS_NSSSD_PATH, NSSS_SWITCH_SHADOW, 30000, 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 ;
+  return nsss_switch_shadow_getbyname(&nsss_switch_query, &nsss_shadow_here, &nsss_shadow_sa_here, name, 0, 0) ? &nsss_shadow_here : 0 ;
 }
diff --git a/src/libnsss/nsss_switch_getspnam_r.c b/src/libnsss/nsss_switch_getspnam_r.c
index 9c6b86f..7652004 100644
--- a/src/libnsss/nsss_switch_getspnam_r.c
+++ b/src/libnsss/nsss_switch_getspnam_r.c
@@ -1,27 +1,36 @@
 /* ISC license. */
 
 #include <errno.h>
+#include <pthread.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_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 ;
+  int e = pthread_mutex_lock(&nsss_switch_query_mutex) ;
+  if (e) return e ;
+  e = errno ;
+  if (!nsss_switch_query_start(NSSS_NSSSD_PATH, NSSS_SWITCH_SHADOW, 30000, 0, 0))
+  {
+    pthread_mutex_unlock(&nsss_switch_query_mutex) ;
+    return errno ;
+  }
   errno = 0 ;
-  if (!nsss_switch_shadow_getbyname(&a, &sp2, &sa, name, 0, 0))
+  if (!nsss_switch_shadow_getbyname(&nsss_switch_query, &sp2, &sa, name, 0, 0))
   {
-    nsss_switch_end(&a, NSSS_SWITCH_SHADOW) ;
+    pthread_mutex_unlock(&nsss_switch_query_mutex) ;
     *spp = 0 ;
     return errno ? errno : (errno = e, 0) ;
   }
-  nsss_switch_end(&a, NSSS_SWITCH_SHADOW) ;
+  pthread_mutex_unlock(&nsss_switch_query_mutex) ;
   if (!nsss_shadow_copy(sp, buf, buflen, &sp2, sa.s, sa.len))
   {
     stralloc_free(&sa) ;
diff --git a/src/libnsss/nsss_switch_grp_get.c b/src/libnsss/nsss_switch_grp_get.c
index 8ba52b1..d925cd1 100644
--- a/src/libnsss/nsss_switch_grp_get.c
+++ b/src/libnsss/nsss_switch_grp_get.c
@@ -1,15 +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_grp_get (nsss_switch_t *a, struct group *gr, stralloc *sa, genalloc *ga, tain const *deadline, tain *stamp)
 {
   unsigned char c = NSSS_SWITCH_GRP_GET ;
-  if (!ipc_timed_send(buffer_fd(&a->b), (char *)&c, 1, deadline, stamp)) return 0 ;
+  if (!nsss_switch_send(a, (char *)&c, 1, deadline, stamp)) return 0 ;
   if (!buffer_timed_get(&a->b, (char *)&c, 1, deadline, stamp)) return 0 ;
   if (c == 255) return 0 ;
   if (c) return (errno = c, 0) ;
diff --git a/src/libnsss/nsss_switch_grp_getbygid.c b/src/libnsss/nsss_switch_grp_getbygid.c
index d40235c..79e95c7 100644
--- a/src/libnsss/nsss_switch_grp_getbygid.c
+++ b/src/libnsss/nsss_switch_grp_getbygid.c
@@ -1,9 +1,10 @@
 /* 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"
 
@@ -11,7 +12,7 @@ int nsss_switch_grp_getbygid (nsss_switch_t *a, struct group *gr, stralloc *sa,
 {
   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 (!nsss_switch_send(a, 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 = (unsigned char)buf[0], 0) ;
diff --git a/src/libnsss/nsss_switch_grp_getbyname.c b/src/libnsss/nsss_switch_grp_getbyname.c
index 2b7448a..de397ce 100644
--- a/src/libnsss/nsss_switch_grp_getbyname.c
+++ b/src/libnsss/nsss_switch_grp_getbyname.c
@@ -3,9 +3,10 @@
 #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"
 
@@ -16,7 +17,7 @@ int nsss_switch_grp_getbyname (nsss_switch_t *a, struct group *gr, stralloc *sa,
   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 (!nsss_switch_sendv(a, 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 = (unsigned char)buf[0], 0) ;
diff --git a/src/libnsss/nsss_switch_grp_getlist.c b/src/libnsss/nsss_switch_grp_getlist.c
index 22fb156..f637c0d 100644
--- a/src/libnsss/nsss_switch_grp_getlist.c
+++ b/src/libnsss/nsss_switch_grp_getlist.c
@@ -13,6 +13,7 @@
 #include <skalibs/unix-timed.h>
 
 #include <nsss/nsss-switch.h>
+#include "nsss-switch-internal.h"
 
  /*
     Expects:
@@ -59,7 +60,7 @@ int nsss_switch_grp_getlist (nsss_switch_t *a, char const *user, gid_t *gids, si
   if (len > NSSS_SWITCH_NAME_MAXLEN - 1) return (errno = EINVAL, 0) ;
   uint64_pack_big(buf + 1, n) ;
   uint32_pack_big(buf + 9, len + 1) ;
-  if (!ipc_timed_sendv(buffer_fd(&a->b), v, 2, deadline, stamp)) return 0 ;
+  if (!nsss_switch_sendv(a, v, 2, deadline, stamp)) return 0 ;
   if (!buffer_timed_get(&a->b, &buf[0], 1, deadline, stamp)) return 0 ;
   if (buf[0]) return (errno = (unsigned char)buf[0], 0) ;
   return nsss_switch_grouplist_read(&a->b, n, r, gids, sa, deadline, stamp) ;
diff --git a/src/libnsss/nsss_switch_op.c b/src/libnsss/nsss_switch_op.c
index 7e9c1b3..4753432 100644
--- a/src/libnsss/nsss_switch_op.c
+++ b/src/libnsss/nsss_switch_op.c
@@ -1,15 +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 const *deadline, tain *stamp)
 {
   unsigned char c ;
-  if (!ipc_timed_send(buffer_fd(&a->b), &op, 1, deadline, stamp)) return 0 ;
+  if (!nsss_switch_send(a, &op, 1, deadline, stamp)) return 0 ;
   if (!buffer_timed_get(&a->b, (char *)&c, 1, deadline, stamp)) return 0 ;
   if (c) return (errno = c, 0) ;
   return 1 ;
diff --git a/src/libnsss/nsss_switch_pwd_get.c b/src/libnsss/nsss_switch_pwd_get.c
index 146e934..b3c3a34 100644
--- a/src/libnsss/nsss_switch_pwd_get.c
+++ b/src/libnsss/nsss_switch_pwd_get.c
@@ -1,15 +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_pwd_get (nsss_switch_t *a, struct passwd *pw, stralloc *sa, tain const *deadline, tain *stamp)
 {
   unsigned char c = NSSS_SWITCH_PWD_GET ;
-  if (!ipc_timed_send(buffer_fd(&a->b), (char *)&c, 1, deadline, stamp)) return 0 ;
+  if (!nsss_switch_send(a, (char *)&c, 1, deadline, stamp)) return 0 ;
   if (!buffer_timed_get(&a->b, (char *)&c, 1, deadline, stamp)) return 0 ;
   if (c == 255) return 0 ;
   if (c) return (errno = c, 0) ;
diff --git a/src/libnsss/nsss_switch_pwd_getbyname.c b/src/libnsss/nsss_switch_pwd_getbyname.c
index eea9923..b360c4e 100644
--- a/src/libnsss/nsss_switch_pwd_getbyname.c
+++ b/src/libnsss/nsss_switch_pwd_getbyname.c
@@ -3,9 +3,10 @@
 #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"
 
@@ -16,7 +17,7 @@ int nsss_switch_pwd_getbyname (nsss_switch_t *a, struct passwd *pw, stralloc *sa
   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 (!nsss_switch_sendv(a, 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 = (unsigned char)buf[0], 0) ;
diff --git a/src/libnsss/nsss_switch_pwd_getbyuid.c b/src/libnsss/nsss_switch_pwd_getbyuid.c
index e5b5c8a..2b3d52f 100644
--- a/src/libnsss/nsss_switch_pwd_getbyuid.c
+++ b/src/libnsss/nsss_switch_pwd_getbyuid.c
@@ -1,9 +1,10 @@
 /* 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"
 
@@ -11,7 +12,7 @@ int nsss_switch_pwd_getbyuid (nsss_switch_t *a, struct passwd *pw, stralloc *sa,
 {
   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 (!nsss_switch_send(a, 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 = (unsigned char)buf[0], 0) ;
diff --git a/src/libnsss/nsss_switch_here.c b/src/libnsss/nsss_switch_query.c
index 994974b..523d4ce 100644
--- a/src/libnsss/nsss_switch_here.c
+++ b/src/libnsss/nsss_switch_query.c
@@ -1,6 +1,8 @@
 /* ISC license. */
 
+#include <pthread.h>
+
 #include <nsss/nsss-switch.h>
 #include "nsss-switch-internal.h"
 
-nsss_switch_t nsss_switch_here = NSSS_SWITCH_ZERO ;
+nsss_switch_t nsss_switch_query = NSSS_SWITCH_ZERO ;
diff --git a/src/libnsss/nsss_switch_query_mutex.c b/src/libnsss/nsss_switch_query_mutex.c
new file mode 100644
index 0000000..549f42b
--- /dev/null
+++ b/src/libnsss/nsss_switch_query_mutex.c
@@ -0,0 +1,7 @@
+/* ISC license. */
+
+#include <pthread.h>
+
+#include "nsss-switch-internal.h"
+
+pthread_mutex_t nsss_switch_query_mutex = PTHREAD_MUTEX_INITIALIZER ;
diff --git a/src/libnsss/nsss_switch_query_start.c b/src/libnsss/nsss_switch_query_start.c
new file mode 100644
index 0000000..007fa90
--- /dev/null
+++ b/src/libnsss/nsss_switch_query_start.c
@@ -0,0 +1,12 @@
+/* ISC license. */
+
+#include <nsss/nsss-switch.h>
+#include "nsss-switch-internal.h"
+
+int nsss_switch_query_start (char const *path, unsigned int what, unsigned int timeout, tain const *deadline, tain *stamp) 
+{
+  unsigned int held = nsss_switch_query.held ;
+  if (!nsss_switch_start(&nsss_switch_query, what, path, deadline, stamp)) return 0 ;
+  if (!held && !nsss_switch_set_timeout(&nsss_switch_query, timeout, deadline, stamp)) return 0 ;
+  return 1 ;
+}
diff --git a/src/libnsss/nsss_switch_send.c b/src/libnsss/nsss_switch_send.c
new file mode 100644
index 0000000..ecef1f4
--- /dev/null
+++ b/src/libnsss/nsss_switch_send.c
@@ -0,0 +1,25 @@
+/* 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_send (nsss_switch_t *a, char const *s, size_t len, tain const *deadline, tain *stamp)
+{
+  if (!ipc_timed_send(buffer_fd(&a->b), s, len, deadline, stamp))
+  {
+    unsigned int what ;
+    char const *path ;
+    if (errno != ECONNRESET || !a->path) return 0 ;
+    what = a->held ;
+    path = a->path ;
+    nsss_switch_end(a, what) ;
+    if (!nsss_switch_start(a, what, path, deadline, stamp)) return 0 ;
+    if (!ipc_timed_send(buffer_fd(&a->b), s, len, deadline, stamp)) return 0 ;
+  }
+  return 1 ;
+}
diff --git a/src/libnsss/nsss_switch_sendv.c b/src/libnsss/nsss_switch_sendv.c
new file mode 100644
index 0000000..2590686
--- /dev/null
+++ b/src/libnsss/nsss_switch_sendv.c
@@ -0,0 +1,25 @@
+/* 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_sendv (nsss_switch_t *a, struct iovec const *v, unsigned int n, tain const *deadline, tain *stamp)
+{
+  if (!ipc_timed_sendv(buffer_fd(&a->b), v, n, deadline, stamp))
+  {
+    unsigned int what ;
+    char const *path ;
+    if (errno != ECONNRESET || !a->path) return 0 ;
+    what = a->held ;
+    path = a->path ;
+    nsss_switch_end(a, what) ;
+    if (!nsss_switch_start(a, what, path, deadline, stamp)) return 0 ;
+    if (!ipc_timed_sendv(buffer_fd(&a->b), v, n, deadline, stamp)) return 0 ;
+  }
+  return 1 ;
+}
diff --git a/src/libnsss/nsss_switch_set_timeout.c b/src/libnsss/nsss_switch_set_timeout.c
new file mode 100644
index 0000000..ce037db
--- /dev/null
+++ b/src/libnsss/nsss_switch_set_timeout.c
@@ -0,0 +1,21 @@
+/* ISC license. */
+
+#include <stdint.h>
+#include <errno.h>
+
+#include <skalibs/uint32.h>
+#include <skalibs/unix-timed.h>
+
+#include <nsss/nsss-switch.h>
+#include "nsss-switch-internal.h"
+
+int nsss_switch_set_timeout (nsss_switch_t *a, unsigned int t, tain const *deadline, tain *stamp)
+{
+  char buf[5] = { NSSS_SWITCH_SET_TIMEOUT } ;
+  uint32_pack_big(buf + 1, (uint32_t)t) ;
+  if (!nsss_switch_send(a, 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 = (unsigned char)buf[0], 0) ;
+  return 1 ;
+}
diff --git a/src/libnsss/nsss_switch_setgrent.c b/src/libnsss/nsss_switch_setgrent.c
index a930568..81bc35c 100644
--- a/src/libnsss/nsss_switch_setgrent.c
+++ b/src/libnsss/nsss_switch_setgrent.c
@@ -7,6 +7,6 @@
 
 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) ;
+  if (!nsss_switch_start(&nsss_switch_enumerator, NSSS_SWITCH_GRP, NSSS_NSSSD_PATH, 0, 0)) return ;
+  nsss_switch_grp_rewind(&nsss_switch_enumerator, 0, 0) ;
 }
diff --git a/src/libnsss/nsss_switch_setpwent.c b/src/libnsss/nsss_switch_setpwent.c
index 371423e..5b21f21 100644
--- a/src/libnsss/nsss_switch_setpwent.c
+++ b/src/libnsss/nsss_switch_setpwent.c
@@ -7,6 +7,6 @@
 
 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) ;
+  if (!nsss_switch_start(&nsss_switch_enumerator, NSSS_SWITCH_PWD, NSSS_NSSSD_PATH, 0, 0)) return ;
+  nsss_switch_pwd_rewind(&nsss_switch_enumerator, 0, 0) ;
 }
diff --git a/src/libnsss/nsss_switch_setspent.c b/src/libnsss/nsss_switch_setspent.c
index 5f5ed8a..fce844c 100644
--- a/src/libnsss/nsss_switch_setspent.c
+++ b/src/libnsss/nsss_switch_setspent.c
@@ -7,6 +7,6 @@
 
 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) ;
+  if (!nsss_switch_start(&nsss_switch_enumerator, NSSS_SWITCH_SHADOW, NSSS_NSSSD_PATH, 0, 0)) return ;
+  nsss_switch_shadow_rewind(&nsss_switch_enumerator, 0, 0) ;
 }
diff --git a/src/libnsss/nsss_switch_shadow_get.c b/src/libnsss/nsss_switch_shadow_get.c
index a2fc431..4c0a722 100644
--- a/src/libnsss/nsss_switch_shadow_get.c
+++ b/src/libnsss/nsss_switch_shadow_get.c
@@ -1,15 +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_shadow_get (nsss_switch_t *a, struct spwd *sp, stralloc *sa, tain const *deadline, tain *stamp)
 {
   unsigned char c = NSSS_SWITCH_SHADOW_GET ;
-  if (!ipc_timed_send(buffer_fd(&a->b), (char *)&c, 1, deadline, stamp)) return 0 ;
+  if (!nsss_switch_send(a, (char *)&c, 1, deadline, stamp)) return 0 ;
   if (!buffer_timed_get(&a->b, (char *)&c, 1, deadline, stamp)) return 0 ;
   if (c == 255) return 0 ;
   if (c) return (errno = c, 0) ;
diff --git a/src/libnsss/nsss_switch_shadow_getbyname.c b/src/libnsss/nsss_switch_shadow_getbyname.c
index d5cf57a..4d2911f 100644
--- a/src/libnsss/nsss_switch_shadow_getbyname.c
+++ b/src/libnsss/nsss_switch_shadow_getbyname.c
@@ -3,9 +3,10 @@
 #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"
 
@@ -16,7 +17,7 @@ int nsss_switch_shadow_getbyname (nsss_switch_t *a, struct spwd *sp, stralloc *s
   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 (!nsss_switch_sendv(a, 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 = (unsigned char)buf[0], 0) ;
diff --git a/src/libnsss/nsss_switch_start.c b/src/libnsss/nsss_switch_start.c
index 220a7e2..ba014ae 100644
--- a/src/libnsss/nsss_switch_start.c
+++ b/src/libnsss/nsss_switch_start.c
@@ -22,6 +22,7 @@ static inline int nsss_switch_connect (nsss_switch_t *a, char const *path, tain
 int nsss_switch_start (nsss_switch_t *a, unsigned int what, char const *path, tain const *deadline, tain *stamp)
 {
   if (!a->held && !nsss_switch_connect(a, path, deadline, stamp)) return 0 ;
-  a->held |= (1U << what) ;
+  a->held |= what & 0x7u ;
+  a->path = path ;
   return 1 ;
 }
diff --git a/src/libnsss/nsss_switch_startf.c b/src/libnsss/nsss_switch_startf.c
new file mode 100644
index 0000000..faabd1f
--- /dev/null
+++ b/src/libnsss/nsss_switch_startf.c
@@ -0,0 +1,26 @@
+/* ISC license. */
+
+#include <sys/types.h>
+
+#include <skalibs/posixplz.h>
+#include <skalibs/buffer.h>
+#include <skalibs/djbunix.h>
+
+#include <nsss/nsss-switch.h>
+
+static inline pid_t nsss_switch_spawn (nsss_switch_t *a, char const *const *argv, tain const *deadline, tain *stamp)
+{
+  int fd ;
+  pid_t pid = child_spawn1_socket(argv[0], argv, (char const *const *)environ, &fd) ;
+  if (!pid) return 0 ;
+  buffer_init(&a->b, &buffer_read, fd, a->buf, NSSS_SWITCH_BUFSIZE) ;
+  return pid ;
+}
+
+int nsss_switch_startf (nsss_switch_t *a, unsigned int what, char const *const *argv, tain const *deadline, tain *stamp)
+{
+  if (!a->held && !nsss_switch_spawn(a, argv, deadline, stamp)) return 0 ;
+  a->held |= what & 0x7u ;
+  a->path = 0 ;
+  return 1 ;
+}
diff --git a/src/nsssd/deps-exe/nsssd-switch b/src/nsssd/deps-exe/nsssd-switch
new file mode 100644
index 0000000..81b2820
--- /dev/null
+++ b/src/nsssd/deps-exe/nsssd-switch
@@ -0,0 +1,5 @@
+${LIBNSSSD}
+${LIBNSSS}
+-lskarnet
+${SOCKET_LIB}
+${SYSCLOCK_LIB}
diff --git a/src/nsssd/deps-exe/nsssd-unix b/src/nsssd/deps-exe/nsssd-unix
index deff087..5958e7a 100644
--- a/src/nsssd/deps-exe/nsssd-unix
+++ b/src/nsssd/deps-exe/nsssd-unix
@@ -1,3 +1,3 @@
-${LIBNSSS}
 ${LIBNSSSD}
+${LIBNSSS}
 -lskarnet
diff --git a/src/nsssd/nsssd-nslcd.c b/src/nsssd/nsssd-nslcd.c
index 75df846..b8e4b00 100644
--- a/src/nsssd/nsssd-nslcd.c
+++ b/src/nsssd/nsssd-nslcd.c
@@ -56,7 +56,7 @@ void *nsssd_handle_init (void)
   return &a ;
 }
 
-int nsssd_handle_start (void *handle, char const *const *argv, char const *const *envp)
+int nsssd_handle_start (void *handle, char const *const *argv)
 {
   nslcd_handle_t *a = handle ;
   if (!argv[0]) strerr_dieusage(100, USAGE) ;
@@ -339,6 +339,7 @@ int nsssd_pwd_getbyname (void *handle, struct passwd *pw, char const *name)
 
 void nsssd_pwd_end (void *handle)
 {
+  (void)handle ;
 }
 
 int nsssd_grp_start (void *handle)
@@ -480,6 +481,7 @@ int nsssd_grp_getlist (void *handle, char const *user, gid_t *gids, size_t n, si
 
 void nsssd_grp_end (void *handle)
 {
+  (void)handle ;
 }
 
 int nsssd_shadow_start (void *handle)
@@ -571,9 +573,10 @@ int nsssd_shadow_getbyname (void *handle, struct spwd *sp, char const *name)
 
 void nsssd_shadow_end (void *handle)
 {
+  (void)handle ;
 }
 
-int main (int argc, char const *const *argv, char const *const *envp)
+int main (int argc, char const *const *argv)
 {
   PROG = "nsssd-nslcd" ;
   {
@@ -593,5 +596,5 @@ int main (int argc, char const *const *argv, char const *const *envp)
     if (t) tain_from_millisecs(&tto, t) ;
   }
 
-  return nsssd_main(argv, envp) ;
+  return nsssd_main(argv) ;
 }
diff --git a/src/nsssd/nsssd-switch.c b/src/nsssd/nsssd-switch.c
new file mode 100644
index 0000000..91eb1ce
--- /dev/null
+++ b/src/nsssd/nsssd-switch.c
@@ -0,0 +1,292 @@
+/* ISC license. */
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <skalibs/types.h>
+#include <skalibs/buffer.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/sgetopt.h>
+#include <skalibs/tai.h>
+
+#include <nsss/nsssd.h>
+#include <nsss/nsss-switch.h>
+#include <nsss/nsss-unix.h>
+
+#define USAGE "nsssd-switch flag1 backend1... \"\" flag2 backend2... \"\""
+#define dieusage() strerr_dieusage(100, USAGE)
+
+#define MAX_BACKENDS 16
+
+static tain tto = TAIN_INFINITE_RELATIVE ;
+
+
+ /* We cannot depend on execline so we duplicate functions here */
+
+static unsigned int el_getstrict (void)
+{
+  static unsigned int strict = 0 ;
+  static int first = 1 ;
+  if (first)
+  {
+    char const *x = getenv("EXECLINE_STRICT") ;
+    first = 0 ;
+    if (x) uint0_scan(x, &strict) ;
+  }
+  return strict ;
+}
+
+static int el_semicolon (char const **argv)
+{
+  static unsigned int nblock = 0 ;
+  int argc1 = 0 ;
+  nblock++ ;
+  for (;; argc1++, argv++)
+  {
+    char const *arg = *argv ;
+    if (!arg) return argc1 + 1 ;
+    if (!arg[0]) return argc1 ;
+    else if (arg[0] == ' ') ++*argv ;
+    else
+    {
+      unsigned int strict = el_getstrict() ;
+      if (strict)
+      {
+        char fmt1[UINT_FMT] ;
+        char fmt2[UINT_FMT] ;
+        fmt1[uint_fmt(fmt1, nblock)] = 0 ;
+        fmt2[uint_fmt(fmt2, (unsigned int)argc1)] = 0 ;
+        if (strict >= 2)
+          strerr_dief6x(100, "unquoted argument ", arg, " at block ", fmt1, " position ", fmt2) ;
+        else
+          strerr_warnw6x("unquoted argument ", arg, " at block ", fmt1, " position ", fmt2) ;
+      }
+    }
+  }
+}
+
+
+ /* Real code here */
+
+typedef struct backend_s backend_t, *backend_t_ref ;
+struct backend_s
+{
+  char const *const *argv ;
+  nsss_switch_t handle ;
+  uint8_t flags ;
+} ;
+
+typedef struct handle_s handle_t, *handle_t_ref ;
+struct handle_s
+{
+  backend_t tab[MAX_BACKENDS] ;
+  unsigned int n ;
+} ;
+
+void *nsssd_handle_init (void)
+{
+  static handle_t a = { .n = 0 } ;
+  return &a ;
+}
+
+int nsssd_handle_start (void *handle, char const *const *argv)
+{
+  static nsss_switch_t const nsss_switch_zero = NSSS_SWITCH_ZERO ;
+  handle_t *a = handle ;
+  char const **args = (char const **)argv ;
+  unsigned int argc = 0 ;
+  while (args[argc])
+  {
+    backend_t *be = &a->tab[a->n] ;
+    int argc1 ;
+    unsigned int flags ;
+    if (!uint0_scan(args[argc++], &flags)) dieusage() ;
+    if (!args[argc]) strerr_dief1x(100, "missing block") ;
+    argc1 = el_semicolon(args + argc) ;
+    if (!argc1) strerr_dief1x(100, "empty block") ;
+    if (!args[argc + argc1]) strerr_dief1x(100, "unterminated block") ;
+    args[argc + argc1] = 0 ;
+    if (a->n++ >= MAX_BACKENDS) strerr_dief1x(100, "too many defined backends") ;
+    be->flags = flags & 0x7 ;
+    be->argv = args + argc ;
+    be->handle = nsss_switch_zero ;
+    argc += argc1 ;
+  }
+  if (!a->n) strerr_dief1x(100, "no defined backends") ;
+  return 1 ;
+}
+
+void nsssd_handle_end (void *handle)
+{
+  handle_t *a = handle ;
+  for (unsigned int i = 0 ; i < a->n ; i++)
+    nsss_switch_end(&a->tab[i].handle, NSSS_SWITCH_PWD | NSSS_SWITCH_GRP | NSSS_SWITCH_SHADOW) ;
+  a->n = 0 ;
+}
+
+int nsssd_pwd_start (void *handle)
+{
+  (void)handle ;
+  return 1 ;
+}
+
+int nsssd_pwd_rewind (void *handle)
+{
+  nsss_unix_setpwent() ;
+  (void)handle ;
+  return 1 ;
+}
+
+int nsssd_pwd_get (void *handle, struct passwd *pw)
+{
+  struct passwd *pw2 = nsss_unix_getpwent() ;
+  if (!pw2) return 0 ;
+  *pw = *pw2 ;
+  (void)handle ;
+  return 1 ;
+}
+
+int nsssd_pwd_getbyuid (void *handle, struct passwd *pw, uid_t uid)
+{
+  struct passwd *pw2 = nsss_unix_getpwuid(uid) ;
+  if (!pw2) return 0 ;
+  *pw = *pw2 ;
+  (void)handle ;
+  return 1 ;
+}
+
+int nsssd_pwd_getbyname (void *handle, struct passwd *pw, char const *name)
+{
+  struct passwd *pw2 = nsss_unix_getpwnam(name) ;
+  if (!pw2) return 0 ;
+  *pw = *pw2 ;
+  (void)handle ;
+  return 1 ;
+}
+
+void nsssd_pwd_end (void *handle)
+{
+  nsss_unix_endpwent() ;
+  (void)handle ;
+}
+
+void nsssd_grp_handle_init (void *handle)
+{
+  (void)handle ;
+}
+
+int nsssd_grp_start (void *handle)
+{
+  (void)handle ;
+  return 1 ;
+}
+
+int nsssd_grp_rewind (void *handle)
+{
+  nsss_unix_setgrent() ;
+  (void)handle ;
+  return 1 ;
+}
+
+int nsssd_grp_get (void *handle, struct group *gr)
+{
+  struct group *gr2 = nsss_unix_getgrent() ;
+  if (!gr2) return 0 ;
+  *gr = *gr2 ;
+  (void)handle ;
+  return 1 ;
+}
+
+int nsssd_grp_getbygid (void *handle, struct group *gr, gid_t gid)
+{
+  struct group *gr2 = nsss_unix_getgrgid(gid) ;
+  if (!gr2) return 0 ;
+  *gr = *gr2 ;
+  (void)handle ;
+  return 1 ;
+}
+
+int nsssd_grp_getbyname (void *handle, struct group *gr, char const *name)
+{
+  struct group *gr2 = nsss_unix_getgrnam(name) ;
+  if (!gr2) return 0 ;
+  *gr = *gr2 ;
+  (void)handle ;
+  return 1 ;
+}
+
+int nsssd_grp_getlist (void *handle, char const *user, gid_t *gids, size_t n, size_t *r)
+{
+  (void)handle ;
+  return nsss_unix_getgrouplist_preadjust(user, gids, n, r) ;
+}
+
+void nsssd_grp_end (void *handle)
+{
+  nsss_unix_endgrent() ;
+  (void)handle ;
+}
+
+void nsssd_shadow_handle_init (void *handle)
+{
+  (void)handle ;
+}
+
+int nsssd_shadow_start (void *handle)
+{
+  (void)handle ;
+  return 1 ;
+}
+
+int nsssd_shadow_rewind (void *handle)
+{
+  nsss_unix_setspent() ;
+  (void)handle ;
+  return 1 ;
+}
+
+int nsssd_shadow_get (void *handle, struct spwd *sp)
+{
+  struct spwd *sp2 = nsss_unix_getspent() ;
+  if (!sp2) return 0 ;
+  *sp = *sp2 ;
+  (void)handle ;
+  return 1 ;
+}
+
+int nsssd_shadow_getbyname (void *handle, struct spwd *sp, char const *name)
+{
+  struct spwd *sp2 = nsss_unix_getspnam(name) ;
+  if (!sp2) return 0 ;
+  *sp = *sp2 ;
+  (void)handle ;
+  return 1 ;
+}
+
+void nsssd_shadow_end (void *handle)
+{
+  nsss_unix_endspent() ;
+  (void)handle ;
+}
+
+int main (int argc, char const *const *argv)
+{
+  PROG = "nsssd-switch" ;
+  {
+    subgetopt l = SUBGETOPT_ZERO ;
+    unsigned int t = 0 ;
+    for (;;)
+    {
+      int opt = subgetopt_r(argc, argv, "t:", &l) ;
+      if (opt == -1) break ;
+      switch (opt)
+      {
+        case 't' : if (!uint0_scan(l.arg, &t)) dieusage() ; break ;
+        default : dieusage() ;
+      }
+    }
+    argc -= l.ind ; argv += l.ind ;
+    if (t) tain_from_millisecs(&tto, t) ;
+  }
+  return nsssd_main(argv) ;
+}
diff --git a/src/nsssd/nsssd-unix.c b/src/nsssd/nsssd-unix.c
index 6cbb3f2..3974cb5 100644
--- a/src/nsssd/nsssd-unix.c
+++ b/src/nsssd/nsssd-unix.c
@@ -1,6 +1,7 @@
 /* ISC license. */
 
 #include <skalibs/strerr2.h>
+
 #include <nsss/pwd-unix.h>
 #include <nsss/grp-unix.h>
 #include <nsss/shadow-unix.h>
@@ -11,11 +12,10 @@ void *nsssd_handle_init (void)
   return 0 ;
 }
 
-int nsssd_handle_start (void *handle, char const *const *argv, char const *const *envp)
+int nsssd_handle_start (void *handle, char const *const *argv)
 {
   (void)handle ;
   (void)argv ;
-  (void)envp ;
   return 1 ;
 }
 
@@ -169,8 +169,9 @@ void nsssd_shadow_end (void *handle)
   (void)handle ;
 }
 
-int main (int argc, char const *const *argv, char const *const *envp)
+int main (int argc, char const *const *argv)
 {
   PROG = "nsssd-unix" ;
-  return nsssd_main(argv+1, envp) ;
+  (void)argc ;
+  return nsssd_main(argv+1) ;
 }
diff --git a/src/nsssd/nsssd_main.c b/src/nsssd/nsssd_main.c
index 9dbc27c..ba23e05 100644
--- a/src/nsssd/nsssd_main.c
+++ b/src/nsssd/nsssd_main.c
@@ -1,5 +1,6 @@
 /* ISC license. */
 
+#include <stdint.h>
 #include <string.h>
 #include <errno.h>
 #include <unistd.h>
@@ -23,12 +24,13 @@
 #include <nsss/nsssd.h>
 
 static unsigned int initted = 0 ;
+static tain tto = TAIN_INFINITE_RELATIVE ;
+static tain outertto = TAIN_INFINITE_RELATIVE ;
 
 static void get0 (char *s, size_t n)
 {
   tain deadline ;
-  tain_ulong(&deadline, 30) ;
-  tain_add_g(&deadline, &deadline) ;
+  tain_add_g(&deadline, &tto) ;
   if (buffer_timed_get_g(buffer_0small, s, n, &deadline) < n)
     strerr_diefu1sys(111, "read from stdin") ;
 }
@@ -37,8 +39,7 @@ static void put1 (char const *s, size_t n)
 {
   size_t w = 0 ;
   tain deadline ;
-  tain_ulong(&deadline, 30) ;
-  tain_add_g(&deadline, &deadline) ;
+  tain_add_g(&deadline, &tto) ;
   while (!buffer_putall(buffer_1, s, n, &w))
   {
     if (!buffer_timed_flush_g(buffer_1, &deadline))
@@ -49,8 +50,7 @@ static void put1 (char const *s, size_t n)
 static void flush1 (void)
 {
   tain deadline ;
-  tain_ulong(&deadline, 2) ;
-  tain_add_g(&deadline, &deadline) ;
+  tain_add_g(&deadline, &tto) ;
   if (!buffer_timed_flush_g(buffer_1, &deadline))
     strerr_diefu1sys(111, "write to stdout") ;
 }
@@ -131,6 +131,16 @@ static inline void print_sp (struct spwd const *sp)
   flush1() ;
 }
 
+static inline void do_set_timeout (void)
+{
+  uint32_t t ;
+  char buf[4] ;
+  get0(buf, 4) ;
+  uint32_unpack_big(buf, &t) ;
+  if (t) tain_from_millisecs(&outertto, t) ;
+  else outertto = tain_infinite_relative ;
+  answer(0) ;
+}
 
 static inline void do_pwend (void *a)
 {
@@ -402,6 +412,7 @@ static inline void do_spget (void *a)
   }
   print_sp(&sp) ;
 }
+
 static inline void do_spnam (void *a)
 {
   struct spwd sp ;
@@ -432,7 +443,7 @@ static inline void do_spnam (void *a)
 }
 
 
-int nsssd_main (char const *const *argv, char const *const *envp)
+int nsssd_main (char const *const *argv)
 {
   void *a ;
 
@@ -452,22 +463,34 @@ int nsssd_main (char const *const *argv, char const *const *envp)
     if (setuid(uid) == -1) strerr_diefu2sys(111, "setuid to ", x) ;
   }
 
+  {
+    char const *x = getenv("NSSSD_TIMEOUT") ;
+    if (x)
+    {
+      uint32_t t ;
+      if (!uint320_scan(x, &t))
+        strerr_dief1x(100, "invalid NSSSD_TIMEOUT") ;
+      if (t) tain_from_millisecs(&tto, t) ;
+    }
+  }
+
   tain_now_set_stopwatch_g() ;                                            
   a = nsssd_handle_init() ;
   if (ndelay_on(0) < 0) strerr_diefu1sys(111, "set stdin non-blocking") ;
   tain_now_g() ;
-  if (!nsssd_handle_start(a, argv, envp))
+  if (!nsssd_handle_start(a, argv))
     strerr_diefu1sys(111, "nsssd_handle_start") ;
 
   for (;;)
   {
     tain deadline ;
     char c ;
-    tain_add_g(&deadline, &tain_infinite_relative) ;
+    tain_add_g(&deadline, &outertto) ;
     if (!buffer_timed_get_g(buffer_0small, &c, 1, &deadline)) break ;
     errno = 0 ;
     switch (c)
     {
+      case NSSS_SWITCH_SET_TIMEOUT : do_set_timeout() ; break ;
       case NSSS_SWITCH_PWD_END : do_pwend(a) ; break ;
       case NSSS_SWITCH_PWD_REWIND : do_pwrewind(a) ; break ;
       case NSSS_SWITCH_PWD_GET : do_pwget(a) ; break ;