4 * Copyright(c) 1989, 1993, 1995
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
38 * Portions Copyright (c) 1996 by Internet Software Consortium.
40 * Permission to use, copy, modify, and distribute this software for any
41 * purpose with or without fee is hereby granted, provided that the above
42 * copyright notice and this permission notice appear in all copies.
44 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
45 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
46 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
47 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
48 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
49 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
50 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
53 #if defined(LIBC_SCCS) && !defined(lint)
54 static const char rcsid
[] = "Id: irpmarshall.c,v 1.7 2006/03/09 23:57:56 marka Exp";
55 #endif /* LIBC_SCCS and not lint */
59 Check values are in approrpriate endian order
.
61 Double check memory allocations on unmarhsalling
68 #include "port_before.h"
70 #include <sys/types.h>
71 #include <sys/socket.h>
73 #include <netinet/in.h>
74 #include <arpa/inet.h>
75 #include <arpa/nameser.h>
89 #include <isc/memcluster.h>
90 #include <isc/irpmarshall.h>
92 #include "port_after.h"
96 static char *strndup(const char *str
, size_t len
);
99 static char **splitarray(const char *buffer
, const char *buffend
, char delim
);
100 static int joinarray(char * const * argv
, char *buffer
, char delim
);
101 static char *getfield(char **res
, size_t reslen
, char **buffer
, char delim
);
102 static size_t joinlength(char * const *argv
);
103 static void free_array(char **argv
, size_t entries
);
105 #define ADDR_T_STR(x) (x == AF_INET ? "AF_INET" :\
106 (x == AF_INET6 ? "AF_INET6" : "UNKNOWN"))
108 #define MAXPADDRSIZE (sizeof "255.255.255.255" + 1)
110 static char COMMA
= ',';
112 static const char *COMMASTR
= ",";
113 static const char *COLONSTR
= ":";
117 /* See big comment at bottom of irpmarshall.h for description. */
121 /* +++++++++++++++++++++++++ struct passwd +++++++++++++++++++++++++ */
124 * int irp_marshall_pw(const struct passwd *pw, char **buffer, size_t *len)
132 * 0 on sucess, -1 on failure.
137 irp_marshall_pw(const struct passwd
*pw
, char **buffer
, size_t *len
) {
138 size_t need
= 1 ; /*%< for null byte */
144 const char *fieldsep
= COLONSTR
;
146 if (pw
== NULL
|| len
== NULL
) {
151 sprintf(pwUid
, "%ld", (long)pw
->pw_uid
);
152 sprintf(pwGid
, "%ld", (long)pw
->pw_gid
);
154 #ifdef HAVE_PW_CHANGE
155 sprintf(pwChange
, "%ld", (long)pw
->pw_change
);
161 #ifdef HAVE_PW_EXPIRE
162 sprintf(pwExpire
, "%ld", (long)pw
->pw_expire
);
169 pwClass
= pw
->pw_class
;
174 need
+= strlen(pw
->pw_name
) + 1; /*%< one for fieldsep */
175 need
+= strlen(pw
->pw_passwd
) + 1;
176 need
+= strlen(pwUid
) + 1;
177 need
+= strlen(pwGid
) + 1;
178 need
+= strlen(pwClass
) + 1;
179 need
+= strlen(pwChange
) + 1;
180 need
+= strlen(pwExpire
) + 1;
181 need
+= strlen(pw
->pw_gecos
) + 1;
182 need
+= strlen(pw
->pw_dir
) + 1;
183 need
+= strlen(pw
->pw_shell
) + 1;
185 if (buffer
== NULL
) {
190 if (*buffer
!= NULL
&& need
> *len
) {
195 if (*buffer
== NULL
) {
196 need
+= 2; /*%< for CRLF */
197 *buffer
= memget(need
);
198 if (*buffer
== NULL
) {
206 strcpy(*buffer
, pw
->pw_name
); strcat(*buffer
, fieldsep
);
207 strcat(*buffer
, pw
->pw_passwd
); strcat(*buffer
, fieldsep
);
208 strcat(*buffer
, pwUid
); strcat(*buffer
, fieldsep
);
209 strcat(*buffer
, pwGid
); strcat(*buffer
, fieldsep
);
210 strcat(*buffer
, pwClass
); strcat(*buffer
, fieldsep
);
211 strcat(*buffer
, pwChange
); strcat(*buffer
, fieldsep
);
212 strcat(*buffer
, pwExpire
); strcat(*buffer
, fieldsep
);
213 strcat(*buffer
, pw
->pw_gecos
); strcat(*buffer
, fieldsep
);
214 strcat(*buffer
, pw
->pw_dir
); strcat(*buffer
, fieldsep
);
215 strcat(*buffer
, pw
->pw_shell
); strcat(*buffer
, fieldsep
);
221 * int irp_unmarshall_pw(struct passwd *pw, char *buffer)
229 * 0 on success, -1 on failure
234 irp_unmarshall_pw(struct passwd
*pw
, char *buffer
) {
235 char *name
, *pass
, *class, *gecos
, *dir
, *shell
;
243 char *tb
= &tmpbuf
[0];
245 int myerrno
= EINVAL
;
247 name
= pass
= class = gecos
= dir
= shell
= NULL
;
252 if (getfield(&name
, 0, &p
, fieldsep
) == NULL
|| strlen(name
) == 0) {
256 /* pw_passwd field */
258 if (getfield(&pass
, 0, &p
, fieldsep
) == NULL
) { /*%< field can be empty */
265 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
269 t
= strtol(tmpbuf
, &tb
, 10);
271 goto error
; /*%< junk in value */
274 if ((long) pwuid
!= t
) { /*%< value must have been too big. */
282 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
286 t
= strtol(tmpbuf
, &tb
, 10);
288 goto error
; /*%< junk in value */
291 if ((long)pwgid
!= t
) { /*%< value must have been too big. */
299 if (getfield(&class, 0, &p
, fieldsep
) == NULL
) {
305 /* pw_change field */
307 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
311 t
= strtol(tmpbuf
, &tb
, 10);
313 goto error
; /*%< junk in value */
315 pwchange
= (time_t)t
;
316 if ((long)pwchange
!= t
) { /*%< value must have been too big. */
322 /* pw_expire field */
324 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
328 t
= strtol(tmpbuf
, &tb
, 10);
330 goto error
; /*%< junk in value */
332 pwexpire
= (time_t)t
;
333 if ((long) pwexpire
!= t
) { /*%< value must have been too big. */
341 if (getfield(&gecos
, 0, &p
, fieldsep
) == NULL
) {
349 if (getfield(&dir
, 0, &p
, fieldsep
) == NULL
) {
357 if (getfield(&shell
, 0, &p
, fieldsep
) == NULL
) {
364 pw
->pw_passwd
= pass
;
367 pw
->pw_gecos
= gecos
;
369 pw
->pw_shell
= shell
;
371 #ifdef HAVE_PW_CHANGE
372 pw
->pw_change
= pwchange
;
375 pw
->pw_class
= class;
377 #ifdef HAVE_PW_EXPIRE
378 pw
->pw_expire
= pwexpire
;
386 if (name
!= NULL
) free(name
);
387 if (pass
!= NULL
) free(pass
);
388 if (gecos
!= NULL
) free(gecos
);
389 if (dir
!= NULL
) free(dir
);
390 if (shell
!= NULL
) free(shell
);
395 /* ------------------------- struct passwd ------------------------- */
396 #endif /* WANT_IRS_PW */
397 /* +++++++++++++++++++++++++ struct group +++++++++++++++++++++++++ */
400 * int irp_marshall_gr(const struct group *gr, char **buffer, size_t *len)
408 * 0 on success, -1 on failure
412 irp_marshall_gr(const struct group
*gr
, char **buffer
, size_t *len
) {
413 size_t need
= 1; /*%< for null byte */
415 const char *fieldsep
= COLONSTR
;
417 if (gr
== NULL
|| len
== NULL
) {
422 sprintf(grGid
, "%ld", (long)gr
->gr_gid
);
424 need
+= strlen(gr
->gr_name
) + 1;
425 #ifndef MISSING_GR_PASSWD
426 need
+= strlen(gr
->gr_passwd
) + 1;
430 need
+= strlen(grGid
) + 1;
431 need
+= joinlength(gr
->gr_mem
) + 1;
433 if (buffer
== NULL
) {
438 if (*buffer
!= NULL
&& need
> *len
) {
443 if (*buffer
== NULL
) {
444 need
+= 2; /*%< for CRLF */
445 *buffer
= memget(need
);
446 if (*buffer
== NULL
) {
454 strcpy(*buffer
, gr
->gr_name
); strcat(*buffer
, fieldsep
);
455 #ifndef MISSING_GR_PASSWD
456 strcat(*buffer
, gr
->gr_passwd
);
458 strcat(*buffer
, fieldsep
);
459 strcat(*buffer
, grGid
); strcat(*buffer
, fieldsep
);
460 joinarray(gr
->gr_mem
, *buffer
, COMMA
) ; strcat(*buffer
, fieldsep
);
466 * int irp_unmarshall_gr(struct group *gr, char *buffer)
474 * 0 on success and -1 on failure.
479 irp_unmarshall_gr(struct group
*gr
, char *buffer
) {
485 char **members
= NULL
;
489 int myerrno
= EINVAL
;
491 if (gr
== NULL
|| buffer
== NULL
) {
500 if (getfield(&name
, 0, &p
, fieldsep
) == NULL
|| strlen(name
) == 0U) {
505 /* gr_passwd field */
507 if (getfield(&pass
, 0, &p
, fieldsep
) == NULL
) {
514 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
518 t
= strtol(tmpbuf
, &tb
, 10);
520 goto error
; /*%< junk in value */
523 if ((long) grgid
!= t
) { /*%< value must have been too big. */
528 /* gr_mem field. Member names are separated by commas */
529 q
= strchr(p
, fieldsep
);
533 members
= splitarray(p
, q
, COMMA
);
534 if (members
== NULL
) {
542 #ifndef MISSING_GR_PASSWD
543 gr
->gr_passwd
= pass
;
546 gr
->gr_mem
= members
;
553 if (name
!= NULL
) free(name
);
554 if (pass
!= NULL
) free(pass
);
560 /* ------------------------- struct group ------------------------- */
565 /* +++++++++++++++++++++++++ struct servent +++++++++++++++++++++++++ */
568 * int irp_marshall_sv(const struct servent *sv, char **buffer, size_t *len)
576 * 0 on success, -1 on failure.
581 irp_marshall_sv(const struct servent
*sv
, char **buffer
, size_t *len
) {
582 size_t need
= 1; /*%< for null byte */
584 const char *fieldsep
= COLONSTR
;
587 if (sv
== NULL
|| len
== NULL
) {
592 /* the int s_port field is actually a short in network order. We
593 want host order to make the marshalled data look correct */
594 realport
= ntohs((short)sv
->s_port
);
595 sprintf(svPort
, "%d", realport
);
597 need
+= strlen(sv
->s_name
) + 1;
598 need
+= joinlength(sv
->s_aliases
) + 1;
599 need
+= strlen(svPort
) + 1;
600 need
+= strlen(sv
->s_proto
) + 1;
602 if (buffer
== NULL
) {
607 if (*buffer
!= NULL
&& need
> *len
) {
612 if (*buffer
== NULL
) {
613 need
+= 2; /*%< for CRLF */
614 *buffer
= memget(need
);
615 if (*buffer
== NULL
) {
623 strcpy(*buffer
, sv
->s_name
); strcat(*buffer
, fieldsep
);
624 joinarray(sv
->s_aliases
, *buffer
, COMMA
); strcat(*buffer
, fieldsep
);
625 strcat(*buffer
, svPort
); strcat(*buffer
, fieldsep
);
626 strcat(*buffer
, sv
->s_proto
); strcat(*buffer
, fieldsep
);
632 * int irp_unmarshall_sv(struct servent *sv, char *buffer)
640 * 0 on success, -1 on failure.
645 irp_unmarshall_sv(struct servent
*sv
, char *buffer
) {
651 char **aliases
= NULL
;
655 int myerrno
= EINVAL
;
657 if (sv
== NULL
|| buffer
== NULL
)
665 if (getfield(&name
, 0, &p
, fieldsep
) == NULL
|| strlen(name
) == 0U) {
670 /* s_aliases field */
671 q
= strchr(p
, fieldsep
);
675 aliases
= splitarray(p
, q
, COMMA
);
676 if (aliases
== NULL
) {
685 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
689 t
= strtol(tmpbuf
, &tb
, 10);
691 goto error
; /*%< junk in value */
694 if ((long) svport
!= t
) { /*%< value must have been too big. */
697 svport
= htons(svport
);
701 if (getfield(&proto
, 0, &p
, fieldsep
) == NULL
) {
706 sv
->s_aliases
= aliases
;
715 if (name
!= NULL
) free(name
);
716 if (proto
!= NULL
) free(proto
);
717 free_array(aliases
, 0);
723 /* ------------------------- struct servent ------------------------- */
725 /* +++++++++++++++++++++++++ struct protoent +++++++++++++++++++++++++ */
728 * int irp_marshall_pr(struct protoent *pr, char **buffer, size_t *len)
736 * 0 on success and -1 on failure.
741 irp_marshall_pr(struct protoent
*pr
, char **buffer
, size_t *len
) {
742 size_t need
= 1; /*%< for null byte */
744 const char *fieldsep
= COLONSTR
;
746 if (pr
== NULL
|| len
== NULL
) {
751 sprintf(prProto
, "%d", (int)pr
->p_proto
);
753 need
+= strlen(pr
->p_name
) + 1;
754 need
+= joinlength(pr
->p_aliases
) + 1;
755 need
+= strlen(prProto
) + 1;
757 if (buffer
== NULL
) {
762 if (*buffer
!= NULL
&& need
> *len
) {
767 if (*buffer
== NULL
) {
768 need
+= 2; /*%< for CRLF */
769 *buffer
= memget(need
);
770 if (*buffer
== NULL
) {
778 strcpy(*buffer
, pr
->p_name
); strcat(*buffer
, fieldsep
);
779 joinarray(pr
->p_aliases
, *buffer
, COMMA
); strcat(*buffer
, fieldsep
);
780 strcat(*buffer
, prProto
); strcat(*buffer
, fieldsep
);
787 * int irp_unmarshall_pr(struct protoent *pr, char *buffer)
795 * 0 on success, -1 on failure
799 int irp_unmarshall_pr(struct protoent
*pr
, char *buffer
) {
804 char **aliases
= NULL
;
808 int myerrno
= EINVAL
;
810 if (pr
== NULL
|| buffer
== NULL
) {
819 if (getfield(&name
, 0, &p
, fieldsep
) == NULL
|| strlen(name
) == 0U) {
824 /* p_aliases field */
825 q
= strchr(p
, fieldsep
);
829 aliases
= splitarray(p
, q
, COMMA
);
830 if (aliases
== NULL
) {
839 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
843 t
= strtol(tmpbuf
, &tb
, 10);
845 goto error
; /*%< junk in value */
848 if ((long) prproto
!= t
) { /*%< value must have been too big. */
853 pr
->p_aliases
= aliases
;
854 pr
->p_proto
= prproto
;
861 if (name
!= NULL
) free(name
);
862 free_array(aliases
, 0);
867 /* ------------------------- struct protoent ------------------------- */
871 /* +++++++++++++++++++++++++ struct hostent +++++++++++++++++++++++++ */
874 * int irp_marshall_ho(struct hostent *ho, char **buffer, size_t *len)
882 * 0 on success, -1 on failure.
887 irp_marshall_ho(struct hostent
*ho
, char **buffer
, size_t *len
) {
888 size_t need
= 1; /*%< for null byte */
896 const char *fieldsep
= "@";
898 if (ho
== NULL
|| len
== NULL
) {
903 switch(ho
->h_addrtype
) {
905 strcpy(hoaddrtype
, "AF_INET");
909 strcpy(hoaddrtype
, "AF_INET6");
917 sprintf(holength
, "%d", ho
->h_length
);
919 need
+= strlen(ho
->h_name
) + 1;
920 need
+= joinlength(ho
->h_aliases
) + 1;
921 need
+= strlen(hoaddrtype
) + 1;
922 need
+= strlen(holength
) + 1;
924 /* we determine an upper bound on the string length needed, not an
926 addrlen
= (ho
->h_addrtype
== AF_INET
? 16 : 46) ; /*%< XX other AF's?? */
927 for (av
= ho
->h_addr_list
; av
!= NULL
&& *av
!= NULL
; av
++)
930 if (buffer
== NULL
) {
935 if (*buffer
!= NULL
&& need
> *len
) {
940 if (*buffer
== NULL
) {
941 need
+= 2; /*%< for CRLF */
942 *buffer
= memget(need
);
943 if (*buffer
== NULL
) {
952 strcpy(*buffer
, ho
->h_name
); strcat(*buffer
, fieldsep
);
953 joinarray(ho
->h_aliases
, *buffer
, COMMA
); strcat(*buffer
, fieldsep
);
954 strcat(*buffer
, hoaddrtype
); strcat(*buffer
, fieldsep
);
955 strcat(*buffer
, holength
); strcat(*buffer
, fieldsep
);
957 p
= *buffer
+ strlen(*buffer
);
958 remlen
= need
- strlen(*buffer
);
959 for (av
= ho
->h_addr_list
; av
!= NULL
&& *av
!= NULL
; av
++) {
960 if (inet_ntop(ho
->h_addrtype
, *av
, p
, remlen
) == NULL
) {
963 if (*(av
+ 1) != NULL
)
968 strcat(*buffer
, fieldsep
);
974 memput(*buffer
, need
);
981 * int irp_unmarshall_ho(struct hostent *ho, char *buffer)
989 * 0 on success, -1 on failure.
994 irp_unmarshall_ho(struct hostent
*ho
, char *buffer
) {
1000 char **aliases
= NULL
;
1001 char **hohaddrlist
= NULL
;
1007 char fieldsep
= '@';
1008 int myerrno
= EINVAL
;
1010 if (ho
== NULL
|| buffer
== NULL
) {
1019 if (getfield(&name
, 0, &p
, fieldsep
) == NULL
|| strlen(name
) == 0U) {
1024 /* h_aliases field */
1025 q
= strchr(p
, fieldsep
);
1029 aliases
= splitarray(p
, q
, COMMA
);
1030 if (aliases
== NULL
) {
1037 /* h_addrtype field */
1039 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
1043 if (strcmp(tmpbuf
, "AF_INET") == 0)
1044 hoaddrtype
= AF_INET
;
1045 else if (strcmp(tmpbuf
, "AF_INET6") == 0)
1046 hoaddrtype
= AF_INET6
;
1051 /* h_length field */
1053 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
1057 t
= strtol(tmpbuf
, &tb
, 10);
1059 goto error
; /*%< junk in value */
1062 if ((long) holength
!= t
) { /*%< value must have been too big. */
1067 /* h_addr_list field */
1068 q
= strchr(p
, fieldsep
);
1072 /* count how many addresss are in there */
1074 for (addrcount
= 1, r
= p
; r
!= q
; r
++) {
1082 hoaddrsize
= (addrcount
+ 1) * sizeof (char *);
1083 hohaddrlist
= malloc(hoaddrsize
);
1084 if (hohaddrlist
== NULL
) {
1089 memset(hohaddrlist
, 0x0, hoaddrsize
);
1091 alist
= hohaddrlist
;
1092 for (t
= 0, r
= p
; r
!= q
; p
= r
+ 1, t
++) {
1094 while (r
!= q
&& *r
!= COMMA
) r
++;
1098 alist
[t
] = malloc(hoaddrtype
== AF_INET
? 4 : 16);
1099 if (alist
[t
] == NULL
) {
1104 if (inet_pton(hoaddrtype
, p
, alist
[t
]) == -1)
1111 ho
->h_aliases
= aliases
;
1112 ho
->h_addrtype
= hoaddrtype
;
1113 ho
->h_length
= holength
;
1114 ho
->h_addr_list
= hohaddrlist
;
1121 if (name
!= NULL
) free(name
);
1122 free_array(hohaddrlist
, 0);
1123 free_array(aliases
, 0);
1128 /* ------------------------- struct hostent------------------------- */
1132 /* +++++++++++++++++++++++++ struct netgrp +++++++++++++++++++++++++ */
1135 * int irp_marshall_ng(const char *host, const char *user,
1136 * const char *domain, char *buffer, size_t *len)
1140 * See note for irp_marshall_ng_start
1144 * 0 on success, 0 on failure.
1149 irp_marshall_ng(const char *host
, const char *user
, const char *domain
,
1150 char **buffer
, size_t *len
) {
1151 size_t need
= 1; /*%< for nul byte */
1152 const char *fieldsep
= ",";
1159 need
+= 4; /*%< two parens and two commas */
1160 need
+= (host
== NULL
? 0 : strlen(host
));
1161 need
+= (user
== NULL
? 0 : strlen(user
));
1162 need
+= (domain
== NULL
? 0 : strlen(domain
));
1164 if (buffer
== NULL
) {
1167 } else if (*buffer
!= NULL
&& need
> *len
) {
1172 if (*buffer
== NULL
) {
1173 need
+= 2; /*%< for CRLF */
1174 *buffer
= memget(need
);
1175 if (*buffer
== NULL
) {
1184 (*buffer
)[1] = '\0';
1187 strcat(*buffer
, host
);
1188 strcat(*buffer
, fieldsep
);
1191 strcat(*buffer
, user
);
1192 strcat(*buffer
, fieldsep
);
1195 strcat(*buffer
, domain
);
1196 strcat(*buffer
, ")");
1206 * int irp_unmarshall_ng(const char **host, const char **user,
1207 * const char **domain, char *buffer)
1211 * Unpacks the BUFFER into 3 character arrays it allocates and assigns
1212 * to *HOST, *USER and *DOMAIN. If any field of the value is empty,
1213 * then the corresponding paramater value will be set to NULL.
1217 * 0 on success and -1 on failure.
1221 irp_unmarshall_ng(const char **hostp
, const char **userp
, const char **domainp
,
1225 char fieldsep
= ',';
1226 int myerrno
= EINVAL
;
1227 char *host
, *user
, *domain
;
1229 if (userp
== NULL
|| hostp
== NULL
||
1230 domainp
== NULL
|| buffer
== NULL
) {
1235 host
= user
= domain
= NULL
;
1238 while (isspace((unsigned char)*p
)) {
1246 while (*q
&& *q
!= fieldsep
)
1250 } else if (q
> p
+ 1) {
1251 host
= strndup(p
, q
- p
);
1257 } else if (*p
!= fieldsep
) {
1259 while (*q
&& *q
!= fieldsep
)
1264 user
= strndup(p
, q
- p
);
1271 } else if (*p
!= ')') {
1273 while (*q
&& *q
!= ')')
1278 domain
= strndup(p
, q
- p
);
1289 if (host
!= NULL
) free(host
);
1290 if (user
!= NULL
) free(user
);
1295 /* ------------------------- struct netgrp ------------------------- */
1300 /* +++++++++++++++++++++++++ struct nwent +++++++++++++++++++++++++ */
1303 * int irp_marshall_nw(struct nwent *ne, char **buffer, size_t *len)
1311 * 0 on success and -1 on failure.
1316 irp_marshall_nw(struct nwent
*ne
, char **buffer
, size_t *len
) {
1317 size_t need
= 1; /*%< for null byte */
1319 char nNet
[MAXPADDRSIZE
];
1320 const char *fieldsep
= COLONSTR
;
1322 if (ne
== NULL
|| len
== NULL
) {
1326 strcpy(nAddrType
, ADDR_T_STR(ne
->n_addrtype
));
1328 if (inet_net_ntop(ne
->n_addrtype
, ne
->n_addr
, ne
->n_length
,
1329 nNet
, sizeof nNet
) == NULL
) {
1334 need
+= strlen(ne
->n_name
) + 1;
1335 need
+= joinlength(ne
->n_aliases
) + 1;
1336 need
+= strlen(nAddrType
) + 1;
1337 need
+= strlen(nNet
) + 1;
1339 if (buffer
== NULL
) {
1344 if (*buffer
!= NULL
&& need
> *len
) {
1349 if (*buffer
== NULL
) {
1350 need
+= 2; /*%< for CRLF */
1351 *buffer
= memget(need
);
1352 if (*buffer
== NULL
) {
1360 strcpy(*buffer
, ne
->n_name
); strcat(*buffer
, fieldsep
);
1361 joinarray(ne
->n_aliases
, *buffer
, COMMA
) ; strcat(*buffer
, fieldsep
);
1362 strcat(*buffer
, nAddrType
); strcat(*buffer
, fieldsep
);
1363 strcat(*buffer
, nNet
); strcat(*buffer
, fieldsep
);
1369 * int irp_unmarshall_nw(struct nwent *ne, char *buffer)
1377 * 0 on success and -1 on failure.
1382 irp_unmarshall_nw(struct nwent
*ne
, char *buffer
) {
1388 char **aliases
= NULL
;
1391 char fieldsep
= ':';
1392 int myerrno
= EINVAL
;
1394 if (ne
== NULL
|| buffer
== NULL
) {
1402 if (getfield(&name
, 0, &p
, fieldsep
) == NULL
|| strlen(name
) == 0U) {
1407 /* n_aliases field. Aliases are separated by commas */
1408 q
= strchr(p
, fieldsep
);
1412 aliases
= splitarray(p
, q
, COMMA
);
1413 if (aliases
== NULL
) {
1420 /* h_addrtype field */
1422 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
1426 if (strcmp(tmpbuf
, "AF_INET") == 0)
1427 naddrtype
= AF_INET
;
1428 else if (strcmp(tmpbuf
, "AF_INET6") == 0)
1429 naddrtype
= AF_INET6
;
1436 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
1441 bits
= inet_net_pton(naddrtype
, tmpbuf
, &nnet
, sizeof nnet
);
1446 /* nnet = ntohl(nnet); */ /* keep in network order for nwent */
1449 ne
->n_aliases
= aliases
;
1450 ne
->n_addrtype
= naddrtype
;
1451 ne
->n_length
= bits
;
1452 ne
->n_addr
= malloc(sizeof nnet
);
1453 if (ne
->n_addr
== NULL
) {
1457 memcpy(ne
->n_addr
, &nnet
, sizeof nnet
);
1464 if (name
!= NULL
) free(name
);
1465 free_array(aliases
, 0);
1471 /* ------------------------- struct nwent ------------------------- */
1474 /* +++++++++++++++++++++++++ struct netent +++++++++++++++++++++++++ */
1477 * int irp_marshall_ne(struct netent *ne, char **buffer, size_t *len)
1485 * 0 on success and -1 on failure.
1490 irp_marshall_ne(struct netent
*ne
, char **buffer
, size_t *len
) {
1491 size_t need
= 1; /*%< for null byte */
1493 char nNet
[MAXPADDRSIZE
];
1494 const char *fieldsep
= COLONSTR
;
1497 if (ne
== NULL
|| len
== NULL
) {
1501 strcpy(nAddrType
, ADDR_T_STR(ne
->n_addrtype
));
1503 nval
= htonl(ne
->n_net
);
1504 if (inet_ntop(ne
->n_addrtype
, &nval
, nNet
, sizeof nNet
) == NULL
) {
1508 need
+= strlen(ne
->n_name
) + 1;
1509 need
+= joinlength(ne
->n_aliases
) + 1;
1510 need
+= strlen(nAddrType
) + 1;
1511 need
+= strlen(nNet
) + 1;
1513 if (buffer
== NULL
) {
1518 if (*buffer
!= NULL
&& need
> *len
) {
1523 if (*buffer
== NULL
) {
1524 need
+= 2; /*%< for CRLF */
1525 *buffer
= memget(need
);
1526 if (*buffer
== NULL
) {
1534 strcpy(*buffer
, ne
->n_name
); strcat(*buffer
, fieldsep
);
1535 joinarray(ne
->n_aliases
, *buffer
, COMMA
) ; strcat(*buffer
, fieldsep
);
1536 strcat(*buffer
, nAddrType
); strcat(*buffer
, fieldsep
);
1537 strcat(*buffer
, nNet
); strcat(*buffer
, fieldsep
);
1543 * int irp_unmarshall_ne(struct netent *ne, char *buffer)
1551 * 0 on success and -1 on failure.
1556 irp_unmarshall_ne(struct netent
*ne
, char *buffer
) {
1562 char **aliases
= NULL
;
1565 char fieldsep
= ':';
1566 int myerrno
= EINVAL
;
1568 if (ne
== NULL
|| buffer
== NULL
) {
1576 if (getfield(&name
, 0, &p
, fieldsep
) == NULL
|| strlen(name
) == 0U) {
1581 /* n_aliases field. Aliases are separated by commas */
1582 q
= strchr(p
, fieldsep
);
1586 aliases
= splitarray(p
, q
, COMMA
);
1587 if (aliases
== NULL
) {
1594 /* h_addrtype field */
1596 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
1600 if (strcmp(tmpbuf
, "AF_INET") == 0)
1601 naddrtype
= AF_INET
;
1602 else if (strcmp(tmpbuf
, "AF_INET6") == 0)
1603 naddrtype
= AF_INET6
;
1610 if (getfield(&tb
, sizeof tmpbuf
, &p
, fieldsep
) == NULL
||
1614 bits
= inet_net_pton(naddrtype
, tmpbuf
, &nnet
, sizeof nnet
);
1621 ne
->n_aliases
= aliases
;
1622 ne
->n_addrtype
= naddrtype
;
1630 if (name
!= NULL
) free(name
);
1631 free_array(aliases
, 0);
1637 /* ------------------------- struct netent ------------------------- */
1640 /* =========================================================================== */
1643 * static char ** splitarray(const char *buffer, const char *buffend, char delim)
1647 * Split a delim separated astring. Not allowed
1648 * to have two delims next to each other. BUFFER points to begining of
1649 * string, BUFFEND points to one past the end of the string
1650 * (i.e. points at where the null byte would be if null
1655 * Returns a malloced array of pointers, each pointer pointing to a
1656 * malloced string. If BUFEER is an empty string, then return values is
1657 * array of 1 pointer that is NULL. Returns NULL on failure.
1662 splitarray(const char *buffer
, const char *buffend
, char delim
) {
1668 if (buffend
< buffer
)
1670 else if (buffend
> buffer
&& *buffer
== delim
)
1672 else if (buffend
> buffer
&& *(buffend
- 1) == delim
)
1675 /* count the number of field and make sure none are empty */
1676 if (buffend
> buffer
+ 1) {
1677 for (count
= 1, q
= buffer
; q
!= buffend
; q
++) {
1679 if (q
> buffer
&& (*(q
- 1) == delim
)) {
1689 count
++ ; /*%< for NULL at end */
1690 aptr
= arr
= malloc(count
* sizeof (char *));
1696 memset(arr
, 0x0, count
* sizeof (char *));
1697 for (p
= buffer
; p
< buffend
; p
++) {
1698 for (q
= p
; *q
!= delim
&& q
!= buffend
; q
++)
1700 *aptr
= strndup(p
, q
- p
);
1707 arr
= malloc(sizeof (char *));
1720 * static size_t joinlength(char * const *argv)
1724 * the number of bytes in all the arrays pointed at
1725 * by argv, including their null bytes(which will usually be turned
1732 joinlength(char * const *argv
) {
1735 while (argv
&& *argv
) {
1736 len
+= (strlen(*argv
) + 1);
1744 * int joinarray(char * const *argv, char *buffer, char delim)
1748 * Copy all the ARGV strings into the end of BUFFER
1749 * separating them with DELIM. BUFFER is assumed to have
1750 * enough space to hold everything and to be already null-terminated.
1754 * 0 unless argv or buffer is NULL.
1760 joinarray(char * const *argv
, char *buffer
, char delim
) {
1764 if (argv
== NULL
|| buffer
== NULL
) {
1772 for (p
= argv
; *p
!= NULL
; p
++) {
1774 if (*(p
+ 1) != NULL
) {
1775 strcat(buffer
, sep
);
1783 * static char * getfield(char **res, size_t reslen, char **ptr, char delim)
1787 * Stores in *RES, which is a buffer of length RESLEN, a
1788 * copy of the bytes from *PTR up to and including the first
1789 * instance of DELIM. If *RES is NULL, then it will be
1790 * assigned a malloced buffer to hold the copy. *PTR is
1791 * modified to point at the found delimiter.
1795 * If there was no delimiter, then NULL is returned,
1796 * otherewise *RES is returned.
1801 getfield(char **res
, size_t reslen
, char **ptr
, char delim
) {
1804 if (res
== NULL
|| ptr
== NULL
|| *ptr
== NULL
) {
1809 q
= strchr(*ptr
, delim
);
1816 *res
= strndup(*ptr
, q
- *ptr
);
1818 if ((size_t)(q
- *ptr
+ 1) > reslen
) { /*%< to big for res */
1822 strncpy(*res
, *ptr
, q
- *ptr
);
1823 (*res
)[q
- *ptr
] = 0x0;
1836 #ifndef HAVE_STRNDUP
1838 * static char * strndup(const char *str, size_t len)
1842 * like strdup, except do len bytes instead of the whole string. Always
1847 * The newly malloced string.
1852 strndup(const char *str
, size_t len
) {
1853 char *p
= malloc(len
+ 1);
1857 strncpy(p
, str
, len
);
1866 * static int strcmp_nws(const char *a, const char *b)
1870 * do a strcmp, except uneven lengths of whitespace compare the same
1877 strcmp_nws(const char *a
, const char *b
) {
1879 if (isspace(*a
) && isspace(*b
)) {
1882 } while (isspace(*a
));
1885 } while (isspace(*b
));
1907 * static void free_array(char **argv, size_t entries)
1911 * Free argv and each of the pointers inside it. The end of
1912 * the array is when a NULL pointer is found inside. If
1913 * entries is > 0, then NULL pointers inside the array do
1914 * not indicate the end of the array.
1919 free_array(char **argv
, size_t entries
) {
1921 int useEntries
= (entries
> 0U);
1926 while ((useEntries
&& entries
> 0U) || *p
) {
1940 /* ************************************************** */
1944 /*% takes an option to indicate what sort of marshalling(read the code) and
1945 an argument. If the argument looks like a marshalled buffer(has a ':'
1946 embedded) then it's unmarshalled and the remarshalled and the new string
1947 is compared to the old one.
1951 main(int argc
, char **argv
) {
1953 char *b
= &buffer
[0];
1954 size_t len
= sizeof buffer
;
1957 if (argc
< 2 || argv
[1][0] != '-')
1960 option
= argv
[1][1];
1968 char *p
= argv
[1], *q
= &buff
[0];
1970 while (getfield(&q
, sizeof buff
, &p
, ':') != NULL
) {
1971 printf("field: \"%s\"\n", q
);
1974 printf("p is now \"%s\"\n", p
);
1980 char **x
= splitarray(argv
[1], argv
[1] + strlen(argv
[1]),
1985 printf("split failed\n");
1987 for (p
= x
; p
!= NULL
&& *p
!= NULL
; p
++) {
1988 printf("\"%s\"\n", *p
);
1999 if (strchr(argv
[1], ':') != NULL
) {
2000 if (irp_unmarshall_nw(&ne
, argv
[1]) != 0) {
2001 printf("Unmarhsalling failed\n");
2005 printf("Name: \"%s\"\n", ne
.n_name
);
2007 for (i
= 0 ; ne
.n_aliases
[i
] != NULL
; i
++)
2008 printf("\n\t\"%s\"", ne
.n_aliases
[i
]);
2009 printf("\nAddrtype: %s\n", ADDR_T_STR(ne
.n_addrtype
));
2010 inet_net_ntop(ne
.n_addrtype
, ne
.n_addr
, ne
.n_length
,
2011 buffer
, sizeof buffer
);
2012 printf("Net: \"%s\"\n", buffer
);
2013 *((long*)ne
.n_addr
) = htonl(*((long*)ne
.n_addr
));
2014 inet_net_ntop(ne
.n_addrtype
, ne
.n_addr
, ne
.n_length
,
2015 buffer
, sizeof buffer
);
2016 printf("Corrected Net: \"%s\"\n", buffer
);
2018 struct netent
*np1
= getnetbyname(argv
[1]);
2019 ne
.n_name
= np1
->n_name
;
2020 ne
.n_aliases
= np1
->n_aliases
;
2021 ne
.n_addrtype
= np1
->n_addrtype
;
2022 ne
.n_addr
= &np1
->n_net
;
2023 ne
.n_length
= (IN_CLASSA(np1
->n_net
) ?
2025 (IN_CLASSB(np1
->n_net
) ?
2027 (IN_CLASSC(np1
->n_net
) ?
2029 np1
->n_net
= htonl(np1
->n_net
);
2030 if (irp_marshall_nw(&ne
, &b
, &len
) != 0) {
2031 printf("Marshalling failed\n");
2040 char **hosts
, **users
, **domains
;
2047 if (strchr(argv
[1], '(') != NULL
) {
2048 if (irp_unmarshall_ng(&ngname
, &entries
,
2049 &hosts
, &users
, &domains
,
2051 printf("unmarshall failed\n");
2055 #define STRVAL(x) (x == NULL ? "*" : x)
2057 printf("%s {\n", ngname
);
2058 for (i
= 0 ; i
< entries
; i
++)
2059 printf("\t\"%s\" : \"%s\" : \"%s\"\n",
2062 STRVAL(domains
[i
]));
2066 irp_marshall_ng_start(ngname
, NULL
, &size
);
2067 for (i
= 0 ; i
< entries
; i
++)
2068 irp_marshall_ng_next(hosts
[i
], users
[i
],
2069 domains
[i
], NULL
, &size
);
2070 irp_marshall_ng_end(NULL
, &size
);
2072 buff
= malloc(size
);
2074 irp_marshall_ng_start(ngname
, buff
, &size
);
2075 for (i
= 0 ; i
< entries
; i
++) {
2076 if (irp_marshall_ng_next(hosts
[i
], users
[i
],
2079 printf("next marshalling failed.\n");
2081 irp_marshall_ng_end(buff
, &size
);
2083 if (strcmp_nws(argv
[1], buff
) != 0) {
2084 printf("compare failed:\n\t%s\n\t%s\n",
2087 printf("compare ok\n");
2090 char *h
, *u
, *d
, *buff
;
2093 /* run through two times. First to figure out how
2094 much of a buffer we need. Second to do the
2095 actual marshalling */
2097 setnetgrent(argv
[1]);
2098 irp_marshall_ng_start(argv
[1], NULL
, &size
);
2099 while (getnetgrent(&h
, &u
, &d
) == 1)
2100 irp_marshall_ng_next(h
, u
, d
, NULL
, &size
);
2101 irp_marshall_ng_end(NULL
, &size
);
2102 endnetgrent(argv
[1]);
2104 buff
= malloc(size
);
2106 setnetgrent(argv
[1]);
2107 if (irp_marshall_ng_start(argv
[1], buff
, &size
) != 0)
2108 printf("Marshalling start failed\n");
2110 while (getnetgrent(&h
, &u
, &d
) == 1) {
2111 if (irp_marshall_ng_next(h
, u
, d
, buff
, &size
)
2113 printf("Marshalling failed\n");
2117 irp_marshall_ng_end(buff
, &size
);
2120 printf("success: %s\n", buff
);
2128 struct hostent he
, *hp
;
2132 if (strchr(argv
[1], '@') != NULL
) {
2133 if (irp_unmarshall_ho(&he
, argv
[1]) != 0) {
2134 printf("unmarshall failed\n");
2138 printf("Host: \"%s\"\nAliases:", he
.h_name
);
2139 for (i
= 0 ; he
.h_aliases
[i
] != NULL
; i
++)
2140 printf("\n\t\t\"%s\"", he
.h_aliases
[i
]);
2141 printf("\nAddr Type: \"%s\"\n",
2142 ADDR_T_STR(he
.h_addrtype
));
2143 printf("Length: %d\nAddresses:", he
.h_length
);
2144 for (i
= 0 ; he
.h_addr_list
[i
] != 0 ; i
++) {
2145 inet_ntop(he
.h_addrtype
, he
.h_addr_list
[i
],
2146 buffer
, sizeof buffer
);
2147 printf("\n\t\"%s\"\n", buffer
);
2151 irp_marshall_ho(&he
, &b
, &len
);
2152 if (strcmp(argv
[1], buffer
) != 0) {
2153 printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n",
2156 printf("compare ok\n");
2159 if ((hp
= gethostbyname(argv
[1])) == NULL
) {
2160 perror("gethostbyname");
2161 printf("\"%s\"\n", argv
[1]);
2165 if (irp_marshall_ho(hp
, &b
, &len
) != 0) {
2166 printf("irp_marshall_ho failed\n");
2170 printf("success: \"%s\"\n", buffer
);
2180 if (strchr(argv
[1], ':') != NULL
) {
2182 memset(sv
, 0xef, sizeof (struct servent
));
2183 if (irp_unmarshall_sv(sv
, argv
[1]) != 0) {
2184 printf("unmarshall failed\n");
2188 irp_marshall_sv(sv
, &b
, &len
);
2189 if (strcmp(argv
[1], buffer
) != 0) {
2190 printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n",
2193 printf("compare ok\n");
2196 if ((sv
= getservbyname(argv
[1], argv
[2])) == NULL
) {
2197 perror("getservent");
2201 if (irp_marshall_sv(sv
, &b
, &len
) != 0) {
2202 printf("irp_marshall_sv failed\n");
2206 printf("success: \"%s\"\n", buffer
);
2215 if (strchr(argv
[1], ':') != NULL
) {
2217 memset(gr
, 0xef, sizeof (struct group
));
2218 if (irp_unmarshall_gr(gr
, argv
[1]) != 0) {
2219 printf("unmarshall failed\n");
2223 irp_marshall_gr(gr
, &b
, &len
);
2224 if (strcmp(argv
[1], buffer
) != 0) {
2225 printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n",
2228 printf("compare ok\n");
2231 if ((gr
= getgrnam(argv
[1])) == NULL
) {
2236 if (irp_marshall_gr(gr
, &b
, &len
) != 0) {
2237 printf("irp_marshall_gr failed\n");
2241 printf("success: \"%s\"\n", buffer
);
2251 if (strchr(argv
[1], ':') != NULL
) {
2253 memset(pw
, 0xef, sizeof (*pw
));
2254 if (irp_unmarshall_pw(pw
, argv
[1]) != 0) {
2255 printf("unmarshall failed\n");
2259 printf("User: \"%s\"\nPasswd: \"%s\"\nUid: %ld\nGid: %ld\n",
2260 pw
->pw_name
, pw
->pw_passwd
, (long)pw
->pw_uid
,
2262 printf("Class: \"%s\"\nChange: %ld\nGecos: \"%s\"\n",
2263 pw
->pw_class
, (long)pw
->pw_change
, pw
->pw_gecos
);
2264 printf("Shell: \"%s\"\nDirectory: \"%s\"\n",
2265 pw
->pw_shell
, pw
->pw_dir
);
2267 pw
= getpwnam(pw
->pw_name
);
2268 irp_marshall_pw(pw
, &b
, &len
);
2269 if (strcmp(argv
[1], buffer
) != 0) {
2270 printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n",
2273 printf("compare ok\n");
2276 if ((pw
= getpwnam(argv
[1])) == NULL
) {
2281 if (irp_marshall_pw(pw
, &b
, &len
) != 0) {
2282 printf("irp_marshall_pw failed\n");
2286 printf("success: \"%s\"\n", buffer
);
2292 printf("Wrong option: %c\n", option
);