1 /* 2 * Copyright(c) 1989, 1993, 1995 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 /* 35 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 36 * Portions Copyright (c) 1996 by Internet Software Consortium. 37 * 38 * Permission to use, copy, modify, and distribute this software for any 39 * purpose with or without fee is hereby granted, provided that the above 40 * copyright notice and this permission notice appear in all copies. 41 * 42 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 43 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 44 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 45 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 46 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 47 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 48 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 49 */ 50 51 #if defined(LIBC_SCCS) && !defined(lint) 52 static const char rcsid[] = "$Id: irpmarshall.c,v 1.7 2006/03/09 23:57:56 marka Exp $"; 53 #endif /* LIBC_SCCS and not lint */ 54 55 #if 0 56 57 Check values are in approrpriate endian order. 58 59 Double check memory allocations on unmarhsalling 60 61 #endif 62 63 64 /* Extern */ 65 66 #include "port_before.h" 67 68 #include <sys/types.h> 69 #include <sys/socket.h> 70 71 #include <netinet/in.h> 72 #include <arpa/inet.h> 73 #include <arpa/nameser.h> 74 75 #include <stdio.h> 76 #include <ctype.h> 77 #include <pwd.h> 78 #include <stdlib.h> 79 #include <string.h> 80 #include <syslog.h> 81 #include <utmp.h> 82 #include <unistd.h> 83 #include <assert.h> 84 #include <errno.h> 85 86 #include <irs.h> 87 #include <isc/memcluster.h> 88 #include <isc/irpmarshall.h> 89 90 #include "port_after.h" 91 92 93 #ifndef HAVE_STRNDUP 94 static char *strndup(const char *str, size_t len); 95 #endif 96 97 static char **splitarray(const char *buffer, const char *buffend, char delim); 98 static int joinarray(char * const * argv, char *buffer, char delim); 99 static char *getfield(char **res, size_t reslen, char **buffer, char delim); 100 static size_t joinlength(char * const *argv); 101 static void free_array(char **argv, size_t entries); 102 103 #define ADDR_T_STR(x) (x == AF_INET ? "AF_INET" :\ 104 (x == AF_INET6 ? "AF_INET6" : "UNKNOWN")) 105 106 #define MAXPADDRSIZE (sizeof "255.255.255.255" + 1) 107 108 static char COMMA = ','; 109 110 static const char *COMMASTR = ","; 111 static const char *COLONSTR = ":"; 112 113 114 115 /* See big comment at bottom of irpmarshall.h for description. */ 116 117 118 #ifdef WANT_IRS_PW 119 /* +++++++++++++++++++++++++ struct passwd +++++++++++++++++++++++++ */ 120 121 /*% 122 * int irp_marshall_pw(const struct passwd *pw, char **buffer, size_t *len) 123 * 124 * notes: \li 125 * 126 * See irpmarshall.h 127 * 128 * return: \li 129 * 130 * 0 on sucess, -1 on failure. 131 * 132 */ 133 134 int 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; 143 144 if (pw == NULL || len == NULL) { 145 errno = EINVAL; 146 return (-1); 147 } 148 149 sprintf(pwUid, "%ld", (long)pw->pw_uid); 150 sprintf(pwGid, "%ld", (long)pw->pw_gid); 151 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 158 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 165 166 #ifdef HAVE_PW_CLASS 167 pwClass = pw->pw_class; 168 #else 169 pwClass = ""; 170 #endif 171 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; 182 183 if (buffer == NULL) { 184 *len = need; 185 return (0); 186 } 187 188 if (*buffer != NULL && need > *len) { 189 errno = EINVAL; 190 return (-1); 191 } 192 193 if (*buffer == NULL) { 194 need += 2; /*%< for CRLF */ 195 *buffer = memget(need); 196 if (*buffer == NULL) { 197 errno = ENOMEM; 198 return (-1); 199 } 200 201 *len = need; 202 } 203 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); 214 215 return (0); 216 } 217 218 /*% 219 * int irp_unmarshall_pw(struct passwd *pw, char *buffer) 220 * 221 * notes: \li 222 * 223 * See irpmarshall.h 224 * 225 * return: \li 226 * 227 * 0 on success, -1 on failure 228 * 229 */ 230 231 int 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; 244 245 name = pass = class = gecos = dir = shell = NULL; 246 p = buffer; 247 248 /* pw_name field */ 249 name = NULL; 250 if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) { 251 goto error; 252 } 253 254 /* pw_passwd field */ 255 pass = NULL; 256 if (getfield(&pass, 0, &p, fieldsep) == NULL) { /*%< field can be empty */ 257 goto error; 258 } 259 260 261 /* pw_uid field */ 262 tb = tmpbuf; 263 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || 264 strlen(tb) == 0) { 265 goto error; 266 } 267 t = strtol(tmpbuf, &tb, 10); 268 if (*tb) { 269 goto error; /*%< junk in value */ 270 } 271 pwuid = (uid_t)t; 272 if ((long) pwuid != t) { /*%< value must have been too big. */ 273 goto error; 274 } 275 276 277 278 /* pw_gid field */ 279 tb = tmpbuf; 280 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || 281 strlen(tb) == 0) { 282 goto error; 283 } 284 t = strtol(tmpbuf, &tb, 10); 285 if (*tb) { 286 goto error; /*%< junk in value */ 287 } 288 pwgid = (gid_t)t; 289 if ((long)pwgid != t) { /*%< value must have been too big. */ 290 goto error; 291 } 292 293 294 295 /* pw_class field */ 296 class = NULL; 297 if (getfield(&class, 0, &p, fieldsep) == NULL) { 298 goto error; 299 } 300 301 302 303 /* pw_change field */ 304 tb = tmpbuf; 305 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || 306 strlen(tb) == 0) { 307 goto error; 308 } 309 t = strtol(tmpbuf, &tb, 10); 310 if (*tb) { 311 goto error; /*%< junk in value */ 312 } 313 pwchange = (time_t)t; 314 if ((long)pwchange != t) { /*%< value must have been too big. */ 315 goto error; 316 } 317 318 319 320 /* pw_expire field */ 321 tb = tmpbuf; 322 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || 323 strlen(tb) == 0) { 324 goto error; 325 } 326 t = strtol(tmpbuf, &tb, 10); 327 if (*tb) { 328 goto error; /*%< junk in value */ 329 } 330 pwexpire = (time_t)t; 331 if ((long) pwexpire != t) { /*%< value must have been too big. */ 332 goto error; 333 } 334 335 336 337 /* pw_gecos field */ 338 gecos = NULL; 339 if (getfield(&gecos, 0, &p, fieldsep) == NULL) { 340 goto error; 341 } 342 343 344 345 /* pw_dir field */ 346 dir = NULL; 347 if (getfield(&dir, 0, &p, fieldsep) == NULL) { 348 goto error; 349 } 350 351 352 353 /* pw_shell field */ 354 shell = NULL; 355 if (getfield(&shell, 0, &p, fieldsep) == NULL) { 356 goto error; 357 } 358 359 360 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; 368 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 378 379 return (0); 380 381 error: 382 errno = myerrno; 383 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); 389 390 return (-1); 391 } 392 393 /* ------------------------- struct passwd ------------------------- */ 394 #endif /* WANT_IRS_PW */ 395 /* +++++++++++++++++++++++++ struct group +++++++++++++++++++++++++ */ 396 397 /*% 398 * int irp_marshall_gr(const struct group *gr, char **buffer, size_t *len) 399 * 400 * notes: \li 401 * 402 * See irpmarshall.h. 403 * 404 * return: \li 405 * 406 * 0 on success, -1 on failure 407 */ 408 409 int 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; 414 415 if (gr == NULL || len == NULL) { 416 errno = EINVAL; 417 return (-1); 418 } 419 420 sprintf(grGid, "%ld", (long)gr->gr_gid); 421 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; 430 431 if (buffer == NULL) { 432 *len = need; 433 return (0); 434 } 435 436 if (*buffer != NULL && need > *len) { 437 errno = EINVAL; 438 return (-1); 439 } 440 441 if (*buffer == NULL) { 442 need += 2; /*%< for CRLF */ 443 *buffer = memget(need); 444 if (*buffer == NULL) { 445 errno = ENOMEM; 446 return (-1); 447 } 448 449 *len = need; 450 } 451 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); 459 460 return (0); 461 } 462 463 /*% 464 * int irp_unmarshall_gr(struct group *gr, char *buffer) 465 * 466 * notes: \li 467 * 468 * See irpmarshall.h 469 * 470 * return: \li 471 * 472 * 0 on success and -1 on failure. 473 * 474 */ 475 476 int 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; 488 489 if (gr == NULL || buffer == NULL) { 490 errno = EINVAL; 491 return (-1); 492 } 493 494 p = buffer; 495 496 /* gr_name field */ 497 name = NULL; 498 if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) { 499 goto error; 500 } 501 502 503 /* gr_passwd field */ 504 pass = NULL; 505 if (getfield(&pass, 0, &p, fieldsep) == NULL) { 506 goto error; 507 } 508 509 510 /* gr_gid field */ 511 tb = tmpbuf; 512 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || 513 strlen(tb) == 0U) { 514 goto error; 515 } 516 t = strtol(tmpbuf, &tb, 10); 517 if (*tb) { 518 goto error; /*%< junk in value */ 519 } 520 grgid = (gid_t)t; 521 if ((long) grgid != t) { /*%< value must have been too big. */ 522 goto error; 523 } 524 525 526 /* gr_mem field. Member names are separated by commas */ 527 q = strchr(p, fieldsep); 528 if (q == NULL) { 529 goto error; 530 } 531 members = splitarray(p, q, COMMA); 532 if (members == NULL) { 533 myerrno = errno; 534 goto error; 535 } 536 p = q + 1; 537 538 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; 545 546 return (0); 547 548 error: 549 errno = myerrno; 550 551 if (name != NULL) free(name); 552 if (pass != NULL) free(pass); 553 554 return (-1); 555 } 556 557 558 /* ------------------------- struct group ------------------------- */ 559 560 561 562 563 /* +++++++++++++++++++++++++ struct servent +++++++++++++++++++++++++ */ 564 565 /*% 566 * int irp_marshall_sv(const struct servent *sv, char **buffer, size_t *len) 567 * 568 * notes: \li 569 * 570 * See irpmarshall.h 571 * 572 * return: \li 573 * 574 * 0 on success, -1 on failure. 575 * 576 */ 577 578 int 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; 584 585 if (sv == NULL || len == NULL) { 586 errno = EINVAL; 587 return (-1); 588 } 589 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); 594 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; 599 600 if (buffer == NULL) { 601 *len = need; 602 return (0); 603 } 604 605 if (*buffer != NULL && need > *len) { 606 errno = EINVAL; 607 return (-1); 608 } 609 610 if (*buffer == NULL) { 611 need += 2; /*%< for CRLF */ 612 *buffer = memget(need); 613 if (*buffer == NULL) { 614 errno = ENOMEM; 615 return (-1); 616 } 617 618 *len = need; 619 } 620 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); 625 626 return (0); 627 } 628 629 /*% 630 * int irp_unmarshall_sv(struct servent *sv, char *buffer) 631 * 632 * notes: \li 633 * 634 * See irpmarshall.h 635 * 636 * return: \li 637 * 638 * 0 on success, -1 on failure. 639 * 640 */ 641 642 int 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; 654 655 if (sv == NULL || buffer == NULL) 656 return (-1); 657 658 p = buffer; 659 660 661 /* s_name field */ 662 name = NULL; 663 if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) { 664 goto error; 665 } 666 667 668 /* s_aliases field */ 669 q = strchr(p, fieldsep); 670 if (q == NULL) { 671 goto error; 672 } 673 aliases = splitarray(p, q, COMMA); 674 if (aliases == NULL) { 675 myerrno = errno; 676 goto error; 677 } 678 p = q + 1; 679 680 681 /* s_port field */ 682 tb = tmpbuf; 683 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || 684 strlen(tb) == 0U) { 685 goto error; 686 } 687 t = strtol(tmpbuf, &tb, 10); 688 if (*tb) { 689 goto error; /*%< junk in value */ 690 } 691 svport = (short)t; 692 if ((long) svport != t) { /*%< value must have been too big. */ 693 goto error; 694 } 695 svport = htons(svport); 696 697 /* s_proto field */ 698 proto = NULL; 699 if (getfield(&proto, 0, &p, fieldsep) == NULL) { 700 goto error; 701 } 702 703 sv->s_name = name; 704 sv->s_aliases = aliases; 705 sv->s_port = svport; 706 sv->s_proto = proto; 707 708 return (0); 709 710 error: 711 errno = myerrno; 712 713 if (name != NULL) free(name); 714 if (proto != NULL) free(proto); 715 free_array(aliases, 0); 716 717 return (-1); 718 } 719 720 721 /* ------------------------- struct servent ------------------------- */ 722 723 /* +++++++++++++++++++++++++ struct protoent +++++++++++++++++++++++++ */ 724 725 /*% 726 * int irp_marshall_pr(struct protoent *pr, char **buffer, size_t *len) 727 * 728 * notes: \li 729 * 730 * See irpmarshall.h 731 * 732 * return: \li 733 * 734 * 0 on success and -1 on failure. 735 * 736 */ 737 738 int 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; 743 744 if (pr == NULL || len == NULL) { 745 errno = EINVAL; 746 return (-1); 747 } 748 749 sprintf(prProto, "%d", (int)pr->p_proto); 750 751 need += strlen(pr->p_name) + 1; 752 need += joinlength(pr->p_aliases) + 1; 753 need += strlen(prProto) + 1; 754 755 if (buffer == NULL) { 756 *len = need; 757 return (0); 758 } 759 760 if (*buffer != NULL && need > *len) { 761 errno = EINVAL; 762 return (-1); 763 } 764 765 if (*buffer == NULL) { 766 need += 2; /*%< for CRLF */ 767 *buffer = memget(need); 768 if (*buffer == NULL) { 769 errno = ENOMEM; 770 return (-1); 771 } 772 773 *len = need; 774 } 775 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); 779 780 return (0); 781 782 } 783 784 /*% 785 * int irp_unmarshall_pr(struct protoent *pr, char *buffer) 786 * 787 * notes: \li 788 * 789 * See irpmarshall.h 790 * 791 * return: \li 792 * 793 * 0 on success, -1 on failure 794 * 795 */ 796 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; 807 808 if (pr == NULL || buffer == NULL) { 809 errno = EINVAL; 810 return (-1); 811 } 812 813 p = buffer; 814 815 /* p_name field */ 816 name = NULL; 817 if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) { 818 goto error; 819 } 820 821 822 /* p_aliases field */ 823 q = strchr(p, fieldsep); 824 if (q == NULL) { 825 goto error; 826 } 827 aliases = splitarray(p, q, COMMA); 828 if (aliases == NULL) { 829 myerrno = errno; 830 goto error; 831 } 832 p = q + 1; 833 834 835 /* p_proto field */ 836 tb = tmpbuf; 837 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || 838 strlen(tb) == 0U) { 839 goto error; 840 } 841 t = strtol(tmpbuf, &tb, 10); 842 if (*tb) { 843 goto error; /*%< junk in value */ 844 } 845 prproto = (int)t; 846 if ((long) prproto != t) { /*%< value must have been too big. */ 847 goto error; 848 } 849 850 pr->p_name = name; 851 pr->p_aliases = aliases; 852 pr->p_proto = prproto; 853 854 return (0); 855 856 error: 857 errno = myerrno; 858 859 if (name != NULL) free(name); 860 free_array(aliases, 0); 861 862 return (-1); 863 } 864 865 /* ------------------------- struct protoent ------------------------- */ 866 867 868 869 /* +++++++++++++++++++++++++ struct hostent +++++++++++++++++++++++++ */ 870 871 /*% 872 * int irp_marshall_ho(struct hostent *ho, char **buffer, size_t *len) 873 * 874 * notes: \li 875 * 876 * See irpmarshall.h. 877 * 878 * return: \li 879 * 880 * 0 on success, -1 on failure. 881 * 882 */ 883 884 int 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 = "@"; 895 896 if (ho == NULL || len == NULL) { 897 errno = EINVAL; 898 return (-1); 899 } 900 901 switch(ho->h_addrtype) { 902 case AF_INET: 903 strcpy(hoaddrtype, "AF_INET"); 904 break; 905 906 case AF_INET6: 907 strcpy(hoaddrtype, "AF_INET6"); 908 break; 909 910 default: 911 errno = EINVAL; 912 return (-1); 913 } 914 915 sprintf(holength, "%d", ho->h_length); 916 917 need += strlen(ho->h_name) + 1; 918 need += joinlength(ho->h_aliases) + 1; 919 need += strlen(hoaddrtype) + 1; 920 need += strlen(holength) + 1; 921 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; 927 928 if (buffer == NULL) { 929 *len = need; 930 return (0); 931 } 932 933 if (*buffer != NULL && need > *len) { 934 errno = EINVAL; 935 return (-1); 936 } 937 938 if (*buffer == NULL) { 939 need += 2; /*%< for CRLF */ 940 *buffer = memget(need); 941 if (*buffer == NULL) { 942 errno = ENOMEM; 943 return (-1); 944 } 945 946 *len = need; 947 malloced = 1; 948 } 949 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); 954 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; 960 } 961 if (*(av + 1) != NULL) 962 strcat(p, COMMASTR); 963 remlen -= strlen(p); 964 p += strlen(p); 965 } 966 strcat(*buffer, fieldsep); 967 968 return (0); 969 970 error: 971 if (malloced) { 972 memput(*buffer, need); 973 } 974 975 return (-1); 976 } 977 978 /*% 979 * int irp_unmarshall_ho(struct hostent *ho, char *buffer) 980 * 981 * notes: \li 982 * 983 * See irpmarshall.h. 984 * 985 * return: \li 986 * 987 * 0 on success, -1 on failure. 988 * 989 */ 990 991 int 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; 1007 1008 if (ho == NULL || buffer == NULL) { 1009 errno = EINVAL; 1010 return (-1); 1011 } 1012 1013 p = buffer; 1014 1015 /* h_name field */ 1016 name = NULL; 1017 if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) { 1018 goto error; 1019 } 1020 1021 1022 /* h_aliases field */ 1023 q = strchr(p, fieldsep); 1024 if (q == NULL) { 1025 goto error; 1026 } 1027 aliases = splitarray(p, q, COMMA); 1028 if (aliases == NULL) { 1029 myerrno = errno; 1030 goto error; 1031 } 1032 p = q + 1; 1033 1034 1035 /* h_addrtype field */ 1036 tb = tmpbuf; 1037 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || 1038 strlen(tb) == 0U) { 1039 goto error; 1040 } 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; 1047 1048 1049 /* h_length field */ 1050 tb = tmpbuf; 1051 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || 1052 strlen(tb) == 0U) { 1053 goto error; 1054 } 1055 t = strtol(tmpbuf, &tb, 10); 1056 if (*tb) { 1057 goto error; /*%< junk in value */ 1058 } 1059 holength = (int)t; 1060 if ((long) holength != t) { /*%< value must have been too big. */ 1061 goto error; 1062 } 1063 1064 1065 /* h_addr_list field */ 1066 q = strchr(p, fieldsep); 1067 if (q == NULL) 1068 goto error; 1069 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++; 1075 } 1076 } else { 1077 addrcount = 0; 1078 } 1079 1080 hoaddrsize = (addrcount + 1) * sizeof (char *); 1081 hohaddrlist = malloc(hoaddrsize); 1082 if (hohaddrlist == NULL) { 1083 myerrno = ENOMEM; 1084 goto error; 1085 } 1086 1087 memset(hohaddrlist, 0x0, hoaddrsize); 1088 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; 1095 1096 alist[t] = malloc(hoaddrtype == AF_INET ? 4 : 16); 1097 if (alist[t] == NULL) { 1098 myerrno = ENOMEM; 1099 goto error; 1100 } 1101 1102 if (inet_pton(hoaddrtype, p, alist[t]) == -1) 1103 goto error; 1104 *r = saved; 1105 } 1106 alist[t] = NULL; 1107 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; 1113 1114 return (0); 1115 1116 error: 1117 errno = myerrno; 1118 1119 if (name != NULL) free(name); 1120 free_array(hohaddrlist, 0); 1121 free_array(aliases, 0); 1122 1123 return (-1); 1124 } 1125 1126 /* ------------------------- struct hostent------------------------- */ 1127 1128 1129 1130 /* +++++++++++++++++++++++++ struct netgrp +++++++++++++++++++++++++ */ 1131 1132 /*% 1133 * int irp_marshall_ng(const char *host, const char *user, 1134 * const char *domain, char *buffer, size_t *len) 1135 * 1136 * notes: \li 1137 * 1138 * See note for irp_marshall_ng_start 1139 * 1140 * return: \li 1141 * 1142 * 0 on success, 0 on failure. 1143 * 1144 */ 1145 1146 int 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 = ","; 1151 1152 if (len == NULL) { 1153 errno = EINVAL; 1154 return (-1); 1155 } 1156 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)); 1161 1162 if (buffer == NULL) { 1163 *len = need; 1164 return (0); 1165 } else if (*buffer != NULL && need > *len) { 1166 errno = EINVAL; 1167 return (-1); 1168 } 1169 1170 if (*buffer == NULL) { 1171 need += 2; /*%< for CRLF */ 1172 *buffer = memget(need); 1173 if (*buffer == NULL) { 1174 errno = ENOMEM; 1175 return (-1); 1176 } 1177 1178 *len = need; 1179 } 1180 1181 (*buffer)[0] = '('; 1182 (*buffer)[1] = '\0'; 1183 1184 if (host != NULL) 1185 strcat(*buffer, host); 1186 strcat(*buffer, fieldsep); 1187 1188 if (user != NULL) 1189 strcat(*buffer, user); 1190 strcat(*buffer, fieldsep); 1191 1192 if (domain != NULL) 1193 strcat(*buffer, domain); 1194 strcat(*buffer, ")"); 1195 1196 return (0); 1197 } 1198 1199 1200 1201 /* ---------- */ 1202 1203 /*% 1204 * int irp_unmarshall_ng(const char **host, const char **user, 1205 * const char **domain, char *buffer) 1206 * 1207 * notes: \li 1208 * 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. 1212 * 1213 * return: \li 1214 * 1215 * 0 on success and -1 on failure. 1216 */ 1217 1218 int 1219 irp_unmarshall_ng(const char **hostp, const char **userp, const char **domainp, 1220 char *buffer) 1221 { 1222 char *p, *q; 1223 char fieldsep = ','; 1224 int myerrno = EINVAL; 1225 char *host, *user, *domain; 1226 1227 if (userp == NULL || hostp == NULL || 1228 domainp == NULL || buffer == NULL) { 1229 errno = EINVAL; 1230 return (-1); 1231 } 1232 1233 host = user = domain = NULL; 1234 1235 p = buffer; 1236 while (isspace((unsigned char)*p)) { 1237 p++; 1238 } 1239 if (*p != '(') { 1240 goto error; 1241 } 1242 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); 1250 } 1251 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; 1261 } 1262 user = strndup(p, q - p); 1263 } else { 1264 p++; 1265 } 1266 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; 1275 } 1276 domain = strndup(p, q - p); 1277 } 1278 *hostp = host; 1279 *userp = user; 1280 *domainp = domain; 1281 1282 return (0); 1283 1284 error: 1285 errno = myerrno; 1286 1287 if (host != NULL) free(host); 1288 if (user != NULL) free(user); 1289 1290 return (-1); 1291 } 1292 1293 /* ------------------------- struct netgrp ------------------------- */ 1294 1295 1296 1297 1298 /* +++++++++++++++++++++++++ struct nwent +++++++++++++++++++++++++ */ 1299 1300 /*% 1301 * int irp_marshall_nw(struct nwent *ne, char **buffer, size_t *len) 1302 * 1303 * notes: \li 1304 * 1305 * See at top. 1306 * 1307 * return: \li 1308 * 1309 * 0 on success and -1 on failure. 1310 * 1311 */ 1312 1313 int 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; 1319 1320 if (ne == NULL || len == NULL) { 1321 return (-1); 1322 } 1323 1324 strcpy(nAddrType, ADDR_T_STR(ne->n_addrtype)); 1325 1326 if (inet_net_ntop(ne->n_addrtype, ne->n_addr, ne->n_length, 1327 nNet, sizeof nNet) == NULL) { 1328 return (-1); 1329 } 1330 1331 1332 need += strlen(ne->n_name) + 1; 1333 need += joinlength(ne->n_aliases) + 1; 1334 need += strlen(nAddrType) + 1; 1335 need += strlen(nNet) + 1; 1336 1337 if (buffer == NULL) { 1338 *len = need; 1339 return (0); 1340 } 1341 1342 if (*buffer != NULL && need > *len) { 1343 errno = EINVAL; 1344 return (-1); 1345 } 1346 1347 if (*buffer == NULL) { 1348 need += 2; /*%< for CRLF */ 1349 *buffer = memget(need); 1350 if (*buffer == NULL) { 1351 errno = ENOMEM; 1352 return (-1); 1353 } 1354 1355 *len = need; 1356 } 1357 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); 1362 1363 return (0); 1364 } 1365 1366 /*% 1367 * int irp_unmarshall_nw(struct nwent *ne, char *buffer) 1368 * 1369 * notes: \li 1370 * 1371 * See note up top. 1372 * 1373 * return: \li 1374 * 1375 * 0 on success and -1 on failure. 1376 * 1377 */ 1378 1379 int 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; 1391 1392 if (ne == NULL || buffer == NULL) { 1393 goto error; 1394 } 1395 1396 p = buffer; 1397 1398 /* n_name field */ 1399 name = NULL; 1400 if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) { 1401 goto error; 1402 } 1403 1404 1405 /* n_aliases field. Aliases are separated by commas */ 1406 q = strchr(p, fieldsep); 1407 if (q == NULL) { 1408 goto error; 1409 } 1410 aliases = splitarray(p, q, COMMA); 1411 if (aliases == NULL) { 1412 myerrno = errno; 1413 goto error; 1414 } 1415 p = q + 1; 1416 1417 1418 /* h_addrtype field */ 1419 tb = tmpbuf; 1420 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || 1421 strlen(tb) == 0U) { 1422 goto error; 1423 } 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; 1430 1431 1432 /* n_net field */ 1433 tb = tmpbuf; 1434 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || 1435 strlen(tb) == 0U) { 1436 goto error; 1437 } 1438 nnet = 0; 1439 bits = inet_net_pton(naddrtype, tmpbuf, &nnet, sizeof nnet); 1440 if (bits < 0) { 1441 goto error; 1442 } 1443 1444 /* nnet = ntohl(nnet); */ /* keep in network order for nwent */ 1445 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; 1453 } 1454 1455 memcpy(ne->n_addr, &nnet, sizeof nnet); 1456 1457 return (0); 1458 1459 error: 1460 errno = myerrno; 1461 1462 if (name != NULL) free(name); 1463 free_array(aliases, 0); 1464 1465 return (-1); 1466 } 1467 1468 1469 /* ------------------------- struct nwent ------------------------- */ 1470 1471 1472 /* +++++++++++++++++++++++++ struct netent +++++++++++++++++++++++++ */ 1473 1474 /*% 1475 * int irp_marshall_ne(struct netent *ne, char **buffer, size_t *len) 1476 * 1477 * notes: \li 1478 * 1479 * See at top. 1480 * 1481 * return: \li 1482 * 1483 * 0 on success and -1 on failure. 1484 * 1485 */ 1486 1487 int 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; 1494 1495 if (ne == NULL || len == NULL) { 1496 return (-1); 1497 } 1498 1499 strcpy(nAddrType, ADDR_T_STR(ne->n_addrtype)); 1500 1501 nval = htonl(ne->n_net); 1502 if (inet_ntop(ne->n_addrtype, &nval, nNet, sizeof nNet) == NULL) { 1503 return (-1); 1504 } 1505 1506 need += strlen(ne->n_name) + 1; 1507 need += joinlength(ne->n_aliases) + 1; 1508 need += strlen(nAddrType) + 1; 1509 need += strlen(nNet) + 1; 1510 1511 if (buffer == NULL) { 1512 *len = need; 1513 return (0); 1514 } 1515 1516 if (*buffer != NULL && need > *len) { 1517 errno = EINVAL; 1518 return (-1); 1519 } 1520 1521 if (*buffer == NULL) { 1522 need += 2; /*%< for CRLF */ 1523 *buffer = memget(need); 1524 if (*buffer == NULL) { 1525 errno = ENOMEM; 1526 return (-1); 1527 } 1528 1529 *len = need; 1530 } 1531 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); 1536 1537 return (0); 1538 } 1539 1540 /*% 1541 * int irp_unmarshall_ne(struct netent *ne, char *buffer) 1542 * 1543 * notes: \li 1544 * 1545 * See note up top. 1546 * 1547 * return: \li 1548 * 1549 * 0 on success and -1 on failure. 1550 * 1551 */ 1552 1553 int 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; 1565 1566 if (ne == NULL || buffer == NULL) { 1567 goto error; 1568 } 1569 1570 p = buffer; 1571 1572 /* n_name field */ 1573 name = NULL; 1574 if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) { 1575 goto error; 1576 } 1577 1578 1579 /* n_aliases field. Aliases are separated by commas */ 1580 q = strchr(p, fieldsep); 1581 if (q == NULL) { 1582 goto error; 1583 } 1584 aliases = splitarray(p, q, COMMA); 1585 if (aliases == NULL) { 1586 myerrno = errno; 1587 goto error; 1588 } 1589 p = q + 1; 1590 1591 1592 /* h_addrtype field */ 1593 tb = tmpbuf; 1594 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || 1595 strlen(tb) == 0U) { 1596 goto error; 1597 } 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; 1604 1605 1606 /* n_net field */ 1607 tb = tmpbuf; 1608 if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || 1609 strlen(tb) == 0U) { 1610 goto error; 1611 } 1612 bits = inet_net_pton(naddrtype, tmpbuf, &nnet, sizeof nnet); 1613 if (bits < 0) { 1614 goto error; 1615 } 1616 nnet = ntohl(nnet); 1617 1618 ne->n_name = name; 1619 ne->n_aliases = aliases; 1620 ne->n_addrtype = naddrtype; 1621 ne->n_net = nnet; 1622 1623 return (0); 1624 1625 error: 1626 errno = myerrno; 1627 1628 if (name != NULL) free(name); 1629 free_array(aliases, 0); 1630 1631 return (-1); 1632 } 1633 1634 1635 /* ------------------------- struct netent ------------------------- */ 1636 1637 1638 /* =========================================================================== */ 1639 1640 /*% 1641 * static char ** splitarray(const char *buffer, const char *buffend, char delim) 1642 * 1643 * notes: \li 1644 * 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). 1650 * 1651 * return: \li 1652 * 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. 1656 * 1657 */ 1658 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; 1665 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); 1672 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); 1680 } 1681 count++; 1682 } 1683 } 1684 } 1685 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); 1692 } 1693 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); 1699 1700 p = q; 1701 aptr++; 1702 } 1703 *aptr = NULL; 1704 } else { 1705 arr = malloc(sizeof (char *)); 1706 if (arr == NULL) { 1707 errno = ENOMEM; 1708 return (NULL); 1709 } 1710 1711 *arr = NULL; 1712 } 1713 1714 return (arr); 1715 } 1716 1717 /*% 1718 * static size_t joinlength(char * const *argv) 1719 * 1720 * return: \li 1721 * 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). 1725 * 1726 * 1727 */ 1728 1729 static size_t 1730 joinlength(char * const *argv) { 1731 int len = 0; 1732 1733 while (argv && *argv) { 1734 len += (strlen(*argv) + 1); 1735 argv++; 1736 } 1737 1738 return (len); 1739 } 1740 1741 /*% 1742 * int joinarray(char * const *argv, char *buffer, char delim) 1743 * 1744 * notes: \li 1745 * 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. 1749 * 1750 * return: \li 1751 * 1752 * 0 unless argv or buffer is NULL. 1753 * 1754 * 1755 */ 1756 1757 static int 1758 joinarray(char * const *argv, char *buffer, char delim) { 1759 char * const *p; 1760 char sep[2]; 1761 1762 if (argv == NULL || buffer == NULL) { 1763 errno = EINVAL; 1764 return (-1); 1765 } 1766 1767 sep[0] = delim; 1768 sep[1] = 0x0; 1769 1770 for (p = argv ; *p != NULL ; p++) { 1771 strcat(buffer, *p); 1772 if (*(p + 1) != NULL) { 1773 strcat(buffer, sep); 1774 } 1775 } 1776 1777 return (0); 1778 } 1779 1780 /*% 1781 * static char * getfield(char **res, size_t reslen, char **ptr, char delim) 1782 * 1783 * notes: \li 1784 * 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. 1790 * 1791 * return: \li 1792 * 1793 * If there was no delimiter, then NULL is returned, 1794 * otherewise *RES is returned. 1795 * 1796 */ 1797 1798 static char * 1799 getfield(char **res, size_t reslen, char **ptr, char delim) { 1800 char *q; 1801 1802 if (res == NULL || ptr == NULL || *ptr == NULL) { 1803 errno = EINVAL; 1804 return (NULL); 1805 } 1806 1807 q = strchr(*ptr, delim); 1808 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; 1822 } 1823 } 1824 *ptr = q + 1; 1825 } 1826 1827 return (*res); 1828 } 1829 1830 1831 1832 1833 1834 #ifndef HAVE_STRNDUP 1835 /* 1836 * static char * strndup(const char *str, size_t len) 1837 * 1838 * notes: \li 1839 * 1840 * like strdup, except do len bytes instead of the whole string. Always 1841 * null-terminates. 1842 * 1843 * return: \li 1844 * 1845 * The newly malloced string. 1846 * 1847 */ 1848 1849 static char * 1850 strndup(const char *str, size_t len) { 1851 char *p = malloc(len + 1); 1852 1853 if (p == NULL) 1854 return (NULL); 1855 strncpy(p, str, len); 1856 p[len] = 0x0; 1857 return (p); 1858 } 1859 #endif 1860 1861 #if WANT_MAIN 1862 1863 /*% 1864 * static int strcmp_nws(const char *a, const char *b) 1865 * 1866 * notes: \li 1867 * 1868 * do a strcmp, except uneven lengths of whitespace compare the same 1869 * 1870 * return: \li 1871 * 1872 */ 1873 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)); 1884 } 1885 if (*a < *b) 1886 return (-1); 1887 else if (*a > *b) 1888 return (1); 1889 1890 a++; 1891 b++;; 1892 } 1893 1894 if (*a == *b) 1895 return (0); 1896 else if (*a > *b) 1897 return (1); 1898 else 1899 return (-1); 1900 } 1901 1902 #endif 1903 1904 /*% 1905 * static void free_array(char **argv, size_t entries) 1906 * 1907 * notes: \li 1908 * 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. 1913 * 1914 */ 1915 1916 static void 1917 free_array(char **argv, size_t entries) { 1918 char **p = argv; 1919 int useEntries = (entries > 0U); 1920 1921 if (argv == NULL) 1922 return; 1923 1924 while ((useEntries && entries > 0U) || *p) { 1925 if (*p) 1926 free(*p); 1927 p++; 1928 if (useEntries) 1929 entries--; 1930 } 1931 free(argv); 1932 } 1933 1934 1935 1936 1937 1938 /* ************************************************** */ 1939 1940 #if WANT_MAIN 1941 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. 1946 */ 1947 1948 int 1949 main(int argc, char **argv) { 1950 char buffer[1024]; 1951 char *b = &buffer[0]; 1952 size_t len = sizeof buffer; 1953 char option; 1954 1955 if (argc < 2 || argv[1][0] != '-') 1956 exit(1); 1957 1958 option = argv[1][1]; 1959 argv++; 1960 argc--; 1961 1962 1963 #if 0 1964 { 1965 char buff[10]; 1966 char *p = argv[1], *q = &buff[0]; 1967 1968 while (getfield(&q, sizeof buff, &p, ':') != NULL) { 1969 printf("field: \"%s\"\n", q); 1970 p++; 1971 } 1972 printf("p is now \"%s\"\n", p); 1973 } 1974 #endif 1975 1976 #if 0 1977 { 1978 char **x = splitarray(argv[1], argv[1] + strlen(argv[1]), 1979 argv[2][0]); 1980 char **p; 1981 1982 if (x == NULL) 1983 printf("split failed\n"); 1984 1985 for (p = x ; p != NULL && *p != NULL ; p++) { 1986 printf("\"%s\"\n", *p); 1987 } 1988 } 1989 #endif 1990 1991 #if 1 1992 switch(option) { 1993 case 'n': { 1994 struct nwent ne; 1995 int i; 1996 1997 if (strchr(argv[1], ':') != NULL) { 1998 if (irp_unmarshall_nw(&ne, argv[1]) != 0) { 1999 printf("Unmarhsalling failed\n"); 2000 exit(1); 2001 } 2002 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) ? 2022 8 : 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"); 2030 } 2031 printf("%s\n", b); 2032 } 2033 break; 2034 } 2035 2036 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; 2044 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); 2051 } 2052 2053 #define STRVAL(x) (x == NULL ? "*" : x) 2054 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"); 2062 2063 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); 2069 2070 buff = malloc(size); 2071 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"); 2078 } 2079 irp_marshall_ng_end(buff, &size); 2080 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"); 2086 } 2087 } else { 2088 char *h, *u, *d, *buff; 2089 size_t size; 2090 2091 /* run through two times. First to figure out how 2092 much of a buffer we need. Second to do the 2093 actual marshalling */ 2094 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]); 2101 2102 buff = malloc(size); 2103 2104 setnetgrent(argv[1]); 2105 if (irp_marshall_ng_start(argv[1], buff, &size) != 0) 2106 printf("Marshalling start failed\n"); 2107 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"); 2112 } 2113 } 2114 2115 irp_marshall_ng_end(buff, &size); 2116 endnetgrent(); 2117 2118 printf("success: %s\n", buff); 2119 } 2120 break; 2121 } 2122 2123 2124 2125 case 'h': { 2126 struct hostent he, *hp; 2127 int i; 2128 2129 2130 if (strchr(argv[1], '@') != NULL) { 2131 if (irp_unmarshall_ho(&he, argv[1]) != 0) { 2132 printf("unmarshall failed\n"); 2133 exit(1); 2134 } 2135 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); 2146 } 2147 printf("\n\n"); 2148 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"); 2155 } 2156 } else { 2157 if ((hp = gethostbyname(argv[1])) == NULL) { 2158 perror("gethostbyname"); 2159 printf("\"%s\"\n", argv[1]); 2160 exit(1); 2161 } 2162 2163 if (irp_marshall_ho(hp, &b, &len) != 0) { 2164 printf("irp_marshall_ho failed\n"); 2165 exit(1); 2166 } 2167 2168 printf("success: \"%s\"\n", buffer); 2169 } 2170 break; 2171 } 2172 2173 2174 case 's': { 2175 struct servent *sv; 2176 struct servent sv1; 2177 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"); 2183 2184 } 2185 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"); 2192 } 2193 } else { 2194 if ((sv = getservbyname(argv[1], argv[2])) == NULL) { 2195 perror("getservent"); 2196 exit(1); 2197 } 2198 2199 if (irp_marshall_sv(sv, &b, &len) != 0) { 2200 printf("irp_marshall_sv failed\n"); 2201 exit(1); 2202 } 2203 2204 printf("success: \"%s\"\n", buffer); 2205 } 2206 break; 2207 } 2208 2209 case 'g': { 2210 struct group *gr; 2211 struct group gr1; 2212 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"); 2218 2219 } 2220 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"); 2227 } 2228 } else { 2229 if ((gr = getgrnam(argv[1])) == NULL) { 2230 perror("getgrnam"); 2231 exit(1); 2232 } 2233 2234 if (irp_marshall_gr(gr, &b, &len) != 0) { 2235 printf("irp_marshall_gr failed\n"); 2236 exit(1); 2237 } 2238 2239 printf("success: \"%s\"\n", buffer); 2240 } 2241 break; 2242 } 2243 2244 2245 case 'p': { 2246 struct passwd *pw; 2247 struct passwd pw1; 2248 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); 2255 } 2256 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); 2264 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"); 2272 } 2273 } else { 2274 if ((pw = getpwnam(argv[1])) == NULL) { 2275 perror("getpwnam"); 2276 exit(1); 2277 } 2278 2279 if (irp_marshall_pw(pw, &b, &len) != 0) { 2280 printf("irp_marshall_pw failed\n"); 2281 exit(1); 2282 } 2283 2284 printf("success: \"%s\"\n", buffer); 2285 } 2286 break; 2287 } 2288 2289 default: 2290 printf("Wrong option: %c\n", option); 2291 break; 2292 } 2293 2294 #endif 2295 2296 return (0); 2297 } 2298 2299 #endif 2300 2301 /*! \file */ 2302