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