]> granicus.if.org Git - strace/blob - stream.c
Remove extra include directives. No code changes.
[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
46 #ifndef HAVE_STROPTS_H
47 #define RS_HIPRI 1
48 struct strbuf {
49         int     maxlen;                 /* no. of bytes in buffer */
50         int     len;                    /* no. of bytes returned */
51         const char *buf;                /* pointer to data */
52 };
53 #define MORECTL 1
54 #define MOREDATA 2
55 #endif /* !HAVE_STROPTS_H */
56
57 static const struct xlat msgflags[] = {
58         { RS_HIPRI,     "RS_HIPRI"      },
59         { 0,            NULL            },
60 };
61
62 static void
63 printstrbuf(struct tcb *tcp, struct strbuf *sbp, int getting)
64 {
65         if (sbp->maxlen == -1 && getting)
66                 tprints("{maxlen=-1}");
67         else {
68                 tprints("{");
69                 if (getting)
70                         tprintf("maxlen=%d, ", sbp->maxlen);
71                 tprintf("len=%d, buf=", sbp->len);
72                 printstr(tcp, (unsigned long) sbp->buf, sbp->len);
73                 tprints("}");
74         }
75 }
76
77 static void
78 printstrbufarg(struct tcb *tcp, int arg, int getting)
79 {
80         struct strbuf buf;
81
82         if (arg == 0)
83                 tprints("NULL");
84         else if (umove(tcp, arg, &buf) < 0)
85                 tprints("{...}");
86         else
87                 printstrbuf(tcp, &buf, getting);
88         tprints(", ");
89 }
90
91 int
92 sys_putmsg(struct tcb *tcp)
93 {
94         int i;
95
96         if (entering(tcp)) {
97                 /* fd */
98                 tprintf("%ld, ", tcp->u_arg[0]);
99                 /* control and data */
100                 for (i = 1; i < 3; i++)
101                         printstrbufarg(tcp, tcp->u_arg[i], 0);
102                 /* flags */
103                 printflags(msgflags, tcp->u_arg[3], "RS_???");
104         }
105         return 0;
106 }
107
108 #if defined(SPARC) || defined(SPARC64)
109 int
110 sys_getmsg(struct tcb *tcp)
111 {
112         int i, flags;
113
114         if (entering(tcp)) {
115                 /* fd */
116                 tprintf("%lu, ", tcp->u_arg[0]);
117         } else {
118                 if (syserror(tcp)) {
119                         tprintf("%#lx, %#lx, %#lx",
120                                 tcp->u_arg[1], tcp->u_arg[2], tcp->u_arg[3]);
121                         return 0;
122                 }
123                 /* control and data */
124                 for (i = 1; i < 3; i++)
125                         printstrbufarg(tcp, tcp->u_arg[i], 1);
126                 /* pointer to flags */
127                 if (tcp->u_arg[3] == 0)
128                         tprints("NULL");
129                 else if (umove(tcp, tcp->u_arg[3], &flags) < 0)
130                         tprints("[?]");
131                 else {
132                         tprints("[");
133                         printflags(msgflags, flags, "RS_???");
134                         tprints("]");
135                 }
136                 /* decode return value */
137                 switch (tcp->u_rval) {
138                 case MORECTL:
139                         tcp->auxstr = "MORECTL";
140                         break;
141                 case MORECTL|MOREDATA:
142                         tcp->auxstr = "MORECTL|MOREDATA";
143                         break;
144                 case MOREDATA:
145                         tcp->auxstr = "MORECTL";
146                         break;
147                 default:
148                         tcp->auxstr = NULL;
149                         break;
150                 }
151         }
152         return RVAL_HEX | RVAL_STR;
153 }
154 #endif
155
156 #if defined SYS_putpmsg || defined SYS_getpmsg
157 static const struct xlat pmsgflags[] = {
158 #ifdef MSG_HIPRI
159         { MSG_HIPRI,    "MSG_HIPRI"     },
160 #endif
161 #ifdef MSG_AND
162         { MSG_ANY,      "MSG_ANY"       },
163 #endif
164 #ifdef MSG_BAND
165         { MSG_BAND,     "MSG_BAND"      },
166 #endif
167         { 0,            NULL            },
168 };
169 #endif
170
171 #ifdef SYS_putpmsg
172 int
173 sys_putpmsg(struct tcb *tcp)
174 {
175         int i;
176
177         if (entering(tcp)) {
178                 /* fd */
179                 tprintf("%ld, ", tcp->u_arg[0]);
180                 /* control and data */
181                 for (i = 1; i < 3; i++)
182                         printstrbufarg(tcp, tcp->u_arg[i], 0);
183                 /* band */
184                 tprintf("%ld, ", tcp->u_arg[3]);
185                 /* flags */
186                 printflags(pmsgflags, tcp->u_arg[4], "MSG_???");
187         }
188         return 0;
189 }
190 #endif /* SYS_putpmsg */
191
192 #ifdef SYS_getpmsg
193 int
194 sys_getpmsg(struct tcb *tcp)
195 {
196         int i, flags;
197
198         if (entering(tcp)) {
199                 /* fd */
200                 tprintf("%lu, ", tcp->u_arg[0]);
201         } else {
202                 if (syserror(tcp)) {
203                         tprintf("%#lx, %#lx, %#lx, %#lx", tcp->u_arg[1],
204                                 tcp->u_arg[2], tcp->u_arg[3], tcp->u_arg[4]);
205                         return 0;
206                 }
207                 /* control and data */
208                 for (i = 1; i < 3; i++)
209                         printstrbufarg(tcp, tcp->u_arg[i], 1);
210                 /* pointer to band */
211                 printnum(tcp, tcp->u_arg[3], "%d");
212                 tprints(", ");
213                 /* pointer to flags */
214                 if (tcp->u_arg[4] == 0)
215                         tprints("NULL");
216                 else if (umove(tcp, tcp->u_arg[4], &flags) < 0)
217                         tprints("[?]");
218                 else {
219                         tprints("[");
220                         printflags(pmsgflags, flags, "MSG_???");
221                         tprints("]");
222                 }
223                 /* decode return value */
224                 switch (tcp->u_rval) {
225                 case MORECTL:
226                         tcp->auxstr = "MORECTL";
227                         break;
228                 case MORECTL|MOREDATA:
229                         tcp->auxstr = "MORECTL|MOREDATA";
230                         break;
231                 case MOREDATA:
232                         tcp->auxstr = "MORECTL";
233                         break;
234                 default:
235                         tcp->auxstr = NULL;
236                         break;
237                 }
238         }
239         return RVAL_HEX | RVAL_STR;
240 }
241 #endif /* SYS_getpmsg */
242
243 #ifdef HAVE_SYS_POLL_H
244
245 static const struct xlat pollflags[] = {
246 #ifdef POLLIN
247         { POLLIN,       "POLLIN"        },
248         { POLLPRI,      "POLLPRI"       },
249         { POLLOUT,      "POLLOUT"       },
250 #ifdef POLLRDNORM
251         { POLLRDNORM,   "POLLRDNORM"    },
252 #endif
253 #ifdef POLLWRNORM
254         { POLLWRNORM,   "POLLWRNORM"    },
255 #endif
256 #ifdef POLLRDBAND
257         { POLLRDBAND,   "POLLRDBAND"    },
258 #endif
259 #ifdef POLLWRBAND
260         { POLLWRBAND,   "POLLWRBAND"    },
261 #endif
262         { POLLERR,      "POLLERR"       },
263         { POLLHUP,      "POLLHUP"       },
264         { POLLNVAL,     "POLLNVAL"      },
265 #endif
266         { 0,            NULL            },
267 };
268
269 static int
270 decode_poll(struct tcb *tcp, long pts)
271 {
272         struct pollfd fds;
273         unsigned nfds;
274         unsigned long size, start, cur, end, abbrev_end;
275         int failed = 0;
276
277         if (entering(tcp)) {
278                 nfds = tcp->u_arg[1];
279                 size = sizeof(fds) * nfds;
280                 start = tcp->u_arg[0];
281                 end = start + size;
282                 if (nfds == 0 || size / sizeof(fds) != nfds || end < start) {
283                         tprintf("%#lx, %d, ",
284                                 tcp->u_arg[0], nfds);
285                         return 0;
286                 }
287                 if (abbrev(tcp)) {
288                         abbrev_end = start + max_strlen * sizeof(fds);
289                         if (abbrev_end < start)
290                                 abbrev_end = end;
291                 } else {
292                         abbrev_end = end;
293                 }
294                 tprints("[");
295                 for (cur = start; cur < end; cur += sizeof(fds)) {
296                         if (cur > start)
297                                 tprints(", ");
298                         if (cur >= abbrev_end) {
299                                 tprints("...");
300                                 break;
301                         }
302                         if (umoven(tcp, cur, sizeof fds, (char *) &fds) < 0) {
303                                 tprints("?");
304                                 failed = 1;
305                                 break;
306                         }
307                         if (fds.fd < 0) {
308                                 tprintf("{fd=%d}", fds.fd);
309                                 continue;
310                         }
311                         tprints("{fd=");
312                         printfd(tcp, fds.fd);
313                         tprints(", events=");
314                         printflags(pollflags, fds.events, "POLL???");
315                         tprints("}");
316                 }
317                 tprints("]");
318                 if (failed)
319                         tprintf(" %#lx", start);
320                 tprintf(", %d, ", nfds);
321                 return 0;
322         } else {
323                 static char outstr[1024];
324                 char *outptr;
325 #define end_outstr (outstr + sizeof(outstr))
326                 const char *flagstr;
327
328                 if (syserror(tcp))
329                         return 0;
330                 if (tcp->u_rval == 0) {
331                         tcp->auxstr = "Timeout";
332                         return RVAL_STR;
333                 }
334
335                 nfds = tcp->u_arg[1];
336                 size = sizeof(fds) * nfds;
337                 start = tcp->u_arg[0];
338                 end = start + size;
339                 if (nfds == 0 || size / sizeof(fds) != nfds || end < start)
340                         return 0;
341                 if (abbrev(tcp)) {
342                         abbrev_end = start + max_strlen * sizeof(fds);
343                         if (abbrev_end < start)
344                                 abbrev_end = end;
345                 } else {
346                         abbrev_end = end;
347                 }
348
349                 outptr = outstr;
350
351                 for (cur = start; cur < end; cur += sizeof(fds)) {
352                         if (umoven(tcp, cur, sizeof fds, (char *) &fds) < 0) {
353                                 if (outptr < end_outstr - 2)
354                                         *outptr++ = '?';
355                                 failed = 1;
356                                 break;
357                         }
358                         if (!fds.revents)
359                                 continue;
360                         if (outptr == outstr) {
361                                 *outptr++ = '[';
362                         } else {
363                                 if (outptr < end_outstr - 3)
364                                         outptr = stpcpy(outptr, ", ");
365                         }
366                         if (cur >= abbrev_end) {
367                                 if (outptr < end_outstr - 4)
368                                         outptr = stpcpy(outptr, "...");
369                                 break;
370                         }
371                         if (outptr < end_outstr - (sizeof("{fd=%d, revents=") + sizeof(int)*3) + 1)
372                                 outptr += sprintf(outptr, "{fd=%d, revents=", fds.fd);
373                         flagstr = sprintflags("", pollflags, fds.revents);
374                         if (outptr < end_outstr - (strlen(flagstr) + 2)) {
375                                 outptr = stpcpy(outptr, flagstr);
376                                 *outptr++ = '}';
377                         }
378                 }
379                 if (failed)
380                         return 0;
381
382                 if (outptr != outstr /* && outptr < end_outstr - 1 (always true)*/)
383                         *outptr++ = ']';
384
385                 *outptr = '\0';
386                 if (pts) {
387                         if (outptr < end_outstr - (10 + TIMESPEC_TEXT_BUFSIZE)) {
388                                 outptr = stpcpy(outptr, outptr == outstr ? "left " : ", left ");
389                                 sprint_timespec(outptr, tcp, pts);
390                         }
391                 }
392
393                 if (outptr == outstr)
394                         return 0;
395
396                 tcp->auxstr = outstr;
397                 return RVAL_STR;
398 #undef end_outstr
399         }
400 }
401
402 int
403 sys_poll(struct tcb *tcp)
404 {
405         int rc = decode_poll(tcp, 0);
406         if (entering(tcp)) {
407 #ifdef INFTIM
408                 if (tcp->u_arg[2] == INFTIM)
409                         tprints("INFTIM");
410                 else
411 #endif
412                         tprintf("%ld", tcp->u_arg[2]);
413         }
414         return rc;
415 }
416
417 int
418 sys_ppoll(struct tcb *tcp)
419 {
420         int rc = decode_poll(tcp, tcp->u_arg[2]);
421         if (entering(tcp)) {
422                 print_timespec(tcp, tcp->u_arg[2]);
423                 tprints(", ");
424                 print_sigset(tcp, tcp->u_arg[3], 0);
425                 tprintf(", %lu", tcp->u_arg[4]);
426         }
427         return rc;
428 }
429
430 #else /* !HAVE_SYS_POLL_H */
431 int
432 sys_poll(struct tcb *tcp)
433 {
434         return 0;
435 }
436 #endif