stty: reorder code, reducing need in forward declarations.
authorDenis Vlasenko <vda.linux@googlemail.com>
Tue, 19 Sep 2006 14:31:44 +0000 (14:31 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Tue, 19 Sep 2006 14:31:44 +0000 (14:31 -0000)
added few missed bits of error checking for parameters.

coreutils/stty.c

index 7fa5feb0dbeaa2664749c00477e96c812e9e5204..378e03e900eb37e5ad553eb9ed5d1cea7cac33da 100644 (file)
@@ -371,30 +371,74 @@ enum {
 
 /* The width of the screen, for output wrapping */
 static int max_col;
-
 /* Current position, to know when to wrap */
 static int current_col;
+static const char *device_name = bb_msg_standard_input;
 
-static const char *  visible(unsigned int ch);
-static int           recover_mode(const char *arg, struct termios *mode);
-static int           screen_columns(void);
-static void          set_mode(const struct mode_info *info,
-                                       int reversed, struct termios *mode);
-static speed_t       string_to_baud(const char *arg);
-static tcflag_t*     mode_type_flag(unsigned type, const struct termios *mode);
-static void          display_all(const struct termios *mode);
-static void          display_changed(const struct termios *mode);
-static void          display_recoverable(const struct termios *mode);
-static void          display_speed(const struct termios *mode, int fancy);
-static void          display_window_size(int fancy);
-static void          sane_mode(struct termios *mode);
-static void          set_control_char_or_die(const struct control_info *info,
-                                       const char *arg, struct termios *mode);
-static void          set_speed(enum speed_setting type,
-                                       const char *arg, struct termios *mode);
-static void          set_window_size(int rows, int cols);
+/* Return a string that is the printable representation of character CH */
+/* Adapted from `cat' by Torbjorn Granlund */
+static const char *visible(unsigned int ch)
+{
+       static char buf[10];
+       char *bpout = buf;
 
-static const char *device_name = bb_msg_standard_input;
+       if (ch == _POSIX_VDISABLE)
+               return "<undef>";
+
+       if (ch >= 128) {
+               ch -= 128;
+               *bpout++ = 'M';
+               *bpout++ = '-';
+       }
+
+       if (ch < 32) {
+               *bpout++ = '^';
+               *bpout++ = ch + 64;
+       } else if (ch < 127) {
+               *bpout++ = ch;
+       } else {
+               *bpout++ = '^';
+               *bpout++ = '?';
+       }
+
+       *bpout = '\0';
+       return buf;
+}
+
+static tcflag_t *mode_type_flag(unsigned type, const struct termios *mode)
+{
+       static const unsigned char tcflag_offsets[] = {
+               offsetof(struct termios, c_cflag), /* control */
+               offsetof(struct termios, c_iflag), /* input */
+               offsetof(struct termios, c_oflag), /* output */
+               offsetof(struct termios, c_lflag), /* local */
+       };
+
+       if (type <= local) {
+               return (tcflag_t*) (((char*)mode) + tcflag_offsets[type]);
+       }
+       return NULL;
+}
+
+static speed_t string_to_baud_or_die(const char *arg)
+{
+       return tty_value_to_baud(bb_xparse_number(arg, 0));
+}
+
+static void set_speed_or_die(enum speed_setting type, const char *arg,
+                                       struct termios *mode)
+{
+       speed_t baud;
+
+       baud = string_to_baud_or_die(arg);
+
+       if (type != output_speed) {     /* either input or both */
+               cfsetispeed(mode, baud);
+       }
+       if (type != input_speed) {      /* either output or both */
+               cfsetospeed(mode, baud);
+       }
+}
 
 static ATTRIBUTE_NORETURN void perror_on_device_and_die(const char *fmt)
 {
@@ -438,6 +482,103 @@ static void wrapf(const char *message, ...)
                current_col = 0;
 }
 
+#ifdef TIOCGWINSZ
+
+static int get_win_size(struct winsize *win)
+{
+       return ioctl(STDIN_FILENO, TIOCGWINSZ, (char *) win);
+}
+
+static void set_window_size(int rows, int cols)
+{
+       struct winsize win;
+
+       if (get_win_size(&win)) {
+               if (errno != EINVAL) {
+                       perror_on_device("%s");
+                       return;
+               }
+               memset(&win, 0, sizeof(win));
+       }
+
+       if (rows >= 0)
+               win.ws_row = rows;
+       if (cols >= 0)
+               win.ws_col = cols;
+
+# ifdef TIOCSSIZE
+       /* Alexander Dupuy <dupuy@cs.columbia.edu> wrote:
+          The following code deals with a bug in the SunOS 4.x (and 3.x?) kernel.
+          This comment from sys/ttold.h describes Sun's twisted logic - a better
+          test would have been (ts_lines > 64k || ts_cols > 64k || ts_cols == 0).
+          At any rate, the problem is gone in Solaris 2.x */
+
+       if (win.ws_row == 0 || win.ws_col == 0) {
+               struct ttysize ttysz;
+
+               ttysz.ts_lines = win.ws_row;
+               ttysz.ts_cols = win.ws_col;
+
+               win.ws_row = win.ws_col = 1;
+
+               if ((ioctl(STDIN_FILENO, TIOCSWINSZ, (char *) &win) != 0)
+               || (ioctl(STDIN_FILENO, TIOCSSIZE, (char *) &ttysz) != 0)) {
+                       perror_on_device("%s");
+               }
+               return;
+       }
+# endif
+
+       if (ioctl(STDIN_FILENO, TIOCSWINSZ, (char *) &win))
+               perror_on_device("%s");
+}
+
+static void display_window_size(int fancy)
+{
+       const char *fmt_str = "%s\0%s: no size information for this device";
+       struct winsize win;
+
+       if (get_win_size(&win)) {
+               if ((errno != EINVAL) || ((fmt_str += 2), !fancy)) {
+                       perror_on_device(fmt_str);
+               }
+       } else {
+               wrapf(fancy ? "rows %d; columns %d;" : "%d %d\n",
+                               win.ws_row, win.ws_col);
+       }
+}
+
+#else /* !TIOCGWINSZ */
+
+static inline void display_window_size(int fancy) {}
+
+#endif /* !TIOCGWINSZ */
+
+static int screen_columns(void)
+{
+       int columns;
+       const char *s;
+
+#ifdef TIOCGWINSZ
+       struct winsize win;
+
+       /* With Solaris 2.[123], this ioctl fails and errno is set to
+          EINVAL for telnet (but not rlogin) sessions.
+          On ISC 3.0, it fails for the console and the serial port
+          (but it works for ptys).
+          It can also fail on any system when stdout isn't a tty.
+          In case of any failure, just use the default */
+       if (get_win_size(&win) == 0 && win.ws_col > 0)
+               return win.ws_col;
+#endif
+
+       columns = 80;
+       if ((s = getenv("COLUMNS"))) {
+               columns = atoi(s);
+       }
+       return columns;
+}
+
 static const struct suffix_mult stty_suffixes[] = {
        {"b",  512 },
        {"k",  1024},
@@ -469,9 +610,9 @@ enum {
        param_rows   = 2 | 0x80,
        param_cols   = 3 | 0x80,
        param_size   = 4,
-       param_ispeed = 5 | 0x80,
-       param_ospeed = 6 | 0x80,
-       param_speed  = 7,
+       param_speed  = 5,
+       param_ispeed = 6 | 0x80,
+       param_ospeed = 7 | 0x80,
 };
 
 static int find_param(const char *name)
@@ -485,13 +626,24 @@ static int find_param(const char *name)
        if (streq(name, "columns")) return param_cols;
        if (streq(name, "size")) return param_size;
 #endif
+       if (streq(name, "speed")) return param_speed;
        if (streq(name, "ispeed")) return param_ispeed;
        if (streq(name, "ospeed")) return param_ospeed;
-       if (streq(name, "speed")) return param_speed;
        return 0;
 }
 
 
+static int recover_mode(const char *arg, struct termios *mode);
+static void set_mode(const struct mode_info *info,
+                               int reversed, struct termios *mode);
+static void display_all(const struct termios *mode);
+static void display_changed(const struct termios *mode);
+static void display_recoverable(const struct termios *mode);
+static void display_speed(const struct termios *mode, int fancy);
+static void sane_mode(struct termios *mode);
+static void set_control_char_or_die(const struct control_info *info,
+                               const char *arg, struct termios *mode);
+
 int stty_main(int argc, char **argv)
 {
        struct termios mode;
@@ -602,13 +754,19 @@ end_option:
                        break;
                case param_size:
 #endif
+               case param_speed:
+                       break;
                case param_ispeed:
+                       /* called for the side effect of xfunc death only */
+                       set_speed_or_die(input_speed, argnext, &mode);
+                       break;
                case param_ospeed:
-               case param_speed:
+                       /* called for the side effect of xfunc death only */
+                       set_speed_or_die(output_speed, argnext, &mode);
                        break;
                default:
                        if (recover_mode(arg, &mode) == 1) break;
-                       if (string_to_baud(arg) != (speed_t) -1) break;
+                       if (string_to_baud_or_die(arg) != (speed_t) -1) break;
                        bb_error_msg_and_die("invalid argument '%s'", arg);
                }
                noargs = 0;
@@ -643,7 +801,6 @@ end_option:
 
        if (verbose_output || recoverable_output || noargs) {
                max_col = screen_columns();
-               current_col = 0;
                output_func(&mode);
                return EXIT_SUCCESS;
        }
@@ -697,32 +854,31 @@ end_option:
                        break;
                case param_size:
                        max_col = screen_columns();
-                       current_col = 0;
                        display_window_size(0);
                        break;
                case param_rows:
                        set_window_size((int) bb_xparse_number(argnext, stty_suffixes), -1);
                        break;
 #endif
+               case param_speed:
+                       max_col = screen_columns();
+                       display_speed(&mode, 0);
+                       break;
                case param_ispeed:
-                       set_speed(input_speed, argnext, &mode);
+                       set_speed_or_die(input_speed, argnext, &mode);
                        speed_was_set = 1;
                        require_set_attr = 1;
                        break;
                case param_ospeed:
-                       set_speed(output_speed, argnext, &mode);
+                       set_speed_or_die(output_speed, argnext, &mode);
                        speed_was_set = 1;
                        require_set_attr = 1;
                        break;
-               case param_speed:
-                       max_col = screen_columns();
-                       display_speed(&mode, 0);
-                       break;
                default:
                        if (recover_mode(arg, &mode) == 1)
                                require_set_attr = 1;
-                       else /* true: if (string_to_baud(arg) != (speed_t) -1) */ {
-                               set_speed(both_speeds, arg, &mode);
+                       else /* true: if (string_to_baud_or_die(arg) != (speed_t) -1) */ {
+                               set_speed_or_die(both_speeds, arg, &mode);
                                speed_was_set = 1;
                                require_set_attr = 1;
                        } /* else - impossible (caught in the first pass):
@@ -805,8 +961,8 @@ end_option:
 #define ECHOKE 0
 #endif
 
-static void
-set_mode(const struct mode_info *info, int reversed, struct termios *mode)
+static void set_mode(const struct mode_info *info, int reversed,
+                                       struct termios *mode)
 {
        tcflag_t *bitsp;
 
@@ -932,9 +1088,8 @@ set_mode(const struct mode_info *info, int reversed, struct termios *mode)
        }
 }
 
-static void
-set_control_char_or_die(const struct control_info *info, const char *arg,
-                                struct termios *mode)
+static void set_control_char_or_die(const struct control_info *info,
+                       const char *arg, struct termios *mode)
 {
        unsigned char value;
 
@@ -945,143 +1100,14 @@ set_control_char_or_die(const struct control_info *info, const char *arg,
        else if (streq(arg, "^-") || streq(arg, "undef"))
                value = _POSIX_VDISABLE;
        else if (arg[0] == '^') { /* Ignore any trailing junk (^Cjunk) */
+               value = arg[1] & 0x1f; /* Non-letters get weird results */
                if (arg[1] == '?')
                        value = 127;
-               else
-                       value = arg[1] & 0x1f; /* Non-letters get weird results */
        } else
                value = bb_xparse_number(arg, stty_suffixes);
        mode->c_cc[info->offset] = value;
 }
 
-static void
-set_speed(enum speed_setting type, const char *arg, struct termios *mode)
-{
-       speed_t baud;
-
-       baud = string_to_baud(arg);
-
-       if (type != output_speed) {     /* either input or both */
-               cfsetispeed(mode, baud);
-       }
-       if (type != input_speed) {      /* either output or both */
-               cfsetospeed(mode, baud);
-       }
-}
-
-#ifdef TIOCGWINSZ
-
-static int get_win_size(struct winsize *win)
-{
-       return ioctl(STDIN_FILENO, TIOCGWINSZ, (char *) win);
-}
-
-static void
-set_window_size(int rows, int cols)
-{
-       struct winsize win;
-
-       if (get_win_size(&win)) {
-               if (errno != EINVAL) {
-                       perror_on_device("%s");
-                       return;
-               }
-               memset(&win, 0, sizeof(win));
-       }
-
-       if (rows >= 0)
-               win.ws_row = rows;
-       if (cols >= 0)
-               win.ws_col = cols;
-
-# ifdef TIOCSSIZE
-       /* Alexander Dupuy <dupuy@cs.columbia.edu> wrote:
-          The following code deals with a bug in the SunOS 4.x (and 3.x?) kernel.
-          This comment from sys/ttold.h describes Sun's twisted logic - a better
-          test would have been (ts_lines > 64k || ts_cols > 64k || ts_cols == 0).
-          At any rate, the problem is gone in Solaris 2.x */
-
-       if (win.ws_row == 0 || win.ws_col == 0) {
-               struct ttysize ttysz;
-
-               ttysz.ts_lines = win.ws_row;
-               ttysz.ts_cols = win.ws_col;
-
-               win.ws_row = win.ws_col = 1;
-
-               if ((ioctl(STDIN_FILENO, TIOCSWINSZ, (char *) &win) != 0)
-               || (ioctl(STDIN_FILENO, TIOCSSIZE, (char *) &ttysz) != 0)) {
-                       perror_on_device("%s");
-               }
-               return;
-       }
-# endif
-
-       if (ioctl(STDIN_FILENO, TIOCSWINSZ, (char *) &win))
-               perror_on_device("%s");
-}
-
-static void display_window_size(int fancy)
-{
-       const char *fmt_str = "%s\0%s: no size information for this device";
-       struct winsize win;
-
-       if (get_win_size(&win)) {
-               if ((errno != EINVAL) || ((fmt_str += 2), !fancy)) {
-                       perror_on_device(fmt_str);
-               }
-       } else {
-               wrapf(fancy ? "rows %d; columns %d;" : "%d %d\n",
-                               win.ws_row, win.ws_col);
-       }
-}
-
-#else /* !TIOCGWINSZ */
-
-static inline void display_window_size(int fancy) {}
-
-#endif /* !TIOCGWINSZ */
-
-static int screen_columns(void)
-{
-       int columns;
-       const char *s;
-
-#ifdef TIOCGWINSZ
-       struct winsize win;
-
-       /* With Solaris 2.[123], this ioctl fails and errno is set to
-          EINVAL for telnet (but not rlogin) sessions.
-          On ISC 3.0, it fails for the console and the serial port
-          (but it works for ptys).
-          It can also fail on any system when stdout isn't a tty.
-          In case of any failure, just use the default */
-       if (get_win_size(&win) == 0 && win.ws_col > 0)
-               return win.ws_col;
-#endif
-
-       columns = 80;
-       if ((s = getenv("COLUMNS"))) {
-               columns = atoi(s);
-       }
-       return columns;
-}
-
-static tcflag_t *mode_type_flag(unsigned type, const struct termios *mode)
-{
-       static const unsigned char tcflag_offsets[] = {
-               offsetof(struct termios, c_cflag), /* control */
-               offsetof(struct termios, c_iflag), /* input */
-               offsetof(struct termios, c_oflag), /* output */
-               offsetof(struct termios, c_lflag), /* local */
-       };
-
-       if (type <= local) {
-               return (tcflag_t*) (((char*)mode) + tcflag_offsets[type]);
-       }
-       return NULL;
-}
-
 static void display_changed(const struct termios *mode)
 {
        int i;
@@ -1140,8 +1166,7 @@ static void display_changed(const struct termios *mode)
        if (current_col) wrapf("\n");
 }
 
-static void
-display_all(const struct termios *mode)
+static void display_all(const struct termios *mode)
 {
        int i;
        tcflag_t *bitsp;
@@ -1214,7 +1239,6 @@ static void display_speed(const struct termios *mode, int fancy)
 static void display_recoverable(const struct termios *mode)
 {
        int i;
-
        printf("%lx:%lx:%lx:%lx",
                   (unsigned long) mode->c_iflag, (unsigned long) mode->c_oflag,
                   (unsigned long) mode->c_cflag, (unsigned long) mode->c_lflag);
@@ -1253,11 +1277,6 @@ static int recover_mode(const char *arg, struct termios *mode)
        return 1;
 }
 
-static speed_t string_to_baud(const char *arg)
-{
-       return tty_value_to_baud(bb_xparse_number(arg, 0));
-}
-
 static void sane_mode(struct termios *mode)
 {
        int i;
@@ -1283,35 +1302,3 @@ static void sane_mode(struct termios *mode)
                }
        }
 }
-
-/* Return a string that is the printable representation of character CH */
-/* Adapted from `cat' by Torbjorn Granlund */
-
-static const char *visible(unsigned int ch)
-{
-       static char buf[10];
-       char *bpout = buf;
-
-       if (ch == _POSIX_VDISABLE) {
-               return "<undef>";
-       }
-
-       if (ch >= 128) {
-               ch -= 128;
-               *bpout++ = 'M';
-               *bpout++ = '-';
-       }
-
-       if (ch < 32) {
-               *bpout++ = '^';
-               *bpout++ = ch + 64;
-       } else if (ch < 127) {
-               *bpout++ = ch;
-       } else {
-               *bpout++ = '^';
-               *bpout++ = '?';
-       }
-
-       *bpout = '\0';
-       return buf;
-}