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