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 * 4. 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
30 #if defined(LIBC_SCCS) && !defined(lint)
31 static char sccsid[] = "@(#)getservent.c 8.1 (Berkeley) 6/4/93";
32 #endif /* LIBC_SCCS and not lint */
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
36 #include <sys/param.h>
37 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <arpa/inet.h>
52 #include <rpcsvc/yp_prot.h>
53 #include <rpcsvc/ypclnt.h>
55 #include "namespace.h"
56 #include "reentrant.h"
57 #include "un-namespace.h"
58 #include "netdb_private.h"
68 SERVENT_STORAGE_INITIAL = 1 << 10, /* 1 KByte */
69 SERVENT_STORAGE_MAX = 1 << 20, /* 1 MByte */
74 enum nss_lookup_type how;
78 static const ns_src defaultsrc[] = {
79 { NSSRC_COMPAT, NS_SUCCESS },
83 static int servent_unpack(char *, struct servent *, char **, size_t, int *);
85 /* files backend declarations */
91 int compat_mode_active;
93 static void files_endstate(void *);
94 NSS_TLS_HANDLING(files);
96 static int files_servent(void *, void *, va_list);
97 static int files_setservent(void *, void *, va_list);
99 /* db backend declarations */
106 static void db_endstate(void *);
107 NSS_TLS_HANDLING(db);
109 static int db_servent(void *, void *, va_list);
110 static int db_setservent(void *, void *, va_list);
113 /* nis backend declarations */
114 static int nis_servent(void *, void *, va_list);
115 static int nis_setservent(void *, void *, va_list);
120 char yp_domain[MAXHOSTNAMELEN];
124 static void nis_endstate(void *);
125 NSS_TLS_HANDLING(nis);
127 static int nis_servent(void *, void *, va_list);
128 static int nis_setservent(void *, void *, va_list);
131 /* compat backend declarations */
132 static int compat_setservent(void *, void *, va_list);
134 /* get** wrappers for get**_r functions declarations */
135 struct servent_state {
140 static void servent_endstate(void *);
141 NSS_TLS_HANDLING(servent);
151 static int wrap_getservbyname_r(struct key, struct servent *, char *, size_t,
153 static int wrap_getservbyport_r(struct key, struct servent *, char *, size_t,
155 static int wrap_getservent_r(struct key, struct servent *, char *, size_t,
157 static struct servent *getserv(int (*fn)(struct key, struct servent *, char *,
158 size_t, struct servent **), struct key);
161 static int serv_id_func(char *, size_t *, va_list, void *);
162 static int serv_marshal_func(char *, size_t *, void *, va_list, void *);
163 static int serv_unmarshal_func(char *, size_t, void *, va_list, void *);
167 servent_unpack(char *p, struct servent *serv, char **aliases,
168 size_t aliases_size, int *errnop)
170 char *cp, **q, *endp;
176 memset(serv, 0, sizeof(struct servent));
178 cp = strpbrk(p, "#\n");
183 p = strpbrk(p, " \t");
187 while (*p == ' ' || *p == '\t')
189 cp = strpbrk(p, ",/");
194 l = strtol(p, &endp, 10);
195 if (endp == p || *endp != '\0' || l < 0 || l > USHRT_MAX)
197 serv->s_port = htons((in_port_t)l);
200 q = serv->s_aliases = aliases;
201 cp = strpbrk(cp, " \t");
205 if (*cp == ' ' || *cp == '\t') {
209 if (q < &aliases[aliases_size - 1]) {
216 cp = strpbrk(cp, " \t");
226 parse_result(struct servent *serv, char *buffer, size_t bufsize,
227 char *resultbuf, size_t resultbuflen, int *errnop)
232 if (bufsize <= resultbuflen + _ALIGNBYTES + sizeof(char *)) {
236 aliases = (char **)_ALIGN(&buffer[resultbuflen + 1]);
237 aliases_size = (buffer + bufsize - (char *)aliases) / sizeof(char *);
238 if (aliases_size < 1) {
243 memcpy(buffer, resultbuf, resultbuflen);
244 buffer[resultbuflen] = '\0';
246 if (servent_unpack(buffer, serv, aliases, aliases_size, errnop) != 0)
247 return ((*errnop == 0) ? NS_NOTFOUND : NS_RETURN);
251 /* files backend implementation */
253 files_endstate(void *p)
260 f = ((struct files_state *)p)->fp;
268 * compat structures. compat and files sources functionalities are almost
269 * equal, so they all are managed by files_servent function
272 files_servent(void *retval, void *mdata, va_list ap)
274 static const ns_src compat_src[] = {
276 { NSSRC_NIS, NS_SUCCESS },
280 ns_dtab compat_dtab[] = {
281 { NSSRC_DB, db_servent,
282 (void *)((struct servent_mdata *)mdata)->how },
284 { NSSRC_NIS, nis_servent,
285 (void *)((struct servent_mdata *)mdata)->how },
290 struct files_state *st;
294 struct servent_mdata *serv_mdata;
299 struct servent *serv;
310 serv_mdata = (struct servent_mdata *)mdata;
311 switch (serv_mdata->how) {
313 name = va_arg(ap, char *);
314 proto = va_arg(ap, char *);
317 port = va_arg(ap, int);
318 proto = va_arg(ap, char *);
326 serv = va_arg(ap, struct servent *);
327 buffer = va_arg(ap, char *);
328 bufsize = va_arg(ap, size_t);
329 errnop = va_arg(ap,int *);
331 *errnop = files_getstate(&st);
336 st->compat_mode_active = 0;
338 if (st->fp == NULL && (st->fp = fopen(_PATH_SERVICES, "r")) == NULL) {
343 if (serv_mdata->how == nss_lt_all)
347 stayopen = st->stayopen;
352 if (!st->compat_mode_active) {
353 if ((line = fgetln(st->fp, &linesize)) == NULL) {
359 if (*line=='+' && serv_mdata->compat_mode != 0)
360 st->compat_mode_active = 1;
363 if (st->compat_mode_active != 0) {
364 switch (serv_mdata->how) {
366 rv = nsdispatch(retval, compat_dtab,
367 NSDB_SERVICES_COMPAT, "getservbyname_r",
368 compat_src, name, proto, serv, buffer,
372 rv = nsdispatch(retval, compat_dtab,
373 NSDB_SERVICES_COMPAT, "getservbyport_r",
374 compat_src, port, proto, serv, buffer,
378 rv = nsdispatch(retval, compat_dtab,
379 NSDB_SERVICES_COMPAT, "getservent_r",
380 compat_src, serv, buffer, bufsize, errnop);
384 if (!(rv & NS_TERMINATE) ||
385 serv_mdata->how != nss_lt_all)
386 st->compat_mode_active = 0;
391 rv = parse_result(serv, buffer, bufsize, line, linesize,
393 if (rv == NS_NOTFOUND)
399 switch (serv_mdata->how) {
401 if (strcmp(name, serv->s_name) == 0)
403 for (cp = serv->s_aliases; *cp; cp++)
404 if (strcmp(name, *cp) == 0)
409 if (proto == 0 || strcmp(serv->s_proto, proto) == 0)
413 if (port != serv->s_port)
416 if (proto == 0 || strcmp(serv->s_proto, proto) == 0)
424 } while (!(rv & NS_TERMINATE));
426 if (!stayopen && st->fp != NULL) {
431 if ((rv == NS_SUCCESS) && (retval != NULL))
432 *(struct servent **)retval=serv;
438 files_setservent(void *retval, void *mdata, va_list ap)
440 struct files_state *st;
444 rv = files_getstate(&st);
448 switch ((enum constants)mdata) {
452 st->fp = fopen(_PATH_SERVICES, "r");
458 if (st->fp != NULL) {
468 st->compat_mode_active = 0;
472 /* db backend implementation */
481 db = ((struct db_state *)p)->db;
489 db_servent(void *retval, void *mdata, va_list ap)
492 DBT key, data, *result;
499 enum nss_lookup_type how;
504 struct servent *serv;
511 how = (enum nss_lookup_type)mdata;
514 name = va_arg(ap, char *);
515 proto = va_arg(ap, char *);
518 port = va_arg(ap, int);
519 proto = va_arg(ap, char *);
527 serv = va_arg(ap, struct servent *);
528 buffer = va_arg(ap, char *);
529 bufsize = va_arg(ap, size_t);
530 errnop = va_arg(ap,int *);
532 *errnop = db_getstate(&st);
536 if (how == nss_lt_all && st->keynum < 0)
537 return (NS_NOTFOUND);
539 if (st->db == NULL) {
540 st->db = dbopen(_PATH_SERVICES_DB, O_RDONLY, 0, DB_HASH, NULL);
541 if (st->db == NULL) {
547 stayopen = (how == nss_lt_all) ? 1 : st->stayopen;
555 key.size = snprintf(buf, sizeof(buf),
558 key.size = snprintf(buf, sizeof(buf),
559 "\376%s/%s", name, proto);
561 if (db->get(db, &key, &data, 0) != 0 ||
562 db->get(db, &data, &key, 0) != 0) {
572 key.size = snprintf(buf, sizeof(buf),
575 key.size = snprintf(buf, sizeof(buf),
576 "\377%d/%s", port, proto);
578 if (db->get(db, &key, &data, 0) != 0 ||
579 db->get(db, &data, &key, 0) != 0) {
587 key.size = snprintf(buf, sizeof(buf), "%d",
590 if (db->get(db, &key, &data, 0) != 0) {
599 rv = parse_result(serv, buffer, bufsize, result->data,
600 result->size - 1, errnop);
602 } while (!(rv & NS_TERMINATE) && how == nss_lt_all);
605 if (!stayopen && st->db != NULL) {
610 if (rv == NS_SUCCESS && retval != NULL)
611 *(struct servent **)retval = serv;
617 db_setservent(void *retval, void *mdata, va_list ap)
624 rv = db_getstate(&st);
628 switch ((enum constants)mdata) {
649 /* nis backend implementation */
652 nis_endstate(void *p)
657 free(((struct nis_state *)p)->yp_key);
662 nis_servent(void *retval, void *mdata, va_list ap)
664 char *resultbuf, *lastkey;
666 char buf[YPMAXRECORD + 2];
668 struct nis_state *st;
671 enum nss_lookup_type how;
676 struct servent *serv;
683 how = (enum nss_lookup_type)mdata;
686 name = va_arg(ap, char *);
687 proto = va_arg(ap, char *);
690 port = va_arg(ap, int);
691 proto = va_arg(ap, char *);
699 serv = va_arg(ap, struct servent *);
700 buffer = va_arg(ap, char *);
701 bufsize = va_arg(ap, size_t);
702 errnop = va_arg(ap, int *);
704 *errnop = nis_getstate(&st);
708 if (st->yp_domain[0] == '\0') {
709 if (getdomainname(st->yp_domain, sizeof st->yp_domain)) {
718 snprintf(buf, sizeof(buf), "%s/%s", name, proto);
719 if (yp_match(st->yp_domain, "services.byname", buf,
720 strlen(buf), &resultbuf, &resultbuflen)) {
726 snprintf(buf, sizeof(buf), "%d/%s", ntohs(port),
730 * We have to be a little flexible
731 * here. Ideally you're supposed to have both
732 * a services.byname and a services.byport
733 * map, but some systems have only
734 * services.byname. FreeBSD cheats a little by
735 * putting the services.byport information in
736 * the same map as services.byname so that
737 * either case will work. We allow for both
738 * possibilities here: if there is no
739 * services.byport map, we try services.byname
742 rv = yp_match(st->yp_domain, "services.byport", buf,
743 strlen(buf), &resultbuf, &resultbuflen);
745 if (rv == YPERR_MAP) {
746 if (yp_match(st->yp_domain,
747 "services.byname", buf,
748 strlen(buf), &resultbuf,
761 if (!st->yp_stepping) {
763 rv = yp_first(st->yp_domain, "services.byname",
764 &st->yp_key, &st->yp_keylen, &resultbuf,
772 lastkey = st->yp_key;
773 rv = yp_next(st->yp_domain, "services.byname",
774 st->yp_key, st->yp_keylen, &st->yp_key,
775 &st->yp_keylen, &resultbuf, &resultbuflen);
786 rv = parse_result(serv, buffer, bufsize, resultbuf,
787 resultbuflen, errnop);
790 } while (!(rv & NS_TERMINATE) && how == nss_lt_all);
793 if (rv == NS_SUCCESS && retval != NULL)
794 *(struct servent **)retval = serv;
800 nis_setservent(void *result, void *mdata, va_list ap)
802 struct nis_state *st;
805 rv = nis_getstate(&st);
809 switch ((enum constants)mdata) {
824 /* compat backend implementation */
826 compat_setservent(void *retval, void *mdata, va_list ap)
828 static const ns_src compat_src[] = {
830 { NSSRC_NIS, NS_SUCCESS },
834 ns_dtab compat_dtab[] = {
835 { NSSRC_DB, db_setservent, mdata },
837 { NSSRC_NIS, nis_setservent, mdata },
843 (void)files_setservent(retval, mdata, ap);
845 switch ((enum constants)mdata) {
848 (void)nsdispatch(retval, compat_dtab, NSDB_SERVICES_COMPAT,
849 "setservent", compat_src, f);
852 (void)nsdispatch(retval, compat_dtab, NSDB_SERVICES_COMPAT,
853 "endservent", compat_src);
864 serv_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata)
870 size_t desired_size, size, size2;
871 enum nss_lookup_type lookup_type;
872 int res = NS_UNAVAIL;
874 lookup_type = (enum nss_lookup_type)cache_mdata;
875 switch (lookup_type) {
877 name = va_arg(ap, char *);
878 proto = va_arg(ap, char *);
881 desired_size = sizeof(enum nss_lookup_type) + size + 1;
883 size2 = strlen(proto);
884 desired_size += size2 + 1;
888 if (desired_size > *buffer_size) {
893 memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
894 memcpy(buffer + sizeof(enum nss_lookup_type), name, size + 1);
897 memcpy(buffer + sizeof(enum nss_lookup_type) + size + 1,
903 port = va_arg(ap, int);
904 proto = va_arg(ap, char *);
906 desired_size = sizeof(enum nss_lookup_type) + sizeof(int);
908 size = strlen(proto);
909 desired_size += size + 1;
913 if (desired_size > *buffer_size) {
918 memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
919 memcpy(buffer + sizeof(enum nss_lookup_type), &port,
923 memcpy(buffer + sizeof(enum nss_lookup_type) +
924 sizeof(int), proto, size + 1);
929 /* should be unreachable */
934 *buffer_size = desired_size;
939 serv_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap,
945 struct servent *serv;
947 size_t orig_buf_size;
949 struct servent new_serv;
956 switch ((enum nss_lookup_type)cache_mdata) {
958 name = va_arg(ap, char *);
959 proto = va_arg(ap, char *);
962 port = va_arg(ap, int);
963 proto = va_arg(ap, char *);
968 /* should be unreachable */
972 serv = va_arg(ap, struct servent *);
973 orig_buf = va_arg(ap, char *);
974 orig_buf_size = va_arg(ap, size_t);
976 desired_size = _ALIGNBYTES + sizeof(struct servent) + sizeof(char *);
977 if (serv->s_name != NULL)
978 desired_size += strlen(serv->s_name) + 1;
979 if (serv->s_proto != NULL)
980 desired_size += strlen(serv->s_proto) + 1;
983 if (serv->s_aliases != NULL) {
984 for (alias = serv->s_aliases; *alias; ++alias) {
985 desired_size += strlen(*alias) + 1;
989 desired_size += _ALIGNBYTES +
990 sizeof(char *) * (aliases_size + 1);
993 if (*buffer_size < desired_size) {
994 /* this assignment is here for future use */
995 *buffer_size = desired_size;
999 memcpy(&new_serv, serv, sizeof(struct servent));
1000 memset(buffer, 0, desired_size);
1002 *buffer_size = desired_size;
1003 p = buffer + sizeof(struct servent) + sizeof(char *);
1004 memcpy(buffer + sizeof(struct servent), &p, sizeof(char *));
1005 p = (char *)_ALIGN(p);
1007 if (new_serv.s_name != NULL) {
1008 size = strlen(new_serv.s_name);
1009 memcpy(p, new_serv.s_name, size);
1010 new_serv.s_name = p;
1014 if (new_serv.s_proto != NULL) {
1015 size = strlen(new_serv.s_proto);
1016 memcpy(p, new_serv.s_proto, size);
1017 new_serv.s_proto = p;
1021 if (new_serv.s_aliases != NULL) {
1022 p = (char *)_ALIGN(p);
1023 memcpy(p, new_serv.s_aliases, sizeof(char *) * aliases_size);
1024 new_serv.s_aliases = (char **)p;
1025 p += sizeof(char *) * (aliases_size + 1);
1027 for (alias = new_serv.s_aliases; *alias; ++alias) {
1028 size = strlen(*alias);
1029 memcpy(p, *alias, size);
1035 memcpy(buffer, &new_serv, sizeof(struct servent));
1036 return (NS_SUCCESS);
1040 serv_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap,
1046 struct servent *serv;
1050 size_t orig_buf_size;
1053 switch ((enum nss_lookup_type)cache_mdata) {
1055 name = va_arg(ap, char *);
1056 proto = va_arg(ap, char *);
1059 port = va_arg(ap, int);
1060 proto = va_arg(ap, char *);
1065 /* should be unreachable */
1066 return (NS_UNAVAIL);
1069 serv = va_arg(ap, struct servent *);
1070 orig_buf = va_arg(ap, char *);
1071 orig_buf_size = va_arg(ap, size_t);
1072 ret_errno = va_arg(ap, int *);
1075 buffer_size - sizeof(struct servent) - sizeof(char *)) {
1076 *ret_errno = ERANGE;
1080 memcpy(serv, buffer, sizeof(struct servent));
1081 memcpy(&p, buffer + sizeof(struct servent), sizeof(char *));
1083 orig_buf = (char *)_ALIGN(orig_buf);
1084 memcpy(orig_buf, buffer + sizeof(struct servent) + sizeof(char *) +
1085 (_ALIGN(p) - (size_t)p),
1086 buffer_size - sizeof(struct servent) - sizeof(char *) -
1087 (_ALIGN(p) - (size_t)p));
1088 p = (char *)_ALIGN(p);
1090 NS_APPLY_OFFSET(serv->s_name, orig_buf, p, char *);
1091 NS_APPLY_OFFSET(serv->s_proto, orig_buf, p, char *);
1092 if (serv->s_aliases != NULL) {
1093 NS_APPLY_OFFSET(serv->s_aliases, orig_buf, p, char **);
1095 for (alias = serv->s_aliases; *alias; ++alias)
1096 NS_APPLY_OFFSET(*alias, orig_buf, p, char *);
1100 *((struct servent **)retval) = serv;
1101 return (NS_SUCCESS);
1104 NSS_MP_CACHE_HANDLING(services);
1105 #endif /* NS_CACHING */
1107 /* get**_r functions implementation */
1109 getservbyname_r(const char *name, const char *proto, struct servent *serv,
1110 char *buffer, size_t bufsize, struct servent **result)
1112 static const struct servent_mdata mdata = { nss_lt_name, 0 };
1113 static const struct servent_mdata compat_mdata = { nss_lt_name, 1 };
1115 static const nss_cache_info cache_info =
1116 NS_COMMON_CACHE_INFO_INITIALIZER(
1117 services, (void *)nss_lt_name,
1118 serv_id_func, serv_marshal_func, serv_unmarshal_func);
1119 #endif /* NS_CACHING */
1120 static const ns_dtab dtab[] = {
1121 { NSSRC_FILES, files_servent, (void *)&mdata },
1122 { NSSRC_DB, db_servent, (void *)nss_lt_name },
1124 { NSSRC_NIS, nis_servent, (void *)nss_lt_name },
1126 { NSSRC_COMPAT, files_servent, (void *)&compat_mdata },
1128 NS_CACHE_CB(&cache_info)
1130 { NULL, NULL, NULL }
1136 rv = nsdispatch(result, dtab, NSDB_SERVICES, "getservbyname_r",
1137 defaultsrc, name, proto, serv, buffer, bufsize, &ret_errno);
1139 if (rv == NS_SUCCESS)
1146 getservbyport_r(int port, const char *proto, struct servent *serv,
1147 char *buffer, size_t bufsize, struct servent **result)
1149 static const struct servent_mdata mdata = { nss_lt_id, 0 };
1150 static const struct servent_mdata compat_mdata = { nss_lt_id, 1 };
1152 static const nss_cache_info cache_info =
1153 NS_COMMON_CACHE_INFO_INITIALIZER(
1154 services, (void *)nss_lt_id,
1155 serv_id_func, serv_marshal_func, serv_unmarshal_func);
1157 static const ns_dtab dtab[] = {
1158 { NSSRC_FILES, files_servent, (void *)&mdata },
1159 { NSSRC_DB, db_servent, (void *)nss_lt_id },
1161 { NSSRC_NIS, nis_servent, (void *)nss_lt_id },
1163 { NSSRC_COMPAT, files_servent, (void *)&compat_mdata },
1165 NS_CACHE_CB(&cache_info)
1167 { NULL, NULL, NULL }
1173 rv = nsdispatch(result, dtab, NSDB_SERVICES, "getservbyport_r",
1174 defaultsrc, port, proto, serv, buffer, bufsize, &ret_errno);
1176 if (rv == NS_SUCCESS)
1183 getservent_r(struct servent *serv, char *buffer, size_t bufsize,
1184 struct servent **result)
1186 static const struct servent_mdata mdata = { nss_lt_all, 0 };
1187 static const struct servent_mdata compat_mdata = { nss_lt_all, 1 };
1189 static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
1190 services, (void *)nss_lt_all,
1191 serv_marshal_func, serv_unmarshal_func);
1193 static const ns_dtab dtab[] = {
1194 { NSSRC_FILES, files_servent, (void *)&mdata },
1195 { NSSRC_DB, db_servent, (void *)nss_lt_all },
1197 { NSSRC_NIS, nis_servent, (void *)nss_lt_all },
1199 { NSSRC_COMPAT, files_servent, (void *)&compat_mdata },
1201 NS_CACHE_CB(&cache_info)
1203 { NULL, NULL, NULL }
1209 rv = nsdispatch(result, dtab, NSDB_SERVICES, "getservent_r",
1210 defaultsrc, serv, buffer, bufsize, &ret_errno);
1212 if (rv == NS_SUCCESS)
1219 setservent(int stayopen)
1222 static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
1223 services, (void *)nss_lt_all,
1226 static const ns_dtab dtab[] = {
1227 { NSSRC_FILES, files_setservent, (void *)SETSERVENT },
1228 { NSSRC_DB, db_setservent, (void *)SETSERVENT },
1230 { NSSRC_NIS, nis_setservent, (void *)SETSERVENT },
1232 { NSSRC_COMPAT, compat_setservent, (void *)SETSERVENT },
1234 NS_CACHE_CB(&cache_info)
1236 { NULL, NULL, NULL }
1239 (void)nsdispatch(NULL, dtab, NSDB_SERVICES, "setservent", defaultsrc,
1247 static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
1248 services, (void *)nss_lt_all,
1251 static const ns_dtab dtab[] = {
1252 { NSSRC_FILES, files_setservent, (void *)ENDSERVENT },
1253 { NSSRC_DB, db_setservent, (void *)ENDSERVENT },
1255 { NSSRC_NIS, nis_setservent, (void *)ENDSERVENT },
1257 { NSSRC_COMPAT, compat_setservent, (void *)ENDSERVENT },
1259 NS_CACHE_CB(&cache_info)
1261 { NULL, NULL, NULL }
1264 (void)nsdispatch(NULL, dtab, NSDB_SERVICES, "endservent", defaultsrc);
1267 /* get** wrappers for get**_r functions implementation */
1269 servent_endstate(void *p)
1274 free(((struct servent_state *)p)->buffer);
1279 wrap_getservbyname_r(struct key key, struct servent *serv, char *buffer,
1280 size_t bufsize, struct servent **res)
1282 return (getservbyname_r(key.name, key.proto, serv, buffer, bufsize,
1287 wrap_getservbyport_r(struct key key, struct servent *serv, char *buffer,
1288 size_t bufsize, struct servent **res)
1290 return (getservbyport_r(key.port, key.proto, serv, buffer, bufsize,
1295 wrap_getservent_r(struct key key, struct servent *serv, char *buffer,
1296 size_t bufsize, struct servent **res)
1298 return (getservent_r(serv, buffer, bufsize, res));
1301 static struct servent *
1302 getserv(int (*fn)(struct key, struct servent *, char *, size_t,
1303 struct servent **), struct key key)
1306 struct servent *res;
1307 struct servent_state * st;
1309 rv = servent_getstate(&st);
1315 if (st->buffer == NULL) {
1316 st->buffer = malloc(SERVENT_STORAGE_INITIAL);
1317 if (st->buffer == NULL)
1319 st->bufsize = SERVENT_STORAGE_INITIAL;
1322 rv = fn(key, &st->serv, st->buffer, st->bufsize, &res);
1323 if (res == NULL && rv == ERANGE) {
1325 if ((st->bufsize << 1) > SERVENT_STORAGE_MAX) {
1331 st->buffer = malloc(st->bufsize);
1332 if (st->buffer == NULL)
1335 } while (res == NULL && rv == ERANGE);
1343 getservbyname(const char *name, const char *proto)
1350 return (getserv(wrap_getservbyname_r, key));
1354 getservbyport(int port, const char *proto)
1361 return (getserv(wrap_getservbyport_r, key));
1372 return (getserv(wrap_getservent_r, key));