xref: /netbsd-src/lib/libc/net/nsdispatch.3 (revision 404fbe5fb94ca1e054339640cabb2801ce52dd30)
1.\"	$NetBSD: nsdispatch.3,v 1.28 2008/05/08 13:01:42 lukem Exp $
2.\"
3.\" Copyright (c) 1997, 1998, 1999, 2004, 2005, 2008
4.\" The NetBSD Foundation, Inc.
5.\" All rights reserved.
6.\"
7.\" This code is derived from software contributed to The NetBSD Foundation
8.\" by Luke Mewburn; and by Jason R. Thorpe.
9.\"
10.\" Redistribution and use in source and binary forms, with or without
11.\" modification, are permitted provided that the following conditions
12.\" are met:
13.\" 1. Redistributions of source code must retain the above copyright
14.\"    notice, this list of conditions and the following disclaimer.
15.\" 2. Redistributions in binary form must reproduce the above copyright
16.\"    notice, this list of conditions and the following disclaimer in the
17.\"    documentation and/or other materials provided with the distribution.
18.\"
19.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29.\" POSSIBILITY OF SUCH DAMAGE.
30.\"
31.Dd May 8, 2008
32.Dt NSDISPATCH 3
33.Os
34.Sh NAME
35.Nm nsdispatch
36.Nd name-service switch dispatcher routine
37.Sh LIBRARY
38.Lb libc
39.Sh SYNOPSIS
40.In nsswitch.h
41.Ft int
42.Fo nsdispatch
43.Fa "void *nsdrv"
44.Fa "const ns_dtab dtab[]"
45.Fa "const char *database"
46.Fa "const char *name"
47.Fa "const ns_src defaults[]"
48.Fa "..."
49.Fc
50.Sh DESCRIPTION
51The
52.Fn nsdispatch
53function invokes the callback functions specified in
54.Fa dtab
55in the order given in
56.Pa /etc/nsswitch.conf
57for the database
58.Fa database
59until the action criteria for a source of that database is fulfilled.
60.Pp
61.Fa nsdrv
62is passed to each callback function to use as necessary
63(to pass back to the caller of
64.Fn nsdispatch ) .
65.Pp
66.Fa dtab
67is an array of
68.Fa ns_dtab
69structures, which have the following format:
70.Bd -ragged -offset indent
71.Bd -literal
72typedef struct {
73	const char *src;
74	nss_method cb;
75	void *cb_data;
76} ns_dtab;
77.Ed
78.Pp
79The
80.Fa dtab
81array should consist of one entry for each source type that has a
82static implementation,
83with
84.Fa src
85as the name of the source,
86.Fa cb
87as a callback function which handles that source, and
88.Fa cb_data
89as a pointer to arbitrary data to be passed to the callback function.
90The last entry in
91.Fa dtab
92should contain
93.Dv NULL
94values for
95.Fa src ,
96.Fa cb ,
97and
98.Fa cb_data .
99.Pp
100The callback function signature is described by the typedef:
101.Pp
102.Bd -ragged -offset indent
103.Ft typedef int
104.Fo \*(lp*nss_method\*(rp
105.Fa "void *cbrv"
106.Fa "void *cbdata"
107.Fa "va_list ap"
108.Fc ;
109.Pp
110.Bl -tag -width cbdata
111.It Fa cbrv
112The
113.Fa nsdrv
114that
115.Fn nsdispatch
116was invoked with.
117.It Fa cbdata
118The
119.Fa cb_data
120member of the array entry for the source that this
121callback function implements in the
122.Fa dtab
123argument of
124.Fn nsdispatch .
125.It Fa ap
126The
127.Fa ...
128arguments to
129.Fn nsdispatch ,
130converted to a
131.Ft va_list .
132.El
133.Ed
134.Ed
135.Pp
136.Fa database
137and
138.Fa name
139are used to select methods from optional per-source
140dynamically-loaded modules.
141.Fa name
142is usually the name of the function calling
143.Fn nsdispatch .
144Note that the callback functions provided by
145.Fa dtab
146take priority over those implemented in dynamically-loaded modules in the
147event of a conflict.
148.Pp
149.Fa defaults
150contains a list of default sources to try in the case of
151a missing or corrupt
152.Xr nsswitch.conf 5 ,
153or if there isn't a relevant entry for
154.Fa database .
155It is an array of
156.Fa ns_src
157structures, which have the following format:
158.Bd -ragged -offset indent
159.Bd -literal
160typedef struct {
161	const char *src;
162	uint32_t flags;
163} ns_src;
164.Ed
165.Pp
166The
167.Fa defaults
168array should consist of one entry for each source to consult by default
169indicated by
170.Fa src ,
171and
172.Fa flags
173set to the desired behavior
174(usually
175.Dv NS_SUCCESS ;
176refer to
177.Sx Callback function return values
178for more information).
179The last entry in
180.Fa defaults
181should have
182.Fa src
183set to
184.Dv NULL
185and
186.Fa flags
187set to 0.
188.Pp
189Some invokers of
190.Fn nsdispatch
191(such as
192.Xr setgrent 3 )
193need to force all callback functions to be invoked,
194irrespective of the action criteria listed in
195.Xr nsswitch.conf 5 .
196This can be achieved by adding
197.Dv NS_FORCEALL
198to
199.Fa defaults[0].flags
200before invoking
201.Fn nsdispatch .
202The return value of
203.Fn nsdispatch
204will be the result of the final callback function invoked.
205.Pp
206For convenience, a global variable defined as:
207.Dl extern const ns_src __nsdefaultsrc[];
208exists which contains a single default entry for
209.Sq files
210for use by callers which don't require complicated default rules.
211.Ed
212.Pp
213.Fa ...
214are optional extra arguments, which
215are passed to the appropriate callback function as a
216.Xr stdarg 3
217variable argument
218list of the type
219.Fa va_list .
220.Pp
221.Nm
222returns the value of the callback function that caused the dispatcher
223to finish, or
224.Dv NS_NOTFOUND
225otherwise.
226.\"
227.Ss Dynamically-loaded module interface
228The
229.Fn nsdispatch
230function loads callback functions from the run-time link-editor's search
231path using the following naming convention:
232.Bd -ragged -offset indent
233.Bd -literal
234nss_\*[Lt]source\*[Gt].so.\*[Lt]version\*[Gt]
235.Ed
236.Bl -tag -width XversionX
237.It Aq source
238The source that the module implements.
239.It Aq version
240The
241.Nm nsdispatch
242module interface version, which is defined by the integer
243.Dv NSS_MODULE_INTERFACE_VERSION ,
244which has the value 0.
245.El
246.Ed
247.Pp
248When a module is loaded,
249.Fn nsdispatch
250looks for and calls the following function in the module:
251.Pp
252.Bd -ragged -offset indent
253.Ft ns_mtab *
254.Fo nss_module_register
255.Fa "const char *source"
256.Fa "u_int *nelems"
257.Fa "nss_module_unregister_fn *unreg"
258.Fc ;
259.Pp
260.Bl -tag -width source
261.It Fa source
262The name of the source that the module implements, as used by
263.Fn nsdispatch
264to construct the module's name.
265.It Fa nelems
266A pointer to an unsigned integer that
267.Fn nss_module_register
268should set to the number of elements in the
269.Ft ns_mtab
270array returned by
271.Fn nss_module_register ,
272or
273.Dv 0
274if there was a failure.
275.It Fa unreg
276A pointer to a function pointer that
277.Fn nss_module_register
278can optionally set to an unregister function to be invoked when the module is
279unloaded, or
280.Dv NULL
281if there isn't one.
282.El
283.Ed
284.Pp
285The unregister function signature is described by the typedef:
286.Pp
287.Bd -ragged -offset indent
288.Ft typedef void
289.Fo \*(lp*nss_module_unregister_fn\*(rp
290.Fa "ns_mtab *mtab"
291.Fa "u_int nelems"
292.Fc ;
293.Pp
294.Bl -tag -width nelems
295.It Fa mtab
296The array of
297.Ft ns_mtab
298structures returned by
299.Fn nss_module_register .
300.It Fa nelems
301The
302.Fa *nelems
303value set by
304.Fn nss_module_register .
305.El
306.Ed
307.Pp
308.Fn nss_module_register
309returns an array of
310.Ft ns_mtab
311structures
312(with
313.Fa *nelems
314entries), or
315.Dv NULL
316if there was a failure.
317The
318.Ft ns_mtab
319structures have the following format:
320.Bd -ragged -offset indent
321.Bd -literal
322typedef struct {
323	const char *database;
324	const char *name;
325	nss_method method;
326	void *mdata;
327} ns_mtab;
328.Ed
329.Pp
330The
331.Fa mtab
332array should consist of one entry for each callback function (method)
333that is implemented,
334with
335.Fa database
336as the name of the database,
337.Fa name
338as the name of the callback function,
339.Fa method
340as the
341.Ft nss_method
342callback function that implements the method, and
343.Fa mdata
344as a pointer to arbitrary data to be passed to the callback function as its
345.Fa cbdata
346argument.
347.Ed
348.\"
349.Ss Valid source types
350While there is support for arbitrary sources, the following
351#defines for commonly implemented sources are provided:
352.Bl -column NSSRC_COMPAT COMPAT -offset indent
353.Sy #define	Value
354.It NSSRC_FILES	"files"
355.It NSSRC_DNS	"dns"
356.It NSSRC_NIS	"nis"
357.It NSSRC_COMPAT	"compat"
358.El
359.Pp
360Refer to
361.Xr nsswitch.conf 5
362for a complete description of what each source type is.
363.\"
364.Ss Valid database types
365While there is support for arbitrary databases, the following
366#defines for currently implemented system databases are provided:
367.Bl -column NSDB_PASSWD_COMPAT PASSWD_COMPAT -offset indent
368.Sy #define	Value
369.It NSDB_HOSTS	"hosts"
370.It NSDB_GROUP	"group"
371.It NSDB_GROUP_COMPAT	"group_compat"
372.It NSDB_NETGROUP	"netgroup"
373.It NSDB_NETWORKS	"networks"
374.It NSDB_PASSWD	"passwd"
375.It NSDB_PASSWD_COMPAT	"passwd_compat"
376.It NSDB_SHELLS	"shells"
377.El
378.Pp
379Refer to
380.Xr nsswitch.conf 5
381for a complete description of what each database is.
382.\"
383.Ss Callback function return values
384The callback functions should return one of the following values
385depending upon status of the lookup:
386.Bl -column NS_NOTFOUND -offset indent
387.Sy "Return value"	Status code
388.It NS_SUCCESS	The requested entry was found.
389.It NS_NOTFOUND	The entry is not present at this source.
390.It NS_TRYAGAIN	The source is busy, and may respond to retries.
391.It NS_UNAVAIL	The source is not responding, or entry is corrupt.
392.El
393.\"
394.Sh CALLBACK FUNCTION API FOR STANDARD DATABASES
395The organization of the
396.Fa ap
397argument for an
398.Fn nss_method
399callback function for a standard method in a standard database is:
400.Bl -enum -offset indent -compact
401.It
402Pointer to return value of the standard function.
403.It
404First argument of the standard function.
405.It
406(etc.)
407.El
408.Pp
409For example, given the standard function
410.Xr getgrnam 3 :
411.Bd -ragged -offset indent -compact
412.Ft struct group *
413.Fn getgrnam "const char *name"
414.Ed
415the
416.Fa ap
417organization used by the callback functions is:
418.Bl -enum -offset indent -compact
419.It
420.Ft "struct group **"
421.It
422.Ft "const char *"
423.El
424.Pp
425.Sy NOTE:
426Not all standard databases are using this calling convention yet;
427those that aren't are noted below.
428These will be changed in the future.
429.Pp
430The callback function names and
431.Ft va_list
432organization for various standard database callback functions are:
433.\"
434.Ss Methods for hosts database
435.Sy NOTE:
436The method APIs for this database will be changing in the near future.
437.Bl -tag -width 3n
438.It Sy getaddrinfo
439.Ft "char *name" ,
440.Ft "const struct addrinfo *pai"
441.Pp
442Returns
443.Ft "struct addrinfo *"
444via
445.Ft "void *cbrv" .
446.It Sy gethostbyaddr
447.Ft "unsigned char *addr" ,
448.Ft "int addrlen" ,
449.Ft "int af"
450.Pp
451Returns
452.Ft "struct hostent *"
453via
454.Ft "void *cbrv" .
455.It Sy gethostbyname
456.Ft "char *name" ,
457.Ft "int namelen" ,
458.Ft "int af"
459.Pp
460Returns
461.Ft "struct hostent *"
462via
463.Ft "void *cbrv" .
464.El
465.\"
466.Ss Methods for group and group_compat databases
467.Bl -tag -width 3n
468.It Sy endgrent
469Empty
470.Fa ap .
471.Pp
472All methods for all sources are invoked for this method name.
473.It Sy getgrent
474.Ft "struct group **retval"
475.Pp
476.Fa *retval
477should be set to a pointer to an internal static
478.Ft "struct group"
479on success,
480.Dv NULL otherwise.
481.Pp
482.Xr getgrent 3
483returns
484.Fa *retval
485if
486.Fn nsdispatch
487returns
488.Dv NS_SUCCESS ,
489.Dv NULL
490otherwise.
491.It Sy getgrent_r
492.Ft "int *retval" ,
493.Ft "struct group *grp" ,
494.Ft "char *buffer" ,
495.Ft "size_t buflen" ,
496.Ft "struct group **result"
497.Pp
498.Fa *retval
499should be set to an appropriate
500.Xr errno 2
501on failure.
502.Pp
503.Xr getgrent_r 3
504returns 0
505if
506.Fn nsdispatch
507returns
508.Dv NS_SUCCESS
509or
510.Dv NS_NOTFOUND ,
511and
512.Fa *retval
513otherwise.
514.It Sy getgrgid
515.Ft "struct group **retval" ,
516.Ft "gid_t gid"
517.Pp
518.Fa *retval
519should be set to a pointer to an internal static
520.Ft "struct group"
521on success,
522.Dv NULL otherwise.
523.Pp
524.Xr getgrgid 3
525returns
526.Fa *retval
527if
528.Fn nsdispatch
529returns
530.Dv NS_SUCCESS ,
531.Dv NULL
532otherwise.
533.It Sy getgrgid_r
534.Ft "int *retval" ,
535.Ft "gid_t gid" ,
536.Ft "struct group *grp" ,
537.Ft "char *buffer" ,
538.Ft "size_t buflen" ,
539.Ft "struct group **result"
540.Pp
541.Fa *retval
542should be set to an appropriate
543.Xr errno 2
544on failure.
545.Pp
546.Xr getgrgid_r 3
547returns 0
548if
549.Fn nsdispatch
550returns
551.Dv NS_SUCCESS
552or
553.Dv NS_NOTFOUND ,
554and
555.Fa *retval
556otherwise.
557.It Sy getgrnam
558.Ft "struct group **retval" ,
559.Ft "const char *name"
560.Pp
561.Fa *retval
562should be set to a pointer to an internal static
563.Ft "struct group"
564on success,
565.Dv NULL otherwise.
566.Pp
567.Xr getgrnam 3
568returns
569.Fa *retval
570if
571.Fn nsdispatch
572returns
573.Dv NS_SUCCESS ,
574.Dv NULL
575otherwise.
576.It Sy getgrnam_r
577.Ft "int *retval" ,
578.Ft "const char *name" ,
579.Ft "struct group *grp" ,
580.Ft "char *buffer" ,
581.Ft "size_t buflen" ,
582.Ft "struct group **result"
583.Pp
584.Fa *retval
585should be set to an appropriate
586.Xr errno 2
587on failure.
588.Pp
589.Xr getgrnam_r 3
590returns 0
591if
592.Fn nsdispatch
593returns
594.Dv NS_SUCCESS
595or
596.Dv NS_NOTFOUND ,
597and
598.Fa *retval
599otherwise.
600.It Sy getgroupmembership
601.Ft "int *retval" ,
602.Ft "const char *name" ,
603.Ft "gid_t basegid" ,
604.Ft "gid_t *groups" ,
605.Ft "int maxgrp" ,
606.Ft "int *groupc"
607.Pp
608.Fa retval
609is unused.
610.Pp
611Lookups for
612.Sy group_compat
613are also stopped if
614.Dv NS_SUCCESS
615was returned to prevent multiple
616.Dq "+:"
617compat entries from being expanded.
618.Pp
619.Xr getgroupmembership 3
620returns
621is -1 if
622.Fa *groupc
623is greater than to
624.Fa maxgrp ,
625and 0 otherwise.
626.It Sy setgroupent
627.Ft "int *retval" ,
628.Ft "int stayopen"
629.Pp
630.Fa retval
631should be set to 0 on failure and 1 on success.
632.Pp
633All methods for all sources are invoked for this method name.
634.It Sy setgrent
635Empty
636.Fa ap .
637.Pp
638All methods for all sources are invoked for this method name.
639.El
640.\"
641.Ss Methods for netgroup database
642.Sy NOTE:
643The method APIs for this database will be changing in the near future.
644.Bl -tag -width 3n
645.It Sy endnetgrent
646Empty
647.Fa ap .
648.It Sy lookup
649.Ft "char *name" ,
650.Ft "char **line" ,
651.Ft "int bywhat"
652.Pp
653Find the given
654.Fa name
655and return its value in
656.Fa line .
657.Fa bywhat
658is one of
659.Dv _NG_KEYBYNAME ,
660.Dv _NG_KEYBYUSER ,
661or
662.Dv _NG_KEYBYHOST .
663.It Sy getnetgrent
664.Ft "int *retval" ,
665.Ft "const char **host" ,
666.Ft "const char **user" ,
667.Ft "const char **domain"
668.Pp
669.Fa *retval
670should be set to 0 for no more netgroup members and 1 otherwise.
671.Pp
672.Xr getnetgrent 3
673returns
674.Fa *retval
675if
676.Fn nsdispatch
677returns
678.Dv NS_SUCCESS ,
6790 otherwise.
680.It Sy innetgr
681.Ft "int *retval" ,
682.Ft "const char *grp" ,
683.Ft "const char *host" ,
684.Ft "const char *user" ,
685.Ft "const char *domain"
686.Pp
687.Fa *retval
688should be set to 1 for a successful match and 0 otherwise.
689.It Sy setnetgrent
690.Ft "const char *netgroup"
691.El
692.\"
693.Ss Methods for networks database
694.Bl -tag -width 3n
695.It Sy getnetbyaddr
696.Ft "struct netent **retval" ,
697.Ft "uint32_t net" ,
698.Ft "int type"
699.Pp
700.Fa *retval
701should be set to a pointer to an internal static
702.Ft "struct netent"
703on success,
704.Dv NULL otherwise.
705.Pp
706.Xr getnetbyaddr 3
707returns
708.Fa *retval
709if
710.Fn nsdispatch
711returns
712.Dv NS_SUCCESS ,
713.Dv NULL
714otherwise.
715.It Sy getnetbyname
716.Ft "struct netent **retval" ,
717.Ft "const char *name"
718.Pp
719.Fa *retval
720should be set to a pointer to an internal static
721.Ft "struct netent"
722on success,
723.Dv NULL otherwise.
724.Pp
725.Xr getnetbyname 3
726returns
727.Fa *retval
728if
729.Fn nsdispatch
730returns
731.Dv NS_SUCCESS ,
732.Dv NULL
733otherwise.
734.El
735.\"
736.Ss Methods for passwd and passwd_compat databases
737.Bl -tag -width 3n
738.It Sy endpwent
739Empty
740.Fa ap .
741.Pp
742All methods for all sources are invoked for this method name.
743.It Sy getpwent
744.Ft "struct passwd **retval"
745.Pp
746.Fa *retval
747should be set to a pointer to an internal static
748.Ft "struct passwd"
749on success,
750.Dv NULL otherwise.
751.Pp
752.Xr getpwent 3
753returns
754.Fa *retval
755if
756.Fn nsdispatch
757returns
758.Dv NS_SUCCESS ,
759.Dv NULL
760otherwise.
761.It Sy getpwent_r
762.Ft "int *retval" ,
763.Ft "struct passwd *pw" ,
764.Ft "char *buffer" ,
765.Ft "size_t buflen" ,
766.Ft "struct passwd **result"
767.Pp
768.Fa *retval
769should be set to an appropriate
770.Xr errno 2
771on failure.
772.Pp
773.Xr getpwent_r 3
774returns 0
775if
776.Fn nsdispatch
777returns
778.Dv NS_SUCCESS
779or
780.Dv NS_NOTFOUND ,
781and
782.Fa *retval
783otherwise.
784.It Sy getpwnam
785.Ft "struct passwd **retval" ,
786.Ft "const char *name"
787.Pp
788.Fa *retval
789should be set to a pointer to an internal static
790.Ft "struct passwd"
791on success,
792.Dv NULL otherwise.
793.Pp
794.Xr getpwnam 3
795returns
796.Fa *retval
797if
798.Fn nsdispatch
799returns
800.Dv NS_SUCCESS ,
801.Dv NULL
802otherwise.
803.It Sy getpwnam_r
804.Ft "int *retval" ,
805.Ft "const char *name" ,
806.Ft "struct passwd *pw" ,
807.Ft "char *buffer" ,
808.Ft "size_t buflen" ,
809.Ft "struct passwd **result"
810.Pp
811.Fa *retval
812should be set to an appropriate
813.Xr errno 2
814on failure.
815.Pp
816.Xr getpwnam_r 3
817returns 0
818if
819.Fn nsdispatch
820returns
821.Dv NS_SUCCESS
822or
823.Dv NS_NOTFOUND ,
824and
825.Fa *retval
826otherwise.
827.It Sy getpwuid
828.Ft "struct passwd **retval" ,
829.Ft "uid_t uid"
830.Pp
831.Fa *retval
832should be set to a pointer to an internal static
833.Ft "struct passwd"
834on success,
835.Dv NULL otherwise.
836.Pp
837.Xr getpwuid 3
838returns
839.Fa *retval
840if
841.Fn nsdispatch
842returns
843.Dv NS_SUCCESS ,
844.Dv NULL
845otherwise.
846.It Sy getpwuid_r
847.Ft "int *retval" ,
848.Ft "uid_t uid" ,
849.Ft "struct passwd *pw" ,
850.Ft "char *buffer" ,
851.Ft "size_t buflen" ,
852.Ft "struct passwd **result"
853.Pp
854.Fa *retval
855should be set to an appropriate
856.Xr errno 2
857on failure.
858.Pp
859.Xr getpwuid_r
860returns 0
861if
862.Fn nsdispatch
863returns
864.Dv NS_SUCCESS
865or
866.Dv NS_NOTFOUND ,
867and
868.Fa *retval
869otherwise.
870.It Sy setpassent
871.Ft "int *retval" ,
872.Ft "int stayopen"
873.Pp
874.Fa retval
875should be set to 0 on failure and 1 on success.
876.Pp
877All methods for all sources are invoked for this method name.
878.It Sy setpwent
879Empty
880.Fa ap .
881.Pp
882All methods for all sources are invoked for this method name.
883.El
884.\"
885.Ss Methods for shells database
886.Bl -tag -width 3n
887.It Sy endusershell
888Empty
889.Fa ap .
890.Pp
891All methods for all sources are invoked for this method name.
892.It Sy getusershell
893.Ft "char **retval"
894.Pp
895.Xr getusershell 3
896returns
897.Fa *retval
898if
899.Fn nsdispatch
900returns
901.Dv NS_SUCCESS ,
902and 0 otherwise.
903.It Sy setusershell
904Empty
905.Fa ap .
906.Pp
907All methods for all sources are invoked for this method name.
908.El
909.\"
910.Sh SEE ALSO
911.Xr ld.elf_so 1 ,
912.Xr hesiod 3 ,
913.Xr stdarg 3 ,
914.Xr ypclnt 3 ,
915.Xr nsswitch.conf 5
916.Sh HISTORY
917The
918.Nm
919routines first appeared in
920.Nx 1.4 .
921Support for dynamically-loaded modules first appeared in
922.Nx 3.0 .
923.Sh AUTHORS
924Luke Mewburn
925.Aq lukem@NetBSD.org
926wrote this freely distributable name-service switch implementation,
927using ideas from the
928.Tn ULTRIX
929.Xr svc.conf 5
930and
931.Tn Solaris
932.Xr nsswitch.conf 4
933manual pages.
934Support for dynamically-loaded modules was added by Jason Thorpe
935.Aq thorpej@NetBSD.org ,
936based on code developed by the
937.Fx
938Project.
939