diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2004-10-17 20:24:24 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2004-10-17 20:24:24 +0000 |
commit | 6119135c871cdb14d2c537be99ec398e13edf027 (patch) | |
tree | 0dd5c7c99caa44c2ea5e7debe0d7beb2abf79729 | |
parent | ee9ebb877e4b54f13e03b0aea8679e04c928043f (diff) |
Reentrant versions of getprotoent(3) and getservent(3). Adapted from
changes in NetBSD by Christos. OK otto@
-rw-r--r-- | include/netdb.h | 48 | ||||
-rw-r--r-- | lib/libc/net/getproto.c | 31 | ||||
-rw-r--r-- | lib/libc/net/getprotoent.3 | 59 | ||||
-rw-r--r-- | lib/libc/net/getprotoent.c | 121 | ||||
-rw-r--r-- | lib/libc/net/getprotoname.c | 32 | ||||
-rw-r--r-- | lib/libc/net/getservbyname.c | 33 | ||||
-rw-r--r-- | lib/libc/net/getservbyport.c | 31 | ||||
-rw-r--r-- | lib/libc/net/getservent.3 | 59 | ||||
-rw-r--r-- | lib/libc/net/getservent.c | 122 |
9 files changed, 393 insertions, 143 deletions
diff --git a/include/netdb.h b/include/netdb.h index 78cadbefff0..84b120a4cc7 100644 --- a/include/netdb.h +++ b/include/netdb.h @@ -1,4 +1,4 @@ -/* $OpenBSD: netdb.h,v 1.19 2004/04/14 07:06:15 itojun Exp $ */ +/* $OpenBSD: netdb.h,v 1.20 2004/10/17 20:24:23 millert Exp $ */ /* * ++Copyright++ 1980, 1983, 1988, 1993 @@ -237,11 +237,37 @@ struct rrsetinfo { struct rdatainfo *rri_sigs; /* individual signatures */ }; +#ifndef POSIX_SOURCE +struct __sFILE; + +struct servent_data { + struct __sFILE *fp; + char **aliases; + int maxaliases; + int stayopen; + char *line; +}; + +struct protoent_data { + struct __sFILE *fp; + char **aliases; + int maxaliases; + int stayopen; + char *line; +}; +#endif + __BEGIN_DECLS void endhostent(void); void endnetent(void); void endprotoent(void); +#ifndef POSIX_SOURCE +void endprotoent_r(struct protoent_data *); +#endif void endservent(void); +#ifndef POSIX_SOURCE +void endservent_r(struct servent_data *); +#endif struct hostent *gethostbyaddr(const char *, int, int); struct hostent *gethostbyname(const char *); struct hostent *gethostbyname2(const char *, int); @@ -252,16 +278,36 @@ struct netent *getnetent(void); struct protoent *getprotobyname(const char *); struct protoent *getprotobynumber(int); struct protoent *getprotoent(void); +#ifndef POSIX_SOURCE +struct protoent *getprotobyname_r(const char *, struct protoent *, + struct protoent_data *); +struct protoent *getprotobynumber_r(int, struct protoent *, + struct protoent_data *); +struct protoent *getprotoent_r(struct protoent *, struct protoent_data *); +#endif struct servent *getservbyname(const char *, const char *); struct servent *getservbyport(int, const char *); struct servent *getservent(void); +#ifndef POSIX_SOURCE +struct servent *getservbyname_r(const char *, const char *, struct servent *, + struct servent_data *); +struct servent *getservbyport_r(int, const char *, struct servent *, + struct servent_data *); +struct servent *getservent_r(struct servent *, struct servent_data *); +#endif void herror(const char *); const char *hstrerror(int); void sethostent(int); /* void sethostfile(const char *); */ void setnetent(int); void setprotoent(int); +#ifndef POSIX_SOURCE +void setprotoent_r(int, struct protoent_data *); +#endif void setservent(int); +#ifndef POSIX_SOURCE +void setservent_r(int, struct servent_data *); +#endif int getaddrinfo(const char *, const char *, const struct addrinfo *, struct addrinfo **); diff --git a/lib/libc/net/getproto.c b/lib/libc/net/getproto.c index dee089d5c2c..3f05a93cce6 100644 --- a/lib/libc/net/getproto.c +++ b/lib/libc/net/getproto.c @@ -28,24 +28,33 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: getproto.c,v 1.4 2003/06/02 20:18:35 millert Exp $"; +static char rcsid[] = "$OpenBSD: getproto.c,v 1.5 2004/10/17 20:24:23 millert Exp $"; #endif /* LIBC_SCCS and not lint */ #include <netdb.h> - -extern int _proto_stayopen; +#include <stdio.h> struct protoent * -getprotobynumber(proto) - register int proto; +getprotobynumber_r(int num, struct protoent *pe, struct protoent_data *pd) { - register struct protoent *p; + struct protoent *p; - setprotoent(_proto_stayopen); - while ((p = getprotoent())) - if (p->p_proto == proto) + setprotoent_r(pd->stayopen, pd); + while ((p = getprotoent_r(pe, pd))) + if (p->p_proto == num) break; - if (!_proto_stayopen) - endprotoent(); + if (!pd->stayopen && pd->fp != NULL) { + (void)fclose(pd->fp); + pd->fp = NULL; + } return (p); } + +struct protoent * +getprotobynumber(int num) +{ + extern struct protoent_data _protoent_data; + static struct protoent proto; + + return getprotobynumber_r(num, &proto, &_protoent_data); +} diff --git a/lib/libc/net/getprotoent.3 b/lib/libc/net/getprotoent.3 index 5c41e6fb7cd..2497f9f7cab 100644 --- a/lib/libc/net/getprotoent.3 +++ b/lib/libc/net/getprotoent.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: getprotoent.3,v 1.10 2004/02/01 19:45:00 nordin Exp $ +.\" $OpenBSD: getprotoent.3,v 1.11 2004/10/17 20:24:23 millert Exp $ .\" .\" Copyright (c) 1983, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -27,28 +27,43 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd June 4, 1993 +.Dd October 13, 2004 .Dt GETPROTOENT 3 .Os .Sh NAME .Nm getprotoent , +.Nm getprotoent_r , .Nm getprotobynumber , +.Nm getprotobynumber_r , .Nm getprotobyname , +.Nm getprotobyname_r , .Nm setprotoent , -.Nm endprotoent +.Nm setprotoent_r , +.Nm endprotoent , +.Nm endprotoent_r .Nd get protocol entry .Sh SYNOPSIS .Fd #include <netdb.h> .Ft struct protoent * .Fn getprotoent "void" .Ft struct protoent * +.Fn getprotoent_r "struct protoent *protoent" "struct protoent_data *protoent_data" +.Ft struct protoent * .Fn getprotobyname "const char *name" .Ft struct protoent * +.Fn getprotobyname_r "const char *name" "struct protoent *protoent" "struct protoent_data *protoent_data" +.Ft struct protoent * .Fn getprotobynumber "int proto" +.Ft struct protoent * +.Fn getprotobynumber_r "int proto" "struct protoent *protoent" "struct protoent_data *protoent_data" .Ft void .Fn setprotoent "int stayopen" .Ft void +.Fn setprotoent_r "int stayopen" "struct protoent_data *protoent_data" +.Ft void .Fn endprotoent "void" +.Ft void +.Fn endprotoent_r "void" "struct protoent_data *protoent_data" .Sh DESCRIPTION The .Fn getprotoent , @@ -104,6 +119,30 @@ functions sequentially search from the beginning of the file until a matching protocol name or protocol number is found, or until .Dv EOF is encountered. +.Pp +The +.Fn getprotoent_r , +.Fn getprotobyport_r , +.Fn getprotobyname_r , +.Fn setprotoent_r , +and +.Fn endprotoent_r +functions are reentrant versions of the above functions that take a +pointer to a +.Fa protoent_data +structure which is used to store state information. +The structure must be zero-filled before it is used +and should be considered opaque for the sake of portability. +.Pp +The +.Fn getprotoent_r , +.Fn getprotobyport_r , +and +.Fn getprotobyname_r +functions +also take a pointer to a +.Fa protoent +structure which is used to store the results of the database lookup. .Sh RETURN VALUES Null pointer (0) returned on .Dv EOF @@ -124,7 +163,17 @@ and .Fn endprotoent functions appeared in .Bx 4.2 . +.Pp +The +.Fn getprotoent_r , +.Fn getprotobyport_r , +.Fn getprotobyname_r , +.Fn setprotoent_r , +and +.Fn endprotoent_r +functions appeared in +.Ox 3.7 . .Sh BUGS -These functions use a static data space; if the data is needed for future use, -it should be copied before any subsequent calls overwrite it. +The non-reentrant functions use a static data space; if the data is needed +for future use, it should be copied before any subsequent calls overwrite it. Only the Internet protocols are currently understood. diff --git a/lib/libc/net/getprotoent.c b/lib/libc/net/getprotoent.c index b2bdd2e1643..f3327db9bd9 100644 --- a/lib/libc/net/getprotoent.c +++ b/lib/libc/net/getprotoent.c @@ -28,69 +28,68 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: getprotoent.c,v 1.5 2003/06/02 20:18:35 millert Exp $"; +static char rcsid[] = "$OpenBSD: getprotoent.c,v 1.6 2004/10/17 20:24:23 millert Exp $"; #endif /* LIBC_SCCS and not lint */ #include <sys/types.h> #include <sys/socket.h> + +#include <errno.h> #include <netdb.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#define MAXALIASES 35 - -static FILE *protof = NULL; -static char line[BUFSIZ+1]; -static struct protoent proto; -static char *proto_aliases[MAXALIASES]; -int _proto_stayopen; - void -setprotoent(f) - int f; +setprotoent_r(int f, struct protoent_data *pd) { - if (protof == NULL) - protof = fopen(_PATH_PROTOCOLS, "r" ); + if (pd->fp == NULL) + pd->fp = fopen(_PATH_PROTOCOLS, "r" ); else - rewind(protof); - _proto_stayopen |= f; + rewind(pd->fp); + pd->stayopen |= f; } void -endprotoent() +endprotoent_r(struct protoent_data *pd) { - if (protof) { - fclose(protof); - protof = NULL; + if (pd->fp) { + fclose(pd->fp); + pd->fp = NULL; } - _proto_stayopen = 0; + free(pd->aliases); + pd->aliases = NULL; + pd->maxaliases = 0; + free(pd->line); + pd->line = NULL; + pd->stayopen = 0; } struct protoent * -getprotoent() +getprotoent_r(struct protoent *pe, struct protoent_data *pd) { char *p, *cp, **q, *endp; - long l; size_t len; + long l; + int serrno; - if (protof == NULL && (protof = fopen(_PATH_PROTOCOLS, "r" )) == NULL) + if (pd->fp == NULL && (pd->fp = fopen(_PATH_PROTOCOLS, "r" )) == NULL) return (NULL); again: - if ((p = fgetln(protof, &len)) == NULL) + if ((p = fgetln(pd->fp, &len)) == NULL) return (NULL); + if (len == 0 || *p == '#' || *p == '\n') + goto again; if (p[len-1] == '\n') len--; - if (len >= sizeof(line) || len == 0) - goto again; - p = memcpy(line, p, len); - line[len] = '\0'; - if (*p == '#') - goto again; - if ((cp = strchr(p, '#')) != NULL) - *cp = '\0'; - proto.p_name = p; - cp = strpbrk(p, " \t"); + if ((cp = memchr(p, '#', len)) != NULL) + len = cp - p; + cp = realloc(pd->line, len + 1); + if (cp == NULL) + return (NULL); + pd->line = pe->p_name = memcpy(cp, p, len); + cp[len] = '\0'; + cp = strpbrk(cp, " \t"); if (cp == NULL) goto again; *cp++ = '\0'; @@ -102,8 +101,18 @@ again: l = strtol(cp, &endp, 10); if (endp == cp || *endp != '\0' || l < 0 || l >= INT_MAX) goto again; - proto.p_proto = l; - q = proto.p_aliases = proto_aliases; + pe->p_proto = l; + if (pd->aliases == NULL) { + pd->maxaliases = 5; + pd->aliases = malloc(pd->maxaliases * sizeof(char *)); + if (pd->aliases == NULL) { + serrno = errno; + endprotoent_r(pd); + errno = serrno; + return (NULL); + } + } + q = pe->p_aliases = pd->aliases; if (p != NULL) { cp = p; while (cp && *cp) { @@ -111,13 +120,47 @@ again: cp++; continue; } - if (q < &proto_aliases[MAXALIASES - 1]) - *q++ = cp; + if (q == &pe->p_aliases[pd->maxaliases - 1]) { + p = realloc(pe->p_aliases, + 2 * pd->maxaliases * sizeof(char *)); + if (p == NULL) { + serrno = errno; + endprotoent_r(pd); + errno = serrno; + return (NULL); + } + pd->maxaliases *= 2; + q = (char **)p + (q - pe->p_aliases); + pe->p_aliases = pd->aliases = (char **)p; + } + *q++ = cp; cp = strpbrk(cp, " \t"); if (cp != NULL) *cp++ = '\0'; } } *q = NULL; - return (&proto); + return (pe); +} + +struct protoent_data _protoent_data; /* shared with getproto{,name}.c */ + +void +setprotoent(int f) +{ + setprotoent_r(f, &_protoent_data); +} + +void +endprotoent(void) +{ + endprotoent_r(&_protoent_data); +} + +struct protoent * +getprotoent(void) +{ + static struct protoent proto; + + return getprotoent_r(&proto, &_protoent_data); } diff --git a/lib/libc/net/getprotoname.c b/lib/libc/net/getprotoname.c index 4742a60a04b..429304e7a1c 100644 --- a/lib/libc/net/getprotoname.c +++ b/lib/libc/net/getprotoname.c @@ -28,23 +28,22 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: getprotoname.c,v 1.4 2003/06/02 20:18:35 millert Exp $"; +static char rcsid[] = "$OpenBSD: getprotoname.c,v 1.5 2004/10/17 20:24:23 millert Exp $"; #endif /* LIBC_SCCS and not lint */ #include <netdb.h> +#include <stdio.h> #include <string.h> -extern int _proto_stayopen; - struct protoent * -getprotobyname(name) - register const char *name; +getprotobyname_r(const char *name, struct protoent *pe, + struct protoent_data *pd) { - register struct protoent *p; - register char **cp; + struct protoent *p; + char **cp; - setprotoent(_proto_stayopen); - while ((p = getprotoent())) { + setprotoent_r(pd->stayopen, pd); + while ((p = getprotoent_r(pe, pd))) { if (strcmp(p->p_name, name) == 0) break; for (cp = p->p_aliases; *cp != 0; cp++) @@ -52,7 +51,18 @@ getprotobyname(name) goto found; } found: - if (!_proto_stayopen) - endprotoent(); + if (!pd->stayopen && pd->fp != NULL) { + fclose(pd->fp); + pd->fp = NULL; + } return (p); } + +struct protoent * +getprotobyname(const char *name) +{ + extern struct protoent_data _protoent_data; + static struct protoent proto; + + return getprotobyname_r(name, &proto, &_protoent_data); +} diff --git a/lib/libc/net/getservbyname.c b/lib/libc/net/getservbyname.c index c5f42a7b9cf..597c42497fc 100644 --- a/lib/libc/net/getservbyname.c +++ b/lib/libc/net/getservbyname.c @@ -28,27 +28,22 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: getservbyname.c,v 1.7 2004/09/16 03:16:50 deraadt Exp $"; +static char rcsid[] = "$OpenBSD: getservbyname.c,v 1.8 2004/10/17 20:24:23 millert Exp $"; #endif /* LIBC_SCCS and not lint */ #include <netdb.h> +#include <stdio.h> #include <string.h> -#include "thread_private.h" - -extern int _serv_stayopen; - -_THREAD_PRIVATE_MUTEX(getservbyname_r); struct servent * getservbyname_r(const char *name, const char *proto, struct servent *se, - char *buf, int buflen) + struct servent_data *sd) { struct servent *p; char **cp; - _THREAD_PRIVATE_MUTEX_LOCK(getservbyname_r); - setservent(_serv_stayopen); - while ((p = getservent())) { + setservent_r(sd->stayopen, sd); + while ((p = getservent_r(se, sd))) { if (strcmp(name, p->s_name) == 0) goto gotname; for (cp = p->s_aliases; *cp; cp++) @@ -59,22 +54,18 @@ gotname: if (proto == 0 || strcmp(p->s_proto, proto) == 0) break; } - if (!_serv_stayopen) - endservent(); - _THREAD_PRIVATE_MUTEX_UNLOCK(getservbyname_r); + if (!sd->stayopen && sd->fp != NULL) { + fclose(sd->fp); + sd->fp = NULL; + } return (p); } struct servent * getservbyname(const char *name, const char *proto) { - _THREAD_PRIVATE_KEY(getservbyname); - static char buf[4096]; - char *bufp = (char*)_THREAD_PRIVATE(getservbyname, buf, NULL); + extern struct servent_data _servent_data; + static struct servent serv; - if (bufp == NULL) - return (NULL); - return getservbyname_r(name, proto, (struct servent*) bufp, - bufp + sizeof(struct servent), - sizeof buf - sizeof(struct servent) ); + return (getservbyname_r(name, proto, &serv, &_servent_data)); } diff --git a/lib/libc/net/getservbyport.c b/lib/libc/net/getservbyport.c index 992a77d638b..e8b8efc5049 100644 --- a/lib/libc/net/getservbyport.c +++ b/lib/libc/net/getservbyport.c @@ -28,29 +28,38 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: getservbyport.c,v 1.4 2003/06/02 20:18:35 millert Exp $"; +static char rcsid[] = "$OpenBSD: getservbyport.c,v 1.5 2004/10/17 20:24:23 millert Exp $"; #endif /* LIBC_SCCS and not lint */ #include <netdb.h> +#include <stdio.h> #include <string.h> -extern int _serv_stayopen; - struct servent * -getservbyport(port, proto) - int port; - const char *proto; +getservbyport_r(int port, const char *proto, struct servent *se, + struct servent_data *sd) { - register struct servent *p; + struct servent *p; - setservent(_serv_stayopen); - while ((p = getservent())) { + setservent_r(sd->stayopen, sd); + while ((p = getservent_r(se, sd))) { if (p->s_port != port) continue; if (proto == 0 || strcmp(p->s_proto, proto) == 0) break; } - if (!_serv_stayopen) - endservent(); + if (!sd->stayopen && sd->fp != NULL) { + fclose(sd->fp); + sd->fp = NULL; + } return (p); } + +struct servent * +getservbyport(int port, const char *proto) +{ + extern struct servent_data _servent_data; + static struct servent serv; + + return (getservbyport_r(port, proto, &serv, &_servent_data)); +} diff --git a/lib/libc/net/getservent.3 b/lib/libc/net/getservent.3 index af75f5037bf..f5294b8f708 100644 --- a/lib/libc/net/getservent.3 +++ b/lib/libc/net/getservent.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: getservent.3,v 1.13 2003/12/30 10:35:36 jmc Exp $ +.\" $OpenBSD: getservent.3,v 1.14 2004/10/17 20:24:23 millert Exp $ .\" .\" Copyright (c) 1983, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -27,28 +27,43 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd January 12, 1994 +.Dd October 13, 2004 .Dt GETSERVENT 3 .Os .Sh NAME .Nm getservent , +.Nm getservent_r , .Nm getservbyport , +.Nm getservbyport_r , .Nm getservbyname , +.Nm getservbyname_r , .Nm setservent , -.Nm endservent +.Nm setservent_r , +.Nm endservent , +.Nm endservent_r .Nd get service entry .Sh SYNOPSIS .Fd #include <netdb.h> .Ft struct servent * .Fn getservent "void" .Ft struct servent * +.Fn getservent_r "struct servent *servent" "struct servent_data *servent_data" +.Ft struct servent * .Fn getservbyname "const char *name" "const char *proto" .Ft struct servent * +.Fn getservbyname_r "const char *name" "const char *proto" "struct servent *servent" "struct servent_data *servent_data" +.Ft struct servent * .Fn getservbyport "int port" "const char *proto" +.Ft struct servent * +.Fn getservbyport_r "int port" "const char *proto" "struct servent *servent" "struct servent_data *servent_data" .Ft void .Fn setservent "int stayopen" .Ft void +.Fn setservent_r "int stayopen" "struct servent_data *servent_data" +.Ft void .Fn endservent "void" +.Ft void +.Fn endservent_r "struct servent_data *servent_data" .Sh DESCRIPTION The .Fn getservent , @@ -110,6 +125,30 @@ is found, or until is encountered. If a protocol name is also supplied (non-null), searches must also match the protocol. +.Pp +The +.Fn getservent_r , +.Fn getservbyport_r , +.Fn getservbyname_r , +.Fn setservent_r , +and +.Fn endservent_r +functions are reentrant versions of the above functions that take a +pointer to a +.Fa servent_data +structure which is used to store state information. +The structure must be zero-filled before it is used +and should be considered opaque for the sake of portability. +.Pp +The +.Fn getservent_r , +.Fn getservbyport_r , +and +.Fn getservbyname_r +functions +also take a pointer to a +.Fa servent +structure which is used to store the results of the database lookup. .Sh FILES .Bl -tag -width /etc/services -compact .It Pa /etc/services @@ -130,8 +169,18 @@ The and .Fn endservent functions appeared in +.Pp .Bx 4.2 . +The +.Fn getservent_r , +.Fn getservbyport_r , +.Fn getservbyname_r , +.Fn setservent_r , +and +.Fn endservent_r +functions appeared in +.Ox 3.7 . .Sh BUGS -These functions use static data storage; if the data is needed for future use, -it should be copied before any subsequent calls overwrite it. +The non-reentrant functions use static data storage; if the data is needed +for future use, it should be copied before any subsequent calls overwrite it. Expecting port numbers to fit in a 32-bit quantity is probably naive. diff --git a/lib/libc/net/getservent.c b/lib/libc/net/getservent.c index 475e25a1f89..9cf53774d6a 100644 --- a/lib/libc/net/getservent.c +++ b/lib/libc/net/getservent.c @@ -28,68 +28,68 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: getservent.c,v 1.7 2004/09/16 03:13:22 deraadt Exp $"; +static char rcsid[] = "$OpenBSD: getservent.c,v 1.8 2004/10/17 20:24:23 millert Exp $"; #endif /* LIBC_SCCS and not lint */ #include <sys/types.h> #include <sys/socket.h> + +#include <errno.h> #include <netdb.h> #include <stdio.h> #include <string.h> #include <stdlib.h> -#define MAXALIASES 35 - -static FILE *servf = NULL; -static char line[BUFSIZ+1]; -static struct servent serv; -static char *serv_aliases[MAXALIASES]; -int _serv_stayopen; - void -setservent(int f) +setservent_r(int f, struct servent_data *sd) { - if (servf == NULL) - servf = fopen(_PATH_SERVICES, "r" ); + if (sd->fp == NULL) + sd->fp = fopen(_PATH_SERVICES, "r" ); else - rewind(servf); - _serv_stayopen |= f; + rewind(sd->fp); + sd->stayopen |= f; } void -endservent(void) +endservent_r(struct servent_data *sd) { - if (servf) { - fclose(servf); - servf = NULL; + if (sd->fp) { + fclose(sd->fp); + sd->fp = NULL; } - _serv_stayopen = 0; + free(sd->aliases); + sd->aliases = NULL; + sd->maxaliases = 0; + free(sd->line); + sd->line = NULL; + sd->stayopen = 0; } struct servent * -getservent(void) +getservent_r(struct servent *se, struct servent_data *sd) { char *p, *cp, **q, *endp; - long l; size_t len; + long l; + int serrno; - if (servf == NULL && (servf = fopen(_PATH_SERVICES, "r" )) == NULL) + if (sd->fp == NULL && (sd->fp = fopen(_PATH_SERVICES, "r" )) == NULL) return (NULL); again: - if ((p = fgetln(servf, &len)) == NULL) + if ((p = fgetln(sd->fp, &len)) == NULL) return (NULL); + if (len == 0 || *p == '#' || *p == '\n') + goto again; if (p[len-1] == '\n') len--; - if (len >= sizeof(line) || len == 0) - goto again; - p = memcpy(line, p, len); - line[len] = '\0'; - if (*p == '#') - goto again; - if ((cp = strchr(p, '#')) != NULL) - *cp = '\0'; - serv.s_name = p; - p = strpbrk(p, " \t"); + if ((cp = memchr(p, '#', len)) != NULL) + len = cp - p; + cp = realloc(sd->line, len + 1); + if (cp == NULL) + return (NULL); + sd->line = se->s_name = memcpy(cp, p, len); + cp[len] = '\0'; + p = strpbrk(cp, " \t"); if (p == NULL) goto again; *p++ = '\0'; @@ -102,9 +102,19 @@ again: l = strtol(p, &endp, 10); if (endp == p || *endp != '\0' || l < 0 || l > USHRT_MAX) goto again; - serv.s_port = htons((in_port_t)l); - serv.s_proto = cp; - q = serv.s_aliases = serv_aliases; + se->s_port = htons((in_port_t)l); + se->s_proto = cp; + if (sd->aliases == NULL) { + sd->maxaliases = 10; + sd->aliases = malloc(sd->maxaliases * sizeof(char *)); + if (sd->aliases == NULL) { + serrno = errno; + endservent_r(sd); + errno = serrno; + return (NULL); + } + } + q = se->s_aliases = sd->aliases; cp = strpbrk(cp, " \t"); if (cp != NULL) *cp++ = '\0'; @@ -113,12 +123,46 @@ again: cp++; continue; } - if (q < &serv_aliases[MAXALIASES - 1]) - *q++ = cp; + if (q == &se->s_aliases[sd->maxaliases - 1]) { + p = realloc(se->s_aliases, + 2 * sd->maxaliases * sizeof(char *)); + if (p == NULL) { + serrno = errno; + endservent_r(sd); + errno = serrno; + return (NULL); + } + sd->maxaliases *= 2; + q = (char **)p + (q - se->s_aliases); + se->s_aliases = sd->aliases = (char **)p; + } + *q++ = cp; cp = strpbrk(cp, " \t"); if (cp != NULL) *cp++ = '\0'; } *q = NULL; - return (&serv); + return (se); +} + +struct servent_data _servent_data; /* shared with getservby{name,port}.c */ + +void +setservent(int f) +{ + setservent_r(f, &_servent_data); +} + +void +endservent(void) +{ + endservent_r(&_servent_data); +} + +struct servent * +getservent(void) +{ + static struct servent serv; + + return getservent_r(&serv, &_servent_data); } |