diff --git a/xulrunner/stub/nsXULStub.cpp b/xulrunner/stub/nsXULStub.cpp --- a/xulrunner/stub/nsXULStub.cpp +++ b/xulrunner/stub/nsXULStub.cpp @@ -109,16 +109,54 @@ static void Output(PRBool isError, const MessageBoxW(NULL, wide_msg, L"XULRunner", flags); #else vfprintf(stderr, fmt, ap); #endif va_end(ap); } +/** + * Return true if |arg| matches the given argument name. + */ +static PRBool IsArg(const char* arg, const char* s) +{ + if (*arg == '-') + { + if (*++arg == '-') + ++arg; + return !strcasecmp(arg, s); + } + +#if defined(XP_WIN) || defined(XP_OS2) + if (*arg == '/') + return !strcasecmp(++arg, s); +#endif + + return PR_FALSE; +} + +static nsresult SetEnvironmentVariable(const char* aEnvVar, const char* aValue) +{ +#if defined(XP_MACOSX) || defined(XP_UNIX) + if (!setenv(aEnvVar, aValue, 1)) + return NS_OK; +#elif defined(WINCE) + static char kAppEnv[MAXPATHLEN]; + _snwprintf(kAppEnv, MAXPATHLEN, L"%s=%s", aEnvVar, aValue); + if (!putenv(kAppEnv)) + return NS_OK; +#elif defined(XP_WIN) + if(::SetEnvironmentVariableA(aEnvVar, aValue)) + return NS_OK; +#endif + + return NS_ERROR_FAILURE; +} + class AutoAppData { public: AutoAppData(nsILocalFile* aINIFile) : mAppData(nsnull) { nsresult rv = XRE_CreateAppData(aINIFile, &mAppData); if (NS_FAILED(rv)) mAppData = nsnull; } @@ -144,60 +182,99 @@ main(int argc, char **argv) nsresult rv; char *lastSlash; char iniPath[MAXPATHLEN]; char tmpPath[MAXPATHLEN]; char greDir[MAXPATHLEN]; PRBool greFound = PR_FALSE; + const char *appDataFile; +#if defined(XP_WIN) + ::GetEnvironmentVariableA("XUL_APP_FILE", appDataFile, MAXPATHLEN); +#else + appDataFile = getenv("XUL_APP_FILE"); +#endif + if (!appDataFile || !*appDataFile) + if (argc > 1 && IsArg(argv[1], "app")) { + if (argc == 2) { + Output(PR_FALSE, "specify APP-FILE (optional)\n"); + return 1; + } + argv[1] = argv[0]; + ++argv; + --argc; + + appDataFile = argv[1]; + argv[1] = argv[0]; + ++argv; + --argc; + + const char kEnvVar[] = "XUL_APP_FILE"; + rv = SetEnvironmentVariable(kEnvVar, appDataFile); + if (NS_FAILED(rv)) + Output(PR_FALSE, "Couldn't set %s.\n", kEnvVar); + } + #if defined(XP_MACOSX) CFBundleRef appBundle = CFBundleGetMainBundle(); if (!appBundle) return 1; CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(appBundle); if (!resourcesURL) return 1; CFURLRef absResourcesURL = CFURLCopyAbsoluteURL(resourcesURL); CFRelease(resourcesURL); if (!absResourcesURL) return 1; + CFStringRef appDataFileStr; + appDataFileStr = (appDataFile && *appDataFile) ? + CFStringCreateWithCString(NULL, appDataFile, kCFStringEncodingUTF8) : + CFSTR("application.ini"); + CFURLRef iniFileURL = CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault, absResourcesURL, - CFSTR("application.ini"), + appDataFileStr, false); CFRelease(absResourcesURL); if (!iniFileURL) return 1; CFStringRef iniPathStr = CFURLCopyFileSystemPath(iniFileURL, kCFURLPOSIXPathStyle); CFRelease(iniFileURL); + CFRelease(appDataFileStr); if (!iniPathStr) return 1; CFStringGetCString(iniPathStr, iniPath, sizeof(iniPath), kCFStringEncodingUTF8); CFRelease(iniPathStr); #else -#ifdef XP_WIN - wchar_t wide_path[MAX_PATH]; - if (!::GetModuleFileNameW(NULL, wide_path, MAX_PATH)) - return 1; - - WideCharToMultiByte(CP_ACP, 0, wide_path,-1, - iniPath, MAX_PATH, NULL, NULL); - - +#if defined (XP_WIN) + if (!(appDataFile && *appDataFile)) { + wchar_t wide_path[MAX_PATH]; + if (!::GetModuleFileNameW(NULL, wide_path, MAX_PATH)) + return 1; + + WideCharToMultiByte(CP_ACP, 0, wide_path,-1, + iniPath, MAX_PATH, NULL, NULL); + } else { + wchar_t wAppDataFile[MAX_PATH]; + wchar_t wIniPath[MAX_PATH]; + MultiByteToWideChar(CP_ACP, 0, appDataFile, -1, wAppDataFile, MAX_PATH); + _wfullpath(wIniPath, wAppDataFile, MAX_PATH); + WideCharToMultiByte(CP_ACP, 0, wIniPath, -1, iniPath, MAX_PATH, 0, 0); + } #elif defined(XP_OS2) PPIB ppib; PTIB ptib; DosGetInfoBlocks(&ptib, &ppib); DosQueryModuleName(ppib->pib_hmte, sizeof(iniPath), iniPath); #elif defined(XP_BEOS) @@ -218,38 +295,40 @@ main(int argc, char **argv) // // 1) use realpath() on argv[0], which works unless we're loaded from the // PATH // 2) manually walk through the PATH and look for ourself // 3) give up struct stat fileStat; - if (!realpath(argv[0], iniPath) || stat(iniPath, &fileStat)) { - const char *path = getenv("PATH"); - if (!path) - return 1; + if (!realpath(appDataFile, iniPath) || stat(iniPath, &fileStat)) { + if (!realpath(argv[0], iniPath) || stat(iniPath, &fileStat)) { + const char *path = getenv("PATH"); + if (!path) + return 1; char *pathdup = strdup(path); if (!pathdup) return 1; - PRBool found = PR_FALSE; - char *token = strtok(pathdup, ":"); - while (token) { - sprintf(tmpPath, "%s/%s", token, argv[0]); - if (realpath(tmpPath, iniPath) && stat(iniPath, &fileStat) == 0) { - found = PR_TRUE; - break; + PRBool found = PR_FALSE; + char *token = strtok(pathdup, ":"); + while (token) { + sprintf(tmpPath, "%s/%s", token, argv[0]); + if (realpath(tmpPath, iniPath) && stat(iniPath, &fileStat) == 0) { + found = PR_TRUE; + break; + } + token = strtok(NULL, ":"); } - token = strtok(NULL, ":"); + free (pathdup); + if (!found) + return 1; } - free (pathdup); - if (!found) - return 1; } #endif lastSlash = strrchr(iniPath, PATH_SEPARATOR_CHAR); if (!lastSlash) return 1; *(++lastSlash) = '\0';