]> rtime.felk.cvut.cz Git - l4.git/blobdiff - l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getservice.c
update
[l4.git] / l4 / pkg / uclibc / lib / contrib / uclibc / libc / inet / getservice.c
index 6d80a1b07febe564ee7547021ca99f5087022375..183099f5c6d4a1ead4adb9df6ee424b5038957d7 100644 (file)
+/* 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 MINTOKENS      3
+#define        MAXALIASES      8       /* we seldomly need more than 1 alias */
+#define MAXTOKENS      (MINTOKENS + MAXALIASES + 1)
+#define BUFSZ          (255)   /* one line */
+#define SBUFSIZE       (BUFSZ + 1 + (sizeof(char *) * MAXTOKENS))
 
-
-
-#define        MAXALIASES      35
-#define SBUFSIZE       (BUFSIZ + 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 size_t servbuf_sz = SBUFSIZE;
 static smallint serv_stayopen;
 
-static void __initbuf(void)
+void setservent(int stayopen)
 {
-    if (!servbuf) {
-       servbuf = malloc(SBUFSIZE);
-       if (!servbuf)
-           abort();
-    }
-}
-
-void setservent(int f)
-{
-    __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;
-       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;
-
-    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;
+       char **tok = NULL;
+       const size_t aliaslen = sizeof(char *) * MAXTOKENS;
+       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, MAXTOKENS - 1, MINTOKENS, "# \t/", PARSE_NORMAL)) {
+               goto DONE;
        }
-       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;
+       result_buf->s_name = *(tok++);
+       result_buf->s_port = htons((u_short) atoi(*(tok++)));
+       result_buf->s_proto = *(tok++);
+       result_buf->s_aliases = tok;
+       *result = result_buf;
+       ret = 0;
+ DONE:
+       __UCLIBC_MUTEX_UNLOCK(mylock);
+ DONE_NOUNLOCK:
+       errno = ret;
+       return errno;
 }
 libc_hidden_def(getservent_r)
 
-struct servent * getservent(void)
+static void __initbuf(void)
 {
-    struct servent *result;
+       if (!servbuf)
+               servbuf = malloc(SBUFSIZE);
+       if (!servbuf)
+               abort();
+}
 
-    __initbuf();
-    getservent_r(&serv, servbuf, SBUFSIZE, &result);
-    return result;
+struct servent *getservent(void)
+{
+       struct servent *result;
+
+       __initbuf();
+       getservent_r(&serve, servbuf, servbuf_sz, &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, servbuf_sz, &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, servbuf_sz, &result);
+       return result;
 }
 libc_hidden_def(getservbyport)