OSDN Git Service

e5a11d2c7a499b084c440a07b0025c32ffad59b6
[uclinux-h8/uClibc.git] / libc / inet / getproto.c
1 /*
2 ** protocols.c                           /etc/protocols 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 <stdlib.h>
62 #include <string.h>
63 #include <errno.h>
64
65 libc_hidden_proto(fopen)
66 libc_hidden_proto(strcmp)
67 libc_hidden_proto(strpbrk)
68 libc_hidden_proto(atoi)
69 libc_hidden_proto(rewind)
70 libc_hidden_proto(fgets)
71 libc_hidden_proto(fclose)
72 libc_hidden_proto(abort)
73
74 #ifdef __UCLIBC_HAS_THREADS__
75 # include <pthread.h>
76 static pthread_mutex_t mylock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
77 #endif
78 #define LOCK    __pthread_mutex_lock(&mylock)
79 #define UNLOCK  __pthread_mutex_unlock(&mylock)
80
81
82
83 #define MAXALIASES      35
84 #define SBUFSIZE        (BUFSIZ + 1 + (sizeof(char *) * MAXALIASES))
85
86 static FILE *protof = NULL;
87 static struct protoent proto;
88 static char *static_aliases = NULL;
89 static int proto_stayopen;
90
91 static void __initbuf(void)
92 {
93     if (!static_aliases) {
94         static_aliases = malloc(SBUFSIZE);
95         if (!static_aliases)
96             abort();
97     }
98 }
99
100 void setprotoent(int f)
101 {
102     LOCK;
103     if (protof == NULL)
104         protof = fopen(_PATH_PROTOCOLS, "r" );
105     else
106         rewind(protof);
107     proto_stayopen |= f;
108     UNLOCK;
109 }
110 libc_hidden_proto(setprotoent)
111 libc_hidden_def(setprotoent)
112
113 void endprotoent(void)
114 {
115     LOCK;
116     if (protof) {
117         fclose(protof);
118         protof = NULL;
119     }
120     proto_stayopen = 0;
121     UNLOCK;
122 }
123 libc_hidden_proto(endprotoent)
124 libc_hidden_def(endprotoent)
125
126 int getprotoent_r(struct protoent *result_buf,
127                   char *buf, size_t buflen,
128                   struct protoent **result)
129 {
130     char *p;
131     register char *cp, **q;
132     char **proto_aliases;
133     char *line;
134
135     *result = NULL;
136
137     if (buflen < sizeof(*proto_aliases)*MAXALIASES) {
138         errno=ERANGE;
139         return errno;
140     }
141     LOCK;
142     proto_aliases=(char **)buf;
143     buf+=sizeof(*proto_aliases)*MAXALIASES;
144     buflen-=sizeof(*proto_aliases)*MAXALIASES;
145
146     if (buflen < BUFSIZ+1) {
147         UNLOCK;
148         errno=ERANGE;
149         return errno;
150     }
151     line=buf;
152     buf+=BUFSIZ+1;
153     buflen-=BUFSIZ+1;
154
155     if (protof == NULL && (protof = fopen(_PATH_PROTOCOLS, "r" )) == NULL) {
156         UNLOCK;
157         return errno;
158     }
159 again:
160     if ((p = fgets(line, BUFSIZ, protof)) == NULL) {
161         UNLOCK;
162         return TRY_AGAIN;
163     }
164
165     if (*p == '#')
166         goto again;
167     cp = strpbrk(p, "#\n");
168     if (cp == NULL)
169         goto again;
170     *cp = '\0';
171     result_buf->p_name = p;
172     cp = strpbrk(p, " \t");
173     if (cp == NULL)
174         goto again;
175     *cp++ = '\0';
176     while (*cp == ' ' || *cp == '\t')
177         cp++;
178     p = strpbrk(cp, " \t");
179     if (p != NULL)
180         *p++ = '\0';
181     result_buf->p_proto = atoi(cp);
182     q = result_buf->p_aliases = proto_aliases;
183     if (p != NULL) {
184         cp = p;
185         while (cp && *cp) {
186             if (*cp == ' ' || *cp == '\t') {
187                 cp++;
188                 continue;
189             }
190             if (q < &proto_aliases[MAXALIASES - 1])
191                 *q++ = cp;
192             cp = strpbrk(cp, " \t");
193             if (cp != NULL)
194                 *cp++ = '\0';
195         }
196     }
197     *q = NULL;
198     *result=result_buf;
199     UNLOCK;
200     return 0;
201 }
202 libc_hidden_proto(getprotoent_r)
203 libc_hidden_def(getprotoent_r)
204
205 struct protoent * getprotoent(void)
206 {
207     struct protoent *result;
208
209     __initbuf();
210     getprotoent_r(&proto, static_aliases, SBUFSIZE, &result);
211     return result;
212 }
213
214
215 int getprotobyname_r(const char *name,
216                     struct protoent *result_buf,
217                     char *buf, size_t buflen,
218                     struct protoent **result)
219 {
220     register char **cp;
221     int ret;
222
223     LOCK;
224     setprotoent(proto_stayopen);
225     while (!(ret=getprotoent_r(result_buf, buf, buflen, result))) {
226         if (strcmp(result_buf->p_name, name) == 0)
227             break;
228         for (cp = result_buf->p_aliases; *cp != 0; cp++)
229             if (strcmp(*cp, name) == 0)
230                 goto found;
231     }
232 found:
233     if (!proto_stayopen)
234         endprotoent();
235     UNLOCK;
236     return *result?0:ret;
237 }
238 libc_hidden_proto(getprotobyname_r)
239 libc_hidden_def(getprotobyname_r)
240
241
242 struct protoent * getprotobyname(const char *name)
243 {
244     struct protoent *result;
245
246     __initbuf();
247     getprotobyname_r(name, &proto, static_aliases, SBUFSIZE, &result);
248     return result;
249 }
250
251
252 int getprotobynumber_r (int proto_num,
253                         struct protoent *result_buf,
254                         char *buf, size_t buflen,
255                         struct protoent **result)
256 {
257     int ret;
258
259     LOCK;
260     setprotoent(proto_stayopen);
261     while (!(ret=getprotoent_r(result_buf, buf, buflen, result)))
262         if (result_buf->p_proto == proto_num)
263             break;
264     if (!proto_stayopen)
265         endprotoent();
266     UNLOCK;
267     return *result?0:ret;
268 }
269 libc_hidden_proto(getprotobynumber_r)
270 libc_hidden_def(getprotobynumber_r)
271
272 struct protoent * getprotobynumber(int proto_num)
273 {
274     struct protoent *result;
275
276     __initbuf();
277     getprotobynumber_r(proto_num, &proto, static_aliases,
278                        SBUFSIZE, &result);
279     return result;
280 }
281