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 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 395