diff options
| author | Fabrice Le Fessant <Fabrice.Le_fessant@inria.fr> | 2010-11-11 06:38:31 +0000 |
|---|---|---|
| committer | Fabrice Le Fessant <Fabrice.Le_fessant@inria.fr> | 2010-11-11 06:38:31 +0000 |
| commit | 174df0ab26c2fb06a075df6fe8d598fd89234cd9 (patch) | |
| tree | 3ddbb0018e6476873891710a95f04190bddff923 /ocaml-binary-annot/stdlib/header.c | |
| download | ocaml-174df0ab26c2fb06a075df6fe8d598fd89234cd9.tar.gz | |
New branch binary-annot by Fabrice Le Fessant from r10789
git-svn-id: http://caml.inria.fr/svn/ocaml/branches/binary-annot@10790 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02
Diffstat (limited to 'ocaml-binary-annot/stdlib/header.c')
| -rw-r--r-- | ocaml-binary-annot/stdlib/header.c | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/ocaml-binary-annot/stdlib/header.c b/ocaml-binary-annot/stdlib/header.c new file mode 100644 index 0000000000..eda76325a6 --- /dev/null +++ b/ocaml-binary-annot/stdlib/header.c @@ -0,0 +1,191 @@ +/***********************************************************************/ +/* */ +/* Objective Caml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1998 Institut National de Recherche en Informatique et */ +/* en Automatique. All rights reserved. This file is distributed */ +/* under the terms of the GNU Library General Public License, with */ +/* the special exception on linking described in file ../LICENSE. */ +/* */ +/***********************************************************************/ + +/* $Id$ */ + +/* The launcher for bytecode executables (if #! is not working) */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "../config/s.h" +#ifdef HAS_UNISTD +#include <unistd.h> +#endif +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include "../byterun/mlvalues.h" +#include "../byterun/exec.h" + +char * default_runtime_path = RUNTIME_NAME; + +#ifndef MAXPATHLEN +#define MAXPATHLEN 1024 +#endif + +#ifndef S_ISREG +#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) +#endif + +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +#ifndef __CYGWIN32__ + +/* Normal Unix search path function */ + +static char * searchpath(char * name) +{ + static char fullname[MAXPATHLEN + 1]; + char * path; + char * p; + char * q; + struct stat st; + + for (p = name; *p != 0; p++) { + if (*p == '/') return name; + } + path = getenv("PATH"); + if (path == NULL) return name; + while(1) { + for (p = fullname; *path != 0 && *path != ':'; p++, path++) + if (p < fullname + MAXPATHLEN) *p = *path; + if (p != fullname && p < fullname + MAXPATHLEN) + *p++ = '/'; + for (q = name; *q != 0; p++, q++) + if (p < fullname + MAXPATHLEN) *p = *q; + *p = 0; + if (stat(fullname, &st) == 0 && S_ISREG(st.st_mode)) break; + if (*path == 0) return name; + path++; + } + return fullname; +} + +#else + +/* Special version for Cygwin32: takes care of the ".exe" implicit suffix */ + +static int file_ok(char * name) +{ + int fd; + /* Cannot use stat() here because it adds ".exe" implicitly */ + fd = open(name, O_RDONLY); + if (fd == -1) return 0; + close(fd); + return 1; +} + +static char * searchpath(char * name) +{ + char * path, * fullname, * p; + + path = getenv("PATH"); + fullname = malloc(strlen(name) + (path == NULL ? 0 : strlen(path)) + 6); + /* 6 = "/" plus ".exe" plus final "\0" */ + if (fullname == NULL) return name; + /* Check for absolute path name */ + for (p = name; *p != 0; p++) { + if (*p == '/' || *p == '\\') { + if (file_ok(name)) return name; + strcpy(fullname, name); + strcat(fullname, ".exe"); + if (file_ok(fullname)) return fullname; + return name; + } + } + /* Search in path */ + if (path == NULL) return name; + while(1) { + for (p = fullname; *path != 0 && *path != ':'; p++, path++) *p = *path; + if (p != fullname) *p++ = '/'; + strcpy(p, name); + if (file_ok(fullname)) return fullname; + strcat(fullname, ".exe"); + if (file_ok(fullname)) return fullname; + if (*path == 0) break; + path++; + } + return name; +} + +#endif + +static unsigned long read_size(char * ptr) +{ + unsigned char * p = (unsigned char *) ptr; + return ((unsigned long) p[0] << 24) + ((unsigned long) p[1] << 16) + + ((unsigned long) p[2] << 8) + p[3]; +} + +static char * read_runtime_path(int fd) +{ + char buffer[TRAILER_SIZE]; + static char runtime_path[MAXPATHLEN]; + int num_sections, i; + uint32 path_size; + long ofs; + + lseek(fd, (long) -TRAILER_SIZE, SEEK_END); + if (read(fd, buffer, TRAILER_SIZE) < TRAILER_SIZE) return NULL; + num_sections = read_size(buffer); + ofs = TRAILER_SIZE + num_sections * 8; + lseek(fd, -ofs, SEEK_END); + path_size = 0; + for (i = 0; i < num_sections; i++) { + if (read(fd, buffer, 8) < 8) return NULL; + if (buffer[0] == 'R' && buffer[1] == 'N' && + buffer[2] == 'T' && buffer[3] == 'M') { + path_size = read_size(buffer + 4); + ofs += path_size; + } else if (path_size > 0) + ofs += read_size(buffer + 4); + } + if (path_size == 0) return default_runtime_path; + if (path_size >= MAXPATHLEN) return NULL; + lseek(fd, -ofs, SEEK_END); + if (read(fd, runtime_path, path_size) != path_size) return NULL; + runtime_path[path_size - 1] = 0; + return runtime_path; +} + +static void errwrite(char * msg) +{ + write(2, msg, strlen(msg)); +} + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +int main(int argc, char ** argv) +{ + char * truename, * runtime_path; + int fd; + + truename = searchpath(argv[0]); + fd = open(truename, O_RDONLY | O_BINARY); + if (fd == -1 || (runtime_path = read_runtime_path(fd)) == NULL) { + errwrite(truename); + errwrite(" not found or is not a bytecode executable file\n"); + return 2; + } + argv[0] = truename; + execv(runtime_path, argv); + errwrite("Cannot exec "); + errwrite(runtime_path); + errwrite("\n"); + return 2; +} |
