source for Unix native launcher
svn: r2989
This commit is contained in:
parent
9d1664a7d2
commit
e30cd7ca41
|
@ -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>
|
||||
|
|
354
src/mzscheme/dynsrc/ustart.c
Normal file
354
src/mzscheme/dynsrc/ustart.c
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user