diff --git a/racket/src/cs/Makefile b/racket/src/cs/Makefile index b138f40a28..8933bafce8 100644 --- a/racket/src/cs/Makefile +++ b/racket/src/cs/Makefile @@ -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 \ diff --git a/racket/src/cs/c/boot.c b/racket/src/cs/c/boot.c index 1a7427da25..8589398c43 100644 --- a/racket/src/cs/c/boot.c +++ b/racket/src/cs/c/boot.c @@ -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 { diff --git a/racket/src/cs/c/boot.h b/racket/src/cs/c/boot.h index d768704fa0..ce8b3b391b 100644 --- a/racket/src/cs/c/boot.h +++ b/racket/src/cs/c/boot.h @@ -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); diff --git a/racket/src/cs/c/main.c b/racket/src/cs/c/main.c index 3807b388d2..1052667088 100644 --- a/racket/src/cs/c/main.c +++ b/racket/src/cs/c/main.c @@ -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 -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 -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); diff --git a/racket/src/cs/main.sps b/racket/src/cs/main.sps index bf053ce2ac..40ed8398b8 100644 --- a/racket/src/cs/main.sps +++ b/racket/src/cs/main.sps @@ -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")