From c8c183f6b4327baf3ba8fa5c28a04fc4777b8082 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen <oswald.buddenhagen@nokia.com> Date: Thu, 9 Apr 2009 19:13:40 +0200 Subject: [PATCH] use temp file to pass env on unix as well the linux command line can be 32k long ... which might still be not enough. well, in fact, it just makes the 'ps' output unreadable. --- src/libs/utils/consoleprocess.h | 7 ++-- src/libs/utils/consoleprocess_unix.cpp | 27 ++++++++++++++- src/libs/utils/process_stub_unix.c | 46 ++++++++++++++++++++------ 3 files changed, 67 insertions(+), 13 deletions(-) diff --git a/src/libs/utils/consoleprocess.h b/src/libs/utils/consoleprocess.h index 53c69c91af7..821e8cb7c87 100644 --- a/src/libs/utils/consoleprocess.h +++ b/src/libs/utils/consoleprocess.h @@ -43,10 +43,13 @@ #include <windows.h> QT_BEGIN_NAMESPACE class QWinEventNotifier; -class QTemporaryFile; QT_END_NAMESPACE #endif +QT_BEGIN_NAMESPACE +class QTemporaryFile; +QT_END_NAMESPACE + namespace Core { namespace Utils { @@ -102,12 +105,12 @@ private: QProcess::ExitStatus m_appStatus; QLocalServer m_stubServer; QLocalSocket *m_stubSocket; + QTemporaryFile *m_tempFile; #ifdef Q_OS_WIN PROCESS_INFORMATION *m_pid; HANDLE m_hInferior; QWinEventNotifier *inferiorFinishedNotifier; QWinEventNotifier *processFinishedNotifier; - QTemporaryFile *m_tempFile; #else QProcess m_process; QByteArray m_stubServerDir; diff --git a/src/libs/utils/consoleprocess_unix.cpp b/src/libs/utils/consoleprocess_unix.cpp index 2e20ac0c37a..276d6c77f23 100644 --- a/src/libs/utils/consoleprocess_unix.cpp +++ b/src/libs/utils/consoleprocess_unix.cpp @@ -72,6 +72,22 @@ bool ConsoleProcess::start(const QString &program, const QStringList &args) return false; } + if (!environment().isEmpty()) { + m_tempFile = new QTemporaryFile(); + if (!m_tempFile->open()) { + stubServerShutdown(); + emit processError(tr("Cannot create temp file: %1").arg(m_tempFile->errorString())); + delete m_tempFile; + m_tempFile = 0; + return false; + } + foreach (const QString &var, environment()) { + m_tempFile->write(var.toLocal8Bit()); + m_tempFile->write("", 1); + } + m_tempFile->flush(); + } + QStringList xtermArgs; xtermArgs << "-e" #ifdef Q_OS_MAC @@ -82,13 +98,16 @@ bool ConsoleProcess::start(const QString &program, const QStringList &args) << (m_debug ? "debug" : "exec") << m_stubServer.fullServerName() << tr("Press <RETURN> to close this window...") - << workingDirectory() << environment() << "" + << workingDirectory() + << (m_tempFile ? m_tempFile->fileName() : 0) << program << args; m_process.start(QLatin1String("xterm"), xtermArgs); if (!m_process.waitForStarted()) { stubServerShutdown(); emit processError(tr("Cannot start console emulator xterm.")); + delete m_tempFile; + m_tempFile = 0; return false; } m_executable = program; @@ -173,6 +192,10 @@ void ConsoleProcess::readStubOutput() emit processError(tr("Cannot execute %1: %2") .arg(m_executable, errorMsg(out.mid(9).toInt()))); } else if (out.startsWith("pid ")) { + // Will not need it any more + delete m_tempFile; + m_tempFile = 0; + m_appPid = out.mid(4).toInt(); emit processStarted(); } else if (out.startsWith("exit ")) { @@ -199,6 +222,8 @@ void ConsoleProcess::stubExited() if (m_stubSocket && m_stubSocket->state() == QLocalSocket::ConnectedState) m_stubSocket->waitForDisconnected(); stubServerShutdown(); + delete m_tempFile; + m_tempFile = 0; if (m_appPid) { m_appStatus = QProcess::CrashExit; m_appCode = -1; diff --git a/src/libs/utils/process_stub_unix.c b/src/libs/utils/process_stub_unix.c index 92c38bb5f0d..9a319403821 100644 --- a/src/libs/utils/process_stub_unix.c +++ b/src/libs/utils/process_stub_unix.c @@ -73,18 +73,19 @@ enum { ArgSocket, ArgMsg, ArgDir, - ArgEnv + ArgEnv, + ArgExe }; -/* syntax: $0 {"run"|"debug"} <pid-socket> <continuation-msg> <workdir> <env...> "" <exe> <args...> */ +/* syntax: $0 {"run"|"debug"} <pid-socket> <continuation-msg> <workdir> <env-file> <exe> <args...> */ /* exit codes: 0 = ok, 1 = invocation error, 3 = internal error */ int main(int argc, char *argv[]) { - int envIdx = ArgEnv; int errNo; int chldPid; int chldStatus; int chldPipe[2]; + char **env = 0; struct sockaddr_un sau; if (argc < ArgEnv) { @@ -111,6 +112,35 @@ int main(int argc, char *argv[]) return 1; } + if (*argv[ArgEnv]) { + FILE *envFd; + char *envdata, *edp; + long size; + int count; + if (!(envFd = fopen(argv[ArgEnv], "r"))) { + fprintf(stderr, "Cannot read creator env file %s: %s\n", + argv[ArgEnv], strerror(errno)); + doExit(1); + } + fseek(envFd, 0, SEEK_END); + size = ftell(envFd); + rewind(envFd); + envdata = malloc(size); + if (fread(envdata, 1, size, envFd) != (size_t)size) { + perror("Failed to read env file"); + doExit(1); + } + fclose(envFd); + for (count = 0, edp = envdata; edp < envdata + size; ++count) + edp += strlen(edp) + 1; + env = malloc((count + 1) * sizeof(char *)); + for (count = 0, edp = envdata; edp < envdata + size; ++count) { + env[count] = edp; + edp += strlen(edp) + 1; + } + env[count] = 0; + } + /* Create execution result notification pipe. */ if (pipe(chldPipe)) { perror("Cannot create status pipe"); @@ -142,14 +172,10 @@ int main(int argc, char *argv[]) ptrace(PT_TRACE_ME, 0, 0, 0); #endif - for (envIdx = ArgEnv; *argv[envIdx]; ++envIdx) ; - if (envIdx != ArgEnv) { - argv[envIdx] = 0; - environ = argv + ArgEnv; - } - ++envIdx; + if (env) + environ = env; - execvp(argv[envIdx], argv + envIdx); + execvp(argv[ArgExe], argv + ArgExe); /* Only expected error: no such file or direcotry, i.e. executable not found */ errNo = errno; write(chldPipe[1], &errNo, sizeof(errNo)); /* Only realistic error case is SIGPIPE */ -- GitLab