ChrisVilches/horsetab

Shebang has an exotic usage

Closed this issue · 6 comments

In this program, shebang is expected to contain the flag that allows the command to receive the script as argument, such as:

sh -c "echo 6"
python3 -c "print(2)"
ruby -e "puts 5"

In these cases, shebang becomes

#!/bin/sh -c
#!/path/python3 -c
#!/path/ruby -e

But in fact, the shebang is meant to represent which interpreter to use to open the file with, not to pass the script as argument.

Ideally the shebang should just be:

#!/bin/sh
#!/path/python3
#!/path/ruby

I guess this would mean having to create a temporary file and then pass it as first argument, such as:

sh my_shell_script

Another solution would be passing the script via stdin. Passing the script via stdin is also not really great.

(Regarding shebang mechanism)
This answer on StackOverflow explains how it works:

Shebang needs a program (executable) and then it passes it the file path as the last argument. So no script as argument nor script via stdin.

The unix kernel's program loader is responsible for doing this. When exec() is called, it asks the kernel to load the program from the file at its argument. It will then check the first 16 bits of the file to see what executable format it has. If it finds that these bits are #! it will use the rest of the first line of the file to find which program it should launch, and it provides the name of the file it was trying to launch (the script) as the last argument to the interpreter program.
The interpreter then runs as normal, and treats the #! as a comment line.

What if instead of parsing the shebang myself, I simply execute a low level exec call and let the OS read it?

Done with temp files (not committed yet, testing)
Worked with zsh and Ruby interpreter.

Deployed. Haven't tested it fully yet. But one thing I found is that if I remove the shebang then it doesn't run (it crashes). So it either has to be added by the user or by default.

Just add back the default one (without the -c this time):

pub static DEFAULT_INTERPRETER: [&str; 2] = ["sh", "-c"];

Then add it conditionally (if it's not present in the file)

MEMO: You can cargo run -- serve with a specified file. So I can just prepare several files for several cases (with shebang, without, bash, ruby, python, etc)

Fixed (default shebang added). Test all cases.