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 #include <poll.h> 31 32 #include "xlat/pollflags.h" 33 34 static bool 35 print_pollfd(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data) 36 { 37 const struct pollfd *fds = elem_buf; 38 39 tprints("{fd="); 40 printfd(tcp, fds->fd); 41 if (fds->fd >= 0) { 42 tprints(", events="); 43 printflags(pollflags, (unsigned short) fds->events, "POLL???"); 44 } 45 tprints("}"); 46 47 return true; 48 } 49 50 static void 51 decode_poll_entering(struct tcb *tcp) 52 { 53 const kernel_ulong_t addr = tcp->u_arg[0]; 54 const unsigned int nfds = tcp->u_arg[1]; 55 struct pollfd fds; 56 57 print_array(tcp, addr, nfds, &fds, sizeof(fds), 58 umoven_or_printaddr, print_pollfd, 0); 59 tprintf(", %u, ", nfds); 60 } 61 62 static int 63 decode_poll_exiting(struct tcb *const tcp, const kernel_ulong_t pts) 64 { 65 struct pollfd fds; 66 const unsigned int nfds = tcp->u_arg[1]; 67 const unsigned long size = sizeof(fds) * nfds; 68 const kernel_ulong_t start = tcp->u_arg[0]; 69 const kernel_ulong_t end = start + size; 70 kernel_ulong_t cur; 71 const unsigned int max_printed = 72 abbrev(tcp) ? max_strlen : -1U; 73 unsigned int printed; 74 75 static char outstr[1024]; 76 char *outptr; 77 #define end_outstr (outstr + sizeof(outstr)) 78 79 if (syserror(tcp)) 80 return 0; 81 if (tcp->u_rval == 0) { 82 tcp->auxstr = "Timeout"; 83 return RVAL_STR; 84 } 85 86 if (!verbose(tcp) || !start || !nfds || 87 size / sizeof(fds) != nfds || end < start) 88 return 0; 89 90 outptr = outstr; 91 92 for (printed = 0, cur = start; cur < end; cur += sizeof(fds)) { 93 if (umove(tcp, cur, &fds) < 0) { 94 if (outptr == outstr) 95 *outptr++ = '['; 96 else 97 outptr = stpcpy(outptr, ", "); 98 outptr += sprintf(outptr, "%#" PRI_klx, cur); 99 break; 100 } 101 if (!fds.revents) 102 continue; 103 if (outptr == outstr) 104 *outptr++ = '['; 105 else 106 outptr = stpcpy(outptr, ", "); 107 if (printed >= max_printed) { 108 outptr = stpcpy(outptr, "..."); 109 break; 110 } 111 112 static const char fmt[] = "{fd=%d, revents="; 113 char fdstr[sizeof(fmt) + sizeof(int) * 3]; 114 sprintf(fdstr, fmt, fds.fd); 115 116 const char *flagstr = sprintflags("", pollflags, 117 (unsigned short) fds.revents); 118 119 if (outptr + strlen(fdstr) + strlen(flagstr) + 1 >= 120 end_outstr - (2 + 2 * sizeof(long) + sizeof(", ], ..."))) { 121 outptr = stpcpy(outptr, "..."); 122 break; 123 } 124 outptr = stpcpy(outptr, fdstr); 125 outptr = stpcpy(outptr, flagstr); 126 *outptr++ = '}'; 127 ++printed; 128 } 129 130 if (outptr != outstr) 131 *outptr++ = ']'; 132 133 *outptr = '\0'; 134 if (pts) { 135 const char *str = sprint_timespec(tcp, pts); 136 137 if (outptr + sizeof(", left ") + strlen(str) < end_outstr) { 138 outptr = stpcpy(outptr, outptr == outstr ? "left " : ", left "); 139 outptr = stpcpy(outptr, str); 140 } else { 141 outptr = stpcpy(outptr, ", ..."); 142 } 143 } 144 145 if (outptr == outstr) 146 return 0; 147 148 tcp->auxstr = outstr; 149 return RVAL_STR; 150 #undef end_outstr 151 } 152 153 SYS_FUNC(poll) 154 { 155 if (entering(tcp)) { 156 decode_poll_entering(tcp); 157 int timeout = tcp->u_arg[2]; 158 159 #ifdef INFTIM 160 if (INFTIM == timeout) 161 tprints("INFTIM"); 162 else 163 #endif 164 tprintf("%d", timeout); 165 166 return 0; 167 } else { 168 return decode_poll_exiting(tcp, 0); 169 } 170 } 171 172 SYS_FUNC(ppoll) 173 { 174 if (entering(tcp)) { 175 decode_poll_entering(tcp); 176 177 print_timespec(tcp, tcp->u_arg[2]); 178 tprints(", "); 179 /* NB: kernel requires arg[4] == NSIG_BYTES */ 180 print_sigset_addr_len(tcp, tcp->u_arg[3], tcp->u_arg[4]); 181 tprintf(", %" PRI_klu, tcp->u_arg[4]); 182 183 return 0; 184 } else { 185 return decode_poll_exiting(tcp, tcp->u_arg[2]); 186 } 187 } 188