From bf6bc9ec9291712c681ad992b03a17fd1e5051cb Mon Sep 17 00:00:00 2001 From: Jay Hemnani <193022578+jayhemnani9910@users.noreply.github.com> Date: Fri, 23 Oct 2026 03:19:13 +0530 Subject: [PATCH 1/2] setsid: accept --ctty, --fork and --wait --- src/uu/setsid/src/setsid.rs | 3 +++ tests/by-util/test_setsid.rs | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/uu/setsid/src/setsid.rs b/src/uu/setsid/src/setsid.rs index a4d99e55..30ef707e 100644 --- a/src/uu/setsid/src/setsid.rs +++ b/src/uu/setsid/src/setsid.rs @@ -169,6 +169,7 @@ pub fn uu_app() -> Command { .arg( Arg::new("ctty") .short('c') + .long("ctty") .action(ArgAction::SetTrue) .value_parser(ValueParser::bool()) .help("Take the current controlling terminal"), @@ -176,6 +177,7 @@ pub fn uu_app() -> Command { .arg( Arg::new("fork") .short('f') + .long("fork") .action(ArgAction::SetTrue) .value_parser(ValueParser::bool()) .long_help("Always create a new process. By default this is only done if we are already a process group lead."), @@ -183,6 +185,7 @@ pub fn uu_app() -> Command { .arg( Arg::new("wait") .short('w') + .long("wait") .action(ArgAction::SetTrue) .value_parser(ValueParser::bool()) .help("Wait for the command to finish and exit with its exit code."), diff --git a/tests/by-util/test_setsid.rs b/tests/by-util/test_setsid.rs index 002873f6..c9fc6b2f 100644 --- a/tests/by-util/test_setsid.rs +++ b/tests/by-util/test_setsid.rs @@ -49,6 +49,24 @@ mod unix { .no_output(); } + #[test] + fn long_options() { + new_ucmd!() + .args(&["--fork", "--wait", "/usr/bin/false"]) + .fails() + .code_is(1) + .no_output(); + new_ucmd!() + .args(&["--wait", "/usr/bin/true"]) + .succeeds() + .no_output(); + // without a terminal --ctty fails, but as an option it is accepted + new_ucmd!() + .args(&["--ctty", "/usr/bin/true"]) + .run() + .stderr_does_not_contain("unexpected argument"); + } + #[test] fn non_fork_returns_not_found_error() { new_ucmd!() From 6a075af3fedac3b8cb917d8ea8a857e3835f7077 Mon Sep 17 00:00:00 2001 From: Jay Hemnani <193022578+jayhemnani9910@users.noreply.github.com> Date: Sun, 25 Oct 2026 13:17:15 +0530 Subject: [PATCH 2/2] setsid: test --wait --ctty against a simulated terminal --- tests/by-util/test_setsid.rs | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/tests/by-util/test_setsid.rs b/tests/by-util/test_setsid.rs index c9fc6b2f..119f37db 100644 --- a/tests/by-util/test_setsid.rs +++ b/tests/by-util/test_setsid.rs @@ -60,11 +60,6 @@ mod unix { .args(&["--wait", "/usr/bin/true"]) .succeeds() .no_output(); - // without a terminal --ctty fails, but as an option it is accepted - new_ucmd!() - .args(&["--ctty", "/usr/bin/true"]) - .run() - .stderr_does_not_contain("unexpected argument"); } #[test] @@ -111,6 +106,37 @@ mod unix { .stderr_is("setsid: failed to set the controlling terminal: Permission denied\r\n"); } + #[cfg(target_os = "linux")] + #[test] + fn long_options_take_new_controlling_tty() { + let shell_cmd = format!( + "/usr/bin/cat /proc/self/stat; {} setsid --wait --ctty /usr/bin/cat /proc/self/stat", + get_tests_binary() + ); + + let cmd_result = UCommand::new() + .terminal_simulation(true) + .arg(&shell_cmd) + .succeeds(); + + let output = cmd_result.code_is(0).no_stderr().stdout_str(); + + // the controlling terminal is the 7th field of /proc/self/stat + let (before, after) = output + .split_once('\n') + .expect("expected 2 lines of output at least"); + let before = before + .split_whitespace() + .nth(6) + .expect("unexpected stat format"); + let after = after + .split_whitespace() + .nth(6) + .expect("unexpected stat format"); + + assert_ne!(before, after); + } + #[cfg(target_os = "linux")] #[test] fn unprivileged_user_can_take_new_controlling_tty() {