diff --git a/docs/changelog b/docs/changelog index c1df3f5..cc89313 100644 --- a/docs/changelog +++ b/docs/changelog @@ -2,7 +2,10 @@ All notable changes to this project will be documented in this file. -## ## [2.0.8] +## [2.0.9] + - - lindbergh elf mostly redone to make the loader work as a stand alone mode. + +## [2.0.8] ### Added - Changed preprocessor for avoiding multiple inclusions to #pragma once and clean some includes. ### Fixed diff --git a/src/lindbergh/lindbergh.c b/src/lindbergh/lindbergh.c index f30c0b7..65673e8 100644 --- a/src/lindbergh/lindbergh.c +++ b/src/lindbergh/lindbergh.c @@ -1,4 +1,6 @@ #include +#include +#include #include #include #include @@ -15,13 +17,37 @@ #define LD_LIBRARY_PATH "LD_LIBRARY_PATH" #define LD_PRELOAD "LD_PRELOAD" #define PRELOAD_FILE_NAME "lindbergh.so" -#define PRELOAD_FILE_FLATPAK "/app/lib32/lindbergh.so" #define TEAM "bobbydilley, retrofan, dkeruza-neo, doozer, francesco, rolel, caviar-x" #define LINDBERGH_CONFIG_PATH "LINDBERGH_CONFIG_PATH" #define MAX_PATH_LEN 1024 +/** + * @brief Calculates the CRC32 of a single byte. + * + * This function calculates the CRC32 value for a given byte of data. + * + * @param crc The current CRC32 value. + * @param data The byte of data to calculate the CRC32 for. + * @return The updated CRC32 value. + */ +uint32_t calcCrc32(uint32_t crc, uint8_t data) +{ + crc ^= data; // No shift needed; working in LSB-first order + for (int i = 0; i < 8; i++) + { + if (crc & 1) + { + crc = (crc >> 1) ^ 0xEDB88320; + } + else + { + crc = (crc >> 1); + } + } + return crc; +} + uint32_t elf_crc = 0; -char *ldPreloadLibrary = ""; // List of all lindbergh executables known, not including the test executables char *games[] = {"main.exe", @@ -126,23 +152,14 @@ uint32_t cleanElfCRC32[] = { int cleanElfCRC32Count = sizeof(cleanElfCRC32) / sizeof(uint32_t); -uint32_t calcCrc32(uint32_t crc, uint8_t data) -{ - crc ^= data; // No shift needed; working in LSB-first order - for (int i = 0; i < 8; i++) - { - if (crc & 1) - { - crc = (crc >> 1) ^ 0xEDB88320; - } - else - { - crc = (crc >> 1); - } - } - return crc; -} - +/** + * @brief Looks up a CRC value in the cleanElfCRC32 table. + * + * This function searches for a given CRC value within the cleanElfCRC32 array. + * + * @param crc The CRC value to look up. + * @return 1 if the CRC is found in the table, 0 otherwise. + */ int lookupCrcTable(uint32_t crc) { for (int x = 0; x < cleanElfCRC32Count; x++) @@ -153,6 +170,73 @@ int lookupCrcTable(uint32_t crc) return 0; } +/** + * @brief Removes double quotes from a string. + * + * This function iterates through the input string and removes any double quote characters. + * It modifies the string in place. + * + * @param str The string to remove double quotes from. + */ +void removeDoubleQuotes(char *str) +{ + if (str == NULL) + { + return; + } + + int j = 0; + for (int i = 0; str[i] != '\0'; i++) + { + if (str[i] != '"') + { + str[j] = str[i]; + j++; + } + } + str[j] = '\0'; +} + +/** + * @brief Calculates the CRC32 of a file. + * + * This function calculates the CRC32 of the specified file. + * + * @param filename The path to the file. + * @param crc The pointer to the variable that will contain the CRC32. + * @return 0 if the CRC32 was calculated successfully, -1 otherwise. + */ +int calculateFileCRC32(const char *filename, uint32_t *crc) +{ + FILE *file = fopen(filename, "rb"); + if (!file) + { + log_error("Could not open file to calculate the CRC32."); + return -1; + } + + *crc = 0xFFFFFFFF; + uint8_t buffer[4096]; + size_t bytesRead; + + while ((bytesRead = fread(buffer, 1, sizeof(buffer), file)) > 0) + { + for (size_t i = 0; i < bytesRead; i++) + { + *crc = calcCrc32(*crc, buffer[i]); + } + } + fclose(file); + return 0; +} + +/** + * @brief Checks if the ELF file is clean based on its CRC32. + * + * This function calculates the CRC32 of the specified ELF file and compares it + * against a list of known clean ELF CRC32 values. + * @param command The command line string containing the path to the ELF file. + */ void isCleanElf(char *command) { char *last_space = strrchr(command, ' '); @@ -166,38 +250,12 @@ void isCleanElf(char *command) strncpy(elfName, command, length); elfName[length] = '\0'; - // Remove double quotes from path if it was added. - int j = 0; - for (int i = 0; elfName[i] != '\0'; i++) - { - if (elfName[i] != '"') - { - elfName[j] = elfName[i]; - j++; - } - } - elfName[j] = '\0'; + removeDoubleQuotes(elfName); - FILE *file = fopen(elfName, "rb"); - if (!file) - { - log_error("Could not calculate the Elf CRC32."); + uint32_t crc; + if (calculateFileCRC32(elfName, &crc) != 0) return; - } - uint32_t crc = 0xFFFFFFFF; - uint8_t buffer[4096]; - size_t bytesRead; - - while ((bytesRead = fread(buffer, 1, sizeof(buffer), file)) > 0) - { - for (size_t i = 0; i < bytesRead; i++) - { - crc = calcCrc32(crc, buffer[i]); - } - } - - fclose(file); crc = crc ^ 0xFFFFFFFF; if (!lookupCrcTable(crc)) @@ -218,26 +276,27 @@ void isCleanElf(char *command) */ void testModePath(char *name) { + printf("name: %s\n", name); char *pos; // Check if a different testmode elf is used - pos = strstr(name, "/hod4M.elf"); + pos = strstr(name, "hod4M.elf"); if (pos != NULL) { - strcpy(pos, "/hod4testM.elf"); + strcpy(pos, "hod4testM.elf"); return; } - pos = strstr(name, "/hodexRI.elf"); + pos = strstr(name, "hodexRI.elf"); if (pos != NULL) { - strcpy(pos, "/hodextestR.elf"); + strcpy(pos, "hodextestR.elf"); return; } - pos = strstr(name, "/Jennifer\"/Jennifer"); + pos = strstr(name, "/Jennifer/\"Jennifer"); if (pos != NULL) { - strcpy(pos, "/Jennifer\"/../JenTest/JenTest"); + strcpy(pos, "/Jennifer/\"../JenTest/JenTest"); return; } @@ -248,17 +307,17 @@ void testModePath(char *name) return; } - pos = strstr(name, "/apacheM.elf"); + pos = strstr(name, "apacheM.elf"); if (pos != NULL) { - strcpy(pos, "/apachetestM.elf"); + strcpy(pos, "apachetestM.elf"); return; } - pos = strstr(name, "/vt3_Lindbergh\"/vt3_Lindbergh"); + pos = strstr(name, "/vt3_Lindbergh/\"vt3_Lindbergh"); if (pos != NULL) { - strcpy(pos, "/vt3_Lindbergh\"/vt3_testmode"); + strcpy(pos, "/vt3_Lindbergh/\"vt3_testmode"); return; } @@ -273,6 +332,13 @@ void testModePath(char *name) strcat(name, " -t"); } +/** + * @brief Checks if a given path is a valid directory. + * + * This function uses the stat system call to determine if the provided path + * corresponds to a directory. + * @param path The path to check. + */ bool isValidDirectory(const char *path) { struct stat statbuf; @@ -283,93 +349,122 @@ bool isValidDirectory(const char *path) return S_ISDIR(statbuf.st_mode); } +/** + * @brief Finds a suitable 32-bit library folder. + * + * This function searches for a directory that is likely to contain 32-bit + * libraries, based on a predefined list of candidate paths. + * @return A dynamically allocated string containing the path to the found + * directory, or NULL if no suitable directory is found. + */ char *find32bLibFolder(void) { - const char *candidates[] = {"lib32", "lib/i386-linux-gnu", "lib/i686-linux-gnu", "lib"}; - int num_candidates = sizeof(candidates) / sizeof(candidates[0]); + const char *folderCandidates[] = {"/app/lib32", "/usr/lib/i386-linux-gnu", "/usr/lib/i686-linux-gnu", "/usr/lib32", "/usr/lib"}; + int numCandidates = sizeof(folderCandidates) / sizeof(folderCandidates[0]); - char current_path[PATH_MAX]; + char currentPath[PATH_MAX]; struct stat st; - char *result_path = NULL; + char *resultPath = NULL; - for (int i = 0; i < num_candidates; ++i) + for (int i = 0; i < numCandidates; ++i) { - int written = snprintf(current_path, sizeof(current_path), "/usr/%s", candidates[i]); + int written = snprintf(currentPath, sizeof(currentPath), "%s", folderCandidates[i]); - if (written < 0 || (size_t)written >= sizeof(current_path)) + if (written < 0 || (size_t)written >= sizeof(currentPath)) continue; - if (stat(current_path, &st) == 0 && S_ISDIR(st.st_mode)) + if (stat(currentPath, &st) == 0 && S_ISDIR(st.st_mode)) { - size_t path_len = strlen(current_path); - result_path = (char *)malloc(path_len + 1); + size_t pathLen = strlen(currentPath); + resultPath = (char *)malloc(pathLen + 1); - if (result_path == NULL) + if (resultPath == NULL) { log_fatal("Failed to allocate memory for result path."); return NULL; } - strcpy(result_path, current_path); - return result_path; + strcpy(resultPath, currentPath); + return resultPath; } } return NULL; } +/** + * @brief Finds the path to the LD_PRELOAD library. + * + * This function searches for the lindbergh.so library in various locations, + * including the current directory and system library folders. + * @return A dynamically allocated string containing the path to the library, or an empty string if not found. + */ char *findLDPreloadLibrary() { - const char *library_name = PRELOAD_FILE_NAME; - static char *empty_string = ""; - char *found_path_ptr = NULL; + char *foundPathPtr = NULL; - char *search_dir = find32bLibFolder(); + char *systemLibFolder = find32bLibFolder(); - if (search_dir == NULL || search_dir[0] == '\0') + if (systemLibFolder == NULL || systemLibFolder[0] == '\0') { - log_error("Error: search_dir is NULL or empty.\n"); - return empty_string; + log_error("Error: library folder not found.\n"); + return ""; } - char full_library_path[PATH_MAX]; + char fullLibPath[PATH_MAX]; - int len_written = snprintf(full_library_path, sizeof(full_library_path), "%s/%s", search_dir, library_name); + int lenWritten = snprintf(fullLibPath, sizeof(fullLibPath), "%s/%s", systemLibFolder, PRELOAD_FILE_NAME); - if (len_written < 0 || (size_t)len_written >= sizeof(full_library_path)) + if (lenWritten < 0 || (size_t)lenWritten >= sizeof(fullLibPath)) { - log_error("find_preload_library_in_specific_dir: Warning: Constructed path is too long or invalid: %s/%s\n", search_dir, - library_name); - return empty_string; + log_error("Warning: Constructed path is too long or invalid: %s/%s\n", systemLibFolder, PRELOAD_FILE_NAME); + return ""; } - if (access(full_library_path, F_OK) == 0) + if (access(PRELOAD_FILE_NAME, F_OK) == 0) // lindbergh.so in current folder { - found_path_ptr = (char *)malloc(strlen(full_library_path) + 1); - if (found_path_ptr == NULL) - { - log_error("find_preload_library_in_specific_dir: Failed to allocate memory for result path"); - return empty_string; - } + char curDir[MAX_PATH_LEN]; + if (getcwd(curDir, sizeof(curDir)) == NULL) + return ""; + size_t len = strlen(curDir) + strlen(PRELOAD_FILE_NAME) + 1; + foundPathPtr = (char *)malloc(len + 1); + if (foundPathPtr == NULL) + return ""; else - { - strcpy(found_path_ptr, full_library_path); - return found_path_ptr; - } + snprintf(foundPathPtr, len + 1, "%s/%s", curDir, PRELOAD_FILE_NAME); } - else + else if (access(fullLibPath, F_OK) == 0) // lindbergh.so in system lib folder { - return empty_string; + foundPathPtr = (char *)malloc(strlen(fullLibPath) + 1); + if (foundPathPtr == NULL) + return ""; + else + strcpy(foundPathPtr, fullLibPath); } + else // lindbergh.so in the ELF folder. + { + return PRELOAD_FILE_NAME; + } + return foundPathPtr; } /** * Makes sure the environment variables are set correctly + * + * This function sets the LD_LIBRARY_PATH and LD_PRELOAD environment variables + * to ensure that the game can find the necessary libraries and preload the + * lindbergh.so library. + * + * @param ldLibPath The path to the LD_PRELOAD library. + * @param curDir The current working directory. + * @param gameDir The directory where the game is located. + * @param zink Flag indicating whether to use Zink. + * @param nvidia Flag indicating whether to use NVIDIA GPU. * to run the game. */ -void setEnvironmentVariables(int isFlatpak, int zink, int nvidia) +void setEnvironmentVariables(char *ldLibPath, char *curDir, char *gameDir, int zink, int nvidia) { // Ensure the library path is set correctly - char libraryPath[128] = {0}; + char libraryPath[MAX_PATH_LEN] = {0}; const char *currentLibraryPath = getenv(LD_LIBRARY_PATH); if (currentLibraryPath != NULL) @@ -380,15 +475,33 @@ void setEnvironmentVariables(int isFlatpak, int zink, int nvidia) strcat(libraryPath, ".:lib:../lib"); + char *tmpLibPath = dirname(strdup(ldLibPath)); + + if (strcmp(tmpLibPath, ".") != 0) + { + strcat(libraryPath, ":"); + strcat(libraryPath, tmpLibPath); + } + + if (curDir != NULL && curDir[0] != '\0' && strcmp(curDir, tmpLibPath) != 0) + { + strcat(libraryPath, ":"); + strcat(libraryPath, curDir); + } + + if (gameDir != NULL && gameDir[0] != '\0') + { + strcat(libraryPath, ":"); + strcat(libraryPath, gameDir); + } + setenv(LD_LIBRARY_PATH, libraryPath, 1); // Ensure the preload path is set correctly - if (isFlatpak) - setenv(LD_PRELOAD, PRELOAD_FILE_FLATPAK, 1); - else if (strcmp(ldPreloadLibrary, "") != 0) - setenv(LD_PRELOAD, ldPreloadLibrary, 1); + if (strcmp(ldLibPath, "") != 0) + setenv(LD_PRELOAD, ldLibPath, 1); else - setenv(LD_PRELOAD, PRELOAD_FILE_NAME, 1); + setenv(LD_PRELOAD, PRELOAD_FILE_NAME, 1); // Should not reach here if (zink) setenv("MESA_LOADER_DRIVER_OVERRIDE", "zink", 1); @@ -401,6 +514,11 @@ void setEnvironmentVariables(int isFlatpak, int zink, int nvidia) } /** + * @brief Prints the usage information for the Lindbergh loader. + * + * This function displays the command-line options and usage instructions for + * the Lindbergh loader. + * @param argv The command-line arguments array. * Prints the usage for the loader */ void printUsage(char *argv[]) @@ -416,10 +534,16 @@ void printUsage(char *argv[]) printf(" --version Displays the version of the loader and team's names\n"); printf(" --help Displays this usage text\n"); printf(" --config | -c Specifies configuration path\n"); - printf(" --gamepath | -g Specifies game path\n"); + printf(" --gamepath | -g Specifies game path without ELF name\n"); } /** + * @brief Lists available evdev controllers and their inputs. + * + * This function initializes the controller system and then iterates through + * the available controllers, printing their names and the names of their + * inputs. + * @return EXIT_SUCCESS on success, EXIT_FAILURE on failure. * Lists available evdev controllers and their inputs */ int listControllers() @@ -453,8 +577,10 @@ int listControllers() } /** - * Small utility to automatically detect the game and run it without - * having to type a long string in. + * @brief Prints the version information of the Lindbergh loader. + * + * This function displays the version number of the Lindbergh loader and the + * names of the team members. */ void printVersion() { printf("Lindbergh Loader v%d.%d\n", MAJOR_VERSION, MINOR_VERSION); @@ -467,7 +593,9 @@ void printVersion() { */ int main(int argc, char *argv[]) { - // Check for --version before directory operations + char gameELF[128] = {0}; + char gameDir[MAX_PATH_LEN] = {0}; + if (argc > 1 && strcmp(argv[1], "--version") == 0) { printVersion(); return EXIT_SUCCESS; @@ -483,151 +611,46 @@ int main(int argc, char *argv[]) { return listControllers(); } - - // We save the current dir to return to it later - char curDir[MAX_PATH_LEN]; - if (getcwd(curDir, sizeof(curDir)) == NULL) - { - log_error("Error: could not get the current directory."); - return EXIT_FAILURE; - } - - // Check if a game folder was passed as a parameter - char gamePath[PATH_MAX] = {0}; - for (int i = 1; i < argc; i++) - { - if (strcmp(argv[i], "-g") == 0 || strcmp(argv[i], "--gamepath") == 0) - { - if (i + 1 >= argc) - { - break; - } - strncpy(gamePath, argv[i + 1], PATH_MAX); - i += 1; - continue; - } - } - - // Look for the games - struct dirent *ent; - DIR *dir; - - if (gamePath[0] != '\0') - { - // Check if the passed folder is valid - if (!isValidDirectory(gamePath)) - { - log_error("The game folder is invalid."); - return EXIT_FAILURE; - } - dir = opendir(gamePath); - } - else - { - dir = opendir(curDir); - } - - if (dir == NULL) - { - log_error("Could not list files in current directory."); - return EXIT_FAILURE; - } - - char *game = NULL; - - int lindberghSharedObjectFound = 0; - int isFlatpak = 0; - - while ((ent = readdir(dir)) != NULL) - { - - if (ent->d_type != DT_REG) - continue; - - if (strcmp(ent->d_name, PRELOAD_FILE_NAME) == 0) - { - lindberghSharedObjectFound = 1; - continue; - } - - int index = 0; - while (game == NULL) - { - if (strcmp(games[index], "END") == 0) - break; - - if (strcmp(ent->d_name, games[index]) == 0) - { - game = games[index]; - break; - } - - index++; - } - - if (game != NULL && lindberghSharedObjectFound) - break; - } - - closedir(dir); - - ldPreloadLibrary = findLDPreloadLibrary(); - - if (!lindberghSharedObjectFound) - { - FILE *file = fopen(PRELOAD_FILE_FLATPAK, "r"); - if (file) - { - fclose(file); - isFlatpak = 1; - } - else if (strcmp(ldPreloadLibrary, "") == 0) - { - log_error("The preload object lindbergh.so was not found in this directory."); - return EXIT_FAILURE; - } - } - // Build up the command to start the game - - int testMode = 0; - int gdb = 0; - int zink = 0; - int nvidia = 0; - int forceGame = 0; - int segaboot = 0; - char extConfigPath[PATH_MAX] = {0}; - char forceGamePath[128] = {0}; + int testMode = false; + int gdb = false; + int zink = false; + int nvidia = false; + int forceGame = false; + int segaboot = false; + char *extConfigPath = NULL; + char *passedGamePath = NULL; + char *forcedGamePath = NULL; for (int i = 1; i < argc; i++) { if (strcmp(argv[i], "-t") == 0 || strcmp(argv[i], "--test") == 0) { - testMode = 1; + testMode = true; continue; } if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--segaboot") == 0) { - segaboot = 1; + segaboot = true; continue; } if (strcmp(argv[i], "--gdb") == 0) { - gdb = 1; + gdb = true; continue; } if (strcmp(argv[i], "-z") == 0 || strcmp(argv[i], "--zink") == 0) { - zink = 1; + zink = true; continue; } if (strcmp(argv[i], "-n") == 0 || strcmp(argv[i], "--nvidia") == 0) { - nvidia = 1; + nvidia = true; continue; } @@ -637,7 +660,7 @@ int main(int argc, char *argv[]) { break; } - strncpy(extConfigPath, argv[i + 1], PATH_MAX); + extConfigPath = strdup(argv[i + 1]); i += 1; continue; } @@ -645,46 +668,153 @@ int main(int argc, char *argv[]) if (strcmp(argv[i], "-g") == 0 || strcmp(argv[i], "--gamepath") == 0) { if (i + 1 >= argc) + { break; + } + passedGamePath = strdup(argv[i + 1]); + i += 1; continue; } // Treat the argument as the game name - strcpy(forceGamePath, argv[i]); - forceGame = 1; + forcedGamePath = strdup(argv[i]); + forceGame = true; + } + + // We save the current dir to return to it later + char curDir[MAX_PATH_LEN]; + if (getcwd(curDir, sizeof(curDir)) == NULL) + { + log_error("Error: could not get the current directory."); + return EXIT_FAILURE; + } + + char command[PATH_MAX] = {0}; + char *forcedGameDir; + char *forcedGameElf; + if (forceGame) + { + if (forcedGamePath != NULL) + { + forcedGameDir = dirname(strdup(forcedGamePath)); + forcedGameElf = basename(strdup(forcedGamePath)); + + if (strcmp(forcedGameDir, ".") == 0) // Only the ELF file name was passed. + { + if (passedGamePath[0] != '\0') + snprintf(gameDir, MAX_PATH_LEN, "%s", passedGamePath); + else + snprintf(gameDir, MAX_PATH_LEN, "./"); + } + else + { + if (passedGamePath != NULL) // ELF with path and also -g option pointing to a folder + log_warn("Warning: elf passed with a path, and -g option enabled. Ignoring -g option."); + + snprintf(gameDir, MAX_PATH_LEN, "%s", forcedGameDir); + } + + if (strcmp(forcedGameElf, ".") != 0) + strcpy(gameELF, forcedGameElf); + // Check if the passed folder is valid + if (!isValidDirectory(gameDir)) + { + log_error("%s is not a valid directory here.", gameDir); + return EXIT_FAILURE; + } + } + } + else + { + // Look for the game ELF's + struct dirent *ent; + DIR *dir; + + if (passedGamePath != NULL && passedGamePath[0] != '\0') + { + snprintf(gameDir, MAX_PATH_LEN, "%s", passedGamePath); + + // Check if the passed folder is valid + if (!isValidDirectory(gameDir)) + { + log_error("%s is not a valid directory.", gameDir); + return EXIT_FAILURE; + } + dir = opendir(gameDir); + } + else + { + snprintf(gameDir, MAX_PATH_LEN, "%s", curDir); + dir = opendir(curDir); + } + + if (dir == NULL) + { + log_error("Could not list files in current directory."); + return EXIT_FAILURE; + } + + bool found = false; + while ((ent = readdir(dir)) != NULL) + { + if (ent->d_type != DT_REG) + continue; + + int index = 0; + while (!found) + { + if (strcmp(games[index], "END") == 0) + break; + + if (strcmp(ent->d_name, games[index]) == 0) + { + strcpy(gameELF, games[index]); + found = true; + break; + } + index++; + } + } + closedir(dir); + } + + if (segaboot) + { + strcpy(gameELF, "segaboot"); + testMode = true; + } + + if (gameELF[0] == '\0') + { + log_error("No lindbergh game found in this directory."); + printUsage(argv); + return EXIT_FAILURE; + } + + sprintf(command, "\"%s/\"%s", gameDir, gameELF); + + char *ldPreloadLibrary = findLDPreloadLibrary(); + + if (strcmp(ldPreloadLibrary, PRELOAD_FILE_NAME) == 0) + { + char lindberghSoPath[MAX_PATH_LEN]; + if (gameDir[0] != '\0') + snprintf(lindberghSoPath, strlen(gameDir) + sizeof(PRELOAD_FILE_NAME) + 1, "%s/%s", gameDir, PRELOAD_FILE_NAME); + + if (access(lindberghSoPath, F_OK) != 0) + { + log_error("The preload object lindbergh.so was not found."); + return EXIT_FAILURE; + } + ldPreloadLibrary = strdup(lindberghSoPath); } // Ensure environment variables are set correctly - setEnvironmentVariables(isFlatpak, zink, nvidia); - - char command[128] = {0}; - if (gamePath[0] != '\0') - sprintf(command, "\"%s\"/", gamePath); - else - strcpy(command, "./"); - - if (forceGame) - { - strcat(command, forceGamePath); - } - else if (segaboot) - { - strcat(command, "segaboot -t"); - } - else - { - if (game == NULL) - { - log_error("No lindbergh game found in this directory."); - return EXIT_FAILURE; - } - strcat(command, game); - } + setEnvironmentVariables(ldPreloadLibrary, curDir, gameDir, zink, nvidia); if (testMode) testModePath(command); - isCleanElf(command); if (gdb) @@ -695,16 +825,16 @@ int main(int argc, char *argv[]) strcpy(command, temp); } - if (extConfigPath[0] != '\0') + if (extConfigPath != NULL && extConfigPath[0] != '\0') { setenv(LINDBERGH_CONFIG_PATH, extConfigPath, 1); } log_info("Starting $ %s", command); - if (gamePath[0] != '\0') + if (gameDir[0] != '\0') { - if (chdir(gamePath) != 0) + if (chdir(gameDir) != 0) { log_error("Could not change to game path."); return EXIT_FAILURE; @@ -712,7 +842,7 @@ int main(int argc, char *argv[]) } int sysCmd = system(command); - if (gamePath[0] != '\0') + if (gameDir[0] != '\0') { if (chdir(curDir) != 0) {