diff options
Diffstat (limited to 'libc/inet/getservice.c')
-rw-r--r-- | libc/inet/getservice.c | 257 |
1 files changed, 143 insertions, 114 deletions
diff --git a/libc/inet/getservice.c b/libc/inet/getservice.c index 0625a46e1..5e90f8198 100644 --- a/libc/inet/getservice.c +++ b/libc/inet/getservice.c @@ -53,6 +53,7 @@ #define __FORCE_GLIBC +#define _GNU_SOURCE #include <features.h> #include <sys/types.h> #include <sys/socket.h> @@ -64,6 +65,21 @@ #include <arpa/inet.h> #include <errno.h> + + +#ifdef __UCLIBC_HAS_THREADS__ +#include <pthread.h> +static pthread_mutex_t mylock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +# define LOCK pthread_mutex_lock(&mylock) +# define UNLOCK pthread_mutex_unlock(&mylock); +#else +# define LOCK +# define UNLOCK +#endif + + + + #define MAXALIASES 35 static FILE *servf = NULL; @@ -73,156 +89,169 @@ static int serv_stayopen; void setservent(int f) { - if (servf == NULL) - servf = fopen(_PATH_SERVICES, "r" ); - else - rewind(servf); - serv_stayopen |= f; + LOCK; + if (servf == NULL) + servf = fopen(_PATH_SERVICES, "r" ); + else + rewind(servf); + serv_stayopen |= f; + UNLOCK; } void endservent(void) { - if (servf) { - fclose(servf); - servf = NULL; - } - serv_stayopen = 0; + LOCK; + if (servf) { + fclose(servf); + servf = NULL; + } + serv_stayopen = 0; + UNLOCK; } struct servent * getservent(void) { - struct servent *result; - getservent_r(&serv, buf, sizeof(buf), &result); - return result; + struct servent *result; + getservent_r(&serv, buf, sizeof(buf), &result); + return result; } struct servent *getservbyname(const char *name, const char *proto) { - struct servent *result; - getservbyname_r(name, proto, &serv, buf, sizeof(buf), &result); - return result; + struct servent *result; + getservbyname_r(name, proto, &serv, buf, sizeof(buf), &result); + return result; } struct servent * getservbyport(int port, const char *proto) { - struct servent *result; - getservbyport_r(port, proto, &serv, buf, sizeof(buf), &result); - return result; + struct servent *result; + getservbyport_r(port, proto, &serv, buf, sizeof(buf), &result); + return result; } int getservent_r(struct servent * result_buf, char * buf, size_t buflen, struct servent ** result) { - char *p; - register char *cp, **q; - char **serv_aliases; - char *line; + char *p; + register char *cp, **q; + char **serv_aliases; + char *line; - *result=NULL; + *result=NULL; - if (buflen < sizeof(*serv_aliases)*MAXALIASES) { - errno=ERANGE; - return errno; - } - serv_aliases=(char **)buf; - buf+=sizeof(*serv_aliases)*MAXALIASES; - buflen-=sizeof(*serv_aliases)*MAXALIASES; - - if (buflen < BUFSIZ+1) { - errno=ERANGE; - return errno; - } - line=buf; - buf+=BUFSIZ+1; - buflen-=BUFSIZ+1; + if (buflen < sizeof(*serv_aliases)*MAXALIASES) { + errno=ERANGE; + return errno; + } + LOCK; + serv_aliases=(char **)buf; + buf+=sizeof(*serv_aliases)*MAXALIASES; + buflen-=sizeof(*serv_aliases)*MAXALIASES; + + if (buflen < BUFSIZ+1) { + UNLOCK; + errno=ERANGE; + return errno; + } + line=buf; + buf+=BUFSIZ+1; + buflen-=BUFSIZ+1; - if (servf == NULL && (servf = fopen(_PATH_SERVICES, "r" )) == NULL) - return errno; + if (servf == NULL && (servf = fopen(_PATH_SERVICES, "r" )) == NULL) { + UNLOCK; + return errno; + } again: - if ((p = fgets(line, BUFSIZ, servf)) == NULL) - return TRY_AGAIN; - if (*p == '#') - goto again; - cp = strpbrk(p, "#\n"); - if (cp == NULL) - goto again; - *cp = '\0'; - result_buf->s_name = p; - p = strpbrk(p, " \t"); - if (p == NULL) - goto again; - *p++ = '\0'; - while (*p == ' ' || *p == '\t') - p++; - cp = strpbrk(p, ",/"); - if (cp == NULL) - goto again; + if ((p = fgets(line, BUFSIZ, servf)) == NULL) { + UNLOCK; + return TRY_AGAIN; + } + if (*p == '#') + goto again; + cp = strpbrk(p, "#\n"); + if (cp == NULL) + goto again; + *cp = '\0'; + result_buf->s_name = p; + p = strpbrk(p, " \t"); + if (p == NULL) + goto again; + *p++ = '\0'; + while (*p == ' ' || *p == '\t') + p++; + cp = strpbrk(p, ",/"); + if (cp == NULL) + goto again; + *cp++ = '\0'; + result_buf->s_port = htons((u_short)atoi(p)); + result_buf->s_proto = cp; + q = result_buf->s_aliases = serv_aliases; + cp = strpbrk(cp, " \t"); + if (cp != NULL) *cp++ = '\0'; - result_buf->s_port = htons((u_short)atoi(p)); - result_buf->s_proto = cp; - q = result_buf->s_aliases = serv_aliases; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &serv_aliases[MAXALIASES - 1]) + *q++ = cp; cp = strpbrk(cp, " \t"); if (cp != NULL) - *cp++ = '\0'; - while (cp && *cp) { - if (*cp == ' ' || *cp == '\t') { - cp++; - continue; - } - if (q < &serv_aliases[MAXALIASES - 1]) - *q++ = cp; - cp = strpbrk(cp, " \t"); - if (cp != NULL) - *cp++ = '\0'; - } - *q = NULL; - *result=result_buf; - return 0; + *cp++ = '\0'; + } + *q = NULL; + *result=result_buf; + UNLOCK; + return 0; } -int getservbyname_r(const char *name, const char *proto, - struct servent * result_buf, - char * buf, size_t buflen, - struct servent ** result) +int getservbyname_r(const char *name, const char *proto, + struct servent * result_buf, char * buf, size_t buflen, + struct servent ** result) { - register char **cp; - int ret; - - setservent(serv_stayopen); - while (!(ret=getservent_r(result_buf, buf, buflen, result))) { - if (strcmp(name, result_buf->s_name) == 0) - goto gotname; - for (cp = result_buf->s_aliases; *cp; cp++) - if (strcmp(name, *cp) == 0) - goto gotname; - continue; + register char **cp; + int ret; + + LOCK; + setservent(serv_stayopen); + while (!(ret=getservent_r(result_buf, buf, buflen, result))) { + if (strcmp(name, result_buf->s_name) == 0) + goto gotname; + for (cp = result_buf->s_aliases; *cp; cp++) + if (strcmp(name, *cp) == 0) + goto gotname; + continue; gotname: - if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0) - break; - } - if (!serv_stayopen) - endservent(); - return *result?0:ret; + if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0) + break; + } + if (!serv_stayopen) + endservent(); + UNLOCK; + return *result?0:ret; } -int getservbyport_r(int port, const char *proto, - struct servent * result_buf, - char * buf, size_t buflen, - struct servent ** result) +int getservbyport_r(int port, const char *proto, + struct servent * result_buf, char * buf, + size_t buflen, struct servent ** result) { - int ret; - - setservent(serv_stayopen); - while (!(ret=getservent_r(result_buf, buf, buflen, result))) { - if (result_buf->s_port != port) - continue; - if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0) - break; - } - if (!serv_stayopen) - endservent(); - return *result?0:ret; + int ret; + + LOCK; + setservent(serv_stayopen); + while (!(ret=getservent_r(result_buf, buf, buflen, result))) { + if (result_buf->s_port != port) + continue; + if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0) + break; + } + if (!serv_stayopen) + endservent(); + UNLOCK; + return *result?0:ret; } |