1.\" $NetBSD: nsdispatch.3,v 1.33 2015/01/04 21:38:58 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 January 4, 2015 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.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 getnamaddr *" 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 getnamaddr *" 462via 463.Ft "void *cbrv" . 464.El 465.Pp 466The 467.Ft "struct getnamaddr" 468is defined internally in libc as: 469.Bd -literal 470struct getnamaddr { 471 struct hostent *hp; 472 char *buf; 473 size_t buflen; 474 int *he; 475}; 476.Ed 477.\" 478.Ss Methods for group and group_compat databases 479.Bl -tag -width 3n 480.It Sy endgrent 481Empty 482.Fa ap . 483.Pp 484All methods for all sources are invoked for this method name. 485.It Sy getgrent 486.Ft "struct group **retval" 487.Pp 488.Fa *retval 489should be set to a pointer to an internal static 490.Ft "struct group" 491on success, 492.Dv NULL 493otherwise. 494.Pp 495.Xr getgrent 3 496returns 497.Fa *retval 498if 499.Fn nsdispatch 500returns 501.Dv NS_SUCCESS , 502.Dv NULL 503otherwise. 504.It Sy getgrent_r 505.Ft "int *retval" , 506.Ft "struct group *grp" , 507.Ft "char *buffer" , 508.Ft "size_t buflen" , 509.Ft "struct group **result" 510.Pp 511.Fa *retval 512should be set to an appropriate 513.Xr errno 2 514on failure. 515.Pp 516.Xr getgrent_r 3 517returns 0 518if 519.Fn nsdispatch 520returns 521.Dv NS_SUCCESS 522or 523.Dv NS_NOTFOUND , 524and 525.Fa *retval 526otherwise. 527.It Sy getgrgid 528.Ft "struct group **retval" , 529.Ft "gid_t gid" 530.Pp 531.Fa *retval 532should be set to a pointer to an internal static 533.Ft "struct group" 534on success, 535.Dv NULL 536otherwise. 537.Pp 538.Xr getgrgid 3 539returns 540.Fa *retval 541if 542.Fn nsdispatch 543returns 544.Dv NS_SUCCESS , 545.Dv NULL 546otherwise. 547.It Sy getgrgid_r 548.Ft "int *retval" , 549.Ft "gid_t gid" , 550.Ft "struct group *grp" , 551.Ft "char *buffer" , 552.Ft "size_t buflen" , 553.Ft "struct group **result" 554.Pp 555.Fa *retval 556should be set to an appropriate 557.Xr errno 2 558on failure. 559.Pp 560.Xr getgrgid_r 3 561returns 0 562if 563.Fn nsdispatch 564returns 565.Dv NS_SUCCESS 566or 567.Dv NS_NOTFOUND , 568and 569.Fa *retval 570otherwise. 571.It Sy getgrnam 572.Ft "struct group **retval" , 573.Ft "const char *name" 574.Pp 575.Fa *retval 576should be set to a pointer to an internal static 577.Ft "struct group" 578on success, 579.Dv NULL 580otherwise. 581.Pp 582.Xr getgrnam 3 583returns 584.Fa *retval 585if 586.Fn nsdispatch 587returns 588.Dv NS_SUCCESS , 589.Dv NULL 590otherwise. 591.It Sy getgrnam_r 592.Ft "int *retval" , 593.Ft "const char *name" , 594.Ft "struct group *grp" , 595.Ft "char *buffer" , 596.Ft "size_t buflen" , 597.Ft "struct group **result" 598.Pp 599.Fa *retval 600should be set to an appropriate 601.Xr errno 2 602on failure. 603.Pp 604.Xr getgrnam_r 3 605returns 0 606if 607.Fn nsdispatch 608returns 609.Dv NS_SUCCESS 610or 611.Dv NS_NOTFOUND , 612and 613.Fa *retval 614otherwise. 615.It Sy getgroupmembership 616.Ft "int *retval" , 617.Ft "const char *name" , 618.Ft "gid_t basegid" , 619.Ft "gid_t *groups" , 620.Ft "int maxgrp" , 621.Ft "int *groupc" 622.Pp 623.Fa retval 624is unused. 625.Pp 626Lookups for 627.Sy group_compat 628are also stopped if 629.Dv NS_SUCCESS 630was returned to prevent multiple 631.Dq "+:" 632compat entries from being expanded. 633.Pp 634.Xr getgroupmembership 3 635returns 636is -1 if 637.Fa *groupc 638is greater than to 639.Fa maxgrp , 640and 0 otherwise. 641.It Sy setgroupent 642.Ft "int *retval" , 643.Ft "int stayopen" 644.Pp 645.Fa retval 646should be set to 0 on failure and 1 on success. 647.Pp 648All methods for all sources are invoked for this method name. 649.It Sy setgrent 650Empty 651.Fa ap . 652.Pp 653All methods for all sources are invoked for this method name. 654.El 655.\" 656.Ss Methods for netgroup database 657.Sy NOTE: 658The method APIs for this database will be changing in the near future. 659.Bl -tag -width 3n 660.It Sy endnetgrent 661Empty 662.Fa ap . 663.It Sy lookup 664.Ft "char *name" , 665.Ft "char **line" , 666.Ft "int bywhat" 667.Pp 668Find the given 669.Fa name 670and return its value in 671.Fa line . 672.Fa bywhat 673is one of 674.Dv _NG_KEYBYNAME , 675.Dv _NG_KEYBYUSER , 676or 677.Dv _NG_KEYBYHOST . 678.It Sy getnetgrent 679.Ft "int *retval" , 680.Ft "const char **host" , 681.Ft "const char **user" , 682.Ft "const char **domain" 683.Pp 684.Fa *retval 685should be set to 0 for no more netgroup members and 1 otherwise. 686.Pp 687.Xr getnetgrent 3 688returns 689.Fa *retval 690if 691.Fn nsdispatch 692returns 693.Dv NS_SUCCESS , 6940 otherwise. 695.It Sy innetgr 696.Ft "int *retval" , 697.Ft "const char *grp" , 698.Ft "const char *host" , 699.Ft "const char *user" , 700.Ft "const char *domain" 701.Pp 702.Fa *retval 703should be set to 1 for a successful match and 0 otherwise. 704.It Sy setnetgrent 705.Ft "const char *netgroup" 706.El 707.\" 708.Ss Methods for networks database 709.Bl -tag -width 3n 710.It Sy getnetbyaddr 711.Ft "struct netent **retval" , 712.Ft "uint32_t net" , 713.Ft "int type" 714.Pp 715.Fa *retval 716should be set to a pointer to an internal static 717.Ft "struct netent" 718on success, 719.Dv NULL 720otherwise. 721.Pp 722.Xr getnetbyaddr 3 723returns 724.Fa *retval 725if 726.Fn nsdispatch 727returns 728.Dv NS_SUCCESS , 729.Dv NULL 730otherwise. 731.It Sy getnetbyname 732.Ft "struct netent **retval" , 733.Ft "const char *name" 734.Pp 735.Fa *retval 736should be set to a pointer to an internal static 737.Ft "struct netent" 738on success, 739.Dv NULL 740otherwise. 741.Pp 742.Xr getnetbyname 3 743returns 744.Fa *retval 745if 746.Fn nsdispatch 747returns 748.Dv NS_SUCCESS , 749.Dv NULL 750otherwise. 751.El 752.\" 753.Ss Methods for passwd and passwd_compat databases 754.Bl -tag -width 3n 755.It Sy endpwent 756Empty 757.Fa ap . 758.Pp 759All methods for all sources are invoked for this method name. 760.It Sy getpwent 761.Ft "struct passwd **retval" 762.Pp 763.Fa *retval 764should be set to a pointer to an internal static 765.Ft "struct passwd" 766on success, 767.Dv NULL 768otherwise. 769.Pp 770.Xr getpwent 3 771returns 772.Fa *retval 773if 774.Fn nsdispatch 775returns 776.Dv NS_SUCCESS , 777.Dv NULL 778otherwise. 779.It Sy getpwent_r 780.Ft "int *retval" , 781.Ft "struct passwd *pw" , 782.Ft "char *buffer" , 783.Ft "size_t buflen" , 784.Ft "struct passwd **result" 785.Pp 786.Fa *retval 787should be set to an appropriate 788.Xr errno 2 789on failure. 790.Pp 791.Xr getpwent_r 3 792returns 0 793if 794.Fn nsdispatch 795returns 796.Dv NS_SUCCESS 797or 798.Dv NS_NOTFOUND , 799and 800.Fa *retval 801otherwise. 802.It Sy getpwnam 803.Ft "struct passwd **retval" , 804.Ft "const char *name" 805.Pp 806.Fa *retval 807should be set to a pointer to an internal static 808.Ft "struct passwd" 809on success, 810.Dv NULL 811otherwise. 812.Pp 813.Xr getpwnam 3 814returns 815.Fa *retval 816if 817.Fn nsdispatch 818returns 819.Dv NS_SUCCESS , 820.Dv NULL 821otherwise. 822.It Sy getpwnam_r 823.Ft "int *retval" , 824.Ft "const char *name" , 825.Ft "struct passwd *pw" , 826.Ft "char *buffer" , 827.Ft "size_t buflen" , 828.Ft "struct passwd **result" 829.Pp 830.Fa *retval 831should be set to an appropriate 832.Xr errno 2 833on failure. 834.Pp 835.Xr getpwnam_r 3 836returns 0 837if 838.Fn nsdispatch 839returns 840.Dv NS_SUCCESS 841or 842.Dv NS_NOTFOUND , 843and 844.Fa *retval 845otherwise. 846.It Sy getpwuid 847.Ft "struct passwd **retval" , 848.Ft "uid_t uid" 849.Pp 850.Fa *retval 851should be set to a pointer to an internal static 852.Ft "struct passwd" 853on success, 854.Dv NULL 855otherwise. 856.Pp 857.Xr getpwuid 3 858returns 859.Fa *retval 860if 861.Fn nsdispatch 862returns 863.Dv NS_SUCCESS , 864.Dv NULL 865otherwise. 866.It Sy getpwuid_r 867.Ft "int *retval" , 868.Ft "uid_t uid" , 869.Ft "struct passwd *pw" , 870.Ft "char *buffer" , 871.Ft "size_t buflen" , 872.Ft "struct passwd **result" 873.Pp 874.Fa *retval 875should be set to an appropriate 876.Xr errno 2 877on failure. 878.Pp 879.Xr getpwuid_r 3 880returns 0 881if 882.Fn nsdispatch 883returns 884.Dv NS_SUCCESS 885or 886.Dv NS_NOTFOUND , 887and 888.Fa *retval 889otherwise. 890.It Sy setpassent 891.Ft "int *retval" , 892.Ft "int stayopen" 893.Pp 894.Fa retval 895should be set to 0 on failure and 1 on success. 896.Pp 897All methods for all sources are invoked for this method name. 898.It Sy setpwent 899Empty 900.Fa ap . 901.Pp 902All methods for all sources are invoked for this method name. 903.El 904.\" 905.Ss Methods for shells database 906.Bl -tag -width 3n 907.It Sy endusershell 908Empty 909.Fa ap . 910.Pp 911All methods for all sources are invoked for this method name. 912.It Sy getusershell 913.Ft "char **retval" 914.Pp 915.Xr getusershell 3 916returns 917.Fa *retval 918if 919.Fn nsdispatch 920returns 921.Dv NS_SUCCESS , 922and 0 otherwise. 923.It Sy setusershell 924Empty 925.Fa ap . 926.Pp 927All methods for all sources are invoked for this method name. 928.El 929.\" 930.Sh SEE ALSO 931.Xr ld.elf_so 1 , 932.Xr hesiod 3 , 933.Xr stdarg 3 , 934.Xr ypclnt 3 , 935.Xr nsswitch.conf 5 936.Sh HISTORY 937The 938.Nm 939routines first appeared in 940.Nx 1.4 . 941Support for dynamically-loaded modules first appeared in 942.Nx 3.0 . 943.Sh AUTHORS 944.An Luke Mewburn 945.Aq Mt lukem@NetBSD.org 946wrote this freely distributable name-service switch implementation, 947using ideas from the 948.Tn ULTRIX 949.Xr svc.conf 5 950and 951.Tn Solaris 952.Xr nsswitch.conf 4 953manual pages. 954Support for dynamically-loaded modules was added by 955.An Jason Thorpe 956.Aq Mt thorpej@NetBSD.org , 957based on code developed by the 958.Fx 959Project. 960