1.\" $NetBSD: nsdispatch.3,v 1.31 2011/04/28 16:16:23 wiz 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.Bl -item -offset indent 71.It 72.Bd -literal 73typedef struct { 74 const char *src; 75 nss_method cb; 76 void *cb_data; 77} ns_dtab; 78.Ed 79.It 80The 81.Fa dtab 82array should consist of one entry for each source type that has a 83static implementation, 84with 85.Fa src 86as the name of the source, 87.Fa cb 88as a callback function which handles that source, and 89.Fa cb_data 90as a pointer to arbitrary data to be passed to the callback function. 91The last entry in 92.Fa dtab 93should contain 94.Dv NULL 95values for 96.Fa src , 97.Fa cb , 98and 99.Fa cb_data . 100.It 101The callback function signature is described by the typedef: 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.Bl -tag -width cbdata 110.It Fa cbrv 111The 112.Fa nsdrv 113that 114.Fn nsdispatch 115was invoked with. 116.It Fa cbdata 117The 118.Fa cb_data 119member of the array entry for the source that this 120callback function implements in the 121.Fa dtab 122argument of 123.Fn nsdispatch . 124.It Fa ap 125The 126.Fa ... 127arguments to 128.Fn nsdispatch , 129converted to a 130.Ft va_list . 131.El 132.Ed 133.El 134.Pp 135.Fa database 136and 137.Fa name 138are used to select methods from optional per-source 139dynamically-loaded modules. 140.Fa name 141is usually the name of the function calling 142.Fn nsdispatch . 143Note that the callback functions provided by 144.Fa dtab 145take priority over those implemented in dynamically-loaded modules in the 146event of a conflict. 147.Pp 148.Fa defaults 149contains a list of default sources to try in the case of 150a missing or corrupt 151.Xr nsswitch.conf 5 , 152or if there isn't a relevant entry for 153.Fa database . 154It is an array of 155.Fa ns_src 156structures, which have the following format: 157.Bl -item -offset indent 158.It 159.Bd -literal 160typedef struct { 161 const char *src; 162 uint32_t flags; 163} ns_src; 164.Ed 165.It 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.It 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.It 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.El 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.Bl -item -offset indent 233.It 234.Bd -literal 235nss_\*[Lt]source\*[Gt].so.\*[Lt]version\*[Gt] 236.Ed 237.Bl -tag -width XversionX 238.It Aq source 239The source that the module implements. 240.It Aq version 241The 242.Nm nsdispatch 243module interface version, which is defined by the integer 244.Dv NSS_MODULE_INTERFACE_VERSION , 245which has the value 0. 246.El 247.El 248.Pp 249When a module is loaded, 250.Fn nsdispatch 251looks for and calls the following function in the module: 252.Pp 253.Bd -ragged -offset indent 254.Ft ns_mtab * 255.Fo nss_module_register 256.Fa "const char *source" 257.Fa "u_int *nelems" 258.Fa "nss_module_unregister_fn *unreg" 259.Fc ; 260.Pp 261.Bl -tag -width source 262.It Fa source 263The name of the source that the module implements, as used by 264.Fn nsdispatch 265to construct the module's name. 266.It Fa nelems 267A pointer to an unsigned integer that 268.Fn nss_module_register 269should set to the number of elements in the 270.Ft ns_mtab 271array returned by 272.Fn nss_module_register , 273or 274.Dv 0 275if there was a failure. 276.It Fa unreg 277A pointer to a function pointer that 278.Fn nss_module_register 279can optionally set to an unregister function to be invoked when the module is 280unloaded, or 281.Dv NULL 282if there isn't one. 283.El 284.Ed 285.Pp 286The unregister function signature is described by the typedef: 287.Pp 288.Bd -ragged -offset indent 289.Ft typedef void 290.Fo \*(lp*nss_module_unregister_fn\*(rp 291.Fa "ns_mtab *mtab" 292.Fa "u_int nelems" 293.Fc ; 294.Pp 295.Bl -tag -width nelems 296.It Fa mtab 297The array of 298.Ft ns_mtab 299structures returned by 300.Fn nss_module_register . 301.It Fa nelems 302The 303.Fa *nelems 304value set by 305.Fn nss_module_register . 306.El 307.Ed 308.Pp 309.Fn nss_module_register 310returns an array of 311.Ft ns_mtab 312structures 313(with 314.Fa *nelems 315entries), or 316.Dv NULL 317if there was a failure. 318The 319.Ft ns_mtab 320structures have the following format: 321.Bl -item -offset indent 322.It 323.Bd -literal 324typedef struct { 325 const char *database; 326 const char *name; 327 nss_method method; 328 void *mdata; 329} ns_mtab; 330.Ed 331.It 332The 333.Fa mtab 334array should consist of one entry for each callback function (method) 335that is implemented, 336with 337.Fa database 338as the name of the database, 339.Fa name 340as the name of the callback function, 341.Fa method 342as the 343.Ft nss_method 344callback function that implements the method, and 345.Fa mdata 346as a pointer to arbitrary data to be passed to the callback function as its 347.Fa cbdata 348argument. 349.El 350.\" 351.Ss Valid source types 352While there is support for arbitrary sources, the following 353#defines for commonly implemented sources are provided: 354.Bl -column NSSRC_COMPAT COMPAT -offset indent 355.It Sy #define Value 356.It NSSRC_FILES "files" 357.It NSSRC_DNS "dns" 358.It NSSRC_NIS "nis" 359.It NSSRC_COMPAT "compat" 360.El 361.Pp 362Refer to 363.Xr nsswitch.conf 5 364for a complete description of what each source type is. 365.\" 366.Ss Valid database types 367While there is support for arbitrary databases, the following 368#defines for currently implemented system databases are provided: 369.Bl -column NSDB_PASSWD_COMPAT PASSWD_COMPAT -offset indent 370.It Sy #define Value 371.It NSDB_HOSTS "hosts" 372.It NSDB_GROUP "group" 373.It NSDB_GROUP_COMPAT "group_compat" 374.It NSDB_NETGROUP "netgroup" 375.It NSDB_NETWORKS "networks" 376.It NSDB_PASSWD "passwd" 377.It NSDB_PASSWD_COMPAT "passwd_compat" 378.It NSDB_SHELLS "shells" 379.El 380.Pp 381Refer to 382.Xr nsswitch.conf 5 383for a complete description of what each database is. 384.\" 385.Ss Callback function return values 386The callback functions should return one of the following values 387depending upon status of the lookup: 388.Bl -column NS_NOTFOUND -offset indent 389.It Sy "Return value" Status code 390.It NS_SUCCESS The requested entry was found. 391.It NS_NOTFOUND The entry is not present at this source. 392.It NS_TRYAGAIN The source is busy, and may respond to retries. 393.It NS_UNAVAIL The source is not responding, or entry is corrupt. 394.El 395.\" 396.Sh CALLBACK FUNCTION API FOR STANDARD DATABASES 397The organization of the 398.Fa ap 399argument for an 400.Fn nss_method 401callback function for a standard method in a standard database is: 402.Bl -enum -offset indent -compact 403.It 404Pointer to return value of the standard function. 405.It 406First argument of the standard function. 407.It 408(etc.) 409.El 410.Pp 411For example, given the standard function 412.Xr getgrnam 3 : 413.Bd -ragged -offset indent -compact 414.Ft struct group * 415.Fn getgrnam "const char *name" 416.Ed 417the 418.Fa ap 419organization used by the callback functions is: 420.Bl -enum -offset indent -compact 421.It 422.Ft "struct group **" 423.It 424.Ft "const char *" 425.El 426.Pp 427.Sy NOTE: 428Not all standard databases are using this calling convention yet; 429those that aren't are noted below. 430These will be changed in the future. 431.Pp 432The callback function names and 433.Ft va_list 434organization for various standard database callback functions are: 435.\" 436.Ss Methods for hosts database 437.Sy NOTE: 438The method APIs for this database will be changing in the near future. 439.Bl -tag -width 3n 440.It Sy getaddrinfo 441.Ft "char *name" , 442.Ft "const struct addrinfo *pai" 443.Pp 444Returns 445.Ft "struct addrinfo *" 446via 447.Ft "void *cbrv" . 448.It Sy gethostbyaddr 449.Ft "unsigned char *addr" , 450.Ft "int addrlen" , 451.Ft "int af" 452.Pp 453Returns 454.Ft "struct hostent *" 455via 456.Ft "void *cbrv" . 457.It Sy gethostbyname 458.Ft "char *name" , 459.Ft "int namelen" , 460.Ft "int af" 461.Pp 462Returns 463.Ft "struct hostent *" 464via 465.Ft "void *cbrv" . 466.El 467.\" 468.Ss Methods for group and group_compat databases 469.Bl -tag -width 3n 470.It Sy endgrent 471Empty 472.Fa ap . 473.Pp 474All methods for all sources are invoked for this method name. 475.It Sy getgrent 476.Ft "struct group **retval" 477.Pp 478.Fa *retval 479should be set to a pointer to an internal static 480.Ft "struct group" 481on success, 482.Dv NULL 483otherwise. 484.Pp 485.Xr getgrent 3 486returns 487.Fa *retval 488if 489.Fn nsdispatch 490returns 491.Dv NS_SUCCESS , 492.Dv NULL 493otherwise. 494.It Sy getgrent_r 495.Ft "int *retval" , 496.Ft "struct group *grp" , 497.Ft "char *buffer" , 498.Ft "size_t buflen" , 499.Ft "struct group **result" 500.Pp 501.Fa *retval 502should be set to an appropriate 503.Xr errno 2 504on failure. 505.Pp 506.Xr getgrent_r 3 507returns 0 508if 509.Fn nsdispatch 510returns 511.Dv NS_SUCCESS 512or 513.Dv NS_NOTFOUND , 514and 515.Fa *retval 516otherwise. 517.It Sy getgrgid 518.Ft "struct group **retval" , 519.Ft "gid_t gid" 520.Pp 521.Fa *retval 522should be set to a pointer to an internal static 523.Ft "struct group" 524on success, 525.Dv NULL 526otherwise. 527.Pp 528.Xr getgrgid 3 529returns 530.Fa *retval 531if 532.Fn nsdispatch 533returns 534.Dv NS_SUCCESS , 535.Dv NULL 536otherwise. 537.It Sy getgrgid_r 538.Ft "int *retval" , 539.Ft "gid_t gid" , 540.Ft "struct group *grp" , 541.Ft "char *buffer" , 542.Ft "size_t buflen" , 543.Ft "struct group **result" 544.Pp 545.Fa *retval 546should be set to an appropriate 547.Xr errno 2 548on failure. 549.Pp 550.Xr getgrgid_r 3 551returns 0 552if 553.Fn nsdispatch 554returns 555.Dv NS_SUCCESS 556or 557.Dv NS_NOTFOUND , 558and 559.Fa *retval 560otherwise. 561.It Sy getgrnam 562.Ft "struct group **retval" , 563.Ft "const char *name" 564.Pp 565.Fa *retval 566should be set to a pointer to an internal static 567.Ft "struct group" 568on success, 569.Dv NULL 570otherwise. 571.Pp 572.Xr getgrnam 3 573returns 574.Fa *retval 575if 576.Fn nsdispatch 577returns 578.Dv NS_SUCCESS , 579.Dv NULL 580otherwise. 581.It Sy getgrnam_r 582.Ft "int *retval" , 583.Ft "const char *name" , 584.Ft "struct group *grp" , 585.Ft "char *buffer" , 586.Ft "size_t buflen" , 587.Ft "struct group **result" 588.Pp 589.Fa *retval 590should be set to an appropriate 591.Xr errno 2 592on failure. 593.Pp 594.Xr getgrnam_r 3 595returns 0 596if 597.Fn nsdispatch 598returns 599.Dv NS_SUCCESS 600or 601.Dv NS_NOTFOUND , 602and 603.Fa *retval 604otherwise. 605.It Sy getgroupmembership 606.Ft "int *retval" , 607.Ft "const char *name" , 608.Ft "gid_t basegid" , 609.Ft "gid_t *groups" , 610.Ft "int maxgrp" , 611.Ft "int *groupc" 612.Pp 613.Fa retval 614is unused. 615.Pp 616Lookups for 617.Sy group_compat 618are also stopped if 619.Dv NS_SUCCESS 620was returned to prevent multiple 621.Dq "+:" 622compat entries from being expanded. 623.Pp 624.Xr getgroupmembership 3 625returns 626is -1 if 627.Fa *groupc 628is greater than to 629.Fa maxgrp , 630and 0 otherwise. 631.It Sy setgroupent 632.Ft "int *retval" , 633.Ft "int stayopen" 634.Pp 635.Fa retval 636should be set to 0 on failure and 1 on success. 637.Pp 638All methods for all sources are invoked for this method name. 639.It Sy setgrent 640Empty 641.Fa ap . 642.Pp 643All methods for all sources are invoked for this method name. 644.El 645.\" 646.Ss Methods for netgroup database 647.Sy NOTE: 648The method APIs for this database will be changing in the near future. 649.Bl -tag -width 3n 650.It Sy endnetgrent 651Empty 652.Fa ap . 653.It Sy lookup 654.Ft "char *name" , 655.Ft "char **line" , 656.Ft "int bywhat" 657.Pp 658Find the given 659.Fa name 660and return its value in 661.Fa line . 662.Fa bywhat 663is one of 664.Dv _NG_KEYBYNAME , 665.Dv _NG_KEYBYUSER , 666or 667.Dv _NG_KEYBYHOST . 668.It Sy getnetgrent 669.Ft "int *retval" , 670.Ft "const char **host" , 671.Ft "const char **user" , 672.Ft "const char **domain" 673.Pp 674.Fa *retval 675should be set to 0 for no more netgroup members and 1 otherwise. 676.Pp 677.Xr getnetgrent 3 678returns 679.Fa *retval 680if 681.Fn nsdispatch 682returns 683.Dv NS_SUCCESS , 6840 otherwise. 685.It Sy innetgr 686.Ft "int *retval" , 687.Ft "const char *grp" , 688.Ft "const char *host" , 689.Ft "const char *user" , 690.Ft "const char *domain" 691.Pp 692.Fa *retval 693should be set to 1 for a successful match and 0 otherwise. 694.It Sy setnetgrent 695.Ft "const char *netgroup" 696.El 697.\" 698.Ss Methods for networks database 699.Bl -tag -width 3n 700.It Sy getnetbyaddr 701.Ft "struct netent **retval" , 702.Ft "uint32_t net" , 703.Ft "int type" 704.Pp 705.Fa *retval 706should be set to a pointer to an internal static 707.Ft "struct netent" 708on success, 709.Dv NULL 710otherwise. 711.Pp 712.Xr getnetbyaddr 3 713returns 714.Fa *retval 715if 716.Fn nsdispatch 717returns 718.Dv NS_SUCCESS , 719.Dv NULL 720otherwise. 721.It Sy getnetbyname 722.Ft "struct netent **retval" , 723.Ft "const char *name" 724.Pp 725.Fa *retval 726should be set to a pointer to an internal static 727.Ft "struct netent" 728on success, 729.Dv NULL 730otherwise. 731.Pp 732.Xr getnetbyname 3 733returns 734.Fa *retval 735if 736.Fn nsdispatch 737returns 738.Dv NS_SUCCESS , 739.Dv NULL 740otherwise. 741.El 742.\" 743.Ss Methods for passwd and passwd_compat databases 744.Bl -tag -width 3n 745.It Sy endpwent 746Empty 747.Fa ap . 748.Pp 749All methods for all sources are invoked for this method name. 750.It Sy getpwent 751.Ft "struct passwd **retval" 752.Pp 753.Fa *retval 754should be set to a pointer to an internal static 755.Ft "struct passwd" 756on success, 757.Dv NULL 758otherwise. 759.Pp 760.Xr getpwent 3 761returns 762.Fa *retval 763if 764.Fn nsdispatch 765returns 766.Dv NS_SUCCESS , 767.Dv NULL 768otherwise. 769.It Sy getpwent_r 770.Ft "int *retval" , 771.Ft "struct passwd *pw" , 772.Ft "char *buffer" , 773.Ft "size_t buflen" , 774.Ft "struct passwd **result" 775.Pp 776.Fa *retval 777should be set to an appropriate 778.Xr errno 2 779on failure. 780.Pp 781.Xr getpwent_r 3 782returns 0 783if 784.Fn nsdispatch 785returns 786.Dv NS_SUCCESS 787or 788.Dv NS_NOTFOUND , 789and 790.Fa *retval 791otherwise. 792.It Sy getpwnam 793.Ft "struct passwd **retval" , 794.Ft "const char *name" 795.Pp 796.Fa *retval 797should be set to a pointer to an internal static 798.Ft "struct passwd" 799on success, 800.Dv NULL 801otherwise. 802.Pp 803.Xr getpwnam 3 804returns 805.Fa *retval 806if 807.Fn nsdispatch 808returns 809.Dv NS_SUCCESS , 810.Dv NULL 811otherwise. 812.It Sy getpwnam_r 813.Ft "int *retval" , 814.Ft "const char *name" , 815.Ft "struct passwd *pw" , 816.Ft "char *buffer" , 817.Ft "size_t buflen" , 818.Ft "struct passwd **result" 819.Pp 820.Fa *retval 821should be set to an appropriate 822.Xr errno 2 823on failure. 824.Pp 825.Xr getpwnam_r 3 826returns 0 827if 828.Fn nsdispatch 829returns 830.Dv NS_SUCCESS 831or 832.Dv NS_NOTFOUND , 833and 834.Fa *retval 835otherwise. 836.It Sy getpwuid 837.Ft "struct passwd **retval" , 838.Ft "uid_t uid" 839.Pp 840.Fa *retval 841should be set to a pointer to an internal static 842.Ft "struct passwd" 843on success, 844.Dv NULL 845otherwise. 846.Pp 847.Xr getpwuid 3 848returns 849.Fa *retval 850if 851.Fn nsdispatch 852returns 853.Dv NS_SUCCESS , 854.Dv NULL 855otherwise. 856.It Sy getpwuid_r 857.Ft "int *retval" , 858.Ft "uid_t uid" , 859.Ft "struct passwd *pw" , 860.Ft "char *buffer" , 861.Ft "size_t buflen" , 862.Ft "struct passwd **result" 863.Pp 864.Fa *retval 865should be set to an appropriate 866.Xr errno 2 867on failure. 868.Pp 869.Xr getpwuid_r 3 870returns 0 871if 872.Fn nsdispatch 873returns 874.Dv NS_SUCCESS 875or 876.Dv NS_NOTFOUND , 877and 878.Fa *retval 879otherwise. 880.It Sy setpassent 881.Ft "int *retval" , 882.Ft "int stayopen" 883.Pp 884.Fa retval 885should be set to 0 on failure and 1 on success. 886.Pp 887All methods for all sources are invoked for this method name. 888.It Sy setpwent 889Empty 890.Fa ap . 891.Pp 892All methods for all sources are invoked for this method name. 893.El 894.\" 895.Ss Methods for shells database 896.Bl -tag -width 3n 897.It Sy endusershell 898Empty 899.Fa ap . 900.Pp 901All methods for all sources are invoked for this method name. 902.It Sy getusershell 903.Ft "char **retval" 904.Pp 905.Xr getusershell 3 906returns 907.Fa *retval 908if 909.Fn nsdispatch 910returns 911.Dv NS_SUCCESS , 912and 0 otherwise. 913.It Sy setusershell 914Empty 915.Fa ap . 916.Pp 917All methods for all sources are invoked for this method name. 918.El 919.\" 920.Sh SEE ALSO 921.Xr ld.elf_so 1 , 922.Xr hesiod 3 , 923.Xr stdarg 3 , 924.Xr ypclnt 3 , 925.Xr nsswitch.conf 5 926.Sh HISTORY 927The 928.Nm 929routines first appeared in 930.Nx 1.4 . 931Support for dynamically-loaded modules first appeared in 932.Nx 3.0 . 933.Sh AUTHORS 934Luke Mewburn 935.Aq lukem@NetBSD.org 936wrote this freely distributable name-service switch implementation, 937using ideas from the 938.Tn ULTRIX 939.Xr svc.conf 5 940and 941.Tn Solaris 942.Xr nsswitch.conf 4 943manual pages. 944Support for dynamically-loaded modules was added by Jason Thorpe 945.Aq thorpej@NetBSD.org , 946based on code developed by the 947.Fx 948Project. 949