Rust - [Shell] Stuck on #IP1, Error Expected: "Program Signature: 4652645643", Received "$"

I was expecting the program to execute but it seems it doesn’t execute and thus giving the correct output. In the exec_external I’m receviving the executable path and then calling it using Command::new(path_of_cmd)

I had suspected the arguments are not being passed to cmd and I made sure by giving command mutable so as to check the length and add args to it. When testing with ls -a it works correctly.

The github repo to my code is GitHub - Rioba-Ian/codecrafters-shell-rust

I’ll appreciate any thoughts or help. Thanks

Since you’re using the Command in Rust, you can use the stdout method on the same to redirect the executed command’s output to the STDOUT stream, which is visible to the user (and the tester).

You would then not need to print the args manually, as the binary itself would take care of printing them. All you need to do is to forward the arguments correctly, and set the streams for output (and optionally error) correctly to match STDOUT (and STDERR).

2 Likes

I’ve changed how the output comes but I’m either getting an extra space which if I try to just use print!({}, output_string) won’t remove it.

Thanks a lot for the suggestion, it fixed the output that the test expects. My function now looks as follows

fn exec_external(cmd: &str, args: &[&str]) {
    println!(
        "Program was passed {} args (including program name).",
        args.len() + 1
    );
    println!("Arg #0 (program name): {}", cmd);

    for (i, arg) in args.iter().enumerate() {
        println!("Arg #{}: {}", i + 1, arg);
    }

    let mut command = Command::new(cmd);

    if args.len() > 1 {
        command.args(args);
    }

    let output = command.output().expect("failed to execute process");

    let output_string = String::from_utf8(output.stdout).expect("Invalid output utf8");

    print!("{}", output_string)
}

Yes! This looks like good progress. But actually, two more changes are needed:

  • You don’t need to print the debugging information like the argument count and the argument. This would cause the tester to fail assertions, as all of this content would be printed twice (once by your shell, and then by the binary)
  • You also need to supply all the args, and remove the check if args.len() > 1 as your arguments are exclusive of the command name.

The final function should be something like:

fn exec_external(cmd: &str, args: &[&str]) {
    let mut command = Command::new(cmd);

    command.args(args);

    let output = command.output().expect("failed to execute process");
    let output_string = String::from_utf8(output.stdout).expect("Invalid output utf8");

    print!("{}", output_string)
}

Also unrelated: The current code fails at the second stage itself. To fix that, you might need to change:

println!("{:?}: command not found", other);

to

println!("{}: command not found", other);

(Removed the debug print so that the command other does not appear quoted.)

I’ve made the adjustments but it looks I’m almost back to the same issues as before. I’ve updated my code on github GitHub - Rioba-Ian/codecrafters-shell-rust.

Asking LLMs has not been fruitful as it will quickly deviate and go completely opposite of the tests.

Thank you for helping.

Can you try using this as the exec_external function? It’s the same as your current implementation, but does not logs the arguments manually (that is the job of the custom_exe).

1 Like

Yeah, it worked. I was doing it wrong.

Thanks a lot for the help.

1 Like

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.