mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-03-16 05:46:25 +00:00
Prepend getcwd to exename early in init (#1048)
This commit is contained in:
parent
2f89c2482a
commit
68dbe5312f
5 changed files with 70 additions and 22 deletions
|
@ -34,6 +34,10 @@
|
||||||
#include "libc/sysv/consts/at.h"
|
#include "libc/sysv/consts/at.h"
|
||||||
#include "libc/sysv/consts/ok.h"
|
#include "libc/sysv/consts/ok.h"
|
||||||
|
|
||||||
|
#ifdef __x86_64__
|
||||||
|
__static_yoink("_init_program_executable_name");
|
||||||
|
#endif
|
||||||
|
|
||||||
#define CTL_KERN 1
|
#define CTL_KERN 1
|
||||||
#define KERN_PROC 14
|
#define KERN_PROC 14
|
||||||
#define KERN_PROC_PATHNAME_FREEBSD 12
|
#define KERN_PROC_PATHNAME_FREEBSD 12
|
||||||
|
@ -88,31 +92,37 @@ static int OldApeLoader(char *s) {
|
||||||
(!strncmp((b = basename(s)), ".ape-", 5) && AllNumDot(b + 5));
|
(!strncmp((b = basename(s)), ".ape-", 5) && AllNumDot(b + 5));
|
||||||
}
|
}
|
||||||
|
|
||||||
// if q exists then turn it into an absolute path. we also try adding
|
static char *CopyWithCwd(const char *q, char *p, char *e) {
|
||||||
// a .com suffix since the ape auto-appends it when resolving
|
char c;
|
||||||
static int TryPath(const char *q, int com) {
|
|
||||||
char c, *p, *e;
|
|
||||||
if (!q) return 0;
|
|
||||||
p = g_prog.u.buf;
|
|
||||||
e = p + sizeof(g_prog.u.buf);
|
|
||||||
if (*q != '/') {
|
if (*q != '/') {
|
||||||
if (q[0] == '.' && q[1] == '/') {
|
if (q[0] == '.' && q[1] == '/') {
|
||||||
q += 2;
|
q += 2;
|
||||||
}
|
}
|
||||||
int got = __getcwd(p, e - p - 1 /* '/' */ - com * 4);
|
int got = __getcwd(p, e - p - 1 /* '/' */);
|
||||||
if (got != -1) {
|
if (got != -1) {
|
||||||
p += got - 1;
|
p += got - 1;
|
||||||
*p++ = '/';
|
*p++ = '/';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while ((c = *q++)) {
|
while ((c = *q++)) {
|
||||||
if (p + com * 4 + 1 /* nul */ < e) {
|
if (p + 1 /* nul */ < e) {
|
||||||
*p++ = c;
|
*p++ = c;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*p = 0;
|
*p = 0;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if q exists then turn it into an absolute path. we also try adding
|
||||||
|
// a .com suffix since the ape auto-appends it when resolving
|
||||||
|
static int TryPath(const char *q, int com) {
|
||||||
|
char *p;
|
||||||
|
if (!(p = CopyWithCwd(q, g_prog.u.buf,
|
||||||
|
g_prog.u.buf + sizeof(g_prog.u.buf) - com * 4))) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (!sys_faccessat(AT_FDCWD, g_prog.u.buf, F_OK, 0)) return 1;
|
if (!sys_faccessat(AT_FDCWD, g_prog.u.buf, F_OK, 0)) return 1;
|
||||||
if (!com) return 0;
|
if (!com) return 0;
|
||||||
p = WRITE32LE(p, READ32LE(".com"));
|
p = WRITE32LE(p, READ32LE(".com"));
|
||||||
|
@ -121,6 +131,16 @@ static int TryPath(const char *q, int com) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if the loader passed a relative path, prepend cwd to it.
|
||||||
|
// called early in init.
|
||||||
|
void __init_program_executable_name(void) {
|
||||||
|
if (__program_executable_name && *__program_executable_name != '/' &&
|
||||||
|
CopyWithCwd(__program_executable_name, g_prog.u.buf,
|
||||||
|
g_prog.u.buf + sizeof(g_prog.u.buf))) {
|
||||||
|
__program_executable_name = g_prog.u.buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline void InitProgramExecutableNameImpl(void) {
|
static inline void InitProgramExecutableNameImpl(void) {
|
||||||
size_t n;
|
size_t n;
|
||||||
ssize_t got;
|
ssize_t got;
|
||||||
|
@ -167,18 +187,6 @@ static inline void InitProgramExecutableNameImpl(void) {
|
||||||
goto UseEmpty;
|
goto UseEmpty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (*__program_executable_name == '/') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// loader passed us a relative path; prepend cwd.
|
|
||||||
if (TryPath(__program_executable_name, 0)) {
|
|
||||||
goto UseBuf;
|
|
||||||
}
|
|
||||||
/* if TryPath fails, it probably failed because getcwd() was too long.
|
|
||||||
we are out of options now; KERN_PROC_PATHNAME et al will return the
|
|
||||||
name of the loader not the binary, and argv et al will at best have
|
|
||||||
the same problem. just use the relative path we got from the loader
|
|
||||||
as-is, and accept that if we chdir then things will break. */
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
27
libc/calls/program_executable_name_init.S
Normal file
27
libc/calls/program_executable_name_init.S
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||||
|
│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/macros.internal.h"
|
||||||
|
|
||||||
|
.init.start 305,_init_program_executable_name
|
||||||
|
push %rdi
|
||||||
|
push %rsi
|
||||||
|
call __init_program_executable_name
|
||||||
|
pop %rsi
|
||||||
|
pop %rdi
|
||||||
|
.init.end 305,_init_program_executable_name
|
|
@ -172,6 +172,9 @@ wontreturn textstartup void cosmo(long *sp, struct Syslib *m1, char *exename,
|
||||||
// initialize file system
|
// initialize file system
|
||||||
__init_fds(argc, argv, envp);
|
__init_fds(argc, argv, envp);
|
||||||
|
|
||||||
|
// prepend cwd to executable path
|
||||||
|
__init_program_executable_name();
|
||||||
|
|
||||||
__enable_tls();
|
__enable_tls();
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
|
@ -47,6 +47,7 @@ void *__mmap_unlocked(void *, size_t, int, int, int, int64_t);
|
||||||
int __munmap_unlocked(char *, size_t);
|
int __munmap_unlocked(char *, size_t);
|
||||||
void __on_arithmetic_overflow(void);
|
void __on_arithmetic_overflow(void);
|
||||||
void __init_fds(int, char **, char **);
|
void __init_fds(int, char **, char **);
|
||||||
|
void __init_program_executable_name(void);
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* ANSI */
|
#endif /* ANSI */
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/metalfile.internal.h"
|
#include "libc/calls/metalfile.internal.h"
|
||||||
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/limits.h"
|
#include "libc/limits.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
|
@ -57,6 +58,9 @@ void SetUpOnce(void) {
|
||||||
|
|
||||||
__attribute__((__constructor__)) static void Child(int argc, char *argv[]) {
|
__attribute__((__constructor__)) static void Child(int argc, char *argv[]) {
|
||||||
if (argc >= 2 && !strcmp(argv[1], "Child")) {
|
if (argc >= 2 && !strcmp(argv[1], "Child")) {
|
||||||
|
if (sys_chdir("/")) {
|
||||||
|
exit(122);
|
||||||
|
}
|
||||||
if (strcmp(argv[2], GetProgramExecutableName())) {
|
if (strcmp(argv[2], GetProgramExecutableName())) {
|
||||||
exit(123);
|
exit(123);
|
||||||
}
|
}
|
||||||
|
@ -138,4 +142,9 @@ TEST(GetProgramExecutableName, movedSelf) {
|
||||||
execve(buf, (char *[]){"hello", "Child", buf, "hello", 0}, (char *[]){0});
|
execve(buf, (char *[]){"hello", "Child", buf, "hello", 0}, (char *[]){0});
|
||||||
abort();
|
abort();
|
||||||
EXITS(0);
|
EXITS(0);
|
||||||
|
SPAWN(fork);
|
||||||
|
execve("./test", (char *[]){"hello", "Child", buf, "hello", 0},
|
||||||
|
(char *[]){0});
|
||||||
|
abort();
|
||||||
|
EXITS(0);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue