#include "installOS.h" | |
#include <signal.h> | |
#include <unistd.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <sys/wait.h> | |
#include <sys/ioctl.h> | |
#include <errno.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <locale.h> | |
#include <gtk/gtk.h> | |
#include <gdk-pixbuf/gdk-pixbuf.h> | |
/* Global Variables */ | |
char dirSeparator = '/'; | |
char pathSeparator = ':'; | |
char* consoleVM = "java"; | |
char* defaultVM = "java"; | |
char* shippedVMDir = "jre/bin/"; | |
/* Define the special arguments for the various Java VMs. */ | |
static char* argVM_JAVA[] = { NULL }; | |
/* Define local variables . */ | |
static int saveArgc = 0; | |
static char** saveArgv = 0; | |
static gboolean gtkInitialized = FALSE; | |
static GtkWidget *label = NULL, *progress = NULL; | |
static GdkColor foreground = {0, 0, 0, 0}; | |
static GdkRectangle progressRect = {0, 0, 0, 0}, messageRect = {0, 0, 0, 0}; | |
static int value = 0, maximum = 100; | |
/* Local functions */ | |
static gboolean splashTimeout(gpointer data); | |
#ifdef MOZILLA_FIX | |
static void fixEnvForMozilla(); | |
#endif /* MOZILLA_FIX */ | |
/* Display a Message */ | |
void displayMessage(char* message) | |
{ | |
GtkWidget* dialog; | |
/* If GTK has not been initialized yet, do it now. */ | |
if (!gtkInitialized) | |
{ | |
initWindowSystem( &saveArgc, saveArgv, 1 ); | |
} | |
dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT, | |
GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, | |
"%s", message); | |
gtk_dialog_run(GTK_DIALOG (dialog)); | |
gtk_widget_destroy(dialog); | |
} | |
/* Initialize the Window System */ | |
void initWindowSystem(int* pArgc, char* argv[], int showSplash) | |
{ | |
/* Save the arguments in case displayMessage() is called in the main launcher. */ | |
if (saveArgv == 0) | |
{ | |
saveArgc = *pArgc; | |
saveArgv = argv; | |
} | |
/* If the splash screen is going to be displayed by this process */ | |
if (showSplash) | |
{ | |
/* Initialize GTK. */ | |
gtk_set_locale(); | |
gtk_init(pArgc, &argv); | |
gdk_set_program_class(officialName); | |
gtkInitialized = TRUE; | |
} | |
} | |
static void readRect(char *str, GdkRectangle *rect) { | |
int x, y, width, height; | |
char *temp = str, *comma; | |
comma = strchr(temp, ','); | |
if (comma == NULL) return; | |
comma[0] = 0; | |
x = atoi(temp); | |
temp = comma + 1; | |
comma = strchr(temp, ','); | |
if (comma == NULL) return; | |
comma[0] = 0; | |
y = atoi(temp); | |
temp = comma + 1; | |
comma = strchr(temp, ','); | |
if (comma == NULL) return; | |
comma[0] = 0; | |
width = atoi(temp); | |
temp = comma + 1; | |
height = atoi(temp); | |
rect->x = x; | |
rect->y = y; | |
rect->width = width; | |
rect->height = height; | |
} | |
static void readColor(char *str, GdkColor *color) { | |
int value = atoi(str); | |
color->red = ((value & 0xFF0000) >> 16) * 0xFF; | |
color->green = ((value & 0xFF00) >> 8) * 0xFF; | |
color->blue = ((value & 0xFF) >> 0) * 0xFF; | |
} | |
static void readInput() { | |
int available; | |
FILE *fd = stdin; | |
char *buffer = NULL, *equals = NULL, *end, *line; | |
ioctl(fileno(fd), FIONREAD, &available); | |
if (available <= 0) return; | |
buffer = malloc(available + 1); | |
available = fread(buffer, 1, available, fd); | |
buffer[available] = 0; | |
line = buffer; | |
while (line != NULL) { | |
end = strchr(line, '\n'); | |
equals = strchr(line, '='); | |
if (end != NULL) end[0] = 0; | |
if (equals != NULL) { | |
char *str = (char *)equals + 1; | |
equals[0] = 0; | |
if (strcmp(line, "maximum") == 0) { | |
maximum = atoi(str); | |
if (progress) { | |
double fraction = maximum == 0 ? 1 : (double)(value / maximum); | |
gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(progress), fraction); | |
} | |
} else if (strcmp(line, "value") == 0) { | |
value = atoi(str); | |
if (progress) { | |
double fraction = maximum == 0 ? 1 : (double)value / maximum; | |
gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(progress), fraction); | |
} | |
} else if (strcmp(line, "progressRect") == 0) { | |
readRect(str, &progressRect); | |
if (progress) { | |
gtk_fixed_move(GTK_FIXED(gtk_widget_get_parent(progress)), progress, progressRect.x, progressRect.y); | |
gtk_widget_set_size_request(GTK_WIDGET(progress), progressRect.width, progressRect.height); | |
} | |
} else if (strcmp(line, "messageRect") == 0) { | |
readRect(str, &messageRect); | |
if (label) { | |
gtk_fixed_move(GTK_FIXED(gtk_widget_get_parent(label)), label, messageRect.x, messageRect.y); | |
gtk_widget_set_size_request(GTK_WIDGET(label), messageRect.width, messageRect.height); | |
} | |
} else if (strcmp(line, "foreground") == 0) { | |
readColor(str, &foreground); | |
if (label) { | |
gtk_widget_modify_fg (label, GTK_STATE_NORMAL, &foreground); | |
} | |
} else if (strcmp(line, "message") == 0) { | |
if (label) { | |
gtk_label_set_text(GTK_LABEL(label), str); | |
} | |
} | |
} | |
if (end != NULL) line = end + 1; | |
else line = NULL; | |
} | |
free(buffer); | |
} | |
static gboolean timerProc(gpointer data) { | |
readInput(); | |
return TRUE; | |
} | |
/* Create and DIsplay the Splash Window */ | |
int showSplash( char* timeoutString, char* featureImage ) | |
{ | |
GdkPixbuf* imageData = NULL; | |
GtkWidget* image, *fixed; | |
GtkWindow* main; | |
int timeout = 0; | |
/* Determine the splash timeout value (in seconds). */ | |
if (timeoutString != NULL && strlen( timeoutString ) > 0) | |
{ | |
sscanf( timeoutString, "%d", &timeout ); | |
} | |
/* Load the feature specific splash image data if defined. */ | |
if (featureImage != NULL) | |
{ | |
imageData = gdk_pixbuf_new_from_file(featureImage, NULL); | |
} | |
/* If the splash image data could not be loaded, return an error. */ | |
if (imageData == NULL) | |
return ENOENT; | |
/* Create the image from its data. */ | |
fixed = gtk_fixed_new(); | |
image = gtk_image_new_from_pixbuf(imageData); | |
label = gtk_label_new(""); | |
progress = gtk_progress_bar_new(); | |
/* Create a top level window for the image. */ | |
main = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL)); | |
gtk_window_set_title(main, officialName); | |
gtk_container_add(GTK_CONTAINER(main), GTK_WIDGET(fixed)); | |
gtk_container_add(GTK_CONTAINER(fixed), GTK_WIDGET(image)); | |
gtk_container_add(GTK_CONTAINER(fixed), GTK_WIDGET(label)); | |
gtk_container_add(GTK_CONTAINER(fixed), GTK_WIDGET(progress)); | |
gtk_misc_set_alignment (GTK_MISC(label), 0.0f, 0.0f); | |
gtk_label_set_justify (GTK_LABEL(label), GTK_JUSTIFY_LEFT); | |
gtk_widget_modify_fg (label, GTK_STATE_NORMAL, &foreground); | |
readInput(); | |
gtk_timeout_add(50, timerProc, NULL); | |
gtk_fixed_move(GTK_FIXED(fixed), label, messageRect.x, messageRect.y); | |
gtk_widget_set_size_request(GTK_WIDGET(label), messageRect.width, messageRect.height); | |
gtk_fixed_move(GTK_FIXED(fixed), progress, progressRect.x, progressRect.y); | |
gtk_widget_set_size_request(GTK_WIDGET(progress), progressRect.width, progressRect.height); | |
gtk_widget_set_size_request(GTK_WIDGET(fixed), gdk_pixbuf_get_width(imageData), gdk_pixbuf_get_height(imageData)); | |
/* Remove window decorations and centre the window on the display. */ | |
gtk_window_set_decorated(main, FALSE); | |
gtk_window_set_position(main, GTK_WIN_POS_CENTER); | |
gtk_window_set_resizable(main, FALSE); | |
/* Set the background pixmap to NULL to avoid a gray flash when the image appears. */ | |
gtk_widget_realize(GTK_WIDGET(main)); | |
gdk_window_set_back_pixmap(GTK_WIDGET(main)->window, NULL, FALSE); | |
/* If a timeout for the splash window was given */ | |
if (timeout != 0) | |
{ | |
/* Add a timeout (in milliseconds) to bring down the splash screen. */ | |
gtk_timeout_add((timeout * 1000), splashTimeout, (gpointer) main); | |
} | |
/* Show the window and wait for the timeout (or until the process is terminated). */ | |
gtk_widget_show_all(GTK_WIDGET (main)); | |
gtk_main (); | |
label = progress = NULL; | |
return 0; | |
} | |
/* Get the window system specific VM arguments */ | |
char** getArgVM( char* vm ) | |
{ | |
char** result; | |
char* version; | |
/* Use the default arguments for a standard Java VM */ | |
result = argVM_JAVA; | |
return result; | |
} | |
/* Start the Java VM | |
* | |
* This method is called to start the Java virtual machine and to wait until it | |
* terminates. The function returns the exit code from the JVM. | |
*/ | |
int startJavaVM( char* args[] ) | |
{ | |
int jvmExitCode = 1; | |
pid_t jvmProcess; | |
int exitCode; | |
#ifdef MOZILLA_FIX | |
fixEnvForMozilla(); | |
#endif /* MOZILLA_FIX */ | |
jvmProcess = fork(); | |
if (jvmProcess == 0) | |
{ | |
/* Child process ... start the JVM */ | |
execv(args[0], args); | |
/* The JVM would not start ... return error code to parent process. */ | |
_exit(errno); | |
} | |
/* If the JVM is still running, wait for it to terminate. */ | |
if (jvmProcess != 0) | |
{ | |
wait(&exitCode); | |
if (WIFEXITED(exitCode)) | |
jvmExitCode = WEXITSTATUS(exitCode); | |
} | |
return jvmExitCode; | |
} | |
/* Splash Timeout - Hide the main window and exit the main loop. */ | |
static gboolean splashTimeout(gpointer data) | |
{ | |
GtkWidget* main = GTK_WIDGET(data); | |
gtk_widget_hide(main); | |
gtk_main_quit(); | |
return FALSE; | |
} | |
/* Set the environmnent required by the SWT Browser widget to bind to Mozilla. | |
* The SWT Browser widget relies on Mozilla on Linux. The LD_LIBRARY_PATH | |
* and the Mozilla environment variable MOZILLA_FIVE_HOME must point | |
* to the installation directory of Mozilla. | |
* | |
* 1. Use the location set by MOZILLA_FIVE_HOME if it is defined | |
* 2. Parse the file /etc/gre.conf if it is defined. This file is | |
* set by the RedtHat RPM manager. | |
*/ | |
#ifdef MOZILLA_FIX | |
void fixEnvForMozilla() { | |
static int fixed = 0; | |
if (fixed) return; | |
{ | |
char *ldPath = (char*)getenv("LD_LIBRARY_PATH"); | |
char *mozillaFiveHome = (char*)getenv("MOZILLA_FIVE_HOME"); | |
char *grePath = NULL; /* Gecko Runtime Environment Location */ | |
char *XPCOM_LIB = "libxpcom.so"; | |
fixed = 1; | |
/* Always dup the string so we can free later */ | |
if (ldPath != NULL) ldPath = strdup(ldPath); | |
else ldPath = strdup(""); | |
/* MOZILLA_FIVE_HOME (if defined) points to the Mozilla | |
* install directory. Don't look any further if it is set. | |
*/ | |
if (mozillaFiveHome != NULL) | |
{ | |
grePath = strdup(mozillaFiveHome); | |
} | |
/* The file gre.conf (if available) points to the | |
* Mozilla install directory. Don't look any further if | |
* it is set. | |
*/ | |
if (grePath == NULL) | |
{ | |
struct stat buf; | |
FILE *file = NULL; | |
#if defined(__amd64__) || defined(__x86_64__) | |
if (stat("/etc/gre64.conf", &buf) == 0) | |
{ | |
file = fopen("/etc/gre64.conf", "r"); | |
} | |
else if (stat("/etc/gre.d/gre64.conf", &buf) == 0) | |
{ | |
file = fopen("/etc/gre.d/gre64.conf", "r"); | |
} else | |
#endif | |
if (stat("/etc/gre.conf", &buf) == 0) | |
{ | |
file = fopen("/etc/gre.conf", "r"); | |
} | |
else if (stat("/etc/gre.d/gre.conf", &buf) == 0) | |
{ | |
file = fopen("/etc/gre.d/gre.conf", "r"); | |
} | |
if (file != NULL) | |
{ | |
char buffer[1024]; | |
char path[1024]; | |
while (fgets(buffer, 1024, file) != NULL) | |
{ | |
if (sscanf(buffer, "GRE_PATH=%s", path) == 1) | |
{ | |
grePath = strdup(path); | |
break; | |
} | |
} | |
fclose(file); | |
} | |
} | |
if (grePath != NULL) | |
{ | |
ldPath = (char*)realloc(ldPath, strlen(ldPath) + strlen(grePath) + 2); | |
if (strlen(ldPath) > 0) strcat(ldPath, ":"); | |
strcat(ldPath, grePath); | |
setenv("LD_LIBRARY_PATH", ldPath, 1); | |
if (mozillaFiveHome == NULL) setenv("MOZILLA_FIVE_HOME", grePath, 1); | |
free(grePath); | |
} | |
free(ldPath); | |
} | |
} | |
#endif /* MOZILLA_FIX */ | |
_TCHAR* getTempPath() | |
{ | |
_TCHAR* buffer = malloc(MAX_PATH*sizeof(_TCHAR)); | |
_TCHAR* tmp; | |
tmp = _ttempnam(_T_INSTALL("/tmp"),_T_INSTALL("_RITMP")); | |
_tcscpy(buffer,tmp); | |
_tcscat(buffer,_T_INSTALL("/")); | |
free(tmp); | |
return buffer; | |
} |