diff options
Diffstat (limited to 'libc')
-rw-r--r-- | libc/inet/getservice.c | 351 |
1 files changed, 139 insertions, 212 deletions
diff --git a/libc/inet/getservice.c b/libc/inet/getservice.c index 6d80a1b07..03f5c29c3 100644 --- a/libc/inet/getservice.c +++ b/libc/inet/getservice.c @@ -1,271 +1,198 @@ +/* vi: set sw=4 ts=4: */ /* -** services.c /etc/services access functions -** -** This file is part of the NYS Library. -** -** The NYS Library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Library General Public License as -** published by the Free Software Foundation; either version 2 of the -** License, or (at your option) any later version. -** -** The NYS Library is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -** Library General Public License for more details. -** -** You should have received a copy of the GNU Library General Public -** License along with the NYS Library; see the file COPYING.LIB. If -** not, write to the Free Software Foundation, Inc., 675 Mass Ave, -** Cambridge, MA 02139, USA. -** -** -** Copyright (c) 1983 Regents of the University of California. -** 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. -** 3. All advertising materials mentioning features or use of this software -** must display the following acknowledgement: -** This product includes software developed by the University of -** California, Berkeley and its contributors. -** 4. Neither the name of the University nor the names of its contributors -** may be used to endorse or promote products derived from this software -** without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE REGENTS 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. + * Copyright (C) 2010 Bernhard Reutner-Fischer <uclibc@uclibc.org> + * + * Licensed under LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + */ + +/* /etc/services +# service-name port/protocol [aliases ...] +discard 9/udp sink null + +service-name: case sensitive friendly name of the service +port: decimal port number +protocol: protocols(5) compatible entry +aliases: case sensitive optional space or tab separated list of other names */ -#define __FORCE_GLIBC #include <features.h> -#include <sys/types.h> -#include <sys/socket.h> #include <netdb.h> -#include <stdio.h> #include <string.h> #include <stdlib.h> #include <netinet/in.h> #include <arpa/inet.h> #include <errno.h> #include <unistd.h> - +#include "internal/parse_config.h" #include <bits/uClibc_mutex.h> __UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); - - - #define MAXALIASES 35 -#define SBUFSIZE (BUFSIZ + 1 + (sizeof(char *) * MAXALIASES)) +#define BUFSZ (80) /* one line */ +#define SBUFSIZE (BUFSZ + 1 + (sizeof(char *) * MAXALIASES)) -static FILE *servf = NULL; -static struct servent serv; +static parser_t *servp = NULL; +static struct servent serve; static char *servbuf = NULL; static smallint serv_stayopen; -static void __initbuf(void) -{ - if (!servbuf) { - servbuf = malloc(SBUFSIZE); - if (!servbuf) - abort(); - } -} - -void setservent(int f) +void setservent(int stayopen) { - __UCLIBC_MUTEX_LOCK(mylock); - if (servf == NULL) - servf = fopen(_PATH_SERVICES, "r" ); - else - rewind(servf); - if (f) serv_stayopen = 1; - __UCLIBC_MUTEX_UNLOCK(mylock); + __UCLIBC_MUTEX_LOCK(mylock); + if (servp) + config_close(servp); + servp = config_open(_PATH_SERVICES); + if (stayopen) + serv_stayopen = 1; + __UCLIBC_MUTEX_UNLOCK(mylock); } libc_hidden_def(setservent) void endservent(void) { - __UCLIBC_MUTEX_LOCK(mylock); - if (servf) { - fclose(servf); - servf = NULL; - } - serv_stayopen = 0; - __UCLIBC_MUTEX_UNLOCK(mylock); + __UCLIBC_MUTEX_LOCK(mylock); + if (servp) { + config_close(servp); + servp = NULL; + } + serv_stayopen = 0; + __UCLIBC_MUTEX_UNLOCK(mylock); } libc_hidden_def(endservent) -int getservent_r(struct servent * result_buf, - char * buf, size_t buflen, - struct servent ** 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; - int rv; - - *result=NULL; - - if (buflen < sizeof(*serv_aliases)*MAXALIASES) { - errno=ERANGE; + char **alias, *cp = NULL; + char **serv_aliases; + char **tok = NULL; + const size_t aliaslen = sizeof(*serv_aliases) * MAXALIASES; + int ret = ERANGE; + + *result = NULL; + if (buflen < aliaslen + || (buflen - aliaslen) < BUFSZ + 1) + goto DONE_NOUNLOCK; + + __UCLIBC_MUTEX_LOCK(mylock); + ret = ENOENT; + if (servp == NULL) + setservent(serv_stayopen); + if (servp == NULL) + goto DONE; + servp->data = buf; + servp->data_len = aliaslen; + servp->line_len = buflen - aliaslen; + /* <name>[[:space:]]<port>/<proto>[[:space:]][<aliases>] */ + if (!config_read(servp, &tok, 4, 3, "# \t/", PARSE_NORMAL)) { + goto DONE; + } + result_buf->s_name = *(tok++); + result_buf->s_port = htons((u_short) atoi(*(tok++))); + result_buf->s_proto = *(tok++); + result_buf->s_aliases = alias = serv_aliases = tok; + cp = *alias; + while (cp && *cp) { + if (alias < &serv_aliases[MAXALIASES - 1]) + *alias++ = cp; + cp = strpbrk(cp, " \t"); + if (cp != NULL) + *cp++ = '\0'; + } + *alias = NULL; + *result = result_buf; + ret = 0; + DONE: + __UCLIBC_MUTEX_UNLOCK(mylock); + DONE_NOUNLOCK: + errno = ret; return errno; - } - __UCLIBC_MUTEX_LOCK(mylock); - serv_aliases=(char **)buf; - buf+=sizeof(*serv_aliases)*MAXALIASES; - buflen-=sizeof(*serv_aliases)*MAXALIASES; - - if (buflen < BUFSIZ+1) { - errno=rv=ERANGE; - goto DONE; - } - line=buf; - buf+=BUFSIZ+1; - buflen-=BUFSIZ+1; +} +libc_hidden_def(getservent_r) - if (servf == NULL && (servf = fopen(_PATH_SERVICES, "r" )) == NULL) { - errno=rv=EIO; - goto DONE; - } -again: - if ((p = fgets(line, BUFSIZ, servf)) == NULL) { - errno=rv=EIO; - goto DONE; - } - 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'; - while (cp && *cp) { - if (*cp == ' ' || *cp == '\t') { - cp++; - continue; +static void __initbuf(void) +{ + if (!servbuf) { + servbuf = malloc(SBUFSIZE); + if (!servbuf) + abort(); } - if (q < &serv_aliases[MAXALIASES - 1]) - *q++ = cp; - cp = strpbrk(cp, " \t"); - if (cp != NULL) - *cp++ = '\0'; - } - *q = NULL; - *result=result_buf; - rv = 0; -DONE: - __UCLIBC_MUTEX_UNLOCK(mylock); - return rv; } -libc_hidden_def(getservent_r) -struct servent * getservent(void) +struct servent *getservent(void) { - struct servent *result; + struct servent *result; - __initbuf(); - getservent_r(&serv, servbuf, SBUFSIZE, &result); - return result; + __initbuf(); + getservent_r(&serve, servbuf, SBUFSIZE, &result); + return result; } int getservbyname_r(const char *name, const char *proto, - struct servent * result_buf, char * buf, size_t buflen, - struct servent ** result) + struct servent *result_buf, char *buf, size_t buflen, + struct servent **result) { - register char **cp; - int ret; - - __UCLIBC_MUTEX_LOCK(mylock); - 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(); - __UCLIBC_MUTEX_UNLOCK(mylock); - return *result?0:ret; + register char **cp; + int ret; + + __UCLIBC_MUTEX_LOCK(mylock); + 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(); + __UCLIBC_MUTEX_UNLOCK(mylock); + return *result ? 0 : ret; } libc_hidden_def(getservbyname_r) struct servent *getservbyname(const char *name, const char *proto) { - struct servent *result; + struct servent *result; - __initbuf(); - getservbyname_r(name, proto, &serv, servbuf, SBUFSIZE, &result); - return result; + __initbuf(); + getservbyname_r(name, proto, &serve, servbuf, SBUFSIZE, &result); + return result; } int getservbyport_r(int port, const char *proto, - struct servent * result_buf, char * buf, - size_t buflen, struct servent ** result) + struct servent *result_buf, char *buf, + size_t buflen, struct servent **result) { - int ret; - - __UCLIBC_MUTEX_LOCK(mylock); - 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(); - __UCLIBC_MUTEX_UNLOCK(mylock); - return *result?0:ret; + int ret; + + __UCLIBC_MUTEX_LOCK(mylock); + 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(); + __UCLIBC_MUTEX_UNLOCK(mylock); + return *result ? 0 : ret; } libc_hidden_def(getservbyport_r) -struct servent * getservbyport(int port, const char *proto) +struct servent *getservbyport(int port, const char *proto) { - struct servent *result; + struct servent *result; - __initbuf(); - getservbyport_r(port, proto, &serv, servbuf, SBUFSIZE, &result); - return result; + __initbuf(); + getservbyport_r(port, proto, &serve, servbuf, SBUFSIZE, &result); + return result; } libc_hidden_def(getservbyport) |