commit 232a5f133e156ed5a134438d71913d44d1a5d4ca
Author: Pavel Sanda <[email protected]>
Date: Thu Sep 17 11:16:21 2026 +0200
Move the cygdrive probe off runCommand
Last runCommand() caller. We can't use argv form as init() runs
before QCoreApplication exists and QProcess is available.
So we move runCommand->runComspec, leave it for _WIN32 only, and drop
parts for other archs. We keep the same windows COMSPEC spawning and
pipeline handling, no change intended.
Deletion of original runCommand comes in the next patch.
The input redirection and the 2>&1 handling not necessary for the
single consumer left, but are kept so that we ship the same code on
Windows without changes.
Don't be deceived, cygdrive query runs in native Windows, not Cygwin.
https://www.mail-archive.com/[email protected]/msg226898.html
Tier 01 DiD / argv 04d: cygdrive probe keeps its own spawn code
Assisted-by: Claude Opus 5
---
src/support/os_win32.cpp | 107 +++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 103 insertions(+), 4 deletions(-)
diff --git a/src/support/os_win32.cpp b/src/support/os_win32.cpp
index a10c17ede0..17c9662336 100644
--- a/src/support/os_win32.cpp
+++ b/src/support/os_win32.cpp
@@ -32,17 +32,21 @@
#include "support/lassert.h"
+#include <cstdio>
#include <cstdlib>
+#include <cstring> // memset
#include <iostream>
#include <vector>
#include <QString>
#include <io.h>
+#include <fcntl.h> // _O_RDONLY
#include <direct.h> // _getdrive
#include <fileapi.h> // GetFinalPathNameByHandle
#include <shlobj.h> // SHGetFolderPath
#include <windef.h>
+#include <windows.h>
#include <shellapi.h>
#include <shlwapi.h>
@@ -89,6 +93,100 @@ bool windows_style_tex_paths_ = true;
string cygdrive = "/cygdrive";
+
+// Run cmd through COMSPEC and return its standard output in result,
+// the return value tells whether the command exited successfully.
+//
+// Relic of the former cross-platform support::runCommand() and it spawns
+// a shell, so you need be extra careful about safety of the arguments.
+// Preferably do not add new callers of this function - we have generic
+// Systemcall and this is used only in init() before QCoreApplication
+// kicks in.
+bool runComspec(string const & cmd, string & result)
+{
+ result.clear();
+
+ if (verbose)
+ lyxerr << "\nRunning: " << cmd << endl;
+ else
+ LYXERR(Debug::INFO,"Running: " << cmd);
+
+ STARTUPINFO startup;
+ PROCESS_INFORMATION process;
+ SECURITY_ATTRIBUTES security;
+ HANDLE in, out;
+ FILE * inf = 0;
+ bool err2out = false;
+ string command;
+ string const infile = trim(split(cmd, command, '<'), " \"");
+ command = rtrim(command);
+ if (suffixIs(command, "2>&1")) {
+ command = rtrim(command, "2>&1");
+ err2out = true;
+ }
+ string const cmdarg = "/d /c \"" + command + "\"";
+ string const comspec = getEnv("COMSPEC");
+
+ security.nLength = sizeof(SECURITY_ATTRIBUTES);
+ security.bInheritHandle = TRUE;
+ security.lpSecurityDescriptor = NULL;
+
+ if (CreatePipe(&in, &out, &security, 0)) {
+ memset(&startup, 0, sizeof(STARTUPINFO));
+ memset(&process, 0, sizeof(PROCESS_INFORMATION));
+
+ startup.cb = sizeof(STARTUPINFO);
+ startup.dwFlags = STARTF_USESTDHANDLES;
+
+ startup.hStdError = err2out ? out :
GetStdHandle(STD_ERROR_HANDLE);
+ startup.hStdInput = infile.empty()
+ ? GetStdHandle(STD_INPUT_HANDLE)
+ : CreateFile(infile.c_str(), GENERIC_READ,
+ FILE_SHARE_READ, &security, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+ startup.hStdOutput = out;
+
+ if (startup.hStdInput != INVALID_HANDLE_VALUE &&
+ CreateProcess(comspec.c_str(), (LPTSTR)cmdarg.c_str(),
+ &security, &security, TRUE, CREATE_NO_WINDOW,
+ 0, 0, &startup, &process)) {
+
+ CloseHandle(process.hThread);
+ int fno = _open_osfhandle((intptr_t)in, _O_RDONLY);
+ CloseHandle(out);
+ inf = _fdopen(fno, "r");
+ }
+ }
+
+ if (!inf) {
+ lyxerr << "RunCommand: could not start child process" << endl;
+ return false;
+ }
+
+ int c = fgetc(inf);
+ while (c != EOF) {
+ result += static_cast<char>(c);
+ c = fgetc(inf);
+ }
+
+ WaitForSingleObject(process.hProcess, INFINITE);
+ DWORD pret;
+ BOOL success = GetExitCodeProcess(process.hProcess, &pret);
+ bool valid = (pret == 0) && success;
+ if (!success)
+ pret = -1;
+ if (!infile.empty())
+ CloseHandle(startup.hStdInput);
+ CloseHandle(process.hProcess);
+ if (fclose(inf) != 0)
+ pret = -1;
+
+ if (pret == -1)
+ perror("RunCommand: could not terminate child process");
+
+ return valid;
+}
+
BOOL terminate_handler(DWORD event)
{
if (event == CTRL_CLOSE_EVENT
@@ -221,8 +319,9 @@ void init(int argc, char ** argv[])
RegCloseKey(hkey);
string const mount = string(buf) + "\\bin\\mount.exe";
if (retval == ERROR_SUCCESS && FileName(mount).exists()) {
- cmd_ret const p =
- runCommand(mount + " --show-cygdrive-prefix");
+ string result;
+ bool const valid = runComspec(
+ mount + " --show-cygdrive-prefix", result);
// The output of the mount command is as follows:
// Prefix Type Flags
// /cygdrive system binmode
@@ -230,8 +329,8 @@ void init(int argc, char ** argv[])
// to the outer split which sets cygdrive with its
// contents until the first blank, discarding the
// unneeded return value.
- if (p.valid && prefixIs(p.result, "Prefix"))
- split(split(p.result, '\n'), cygdrive, ' ');
+ if (valid && prefixIs(result, "Prefix"))
+ split(split(result, '\n'), cygdrive, ' ');
}
}
--
lyx-cvs mailing list
[email protected]
https://lists.lyx.org/mailman/listinfo/lyx-cvs