diff options
author | ume <ume@FreeBSD.org> | 2005-04-15 18:09:39 +0000 |
---|---|---|
committer | ume <ume@FreeBSD.org> | 2005-04-15 18:09:39 +0000 |
commit | 0e0eae8d50404b8ab351262f4842141ecad7c8bf (patch) | |
tree | 2fd0e9d2691a20c87c597508ff7d61a5874d6384 /lib/libc/net | |
parent | b4fe46443177bf4d6da9e3525d1cc487e38f0116 (diff) | |
download | FreeBSD-src-0e0eae8d50404b8ab351262f4842141ecad7c8bf.zip FreeBSD-src-0e0eae8d50404b8ab351262f4842141ecad7c8bf.tar.gz |
- add getserv{byname,byport,ent}_r for internal use within libc.
- make getserv{byname,byport,ent} thread-safe.
Reviewed by: gnn
Diffstat (limited to 'lib/libc/net')
-rw-r--r-- | lib/libc/net/getservbyname.c | 50 | ||||
-rw-r--r-- | lib/libc/net/getservbyport.c | 49 | ||||
-rw-r--r-- | lib/libc/net/getservent.c | 245 | ||||
-rw-r--r-- | lib/libc/net/netdb_private.h | 71 |
4 files changed, 288 insertions, 127 deletions
diff --git a/lib/libc/net/getservbyname.c b/lib/libc/net/getservbyname.c index 79769f6..5724d99 100644 --- a/lib/libc/net/getservbyname.c +++ b/lib/libc/net/getservbyname.c @@ -39,43 +39,51 @@ __FBSDID("$FreeBSD$"); #include <netdb.h> #include <string.h> +#include "netdb_private.h" -extern int _serv_stayopen; - -struct servent * -getservbyname(name, proto) - const char *name, *proto; +int +getservbyname_r(const char *name, const char *proto, struct servent *se, + struct servent_data *sed) { - struct servent *p; char **cp; + int error; #ifdef YP - extern char *___getservbyname_yp; - extern char *___getservbyproto_yp; - - ___getservbyname_yp = (char *)name; - ___getservbyproto_yp = (char *)proto; + sed->getservbyname_yp = (char *)name; + sed->getservbyproto_yp = (char *)proto; #endif - setservent(_serv_stayopen); - while ( (p = getservent()) ) { - if (strcmp(name, p->s_name) == 0) + setservent_r(sed->stayopen, sed); + while ((error = getservent_r(se, sed)) == 0) { + if (strcmp(name, se->s_name) == 0) goto gotname; - for (cp = p->s_aliases; *cp; cp++) + for (cp = se->s_aliases; *cp; cp++) if (strcmp(name, *cp) == 0) goto gotname; continue; gotname: - if (proto == 0 || strcmp(p->s_proto, proto) == 0) + if (proto == 0 || strcmp(se->s_proto, proto) == 0) break; } - if (!_serv_stayopen) - endservent(); + if (!sed->stayopen) + endservent_r(sed); #ifdef YP - ___getservbyname_yp = NULL; - ___getservbyproto_yp = NULL; + sed->getservbyname_yp = NULL; + sed->getservbyproto_yp = NULL; #endif - return (p); + return (error); +} + +struct servent * +getservbyname(const char *name, const char *proto) +{ + struct servdata *sd; + + if ((sd = _servdata_init()) == NULL) + return (NULL); + if (getservbyname_r(name, proto, &sd->serv, &sd->data) != 0) + return (NULL); + return (&sd->serv); } diff --git a/lib/libc/net/getservbyport.c b/lib/libc/net/getservbyport.c index 2efb60f..cb4bc10 100644 --- a/lib/libc/net/getservbyport.c +++ b/lib/libc/net/getservbyport.c @@ -39,38 +39,45 @@ __FBSDID("$FreeBSD$"); #include <netdb.h> #include <string.h> +#include "netdb_private.h" -extern int _serv_stayopen; - -struct servent * -getservbyport(port, proto) - int port; - const char *proto; +int +getservbyport_r(int port, const char *proto, struct servent *se, + struct servent_data *sed) { - struct servent *p; + int error; #ifdef YP - extern int ___getservbyport_yp; - extern char *___getservbyproto_yp; - - ___getservbyport_yp = port; - ___getservbyproto_yp = (char *)proto; + sed->getservbyport_yp = port; + sed->getservbyproto_yp = (char *)proto; #endif - setservent(_serv_stayopen); - while ( (p = getservent()) ) { - if (p->s_port != port) + setservent_r(sed->stayopen, sed); + while ((error = getservent_r(se, sed)) == 0) { + if (se->s_port != port) continue; - if (proto == 0 || strcmp(p->s_proto, proto) == 0) + if (proto == 0 || strcmp(se->s_proto, proto) == 0) break; } - if (!_serv_stayopen) - endservent(); + if (!sed->stayopen) + endservent_r(sed); #ifdef YP - ___getservbyport_yp = 0; - ___getservbyproto_yp = NULL; + sed->getservbyport_yp = 0; + sed->getservbyproto_yp = NULL; #endif - return (p); + return (error); +} + +struct servent * +getservbyport(int port, const char *proto) +{ + struct servdata *sd; + + if ((sd = _servdata_init()) == NULL) + return (NULL); + if (getservbyport_r(port, proto, &sd->serv, &sd->data) != 0) + return (NULL); + return (&sd->serv); } diff --git a/lib/libc/net/getservent.c b/lib/libc/net/getservent.c index 7e44235..e177256 100644 --- a/lib/libc/net/getservent.c +++ b/lib/libc/net/getservent.c @@ -48,41 +48,85 @@ __FBSDID("$FreeBSD$"); #include <rpc/rpc.h> #include <rpcsvc/yp_prot.h> #include <rpcsvc/ypclnt.h> -static int serv_stepping_yp = 0; #endif -#include "libc_private.h" +#include "namespace.h" +#include "reentrant.h" +#include "un-namespace.h" +#include "netdb_private.h" -#define MAXALIASES 35 +static struct servdata servdata; +static thread_key_t servdata_key; +static once_t servdata_init_once = ONCE_INITIALIZER; +static int servdata_thr_keycreated = 0; -static FILE *servf = NULL; -static char line[BUFSIZ+1]; -static struct servent serv; -static char *serv_aliases[MAXALIASES]; -int _serv_stayopen; +static void +servent_data_clear(struct servent_data *sed) +{ + if (sed->fp) { + fclose(sed->fp); + sed->fp = NULL; + } + if (sed->key) { + free(sed->key); + sed->key = NULL; + } +} -#ifdef YP -char *___getservbyname_yp = NULL; -char *___getservbyproto_yp = NULL; -int ___getservbyport_yp = 0; -static char *yp_domain = NULL; +static void +servdata_free(void *ptr) +{ + struct servdata *sd = ptr; + + if (sd == NULL) + return; + servent_data_clear(&sd->data); + free(sd); +} + +static void +servdata_keycreate(void) +{ + servdata_thr_keycreated = + (thr_keycreate(&servdata_key, servdata_free) == 0); +} +struct servdata * +_servdata_init(void) +{ + struct servdata *sd; + + if (thr_main() != 0) + return (&servdata); + if (thr_once(&servdata_init_once, servdata_keycreate) != 0 || + !servdata_thr_keycreated) + return (NULL); + if ((sd = thr_getspecific(servdata_key)) != NULL) + return (sd); + if ((sd = calloc(1, sizeof(*sd))) == NULL) + return (NULL); + if (thr_setspecific(servdata_key, sd) == 0) + return (sd); + free(sd); + return (NULL); +} + +#ifdef YP static int -_getservbyport_yp(line) - char *line; +_getservbyport_yp(struct servent_data *sed) { char *result; int resultlen; char buf[YPMAXRECORD + 2]; int rv; - snprintf(buf, sizeof(buf), "%d/%s", ntohs(___getservbyport_yp), - ___getservbyproto_yp); + snprintf(buf, sizeof(buf), "%d/%s", + ntohs(sed->getservbyport_yp), sed->getservbyproto_yp); - ___getservbyport_yp = 0; - ___getservbyproto_yp = NULL; + sed->getservbyport_yp = 0; + sed->getservbyproto_yp = NULL; - if(!yp_domain) { - if(yp_get_default_domain(&yp_domain)) + if (!sed->yp_domain) { + if (yp_get_default_domain(&sed->yp_domain)) return (0); } @@ -95,10 +139,10 @@ _getservbyport_yp(line) * possibilities here: if there is no services.byport map, we try * services.byname instead. */ - if ((rv = yp_match(yp_domain, "services.byport", buf, strlen(buf), + if ((rv = yp_match(sed->yp_domain, "services.byport", buf, strlen(buf), &result, &resultlen))) { if (rv == YPERR_MAP) { - if (yp_match(yp_domain, "services.byname", buf, + if (yp_match(sed->yp_domain, "services.byname", buf, strlen(buf), &result, &resultlen)) return(0); } else @@ -106,80 +150,77 @@ _getservbyport_yp(line) } /* getservent() expects lines terminated with \n -- make it happy */ - snprintf(line, BUFSIZ, "%.*s\n", resultlen, result); + snprintf(sed->line, BUFSIZ, "%.*s\n", resultlen, result); free(result); return(1); } static int -_getservbyname_yp(line) - char *line; +_getservbyname_yp(struct servent_data *sed) { char *result; int resultlen; char buf[YPMAXRECORD + 2]; - if(!yp_domain) { - if(yp_get_default_domain(&yp_domain)) + if(!sed->yp_domain) { + if(yp_get_default_domain(&sed->yp_domain)) return (0); } - snprintf(buf, sizeof(buf), "%s/%s", ___getservbyname_yp, - ___getservbyproto_yp); + snprintf(buf, sizeof(buf), "%s/%s", sed->getservbyname_yp, + sed->getservbyproto_yp); - ___getservbyname_yp = 0; - ___getservbyproto_yp = NULL; + sed->getservbyname_yp = 0; + sed->getservbyproto_yp = NULL; - if (yp_match(yp_domain, "services.byname", buf, strlen(buf), - &result, &resultlen)) { + if (yp_match(sed->yp_domain, "services.byname", buf, strlen(buf), + &result, &resultlen)) { return(0); } /* getservent() expects lines terminated with \n -- make it happy */ - snprintf(line, BUFSIZ, "%.*s\n", resultlen, result); + snprintf(sed->line, BUFSIZ, "%.*s\n", resultlen, result); free(result); return(1); } static int -_getservent_yp(line) - char *line; +_getservent_yp(struct servent_data *sed) { - static char *key = NULL; - static int keylen; char *lastkey, *result; int resultlen; int rv; - if(!yp_domain) { - if(yp_get_default_domain(&yp_domain)) + if (!sed->yp_domain) { + if (yp_get_default_domain(&sed->yp_domain)) return (0); } - if (!serv_stepping_yp) { - if (key) - free(key); - if ((rv = yp_first(yp_domain, "services.byname", &key, &keylen, - &result, &resultlen))) { - serv_stepping_yp = 0; + if (!sed->stepping_yp) { + if (sed->key) + free(sed->key); + rv = yp_first(sed->yp_domain, "services.byname", &sed->key, + &sed->keylen, &result, &resultlen); + if (rv) { + sed->stepping_yp = 0; return(0); } - serv_stepping_yp = 1; + sed->stepping_yp = 1; } else { - lastkey = key; - rv = yp_next(yp_domain, "services.byname", key, keylen, &key, - &keylen, &result, &resultlen); + lastkey = sed->key; + rv = yp_next(sed->yp_domain, "services.byname", sed->key, + sed->keylen, &sed->key, &sed->keylen, &result, &resultlen); free(lastkey); if (rv) { - serv_stepping_yp = 0; + sed->stepping_yp = 0; return (0); } } /* getservent() expects lines terminated with \n -- make it happy */ - snprintf(line, BUFSIZ, "%.*s\n", resultlen, result); + snprintf(sed->line, BUFSIZ, "%.*s\n", resultlen, result); free(result); @@ -188,55 +229,54 @@ _getservent_yp(line) #endif void -setservent(f) - int f; +setservent_r(int f, struct servent_data *sed) { - if (servf == NULL) - servf = fopen(_PATH_SERVICES, "r" ); + if (sed->fp == NULL) + sed->fp = fopen(_PATH_SERVICES, "r"); else - rewind(servf); - _serv_stayopen |= f; + rewind(sed->fp); + sed->stayopen |= f; } void -endservent() +endservent_r(struct servent_data *sed) { - if (servf) { - fclose(servf); - servf = NULL; - } - _serv_stayopen = 0; + servent_data_clear(sed); + sed->stayopen = 0; + sed->stepping_yp = 0; + sed->yp_domain = NULL; } -struct servent * -getservent() +int +getservent_r(struct servent *se, struct servent_data *sed) { char *p; - char *cp, **q; + char *cp, **q, *endp; + long l; #ifdef YP - if (serv_stepping_yp && _getservent_yp(line)) { - p = (char *)&line; + if (sed->stepping_yp && _getservent_yp(sed)) { + p = sed->line; goto unpack; } tryagain: #endif - if (servf == NULL && (servf = fopen(_PATH_SERVICES, "r" )) == NULL) - return (NULL); + if (sed->fp == NULL && (sed->fp = fopen(_PATH_SERVICES, "r")) == NULL) + return (-1); again: - if ((p = fgets(line, BUFSIZ, servf)) == NULL) - return (NULL); + if ((p = fgets(sed->line, BUFSIZ, sed->fp)) == NULL) + return (-1); #ifdef YP if (*p == '+' && _yp_check(NULL)) { - if (___getservbyname_yp != NULL) { - if (!_getservbyname_yp(line)) + if (sed->getservbyname_yp != NULL) { + if (!_getservbyname_yp(sed)) goto tryagain; } - else if (___getservbyport_yp != 0) { - if (!_getservbyport_yp(line)) + else if (sed->getservbyport_yp != 0) { + if (!_getservbyport_yp(sed)) goto tryagain; } - else if (!_getservent_yp(line)) + else if (!_getservent_yp(sed)) goto tryagain; } unpack: @@ -246,7 +286,7 @@ unpack: cp = strpbrk(p, "#\n"); if (cp != NULL) *cp = '\0'; - serv.s_name = p; + se->s_name = p; p = strpbrk(p, " \t"); if (p == NULL) goto again; @@ -257,9 +297,12 @@ unpack: if (cp == NULL) goto again; *cp++ = '\0'; - serv.s_port = htons((u_short)atoi(p)); - serv.s_proto = cp; - q = serv.s_aliases = serv_aliases; + l = strtol(p, &endp, 10); + if (endp == p || *endp != '\0' || l < 0 || l > USHRT_MAX) + goto again; + se->s_port = htons((in_port_t)l); + se->s_proto = cp; + q = se->s_aliases = sed->aliases; cp = strpbrk(cp, " \t"); if (cp != NULL) *cp++ = '\0'; @@ -268,12 +311,44 @@ unpack: cp++; continue; } - if (q < &serv_aliases[MAXALIASES - 1]) + if (q < &sed->aliases[SERVENT_MAXALIASES - 1]) *q++ = cp; cp = strpbrk(cp, " \t"); if (cp != NULL) *cp++ = '\0'; } *q = NULL; - return (&serv); + return (0); +} + +void +setservent(int f) +{ + struct servdata *sd; + + if ((sd = _servdata_init()) == NULL) + return; + setservent_r(f, &sd->data); +} + +void +endservent(void) +{ + struct servdata *sd; + + if ((sd = _servdata_init()) == NULL) + return; + endservent_r(&sd->data); +} + +struct servent * +getservent(void) +{ + struct servdata *sd; + + if ((sd = _servdata_init()) == NULL) + return (NULL); + if (getservent_r(&sd->serv, &sd->data) != 0) + return (NULL); + return (&sd->serv); } diff --git a/lib/libc/net/netdb_private.h b/lib/libc/net/netdb_private.h new file mode 100644 index 0000000..3795b3a --- /dev/null +++ b/lib/libc/net/netdb_private.h @@ -0,0 +1,71 @@ +/*- + * Copyright (C) 2005 The FreeBSD Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _NETDB_PRIVATE_H_ +#define _NETDB_PRIVATE_H_ + +#include <stdio.h> /* XXX: for BUFSIZ */ + +#define SERVENT_MAXALIASES 35 + +struct servent_data { + FILE *fp; + char *aliases[SERVENT_MAXALIASES]; + int stayopen; + char line[BUFSIZ + 1]; +#ifdef YP + int stepping_yp; + char *getservbyname_yp; + char *getservbyproto_yp; + int getservbyport_yp; + char *yp_domain; + char *key; + int keylen; +#endif +}; + +struct servdata { + struct servent serv; + struct servent_data data; +}; + +#define endservent_r _endservent_r +#define getservbyname_r _getservbyname_r +#define getservbyport_r _getservbyport_r +#define getservent_r _getservent_r +#define setservent_r _setservent_r + +struct servdata *_servdata_init(void); +void endservent_r(struct servent_data *); +int getservbyname_r(const char *, const char *, struct servent *, + struct servent_data *); +int getservbyport_r(int, const char *, struct servent *, + struct servent_data *); +int getservent_r(struct servent *, struct servent_data *); +void setservent_r(int, struct servent_data *); + +#endif /* _NETDB_PRIVATE_H_ */ |