cs: fix exec-file and run-file setup

Allow embedded command-line argument to adjust exec-file, for
example.
This commit is contained in:
Matthew Flatt 2018-11-11 08:11:17 -07:00
parent f10e6d43bf
commit 7ab69142f4
5 changed files with 161 additions and 39 deletions

View File

@ -19,7 +19,7 @@ RUMBLE_UNSAFE_COMP = --unsafe
COMPILE_FILE = $(SCHEME) --script compile-file.ss $(UNSAFE_COMP) $(COMPRESS_COMP) $(DEBUG_COMP) --dest "$(BUILDDIR)"
COMPILE_FILE_DEPS = compile-file.ss include.ss place-register.ss
RACKET_SETUP_ARGS = ../../bin/racket ../collects ../etc 0 true false 0 ""
RACKET_SETUP_ARGS = ../../bin/racket ../../bin/racket ../collects ../etc 0 true false 0 ""
PRIMITIVES_TABLES = primitive/kernel.ss primitive/unsafe.ss primitive/flfxnum.ss \
primitive/paramz.ss primitive/extfl.ss primitive/network.ss \

View File

@ -91,12 +91,12 @@ static void init_foreign()
Sforeign_symbol("racket_errno", (void *)racket_errno);
}
void racket_boot(int argc, char **argv, char *self,
void racket_boot(int argc, char **argv, char *exec_file, char *run_file,
char *boot_exe, long segment_offset,
char *coldir, char *configdir,
int pos1, int pos2, int pos3,
int cs_compiled_subdir, int is_gui,
int wm_is_gracket, const char *gracket_guid)
int wm_is_gracket, char *gracket_guid)
/* exe argument already stripped from argv */
{
#if !defined(RACKET_USE_FRAMEWORK) || !defined(RACKET_AS_BOOT)
@ -148,7 +148,7 @@ void racket_boot(int argc, char **argv, char *self,
l = Scons(Sbytevector(argv[i]), l);
}
l = Scons(Sbytevector(gracket_guid), l);
sprintf(wm_is_gracket_s, "%ld", wm_is_gracket);
sprintf(wm_is_gracket_s, "%d", wm_is_gracket);
l = Scons(Sbytevector(wm_is_gracket_s), l);
l = Scons(Sbytevector(is_gui ? "true" : "false"), l);
l = Scons(Sbytevector(cs_compiled_subdir ? "true" : "false"), l);
@ -156,7 +156,8 @@ void racket_boot(int argc, char **argv, char *self,
l = Scons(Sbytevector(segment_offset_s), l);
l = Scons(Sbytevector(configdir), l);
l = Scons(Sbytevector(coldir), l);
l = Scons(Sbytevector(self), l);
l = Scons(Sbytevector(run_file), l);
l = Scons(Sbytevector(exec_file), l);
#ifdef RACKET_AS_BOOT
{

View File

@ -1,13 +1,13 @@
BOOT_EXTERN void racket_boot(int argc, char **argv, char *self,
BOOT_EXTERN void racket_boot(int argc, char **argv, char *exec_file, char *run_file,
char *boot_exe, long segment_offset,
char *coldir, char *configdir,
int pos1, int pos2, int pos3,
int cs_compiled_subdir, int is_gui,
int wm_is_gracket, const char *gracket_guid);
int wm_is_gracket, char *gracket_guid);
typedef void (*racket_boot_t)(int argc, char **argv, char *self,
typedef void (*racket_boot_t)(int argc, char **argv, char *exec_file, char *run_file,
char* boot_exe, long segment_offset,
char *coldir, char *configdir,
int pos1, int pos2, int pos3,
int cs_compiled_subdir, int is_gui,
int wm_is_gracket, const char *gracket_guid);
int wm_is_gracket, char *gracket_guid);

View File

@ -32,9 +32,11 @@ static int scheme_utf8_encode(unsigned int *path, int zero_offset, int len,
char *boot_file_data = "BooT FilE OffsetS:xxxxyyyyyzzzz";
static int boot_file_offset = 18;
#define USE_GENERIC_GET_SELF_PATH
#ifdef OS_X
# include <mach-o/dyld.h>
static char *get_self_path()
static char *get_self_path(char *exec_file)
{
char buf[1024], *s;
uint32_t size = sizeof(buf);
@ -52,11 +54,12 @@ static char *get_self_path()
exit(1);
}
}
# undef USE_GENERIC_GET_SELF_PATH
#endif
#if defined(__linux__)
# include <errno.h>
static char *get_self_path()
static char *get_self_path(char *exec_file)
{
char buf[256], *s = buf;
ssize_t len, blen = sizeof(buf);
@ -76,6 +79,7 @@ static char *get_self_path()
buf[len] = 0;
return strdup(buf);
}
# undef USE_GENERIC_GET_SELF_PATH
#endif
@ -138,11 +142,6 @@ static char *string_to_utf8(wchar_t *p)
return r;
}
static char *get_self_path()
{
return string_to_utf8(get_self_executable_path());
}
static int scheme_utf8_encode(unsigned int *path, int zero_offset, int len,
char *dest, int offset, int get_utf16)
{
@ -154,6 +153,119 @@ static int scheme_utf8_encode(unsigned int *path, int zero_offset, int len,
}
# include "../start/parse_cmdl.inc"
# undef USE_GENERIC_GET_SELF_PATH
#endif
#ifdef USE_GENERIC_GET_SELF_PATH
/* Get executable path via argv[0] and the `PATH` encironment variable */
static int has_slash(char *s)
{
while (*s) {
if (s[0] == '/')
return 1;
s++;
}
return 0;
}
static char *do_path_append(char *s1, int l1, char *s2)
{
int l2;
char *s;
l2 = strlen(s2);
s = (char *)malloc(l1 + l2 + 2);
memcpy(s, s1, l1);
if (s[l1 - 1] != '/') {
s[l1++] = '/';
}
memcpy(s + l1, s2, l2);
s[l1 + l2] = 0;
return s;
}
static char *path_append(char *s1, char *s2)
{
return do_path_append(s1, strlen(s1), s2);
}
static char *copy_string(char *s1)
{
int l1;
char *s;
if (!s1) return NULL;
l1 = strlen(s1);
s = (char *)malloc(l1 + 1);
memcpy(s, s1, l1 + 1);
return s;
}
static int executable_exists(char *path)
{
return (access(path, X_OK) == 0);
}
static char *get_self_path(char *exec_file)
{
if (exec_file[0] == '/') {
/* Absolute path */
return exec_file;
} else if (has_slash(exec_file)) {
/* Relative path with a directory: */
char *buf;
long buflen = 4096;
buf = (char *)malloc(buflen);
return path_append(getcwd(buf, buflen), exec_file);
} else {
/* We have to find the executable by searching PATH: */
char *path = copy_string(getenv("PATH")), *p, *m;
int more;
if (!path) {
path = "";
}
while (1) {
/* Try each element of path: */
for (p = path; *p && (*p != ':'); p++) { }
if (*p) {
*p = 0;
more = 1;
} else
more = 0;
if (!*path)
break;
m = path_append(path, exec_file);
if (executable_exists(m)) {
if (m[0] != '/')
m = path_append(getcwd(NULL, 0), m);
return m;
}
free(m);
if (more)
path = p + 1;
else
break;
}
return exec_file;
}
}
#endif
#ifdef NO_GET_SEGMENT_OFFSET
@ -169,9 +281,9 @@ static long get_segment_offset()
static int bytes_main(int argc, char **argv,
/* for Windows GUI mode */
int wm_is_gracket, const char *gracket_guid)
int wm_is_gracket, char *gracket_guid)
{
char *self, *boot_exe, *prog = argv[0], *sprog = NULL;
char *boot_exe, *exec_file = argv[0], *run_file = NULL;
int pos1, pos2, pos3;
long boot_offset;
long segment_offset;
@ -188,27 +300,28 @@ static int bytes_main(int argc, char **argv,
argv++;
}
extract_built_in_arguments(&prog, &sprog, &argc, &argv);
segment_offset = get_segment_offset();
self = get_self_path();
#ifdef WIN32
# define racket_boot racket_boot_p
dll_path = load_delayed_dll_x(NULL, "libracketcsxxxxxxx.dll", &dll);
boot_exe = string_to_utf8(dll_path);
racket_boot_p = (racket_boot_t)GetProcAddress(dll, "racket_boot");
#else
boot_exe = self;
boot_exe = get_self_path(exec_file);
#endif
extract_built_in_arguments(&exec_file, &run_file, &argc, &argv);
if (!run_file)
run_file = exec_file;
segment_offset = get_segment_offset();
memcpy(&pos1, boot_file_data + boot_file_offset, sizeof(pos1));
memcpy(&pos2, boot_file_data + boot_file_offset + 4, sizeof(pos2));
memcpy(&pos3, boot_file_data + boot_file_offset + 8, sizeof(pos2));
boot_offset = 0;
#ifdef ELF_FIND_BOOT_SECTION
boot_offset = find_boot_section(self);
boot_offset = find_boot_section(boot_exe);
#endif
#ifdef WIN32
boot_offset = find_resource_offset(dll_path, 259);
@ -218,7 +331,7 @@ static int bytes_main(int argc, char **argv,
pos2 += boot_offset;
pos3 += boot_offset;
racket_boot(argc, argv, self,
racket_boot(argc, argv, exec_file, run_file,
boot_exe, segment_offset,
extract_coldir(), extract_configdir(),
pos1, pos2, pos3,
@ -235,7 +348,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR ignored
char **argv;
char *normalized_path;
int wm = 0;
const char *guid = "";
char *guid = "";
argv = cmdline_to_argv(&argc, &normalized_path);

View File

@ -54,25 +54,33 @@
(bytes->string/locale s #\?)
s))
the-command-line-arguments/maybe-bytes))
(define (->path s)
(cond
[(bytes? s) (bytes->path s)]
[else (string->path s)]))
(define builtin-argc 8)
(define builtin-argc 9)
(seq
(unless (>= (length the-command-line-arguments) builtin-argc)
(error 'racket (string-append
"expected `self`, `collects`, and `libs` paths"
"expected `exec-file`, `run-file`, `collects`, and `etc` paths"
" plus `segment-offset`, `cs-compiled-subdir?`, `is-gui?`,"
" `wm-is-gracket`, and `gracket-guid`"
" to start")))
(set-exec-file! (path->complete-path (car the-command-line-arguments))))
(define init-collects-dir (let ([s (cadr the-command-line-arguments)])
(if (equal? s "") 'disable (string->path s))))
(define init-config-dir (string->path (or (getenv "PLTCONFIGDIR")
(caddr the-command-line-arguments))))
(define segment-offset (#%string->number (list-ref the-command-line-arguments 3)))
(define cs-compiled-subdir? (string=? "true" (list-ref the-command-line-arguments 4)))
(define gracket? (string=? "true" (list-ref the-command-line-arguments 5)))
(define wm-is-gracket (string->number (list-ref the-command-line-arguments 6)))
(define gracket-guid (list-ref the-command-line-arguments 7))
(set-exec-file! (->path (list-ref the-command-line-arguments/maybe-bytes 0)))
(set-run-file! (->path (list-ref the-command-line-arguments/maybe-bytes 1))))
(define init-collects-dir (let ([s (list-ref the-command-line-arguments/maybe-bytes 2)])
(if (or (equal? s "")
(equal? s '#vu8()))
'disable
(->path s))))
(define init-config-dir (->path (or (getenv "PLTCONFIGDIR")
(list-ref the-command-line-arguments/maybe-bytes 3))))
(define segment-offset (#%string->number (list-ref the-command-line-arguments 4)))
(define cs-compiled-subdir? (string=? "true" (list-ref the-command-line-arguments 5)))
(define gracket? (string=? "true" (list-ref the-command-line-arguments 6)))
(define wm-is-gracket (string->number (list-ref the-command-line-arguments 7)))
(define gracket-guid (list-ref the-command-line-arguments 8))
(seq
(when (foreign-entry? "racket_exit")