| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 | /* 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 nullservice-name: case sensitive friendly name of the serviceport: decimal port numberprotocol: protocols(5) compatible entryaliases: 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 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))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 **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;	}	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)static void __initbuf(void){	if (!servbuf)		servbuf = malloc(SBUFSIZE);	if (!servbuf)		abort();}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){	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;	__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){	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;	__initbuf();	getservbyport_r(port, proto, &serve, servbuf, servbuf_sz, &result);	return result;}libc_hidden_def(getservbyport)
 |