The first could be Kernel::exec, and would simply run the process
given. No shell interpretation would ever be done on the argument(s).
Give it one string, and that’s the program it runs. Give it multiple
strings to pass multiple arguments.
Yes, but in the Unix/C world exec() replaces the existing program and
so exec() without fork() is a not-so-useful combination. For
whatever reason it came to pass that Kernel#exec on windows is
actually a Windows version of fork/exec making exec
non-portable.
A second routine, “Kernel::exec_cmd” let’s call it, could take in
exactly one string, and would pass it through the platform’s command
interpreter. This would be documented with all the ugly warnings that
are required so people don’t write
You are describing “Kernel::system” without the funny two-element
array caveat.
I think a better partitioning of the problem would be:
fork/exec: craft what you need, only available on *nix systems
system: execute a command line via the command-interpreter
run: execute a program without using the command-interpreter
I just made up the name ‘run’. I don’t think there are standards
that specify such an interface, which is why exec/system have been
munged, I guess.
But wouldn’t that affect the program cmd, because it is having
something passed to it?
No. This code
exec([cmd, cmd])
is running cmd with no arguments. The second occurrence of “cmd” is
what is actually passed in to the process as its program name
(available to C programs via argv[0] in main(), for example).
So with the two-item list, there is no shell interpretation. To add
arguments, use
exec([cmd, cmd], arg, arg)
but that is the same as
exec(cmd, arg, arg)
simply because once you have at least two arguments to “exec”, it
behaves in the no-shell fashion anyhow.
One could “trick” a program by running
exec([cmd, “string”], arg, arg)
and the program would execute, but see “string” as how it was invoked.
This confuses some applications, but is possible.
No, not true. system() always lets the Ruby process continue on after
the sub-program is finished, but a system() with two or more arguments
doesn’t run any shell. It runs the sub-program directly as a child.
The same rules apply to exec() and system() that have been discussed
in this thread.
not-so-useful combination.
Well, I argue that exec() without fork() is useful in any world, but
it may not be available in some. It can be poorly emulated by
CreateProcess() and exit().
My point was not this though; it was simply that instead of having one
routine behave in two very different ways (exec via shell and exec
directly), there should have been two routines. Getting those confused
is the source of many, many bugs.
I would bet that any piece of code you gave me in Perl or Ruby (or any
other language that supports this idiom) that used system() or exec()
would have a very high chance of containing bugs related to this very
problem. I’ve seen it all the time.
I think a better partitioning of the problem would be:
fork/exec: craft what you need, only available on
*nix systems
system: execute a command line via the
command-interpreter
run: execute a program without using the
command-interpreter
Well, my exec and exec_cmd suggestions were meant to have analogs of
system and system_cmd that did the implicit fork on unix. My exec is
like your first exec, except there are two - one via the shell and one
via the system call.
My system is like your system, and my system_cmd is like your run.
We’re speaking the same language; just using different words.