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