From 8f2b94495648c1d9a80950e884253fefb36908c4 Mon Sep 17 00:00:00 2001 From: Frode Nordahl Date: Fri, 9 May 2025 15:41:56 +0000 Subject: [PATCH] coreutils: Print usage to stderr. Scripts exist that may call one of the multi-binary entry points with argument 0 set to some other value than the name of the entry point. One example is the Open vSwitch testsuite which makes use of /bin/true as an argument to the bash builtin `exec` to check whether it supports the '-a' argument [0]. In this situation coreutils will print usage on standard output, which makes unnecessary noise. Printing usage on standard error, which is customary for other tools, allows the script to succeed. 0: https://github.com/openvswitch/ovs/blob/28064e9fa50d/tests/ovs-macros.at#L199 Signed-off-by: Frode Nordahl --- src/bin/coreutils.rs | 14 +++++++------- tests/test_util_name.rs | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/bin/coreutils.rs b/src/bin/coreutils.rs index b29e7ea2337..4a771a1738b 100644 --- a/src/bin/coreutils.rs +++ b/src/bin/coreutils.rs @@ -20,18 +20,18 @@ const VERSION: &str = env!("CARGO_PKG_VERSION"); include!(concat!(env!("OUT_DIR"), "/uutils_map.rs")); fn usage(utils: &UtilityMap, name: &str) { - println!("{name} {VERSION} (multi-call binary)\n"); - println!("Usage: {name} [function [arguments...]]"); - println!(" {name} --list\n"); - println!("Options:"); - println!(" --list lists all defined functions, one per row\n"); - println!("Currently defined functions:\n"); + eprintln!("{name} {VERSION} (multi-call binary)\n"); + eprintln!("Usage: {name} [function [arguments...]]"); + eprintln!(" {name} --list\n"); + eprintln!("Options:"); + eprintln!(" --list lists all defined functions, one per row\n"); + eprintln!("Currently defined functions:\n"); #[allow(clippy::map_clone)] let mut utils: Vec<&str> = utils.keys().map(|&s| s).collect(); utils.sort_unstable(); let display_list = utils.join(", "); let width = cmp::min(textwrap::termwidth(), 100) - 4 * 2; // (opinion/heuristic) max 100 chars wide with 4 character side indentions - println!( + eprintln!( "{}", textwrap::indent(&textwrap::fill(&display_list, width), " ") ); diff --git a/tests/test_util_name.rs b/tests/test_util_name.rs index 7a8a076e893..79d000443fc 100644 --- a/tests/test_util_name.rs +++ b/tests/test_util_name.rs @@ -120,8 +120,8 @@ fn util_invalid_name_help() { .unwrap(); let output = child.wait_with_output().unwrap(); assert_eq!(output.status.code(), Some(0)); - assert_eq!(output.stderr, b""); - let output_str = String::from_utf8(output.stdout).unwrap(); + assert_eq!(output.stdout, b""); + let output_str = String::from_utf8(output.stderr).unwrap(); assert!(output_str.contains("(multi-call binary)"), "{output_str:?}"); assert!( output_str.contains("Usage: invalid_name [function "), @@ -159,8 +159,8 @@ fn util_non_utf8_name_help() { .unwrap(); let output = child.wait_with_output().unwrap(); assert_eq!(output.status.code(), Some(0)); - assert_eq!(output.stderr, b""); - let output_str = String::from_utf8(output.stdout).unwrap(); + assert_eq!(output.stdout, b""); + let output_str = String::from_utf8(output.stderr).unwrap(); assert!(output_str.contains("(multi-call binary)"), "{output_str:?}"); assert!( output_str.contains("Usage: [function "),