]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - lib/libc/rpc/getrpcent.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / lib / libc / rpc / getrpcent.c
1 /*      $NetBSD: getrpcent.c,v 1.17 2000/01/22 22:19:17 mycroft Exp $   */
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 or with the express written consent of
10  * Sun Microsystems, Inc.
11  *
12  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
13  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
14  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
15  *
16  * Sun RPC is provided with no support and without any obligation on the
17  * part of Sun Microsystems, Inc. to assist in its use, correction,
18  * modification or enhancement.
19  *
20  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
21  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
22  * OR ANY PART THEREOF.
23  *
24  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
25  * or profits or other special, indirect and consequential damages, even if
26  * Sun has been advised of the possibility of such damages.
27  *
28  * Sun Microsystems, Inc.
29  * 2550 Garcia Avenue
30  * Mountain View, California  94043
31  */
32
33 #if defined(LIBC_SCCS) && !defined(lint)
34 static char *sccsid = "@(#)getrpcent.c 1.14 91/03/11 Copyr 1984 Sun Micro";
35 #endif
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38
39 /*
40  * Copyright (c) 1984 by Sun Microsystems, Inc.
41  */
42
43 #include <sys/param.h>
44 #include <sys/types.h>
45 #include <sys/socket.h>
46 #include <arpa/inet.h>
47 #include <assert.h>
48 #include <errno.h>
49 #include <nsswitch.h>
50 #include <netinet/in.h>
51 #include <stdio.h>
52 #include <string.h>
53 #include <stdarg.h>
54 #include <stdlib.h>
55 #include <rpc/rpc.h>
56 #ifdef YP
57 #include <rpcsvc/yp_prot.h>
58 #include <rpcsvc/ypclnt.h>
59 #endif
60 #include <unistd.h>
61 #include "namespace.h"
62 #include "reentrant.h"
63 #include "un-namespace.h"
64 #include "libc_private.h"
65 #include "nss_tls.h"
66 #ifdef NS_CACHING
67 #include "nscache.h"
68 #endif
69
70 #define RPCDB   "/etc/rpc"
71
72 /* nsswitch declarations */
73 enum constants
74 {
75         SETRPCENT = 1,
76         ENDRPCENT = 2,
77         RPCENT_STORAGE_INITIAL  = 1 << 10, /* 1 KByte */
78         RPCENT_STORAGE_MAX      = 1 << 20, /* 1 MByte */
79 };
80
81 static const ns_src defaultsrc[] = {
82         { NSSRC_FILES, NS_SUCCESS },
83 #ifdef YP
84         { NSSRC_NIS, NS_SUCCESS },
85 #endif
86         { NULL, 0 }
87 };
88
89 /* files backend declarations */
90 struct files_state {
91         FILE    *fp;
92         int     stayopen;
93 };
94
95 static  int     files_rpcent(void *, void *, va_list);
96 static  int     files_setrpcent(void *, void *, va_list);
97
98 static  void    files_endstate(void *);
99 NSS_TLS_HANDLING(files);
100
101 /* nis backend declarations */
102 #ifdef YP
103 struct nis_state {
104         char    domain[MAXHOSTNAMELEN];
105         char    *current;
106         int     currentlen;
107         int     stepping;
108         int     no_name_map;
109 };
110
111 static  int     nis_rpcent(void *, void *, va_list);
112 static  int     nis_setrpcent(void *, void *, va_list);
113
114 static  void    nis_endstate(void *);
115 NSS_TLS_HANDLING(nis);
116 #endif
117
118 /* get** wrappers for get**_r functions declarations */
119 struct rpcent_state {
120         struct rpcent   rpc;
121         char            *buffer;
122         size_t  bufsize;
123 };
124 static  void    rpcent_endstate(void *);
125 NSS_TLS_HANDLING(rpcent);
126
127 union key {
128         const char      *name;
129         int             number;
130 };
131
132 static int wrap_getrpcbyname_r(union key, struct rpcent *, char *,
133                         size_t, struct rpcent **);
134 static int wrap_getrpcbynumber_r(union key, struct rpcent *, char *,
135                         size_t, struct rpcent **);
136 static int wrap_getrpcent_r(union key, struct rpcent *, char *,
137                         size_t, struct rpcent **);
138 static struct rpcent *getrpc(int (*fn)(union key, struct rpcent *, char *,
139                         size_t, struct rpcent **), union key);
140
141 #ifdef NS_CACHING
142 static int rpc_id_func(char *, size_t *, va_list, void *);
143 static int rpc_marshal_func(char *, size_t *, void *, va_list, void *);
144 static int rpc_unmarshal_func(char *, size_t, void *, va_list, void *);
145 #endif
146
147 static int
148 rpcent_unpack(char *p, struct rpcent *rpc, char **r_aliases,
149         size_t aliases_size, int *errnop)
150 {
151         char *cp, **q;
152
153         assert(p != NULL);
154
155         if (*p == '#')
156                 return (-1);
157         cp = strpbrk(p, "#\n");
158         if (cp == NULL)
159                 return (-1);
160         *cp = '\0';
161         cp = strpbrk(p, " \t");
162         if (cp == NULL)
163                 return (-1);
164         *cp++ = '\0';
165         /* THIS STUFF IS INTERNET SPECIFIC */
166         rpc->r_name = p;
167         while (*cp == ' ' || *cp == '\t')
168                 cp++;
169         rpc->r_number = atoi(cp);
170         q = rpc->r_aliases = r_aliases;
171         cp = strpbrk(cp, " \t");
172         if (cp != NULL)
173                 *cp++ = '\0';
174         while (cp && *cp) {
175                 if (*cp == ' ' || *cp == '\t') {
176                         cp++;
177                         continue;
178                 }
179                 if (q < &(r_aliases[aliases_size - 1]))
180                         *q++ = cp;
181                 else {
182                         *errnop = ERANGE;
183                         return -1;
184                 }
185
186                 cp = strpbrk(cp, " \t");
187                 if (cp != NULL)
188                         *cp++ = '\0';
189         }
190         *q = NULL;
191         return 0;
192 }
193
194 /* files backend implementation */
195 static  void
196 files_endstate(void *p)
197 {
198         FILE * f;
199
200         if (p == NULL)
201                 return;
202
203         f = ((struct files_state *)p)->fp;
204         if (f != NULL)
205                 fclose(f);
206
207         free(p);
208 }
209
210 static int
211 files_rpcent(void *retval, void *mdata, va_list ap)
212 {
213         char *name;
214         int number;
215         struct rpcent *rpc;
216         char *buffer;
217         size_t bufsize;
218         int *errnop;
219
220         char *line;
221         size_t linesize;
222         char **aliases;
223         int aliases_size;
224         char **rp;
225
226         struct files_state      *st;
227         int rv;
228         int stayopen;
229         enum nss_lookup_type how;
230
231         how = (enum nss_lookup_type)mdata;
232         switch (how)
233         {
234         case nss_lt_name:
235                 name = va_arg(ap, char *);
236                 break;
237         case nss_lt_id:
238                 number = va_arg(ap, int);
239                 break;
240         case nss_lt_all:
241                 break;
242         default:
243                 return (NS_NOTFOUND);
244         }
245
246         rpc = va_arg(ap, struct rpcent *);
247         buffer = va_arg(ap, char *);
248         bufsize = va_arg(ap, size_t);
249         errnop = va_arg(ap, int *);
250
251         *errnop = files_getstate(&st);
252         if (*errnop != 0)
253                 return (NS_UNAVAIL);
254
255         if (st->fp == NULL && (st->fp = fopen(RPCDB, "r")) == NULL) {
256                 *errnop = errno;
257                 return (NS_UNAVAIL);
258         }
259
260         if (how == nss_lt_all)
261                 stayopen = 1;
262         else {
263                 rewind(st->fp);
264                 stayopen = st->stayopen;
265         }
266
267         do {
268                 if ((line = fgetln(st->fp, &linesize)) == NULL) {
269                         *errnop = errno;
270                         rv = NS_RETURN;
271                         break;
272                 }
273
274                 if (bufsize <= linesize + _ALIGNBYTES + sizeof(char *)) {
275                         *errnop = ERANGE;
276                         rv = NS_RETURN;
277                         break;
278                 }
279
280                 aliases = (char **)_ALIGN(&buffer[linesize+1]);
281                 aliases_size = (buffer + bufsize -
282                         (char *)aliases)/sizeof(char *);
283                 if (aliases_size < 1) {
284                         *errnop = ERANGE;
285                         rv = NS_RETURN;
286                         break;
287                 }
288
289                 memcpy(buffer, line, linesize);
290                 buffer[linesize] = '\0';
291
292                 rv = rpcent_unpack(buffer, rpc, aliases, aliases_size, errnop);
293                 if (rv != 0) {
294                         if (*errnop == 0) {
295                                 rv = NS_NOTFOUND;
296                                 continue;
297                         }
298                         else {
299                                 rv = NS_RETURN;
300                                 break;
301                         }
302                 }
303
304                 switch (how)
305                 {
306                 case nss_lt_name:
307                         if (strcmp(rpc->r_name, name) == 0)
308                                 goto done;
309                         for (rp = rpc->r_aliases; *rp != NULL; rp++) {
310                                 if (strcmp(*rp, name) == 0)
311                                         goto done;
312                         }
313                         rv = NS_NOTFOUND;
314                         continue;
315 done:
316                         rv = NS_SUCCESS;
317                         break;
318                 case nss_lt_id:
319                         rv = (rpc->r_number == number) ? NS_SUCCESS :
320                                 NS_NOTFOUND;
321                         break;
322                 case nss_lt_all:
323                         rv = NS_SUCCESS;
324                         break;
325                 }
326
327         } while (!(rv & NS_TERMINATE));
328
329         if (!stayopen && st->fp!=NULL) {
330                 fclose(st->fp);
331                 st->fp = NULL;
332         }
333
334         if ((rv == NS_SUCCESS) && (retval != NULL))
335                 *((struct rpcent **)retval) = rpc;
336
337         return (rv);
338 }
339
340 static int
341 files_setrpcent(void *retval, void *mdata, va_list ap)
342 {
343         struct files_state      *st;
344         int     rv;
345         int     f;
346
347         rv = files_getstate(&st);
348         if (rv != 0)
349                 return (NS_UNAVAIL);
350
351         switch ((enum constants)mdata)
352         {
353         case SETRPCENT:
354                 f = va_arg(ap,int);
355                 if (st->fp == NULL)
356                         st->fp = fopen(RPCDB, "r");
357                 else
358                         rewind(st->fp);
359                 st->stayopen |= f;
360                 break;
361         case ENDRPCENT:
362                 if (st->fp != NULL) {
363                         fclose(st->fp);
364                         st->fp = NULL;
365                 }
366                 st->stayopen = 0;
367                 break;
368         default:
369                 break;
370         }
371
372         return (NS_UNAVAIL);
373 }
374
375 /* nis backend implementation */
376 #ifdef YP
377 static  void
378 nis_endstate(void *p)
379 {
380         if (p == NULL)
381                 return;
382
383         free(((struct nis_state *)p)->current);
384         free(p);
385 }
386
387 static int
388 nis_rpcent(void *retval, void *mdata, va_list ap)
389 {
390         char            *name;
391         int             number;
392         struct rpcent   *rpc;
393         char            *buffer;
394         size_t  bufsize;
395         int             *errnop;
396
397         char            **rp;
398         char            **aliases;
399         int             aliases_size;
400
401         char    *lastkey;
402         char    *resultbuf;
403         int     resultbuflen;
404         char    buf[YPMAXRECORD + 2];
405
406         struct nis_state        *st;
407         int             rv;
408         enum nss_lookup_type    how;
409         int     no_name_active;
410
411         how = (enum nss_lookup_type)mdata;
412         switch (how)
413         {
414         case nss_lt_name:
415                 name = va_arg(ap, char *);
416                 break;
417         case nss_lt_id:
418                 number = va_arg(ap, int);
419                 break;
420         case nss_lt_all:
421                 break;
422         default:
423                 return (NS_NOTFOUND);
424         }
425
426         rpc = va_arg(ap, struct rpcent *);
427         buffer = va_arg(ap, char *);
428         bufsize = va_arg(ap, size_t);
429         errnop = va_arg(ap, int *);
430
431         *errnop = nis_getstate(&st);
432         if (*errnop != 0)
433                 return (NS_UNAVAIL);
434
435         if (st->domain[0] == '\0') {
436                 if (getdomainname(st->domain, sizeof(st->domain)) != 0) {
437                         *errnop = errno;
438                         return (NS_UNAVAIL);
439                 }
440         }
441
442         no_name_active = 0;
443         do {
444                 switch (how)
445                 {
446                 case nss_lt_name:
447                         if (!st->no_name_map)
448                         {
449                                 snprintf(buf, sizeof buf, "%s", name);
450                                 rv = yp_match(st->domain, "rpc.byname", buf,
451                                         strlen(buf), &resultbuf, &resultbuflen);
452
453                                 switch (rv) {
454                                 case 0:
455                                         break;
456                                 case YPERR_MAP:
457                                         st->stepping = 0;
458                                         no_name_active = 1;
459                                         how = nss_lt_all;
460
461                                         rv = NS_NOTFOUND;
462                                         continue;
463                                 default:
464                                         rv = NS_NOTFOUND;
465                                         goto fin;
466                                 }
467                         } else {
468                                 st->stepping = 0;
469                                 no_name_active = 1;
470                                 how = nss_lt_all;
471
472                                 rv = NS_NOTFOUND;
473                                 continue;
474                         }
475                 break;
476                 case nss_lt_id:
477                         snprintf(buf, sizeof buf, "%d", number);
478                         if (yp_match(st->domain, "rpc.bynumber", buf,
479                                 strlen(buf), &resultbuf, &resultbuflen)) {
480                                 rv = NS_NOTFOUND;
481                                 goto fin;
482                         }
483                         break;
484                 case nss_lt_all:
485                                 if (!st->stepping) {
486                                         rv = yp_first(st->domain, "rpc.bynumber",
487                                                 &st->current,
488                                                 &st->currentlen, &resultbuf,
489                                                 &resultbuflen);
490                                         if (rv) {
491                                                 rv = NS_NOTFOUND;
492                                                 goto fin;
493                                         }
494                                         st->stepping = 1;
495                                 } else {
496                                         lastkey = st->current;
497                                         rv = yp_next(st->domain, "rpc.bynumber",
498                                                 st->current,
499                                                 st->currentlen, &st->current,
500                                                 &st->currentlen,
501                                                 &resultbuf,     &resultbuflen);
502                                         free(lastkey);
503                                         if (rv) {
504                                                 st->stepping = 0;
505                                                 rv = NS_NOTFOUND;
506                                                 goto fin;
507                                         }
508                                 }
509                         break;
510                 }
511
512                 /* we need a room for additional \n symbol */
513                 if (bufsize <= resultbuflen + 1 + _ALIGNBYTES +
514                     sizeof(char *)) {
515                         *errnop = ERANGE;
516                         rv = NS_RETURN;
517                         break;
518                 }
519
520                 aliases=(char **)_ALIGN(&buffer[resultbuflen+2]);
521                 aliases_size = (buffer + bufsize - (char *)aliases) /
522                         sizeof(char *);
523                 if (aliases_size < 1) {
524                         *errnop = ERANGE;
525                         rv = NS_RETURN;
526                         break;
527                 }
528
529                 /*
530                  * rpcent_unpack expects lines terminated with \n -- make it happy
531                  */
532                 memcpy(buffer, resultbuf, resultbuflen);
533                 buffer[resultbuflen] = '\n';
534                 buffer[resultbuflen+1] = '\0';
535                 free(resultbuf);
536
537                 if (rpcent_unpack(buffer, rpc, aliases, aliases_size,
538                     errnop) != 0) {
539                         if (*errnop == 0)
540                                 rv = NS_NOTFOUND;
541                         else
542                                 rv = NS_RETURN;
543                 } else {
544                         if ((how == nss_lt_all) && (no_name_active != 0)) {
545                                 if (strcmp(rpc->r_name, name) == 0)
546                                         goto done;
547                                 for (rp = rpc->r_aliases; *rp != NULL; rp++) {
548                                         if (strcmp(*rp, name) == 0)
549                                                 goto done;
550                                 }
551                                 rv = NS_NOTFOUND;
552                                 continue;
553 done:
554                                 rv = NS_SUCCESS;
555                         } else
556                                 rv = NS_SUCCESS;
557                 }
558
559         } while (!(rv & NS_TERMINATE) && (how == nss_lt_all));
560
561 fin:
562         if ((rv == NS_SUCCESS) && (retval != NULL))
563                 *((struct rpcent **)retval) = rpc;
564
565         return (rv);
566 }
567
568 static int
569 nis_setrpcent(void *retval, void *mdata, va_list ap)
570 {
571         struct nis_state        *st;
572         int     rv;
573
574         rv = nis_getstate(&st);
575         if (rv != 0)
576                 return (NS_UNAVAIL);
577
578         switch ((enum constants)mdata)
579         {
580         case SETRPCENT:
581         case ENDRPCENT:
582                 free(st->current);
583                 st->current = NULL;
584                 st->stepping = 0;
585                 break;
586         default:
587                 break;
588         }
589
590         return (NS_UNAVAIL);
591 }
592 #endif
593
594 #ifdef NS_CACHING
595 static int
596 rpc_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata)
597 {
598         char *name;
599         int rpc;
600
601         size_t desired_size, size;
602         enum nss_lookup_type lookup_type;
603         int res = NS_UNAVAIL;
604
605         lookup_type = (enum nss_lookup_type)cache_mdata;
606         switch (lookup_type) {
607         case nss_lt_name:
608                 name = va_arg(ap, char *);
609
610                 size = strlen(name);
611                 desired_size = sizeof(enum nss_lookup_type) + size + 1;
612                 if (desired_size > *buffer_size) {
613                         res = NS_RETURN;
614                         goto fin;
615                 }
616
617                 memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
618                 memcpy(buffer + sizeof(enum nss_lookup_type), name, size + 1);
619
620                 res = NS_SUCCESS;
621                 break;
622         case nss_lt_id:
623                 rpc = va_arg(ap, int);
624
625                 desired_size = sizeof(enum nss_lookup_type) + sizeof(int);
626                 if (desired_size > *buffer_size) {
627                         res = NS_RETURN;
628                         goto fin;
629                 }
630
631                 memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
632                 memcpy(buffer + sizeof(enum nss_lookup_type), &rpc,
633                     sizeof(int));
634
635                 res = NS_SUCCESS;
636                 break;
637         default:
638                 /* should be unreachable */
639                 return (NS_UNAVAIL);
640         }
641
642 fin:
643         *buffer_size = desired_size;
644         return (res);
645 }
646
647 static int
648 rpc_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap,
649     void *cache_mdata)
650 {
651         char *name;
652         int num;
653         struct rpcent *rpc;
654         char *orig_buf;
655         size_t orig_buf_size;
656
657         struct rpcent new_rpc;
658         size_t desired_size, size, aliases_size;
659         char *p;
660         char **alias;
661
662         switch ((enum nss_lookup_type)cache_mdata) {
663         case nss_lt_name:
664                 name = va_arg(ap, char *);
665                 break;
666         case nss_lt_id:
667                 num = va_arg(ap, int);
668                 break;
669         case nss_lt_all:
670                 break;
671         default:
672                 /* should be unreachable */
673                 return (NS_UNAVAIL);
674         }
675
676         rpc = va_arg(ap, struct rpcent *);
677         orig_buf = va_arg(ap, char *);
678         orig_buf_size = va_arg(ap, size_t);
679
680         desired_size = _ALIGNBYTES + sizeof(struct rpcent) + sizeof(char *);
681         if (rpc->r_name != NULL)
682                 desired_size += strlen(rpc->r_name) + 1;
683
684         if (rpc->r_aliases != NULL) {
685                 aliases_size = 0;
686                 for (alias = rpc->r_aliases; *alias; ++alias) {
687                         desired_size += strlen(*alias) + 1;
688                         ++aliases_size;
689                 }
690
691                 desired_size += _ALIGNBYTES + (aliases_size + 1) *
692                     sizeof(char *);
693         }
694
695         if (*buffer_size < desired_size) {
696                 /* this assignment is here for future use */
697                 *buffer_size = desired_size;
698                 return (NS_RETURN);
699         }
700
701         new_rpc = *rpc;
702
703         *buffer_size = desired_size;
704         memset(buffer, 0, desired_size);
705         p = buffer + sizeof(struct rpcent) + sizeof(char *);
706         memcpy(buffer + sizeof(struct rpcent), &p, sizeof(char *));
707         p = (char *)_ALIGN(p);
708
709         if (new_rpc.r_name != NULL) {
710                 size = strlen(new_rpc.r_name);
711                 memcpy(p, new_rpc.r_name, size);
712                 new_rpc.r_name = p;
713                 p += size + 1;
714         }
715
716         if (new_rpc.r_aliases != NULL) {
717                 p = (char *)_ALIGN(p);
718                 memcpy(p, new_rpc.r_aliases, sizeof(char *) * aliases_size);
719                 new_rpc.r_aliases = (char **)p;
720                 p += sizeof(char *) * (aliases_size + 1);
721
722                 for (alias = new_rpc.r_aliases; *alias; ++alias) {
723                         size = strlen(*alias);
724                         memcpy(p, *alias, size);
725                         *alias = p;
726                         p += size + 1;
727                 }
728         }
729
730         memcpy(buffer, &new_rpc, sizeof(struct rpcent));
731         return (NS_SUCCESS);
732 }
733
734 static int
735 rpc_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap,
736     void *cache_mdata)
737 {
738         char *name;
739         int num;
740         struct rpcent *rpc;
741         char *orig_buf;
742         size_t orig_buf_size;
743         int *ret_errno;
744
745         char *p;
746         char **alias;
747
748         switch ((enum nss_lookup_type)cache_mdata) {
749         case nss_lt_name:
750                 name = va_arg(ap, char *);
751                 break;
752         case nss_lt_id:
753                 num = va_arg(ap, int);
754                 break;
755         case nss_lt_all:
756                 break;
757         default:
758                 /* should be unreachable */
759                 return (NS_UNAVAIL);
760         }
761
762         rpc = va_arg(ap, struct rpcent *);
763         orig_buf = va_arg(ap, char *);
764         orig_buf_size = va_arg(ap, size_t);
765         ret_errno = va_arg(ap, int *);
766
767         if (orig_buf_size <
768             buffer_size - sizeof(struct rpcent) - sizeof(char *)) {
769                 *ret_errno = ERANGE;
770                 return (NS_RETURN);
771         }
772
773         memcpy(rpc, buffer, sizeof(struct rpcent));
774         memcpy(&p, buffer + sizeof(struct rpcent), sizeof(char *));
775
776         orig_buf = (char *)_ALIGN(orig_buf);
777         memcpy(orig_buf, buffer + sizeof(struct rpcent) + sizeof(char *) +
778             _ALIGN(p) - (size_t)p,
779             buffer_size - sizeof(struct rpcent) - sizeof(char *) -
780             _ALIGN(p) + (size_t)p);
781         p = (char *)_ALIGN(p);
782
783         NS_APPLY_OFFSET(rpc->r_name, orig_buf, p, char *);
784         if (rpc->r_aliases != NULL) {
785                 NS_APPLY_OFFSET(rpc->r_aliases, orig_buf, p, char **);
786
787                 for (alias = rpc->r_aliases     ; *alias; ++alias)
788                         NS_APPLY_OFFSET(*alias, orig_buf, p, char *);
789         }
790
791         if (retval != NULL)
792                 *((struct rpcent **)retval) = rpc;
793
794         return (NS_SUCCESS);
795 }
796
797 NSS_MP_CACHE_HANDLING(rpc);
798 #endif /* NS_CACHING */
799
800
801 /* get**_r functions implementation */
802 static int
803 getrpcbyname_r(const char *name, struct rpcent *rpc, char *buffer,
804         size_t bufsize, struct rpcent **result)
805 {
806 #ifdef NS_CACHING
807         static const nss_cache_info cache_info =
808                 NS_COMMON_CACHE_INFO_INITIALIZER(
809                 rpc, (void *)nss_lt_name,
810                 rpc_id_func, rpc_marshal_func, rpc_unmarshal_func);
811 #endif
812         static const ns_dtab dtab[] = {
813                 { NSSRC_FILES, files_rpcent, (void *)nss_lt_name },
814 #ifdef YP
815                 { NSSRC_NIS, nis_rpcent, (void *)nss_lt_name },
816 #endif
817 #ifdef NS_CACHING
818                 NS_CACHE_CB(&cache_info)
819 #endif
820                 { NULL, NULL, NULL }
821         };
822         int rv, ret_errno;
823
824         ret_errno = 0;
825         *result = NULL;
826         rv = nsdispatch(result, dtab, NSDB_RPC, "getrpcbyname_r", defaultsrc,
827             name, rpc, buffer, bufsize, &ret_errno);
828
829         if (rv == NS_SUCCESS)
830                 return (0);
831         else
832                 return (ret_errno);
833 }
834
835 static int
836 getrpcbynumber_r(int number, struct rpcent *rpc, char *buffer,
837         size_t bufsize, struct rpcent **result)
838 {
839 #ifdef NS_CACHING
840         static const nss_cache_info cache_info =
841                 NS_COMMON_CACHE_INFO_INITIALIZER(
842                 rpc, (void *)nss_lt_id,
843                 rpc_id_func, rpc_marshal_func, rpc_unmarshal_func);
844 #endif
845         static const ns_dtab dtab[] = {
846                 { NSSRC_FILES, files_rpcent, (void *)nss_lt_id },
847 #ifdef YP
848                 { NSSRC_NIS, nis_rpcent, (void *)nss_lt_id },
849 #endif
850 #ifdef NS_CACHING
851                 NS_CACHE_CB(&cache_info)
852 #endif
853                 { NULL, NULL, NULL }
854         };
855         int rv, ret_errno;
856
857         ret_errno = 0;
858         *result = NULL;
859         rv = nsdispatch(result, dtab, NSDB_RPC, "getrpcbynumber_r", defaultsrc,
860             number, rpc, buffer, bufsize, &ret_errno);
861
862         if (rv == NS_SUCCESS)
863                 return (0);
864         else
865                 return (ret_errno);
866 }
867
868 static int
869 getrpcent_r(struct rpcent *rpc, char *buffer, size_t bufsize,
870         struct rpcent **result)
871 {
872 #ifdef NS_CACHING
873         static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
874                 rpc, (void *)nss_lt_all,
875                 rpc_marshal_func, rpc_unmarshal_func);
876 #endif
877         static const ns_dtab dtab[] = {
878                 { NSSRC_FILES, files_rpcent, (void *)nss_lt_all },
879 #ifdef YP
880                 { NSSRC_NIS, nis_rpcent, (void *)nss_lt_all },
881 #endif
882 #ifdef NS_CACHING
883                 NS_CACHE_CB(&cache_info)
884 #endif
885                 { NULL, NULL, NULL }
886         };
887         int rv, ret_errno;
888
889         ret_errno = 0;
890         *result = NULL;
891         rv = nsdispatch(result, dtab, NSDB_RPC, "getrpcent_r", defaultsrc,
892             rpc, buffer, bufsize, &ret_errno);
893
894         if (rv == NS_SUCCESS)
895                 return (0);
896         else
897                 return (ret_errno);
898 }
899
900 /* get** wrappers for get**_r functions implementation */
901 static  void
902 rpcent_endstate(void *p)
903 {
904         if (p == NULL)
905                 return;
906
907         free(((struct rpcent_state *)p)->buffer);
908         free(p);
909 }
910
911 static  int
912 wrap_getrpcbyname_r(union key key, struct rpcent *rpc, char *buffer,
913     size_t bufsize, struct rpcent **res)
914 {
915         return (getrpcbyname_r(key.name, rpc, buffer, bufsize, res));
916 }
917
918 static  int
919 wrap_getrpcbynumber_r(union key key, struct rpcent *rpc, char *buffer,
920     size_t bufsize, struct rpcent **res)
921 {
922         return (getrpcbynumber_r(key.number, rpc, buffer, bufsize, res));
923 }
924
925 static  int
926 wrap_getrpcent_r(union key key __unused, struct rpcent *rpc, char *buffer,
927     size_t bufsize, struct rpcent **res)
928 {
929         return (getrpcent_r(rpc, buffer, bufsize, res));
930 }
931
932 static struct rpcent *
933 getrpc(int (*fn)(union key, struct rpcent *, char *, size_t, struct rpcent **),
934     union key key)
935 {
936         int              rv;
937         struct rpcent   *res;
938         struct rpcent_state * st;
939
940         rv=rpcent_getstate(&st);
941         if (rv != 0) {
942                 errno = rv;
943                 return NULL;
944         }
945
946         if (st->buffer == NULL) {
947                 st->buffer = malloc(RPCENT_STORAGE_INITIAL);
948                 if (st->buffer == NULL)
949                         return (NULL);
950                 st->bufsize = RPCENT_STORAGE_INITIAL;
951         }
952         do {
953                 rv = fn(key, &st->rpc, st->buffer, st->bufsize, &res);
954                 if (res == NULL && rv == ERANGE) {
955                         free(st->buffer);
956                         if ((st->bufsize << 1) > RPCENT_STORAGE_MAX) {
957                                 st->buffer = NULL;
958                                 errno = ERANGE;
959                                 return (NULL);
960                         }
961                         st->bufsize <<= 1;
962                         st->buffer = malloc(st->bufsize);
963                         if (st->buffer == NULL)
964                                 return (NULL);
965                 }
966         } while (res == NULL && rv == ERANGE);
967         if (rv != 0)
968                 errno = rv;
969
970         return (res);
971 }
972
973 struct rpcent *
974 getrpcbyname(char *name)
975 {
976         union key key;
977
978         key.name = name;
979
980         return (getrpc(wrap_getrpcbyname_r, key));
981 }
982
983 struct rpcent *
984 getrpcbynumber(int number)
985 {
986         union key key;
987
988         key.number = number;
989
990         return (getrpc(wrap_getrpcbynumber_r, key));
991 }
992
993 struct rpcent *
994 getrpcent()
995 {
996         union key key;
997
998         key.number = 0; /* not used */
999
1000         return (getrpc(wrap_getrpcent_r, key));
1001 }
1002
1003 void
1004 setrpcent(int stayopen)
1005 {
1006 #ifdef NS_CACHING
1007         static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
1008                 rpc, (void *)nss_lt_all,
1009                 NULL, NULL);
1010 #endif
1011
1012         static const ns_dtab dtab[] = {
1013                 { NSSRC_FILES, files_setrpcent, (void *)SETRPCENT },
1014 #ifdef YP
1015                 { NSSRC_NIS, nis_setrpcent, (void *)SETRPCENT },
1016 #endif
1017 #ifdef NS_CACHING
1018                 NS_CACHE_CB(&cache_info)
1019 #endif
1020                 { NULL, NULL, NULL }
1021         };
1022
1023         (void)nsdispatch(NULL, dtab, NSDB_RPC, "setrpcent", defaultsrc,
1024                 stayopen);
1025 }
1026
1027 void
1028 endrpcent()
1029 {
1030 #ifdef NS_CACHING
1031         static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
1032                 rpc, (void *)nss_lt_all,
1033                 NULL, NULL);
1034 #endif
1035
1036         static const ns_dtab dtab[] = {
1037                 { NSSRC_FILES, files_setrpcent, (void *)ENDRPCENT },
1038 #ifdef YP
1039                 { NSSRC_NIS, nis_setrpcent, (void *)ENDRPCENT },
1040 #endif
1041 #ifdef NS_CACHING
1042                 NS_CACHE_CB(&cache_info)
1043 #endif
1044                 { NULL, NULL, NULL }
1045         };
1046
1047         (void)nsdispatch(NULL, dtab, NSDB_RPC, "endrpcent", defaultsrc);
1048 }