5

Similar question to Linux equivalent of GetCommandLine and CommandLineToArgv

Is it possible to get the raw command line in linux? The file /proc/self/cmdline is destroyd.

./a.out files="file 1","file 2" param="2"

prints

./a.outfiles=file 1,file 2param=2

which is junk

Escaping command line does work for all arguments but the first.

./a.out files=\"fil 1\",\"fil 2\"\ param=\"2\"

prints

./a.outfiles="fil1","fil2" param="2"
user877329
  • 6,717
  • 8
  • 46
  • 88
  • How about outputting a space between arguments – Vovanium Dec 26 '12 at 15:35
  • 1
    it seems arguments are separated with 0-bytes and quotes are removed. `cat /proc/self/cmdline | tr '\000' ' '` returns `cat /proc/self/cmdline ` – aragaer Dec 26 '12 at 15:36
  • 1
    And `/proc/self/cmdline` doesn't contain the "raw" command line; it contains exactly the same information as `argv`. – Keith Thompson Dec 26 '12 at 16:24
  • 1
    This is one of the fundamental differences between Windows and UNIX. Neither approach is fundamentally right or wrong, they both have different advantages and disadvantages. – Harry Johnston Dec 29 '12 at 00:55

1 Answers1

11

You can't do that. The command line arguments are actually passed to the new process as individual strings. See the linux kernel source: kernel_execve

Note that kernel_execve(...) takes a const char *argv[] - so there is no such thing as a long string commandline in Linux - it's the layer above that needs to split the arguments into separate components.

Edit: actually, the system call is here:

excve system call

But the statement above still applies. The parameter for argv is already split by the time the kernel gets it from the C-library call to exec.

It is the responsibility of the "starter of the program" (typically a shell, but doesn't have to be) to produce the argv[] array. It will do the "globbing" (expansion of wildcard filenames to the actual files that it matches) and stripping of quotations, variable replacement and so on.

I would also point out that although there are several variants of "exec" in the C library, there is only one way into the kernel. All variants end up in the execve system call that I linked to above. The other variants are simply because the caller may not fancy splitting arguments into invdividual elements, so the C library "helps out" by doing that for the programmer. Similarly for passing an environment array to the new program - if the programmer don't need specific environment, he/she can just call the variant that automatically take the parent process env.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • 1
    Specifically, all the quoting and globbing was handled by the shell. Only if the shell stored the original somewhere the child can access, can you get to it. And that would be shell-specific. – Ben Voigt Dec 26 '12 at 15:56
  • Mats, I suggest adding the information from @BenVoigt's comment to your answer (though programs other than shells can also invoke programs, and may build `argv` in different ways). – Keith Thompson Dec 26 '12 at 16:00
  • @Keith: The parent process doesn't have to be a shell, true. But then there isn't any command-line to discuss at all, only an array of arguments to `exec`. Related: `system()` invokes the shell for command-line processing. – Ben Voigt Dec 26 '12 at 16:04
  • 1
    @BenVoigt: There's a command line *in the shell*; the point is that it's not visible to the invoked process. – Keith Thompson Dec 26 '12 at 16:09
  • 3
    Updated a bit. I just hope this is worth the effort... :) – Mats Petersson Dec 26 '12 at 16:09
  • @Keith: It'd not visible to the invoked process *in any standard fashion*. I'm sure we could figure out how to write a shell that passes it somehow (temporary file, marked as delete-on-close, and using a pre-agreed file descriptor). – Ben Voigt Dec 26 '12 at 16:25
  • Conclusion: There is no PRACTICAL & SIMPLE way to get this sort of data to the current process. – Mats Petersson Dec 26 '12 at 16:34
  • 2
    @Mats Petersson: What if the shell just puts everything after the program name into the first string? Also, this behavior actually makes GetCommandLine in Wine incompatible, since the * is expanded. A Windows program might expect this symbol. – user877329 Jan 19 '13 at 15:29
  • @BenVoigt Or the shell could simply set an environment variable named `SHELL_ORIGINAL_INVOCATION` or something like this. But why would it? Most Linux programmers are okay with shell-processed command line, so there is no demand for this. – Joker_vD May 24 '13 at 07:10