2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * @(#)getservent.c 8.1 (Berkeley) 6/4/93
30 * $FreeBSD: src/lib/libc/net/getservent.c,v 1.23 2007/01/09 00:28:02 imp Exp $
33 #include <sys/param.h>
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <arpa/inet.h>
47 #include <rpcsvc/yp_prot.h>
48 #include <rpcsvc/ypclnt.h>
50 #include "namespace.h"
51 #include "reentrant.h"
52 #include "un-namespace.h"
53 #include "netdb_private.h"
63 SERVENT_STORAGE_INITIAL
= 1 << 10, /* 1 KByte */
64 SERVENT_STORAGE_MAX
= 1 << 20, /* 1 MByte */
69 enum nss_lookup_type how
;
73 static const ns_src defaultsrc
[] = {
74 { NSSRC_COMPAT
, NS_SUCCESS
},
78 static int servent_unpack(char *, struct servent
*, char **, size_t, int *);
80 /* files backend declarations */
86 int compat_mode_active
;
88 static void files_endstate(void *);
89 NSS_TLS_HANDLING(files
);
91 static int files_servent(void *, void *, va_list);
92 static int files_setservent(void *, void *, va_list);
95 /* nis backend declarations */
96 static int nis_servent(void *, void *, va_list);
97 static int nis_setservent(void *, void *, va_list);
102 char yp_domain
[MAXHOSTNAMELEN
];
106 static void nis_endstate(void *);
107 NSS_TLS_HANDLING(nis
);
109 static int nis_servent(void *, void *, va_list);
110 static int nis_setservent(void *, void *, va_list);
113 /* compat backend declarations */
114 static int compat_setservent(void *, void *, va_list);
116 /* get** wrappers for get**_r functions declarations */
117 struct servent_state
{
122 static void servent_endstate(void *);
123 NSS_TLS_HANDLING(servent
);
133 static int wrap_getservbyname_r(struct key
, struct servent
*, char *, size_t,
135 static int wrap_getservbyport_r(struct key
, struct servent
*, char *, size_t,
137 static int wrap_getservent_r(struct key
, struct servent
*, char *, size_t,
139 static struct servent
*getserv(int (*fn
)(struct key
, struct servent
*, char *,
140 size_t, struct servent
**), struct key
);
143 static int serv_id_func(char *, size_t *, va_list, void *);
144 static int serv_marshal_func(char *, size_t *, void *, va_list, void *);
145 static int serv_unmarshal_func(char *, size_t, void *, va_list, void *);
149 servent_unpack(char *p
, struct servent
*serv
, char **aliases
,
150 size_t aliases_size
, int *errnop
)
152 char *cp
, **q
, *endp
;
158 memset(serv
, 0, sizeof(struct servent
));
160 cp
= strpbrk(p
, "#\n");
165 p
= strpbrk(p
, " \t");
169 while (*p
== ' ' || *p
== '\t')
171 cp
= strpbrk(p
, ",/");
176 l
= strtol(p
, &endp
, 10);
177 if (endp
== p
|| *endp
!= '\0' || l
< 0 || l
> USHRT_MAX
)
179 serv
->s_port
= htons((in_port_t
)l
);
182 q
= serv
->s_aliases
= aliases
;
183 cp
= strpbrk(cp
, " \t");
187 if (*cp
== ' ' || *cp
== '\t') {
191 if (q
< &aliases
[aliases_size
- 1]) {
198 cp
= strpbrk(cp
, " \t");
207 /* files backend implementation */
209 files_endstate(void *p
)
216 f
= ((struct files_state
*)p
)->fp
;
224 * compat structures. compat and files sources functionalities are almost
225 * equal, so they all are managed by files_servent function
228 files_servent(void *retval
, void *mdata
, va_list ap
)
230 static const ns_src compat_src
[] = {
232 { NSSRC_NIS
, NS_SUCCESS
},
236 ns_dtab compat_dtab
[] = {
238 { NSSRC_NIS
, nis_servent
,
239 (void *)((struct servent_mdata
*)mdata
)->how
},
244 struct files_state
*st
;
248 struct servent_mdata
*serv_mdata
;
253 struct servent
*serv
;
266 serv_mdata
= (struct servent_mdata
*)mdata
;
267 switch (serv_mdata
->how
) {
269 name
= va_arg(ap
, char *);
270 proto
= va_arg(ap
, char *);
273 port
= va_arg(ap
, int);
274 proto
= va_arg(ap
, char *);
282 serv
= va_arg(ap
, struct servent
*);
283 buffer
= va_arg(ap
, char *);
284 bufsize
= va_arg(ap
, size_t);
285 errnop
= va_arg(ap
,int *);
287 *errnop
= files_getstate(&st
);
292 st
->compat_mode_active
= 0;
294 if (st
->fp
== NULL
&& (st
->fp
= fopen(_PATH_SERVICES
, "r")) == NULL
) {
299 if (serv_mdata
->how
== nss_lt_all
)
303 stayopen
= st
->stayopen
;
308 if (!st
->compat_mode_active
) {
309 if ((line
= fgetln(st
->fp
, &linesize
)) == NULL
) {
316 if (serv_mdata
->compat_mode
!= 0)
317 st
->compat_mode_active
= 1;
319 if (bufsize
<= linesize
+ _ALIGNBYTES
+
325 aliases
= (char **)_ALIGN(&buffer
[linesize
+1]);
326 aliases_size
= (buffer
+ bufsize
-
327 (char *)aliases
) / sizeof(char *);
328 if (aliases_size
< 1) {
334 memcpy(buffer
, line
, linesize
);
335 buffer
[linesize
] = '\0';
339 if (st
->compat_mode_active
!= 0) {
340 switch (serv_mdata
->how
) {
342 rv
= nsdispatch(retval
, compat_dtab
,
343 NSDB_SERVICES_COMPAT
, "getservbyname_r",
344 compat_src
, name
, proto
, serv
, buffer
,
348 rv
= nsdispatch(retval
, compat_dtab
,
349 NSDB_SERVICES_COMPAT
, "getservbyport_r",
350 compat_src
, port
, proto
, serv
, buffer
,
354 rv
= nsdispatch(retval
, compat_dtab
,
355 NSDB_SERVICES_COMPAT
, "getservent_r",
356 compat_src
, serv
, buffer
, bufsize
, errnop
);
360 if (!(rv
& NS_TERMINATE
) ||
361 serv_mdata
->how
!= nss_lt_all
)
362 st
->compat_mode_active
= 0;
367 rv
= servent_unpack(buffer
, serv
, aliases
, aliases_size
,
381 switch (serv_mdata
->how
) {
383 if (strcmp(name
, serv
->s_name
) == 0)
385 for (cp
= serv
->s_aliases
; *cp
; cp
++)
386 if (strcmp(name
, *cp
) == 0)
391 if (proto
== NULL
|| strcmp(serv
->s_proto
, proto
) == 0)
395 if (port
!= serv
->s_port
)
398 if (proto
== NULL
|| strcmp(serv
->s_proto
, proto
) == 0)
406 } while (!(rv
& NS_TERMINATE
));
408 if (!stayopen
&& st
->fp
!= NULL
) {
413 if ((rv
== NS_SUCCESS
) && (retval
!= NULL
))
414 *(struct servent
**)retval
=serv
;
420 files_setservent(void *retval __unused
, void *mdata
, va_list ap
)
422 struct files_state
*st
;
426 rv
= files_getstate(&st
);
430 switch ((enum constants
)mdata
) {
434 st
->fp
= fopen(_PATH_SERVICES
, "r");
440 if (st
->fp
!= NULL
) {
450 st
->compat_mode_active
= 0;
454 /* nis backend implementation */
457 nis_endstate(void *p
)
462 free(((struct nis_state
*)p
)->yp_key
);
467 nis_servent(void *retval
, void *mdata
, va_list ap
)
469 char *resultbuf
, *lastkey
;
471 char buf
[YPMAXRECORD
+ 2];
473 struct nis_state
*st
;
476 enum nss_lookup_type how
;
481 struct servent
*serv
;
491 how
= (enum nss_lookup_type
)mdata
;
494 name
= va_arg(ap
, char *);
495 proto
= va_arg(ap
, char *);
498 port
= va_arg(ap
, int);
499 proto
= va_arg(ap
, char *);
507 serv
= va_arg(ap
, struct servent
*);
508 buffer
= va_arg(ap
, char *);
509 bufsize
= va_arg(ap
, size_t);
510 errnop
= va_arg(ap
, int *);
512 *errnop
= nis_getstate(&st
);
516 if (st
->yp_domain
[0] == '\0') {
517 if (getdomainname(st
->yp_domain
, sizeof st
->yp_domain
)) {
526 snprintf(buf
, sizeof(buf
), "%s/%s", name
, proto
);
527 if (yp_match(st
->yp_domain
, "services.byname", buf
,
528 strlen(buf
), &resultbuf
, &resultbuflen
)) {
534 snprintf(buf
, sizeof(buf
), "%d/%s", ntohs(port
),
538 * We have to be a little flexible
539 * here. Ideally you're supposed to have both
540 * a services.byname and a services.byport
541 * map, but some systems have only
542 * services.byname. FreeBSD cheats a little by
543 * putting the services.byport information in
544 * the same map as services.byname so that
545 * either case will work. We allow for both
546 * possibilities here: if there is no
547 * services.byport map, we try services.byname
550 rv
= yp_match(st
->yp_domain
, "services.byport", buf
,
551 strlen(buf
), &resultbuf
, &resultbuflen
);
553 if (rv
== YPERR_MAP
) {
554 if (yp_match(st
->yp_domain
,
555 "services.byname", buf
,
556 strlen(buf
), &resultbuf
,
569 if (!st
->yp_stepping
) {
571 rv
= yp_first(st
->yp_domain
, "services.byname",
572 &st
->yp_key
, &st
->yp_keylen
, &resultbuf
,
580 lastkey
= st
->yp_key
;
581 rv
= yp_next(st
->yp_domain
, "services.byname",
582 st
->yp_key
, st
->yp_keylen
, &st
->yp_key
,
583 &st
->yp_keylen
, &resultbuf
, &resultbuflen
);
594 /* we need a room for additional \n symbol */
596 resultbuflen
+ 1 + _ALIGNBYTES
+ sizeof(char *)) {
602 aliases
= (char **)_ALIGN(&buffer
[resultbuflen
+ 2]);
604 (buffer
+ bufsize
- (char *)aliases
) / sizeof(char *);
605 if (aliases_size
< 1) {
612 * servent_unpack expects lines terminated with \n --
615 memcpy(buffer
, resultbuf
, resultbuflen
);
616 buffer
[resultbuflen
] = '\n';
617 buffer
[resultbuflen
+ 1] = '\0';
619 if (servent_unpack(buffer
, serv
, aliases
, aliases_size
,
629 } while (!(rv
& NS_TERMINATE
) && how
== nss_lt_all
);
632 if (rv
== NS_SUCCESS
&& retval
!= NULL
)
633 *(struct servent
**)retval
= serv
;
639 nis_setservent(void *result __unused
, void *mdata
, va_list ap __unused
)
641 struct nis_state
*st
;
644 rv
= nis_getstate(&st
);
648 switch ((enum constants
)mdata
) {
663 /* compat backend implementation */
665 compat_setservent(void *retval
, void *mdata
, va_list ap
)
667 static const ns_src compat_src
[] = {
669 { NSSRC_NIS
, NS_SUCCESS
},
673 ns_dtab compat_dtab
[] = {
675 { NSSRC_NIS
, nis_setservent
, mdata
},
681 files_setservent(retval
, mdata
, ap
);
683 switch ((enum constants
)mdata
) {
686 nsdispatch(retval
, compat_dtab
, NSDB_SERVICES_COMPAT
,
687 "setservent", compat_src
, f
);
690 nsdispatch(retval
, compat_dtab
, NSDB_SERVICES_COMPAT
,
691 "endservent", compat_src
);
702 serv_id_func(char *buffer
, size_t *buffer_size
, va_list ap
, void *cache_mdata
)
708 size_t desired_size
, size
, size2
;
709 enum nss_lookup_type lookup_type
;
710 int res
= NS_UNAVAIL
;
712 lookup_type
= (enum nss_lookup_type
)cache_mdata
;
713 switch (lookup_type
) {
715 name
= va_arg(ap
, char *);
716 proto
= va_arg(ap
, char *);
719 desired_size
= sizeof(enum nss_lookup_type
) + size
+ 1;
721 size2
= strlen(proto
);
722 desired_size
+= size2
+ 1;
726 if (desired_size
> *buffer_size
) {
731 memcpy(buffer
, &lookup_type
, sizeof(enum nss_lookup_type
));
732 memcpy(buffer
+ sizeof(enum nss_lookup_type
), name
, size
+ 1);
735 memcpy(buffer
+ sizeof(enum nss_lookup_type
) + size
+ 1,
741 port
= va_arg(ap
, int);
742 proto
= va_arg(ap
, char *);
744 desired_size
= sizeof(enum nss_lookup_type
) + sizeof(int);
746 size
= strlen(proto
);
747 desired_size
+= size
+ 1;
751 if (desired_size
> *buffer_size
) {
756 memcpy(buffer
, &lookup_type
, sizeof(enum nss_lookup_type
));
757 memcpy(buffer
+ sizeof(enum nss_lookup_type
), &port
,
761 memcpy(buffer
+ sizeof(enum nss_lookup_type
) +
762 sizeof(int), proto
, size
+ 1);
767 /* should be unreachable */
772 *buffer_size
= desired_size
;
777 serv_marshal_func(char *buffer
, size_t *buffer_size
, void *retval __unused
,
778 va_list ap
, void *cache_mdata
)
781 char *proto __unused
;
783 struct servent
*serv
;
784 char *orig_buf __unused
;
785 size_t orig_buf_size __unused
;
787 struct servent new_serv
;
794 switch ((enum nss_lookup_type
)cache_mdata
) {
796 name
= va_arg(ap
, char *);
797 proto
= va_arg(ap
, char *);
800 port
= va_arg(ap
, int);
801 proto
= va_arg(ap
, char *);
806 /* should be unreachable */
810 serv
= va_arg(ap
, struct servent
*);
811 orig_buf
= va_arg(ap
, char *);
812 orig_buf_size
= va_arg(ap
, size_t);
814 desired_size
= _ALIGNBYTES
+ sizeof(struct servent
) + sizeof(char *);
815 if (serv
->s_name
!= NULL
)
816 desired_size
+= strlen(serv
->s_name
) + 1;
817 if (serv
->s_proto
!= NULL
)
818 desired_size
+= strlen(serv
->s_proto
) + 1;
821 if (serv
->s_aliases
!= NULL
) {
822 for (alias
= serv
->s_aliases
; *alias
; ++alias
) {
823 desired_size
+= strlen(*alias
) + 1;
827 desired_size
+= _ALIGNBYTES
+
828 sizeof(char *) * (aliases_size
+ 1);
831 if (*buffer_size
< desired_size
) {
832 /* this assignment is here for future use */
833 *buffer_size
= desired_size
;
837 memcpy(&new_serv
, serv
, sizeof(struct servent
));
838 memset(buffer
, 0, desired_size
);
840 *buffer_size
= desired_size
;
841 p
= buffer
+ sizeof(struct servent
) + sizeof(char *);
842 memcpy(buffer
+ sizeof(struct servent
), &p
, sizeof(char *));
843 p
= (char *)_ALIGN(p
);
845 if (new_serv
.s_name
!= NULL
) {
846 size
= strlen(new_serv
.s_name
);
847 memcpy(p
, new_serv
.s_name
, size
);
852 if (new_serv
.s_proto
!= NULL
) {
853 size
= strlen(new_serv
.s_proto
);
854 memcpy(p
, new_serv
.s_proto
, size
);
855 new_serv
.s_proto
= p
;
859 if (new_serv
.s_aliases
!= NULL
) {
860 p
= (char *)_ALIGN(p
);
861 memcpy(p
, new_serv
.s_aliases
, sizeof(char *) * aliases_size
);
862 new_serv
.s_aliases
= (char **)p
;
863 p
+= sizeof(char *) * (aliases_size
+ 1);
865 for (alias
= new_serv
.s_aliases
; *alias
; ++alias
) {
866 size
= strlen(*alias
);
867 memcpy(p
, *alias
, size
);
873 memcpy(buffer
, &new_serv
, sizeof(struct servent
));
878 serv_unmarshal_func(char *buffer
, size_t buffer_size
, void *retval
, va_list ap
,
882 char *proto __unused
;
884 struct servent
*serv
;
888 size_t orig_buf_size
;
891 switch ((enum nss_lookup_type
)cache_mdata
) {
893 name
= va_arg(ap
, char *);
894 proto
= va_arg(ap
, char *);
897 port
= va_arg(ap
, int);
898 proto
= va_arg(ap
, char *);
903 /* should be unreachable */
907 serv
= va_arg(ap
, struct servent
*);
908 orig_buf
= va_arg(ap
, char *);
909 orig_buf_size
= va_arg(ap
, size_t);
910 ret_errno
= va_arg(ap
, int *);
913 buffer_size
- sizeof(struct servent
) - sizeof(char *)) {
918 memcpy(serv
, buffer
, sizeof(struct servent
));
919 memcpy(&p
, buffer
+ sizeof(struct servent
), sizeof(char *));
921 orig_buf
= (char *)_ALIGN(orig_buf
);
922 memcpy(orig_buf
, buffer
+ sizeof(struct servent
) + sizeof(char *) +
923 (_ALIGN(p
) - (size_t)p
),
924 buffer_size
- sizeof(struct servent
) - sizeof(char *) -
925 (_ALIGN(p
) - (size_t)p
));
926 p
= (char *)_ALIGN(p
);
928 NS_APPLY_OFFSET(serv
->s_name
, orig_buf
, p
, char *);
929 NS_APPLY_OFFSET(serv
->s_proto
, orig_buf
, p
, char *);
930 if (serv
->s_aliases
!= NULL
) {
931 NS_APPLY_OFFSET(serv
->s_aliases
, orig_buf
, p
, char **);
933 for (alias
= serv
->s_aliases
; *alias
; ++alias
)
934 NS_APPLY_OFFSET(*alias
, orig_buf
, p
, char *);
938 *((struct servent
**)retval
) = serv
;
942 NSS_MP_CACHE_HANDLING(services
);
943 #endif /* NS_CACHING */
945 /* get**_r functions implementation */
947 getservbyname_r(const char *name
, const char *proto
, struct servent
*serv
,
948 char *buffer
, size_t bufsize
, struct servent
**result
)
950 static const struct servent_mdata mdata
= { nss_lt_name
, 0 };
951 static const struct servent_mdata compat_mdata
= { nss_lt_name
, 1 };
953 static const nss_cache_info cache_info
=
954 NS_COMMON_CACHE_INFO_INITIALIZER(
955 services
, (void *)nss_lt_name
,
956 serv_id_func
, serv_marshal_func
, serv_unmarshal_func
);
957 #endif /* NS_CACHING */
958 static const ns_dtab dtab
[] = {
959 { NSSRC_FILES
, files_servent
, (void *)&mdata
},
961 { NSSRC_NIS
, nis_servent
, (void *)nss_lt_name
},
963 { NSSRC_COMPAT
, files_servent
, (void *)&compat_mdata
},
965 NS_CACHE_CB(&cache_info
)
973 rv
= nsdispatch(result
, dtab
, NSDB_SERVICES
, "getservbyname_r",
974 defaultsrc
, name
, proto
, serv
, buffer
, bufsize
, &ret_errno
);
976 if (rv
== NS_SUCCESS
)
983 getservbyport_r(int port
, const char *proto
, struct servent
*serv
,
984 char *buffer
, size_t bufsize
, struct servent
**result
)
986 static const struct servent_mdata mdata
= { nss_lt_id
, 0 };
987 static const struct servent_mdata compat_mdata
= { nss_lt_id
, 1 };
989 static const nss_cache_info cache_info
=
990 NS_COMMON_CACHE_INFO_INITIALIZER(
991 services
, (void *)nss_lt_id
,
992 serv_id_func
, serv_marshal_func
, serv_unmarshal_func
);
994 static const ns_dtab dtab
[] = {
995 { NSSRC_FILES
, files_servent
, (void *)&mdata
},
997 { NSSRC_NIS
, nis_servent
, (void *)nss_lt_id
},
999 { NSSRC_COMPAT
, files_servent
, (void *)&compat_mdata
},
1001 NS_CACHE_CB(&cache_info
)
1003 { NULL
, NULL
, NULL
}
1009 rv
= nsdispatch(result
, dtab
, NSDB_SERVICES
, "getservbyport_r",
1010 defaultsrc
, port
, proto
, serv
, buffer
, bufsize
, &ret_errno
);
1012 if (rv
== NS_SUCCESS
)
1019 getservent_r(struct servent
*serv
, char *buffer
, size_t bufsize
,
1020 struct servent
**result
)
1022 static const struct servent_mdata mdata
= { nss_lt_all
, 0 };
1023 static const struct servent_mdata compat_mdata
= { nss_lt_all
, 1 };
1025 static const nss_cache_info cache_info
= NS_MP_CACHE_INFO_INITIALIZER(
1026 services
, (void *)nss_lt_all
,
1027 serv_marshal_func
, serv_unmarshal_func
);
1029 static const ns_dtab dtab
[] = {
1030 { NSSRC_FILES
, files_servent
, (void *)&mdata
},
1032 { NSSRC_NIS
, nis_servent
, (void *)nss_lt_all
},
1034 { NSSRC_COMPAT
, files_servent
, (void *)&compat_mdata
},
1036 NS_CACHE_CB(&cache_info
)
1038 { NULL
, NULL
, NULL
}
1044 rv
= nsdispatch(result
, dtab
, NSDB_SERVICES
, "getservent_r",
1045 defaultsrc
, serv
, buffer
, bufsize
, &ret_errno
);
1047 if (rv
== NS_SUCCESS
)
1054 setservent(int stayopen
)
1057 static const nss_cache_info cache_info
= NS_MP_CACHE_INFO_INITIALIZER(
1058 services
, (void *)nss_lt_all
,
1061 static const ns_dtab dtab
[] = {
1062 { NSSRC_FILES
, files_setservent
, (void *)SETSERVENT
},
1064 { NSSRC_NIS
, nis_setservent
, (void *)SETSERVENT
},
1066 { NSSRC_COMPAT
, compat_setservent
, (void *)SETSERVENT
},
1068 NS_CACHE_CB(&cache_info
)
1070 { NULL
, NULL
, NULL
}
1073 nsdispatch(NULL
, dtab
, NSDB_SERVICES
, "setservent", defaultsrc
,
1081 static const nss_cache_info cache_info
= NS_MP_CACHE_INFO_INITIALIZER(
1082 services
, (void *)nss_lt_all
,
1085 static const ns_dtab dtab
[] = {
1086 { NSSRC_FILES
, files_setservent
, (void *)ENDSERVENT
},
1088 { NSSRC_NIS
, nis_setservent
, (void *)ENDSERVENT
},
1090 { NSSRC_COMPAT
, compat_setservent
, (void *)ENDSERVENT
},
1092 NS_CACHE_CB(&cache_info
)
1094 { NULL
, NULL
, NULL
}
1097 nsdispatch(NULL
, dtab
, NSDB_SERVICES
, "endservent", defaultsrc
);
1100 /* get** wrappers for get**_r functions implementation */
1102 servent_endstate(void *p
)
1107 free(((struct servent_state
*)p
)->buffer
);
1112 wrap_getservbyname_r(struct key key
, struct servent
*serv
, char *buffer
,
1113 size_t bufsize
, struct servent
**res
)
1115 return (getservbyname_r(key
.name
, key
.proto
, serv
, buffer
, bufsize
,
1120 wrap_getservbyport_r(struct key key
, struct servent
*serv
, char *buffer
,
1121 size_t bufsize
, struct servent
**res
)
1123 return (getservbyport_r(key
.port
, key
.proto
, serv
, buffer
, bufsize
,
1128 wrap_getservent_r(struct key key __unused
, struct servent
*serv
, char *buffer
,
1129 size_t bufsize
, struct servent
**res
)
1131 return (getservent_r(serv
, buffer
, bufsize
, res
));
1134 static struct servent
*
1135 getserv(int (*fn
)(struct key
, struct servent
*, char *, size_t,
1136 struct servent
**), struct key key
)
1139 struct servent
*res
;
1140 struct servent_state
* st
;
1142 rv
= servent_getstate(&st
);
1148 if (st
->buffer
== NULL
) {
1149 st
->buffer
= malloc(SERVENT_STORAGE_INITIAL
);
1150 if (st
->buffer
== NULL
)
1152 st
->bufsize
= SERVENT_STORAGE_INITIAL
;
1155 rv
= fn(key
, &st
->serv
, st
->buffer
, st
->bufsize
, &res
);
1156 if (res
== NULL
&& rv
== ERANGE
) {
1158 if ((st
->bufsize
<< 1) > SERVENT_STORAGE_MAX
) {
1164 st
->buffer
= malloc(st
->bufsize
);
1165 if (st
->buffer
== NULL
)
1168 } while (res
== NULL
&& rv
== ERANGE
);
1176 getservbyname(const char *name
, const char *proto
)
1183 return (getserv(wrap_getservbyname_r
, key
));
1187 getservbyport(int port
, const char *proto
)
1194 return (getserv(wrap_getservbyport_r
, key
));
1205 return (getserv(wrap_getservent_r
, key
));