Merge from vendor branch LIBARCHIVE:
[dragonfly.git] / contrib / bind-9.3 / lib / bind / irs / irpmarshall.c
1 /*
2  * Copyright(c) 1989, 1993, 1995
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 /*
35  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
36  * Portions Copyright (c) 1996 by Internet Software Consortium.
37  *
38  * Permission to use, copy, modify, and distribute this software for any
39  * purpose with or without fee is hereby granted, provided that the above
40  * copyright notice and this permission notice appear in all copies.
41  *
42  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
43  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
44  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
45  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
46  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
47  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
48  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
49  */
50
51 #if defined(LIBC_SCCS) && !defined(lint)
52 static const char rcsid[] = "$Id: irpmarshall.c,v 1.3.206.4 2006/03/10 00:17:21 marka Exp $";
53 #endif /* LIBC_SCCS and not lint */
54
55 #if 0
56
57 Check values are in approrpriate endian order.
58
59 Double check memory allocations on unmarhsalling
60
61 #endif
62
63
64 /* Extern */
65
66 #include "port_before.h"
67
68 #include <sys/types.h>
69 #include <sys/socket.h>
70
71 #include <netinet/in.h>
72 #include <arpa/inet.h>
73 #include <arpa/nameser.h>
74
75 #include <stdio.h>
76 #include <ctype.h>
77 #include <pwd.h>
78 #include <stdlib.h>
79 #include <string.h>
80 #include <syslog.h>
81 #include <utmp.h>
82 #include <unistd.h>
83 #include <assert.h>
84 #include <errno.h>
85
86 #include <irs.h>
87 #include <isc/memcluster.h>
88 #include <isc/irpmarshall.h>
89
90 #include "port_after.h"
91
92
93 #ifndef HAVE_STRNDUP
94 static char    *strndup(const char *str, size_t len);
95 #endif
96
97 static char   **splitarray(const char *buffer, const char *buffend, char delim);
98 static int      joinarray(char * const * argv, char *buffer, char delim);
99 static char    *getfield(char **res, size_t reslen, char **buffer, char delim);
100 static size_t   joinlength(char * const *argv);
101 static void     free_array(char **argv, size_t entries);
102
103 #define ADDR_T_STR(x) (x == AF_INET ? "AF_INET" :\
104                        (x == AF_INET6 ? "AF_INET6" : "UNKNOWN"))
105
106 #define MAXPADDRSIZE (sizeof "255.255.255.255" + 1)
107
108 static char COMMA = ',';
109
110 static const char *COMMASTR = ",";
111 static const char *COLONSTR = ":";
112
113
114
115 /* See big comment at bottom of irpmarshall.h for description. */
116
117
118 #ifdef WANT_IRS_PW
119 /* +++++++++++++++++++++++++ struct passwd +++++++++++++++++++++++++ */
120
121
122 /*
123  * int irp_marshall_pw(const struct passwd *pw, char **buffer, size_t *len)
124  *
125  * notes:
126  *
127  *      See above
128  *
129  * return:
130  *
131  *      0 on sucess, -1 on failure.
132  *
133  */
134
135 int
136 irp_marshall_pw(const struct passwd *pw, char **buffer, size_t *len) {
137         size_t need = 1 ;               /* for null byte */
138         char pwUid[24];
139         char pwGid[24];
140         char pwChange[24];
141         char pwExpire[24];
142         const char *pwClass;
143         const char *fieldsep = COLONSTR;
144
145         if (pw == NULL || len == NULL) {
146                 errno = EINVAL;
147                 return (-1);
148         }
149
150         sprintf(pwUid, "%ld", (long)pw->pw_uid);
151         sprintf(pwGid, "%ld", (long)pw->pw_gid);
152
153 #ifdef HAVE_PW_CHANGE
154         sprintf(pwChange, "%ld", (long)pw->pw_change);
155 #else
156         pwChange[0] = '0';
157         pwChange[1] = '\0';
158 #endif
159
160 #ifdef HAVE_PW_EXPIRE
161         sprintf(pwExpire, "%ld", (long)pw->pw_expire);
162 #else
163         pwExpire[0] = '0';
164         pwExpire[1] = '\0';
165 #endif
166
167 #ifdef HAVE_PW_CLASS
168         pwClass = pw->pw_class;
169 #else
170         pwClass = "";
171 #endif
172
173         need += strlen(pw->pw_name)     + 1; /* one for fieldsep */
174         need += strlen(pw->pw_passwd)   + 1;
175         need += strlen(pwUid)           + 1;
176         need += strlen(pwGid)           + 1;
177         need += strlen(pwClass)         + 1;
178         need += strlen(pwChange)        + 1;
179         need += strlen(pwExpire)        + 1;
180         need += strlen(pw->pw_gecos)    + 1;
181         need += strlen(pw->pw_dir)      + 1;
182         need += strlen(pw->pw_shell)    + 1;
183
184         if (buffer == NULL) {
185                 *len = need;
186                 return (0);
187         }
188
189         if (*buffer != NULL && need > *len) {
190                 errno = EINVAL;
191                 return (-1);
192         }
193
194         if (*buffer == NULL) {
195                 need += 2;              /* for CRLF */
196                 *buffer = memget(need);
197                 if (*buffer == NULL) {
198                         errno = ENOMEM;
199                         return (-1);
200                 }
201
202                 *len = need;
203         }
204
205         strcpy(*buffer, pw->pw_name);           strcat(*buffer, fieldsep);
206         strcat(*buffer, pw->pw_passwd);         strcat(*buffer, fieldsep);
207         strcat(*buffer, pwUid);                 strcat(*buffer, fieldsep);
208         strcat(*buffer, pwGid);                 strcat(*buffer, fieldsep);
209         strcat(*buffer, pwClass);               strcat(*buffer, fieldsep);
210         strcat(*buffer, pwChange);              strcat(*buffer, fieldsep);
211         strcat(*buffer, pwExpire);              strcat(*buffer, fieldsep);
212         strcat(*buffer, pw->pw_gecos);          strcat(*buffer, fieldsep);
213         strcat(*buffer, pw->pw_dir);            strcat(*buffer, fieldsep);
214         strcat(*buffer, pw->pw_shell);          strcat(*buffer, fieldsep);
215
216         return (0);
217 }
218
219
220
221
222
223 /*
224  * int irp_unmarshall_pw(struct passwd *pw, char *buffer)
225  *
226  * notes:
227  *
228  *      see above
229  *
230  * return:
231  *
232  *      0 on success, -1 on failure
233  *
234  */
235
236 int
237 irp_unmarshall_pw(struct passwd *pw, char *buffer) {
238         char *name, *pass, *class, *gecos, *dir, *shell;
239         uid_t pwuid;
240         gid_t pwgid;
241         time_t pwchange;
242         time_t pwexpire;
243         char *p;
244         long t;
245         char tmpbuf[24];
246         char *tb = &tmpbuf[0];
247         char fieldsep = ':';
248         int myerrno = EINVAL;
249
250         name = pass = class = gecos = dir = shell = NULL;
251         p = buffer;
252
253         /* pw_name field */
254         name = NULL;
255         if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) {
256                 goto error;
257         }
258
259         /* pw_passwd field */
260         pass = NULL;
261         if (getfield(&pass, 0, &p, fieldsep) == NULL) { /* field can be empty */
262                 goto error;
263         }
264
265
266         /* pw_uid field */
267         tb = tmpbuf;
268         if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
269             strlen(tb) == 0) {
270                 goto error;
271         }
272         t = strtol(tmpbuf, &tb, 10);
273         if (*tb) {
274                 goto error;     /* junk in value */
275         }
276         pwuid = (uid_t)t;
277         if ((long) pwuid != t) {        /* value must have been too big. */
278                 goto error;
279         }
280
281
282
283         /* pw_gid field */
284         tb = tmpbuf;
285         if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
286             strlen(tb) == 0) {
287                 goto error;
288         }
289         t = strtol(tmpbuf, &tb, 10);
290         if (*tb) {
291                 goto error;     /* junk in value */
292         }
293         pwgid = (gid_t)t;
294         if ((long)pwgid != t) { /* value must have been too big. */
295                 goto error;
296         }
297
298
299
300         /* pw_class field */
301         class = NULL;
302         if (getfield(&class, 0, &p, fieldsep) == NULL) {
303                 goto error;
304         }
305
306
307
308         /* pw_change field */
309         tb = tmpbuf;
310         if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
311             strlen(tb) == 0) {
312                 goto error;
313         }
314         t = strtol(tmpbuf, &tb, 10);
315         if (*tb) {
316                 goto error;     /* junk in value */
317         }
318         pwchange = (time_t)t;
319         if ((long)pwchange != t) {      /* value must have been too big. */
320                 goto error;
321         }
322
323
324
325         /* pw_expire field */
326         tb = tmpbuf;
327         if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
328             strlen(tb) == 0) {
329                 goto error;
330         }
331         t = strtol(tmpbuf, &tb, 10);
332         if (*tb) {
333                 goto error;     /* junk in value */
334         }
335         pwexpire = (time_t)t;
336         if ((long) pwexpire != t) {     /* value must have been too big. */
337                 goto error;
338         }
339
340
341
342         /* pw_gecos field */
343         gecos = NULL;
344         if (getfield(&gecos, 0, &p, fieldsep) == NULL) {
345                 goto error;
346         }
347
348
349
350         /* pw_dir field */
351         dir = NULL;
352         if (getfield(&dir, 0, &p, fieldsep) == NULL) {
353                 goto error;
354         }
355
356
357
358         /* pw_shell field */
359         shell = NULL;
360         if (getfield(&shell, 0, &p, fieldsep) == NULL) {
361                 goto error;
362         }
363
364
365
366         pw->pw_name = name;
367         pw->pw_passwd = pass;
368         pw->pw_uid = pwuid;
369         pw->pw_gid = pwgid;
370         pw->pw_gecos = gecos;
371         pw->pw_dir = dir;
372         pw->pw_shell = shell;
373
374 #ifdef HAVE_PW_CHANGE
375         pw->pw_change = pwchange;
376 #endif
377 #ifdef HAVE_PW_CLASS
378         pw->pw_class = class;
379 #endif
380 #ifdef HAVE_PW_EXPIRE
381         pw->pw_expire = pwexpire;
382 #endif
383
384         return (0);
385
386  error:
387         errno = myerrno;
388
389         if (name != NULL) free(name);
390         if (pass != NULL) free(pass);
391         if (gecos != NULL) free(gecos);
392         if (dir != NULL) free(dir);
393         if (shell != NULL) free(shell);
394
395         return (-1);
396 }
397
398 /* ------------------------- struct passwd ------------------------- */
399 #endif /* WANT_IRS_PW */
400
401
402
403 /* +++++++++++++++++++++++++ struct group +++++++++++++++++++++++++ */
404
405
406
407 /*
408  * int irp_marshall_gr(const struct group *gr, char **buffer, size_t *len)
409  *
410  * notes:
411  *
412  *      see above.
413  *
414  * return:
415  *
416  *      0 on success, -1 on failure
417  */
418
419 int
420 irp_marshall_gr(const struct group *gr, char **buffer, size_t *len) {
421         size_t need = 1;        /* for null byte */
422         char grGid[24];
423         const char *fieldsep = COLONSTR;
424
425         if (gr == NULL || len == NULL) {
426                 errno = EINVAL;
427                 return (-1);
428         }
429
430         sprintf(grGid, "%ld", (long)gr->gr_gid);
431
432         need += strlen(gr->gr_name) + 1;
433 #ifndef MISSING_GR_PASSWD
434         need += strlen(gr->gr_passwd) + 1;
435 #else
436         need++;
437 #endif
438         need += strlen(grGid) + 1;
439         need += joinlength(gr->gr_mem) + 1;
440
441         if (buffer == NULL) {
442                 *len = need;
443                 return (0);
444         }
445
446         if (*buffer != NULL && need > *len) {
447                 errno = EINVAL;
448                 return (-1);
449         }
450
451         if (*buffer == NULL) {
452                 need += 2;              /* for CRLF */
453                 *buffer = memget(need);
454                 if (*buffer == NULL) {
455                         errno = ENOMEM;
456                         return (-1);
457                 }
458
459                 *len = need;
460         }
461
462         strcpy(*buffer, gr->gr_name);           strcat(*buffer, fieldsep);
463 #ifndef MISSING_GR_PASSWD
464         strcat(*buffer, gr->gr_passwd);
465 #endif
466         strcat(*buffer, fieldsep);
467         strcat(*buffer, grGid);                 strcat(*buffer, fieldsep);
468         joinarray(gr->gr_mem, *buffer, COMMA) ; strcat(*buffer, fieldsep);
469
470         return (0);
471 }
472
473
474
475
476 /*
477  * int irp_unmarshall_gr(struct group *gr, char *buffer)
478  *
479  * notes:
480  *
481  *      see above
482  *
483  * return:
484  *
485  *      0 on success and -1 on failure.
486  *
487  */
488
489 int
490 irp_unmarshall_gr(struct group *gr, char *buffer) {
491         char *p, *q;
492         gid_t grgid;
493         long t;
494         char *name = NULL;
495         char *pass = NULL;
496         char **members = NULL;
497         char tmpbuf[24];
498         char *tb;
499         char fieldsep = ':';
500         int myerrno = EINVAL;
501
502         if (gr == NULL || buffer == NULL) {
503                 errno = EINVAL;
504                 return (-1);
505         }
506
507         p = buffer;
508
509         /* gr_name field */
510         name = NULL;
511         if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) {
512                 goto error;
513         }
514
515
516         /* gr_passwd field */
517         pass = NULL;
518         if (getfield(&pass, 0, &p, fieldsep) == NULL) {
519                 goto error;
520         }
521
522
523         /* gr_gid field */
524         tb = tmpbuf;
525         if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
526             strlen(tb) == 0U) {
527                 goto error;
528         }
529         t = strtol(tmpbuf, &tb, 10);
530         if (*tb) {
531                 goto error;     /* junk in value */
532         }
533         grgid = (gid_t)t;
534         if ((long) grgid != t) {        /* value must have been too big. */
535                 goto error;
536         }
537
538
539         /* gr_mem field. Member names are separated by commas */
540         q = strchr(p, fieldsep);
541         if (q == NULL) {
542                 goto error;
543         }
544         members = splitarray(p, q, COMMA);
545         if (members == NULL) {
546                 myerrno = errno;
547                 goto error;
548         }
549         p = q + 1;
550
551
552         gr->gr_name = name;
553 #ifndef MISSING_GR_PASSWD
554         gr->gr_passwd = pass;
555 #endif
556         gr->gr_gid = grgid;
557         gr->gr_mem = members;
558
559         return (0);
560
561  error:
562         errno = myerrno;
563
564         if (name != NULL) free(name);
565         if (pass != NULL) free(pass);
566
567         return (-1);
568 }
569
570
571 /* ------------------------- struct group ------------------------- */
572
573
574
575
576 /* +++++++++++++++++++++++++ struct servent +++++++++++++++++++++++++ */
577
578
579
580 /*
581  * int irp_marshall_sv(const struct servent *sv, char **buffer, size_t *len)
582  *
583  * notes:
584  *
585  *      see above
586  *
587  * return:
588  *
589  *      0 on success, -1 on failure.
590  *
591  */
592
593 int
594 irp_marshall_sv(const struct servent *sv, char **buffer, size_t *len) {
595         size_t need = 1;        /* for null byte */
596         char svPort[24];
597         const char *fieldsep = COLONSTR;
598         short realport;
599
600         if (sv == NULL || len == NULL) {
601                 errno = EINVAL;
602                 return (-1);
603         }
604
605         /* the int s_port field is actually a short in network order. We
606            want host order to make the marshalled data look correct */
607         realport = ntohs((short)sv->s_port);
608         sprintf(svPort, "%d", realport);
609
610         need += strlen(sv->s_name) + 1;
611         need += joinlength(sv->s_aliases) + 1;
612         need += strlen(svPort) + 1;
613         need += strlen(sv->s_proto) + 1;
614
615         if (buffer == NULL) {
616                 *len = need;
617                 return (0);
618         }
619
620         if (*buffer != NULL && need > *len) {
621                 errno = EINVAL;
622                 return (-1);
623         }
624
625         if (*buffer == NULL) {
626                 need += 2;              /* for CRLF */
627                 *buffer = memget(need);
628                 if (*buffer == NULL) {
629                         errno = ENOMEM;
630                         return (-1);
631                 }
632
633                 *len = need;
634         }
635
636         strcpy(*buffer, sv->s_name);            strcat(*buffer, fieldsep);
637         joinarray(sv->s_aliases, *buffer, COMMA); strcat(*buffer, fieldsep);
638         strcat(*buffer, svPort);                strcat(*buffer, fieldsep);
639         strcat(*buffer, sv->s_proto);           strcat(*buffer, fieldsep);
640
641         return (0);
642 }
643
644
645
646
647
648 /*
649  * int irp_unmarshall_sv(struct servent *sv, char *buffer)
650  *
651  * notes:
652  *
653  *      see above
654  *
655  * return:
656  *
657  *      0 on success, -1 on failure.
658  *
659  */
660
661 int
662 irp_unmarshall_sv(struct servent *sv, char *buffer) {
663         char *p, *q;
664         short svport;
665         long t;
666         char *name = NULL;
667         char *proto = NULL;
668         char **aliases = NULL;
669         char tmpbuf[24];
670         char *tb;
671         char fieldsep = ':';
672         int myerrno = EINVAL;
673
674         if (sv == NULL || buffer == NULL)
675                 return (-1);
676
677         p = buffer;
678
679
680         /* s_name field */
681         name = NULL;
682         if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) {
683                 goto error;
684         }
685
686
687         /* s_aliases field */
688         q = strchr(p, fieldsep);
689         if (q == NULL) {
690                 goto error;
691         }
692         aliases = splitarray(p, q, COMMA);
693         if (aliases == NULL) {
694                 myerrno = errno;
695                 goto error;
696         }
697         p = q + 1;
698
699
700         /* s_port field */
701         tb = tmpbuf;
702         if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
703             strlen(tb) == 0U) {
704                 goto error;
705         }
706         t = strtol(tmpbuf, &tb, 10);
707         if (*tb) {
708                 goto error;     /* junk in value */
709         }
710         svport = (short)t;
711         if ((long) svport != t) {       /* value must have been too big. */
712                 goto error;
713         }
714         svport = htons(svport);
715
716         /* s_proto field */
717         proto = NULL;
718         if (getfield(&proto, 0, &p, fieldsep) == NULL) {
719                 goto error;
720         }
721
722         sv->s_name = name;
723         sv->s_aliases = aliases;
724         sv->s_port = svport;
725         sv->s_proto = proto;
726
727         return (0);
728
729  error:
730         errno = myerrno;
731
732         if (name != NULL) free(name);
733         if (proto != NULL) free(proto);
734         free_array(aliases, 0);
735
736         return (-1);
737 }
738
739
740 /* ------------------------- struct servent ------------------------- */
741
742 /* +++++++++++++++++++++++++ struct protoent +++++++++++++++++++++++++ */
743
744
745
746 /*
747  * int irp_marshall_pr(struct protoent *pr, char **buffer, size_t *len)
748  *
749  * notes:
750  *
751  *      see above
752  *
753  * return:
754  *
755  *      0 on success and -1 on failure.
756  *
757  */
758
759 int
760 irp_marshall_pr(struct protoent *pr, char **buffer, size_t *len) {
761         size_t need = 1;        /* for null byte */
762         char prProto[24];
763         const char *fieldsep = COLONSTR;
764
765         if (pr == NULL || len == NULL) {
766                 errno = EINVAL;
767                 return (-1);
768         }
769
770         sprintf(prProto, "%d", (int)pr->p_proto);
771
772         need += strlen(pr->p_name) + 1;
773         need += joinlength(pr->p_aliases) + 1;
774         need += strlen(prProto) + 1;
775
776         if (buffer == NULL) {
777                 *len = need;
778                 return (0);
779         }
780
781         if (*buffer != NULL && need > *len) {
782                 errno = EINVAL;
783                 return (-1);
784         }
785
786         if (*buffer == NULL) {
787                 need += 2;              /* for CRLF */
788                 *buffer = memget(need);
789                 if (*buffer == NULL) {
790                         errno = ENOMEM;
791                         return (-1);
792                 }
793
794                 *len = need;
795         }
796
797         strcpy(*buffer, pr->p_name);            strcat(*buffer, fieldsep);
798         joinarray(pr->p_aliases, *buffer, COMMA); strcat(*buffer, fieldsep);
799         strcat(*buffer, prProto);               strcat(*buffer, fieldsep);
800
801         return (0);
802
803 }
804
805
806
807 /*
808  * int irp_unmarshall_pr(struct protoent *pr, char *buffer)
809  *
810  * notes:
811  *
812  *      See above
813  *
814  * return:
815  *
816  *      0 on success, -1 on failure
817  *
818  */
819
820 int irp_unmarshall_pr(struct protoent *pr, char *buffer) {
821         char *p, *q;
822         int prproto;
823         long t;
824         char *name = NULL;
825         char **aliases = NULL;
826         char tmpbuf[24];
827         char *tb;
828         char fieldsep = ':';
829         int myerrno = EINVAL;
830
831         if (pr == NULL || buffer == NULL) {
832                 errno = EINVAL;
833                 return (-1);
834         }
835
836         p = buffer;
837
838         /* p_name field */
839         name = NULL;
840         if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) {
841                 goto error;
842         }
843
844
845         /* p_aliases field */
846         q = strchr(p, fieldsep);
847         if (q == NULL) {
848                 goto error;
849         }
850         aliases = splitarray(p, q, COMMA);
851         if (aliases == NULL) {
852                 myerrno = errno;
853                 goto error;
854         }
855         p = q + 1;
856
857
858         /* p_proto field */
859         tb = tmpbuf;
860         if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
861             strlen(tb) == 0U) {
862                 goto error;
863         }
864         t = strtol(tmpbuf, &tb, 10);
865         if (*tb) {
866                 goto error;     /* junk in value */
867         }
868         prproto = (int)t;
869         if ((long) prproto != t) {      /* value must have been too big. */
870                 goto error;
871         }
872
873         pr->p_name = name;
874         pr->p_aliases = aliases;
875         pr->p_proto = prproto;
876
877         return (0);
878
879  error:
880         errno = myerrno;
881
882         if (name != NULL) free(name);
883         free_array(aliases, 0);
884
885         return (-1);
886 }
887
888 /* ------------------------- struct protoent ------------------------- */
889
890
891
892 /* +++++++++++++++++++++++++ struct hostent +++++++++++++++++++++++++ */
893
894
895 /*
896  * int irp_marshall_ho(struct hostent *ho, char **buffer, size_t *len)
897  *
898  * notes:
899  *
900  *      see above.
901  *
902  * return:
903  *
904  *      0 on success, -1 on failure.
905  *
906  */
907
908 int
909 irp_marshall_ho(struct hostent *ho, char **buffer, size_t *len) {
910         size_t need = 1;        /* for null byte */
911         char hoaddrtype[24];
912         char holength[24];
913         char **av;
914         char *p;
915         int addrlen;
916         int malloced = 0;
917         size_t remlen;
918         const char *fieldsep = "@";
919
920         if (ho == NULL || len == NULL) {
921                 errno = EINVAL;
922                 return (-1);
923         }
924
925         switch(ho->h_addrtype) {
926         case AF_INET:
927                 strcpy(hoaddrtype, "AF_INET");
928                 break;
929
930         case AF_INET6:
931                 strcpy(hoaddrtype, "AF_INET6");
932                 break;
933
934         default:
935                 errno = EINVAL;
936                 return (-1);
937         }
938
939         sprintf(holength, "%d", ho->h_length);
940
941         need += strlen(ho->h_name) + 1;
942         need += joinlength(ho->h_aliases) + 1;
943         need += strlen(hoaddrtype) + 1;
944         need += strlen(holength) + 1;
945
946         /* we determine an upper bound on the string length needed, not an
947            exact length. */
948         addrlen = (ho->h_addrtype == AF_INET ? 16 : 46) ; /* XX other AF's?? */
949         for (av = ho->h_addr_list; av != NULL && *av != NULL ; av++)
950                 need += addrlen;
951
952         if (buffer == NULL) {
953                 *len = need;
954                 return (0);
955         }
956
957         if (*buffer != NULL && need > *len) {
958                 errno = EINVAL;
959                 return (-1);
960         }
961
962         if (*buffer == NULL) {
963                 need += 2;              /* for CRLF */
964                 *buffer = memget(need);
965                 if (*buffer == NULL) {
966                         errno = ENOMEM;
967                         return (-1);
968                 }
969
970                 *len = need;
971                 malloced = 1;
972         }
973
974         strcpy(*buffer, ho->h_name);            strcat(*buffer, fieldsep);
975         joinarray(ho->h_aliases, *buffer, COMMA); strcat(*buffer, fieldsep);
976         strcat(*buffer, hoaddrtype);            strcat(*buffer, fieldsep);
977         strcat(*buffer, holength);              strcat(*buffer, fieldsep);
978
979         p = *buffer + strlen(*buffer);
980         remlen = need - strlen(*buffer);
981         for (av = ho->h_addr_list ; av != NULL && *av != NULL ; av++) {
982                 if (inet_ntop(ho->h_addrtype, *av, p, remlen) == NULL) {
983                         goto error;
984                 }
985                 if (*(av + 1) != NULL)
986                         strcat(p, COMMASTR);
987                 remlen -= strlen(p);
988                 p += strlen(p);
989         }
990         strcat(*buffer, fieldsep);
991
992         return (0);
993
994  error:
995         if (malloced) {
996                 memput(*buffer, need);
997         }
998
999         return (-1);
1000 }
1001
1002
1003
1004 /*
1005  * int irp_unmarshall_ho(struct hostent *ho, char *buffer)
1006  *
1007  * notes:
1008  *
1009  *      See above.
1010  *
1011  * return:
1012  *
1013  *      0 on success, -1 on failure.
1014  *
1015  */
1016
1017 int
1018 irp_unmarshall_ho(struct hostent *ho, char *buffer) {
1019         char *p, *q, *r;
1020         int hoaddrtype;
1021         int holength;
1022         long t;
1023         char *name;
1024         char **aliases = NULL;
1025         char **hohaddrlist = NULL;
1026         size_t hoaddrsize;
1027         char tmpbuf[24];
1028         char *tb;
1029         char **alist;
1030         int addrcount;
1031         char fieldsep = '@';
1032         int myerrno = EINVAL;
1033
1034         if (ho == NULL || buffer == NULL) {
1035                 errno = EINVAL;
1036                 return (-1);
1037         }
1038
1039         p = buffer;
1040
1041         /* h_name field */
1042         name = NULL;
1043         if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) {
1044                 goto error;
1045         }
1046
1047
1048         /* h_aliases field */
1049         q = strchr(p, fieldsep);
1050         if (q == NULL) {
1051                 goto error;
1052         }
1053         aliases = splitarray(p, q, COMMA);
1054         if (aliases == NULL) {
1055                 myerrno = errno;
1056                 goto error;
1057         }
1058         p = q + 1;
1059
1060
1061         /* h_addrtype field */
1062         tb = tmpbuf;
1063         if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
1064             strlen(tb) == 0U) {
1065                 goto error;
1066         }
1067         if (strcmp(tmpbuf, "AF_INET") == 0)
1068                 hoaddrtype = AF_INET;
1069         else if (strcmp(tmpbuf, "AF_INET6") == 0)
1070                 hoaddrtype = AF_INET6;
1071         else
1072                 goto error;
1073
1074
1075         /* h_length field */
1076         tb = tmpbuf;
1077         if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
1078             strlen(tb) == 0U) {
1079                 goto error;
1080         }
1081         t = strtol(tmpbuf, &tb, 10);
1082         if (*tb) {
1083                 goto error;     /* junk in value */
1084         }
1085         holength = (int)t;
1086         if ((long) holength != t) {     /* value must have been too big. */
1087                 goto error;
1088         }
1089
1090
1091         /* h_addr_list field */
1092         q = strchr(p, fieldsep);
1093         if (q == NULL)
1094                 goto error;
1095
1096         /* count how many addresss are in there */
1097         if (q > p + 1) {
1098                 for (addrcount = 1, r = p ; r != q ; r++) {
1099                         if (*r == COMMA)
1100                                 addrcount++;
1101                 }
1102         } else {
1103                 addrcount = 0;
1104         }
1105
1106         hoaddrsize = (addrcount + 1) * sizeof (char *);
1107         hohaddrlist = malloc(hoaddrsize);
1108         if (hohaddrlist == NULL) {
1109                 myerrno = ENOMEM;
1110                 goto error;
1111         }
1112
1113         memset(hohaddrlist, 0x0, hoaddrsize);
1114
1115         alist = hohaddrlist;
1116         for (t = 0, r = p ; r != q ; p = r + 1, t++) {
1117                 char saved;
1118                 while (r != q && *r != COMMA) r++;
1119                 saved = *r;
1120                 *r = 0x0;
1121
1122                 alist[t] = malloc(hoaddrtype == AF_INET ? 4 : 16);
1123                 if (alist[t] == NULL) {
1124                         myerrno = ENOMEM;
1125                         goto error;
1126                 }
1127
1128                 if (inet_pton(hoaddrtype, p, alist[t]) == -1)
1129                         goto error;
1130                 *r = saved;
1131         }
1132         alist[t] = NULL;
1133
1134         ho->h_name = name;
1135         ho->h_aliases = aliases;
1136         ho->h_addrtype = hoaddrtype;
1137         ho->h_length = holength;
1138         ho->h_addr_list = hohaddrlist;
1139
1140         return (0);
1141
1142  error:
1143         errno = myerrno;
1144
1145         if (name != NULL) free(name);
1146         free_array(hohaddrlist, 0);
1147         free_array(aliases, 0);
1148
1149         return (-1);
1150 }
1151
1152 /* ------------------------- struct hostent------------------------- */
1153
1154
1155
1156 /* +++++++++++++++++++++++++ struct netgrp +++++++++++++++++++++++++ */
1157
1158
1159 /*
1160  * int irp_marshall_ng(const char *host, const char *user,
1161  *                     const char *domain, char *buffer, size_t *len)
1162  *
1163  * notes:
1164  *
1165  *      See note for irp_marshall_ng_start
1166  *
1167  * return:
1168  *
1169  *      0 on success, 0 on failure.
1170  *
1171  */
1172
1173 int
1174 irp_marshall_ng(const char *host, const char *user, const char *domain,
1175                 char **buffer, size_t *len) {
1176         size_t need = 1; /* for nul byte */
1177         const char *fieldsep = ",";
1178
1179         if (len == NULL) {
1180                 errno = EINVAL;
1181                 return (-1);
1182         }
1183
1184         need += 4;                     /* two parens and two commas */
1185         need += (host == NULL ? 0 : strlen(host));
1186         need += (user == NULL ? 0 : strlen(user));
1187         need += (domain == NULL ? 0 : strlen(domain));
1188
1189         if (buffer == NULL) {
1190                 *len = need;
1191                 return (0);
1192         } else if (*buffer != NULL && need > *len) {
1193                 errno = EINVAL;
1194                 return (-1);
1195         }
1196
1197         if (*buffer == NULL) {
1198                 need += 2;              /* for CRLF */
1199                 *buffer = memget(need);
1200                 if (*buffer == NULL) {
1201                         errno = ENOMEM;
1202                         return (-1);
1203                 }
1204
1205                 *len = need;
1206         }
1207
1208         (*buffer)[0] = '(';
1209         (*buffer)[1] = '\0';
1210
1211         if (host != NULL)
1212                 strcat(*buffer, host);
1213         strcat(*buffer, fieldsep);
1214
1215         if (user != NULL)
1216                 strcat(*buffer, user);
1217         strcat(*buffer, fieldsep);
1218
1219         if (domain != NULL)
1220                 strcat(*buffer, domain);
1221         strcat(*buffer, ")");
1222
1223         return (0);
1224 }
1225
1226
1227
1228 /* ---------- */
1229
1230
1231 /*
1232  * int irp_unmarshall_ng(const char **host, const char **user,
1233  *                       const char **domain, char *buffer)
1234  *
1235  * notes:
1236  *
1237  *      Unpacks the BUFFER into 3 character arrays it allocates and assigns
1238  *      to *HOST, *USER and *DOMAIN. If any field of the value is empty,
1239  *      then the corresponding paramater value will be set to NULL.
1240  *
1241  * return:
1242  *
1243  *      0 on success and -1 on failure.
1244  */
1245
1246 int
1247 irp_unmarshall_ng(const char **hostp, const char **userp, const char **domainp,
1248                   char *buffer)
1249 {
1250         char *p, *q;
1251         char fieldsep = ',';
1252         int myerrno = EINVAL;
1253         char *host, *user, *domain;
1254
1255         if (userp == NULL || hostp == NULL ||
1256             domainp == NULL || buffer == NULL) {
1257                 errno = EINVAL;
1258                 return (-1);
1259         }
1260
1261         host = user = domain = NULL;
1262
1263         p = buffer;
1264         while (isspace((unsigned char)*p)) {
1265                 p++;
1266         }
1267         if (*p != '(') {
1268                 goto error;
1269         }
1270
1271         q = p + 1;
1272         while (*q && *q != fieldsep)
1273                 q++;
1274         if (!*q) {
1275                 goto error;
1276         } else if (q > p + 1) {
1277                 host = strndup(p, q - p);
1278         }
1279
1280         p = q + 1;
1281         if (!*p) {
1282                 goto error;
1283         } else if (*p != fieldsep) {
1284                 q = p + 1;
1285                 while (*q && *q != fieldsep)
1286                         q++;
1287                 if (!*q) {
1288                         goto error;
1289                 }
1290                 user = strndup(p, q - p);
1291         } else {
1292                 p++;
1293         }
1294
1295         if (!*p) {
1296                 goto error;
1297         } else if (*p != ')') {
1298                 q = p + 1;
1299                 while (*q && *q != ')')
1300                         q++;
1301                 if (!*q) {
1302                         goto error;
1303                 }
1304                 domain = strndup(p, q - p);
1305         }
1306         *hostp = host;
1307         *userp = user;
1308         *domainp = domain;
1309
1310         return (0);
1311
1312  error:
1313         errno = myerrno;
1314
1315         if (host != NULL) free(host);
1316         if (user != NULL) free(user);
1317
1318         return (-1);
1319 }
1320
1321 /* ------------------------- struct netgrp ------------------------- */
1322
1323
1324
1325
1326 /* +++++++++++++++++++++++++ struct nwent +++++++++++++++++++++++++ */
1327
1328
1329 /*
1330  * int irp_marshall_nw(struct nwent *ne, char **buffer, size_t *len)
1331  *
1332  * notes:
1333  *
1334  *      See at top.
1335  *
1336  * return:
1337  *
1338  *      0 on success and -1 on failure.
1339  *
1340  */
1341
1342 int
1343 irp_marshall_nw(struct nwent *ne, char **buffer, size_t *len) {
1344         size_t need = 1;        /* for null byte */
1345         char nAddrType[24];
1346         char nNet[MAXPADDRSIZE];
1347         const char *fieldsep = COLONSTR;
1348
1349         if (ne == NULL || len == NULL) {
1350                 return (-1);
1351         }
1352
1353         strcpy(nAddrType, ADDR_T_STR(ne->n_addrtype));
1354
1355         if (inet_net_ntop(ne->n_addrtype, ne->n_addr, ne->n_length,
1356                           nNet, sizeof nNet) == NULL) {
1357                 return (-1);
1358         }
1359
1360
1361         need += strlen(ne->n_name) + 1;
1362         need += joinlength(ne->n_aliases) + 1;
1363         need += strlen(nAddrType) + 1;
1364         need += strlen(nNet) + 1;
1365
1366         if (buffer == NULL) {
1367                 *len = need;
1368                 return (0);
1369         }
1370
1371         if (*buffer != NULL && need > *len) {
1372                 errno = EINVAL;
1373                 return (-1);
1374         }
1375
1376         if (*buffer == NULL) {
1377                 need += 2;              /* for CRLF */
1378                 *buffer = memget(need);
1379                 if (*buffer == NULL) {
1380                         errno = ENOMEM;
1381                         return (-1);
1382                 }
1383
1384                 *len = need;
1385         }
1386
1387         strcpy(*buffer, ne->n_name);            strcat(*buffer, fieldsep);
1388         joinarray(ne->n_aliases, *buffer, COMMA) ; strcat(*buffer, fieldsep);
1389         strcat(*buffer, nAddrType);             strcat(*buffer, fieldsep);
1390         strcat(*buffer, nNet);                  strcat(*buffer, fieldsep);
1391
1392         return (0);
1393 }
1394
1395
1396
1397 /*
1398  * int irp_unmarshall_nw(struct nwent *ne, char *buffer)
1399  *
1400  * notes:
1401  *
1402  *      See note up top.
1403  *
1404  * return:
1405  *
1406  *      0 on success and -1 on failure.
1407  *
1408  */
1409
1410 int
1411 irp_unmarshall_nw(struct nwent *ne, char *buffer) {
1412         char *p, *q;
1413         int naddrtype;
1414         long nnet;
1415         int bits;
1416         char *name = NULL;
1417         char **aliases = NULL;
1418         char tmpbuf[24];
1419         char *tb;
1420         char fieldsep = ':';
1421         int myerrno = EINVAL;
1422
1423         if (ne == NULL || buffer == NULL) {
1424                 goto error;
1425         }
1426
1427         p = buffer;
1428
1429         /* n_name field */
1430         name = NULL;
1431         if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) {
1432                 goto error;
1433         }
1434
1435
1436         /* n_aliases field. Aliases are separated by commas */
1437         q = strchr(p, fieldsep);
1438         if (q == NULL) {
1439                 goto error;
1440         }
1441         aliases = splitarray(p, q, COMMA);
1442         if (aliases == NULL) {
1443                 myerrno = errno;
1444                 goto error;
1445         }
1446         p = q + 1;
1447
1448
1449         /* h_addrtype field */
1450         tb = tmpbuf;
1451         if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
1452             strlen(tb) == 0U) {
1453                 goto error;
1454         }
1455         if (strcmp(tmpbuf, "AF_INET") == 0)
1456                 naddrtype = AF_INET;
1457         else if (strcmp(tmpbuf, "AF_INET6") == 0)
1458                 naddrtype = AF_INET6;
1459         else
1460                 goto error;
1461
1462
1463         /* n_net field */
1464         tb = tmpbuf;
1465         if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
1466             strlen(tb) == 0U) {
1467                 goto error;
1468         }
1469         nnet = 0;
1470         bits = inet_net_pton(naddrtype, tmpbuf, &nnet, sizeof nnet);
1471         if (bits < 0) {
1472                 goto error;
1473         }
1474
1475         /* nnet = ntohl(nnet); */ /* keep in network order for nwent */
1476
1477         ne->n_name = name;
1478         ne->n_aliases = aliases;
1479         ne->n_addrtype = naddrtype;
1480         ne->n_length = bits;
1481         ne->n_addr = malloc(sizeof nnet);
1482         if (ne->n_addr == NULL) {
1483                 goto error;
1484         }
1485
1486         memcpy(ne->n_addr, &nnet, sizeof nnet);
1487
1488         return (0);
1489
1490  error:
1491         errno = myerrno;
1492
1493         if (name != NULL) free(name);
1494         free_array(aliases, 0);
1495
1496         return (-1);
1497 }
1498
1499
1500 /* ------------------------- struct nwent ------------------------- */
1501
1502
1503 /* +++++++++++++++++++++++++ struct netent +++++++++++++++++++++++++ */
1504
1505
1506 /*
1507  * int irp_marshall_ne(struct netent *ne, char **buffer, size_t *len)
1508  *
1509  * notes:
1510  *
1511  *      See at top.
1512  *
1513  * return:
1514  *
1515  *      0 on success and -1 on failure.
1516  *
1517  */
1518
1519 int
1520 irp_marshall_ne(struct netent *ne, char **buffer, size_t *len) {
1521         size_t need = 1;        /* for null byte */
1522         char nAddrType[24];
1523         char nNet[MAXPADDRSIZE];
1524         const char *fieldsep = COLONSTR;
1525         long nval;
1526
1527         if (ne == NULL || len == NULL) {
1528                 return (-1);
1529         }
1530
1531         strcpy(nAddrType, ADDR_T_STR(ne->n_addrtype));
1532
1533         nval = htonl(ne->n_net);
1534         if (inet_ntop(ne->n_addrtype, &nval, nNet, sizeof nNet) == NULL) {
1535                 return (-1);
1536         }
1537
1538         need += strlen(ne->n_name) + 1;
1539         need += joinlength(ne->n_aliases) + 1;
1540         need += strlen(nAddrType) + 1;
1541         need += strlen(nNet) + 1;
1542
1543         if (buffer == NULL) {
1544                 *len = need;
1545                 return (0);
1546         }
1547
1548         if (*buffer != NULL && need > *len) {
1549                 errno = EINVAL;
1550                 return (-1);
1551         }
1552
1553         if (*buffer == NULL) {
1554                 need += 2;              /* for CRLF */
1555                 *buffer = memget(need);
1556                 if (*buffer == NULL) {
1557                         errno = ENOMEM;
1558                         return (-1);
1559                 }
1560
1561                 *len = need;
1562         }
1563
1564         strcpy(*buffer, ne->n_name);            strcat(*buffer, fieldsep);
1565         joinarray(ne->n_aliases, *buffer, COMMA) ; strcat(*buffer, fieldsep);
1566         strcat(*buffer, nAddrType);             strcat(*buffer, fieldsep);
1567         strcat(*buffer, nNet);                  strcat(*buffer, fieldsep);
1568
1569         return (0);
1570 }
1571
1572
1573
1574 /*
1575  * int irp_unmarshall_ne(struct netent *ne, char *buffer)
1576  *
1577  * notes:
1578  *
1579  *      See note up top.
1580  *
1581  * return:
1582  *
1583  *      0 on success and -1 on failure.
1584  *
1585  */
1586
1587 int
1588 irp_unmarshall_ne(struct netent *ne, char *buffer) {
1589         char *p, *q;
1590         int naddrtype;
1591         long nnet;
1592         int bits;
1593         char *name = NULL;
1594         char **aliases = NULL;
1595         char tmpbuf[24];
1596         char *tb;
1597         char fieldsep = ':';
1598         int myerrno = EINVAL;
1599
1600         if (ne == NULL || buffer == NULL) {
1601                 goto error;
1602         }
1603
1604         p = buffer;
1605
1606         /* n_name field */
1607         name = NULL;
1608         if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) {
1609                 goto error;
1610         }
1611
1612
1613         /* n_aliases field. Aliases are separated by commas */
1614         q = strchr(p, fieldsep);
1615         if (q == NULL) {
1616                 goto error;
1617         }
1618         aliases = splitarray(p, q, COMMA);
1619         if (aliases == NULL) {
1620                 myerrno = errno;
1621                 goto error;
1622         }
1623         p = q + 1;
1624
1625
1626         /* h_addrtype field */
1627         tb = tmpbuf;
1628         if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
1629             strlen(tb) == 0U) {
1630                 goto error;
1631         }
1632         if (strcmp(tmpbuf, "AF_INET") == 0)
1633                 naddrtype = AF_INET;
1634         else if (strcmp(tmpbuf, "AF_INET6") == 0)
1635                 naddrtype = AF_INET6;
1636         else
1637                 goto error;
1638
1639
1640         /* n_net field */
1641         tb = tmpbuf;
1642         if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
1643             strlen(tb) == 0U) {
1644                 goto error;
1645         }
1646         bits = inet_net_pton(naddrtype, tmpbuf, &nnet, sizeof nnet);
1647         if (bits < 0) {
1648                 goto error;
1649         }
1650         nnet = ntohl(nnet);
1651
1652         ne->n_name = name;
1653         ne->n_aliases = aliases;
1654         ne->n_addrtype = naddrtype;
1655         ne->n_net = nnet;
1656
1657         return (0);
1658
1659  error:
1660         errno = myerrno;
1661
1662         if (name != NULL) free(name);
1663         free_array(aliases, 0);
1664
1665         return (-1);
1666 }
1667
1668
1669 /* ------------------------- struct netent ------------------------- */
1670
1671
1672 /* =========================================================================== */
1673
1674
1675 /*
1676  * static char ** splitarray(const char *buffer, const char *buffend, char delim)
1677  *
1678  * notes:
1679  *
1680  *      Split a delim separated astring. Not allowed
1681  *      to have two delims next to each other. BUFFER points to begining of
1682  *      string, BUFFEND points to one past the end of the string
1683  *      (i.e. points at where the null byte would be if null
1684  *      terminated).
1685  *
1686  * return:
1687  *
1688  *      Returns a malloced array of pointers, each pointer pointing to a
1689  *      malloced string. If BUFEER is an empty string, then return values is
1690  *      array of 1 pointer that is NULL. Returns NULL on failure.
1691  *
1692  */
1693
1694 static char **
1695 splitarray(const char *buffer, const char *buffend, char delim) {
1696         const char *p, *q;
1697         int count = 0;
1698         char **arr = NULL;
1699         char **aptr;
1700
1701         if (buffend < buffer)
1702                 return (NULL);
1703         else if (buffend > buffer && *buffer == delim)
1704                 return (NULL);
1705         else if (buffend > buffer && *(buffend - 1) == delim)
1706                 return (NULL);
1707
1708         /* count the number of field and make sure none are empty */
1709         if (buffend > buffer + 1) {
1710                 for (count = 1, q = buffer ; q != buffend ; q++) {
1711                         if (*q == delim) {
1712                                 if (q > buffer && (*(q - 1) == delim)) {
1713                                         errno = EINVAL;
1714                                         return (NULL);
1715                                 }
1716                                 count++;
1717                         }
1718                 }
1719         }
1720
1721         if (count > 0) {
1722                 count++ ;               /* for NULL at end */
1723                 aptr = arr = malloc(count * sizeof (char *));
1724                 if (aptr == NULL) {
1725                          errno = ENOMEM;
1726                          return (NULL);
1727                  }
1728
1729                 memset(arr, 0x0, count * sizeof (char *));
1730                 for (p = buffer ; p < buffend ; p++) {
1731                         for (q = p ; *q != delim && q != buffend ; q++)
1732                                 /* nothing */;
1733                         *aptr = strndup(p, q - p);
1734
1735                         p = q;
1736                         aptr++;
1737                 }
1738                 *aptr = NULL;
1739         } else {
1740                 arr = malloc(sizeof (char *));
1741                 if (arr == NULL) {
1742                         errno = ENOMEM;
1743                         return (NULL);
1744                 }
1745
1746                 *arr = NULL;
1747         }
1748
1749         return (arr);
1750 }
1751
1752
1753
1754
1755 /*
1756  * static size_t joinlength(char * const *argv)
1757  *
1758  * return:
1759  *
1760  *      the number of bytes in all the arrays pointed at
1761  *      by argv, including their null bytes(which will usually be turned
1762  *      into commas).
1763  *
1764  *
1765  */
1766
1767 static size_t
1768 joinlength(char * const *argv) {
1769         int len = 0;
1770
1771         while (argv && *argv) {
1772                 len += (strlen(*argv) + 1);
1773                 argv++;
1774         }
1775
1776         return (len);
1777 }
1778
1779
1780
1781 /*
1782  * int joinarray(char * const *argv, char *buffer, char delim)
1783  *
1784  * notes:
1785  *
1786  *      Copy all the ARGV strings into the end of BUFFER
1787  *      separating them with DELIM.  BUFFER is assumed to have
1788  *      enough space to hold everything and to be already null-terminated.
1789  *
1790  * return:
1791  *
1792  *      0 unless argv or buffer is NULL.
1793  *
1794  *
1795  */
1796
1797 static int
1798 joinarray(char * const *argv, char *buffer, char delim) {
1799         char * const *p;
1800         char sep[2];
1801
1802         if (argv == NULL || buffer == NULL) {
1803                 errno = EINVAL;
1804                 return (-1);
1805         }
1806
1807         sep[0] = delim;
1808         sep[1] = 0x0;
1809
1810         for (p = argv ; *p != NULL ; p++) {
1811                 strcat(buffer, *p);
1812                 if (*(p + 1) != NULL) {
1813                         strcat(buffer, sep);
1814                 }
1815         }
1816
1817         return (0);
1818 }
1819
1820
1821 /*
1822  * static char * getfield(char **res, size_t reslen, char **ptr, char delim)
1823  *
1824  * notes:
1825  *
1826  *      Stores in *RES, which is a buffer of length RESLEN, a
1827  *      copy of the bytes from *PTR up to and including the first
1828  *      instance of DELIM. If *RES is NULL, then it will be
1829  *      assigned a malloced buffer to hold the copy. *PTR is
1830  *      modified to point at the found delimiter.
1831  *
1832  * return:
1833  *
1834  *      If there was no delimiter, then NULL is returned,
1835  *      otherewise *RES is returned.
1836  *
1837  */
1838
1839 static char *
1840 getfield(char **res, size_t reslen, char **ptr, char delim) {
1841         char *q;
1842
1843         if (res == NULL || ptr == NULL || *ptr == NULL) {
1844                 errno = EINVAL;
1845                 return (NULL);
1846         }
1847
1848         q = strchr(*ptr, delim);
1849
1850         if (q == NULL) {
1851                 errno = EINVAL;
1852                 return (NULL);
1853         } else {
1854                 if (*res == NULL) {
1855                         *res = strndup(*ptr, q - *ptr);
1856                 } else {
1857                         if ((size_t)(q - *ptr + 1) > reslen) { /* to big for res */
1858                                 errno = EINVAL;
1859                                 return (NULL);
1860                         } else {
1861                                 strncpy(*res, *ptr, q - *ptr);
1862                                 (*res)[q - *ptr] = 0x0;
1863                         }
1864                 }
1865                 *ptr = q + 1;
1866         }
1867
1868         return (*res);
1869 }
1870
1871
1872
1873
1874
1875 #ifndef HAVE_STRNDUP
1876 /*
1877  * static char * strndup(const char *str, size_t len)
1878  *
1879  * notes:
1880  *
1881  *      like strdup, except do len bytes instead of the whole string. Always
1882  *      null-terminates.
1883  *
1884  * return:
1885  *
1886  *      The newly malloced string.
1887  *
1888  */
1889
1890 static char *
1891 strndup(const char *str, size_t len) {
1892         char *p = malloc(len + 1);
1893
1894         if (p == NULL)
1895                 return (NULL);
1896         strncpy(p, str, len);
1897         p[len] = 0x0;
1898         return (p);
1899 }
1900 #endif
1901
1902 #if WANT_MAIN
1903
1904 /*
1905  * static int strcmp_nws(const char *a, const char *b)
1906  *
1907  * notes:
1908  *
1909  *      do a strcmp, except uneven lengths of whitespace compare the same
1910  *
1911  * return:
1912  *
1913  */
1914
1915 static int
1916 strcmp_nws(const char *a, const char *b) {
1917         while (*a && *b) {
1918                 if (isspace(*a) && isspace(*b)) {
1919                         do {
1920                                 a++;
1921                         } while (isspace(*a));
1922                         do {
1923                                 b++;
1924                         } while (isspace(*b));
1925                 }
1926                 if (*a < *b)
1927                         return (-1);
1928                 else if (*a > *b)
1929                         return (1);
1930
1931                 a++;
1932                 b++;;
1933         }
1934
1935         if (*a == *b)
1936                 return (0);
1937         else if (*a > *b)
1938                 return (1);
1939         else
1940                 return (-1);
1941 }
1942
1943 #endif
1944
1945
1946
1947
1948
1949 /*
1950  * static void free_array(char **argv, size_t entries)
1951  *
1952  * notes:
1953  *
1954  *      Free argv and each of the pointers inside it. The end of
1955  *      the array is when a NULL pointer is found inside. If
1956  *      entries is > 0, then NULL pointers inside the array do
1957  *      not indicate the end of the array.
1958  *
1959  */
1960
1961 static void
1962 free_array(char **argv, size_t entries) {
1963         char **p = argv;
1964         int useEntries = (entries > 0U);
1965
1966         if (argv == NULL)
1967                 return;
1968
1969         while ((useEntries && entries > 0U) || *p) {
1970                 if (*p)
1971                         free(*p);
1972                 p++;
1973                 if (useEntries)
1974                         entries--;
1975         }
1976         free(argv);
1977 }
1978
1979
1980
1981
1982
1983 /* ************************************************** */
1984
1985 #if WANT_MAIN
1986
1987 /* takes an option to indicate what sort of marshalling(read the code) and
1988    an argument. If the argument looks like a marshalled buffer(has a ':'
1989    embedded) then it's unmarshalled and the remarshalled and the new string
1990    is compared to the old one.
1991 */
1992
1993 int
1994 main(int argc, char **argv) {
1995         char buffer[1024];
1996         char *b = &buffer[0];
1997         size_t len = sizeof buffer;
1998         char option;
1999
2000         if (argc < 2 || argv[1][0] != '-')
2001                 exit(1);
2002
2003         option = argv[1][1];
2004         argv++;
2005         argc--;
2006
2007
2008 #if 0
2009         {
2010                 char buff[10];
2011                 char *p = argv[1], *q = &buff[0];
2012
2013                 while (getfield(&q, sizeof buff, &p, ':') != NULL) {
2014                         printf("field: \"%s\"\n", q);
2015                         p++;
2016                 }
2017                 printf("p is now \"%s\"\n", p);
2018         }
2019 #endif
2020
2021 #if 0
2022         {
2023                 char **x = splitarray(argv[1], argv[1] + strlen(argv[1]),
2024                                       argv[2][0]);
2025                 char **p;
2026
2027                 if (x == NULL)
2028                         printf("split failed\n");
2029
2030                 for (p = x ; p != NULL && *p != NULL ; p++) {
2031                         printf("\"%s\"\n", *p);
2032                 }
2033         }
2034 #endif
2035
2036 #if 1
2037         switch(option) {
2038         case 'n': {
2039                 struct nwent ne;
2040                 int i;
2041
2042                 if (strchr(argv[1], ':') != NULL) {
2043                         if (irp_unmarshall_nw(&ne, argv[1]) != 0) {
2044                                 printf("Unmarhsalling failed\n");
2045                                 exit(1);
2046                         }
2047
2048                         printf("Name: \"%s\"\n", ne.n_name);
2049                         printf("Aliases:");
2050                         for (i = 0 ; ne.n_aliases[i] != NULL ; i++)
2051                                 printf("\n\t\"%s\"", ne.n_aliases[i]);
2052                         printf("\nAddrtype: %s\n", ADDR_T_STR(ne.n_addrtype));
2053                         inet_net_ntop(ne.n_addrtype, ne.n_addr, ne.n_length,
2054                                       buffer, sizeof buffer);
2055                         printf("Net: \"%s\"\n", buffer);
2056                         *((long*)ne.n_addr) = htonl(*((long*)ne.n_addr));
2057                         inet_net_ntop(ne.n_addrtype, ne.n_addr, ne.n_length,
2058                                       buffer, sizeof buffer);
2059                         printf("Corrected Net: \"%s\"\n", buffer);
2060                 } else {
2061                         struct netent *np1 = getnetbyname(argv[1]);
2062                         ne.n_name = np1->n_name;
2063                         ne.n_aliases = np1->n_aliases;
2064                         ne.n_addrtype = np1->n_addrtype;
2065                         ne.n_addr = &np1->n_net;
2066                         ne.n_length = (IN_CLASSA(np1->n_net) ?
2067                                        8 :
2068                                        (IN_CLASSB(np1->n_net) ?
2069                                         16 :
2070                                         (IN_CLASSC(np1->n_net) ?
2071                                          24 : -1)));
2072                         np1->n_net = htonl(np1->n_net);
2073                         if (irp_marshall_nw(&ne, &b, &len) != 0) {
2074                                 printf("Marshalling failed\n");
2075                         }
2076                         printf("%s\n", b);
2077                 }
2078                 break;
2079         }
2080
2081
2082         case 'r': {
2083                 char **hosts, **users, **domains;
2084                 size_t entries;
2085                 int i;
2086                 char *buff;
2087                 size_t size;
2088                 char *ngname;
2089
2090                 if (strchr(argv[1], '(') != NULL) {
2091                         if (irp_unmarshall_ng(&ngname, &entries,
2092                                               &hosts, &users, &domains,
2093                                               argv[1]) != 0) {
2094                                 printf("unmarshall failed\n");
2095                                 exit(1);
2096                         }
2097
2098 #define STRVAL(x) (x == NULL ? "*" : x)
2099
2100                         printf("%s {\n", ngname);
2101                         for (i = 0 ; i < entries ; i++)
2102                                 printf("\t\"%s\" : \"%s\" : \"%s\"\n",
2103                                        STRVAL(hosts[i]),
2104                                        STRVAL(users[i]),
2105                                        STRVAL(domains[i]));
2106                         printf("}\n\n\n");
2107
2108
2109                         irp_marshall_ng_start(ngname, NULL, &size);
2110                         for (i = 0 ; i < entries ; i++)
2111                                 irp_marshall_ng_next(hosts[i], users[i],
2112                                                      domains[i], NULL, &size);
2113                         irp_marshall_ng_end(NULL, &size);
2114
2115                         buff = malloc(size);
2116
2117                         irp_marshall_ng_start(ngname, buff, &size);
2118                         for (i = 0 ; i < entries ; i++) {
2119                                 if (irp_marshall_ng_next(hosts[i], users[i],
2120                                                          domains[i], buff,
2121                                                          &size) != 0)
2122                                         printf("next marshalling failed.\n");
2123                         }
2124                         irp_marshall_ng_end(buff, &size);
2125
2126                         if (strcmp_nws(argv[1], buff) != 0) {
2127                                 printf("compare failed:\n\t%s\n\t%s\n",
2128                                        buffer, argv[1]);
2129                         } else {
2130                                 printf("compare ok\n");
2131                         }
2132                 } else {
2133                         char *h, *u, *d, *buff;
2134                         size_t size;
2135
2136                         /* run through two times. First to figure out how
2137                            much of a buffer we need. Second to do the
2138                            actual marshalling */
2139
2140                         setnetgrent(argv[1]);
2141                         irp_marshall_ng_start(argv[1], NULL, &size);
2142                         while (getnetgrent(&h, &u, &d) == 1)
2143                                 irp_marshall_ng_next(h, u, d, NULL, &size);
2144                         irp_marshall_ng_end(NULL, &size);
2145                         endnetgrent(argv[1]);
2146
2147                         buff = malloc(size);
2148
2149                         setnetgrent(argv[1]);
2150                         if (irp_marshall_ng_start(argv[1], buff, &size) != 0)
2151                                 printf("Marshalling start failed\n");
2152
2153                         while (getnetgrent(&h, &u, &d) == 1) {
2154                                 if (irp_marshall_ng_next(h, u, d, buff, &size)
2155                                     != 0) {
2156                                         printf("Marshalling failed\n");
2157                                 }
2158                         }
2159
2160                         irp_marshall_ng_end(buff, &size);
2161                         endnetgrent();
2162
2163                         printf("success: %s\n", buff);
2164                 }
2165                 break;
2166         }
2167
2168
2169
2170         case 'h': {
2171                 struct hostent he, *hp;
2172                 int i;
2173
2174
2175                 if (strchr(argv[1], '@') != NULL) {
2176                         if (irp_unmarshall_ho(&he, argv[1]) != 0) {
2177                                 printf("unmarshall failed\n");
2178                                 exit(1);
2179                         }
2180
2181                         printf("Host: \"%s\"\nAliases:", he.h_name);
2182                         for (i = 0 ; he.h_aliases[i] != NULL ; i++)
2183                                 printf("\n\t\t\"%s\"", he.h_aliases[i]);
2184                         printf("\nAddr Type: \"%s\"\n",
2185                                ADDR_T_STR(he.h_addrtype));
2186                         printf("Length: %d\nAddresses:", he.h_length);
2187                         for (i = 0 ; he.h_addr_list[i] != 0 ; i++) {
2188                                 inet_ntop(he.h_addrtype, he.h_addr_list[i],
2189                                           buffer, sizeof buffer);
2190                                 printf("\n\t\"%s\"\n", buffer);
2191                         }
2192                         printf("\n\n");
2193
2194                         irp_marshall_ho(&he, &b, &len);
2195                         if (strcmp(argv[1], buffer) != 0) {
2196                                 printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n",
2197                                        buffer, argv[1]);
2198                         } else {
2199                                 printf("compare ok\n");
2200                         }
2201                 } else {
2202                         if ((hp = gethostbyname(argv[1])) == NULL) {
2203                                 perror("gethostbyname");
2204                                 printf("\"%s\"\n", argv[1]);
2205                                 exit(1);
2206                         }
2207
2208                         if (irp_marshall_ho(hp, &b, &len) != 0) {
2209                                 printf("irp_marshall_ho failed\n");
2210                                 exit(1);
2211                         }
2212
2213                         printf("success: \"%s\"\n", buffer);
2214                 }
2215                 break;
2216         }
2217
2218
2219         case 's': {
2220                 struct servent *sv;
2221                 struct servent sv1;
2222
2223                 if (strchr(argv[1], ':') != NULL) {
2224                         sv = &sv1;
2225                         memset(sv, 0xef, sizeof (struct servent));
2226                         if (irp_unmarshall_sv(sv, argv[1]) != 0) {
2227                                 printf("unmarshall failed\n");
2228
2229                         }
2230
2231                         irp_marshall_sv(sv, &b, &len);
2232                         if (strcmp(argv[1], buffer) != 0) {
2233                                 printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n",
2234                                        buffer, argv[1]);
2235                         } else {
2236                                 printf("compare ok\n");
2237                         }
2238                 } else {
2239                         if ((sv = getservbyname(argv[1], argv[2])) == NULL) {
2240                                 perror("getservent");
2241                                 exit(1);
2242                         }
2243
2244                         if (irp_marshall_sv(sv, &b, &len) != 0) {
2245                                 printf("irp_marshall_sv failed\n");
2246                                 exit(1);
2247                         }
2248
2249                         printf("success: \"%s\"\n", buffer);
2250                 }
2251                 break;
2252         }
2253
2254         case 'g': {
2255                 struct group *gr;
2256                 struct group gr1;
2257
2258                 if (strchr(argv[1], ':') != NULL) {
2259                         gr = &gr1;
2260                         memset(gr, 0xef, sizeof (struct group));
2261                         if (irp_unmarshall_gr(gr, argv[1]) != 0) {
2262                                 printf("unmarshall failed\n");
2263
2264                         }
2265
2266                         irp_marshall_gr(gr, &b, &len);
2267                         if (strcmp(argv[1], buffer) != 0) {
2268                                 printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n",
2269                                        buffer, argv[1]);
2270                         } else {
2271                                 printf("compare ok\n");
2272                         }
2273                 } else {
2274                         if ((gr = getgrnam(argv[1])) == NULL) {
2275                                 perror("getgrnam");
2276                                 exit(1);
2277                         }
2278
2279                         if (irp_marshall_gr(gr, &b, &len) != 0) {
2280                                 printf("irp_marshall_gr failed\n");
2281                                 exit(1);
2282                         }
2283
2284                         printf("success: \"%s\"\n", buffer);
2285                 }
2286                 break;
2287         }
2288
2289
2290         case 'p': {
2291                 struct passwd *pw;
2292                 struct passwd pw1;
2293
2294                 if (strchr(argv[1], ':') != NULL) {
2295                         pw = &pw1;
2296                         memset(pw, 0xef, sizeof (*pw));
2297                         if (irp_unmarshall_pw(pw, argv[1]) != 0) {
2298                                 printf("unmarshall failed\n");
2299                                 exit(1);
2300                         }
2301
2302                         printf("User: \"%s\"\nPasswd: \"%s\"\nUid: %ld\nGid: %ld\n",
2303                                pw->pw_name, pw->pw_passwd, (long)pw->pw_uid,
2304                                (long)pw->pw_gid);
2305                         printf("Class: \"%s\"\nChange: %ld\nGecos: \"%s\"\n",
2306                                pw->pw_class, (long)pw->pw_change, pw->pw_gecos);
2307                         printf("Shell: \"%s\"\nDirectory: \"%s\"\n",
2308                                pw->pw_shell, pw->pw_dir);
2309
2310                         pw = getpwnam(pw->pw_name);
2311                         irp_marshall_pw(pw, &b, &len);
2312                         if (strcmp(argv[1], buffer) != 0) {
2313                                 printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n",
2314                                        buffer, argv[1]);
2315                         } else {
2316                                 printf("compare ok\n");
2317                         }
2318                 } else {
2319                         if ((pw = getpwnam(argv[1])) == NULL) {
2320                                 perror("getpwnam");
2321                                 exit(1);
2322                         }
2323
2324                         if (irp_marshall_pw(pw, &b, &len) != 0) {
2325                                 printf("irp_marshall_pw failed\n");
2326                                 exit(1);
2327                         }
2328
2329                         printf("success: \"%s\"\n", buffer);
2330                 }
2331                 break;
2332         }
2333
2334         default:
2335                 printf("Wrong option: %c\n", option);
2336                 break;
2337         }
2338
2339 #endif
2340
2341         return (0);
2342 }
2343
2344 #endif