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