@@ -203,27 +203,24 @@ 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
- let mut settings_iter = settings. into_iter ( ) ;
206
+ let mut settings_iter = settings. iter ( ) ;
207
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
- }
208
+ if let Some ( char_index) = is_control_char ( setting) {
209
+ let Some ( new_cc) = settings_iter. next ( ) else {
210
+ return Err ( USimpleError :: new (
211
+ 1 ,
212
+ format ! ( "no mapping specified for '{setting}'" ) ,
213
+ ) ) ;
217
214
} ;
218
- if let ControlFlow :: Break ( false ) = apply_char_mapping ( & mut termios, setting, new_cc)
215
+ if let ControlFlow :: Break ( false ) =
216
+ apply_char_mapping ( & mut termios, setting, char_index, new_cc)
219
217
{
220
218
return Err ( USimpleError :: new (
221
219
1 ,
222
220
format ! ( "invalid mapping '{setting}' => '{new_cc}'" ) ,
223
221
) ) ;
224
222
}
225
- }
226
- else if let ControlFlow :: Break ( false ) = apply_setting ( & mut termios, setting) {
223
+ } else if let ControlFlow :: Break ( false ) = apply_setting ( & mut termios, setting) {
227
224
return Err ( USimpleError :: new (
228
225
1 ,
229
226
format ! ( "invalid argument '{setting}'" ) ,
@@ -293,13 +290,13 @@ fn print_terminal_size(termios: &Termios, opts: &Options) -> nix::Result<()> {
293
290
Ok ( ( ) )
294
291
}
295
292
296
- fn is_control_char ( option : & str ) -> bool {
293
+ fn is_control_char ( option : & str ) -> Option < SpecialCharacterIndices > {
297
294
for cc in CONTROL_CHARS {
298
295
if option == cc. 0 {
299
- return true ;
296
+ return Some ( cc . 1 ) ;
300
297
}
301
298
}
302
- false
299
+ None
303
300
}
304
301
305
302
fn control_char_to_string ( cc : nix:: libc:: cc_t ) -> nix:: Result < String > {
@@ -490,9 +487,34 @@ fn apply_baud_rate_flag(termios: &mut Termios, input: &str) -> ControlFlow<bool>
490
487
ControlFlow :: Continue ( ( ) )
491
488
}
492
489
493
- fn apply_char_mapping ( termios : & mut Termios , cc : & str , new_cc : & str ) -> ControlFlow < bool > {
494
- println ! ( "{cc} {new_cc}" ) ;
495
- ControlFlow :: Break ( true )
490
+ fn apply_char_mapping (
491
+ termios : & mut Termios ,
492
+ cc : & str ,
493
+ control_char_index : SpecialCharacterIndices ,
494
+ new_cc : & str ,
495
+ ) -> ControlFlow < bool > {
496
+ if let Some ( val) = string_to_control_char ( new_cc) {
497
+ termios. control_chars [ control_char_index as usize ] = val;
498
+ return ControlFlow :: Break ( true ) ;
499
+ }
500
+ ControlFlow :: Break ( false )
501
+ }
502
+
503
+ // GNU stty defines some valid values for the control character mappings
504
+ // 1. Standard character, can be a a single char (ie 'C') or hat notation (ie '^C')
505
+ // 2. Integer
506
+ // a. hexadecimal, prefixed by '0x'
507
+ // b. octal, prefixed by '0'
508
+ // c. decimal, no prefix
509
+ // 3. Disabling the control character: '^-' or 'undef'
510
+ //
511
+ // This function returns the ascii value of the given char, or None if the input cannot be parsed
512
+ fn string_to_control_char ( s : & str ) -> Option < u8 > {
513
+ // try to parse int, then char
514
+ if s == "undef" || s == "^-" {
515
+ return Some ( 0 ) ;
516
+ }
517
+ None
496
518
}
497
519
498
520
pub fn uu_app ( ) -> Command {
0 commit comments