From 59c318b7fa54e65bd05d33580638466b4f48e778 Mon Sep 17 00:00:00 2001 From: Alexander Shirokov Date: Sun, 4 May 2025 11:15:27 +0200 Subject: [PATCH 1/3] uucore: printf_writer: handle ControlFlow result This commit explicitly handles the result of the `write` function and allows an early stop when a `ControlFlow::Break` is received. It seems that currently only writing `EscapedChar::End` will trigger a break. In all other cases, `ControlFlow::Continue` is returned. --- src/uucore/src/lib/features/format/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/uucore/src/lib/features/format/mod.rs b/src/uucore/src/lib/features/format/mod.rs index 0a887d0754..ee17d96da7 100644 --- a/src/uucore/src/lib/features/format/mod.rs +++ b/src/uucore/src/lib/features/format/mod.rs @@ -283,7 +283,9 @@ fn printf_writer<'a>( let args = args.into_iter().cloned().collect::>(); let mut args = FormatArguments::new(&args); for item in parse_spec_only(format_string.as_ref()) { - item?.write(&mut writer, &mut args)?; + if item?.write(&mut writer, &mut args)?.is_break() { + break; + } } Ok(()) } From 132f9fa751243e839d5adfb3d807b6661a11e9a8 Mon Sep 17 00:00:00 2001 From: Alexander Shirokov Date: Sun, 4 May 2025 12:03:23 +0200 Subject: [PATCH 2/3] echo: execute: handle ControlFlow result This commit analyzes the return value of the `write` function and stops the echo when a break is received. It allows: - simplifying the function's logic. Now, we don't rely on the item type and only analyze the return value. - avoiding compiler warnings about the unused `ControlFlow` result (nightly only). Since a break can only be triggered by `EscapedChar::End`, the old and new versions should be equivalent. --- src/uu/echo/src/echo.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/uu/echo/src/echo.rs b/src/uu/echo/src/echo.rs index a59ba86d6b..184cf960b1 100644 --- a/src/uu/echo/src/echo.rs +++ b/src/uu/echo/src/echo.rs @@ -9,7 +9,7 @@ use std::env; use std::ffi::{OsStr, OsString}; use std::io::{self, StdoutLock, Write}; use uucore::error::{UResult, USimpleError}; -use uucore::format::{EscapedChar, FormatChar, OctalParsing, parse_escape_only}; +use uucore::format::{FormatChar, OctalParsing, parse_escape_only}; use uucore::{format_usage, help_about, help_section, help_usage}; const ABOUT: &str = help_about!("echo.md"); @@ -150,10 +150,9 @@ fn execute( if escaped { for item in parse_escape_only(bytes, OctalParsing::ThreeDigits) { - match item { - EscapedChar::End => return Ok(()), - c => c.write(&mut *stdout_lock)?, - }; + if item.write(&mut *stdout_lock)?.is_break() { + return Ok(()); + } } } else { stdout_lock.write_all(bytes)?; From 9bebde5d173b20178eda250c8a565682e12a91fc Mon Sep 17 00:00:00 2001 From: Alexander Shirokov Date: Sun, 4 May 2025 18:31:08 +0200 Subject: [PATCH 3/3] echo: add test for Ctrl-C sequence --- tests/by-util/test_echo.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/by-util/test_echo.rs b/tests/by-util/test_echo.rs index 60103b620f..5b08c484db 100644 --- a/tests/by-util/test_echo.rs +++ b/tests/by-util/test_echo.rs @@ -657,3 +657,12 @@ fn test_uchild_when_run_no_wait_with_a_non_blocking_util() { // we should be able to call wait without panics and apply some assertions child.wait().unwrap().code_is(0).no_stdout().no_stderr(); } + +#[test] +fn test_escape_sequence_ctrl_c() { + new_ucmd!() + .args(&["-e", "show\\c123"]) + .run() + .success() + .stdout_only("show"); +}