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