1 /* 2 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs (at) world.std.com> 3 * Copyright (c) 1996-2017 The strace developers. 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 /* 31 * The C library's definition of struct termios might differ from 32 * the kernel one, and we need to use the kernel layout. 33 */ 34 #include <linux/termios.h> 35 36 #include "xlat/tcxonc_options.h" 37 #include "xlat/tcflsh_options.h" 38 #include "xlat/baud_options.h" 39 #include "xlat/modem_flags.h" 40 41 static void 42 decode_termios(struct tcb *const tcp, const kernel_ulong_t addr) 43 { 44 struct termios tios; 45 46 tprints(", "); 47 if (umove_or_printaddr(tcp, addr, &tios)) 48 return; 49 if (abbrev(tcp)) { 50 tprints("{"); 51 printxval(baud_options, tios.c_cflag & CBAUD, "B???"); 52 tprintf(" %sopost %sisig %sicanon %secho ...}", 53 (tios.c_oflag & OPOST) ? "" : "-", 54 (tios.c_lflag & ISIG) ? "" : "-", 55 (tios.c_lflag & ICANON) ? "" : "-", 56 (tios.c_lflag & ECHO) ? "" : "-"); 57 return; 58 } 59 tprintf("{c_iflags=%#lx, c_oflags=%#lx, ", 60 (long) tios.c_iflag, (long) tios.c_oflag); 61 tprintf("c_cflags=%#lx, c_lflags=%#lx, ", 62 (long) tios.c_cflag, (long) tios.c_lflag); 63 tprintf("c_line=%u, ", tios.c_line); 64 if (!(tios.c_lflag & ICANON)) 65 tprintf("c_cc[VMIN]=%d, c_cc[VTIME]=%d, ", 66 tios.c_cc[VMIN], tios.c_cc[VTIME]); 67 tprints("c_cc="); 68 print_quoted_string((char *) tios.c_cc, NCCS, QUOTE_FORCE_HEX); 69 tprints("}"); 70 } 71 72 static void 73 decode_termio(struct tcb *const tcp, const kernel_ulong_t addr) 74 { 75 struct termio tio; 76 int i; 77 78 tprints(", "); 79 if (umove_or_printaddr(tcp, addr, &tio)) 80 return; 81 if (abbrev(tcp)) { 82 tprints("{"); 83 printxval(baud_options, tio.c_cflag & CBAUD, "B???"); 84 tprintf(" %sopost %sisig %sicanon %secho ...}", 85 (tio.c_oflag & OPOST) ? "" : "-", 86 (tio.c_lflag & ISIG) ? "" : "-", 87 (tio.c_lflag & ICANON) ? "" : "-", 88 (tio.c_lflag & ECHO) ? "" : "-"); 89 return; 90 } 91 tprintf("{c_iflags=%#lx, c_oflags=%#lx, ", 92 (long) tio.c_iflag, (long) tio.c_oflag); 93 tprintf("c_cflags=%#lx, c_lflags=%#lx, ", 94 (long) tio.c_cflag, (long) tio.c_lflag); 95 tprintf("c_line=%u, ", tio.c_line); 96 #ifdef _VMIN 97 if (!(tio.c_lflag & ICANON)) 98 tprintf("c_cc[_VMIN]=%d, c_cc[_VTIME]=%d, ", 99 tio.c_cc[_VMIN], tio.c_cc[_VTIME]); 100 #else /* !_VMIN */ 101 if (!(tio.c_lflag & ICANON)) 102 tprintf("c_cc[VMIN]=%d, c_cc[VTIME]=%d, ", 103 tio.c_cc[VMIN], tio.c_cc[VTIME]); 104 #endif /* !_VMIN */ 105 tprints("c_cc=\""); 106 for (i = 0; i < NCC; i++) 107 tprintf("\\x%02x", tio.c_cc[i]); 108 tprints("\"}"); 109 } 110 111 static void 112 decode_winsize(struct tcb *const tcp, const kernel_ulong_t addr) 113 { 114 struct winsize ws; 115 116 tprints(", "); 117 if (umove_or_printaddr(tcp, addr, &ws)) 118 return; 119 tprintf("{ws_row=%d, ws_col=%d, ws_xpixel=%d, ws_ypixel=%d}", 120 ws.ws_row, ws.ws_col, ws.ws_xpixel, ws.ws_ypixel); 121 } 122 123 #ifdef TIOCGSIZE 124 static void 125 decode_ttysize(struct tcb *const tcp, const kernel_ulong_t addr) 126 { 127 struct ttysize ts; 128 129 tprints(", "); 130 if (umove_or_printaddr(tcp, addr, &ts)) 131 return; 132 tprintf("{ts_lines=%d, ts_cols=%d}", 133 ts.ts_lines, ts.ts_cols); 134 } 135 #endif 136 137 static void 138 decode_modem_flags(struct tcb *const tcp, const kernel_ulong_t addr) 139 { 140 int i; 141 142 tprints(", "); 143 if (umove_or_printaddr(tcp, addr, &i)) 144 return; 145 tprints("["); 146 printflags(modem_flags, i, "TIOCM_???"); 147 tprints("]"); 148 } 149 150 int 151 term_ioctl(struct tcb *const tcp, const unsigned int code, 152 const kernel_ulong_t arg) 153 { 154 switch (code) { 155 /* struct termios */ 156 case TCGETS: 157 #ifdef TCGETS2 158 case TCGETS2: 159 #endif 160 case TIOCGLCKTRMIOS: 161 if (entering(tcp)) 162 return 0; 163 case TCSETS: 164 #ifdef TCSETS2 165 case TCSETS2: 166 #endif 167 case TCSETSW: 168 #ifdef TCSETSW2 169 case TCSETSW2: 170 #endif 171 case TCSETSF: 172 #ifdef TCSETSF2 173 case TCSETSF2: 174 #endif 175 case TIOCSLCKTRMIOS: 176 decode_termios(tcp, arg); 177 break; 178 179 /* struct termio */ 180 case TCGETA: 181 if (entering(tcp)) 182 return 0; 183 case TCSETA: 184 case TCSETAW: 185 case TCSETAF: 186 decode_termio(tcp, arg); 187 break; 188 189 /* struct winsize */ 190 case TIOCGWINSZ: 191 if (entering(tcp)) 192 return 0; 193 case TIOCSWINSZ: 194 decode_winsize(tcp, arg); 195 break; 196 197 /* struct ttysize */ 198 #ifdef TIOCGSIZE 199 case TIOCGSIZE: 200 if (entering(tcp)) 201 return 0; 202 case TIOCSSIZE: 203 decode_ttysize(tcp, arg); 204 break; 205 #endif 206 207 /* ioctls with a direct decodable arg */ 208 case TCXONC: 209 tprints(", "); 210 printxval64(tcxonc_options, arg, "TC???"); 211 break; 212 case TCFLSH: 213 tprints(", "); 214 printxval64(tcflsh_options, arg, "TC???"); 215 break; 216 case TCSBRK: 217 case TCSBRKP: 218 case TIOCSCTTY: 219 tprintf(", %d", (int) arg); 220 break; 221 222 /* ioctls with an indirect parameter displayed as modem flags */ 223 case TIOCMGET: 224 if (entering(tcp)) 225 return 0; 226 case TIOCMBIS: 227 case TIOCMBIC: 228 case TIOCMSET: 229 decode_modem_flags(tcp, arg); 230 break; 231 232 /* ioctls with an indirect parameter displayed in decimal */ 233 case TIOCGPGRP: 234 case TIOCGSID: 235 case TIOCGETD: 236 case TIOCGSOFTCAR: 237 case TIOCGPTN: 238 case FIONREAD: 239 case TIOCOUTQ: 240 #ifdef TIOCGEXCL 241 case TIOCGEXCL: 242 #endif 243 #ifdef TIOCGDEV 244 case TIOCGDEV: 245 #endif 246 if (entering(tcp)) 247 return 0; 248 case TIOCSPGRP: 249 case TIOCSETD: 250 case FIONBIO: 251 case FIOASYNC: 252 case TIOCPKT: 253 case TIOCSSOFTCAR: 254 case TIOCSPTLCK: 255 tprints(", "); 256 printnum_int(tcp, arg, "%d"); 257 break; 258 259 /* ioctls with an indirect parameter displayed as a char */ 260 case TIOCSTI: 261 tprints(", "); 262 printstrn(tcp, arg, 1); 263 break; 264 265 /* ioctls with no parameters */ 266 267 case TIOCSBRK: 268 case TIOCCBRK: 269 case TIOCCONS: 270 case TIOCNOTTY: 271 case TIOCEXCL: 272 case TIOCNXCL: 273 case FIOCLEX: 274 case FIONCLEX: 275 #ifdef TIOCVHANGUP 276 case TIOCVHANGUP: 277 #endif 278 #ifdef TIOCSSERIAL 279 case TIOCSSERIAL: 280 #endif 281 break; 282 283 /* ioctls which are unknown */ 284 285 default: 286 return RVAL_DECODED; 287 } 288 289 return RVAL_IOCTL_DECODED; 290 } 291