Read shell message with process::Command before write to STDIN

Hello.

I have simple shell script, which asks for input and return it:

#!/bin/sh

read -p "Enter something: " input
echo "You entered: $input"

Idea is to simulate more complicated utility that can return something after execution depends on condition. So my rust script looks:

    fn main() {
        
        let mut sh = Command::new("/usr/bin/sh");
        let mut child = sh
            .arg("-c").arg("/path_to/test_sh")
            .stdin(Stdio::piped()).stdout(Stdio::piped()).stderr(Stdio::piped())
            .spawn().unwrap();
           

        let mut stdin = child.stdin.take().unwrap();
        thread::spawn(move || {
                stdin.write_all("asdf".as_bytes());
        });
        
        let output = child.wait_with_output().unwrap();
        println!("OUT: {:?}", output);

The output is expected:

OUT: Output { status: ExitStatus(unix_wait_status(0)), stdout: "You entered: asdf\n", stderr: "" }

But where is my shell "Enter something: "?
How can I get it?
Is it possible to read it before any write to stdin?

Thank you advice.

The shell providing the read command will only display a prompt if input is coming from a terminal. A pipe is not a terminal.

3 Likes

Thank you for your replay.
But I do not understand it, rust was able to write into shell and got last shell replay.

I do also understand that the first message from shell "Enter something: " was not ended and shell kept running waiting for any input. If I remember correctly in Go they suggested to run shell in a thread and communicate via 2 pipes: parent receives messages from child and child from parent, then child finish. I need to search something similar here.

The shell's read command in particular is deciding not to print its prompt text. You got all the output the shell actually produced.

If you want the shell to print its prompts you will have to attach a pseudo-terminal (pty) to the child process instead of pipes. Rust's std doesn't support this, but maybe nix could help.