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