source for Unix native launcher

svn: r2989
This commit is contained in:
Matthew Flatt 2006-05-19 17:41:26 +00:00
parent 9d1664a7d2
commit e30cd7ca41
2 changed files with 355 additions and 1 deletions

View File

@ -1,7 +1,7 @@
/* Launcher program for Windows. */
/* Builds a MzScheme starter if MZSTART is defined. */
/* Builds a MrEd starter if MRSTART is defined. */
/* If neither is defined, MZSTART is auto-defined */
/* If neither is defined, MZSTART is auto-defined. */
#include <windows.h>
#include <stdlib.h>

View File

@ -0,0 +1,354 @@
/* "Embedding" program for Unix/X11, to be used as
an alternative to embedding in the actual MzScheme
or MrEd binary. */
#include <sys/types.h>
#include <sys/uio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
char *config = "[Replace me with offset info ]";
char *binary_type_hack = "bINARy tYPe:ezi";
/* This path list is used instead of the one in the MzScheme/MrEd
binary. That way, the same MzScheme/MrEd binary can be shared
among embedding exectuables that have different collection
paths. */
static char *_coldir = "coLLECTs dIRECTORy:" /* <- this tag stays, so we can find it again */
"../collects"
"\0\0" /* <- 1st nul terminates path, 2nd terminates path list */
/* Pad with at least 1024 bytes: */
"****************************************************************"
"****************************************************************"
"****************************************************************"
"****************************************************************"
"****************************************************************"
"****************************************************************"
"****************************************************************"
"****************************************************************"
"****************************************************************"
"****************************************************************"
"****************************************************************"
"****************************************************************"
"****************************************************************"
"****************************************************************"
"****************************************************************"
"****************************************************************";
static int _coldir_offset = 19; /* Skip permanent tag */
typedef struct {
char *flag;
int arg_count;
} X_flag_entry;
static X_flag_entry X_flags[] = {
{ "-display", 1 },
{ "-geometry", 1 },
{ "-bg", 1 },
{ "-background", 1 },
{ "-fg", 1 },
{ "-foreground", 1 },
{ "-fn", 1 },
{ "-font", 1 },
{ "-iconic", 0 },
{ "-name", 1 },
{ "-rv", 0 },
{ "-reverse", 0 },
{ "+rv", 0 },
{ "-selectionTimeout", 1 },
{ "-synchronous", 0 },
{ "-title", 1 },
{ "-xnllanguage", 1 },
{ "-xrm", 1 },
{ NULL, 0 }
};
static int is_x_flag(char *s)
{
X_flag_entry *x = X_flags;
while (x->flag) {
if (!strcmp(x->flag, s))
return x->arg_count + 1;
x++;
}
return 0;
}
static void write_str(int fd, char *s)
{
write(fd, s, strlen(s));
}
static char *num_to_string(int n)
{
if (!n)
return "0";
else {
char *d = (char *)malloc(20) + 19;
*d = 0;
while (n) {
d--;
*d = (n % 10) + '0';
n = n / 10;
}
return d;
}
}
static char *string_append(char *s1, char *s2)
{
int l1, l2;
char *s;
l1 = strlen(s1);
l2 = strlen(s2);
s = (char *)malloc(l1 + l2 + 1);
memcpy(s, s1, l1);
memcpy(s + l1, s2, l2);
s[l1 + l2] = 0;
return s;
}
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 int executable_exists(char *path)
{
return (access(path, X_OK) == 0);
}
static int as_int(char *_c)
{
unsigned char *c = (unsigned char *)_c;
return c[0] | ((int)c[1] << 8) | ((int)c[2] << 16) | ((int)c[3] << 24);
}
static int has_slash(char *s)
{
while (*s) {
if (s[0] == '/')
return 1;
s++;
}
return 0;
}
char *absolutize(char *p, char *d)
{
int l1;
if (p[0] == '/')
return p;
/* Strip filename off d: */
l1 = strlen(d);
while (l1 && (d[l1- 1] != '/')) {
l1--;
}
if (l1)
return do_path_append(d, l1, p);
else
return p;
}
static char *next_string(char *s)
{
return s + strlen(s) + 1;
}
int main(int argc, char **argv)
{
char *me = argv[0], *data, **new_argv;
char *exe_path, *lib_path, *dll_path;
int start, cmd_end, end, count, fd, v, x11;
int argpos, inpos, collcount = 1;
if (me[0] == '/') {
/* Absolute path */
} else if (has_slash(me)) {
/* Relative path with a directory: */
me = path_append(getcwd(NULL, 0), me);
} else {
/* We have to find the executable by searching PATH: */
char *path = 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, me);
if (executable_exists(m)) {
if (m[0] != '/')
m = path_append(getcwd(NULL, 0), m);
me = m;
break;
}
free(m);
if (more)
path = p + 1;
else
break;
}
}
/* me is now an absolute path to the binary */
start = as_int(config);
cmd_end = as_int(config + 4);
end = as_int(config + 8);
count = as_int(config + 12);
x11 = as_int(config + 16);
{
int offset, len;
offset = _coldir_offset;
while (1) {
len = strlen(_coldir + offset);
offset += len + 1;
if (!_coldir[offset])
break;
collcount++;
}
}
data = (char *)malloc(cmd_end - start);
new_argv = (char **)malloc((count + argc + (2 * collcount) + 8) * sizeof(char*));
fd = open(me, O_RDONLY, 0);
lseek(fd, start, SEEK_SET);
read(fd, data, cmd_end - start);
exe_path = data;
data = next_string(data);
lib_path = data;
data = next_string(data);
exe_path = absolutize(exe_path, me);
lib_path = absolutize(lib_path, me);
dll_path = getenv("LD_LIBRARY_PATH");
if (!dll_path) {
dll_path = "";
}
dll_path = string_append(dll_path, ":");
dll_path = string_append(lib_path, dll_path);
dll_path = string_append("LD_LIBRARY_PATH=", dll_path);
putenv(dll_path);
new_argv[0] = me;
argpos = 1;
inpos = 1;
/* Keep all X11 flags to the front: */
if (x11) {
int n;
while (inpos < argc) {
n = is_x_flag(argv[inpos]);
if (!n)
break;
if (inpos + n > argc) {
write_str(2, argv[0]);
write_str(2, ": missing an argument for ");
write_str(2, argv[inpos]);
write_str(2, "\n");
return 1;
}
while (n--) {
new_argv[argpos++] = argv[inpos++];
}
}
}
/* Add -X and -S flags */
{
int offset, len;
offset = _coldir_offset;
new_argv[argpos++] = "-X";
new_argv[argpos++] = _coldir + offset;
while (1) {
len = strlen(_coldir + offset);
offset += len + 1;
if (!_coldir[offset])
break;
new_argv[argpos++] = "-S";
new_argv[argpos++] = _coldir + offset;
}
}
/* Add -k flag */
new_argv[argpos++] = "-k";
new_argv[argpos++] = num_to_string(cmd_end);
new_argv[argpos++] = num_to_string(end);
/* Add built-in flags: */
while (count--) {
new_argv[argpos++] = data;
data = next_string(data);
}
/* Propagate new flags (after the X11 flags) */
while (inpos < argc) {
new_argv[argpos++] = argv[inpos++];
}
new_argv[argpos] = NULL;
/* Execute the original binary: */
v = execv(exe_path, new_argv);
write_str(2, argv[0]);
write_str(2, ": failed to start ");
write_str(2, exe_path);
write_str(2, "\n");
return v;
}