drop the use of getprotobyname_r()
[project/librpc-uclibc.git] / getrpcent.c
1 /* @(#)getrpcent.c      2.2 88/07/29 4.0 RPCSRC */
2
3 /*
4  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
5  * unrestricted use provided that this legend is included on all tape
6  * media and as a part of the software program in whole or part.  Users
7  * may copy or modify Sun RPC without charge, but are not authorized
8  * to license or distribute it to anyone else except as part of a product or
9  * program developed by the user.
10  *
11  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
12  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
13  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
14  *
15  * Sun RPC is provided with no support and without any obligation on the
16  * part of Sun Microsystems, Inc. to assist in its use, correction,
17  * modification or enhancement.
18  *
19  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
20  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
21  * OR ANY PART THEREOF.
22  *
23  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
24  * or profits or other special, indirect and consequential damages, even if
25  * Sun has been advised of the possibility of such damages.
26  *
27  * Sun Microsystems, Inc.
28  * 2550 Garcia Avenue
29  * Mountain View, California  94043
30  */
31
32 /*
33  * Copyright (c) 1985 by Sun Microsystems, Inc.
34  */
35
36 #define __FORCE_GLIBC
37 #include <features.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <sys/types.h>
41 #include <rpc/rpc.h>
42 #include <netdb.h>
43 #include <sys/socket.h>
44 #include <arpa/inet.h>
45 #include <errno.h>
46
47
48 /*
49  * Internet version.
50  */
51 static struct rpcdata {
52         FILE *rpcf;
53         char *current;
54         int currentlen;
55         int stayopen;
56 #define MAXALIASES      35
57         char *rpc_aliases[MAXALIASES];
58         struct rpcent rpc;
59         char line[BUFSIZ + 1];
60         char *domain;
61 } *rpcdata;
62
63 static const char RPCDB[] = "/etc/rpc";
64
65 static struct rpcdata *_rpcdata(void)
66 {
67         register struct rpcdata *d = rpcdata;
68
69         if (d == NULL) {
70                 d = (struct rpcdata *) calloc(1, sizeof(struct rpcdata));
71
72                 rpcdata = d;
73         }
74         return d;
75 }
76
77 void endrpcent(void)
78 {
79         register struct rpcdata *d = _rpcdata();
80
81         if (d == NULL)
82                 return;
83         if (d->stayopen)
84                 return;
85         free(d->current);
86         d->current = NULL;
87         if (d->rpcf) {
88                 fclose(d->rpcf);
89                 d->rpcf = NULL;
90         }
91 }
92 libc_hidden_def(endrpcent)
93
94 void setrpcent(int f)
95 {
96         register struct rpcdata *d = _rpcdata();
97
98         if (d == NULL)
99                 return;
100         if (d->rpcf == NULL)
101                 d->rpcf = fopen(RPCDB, "r");
102         else
103                 rewind(d->rpcf);
104         free(d->current);
105         d->current = NULL;
106         d->stayopen |= f;
107 }
108 libc_hidden_def(setrpcent)
109
110 static struct rpcent *interpret(struct rpcdata *);
111
112 static struct rpcent *__get_next_rpcent(struct rpcdata *d)
113 {
114         if (fgets(d->line, BUFSIZ, d->rpcf) == NULL)
115                 return NULL;
116         return interpret(d);
117 }
118
119 struct rpcent *getrpcent(void)
120 {
121         register struct rpcdata *d = _rpcdata();
122
123         if (d == NULL)
124                 return NULL;
125         if (d->rpcf == NULL && (d->rpcf = fopen(RPCDB, "r")) == NULL)
126                 return NULL;
127         return __get_next_rpcent(d);
128 }
129 libc_hidden_def(getrpcent)
130
131 struct rpcent *getrpcbynumber(register int number)
132 {
133         register struct rpcdata *d = _rpcdata();
134         register struct rpcent *rpc;
135
136         if (d == NULL)
137                 return NULL;
138         setrpcent(0);
139         while ((rpc = getrpcent())) {
140                 if (rpc->r_number == number)
141                         break;
142         }
143         endrpcent();
144         return rpc;
145 }
146 libc_hidden_def(getrpcbynumber)
147
148 struct rpcent *getrpcbyname(const char *name)
149 {
150         struct rpcent *rpc;
151         char **rp;
152
153         setrpcent(0);
154         while ((rpc = getrpcent())) {
155                 if (strcmp(rpc->r_name, name) == 0)
156                         return rpc;
157                 for (rp = rpc->r_aliases; *rp != NULL; rp++) {
158                         if (strcmp(*rp, name) == 0)
159                                 return rpc;
160                 }
161         }
162         endrpcent();
163         return NULL;
164 }
165 libc_hidden_def(getrpcbyname)
166
167 #ifdef __linux__
168 static char *firstwhite(char *s)
169 {
170         char *s1, *s2;
171
172         s1 = strchr(s, ' ');
173         s2 = strchr(s, '\t');
174         if (s1) {
175                 if (s2)
176                         return (s1 < s2) ? s1 : s2;
177                 else
178                         return s1;
179         } else
180                 return s2;
181 }
182 #endif
183
184 static struct rpcent *interpret(register struct rpcdata *d)
185 {
186         char *p;
187         register char *cp, **q;
188
189         p = d->line;
190         d->line[strlen(p)-1] = '\n';
191         if (*p == '#')
192                 return __get_next_rpcent(d);
193         cp = strchr(p, '#');
194         if (cp == NULL) {
195                 cp = strchr(p, '\n');
196                 if (cp == NULL)
197                         return __get_next_rpcent(d);
198         }
199         *cp = '\0';
200 #ifdef __linux__
201         if ((cp = firstwhite(p)))
202                 *cp++ = 0;
203         else
204                 return __get_next_rpcent(d);
205 #else
206         cp = strchr(p, ' ');
207         if (cp == NULL) {
208                 cp = strchr(p, '\t');
209                 if (cp == NULL)
210                         return __get_next_rpcent(d);
211         }
212         *cp++ = '\0';
213 #endif
214         /* THIS STUFF IS INTERNET SPECIFIC */
215         d->rpc.r_name = d->line;
216         while (*cp == ' ' || *cp == '\t')
217                 cp++;
218         d->rpc.r_number = atoi(cp);
219         q = d->rpc.r_aliases = d->rpc_aliases;
220 #ifdef __linux__
221         if ((cp = firstwhite(cp)))
222                 *cp++ = '\0';
223 #else
224         cp = strchr(p, ' ');
225         if (cp != NULL)
226                 *cp++ = '\0';
227         else {
228                 cp = strchr(p, '\t');
229                 if (cp != NULL)
230                         *cp++ = '\0';
231         }
232 #endif
233         while (cp && *cp) {
234                 if (*cp == ' ' || *cp == '\t') {
235                         cp++;
236                         continue;
237                 }
238                 if (q < &(d->rpc_aliases[MAXALIASES - 1]))
239                         *q++ = cp;
240 #ifdef __linux__
241                 if ((cp = firstwhite(cp)))
242                         *cp++ = '\0';
243 #else
244                 cp = strchr(p, ' ');
245                 if (cp != NULL)
246                         *cp++ = '\0';
247                 else {
248                         cp = strchr(p, '\t');
249                         if (cp != NULL)
250                                 *cp++ = '\0';
251                 }
252 #endif
253         }
254         *q = NULL;
255         return &d->rpc;
256 }
257
258 #if defined(__UCLIBC_HAS_REENTRANT_RPC__)
259
260 __UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
261
262
263 static int __copy_rpcent(struct rpcent *r, struct rpcent *result_buf, char *buffer,
264                 size_t buflen, struct rpcent **result)
265 {
266         size_t i, s;
267
268         *result = NULL;
269
270         if (!r)
271                 return ENOENT;
272
273         /* copy the struct from the shared mem */
274         memset(result_buf, 0x00, sizeof(*result_buf));
275         memset(buffer, 0x00, buflen);
276
277         result_buf->r_number = r->r_number;
278
279         /* copy the aliases ... need to not only copy the alias strings,
280          * but the array of pointers to the alias strings */
281         i = 0;
282         while (r->r_aliases[i++]) ;
283
284         s = i-- * sizeof(char*);
285         if (buflen < s)
286                 goto err_out;
287         result_buf->r_aliases = (char**)buffer;
288         buffer += s;
289         buflen -= s;
290
291         while (i-- > 0) {
292                 s = strlen(r->r_aliases[i]) + 1;
293                 if (buflen < s)
294                         goto err_out;
295                 result_buf->r_aliases[i] = buffer;
296                 buffer += s;
297                 buflen -= s;
298                 memcpy(result_buf->r_aliases[i], r->r_aliases[i], s);
299         }
300
301         /* copy the name */
302         i = strlen(r->r_name);
303         if (buflen <= i)
304                 goto err_out;
305         result_buf->r_name = buffer;
306         memcpy(result_buf->r_name, r->r_name, i);
307
308         /* that was a hoot eh ? */
309         *result = result_buf;
310
311         return 0;
312 err_out:
313         return ERANGE;
314 }
315
316 int getrpcbynumber_r(int number, struct rpcent *result_buf, char *buffer,
317                 size_t buflen, struct rpcent **result)
318 {
319         int ret;
320         __UCLIBC_MUTEX_LOCK(mylock);
321         ret = __copy_rpcent(getrpcbynumber(number), result_buf, buffer, buflen, result);
322         __UCLIBC_MUTEX_UNLOCK(mylock);
323         return ret;
324 }
325
326 int getrpcbyname_r(const char *name, struct rpcent *result_buf, char *buffer,
327                 size_t buflen, struct rpcent **result)
328 {
329         int ret;
330         __UCLIBC_MUTEX_LOCK(mylock);
331         ret = __copy_rpcent(getrpcbyname(name), result_buf, buffer, buflen, result);
332         __UCLIBC_MUTEX_UNLOCK(mylock);
333         return ret;
334 }
335
336 int getrpcent_r(struct rpcent *result_buf, char *buffer,
337                 size_t buflen, struct rpcent **result)
338 {
339         int ret;
340         __UCLIBC_MUTEX_LOCK(mylock);
341         ret = __copy_rpcent(getrpcent(), result_buf, buffer, buflen, result);
342         __UCLIBC_MUTEX_UNLOCK(mylock);
343         return ret;
344 }
345
346 #endif /* __UCLIBC_HAS_REENTRANT_RPC__ */