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