diff --git a/src/core/HostShell.lua b/src/core/HostShell.lua new file mode 100644 index 00000000..2ce06b9b --- /dev/null +++ b/src/core/HostShell.lua @@ -0,0 +1,23 @@ +-- Helpers for calling host tools (curl, zenity/kdialog, ...). + +local HostShell = {} + +-- Our AppRun exports LD_LIBRARY_PATH="$APPDIR/lib:..." so every subprocess we +-- spawn tries to link against the libraries we're shipping instead of the +-- system ones. We want to unset the var so that any system tools can find +-- their proper libraries. Only needed when running in an AppImage. +function HostShell.envPrefix() + if os.getenv("APPIMAGE") then + return "env -u LD_LIBRARY_PATH " + end + return "" +end + +-- Wraps io.popen with the AppImage env fix applied and lua errors swallowed +function HostShell.popen(command, mode) + local ok, pipe = pcall(io.popen, HostShell.envPrefix() .. command, mode or "r") + if not ok or not pipe then return nil end + return pipe +end + +return HostShell diff --git a/src/import/RomImporter.lua b/src/import/RomImporter.lua index 5eb9318f..c604f1cf 100644 --- a/src/import/RomImporter.lua +++ b/src/import/RomImporter.lua @@ -1,5 +1,6 @@ local GameVersion = require("src.core.GameVersion") local Strings = require("src.core.Strings") +local HostShell = require("src.core.HostShell") local RomImporter = {} RomImporter.__index = RomImporter @@ -285,7 +286,7 @@ end local function commandOutput(command) releasePointerGrab() - local pipe = io.popen(command, "r") + local pipe = HostShell.popen(command) if not pipe then return nil end local result = pipe:read("*a") pipe:close() diff --git a/src/update/check_worker.lua b/src/update/check_worker.lua index 258428a0..24ed03a7 100644 --- a/src/update/check_worker.lua +++ b/src/update/check_worker.lua @@ -35,6 +35,7 @@ local Json = loadModule("src/link/Json.lua") local Check = loadModule("src/update/Check.lua") local Version = loadModule("src/core/Version.lua") local Semver = loadModule("src/update/Semver.lua") +local HostShell = loadModule("src/core/HostShell.lua") -- Boot's top-level require("src.update.Semver") cannot resolve in this thread -- (no src.* searcher), which would leave Boot nil and the minShell gate -- permanently permissive. Seed the loaded table first so it resolves. @@ -76,8 +77,8 @@ local function curlCapture(url) .. "-H " .. shq("User-Agent: gen1recomp-updater") .. " " .. "-H " .. shq("Accept: application/vnd.github+json") .. " " .. shq(url) - local ok, pipe = pcall(io.popen, cmd) - if not ok or not pipe then return nil end + local pipe = HostShell.popen(cmd) + if not pipe then return nil end local out = pipe:read("*a") pipe:close() if not out or out == "" then return nil end @@ -85,8 +86,8 @@ local function curlCapture(url) end local function haveCurl() - local ok, pipe = pcall(io.popen, "curl --version") - if not ok or not pipe then return false end + local pipe = HostShell.popen("curl --version") + if not pipe then return false end local out = pipe:read("*a") pipe:close() return out ~= nil and out:find("curl", 1, true) ~= nil @@ -239,7 +240,7 @@ local function launchDownload(url, partAbs, doneAbs) os.execute('start "" /b ' .. shq(saveDir .. "/" .. batRel)) else -- ( ... ) & backgrounds the whole group so os.execute returns at once - os.execute("( curl -fsSL --connect-timeout 15 --max-time 900 -o " + os.execute("( " .. HostShell.envPrefix() .. "curl -fsSL --connect-timeout 15 --max-time 900 -o " .. shq(partAbs) .. " " .. shq(url) .. " ; touch " .. shq(doneAbs) .. " ) >/dev/null 2>&1 &") end