Detect FPU by checking CPUID features.
[dragonfly.git] / contrib / bind-9.5.2 / lib / bind / irs / irpmarshall.c
blob85ffff1866a75e145d31d9fa4c8be3c8cd2f173e
1 /*
2 * Copyright(c) 1989, 1993, 1995
3 * The Regents of the University of California. All rights reserved.
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.
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.
35 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
36 * Portions Copyright (c) 1996 by Internet Software Consortium.
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.
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.
51 #if defined(LIBC_SCCS) && !defined(lint)
52 static const char rcsid[] = "$Id: irpmarshall.c,v 1.7 2006/03/09 23:57:56 marka Exp $";
53 #endif /* LIBC_SCCS and not lint */
55 #if 0
57 Check values are in approrpriate endian order.
59 Double check memory allocations on unmarhsalling
61 #endif
64 /* Extern */
66 #include "port_before.h"
68 #include <sys/types.h>
69 #include <sys/socket.h>
71 #include <netinet/in.h>
72 #include <arpa/inet.h>
73 #include <arpa/nameser.h>
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>
86 #include <irs.h>
87 #include <isc/memcluster.h>
88 #include <isc/irpmarshall.h>
90 #include "port_after.h"
93 #ifndef HAVE_STRNDUP
94 static char *strndup(const char *str, size_t len);
95 #endif
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);
103 #define ADDR_T_STR(x) (x == AF_INET ? "AF_INET" :\
104 (x == AF_INET6 ? "AF_INET6" : "UNKNOWN"))
106 #define MAXPADDRSIZE (sizeof "255.255.255.255" + 1)
108 static char COMMA = ',';
110 static const char *COMMASTR = ",";
111 static const char *COLONSTR = ":";
115 /* See big comment at bottom of irpmarshall.h for description. */
118 #ifdef WANT_IRS_PW
119 /* +++++++++++++++++++++++++ struct passwd +++++++++++++++++++++++++ */
122 * int irp_marshall_pw(const struct passwd *pw, char **buffer, size_t *len)
124 * notes: \li
126 * See irpmarshall.h
128 * return: \li
130 * 0 on sucess, -1 on failure.
135 irp_marshall_pw(const struct passwd *pw, char **buffer, size_t *len) {
136 size_t need = 1 ; /*%< for null byte */
137 char pwUid[24];
138 char pwGid[24];
139 char pwChange[24];
140 char pwExpire[24];
141 const char *pwClass;
142 const char *fieldsep = COLONSTR;
144 if (pw == NULL || len == NULL) {
145 errno = EINVAL;
146 return (-1);
149 sprintf(pwUid, "%ld", (long)pw->pw_uid);
150 sprintf(pwGid, "%ld", (long)pw->pw_gid);
152 #ifdef HAVE_PW_CHANGE
153 sprintf(pwChange, "%ld", (long)pw->pw_change);
154 #else
155 pwChange[0] = '0';
156 pwChange[1] = '\0';
157 #endif
159 #ifdef HAVE_PW_EXPIRE
160 sprintf(pwExpire, "%ld", (long)pw->pw_expire);
161 #else
162 pwExpire[0] = '0';
163 pwExpire[1] = '\0';
164 #endif
166 #ifdef HAVE_PW_CLASS
167 pwClass = pw->pw_class;
168 #else
169 pwClass = "";
170 #endif
172 need += strlen(pw->pw_name) + 1; /*%< one for fieldsep */
173 need += strlen(pw->pw_passwd) + 1;
174 need += strlen(pwUid) + 1;
175 need += strlen(pwGid) + 1;
176 need += strlen(pwClass) + 1;
177 need += strlen(pwChange) + 1;
178 need += strlen(pwExpire) + 1;
179 need += strlen(pw->pw_gecos) + 1;
180 need += strlen(pw->pw_dir) + 1;
181 need += strlen(pw->pw_shell) + 1;
183 if (buffer == NULL) {
184 *len = need;
185 return (0);
188 if (*buffer != NULL && need > *len) {
189 errno = EINVAL;
190 return (-1);
193 if (*buffer == NULL) {
194 need += 2; /*%< for CRLF */
195 *buffer = memget(need);
196 if (*buffer == NULL) {
197 errno = ENOMEM;
198 return (-1);
201 *len = need;
204 strcpy(*buffer, pw->pw_name); strcat(*buffer, fieldsep);
205 strcat(*buffer, pw->pw_passwd); strcat(*buffer, fieldsep);
206 strcat(*buffer, pwUid); strcat(*buffer, fieldsep);
207 strcat(*buffer, pwGid); strcat(*buffer, fieldsep);
208 strcat(*buffer, pwClass); strcat(*buffer, fieldsep);
209 strcat(*buffer, pwChange); strcat(*buffer, fieldsep);
210 strcat(*buffer, pwExpire); strcat(*buffer, fieldsep);
211 strcat(*buffer, pw->pw_gecos); strcat(*buffer, fieldsep);
212 strcat(*buffer, pw->pw_dir); strcat(*buffer, fieldsep);
213 strcat(*buffer, pw->pw_shell); strcat(*buffer, fieldsep);
215 return (0);
219 * int irp_unmarshall_pw(struct passwd *pw, char *buffer)
221 * notes: \li
223 * See irpmarshall.h
225 * return: \li
227 * 0 on success, -1 on failure
232 irp_unmarshall_pw(struct passwd *pw, char *buffer) {
233 char *name, *pass, *class, *gecos, *dir, *shell;
234 uid_t pwuid;
235 gid_t pwgid;
236 time_t pwchange;
237 time_t pwexpire;
238 char *p;
239 long t;
240 char tmpbuf[24];
241 char *tb = &tmpbuf[0];
242 char fieldsep = ':';
243 int myerrno = EINVAL;
245 name = pass = class = gecos = dir = shell = NULL;
246 p = buffer;
248 /* pw_name field */
249 name = NULL;
250 if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) {
251 goto error;
254 /* pw_passwd field */
255 pass = NULL;
256 if (getfield(&pass, 0, &p, fieldsep) == NULL) { /*%< field can be empty */
257 goto error;
261 /* pw_uid field */
262 tb = tmpbuf;
263 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
264 strlen(tb) == 0) {
265 goto error;
267 t = strtol(tmpbuf, &tb, 10);
268 if (*tb) {
269 goto error; /*%< junk in value */
271 pwuid = (uid_t)t;
272 if ((long) pwuid != t) { /*%< value must have been too big. */
273 goto error;
278 /* pw_gid field */
279 tb = tmpbuf;
280 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
281 strlen(tb) == 0) {
282 goto error;
284 t = strtol(tmpbuf, &tb, 10);
285 if (*tb) {
286 goto error; /*%< junk in value */
288 pwgid = (gid_t)t;
289 if ((long)pwgid != t) { /*%< value must have been too big. */
290 goto error;
295 /* pw_class field */
296 class = NULL;
297 if (getfield(&class, 0, &p, fieldsep) == NULL) {
298 goto error;
303 /* pw_change field */
304 tb = tmpbuf;
305 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
306 strlen(tb) == 0) {
307 goto error;
309 t = strtol(tmpbuf, &tb, 10);
310 if (*tb) {
311 goto error; /*%< junk in value */
313 pwchange = (time_t)t;
314 if ((long)pwchange != t) { /*%< value must have been too big. */
315 goto error;
320 /* pw_expire field */
321 tb = tmpbuf;
322 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
323 strlen(tb) == 0) {
324 goto error;
326 t = strtol(tmpbuf, &tb, 10);
327 if (*tb) {
328 goto error; /*%< junk in value */
330 pwexpire = (time_t)t;
331 if ((long) pwexpire != t) { /*%< value must have been too big. */
332 goto error;
337 /* pw_gecos field */
338 gecos = NULL;
339 if (getfield(&gecos, 0, &p, fieldsep) == NULL) {
340 goto error;
345 /* pw_dir field */
346 dir = NULL;
347 if (getfield(&dir, 0, &p, fieldsep) == NULL) {
348 goto error;
353 /* pw_shell field */
354 shell = NULL;
355 if (getfield(&shell, 0, &p, fieldsep) == NULL) {
356 goto error;
361 pw->pw_name = name;
362 pw->pw_passwd = pass;
363 pw->pw_uid = pwuid;
364 pw->pw_gid = pwgid;
365 pw->pw_gecos = gecos;
366 pw->pw_dir = dir;
367 pw->pw_shell = shell;
369 #ifdef HAVE_PW_CHANGE
370 pw->pw_change = pwchange;
371 #endif
372 #ifdef HAVE_PW_CLASS
373 pw->pw_class = class;
374 #endif
375 #ifdef HAVE_PW_EXPIRE
376 pw->pw_expire = pwexpire;
377 #endif
379 return (0);
381 error:
382 errno = myerrno;
384 if (name != NULL) free(name);
385 if (pass != NULL) free(pass);
386 if (gecos != NULL) free(gecos);
387 if (dir != NULL) free(dir);
388 if (shell != NULL) free(shell);
390 return (-1);
393 /* ------------------------- struct passwd ------------------------- */
394 #endif /* WANT_IRS_PW */
395 /* +++++++++++++++++++++++++ struct group +++++++++++++++++++++++++ */
398 * int irp_marshall_gr(const struct group *gr, char **buffer, size_t *len)
400 * notes: \li
402 * See irpmarshall.h.
404 * return: \li
406 * 0 on success, -1 on failure
410 irp_marshall_gr(const struct group *gr, char **buffer, size_t *len) {
411 size_t need = 1; /*%< for null byte */
412 char grGid[24];
413 const char *fieldsep = COLONSTR;
415 if (gr == NULL || len == NULL) {
416 errno = EINVAL;
417 return (-1);
420 sprintf(grGid, "%ld", (long)gr->gr_gid);
422 need += strlen(gr->gr_name) + 1;
423 #ifndef MISSING_GR_PASSWD
424 need += strlen(gr->gr_passwd) + 1;
425 #else
426 need++;
427 #endif
428 need += strlen(grGid) + 1;
429 need += joinlength(gr->gr_mem) + 1;
431 if (buffer == NULL) {
432 *len = need;
433 return (0);
436 if (*buffer != NULL && need > *len) {
437 errno = EINVAL;
438 return (-1);
441 if (*buffer == NULL) {
442 need += 2; /*%< for CRLF */
443 *buffer = memget(need);
444 if (*buffer == NULL) {
445 errno = ENOMEM;
446 return (-1);
449 *len = need;
452 strcpy(*buffer, gr->gr_name); strcat(*buffer, fieldsep);
453 #ifndef MISSING_GR_PASSWD
454 strcat(*buffer, gr->gr_passwd);
455 #endif
456 strcat(*buffer, fieldsep);
457 strcat(*buffer, grGid); strcat(*buffer, fieldsep);
458 joinarray(gr->gr_mem, *buffer, COMMA) ; strcat(*buffer, fieldsep);
460 return (0);
464 * int irp_unmarshall_gr(struct group *gr, char *buffer)
466 * notes: \li
468 * See irpmarshall.h
470 * return: \li
472 * 0 on success and -1 on failure.
477 irp_unmarshall_gr(struct group *gr, char *buffer) {
478 char *p, *q;
479 gid_t grgid;
480 long t;
481 char *name = NULL;
482 char *pass = NULL;
483 char **members = NULL;
484 char tmpbuf[24];
485 char *tb;
486 char fieldsep = ':';
487 int myerrno = EINVAL;
489 if (gr == NULL || buffer == NULL) {
490 errno = EINVAL;
491 return (-1);
494 p = buffer;
496 /* gr_name field */
497 name = NULL;
498 if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) {
499 goto error;
503 /* gr_passwd field */
504 pass = NULL;
505 if (getfield(&pass, 0, &p, fieldsep) == NULL) {
506 goto error;
510 /* gr_gid field */
511 tb = tmpbuf;
512 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
513 strlen(tb) == 0U) {
514 goto error;
516 t = strtol(tmpbuf, &tb, 10);
517 if (*tb) {
518 goto error; /*%< junk in value */
520 grgid = (gid_t)t;
521 if ((long) grgid != t) { /*%< value must have been too big. */
522 goto error;
526 /* gr_mem field. Member names are separated by commas */
527 q = strchr(p, fieldsep);
528 if (q == NULL) {
529 goto error;
531 members = splitarray(p, q, COMMA);
532 if (members == NULL) {
533 myerrno = errno;
534 goto error;
536 p = q + 1;
539 gr->gr_name = name;
540 #ifndef MISSING_GR_PASSWD
541 gr->gr_passwd = pass;
542 #endif
543 gr->gr_gid = grgid;
544 gr->gr_mem = members;
546 return (0);
548 error:
549 errno = myerrno;
551 if (name != NULL) free(name);
552 if (pass != NULL) free(pass);
554 return (-1);
558 /* ------------------------- struct group ------------------------- */
563 /* +++++++++++++++++++++++++ struct servent +++++++++++++++++++++++++ */
566 * int irp_marshall_sv(const struct servent *sv, char **buffer, size_t *len)
568 * notes: \li
570 * See irpmarshall.h
572 * return: \li
574 * 0 on success, -1 on failure.
579 irp_marshall_sv(const struct servent *sv, char **buffer, size_t *len) {
580 size_t need = 1; /*%< for null byte */
581 char svPort[24];
582 const char *fieldsep = COLONSTR;
583 short realport;
585 if (sv == NULL || len == NULL) {
586 errno = EINVAL;
587 return (-1);
590 /* the int s_port field is actually a short in network order. We
591 want host order to make the marshalled data look correct */
592 realport = ntohs((short)sv->s_port);
593 sprintf(svPort, "%d", realport);
595 need += strlen(sv->s_name) + 1;
596 need += joinlength(sv->s_aliases) + 1;
597 need += strlen(svPort) + 1;
598 need += strlen(sv->s_proto) + 1;
600 if (buffer == NULL) {
601 *len = need;
602 return (0);
605 if (*buffer != NULL && need > *len) {
606 errno = EINVAL;
607 return (-1);
610 if (*buffer == NULL) {
611 need += 2; /*%< for CRLF */
612 *buffer = memget(need);
613 if (*buffer == NULL) {
614 errno = ENOMEM;
615 return (-1);
618 *len = need;
621 strcpy(*buffer, sv->s_name); strcat(*buffer, fieldsep);
622 joinarray(sv->s_aliases, *buffer, COMMA); strcat(*buffer, fieldsep);
623 strcat(*buffer, svPort); strcat(*buffer, fieldsep);
624 strcat(*buffer, sv->s_proto); strcat(*buffer, fieldsep);
626 return (0);
630 * int irp_unmarshall_sv(struct servent *sv, char *buffer)
632 * notes: \li
634 * See irpmarshall.h
636 * return: \li
638 * 0 on success, -1 on failure.
643 irp_unmarshall_sv(struct servent *sv, char *buffer) {
644 char *p, *q;
645 short svport;
646 long t;
647 char *name = NULL;
648 char *proto = NULL;
649 char **aliases = NULL;
650 char tmpbuf[24];
651 char *tb;
652 char fieldsep = ':';
653 int myerrno = EINVAL;
655 if (sv == NULL || buffer == NULL)
656 return (-1);
658 p = buffer;
661 /* s_name field */
662 name = NULL;
663 if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) {
664 goto error;
668 /* s_aliases field */
669 q = strchr(p, fieldsep);
670 if (q == NULL) {
671 goto error;
673 aliases = splitarray(p, q, COMMA);
674 if (aliases == NULL) {
675 myerrno = errno;
676 goto error;
678 p = q + 1;
681 /* s_port field */
682 tb = tmpbuf;
683 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
684 strlen(tb) == 0U) {
685 goto error;
687 t = strtol(tmpbuf, &tb, 10);
688 if (*tb) {
689 goto error; /*%< junk in value */
691 svport = (short)t;
692 if ((long) svport != t) { /*%< value must have been too big. */
693 goto error;
695 svport = htons(svport);
697 /* s_proto field */
698 proto = NULL;
699 if (getfield(&proto, 0, &p, fieldsep) == NULL) {
700 goto error;
703 sv->s_name = name;
704 sv->s_aliases = aliases;
705 sv->s_port = svport;
706 sv->s_proto = proto;
708 return (0);
710 error:
711 errno = myerrno;
713 if (name != NULL) free(name);
714 if (proto != NULL) free(proto);
715 free_array(aliases, 0);
717 return (-1);
721 /* ------------------------- struct servent ------------------------- */
723 /* +++++++++++++++++++++++++ struct protoent +++++++++++++++++++++++++ */
726 * int irp_marshall_pr(struct protoent *pr, char **buffer, size_t *len)
728 * notes: \li
730 * See irpmarshall.h
732 * return: \li
734 * 0 on success and -1 on failure.
739 irp_marshall_pr(struct protoent *pr, char **buffer, size_t *len) {
740 size_t need = 1; /*%< for null byte */
741 char prProto[24];
742 const char *fieldsep = COLONSTR;
744 if (pr == NULL || len == NULL) {
745 errno = EINVAL;
746 return (-1);
749 sprintf(prProto, "%d", (int)pr->p_proto);
751 need += strlen(pr->p_name) + 1;
752 need += joinlength(pr->p_aliases) + 1;
753 need += strlen(prProto) + 1;
755 if (buffer == NULL) {
756 *len = need;
757 return (0);
760 if (*buffer != NULL && need > *len) {
761 errno = EINVAL;
762 return (-1);
765 if (*buffer == NULL) {
766 need += 2; /*%< for CRLF */
767 *buffer = memget(need);
768 if (*buffer == NULL) {
769 errno = ENOMEM;
770 return (-1);
773 *len = need;
776 strcpy(*buffer, pr->p_name); strcat(*buffer, fieldsep);
777 joinarray(pr->p_aliases, *buffer, COMMA); strcat(*buffer, fieldsep);
778 strcat(*buffer, prProto); strcat(*buffer, fieldsep);
780 return (0);
785 * int irp_unmarshall_pr(struct protoent *pr, char *buffer)
787 * notes: \li
789 * See irpmarshall.h
791 * return: \li
793 * 0 on success, -1 on failure
797 int irp_unmarshall_pr(struct protoent *pr, char *buffer) {
798 char *p, *q;
799 int prproto;
800 long t;
801 char *name = NULL;
802 char **aliases = NULL;
803 char tmpbuf[24];
804 char *tb;
805 char fieldsep = ':';
806 int myerrno = EINVAL;
808 if (pr == NULL || buffer == NULL) {
809 errno = EINVAL;
810 return (-1);
813 p = buffer;
815 /* p_name field */
816 name = NULL;
817 if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) {
818 goto error;
822 /* p_aliases field */
823 q = strchr(p, fieldsep);
824 if (q == NULL) {
825 goto error;
827 aliases = splitarray(p, q, COMMA);
828 if (aliases == NULL) {
829 myerrno = errno;
830 goto error;
832 p = q + 1;
835 /* p_proto field */
836 tb = tmpbuf;
837 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
838 strlen(tb) == 0U) {
839 goto error;
841 t = strtol(tmpbuf, &tb, 10);
842 if (*tb) {
843 goto error; /*%< junk in value */
845 prproto = (int)t;
846 if ((long) prproto != t) { /*%< value must have been too big. */
847 goto error;
850 pr->p_name = name;
851 pr->p_aliases = aliases;
852 pr->p_proto = prproto;
854 return (0);
856 error:
857 errno = myerrno;
859 if (name != NULL) free(name);
860 free_array(aliases, 0);
862 return (-1);
865 /* ------------------------- struct protoent ------------------------- */
869 /* +++++++++++++++++++++++++ struct hostent +++++++++++++++++++++++++ */
872 * int irp_marshall_ho(struct hostent *ho, char **buffer, size_t *len)
874 * notes: \li
876 * See irpmarshall.h.
878 * return: \li
880 * 0 on success, -1 on failure.
885 irp_marshall_ho(struct hostent *ho, char **buffer, size_t *len) {
886 size_t need = 1; /*%< for null byte */
887 char hoaddrtype[24];
888 char holength[24];
889 char **av;
890 char *p;
891 int addrlen;
892 int malloced = 0;
893 size_t remlen;
894 const char *fieldsep = "@";
896 if (ho == NULL || len == NULL) {
897 errno = EINVAL;
898 return (-1);
901 switch(ho->h_addrtype) {
902 case AF_INET:
903 strcpy(hoaddrtype, "AF_INET");
904 break;
906 case AF_INET6:
907 strcpy(hoaddrtype, "AF_INET6");
908 break;
910 default:
911 errno = EINVAL;
912 return (-1);
915 sprintf(holength, "%d", ho->h_length);
917 need += strlen(ho->h_name) + 1;
918 need += joinlength(ho->h_aliases) + 1;
919 need += strlen(hoaddrtype) + 1;
920 need += strlen(holength) + 1;
922 /* we determine an upper bound on the string length needed, not an
923 exact length. */
924 addrlen = (ho->h_addrtype == AF_INET ? 16 : 46) ; /*%< XX other AF's?? */
925 for (av = ho->h_addr_list; av != NULL && *av != NULL ; av++)
926 need += addrlen;
928 if (buffer == NULL) {
929 *len = need;
930 return (0);
933 if (*buffer != NULL && need > *len) {
934 errno = EINVAL;
935 return (-1);
938 if (*buffer == NULL) {
939 need += 2; /*%< for CRLF */
940 *buffer = memget(need);
941 if (*buffer == NULL) {
942 errno = ENOMEM;
943 return (-1);
946 *len = need;
947 malloced = 1;
950 strcpy(*buffer, ho->h_name); strcat(*buffer, fieldsep);
951 joinarray(ho->h_aliases, *buffer, COMMA); strcat(*buffer, fieldsep);
952 strcat(*buffer, hoaddrtype); strcat(*buffer, fieldsep);
953 strcat(*buffer, holength); strcat(*buffer, fieldsep);
955 p = *buffer + strlen(*buffer);
956 remlen = need - strlen(*buffer);
957 for (av = ho->h_addr_list ; av != NULL && *av != NULL ; av++) {
958 if (inet_ntop(ho->h_addrtype, *av, p, remlen) == NULL) {
959 goto error;
961 if (*(av + 1) != NULL)
962 strcat(p, COMMASTR);
963 remlen -= strlen(p);
964 p += strlen(p);
966 strcat(*buffer, fieldsep);
968 return (0);
970 error:
971 if (malloced) {
972 memput(*buffer, need);
975 return (-1);
979 * int irp_unmarshall_ho(struct hostent *ho, char *buffer)
981 * notes: \li
983 * See irpmarshall.h.
985 * return: \li
987 * 0 on success, -1 on failure.
992 irp_unmarshall_ho(struct hostent *ho, char *buffer) {
993 char *p, *q, *r;
994 int hoaddrtype;
995 int holength;
996 long t;
997 char *name;
998 char **aliases = NULL;
999 char **hohaddrlist = NULL;
1000 size_t hoaddrsize;
1001 char tmpbuf[24];
1002 char *tb;
1003 char **alist;
1004 int addrcount;
1005 char fieldsep = '@';
1006 int myerrno = EINVAL;
1008 if (ho == NULL || buffer == NULL) {
1009 errno = EINVAL;
1010 return (-1);
1013 p = buffer;
1015 /* h_name field */
1016 name = NULL;
1017 if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) {
1018 goto error;
1022 /* h_aliases field */
1023 q = strchr(p, fieldsep);
1024 if (q == NULL) {
1025 goto error;
1027 aliases = splitarray(p, q, COMMA);
1028 if (aliases == NULL) {
1029 myerrno = errno;
1030 goto error;
1032 p = q + 1;
1035 /* h_addrtype field */
1036 tb = tmpbuf;
1037 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
1038 strlen(tb) == 0U) {
1039 goto error;
1041 if (strcmp(tmpbuf, "AF_INET") == 0)
1042 hoaddrtype = AF_INET;
1043 else if (strcmp(tmpbuf, "AF_INET6") == 0)
1044 hoaddrtype = AF_INET6;
1045 else
1046 goto error;
1049 /* h_length field */
1050 tb = tmpbuf;
1051 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
1052 strlen(tb) == 0U) {
1053 goto error;
1055 t = strtol(tmpbuf, &tb, 10);
1056 if (*tb) {
1057 goto error; /*%< junk in value */
1059 holength = (int)t;
1060 if ((long) holength != t) { /*%< value must have been too big. */
1061 goto error;
1065 /* h_addr_list field */
1066 q = strchr(p, fieldsep);
1067 if (q == NULL)
1068 goto error;
1070 /* count how many addresss are in there */
1071 if (q > p + 1) {
1072 for (addrcount = 1, r = p ; r != q ; r++) {
1073 if (*r == COMMA)
1074 addrcount++;
1076 } else {
1077 addrcount = 0;
1080 hoaddrsize = (addrcount + 1) * sizeof (char *);
1081 hohaddrlist = malloc(hoaddrsize);
1082 if (hohaddrlist == NULL) {
1083 myerrno = ENOMEM;
1084 goto error;
1087 memset(hohaddrlist, 0x0, hoaddrsize);
1089 alist = hohaddrlist;
1090 for (t = 0, r = p ; r != q ; p = r + 1, t++) {
1091 char saved;
1092 while (r != q && *r != COMMA) r++;
1093 saved = *r;
1094 *r = 0x0;
1096 alist[t] = malloc(hoaddrtype == AF_INET ? 4 : 16);
1097 if (alist[t] == NULL) {
1098 myerrno = ENOMEM;
1099 goto error;
1102 if (inet_pton(hoaddrtype, p, alist[t]) == -1)
1103 goto error;
1104 *r = saved;
1106 alist[t] = NULL;
1108 ho->h_name = name;
1109 ho->h_aliases = aliases;
1110 ho->h_addrtype = hoaddrtype;
1111 ho->h_length = holength;
1112 ho->h_addr_list = hohaddrlist;
1114 return (0);
1116 error:
1117 errno = myerrno;
1119 if (name != NULL) free(name);
1120 free_array(hohaddrlist, 0);
1121 free_array(aliases, 0);
1123 return (-1);
1126 /* ------------------------- struct hostent------------------------- */
1130 /* +++++++++++++++++++++++++ struct netgrp +++++++++++++++++++++++++ */
1133 * int irp_marshall_ng(const char *host, const char *user,
1134 * const char *domain, char *buffer, size_t *len)
1136 * notes: \li
1138 * See note for irp_marshall_ng_start
1140 * return: \li
1142 * 0 on success, 0 on failure.
1147 irp_marshall_ng(const char *host, const char *user, const char *domain,
1148 char **buffer, size_t *len) {
1149 size_t need = 1; /*%< for nul byte */
1150 const char *fieldsep = ",";
1152 if (len == NULL) {
1153 errno = EINVAL;
1154 return (-1);
1157 need += 4; /*%< two parens and two commas */
1158 need += (host == NULL ? 0 : strlen(host));
1159 need += (user == NULL ? 0 : strlen(user));
1160 need += (domain == NULL ? 0 : strlen(domain));
1162 if (buffer == NULL) {
1163 *len = need;
1164 return (0);
1165 } else if (*buffer != NULL && need > *len) {
1166 errno = EINVAL;
1167 return (-1);
1170 if (*buffer == NULL) {
1171 need += 2; /*%< for CRLF */
1172 *buffer = memget(need);
1173 if (*buffer == NULL) {
1174 errno = ENOMEM;
1175 return (-1);
1178 *len = need;
1181 (*buffer)[0] = '(';
1182 (*buffer)[1] = '\0';
1184 if (host != NULL)
1185 strcat(*buffer, host);
1186 strcat(*buffer, fieldsep);
1188 if (user != NULL)
1189 strcat(*buffer, user);
1190 strcat(*buffer, fieldsep);
1192 if (domain != NULL)
1193 strcat(*buffer, domain);
1194 strcat(*buffer, ")");
1196 return (0);
1201 /* ---------- */
1204 * int irp_unmarshall_ng(const char **host, const char **user,
1205 * const char **domain, char *buffer)
1207 * notes: \li
1209 * Unpacks the BUFFER into 3 character arrays it allocates and assigns
1210 * to *HOST, *USER and *DOMAIN. If any field of the value is empty,
1211 * then the corresponding paramater value will be set to NULL.
1213 * return: \li
1215 * 0 on success and -1 on failure.
1219 irp_unmarshall_ng(const char **hostp, const char **userp, const char **domainp,
1220 char *buffer)
1222 char *p, *q;
1223 char fieldsep = ',';
1224 int myerrno = EINVAL;
1225 char *host, *user, *domain;
1227 if (userp == NULL || hostp == NULL ||
1228 domainp == NULL || buffer == NULL) {
1229 errno = EINVAL;
1230 return (-1);
1233 host = user = domain = NULL;
1235 p = buffer;
1236 while (isspace((unsigned char)*p)) {
1237 p++;
1239 if (*p != '(') {
1240 goto error;
1243 q = p + 1;
1244 while (*q && *q != fieldsep)
1245 q++;
1246 if (!*q) {
1247 goto error;
1248 } else if (q > p + 1) {
1249 host = strndup(p, q - p);
1252 p = q + 1;
1253 if (!*p) {
1254 goto error;
1255 } else if (*p != fieldsep) {
1256 q = p + 1;
1257 while (*q && *q != fieldsep)
1258 q++;
1259 if (!*q) {
1260 goto error;
1262 user = strndup(p, q - p);
1263 } else {
1264 p++;
1267 if (!*p) {
1268 goto error;
1269 } else if (*p != ')') {
1270 q = p + 1;
1271 while (*q && *q != ')')
1272 q++;
1273 if (!*q) {
1274 goto error;
1276 domain = strndup(p, q - p);
1278 *hostp = host;
1279 *userp = user;
1280 *domainp = domain;
1282 return (0);
1284 error:
1285 errno = myerrno;
1287 if (host != NULL) free(host);
1288 if (user != NULL) free(user);
1290 return (-1);
1293 /* ------------------------- struct netgrp ------------------------- */
1298 /* +++++++++++++++++++++++++ struct nwent +++++++++++++++++++++++++ */
1301 * int irp_marshall_nw(struct nwent *ne, char **buffer, size_t *len)
1303 * notes: \li
1305 * See at top.
1307 * return: \li
1309 * 0 on success and -1 on failure.
1314 irp_marshall_nw(struct nwent *ne, char **buffer, size_t *len) {
1315 size_t need = 1; /*%< for null byte */
1316 char nAddrType[24];
1317 char nNet[MAXPADDRSIZE];
1318 const char *fieldsep = COLONSTR;
1320 if (ne == NULL || len == NULL) {
1321 return (-1);
1324 strcpy(nAddrType, ADDR_T_STR(ne->n_addrtype));
1326 if (inet_net_ntop(ne->n_addrtype, ne->n_addr, ne->n_length,
1327 nNet, sizeof nNet) == NULL) {
1328 return (-1);
1332 need += strlen(ne->n_name) + 1;
1333 need += joinlength(ne->n_aliases) + 1;
1334 need += strlen(nAddrType) + 1;
1335 need += strlen(nNet) + 1;
1337 if (buffer == NULL) {
1338 *len = need;
1339 return (0);
1342 if (*buffer != NULL && need > *len) {
1343 errno = EINVAL;
1344 return (-1);
1347 if (*buffer == NULL) {
1348 need += 2; /*%< for CRLF */
1349 *buffer = memget(need);
1350 if (*buffer == NULL) {
1351 errno = ENOMEM;
1352 return (-1);
1355 *len = need;
1358 strcpy(*buffer, ne->n_name); strcat(*buffer, fieldsep);
1359 joinarray(ne->n_aliases, *buffer, COMMA) ; strcat(*buffer, fieldsep);
1360 strcat(*buffer, nAddrType); strcat(*buffer, fieldsep);
1361 strcat(*buffer, nNet); strcat(*buffer, fieldsep);
1363 return (0);
1367 * int irp_unmarshall_nw(struct nwent *ne, char *buffer)
1369 * notes: \li
1371 * See note up top.
1373 * return: \li
1375 * 0 on success and -1 on failure.
1380 irp_unmarshall_nw(struct nwent *ne, char *buffer) {
1381 char *p, *q;
1382 int naddrtype;
1383 long nnet;
1384 int bits;
1385 char *name = NULL;
1386 char **aliases = NULL;
1387 char tmpbuf[24];
1388 char *tb;
1389 char fieldsep = ':';
1390 int myerrno = EINVAL;
1392 if (ne == NULL || buffer == NULL) {
1393 goto error;
1396 p = buffer;
1398 /* n_name field */
1399 name = NULL;
1400 if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) {
1401 goto error;
1405 /* n_aliases field. Aliases are separated by commas */
1406 q = strchr(p, fieldsep);
1407 if (q == NULL) {
1408 goto error;
1410 aliases = splitarray(p, q, COMMA);
1411 if (aliases == NULL) {
1412 myerrno = errno;
1413 goto error;
1415 p = q + 1;
1418 /* h_addrtype field */
1419 tb = tmpbuf;
1420 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
1421 strlen(tb) == 0U) {
1422 goto error;
1424 if (strcmp(tmpbuf, "AF_INET") == 0)
1425 naddrtype = AF_INET;
1426 else if (strcmp(tmpbuf, "AF_INET6") == 0)
1427 naddrtype = AF_INET6;
1428 else
1429 goto error;
1432 /* n_net field */
1433 tb = tmpbuf;
1434 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
1435 strlen(tb) == 0U) {
1436 goto error;
1438 nnet = 0;
1439 bits = inet_net_pton(naddrtype, tmpbuf, &nnet, sizeof nnet);
1440 if (bits < 0) {
1441 goto error;
1444 /* nnet = ntohl(nnet); */ /* keep in network order for nwent */
1446 ne->n_name = name;
1447 ne->n_aliases = aliases;
1448 ne->n_addrtype = naddrtype;
1449 ne->n_length = bits;
1450 ne->n_addr = malloc(sizeof nnet);
1451 if (ne->n_addr == NULL) {
1452 goto error;
1455 memcpy(ne->n_addr, &nnet, sizeof nnet);
1457 return (0);
1459 error:
1460 errno = myerrno;
1462 if (name != NULL) free(name);
1463 free_array(aliases, 0);
1465 return (-1);
1469 /* ------------------------- struct nwent ------------------------- */
1472 /* +++++++++++++++++++++++++ struct netent +++++++++++++++++++++++++ */
1475 * int irp_marshall_ne(struct netent *ne, char **buffer, size_t *len)
1477 * notes: \li
1479 * See at top.
1481 * return: \li
1483 * 0 on success and -1 on failure.
1488 irp_marshall_ne(struct netent *ne, char **buffer, size_t *len) {
1489 size_t need = 1; /*%< for null byte */
1490 char nAddrType[24];
1491 char nNet[MAXPADDRSIZE];
1492 const char *fieldsep = COLONSTR;
1493 long nval;
1495 if (ne == NULL || len == NULL) {
1496 return (-1);
1499 strcpy(nAddrType, ADDR_T_STR(ne->n_addrtype));
1501 nval = htonl(ne->n_net);
1502 if (inet_ntop(ne->n_addrtype, &nval, nNet, sizeof nNet) == NULL) {
1503 return (-1);
1506 need += strlen(ne->n_name) + 1;
1507 need += joinlength(ne->n_aliases) + 1;
1508 need += strlen(nAddrType) + 1;
1509 need += strlen(nNet) + 1;
1511 if (buffer == NULL) {
1512 *len = need;
1513 return (0);
1516 if (*buffer != NULL && need > *len) {
1517 errno = EINVAL;
1518 return (-1);
1521 if (*buffer == NULL) {
1522 need += 2; /*%< for CRLF */
1523 *buffer = memget(need);
1524 if (*buffer == NULL) {
1525 errno = ENOMEM;
1526 return (-1);
1529 *len = need;
1532 strcpy(*buffer, ne->n_name); strcat(*buffer, fieldsep);
1533 joinarray(ne->n_aliases, *buffer, COMMA) ; strcat(*buffer, fieldsep);
1534 strcat(*buffer, nAddrType); strcat(*buffer, fieldsep);
1535 strcat(*buffer, nNet); strcat(*buffer, fieldsep);
1537 return (0);
1541 * int irp_unmarshall_ne(struct netent *ne, char *buffer)
1543 * notes: \li
1545 * See note up top.
1547 * return: \li
1549 * 0 on success and -1 on failure.
1554 irp_unmarshall_ne(struct netent *ne, char *buffer) {
1555 char *p, *q;
1556 int naddrtype;
1557 long nnet;
1558 int bits;
1559 char *name = NULL;
1560 char **aliases = NULL;
1561 char tmpbuf[24];
1562 char *tb;
1563 char fieldsep = ':';
1564 int myerrno = EINVAL;
1566 if (ne == NULL || buffer == NULL) {
1567 goto error;
1570 p = buffer;
1572 /* n_name field */
1573 name = NULL;
1574 if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) {
1575 goto error;
1579 /* n_aliases field. Aliases are separated by commas */
1580 q = strchr(p, fieldsep);
1581 if (q == NULL) {
1582 goto error;
1584 aliases = splitarray(p, q, COMMA);
1585 if (aliases == NULL) {
1586 myerrno = errno;
1587 goto error;
1589 p = q + 1;
1592 /* h_addrtype field */
1593 tb = tmpbuf;
1594 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
1595 strlen(tb) == 0U) {
1596 goto error;
1598 if (strcmp(tmpbuf, "AF_INET") == 0)
1599 naddrtype = AF_INET;
1600 else if (strcmp(tmpbuf, "AF_INET6") == 0)
1601 naddrtype = AF_INET6;
1602 else
1603 goto error;
1606 /* n_net field */
1607 tb = tmpbuf;
1608 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL ||
1609 strlen(tb) == 0U) {
1610 goto error;
1612 bits = inet_net_pton(naddrtype, tmpbuf, &nnet, sizeof nnet);
1613 if (bits < 0) {
1614 goto error;
1616 nnet = ntohl(nnet);
1618 ne->n_name = name;
1619 ne->n_aliases = aliases;
1620 ne->n_addrtype = naddrtype;
1621 ne->n_net = nnet;
1623 return (0);
1625 error:
1626 errno = myerrno;
1628 if (name != NULL) free(name);
1629 free_array(aliases, 0);
1631 return (-1);
1635 /* ------------------------- struct netent ------------------------- */
1638 /* =========================================================================== */
1641 * static char ** splitarray(const char *buffer, const char *buffend, char delim)
1643 * notes: \li
1645 * Split a delim separated astring. Not allowed
1646 * to have two delims next to each other. BUFFER points to begining of
1647 * string, BUFFEND points to one past the end of the string
1648 * (i.e. points at where the null byte would be if null
1649 * terminated).
1651 * return: \li
1653 * Returns a malloced array of pointers, each pointer pointing to a
1654 * malloced string. If BUFEER is an empty string, then return values is
1655 * array of 1 pointer that is NULL. Returns NULL on failure.
1659 static char **
1660 splitarray(const char *buffer, const char *buffend, char delim) {
1661 const char *p, *q;
1662 int count = 0;
1663 char **arr = NULL;
1664 char **aptr;
1666 if (buffend < buffer)
1667 return (NULL);
1668 else if (buffend > buffer && *buffer == delim)
1669 return (NULL);
1670 else if (buffend > buffer && *(buffend - 1) == delim)
1671 return (NULL);
1673 /* count the number of field and make sure none are empty */
1674 if (buffend > buffer + 1) {
1675 for (count = 1, q = buffer ; q != buffend ; q++) {
1676 if (*q == delim) {
1677 if (q > buffer && (*(q - 1) == delim)) {
1678 errno = EINVAL;
1679 return (NULL);
1681 count++;
1686 if (count > 0) {
1687 count++ ; /*%< for NULL at end */
1688 aptr = arr = malloc(count * sizeof (char *));
1689 if (aptr == NULL) {
1690 errno = ENOMEM;
1691 return (NULL);
1694 memset(arr, 0x0, count * sizeof (char *));
1695 for (p = buffer ; p < buffend ; p++) {
1696 for (q = p ; *q != delim && q != buffend ; q++)
1697 /* nothing */;
1698 *aptr = strndup(p, q - p);
1700 p = q;
1701 aptr++;
1703 *aptr = NULL;
1704 } else {
1705 arr = malloc(sizeof (char *));
1706 if (arr == NULL) {
1707 errno = ENOMEM;
1708 return (NULL);
1711 *arr = NULL;
1714 return (arr);
1718 * static size_t joinlength(char * const *argv)
1720 * return: \li
1722 * the number of bytes in all the arrays pointed at
1723 * by argv, including their null bytes(which will usually be turned
1724 * into commas).
1729 static size_t
1730 joinlength(char * const *argv) {
1731 int len = 0;
1733 while (argv && *argv) {
1734 len += (strlen(*argv) + 1);
1735 argv++;
1738 return (len);
1742 * int joinarray(char * const *argv, char *buffer, char delim)
1744 * notes: \li
1746 * Copy all the ARGV strings into the end of BUFFER
1747 * separating them with DELIM. BUFFER is assumed to have
1748 * enough space to hold everything and to be already null-terminated.
1750 * return: \li
1752 * 0 unless argv or buffer is NULL.
1757 static int
1758 joinarray(char * const *argv, char *buffer, char delim) {
1759 char * const *p;
1760 char sep[2];
1762 if (argv == NULL || buffer == NULL) {
1763 errno = EINVAL;
1764 return (-1);
1767 sep[0] = delim;
1768 sep[1] = 0x0;
1770 for (p = argv ; *p != NULL ; p++) {
1771 strcat(buffer, *p);
1772 if (*(p + 1) != NULL) {
1773 strcat(buffer, sep);
1777 return (0);
1781 * static char * getfield(char **res, size_t reslen, char **ptr, char delim)
1783 * notes: \li
1785 * Stores in *RES, which is a buffer of length RESLEN, a
1786 * copy of the bytes from *PTR up to and including the first
1787 * instance of DELIM. If *RES is NULL, then it will be
1788 * assigned a malloced buffer to hold the copy. *PTR is
1789 * modified to point at the found delimiter.
1791 * return: \li
1793 * If there was no delimiter, then NULL is returned,
1794 * otherewise *RES is returned.
1798 static char *
1799 getfield(char **res, size_t reslen, char **ptr, char delim) {
1800 char *q;
1802 if (res == NULL || ptr == NULL || *ptr == NULL) {
1803 errno = EINVAL;
1804 return (NULL);
1807 q = strchr(*ptr, delim);
1809 if (q == NULL) {
1810 errno = EINVAL;
1811 return (NULL);
1812 } else {
1813 if (*res == NULL) {
1814 *res = strndup(*ptr, q - *ptr);
1815 } else {
1816 if ((size_t)(q - *ptr + 1) > reslen) { /*%< to big for res */
1817 errno = EINVAL;
1818 return (NULL);
1819 } else {
1820 strncpy(*res, *ptr, q - *ptr);
1821 (*res)[q - *ptr] = 0x0;
1824 *ptr = q + 1;
1827 return (*res);
1834 #ifndef HAVE_STRNDUP
1836 * static char * strndup(const char *str, size_t len)
1838 * notes: \li
1840 * like strdup, except do len bytes instead of the whole string. Always
1841 * null-terminates.
1843 * return: \li
1845 * The newly malloced string.
1849 static char *
1850 strndup(const char *str, size_t len) {
1851 char *p = malloc(len + 1);
1853 if (p == NULL)
1854 return (NULL);
1855 strncpy(p, str, len);
1856 p[len] = 0x0;
1857 return (p);
1859 #endif
1861 #if WANT_MAIN
1864 * static int strcmp_nws(const char *a, const char *b)
1866 * notes: \li
1868 * do a strcmp, except uneven lengths of whitespace compare the same
1870 * return: \li
1874 static int
1875 strcmp_nws(const char *a, const char *b) {
1876 while (*a && *b) {
1877 if (isspace(*a) && isspace(*b)) {
1878 do {
1879 a++;
1880 } while (isspace(*a));
1881 do {
1882 b++;
1883 } while (isspace(*b));
1885 if (*a < *b)
1886 return (-1);
1887 else if (*a > *b)
1888 return (1);
1890 a++;
1891 b++;;
1894 if (*a == *b)
1895 return (0);
1896 else if (*a > *b)
1897 return (1);
1898 else
1899 return (-1);
1902 #endif
1905 * static void free_array(char **argv, size_t entries)
1907 * notes: \li
1909 * Free argv and each of the pointers inside it. The end of
1910 * the array is when a NULL pointer is found inside. If
1911 * entries is > 0, then NULL pointers inside the array do
1912 * not indicate the end of the array.
1916 static void
1917 free_array(char **argv, size_t entries) {
1918 char **p = argv;
1919 int useEntries = (entries > 0U);
1921 if (argv == NULL)
1922 return;
1924 while ((useEntries && entries > 0U) || *p) {
1925 if (*p)
1926 free(*p);
1927 p++;
1928 if (useEntries)
1929 entries--;
1931 free(argv);
1938 /* ************************************************** */
1940 #if WANT_MAIN
1942 /*% takes an option to indicate what sort of marshalling(read the code) and
1943 an argument. If the argument looks like a marshalled buffer(has a ':'
1944 embedded) then it's unmarshalled and the remarshalled and the new string
1945 is compared to the old one.
1949 main(int argc, char **argv) {
1950 char buffer[1024];
1951 char *b = &buffer[0];
1952 size_t len = sizeof buffer;
1953 char option;
1955 if (argc < 2 || argv[1][0] != '-')
1956 exit(1);
1958 option = argv[1][1];
1959 argv++;
1960 argc--;
1963 #if 0
1965 char buff[10];
1966 char *p = argv[1], *q = &buff[0];
1968 while (getfield(&q, sizeof buff, &p, ':') != NULL) {
1969 printf("field: \"%s\"\n", q);
1970 p++;
1972 printf("p is now \"%s\"\n", p);
1974 #endif
1976 #if 0
1978 char **x = splitarray(argv[1], argv[1] + strlen(argv[1]),
1979 argv[2][0]);
1980 char **p;
1982 if (x == NULL)
1983 printf("split failed\n");
1985 for (p = x ; p != NULL && *p != NULL ; p++) {
1986 printf("\"%s\"\n", *p);
1989 #endif
1991 #if 1
1992 switch(option) {
1993 case 'n': {
1994 struct nwent ne;
1995 int i;
1997 if (strchr(argv[1], ':') != NULL) {
1998 if (irp_unmarshall_nw(&ne, argv[1]) != 0) {
1999 printf("Unmarhsalling failed\n");
2000 exit(1);
2003 printf("Name: \"%s\"\n", ne.n_name);
2004 printf("Aliases:");
2005 for (i = 0 ; ne.n_aliases[i] != NULL ; i++)
2006 printf("\n\t\"%s\"", ne.n_aliases[i]);
2007 printf("\nAddrtype: %s\n", ADDR_T_STR(ne.n_addrtype));
2008 inet_net_ntop(ne.n_addrtype, ne.n_addr, ne.n_length,
2009 buffer, sizeof buffer);
2010 printf("Net: \"%s\"\n", buffer);
2011 *((long*)ne.n_addr) = htonl(*((long*)ne.n_addr));
2012 inet_net_ntop(ne.n_addrtype, ne.n_addr, ne.n_length,
2013 buffer, sizeof buffer);
2014 printf("Corrected Net: \"%s\"\n", buffer);
2015 } else {
2016 struct netent *np1 = getnetbyname(argv[1]);
2017 ne.n_name = np1->n_name;
2018 ne.n_aliases = np1->n_aliases;
2019 ne.n_addrtype = np1->n_addrtype;
2020 ne.n_addr = &np1->n_net;
2021 ne.n_length = (IN_CLASSA(np1->n_net) ?
2023 (IN_CLASSB(np1->n_net) ?
2024 16 :
2025 (IN_CLASSC(np1->n_net) ?
2026 24 : -1)));
2027 np1->n_net = htonl(np1->n_net);
2028 if (irp_marshall_nw(&ne, &b, &len) != 0) {
2029 printf("Marshalling failed\n");
2031 printf("%s\n", b);
2033 break;
2037 case 'r': {
2038 char **hosts, **users, **domains;
2039 size_t entries;
2040 int i;
2041 char *buff;
2042 size_t size;
2043 char *ngname;
2045 if (strchr(argv[1], '(') != NULL) {
2046 if (irp_unmarshall_ng(&ngname, &entries,
2047 &hosts, &users, &domains,
2048 argv[1]) != 0) {
2049 printf("unmarshall failed\n");
2050 exit(1);
2053 #define STRVAL(x) (x == NULL ? "*" : x)
2055 printf("%s {\n", ngname);
2056 for (i = 0 ; i < entries ; i++)
2057 printf("\t\"%s\" : \"%s\" : \"%s\"\n",
2058 STRVAL(hosts[i]),
2059 STRVAL(users[i]),
2060 STRVAL(domains[i]));
2061 printf("}\n\n\n");
2064 irp_marshall_ng_start(ngname, NULL, &size);
2065 for (i = 0 ; i < entries ; i++)
2066 irp_marshall_ng_next(hosts[i], users[i],
2067 domains[i], NULL, &size);
2068 irp_marshall_ng_end(NULL, &size);
2070 buff = malloc(size);
2072 irp_marshall_ng_start(ngname, buff, &size);
2073 for (i = 0 ; i < entries ; i++) {
2074 if (irp_marshall_ng_next(hosts[i], users[i],
2075 domains[i], buff,
2076 &size) != 0)
2077 printf("next marshalling failed.\n");
2079 irp_marshall_ng_end(buff, &size);
2081 if (strcmp_nws(argv[1], buff) != 0) {
2082 printf("compare failed:\n\t%s\n\t%s\n",
2083 buffer, argv[1]);
2084 } else {
2085 printf("compare ok\n");
2087 } else {
2088 char *h, *u, *d, *buff;
2089 size_t size;
2091 /* run through two times. First to figure out how
2092 much of a buffer we need. Second to do the
2093 actual marshalling */
2095 setnetgrent(argv[1]);
2096 irp_marshall_ng_start(argv[1], NULL, &size);
2097 while (getnetgrent(&h, &u, &d) == 1)
2098 irp_marshall_ng_next(h, u, d, NULL, &size);
2099 irp_marshall_ng_end(NULL, &size);
2100 endnetgrent(argv[1]);
2102 buff = malloc(size);
2104 setnetgrent(argv[1]);
2105 if (irp_marshall_ng_start(argv[1], buff, &size) != 0)
2106 printf("Marshalling start failed\n");
2108 while (getnetgrent(&h, &u, &d) == 1) {
2109 if (irp_marshall_ng_next(h, u, d, buff, &size)
2110 != 0) {
2111 printf("Marshalling failed\n");
2115 irp_marshall_ng_end(buff, &size);
2116 endnetgrent();
2118 printf("success: %s\n", buff);
2120 break;
2125 case 'h': {
2126 struct hostent he, *hp;
2127 int i;
2130 if (strchr(argv[1], '@') != NULL) {
2131 if (irp_unmarshall_ho(&he, argv[1]) != 0) {
2132 printf("unmarshall failed\n");
2133 exit(1);
2136 printf("Host: \"%s\"\nAliases:", he.h_name);
2137 for (i = 0 ; he.h_aliases[i] != NULL ; i++)
2138 printf("\n\t\t\"%s\"", he.h_aliases[i]);
2139 printf("\nAddr Type: \"%s\"\n",
2140 ADDR_T_STR(he.h_addrtype));
2141 printf("Length: %d\nAddresses:", he.h_length);
2142 for (i = 0 ; he.h_addr_list[i] != 0 ; i++) {
2143 inet_ntop(he.h_addrtype, he.h_addr_list[i],
2144 buffer, sizeof buffer);
2145 printf("\n\t\"%s\"\n", buffer);
2147 printf("\n\n");
2149 irp_marshall_ho(&he, &b, &len);
2150 if (strcmp(argv[1], buffer) != 0) {
2151 printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n",
2152 buffer, argv[1]);
2153 } else {
2154 printf("compare ok\n");
2156 } else {
2157 if ((hp = gethostbyname(argv[1])) == NULL) {
2158 perror("gethostbyname");
2159 printf("\"%s\"\n", argv[1]);
2160 exit(1);
2163 if (irp_marshall_ho(hp, &b, &len) != 0) {
2164 printf("irp_marshall_ho failed\n");
2165 exit(1);
2168 printf("success: \"%s\"\n", buffer);
2170 break;
2174 case 's': {
2175 struct servent *sv;
2176 struct servent sv1;
2178 if (strchr(argv[1], ':') != NULL) {
2179 sv = &sv1;
2180 memset(sv, 0xef, sizeof (struct servent));
2181 if (irp_unmarshall_sv(sv, argv[1]) != 0) {
2182 printf("unmarshall failed\n");
2186 irp_marshall_sv(sv, &b, &len);
2187 if (strcmp(argv[1], buffer) != 0) {
2188 printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n",
2189 buffer, argv[1]);
2190 } else {
2191 printf("compare ok\n");
2193 } else {
2194 if ((sv = getservbyname(argv[1], argv[2])) == NULL) {
2195 perror("getservent");
2196 exit(1);
2199 if (irp_marshall_sv(sv, &b, &len) != 0) {
2200 printf("irp_marshall_sv failed\n");
2201 exit(1);
2204 printf("success: \"%s\"\n", buffer);
2206 break;
2209 case 'g': {
2210 struct group *gr;
2211 struct group gr1;
2213 if (strchr(argv[1], ':') != NULL) {
2214 gr = &gr1;
2215 memset(gr, 0xef, sizeof (struct group));
2216 if (irp_unmarshall_gr(gr, argv[1]) != 0) {
2217 printf("unmarshall failed\n");
2221 irp_marshall_gr(gr, &b, &len);
2222 if (strcmp(argv[1], buffer) != 0) {
2223 printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n",
2224 buffer, argv[1]);
2225 } else {
2226 printf("compare ok\n");
2228 } else {
2229 if ((gr = getgrnam(argv[1])) == NULL) {
2230 perror("getgrnam");
2231 exit(1);
2234 if (irp_marshall_gr(gr, &b, &len) != 0) {
2235 printf("irp_marshall_gr failed\n");
2236 exit(1);
2239 printf("success: \"%s\"\n", buffer);
2241 break;
2245 case 'p': {
2246 struct passwd *pw;
2247 struct passwd pw1;
2249 if (strchr(argv[1], ':') != NULL) {
2250 pw = &pw1;
2251 memset(pw, 0xef, sizeof (*pw));
2252 if (irp_unmarshall_pw(pw, argv[1]) != 0) {
2253 printf("unmarshall failed\n");
2254 exit(1);
2257 printf("User: \"%s\"\nPasswd: \"%s\"\nUid: %ld\nGid: %ld\n",
2258 pw->pw_name, pw->pw_passwd, (long)pw->pw_uid,
2259 (long)pw->pw_gid);
2260 printf("Class: \"%s\"\nChange: %ld\nGecos: \"%s\"\n",
2261 pw->pw_class, (long)pw->pw_change, pw->pw_gecos);
2262 printf("Shell: \"%s\"\nDirectory: \"%s\"\n",
2263 pw->pw_shell, pw->pw_dir);
2265 pw = getpwnam(pw->pw_name);
2266 irp_marshall_pw(pw, &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");
2273 } else {
2274 if ((pw = getpwnam(argv[1])) == NULL) {
2275 perror("getpwnam");
2276 exit(1);
2279 if (irp_marshall_pw(pw, &b, &len) != 0) {
2280 printf("irp_marshall_pw failed\n");
2281 exit(1);
2284 printf("success: \"%s\"\n", buffer);
2286 break;
2289 default:
2290 printf("Wrong option: %c\n", option);
2291 break;
2294 #endif
2296 return (0);
2299 #endif
2301 /*! \file */