619 |
|
|
620 |
|
|
621 |
struct globals { |
struct globals { |
622 |
const char *device_name; // = bb_msg_standard_input; |
const char *device_name; |
623 |
/* The width of the screen, for output wrapping */ |
/* The width of the screen, for output wrapping */ |
624 |
unsigned max_col; // = 80; |
unsigned max_col; |
625 |
/* Current position, to know when to wrap */ |
/* Current position, to know when to wrap */ |
626 |
unsigned current_col; |
unsigned current_col; |
627 |
char buf[10]; |
char buf[10]; |
677 |
return NULL; |
return NULL; |
678 |
} |
} |
679 |
|
|
680 |
static void set_speed_or_die(enum speed_setting type, const char *const arg, |
static void set_speed_or_die(enum speed_setting type, const char *arg, |
681 |
struct termios * const mode) |
struct termios *mode) |
682 |
{ |
{ |
683 |
speed_t baud; |
speed_t baud; |
684 |
|
|
734 |
G.current_col = 0; |
G.current_col = 0; |
735 |
} |
} |
736 |
|
|
737 |
static void set_window_size(const int rows, const int cols) |
static void newline(void) |
738 |
|
{ |
739 |
|
if (G.current_col != 0) |
740 |
|
wrapf("\n"); |
741 |
|
} |
742 |
|
|
743 |
|
static void set_window_size(int rows, int cols) |
744 |
{ |
{ |
745 |
struct winsize win = { 0, 0, 0, 0 }; |
struct winsize win = { 0, 0, 0, 0 }; |
746 |
|
|
761 |
perror_on_device("%s"); |
perror_on_device("%s"); |
762 |
} |
} |
763 |
|
|
764 |
static void display_window_size(const int fancy) |
static void display_window_size(int fancy) |
765 |
{ |
{ |
766 |
const char *fmt_str = "%s\0%s: no size information for this device"; |
const char *fmt_str = "%s\0%s: no size information for this device"; |
767 |
unsigned width, height; |
unsigned width, height; |
771 |
perror_on_device(fmt_str); |
perror_on_device(fmt_str); |
772 |
} |
} |
773 |
} else { |
} else { |
774 |
wrapf(fancy ? "rows %d; columns %d;" : "%d %d\n", |
wrapf(fancy ? "rows %u; columns %u;" : "%u %u\n", |
775 |
height, width); |
height, width); |
776 |
} |
} |
777 |
} |
} |
780 |
{ "b", 512 }, |
{ "b", 512 }, |
781 |
{ "k", 1024 }, |
{ "k", 1024 }, |
782 |
{ "B", 1024 }, |
{ "B", 1024 }, |
783 |
{ } |
{ "", 0 } |
784 |
}; |
}; |
785 |
|
|
786 |
static const struct mode_info *find_mode(const char *name) |
static const struct mode_info *find_mode(const char *name) |
807 |
param_ospeed = 8 | 0x80, |
param_ospeed = 8 | 0x80, |
808 |
}; |
}; |
809 |
|
|
810 |
static int find_param(const char *const name) |
static int find_param(const char *name) |
811 |
{ |
{ |
812 |
static const char params[] ALIGN1 = |
static const char params[] ALIGN1 = |
813 |
"line\0" /* 1 */ |
"line\0" /* 1 */ |
870 |
|
|
871 |
static void display_speed(const struct termios *mode, int fancy) |
static void display_speed(const struct termios *mode, int fancy) |
872 |
{ |
{ |
873 |
//01234567 8 9 |
//____________________ 01234567 8 9 |
874 |
const char *fmt_str = "%lu %lu\n\0ispeed %lu baud; ospeed %lu baud;"; |
const char *fmt_str = "%lu %lu\n\0ispeed %lu baud; ospeed %lu baud;"; |
875 |
unsigned long ispeed, ospeed; |
unsigned long ispeed, ospeed; |
876 |
|
|
877 |
ospeed = ispeed = cfgetispeed(mode); |
ospeed = ispeed = cfgetispeed(mode); |
878 |
if (ispeed == 0 || ispeed == (ospeed = cfgetospeed(mode))) { |
if (ispeed == 0 || ispeed == (ospeed = cfgetospeed(mode))) { |
879 |
ispeed = ospeed; /* in case ispeed was 0 */ |
ispeed = ospeed; /* in case ispeed was 0 */ |
880 |
//0123 4 5 6 7 8 9 |
//________ 0123 4 5 6 7 8 9 |
881 |
fmt_str = "%lu\n\0\0\0\0\0speed %lu baud;"; |
fmt_str = "%lu\n\0\0\0\0\0speed %lu baud;"; |
882 |
} |
} |
883 |
if (fancy) fmt_str += 9; |
if (fancy) fmt_str += 9; |
884 |
wrapf(fmt_str, tty_baud_to_value(ispeed), tty_baud_to_value(ospeed)); |
wrapf(fmt_str, tty_baud_to_value(ispeed), tty_baud_to_value(ospeed)); |
885 |
} |
} |
886 |
|
|
887 |
static void do_display(const struct termios *mode, const int all) |
static void do_display(const struct termios *mode, int all) |
888 |
{ |
{ |
889 |
int i; |
int i; |
890 |
tcflag_t *bitsp; |
tcflag_t *bitsp; |
895 |
if (all) |
if (all) |
896 |
display_window_size(1); |
display_window_size(1); |
897 |
#ifdef HAVE_C_LINE |
#ifdef HAVE_C_LINE |
898 |
wrapf("line = %d;\n", mode->c_line); |
wrapf("line = %u;\n", mode->c_line); |
899 |
#else |
#else |
900 |
wrapf("\n"); |
newline(); |
901 |
#endif |
#endif |
902 |
|
|
903 |
for (i = 0; i != CIDX_min; ++i) { |
for (i = 0; i != CIDX_min; ++i) { |
908 |
#endif |
#endif |
909 |
/* If eof uses the same slot as min, only print whichever applies */ |
/* If eof uses the same slot as min, only print whichever applies */ |
910 |
#if VEOF == VMIN |
#if VEOF == VMIN |
911 |
if ((mode->c_lflag & ICANON) == 0 |
if (!(mode->c_lflag & ICANON) |
912 |
&& (i == CIDX_eof || i == CIDX_eol) |
&& (i == CIDX_eof || i == CIDX_eol) |
913 |
) { |
) { |
914 |
continue; |
continue; |
920 |
#if VEOF == VMIN |
#if VEOF == VMIN |
921 |
if ((mode->c_lflag & ICANON) == 0) |
if ((mode->c_lflag & ICANON) == 0) |
922 |
#endif |
#endif |
923 |
wrapf("min = %d; time = %d;", mode->c_cc[VMIN], mode->c_cc[VTIME]); |
wrapf("min = %u; time = %u;", mode->c_cc[VMIN], mode->c_cc[VTIME]); |
924 |
if (G.current_col) wrapf("\n"); |
newline(); |
925 |
|
|
926 |
for (i = 0; i < NUM_mode_info; ++i) { |
for (i = 0; i < NUM_mode_info; ++i) { |
927 |
if (mode_info[i].flags & OMIT) |
if (mode_info[i].flags & OMIT) |
928 |
continue; |
continue; |
929 |
if (mode_info[i].type != prev_type) { |
if (mode_info[i].type != prev_type) { |
930 |
/* wrapf("\n"); */ |
newline(); |
|
if (G.current_col) wrapf("\n"); |
|
931 |
prev_type = mode_info[i].type; |
prev_type = mode_info[i].type; |
932 |
} |
} |
933 |
|
|
944 |
} |
} |
945 |
} |
} |
946 |
} |
} |
947 |
if (G.current_col) wrapf("\n"); |
newline(); |
948 |
} |
} |
949 |
|
|
950 |
static void sane_mode(struct termios *mode) |
static void sane_mode(struct termios *mode) |
1143 |
value = xatoul_range_sfx(arg, 0, 0xff, stty_suffixes); |
value = xatoul_range_sfx(arg, 0, 0xff, stty_suffixes); |
1144 |
else if (arg[0] == '\0' || arg[1] == '\0') |
else if (arg[0] == '\0' || arg[1] == '\0') |
1145 |
value = arg[0]; |
value = arg[0]; |
1146 |
else if (!strcmp(arg, "^-") || !strcmp(arg, "undef")) |
else if (strcmp(arg, "^-") == 0 || strcmp(arg, "undef") == 0) |
1147 |
value = _POSIX_VDISABLE; |
value = _POSIX_VDISABLE; |
1148 |
else if (arg[0] == '^') { /* Ignore any trailing junk (^Cjunk) */ |
else if (arg[0] == '^') { /* Ignore any trailing junk (^Cjunk) */ |
1149 |
value = arg[1] & 0x1f; /* Non-letters get weird results */ |
value = arg[1] & 0x1f; /* Non-letters get weird results */ |
1161 |
#define STTY_noargs (1 << 4) |
#define STTY_noargs (1 << 4) |
1162 |
|
|
1163 |
int stty_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
int stty_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
1164 |
int stty_main(int argc, char **argv) |
int stty_main(int argc UNUSED_PARAM, char **argv) |
1165 |
{ |
{ |
1166 |
struct termios mode; |
struct termios mode; |
1167 |
void (*output_func)(const struct termios *, const int); |
void (*output_func)(const struct termios *, int); |
1168 |
const char *file_name = NULL; |
const char *file_name = NULL; |
1169 |
int display_all = 0; |
int display_all = 0; |
1170 |
int stty_state; |
int stty_state; |
1216 |
if (!file_name) |
if (!file_name) |
1217 |
bb_error_msg_and_die(bb_msg_requires_arg, "-F"); |
bb_error_msg_and_die(bb_msg_requires_arg, "-F"); |
1218 |
/* remove -F param from arg[vc] */ |
/* remove -F param from arg[vc] */ |
1219 |
--argc; |
while (argv[p]) { |
1220 |
while (argv[p]) { argv[p] = argv[p+1]; ++p; } |
argv[p] = argv[p+1]; |
1221 |
|
++p; |
1222 |
|
} |
1223 |
} |
} |
1224 |
goto end_option; |
goto end_option; |
1225 |
default: |
default: |
1294 |
(STTY_verbose_output | STTY_recoverable_output)) |
(STTY_verbose_output | STTY_recoverable_output)) |
1295 |
bb_error_msg_and_die("verbose and stty-readable output styles are mutually exclusive"); |
bb_error_msg_and_die("verbose and stty-readable output styles are mutually exclusive"); |
1296 |
/* Specifying -a or -g with non-options is an error */ |
/* Specifying -a or -g with non-options is an error */ |
1297 |
if (!(stty_state & STTY_noargs) && |
if (!(stty_state & STTY_noargs) |
1298 |
(stty_state & (STTY_verbose_output | STTY_recoverable_output))) |
&& (stty_state & (STTY_verbose_output | STTY_recoverable_output)) |
1299 |
|
) { |
1300 |
bb_error_msg_and_die("modes may not be set when specifying an output style"); |
bb_error_msg_and_die("modes may not be set when specifying an output style"); |
1301 |
|
} |
1302 |
|
|
1303 |
/* Now it is safe to start doing things */ |
/* Now it is safe to start doing things */ |
1304 |
if (file_name) { |
if (file_name) { |
|
int fd, fdflags; |
|
1305 |
G.device_name = file_name; |
G.device_name = file_name; |
1306 |
fd = xopen(G.device_name, O_RDONLY | O_NONBLOCK); |
xmove_fd(xopen_nonblocking(G.device_name), STDIN_FILENO); |
1307 |
if (fd != STDIN_FILENO) { |
ndelay_off(STDIN_FILENO); |
|
dup2(fd, STDIN_FILENO); |
|
|
close(fd); |
|
|
} |
|
|
fdflags = fcntl(STDIN_FILENO, F_GETFL); |
|
|
if (fdflags < 0 || |
|
|
fcntl(STDIN_FILENO, F_SETFL, fdflags & ~O_NONBLOCK) < 0) |
|
|
perror_on_device_and_die("%s: cannot reset non-blocking mode"); |
|
1308 |
} |
} |
1309 |
|
|
1310 |
/* Initialize to all zeroes so there is no risk memcmp will report a |
/* Initialize to all zeroes so there is no risk memcmp will report a |
1367 |
#endif |
#endif |
1368 |
#ifdef TIOCGWINSZ |
#ifdef TIOCGWINSZ |
1369 |
case param_cols: |
case param_cols: |
1370 |
|
case param_columns: |
1371 |
set_window_size(-1, xatoul_sfx(argnext, stty_suffixes)); |
set_window_size(-1, xatoul_sfx(argnext, stty_suffixes)); |
1372 |
break; |
break; |
1373 |
case param_size: |
case param_size: |