Sujet : Re: Case Insensitive File Systems -- Torvalds Hates Them
De : invalid (at) *nospam* invalid.invalid (Richard Kettlewell)
Groupes : comp.os.linux.miscDate : 04. May 2025, 18:15:26
Autres entêtes
Organisation : terraraq NNTP server
Message-ID : <wwvfrhknvpt.fsf@LkoBDZeT.terraraq.uk>
References : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
User-Agent : Gnus/5.13 (Gnus v5.13) Emacs/28.2 (gnu/linux)
The Natural Philosopher <
tnp@invalid.invalid> writes:
On 04/05/2025 14:41, Richard Kettlewell wrote:
I mean you can trace the transmission of the command line from parent
to child process through the startup. There’s no splitting in there,
it’s an array of strings from top to bottom.
>
But the command line is not an array of strings... any more than this
line of text is. That's what I don't understand. It's a single string
The command line _in the shell_ is a single string, that you have typed
in:
mv ugly_filename.txt 'beautiful filename.txt'
Once the shell reads it, that still looks like a single string:
char *cmdline = "mv ugly_filename.txt 'beautiful filename.txt'";
The shell splits it (and follows its rules for quotes, etc), creating an
array of strings with a null pointer at the end:
char *argv[] = {
"mv",
"ugly_filename.txt",
"beautiful filename.txt",
NULL,
};
The shell creates a child process by calling fork(), and within that
child process, runs the required command by calling execve().
if(fork() == 0) {
// child process
execve("/bin/mv", argv, _environ);
}
The kernel loads /bin/mv and provides a copy of the argv array to the C
runtime’s entry point. The C runtime startup code in modern systems is
nontrivial but on older systems it’s a handful of lines of assembler,
e.g. here from the VAX variant of Unix System III:
https://www.greenend.org.uk/rjk/junk/crt0.s There’s no parsing or splitting of command lines here - just figuring
out where the boundary between argv and the environment is, in the loop
between L1 and L2. After that it calls main(), and when that returns it
hands offthe result to exit().
int main(int argc, char **argv) { // mv.c with all the fluff removed l-)
if(rename(argv[1], argv[2]) < 0) {
perror("rename");
exit(1);
}
exit(0);
}
The splitting on spaces (and handling of quotes etc) happens in the
shell.
>
An array by definition is already split. On what basis is it split?
An array by definition is an indexed collection of values - i.e. you can
talk about argv[0], argv[1], etc. How you create it is up to you. You
can take a string and split it in some way (which is what the shell
does) or you can just create the elements independently (which is a
common way to execute other programs without involving the shell and all
its issues with spaces).
-- https://www.greenend.org.uk/rjk/