Home | History | Annotate | Download | only in strace
      1 /*
      2  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs (at) world.std.com>
      3  * Copyright (c) 1996-1999 Wichert Akkerman <wichert (at) cistron.nl>
      4  * All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. The name of the author may not be used to endorse or promote products
     15  *    derived from this software without specific prior written permission.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  *
     28  *	$Id: stream.c,v 1.24 2005/06/01 19:22:07 roland Exp $
     29  */
     30 
     31 #include "defs.h"
     32 #include <sys/syscall.h>
     33 
     34 #ifdef HAVE_POLL_H
     35 #include <poll.h>
     36 #endif
     37 #ifdef HAVE_SYS_POLL_H
     38 #include <sys/poll.h>
     39 #endif
     40 #ifdef HAVE_STROPTS_H
     41 #include <stropts.h>
     42 #endif
     43 #ifdef HAVE_SYS_CONF_H
     44 #include <sys/conf.h>
     45 #endif
     46 #ifdef HAVE_SYS_STREAM_H
     47 #include <sys/stream.h>
     48 #endif
     49 #ifdef HAVE_SYS_TIHDR_H
     50 #include <sys/tihdr.h>
     51 #endif
     52 
     53 #if defined(HAVE_SYS_STREAM_H) || defined(LINUX) || defined(FREEBSD)
     54 
     55 #ifndef HAVE_STROPTS_H
     56 #define RS_HIPRI 1
     57 struct strbuf {
     58         int     maxlen;                 /* no. of bytes in buffer */
     59         int     len;                    /* no. of bytes returned */
     60         char    *buf;                   /* pointer to data */
     61 };
     62 #define MORECTL 1
     63 #define MOREDATA 2
     64 #endif /* !HAVE_STROPTS_H */
     65 
     66 #ifdef HAVE_SYS_TIUSER_H
     67 #include <sys/tiuser.h>
     68 #include <sys/sockmod.h>
     69 #include <sys/timod.h>
     70 #endif /* HAVE_SYS_TIUSER_H */
     71 
     72 #ifndef FREEBSD
     73 static const struct xlat msgflags[] = {
     74 	{ RS_HIPRI,	"RS_HIPRI"	},
     75 	{ 0,		NULL		},
     76 };
     77 
     78 
     79 static void
     80 printstrbuf(tcp, sbp, getting)
     81 struct tcb *tcp;
     82 struct strbuf *sbp;
     83 int getting;
     84 {
     85 	if (sbp->maxlen == -1 && getting)
     86 		tprintf("{maxlen=-1}");
     87 	else {
     88 		tprintf("{");
     89 		if (getting)
     90 			tprintf("maxlen=%d, ", sbp->maxlen);
     91 		tprintf("len=%d, buf=", sbp->len);
     92 		printstr(tcp, (unsigned long) sbp->buf, sbp->len);
     93 		tprintf("}");
     94 	}
     95 }
     96 
     97 static void
     98 printstrbufarg(tcp, arg, getting)
     99 struct tcb *tcp;
    100 int arg;
    101 int getting;
    102 {
    103 	struct strbuf buf;
    104 
    105 	if (arg == 0)
    106 		tprintf("NULL");
    107 	else if (umove(tcp, arg, &buf) < 0)
    108 		tprintf("{...}");
    109 	else
    110 		printstrbuf(tcp, &buf, getting);
    111 	tprintf(", ");
    112 }
    113 
    114 int
    115 sys_putmsg(tcp)
    116 struct tcb *tcp;
    117 {
    118 	int i;
    119 
    120 	if (entering(tcp)) {
    121 		/* fd */
    122 		tprintf("%ld, ", tcp->u_arg[0]);
    123 		/* control and data */
    124 		for (i = 1; i < 3; i++)
    125 			printstrbufarg(tcp, tcp->u_arg[i], 0);
    126 		/* flags */
    127 		printflags(msgflags, tcp->u_arg[3], "RS_???");
    128 	}
    129 	return 0;
    130 }
    131 
    132 int
    133 sys_getmsg(tcp)
    134 struct tcb *tcp;
    135 {
    136 	int i, flags;
    137 
    138 	if (entering(tcp)) {
    139 		/* fd */
    140 		tprintf("%lu, ", tcp->u_arg[0]);
    141 	} else {
    142 		if (syserror(tcp)) {
    143 			tprintf("%#lx, %#lx, %#lx",
    144 				tcp->u_arg[1], tcp->u_arg[2], tcp->u_arg[3]);
    145 			return 0;
    146 		}
    147 		/* control and data */
    148 		for (i = 1; i < 3; i++)
    149 			printstrbufarg(tcp, tcp->u_arg[i], 1);
    150 		/* pointer to flags */
    151 		if (tcp->u_arg[3] == 0)
    152 			tprintf("NULL");
    153 		else if (umove(tcp, tcp->u_arg[3], &flags) < 0)
    154 			tprintf("[?]");
    155 		else {
    156 			tprintf("[");
    157 			printflags(msgflags, flags, "RS_???");
    158 			tprintf("]");
    159 		}
    160 		/* decode return value */
    161 		switch (tcp->u_rval) {
    162 		case MORECTL:
    163 			tcp->auxstr = "MORECTL";
    164 			break;
    165 		case MORECTL|MOREDATA:
    166 			tcp->auxstr = "MORECTL|MOREDATA";
    167 			break;
    168 		case MOREDATA:
    169 			tcp->auxstr = "MORECTL";
    170 			break;
    171 		default:
    172 			tcp->auxstr = NULL;
    173 			break;
    174 		}
    175 	}
    176 	return RVAL_HEX | RVAL_STR;
    177 }
    178 
    179 #if defined SYS_putpmsg || defined SYS_getpmsg
    180 static const struct xlat pmsgflags[] = {
    181 #ifdef MSG_HIPRI
    182 	{ MSG_HIPRI,	"MSG_HIPRI"	},
    183 #endif
    184 #ifdef MSG_AND
    185 	{ MSG_ANY,	"MSG_ANY"	},
    186 #endif
    187 #ifdef MSG_BAND
    188 	{ MSG_BAND,	"MSG_BAND"	},
    189 #endif
    190 	{ 0,		NULL		},
    191 };
    192 #endif
    193 
    194 #ifdef SYS_putpmsg
    195 int
    196 sys_putpmsg(tcp)
    197 struct tcb *tcp;
    198 {
    199 	int i;
    200 
    201 	if (entering(tcp)) {
    202 		/* fd */
    203 		tprintf("%ld, ", tcp->u_arg[0]);
    204 		/* control and data */
    205 		for (i = 1; i < 3; i++)
    206 			printstrbufarg(tcp, tcp->u_arg[i], 0);
    207 		/* band */
    208 		tprintf("%ld, ", tcp->u_arg[3]);
    209 		/* flags */
    210 		printflags(pmsgflags, tcp->u_arg[4], "MSG_???");
    211 	}
    212 	return 0;
    213 }
    214 #endif /* SYS_putpmsg */
    215 
    216 #ifdef SYS_getpmsg
    217 int
    218 sys_getpmsg(tcp)
    219 struct tcb *tcp;
    220 {
    221 	int i, flags;
    222 
    223 	if (entering(tcp)) {
    224 		/* fd */
    225 		tprintf("%lu, ", tcp->u_arg[0]);
    226 	} else {
    227 		if (syserror(tcp)) {
    228 			tprintf("%#lx, %#lx, %#lx, %#lx", tcp->u_arg[1],
    229 				tcp->u_arg[2], tcp->u_arg[3], tcp->u_arg[4]);
    230 			return 0;
    231 		}
    232 		/* control and data */
    233 		for (i = 1; i < 3; i++)
    234 			printstrbufarg(tcp, tcp->u_arg[i], 1);
    235 		/* pointer to band */
    236 		printnum(tcp, tcp->u_arg[3], "%d");
    237 		tprintf(", ");
    238 		/* pointer to flags */
    239 		if (tcp->u_arg[4] == 0)
    240 			tprintf("NULL");
    241 		else if (umove(tcp, tcp->u_arg[4], &flags) < 0)
    242 			tprintf("[?]");
    243 		else {
    244 			tprintf("[");
    245 			printflags(pmsgflags, flags, "MSG_???");
    246 			tprintf("]");
    247 		}
    248 		/* decode return value */
    249 		switch (tcp->u_rval) {
    250 		case MORECTL:
    251 			tcp->auxstr = "MORECTL";
    252 			break;
    253 		case MORECTL|MOREDATA:
    254 			tcp->auxstr = "MORECTL|MOREDATA";
    255 			break;
    256 		case MOREDATA:
    257 			tcp->auxstr = "MORECTL";
    258 			break;
    259 		default:
    260 			tcp->auxstr = NULL;
    261 			break;
    262 		}
    263 	}
    264 	return RVAL_HEX | RVAL_STR;
    265 }
    266 #endif /* SYS_getpmsg */
    267 
    268 #endif /* !FREEBSD */
    269 
    270 
    271 #ifdef HAVE_SYS_POLL_H
    272 
    273 static const struct xlat pollflags[] = {
    274 #ifdef POLLIN
    275 	{ POLLIN,	"POLLIN"	},
    276 	{ POLLPRI,	"POLLPRI"	},
    277 	{ POLLOUT,	"POLLOUT"	},
    278 #ifdef POLLRDNORM
    279 	{ POLLRDNORM,	"POLLRDNORM"	},
    280 #endif
    281 #ifdef POLLWRNORM
    282 	{ POLLWRNORM,	"POLLWRNORM"	},
    283 #endif
    284 #ifdef POLLRDBAND
    285 	{ POLLRDBAND,	"POLLRDBAND"	},
    286 #endif
    287 #ifdef POLLWRBAND
    288 	{ POLLWRBAND,	"POLLWRBAND"	},
    289 #endif
    290 	{ POLLERR,	"POLLERR"	},
    291 	{ POLLHUP,	"POLLHUP"	},
    292 	{ POLLNVAL,	"POLLNVAL"	},
    293 #endif
    294 	{ 0,		NULL		},
    295 };
    296 
    297 int
    298 sys_poll(tcp)
    299 struct tcb *tcp;
    300 {
    301 	struct pollfd fds;
    302 	unsigned nfds;
    303 	unsigned long size, start, cur, end, abbrev_end;
    304 	int failed = 0;
    305 
    306 	if (entering(tcp))
    307 		return 0;
    308 
    309 	nfds = tcp->u_arg[1];
    310 	size = sizeof(fds) * nfds;
    311 	start = tcp->u_arg[0];
    312 	end = start + size;
    313 	if (nfds == 0 || size / sizeof(fds) != nfds || end < start) {
    314 		tprintf("%#lx, %d, %ld",
    315 			tcp->u_arg[0], nfds, tcp->u_arg[2]);
    316 		return 0;
    317 	}
    318 	if (abbrev(tcp)) {
    319 		abbrev_end = start + max_strlen * sizeof(fds);
    320 		if (abbrev_end < start)
    321 			abbrev_end = end;
    322 	} else {
    323 		abbrev_end = end;
    324 	}
    325 	tprintf("[");
    326 	for (cur = start; cur < end; cur += sizeof(fds)) {
    327 		if (cur > start)
    328 			tprintf(", ");
    329 		if (cur >= abbrev_end) {
    330 			tprintf("...");
    331 			break;
    332 		}
    333 		if (umoven(tcp, cur, sizeof fds, (char *) &fds) < 0) {
    334 			tprintf("?");
    335 			failed = 1;
    336 			break;
    337 		}
    338 		if (fds.fd < 0) {
    339 			tprintf("{fd=%d}", fds.fd);
    340 			continue;
    341 		}
    342 		tprintf("{fd=%d, events=", fds.fd);
    343 		printflags(pollflags, fds.events, "POLL???");
    344 		if (!syserror(tcp) && fds.revents) {
    345 			tprintf(", revents=");
    346 			printflags(pollflags, fds.revents, "POLL???");
    347 		}
    348 		tprintf("}");
    349 	}
    350 	tprintf("]");
    351 	if (failed)
    352 		tprintf(" %#lx", start);
    353 	tprintf(", %d, ", nfds);
    354 #ifdef INFTIM
    355 	if (tcp->u_arg[2] == INFTIM)
    356 		tprintf("INFTIM");
    357 	else
    358 #endif
    359 		tprintf("%ld", tcp->u_arg[2]);
    360 	return 0;
    361 }
    362 
    363 
    364 #else /* !HAVE_SYS_POLL_H */
    365 int
    366 sys_poll(tcp)
    367 struct tcb *tcp;
    368 {
    369     	return 0;
    370 }
    371 #endif
    372 
    373 #if !defined(LINUX) && !defined(FREEBSD)
    374 
    375 static const struct xlat stream_flush_options[] = {
    376 	{ FLUSHR,	"FLUSHR"	},
    377 	{ FLUSHW,	"FLUSHW"	},
    378 	{ FLUSHRW,	"FLUSHRW"	},
    379 #ifdef FLUSHBAND
    380 	{ FLUSHBAND,	"FLUSHBAND"	},
    381 #endif
    382 	{ 0,		NULL		},
    383 };
    384 
    385 static const struct xlat stream_setsig_flags[] = {
    386 	{ S_INPUT,	"S_INPUT"	},
    387 	{ S_HIPRI,	"S_HIPRI"	},
    388 	{ S_OUTPUT,	"S_OUTPUT"	},
    389 	{ S_MSG,	"S_MSG"		},
    390 #ifdef S_ERROR
    391 	{ S_ERROR,	"S_ERROR"	},
    392 #endif
    393 #ifdef S_HANGUP
    394 	{ S_HANGUP,	"S_HANGUP"	},
    395 #endif
    396 #ifdef S_RDNORM
    397 	{ S_RDNORM,	"S_RDNORM"	},
    398 #endif
    399 #ifdef S_WRNORM
    400 	{ S_WRNORM,	"S_WRNORM"	},
    401 #endif
    402 #ifdef S_RDBAND
    403 	{ S_RDBAND,	"S_RDBAND"	},
    404 #endif
    405 #ifdef S_WRBAND
    406 	{ S_WRBAND,	"S_WRBAND"	},
    407 #endif
    408 #ifdef S_BANDURG
    409 	{ S_BANDURG,	"S_BANDURG"	},
    410 #endif
    411 	{ 0,		NULL		},
    412 };
    413 
    414 static const struct xlat stream_read_options[] = {
    415 	{ RNORM,	"RNORM"		},
    416 	{ RMSGD,	"RMSGD"		},
    417 	{ RMSGN,	"RMSGN"		},
    418 	{ 0,		NULL		},
    419 };
    420 
    421 static const struct xlat stream_read_flags[] = {
    422 #ifdef RPROTDAT
    423 	{ RPROTDAT,	"RPROTDAT"	},
    424 #endif
    425 #ifdef RPROTDIS
    426 	{ RPROTDIS,	"RPROTDIS"	},
    427 #endif
    428 #ifdef RPROTNORM
    429 	{ RPROTNORM,	"RPROTNORM"	},
    430 #endif
    431 	{ 0,		NULL		},
    432 };
    433 
    434 #ifndef RMODEMASK
    435 #define RMODEMASK (~0)
    436 #endif
    437 
    438 #ifdef I_SWROPT
    439 static const struct xlat stream_write_flags[] = {
    440 	{ SNDZERO,	"SNDZERO"	},
    441 	{ SNDPIPE,	"SNDPIPE"	},
    442 	{ 0,		NULL		},
    443 };
    444 #endif /* I_SWROPT */
    445 
    446 #ifdef I_ATMARK
    447 static const struct xlat stream_atmark_options[] = {
    448 	{ ANYMARK,	"ANYMARK"	},
    449 	{ LASTMARK,	"LASTMARK"	},
    450 	{ 0,		NULL		},
    451 };
    452 #endif /* I_ATMARK */
    453 
    454 #ifdef TI_BIND
    455 static const struct xlat transport_user_options[] = {
    456 	{ T_CONN_REQ,	"T_CONN_REQ"	},
    457 	{ T_CONN_RES,	"T_CONN_RES"	},
    458 	{ T_DISCON_REQ,	"T_DISCON_REQ"	},
    459 	{ T_DATA_REQ,	"T_DATA_REQ"	},
    460 	{ T_EXDATA_REQ,	"T_EXDATA_REQ"	},
    461 	{ T_INFO_REQ,	"T_INFO_REQ"	},
    462 	{ T_BIND_REQ,	"T_BIND_REQ"	},
    463 	{ T_UNBIND_REQ,	"T_UNBIND_REQ"	},
    464 	{ T_UNITDATA_REQ,"T_UNITDATA_REQ"},
    465 	{ T_OPTMGMT_REQ,"T_OPTMGMT_REQ"	},
    466 	{ T_ORDREL_REQ,	"T_ORDREL_REQ"	},
    467 	{ 0,		NULL		},
    468 };
    469 
    470 static const struct xlat transport_user_flags [] = {
    471 	{ 0,		"0"		},
    472 	{ T_MORE,	"T_MORE"	},
    473 	{ T_EXPEDITED,	"T_EXPEDITED"	},
    474 	{ T_NEGOTIATE,	"T_NEGOTIATE"	},
    475 	{ T_CHECK,	"T_CHECK"	},
    476 	{ T_DEFAULT,	"T_DEFAULT"	},
    477 	{ T_SUCCESS,	"T_SUCCESS"	},
    478 	{ T_FAILURE,	"T_FAILURE"	},
    479 	{ T_CURRENT,	"T_CURRENT"	},
    480 	{ T_PARTSUCCESS,"T_PARTSUCCESS"	},
    481 	{ T_READONLY,	"T_READONLY"	},
    482 	{ T_NOTSUPPORT,	"T_NOTSUPPORT"	},
    483 	{ 0,		NULL		},
    484 };
    485 
    486 
    487 #ifdef HAVE_STRUCT_T_OPTHDR
    488 
    489 static const struct xlat xti_level [] = {
    490 	{ XTI_GENERIC,	"XTI_GENERIC"	},
    491 	{ 0,		NULL		},
    492 };
    493 
    494 static const struct xlat xti_generic [] = {
    495 	{ XTI_DEBUG,	"XTI_DEBUG"	},
    496 	{ XTI_LINGER,	"XTI_LINGER"	},
    497 	{ XTI_RCVBUF,	"XTI_RCVBUF"	},
    498 	{ XTI_RCVLOWAT,	"XTI_RCVLOWAT"	},
    499 	{ XTI_SNDBUF,	"XTI_SNDBUF"	},
    500 	{ XTI_SNDLOWAT,	"XTI_SNDLOWAT"	},
    501 	{ 0,		NULL		},
    502 };
    503 
    504 
    505 
    506 void
    507 print_xti_optmgmt (tcp, addr, len)
    508 struct tcb *tcp;
    509 long addr;
    510 int len;
    511 {
    512 	int c = 0;
    513 	struct t_opthdr hdr;
    514 
    515 	while (len >= (int) sizeof hdr) {
    516 		if (umove(tcp, addr, &hdr) < 0) break;
    517 		if (c++) {
    518 			tprintf (", ");
    519 		}
    520 		else if (len > hdr.len + sizeof hdr) {
    521 			tprintf ("[");
    522 		}
    523 		tprintf ("{level=");
    524 		printxval (xti_level, hdr.level, "???");
    525 		tprintf (", name=");
    526 		switch (hdr.level) {
    527 		    case XTI_GENERIC:
    528 			printxval (xti_generic, hdr.name, "XTI_???");
    529 			break;
    530 		    default:
    531 			tprintf ("%ld", hdr.name);
    532 			break;
    533 		}
    534 		tprintf (", status=");
    535 		printxval (transport_user_flags,  hdr.status, "T_???");
    536 		addr += sizeof hdr;
    537 		len -= sizeof hdr;
    538 		if ((hdr.len -= sizeof hdr) > 0) {
    539 			if (hdr.len > len) break;
    540 			tprintf (", val=");
    541 			if (len == sizeof (int))
    542 				printnum (tcp, addr, "%d");
    543 			else
    544 				printstr (tcp, addr, hdr.len);
    545 			addr += hdr.len;
    546 			len -= hdr.len;
    547 		}
    548 		tprintf ("}");
    549 	}
    550 	if (len > 0) {
    551 		if (c++) tprintf (", ");
    552 		printstr (tcp, addr, len);
    553 	}
    554 	if (c > 1) tprintf ("]");
    555 }
    556 
    557 #endif
    558 
    559 
    560 static void
    561 print_optmgmt (tcp, addr, len)
    562 struct tcb *tcp;
    563 long addr;
    564 int len;
    565 {
    566 	/* We don't know how to tell if TLI (socket) or XTI
    567 	   optmgmt is being used yet, assume TLI. */
    568 #if defined (HAVE_STRUCT_OPTHDR)
    569 	print_sock_optmgmt (tcp, addr, len);
    570 #elif defined (HAVE_STRUCT_T_OPTHDR)
    571 	print_xti_optmgmt (tcp, addr, len);
    572 #else
    573 	printstr (tcp, addr, len);
    574 #endif
    575 }
    576 
    577 
    578 
    579 
    580 static const struct xlat service_type [] = {
    581 	{ T_COTS,	"T_COTS"	},
    582 	{ T_COTS_ORD,	"T_COTS_ORD"	},
    583 	{ T_CLTS,	"T_CLTS"	},
    584 	{ 0,		NULL		},
    585 };
    586 
    587 static const struct xlat ts_state [] = {
    588 	{ TS_UNBND,	"TS_UNBND"	},
    589 	{ TS_WACK_BREQ,	"TS_WACK_BREQ"	},
    590 	{ TS_WACK_UREQ,	"TS_WACK_UREQ"	},
    591 	{ TS_IDLE,	"TS_IDLE"	},
    592 	{ TS_WACK_OPTREQ,"TS_WACK_OPTREQ"},
    593 	{ TS_WACK_CREQ,	"TS_WACK_CREQ"	},
    594 	{ TS_WCON_CREQ,	"TS_WCON_CREQ"	},
    595 	{ TS_WRES_CIND,	"TS_WRES_CIND"	},
    596 	{ TS_WACK_CRES,	"TS_WACK_CRES"	},
    597 	{ TS_DATA_XFER,	"TS_DATA_XFER"	},
    598 	{ TS_WIND_ORDREL,"TS_WIND_ORDREL"},
    599 	{ TS_WREQ_ORDREL,"TS_WREQ_ORDREL"},
    600 	{ TS_WACK_DREQ6,"TS_WACK_DREQ6"	},
    601 	{ TS_WACK_DREQ7,"TS_WACK_DREQ7"	},
    602 	{ TS_WACK_DREQ9,"TS_WACK_DREQ9"	},
    603 	{ TS_WACK_DREQ10,"TS_WACK_DREQ10"},
    604 	{ TS_WACK_DREQ11,"TS_WACK_DREQ11"},
    605 	{ 0,		NULL		},
    606 };
    607 
    608 static const struct xlat provider_flags [] = {
    609 	{ 0,		"0"		},
    610 	{ SENDZERO,	"SENDZERO"	},
    611 	{ EXPINLINE,	"EXPINLINE"	},
    612 	{ XPG4_1,	"XPG4_1"	},
    613 	{ 0,		NULL		},
    614 };
    615 
    616 
    617 static const struct xlat tli_errors [] = {
    618 	{ TBADADDR,	"TBADADDR"	},
    619 	{ TBADOPT,	"TBADOPT"	},
    620 	{ TACCES,	"TACCES"	},
    621 	{ TBADF,	"TBADF"		},
    622 	{ TNOADDR,	"TNOADDR"	},
    623 	{ TOUTSTATE,	"TOUTSTATE"	},
    624 	{ TBADSEQ,	"TBADSEQ"	},
    625 	{ TSYSERR,	"TSYSERR"	},
    626 	{ TLOOK,	"TLOOK"		},
    627 	{ TBADDATA,	"TBADDATA"	},
    628 	{ TBUFOVFLW,	"TBUFOVFLW"	},
    629 	{ TFLOW,	"TFLOW"		},
    630 	{ TNODATA,	"TNODATA"	},
    631 	{ TNODIS,	"TNODIS"	},
    632 	{ TNOUDERR,	"TNOUDERR"	},
    633 	{ TBADFLAG,	"TBADFLAG"	},
    634 	{ TNOREL,	"TNOREL"	},
    635 	{ TNOTSUPPORT,	"TNOTSUPPORT"	},
    636 	{ TSTATECHNG,	"TSTATECHNG"	},
    637 	{ TNOSTRUCTYPE,	"TNOSTRUCTYPE"	},
    638 	{ TBADNAME,	"TBADNAME"	},
    639 	{ TBADQLEN,	"TBADQLEN"	},
    640 	{ TADDRBUSY,	"TADDRBUSY"	},
    641 	{ TINDOUT,	"TINDOUT"	},
    642 	{ TPROVMISMATCH,"TPROVMISMATCH"	},
    643 	{ TRESQLEN,	"TRESQLEN"	},
    644 	{ TRESADDR,	"TRESADDR"	},
    645 	{ TQFULL,	"TQFULL"	},
    646 	{ TPROTO,	"TPROTO"	},
    647 	{ 0,		NULL		},
    648 };
    649 
    650 
    651 static int
    652 print_transport_message (tcp, expect, addr, len)
    653 struct tcb *tcp;
    654 int expect;
    655 long addr;
    656 int len;
    657 {
    658 	union T_primitives m;
    659 	int c = 0;
    660 
    661 	if (len < sizeof m.type) goto dump;
    662 
    663 	if (umove (tcp, addr, &m.type) < 0) goto dump;
    664 
    665 #define GET(type, struct)	\
    666 	do {							\
    667 		if (len < sizeof m.struct) goto dump;		\
    668 		if (umove (tcp, addr, &m.struct) < 0) goto dump;\
    669 		tprintf ("{");					\
    670 		if (expect != type) {				\
    671 			++c;					\
    672 			tprintf (#type);			\
    673 		}						\
    674 	}							\
    675 	while (0)
    676 
    677 #define COMMA() \
    678 	do { if (c++) tprintf (", "); } while (0)
    679 
    680 
    681 #define STRUCT(struct, elem, print)					\
    682 	do {								\
    683 		COMMA ();						\
    684 		if (m.struct.elem##_length < 0 ||			\
    685 		    m.struct.elem##_offset < sizeof m.struct ||		\
    686 		    m.struct.elem##_offset + m.struct.elem##_length > len) \
    687 		{							\
    688 			tprintf (#elem "_length=%ld, " #elem "_offset=%ld",\
    689 				m.struct.elem##_length,			\
    690 				m.struct.elem##_offset);		\
    691 		}							\
    692 		else {							\
    693 			tprintf (#elem "=");				\
    694 			print (tcp,					\
    695 				 addr + m.struct.elem##_offset,		\
    696 				 m.struct.elem##_length);		\
    697 		}							\
    698 	}								\
    699 	while (0)
    700 
    701 #define ADDR(struct, elem) STRUCT (struct, elem, printstr)
    702 
    703 	switch (m.type) {
    704 #ifdef T_CONN_REQ
    705 	    case T_CONN_REQ:	/* connect request   */
    706 		GET (T_CONN_REQ, conn_req);
    707 		ADDR (conn_req, DEST);
    708 		ADDR (conn_req, OPT);
    709 		break;
    710 #endif
    711 #ifdef T_CONN_RES
    712 	    case T_CONN_RES:	/* connect response   */
    713 		GET (T_CONN_RES, conn_res);
    714 #ifdef HAVE_STRUCT_T_CONN_RES_QUEUE_PTR
    715 		COMMA ();
    716 		tprintf ("QUEUE=%p", m.conn_res.QUEUE_ptr);
    717 #elif defined HAVE_STRUCT_T_CONN_RES_ACCEPTOR_ID
    718 		COMMA ();
    719 		tprintf ("ACCEPTOR=%#lx", m.conn_res.ACCEPTOR_id);
    720 #endif
    721 		ADDR (conn_res, OPT);
    722 		COMMA ();
    723 		tprintf ("SEQ=%ld", m.conn_res.SEQ_number);
    724 		break;
    725 #endif
    726 #ifdef T_DISCON_REQ
    727 	    case T_DISCON_REQ:	/* disconnect request */
    728 		GET (T_DISCON_REQ, discon_req);
    729 		COMMA ();
    730 		tprintf ("SEQ=%ld", m.discon_req.SEQ_number);
    731 		break;
    732 #endif
    733 #ifdef T_DATA_REQ
    734 	    case T_DATA_REQ:	/* data request       */
    735 		GET (T_DATA_REQ, data_req);
    736 		COMMA ();
    737 		tprintf ("MORE=%ld", m.data_req.MORE_flag);
    738 		break;
    739 #endif
    740 #ifdef T_EXDATA_REQ
    741 	    case T_EXDATA_REQ:	/* expedited data req */
    742 		GET (T_EXDATA_REQ, exdata_req);
    743 		COMMA ();
    744 		tprintf ("MORE=%ld", m.exdata_req.MORE_flag);
    745 		break;
    746 #endif
    747 #ifdef T_INFO_REQ
    748 	    case T_INFO_REQ:	/* information req    */
    749 		GET (T_INFO_REQ, info_req);
    750 		break;
    751 #endif
    752 #ifdef T_BIND_REQ
    753 	    case T_BIND_REQ:	/* bind request       */
    754 #ifdef O_T_BIND_REQ
    755 	    case O_T_BIND_REQ:	/* Ugly xti/tli hack */
    756 #endif
    757 		GET (T_BIND_REQ, bind_req);
    758 		ADDR (bind_req, ADDR);
    759 		COMMA ();
    760 		tprintf ("CONIND=%ld", m.bind_req.CONIND_number);
    761 		break;
    762 #endif
    763 #ifdef T_UNBIND_REQ
    764 	    case T_UNBIND_REQ:	/* unbind request     */
    765 		GET (T_UNBIND_REQ, unbind_req);
    766 		break;
    767 #endif
    768 #ifdef T_UNITDATA_REQ
    769 	    case T_UNITDATA_REQ:	/* unitdata requset   */
    770 		GET (T_UNITDATA_REQ, unitdata_req);
    771 		ADDR (unitdata_req, DEST);
    772 		ADDR (unitdata_req, OPT);
    773 		break;
    774 #endif
    775 #ifdef T_OPTMGMT_REQ
    776 	    case T_OPTMGMT_REQ:	/* manage opt req     */
    777 		GET (T_OPTMGMT_REQ, optmgmt_req);
    778 		COMMA ();
    779 		tprintf ("MGMT=");
    780 		printflags (transport_user_flags, m.optmgmt_req.MGMT_flags,
    781 			    "T_???");
    782 		STRUCT (optmgmt_req, OPT, print_optmgmt);
    783 		break;
    784 #endif
    785 #ifdef T_ORDREL_REQ
    786 	    case T_ORDREL_REQ:	/* orderly rel req    */
    787 		GET (T_ORDREL_REQ, ordrel_req);
    788 		break;
    789 #endif
    790 #ifdef T_CONN_IND
    791 	    case T_CONN_IND:	/* connect indication */
    792 		GET (T_CONN_IND, conn_ind);
    793 		ADDR (conn_ind, SRC);
    794 		ADDR (conn_ind, OPT);
    795 		tprintf (", SEQ=%ld", m.conn_ind.SEQ_number);
    796 		break;
    797 #endif
    798 #ifdef T_CONN_CON
    799 	    case T_CONN_CON:	/* connect corfirm    */
    800 		GET (T_CONN_CON, conn_con);
    801 		ADDR (conn_con, RES);
    802 		ADDR (conn_con, OPT);
    803 		break;
    804 #endif
    805 #ifdef T_DISCON_IND
    806 	    case T_DISCON_IND:	/* discon indication  */
    807 		GET (T_DISCON_IND, discon_ind);
    808 		COMMA ();
    809 		tprintf ("DISCON=%ld, SEQ=%ld",
    810 			 m.discon_ind.DISCON_reason, m.discon_ind.SEQ_number);
    811 		break;
    812 #endif
    813 #ifdef T_DATA_IND
    814 	    case T_DATA_IND:	/* data indication    */
    815 		GET (T_DATA_IND, data_ind);
    816 		COMMA ();
    817 		tprintf ("MORE=%ld", m.data_ind.MORE_flag);
    818 		break;
    819 #endif
    820 #ifdef T_EXDATA_IND
    821 	    case T_EXDATA_IND:	/* expedited data ind */
    822 		GET (T_EXDATA_IND, exdata_ind);
    823 		COMMA ();
    824 		tprintf ("MORE=%ld", m.exdata_ind.MORE_flag);
    825 		break;
    826 #endif
    827 #ifdef T_INFO_ACK
    828 	    case T_INFO_ACK:	/* info ack           */
    829 		GET (T_INFO_ACK, info_ack);
    830 		COMMA ();
    831 		tprintf ("TSDU=%ld, ETSDU=%ld, CDATA=%ld, DDATA=%ld, "
    832 			 "ADDR=%ld, OPT=%ld, TIDU=%ld, SERV=",
    833 			 m.info_ack.TSDU_size, m.info_ack.ETSDU_size,
    834 			 m.info_ack.CDATA_size, m.info_ack.DDATA_size,
    835 			 m.info_ack.ADDR_size, m.info_ack.OPT_size,
    836 			 m.info_ack.TIDU_size);
    837 		printxval (service_type, m.info_ack.SERV_type, "T_???");
    838 		tprintf (", CURRENT=");
    839 		printxval (ts_state, m.info_ack.CURRENT_state, "TS_???");
    840 		tprintf (", PROVIDER=");
    841 		printflags (provider_flags, m.info_ack.PROVIDER_flag, "???");
    842 		break;
    843 #endif
    844 #ifdef T_BIND_ACK
    845 	    case T_BIND_ACK:	/* bind ack           */
    846 		GET (T_BIND_ACK, bind_ack);
    847 		ADDR (bind_ack, ADDR);
    848 		tprintf (", CONIND=%ld", m.bind_ack.CONIND_number);
    849 		break;
    850 #endif
    851 #ifdef T_ERROR_ACK
    852 	    case T_ERROR_ACK:	/* error ack          */
    853 		GET (T_ERROR_ACK, error_ack);
    854 		COMMA ();
    855 		tprintf ("ERROR=");
    856 		printxval (transport_user_options,
    857 			   m.error_ack.ERROR_prim, "TI_???");
    858 		tprintf (", TLI=");
    859 		printxval (tli_errors, m.error_ack.TLI_error, "T???");
    860 		tprintf ("UNIX=%s", strerror (m.error_ack.UNIX_error));
    861 		break;
    862 #endif
    863 #ifdef T_OK_ACK
    864 	    case T_OK_ACK:	/* ok ack             */
    865 		GET (T_OK_ACK, ok_ack);
    866 		COMMA ();
    867 		tprintf ("CORRECT=");
    868 		printxval (transport_user_options,
    869 			   m.ok_ack.CORRECT_prim, "TI_???");
    870 		break;
    871 #endif
    872 #ifdef T_UNITDATA_IND
    873 	    case T_UNITDATA_IND:	/* unitdata ind       */
    874 		GET (T_UNITDATA_IND, unitdata_ind);
    875 		ADDR (unitdata_ind, SRC);
    876 		ADDR (unitdata_ind, OPT);
    877 		break;
    878 #endif
    879 #ifdef T_UDERROR_IND
    880 	    case T_UDERROR_IND:	/* unitdata error ind */
    881 		GET (T_UDERROR_IND, uderror_ind);
    882 		ADDR (uderror_ind, DEST);
    883 		ADDR (uderror_ind, OPT);
    884 		tprintf (", ERROR=%ld", m.uderror_ind.ERROR_type);
    885 		break;
    886 #endif
    887 #ifdef T_OPTMGMT_ACK
    888 	    case T_OPTMGMT_ACK:	/* manage opt ack     */
    889 		GET (T_OPTMGMT_ACK, optmgmt_ack);
    890 		COMMA ();
    891 		tprintf ("MGMT=");
    892 		printflags (transport_user_flags, m.optmgmt_ack.MGMT_flags,
    893 			    "T_???");
    894 		STRUCT (optmgmt_ack, OPT, print_optmgmt);
    895 		break;
    896 #endif
    897 #ifdef T_ORDREL_IND
    898 	case T_ORDREL_IND:	/* orderly rel ind    */
    899 		GET (T_ORDREL_IND, ordrel_ind);
    900 		break;
    901 #endif
    902 #ifdef T_ADDR_REQ
    903 	    case T_ADDR_REQ:	/* address req        */
    904 		GET (T_ADDR_REQ, addr_req);
    905 		break;
    906 #endif
    907 #ifdef T_ADDR_ACK
    908 	    case T_ADDR_ACK:	/* address response   */
    909 		GET (T_ADDR_ACK, addr_ack);
    910 		ADDR (addr_ack, LOCADDR);
    911 		ADDR (addr_ack, REMADDR);
    912 		break;
    913 #endif
    914 	    default:
    915 	    dump:
    916 		c = -1;
    917 		printstr(tcp, addr, len);
    918 		break;
    919 	}
    920 
    921 	if (c >= 0) tprintf ("}");
    922 
    923 #undef ADDR
    924 #undef COMMA
    925 #undef STRUCT
    926 
    927 	return 0;
    928 }
    929 
    930 
    931 #endif /* TI_BIND */
    932 
    933 
    934 static int
    935 internal_stream_ioctl(tcp, arg)
    936 struct tcb *tcp;
    937 int arg;
    938 {
    939 	struct strioctl si;
    940 	struct ioctlent *iop;
    941 	int in_and_out;
    942 	int timod = 0;
    943 #ifdef SI_GETUDATA
    944 	struct si_udata udata;
    945 #endif /* SI_GETUDATA */
    946 
    947 	if (!arg)
    948 		return 0;
    949 	if (umove(tcp, arg, &si) < 0) {
    950 		if (entering(tcp))
    951 			tprintf(", {...}");
    952 		return 1;
    953 	}
    954 	if (entering(tcp)) {
    955 		iop = ioctl_lookup(si.ic_cmd);
    956 		if (iop) {
    957 			tprintf(", {ic_cmd=%s", iop->symbol);
    958 			while ((iop = ioctl_next_match(iop)))
    959 				tprintf(" or %s", iop->symbol);
    960 		} else
    961 			tprintf(", {ic_cmd=%#x", si.ic_cmd);
    962 		if (si.ic_timout == INFTIM)
    963 			tprintf(", ic_timout=INFTIM, ");
    964 		else
    965 			tprintf(" ic_timout=%d, ", si.ic_timout);
    966 	}
    967 	in_and_out = 1;
    968 	switch (si.ic_cmd) {
    969 #ifdef SI_GETUDATA
    970 	case SI_GETUDATA:
    971 		in_and_out = 0;
    972 		break;
    973 #endif /* SI_GETUDATA */
    974 	}
    975 	if (in_and_out) {
    976 		if (entering(tcp))
    977 			tprintf("/* in */ ");
    978 		else
    979 			tprintf(", /* out */ ");
    980 	}
    981 	if (in_and_out || entering(tcp))
    982 		tprintf("ic_len=%d, ic_dp=", si.ic_len);
    983 	switch (si.ic_cmd) {
    984 #ifdef TI_BIND
    985 	case TI_BIND:
    986 		/* in T_BIND_REQ, out T_BIND_ACK */
    987 		++timod;
    988 		if (entering(tcp)) {
    989 			print_transport_message (tcp,
    990 						 T_BIND_REQ,
    991 						 si.ic_dp, si.ic_len);
    992 		}
    993 		else {
    994 			print_transport_message (tcp,
    995 						 T_BIND_ACK,
    996 						 si.ic_dp, si.ic_len);
    997 		}
    998 		break;
    999 #endif /* TI_BIND */
   1000 #ifdef TI_UNBIND
   1001 	case TI_UNBIND:
   1002 		/* in T_UNBIND_REQ, out T_OK_ACK */
   1003 		++timod;
   1004 		if (entering(tcp)) {
   1005 			print_transport_message (tcp,
   1006 						 T_UNBIND_REQ,
   1007 						 si.ic_dp, si.ic_len);
   1008 		}
   1009 		else {
   1010 			print_transport_message (tcp,
   1011 						 T_OK_ACK,
   1012 						 si.ic_dp, si.ic_len);
   1013 		}
   1014 		break;
   1015 #endif /* TI_UNBIND */
   1016 #ifdef TI_GETINFO
   1017 	case TI_GETINFO:
   1018 		/* in T_INFO_REQ, out T_INFO_ACK */
   1019 		++timod;
   1020 		if (entering(tcp)) {
   1021 			print_transport_message (tcp,
   1022 						 T_INFO_REQ,
   1023 						 si.ic_dp, si.ic_len);
   1024 		}
   1025 		else {
   1026 			print_transport_message (tcp,
   1027 						 T_INFO_ACK,
   1028 						 si.ic_dp, si.ic_len);
   1029 		}
   1030 		break;
   1031 #endif /* TI_GETINFO */
   1032 #ifdef TI_OPTMGMT
   1033 	case TI_OPTMGMT:
   1034 		/* in T_OPTMGMT_REQ, out T_OPTMGMT_ACK */
   1035 		++timod;
   1036 		if (entering(tcp)) {
   1037 			print_transport_message (tcp,
   1038 						 T_OPTMGMT_REQ,
   1039 						 si.ic_dp, si.ic_len);
   1040 		}
   1041 		else {
   1042 			print_transport_message (tcp,
   1043 						 T_OPTMGMT_ACK,
   1044 						 si.ic_dp, si.ic_len);
   1045 		}
   1046 		break;
   1047 #endif /* TI_OPTMGMT */
   1048 #ifdef SI_GETUDATA
   1049 	case SI_GETUDATA:
   1050 		if (entering(tcp))
   1051 			break;
   1052 #if 0
   1053 		tprintf("struct si_udata ");
   1054 #endif
   1055 		if (umove(tcp, (int) si.ic_dp, &udata) < 0)
   1056 			tprintf("{...}");
   1057 		else {
   1058 			tprintf("{tidusize=%d, addrsize=%d, ",
   1059 				udata.tidusize, udata.addrsize);
   1060 			tprintf("optsize=%d, etsdusize=%d, ",
   1061 				udata.optsize, udata.etsdusize);
   1062 			tprintf("servtype=%d, so_state=%d, ",
   1063 				udata.servtype, udata.so_state);
   1064 			tprintf("so_options=%d", udata.so_options);
   1065 #if 0
   1066 			tprintf(", tsdusize=%d", udata.tsdusize);
   1067 #endif
   1068 			tprintf("}");
   1069 		}
   1070 		break;
   1071 #endif /* SI_GETUDATA */
   1072 	default:
   1073 		printstr(tcp, (long) si.ic_dp, si.ic_len);
   1074 		break;
   1075 	}
   1076 	if (exiting(tcp)) {
   1077 		tprintf("}");
   1078 		if (timod && tcp->u_rval) {
   1079 			tcp->auxstr = xlookup (tli_errors, tcp->u_rval);
   1080 			return RVAL_STR + 1;
   1081 		}
   1082 	}
   1083 
   1084 	return 1;
   1085 }
   1086 
   1087 int
   1088 stream_ioctl(tcp, code, arg)
   1089 struct tcb *tcp;
   1090 int code, arg;
   1091 {
   1092 #ifdef I_LIST
   1093 	int i;
   1094 #endif
   1095 	int val;
   1096 #ifdef I_FLUSHBAND
   1097 	struct bandinfo bi;
   1098 #endif
   1099 	struct strpeek sp;
   1100 	struct strfdinsert sfi;
   1101 	struct strrecvfd srf;
   1102 #ifdef I_LIST
   1103 	struct str_list sl;
   1104 #endif
   1105 
   1106 	/* I_STR is a special case because the data is read & written. */
   1107 	if (code == I_STR)
   1108 		return internal_stream_ioctl(tcp, arg);
   1109 	if (entering(tcp))
   1110 		return 0;
   1111 
   1112 	switch (code) {
   1113 	case I_PUSH:
   1114 	case I_LOOK:
   1115 	case I_FIND:
   1116 		/* arg is a string */
   1117 		tprintf(", ");
   1118 		printpath(tcp, arg);
   1119 		return 1;
   1120 	case I_POP:
   1121 		/* doesn't take an argument */
   1122 		return 1;
   1123 	case I_FLUSH:
   1124 		/* argument is an option */
   1125 		tprintf(", ");
   1126 		printxval(stream_flush_options, arg, "FLUSH???");
   1127 		return 1;
   1128 #ifdef I_FLUSHBAND
   1129 	case I_FLUSHBAND:
   1130 		/* argument is a pointer to a bandinfo struct */
   1131 		if (umove(tcp, arg, &bi) < 0)
   1132 			tprintf(", {...}");
   1133 		else {
   1134 			tprintf(", {bi_pri=%d, bi_flag=", bi.bi_pri);
   1135 			printflags(stream_flush_options, bi.bi_flag, "FLUSH???");
   1136 			tprintf("}");
   1137 		}
   1138 		return 1;
   1139 #endif /* I_FLUSHBAND */
   1140 	case I_SETSIG:
   1141 		/* argument is a set of flags */
   1142 		tprintf(", ");
   1143 		printflags(stream_setsig_flags, arg, "S_???");
   1144 		return 1;
   1145 	case I_GETSIG:
   1146 		/* argument is a pointer to a set of flags */
   1147 		if (syserror(tcp))
   1148 			return 0;
   1149 		tprintf(", [");
   1150 		if (umove(tcp, arg, &val) < 0)
   1151 			tprintf("?");
   1152 		else
   1153 			printflags(stream_setsig_flags, val, "S_???");
   1154 		tprintf("]");
   1155 		return 1;
   1156 	case I_PEEK:
   1157 		/* argument is a pointer to a strpeek structure */
   1158 		if (syserror(tcp) || !arg)
   1159 			return 0;
   1160 		if (umove(tcp, arg, &sp) < 0) {
   1161 			tprintf(", {...}");
   1162 			return 1;
   1163 		}
   1164 		tprintf(", {ctlbuf=");
   1165 		printstrbuf(tcp, &sp.ctlbuf, 1);
   1166 		tprintf(", databuf=");
   1167 		printstrbuf(tcp, &sp.databuf, 1);
   1168 		tprintf(", flags=");
   1169 		printflags(msgflags, sp.flags, "RS_???");
   1170 		tprintf("}");
   1171 		return 1;
   1172 	case I_SRDOPT:
   1173 		/* argument is an option with flags */
   1174 		tprintf(", ");
   1175 		printxval(stream_read_options, arg & RMODEMASK, "R???");
   1176 		addflags(stream_read_flags, arg & ~RMODEMASK);
   1177 		return 1;
   1178 	case I_GRDOPT:
   1179 		/* argument is an pointer to an option with flags */
   1180 		if (syserror(tcp))
   1181 			return 0;
   1182 		tprintf(", [");
   1183 		if (umove(tcp, arg, &val) < 0)
   1184 			tprintf("?");
   1185 		else {
   1186 			printxval(stream_read_options,
   1187 				  arg & RMODEMASK, "R???");
   1188 			addflags(stream_read_flags, arg & ~RMODEMASK);
   1189 		}
   1190 		tprintf("]");
   1191 		return 1;
   1192 	case I_NREAD:
   1193 #ifdef I_GETBAND
   1194 	case I_GETBAND:
   1195 #endif
   1196 #ifdef I_SETCLTIME
   1197 	case I_SETCLTIME:
   1198 #endif
   1199 #ifdef I_GETCLTIME
   1200 	case I_GETCLTIME:
   1201 #endif
   1202 		/* argument is a pointer to a decimal integer */
   1203 		if (syserror(tcp))
   1204 			return 0;
   1205 		tprintf(", ");
   1206 		printnum(tcp, arg, "%d");
   1207 		return 1;
   1208 	case I_FDINSERT:
   1209 		/* argument is a pointer to a strfdinsert structure */
   1210 		if (syserror(tcp) || !arg)
   1211 			return 0;
   1212 		if (umove(tcp, arg, &sfi) < 0) {
   1213 			tprintf(", {...}");
   1214 			return 1;
   1215 		}
   1216 		tprintf(", {ctlbuf=");
   1217 		printstrbuf(tcp, &sfi.ctlbuf, 1);
   1218 		tprintf(", databuf=");
   1219 		printstrbuf(tcp, &sfi.databuf, 1);
   1220 		tprintf(", flags=");
   1221 		printflags(msgflags, sfi.flags, "RS_???");
   1222 		tprintf(", filedes=%d, offset=%d}", sfi.fildes, sfi.offset);
   1223 		return 1;
   1224 #ifdef I_SWROPT
   1225 	case I_SWROPT:
   1226 		/* argument is a set of flags */
   1227 		tprintf(", ");
   1228 		printflags(stream_write_flags, arg, "SND???");
   1229 		return 1;
   1230 #endif /* I_SWROPT */
   1231 #ifdef I_GWROPT
   1232 	case I_GWROPT:
   1233 		/* argument is an pointer to an option with flags */
   1234 		if (syserror(tcp))
   1235 			return 0;
   1236 		tprintf(", [");
   1237 		if (umove(tcp, arg, &val) < 0)
   1238 			tprintf("?");
   1239 		else
   1240 			printflags(stream_write_flags, arg, "SND???");
   1241 		tprintf("]");
   1242 		return 1;
   1243 #endif /* I_GWROPT */
   1244 	case I_SENDFD:
   1245 #ifdef I_CKBAND
   1246 	case I_CKBAND:
   1247 #endif
   1248 #ifdef I_CANPUT
   1249 	case I_CANPUT:
   1250 #endif
   1251 	case I_LINK:
   1252 	case I_UNLINK:
   1253 	case I_PLINK:
   1254 	case I_PUNLINK:
   1255 		/* argument is a decimal integer */
   1256 		tprintf(", %d", arg);
   1257 		return 1;
   1258 	case I_RECVFD:
   1259 		/* argument is a pointer to a strrecvfd structure */
   1260 		if (syserror(tcp) || !arg)
   1261 			return 0;
   1262 		if (umove(tcp, arg, &srf) < 0) {
   1263 			tprintf(", {...}");
   1264 			return 1;
   1265 		}
   1266 		tprintf(", {fd=%d, uid=%lu, gid=%lu}", srf.fd,
   1267 			(unsigned long) srf.uid, (unsigned long) srf.gid);
   1268 		return 1;
   1269 #ifdef I_LIST
   1270 	case I_LIST:
   1271 		if (syserror(tcp))
   1272 			return 0;
   1273 		if (arg == 0) {
   1274 			tprintf(", NULL");
   1275 			return 1;
   1276 		}
   1277 		if (umove(tcp, arg, &sl) < 0) {
   1278 			tprintf(", {...}");
   1279 			return 1;
   1280 		}
   1281 		tprintf(", {sl_nmods=%d, sl_modlist=[", sl.sl_nmods);
   1282 		for (i = 0; i < tcp->u_rval; i++) {
   1283 			if (i)
   1284 				tprintf(", ");
   1285 			printpath(tcp, (int) sl.sl_modlist[i].l_name);
   1286 		}
   1287 		tprintf("]}");
   1288 		return 1;
   1289 #endif /* I_LIST */
   1290 #ifdef I_ATMARK
   1291 	case I_ATMARK:
   1292 		tprintf(", ");
   1293 		printxval(stream_atmark_options, arg, "???MARK");
   1294 		return 1;
   1295 #endif /* I_ATMARK */
   1296 	default:
   1297 		return 0;
   1298 	}
   1299 }
   1300 
   1301 #endif /* !LINUX && !FREEBSD */
   1302 
   1303 #endif /* HAVE_SYS_STREAM_H || LINUX || FREEBSD */
   1304