| /* 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/protocols | 
 | #   protocol-name   number   [aliases ...] | 
 | ip                  0        IP  # internet protocol, pseudo protocol number | 
 |  | 
 | protocol-name: case sensitive friendly name of the IP protocol | 
 | number: decimal protocol number | 
 | 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 MINTOKENS	2 | 
 | #define	MAXALIASES	8 /* will probably never be more than one */ | 
 | #define MAXTOKENS	(MINTOKENS + MAXALIASES + 1) | 
 | #define BUFSZ		(255) /* one line */ | 
 | #define SBUFSIZE	(BUFSZ + 1 + (sizeof(char *) * MAXTOKENS)) | 
 |  | 
 | static parser_t *protop = NULL; | 
 | static struct protoent protoe; | 
 | static char *protobuf = NULL; | 
 | static smallint proto_stayopen; | 
 |  | 
 | void setprotoent(int stayopen) | 
 | { | 
 | 	__UCLIBC_MUTEX_LOCK(mylock); | 
 | 	if (protop) | 
 | 		config_close(protop); | 
 | 	protop = config_open(_PATH_PROTOCOLS); | 
 | 	if (stayopen) | 
 | 		proto_stayopen = 1; | 
 | 	__UCLIBC_MUTEX_UNLOCK(mylock); | 
 | } | 
 | libc_hidden_def(setprotoent) | 
 |  | 
 | void endprotoent(void) | 
 | { | 
 | 	__UCLIBC_MUTEX_LOCK(mylock); | 
 | 	if (protop) { | 
 | 		config_close(protop); | 
 | 		protop = NULL; | 
 | 	} | 
 | 	proto_stayopen = 0; | 
 | 	__UCLIBC_MUTEX_UNLOCK(mylock); | 
 | } | 
 | libc_hidden_def(endprotoent) | 
 |  | 
 | int getprotoent_r(struct protoent *result_buf, | 
 | 				 char *buf, size_t buflen, struct protoent **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); | 
 | 	//tok = (char **) buf; | 
 | 	ret = ENOENT; | 
 | 	if (protop == NULL) | 
 | 		setprotoent(proto_stayopen); | 
 | 	if (protop == NULL) | 
 | 		goto DONE; | 
 | 	protop->data = buf; | 
 | 	protop->data_len = aliaslen; | 
 | 	protop->line_len = buflen - aliaslen; | 
 | 	/* <name>[[:space:]]<protonumber>[[:space:]][<aliases>] */ | 
 | 	if (!config_read(protop, &tok, MAXTOKENS - 1, MINTOKENS, "# \t/", PARSE_NORMAL)) { | 
 | 		goto DONE; | 
 | 	} | 
 | 	result_buf->p_name = *(tok++); | 
 | 	result_buf->p_proto = atoi(*(tok++)); | 
 | 	result_buf->p_aliases = tok; | 
 | 	*result = result_buf; | 
 | 	ret = 0; | 
 |  DONE: | 
 | 	__UCLIBC_MUTEX_UNLOCK(mylock); | 
 |  DONE_NOUNLOCK: | 
 | 	errno = ret; | 
 | 	return errno; | 
 | } | 
 | libc_hidden_def(getprotoent_r) | 
 |  | 
 | static void __initbuf(void) | 
 | { | 
 | 	if (!protobuf) { | 
 | 		protobuf = malloc(SBUFSIZE); | 
 | 		if (!protobuf) | 
 | 			abort(); | 
 | 	} | 
 | } | 
 |  | 
 | struct protoent *getprotoent(void) | 
 | { | 
 | 	struct protoent *result; | 
 |  | 
 | 	__initbuf(); | 
 | 	getprotoent_r(&protoe, protobuf, SBUFSIZE, &result); | 
 | 	return result; | 
 | } | 
 |  | 
 | int getprotobyname_r(const char *name, | 
 | 					struct protoent *result_buf, char *buf, size_t buflen, | 
 | 					struct protoent **result) | 
 | { | 
 | 	register char **cp; | 
 | 	int ret; | 
 |  | 
 | 	__UCLIBC_MUTEX_LOCK(mylock); | 
 | 	setprotoent(proto_stayopen); | 
 | 	while (!(ret = getprotoent_r(result_buf, buf, buflen, result))) { | 
 | 		if (strcmp(name, result_buf->p_name) == 0) | 
 | 			break; | 
 | 		for (cp = result_buf->p_aliases; *cp; cp++) | 
 | 			if (strcmp(name, *cp) == 0) | 
 | 				goto gotname; | 
 | 	} | 
 |  gotname: | 
 | 	if (!proto_stayopen) | 
 | 		endprotoent(); | 
 | 	__UCLIBC_MUTEX_UNLOCK(mylock); | 
 | 	return *result ? 0 : ret; | 
 | } | 
 | libc_hidden_def(getprotobyname_r) | 
 |  | 
 | struct protoent *getprotobyname(const char *name) | 
 | { | 
 | 	struct protoent *result; | 
 |  | 
 | 	__initbuf(); | 
 | 	getprotobyname_r(name, &protoe, protobuf, SBUFSIZE, &result); | 
 | 	return result; | 
 | } | 
 |  | 
 | int getprotobynumber_r(int proto, | 
 | 					struct protoent *result_buf, char *buf, | 
 | 					size_t buflen, struct protoent **result) | 
 | { | 
 | 	int ret; | 
 |  | 
 | 	__UCLIBC_MUTEX_LOCK(mylock); | 
 | 	setprotoent(proto_stayopen); | 
 | 	while (!(ret = getprotoent_r(result_buf, buf, buflen, result))) { | 
 | 		if (proto == result_buf->p_proto) | 
 | 			break; | 
 | 	} | 
 | 	if (!proto_stayopen) | 
 | 		endprotoent(); | 
 | 	__UCLIBC_MUTEX_UNLOCK(mylock); | 
 | 	return *result ? 0 : ret; | 
 | } | 
 | libc_hidden_def(getprotobynumber_r) | 
 |  | 
 | struct protoent *getprotobynumber(int proto) | 
 | { | 
 | 	struct protoent *result; | 
 |  | 
 | 	__initbuf(); | 
 | 	getprotobynumber_r(proto, &protoe, protobuf, SBUFSIZE, &result); | 
 | 	return result; | 
 | } | 
 |  |