]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4re-core/uclibc/lib/contrib/uclibc/libc/inet/getservice.c
Update
[l4.git] / l4 / pkg / l4re-core / uclibc / lib / contrib / uclibc / libc / inet / getservice.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Copyright (C) 2010 Bernhard Reutner-Fischer <uclibc@uclibc.org>
4  *
5  * Licensed under LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
6  */
7
8 /* /etc/services
9 #   service-name   port/protocol   [aliases ...]
10 discard               9/udp        sink null
11
12 service-name: case sensitive friendly name of the service
13 port: decimal port number
14 protocol: protocols(5) compatible entry
15 aliases: case sensitive optional space or tab separated list of other names
16 */
17
18 #include <features.h>
19 #include <netdb.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <netinet/in.h>
23 #include <arpa/inet.h>
24 #include <errno.h>
25 #include <unistd.h>
26 #include "internal/parse_config.h"
27
28 #include <bits/uClibc_mutex.h>
29 __UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
30
31 #define MINTOKENS       3
32 #define MAXALIASES      8       /* we seldomly need more than 1 alias */
33 #define MAXTOKENS       (MINTOKENS + MAXALIASES + 1)
34 #define BUFSZ           (255)   /* one line */
35 #define SBUFSIZE        (BUFSZ + 1 + (sizeof(char *) * MAXTOKENS))
36
37 static parser_t *servp = NULL;
38 static struct servent serve;
39 static char *servbuf = NULL;
40 static size_t servbuf_sz = SBUFSIZE;
41 static smallint serv_stayopen;
42
43 void setservent(int stayopen)
44 {
45         __UCLIBC_MUTEX_LOCK(mylock);
46         if (servp)
47                 config_close(servp);
48         servp = config_open(_PATH_SERVICES);
49         if (stayopen)
50                 serv_stayopen = 1;
51         __UCLIBC_MUTEX_UNLOCK(mylock);
52 }
53 libc_hidden_def(setservent)
54
55 void endservent(void)
56 {
57         __UCLIBC_MUTEX_LOCK(mylock);
58         if (servp) {
59                 config_close(servp);
60                 servp = NULL;
61         }
62         serv_stayopen = 0;
63         __UCLIBC_MUTEX_UNLOCK(mylock);
64 }
65 libc_hidden_def(endservent)
66
67 int getservent_r(struct servent *result_buf,
68                                  char *buf, size_t buflen, struct servent **result)
69 {
70         char **tok = NULL;
71         const size_t aliaslen = sizeof(char *) * MAXTOKENS;
72         int ret = ERANGE;
73
74         *result = NULL;
75         if (buflen < aliaslen
76                 || (buflen - aliaslen) < BUFSZ + 1)
77                 goto DONE_NOUNLOCK;
78
79         __UCLIBC_MUTEX_LOCK(mylock);
80         ret = ENOENT;
81         if (servp == NULL)
82                 setservent(serv_stayopen);
83         if (servp == NULL)
84                 goto DONE;
85
86         servp->data = buf;
87         servp->data_len = aliaslen;
88         servp->line_len = buflen - aliaslen;
89         /* <name>[[:space:]]<port>/<proto>[[:space:]][<aliases>] */
90         if (!config_read(servp, &tok, MAXTOKENS - 1, MINTOKENS, "# \t/", PARSE_NORMAL)) {
91                 goto DONE;
92         }
93         result_buf->s_name = *(tok++);
94         result_buf->s_port = htons((u_short) atoi(*(tok++)));
95         result_buf->s_proto = *(tok++);
96         result_buf->s_aliases = tok;
97         *result = result_buf;
98         ret = 0;
99  DONE:
100         __UCLIBC_MUTEX_UNLOCK(mylock);
101  DONE_NOUNLOCK:
102         errno = ret;
103         return errno;
104 }
105 libc_hidden_def(getservent_r)
106
107 static void __initbuf(void)
108 {
109         if (!servbuf)
110                 servbuf = malloc(SBUFSIZE);
111         if (!servbuf)
112                 abort();
113 }
114
115 struct servent *getservent(void)
116 {
117         struct servent *result;
118
119         __initbuf();
120         getservent_r(&serve, servbuf, servbuf_sz, &result);
121         return result;
122 }
123
124 int getservbyname_r(const char *name, const char *proto,
125                                         struct servent *result_buf, char *buf, size_t buflen,
126                                         struct servent **result)
127 {
128         register char **cp;
129         int ret;
130
131         __UCLIBC_MUTEX_LOCK(mylock);
132         setservent(serv_stayopen);
133         while (!(ret = getservent_r(result_buf, buf, buflen, result))) {
134                 if (strcmp(name, result_buf->s_name) == 0)
135                         goto gotname;
136                 for (cp = result_buf->s_aliases; *cp; cp++)
137                         if (strcmp(name, *cp) == 0)
138                                 goto gotname;
139                 continue;
140  gotname:
141                 if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0)
142                         break;
143         }
144         if (!serv_stayopen)
145                 endservent();
146         __UCLIBC_MUTEX_UNLOCK(mylock);
147         return *result ? 0 : ret;
148 }
149 libc_hidden_def(getservbyname_r)
150
151 struct servent *getservbyname(const char *name, const char *proto)
152 {
153         struct servent *result;
154
155         __initbuf();
156         getservbyname_r(name, proto, &serve, servbuf, servbuf_sz, &result);
157         return result;
158 }
159
160
161 int getservbyport_r(int port, const char *proto,
162                                         struct servent *result_buf, char *buf,
163                                         size_t buflen, struct servent **result)
164 {
165         int ret;
166
167         __UCLIBC_MUTEX_LOCK(mylock);
168         setservent(serv_stayopen);
169         while (!(ret = getservent_r(result_buf, buf, buflen, result))) {
170                 if (result_buf->s_port != port)
171                         continue;
172                 if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0)
173                         break;
174         }
175         if (!serv_stayopen)
176                 endservent();
177         __UCLIBC_MUTEX_UNLOCK(mylock);
178         return *result ? 0 : ret;
179 }
180 libc_hidden_def(getservbyport_r)
181
182 struct servent *getservbyport(int port, const char *proto)
183 {
184         struct servent *result;
185
186         __initbuf();
187         getservbyport_r(port, proto, &serve, servbuf, servbuf_sz, &result);
188         return result;
189 }
190 libc_hidden_def(getservbyport)