- reuse option_mask32 for state-handling in main
- improve check for errors from fcntl
This commit is contained in:
		@@ -1014,24 +1014,19 @@ static void set_control_char_or_die(const struct control_info *info,
 | 
			
		||||
	mode->c_cc[info->offset] = value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define STTY_require_set_attr	(1<<0)
 | 
			
		||||
#define STTY_speed_was_set		(1<<1)
 | 
			
		||||
#define STTY_verbose_output		(1<<2)
 | 
			
		||||
#define STTY_recoverable_output	(1<<3)
 | 
			
		||||
#define STTY_noargs				(1<<4)
 | 
			
		||||
int stty_main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	struct termios mode;
 | 
			
		||||
	void (*output_func)(const struct termios *);
 | 
			
		||||
	const char *file_name = NULL;
 | 
			
		||||
	int require_set_attr;
 | 
			
		||||
	int speed_was_set;
 | 
			
		||||
	int verbose_output;
 | 
			
		||||
	int recoverable_output;
 | 
			
		||||
	int noargs;
 | 
			
		||||
	int k;
 | 
			
		||||
 | 
			
		||||
	option_mask32 = STTY_noargs;
 | 
			
		||||
	output_func = display_changed;
 | 
			
		||||
	noargs = 1;
 | 
			
		||||
	speed_was_set = 0;
 | 
			
		||||
	require_set_attr = 0;
 | 
			
		||||
	verbose_output = 0;
 | 
			
		||||
	recoverable_output = 0;
 | 
			
		||||
 | 
			
		||||
	/* First pass: only parse/verify command line params */
 | 
			
		||||
	k = 0;
 | 
			
		||||
@@ -1047,8 +1042,8 @@ int stty_main(int argc, char **argv)
 | 
			
		||||
			mp = find_mode(arg+1);
 | 
			
		||||
			if (mp) {
 | 
			
		||||
				if (!(mp->flags & REV))
 | 
			
		||||
					bb_error_msg_and_die("invalid argument '%s'", arg);
 | 
			
		||||
				noargs = 0;
 | 
			
		||||
					goto invalid_argument;
 | 
			
		||||
				option_mask32 &= ~STTY_noargs;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			/* It is an option - parse it */
 | 
			
		||||
@@ -1056,11 +1051,11 @@ int stty_main(int argc, char **argv)
 | 
			
		||||
			while (arg[++i]) {
 | 
			
		||||
				switch (arg[i]) {
 | 
			
		||||
				case 'a':
 | 
			
		||||
					verbose_output = 1;
 | 
			
		||||
					option_mask32 |= STTY_verbose_output;
 | 
			
		||||
					output_func = display_all;
 | 
			
		||||
					break;
 | 
			
		||||
				case 'g':
 | 
			
		||||
					recoverable_output = 1;
 | 
			
		||||
					option_mask32 |= STTY_recoverable_output;
 | 
			
		||||
					output_func = display_recoverable;
 | 
			
		||||
					break;
 | 
			
		||||
				case 'F':
 | 
			
		||||
@@ -1078,7 +1073,7 @@ int stty_main(int argc, char **argv)
 | 
			
		||||
					}
 | 
			
		||||
					goto end_option;
 | 
			
		||||
				default:
 | 
			
		||||
					bb_error_msg_and_die("invalid argument '%s'", arg);
 | 
			
		||||
					goto invalid_argument;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
end_option:
 | 
			
		||||
@@ -1087,7 +1082,7 @@ end_option:
 | 
			
		||||
 | 
			
		||||
		mp = find_mode(arg);
 | 
			
		||||
		if (mp) {
 | 
			
		||||
			noargs = 0;
 | 
			
		||||
			option_mask32 &= ~STTY_noargs;
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -1097,7 +1092,7 @@ end_option:
 | 
			
		||||
				bb_error_msg_and_die(bb_msg_requires_arg, arg);
 | 
			
		||||
			/* called for the side effect of xfunc death only */
 | 
			
		||||
			set_control_char_or_die(cp, argnext, &mode);
 | 
			
		||||
			noargs = 0;
 | 
			
		||||
			option_mask32 &= ~STTY_noargs;
 | 
			
		||||
			++k;
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
@@ -1137,16 +1132,19 @@ end_option:
 | 
			
		||||
		default:
 | 
			
		||||
			if (recover_mode(arg, &mode) == 1) break;
 | 
			
		||||
			if (string_to_baud_or_die(arg) != (speed_t) -1) break;
 | 
			
		||||
invalid_argument:
 | 
			
		||||
			bb_error_msg_and_die("invalid argument '%s'", arg);
 | 
			
		||||
		}
 | 
			
		||||
		noargs = 0;
 | 
			
		||||
		option_mask32 &= ~STTY_noargs;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Specifying both -a and -g is an error */
 | 
			
		||||
	if (verbose_output && recoverable_output)
 | 
			
		||||
	if ((option_mask32 & (STTY_verbose_output | STTY_recoverable_output)) ==
 | 
			
		||||
		(STTY_verbose_output | STTY_recoverable_output))
 | 
			
		||||
		bb_error_msg_and_die("verbose and stty-readable output styles are mutually exclusive");
 | 
			
		||||
	/* Specifying -a or -g with non-options is an error */
 | 
			
		||||
	if (!noargs && (verbose_output || recoverable_output))
 | 
			
		||||
	if (!(option_mask32 & STTY_noargs) &&
 | 
			
		||||
		(option_mask32 & (STTY_verbose_output | STTY_recoverable_output)))
 | 
			
		||||
		bb_error_msg_and_die("modes may not be set when specifying an output style");
 | 
			
		||||
 | 
			
		||||
	/* Now it is safe to start doing things */
 | 
			
		||||
@@ -1159,7 +1157,8 @@ end_option:
 | 
			
		||||
			close(fd);
 | 
			
		||||
		}
 | 
			
		||||
		fdflags = fcntl(STDIN_FILENO, F_GETFL);
 | 
			
		||||
		if (fdflags == -1 || fcntl(STDIN_FILENO, F_SETFL, fdflags & ~O_NONBLOCK) < 0)
 | 
			
		||||
		if (fdflags < 0 ||
 | 
			
		||||
			fcntl(STDIN_FILENO, F_SETFL, fdflags & ~O_NONBLOCK) < 0)
 | 
			
		||||
			perror_on_device_and_die("%s: cannot reset non-blocking mode");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -1169,7 +1168,7 @@ end_option:
 | 
			
		||||
	if (tcgetattr(STDIN_FILENO, &mode))
 | 
			
		||||
		perror_on_device_and_die("%s");
 | 
			
		||||
 | 
			
		||||
	if (verbose_output || recoverable_output || noargs) {
 | 
			
		||||
	if (option_mask32 & (STTY_verbose_output | STTY_recoverable_output | STTY_noargs)) {
 | 
			
		||||
		max_col = screen_columns_or_die();
 | 
			
		||||
		output_func(&mode);
 | 
			
		||||
		return EXIT_SUCCESS;
 | 
			
		||||
@@ -1188,7 +1187,7 @@ end_option:
 | 
			
		||||
			mp = find_mode(arg+1);
 | 
			
		||||
			if (mp) {
 | 
			
		||||
				set_mode(mp, 1 /* reversed */, &mode);
 | 
			
		||||
				require_set_attr = 1;
 | 
			
		||||
				option_mask32 |= STTY_require_set_attr;
 | 
			
		||||
			}
 | 
			
		||||
			/* It is an option - already parsed. Skip it */
 | 
			
		||||
			continue;
 | 
			
		||||
@@ -1197,7 +1196,7 @@ end_option:
 | 
			
		||||
		mp = find_mode(arg);
 | 
			
		||||
		if (mp) {
 | 
			
		||||
			set_mode(mp, 0 /* non-reversed */, &mode);
 | 
			
		||||
			require_set_attr = 1;
 | 
			
		||||
			option_mask32 |= STTY_require_set_attr;
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -1205,7 +1204,7 @@ end_option:
 | 
			
		||||
		if (cp) {
 | 
			
		||||
			++k;
 | 
			
		||||
			set_control_char_or_die(cp, argnext, &mode);
 | 
			
		||||
			require_set_attr = 1;
 | 
			
		||||
			option_mask32 |= STTY_require_set_attr;
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -1218,7 +1217,7 @@ end_option:
 | 
			
		||||
#ifdef HAVE_C_LINE
 | 
			
		||||
		case param_line:
 | 
			
		||||
			mode.c_line = xatoul_sfx(argnext, stty_suffixes);
 | 
			
		||||
			require_set_attr = 1;
 | 
			
		||||
			option_mask32 |= STTY_require_set_attr;
 | 
			
		||||
			break;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef TIOCGWINSZ
 | 
			
		||||
@@ -1237,27 +1236,24 @@ end_option:
 | 
			
		||||
			break;
 | 
			
		||||
		case param_ispeed:
 | 
			
		||||
			set_speed_or_die(input_speed, argnext, &mode);
 | 
			
		||||
			speed_was_set = 1;
 | 
			
		||||
			require_set_attr = 1;
 | 
			
		||||
			option_mask32 |= (STTY_require_set_attr | STTY_speed_was_set);
 | 
			
		||||
			break;
 | 
			
		||||
		case param_ospeed:
 | 
			
		||||
			set_speed_or_die(output_speed, argnext, &mode);
 | 
			
		||||
			speed_was_set = 1;
 | 
			
		||||
			require_set_attr = 1;
 | 
			
		||||
			option_mask32 |= (STTY_require_set_attr | STTY_speed_was_set);
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			if (recover_mode(arg, &mode) == 1)
 | 
			
		||||
				require_set_attr = 1;
 | 
			
		||||
				option_mask32 |= STTY_require_set_attr;
 | 
			
		||||
			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;
 | 
			
		||||
				option_mask32 |= (STTY_require_set_attr | STTY_speed_was_set);
 | 
			
		||||
			} /* else - impossible (caught in the first pass):
 | 
			
		||||
				bb_error_msg_and_die("invalid argument '%s'", arg); */
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (require_set_attr) {
 | 
			
		||||
	if (option_mask32 & STTY_require_set_attr) {
 | 
			
		||||
		struct termios new_mode;
 | 
			
		||||
 | 
			
		||||
		if (tcsetattr(STDIN_FILENO, TCSADRAIN, &mode))
 | 
			
		||||
@@ -1288,7 +1284,8 @@ end_option:
 | 
			
		||||
			   error for a true failure to set the baud rate */
 | 
			
		||||
 | 
			
		||||
			new_mode.c_cflag &= (~CIBAUD);
 | 
			
		||||
			if (speed_was_set || memcmp(&mode, &new_mode, sizeof(mode)) != 0)
 | 
			
		||||
			if (option_mask32 & STTY_speed_was_set ||
 | 
			
		||||
				memcmp(&mode, &new_mode, sizeof(mode)) != 0)
 | 
			
		||||
#endif
 | 
			
		||||
				perror_on_device_and_die("%s: cannot perform all requested operations");
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user