The char *apple[] Argument Vector
We're all familiar with the arguments passed to the main function by the OS:
int argcchar *argv[]char *envp[]
But programs started on Mac OS X (i.e. Darwin) actually have access to another argument - the
apple vector. The apple vector is defined as char *apple[] and it's passed as the 4th argument to the main() function (it's actually stored right after envp on the stack). But what is it used for? Well, Apple can use the
apple vector to pass whatever "hidden" parameters they want to any program. And they do actually use it, too. Currently, apple[0] contains the path where the executing binary was found on disk. What's that you say? How is apple[0] different from argv[0]? The difference is that argv[0] can be set to any arbitrary value when execve(2) is called. For example, shells often differentiate a login shell from a regular shell by starting login shells with the first character in argv[0] being a -. For example:
$ ps aux | grep -- -bash
jgm 262 0.0 0.1 27820 752 p1 S 5Feb06 0:01.58 -bash
So, we can see that the bash login shell on my Mac was started with a dash in its name. In this example, bash's
argv[0] would equal -bash, but its apple[0] would contain the path to where the bash binary was actually found (likely apple[0] would be /bin/bash).Let's write a simple program to see all this in action:
// Compile with: gcc -o apple apple.c
#include <stdio.h>
int main(int argc, char *argv[], char *envp[], char *apple[]) {
printf("argv[0] = %s\n", argv[0]);
printf("apple[0] = %s\n", apple[0]);
return 0;
}
And here's a few runs:
$ ./apple
argv[0] = ./apple
apple[0] = ./apple
$ PATH=. apple
argv[0] = apple
apple[0] = ./apple
$ PATH=/Users/jgm apple
argv[0] = apple
apple[0] = /Users/jgm/apple
So, we can see that
apple[0] is not the same as argv[0] and that it contains the path to where the executing image was found on disk (taking into account the $PATH).Now, if want to test the bash example above (where
argv[0] doesn't match the binary name), we can write another small test program:
// Compile with: gcc -o exec_apple exec_apple.c
#include <unistd.h>
int main() {
char *theArgv[] = {"-apple", NULL};
execve("./apple", theArgv, NULL);
return 1;
}
And a run:
$ ./exec_apple
argv[0] = -apple
apple[0] = ./apple
So, just as we expected;
argv[0] can really be set to anything by execve(2) but apple[0] should always contain the real path to the executing binary image.Pretty neat huh?
UPDATE 10/30/2006 here


No comments:
Post a Comment