|
8 | 8 | mod flags;
|
9 | 9 |
|
10 | 10 | use clap::{Arg, ArgAction, ArgMatches, Command};
|
11 |
| -use nix::libc::{O_NONBLOCK, TIOCGWINSZ, TIOCSWINSZ, c_ushort}; |
| 11 | +use nix::libc::{c_ushort, O_NONBLOCK, TIOCGWINSZ, TIOCSWINSZ}; |
12 | 12 | use nix::sys::termios::{
|
13 |
| - ControlFlags, InputFlags, LocalFlags, OutputFlags, SpecialCharacterIndices, Termios, |
14 |
| - cfgetospeed, cfsetospeed, tcgetattr, tcsetattr, |
| 13 | + cfgetospeed, cfsetospeed, tcgetattr, tcsetattr, ControlFlags, InputFlags, LocalFlags, |
| 14 | + OutputFlags, SpecialCharacterIndices, Termios, |
15 | 15 | };
|
16 | 16 | use nix::{ioctl_read_bad, ioctl_write_ptr_bad};
|
17 | 17 | use std::fs::File;
|
18 |
| -use std::io::{self, Stdout, stdout}; |
| 18 | +use std::io::{self, stdout, Stdout}; |
19 | 19 | use std::ops::ControlFlow;
|
20 | 20 | use std::os::fd::{AsFd, BorrowedFd};
|
21 | 21 | use std::os::unix::fs::OpenOptionsExt;
|
@@ -203,8 +203,27 @@ fn stty(opts: &Options) -> UResult<()> {
|
203 | 203 | let mut termios = tcgetattr(opts.file.as_fd()).expect("Could not get terminal attributes");
|
204 | 204 |
|
205 | 205 | if let Some(settings) = &opts.settings {
|
206 |
| - for setting in settings { |
207 |
| - if let ControlFlow::Break(false) = apply_setting(&mut termios, setting) { |
| 206 | + let mut settings_iter = settings.into_iter(); |
| 207 | + while let Some(setting) = settings_iter.next() { |
| 208 | + if is_control_char(setting) { |
| 209 | + let new_cc = match settings_iter.next() { |
| 210 | + Some(cc) => cc, |
| 211 | + None => { |
| 212 | + return Err(USimpleError::new( |
| 213 | + 1, |
| 214 | + format!("no mapping specified for '{setting}'"), |
| 215 | + )); |
| 216 | + } |
| 217 | + }; |
| 218 | + if let ControlFlow::Break(false) = apply_char_mapping(&mut termios, setting, new_cc) |
| 219 | + { |
| 220 | + return Err(USimpleError::new( |
| 221 | + 1, |
| 222 | + format!("invalid mapping '{setting}' => '{new_cc}'"), |
| 223 | + )); |
| 224 | + } |
| 225 | + } |
| 226 | + else if let ControlFlow::Break(false) = apply_setting(&mut termios, setting) { |
208 | 227 | return Err(USimpleError::new(
|
209 | 228 | 1,
|
210 | 229 | format!("invalid argument '{setting}'"),
|
@@ -274,6 +293,15 @@ fn print_terminal_size(termios: &Termios, opts: &Options) -> nix::Result<()> {
|
274 | 293 | Ok(())
|
275 | 294 | }
|
276 | 295 |
|
| 296 | +fn is_control_char(option: &str) -> bool { |
| 297 | + for cc in CONTROL_CHARS { |
| 298 | + if option == cc.0 { |
| 299 | + return true; |
| 300 | + } |
| 301 | + } |
| 302 | + false |
| 303 | +} |
| 304 | + |
277 | 305 | fn control_char_to_string(cc: nix::libc::cc_t) -> nix::Result<String> {
|
278 | 306 | if cc == 0 {
|
279 | 307 | return Ok("<undef>".to_string());
|
@@ -462,6 +490,11 @@ fn apply_baud_rate_flag(termios: &mut Termios, input: &str) -> ControlFlow<bool>
|
462 | 490 | ControlFlow::Continue(())
|
463 | 491 | }
|
464 | 492 |
|
| 493 | +fn apply_char_mapping(termios: &mut Termios, cc: &str, new_cc: &str) -> ControlFlow<bool> { |
| 494 | + println!("{cc} {new_cc}"); |
| 495 | + ControlFlow::Break(true) |
| 496 | +} |
| 497 | + |
465 | 498 | pub fn uu_app() -> Command {
|
466 | 499 | Command::new(uucore::util_name())
|
467 | 500 | .version(uucore::crate_version!())
|
|
0 commit comments