2 * SPDX-License-Identifier: BSD-3-Clause
4 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #if defined(LIBC_SCCS) && !defined(lint)
33 static char sccsid[] = "@(#)getservent.c 8.1 (Berkeley) 6/4/93";
34 #endif /* LIBC_SCCS and not lint */
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
38 #include <sys/param.h>
39 #include <sys/socket.h>
40 #include <arpa/inet.h>
53 #include <rpcsvc/yp_prot.h>
54 #include <rpcsvc/ypclnt.h>
56 #include "namespace.h"
57 #include "reentrant.h"
58 #include "un-namespace.h"
59 #include "netdb_private.h"
69 SERVENT_STORAGE_INITIAL = 1 << 10, /* 1 KByte */
70 SERVENT_STORAGE_MAX = 1 << 20, /* 1 MByte */
75 enum nss_lookup_type how;
79 static const ns_src defaultsrc[] = {
80 { NSSRC_COMPAT, NS_SUCCESS },
84 static int servent_unpack(char *, struct servent *, char **, size_t, int *);
86 /* files backend declarations */
92 int compat_mode_active;
94 static void files_endstate(void *);
95 NSS_TLS_HANDLING(files);
97 static int files_servent(void *, void *, va_list);
98 static int files_setservent(void *, void *, va_list);
100 /* db backend declarations */
107 static void db_endstate(void *);
108 NSS_TLS_HANDLING(db);
110 static int db_servent(void *, void *, va_list);
111 static int db_setservent(void *, void *, va_list);
114 /* nis backend declarations */
115 static int nis_servent(void *, void *, va_list);
116 static int nis_setservent(void *, void *, va_list);
121 char yp_domain[MAXHOSTNAMELEN];
125 static void nis_endstate(void *);
126 NSS_TLS_HANDLING(nis);
128 static int nis_servent(void *, void *, va_list);
129 static int nis_setservent(void *, void *, va_list);
132 /* compat backend declarations */
133 static int compat_setservent(void *, void *, va_list);
135 /* get** wrappers for get**_r functions declarations */
136 struct servent_state {
141 static void servent_endstate(void *);
142 NSS_TLS_HANDLING(servent);
152 static int wrap_getservbyname_r(struct key, struct servent *, char *, size_t,
154 static int wrap_getservbyport_r(struct key, struct servent *, char *, size_t,
156 static int wrap_getservent_r(struct key, struct servent *, char *, size_t,
158 static struct servent *getserv(int (*fn)(struct key, struct servent *, char *,
159 size_t, struct servent **), struct key);
162 static int serv_id_func(char *, size_t *, va_list, void *);
163 static int serv_marshal_func(char *, size_t *, void *, va_list, void *);
164 static int serv_unmarshal_func(char *, size_t, void *, va_list, void *);
168 servent_unpack(char *p, struct servent *serv, char **aliases,
169 size_t aliases_size, int *errnop)
171 char *cp, **q, *endp;
177 memset(serv, 0, sizeof(struct servent));
179 cp = strpbrk(p, "#\n");
184 p = strpbrk(p, " \t");
188 while (*p == ' ' || *p == '\t')
190 cp = strpbrk(p, ",/");
195 l = strtol(p, &endp, 10);
196 if (endp == p || *endp != '\0' || l < 0 || l > USHRT_MAX)
198 serv->s_port = htons((in_port_t)l);
201 q = serv->s_aliases = aliases;
202 cp = strpbrk(cp, " \t");
206 if (*cp == ' ' || *cp == '\t') {
210 if (q < &aliases[aliases_size - 1]) {
217 cp = strpbrk(cp, " \t");
227 parse_result(struct servent *serv, char *buffer, size_t bufsize,
228 char *resultbuf, size_t resultbuflen, int *errnop)
233 if (bufsize <= resultbuflen + _ALIGNBYTES + sizeof(char *)) {
237 aliases = (char **)_ALIGN(&buffer[resultbuflen + 1]);
238 aliases_size = (buffer + bufsize - (char *)aliases) / sizeof(char *);
239 if (aliases_size < 1) {
244 memcpy(buffer, resultbuf, resultbuflen);
245 buffer[resultbuflen] = '\0';
247 if (servent_unpack(buffer, serv, aliases, aliases_size, errnop) != 0)
248 return ((*errnop == 0) ? NS_NOTFOUND : NS_RETURN);
252 /* files backend implementation */
254 files_endstate(void *p)
261 f = ((struct files_state *)p)->fp;
269 * compat structures. compat and files sources functionalities are almost
270 * equal, so they all are managed by files_servent function
273 files_servent(void *retval, void *mdata, va_list ap)
275 static const ns_src compat_src[] = {
277 { NSSRC_NIS, NS_SUCCESS },
281 ns_dtab compat_dtab[] = {
282 { NSSRC_DB, db_servent,
283 (void *)((struct servent_mdata *)mdata)->how },
285 { NSSRC_NIS, nis_servent,
286 (void *)((struct servent_mdata *)mdata)->how },
291 struct files_state *st;
295 struct servent_mdata *serv_mdata;
300 struct servent *serv;
311 serv_mdata = (struct servent_mdata *)mdata;
312 switch (serv_mdata->how) {
314 name = va_arg(ap, char *);
315 proto = va_arg(ap, char *);
318 port = va_arg(ap, int);
319 proto = va_arg(ap, char *);
327 serv = va_arg(ap, struct servent *);
328 buffer = va_arg(ap, char *);
329 bufsize = va_arg(ap, size_t);
330 errnop = va_arg(ap,int *);
332 *errnop = files_getstate(&st);
337 st->compat_mode_active = 0;
339 if (st->fp == NULL && (st->fp = fopen(_PATH_SERVICES, "re")) == NULL) {
344 if (serv_mdata->how == nss_lt_all)
348 stayopen = st->stayopen;
353 if (!st->compat_mode_active) {
354 if ((line = fgetln(st->fp, &linesize)) == NULL) {
360 if (*line=='+' && serv_mdata->compat_mode != 0)
361 st->compat_mode_active = 1;
364 if (st->compat_mode_active != 0) {
365 switch (serv_mdata->how) {
367 rv = nsdispatch(retval, compat_dtab,
368 NSDB_SERVICES_COMPAT, "getservbyname_r",
369 compat_src, name, proto, serv, buffer,
373 rv = nsdispatch(retval, compat_dtab,
374 NSDB_SERVICES_COMPAT, "getservbyport_r",
375 compat_src, port, proto, serv, buffer,
379 rv = nsdispatch(retval, compat_dtab,
380 NSDB_SERVICES_COMPAT, "getservent_r",
381 compat_src, serv, buffer, bufsize, errnop);
385 if (!(rv & NS_TERMINATE) ||
386 serv_mdata->how != nss_lt_all)
387 st->compat_mode_active = 0;
392 rv = parse_result(serv, buffer, bufsize, line, linesize,
394 if (rv == NS_NOTFOUND)
400 switch (serv_mdata->how) {
402 if (strcmp(name, serv->s_name) == 0)
404 for (cp = serv->s_aliases; *cp; cp++)
405 if (strcmp(name, *cp) == 0)
410 if (proto == NULL || strcmp(serv->s_proto, proto) == 0)
414 if (port != serv->s_port)
417 if (proto == NULL || strcmp(serv->s_proto, proto) == 0)
425 } while (!(rv & NS_TERMINATE));
427 if (!stayopen && st->fp != NULL) {
432 if ((rv == NS_SUCCESS) && (retval != NULL))
433 *(struct servent **)retval=serv;
439 files_setservent(void *retval, void *mdata, va_list ap)
441 struct files_state *st;
445 rv = files_getstate(&st);
449 switch ((enum constants)mdata) {
453 st->fp = fopen(_PATH_SERVICES, "re");
459 if (st->fp != NULL) {
469 st->compat_mode_active = 0;
473 /* db backend implementation */
482 db = ((struct db_state *)p)->db;
490 db_servent(void *retval, void *mdata, va_list ap)
493 DBT key, data, *result;
500 enum nss_lookup_type how;
505 struct servent *serv;
512 how = (enum nss_lookup_type)mdata;
515 name = va_arg(ap, char *);
516 proto = va_arg(ap, char *);
519 port = va_arg(ap, int);
520 proto = va_arg(ap, char *);
528 serv = va_arg(ap, struct servent *);
529 buffer = va_arg(ap, char *);
530 bufsize = va_arg(ap, size_t);
531 errnop = va_arg(ap,int *);
533 *errnop = db_getstate(&st);
537 if (how == nss_lt_all && st->keynum < 0)
538 return (NS_NOTFOUND);
540 if (st->db == NULL) {
541 st->db = dbopen(_PATH_SERVICES_DB, O_RDONLY, 0, DB_HASH, NULL);
542 if (st->db == NULL) {
548 stayopen = (how == nss_lt_all) ? 1 : st->stayopen;
556 key.size = snprintf(buf, sizeof(buf),
559 key.size = snprintf(buf, sizeof(buf),
560 "\376%s/%s", name, proto);
562 if (db->get(db, &key, &data, 0) != 0 ||
563 db->get(db, &data, &key, 0) != 0) {
573 key.size = snprintf(buf, sizeof(buf),
576 key.size = snprintf(buf, sizeof(buf),
577 "\377%d/%s", port, proto);
579 if (db->get(db, &key, &data, 0) != 0 ||
580 db->get(db, &data, &key, 0) != 0) {
588 key.size = snprintf(buf, sizeof(buf), "%d",
591 if (db->get(db, &key, &data, 0) != 0) {
600 rv = parse_result(serv, buffer, bufsize, result->data,
601 result->size - 1, errnop);
603 } while (!(rv & NS_TERMINATE) && how == nss_lt_all);
606 if (!stayopen && st->db != NULL) {
611 if (rv == NS_SUCCESS && retval != NULL)
612 *(struct servent **)retval = serv;
618 db_setservent(void *retval, void *mdata, va_list ap)
625 rv = db_getstate(&st);
629 switch ((enum constants)mdata) {
650 /* nis backend implementation */
653 nis_endstate(void *p)
658 free(((struct nis_state *)p)->yp_key);
663 nis_servent(void *retval, void *mdata, va_list ap)
665 char *resultbuf, *lastkey;
669 struct nis_state *st;
672 enum nss_lookup_type how;
677 struct servent *serv;
685 how = (enum nss_lookup_type)mdata;
688 name = va_arg(ap, char *);
689 proto = va_arg(ap, char *);
692 port = va_arg(ap, int);
693 proto = va_arg(ap, char *);
701 serv = va_arg(ap, struct servent *);
702 buffer = va_arg(ap, char *);
703 bufsize = va_arg(ap, size_t);
704 errnop = va_arg(ap, int *);
706 *errnop = nis_getstate(&st);
710 if (st->yp_domain[0] == '\0') {
711 if (getdomainname(st->yp_domain, sizeof st->yp_domain)) {
721 asprintf(&buf, "%s/%s", name, proto);
723 return (NS_TRYAGAIN);
724 if (yp_match(st->yp_domain, "services.byname", buf,
725 strlen(buf), &resultbuf, &resultbuflen)) {
732 asprintf(&buf, "%d/%s", ntohs(port), proto);
734 return (NS_TRYAGAIN);
737 * We have to be a little flexible
738 * here. Ideally you're supposed to have both
739 * a services.byname and a services.byport
740 * map, but some systems have only
741 * services.byname. FreeBSD cheats a little by
742 * putting the services.byport information in
743 * the same map as services.byname so that
744 * either case will work. We allow for both
745 * possibilities here: if there is no
746 * services.byport map, we try services.byname
749 rv = yp_match(st->yp_domain, "services.byport", buf,
750 strlen(buf), &resultbuf, &resultbuflen);
752 if (rv == YPERR_MAP) {
753 if (yp_match(st->yp_domain,
754 "services.byname", buf,
755 strlen(buf), &resultbuf,
768 if (!st->yp_stepping) {
770 rv = yp_first(st->yp_domain, "services.byname",
771 &st->yp_key, &st->yp_keylen, &resultbuf,
779 lastkey = st->yp_key;
780 rv = yp_next(st->yp_domain, "services.byname",
781 st->yp_key, st->yp_keylen, &st->yp_key,
782 &st->yp_keylen, &resultbuf, &resultbuflen);
793 rv = parse_result(serv, buffer, bufsize, resultbuf,
794 resultbuflen, errnop);
797 } while (!(rv & NS_TERMINATE) && how == nss_lt_all);
801 if (rv == NS_SUCCESS && retval != NULL)
802 *(struct servent **)retval = serv;
808 nis_setservent(void *result, void *mdata, va_list ap)
810 struct nis_state *st;
813 rv = nis_getstate(&st);
817 switch ((enum constants)mdata) {
832 /* compat backend implementation */
834 compat_setservent(void *retval, void *mdata, va_list ap)
836 static const ns_src compat_src[] = {
838 { NSSRC_NIS, NS_SUCCESS },
842 ns_dtab compat_dtab[] = {
843 { NSSRC_DB, db_setservent, mdata },
845 { NSSRC_NIS, nis_setservent, mdata },
851 (void)files_setservent(retval, mdata, ap);
853 switch ((enum constants)mdata) {
856 (void)nsdispatch(retval, compat_dtab, NSDB_SERVICES_COMPAT,
857 "setservent", compat_src, f);
860 (void)nsdispatch(retval, compat_dtab, NSDB_SERVICES_COMPAT,
861 "endservent", compat_src);
872 serv_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata)
878 size_t desired_size, size, size2;
879 enum nss_lookup_type lookup_type;
880 int res = NS_UNAVAIL;
882 lookup_type = (enum nss_lookup_type)cache_mdata;
883 switch (lookup_type) {
885 name = va_arg(ap, char *);
886 proto = va_arg(ap, char *);
889 desired_size = sizeof(enum nss_lookup_type) + size + 1;
891 size2 = strlen(proto);
892 desired_size += size2 + 1;
896 if (desired_size > *buffer_size) {
901 memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
902 memcpy(buffer + sizeof(enum nss_lookup_type), name, size + 1);
905 memcpy(buffer + sizeof(enum nss_lookup_type) + size + 1,
911 port = va_arg(ap, int);
912 proto = va_arg(ap, char *);
914 desired_size = sizeof(enum nss_lookup_type) + sizeof(int);
916 size = strlen(proto);
917 desired_size += size + 1;
921 if (desired_size > *buffer_size) {
926 memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
927 memcpy(buffer + sizeof(enum nss_lookup_type), &port,
931 memcpy(buffer + sizeof(enum nss_lookup_type) +
932 sizeof(int), proto, size + 1);
937 /* should be unreachable */
942 *buffer_size = desired_size;
947 serv_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap,
953 struct servent *serv;
955 size_t orig_buf_size;
957 struct servent new_serv;
964 switch ((enum nss_lookup_type)cache_mdata) {
966 name = va_arg(ap, char *);
967 proto = va_arg(ap, char *);
970 port = va_arg(ap, int);
971 proto = va_arg(ap, char *);
976 /* should be unreachable */
980 serv = va_arg(ap, struct servent *);
981 orig_buf = va_arg(ap, char *);
982 orig_buf_size = va_arg(ap, size_t);
984 desired_size = _ALIGNBYTES + sizeof(struct servent) + sizeof(char *);
985 if (serv->s_name != NULL)
986 desired_size += strlen(serv->s_name) + 1;
987 if (serv->s_proto != NULL)
988 desired_size += strlen(serv->s_proto) + 1;
991 if (serv->s_aliases != NULL) {
992 for (alias = serv->s_aliases; *alias; ++alias) {
993 desired_size += strlen(*alias) + 1;
997 desired_size += _ALIGNBYTES +
998 sizeof(char *) * (aliases_size + 1);
1001 if (*buffer_size < desired_size) {
1002 /* this assignment is here for future use */
1003 *buffer_size = desired_size;
1007 memcpy(&new_serv, serv, sizeof(struct servent));
1008 memset(buffer, 0, desired_size);
1010 *buffer_size = desired_size;
1011 p = buffer + sizeof(struct servent) + sizeof(char *);
1012 memcpy(buffer + sizeof(struct servent), &p, sizeof(char *));
1013 p = (char *)_ALIGN(p);
1015 if (new_serv.s_name != NULL) {
1016 size = strlen(new_serv.s_name);
1017 memcpy(p, new_serv.s_name, size);
1018 new_serv.s_name = p;
1022 if (new_serv.s_proto != NULL) {
1023 size = strlen(new_serv.s_proto);
1024 memcpy(p, new_serv.s_proto, size);
1025 new_serv.s_proto = p;
1029 if (new_serv.s_aliases != NULL) {
1030 p = (char *)_ALIGN(p);
1031 memcpy(p, new_serv.s_aliases, sizeof(char *) * aliases_size);
1032 new_serv.s_aliases = (char **)p;
1033 p += sizeof(char *) * (aliases_size + 1);
1035 for (alias = new_serv.s_aliases; *alias; ++alias) {
1036 size = strlen(*alias);
1037 memcpy(p, *alias, size);
1043 memcpy(buffer, &new_serv, sizeof(struct servent));
1044 return (NS_SUCCESS);
1048 serv_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap,
1054 struct servent *serv;
1058 size_t orig_buf_size;
1061 switch ((enum nss_lookup_type)cache_mdata) {
1063 name = va_arg(ap, char *);
1064 proto = va_arg(ap, char *);
1067 port = va_arg(ap, int);
1068 proto = va_arg(ap, char *);
1073 /* should be unreachable */
1074 return (NS_UNAVAIL);
1077 serv = va_arg(ap, struct servent *);
1078 orig_buf = va_arg(ap, char *);
1079 orig_buf_size = va_arg(ap, size_t);
1080 ret_errno = va_arg(ap, int *);
1083 buffer_size - sizeof(struct servent) - sizeof(char *)) {
1084 *ret_errno = ERANGE;
1088 memcpy(serv, buffer, sizeof(struct servent));
1089 memcpy(&p, buffer + sizeof(struct servent), sizeof(char *));
1091 orig_buf = (char *)_ALIGN(orig_buf);
1092 memcpy(orig_buf, buffer + sizeof(struct servent) + sizeof(char *) +
1093 (_ALIGN(p) - (size_t)p),
1094 buffer_size - sizeof(struct servent) - sizeof(char *) -
1095 (_ALIGN(p) - (size_t)p));
1096 p = (char *)_ALIGN(p);
1098 NS_APPLY_OFFSET(serv->s_name, orig_buf, p, char *);
1099 NS_APPLY_OFFSET(serv->s_proto, orig_buf, p, char *);
1100 if (serv->s_aliases != NULL) {
1101 NS_APPLY_OFFSET(serv->s_aliases, orig_buf, p, char **);
1103 for (alias = serv->s_aliases; *alias; ++alias)
1104 NS_APPLY_OFFSET(*alias, orig_buf, p, char *);
1108 *((struct servent **)retval) = serv;
1109 return (NS_SUCCESS);
1112 NSS_MP_CACHE_HANDLING(services);
1113 #endif /* NS_CACHING */
1115 /* get**_r functions implementation */
1117 getservbyname_r(const char *name, const char *proto, struct servent *serv,
1118 char *buffer, size_t bufsize, struct servent **result)
1120 static const struct servent_mdata mdata = { nss_lt_name, 0 };
1121 static const struct servent_mdata compat_mdata = { nss_lt_name, 1 };
1123 static const nss_cache_info cache_info =
1124 NS_COMMON_CACHE_INFO_INITIALIZER(
1125 services, (void *)nss_lt_name,
1126 serv_id_func, serv_marshal_func, serv_unmarshal_func);
1127 #endif /* NS_CACHING */
1128 static const ns_dtab dtab[] = {
1129 { NSSRC_FILES, files_servent, (void *)&mdata },
1130 { NSSRC_DB, db_servent, (void *)nss_lt_name },
1132 { NSSRC_NIS, nis_servent, (void *)nss_lt_name },
1134 { NSSRC_COMPAT, files_servent, (void *)&compat_mdata },
1136 NS_CACHE_CB(&cache_info)
1138 { NULL, NULL, NULL }
1144 rv = nsdispatch(result, dtab, NSDB_SERVICES, "getservbyname_r",
1145 defaultsrc, name, proto, serv, buffer, bufsize, &ret_errno);
1147 if (rv == NS_SUCCESS)
1154 getservbyport_r(int port, const char *proto, struct servent *serv,
1155 char *buffer, size_t bufsize, struct servent **result)
1157 static const struct servent_mdata mdata = { nss_lt_id, 0 };
1158 static const struct servent_mdata compat_mdata = { nss_lt_id, 1 };
1160 static const nss_cache_info cache_info =
1161 NS_COMMON_CACHE_INFO_INITIALIZER(
1162 services, (void *)nss_lt_id,
1163 serv_id_func, serv_marshal_func, serv_unmarshal_func);
1165 static const ns_dtab dtab[] = {
1166 { NSSRC_FILES, files_servent, (void *)&mdata },
1167 { NSSRC_DB, db_servent, (void *)nss_lt_id },
1169 { NSSRC_NIS, nis_servent, (void *)nss_lt_id },
1171 { NSSRC_COMPAT, files_servent, (void *)&compat_mdata },
1173 NS_CACHE_CB(&cache_info)
1175 { NULL, NULL, NULL }
1181 rv = nsdispatch(result, dtab, NSDB_SERVICES, "getservbyport_r",
1182 defaultsrc, port, proto, serv, buffer, bufsize, &ret_errno);
1184 if (rv == NS_SUCCESS)
1191 getservent_r(struct servent *serv, char *buffer, size_t bufsize,
1192 struct servent **result)
1194 static const struct servent_mdata mdata = { nss_lt_all, 0 };
1195 static const struct servent_mdata compat_mdata = { nss_lt_all, 1 };
1197 static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
1198 services, (void *)nss_lt_all,
1199 serv_marshal_func, serv_unmarshal_func);
1201 static const ns_dtab dtab[] = {
1202 { NSSRC_FILES, files_servent, (void *)&mdata },
1203 { NSSRC_DB, db_servent, (void *)nss_lt_all },
1205 { NSSRC_NIS, nis_servent, (void *)nss_lt_all },
1207 { NSSRC_COMPAT, files_servent, (void *)&compat_mdata },
1209 NS_CACHE_CB(&cache_info)
1211 { NULL, NULL, NULL }
1217 rv = nsdispatch(result, dtab, NSDB_SERVICES, "getservent_r",
1218 defaultsrc, serv, buffer, bufsize, &ret_errno);
1220 if (rv == NS_SUCCESS)
1227 setservent(int stayopen)
1230 static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
1231 services, (void *)nss_lt_all,
1234 static const ns_dtab dtab[] = {
1235 { NSSRC_FILES, files_setservent, (void *)SETSERVENT },
1236 { NSSRC_DB, db_setservent, (void *)SETSERVENT },
1238 { NSSRC_NIS, nis_setservent, (void *)SETSERVENT },
1240 { NSSRC_COMPAT, compat_setservent, (void *)SETSERVENT },
1242 NS_CACHE_CB(&cache_info)
1244 { NULL, NULL, NULL }
1247 (void)nsdispatch(NULL, dtab, NSDB_SERVICES, "setservent", defaultsrc,
1255 static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
1256 services, (void *)nss_lt_all,
1259 static const ns_dtab dtab[] = {
1260 { NSSRC_FILES, files_setservent, (void *)ENDSERVENT },
1261 { NSSRC_DB, db_setservent, (void *)ENDSERVENT },
1263 { NSSRC_NIS, nis_setservent, (void *)ENDSERVENT },
1265 { NSSRC_COMPAT, compat_setservent, (void *)ENDSERVENT },
1267 NS_CACHE_CB(&cache_info)
1269 { NULL, NULL, NULL }
1272 (void)nsdispatch(NULL, dtab, NSDB_SERVICES, "endservent", defaultsrc);
1275 /* get** wrappers for get**_r functions implementation */
1277 servent_endstate(void *p)
1282 free(((struct servent_state *)p)->buffer);
1287 wrap_getservbyname_r(struct key key, struct servent *serv, char *buffer,
1288 size_t bufsize, struct servent **res)
1290 return (getservbyname_r(key.name, key.proto, serv, buffer, bufsize,
1295 wrap_getservbyport_r(struct key key, struct servent *serv, char *buffer,
1296 size_t bufsize, struct servent **res)
1298 return (getservbyport_r(key.port, key.proto, serv, buffer, bufsize,
1303 wrap_getservent_r(struct key key, struct servent *serv, char *buffer,
1304 size_t bufsize, struct servent **res)
1306 return (getservent_r(serv, buffer, bufsize, res));
1309 static struct servent *
1310 getserv(int (*fn)(struct key, struct servent *, char *, size_t,
1311 struct servent **), struct key key)
1314 struct servent *res;
1315 struct servent_state * st;
1317 rv = servent_getstate(&st);
1323 if (st->buffer == NULL) {
1324 st->buffer = malloc(SERVENT_STORAGE_INITIAL);
1325 if (st->buffer == NULL)
1327 st->bufsize = SERVENT_STORAGE_INITIAL;
1330 rv = fn(key, &st->serv, st->buffer, st->bufsize, &res);
1331 if (res == NULL && rv == ERANGE) {
1333 if ((st->bufsize << 1) > SERVENT_STORAGE_MAX) {
1339 st->buffer = malloc(st->bufsize);
1340 if (st->buffer == NULL)
1343 } while (res == NULL && rv == ERANGE);
1351 getservbyname(const char *name, const char *proto)
1358 return (getserv(wrap_getservbyname_r, key));
1362 getservbyport(int port, const char *proto)
1369 return (getserv(wrap_getservbyport_r, key));
1380 return (getserv(wrap_getservent_r, key));