1/* $NetBSD: irpmarshall.c,v 1.1.1.1 2009/04/12 15:33:41 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) 54static 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 59Check values are in approrpriate endian order. 60 61Double 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 96static char *strndup(const char *str, size_t len); 97#endif 98 99static char **splitarray(const char *buffer, const char *buffend, char delim); 100static int joinarray(char * const * argv, char *buffer, char delim); 101static char *getfield(char **res, size_t reslen, char **buffer, char delim); 102static size_t joinlength(char * const *argv); 103static 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 110static char COMMA = ','; 111 112static const char *COMMASTR = ","; 113static 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 136int 137irp_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 233int 234irp_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 411int 412irp_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 478int 479irp_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 580int 581irp_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 644int 645irp_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 740int 741irp_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 799int 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 886int 887irp_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 993int 994irp_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 1148int 1149irp_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 1220int 1221irp_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 1315int 1316irp_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 1381int 1382irp_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 1489int 1490irp_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 1555int 1556irp_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 1661static char ** 1662splitarray(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 1731static size_t 1732joinlength(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 1759static int 1760joinarray(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 1800static char * 1801getfield(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 1851static char * 1852strndup(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 1876static int 1877strcmp_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 1918static void 1919free_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 1950int 1951main(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