123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- /* vi: set sw=4 ts=4: */
- /*
- * 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
- */
- #include <features.h>
- #include <netdb.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 BUFSZ (80) /* one line */
- #define SBUFSIZE (BUFSZ + 1 + (sizeof(char *) * MAXALIASES))
- static parser_t *servp = NULL;
- static struct servent serve;
- static char *servbuf = NULL;
- static size_t servbuf_sz = SBUFSIZE;
- static smallint serv_stayopen;
- void setservent(int stayopen)
- {
- __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 (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)
- {
- char **alias;
- char **serv_aliases;
- char **tok = NULL;
- const size_t aliaslen = sizeof(*serv_aliases) * MAXALIASES;
- int ret = ENOENT;
- *result = NULL;
- if (buflen < aliaslen
- || (buflen - aliaslen) < BUFSZ + 1)
- goto DONE_NOUNLOCK;
- __UCLIBC_MUTEX_LOCK(mylock);
- 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, MAXALIASES, 3, "# \t/", PARSE_NORMAL)) {
- ret = ERANGE;
- 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;
- *result = result_buf;
- ret = 0;
- DONE:
- __UCLIBC_MUTEX_UNLOCK(mylock);
- DONE_NOUNLOCK:
- errno = ret;
- return errno;
- }
- libc_hidden_def(getservent_r)
- static void __initbuf(void)
- {
- if (servbuf)
- servbuf_sz += BUFSZ;
- servbuf = realloc(servbuf, servbuf_sz);
- if (!servbuf)
- abort();
- }
- struct servent *getservent(void)
- {
- struct servent *result;
- do {
- __initbuf();
- } while (getservent_r(&serve, servbuf, servbuf_sz, &result) == ERANGE);
- return result;
- }
- int getservbyname_r(const char *name, const char *proto,
- 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;
- }
- libc_hidden_def(getservbyname_r)
- struct servent *getservbyname(const char *name, const char *proto)
- {
- struct servent *result;
- do {
- __initbuf();
- } while (getservbyname_r(name, proto, &serve, servbuf, servbuf_sz, &result)
- == ERANGE);
- return result;
- }
- int getservbyport_r(int port, const char *proto,
- 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;
- }
- libc_hidden_def(getservbyport_r)
- struct servent *getservbyport(int port, const char *proto)
- {
- struct servent *result;
- do {
- __initbuf();
- } while (getservbyport_r(port, proto, &serve, servbuf, servbuf_sz, &result)
- == ERANGE);
- return result;
- }
- libc_hidden_def(getservbyport)
|