Skip to content

Commit 10d4e56

Browse files
authored
Merge pull request #48 from mrnoname1000/simple-unix-launcher
Replace Unix launcher with simple wrapper that executes jruby.sh
2 parents a477095 + 964a5a1 commit 10d4e56

File tree

5 files changed

+167
-156
lines changed

5 files changed

+167
-156
lines changed

inc/Makefile-conf.mk

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,22 +21,24 @@ include Makefile
2121
OBJECTDIR=build/${CONF}/${CND_PLATFORM}
2222

2323
# Object Files
24-
OBJECTFILES = ${OBJECTDIR}/argparser.o \
25-
${OBJECTDIR}/utilsfuncs.o \
26-
${OBJECTDIR}/ng.o \
27-
${OBJECTDIR}/strlcpy.o \
28-
${OBJECTDIR}/jrubyexe.o
24+
OBJECTFILES = ${OBJECTDIR}/jrubyexe.o
2925

3026
ifdef JAVA_HOME
3127
JAVA_INCLUDE = $(subst \,/,${JAVA_HOME})/include
3228
INCLUDES = "-I${JAVA_INCLUDE}"
3329
endif
3430

3531
ifdef MINGW
36-
OBJECTFILES += ${OBJECTDIR}/utilsfuncswin.o \
37-
${OBJECTDIR}/platformlauncher.o \
38-
${OBJECTDIR}/jvmlauncher.o \
39-
${OBJECTDIR}/jruby.o
32+
OBJECTFILES +=
33+
# Object Files
34+
OBJECTFILES = ${OBJECTDIR}/argparser.o \
35+
${OBJECTDIR}/utilsfuncs.o \
36+
${OBJECTDIR}/ng.o \
37+
${OBJECTDIR}/strlcpy.o \
38+
${OBJECTDIR}/utilsfuncswin.o \
39+
${OBJECTDIR}/platformlauncher.o \
40+
${OBJECTDIR}/jvmlauncher.o \
41+
${OBJECTDIR}/jruby.o
4042
INCLUDES += "-I${JAVA_INCLUDE}/win32"
4143
else
4244
OBJECTFILES += ${OBJECTDIR}/unixlauncher.o

jrubyexe.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,18 +50,18 @@ const char *CON_ATTACH_MSG =
5050
"*WARNING*: The non-console JRubyW launcher is forced to attach to console.\n"
5151
"This may cause unexpected behavior of CMD console. Use:\n"
5252
" start /wait jrubyw.exe -Xconsole attach [args]\n";
53+
54+
#include "utilsfuncs.h"
5355
#endif // JRUBYW
5456
#else
5557
#include "unixlauncher.h"
5658
#endif // WIN32
5759

58-
#include "utilsfuncs.h"
59-
6060

