Keep argv[0], add COSMOPOLITAN_PROGRAM_EXECUTABLE (#980)

* Introduce env.com

Handy tool for debugging environment issues.

* Inject path as COSMOPOLITAN_PROGRAM_EXECUTABLE

`argv[0]` was previously being used as a communication channel between
the loader and the binary, giving the binary its full path for use e.g.
in `GetProgramExecutableName`. But `argv[0]` is not a good channel for
this; much of what made 2a3813c6 so gross is due to that.

This change fixes the issue by preserving `argv[0]` and establishing a
new communication channel: `COSMOPOLITAN_PROGRAM_EXECUTABLE`.

The M1 loader will always set this as the first variable. Linux should
soon follow. On the other side, `GetProgramExecutableName` checks that
variable first. If it sees it, it trusts it as-is.

A lot of the churn in `ape/ape-m1.c` in this change is actually backing
out hacks introduced in 2a3813c6; the best comparison is:

    git diff 2a3813c6^..
This commit is contained in:
Jōshin 2023-12-04 15:45:46 -05:00 committed by GitHub
parent 2a3813c6cf
commit ed8fadea37
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 168 additions and 38 deletions

View file

@ -36,6 +36,8 @@
#define KERN_PROC 14
#define KERN_PROC_PATHNAME_FREEBSD 12
#define KERN_PROC_PATHNAME_NETBSD 5
#define VARNAME "COSMOPOLITAN_PROGRAM_EXECUTABLE="
#define VARSIZE (sizeof(VARNAME) - 1)
static struct {
atomic_uint once;
@ -77,6 +79,13 @@ static inline void InitProgramExecutableNameImpl(void) {
goto CopyString;
}
/* new-style loader supplies the full program path as the first
environment variable; if it is defined, trust it as-is. */
if (*__envp && !strncmp(*__envp, VARNAME, VARSIZE)) {
strlcpy(g_prog.u.buf, *__envp + VARSIZE, sizeof(g_prog.u.buf));
return;
}
// if argv[0] exists then turn it into an absolute path. we also try
// adding a .com suffix since the ape auto-appends it when resolving
if ((q = __argv[0])) {
@ -146,6 +155,7 @@ static inline void InitProgramExecutableNameImpl(void) {
}
}
*p = 0;
return;
}
// if we don't even have that then empty the string