diff options
Diffstat (limited to 'lib/libc/rpc/getrpcent.c')
-rw-r--r-- | lib/libc/rpc/getrpcent.c | 1048 |
1 files changed, 1048 insertions, 0 deletions
diff --git a/lib/libc/rpc/getrpcent.c b/lib/libc/rpc/getrpcent.c new file mode 100644 index 0000000..abee480 --- /dev/null +++ b/lib/libc/rpc/getrpcent.c @@ -0,0 +1,1048 @@ +/* $NetBSD: getrpcent.c,v 1.17 2000/01/22 22:19:17 mycroft Exp $ */ + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char *sccsid = "@(#)getrpcent.c 1.14 91/03/11 Copyr 1984 Sun Micro"; +#endif +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +/* + * Copyright (c) 1984 by Sun Microsystems, Inc. + */ + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <assert.h> +#include <errno.h> +#include <nsswitch.h> +#include <netinet/in.h> +#include <stdio.h> +#include <string.h> +#include <stdarg.h> +#include <stdlib.h> +#include <rpc/rpc.h> +#ifdef YP +#include <rpcsvc/yp_prot.h> +#include <rpcsvc/ypclnt.h> +#endif +#include <unistd.h> +#include "namespace.h" +#include "reentrant.h" +#include "un-namespace.h" +#include "libc_private.h" +#include "nss_tls.h" +#ifdef NS_CACHING +#include "nscache.h" +#endif + +#define RPCDB "/etc/rpc" + +/* nsswitch declarations */ +enum constants +{ + SETRPCENT = 1, + ENDRPCENT = 2, + RPCENT_STORAGE_INITIAL = 1 << 10, /* 1 KByte */ + RPCENT_STORAGE_MAX = 1 << 20, /* 1 MByte */ +}; + +static const ns_src defaultsrc[] = { + { NSSRC_FILES, NS_SUCCESS }, +#ifdef YP + { NSSRC_NIS, NS_SUCCESS }, +#endif + { NULL, 0 } +}; + +/* files backend declarations */ +struct files_state { + FILE *fp; + int stayopen; +}; + +static int files_rpcent(void *, void *, va_list); +static int files_setrpcent(void *, void *, va_list); + +static void files_endstate(void *); +NSS_TLS_HANDLING(files); + +/* nis backend declarations */ +#ifdef YP +struct nis_state { + char domain[MAXHOSTNAMELEN]; + char *current; + int currentlen; + int stepping; + int no_name_map; +}; + +static int nis_rpcent(void *, void *, va_list); +static int nis_setrpcent(void *, void *, va_list); + +static void nis_endstate(void *); +NSS_TLS_HANDLING(nis); +#endif + +/* get** wrappers for get**_r functions declarations */ +struct rpcent_state { + struct rpcent rpc; + char *buffer; + size_t bufsize; +}; +static void rpcent_endstate(void *); +NSS_TLS_HANDLING(rpcent); + +union key { + const char *name; + int number; +}; + +static int wrap_getrpcbyname_r(union key, struct rpcent *, char *, + size_t, struct rpcent **); +static int wrap_getrpcbynumber_r(union key, struct rpcent *, char *, + size_t, struct rpcent **); +static int wrap_getrpcent_r(union key, struct rpcent *, char *, + size_t, struct rpcent **); +static struct rpcent *getrpc(int (*fn)(union key, struct rpcent *, char *, + size_t, struct rpcent **), union key); + +#ifdef NS_CACHING +static int rpc_id_func(char *, size_t *, va_list, void *); +static int rpc_marshal_func(char *, size_t *, void *, va_list, void *); +static int rpc_unmarshal_func(char *, size_t, void *, va_list, void *); +#endif + +static int +rpcent_unpack(char *p, struct rpcent *rpc, char **r_aliases, + size_t aliases_size, int *errnop) +{ + char *cp, **q; + + assert(p != NULL); + + if (*p == '#') + return (-1); + cp = strpbrk(p, "#\n"); + if (cp == NULL) + return (-1); + *cp = '\0'; + cp = strpbrk(p, " \t"); + if (cp == NULL) + return (-1); + *cp++ = '\0'; + /* THIS STUFF IS INTERNET SPECIFIC */ + rpc->r_name = p; + while (*cp == ' ' || *cp == '\t') + cp++; + rpc->r_number = atoi(cp); + q = rpc->r_aliases = r_aliases; + cp = strpbrk(cp, " \t"); + if (cp != NULL) + *cp++ = '\0'; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &(r_aliases[aliases_size - 1])) + *q++ = cp; + else { + *errnop = ERANGE; + return -1; + } + + cp = strpbrk(cp, " \t"); + if (cp != NULL) + *cp++ = '\0'; + } + *q = NULL; + return 0; +} + +/* files backend implementation */ +static void +files_endstate(void *p) +{ + FILE * f; + + if (p == NULL) + return; + + f = ((struct files_state *)p)->fp; + if (f != NULL) + fclose(f); + + free(p); +} + +static int +files_rpcent(void *retval, void *mdata, va_list ap) +{ + char *name; + int number; + struct rpcent *rpc; + char *buffer; + size_t bufsize; + int *errnop; + + char *line; + size_t linesize; + char **aliases; + int aliases_size; + char **rp; + + struct files_state *st; + int rv; + int stayopen; + enum nss_lookup_type how; + + how = (enum nss_lookup_type)mdata; + switch (how) + { + case nss_lt_name: + name = va_arg(ap, char *); + break; + case nss_lt_id: + number = va_arg(ap, int); + break; + case nss_lt_all: + break; + default: + return (NS_NOTFOUND); + } + + rpc = va_arg(ap, struct rpcent *); + buffer = va_arg(ap, char *); + bufsize = va_arg(ap, size_t); + errnop = va_arg(ap, int *); + + *errnop = files_getstate(&st); + if (*errnop != 0) + return (NS_UNAVAIL); + + if (st->fp == NULL && (st->fp = fopen(RPCDB, "r")) == NULL) { + *errnop = errno; + return (NS_UNAVAIL); + } + + if (how == nss_lt_all) + stayopen = 1; + else { + rewind(st->fp); + stayopen = st->stayopen; + } + + do { + if ((line = fgetln(st->fp, &linesize)) == NULL) { + *errnop = errno; + rv = NS_RETURN; + break; + } + + if (bufsize <= linesize + _ALIGNBYTES + sizeof(char *)) { + *errnop = ERANGE; + rv = NS_RETURN; + break; + } + + aliases = (char **)_ALIGN(&buffer[linesize+1]); + aliases_size = (buffer + bufsize - + (char *)aliases)/sizeof(char *); + if (aliases_size < 1) { + *errnop = ERANGE; + rv = NS_RETURN; + break; + } + + memcpy(buffer, line, linesize); + buffer[linesize] = '\0'; + + rv = rpcent_unpack(buffer, rpc, aliases, aliases_size, errnop); + if (rv != 0) { + if (*errnop == 0) { + rv = NS_NOTFOUND; + continue; + } + else { + rv = NS_RETURN; + break; + } + } + + switch (how) + { + case nss_lt_name: + if (strcmp(rpc->r_name, name) == 0) + goto done; + for (rp = rpc->r_aliases; *rp != NULL; rp++) { + if (strcmp(*rp, name) == 0) + goto done; + } + rv = NS_NOTFOUND; + continue; +done: + rv = NS_SUCCESS; + break; + case nss_lt_id: + rv = (rpc->r_number == number) ? NS_SUCCESS : + NS_NOTFOUND; + break; + case nss_lt_all: + rv = NS_SUCCESS; + break; + } + + } while (!(rv & NS_TERMINATE)); + + if (!stayopen && st->fp!=NULL) { + fclose(st->fp); + st->fp = NULL; + } + + if ((rv == NS_SUCCESS) && (retval != NULL)) + *((struct rpcent **)retval) = rpc; + + return (rv); +} + +static int +files_setrpcent(void *retval, void *mdata, va_list ap) +{ + struct files_state *st; + int rv; + int f; + + rv = files_getstate(&st); + if (rv != 0) + return (NS_UNAVAIL); + + switch ((enum constants)mdata) + { + case SETRPCENT: + f = va_arg(ap,int); + if (st->fp == NULL) + st->fp = fopen(RPCDB, "r"); + else + rewind(st->fp); + st->stayopen |= f; + break; + case ENDRPCENT: + if (st->fp != NULL) { + fclose(st->fp); + st->fp = NULL; + } + st->stayopen = 0; + break; + default: + break; + } + + return (NS_UNAVAIL); +} + +/* nis backend implementation */ +#ifdef YP +static void +nis_endstate(void *p) +{ + if (p == NULL) + return; + + free(((struct nis_state *)p)->current); + free(p); +} + +static int +nis_rpcent(void *retval, void *mdata, va_list ap) +{ + char *name; + int number; + struct rpcent *rpc; + char *buffer; + size_t bufsize; + int *errnop; + + char **rp; + char **aliases; + int aliases_size; + + char *lastkey; + char *resultbuf; + int resultbuflen; + char buf[YPMAXRECORD + 2]; + + struct nis_state *st; + int rv; + enum nss_lookup_type how; + int no_name_active; + + how = (enum nss_lookup_type)mdata; + switch (how) + { + case nss_lt_name: + name = va_arg(ap, char *); + break; + case nss_lt_id: + number = va_arg(ap, int); + break; + case nss_lt_all: + break; + default: + return (NS_NOTFOUND); + } + + rpc = va_arg(ap, struct rpcent *); + buffer = va_arg(ap, char *); + bufsize = va_arg(ap, size_t); + errnop = va_arg(ap, int *); + + *errnop = nis_getstate(&st); + if (*errnop != 0) + return (NS_UNAVAIL); + + if (st->domain[0] == '\0') { + if (getdomainname(st->domain, sizeof(st->domain)) != 0) { + *errnop = errno; + return (NS_UNAVAIL); + } + } + + no_name_active = 0; + do { + switch (how) + { + case nss_lt_name: + if (!st->no_name_map) + { + snprintf(buf, sizeof buf, "%s", name); + rv = yp_match(st->domain, "rpc.byname", buf, + strlen(buf), &resultbuf, &resultbuflen); + + switch (rv) { + case 0: + break; + case YPERR_MAP: + st->stepping = 0; + no_name_active = 1; + how = nss_lt_all; + + rv = NS_NOTFOUND; + continue; + default: + rv = NS_NOTFOUND; + goto fin; + } + } else { + st->stepping = 0; + no_name_active = 1; + how = nss_lt_all; + + rv = NS_NOTFOUND; + continue; + } + break; + case nss_lt_id: + snprintf(buf, sizeof buf, "%d", number); + if (yp_match(st->domain, "rpc.bynumber", buf, + strlen(buf), &resultbuf, &resultbuflen)) { + rv = NS_NOTFOUND; + goto fin; + } + break; + case nss_lt_all: + if (!st->stepping) { + rv = yp_first(st->domain, "rpc.bynumber", + &st->current, + &st->currentlen, &resultbuf, + &resultbuflen); + if (rv) { + rv = NS_NOTFOUND; + goto fin; + } + st->stepping = 1; + } else { + lastkey = st->current; + rv = yp_next(st->domain, "rpc.bynumber", + st->current, + st->currentlen, &st->current, + &st->currentlen, + &resultbuf, &resultbuflen); + free(lastkey); + if (rv) { + st->stepping = 0; + rv = NS_NOTFOUND; + goto fin; + } + } + break; + } + + /* we need a room for additional \n symbol */ + if (bufsize <= resultbuflen + 1 + _ALIGNBYTES + + sizeof(char *)) { + *errnop = ERANGE; + rv = NS_RETURN; + break; + } + + aliases=(char **)_ALIGN(&buffer[resultbuflen+2]); + aliases_size = (buffer + bufsize - (char *)aliases) / + sizeof(char *); + if (aliases_size < 1) { + *errnop = ERANGE; + rv = NS_RETURN; + break; + } + + /* + * rpcent_unpack expects lines terminated with \n -- make it happy + */ + memcpy(buffer, resultbuf, resultbuflen); + buffer[resultbuflen] = '\n'; + buffer[resultbuflen+1] = '\0'; + free(resultbuf); + + if (rpcent_unpack(buffer, rpc, aliases, aliases_size, + errnop) != 0) { + if (*errnop == 0) + rv = NS_NOTFOUND; + else + rv = NS_RETURN; + } else { + if ((how == nss_lt_all) && (no_name_active != 0)) { + if (strcmp(rpc->r_name, name) == 0) + goto done; + for (rp = rpc->r_aliases; *rp != NULL; rp++) { + if (strcmp(*rp, name) == 0) + goto done; + } + rv = NS_NOTFOUND; + continue; +done: + rv = NS_SUCCESS; + } else + rv = NS_SUCCESS; + } + + } while (!(rv & NS_TERMINATE) && (how == nss_lt_all)); + +fin: + if ((rv == NS_SUCCESS) && (retval != NULL)) + *((struct rpcent **)retval) = rpc; + + return (rv); +} + +static int +nis_setrpcent(void *retval, void *mdata, va_list ap) +{ + struct nis_state *st; + int rv; + + rv = nis_getstate(&st); + if (rv != 0) + return (NS_UNAVAIL); + + switch ((enum constants)mdata) + { + case SETRPCENT: + case ENDRPCENT: + free(st->current); + st->current = NULL; + st->stepping = 0; + break; + default: + break; + } + + return (NS_UNAVAIL); +} +#endif + +#ifdef NS_CACHING +static int +rpc_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata) +{ + char *name; + int rpc; + + size_t desired_size, size; + enum nss_lookup_type lookup_type; + int res = NS_UNAVAIL; + + lookup_type = (enum nss_lookup_type)cache_mdata; + switch (lookup_type) { + case nss_lt_name: + name = va_arg(ap, char *); + + size = strlen(name); + desired_size = sizeof(enum nss_lookup_type) + size + 1; + if (desired_size > *buffer_size) { + res = NS_RETURN; + goto fin; + } + + memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type)); + memcpy(buffer + sizeof(enum nss_lookup_type), name, size + 1); + + res = NS_SUCCESS; + break; + case nss_lt_id: + rpc = va_arg(ap, int); + + desired_size = sizeof(enum nss_lookup_type) + sizeof(int); + if (desired_size > *buffer_size) { + res = NS_RETURN; + goto fin; + } + + memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type)); + memcpy(buffer + sizeof(enum nss_lookup_type), &rpc, + sizeof(int)); + + res = NS_SUCCESS; + break; + default: + /* should be unreachable */ + return (NS_UNAVAIL); + } + +fin: + *buffer_size = desired_size; + return (res); +} + +static int +rpc_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap, + void *cache_mdata) +{ + char *name; + int num; + struct rpcent *rpc; + char *orig_buf; + size_t orig_buf_size; + + struct rpcent new_rpc; + size_t desired_size, size, aliases_size; + char *p; + char **alias; + + switch ((enum nss_lookup_type)cache_mdata) { + case nss_lt_name: + name = va_arg(ap, char *); + break; + case nss_lt_id: + num = va_arg(ap, int); + break; + case nss_lt_all: + break; + default: + /* should be unreachable */ + return (NS_UNAVAIL); + } + + rpc = va_arg(ap, struct rpcent *); + orig_buf = va_arg(ap, char *); + orig_buf_size = va_arg(ap, size_t); + + desired_size = _ALIGNBYTES + sizeof(struct rpcent) + sizeof(char *); + if (rpc->r_name != NULL) + desired_size += strlen(rpc->r_name) + 1; + + if (rpc->r_aliases != NULL) { + aliases_size = 0; + for (alias = rpc->r_aliases; *alias; ++alias) { + desired_size += strlen(*alias) + 1; + ++aliases_size; + } + + desired_size += _ALIGNBYTES + (aliases_size + 1) * + sizeof(char *); + } + + if (*buffer_size < desired_size) { + /* this assignment is here for future use */ + *buffer_size = desired_size; + return (NS_RETURN); + } + + memcpy(&new_rpc, rpc, sizeof(struct rpcent)); + + *buffer_size = desired_size; + memset(buffer, 0, desired_size); + p = buffer + sizeof(struct rpcent) + sizeof(char *); + memcpy(buffer + sizeof(struct rpcent), &p, sizeof(char *)); + p = (char *)_ALIGN(p); + + if (new_rpc.r_name != NULL) { + size = strlen(new_rpc.r_name); + memcpy(p, new_rpc.r_name, size); + new_rpc.r_name = p; + p += size + 1; + } + + if (new_rpc.r_aliases != NULL) { + p = (char *)_ALIGN(p); + memcpy(p, new_rpc.r_aliases, sizeof(char *) * aliases_size); + new_rpc.r_aliases = (char **)p; + p += sizeof(char *) * (aliases_size + 1); + + for (alias = new_rpc.r_aliases; *alias; ++alias) { + size = strlen(*alias); + memcpy(p, *alias, size); + *alias = p; + p += size + 1; + } + } + + memcpy(buffer, &new_rpc, sizeof(struct rpcent)); + return (NS_SUCCESS); +} + +static int +rpc_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap, + void *cache_mdata) +{ + char *name; + int num; + struct rpcent *rpc; + char *orig_buf; + size_t orig_buf_size; + int *ret_errno; + + char *p; + char **alias; + + switch ((enum nss_lookup_type)cache_mdata) { + case nss_lt_name: + name = va_arg(ap, char *); + break; + case nss_lt_id: + num = va_arg(ap, int); + break; + case nss_lt_all: + break; + default: + /* should be unreachable */ + return (NS_UNAVAIL); + } + + rpc = va_arg(ap, struct rpcent *); + orig_buf = va_arg(ap, char *); + orig_buf_size = va_arg(ap, size_t); + ret_errno = va_arg(ap, int *); + + if (orig_buf_size < + buffer_size - sizeof(struct rpcent) - sizeof(char *)) { + *ret_errno = ERANGE; + return (NS_RETURN); + } + + memcpy(rpc, buffer, sizeof(struct rpcent)); + memcpy(&p, buffer + sizeof(struct rpcent), sizeof(char *)); + + orig_buf = (char *)_ALIGN(orig_buf); + memcpy(orig_buf, buffer + sizeof(struct rpcent) + sizeof(char *) + + _ALIGN(p) - (size_t)p, + buffer_size - sizeof(struct rpcent) - sizeof(char *) - + _ALIGN(p) + (size_t)p); + p = (char *)_ALIGN(p); + + NS_APPLY_OFFSET(rpc->r_name, orig_buf, p, char *); + if (rpc->r_aliases != NULL) { + NS_APPLY_OFFSET(rpc->r_aliases, orig_buf, p, char **); + + for (alias = rpc->r_aliases ; *alias; ++alias) + NS_APPLY_OFFSET(*alias, orig_buf, p, char *); + } + + if (retval != NULL) + *((struct rpcent **)retval) = rpc; + + return (NS_SUCCESS); +} + +NSS_MP_CACHE_HANDLING(rpc); +#endif /* NS_CACHING */ + + +/* get**_r functions implementation */ +static int +getrpcbyname_r(const char *name, struct rpcent *rpc, char *buffer, + size_t bufsize, struct rpcent **result) +{ +#ifdef NS_CACHING + static const nss_cache_info cache_info = + NS_COMMON_CACHE_INFO_INITIALIZER( + rpc, (void *)nss_lt_name, + rpc_id_func, rpc_marshal_func, rpc_unmarshal_func); +#endif + static const ns_dtab dtab[] = { + { NSSRC_FILES, files_rpcent, (void *)nss_lt_name }, +#ifdef YP + { NSSRC_NIS, nis_rpcent, (void *)nss_lt_name }, +#endif +#ifdef NS_CACHING + NS_CACHE_CB(&cache_info) +#endif + { NULL, NULL, NULL } + }; + int rv, ret_errno; + + ret_errno = 0; + *result = NULL; + rv = nsdispatch(result, dtab, NSDB_RPC, "getrpcbyname_r", defaultsrc, + name, rpc, buffer, bufsize, &ret_errno); + + if (rv == NS_SUCCESS) + return (0); + else + return (ret_errno); +} + +static int +getrpcbynumber_r(int number, struct rpcent *rpc, char *buffer, + size_t bufsize, struct rpcent **result) +{ +#ifdef NS_CACHING + static const nss_cache_info cache_info = + NS_COMMON_CACHE_INFO_INITIALIZER( + rpc, (void *)nss_lt_id, + rpc_id_func, rpc_marshal_func, rpc_unmarshal_func); +#endif + static const ns_dtab dtab[] = { + { NSSRC_FILES, files_rpcent, (void *)nss_lt_id }, +#ifdef YP + { NSSRC_NIS, nis_rpcent, (void *)nss_lt_id }, +#endif +#ifdef NS_CACHING + NS_CACHE_CB(&cache_info) +#endif + { NULL, NULL, NULL } + }; + int rv, ret_errno; + + ret_errno = 0; + *result = NULL; + rv = nsdispatch(result, dtab, NSDB_RPC, "getrpcbynumber_r", defaultsrc, + number, rpc, buffer, bufsize, &ret_errno); + + if (rv == NS_SUCCESS) + return (0); + else + return (ret_errno); +} + +static int +getrpcent_r(struct rpcent *rpc, char *buffer, size_t bufsize, + struct rpcent **result) +{ +#ifdef NS_CACHING + static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER( + rpc, (void *)nss_lt_all, + rpc_marshal_func, rpc_unmarshal_func); +#endif + static const ns_dtab dtab[] = { + { NSSRC_FILES, files_rpcent, (void *)nss_lt_all }, +#ifdef YP + { NSSRC_NIS, nis_rpcent, (void *)nss_lt_all }, +#endif +#ifdef NS_CACHING + NS_CACHE_CB(&cache_info) +#endif + { NULL, NULL, NULL } + }; + int rv, ret_errno; + + ret_errno = 0; + *result = NULL; + rv = nsdispatch(result, dtab, NSDB_RPC, "getrpcent_r", defaultsrc, + rpc, buffer, bufsize, &ret_errno); + + if (rv == NS_SUCCESS) + return (0); + else + return (ret_errno); +} + +/* get** wrappers for get**_r functions implementation */ +static void +rpcent_endstate(void *p) +{ + if (p == NULL) + return; + + free(((struct rpcent_state *)p)->buffer); + free(p); +} + +static int +wrap_getrpcbyname_r(union key key, struct rpcent *rpc, char *buffer, + size_t bufsize, struct rpcent **res) +{ + return (getrpcbyname_r(key.name, rpc, buffer, bufsize, res)); +} + +static int +wrap_getrpcbynumber_r(union key key, struct rpcent *rpc, char *buffer, + size_t bufsize, struct rpcent **res) +{ + return (getrpcbynumber_r(key.number, rpc, buffer, bufsize, res)); +} + +static int +wrap_getrpcent_r(union key key __unused, struct rpcent *rpc, char *buffer, + size_t bufsize, struct rpcent **res) +{ + return (getrpcent_r(rpc, buffer, bufsize, res)); +} + +static struct rpcent * +getrpc(int (*fn)(union key, struct rpcent *, char *, size_t, struct rpcent **), + union key key) +{ + int rv; + struct rpcent *res; + struct rpcent_state * st; + + rv=rpcent_getstate(&st); + if (rv != 0) { + errno = rv; + return NULL; + } + + if (st->buffer == NULL) { + st->buffer = malloc(RPCENT_STORAGE_INITIAL); + if (st->buffer == NULL) + return (NULL); + st->bufsize = RPCENT_STORAGE_INITIAL; + } + do { + rv = fn(key, &st->rpc, st->buffer, st->bufsize, &res); + if (res == NULL && rv == ERANGE) { + free(st->buffer); + if ((st->bufsize << 1) > RPCENT_STORAGE_MAX) { + st->buffer = NULL; + errno = ERANGE; + return (NULL); + } + st->bufsize <<= 1; + st->buffer = malloc(st->bufsize); + if (st->buffer == NULL) + return (NULL); + } + } while (res == NULL && rv == ERANGE); + if (rv != 0) + errno = rv; + + return (res); +} + +struct rpcent * +getrpcbyname(char *name) +{ + union key key; + + key.name = name; + + return (getrpc(wrap_getrpcbyname_r, key)); +} + +struct rpcent * +getrpcbynumber(int number) +{ + union key key; + + key.number = number; + + return (getrpc(wrap_getrpcbynumber_r, key)); +} + +struct rpcent * +getrpcent() +{ + union key key; + + key.number = 0; /* not used */ + + return (getrpc(wrap_getrpcent_r, key)); +} + +void +setrpcent(int stayopen) +{ +#ifdef NS_CACHING + static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER( + rpc, (void *)nss_lt_all, + NULL, NULL); +#endif + + static const ns_dtab dtab[] = { + { NSSRC_FILES, files_setrpcent, (void *)SETRPCENT }, +#ifdef YP + { NSSRC_NIS, nis_setrpcent, (void *)SETRPCENT }, +#endif +#ifdef NS_CACHING + NS_CACHE_CB(&cache_info) +#endif + { NULL, NULL, NULL } + }; + + (void)nsdispatch(NULL, dtab, NSDB_RPC, "setrpcent", defaultsrc, + stayopen); +} + +void +endrpcent() +{ +#ifdef NS_CACHING + static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER( + rpc, (void *)nss_lt_all, + NULL, NULL); +#endif + + static const ns_dtab dtab[] = { + { NSSRC_FILES, files_setrpcent, (void *)ENDRPCENT }, +#ifdef YP + { NSSRC_NIS, nis_setrpcent, (void *)ENDRPCENT }, +#endif +#ifdef NS_CACHING + NS_CACHE_CB(&cache_info) +#endif + { NULL, NULL, NULL } + }; + + (void)nsdispatch(NULL, dtab, NSDB_RPC, "endrpcent", defaultsrc); +} |