Skip to content

Replace Unix launcher with simple wrapper that executes jruby.sh #48

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions inc/Makefile-conf.mk
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,24 @@ include Makefile
OBJECTDIR=build/${CONF}/${CND_PLATFORM}

# Object Files
OBJECTFILES = ${OBJECTDIR}/argparser.o \
${OBJECTDIR}/utilsfuncs.o \
${OBJECTDIR}/ng.o \
${OBJECTDIR}/strlcpy.o \
${OBJECTDIR}/jrubyexe.o
OBJECTFILES = ${OBJECTDIR}/jrubyexe.o

ifdef JAVA_HOME
JAVA_INCLUDE = $(subst \,/,${JAVA_HOME})/include
INCLUDES = "-I${JAVA_INCLUDE}"
endif

ifdef MINGW
OBJECTFILES += ${OBJECTDIR}/utilsfuncswin.o \
${OBJECTDIR}/platformlauncher.o \
${OBJECTDIR}/jvmlauncher.o \
${OBJECTDIR}/jruby.o
OBJECTFILES +=
# Object Files
OBJECTFILES = ${OBJECTDIR}/argparser.o \
${OBJECTDIR}/utilsfuncs.o \
${OBJECTDIR}/ng.o \
${OBJECTDIR}/strlcpy.o \
${OBJECTDIR}/utilsfuncswin.o \
${OBJECTDIR}/platformlauncher.o \
${OBJECTDIR}/jvmlauncher.o \
${OBJECTDIR}/jruby.o
INCLUDES += "-I${JAVA_INCLUDE}/win32"
else
OBJECTFILES += ${OBJECTDIR}/unixlauncher.o
Expand Down
9 changes: 4 additions & 5 deletions jrubyexe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,18 @@ const char *CON_ATTACH_MSG =
"*WARNING*: The non-console JRubyW launcher is forced to attach to console.\n"
"This may cause unexpected behavior of CMD console. Use:\n"
" start /wait jrubyw.exe -Xconsole attach [args]\n";

#include "utilsfuncs.h"
#endif // JRUBYW
#else
#include "unixlauncher.h"
#endif // WIN32

#include "utilsfuncs.h"


int main(int argc, char *argv[], char* envp[]) {
#ifdef WIN32
checkLoggingArg(argc, argv, true);

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

#else // !WIN32
UnixLauncher launcher;
return launcher.run(argc, argv, envp);
return unixlauncher_run(argc, argv, envp);
#endif // WIN32
}
143 changes: 143 additions & 0 deletions unixlauncher.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
#include <errno.h>
#include <libgen.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

/*
* Copyright 2009-2025 JRuby Team (www.jruby.org).
*
* This program finds JRUBY_HOME and executes the JRuby launcher script
* contained within it.
*/

static const char script_name[] = "jruby.sh";


static char *which(const char *const executable) {
const size_t exe_length = strlen(executable);
char *exe_path = NULL;
size_t exe_path_size = 0;

// Iterate through PATH to find executable
char *dirs = getenv("PATH");
if (dirs == NULL) {
return NULL;
}
size_t dirs_length = strlen(dirs);
// Temporarily replace null terminator with colon
dirs[dirs_length] = ':';

size_t dir_head = 0;
size_t i = 0;
do {
if (dirs[i] == ':') {
// Declare convenient path variables
char *const dir = dirs + dir_head;
const size_t dir_length = i - dir_head;
const size_t new_path_length = dir_length + exe_length + 1;

// Allocate enough space for concatenated path
if (exe_path_size < new_path_length + 1) {
// Leave space for null terminator
exe_path = realloc(exe_path, new_path_length + 1);
exe_path_size = new_path_length + 1;
}

// Concatenate path and executable
memcpy(exe_path, dir, dir_length);
exe_path[dir_length] = '/';
memcpy(exe_path + dir_length + 1, executable, exe_length);
exe_path[new_path_length] = '\0';

// Check if we can execute
if (0 == access(exe_path, R_OK | X_OK)) {
goto success;
}

dir_head = i + 1;
}
} while (dirs[i++]);

// Lookup has failed, free if necessary and return NULL
if (exe_path != NULL) {
free(exe_path);
exe_path = NULL;
}
success:
// Restore null terminator
dirs[dirs_length] = '\0';

return exe_path;
}


int unixlauncher_run(int argc, char *argv[], char *envp[]) {
if (argc == 0 || argv[0][0] == '\0') {
fputs("Error: No executable provided!", stderr);
return 2;
}

// Find ourselves
char *original_self = argv[0];
char *self_path;

// Detect whether argv[0] contains forward slashes
bool self_is_path = false;
for (size_t i = 0; original_self[i]; i++) {
if (original_self[i] == '/') {
self_is_path = true;
break;
}
}

if (self_is_path) { // argv[0] is a path to an executable
self_path = realpath(original_self, NULL);
} else { // argv[0] is basename of executable
// Iterate through PATH to find script
self_path = which(argv[0]);

if (self_path == NULL) {
fprintf(stderr, "Error: Could not find %s executable\n", script_name);
return 1;
}

// Juggle malloc'd paths
char *real_path = realpath(self_path, NULL);
free(self_path);
self_path = real_path;
}

// Find our parent directory
char *script_dir = dirname(self_path);
if (self_path != script_dir) {
// Free malloc'd self_path if dirname returned statically allocated string
free(self_path);
}
size_t script_dir_length = strlen(script_dir);

// Allocate space for complete script path
size_t script_path_length = strlen(script_name) + script_dir_length + 1;
// Leave space for null terminator
char *script_path = malloc(script_path_length + 1);

// Concatenate script dir and script name
memcpy(script_path, script_dir, script_dir_length);
script_path[script_dir_length] = '/';
memcpy(script_path + script_dir_length + 1, script_name, strlen(script_name));
script_path[script_path_length] = '\0';

// Reuse argv for script command line
argv[0] = script_path;
int ret = execv(argv[0], argv);

if (ret < 0) {
fprintf(stderr, "%s: %s: %s\n", original_self, strerror(errno), script_path);
}

free(self_path);
free(script_path);
return EXIT_FAILURE;
}
131 changes: 0 additions & 131 deletions unixlauncher.cpp

This file was deleted.

20 changes: 9 additions & 11 deletions unixlauncher.h
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
/*
* Copyright 2009-2010 JRuby Team (www.jruby.org).
* Copyright 2009-2025 JRuby Team (www.jruby.org).
*/


#ifndef _UNIXLAUNCHER_H_
#define _UNIXLAUNCHER_H_

#include "argparser.h"
#ifdef __cplusplus
extern "C"
{
#endif

class UnixLauncher : public ArgParser {
public:
UnixLauncher();
virtual ~UnixLauncher();
int unixlauncher_run(int argc, char *argv[], char *envp[]);

int run(int argc, char* argv[], char* envp[]);

private:
UnixLauncher(const UnixLauncher& orig);
};
#ifdef __cplusplus
}
#endif

#endif // ! _UNIXLAUNCHER_H_
Loading