]> granicus.if.org Git - strace/blob - desc.c
The `too much stuff, just check the ChangeLog' update
[strace] / desc.c
1 /*
2  * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3  * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
5  * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  *      $Id$
31  */
32
33 #include "defs.h"
34
35 #include <fcntl.h>
36 #include <sys/file.h>
37
38 static struct xlat fcntlcmds[] = {
39         { F_DUPFD,      "F_DUPFD"       },
40         { F_GETFD,      "F_GETFD"       },
41         { F_SETFD,      "F_SETFD"       },
42         { F_GETFL,      "F_GETFL"       },
43         { F_SETFL,      "F_SETFL"       },
44         { F_GETLK,      "F_GETLK"       },
45         { F_SETLK,      "F_SETLK"       },
46         { F_SETLKW,     "F_SETLKW"      },
47         { F_GETOWN,     "F_GETOWN"      },
48         { F_SETOWN,     "F_SETOWN"      },
49 #ifdef F_RSETLK
50         { F_RSETLK,     "F_RSETLK"      },
51 #endif
52 #ifdef F_RSETLKW
53         { F_RSETLKW,    "F_RSETLKW"     },
54 #endif
55 #ifdef F_RGETLK
56         { F_RGETLK,     "F_RGETLK"      },
57 #endif
58 #ifdef F_CNVT
59         { F_CNVT,       "F_CNVT"        },
60 #endif
61 #ifdef F_SETSIG
62         { F_SETSIG,     "F_SETSIG"      },
63 #endif
64 #ifdef F_GETSIG
65         { F_GETSIG,     "F_GETSIG"      },
66 #endif
67         { 0,            NULL            },
68 };
69
70 static struct xlat fdflags[] = {
71 #ifdef FD_CLOEXEC
72         { FD_CLOEXEC,   "FD_CLOEXEC"    },
73 #endif
74         { 0,            NULL            },
75 };
76
77 #ifdef LOCK_SH
78
79 static struct xlat flockcmds[] = {
80         { LOCK_SH,      "LOCK_SH"       },
81         { LOCK_EX,      "LOCK_EX"       },
82         { LOCK_NB,      "LOCK_NB"       },
83         { LOCK_UN,      "LOCK_UN"       },
84         { 0,            NULL            },
85 };
86
87 #endif /* LOCK_SH */
88
89 static struct xlat lockfcmds[] = {
90         { F_RDLCK,      "F_RDLCK"       },
91         { F_WRLCK,      "F_WRLCK"       },
92         { F_UNLCK,      "F_UNLCK"       },
93 #ifdef F_EXLCK
94         { F_EXLCK,      "F_EXLCK"       },
95 #endif
96 #ifdef F_SHLCK
97         { F_SHLCK,      "F_SHLCK"       },
98 #endif
99         { 0,            NULL            },
100 };
101
102 static struct xlat whence[] = {
103         { SEEK_SET,     "SEEK_SET"      },
104         { SEEK_CUR,     "SEEK_CUR"      },
105         { SEEK_END,     "SEEK_END"      },
106         { 0,            NULL            },
107 };
108
109 /* fcntl/lockf */
110 static void
111 printflock(tcp, addr, getlk)
112 struct tcb *tcp;
113 long addr;
114 int getlk;
115 {
116         struct flock fl;
117
118         if (umove(tcp, addr, &fl) < 0) {
119                 tprintf("{...}");
120                 return;
121         }
122         tprintf("{type=");
123         printxval(lockfcmds, fl.l_type, "F_???");
124         tprintf(", whence=");
125         printxval(whence, fl.l_whence, "SEEK_???");
126         tprintf(", start=%ld, len=%ld", fl.l_start, fl.l_len);
127         if (getlk)
128                 tprintf(", pid=%lu}", (unsigned long) fl.l_pid);
129         else
130                 tprintf("}");
131 }
132
133 static char *
134 sprintflags(xlat, flags)
135 struct xlat *xlat;
136 int flags;
137 {
138         static char outstr[1024];
139         char *sep;
140
141         strcpy(outstr, "flags ");
142         sep = "";
143         for (; xlat->str; xlat++) {
144                 if ((flags & xlat->val) == xlat->val) {
145                         sprintf(outstr + strlen(outstr),
146                                 "%s%s", sep, xlat->str);
147                         sep = "|";
148                         flags &= ~xlat->val;
149                 }
150         }
151         if (flags)
152                 sprintf(outstr + strlen(outstr),
153                         "%s%#x", sep, flags);
154         return outstr;
155 }
156
157 int
158 sys_fcntl(tcp)
159 struct tcb *tcp;
160 {
161         extern struct xlat openmodes[];
162
163         if (entering(tcp)) {
164                 tprintf("%ld, ", tcp->u_arg[0]);
165                 printxval(fcntlcmds, tcp->u_arg[1], "F_???");
166                 switch (tcp->u_arg[1]) {
167                 case F_SETFD:
168                         tprintf(", ");
169                         if (printflags(fdflags, tcp->u_arg[2]) == 0)
170                                 tprintf("0");
171                         break;
172                 case F_SETOWN: case F_DUPFD:
173                         tprintf(", %ld", tcp->u_arg[2]);
174                         break;
175                 case F_SETFL:
176                         tprintf(", ");
177                         if (printflags(openmodes, tcp->u_arg[2] + 1) == 0)
178                                 tprintf("0");
179                         break;
180                 case F_SETLK: case F_SETLKW:
181                         tprintf(", ");
182                         printflock(tcp, tcp->u_arg[2], 0);
183                         break;
184                 }
185         }
186         else {
187                 switch (tcp->u_arg[1]) {
188                 case F_DUPFD:
189                 case F_SETFD: case F_SETFL:
190                 case F_SETLK: case F_SETLKW:
191                 case F_SETOWN: case F_GETOWN:
192                         break;
193                 case F_GETFD:
194                         if (tcp->u_rval == 0)
195                                 return 0;
196                         tcp->auxstr = sprintflags(fdflags, tcp->u_rval);
197                         return RVAL_HEX|RVAL_STR;
198                 case F_GETFL:
199                         tcp->auxstr = sprintflags(openmodes, tcp->u_rval + 1);
200                         return RVAL_HEX|RVAL_STR;
201                 case F_GETLK:
202                         tprintf(", ");
203                         printflock(tcp, tcp->u_arg[2], 1);
204                         break;
205                 default:
206                         tprintf(", %#lx", tcp->u_arg[2]);
207                         break;
208                 }
209         }
210         return 0;
211 }
212
213 #ifdef LOCK_SH
214
215 int
216 sys_flock(tcp)
217 struct tcb *tcp;
218 {
219         if (entering(tcp)) {
220                 tprintf("%ld, ", tcp->u_arg[0]);
221                 if (!printflags(flockcmds, tcp->u_arg[1]))
222                         tprintf("LOCK_???");
223         }
224         return 0;
225 }
226 #endif /* LOCK_SH */
227
228 int
229 sys_close(tcp)
230 struct tcb *tcp;
231 {
232         if (entering(tcp)) {
233                 tprintf("%ld", tcp->u_arg[0]);
234         }
235         return 0;
236 }
237
238 int
239 sys_dup(tcp)
240 struct tcb *tcp;
241 {
242         if (entering(tcp)) {
243                 tprintf("%ld", tcp->u_arg[0]);
244         }
245         return 0;
246 }
247
248 int
249 sys_dup2(tcp)
250 struct tcb *tcp;
251 {
252         if (entering(tcp)) {
253                 tprintf("%ld, %ld", tcp->u_arg[0], tcp->u_arg[1]);
254         }
255         return 0;
256 }
257
258 int
259 sys_getdtablesize(tcp)
260 struct tcb *tcp;
261 {
262         return 0;
263 }
264
265 static int
266 decode_select(tcp, args, bitness)
267 struct tcb *tcp;
268 long *args;
269 int bitness;
270 {
271         int i, j, nfds;
272         fd_set fds;
273         struct timeval tv;
274 #ifdef ALPHA
275         struct timeval32 {
276                 unsigned tv_sec;
277                 unsigned tv_usec;
278         } *tv32;
279 #endif
280         static char outstr[1024];
281         char *sep;
282         long arg;
283
284         if (entering(tcp)) {
285                 nfds = args[0];
286                 tprintf("%d", nfds);
287                 for (i = 0; i < 3; i++) {
288                         arg = args[i+1];
289                         if (arg == 0) {
290                                 tprintf(", NULL");
291                                 continue;
292                         }
293                         if (!verbose(tcp)) {
294                                 tprintf(", %#lx", arg);
295                                 continue;
296                         }
297                         if (umove(tcp, arg, &fds) < 0) {
298                                 tprintf(", [?]");
299                                 continue;
300                         }
301                         tprintf(", [");
302                         for (j = 0, sep = ""; j < nfds; j++) {
303                                 if (FD_ISSET(j, &fds)) {
304                                         tprintf("%s%u", sep, j);
305                                         sep = " ";
306                                 }
307                         }
308                         tprintf("]");
309                 }
310                 if (!args[4])
311                         tprintf(", NULL");
312                 else if (!verbose(tcp))
313                         tprintf(", %#lx", args[4]);
314                 else if (umove(tcp, args[4], &tv) < 0)
315                         tprintf(", {...}");
316                 else {
317 #ifdef ALPHA
318                         if (bitness) {
319                                 tv32=(struct timeval32*)&tv;
320                                 tprintf(", {%u, %u}", tv32->tv_sec, tv32->tv_usec);
321                         } else
322 #endif
323                                 tprintf(", {%lu, %lu}",
324                                         (long) tv.tv_sec, (long) tv.tv_usec);
325                 }
326         }
327         else
328         {
329                 unsigned int cumlen = 0;
330                 char *sep = "";
331
332                 if (syserror(tcp))
333                         return 0;
334
335                 if ((nfds = tcp->u_rval) == 0) {
336                         tcp->auxstr = "Timeout";
337                         return RVAL_STR;
338                 }
339                 outstr[0] = '\0';
340                 for (i = 0; i < 3; i++) {
341                         int first = 1;
342                         char str[20];
343
344                         tcp->auxstr = outstr;
345                         arg = args[i+1];
346                         if (!arg || umove(tcp, arg, &fds) < 0)
347                                 continue;
348                         for (j = 0; j < args[0]; j++) {
349                                 if (FD_ISSET(j, &fds)) {
350                                         if (first) {
351                                                 sprintf(str, "%s%s [%u", sep,
352                                                         i == 0 ? "in" :
353                                                         i == 1 ? "out" :
354                                                         "except", j);
355                                                 first = 0;
356                                                 sep = ", ";
357                                         }
358                                         else
359                                                 sprintf(str, " %u", j);
360                                         cumlen += strlen(str);
361                                         if (cumlen < sizeof(outstr))
362                                                 strcat(outstr, str);
363                                         nfds--;
364                                 }
365                         }
366                         if (cumlen)
367                                 strcat(outstr, "]");
368                         if (nfds == 0)
369                                 break;
370                 }
371 #ifdef LINUX
372                 /* This contains no useful information on SunOS.  */
373                 if (args[4]) {
374                         char str[20];
375
376                         if (umove(tcp, args[4], &tv) >= 0) {
377 #ifdef ALPHA
378                                 if (bitness) {
379                                         tv32=(struct timeval32*)&tv;
380                                         sprintf(str, "%sleft {%u, %u}", sep,
381                                                 tv32->tv_sec, tv32->tv_usec);
382                                 } else
383 #endif
384                                         sprintf(str, "%sleft {%lu, %lu}", sep,
385                                                 (long) tv.tv_sec, (long) tv.tv_usec);
386
387                                 if ((cumlen += strlen(str)) < sizeof(outstr))
388                                         strcat(outstr, str);
389                         }
390                 }
391 #endif /* LINUX */
392                 return RVAL_STR;
393         }
394         return 0;
395 }
396
397 #ifdef LINUX
398
399 int
400 sys_oldselect(tcp)
401 struct tcb *tcp;
402 {
403         long args[5];
404
405         if (umoven(tcp, tcp->u_arg[0], sizeof args, (char *) args) < 0) {
406                 tprintf("[...]");
407                 return 0;
408         }
409         return decode_select(tcp, args, 0);
410 }
411
412 #ifdef ALPHA
413 sys_osf_select(tcp)
414 struct tcb *tcp;
415 {
416         long *args = tcp->u_arg;
417         return decode_select(tcp, args, 1);
418 }
419 #endif
420
421 #endif /* LINUX */
422
423 int
424 sys_select(tcp)
425 struct tcb *tcp;
426 {
427         long *args = tcp->u_arg;
428         return decode_select(tcp, args, 0);
429 }