commit bdd8f145a67d166b060f161025129cf6fe860a3a
Author: Pavel Sanda <[email protected]>
Date: Thu Sep 17 02:55:40 2026 +0200
Run the CAS through Systemcall instead of runCommand
Rerouting to argv form would not work here (unless we rewrite the API
just for this consumer so it deals with stdin/out).
Fortunately we have startscript() which spawns without a shell and its
parsecmd() already understands the redirections these commands use,
including the 2>&1 that octave is invoked with. startscript() reports
an exit code rather than the output, so collect the output in a second
temp file and read it back.
There is no way how to get rid of shell on windows, because of .bat
invocations (e.g. maxima.bat).
Compatibility change here, runCommand() used to return the raw bytes,
while fileContents() decodes them as UTF-8 and to_utf8() encodes them
back: output which is not valid UTF-8 now comes back with replacement
characters, and output containing a NUL byte is truncated there.
Should not be a problem for CAS exchange though.
Tier 01 DiD / argv 04c: CAS via Systemcall, no shell
https://www.mail-archive.com/[email protected]/msg226885.html
Assisted-by: Claude Opus 5
---
src/mathed/MathExtern.cpp | 48 +++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 44 insertions(+), 4 deletions(-)
diff --git a/src/mathed/MathExtern.cpp b/src/mathed/MathExtern.cpp
index 531138b358..0f50e63504 100644
--- a/src/mathed/MathExtern.cpp
+++ b/src/mathed/MathExtern.cpp
@@ -39,10 +39,12 @@
#include "support/debug.h"
#include "support/docstream.h"
+#include "support/environment.h"
#include "support/FileName.h"
#include "support/filetools.h"
#include "support/gettext.h"
#include "support/lstrings.h"
+#include "support/Systemcall.h"
#include "support/TempFile.h"
#include "support/textutils.h"
@@ -1136,13 +1138,51 @@ namespace {
ofstream os(cas_tmpfile.toFilesystemEncoding().c_str());
os << data << endl;
os.close();
- string command = cmd + " < "
- + quoteName(cas_tmpfile.toFilesystemEncoding());
+
+ // startscript() reports an exit code, so collect the output of
+ // the CAS in a file as well.
+ unique_ptr<TempFile> outfile(new TempFile("casoutput"));
+ outfile->setAutoRemove(false);
+ FileName const cas_outfile = outfile->name();
+ outfile.reset();
+
+ if (cas_outfile.empty()) {
+ lyxerr << "Warning: cannot create temporary file."
+ << endl;
+ cas_tmpfile.removeFile();
+ return string();
+ }
+
+ string redirect =
+ " < " + quoteName(cas_tmpfile.toFilesystemEncoding())
+ + " > " + quoteName(cas_outfile.toFilesystemEncoding());
lyxerr << "calling: " << cmd
<< "\ninput: '" << data << "'" << endl;
- cmd_ret const ret = runCommand(command);
+ Systemcall one;
+#if defined(_WIN32)
+ // CreateProcess() can't run .bat, so for windows we need to
+ // stay in realm of shell. Only the command goes to the
interpreter.
+ string command = cmd;
+ // Keep redirection out of interpreter.
+ if (suffixIs(command, "2>&1")) {
+ command = rtrim(command.substr(0, command.size() - 4));
+ redirect += " 2>&1";
+ }
+ one.startscript(Systemcall::Wait,
+ quoteName(getEnv("COMSPEC")) + " /d /c "
+ + quoteName(command) + redirect);
+#else
+ one.startscript(Systemcall::Wait, cmd + redirect);
+#endif
+
+ // Read what the CAS produced whatever its exit code was: a
+ // failing run still prints the diagnostics the callers parse
+ // (octave is invoked with 2>&1 for exactly that reason).
+ string const result =
to_utf8(cas_outfile.fileContents("UTF-8"));
+
cas_tmpfile.removeFile();
- return ret.result;
+ cas_outfile.removeFile();
+ return result;
}
size_t get_matching_brace(string const & str, size_t i)
--
lyx-cvs mailing list
[email protected]
https://lists.lyx.org/mailman/listinfo/lyx-cvs