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/socket.h>
38 #include <arpa/inet.h>
51 #include <rpcsvc/yp_prot.h>
52 #include <rpcsvc/ypclnt.h>
54 #include "namespace.h"
55 #include "reentrant.h"
56 #include "un-namespace.h"
57 #include "netdb_private.h"
67 SERVENT_STORAGE_INITIAL = 1 << 10, /* 1 KByte */
68 SERVENT_STORAGE_MAX = 1 << 20, /* 1 MByte */
73 enum nss_lookup_type how;
77 static const ns_src defaultsrc[] = {
78 { NSSRC_COMPAT, NS_SUCCESS },
82 static int servent_unpack(char *, struct servent *, char **, size_t, int *);
84 /* files backend declarations */
90 int compat_mode_active;
92 static void files_endstate(void *);
93 NSS_TLS_HANDLING(files);
95 static int files_servent(void *, void *, va_list);
96 static int files_setservent(void *, void *, va_list);
98 /* db backend declarations */
105 static void db_endstate(void *);
106 NSS_TLS_HANDLING(db);
108 static int db_servent(void *, void *, va_list);
109 static int db_setservent(void *, void *, va_list);
112 /* nis backend declarations */
113 static int nis_servent(void *, void *, va_list);
114 static int nis_setservent(void *, void *, va_list);
119 char yp_domain[MAXHOSTNAMELEN];
123 static void nis_endstate(void *);
124 NSS_TLS_HANDLING(nis);
126 static int nis_servent(void *, void *, va_list);
127 static int nis_setservent(void *, void *, va_list);
130 /* compat backend declarations */
131 static int compat_setservent(void *, void *, va_list);
133 /* get** wrappers for get**_r functions declarations */
134 struct servent_state {
139 static void servent_endstate(void *);
140 NSS_TLS_HANDLING(servent);
150 static int wrap_getservbyname_r(struct key, struct servent *, char *, size_t,
152 static int wrap_getservbyport_r(struct key, struct servent *, char *, size_t,
154 static int wrap_getservent_r(struct key, struct servent *, char *, size_t,
156 static struct servent *getserv(int (*fn)(struct key, struct servent *, char *,
157 size_t, struct servent **), struct key);
160 static int serv_id_func(char *, size_t *, va_list, void *);
161 static int serv_marshal_func(char *, size_t *, void *, va_list, void *);
162 static int serv_unmarshal_func(char *, size_t, void *, va_list, void *);
166 servent_unpack(char *p, struct servent *serv, char **aliases,
167 size_t aliases_size, int *errnop)
169 char *cp, **q, *endp;
175 memset(serv, 0, sizeof(struct servent));
177 cp = strpbrk(p, "#\n");
182 p = strpbrk(p, " \t");
186 while (*p == ' ' || *p == '\t')
188 cp = strpbrk(p, ",/");
193 l = strtol(p, &endp, 10);
194 if (endp == p || *endp != '\0' || l < 0 || l > USHRT_MAX)
196 serv->s_port = htons((in_port_t)l);
199 q = serv->s_aliases = aliases;
200 cp = strpbrk(cp, " \t");
204 if (*cp == ' ' || *cp == '\t') {
208 if (q < &aliases[aliases_size - 1]) {
215 cp = strpbrk(cp, " \t");
225 parse_result(struct servent *serv, char *buffer, size_t bufsize,
226 char *resultbuf, size_t resultbuflen, int *errnop)
231 if (bufsize <= resultbuflen + _ALIGNBYTES + sizeof(char *)) {
235 aliases = (char **)_ALIGN(&buffer[resultbuflen + 1]);
236 aliases_size = (buffer + bufsize - (char *)aliases) / sizeof(char *);
237 if (aliases_size < 1) {
242 memcpy(buffer, resultbuf, resultbuflen);
243 buffer[resultbuflen] = '\0';
245 if (servent_unpack(buffer, serv, aliases, aliases_size, errnop) != 0)
246 return ((*errnop == 0) ? NS_NOTFOUND : NS_RETURN);
250 /* files backend implementation */
252 files_endstate(void *p)
259 f = ((struct files_state *)p)->fp;
267 * compat structures. compat and files sources functionalities are almost
268 * equal, so they all are managed by files_servent function
271 files_servent(void *retval, void *mdata, va_list ap)
273 static const ns_src compat_src[] = {
275 { NSSRC_NIS, NS_SUCCESS },
279 ns_dtab compat_dtab[] = {
280 { NSSRC_DB, db_servent,
281 (void *)((struct servent_mdata *)mdata)->how },
283 { NSSRC_NIS, nis_servent,
284 (void *)((struct servent_mdata *)mdata)->how },
289 struct files_state *st;
293 struct servent_mdata *serv_mdata;
298 struct servent *serv;
309 serv_mdata = (struct servent_mdata *)mdata;
310 switch (serv_mdata->how) {
312 name = va_arg(ap, char *);
313 proto = va_arg(ap, char *);
316 port = va_arg(ap, int);
317 proto = va_arg(ap, char *);
325 serv = va_arg(ap, struct servent *);
326 buffer = va_arg(ap, char *);
327 bufsize = va_arg(ap, size_t);
328 errnop = va_arg(ap,int *);
330 *errnop = files_getstate(&st);
335 st->compat_mode_active = 0;
337 if (st->fp == NULL && (st->fp = fopen(_PATH_SERVICES, "re")) == NULL) {
342 if (serv_mdata->how == nss_lt_all)
346 stayopen = st->stayopen;
351 if (!st->compat_mode_active) {
352 if ((line = fgetln(st->fp, &linesize)) == NULL) {
358 if (*line=='+' && serv_mdata->compat_mode != 0)
359 st->compat_mode_active = 1;
362 if (st->compat_mode_active != 0) {
363 switch (serv_mdata->how) {
365 rv = nsdispatch(retval, compat_dtab,
366 NSDB_SERVICES_COMPAT, "getservbyname_r",
367 compat_src, name, proto, serv, buffer,
371 rv = nsdispatch(retval, compat_dtab,
372 NSDB_SERVICES_COMPAT, "getservbyport_r",
373 compat_src, port, proto, serv, buffer,
377 rv = nsdispatch(retval, compat_dtab,
378 NSDB_SERVICES_COMPAT, "getservent_r",
379 compat_src, serv, buffer, bufsize, errnop);
383 if (!(rv & NS_TERMINATE) ||
384 serv_mdata->how != nss_lt_all)
385 st->compat_mode_active = 0;
390 rv = parse_result(serv, buffer, bufsize, line, linesize,
392 if (rv == NS_NOTFOUND)
398 switch (serv_mdata->how) {
400 if (strcmp(name, serv->s_name) == 0)
402 for (cp = serv->s_aliases; *cp; cp++)
403 if (strcmp(name, *cp) == 0)
408 if (proto == NULL || strcmp(serv->s_proto, proto) == 0)
412 if (port != serv->s_port)
415 if (proto == NULL || strcmp(serv->s_proto, proto) == 0)
423 } while (!(rv & NS_TERMINATE));
425 if (!stayopen && st->fp != NULL) {
430 if ((rv == NS_SUCCESS) && (retval != NULL))
431 *(struct servent **)retval=serv;
437 files_setservent(void *retval, void *mdata, va_list ap)
439 struct files_state *st;
443 rv = files_getstate(&st);
447 switch ((enum constants)mdata) {
451 st->fp = fopen(_PATH_SERVICES, "re");
457 if (st->fp != NULL) {
467 st->compat_mode_active = 0;
471 /* db backend implementation */
480 db = ((struct db_state *)p)->db;
488 db_servent(void *retval, void *mdata, va_list ap)
491 DBT key, data, *result;
498 enum nss_lookup_type how;
503 struct servent *serv;
510 how = (enum nss_lookup_type)mdata;
513 name = va_arg(ap, char *);
514 proto = va_arg(ap, char *);
517 port = va_arg(ap, int);
518 proto = va_arg(ap, char *);
526 serv = va_arg(ap, struct servent *);
527 buffer = va_arg(ap, char *);
528 bufsize = va_arg(ap, size_t);
529 errnop = va_arg(ap,int *);
531 *errnop = db_getstate(&st);
535 if (how == nss_lt_all && st->keynum < 0)
536 return (NS_NOTFOUND);
538 if (st->db == NULL) {
539 st->db = dbopen(_PATH_SERVICES_DB, O_RDONLY, 0, DB_HASH, NULL);
540 if (st->db == NULL) {
546 stayopen = (how == nss_lt_all) ? 1 : st->stayopen;
554 key.size = snprintf(buf, sizeof(buf),
557 key.size = snprintf(buf, sizeof(buf),
558 "\376%s/%s", name, proto);
560 if (db->get(db, &key, &data, 0) != 0 ||
561 db->get(db, &data, &key, 0) != 0) {
571 key.size = snprintf(buf, sizeof(buf),
574 key.size = snprintf(buf, sizeof(buf),
575 "\377%d/%s", port, proto);
577 if (db->get(db, &key, &data, 0) != 0 ||
578 db->get(db, &data, &key, 0) != 0) {
586 key.size = snprintf(buf, sizeof(buf), "%d",
589 if (db->get(db, &key, &data, 0) != 0) {
598 rv = parse_result(serv, buffer, bufsize, result->data,
599 result->size - 1, errnop);
601 } while (!(rv & NS_TERMINATE) && how == nss_lt_all);
604 if (!stayopen && st->db != NULL) {
609 if (rv == NS_SUCCESS && retval != NULL)
610 *(struct servent **)retval = serv;
616 db_setservent(void *retval, void *mdata, va_list ap)
623 rv = db_getstate(&st);
627 switch ((enum constants)mdata) {
648 /* nis backend implementation */
651 nis_endstate(void *p)
656 free(((struct nis_state *)p)->yp_key);
661 nis_servent(void *retval, void *mdata, va_list ap)
663 char *resultbuf, *lastkey;
665 char buf[YPMAXRECORD + 2];
667 struct nis_state *st;
670 enum nss_lookup_type how;
675 struct servent *serv;
682 how = (enum nss_lookup_type)mdata;
685 name = va_arg(ap, char *);
686 proto = va_arg(ap, char *);
689 port = va_arg(ap, int);
690 proto = va_arg(ap, char *);
698 serv = va_arg(ap, struct servent *);
699 buffer = va_arg(ap, char *);
700 bufsize = va_arg(ap, size_t);
701 errnop = va_arg(ap, int *);
703 *errnop = nis_getstate(&st);
707 if (st->yp_domain[0] == '\0') {
708 if (getdomainname(st->yp_domain, sizeof st->yp_domain)) {
717 snprintf(buf, sizeof(buf), "%s/%s", name, proto);
718 if (yp_match(st->yp_domain, "services.byname", buf,
719 strlen(buf), &resultbuf, &resultbuflen)) {
725 snprintf(buf, sizeof(buf), "%d/%s", ntohs(port),
729 * We have to be a little flexible
730 * here. Ideally you're supposed to have both
731 * a services.byname and a services.byport
732 * map, but some systems have only
733 * services.byname. FreeBSD cheats a little by
734 * putting the services.byport information in
735 * the same map as services.byname so that
736 * either case will work. We allow for both
737 * possibilities here: if there is no
738 * services.byport map, we try services.byname
741 rv = yp_match(st->yp_domain, "services.byport", buf,
742 strlen(buf), &resultbuf, &resultbuflen);
744 if (rv == YPERR_MAP) {
745 if (yp_match(st->yp_domain,
746 "services.byname", buf,
747 strlen(buf), &resultbuf,
760 if (!st->yp_stepping) {
762 rv = yp_first(st->yp_domain, "services.byname",
763 &st->yp_key, &st->yp_keylen, &resultbuf,
771 lastkey = st->yp_key;
772 rv = yp_next(st->yp_domain, "services.byname",
773 st->yp_key, st->yp_keylen, &st->yp_key,
774 &st->yp_keylen, &resultbuf, &resultbuflen);
785 rv = parse_result(serv, buffer, bufsize, resultbuf,
786 resultbuflen, errnop);
789 } while (!(rv & NS_TERMINATE) && how == nss_lt_all);
792 if (rv == NS_SUCCESS && retval != NULL)
793 *(struct servent **)retval = serv;
799 nis_setservent(void *result, void *mdata, va_list ap)
801 struct nis_state *st;
804 rv = nis_getstate(&st);
808 switch ((enum constants)mdata) {
823 /* compat backend implementation */
825 compat_setservent(void *retval, void *mdata, va_list ap)
827 static const ns_src compat_src[] = {
829 { NSSRC_NIS, NS_SUCCESS },
833 ns_dtab compat_dtab[] = {
834 { NSSRC_DB, db_setservent, mdata },
836 { NSSRC_NIS, nis_setservent, mdata },
842 (void)files_setservent(retval, mdata, ap);
844 switch ((enum constants)mdata) {
847 (void)nsdispatch(retval, compat_dtab, NSDB_SERVICES_COMPAT,
848 "setservent", compat_src, f);
851 (void)nsdispatch(retval, compat_dtab, NSDB_SERVICES_COMPAT,
852 "endservent", compat_src);
863 serv_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata)
869 size_t desired_size, size, size2;
870 enum nss_lookup_type lookup_type;
871 int res = NS_UNAVAIL;
873 lookup_type = (enum nss_lookup_type)cache_mdata;
874 switch (lookup_type) {
876 name = va_arg(ap, char *);
877 proto = va_arg(ap, char *);
880 desired_size = sizeof(enum nss_lookup_type) + size + 1;
882 size2 = strlen(proto);
883 desired_size += size2 + 1;
887 if (desired_size > *buffer_size) {
892 memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
893 memcpy(buffer + sizeof(enum nss_lookup_type), name, size + 1);
896 memcpy(buffer + sizeof(enum nss_lookup_type) + size + 1,
902 port = va_arg(ap, int);
903 proto = va_arg(ap, char *);
905 desired_size = sizeof(enum nss_lookup_type) + sizeof(int);
907 size = strlen(proto);
908 desired_size += size + 1;
912 if (desired_size > *buffer_size) {
917 memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
918 memcpy(buffer + sizeof(enum nss_lookup_type), &port,
922 memcpy(buffer + sizeof(enum nss_lookup_type) +
923 sizeof(int), proto, size + 1);
928 /* should be unreachable */
933 *buffer_size = desired_size;
938 serv_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap,
944 struct servent *serv;
946 size_t orig_buf_size;
948 struct servent new_serv;
955 switch ((enum nss_lookup_type)cache_mdata) {
957 name = va_arg(ap, char *);
958 proto = va_arg(ap, char *);
961 port = va_arg(ap, int);
962 proto = va_arg(ap, char *);
967 /* should be unreachable */
971 serv = va_arg(ap, struct servent *);
972 orig_buf = va_arg(ap, char *);
973 orig_buf_size = va_arg(ap, size_t);
975 desired_size = _ALIGNBYTES + sizeof(struct servent) + sizeof(char *);
976 if (serv->s_name != NULL)
977 desired_size += strlen(serv->s_name) + 1;
978 if (serv->s_proto != NULL)
979 desired_size += strlen(serv->s_proto) + 1;
982 if (serv->s_aliases != NULL) {
983 for (alias = serv->s_aliases; *alias; ++alias) {
984 desired_size += strlen(*alias) + 1;
988 desired_size += _ALIGNBYTES +
989 sizeof(char *) * (aliases_size + 1);
992 if (*buffer_size < desired_size) {
993 /* this assignment is here for future use */
994 *buffer_size = desired_size;
998 memcpy(&new_serv, serv, sizeof(struct servent));
999 memset(buffer, 0, desired_size);
1001 *buffer_size = desired_size;
1002 p = buffer + sizeof(struct servent) + sizeof(char *);
1003 memcpy(buffer + sizeof(struct servent), &p, sizeof(char *));
1004 p = (char *)_ALIGN(p);
1006 if (new_serv.s_name != NULL) {
1007 size = strlen(new_serv.s_name);
1008 memcpy(p, new_serv.s_name, size);
1009 new_serv.s_name = p;
1013 if (new_serv.s_proto != NULL) {
1014 size = strlen(new_serv.s_proto);
1015 memcpy(p, new_serv.s_proto, size);
1016 new_serv.s_proto = p;
1020 if (new_serv.s_aliases != NULL) {
1021 p = (char *)_ALIGN(p);
1022 memcpy(p, new_serv.s_aliases, sizeof(char *) * aliases_size);
1023 new_serv.s_aliases = (char **)p;
1024 p += sizeof(char *) * (aliases_size + 1);
1026 for (alias = new_serv.s_aliases; *alias; ++alias) {
1027 size = strlen(*alias);
1028 memcpy(p, *alias, size);
1034 memcpy(buffer, &new_serv, sizeof(struct servent));
1035 return (NS_SUCCESS);
1039 serv_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap,
1045 struct servent *serv;
1049 size_t orig_buf_size;
1052 switch ((enum nss_lookup_type)cache_mdata) {
1054 name = va_arg(ap, char *);
1055 proto = va_arg(ap, char *);
1058 port = va_arg(ap, int);
1059 proto = va_arg(ap, char *);
1064 /* should be unreachable */
1065 return (NS_UNAVAIL);
1068 serv = va_arg(ap, struct servent *);
1069 orig_buf = va_arg(ap, char *);
1070 orig_buf_size = va_arg(ap, size_t);
1071 ret_errno = va_arg(ap, int *);
1074 buffer_size - sizeof(struct servent) - sizeof(char *)) {
1075 *ret_errno = ERANGE;
1079 memcpy(serv, buffer, sizeof(struct servent));
1080 memcpy(&p, buffer + sizeof(struct servent), sizeof(char *));
1082 orig_buf = (char *)_ALIGN(orig_buf);
1083 memcpy(orig_buf, buffer + sizeof(struct servent) + sizeof(char *) +
1084 (_ALIGN(p) - (size_t)p),
1085 buffer_size - sizeof(struct servent) - sizeof(char *) -
1086 (_ALIGN(p) - (size_t)p));
1087 p = (char *)_ALIGN(p);
1089 NS_APPLY_OFFSET(serv->s_name, orig_buf, p, char *);
1090 NS_APPLY_OFFSET(serv->s_proto, orig_buf, p, char *);
1091 if (serv->s_aliases != NULL) {
1092 NS_APPLY_OFFSET(serv->s_aliases, orig_buf, p, char **);
1094 for (alias = serv->s_aliases; *alias; ++alias)
1095 NS_APPLY_OFFSET(*alias, orig_buf, p, char *);
1099 *((struct servent **)retval) = serv;
1100 return (NS_SUCCESS);
1103 NSS_MP_CACHE_HANDLING(services);
1104 #endif /* NS_CACHING */
1106 /* get**_r functions implementation */
1108 getservbyname_r(const char *name, const char *proto, struct servent *serv,
1109 char *buffer, size_t bufsize, struct servent **result)
1111 static const struct servent_mdata mdata = { nss_lt_name, 0 };
1112 static const struct servent_mdata compat_mdata = { nss_lt_name, 1 };
1114 static const nss_cache_info cache_info =
1115 NS_COMMON_CACHE_INFO_INITIALIZER(
1116 services, (void *)nss_lt_name,
1117 serv_id_func, serv_marshal_func, serv_unmarshal_func);
1118 #endif /* NS_CACHING */
1119 static const ns_dtab dtab[] = {
1120 { NSSRC_FILES, files_servent, (void *)&mdata },
1121 { NSSRC_DB, db_servent, (void *)nss_lt_name },
1123 { NSSRC_NIS, nis_servent, (void *)nss_lt_name },
1125 { NSSRC_COMPAT, files_servent, (void *)&compat_mdata },
1127 NS_CACHE_CB(&cache_info)
1129 { NULL, NULL, NULL }
1135 rv = nsdispatch(result, dtab, NSDB_SERVICES, "getservbyname_r",
1136 defaultsrc, name, proto, serv, buffer, bufsize, &ret_errno);
1138 if (rv == NS_SUCCESS)
1145 getservbyport_r(int port, const char *proto, struct servent *serv,
1146 char *buffer, size_t bufsize, struct servent **result)
1148 static const struct servent_mdata mdata = { nss_lt_id, 0 };
1149 static const struct servent_mdata compat_mdata = { nss_lt_id, 1 };
1151 static const nss_cache_info cache_info =
1152 NS_COMMON_CACHE_INFO_INITIALIZER(
1153 services, (void *)nss_lt_id,
1154 serv_id_func, serv_marshal_func, serv_unmarshal_func);
1156 static const ns_dtab dtab[] = {
1157 { NSSRC_FILES, files_servent, (void *)&mdata },
1158 { NSSRC_DB, db_servent, (void *)nss_lt_id },
1160 { NSSRC_NIS, nis_servent, (void *)nss_lt_id },
1162 { NSSRC_COMPAT, files_servent, (void *)&compat_mdata },
1164 NS_CACHE_CB(&cache_info)
1166 { NULL, NULL, NULL }
1172 rv = nsdispatch(result, dtab, NSDB_SERVICES, "getservbyport_r",
1173 defaultsrc, port, proto, serv, buffer, bufsize, &ret_errno);
1175 if (rv == NS_SUCCESS)
1182 getservent_r(struct servent *serv, char *buffer, size_t bufsize,
1183 struct servent **result)
1185 static const struct servent_mdata mdata = { nss_lt_all, 0 };
1186 static const struct servent_mdata compat_mdata = { nss_lt_all, 1 };
1188 static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
1189 services, (void *)nss_lt_all,
1190 serv_marshal_func, serv_unmarshal_func);
1192 static const ns_dtab dtab[] = {
1193 { NSSRC_FILES, files_servent, (void *)&mdata },
1194 { NSSRC_DB, db_servent, (void *)nss_lt_all },
1196 { NSSRC_NIS, nis_servent, (void *)nss_lt_all },
1198 { NSSRC_COMPAT, files_servent, (void *)&compat_mdata },
1200 NS_CACHE_CB(&cache_info)
1202 { NULL, NULL, NULL }
1208 rv = nsdispatch(result, dtab, NSDB_SERVICES, "getservent_r",
1209 defaultsrc, serv, buffer, bufsize, &ret_errno);
1211 if (rv == NS_SUCCESS)
1218 setservent(int stayopen)
1221 static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
1222 services, (void *)nss_lt_all,
1225 static const ns_dtab dtab[] = {
1226 { NSSRC_FILES, files_setservent, (void *)SETSERVENT },
1227 { NSSRC_DB, db_setservent, (void *)SETSERVENT },
1229 { NSSRC_NIS, nis_setservent, (void *)SETSERVENT },
1231 { NSSRC_COMPAT, compat_setservent, (void *)SETSERVENT },
1233 NS_CACHE_CB(&cache_info)
1235 { NULL, NULL, NULL }
1238 (void)nsdispatch(NULL, dtab, NSDB_SERVICES, "setservent", defaultsrc,
1246 static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
1247 services, (void *)nss_lt_all,
1250 static const ns_dtab dtab[] = {
1251 { NSSRC_FILES, files_setservent, (void *)ENDSERVENT },
1252 { NSSRC_DB, db_setservent, (void *)ENDSERVENT },
1254 { NSSRC_NIS, nis_setservent, (void *)ENDSERVENT },
1256 { NSSRC_COMPAT, compat_setservent, (void *)ENDSERVENT },
1258 NS_CACHE_CB(&cache_info)
1260 { NULL, NULL, NULL }
1263 (void)nsdispatch(NULL, dtab, NSDB_SERVICES, "endservent", defaultsrc);
1266 /* get** wrappers for get**_r functions implementation */
1268 servent_endstate(void *p)
1273 free(((struct servent_state *)p)->buffer);
1278 wrap_getservbyname_r(struct key key, struct servent *serv, char *buffer,
1279 size_t bufsize, struct servent **res)
1281 return (getservbyname_r(key.name, key.proto, serv, buffer, bufsize,
1286 wrap_getservbyport_r(struct key key, struct servent *serv, char *buffer,
1287 size_t bufsize, struct servent **res)
1289 return (getservbyport_r(key.port, key.proto, serv, buffer, bufsize,
1294 wrap_getservent_r(struct key key, struct servent *serv, char *buffer,
1295 size_t bufsize, struct servent **res)
1297 return (getservent_r(serv, buffer, bufsize, res));
1300 static struct servent *
1301 getserv(int (*fn)(struct key, struct servent *, char *, size_t,
1302 struct servent **), struct key key)
1305 struct servent *res;
1306 struct servent_state * st;
1308 rv = servent_getstate(&st);
1314 if (st->buffer == NULL) {
1315 st->buffer = malloc(SERVENT_STORAGE_INITIAL);
1316 if (st->buffer == NULL)
1318 st->bufsize = SERVENT_STORAGE_INITIAL;
1321 rv = fn(key, &st->serv, st->buffer, st->bufsize, &res);
1322 if (res == NULL && rv == ERANGE) {
1324 if ((st->bufsize << 1) > SERVENT_STORAGE_MAX) {
1330 st->buffer = malloc(st->bufsize);
1331 if (st->buffer == NULL)
1334 } while (res == NULL && rv == ERANGE);
1342 getservbyname(const char *name, const char *proto)
1349 return (getserv(wrap_getservbyname_r, key));
1353 getservbyport(int port, const char *proto)
1360 return (getserv(wrap_getservbyport_r, key));
1371 return (getserv(wrap_getservent_r, key));