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