6161
int main(int argc, char *argv[], char* envp[]) {
62+
#ifdef WIN32
6263
checkLoggingArg(argc, argv, true);
6364

64-
#ifdef WIN32
6565
#ifdef JRUBYW
6666
if (!isConsoleAttached()) {
6767
logMsg("Console is not attached, assume WINDOW mode");
@@ -78,7 +78,6 @@ int main(int argc, char *argv[], char* envp[]) {
7878
return loader.start("jruby.dll", argc - 1, argv + 1, argv[0]);
7979

8080
#else // !WIN32
81-
UnixLauncher launcher;
82-
return launcher.run(argc, argv, envp);
81+
return unixlauncher_run(argc, argv, envp);
8382
#endif // WIN32
8483
}

unixlauncher.c

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
#include <errno.h>
2+
#include <libgen.h>
3+
#include <stdbool.h>
4+
#include <stdio.h>
5+
#include <stdlib.h>
6+
#include <string.h>
7+
#include <unistd.h>
8+
9+
/*
10+
* Copyright 2009-2025 JRuby Team (www.jruby.org).
11+
*
12+
* This program finds JRUBY_HOME and executes the JRuby launcher script
13+
* contained within it.
14+
*/
15+
16+
static const char script_name[] = "jruby.sh";
17+
18+
19+
static char *which(const char *const executable) {
20+
const size_t exe_length = strlen(executable);
21+
char *exe_path = NULL;
22+
size_t exe_path_size = 0;
23+
24+
// Iterate through PATH to find executable
25+
char *dirs = getenv("PATH");
26+
if (dirs == NULL) {
27+
return NULL;
28+
}
29+
size_t dirs_length = strlen(dirs);
30+
// Temporarily replace null terminator with colon
31+
dirs[dirs_length] = ':';
32+
33+
size_t dir_head = 0;
34+
size_t i = 0;
35+
do {
36+
if (dirs[i] == ':') {
37+
// Declare convenient path variables
38+
char *const dir = dirs + dir_head;
39+
const size_t dir_length = i - dir_head;
40+
const size_t new_path_length = dir_length + exe_length + 1;
41+
42+
// Allocate enough space for concatenated path
43+
if (exe_path_size < new_path_length + 1) {
44+
// Leave space for null terminator
45+
exe_path = realloc(exe_path, new_path_length + 1);
46+
exe_path_size = new_path_length + 1;
47+
}
48+
49+
// Concatenate path and executable
50+
memcpy(exe_path, dir, dir_length);
51+
exe_path[dir_length] = '/';
52+
memcpy(exe_path + dir_length + 1, executable, exe_length);
53+
exe_path[new_path_length] = '\0';
54+
55+
// Check if we can execute
56+
if (0 == access(exe_path, R_OK | X_OK)) {
57+
goto success;
58+
}
59+
60+
dir_head = i + 1;
61+
}
62+
} while (dirs[i++]);
63+
64+
// Lookup has failed, free if necessary and return NULL
65+
if (exe_path != NULL) {
66+
free(exe_path);
67+
exe_path = NULL;
68+
}
69+
success:
70+
// Restore null terminator
71+
dirs[dirs_length] = '\0';
72+
73+
return exe_path;
74+
}
75+
76+
77+
int unixlauncher_run(int argc, char *argv[], char *envp[]) {
78+
if (argc == 0 || argv[0][0] == '\0') {
79+
fputs("Error: No executable provided!", stderr);
80+
return 2;
81+
}
82+
83+
// Find ourselves
84+
char *original_self = argv[0];
85+
char *self_path;
86+
87+
// Detect whether argv[0] contains forward slashes
88+
bool self_is_path = false;
89+
for (size_t i = 0; original_self[i]; i++) {
90+
if (original_self[i] == '/') {
91+
self_is_path = true;
92+
break;
93+
}
94+
}
95+
96+
if (self_is_path) { // argv[0] is a path to an executable
97+
self_path = realpath(original_self, NULL);
98+
} else { // argv[0] is basename of executable
99+
// Iterate through PATH to find script
100+
self_path = which(argv[0]);
101+
102+
if (self_path == NULL) {
103+
fprintf(stderr, "Error: Could not find %s executable\n", script_name);
104+
return 1;
105+
}
106+
107+
// Juggle malloc'd paths
108+
char *real_path = realpath(self_path, NULL);
109+
free(self_path);
110+
self_path = real_path;
111+
}
112+
113+
// Find our parent directory
114+
char *script_dir = dirname(self_path);
115+
if (self_path != script_dir) {
116+
// Free malloc'd self_path if dirname returned statically allocated string
117+
free(self_path);
118+
}
119+
size_t script_dir_length = strlen(script_dir);
120+
121+
// Allocate space for complete script path
122+
size_t script_path_length = strlen(script_name) + script_dir_length + 1;
123+
// Leave space for null terminator
124+
char *script_path = malloc(script_path_length + 1);
125+
126+
// Concatenate script dir and script name
127+
memcpy(script_path, script_dir, script_dir_length);
128+
script_path[script_dir_length] = '/';
129+
memcpy(script_path + script_dir_length + 1, script_name, strlen(script_name));
130+
script_path[script_path_length] = '\0';
131+
132+
// Reuse argv for script command line
133+
argv[0] = script_path;
134+
int ret = execv(argv[0], argv);
135+
136+
if (ret < 0) {
137+
fprintf(stderr, "%s: %s: %s\n", original_self, strerror(errno), script_path);
138+
}
139+
140+
free(self_path);
141+
free(script_path);
142+
return EXIT_FAILURE;
143+
}

unixlauncher.cpp

Lines changed: 0 additions & 131 deletions
This file was deleted.

unixlauncher.h

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,20 @@
11
/*
2-
* Copyright 2009-2010 JRuby Team (www.jruby.org).
2+
* Copyright 2009-2025 JRuby Team (www.jruby.org).
33
*/
44

55

66
#ifndef _UNIXLAUNCHER_H_
77
#define _UNIXLAUNCHER_H_
88

9-
#include "argparser.h"
9+
#ifdef __cplusplus
10+
extern "C"
11+
{
12+
#endif
1013

11-
class UnixLauncher : public ArgParser {
12-
public:
13-
UnixLauncher();
14-
virtual ~UnixLauncher();
14+
int unixlauncher_run(int argc, char *argv[], char *envp[]);
1515

16-
int run(int argc, char* argv[], char* envp[]);
17-
18-
private:
19-
UnixLauncher(const UnixLauncher& orig);
20-
};
16+
#ifdef __cplusplus
17+
}
18+
#endif
2119

2220
#endif // ! _UNIXLAUNCHER_H_

0 commit comments

Comments
 (0)