diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/stty.c | 75 |
1 files changed, 47 insertions, 28 deletions
diff --git a/src/stty.c b/src/stty.c index ce0cb0cae..eb269075d 100644 --- a/src/stty.c +++ b/src/stty.c @@ -1654,42 +1654,61 @@ display_recoverable (struct termios *mode) putchar ('\n'); } +/* NOTE: identical to below, modulo use of tcflag_t */ +static int +strtoul_tcflag_t (char const *s, int base, char **p, tcflag_t *result, + char delim) +{ + unsigned long ul; + errno = 0; + ul = strtoul (s, p, base); + if (errno || **p != delim || *p == s || (tcflag_t) ul != ul) + return -1; + *result = ul; + return 0; +} + +/* NOTE: identical to above, modulo use of cc_t */ +static int +strtoul_cc_t (char const *s, int base, char **p, cc_t *result, char delim) +{ + unsigned long ul; + errno = 0; + ul = strtoul (s, p, base); + if (errno || **p != delim || *p == s || (cc_t) ul != ul) + return -1; + *result = ul; + return 0; +} + +/* Parse the output of display_recoverable. + Return false if any part of it is invalid. */ static bool recover_mode (char const *arg, struct termios *mode) { + tcflag_t flag[4]; + char const *s = arg; size_t i; - int n; - unsigned long int chr; - unsigned long int iflag, oflag, cflag, lflag; - - /* Scan into temporaries since it is too much trouble to figure out - the right format for `tcflag_t'. */ - if (sscanf (arg, "%lx:%lx:%lx:%lx%n", - &iflag, &oflag, &cflag, &lflag, &n) != 4) - return false; - mode->c_iflag = iflag; - mode->c_oflag = oflag; - mode->c_cflag = cflag; - mode->c_lflag = lflag; - if (mode->c_iflag != iflag - || mode->c_oflag != oflag - || mode->c_cflag != cflag - || mode->c_lflag != lflag) - return false; - arg += n; - for (i = 0; i < NCCS; ++i) + for (i = 0; i < 4; i++) { - if (sscanf (arg, ":%lx%n", &chr, &n) != 1) + char *p; + if (strtoul_tcflag_t (s, 16, &p, flag + i, ':') != 0) return false; - mode->c_cc[i] = chr; - if (mode->c_cc[i] != chr) - return false; - arg += n; + s = p + 1; } + mode->c_iflag = flag[0]; + mode->c_oflag = flag[1]; + mode->c_cflag = flag[2]; + mode->c_lflag = flag[3]; - /* Fail if there are too many fields. */ - if (*arg != '\0') - return false; + for (i = 0; i < NCCS; ++i) + { + char *p; + char delim = i < NCCS - 1 ? ':' : '\0'; + if (strtoul_cc_t (s, 16, &p, mode->c_cc + i, delim) != 0) + return false; + s = p + 1; + } return true; } |