diff --git a/src/libs/utils/consoleprocess.h b/src/libs/utils/consoleprocess.h index 53c69c91af7206d52c76179b50664a18ef4e4d08..821e8cb7c8785c2ddb53e3cdb46d4424c2120950 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 2e20ac0c37aca3c6f36eb27a8ef25993e4e48129..276d6c77f23f8338551b205ce23e94fbbc7934fd 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 92c38bb5f0d30070ee1ff43339250a0b259327d0..9a3194038215f48d5ff99a767ed612dcf012651b 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 */