|
@@ -1,271 +1,198 @@
|
|
|
+
|
|
|
|
|
|
-** 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.
|
|
|
+ */
|
|
|
+
|
|
|
+
|
|
|
+# 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)
|
|
|
+#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;
|
|
|
+
|
|
|
+ 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)
|