term: improve decoding of termios and termio structures

This commit is contained in:
Eugene Syromyatnikov
2017-09-13 21:20:16 +02:00
committed by Dmitry V. Levin
parent 882957c7dd
commit c00a4ca7d8
17 changed files with 373 additions and 56 deletions

View File

@ -283,6 +283,12 @@ AC_CHECK_TYPES([struct stat64, struct __old_kernel_stat],,,
[#include <sys/types.h>
#include <asm/stat.h>])
AC_CHECK_TYPES([struct termios2],,,
[#include <linux/termios.h>])
AC_CHECK_MEMBERS([struct termios.c_ispeed, struct termios.c_ospeed],,,
[#include <linux/termios.h>])
AC_CHECK_TYPES([struct user_desc],
[AC_CHECK_MEMBERS([struct user_desc.lm],,,
[#include <asm/ldt.h>])],,

279
term.c
View File

@ -18,6 +18,151 @@
#include "xlat/baud_options.h"
#include "xlat/modem_flags.h"
#include "xlat/term_cflags.h"
#include "xlat/term_cflags_csize.h"
#include "xlat/term_iflags.h"
#include "xlat/term_lflags.h"
#include "xlat/term_oflags.h"
#include "xlat/term_oflags_bsdly.h"
#include "xlat/term_oflags_crdly.h"
#include "xlat/term_oflags_ffdly.h"
#include "xlat/term_oflags_nldly.h"
#include "xlat/term_oflags_tabdly.h"
#include "xlat/term_oflags_vtdly.h"
#include "xlat/term_line_discs.h"
#include "xlat/termio_cc.h"
#include "xlat/termios_cc.h"
static void
decode_oflag(uint64_t val)
{
static const struct {
const struct xlat *xl;
uint64_t mask;
const char *dfl;
} xlats[] = {
{ term_oflags_nldly, NLDLY, "NL?" },
{ term_oflags_crdly, CRDLY, "CR?" },
{ term_oflags_tabdly, TABDLY, "TAB?" },
{ term_oflags_bsdly, BSDLY, "BS?" },
{ term_oflags_vtdly, VTDLY, "VT?" },
{ term_oflags_ffdly, FFDLY, "FF?" },
};
unsigned i;
for (i = 0; i < ARRAY_SIZE(xlats); i++) {
printxval64(xlats[i].xl, val & xlats[i].mask, xlats[i].dfl);
tprints("|");
val &= ~xlats[i].mask;
}
printflags64(term_oflags, val, NULL);
}
static void
decode_cflag(uint64_t val)
{
printxval64(baud_options, val & CBAUD, "B???");
tprints("|");
if (val & CIBAUD) {
printxval64(baud_options, (val & CIBAUD) >> IBSHIFT, "B???");
tprintf("<<IBSHIFT|");
}
printxval64(term_cflags_csize, val & CSIZE, "CS?");
tprints("|");
val &= ~(CBAUD | CIBAUD | CSIZE);
printflags64(term_cflags, val, NULL);
}
static void
decode_flags(uint64_t iflag, uint64_t oflag, uint64_t cflag, uint64_t lflag)
{
tprints("c_iflag=");
printflags64(term_iflags, iflag, NULL);
tprints(", c_oflag=");
decode_oflag(oflag);
tprints(", c_cflag=");
decode_cflag(cflag);
tprints(", c_lflag=");
printflags64(term_lflags, lflag, NULL);
}
static void
decode_line_disc(uint64_t line)
{
tprints("c_line=");
printxval(term_line_discs, line, "N_???");
}
static void
print_cc_char(bool *first, const unsigned char *data, const char *s,
unsigned idx)
{
if (*first)
*first = false;
else
tprints(", ");
if (s)
tprintf("[%s] = ", s);
else
tprintf("[%u] = ", idx);
tprintf("%#hhx", data[idx]);
}
static void
decode_term_cc(const struct xlat *xl, const unsigned char *data, unsigned size)
{
unsigned i = 0;
bool first = true;
tprints("[");
for (i = 0; i < size; i++)
print_cc_char(&first, data, xlookup(xl, i), i);
tprints("]");
}
#ifdef HAVE_STRUCT_TERMIOS2
static void
decode_termios2(struct tcb *const tcp, const kernel_ulong_t addr)
{
struct termios2 tios;
tprints(", ");
if (umove_or_printaddr(tcp, addr, &tios))
return;
tprints("{");
decode_flags(tios.c_iflag, tios.c_oflag, tios.c_cflag, tios.c_lflag);
tprints(", ");
if (abbrev(tcp)) {
tprints("...");
} else {
decode_line_disc(tios.c_line);
if (!(tios.c_lflag & ICANON))
tprintf(", c_cc[VMIN]=%u, c_cc[VTIME]=%u",
tios.c_cc[VMIN], tios.c_cc[VTIME]);
tprints(", c_cc=");
/* SPARC has two additional bytes in c_cc. */
decode_term_cc(termios_cc, tios.c_cc, sizeof(tios.c_cc));
tprintf(", c_ispeed=%u", tios.c_ispeed);
tprintf(", c_ospeed=%u", tios.c_ospeed);
}
tprints("}");
}
#endif /* HAVE_STRUCT_TERMIOS2 */
static void
decode_termios(struct tcb *const tcp, const kernel_ulong_t addr)
{
@ -26,26 +171,38 @@ decode_termios(struct tcb *const tcp, const kernel_ulong_t addr)
tprints(", ");
if (umove_or_printaddr(tcp, addr, &tios))
return;
tprints("{");
decode_flags(tios.c_iflag, tios.c_oflag, tios.c_cflag, tios.c_lflag);
tprints(", ");
if (abbrev(tcp)) {
tprints("{");
printxval(baud_options, tios.c_cflag & CBAUD, "B???");
tprintf(" %sopost %sisig %sicanon %secho ...}",
(tios.c_oflag & OPOST) ? "" : "-",
(tios.c_lflag & ISIG) ? "" : "-",
(tios.c_lflag & ICANON) ? "" : "-",
(tios.c_lflag & ECHO) ? "" : "-");
return;
tprints("...");
} else {
decode_line_disc(tios.c_line);
if (!(tios.c_lflag & ICANON))
tprintf(", c_cc[VMIN]=%u, c_cc[VTIME]=%u",
tios.c_cc[VMIN], tios.c_cc[VTIME]);
tprints(", c_cc=");
/*
* Fun fact: MIPS has NCCS defined to 23, SPARC to 17 and
* everything else to 19.
*/
decode_term_cc(termios_cc, tios.c_cc,
MIN(NCCS, sizeof(tios.c_cc)));
/*
* alpha and powerpc have those in struct termios instead of
* having a separate struct termios2.
*/
#ifdef HAVE_STRUCT_TERMIOS_C_ISPEED
tprintf(", c_ispeed=%u", tios.c_ispeed);
#endif
#ifdef HAVE_STRUCT_TERMIOS_C_OSPEED
tprintf(", c_ospeed=%u", tios.c_ospeed);
#endif
}
tprintf("{c_iflags=%#lx, c_oflags=%#lx, ",
(long) tios.c_iflag, (long) tios.c_oflag);
tprintf("c_cflags=%#lx, c_lflags=%#lx, ",
(long) tios.c_cflag, (long) tios.c_lflag);
tprintf("c_line=%u, ", tios.c_line);
if (!(tios.c_lflag & ICANON))
tprintf("c_cc[VMIN]=%d, c_cc[VTIME]=%d, ",
tios.c_cc[VMIN], tios.c_cc[VTIME]);
tprints("c_cc=");
print_quoted_string((char *) tios.c_cc, NCCS, QUOTE_FORCE_HEX);
tprints("}");
}
@ -53,39 +210,40 @@ static void
decode_termio(struct tcb *const tcp, const kernel_ulong_t addr)
{
struct termio tio;
int i;
tprints(", ");
if (umove_or_printaddr(tcp, addr, &tio))
return;
tprints("{");
decode_flags(tio.c_iflag, tio.c_oflag, tio.c_cflag, tio.c_lflag);
tprints(", ");
if (abbrev(tcp)) {
tprints("{");
printxval(baud_options, tio.c_cflag & CBAUD, "B???");
tprintf(" %sopost %sisig %sicanon %secho ...}",
(tio.c_oflag & OPOST) ? "" : "-",
(tio.c_lflag & ISIG) ? "" : "-",
(tio.c_lflag & ICANON) ? "" : "-",
(tio.c_lflag & ECHO) ? "" : "-");
return;
}
tprintf("{c_iflags=%#lx, c_oflags=%#lx, ",
(long) tio.c_iflag, (long) tio.c_oflag);
tprintf("c_cflags=%#lx, c_lflags=%#lx, ",
(long) tio.c_cflag, (long) tio.c_lflag);
tprintf("c_line=%u, ", tio.c_line);
#ifdef _VMIN
if (!(tio.c_lflag & ICANON))
tprintf("c_cc[_VMIN]=%d, c_cc[_VTIME]=%d, ",
tio.c_cc[_VMIN], tio.c_cc[_VTIME]);
tprints("...");
} else {
decode_line_disc(tio.c_line);
#ifdef _VMIN /* thanks, alpha and powerpc */
if (!(tio.c_lflag & ICANON))
tprintf(", c_cc[_VMIN]=%d, c_cc[_VTIME]=%d",
tio.c_cc[_VMIN], tio.c_cc[_VTIME]);
tprints(", c_cc=");
decode_term_cc(termio_cc, tio.c_cc,
MIN(NCC, sizeof(tio.c_cc)));
#else /* !_VMIN */
if (!(tio.c_lflag & ICANON))
tprintf("c_cc[VMIN]=%d, c_cc[VTIME]=%d, ",
tio.c_cc[VMIN], tio.c_cc[VTIME]);
if (!(tio.c_lflag & ICANON))
tprintf(", c_cc[VMIN]=%d, c_cc[VTIME]=%d",
tio.c_cc[VMIN], tio.c_cc[VTIME]);
tprints(", c_cc=");
decode_term_cc(termios_cc, tio.c_cc,
MIN(NCC, sizeof(tio.c_cc)));
#endif /* !_VMIN */
tprints("c_cc=\"");
for (i = 0; i < NCC; i++)
tprintf("\\x%02x", tio.c_cc[i]);
tprints("\"}");
}
tprints("}");
}
static void
@ -132,27 +290,36 @@ term_ioctl(struct tcb *const tcp, const unsigned int code,
const kernel_ulong_t arg)
{
switch (code) {
#ifdef HAVE_STRUCT_TERMIOS2
/* struct termios2 */
# ifdef TCGETS2
case TCGETS2:
# endif
if (entering(tcp))
return 0;
ATTRIBUTE_FALLTHROUGH;
# ifdef TCSETS2
case TCSETS2:
# endif
# ifdef TCSETSW2
case TCSETSW2:
# endif
# ifdef TCSETSF2
case TCSETSF2:
# endif
decode_termios2(tcp, arg);
break;
#endif /* HAVE_STRUCT_TERMIOS2 */
/* struct termios */
case TCGETS:
#ifdef TCGETS2
case TCGETS2:
#endif
case TIOCGLCKTRMIOS:
if (entering(tcp))
return 0;
ATTRIBUTE_FALLTHROUGH;
case TCSETS:
#ifdef TCSETS2
case TCSETS2:
#endif
case TCSETSW:
#ifdef TCSETSW2
case TCSETSW2:
#endif
case TCSETSF:
#ifdef TCSETSF2
case TCSETSF2:
#endif
case TIOCSLCKTRMIOS:
decode_termios(tcp, arg);
break;

View File

@ -15,11 +15,15 @@ B9600
B19200
B38400
B57600
B76800
B115200
B153600
B230400
B307200
B460800
B500000
B576000
B614400
B921600
B1000000
B1152000
@ -31,3 +35,4 @@ B3500000
B4000000
EXTA
EXTB
BOTHER

9
xlat/term_cflags.in Normal file
View File

@ -0,0 +1,9 @@
CSTOPB
CREAD
PARENB
PARODD
HUPCL
CLOCAL
CTVB /* VisioBraille Terminal flow control */
CMSPAR /* mark or space (stick) parity */
CRTSCTS /* flow control */

View File

@ -0,0 +1,4 @@
CS5
CS6
CS7
CS8

15
xlat/term_iflags.in Normal file
View File

@ -0,0 +1,15 @@
IGNBRK /* Ignore break condition. */
BRKINT /* Signal interrupt on break. */
IGNPAR /* Ignore characters with parity errors. */
PARMRK /* Mark parity and framing errors. */
INPCK /* Enable input parity check. */
ISTRIP /* Strip 8th bit off characters. */
INLCR /* Map NL to CR on input. */
IGNCR /* Ignore CR. */
ICRNL /* Map CR to NL on input. */
IUCLC /* Map upper case to lower case on input. */
IXON /* Enable start/stop output control. */
IXANY /* Any character will restart after stop. */
IXOFF /* Enable start/stop input control. */
IMAXBEL /* Ring bell when input queue is full. */
IUTF8 /* Input is UTF-8 */

18
xlat/term_lflags.in Normal file
View File

@ -0,0 +1,18 @@
ISIG /* Enable signals. */
ICANON /* Do erase and kill processing. */
XCASE
ECHO /* Enable echo. */
ECHOE /* Visual erase for ERASE. */
ECHOK /* Echo NL after KILL. */
ECHONL /* Echo NL even if ECHO is off. */
NOFLSH /* Disable flush after interrupt. */
IEXTEN /* Enable DISCARD and LNEXT. */
ECHOCTL /* Echo control characters as ^X. */
ECHOPRT /* Hardcopy visual erase. */
ECHOKE /* Visual erase for KILL. */
FLUSHO
PENDIN /* Retype pending input (state). */
TOSTOP /* Send SIGTTOU for background output. */
EXTPROC /* External processing on pty */
DEFECHO /* SUNOS thing, what is it? */

28
xlat/term_line_discs.in Normal file
View File

@ -0,0 +1,28 @@
N_TTY 0
N_SLIP 1
N_MOUSE 2
N_PPP 3
N_STRIP 4
N_AX25 5
N_X25 6 /* X.25 async */
N_6PACK 7
N_MASC 8 /* Reserved for Mobitex module <kaz@cafe.net> */
N_R3964 9 /* Reserved for Simatic R3964 module */
N_PROFIBUS_FDL 10 /* Reserved for Profibus */
N_IRDA 11 /* Linux IrDa - http://irda.sourceforge.net/ */
N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards about SMS messages */
N_HDLC 13 /* synchronous HDLC */
N_SYNC_PPP 14 /* synchronous PPP */
N_HCI 15 /* Bluetooth HCI UART */
N_GIGASET_M101 16 /* Siemens Gigaset M101 serial DECT adapter */
N_SLCAN 17 /* Serial / USB serial CAN Adaptors */
N_PPS 18 /* Pulse per Second */
N_V253 19 /* Codec control over voice modem */
N_CAIF 20 /* CAIF protocol for talking to modems */
N_GSM0710 21 /* GSM 0710 Mux */
N_TI_WL 22 /* for TI's WL BT, FM, GPS combo chips */
N_TRACESINK 23 /* Trace data routing for MIPI P1149.7 */
N_TRACEROUTER 24 /* Trace data routing for MIPI P1149.7 */
N_NCI 25 /* NFC NCI UART */
N_SPEAKUP 26 /* Speakup communication with synths */
N_NULL 27 /* Null ldisc used for error handling */

15
xlat/term_oflags.in Normal file
View File

@ -0,0 +1,15 @@
#ifdef ALPHA
XTABS /* required by POSIX to == TAB3; but not on Alpha! */
#endif
OPOST /* Perform output processing. */
OLCUC /* Map lower case to upper case on output. */
ONLCR /* Map NL to CR-NL on output. */
OCRNL
ONOCR
ONLRET
OFILL
OFDEL
PAGEOUT /* SUNOS specific */
WRAP /* SUNOS specific */

View File

@ -0,0 +1,2 @@
BS1
BS0

View File

@ -0,0 +1,4 @@
CR0
CR1
CR2
CR3

View File

@ -0,0 +1,2 @@
FF0
FF1

View File

@ -0,0 +1,4 @@
NL0
NL1
NL2
NL3

View File

@ -0,0 +1,8 @@
#ifndef ALPHA
XTABS /* required by POSIX to == TAB3; but not on Alpha! */
#endif
TAB0
TAB1
TAB2
TAB3

View File

@ -0,0 +1,2 @@
VT0
VT1

10
xlat/termio_cc.in Normal file
View File

@ -0,0 +1,10 @@
_VINTR
_VQUIT
_VERASE
_VKILL
_VEOF
_VMIN
_VEOL
_VTIME
_VEOL2
_VSWTC

18
xlat/termios_cc.in Normal file
View File

@ -0,0 +1,18 @@
VINTR /* Interrupt character [ISIG]. */
VQUIT /* Quit character [ISIG]. */
VERASE /* Erase character [ICANON]. */
VKILL /* Kill-line character [ICANON]. */
VEOL2 /* Second EOL character [ICANON]. */
VSWTC /* ??? */
VSTART /* Start (X-ON) character [IXON, IXOFF]. */
VSTOP /* Stop (X-OFF) character [IXON, IXOFF]. */
VSUSP /* Suspend character [ISIG]. */
VDSUSP /* Delayed suspend character [ISIG]. */
VREPRINT /* Reprint-line character [ICANON]. */
VDISCARD /* Discard character [IEXTEN]. */
VWERASE /* Word-erase character [ICANON]. */
VLNEXT /* Literal-next character [IEXTEN]. */
VEOF /* End-of-file character [ICANON]. */
VEOL /* End-of-line character [ICANON]. */
VMIN /* Minimum number of bytes read at once [!ICANON]. */
VTIME /* Time-out value (tenths of a second) [!ICANON]. */