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