summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2004-10-17 20:24:24 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2004-10-17 20:24:24 +0000
commit6119135c871cdb14d2c537be99ec398e13edf027 (patch)
tree0dd5c7c99caa44c2ea5e7debe0d7beb2abf79729
parentee9ebb877e4b54f13e03b0aea8679e04c928043f (diff)
Reentrant versions of getprotoent(3) and getservent(3). Adapted from
changes in NetBSD by Christos. OK otto@
-rw-r--r--include/netdb.h48
-rw-r--r--lib/libc/net/getproto.c31
-rw-r--r--lib/libc/net/getprotoent.359
-rw-r--r--lib/libc/net/getprotoent.c121
-rw-r--r--lib/libc/net/getprotoname.c32
-rw-r--r--lib/libc/net/getservbyname.c33
-rw-r--r--lib/libc/net/getservbyport.c31
-rw-r--r--lib/libc/net/getservent.359
-rw-r--r--lib/libc/net/getservent.c122
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);
}