diff options
-rw-r--r-- | libc/inet/getproto.c | 349 |
1 files changed, 137 insertions, 212 deletions
diff --git a/libc/inet/getproto.c b/libc/inet/getproto.c index bf7c09371..bcf507bda 100644 --- a/libc/inet/getproto.c +++ b/libc/inet/getproto.c @@ -1,266 +1,191 @@ +/* vi: set sw=4 ts=4: */ /* -** protocols.c /etc/protocols 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/protocols +# protocol-name number [aliases ...] +ip 0 IP # internet protocol, pseudo protocol number + +protocol-name: case sensitive friendly name of the IP protocol +number: decimal protocol number +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 <stdlib.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 *protof = NULL; -static struct protoent proto; -static char *static_aliases = NULL; +static parser_t *protop = NULL; +static struct protoent protoe; +static char *protobuf = NULL; static smallint proto_stayopen; -static void __initbuf(void) +void setprotoent(int stayopen) { - if (!static_aliases) { - static_aliases = malloc(SBUFSIZE); - if (!static_aliases) - abort(); - } -} - -void setprotoent(int f) -{ - __UCLIBC_MUTEX_LOCK(mylock); - if (protof == NULL) - protof = fopen(_PATH_PROTOCOLS, "r" ); - else - rewind(protof); - if (f) proto_stayopen = 1; - __UCLIBC_MUTEX_UNLOCK(mylock); + __UCLIBC_MUTEX_LOCK(mylock); + if (protop) + config_close(protop); + protop = config_open(_PATH_PROTOCOLS); + if (stayopen) + proto_stayopen = 1; + __UCLIBC_MUTEX_UNLOCK(mylock); } libc_hidden_def(setprotoent) void endprotoent(void) { - __UCLIBC_MUTEX_LOCK(mylock); - if (protof) { - fclose(protof); - protof = NULL; - } - proto_stayopen = 0; - __UCLIBC_MUTEX_UNLOCK(mylock); + __UCLIBC_MUTEX_LOCK(mylock); + if (protop) { + config_close(protop); + protop = NULL; + } + proto_stayopen = 0; + __UCLIBC_MUTEX_UNLOCK(mylock); } libc_hidden_def(endprotoent) int getprotoent_r(struct protoent *result_buf, - char *buf, size_t buflen, - struct protoent **result) + char *buf, size_t buflen, struct protoent **result) { - char *p; - register char *cp, **q; - char **proto_aliases; - char *line; - int rv; - - *result = NULL; - - if (buflen < sizeof(*proto_aliases)*MAXALIASES) { - errno=ERANGE; - return errno; - } - __UCLIBC_MUTEX_LOCK(mylock); - proto_aliases=(char **)buf; - buf+=sizeof(*proto_aliases)*MAXALIASES; - buflen-=sizeof(*proto_aliases)*MAXALIASES; - - if (buflen < BUFSIZ+1) { - errno=rv=ERANGE; - goto DONE; - } - line=buf; - buf+=BUFSIZ+1; - buflen-=BUFSIZ+1; - - if (protof == NULL && (protof = fopen(_PATH_PROTOCOLS, "r" )) == NULL) { - rv=errno; - goto DONE; - } -again: - if ((p = fgets(line, BUFSIZ, protof)) == NULL) { - rv=ENOENT; - goto DONE; - } - - if (*p == '#') - goto again; - cp = strpbrk(p, "#\n"); - if (cp == NULL) - goto again; - *cp = '\0'; - result_buf->p_name = p; - cp = strpbrk(p, " \t"); - if (cp == NULL) - goto again; - *cp++ = '\0'; - while (*cp == ' ' || *cp == '\t') - cp++; - p = strpbrk(cp, " \t"); - if (p != NULL) - *p++ = '\0'; - result_buf->p_proto = atoi(cp); - q = result_buf->p_aliases = proto_aliases; - if (p != NULL) { - cp = p; + char **alias, *cp = NULL; + char **proto_aliases; + char **tok = NULL; + const size_t aliaslen = sizeof(*proto_aliases) * MAXALIASES; + int ret = ERANGE; + + *result = NULL; + if (buflen < aliaslen + || (buflen - aliaslen) < BUFSZ + 1) + goto DONE_NOUNLOCK; + + __UCLIBC_MUTEX_LOCK(mylock); + //tok = (char **) buf; + ret = ENOENT; + if (protop == NULL) + setprotoent(proto_stayopen); + if (protop == NULL) + goto DONE; + protop->data = buf; + protop->data_len = aliaslen; + protop->line_len = buflen - aliaslen; + /* <name>[[:space:]]<protonumber>[[:space:]][<aliases>] */ + if (!config_read(protop, &tok, 3, 2, "# \t/", PARSE_NORMAL)) { + goto DONE; + } + result_buf->p_name = *(tok++); + result_buf->p_proto = atoi(*(tok++)); + result_buf->p_aliases = alias = proto_aliases = tok; + cp = *alias; while (cp && *cp) { - if (*cp == ' ' || *cp == '\t') { - cp++; - continue; - } - if (q < &proto_aliases[MAXALIASES - 1]) - *q++ = cp; - cp = strpbrk(cp, " \t"); - if (cp != NULL) - *cp++ = '\0'; + if (alias < &proto_aliases[MAXALIASES - 1]) + *alias++ = cp; + cp = strpbrk(cp, " \t"); + if (cp != NULL) + *cp++ = '\0'; } - } - *q = NULL; - *result=result_buf; - rv = 0; -DONE: - __UCLIBC_MUTEX_UNLOCK(mylock); - return rv; + *alias = NULL; + *result = result_buf; + ret = 0; + DONE: + __UCLIBC_MUTEX_UNLOCK(mylock); + DONE_NOUNLOCK: + errno = ret; + return errno; } libc_hidden_def(getprotoent_r) -struct protoent * getprotoent(void) +static void __initbuf(void) { - struct protoent *result; - - __initbuf(); - getprotoent_r(&proto, static_aliases, SBUFSIZE, &result); - return result; + if (!protobuf) { + protobuf = malloc(SBUFSIZE); + if (!protobuf) + abort(); + } } +struct protoent *getprotoent(void) +{ + struct protoent *result; + + __initbuf(); + getprotoent_r(&protoe, protobuf, SBUFSIZE, &result); + return result; +} int getprotobyname_r(const char *name, - struct protoent *result_buf, - char *buf, size_t buflen, - struct protoent **result) + struct protoent *result_buf, char *buf, size_t buflen, + struct protoent **result) { - register char **cp; - int ret; - - __UCLIBC_MUTEX_LOCK(mylock); - setprotoent(proto_stayopen); - while (!(ret=getprotoent_r(result_buf, buf, buflen, result))) { - if (strcmp(result_buf->p_name, name) == 0) - break; - for (cp = result_buf->p_aliases; *cp != 0; cp++) - if (strcmp(*cp, name) == 0) - goto found; - } -found: - if (!proto_stayopen) - endprotoent(); - __UCLIBC_MUTEX_UNLOCK(mylock); - return *result?0:ret; + register char **cp; + int ret; + + __UCLIBC_MUTEX_LOCK(mylock); + setprotoent(proto_stayopen); + while (!(ret = getprotoent_r(result_buf, buf, buflen, result))) { + if (strcmp(name, result_buf->p_name) == 0) + break; + for (cp = result_buf->p_aliases; *cp; cp++) + if (strcmp(name, *cp) == 0) + goto gotname; + } + gotname: + if (!proto_stayopen) + endprotoent(); + __UCLIBC_MUTEX_UNLOCK(mylock); + return *result ? 0 : ret; } libc_hidden_def(getprotobyname_r) - -struct protoent * getprotobyname(const char *name) +struct protoent *getprotobyname(const char *name) { - struct protoent *result; + struct protoent *result; - __initbuf(); - getprotobyname_r(name, &proto, static_aliases, SBUFSIZE, &result); - return result; + __initbuf(); + getprotobyname_r(name, &protoe, protobuf, SBUFSIZE, &result); + return result; } - -int getprotobynumber_r (int proto_num, - struct protoent *result_buf, - char *buf, size_t buflen, - struct protoent **result) +int getprotobynumber_r(int proto, + struct protoent *result_buf, char *buf, + size_t buflen, struct protoent **result) { - int ret; + int ret; - __UCLIBC_MUTEX_LOCK(mylock); - setprotoent(proto_stayopen); - while (!(ret=getprotoent_r(result_buf, buf, buflen, result))) - if (result_buf->p_proto == proto_num) - break; - if (!proto_stayopen) - endprotoent(); - __UCLIBC_MUTEX_UNLOCK(mylock); - return *result?0:ret; + __UCLIBC_MUTEX_LOCK(mylock); + setprotoent(proto_stayopen); + while (!(ret = getprotoent_r(result_buf, buf, buflen, result))) { + if (proto == result_buf->p_proto) + break; + } + if (!proto_stayopen) + endprotoent(); + __UCLIBC_MUTEX_UNLOCK(mylock); + return *result ? 0 : ret; } libc_hidden_def(getprotobynumber_r) -struct protoent * getprotobynumber(int proto_num) +struct protoent *getprotobynumber(int proto) { - struct protoent *result; + struct protoent *result; - __initbuf(); - getprotobynumber_r(proto_num, &proto, static_aliases, - SBUFSIZE, &result); - return result; + __initbuf(); + getprotobynumber_r(proto, &protoe, protobuf, SBUFSIZE, &result); + return result; } |