stty: fix a longstanding FIXME (was able to die half-way setting term params)
This commit is contained in:
parent
85f9e32f7f
commit
7eab79acc5
412
coreutils/stty.c
412
coreutils/stty.c
@ -173,7 +173,7 @@ struct mode_info {
|
|||||||
|
|
||||||
#define MI_ENTRY(N,T,F,B,M) { N, T, F, M, B }
|
#define MI_ENTRY(N,T,F,B,M) { N, T, F, M, B }
|
||||||
|
|
||||||
static const struct mode_info mode_info[] = {
|
static const struct mode_info mode_info[] = {
|
||||||
MI_ENTRY("parenb", control, REV, PARENB, 0 ),
|
MI_ENTRY("parenb", control, REV, PARENB, 0 ),
|
||||||
MI_ENTRY("parodd", control, REV, PARODD, 0 ),
|
MI_ENTRY("parodd", control, REV, PARODD, 0 ),
|
||||||
MI_ENTRY("cs5", control, 0, CS5, CSIZE),
|
MI_ENTRY("cs5", control, 0, CS5, CSIZE),
|
||||||
@ -333,7 +333,7 @@ struct control_info {
|
|||||||
|
|
||||||
/* Control characters. */
|
/* Control characters. */
|
||||||
|
|
||||||
static const struct control_info control_info[] = {
|
static const struct control_info control_info[] = {
|
||||||
{"intr", CINTR, VINTR},
|
{"intr", CINTR, VINTR},
|
||||||
{"quit", CQUIT, VQUIT},
|
{"quit", CQUIT, VQUIT},
|
||||||
{"erase", CERASE, VERASE},
|
{"erase", CERASE, VERASE},
|
||||||
@ -380,9 +380,9 @@ enum {
|
|||||||
#define EMT(t) ((enum mode_type)(t))
|
#define EMT(t) ((enum mode_type)(t))
|
||||||
|
|
||||||
static const char * visible(unsigned int ch);
|
static const char * visible(unsigned int ch);
|
||||||
static int recover_mode(char *arg, struct termios *mode);
|
static int recover_mode(const char *arg, struct termios *mode);
|
||||||
static int screen_columns(void);
|
static int screen_columns(void);
|
||||||
static int set_mode(const struct mode_info *info,
|
static void set_mode(const struct mode_info *info,
|
||||||
int reversed, struct termios *mode);
|
int reversed, struct termios *mode);
|
||||||
static speed_t string_to_baud(const char *arg);
|
static speed_t string_to_baud(const char *arg);
|
||||||
static tcflag_t* mode_type_flag(enum mode_type type, struct termios *mode);
|
static tcflag_t* mode_type_flag(enum mode_type type, struct termios *mode);
|
||||||
@ -398,7 +398,7 @@ static void set_speed(enum speed_setting type,
|
|||||||
const char *arg, struct termios *mode);
|
const char *arg, struct termios *mode);
|
||||||
static void set_window_size(int rows, int cols);
|
static void set_window_size(int rows, int cols);
|
||||||
|
|
||||||
static const char *device_name;
|
static const char *device_name = bb_msg_standard_input;
|
||||||
|
|
||||||
static ATTRIBUTE_NORETURN void perror_on_device(const char *fmt)
|
static ATTRIBUTE_NORETURN void perror_on_device(const char *fmt)
|
||||||
{
|
{
|
||||||
@ -445,80 +445,192 @@ static const struct suffix_mult stty_suffixes[] = {
|
|||||||
{NULL, 0 }
|
{NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct mode_info *find_mode(const char *name)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < NUM_mode_info; ++i)
|
||||||
|
if (STREQ(name, mode_info[i].name))
|
||||||
|
return &mode_info[i];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct control_info *find_control(const char *name)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < NUM_control_info; ++i)
|
||||||
|
if (STREQ(name, control_info[i].name))
|
||||||
|
return &control_info[i];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
param_need_arg = 0x80,
|
||||||
|
param_line = 1 | 0x80,
|
||||||
|
param_rows = 2 | 0x80,
|
||||||
|
param_cols = 3 | 0x80,
|
||||||
|
param_size = 4,
|
||||||
|
param_ispeed = 5 | 0x80,
|
||||||
|
param_ospeed = 6 | 0x80,
|
||||||
|
param_speed = 7,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int find_param(const char *name)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_C_LINE
|
||||||
|
if (STREQ(name, "line")) return param_line;
|
||||||
|
#endif
|
||||||
|
#ifdef TIOCGWINSZ
|
||||||
|
if (STREQ(name, "rows")) return param_rows;
|
||||||
|
if (STREQ(name, "cols")) return param_cols;
|
||||||
|
if (STREQ(name, "columns")) return param_cols;
|
||||||
|
if (STREQ(name, "size")) return param_size;
|
||||||
|
#endif
|
||||||
|
if (STREQ(name, "ispeed")) return param_ispeed;
|
||||||
|
if (STREQ(name, "ospeed")) return param_ospeed;
|
||||||
|
if (STREQ(name, "speed")) return param_speed;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int stty_main(int argc, char **argv)
|
int stty_main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct termios mode;
|
struct termios mode;
|
||||||
void (*output_func)(struct termios *);
|
void (*output_func)(struct termios *);
|
||||||
int optc;
|
const char *file_name = NULL;
|
||||||
int require_set_attr;
|
int require_set_attr;
|
||||||
int speed_was_set;
|
int speed_was_set;
|
||||||
int verbose_output;
|
int verbose_output;
|
||||||
int recoverable_output;
|
int recoverable_output;
|
||||||
int k;
|
int noargs;
|
||||||
int noargs = 1;
|
int k;
|
||||||
char * file_name = NULL;
|
|
||||||
|
|
||||||
output_func = display_changed;
|
output_func = display_changed;
|
||||||
|
noargs = 1;
|
||||||
|
speed_was_set = 0;
|
||||||
|
require_set_attr = 0;
|
||||||
verbose_output = 0;
|
verbose_output = 0;
|
||||||
recoverable_output = 0;
|
recoverable_output = 0;
|
||||||
|
|
||||||
/* Don't print error messages for unrecognized options. */
|
/* First pass: only parse/verify command line params */
|
||||||
opterr = 0;
|
k = 0;
|
||||||
|
while (argv[++k]) {
|
||||||
|
const struct mode_info *mp;
|
||||||
|
const struct control_info *cp;
|
||||||
|
const char *arg = argv[k];
|
||||||
|
const char *argnext = argv[k+1];
|
||||||
|
int param;
|
||||||
|
|
||||||
while ((optc = getopt(argc, argv, "agF:")) != -1) {
|
if (arg[0] == '-') {
|
||||||
switch (optc) {
|
int i;
|
||||||
case 'a':
|
mp = find_mode(arg+1);
|
||||||
verbose_output = 1;
|
if (mp) {
|
||||||
output_func = display_all;
|
if (!(mp->flags & REV))
|
||||||
break;
|
bb_error_msg_and_die("invalid argument '%s'", arg);
|
||||||
|
noargs = 0;
|
||||||
case 'g':
|
continue;
|
||||||
recoverable_output = 1;
|
}
|
||||||
output_func = display_recoverable;
|
/* It is an option - parse it */
|
||||||
break;
|
i = 0;
|
||||||
|
while (arg[++i]) {
|
||||||
case 'F':
|
switch (arg[i]) {
|
||||||
if (file_name)
|
case 'a':
|
||||||
bb_error_msg_and_die("only one device may be specified");
|
verbose_output = 1;
|
||||||
file_name = optarg;
|
output_func = display_all;
|
||||||
break;
|
break;
|
||||||
|
case 'g':
|
||||||
default: /* unrecognized option */
|
recoverable_output = 1;
|
||||||
noargs = 0;
|
output_func = display_recoverable;
|
||||||
break;
|
break;
|
||||||
|
case 'F':
|
||||||
|
if (file_name)
|
||||||
|
bb_error_msg_and_die("only one device may be specified");
|
||||||
|
file_name = &arg[i+1]; /* "-Fdevice" ? */
|
||||||
|
if (!file_name[0]) { /* nope, "-F device" */
|
||||||
|
int p = k+1; /* argv[p] is argnext */
|
||||||
|
file_name = argnext;
|
||||||
|
if (!file_name)
|
||||||
|
bb_error_msg_and_die(bb_msg_requires_arg, "-F");
|
||||||
|
/* remove -F param from arg[vc] */
|
||||||
|
--argc;
|
||||||
|
while (argv[p+1]) { argv[p] = argv[p+1]; ++p; }
|
||||||
|
}
|
||||||
|
goto end_option;
|
||||||
|
default:
|
||||||
|
bb_error_msg_and_die("invalid argument '%s'", arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end_option:
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (noargs == 0)
|
mp = find_mode(arg);
|
||||||
|
if (mp) {
|
||||||
|
noargs = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
cp = find_control(arg);
|
||||||
|
if (cp) {
|
||||||
|
if (!argnext)
|
||||||
|
bb_error_msg_and_die(bb_msg_requires_arg, arg);
|
||||||
|
noargs = 0;
|
||||||
|
++k;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
param = find_param(arg);
|
||||||
|
if (param & param_need_arg) {
|
||||||
|
if (!argnext)
|
||||||
|
bb_error_msg_and_die(bb_msg_requires_arg, arg);
|
||||||
|
++k;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (param) {
|
||||||
|
#ifdef HAVE_C_LINE
|
||||||
|
case param_line:
|
||||||
|
bb_xparse_number(argnext, stty_suffixes);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef TIOCGWINSZ
|
||||||
|
case param_rows:
|
||||||
|
bb_xparse_number(argnext, stty_suffixes);
|
||||||
|
break;
|
||||||
|
case param_cols:
|
||||||
|
bb_xparse_number(argnext, stty_suffixes);
|
||||||
|
break;
|
||||||
|
case param_size:
|
||||||
|
#endif
|
||||||
|
case param_ispeed:
|
||||||
|
case param_ospeed:
|
||||||
|
case param_speed:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (recover_mode(arg, &mode) == 1) break;
|
||||||
|
if (string_to_baud(arg) != (speed_t) -1) break;
|
||||||
|
bb_error_msg_and_die("invalid argument '%s'", arg);
|
||||||
|
}
|
||||||
|
noargs = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (optind < argc)
|
/* Specifying both -a and -g is an error */
|
||||||
noargs = 0;
|
if (verbose_output && recoverable_output)
|
||||||
|
bb_error_msg_and_die("verbose and stty-readable output styles are mutually exclusive");
|
||||||
/* Specifying both -a and -g gets an error. */
|
/* Specifying -a or -g with non-options is an error */
|
||||||
if (verbose_output & recoverable_output)
|
if (!noargs && (verbose_output || recoverable_output))
|
||||||
bb_error_msg_and_die ("verbose and stty-readable output styles are mutually exclusive");
|
bb_error_msg_and_die("modes may not be set when specifying an output style");
|
||||||
|
|
||||||
/* Specifying any other arguments with -a or -g gets an error. */
|
|
||||||
if (~noargs & (verbose_output | recoverable_output))
|
|
||||||
bb_error_msg_and_die ("modes may not be set when specifying an output style");
|
|
||||||
|
|
||||||
/* FIXME: it'd be better not to open the file until we've verified
|
|
||||||
that all arguments are valid. Otherwise, we could end up doing
|
|
||||||
only some of the requested operations and then failing, probably
|
|
||||||
leaving things in an undesirable state. */
|
|
||||||
|
|
||||||
|
/* Now it is safe to start doing things */
|
||||||
if (file_name) {
|
if (file_name) {
|
||||||
int fdflags;
|
int fd, fdflags;
|
||||||
|
|
||||||
device_name = file_name;
|
device_name = file_name;
|
||||||
fclose(stdin);
|
fd = xopen(device_name, O_RDONLY | O_NONBLOCK);
|
||||||
xopen(device_name, O_RDONLY | O_NONBLOCK);
|
if (fd != 0) {
|
||||||
|
dup2(fd, 0);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
fdflags = fcntl(STDIN_FILENO, F_GETFL);
|
fdflags = fcntl(STDIN_FILENO, F_GETFL);
|
||||||
if (fdflags == -1 || fcntl(STDIN_FILENO, F_SETFL, fdflags & ~O_NONBLOCK) < 0)
|
if (fdflags == -1 || fcntl(STDIN_FILENO, F_SETFL, fdflags & ~O_NONBLOCK) < 0)
|
||||||
perror_on_device("%s: couldn't reset non-blocking mode");
|
perror_on_device("%s: couldn't reset non-blocking mode");
|
||||||
} else {
|
|
||||||
device_name = bb_msg_standard_input;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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
|
||||||
@ -527,122 +639,92 @@ int stty_main(int argc, char **argv)
|
|||||||
if (tcgetattr(STDIN_FILENO, &mode))
|
if (tcgetattr(STDIN_FILENO, &mode))
|
||||||
perror_on_device("%s");
|
perror_on_device("%s");
|
||||||
|
|
||||||
if (verbose_output | recoverable_output | noargs) {
|
if (verbose_output || recoverable_output || noargs) {
|
||||||
max_col = screen_columns();
|
max_col = screen_columns();
|
||||||
current_col = 0;
|
current_col = 0;
|
||||||
output_func(&mode);
|
output_func(&mode);
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
speed_was_set = 0;
|
/* Second pass: perform actions */
|
||||||
require_set_attr = 0;
|
|
||||||
k = 0;
|
k = 0;
|
||||||
while (++k < argc) {
|
while (argv[++k]) {
|
||||||
int match_found = 0;
|
const struct mode_info *mp;
|
||||||
int reversed = 0;
|
const struct control_info *cp;
|
||||||
int i;
|
const char *arg = argv[k];
|
||||||
|
const char *argnext = argv[k+1];
|
||||||
|
int param;
|
||||||
|
|
||||||
if (argv[k][0] == '-') {
|
if (arg[0] == '-') {
|
||||||
char *find_dev_opt;
|
mp = find_mode(arg+1);
|
||||||
|
if (mp) {
|
||||||
++argv[k];
|
set_mode(mp, 1 /* reversed */, &mode);
|
||||||
|
|
||||||
/* Handle "-a", "-ag", "-aF/dev/foo", "-aF /dev/foo", etc.
|
|
||||||
Find the options that have been parsed. This is really
|
|
||||||
gross, but it's needed because stty SETTINGS look like options to
|
|
||||||
getopt(), so we need to work around things in a really horrible
|
|
||||||
way. If any new options are ever added to stty, the short option
|
|
||||||
MUST NOT be a letter which is the first letter of one of the
|
|
||||||
possible stty settings.
|
|
||||||
*/
|
|
||||||
find_dev_opt = strchr(argv[k], 'F'); /* find -*F* */
|
|
||||||
if(find_dev_opt) {
|
|
||||||
if(find_dev_opt[1]==0) /* -*F /dev/foo */
|
|
||||||
k++; /* skip /dev/foo */
|
|
||||||
continue; /* else -*F/dev/foo - no skip */
|
|
||||||
}
|
}
|
||||||
if(argv[k][0]=='a' || argv[k][0]=='g')
|
/* It is an option - already parsed. Skip it */
|
||||||
continue;
|
continue;
|
||||||
/* Is not options - is reverse params */
|
|
||||||
reversed = 1;
|
|
||||||
}
|
}
|
||||||
for (i = 0; i < NUM_mode_info; ++i)
|
|
||||||
if (STREQ(argv[k], mode_info[i].name)) {
|
|
||||||
match_found = set_mode(&mode_info[i], reversed, &mode);
|
|
||||||
require_set_attr = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (match_found == 0 && reversed)
|
mp = find_mode(arg);
|
||||||
bb_error_msg_and_die("invalid argument `%s'", --argv[k]);
|
if (mp) {
|
||||||
|
set_mode(mp, 0 /* non-reversed */, &mode);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (match_found == 0)
|
cp = find_control(arg);
|
||||||
for (i = 0; i < NUM_control_info; ++i)
|
if (cp) {
|
||||||
if (STREQ(argv[k], control_info[i].name)) {
|
++k;
|
||||||
if (k == argc - 1)
|
set_control_char(cp, argnext, &mode);
|
||||||
bb_error_msg_and_die(bb_msg_requires_arg, argv[k]);
|
continue;
|
||||||
match_found = 1;
|
}
|
||||||
++k;
|
|
||||||
set_control_char(&control_info[i], argv[k], &mode);
|
|
||||||
require_set_attr = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (match_found == 0) {
|
param = find_param(arg);
|
||||||
if (STREQ(argv[k], "ispeed")) {
|
if (param & param_need_arg) {
|
||||||
if (k == argc - 1)
|
++k;
|
||||||
bb_error_msg_and_die(bb_msg_requires_arg, argv[k]);
|
}
|
||||||
++k;
|
|
||||||
set_speed(input_speed, argv[k], &mode);
|
switch (param) {
|
||||||
speed_was_set = 1;
|
|
||||||
require_set_attr = 1;
|
|
||||||
} else if (STREQ(argv[k], "ospeed")) {
|
|
||||||
if (k == argc - 1)
|
|
||||||
bb_error_msg_and_die(bb_msg_requires_arg, argv[k]);
|
|
||||||
++k;
|
|
||||||
set_speed(output_speed, argv[k], &mode);
|
|
||||||
speed_was_set = 1;
|
|
||||||
require_set_attr = 1;
|
|
||||||
}
|
|
||||||
#ifdef TIOCGWINSZ
|
|
||||||
else if (STREQ(argv[k], "rows")) {
|
|
||||||
if (k == argc - 1)
|
|
||||||
bb_error_msg_and_die(bb_msg_requires_arg, argv[k]);
|
|
||||||
++k;
|
|
||||||
set_window_size((int) bb_xparse_number(argv[k], stty_suffixes),
|
|
||||||
-1);
|
|
||||||
} else if (STREQ(argv[k], "cols") || STREQ(argv[k], "columns")) {
|
|
||||||
if (k == argc - 1)
|
|
||||||
bb_error_msg_and_die(bb_msg_requires_arg, argv[k]);
|
|
||||||
++k;
|
|
||||||
set_window_size(-1,
|
|
||||||
(int) bb_xparse_number(argv[k], stty_suffixes));
|
|
||||||
} else if (STREQ(argv[k], "size")) {
|
|
||||||
max_col = screen_columns();
|
|
||||||
current_col = 0;
|
|
||||||
display_window_size(0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_C_LINE
|
#ifdef HAVE_C_LINE
|
||||||
else if (STREQ(argv[k], "line")) {
|
case param_line:
|
||||||
if (k == argc - 1)
|
mode.c_line = bb_xparse_number(argnext, stty_suffixes);
|
||||||
bb_error_msg_and_die(bb_msg_requires_arg, argv[k]);
|
require_set_attr = 1;
|
||||||
++k;
|
break;
|
||||||
mode.c_line = bb_xparse_number(argv[k], stty_suffixes);
|
|
||||||
require_set_attr = 1;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
else if (STREQ(argv[k], "speed")) {
|
#ifdef TIOCGWINSZ
|
||||||
max_col = screen_columns();
|
case param_cols:
|
||||||
display_speed(&mode, 0);
|
set_window_size(-1, (int) bb_xparse_number(argnext, stty_suffixes));
|
||||||
} else if (recover_mode(argv[k], &mode) == 1)
|
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_ispeed:
|
||||||
|
set_speed(input_speed, argnext, &mode);
|
||||||
|
speed_was_set = 1;
|
||||||
|
require_set_attr = 1;
|
||||||
|
break;
|
||||||
|
case param_ospeed:
|
||||||
|
set_speed(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;
|
require_set_attr = 1;
|
||||||
else if (string_to_baud(argv[k]) != (speed_t) - 1) {
|
else /* true: if (string_to_baud(arg) != (speed_t) -1) */ {
|
||||||
set_speed(both_speeds, argv[k], &mode);
|
set_speed(both_speeds, arg, &mode);
|
||||||
speed_was_set = 1;
|
speed_was_set = 1;
|
||||||
require_set_attr = 1;
|
require_set_attr = 1;
|
||||||
} else
|
} /* else - impossible (caught in the first pass):
|
||||||
bb_error_msg_and_die("invalid argument `%s'", argv[k]);
|
bb_error_msg_and_die("invalid argument '%s'", arg); */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -665,13 +747,6 @@ int stty_main(int argc, char **argv)
|
|||||||
if (tcgetattr(STDIN_FILENO, &new_mode))
|
if (tcgetattr(STDIN_FILENO, &new_mode))
|
||||||
perror_on_device("%s");
|
perror_on_device("%s");
|
||||||
|
|
||||||
/* Normally, one shouldn't use memcmp to compare structures that
|
|
||||||
may have `holes' containing uninitialized data, but we have been
|
|
||||||
careful to initialize the storage of these two variables to all
|
|
||||||
zeroes. One might think it more efficient simply to compare the
|
|
||||||
modified fields, but that would require enumerating those fields --
|
|
||||||
and not all systems have the same fields in this structure. */
|
|
||||||
|
|
||||||
if (memcmp(&mode, &new_mode, sizeof(mode)) != 0) {
|
if (memcmp(&mode, &new_mode, sizeof(mode)) != 0) {
|
||||||
#ifdef CIBAUD
|
#ifdef CIBAUD
|
||||||
/* SunOS 4.1.3 (at least) has the problem that after this sequence,
|
/* SunOS 4.1.3 (at least) has the problem that after this sequence,
|
||||||
@ -695,14 +770,11 @@ int stty_main(int argc, char **argv)
|
|||||||
|
|
||||||
/* Return 0 if not applied because not reversible; otherwise return 1. */
|
/* Return 0 if not applied because not reversible; otherwise return 1. */
|
||||||
|
|
||||||
static int
|
static void
|
||||||
set_mode(const struct mode_info *info, int reversed, struct termios *mode)
|
set_mode(const struct mode_info *info, int reversed, struct termios *mode)
|
||||||
{
|
{
|
||||||
tcflag_t *bitsp;
|
tcflag_t *bitsp;
|
||||||
|
|
||||||
if (reversed && (info->flags & REV) == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
bitsp = mode_type_flag(EMT(info->type), mode);
|
bitsp = mode_type_flag(EMT(info->type), mode);
|
||||||
|
|
||||||
if (bitsp == NULL) {
|
if (bitsp == NULL) {
|
||||||
@ -861,8 +933,6 @@ set_mode(const struct mode_info *info, int reversed, struct termios *mode)
|
|||||||
*bitsp = *bitsp & ~((unsigned long)info->mask) & ~info->bits;
|
*bitsp = *bitsp & ~((unsigned long)info->mask) & ~info->bits;
|
||||||
else
|
else
|
||||||
*bitsp = (*bitsp & ~((unsigned long)info->mask)) | info->bits;
|
*bitsp = (*bitsp & ~((unsigned long)info->mask)) | info->bits;
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1179,7 +1249,7 @@ static void display_recoverable(struct termios *mode)
|
|||||||
putchar('\n');
|
putchar('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
static int recover_mode(char *arg, struct termios *mode)
|
static int recover_mode(const char *arg, struct termios *mode)
|
||||||
{
|
{
|
||||||
int i, n;
|
int i, n;
|
||||||
unsigned int chr;
|
unsigned int chr;
|
||||||
@ -1269,5 +1339,5 @@ static const char *visible(unsigned int ch)
|
|||||||
}
|
}
|
||||||
|
|
||||||
*bpout = '\0';
|
*bpout = '\0';
|
||||||
return (const char *) buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user