libdl: first execute all destructors, then munmap library
[uclibc-ng.git] / libc / inet / getproto.c
blobdadcf19e51afca3eb2d6e15263ca095f087c8854
1 /*
2 * Copyright (C) 2010 Bernhard Reutner-Fischer <uclibc@uclibc.org>
4 * Licensed under LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
5 */
7 /* /etc/protocols
8 # protocol-name number [aliases ...]
9 ip 0 IP # internet protocol, pseudo protocol number
11 protocol-name: case sensitive friendly name of the IP protocol
12 number: decimal protocol number
13 aliases: case sensitive optional space or tab separated list of other names
16 #include <features.h>
17 #include <netdb.h>
18 #include <string.h>
19 #include <stdlib.h>
20 #include <netinet/in.h>
21 #include <arpa/inet.h>
22 #include <errno.h>
23 #include <unistd.h>
24 #include "internal/parse_config.h"
26 #include <bits/uClibc_mutex.h>
27 __UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
29 #define MINTOKENS 2
30 #define MAXALIASES 8 /* will probably never be more than one */
31 #define MAXTOKENS (MINTOKENS + MAXALIASES + 1)
32 #define BUFSZ (255) /* one line */
33 #define SBUFSIZE (BUFSZ + 1 + (sizeof(char *) * MAXTOKENS))
35 static parser_t *protop = NULL;
36 static struct protoent protoe;
37 static char *protobuf = NULL;
38 static smallint proto_stayopen;
40 void setprotoent(int stayopen)
42 __UCLIBC_MUTEX_LOCK(mylock);
43 if (protop)
44 config_close(protop);
45 protop = config_open(_PATH_PROTOCOLS);
46 if (stayopen)
47 proto_stayopen = 1;
48 __UCLIBC_MUTEX_UNLOCK(mylock);
50 libc_hidden_def(setprotoent)
52 void endprotoent(void)
54 __UCLIBC_MUTEX_LOCK(mylock);
55 if (protop) {
56 config_close(protop);
57 protop = NULL;
59 proto_stayopen = 0;
60 __UCLIBC_MUTEX_UNLOCK(mylock);
62 libc_hidden_def(endprotoent)
64 int getprotoent_r(struct protoent *result_buf,
65 char *buf, size_t buflen, struct protoent **result)
67 char **tok = NULL;
68 const size_t aliaslen = sizeof(char *) * MAXTOKENS;
69 int ret = ERANGE;
71 *result = NULL;
72 if (buflen < aliaslen
73 || (buflen - aliaslen) < BUFSZ + 1)
74 goto DONE_NOUNLOCK;
76 __UCLIBC_MUTEX_LOCK(mylock);
77 //tok = (char **) buf;
78 ret = ENOENT;
79 if (protop == NULL)
80 setprotoent(proto_stayopen);
81 if (protop == NULL)
82 goto DONE;
83 protop->data = buf;
84 protop->data_len = aliaslen;
85 protop->line_len = buflen - aliaslen;
86 /* <name>[[:space:]]<protonumber>[[:space:]][<aliases>] */
87 if (!config_read(protop, &tok, MAXTOKENS - 1, MINTOKENS, "# \t/", PARSE_NORMAL)) {
88 goto DONE;
90 result_buf->p_name = *(tok++);
91 result_buf->p_proto = atoi(*(tok++));
92 result_buf->p_aliases = tok;
93 *result = result_buf;
94 ret = 0;
95 DONE:
96 __UCLIBC_MUTEX_UNLOCK(mylock);
97 DONE_NOUNLOCK:
98 errno = ret;
99 return errno;
101 libc_hidden_def(getprotoent_r)
103 static void __initbuf(void)
105 if (!protobuf) {
106 protobuf = malloc(SBUFSIZE);
107 if (!protobuf)
108 abort();
112 struct protoent *getprotoent(void)
114 struct protoent *result;
116 __initbuf();
117 getprotoent_r(&protoe, protobuf, SBUFSIZE, &result);
118 return result;
121 int getprotobyname_r(const char *name,
122 struct protoent *result_buf, char *buf, size_t buflen,
123 struct protoent **result)
125 register char **cp;
126 int ret;
128 __UCLIBC_MUTEX_LOCK(mylock);
129 setprotoent(proto_stayopen);
130 while (!(ret = getprotoent_r(result_buf, buf, buflen, result))) {
131 if (strcmp(name, result_buf->p_name) == 0)
132 break;
133 for (cp = result_buf->p_aliases; *cp; cp++)
134 if (strcmp(name, *cp) == 0)
135 goto gotname;
137 gotname:
138 if (!proto_stayopen)
139 endprotoent();
140 __UCLIBC_MUTEX_UNLOCK(mylock);
141 return *result ? 0 : ret;
143 libc_hidden_def(getprotobyname_r)
145 struct protoent *getprotobyname(const char *name)
147 struct protoent *result;
149 __initbuf();
150 getprotobyname_r(name, &protoe, protobuf, SBUFSIZE, &result);
151 return result;
154 int getprotobynumber_r(int proto,
155 struct protoent *result_buf, char *buf,
156 size_t buflen, struct protoent **result)
158 int ret;
160 __UCLIBC_MUTEX_LOCK(mylock);
161 setprotoent(proto_stayopen);
162 while (!(ret = getprotoent_r(result_buf, buf, buflen, result))) {
163 if (proto == result_buf->p_proto)
164 break;
166 if (!proto_stayopen)
167 endprotoent();
168 __UCLIBC_MUTEX_UNLOCK(mylock);
169 return *result ? 0 : ret;
171 libc_hidden_def(getprotobynumber_r)
173 struct protoent *getprotobynumber(int proto)
175 struct protoent *result;
177 __initbuf();
178 getprotobynumber_r(proto, &protoe, protobuf, SBUFSIZE, &result);
179 return result;