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