diff --git a/browser/app/nsBrowserApp.cpp b/browser/app/nsBrowserApp.cpp index 022fbaed4586..51e99fc94634 100644 --- a/browser/app/nsBrowserApp.cpp +++ b/browser/app/nsBrowserApp.cpp @@ -232,9 +232,9 @@ static int do_main(int argc, char* argv[], char* envp[]) } static nsresult -InitXPCOMGlue() +InitXPCOMGlue(const char *argv0) { - UniqueFreePtr exePath = BinaryPath::Get(); + UniqueFreePtr exePath = BinaryPath::Get(argv0); if (!exePath) { Output("Couldn't find the application directory.\n"); return NS_ERROR_FAILURE; @@ -272,7 +272,7 @@ int main(int argc, char* argv[], char* envp[]) } #endif - nsresult rv = InitXPCOMGlue(); + nsresult rv = InitXPCOMGlue(argv[0]); if (NS_FAILED(rv)) { return 255; } @@ -290,7 +290,7 @@ int main(int argc, char* argv[], char* envp[]) DllBlocklist_Initialize(); #endif - nsresult rv = InitXPCOMGlue(); + nsresult rv = InitXPCOMGlue(argv[0]); if (NS_FAILED(rv)) { return 255; } diff --git a/ipc/glue/ScopedXREEmbed.cpp b/ipc/glue/ScopedXREEmbed.cpp index 4f19b9502b9a..b419fdb42175 100644 --- a/ipc/glue/ScopedXREEmbed.cpp +++ b/ipc/glue/ScopedXREEmbed.cpp @@ -46,8 +46,17 @@ ScopedXREEmbed::SetAppDir(const nsACString& aPath) void ScopedXREEmbed::Start() { + std::string path; +#if defined(OS_WIN) + path = WideToUTF8(CommandLine::ForCurrentProcess()->program()); +#elif defined(OS_POSIX) + path = CommandLine::ForCurrentProcess()->argv()[0]; +#else +# error Sorry +#endif + nsCOMPtr localFile; - nsresult rv = XRE_GetBinaryPath(getter_AddRefs(localFile)); + nsresult rv = XRE_GetBinaryPath(path.c_str(), getter_AddRefs(localFile)); if (NS_FAILED(rv)) return; diff --git a/js/xpconnect/src/XPCShellImpl.cpp b/js/xpconnect/src/XPCShellImpl.cpp index 0c4841ad690f..c0749a6af63f 100644 --- a/js/xpconnect/src/XPCShellImpl.cpp +++ b/js/xpconnect/src/XPCShellImpl.cpp @@ -1115,7 +1115,7 @@ XRE_XPCShellMain(int argc, char** argv, char** envp, { // Start scoping nsCOMPtrs nsCOMPtr appFile; - rv = XRE_GetBinaryPath(getter_AddRefs(appFile)); + rv = XRE_GetBinaryPath(argv[0], getter_AddRefs(appFile)); if (NS_FAILED(rv)) { printf("Couldn't find application file.\n"); return 1; diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index 97e68fc1e468..6ec497033ebf 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -1875,9 +1875,9 @@ XRE_InitOmnijar(nsIFile* greOmni, nsIFile* appOmni) } nsresult -XRE_GetBinaryPath(nsIFile* *aResult) +XRE_GetBinaryPath(const char* argv0, nsIFile* *aResult) { - return mozilla::BinaryPath::GetFile(aResult); + return mozilla::BinaryPath::GetFile(argv0, aResult); } #ifdef XP_WIN @@ -1916,7 +1916,7 @@ static nsresult LaunchChild(nsINativeAppSupport* aNative, LaunchChildMac(gRestartArgc, gRestartArgv); #else nsCOMPtr lf; - nsresult rv = XRE_GetBinaryPath(getter_AddRefs(lf)); + nsresult rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf)); if (NS_FAILED(rv)) return rv; @@ -4785,7 +4785,7 @@ XREMain::XRE_main(int argc, char* argv[], const BootstrapConfig& aConfig) gAppData = mAppData.get(); nsCOMPtr binFile; - rv = XRE_GetBinaryPath(getter_AddRefs(binFile)); + rv = XRE_GetBinaryPath(argv[0], getter_AddRefs(binFile)); NS_ENSURE_SUCCESS(rv, 1); rv = binFile->GetPath(gAbsoluteArgv0Path); @@ -4793,7 +4793,7 @@ XREMain::XRE_main(int argc, char* argv[], const BootstrapConfig& aConfig) if (!mAppData->xreDirectory) { nsCOMPtr lf; - rv = XRE_GetBinaryPath(getter_AddRefs(lf)); + rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf)); if (NS_FAILED(rv)) return 2; @@ -4976,7 +4976,7 @@ XRE_InitCommandLine(int aArgc, char* aArgv[]) // get the canonical version of the binary's path nsCOMPtr binFile; - rv = XRE_GetBinaryPath(getter_AddRefs(binFile)); + rv = XRE_GetBinaryPath(aArgv[0], getter_AddRefs(binFile)); if (NS_FAILED(rv)) return NS_ERROR_FAILURE; diff --git a/toolkit/xre/nsUpdateDriver.cpp b/toolkit/xre/nsUpdateDriver.cpp index 5f56f753cb5b..bdbc1cf27a57 100644 --- a/toolkit/xre/nsUpdateDriver.cpp +++ b/toolkit/xre/nsUpdateDriver.cpp @@ -508,7 +508,7 @@ ApplyUpdate(nsIFile *greDir, nsIFile *updateDir, nsIFile *appDir, int appArgc, // Get the application file path used by the updater to restart the // application after the update has finished. nsCOMPtr appFile; - XRE_GetBinaryPath(getter_AddRefs(appFile)); + XRE_GetBinaryPath(appArgv[0], getter_AddRefs(appFile)); if (!appFile) { return; } diff --git a/toolkit/xre/nsXREDirProvider.cpp b/toolkit/xre/nsXREDirProvider.cpp index 546612d39562..08e31da5a484 100644 --- a/toolkit/xre/nsXREDirProvider.cpp +++ b/toolkit/xre/nsXREDirProvider.cpp @@ -426,9 +426,9 @@ nsXREDirProvider::GetFile(const char* aProperty, bool* aPersistent, else if (!strcmp(aProperty, NS_APP_USER_PROFILES_LOCAL_ROOT_DIR)) { rv = GetUserProfilesLocalDir(getter_AddRefs(file), nullptr, nullptr, nullptr); } - else if (!strcmp(aProperty, XRE_EXECUTABLE_FILE)) { + else if (!strcmp(aProperty, XRE_EXECUTABLE_FILE) && gArgv[0]) { nsCOMPtr lf; - rv = XRE_GetBinaryPath(getter_AddRefs(lf)); + rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf)); if (NS_SUCCEEDED(rv)) file = lf; } @@ -928,7 +928,7 @@ nsXREDirProvider::GetFilesInternal(const char* aProperty, if (mozilla::Preferences::GetBool("plugins.load_appdir_plugins", false)) { nsCOMPtr appdir; - rv = XRE_GetBinaryPath(getter_AddRefs(appdir)); + rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(appdir)); if (NS_SUCCEEDED(rv)) { appdir->SetNativeLeafName(NS_LITERAL_CSTRING("plugins")); directories.AppendObject(appdir); diff --git a/xpcom/build/BinaryPath.h b/xpcom/build/BinaryPath.h index a078695af25b..617fd2e0b9d1 100644 --- a/xpcom/build/BinaryPath.h +++ b/xpcom/build/BinaryPath.h @@ -13,17 +13,8 @@ #elif defined(XP_MACOSX) #include #elif defined(XP_UNIX) -#include -#include -#include -#endif -#if defined(__FreeBSD__) || defined(__DragonFly__) || \ - defined(__FreeBSD_kernel__) || defined(__NetBSD__) || \ - defined(__OpenBSD__) -#include -#endif -#if defined(__OpenBSD__) #include +#include #endif #include "mozilla/UniquePtr.h" #include "mozilla/UniquePtrExtensions.h" @@ -40,10 +31,10 @@ class BinaryPath { public: #ifdef XP_WIN - static nsresult Get(char aResult[MAXPATHLEN]) + static nsresult Get(const char* argv0, char aResult[MAXPATHLEN]) { wchar_t wide_path[MAXPATHLEN]; - nsresult rv = GetW(wide_path); + nsresult rv = GetW(argv0, wide_path); if (NS_FAILED(rv)) { return rv; } @@ -58,7 +49,7 @@ public: static wchar_t exeLongPath[MAXPATHLEN] = L""; if (!cached) { - nsresult rv = GetW(exeLongPath); + nsresult rv = GetW(nullptr, exeLongPath); if (NS_FAILED(rv)) { return rv; @@ -79,7 +70,7 @@ public: } private: - static nsresult GetW(wchar_t aResult[MAXPATHLEN]) + static nsresult GetW(const char* argv0, wchar_t aResult[MAXPATHLEN]) { static bool cached = false; static wchar_t moduleFileName[MAXPATHLEN] = L""; @@ -100,7 +91,7 @@ private: } #elif defined(XP_MACOSX) - static nsresult Get(char aResult[MAXPATHLEN]) + static nsresult Get(const char* argv0, char aResult[MAXPATHLEN]) { // Works even if we're not bundled. CFBundleRef appBundle = CFBundleGetMainBundle(); @@ -140,7 +131,7 @@ private: } #elif defined(ANDROID) - static nsresult Get(char aResult[MAXPATHLEN]) + static nsresult Get(const char* argv0, char aResult[MAXPATHLEN]) { // On Android, we use the GRE_HOME variable that is set by the Java // bootstrap code. @@ -154,72 +145,14 @@ private: return NS_OK; } -#elif defined(XP_LINUX) || defined(XP_SOLARIS) - static nsresult Get(char aResult[MAXPATHLEN]) - { -# if defined(XP_SOLARIS) - const char path[] = "/proc/self/path/a.out"; -# else - const char path[] = "/proc/self/exe"; -# endif - - ssize_t len = readlink(path, aResult, MAXPATHLEN - 1); - if (len < 0) { - return NS_ERROR_FAILURE; - } - aResult[len] = '\0'; - return NS_OK; - } - -#elif defined(__FreeBSD__) || defined(__DragonFly__) || \ - defined(__FreeBSD_kernel__) || defined(__NetBSD__) - static nsresult Get(char aResult[MAXPATHLEN]) - { - int mib[4]; - mib[0] = CTL_KERN; -#ifdef __NetBSD__ - mib[1] = KERN_PROC_ARGS; - mib[2] = -1; - mib[3] = KERN_PROC_PATHNAME; -#else - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PATHNAME; - mib[3] = -1; -#endif - - size_t len = MAXPATHLEN; - if (sysctl(mib, 4, aResult, &len, nullptr, 0) < 0) { - return NS_ERROR_FAILURE; - } - - return NS_OK; - } - -#elif defined(__OpenBSD__) - static nsresult Get(char aResult[MAXPATHLEN]) - { - int mib[4]; - mib[0] = CTL_KERN; - mib[1] = KERN_PROC_ARGS; - mib[2] = getpid(); - mib[3] = KERN_PROC_ARGV; - - size_t len = 0; - if (sysctl(mib, 4, nullptr, &len, nullptr, 0) < 0) { - return NS_ERROR_FAILURE; - } - - auto argv = MakeUnique(len / sizeof(const char*)); - if (sysctl(mib, 4, argv.get(), &len, nullptr, 0) < 0) { - return NS_ERROR_FAILURE; - } - - return GetFromArgv0(argv[0], aResult); - } - - static nsresult GetFromArgv0(const char* aArgv0, char aResult[MAXPATHLEN]) +#elif defined(XP_UNIX) + static nsresult Get(const char* aArgv0, char aResult[MAXPATHLEN]) { struct stat fileStat; + // on unix, there is no official way to get the path of the current binary. + // instead of using the MOZILLA_FIVE_HOME hack, which doesn't scale to + // multiple applications, we will try a series of techniques: + // // 1) use realpath() on argv[0], which works unless we're loaded from the // PATH. Only do so if argv[0] looks like a path (contains a /). // 2) manually walk through the PATH and look for ourself @@ -262,10 +195,10 @@ private: #endif public: - static UniqueFreePtr Get() + static UniqueFreePtr Get(const char *aArgv0) { char path[MAXPATHLEN]; - if (NS_FAILED(Get(path))) { + if (NS_FAILED(Get(aArgv0, path))) { return nullptr; } UniqueFreePtr result; @@ -274,15 +207,15 @@ public: } #ifdef MOZILLA_INTERNAL_API - static nsresult GetFile(nsIFile** aResult) + static nsresult GetFile(const char* aArgv0, nsIFile** aResult) { nsCOMPtr lf; #ifdef XP_WIN wchar_t exePath[MAXPATHLEN]; - nsresult rv = GetW(exePath); + nsresult rv = GetW(aArgv0, exePath); #else char exePath[MAXPATHLEN]; - nsresult rv = Get(exePath); + nsresult rv = Get(aArgv0, exePath); #endif if (NS_FAILED(rv)) { return rv; diff --git a/xpcom/build/nsXULAppAPI.h b/xpcom/build/nsXULAppAPI.h index 293d10617170..e172b492dd27 100644 --- a/xpcom/build/nsXULAppAPI.h +++ b/xpcom/build/nsXULAppAPI.h @@ -205,9 +205,12 @@ XRE_API(nsresult, /** * Get the path of the running application binary and store it in aResult. + * @param aArgv0 The value passed as argv[0] of main(). This value is only + * used on *nix, and only when other methods of determining + * the binary path have failed. */ XRE_API(nsresult, - XRE_GetBinaryPath, (nsIFile** aResult)) + XRE_GetBinaryPath, (const char* aArgv0, nsIFile** aResult)) /** * Get the static module built in to libxul.