OSDN Git Service

hidden_def/hidden_proto: convert all users (I hope) termios split, add some missing...
[uclinux-h8/uClibc.git] / libc / inet / getservice.c
1 /*
2 ** services.c                           /etc/services access functions
3 **
4 ** This file is part of the NYS Library.
5 **
6 ** The NYS Library is free software; you can redistribute it and/or
7 ** modify it under the terms of the GNU Library General Public License as
8 ** published by the Free Software Foundation; either version 2 of the
9 ** License, or (at your option) any later version.
10 **
11 ** The NYS Library is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 ** Library General Public License for more details.
15 **
16 ** You should have received a copy of the GNU Library General Public
17 ** License along with the NYS Library; see the file COPYING.LIB.  If
18 ** not, write to the Free Software Foundation, Inc., 675 Mass Ave,
19 ** Cambridge, MA 02139, USA.
20 **
21 **
22 ** Copyright (c) 1983 Regents of the University of California.
23 ** All rights reserved.
24 **
25 ** Redistribution and use in source and binary forms, with or without
26 ** modification, are permitted provided that the following conditions
27 ** are met:
28 ** 1. Redistributions of source code must retain the above copyright
29 **    notice, this list of conditions and the following disclaimer.
30 ** 2. Redistributions in binary form must reproduce the above copyright
31 **    notice, this list of conditions and the following disclaimer in the
32 **    documentation and/or other materials provided with the distribution.
33 ** 3. All advertising materials mentioning features or use of this software
34 **    must display the following acknowledgement:
35 **      This product includes software developed by the University of
36 **      California, Berkeley and its contributors.
37 ** 4. Neither the name of the University nor the names of its contributors
38 **    may be used to endorse or promote products derived from this software
39 **    without specific prior written permission.
40 **
41 ** THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
42 ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 ** ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
45 ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 ** SUCH DAMAGE.
52 */
53
54 #define __FORCE_GLIBC
55 #define _GNU_SOURCE
56 #include <features.h>
57 #include <sys/types.h>
58 #include <sys/socket.h>
59 #include <netdb.h>
60 #include <stdio.h>
61 #include <string.h>
62 #include <stdlib.h>
63 #include <netinet/in.h>
64 #include <arpa/inet.h>
65 #include <errno.h>
66
67 libc_hidden_proto(strcmp)
68 libc_hidden_proto(strpbrk)
69 libc_hidden_proto(fopen)
70 libc_hidden_proto(fclose)
71 libc_hidden_proto(atoi)
72 libc_hidden_proto(rewind)
73 libc_hidden_proto(fgets)
74 libc_hidden_proto(abort)
75
76 #ifdef __UCLIBC_HAS_THREADS__
77 # include <pthread.h>
78 static pthread_mutex_t mylock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
79 #endif
80 #define LOCK    __pthread_mutex_lock(&mylock)
81 #define UNLOCK  __pthread_mutex_unlock(&mylock)
82
83
84
85
86 #define MAXALIASES      35
87 #define SBUFSIZE        (BUFSIZ + 1 + (sizeof(char *) * MAXALIASES))
88
89 static FILE *servf = NULL;
90 static struct servent serv;
91 static char *servbuf = NULL;
92 static int serv_stayopen;
93
94 static void __initbuf(void)
95 {
96     if (!servbuf) {
97         servbuf = malloc(SBUFSIZE);
98         if (!servbuf)
99             abort();
100     }
101 }
102
103 void setservent(int f)
104 {
105     LOCK;
106     if (servf == NULL)
107         servf = fopen(_PATH_SERVICES, "r" );
108     else
109         rewind(servf);
110     serv_stayopen |= f;
111     UNLOCK;
112 }
113 libc_hidden_proto(setservent)
114 libc_hidden_def(setservent)
115
116 void endservent(void)
117 {
118     LOCK;
119     if (servf) {
120         fclose(servf);
121         servf = NULL;
122     }
123     serv_stayopen = 0;
124     UNLOCK;
125 }
126 libc_hidden_proto(endservent)
127 libc_hidden_def(endservent)
128
129 int getservent_r(struct servent * result_buf,
130                  char * buf, size_t buflen,
131                  struct servent ** result)
132 {
133     char *p;
134     register char *cp, **q;
135     char **serv_aliases;
136     char *line;
137
138     *result=NULL;
139
140     if (buflen < sizeof(*serv_aliases)*MAXALIASES) {
141         errno=ERANGE;
142         return errno;
143     }
144     LOCK;
145     serv_aliases=(char **)buf;
146     buf+=sizeof(*serv_aliases)*MAXALIASES;
147     buflen-=sizeof(*serv_aliases)*MAXALIASES;
148
149     if (buflen < BUFSIZ+1) {
150         UNLOCK;
151         errno=ERANGE;
152         return errno;
153     }
154     line=buf;
155     buf+=BUFSIZ+1;
156     buflen-=BUFSIZ+1;
157
158     if (servf == NULL && (servf = fopen(_PATH_SERVICES, "r" )) == NULL) {
159         UNLOCK;
160         errno=EIO;
161         return errno;
162     }
163 again:
164     if ((p = fgets(line, BUFSIZ, servf)) == NULL) {
165         UNLOCK;
166         errno=EIO;
167         return errno;
168     }
169     if (*p == '#')
170         goto again;
171     cp = strpbrk(p, "#\n");
172     if (cp == NULL)
173         goto again;
174     *cp = '\0';
175     result_buf->s_name = p;
176     p = strpbrk(p, " \t");
177     if (p == NULL)
178         goto again;
179     *p++ = '\0';
180     while (*p == ' ' || *p == '\t')
181         p++;
182     cp = strpbrk(p, ",/");
183     if (cp == NULL)
184         goto again;
185     *cp++ = '\0';
186     result_buf->s_port = htons((u_short)atoi(p));
187     result_buf->s_proto = cp;
188     q = result_buf->s_aliases = serv_aliases;
189     cp = strpbrk(cp, " \t");
190     if (cp != NULL)
191         *cp++ = '\0';
192     while (cp && *cp) {
193         if (*cp == ' ' || *cp == '\t') {
194             cp++;
195             continue;
196         }
197         if (q < &serv_aliases[MAXALIASES - 1])
198             *q++ = cp;
199         cp = strpbrk(cp, " \t");
200         if (cp != NULL)
201             *cp++ = '\0';
202     }
203     *q = NULL;
204     *result=result_buf;
205     UNLOCK;
206     return 0;
207 }
208 libc_hidden_proto(getservent_r)
209 libc_hidden_def(getservent_r)
210
211 struct servent * getservent(void)
212 {
213     struct servent *result;
214
215     __initbuf();
216     getservent_r(&serv, servbuf, SBUFSIZE, &result);
217     return result;
218 }
219
220 int getservbyname_r(const char *name, const char *proto,
221         struct servent * result_buf, char * buf, size_t buflen,
222         struct servent ** result)
223 {
224     register char **cp;
225     int ret;
226
227     LOCK;
228     setservent(serv_stayopen);
229     while (!(ret=getservent_r(result_buf, buf, buflen, result))) {
230         if (strcmp(name, result_buf->s_name) == 0)
231             goto gotname;
232         for (cp = result_buf->s_aliases; *cp; cp++)
233             if (strcmp(name, *cp) == 0)
234                 goto gotname;
235         continue;
236 gotname:
237         if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0)
238             break;
239     }
240     if (!serv_stayopen)
241         endservent();
242     UNLOCK;
243     return *result?0:ret;
244 }
245 libc_hidden_proto(getservbyname_r)
246 libc_hidden_def(getservbyname_r)
247
248 struct servent *getservbyname(const char *name, const char *proto)
249 {
250     struct servent *result;
251
252     __initbuf();
253     getservbyname_r(name, proto, &serv, servbuf, SBUFSIZE, &result);
254     return result;
255 }
256
257
258 int getservbyport_r(int port, const char *proto,
259         struct servent * result_buf, char * buf,
260         size_t buflen, struct servent ** result)
261 {
262     int ret;
263
264     LOCK;
265     setservent(serv_stayopen);
266     while (!(ret=getservent_r(result_buf, buf, buflen, result))) {
267         if (result_buf->s_port != port)
268             continue;
269         if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0)
270             break;
271     }
272     if (!serv_stayopen)
273         endservent();
274     UNLOCK;
275     return *result?0:ret;
276 }
277 libc_hidden_proto(getservbyport_r)
278 libc_hidden_def(getservbyport_r)
279
280 struct servent * getservbyport(int port, const char *proto)
281 {
282     struct servent *result;
283
284     __initbuf();
285     getservbyport_r(port, proto, &serv, servbuf, SBUFSIZE, &result);
286     return result;
287 }
288 libc_hidden_proto(getservbyport)
289 libc_hidden_def(getservbyport)