summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libc/inet/getservice.c351
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)