3 ms·
> most languages (including Python) have constructs that call shell. Rust's stdlib doesn't. You must pass arguments as array. https://doc.rust-lang.org/std/pr
by the8472 8y ago
> most languages (including Python) have constructs that call shell.
Rust's stdlib doesn't. You must pass arguments as array.
https://doc.rust-lang.org/std/process/struct.Command.html https://doc.rust-lang.org/std/process/struct.Command.html
- kazinator 8y agoAn exec-like mechanism be used to construct a [ "/bin/sh" "/bin/sh" "-c" "yourcommandhere", NULL ] argument vector.
- the8472 8y agosure, but then you're intentionally making things harder on yourself
- kazinator 8y agoMaking what harder on yourself? What if yourcommandhere is shell syntax, like "for x in *.foo; do echo $foo; done"? That can't be executed directly as a process argument list. If all you have is a wrapper for execv, then you have to construct a call to "sh", where that command is all in one argument following a "-c" argument. You said that Rust doesn't have a library function for calling the shell but only process execution; I'm showing how you make one in such a situation. A language and its library won't prevent applications from calling the shell, unless it's uselessly crippled.
- the8472 8y ago> What if yourcommandhere is shell syntax, like "for x in *.foo; do echo $foo; done" Then you readdir, loop, println. no need to use the shell > You said that Rust doesn't have a library function for calling the shell but only process execution; I'm showing how you make one in such a situation. You're stating the obvious. My point was that it has no footgun which automatically defers to the shell or does shell-like argument extraction from a single string when spawning child processes. Other languages have those things in their standard library which is a source of errors that rust avoids. It does provide a regular gun which you can repurposed as a make-shift footgun by taking the conscious action of aiming down first.
- kazinator 8y ago> Then you readdir, loop, println. no need to use the shell Yes; you have a Turing complete language, so why would you use the shell? The point that you've lost sight of here is that someone can do that and someone likely will. (I don't disagree with you; I think that "shelling out" commands from decent programmign languages is an anti-pattern.) Have you seen this? https://doc.rust-lang.org/std/process/struct.Command.html https://doc.rust-lang.org/std/process/struct.Command.html Look, an example of what I'm talking about, right on the Rust site: how to send "echo hello" to your shell on Windows and Unix. You don't think someone's going to copy and paste this, and substitute whatever command they want?
- the8472 8y agoI agree that documentation sets a bad example. > The point that you've lost sight of here is that someone can do that and someone likely will. Sure, that is inherent in the freedom of powerful tools, you can also use them to do dangerous things. But that is besides the point. The point is that the default and simplest way is the safe way to spawn commands. You have to do extra work to invoke dangerous shellisms. You need to at least understand that arguments are conceptually not one long string but an array of several strings, and to invoke a shell you would already have to start with splitting that invocation into an array, so you gain little from then writing the rest of your command as one string, you might as well split up all of them and avoid all those escaping pitfalls. This is the contrast to other languages which have constructs like system("echo foo"), spawn_sh("echo foo") or whatever which are superficially easier to easier use than launching child processes the safe way. In this regard rust is safer than most other languages, since it has no "construct which calls the shell" - note the active voice used here, "can be used to call a shell", passive, is a different case. This is all I have claimed in this thread.