Home | History | Annotate | Download | only in strace
      1 /*
      2  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs (at) world.std.com>
      3  * Copyright (c) 1996-1999 Wichert Akkerman <wichert (at) 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
    402