]> granicus.if.org Git - strace/blob - stream.c
readahead.c: make use of RVAL_DECODED
[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 SYS_FUNC(putmsg)
90 {
91         int i;
92
93         if (entering(tcp)) {
94                 /* fd */
95                 tprintf("%ld, ", tcp->u_arg[0]);
96                 /* control and data */
97                 for (i = 1; i < 3; i++)
98                         printstrbufarg(tcp, tcp->u_arg[i], 0);
99                 /* flags */
100                 printflags(msgflags, tcp->u_arg[3], "RS_???");
101         }
102         return 0;
103 }
104
105 SYS_FUNC(getmsg)
106 {
107         int i, flags;
108
109         if (entering(tcp)) {
110                 /* fd */
111                 tprintf("%lu, ", tcp->u_arg[0]);
112         } else {
113                 if (syserror(tcp)) {
114                         tprintf("%#lx, %#lx, %#lx",
115                                 tcp->u_arg[1], tcp->u_arg[2], tcp->u_arg[3]);
116                         return 0;
117                 }
118                 /* control and data */
119                 for (i = 1; i < 3; i++)
120                         printstrbufarg(tcp, tcp->u_arg[i], 1);
121                 /* pointer to flags */
122                 if (tcp->u_arg[3] == 0)
123                         tprints("NULL");
124                 else if (umove(tcp, tcp->u_arg[3], &flags) < 0)
125                         tprints("[?]");
126                 else {
127                         tprints("[");
128                         printflags(msgflags, flags, "RS_???");
129                         tprints("]");
130                 }
131                 /* decode return value */
132                 switch (tcp->u_rval) {
133                 case MORECTL:
134                         tcp->auxstr = "MORECTL";
135                         break;
136                 case MORECTL|MOREDATA:
137                         tcp->auxstr = "MORECTL|MOREDATA";
138                         break;
139                 case MOREDATA:
140                         tcp->auxstr = "MORECTL";
141                         break;
142                 default:
143                         tcp->auxstr = NULL;
144                         break;
145                 }
146         }
147         return RVAL_HEX | RVAL_STR;
148 }
149
150 # if defined SYS_putpmsg || defined SYS_getpmsg
151 #include "xlat/pmsgflags.h"
152 #  ifdef SYS_putpmsg
153 SYS_FUNC(putpmsg)
154 {
155         int i;
156
157         if (entering(tcp)) {
158                 /* fd */
159                 tprintf("%ld, ", tcp->u_arg[0]);
160                 /* control and data */
161                 for (i = 1; i < 3; i++)
162                         printstrbufarg(tcp, tcp->u_arg[i], 0);
163                 /* band */
164                 tprintf("%ld, ", tcp->u_arg[3]);
165                 /* flags */
166                 printflags(pmsgflags, tcp->u_arg[4], "MSG_???");
167         }
168         return 0;
169 }
170 #  endif
171 #  ifdef SYS_getpmsg
172 SYS_FUNC(getpmsg)
173 {
174         int i, flags;
175
176         if (entering(tcp)) {
177                 /* fd */
178                 tprintf("%lu, ", tcp->u_arg[0]);
179         } else {
180                 if (syserror(tcp)) {
181                         tprintf("%#lx, %#lx, %#lx, %#lx", tcp->u_arg[1],
182                                 tcp->u_arg[2], tcp->u_arg[3], tcp->u_arg[4]);
183                         return 0;
184                 }
185                 /* control and data */
186                 for (i = 1; i < 3; i++)
187                         printstrbufarg(tcp, tcp->u_arg[i], 1);
188                 /* pointer to band */
189                 printnum_int(tcp, tcp->u_arg[3], "%d");
190                 tprints(", ");
191                 /* pointer to flags */
192                 if (tcp->u_arg[4] == 0)
193                         tprints("NULL");
194                 else if (umove(tcp, tcp->u_arg[4], &flags) < 0)
195                         tprints("[?]");
196                 else {
197                         tprints("[");
198                         printflags(pmsgflags, flags, "MSG_???");
199                         tprints("]");
200                 }
201                 /* decode return value */
202                 switch (tcp->u_rval) {
203                 case MORECTL:
204                         tcp->auxstr = "MORECTL";
205                         break;
206                 case MORECTL|MOREDATA:
207                         tcp->auxstr = "MORECTL|MOREDATA";
208                         break;
209                 case MOREDATA:
210                         tcp->auxstr = "MORECTL";
211                         break;
212                 default:
213                         tcp->auxstr = NULL;
214                         break;
215                 }
216         }
217         return RVAL_HEX | RVAL_STR;
218 }
219 #  endif
220 # endif /* getpmsg/putpmsg */
221
222 #endif /* STREAMS syscalls support */
223
224
225 #ifdef HAVE_SYS_POLL_H
226
227 #include "xlat/pollflags.h"
228
229 static int
230 decode_poll(struct tcb *tcp, long pts)
231 {
232         struct pollfd fds;
233         unsigned nfds;
234         unsigned long size, start, cur, end, abbrev_end;
235         int failed = 0;
236
237         if (entering(tcp)) {
238                 nfds = tcp->u_arg[1];
239                 size = sizeof(fds) * nfds;
240                 start = tcp->u_arg[0];
241                 end = start + size;
242                 if (nfds == 0 || size / sizeof(fds) != nfds || end < start) {
243                         tprintf("%#lx, %d, ",
244                                 tcp->u_arg[0], nfds);
245                         return 0;
246                 }
247                 if (abbrev(tcp)) {
248                         abbrev_end = start + max_strlen * sizeof(fds);
249                         if (abbrev_end < start)
250                                 abbrev_end = end;
251                 } else {
252                         abbrev_end = end;
253                 }
254                 tprints("[");
255                 for (cur = start; cur < end; cur += sizeof(fds)) {
256                         if (cur > start)
257                                 tprints(", ");
258                         if (cur >= abbrev_end) {
259                                 tprints("...");
260                                 break;
261                         }
262                         if (umoven(tcp, cur, sizeof fds, &fds) < 0) {
263                                 tprints("?");
264                                 failed = 1;
265                                 break;
266                         }
267                         if (fds.fd < 0) {
268                                 tprintf("{fd=%d}", fds.fd);
269                                 continue;
270                         }
271                         tprints("{fd=");
272                         printfd(tcp, fds.fd);
273                         tprints(", events=");
274                         printflags(pollflags, fds.events, "POLL???");
275                         tprints("}");
276                 }
277                 tprints("]");
278                 if (failed)
279                         tprintf(" %#lx", start);
280                 tprintf(", %d, ", nfds);
281                 return 0;
282         } else {
283                 static char outstr[1024];
284                 char *outptr;
285 #define end_outstr (outstr + sizeof(outstr))
286                 const char *flagstr;
287
288                 if (syserror(tcp))
289                         return 0;
290                 if (tcp->u_rval == 0) {
291                         tcp->auxstr = "Timeout";
292                         return RVAL_STR;
293                 }
294
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                         return 0;
301                 if (abbrev(tcp)) {
302                         abbrev_end = start + max_strlen * sizeof(fds);
303                         if (abbrev_end < start)
304                                 abbrev_end = end;
305                 } else {
306                         abbrev_end = end;
307                 }
308
309                 outptr = outstr;
310
311                 for (cur = start; cur < end; cur += sizeof(fds)) {
312                         if (umoven(tcp, cur, sizeof fds, &fds) < 0) {
313                                 if (outptr < end_outstr - 2)
314                                         *outptr++ = '?';
315                                 failed = 1;
316                                 break;
317                         }
318                         if (!fds.revents)
319                                 continue;
320                         if (outptr == outstr) {
321                                 *outptr++ = '[';
322                         } else {
323                                 if (outptr < end_outstr - 3)
324                                         outptr = stpcpy(outptr, ", ");
325                         }
326                         if (cur >= abbrev_end) {
327                                 if (outptr < end_outstr - 4)
328                                         outptr = stpcpy(outptr, "...");
329                                 break;
330                         }
331                         if (outptr < end_outstr - (sizeof("{fd=%d, revents=") + sizeof(int)*3) + 1)
332                                 outptr += sprintf(outptr, "{fd=%d, revents=", fds.fd);
333                         flagstr = sprintflags("", pollflags, fds.revents);
334                         if (outptr < end_outstr - (strlen(flagstr) + 2)) {
335                                 outptr = stpcpy(outptr, flagstr);
336                                 *outptr++ = '}';
337                         }
338                 }
339                 if (failed)
340                         return 0;
341
342                 if (outptr != outstr /* && outptr < end_outstr - 1 (always true)*/)
343                         *outptr++ = ']';
344
345                 *outptr = '\0';
346                 if (pts) {
347                         if (outptr < end_outstr - (10 + TIMESPEC_TEXT_BUFSIZE)) {
348                                 outptr = stpcpy(outptr, outptr == outstr ? "left " : ", left ");
349                                 sprint_timespec(outptr, tcp, pts);
350                         }
351                 }
352
353                 if (outptr == outstr)
354                         return 0;
355
356                 tcp->auxstr = outstr;
357                 return RVAL_STR;
358 #undef end_outstr
359         }
360 }
361
362 SYS_FUNC(poll)
363 {
364         int rc = decode_poll(tcp, 0);
365         if (entering(tcp)) {
366 # ifdef INFTIM
367                 if (tcp->u_arg[2] == INFTIM)
368                         tprints("INFTIM");
369                 else
370 # endif
371                         tprintf("%ld", tcp->u_arg[2]);
372         }
373         return rc;
374 }
375
376 SYS_FUNC(ppoll)
377 {
378         int rc = decode_poll(tcp, tcp->u_arg[2]);
379         if (entering(tcp)) {
380                 print_timespec(tcp, tcp->u_arg[2]);
381                 tprints(", ");
382                 /* NB: kernel requires arg[4] == NSIG / 8 */
383                 print_sigset_addr_len(tcp, tcp->u_arg[3], tcp->u_arg[4]);
384                 tprintf(", %lu", tcp->u_arg[4]);
385         }
386         return rc;
387 }
388
389 #else /* !HAVE_SYS_POLL_H */
390 SYS_FUNC(poll)
391 {
392         return 0;
393 }
394 #endif