commit e265dd06984e4208214afd6e1415a162a37e73a4
Author: Pavel Sanda <[email protected]>
Date:   Tue Sep 8 21:42:02 2026 +0200

    Probe the python interpreter without a shell
    
    Reroute python_call() and python_info() to startscriptArgv() so
    os.cpp is left with no runCommand().
    
    Adds new os::pythonArgvForm() for the argv-form callers.
    
    Tier 01 DiD / argv 03a: python argv probe
    
    https://www.mail-archive.com/[email protected]/msg226780.html
    
    Assisted-by: Claude Opus 5
---
 src/support/os.cpp | 48 +++++++++++++++++++++++++++++++++++++++++-------
 src/support/os.h   |  5 +++++
 2 files changed, 46 insertions(+), 7 deletions(-)

diff --git a/src/support/os.cpp b/src/support/os.cpp
index 08c3f347d6..a368f037e5 100644
--- a/src/support/os.cpp
+++ b/src/support/os.cpp
@@ -19,6 +19,7 @@
 #include "support/debug.h"
 #include "support/filetools.h"
 #include "support/qstring_helpers.h"
+#include "support/Systemcall.h"
 
 #include <QDir>
 
@@ -58,20 +59,33 @@ int timeout_ms()
 
 static string const python_call(string const & binary, bool verbose = false)
 {
-       const string version_info = " -c \"import sys; 
print(sys.version_info[:2], end='')\"";
+       const string version_script = "import sys; print(sys.version_info[:2], 
end='')";
        // Default to "python3" if no binary is given.
        if (binary.empty())
                return "python3";
 
        if (verbose)
                lyxerr << "Examining " << binary << "\n";
-       // Check whether this is a python 2 or 3 binary.
-       cmd_ret const out = runCommand(binary + version_info);
+       // Check whether this is a python 2 or 3 binary. The candidate may be
+       // a bare name ("python3"), a name plus argument ("py -3") or a quoted
+       // absolute path found with walking-path fallback; split it into argv
+       // so the probe never goes through a shell.
+       vector<string> argv = splitCommandTokens(binary);
+       if (argv.empty())
+               return string();
+       string const program = argv.front();
+       argv.erase(argv.begin());
+       argv.push_back("-c");
+       argv.push_back(version_script);
+
+       Systemcall one;
+       string result;
+       int const ret = one.startscriptArgv(program, argv, &result);
 
        smatch sm;
        try {
                static regex const python_reg("\\((\\d*), (\\d*)\\)");
-               if (!out.valid || !regex_match(out.result, sm, python_reg))
+               if (ret != Systemcall::OK || !regex_match(result, sm, 
python_reg))
                        return string();
        } catch(regex_error const & /*e*/) {
                LYXERR0("Regex error! This should not happen.");
@@ -88,7 +102,7 @@ static string const python_call(string const & binary, bool 
verbose = false)
                return string();
 
        if (verbose)
-               lyxerr << "Found Python " << out.result << "\n";
+               lyxerr << "Found Python " << result << "\n";
        return binary;
 }
 
@@ -162,12 +176,32 @@ bool hasPython()
        return !(python_call(python()).empty());
 }
 
+vector<string> pythonArgvForm()
+{
+       return splitCommandTokens(python());
+}
+
+
+// consumers: About dialog
 string const python_info()
 {
-       const string info_version = " -c \"import sys; print('{} 
({})'.format(sys.version.split()[0],sys.executable), end='')\"";
+       const string info_script = "import sys; print('{} 
({})'.format(sys.version.split()[0],sys.executable), end='')";
        if (!hasPython())
                return("None");
-       return (runCommand(python() + info_version).result);
+
+       vector<string> argv = pythonArgvForm();
+       if (argv.empty())
+               return("None");
+       string const program = argv.front();
+       argv.erase(argv.begin());
+       argv.push_back("-c");
+       argv.push_back(info_script);
+
+       Systemcall one;
+       string result;
+       if (one.startscriptArgv(program, argv, &result) != Systemcall::OK)
+               return("None");
+       return result;
 }
 
 } // namespace os
diff --git a/src/support/os.h b/src/support/os.h
index 1b664e4444..c4c6e10419 100644
--- a/src/support/os.h
+++ b/src/support/os.h
@@ -16,6 +16,7 @@
 
 #include "support/docstring.h"
 #include <cstddef>
+#include <vector>
 
 
 namespace lyx {
@@ -62,6 +63,10 @@ int timeout_ms();
 /// @param reset True if the python path should be recomputed
 std::string const python(bool reset = false);
 
+/// Take python() output and split it into program + leading arguments, for 
invocation
+/// via Systemcall::startscriptArgv (no shell, no command-line re-parsing).
+std::vector<std::string> pythonArgvForm();
+
 /// Check for availability of the python interpreter
 bool hasPython();
 
-- 
lyx-cvs mailing list
[email protected]
https://lists.lyx.org/mailman/listinfo/lyx-cvs

Reply via email to