1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
#include "clConsoleCodeLiteTerminal.h"
#include "cl_standard_paths.h"
#include "file_logger.h"
#include "fileutils.h"
#include "procutils.h"
#include <wx/arrstr.h>
#include <wx/tokenzr.h>
clConsoleCodeLiteTerminal::clConsoleCodeLiteTerminal()
{
wxString cmd = GetBinary();
#ifndef __WXOSX__
WrapWithQuotesIfNeeded(cmd);
#endif
SetTerminalCommand(wxString() << cmd << " --working-directory=%WD% --file=%COMMANDFILE%");
SetEmptyTerminalCommand(wxString() << cmd << " --working-directory=%WD%");
}
clConsoleCodeLiteTerminal::~clConsoleCodeLiteTerminal() {}
wxString clConsoleCodeLiteTerminal::PrepareCommand()
{
// Build the command to execute
wxString commandToExecute;
if(IsTerminalNeeded()) {
wxFileName tmpfile(clStandardPaths::Get().GetTempDir(), "codelite-terminal.txt");
bool hasCommand = !GetCommand().IsEmpty();
commandToExecute = hasCommand ? GetTerminalCommand() : GetEmptyTerminalCommand();
// For testing purposes
wxString command = WrapWithQuotesIfNeeded(GetCommand());
if(!command.IsEmpty()) {
#ifdef __WXMSW__
command.Prepend("start /B /WAIT "); // start the application in the foreground
#endif
if(!GetCommandArgs().IsEmpty()) {
wxString cmdArgs = GetCommandArgs();
command << " " << GetCommandArgs();
}
// Write the content of the command into a file
FileUtils::WriteFileContent(tmpfile, command);
}
wxString wd = GetWorkingDirectory();
if(wd.IsEmpty() || !wxFileName::DirExists(wd)) {
wd = WrapWithQuotesIfNeeded(wxGetCwd());
}
if(IsWaitWhenDone()) {
commandToExecute << " --wait ";
}
wxString commandFile = tmpfile.GetFullPath();
commandFile = WrapWithQuotesIfNeeded(commandFile);
commandToExecute.Replace("%COMMANDFILE%", commandFile);
commandToExecute.Replace("%WD%", wd);
} else {
commandToExecute = WrapWithQuotesIfNeeded(GetCommand());
if(!GetCommandArgs().IsEmpty()) {
commandToExecute << " " << GetCommandArgs();
}
}
return commandToExecute;
}
bool clConsoleCodeLiteTerminal::StartForDebugger()
{
#ifdef __WXMSW__
return false;
#else
// generate a random value to differntiate this instance of codelite
// from other instances
time_t curtime = time(NULL);
int randomSeed = (curtime % 947);
wxString secondsToSleep;
secondsToSleep << (85765 + randomSeed);
wxString sleepCommand = "/bin/sleep";
sleepCommand << " " << secondsToSleep;
wxString homedir = wxGetHomeDir();
if(homedir.Contains(" ")) {
homedir.Prepend("\"").Append("\"");
}
wxString commandToExecute;
commandToExecute << GetBinary();
#ifndef __WXOSX__
WrapWithQuotesIfNeeded(commandToExecute);
#endif
wxFileName tmpfile("/tmp", "codelite-terminal.txt");
tmpfile.SetFullName(wxString() << "codelite-terminal." << secondsToSleep << ".txt");
commandToExecute << " --print-tty=" << tmpfile.GetFullPath() << " --working-directory=" << homedir
<< " --command=\"" << sleepCommand << "\"";
m_pid = ::wxExecute(commandToExecute);
// Let it start ... (wait for it up to 5 seconds)
for(size_t i = 0; i < 100; ++i) {
if(tmpfile.FileExists()) {
FileUtils::ReadFileContent(tmpfile.GetFullPath(), m_tty);
// On GTK, redirection to TTY does not work with lldb
// as a workaround, we create a symlink with different name
// Keep the real tty
m_realPts = m_tty;
wxString symlinkName = m_tty;
symlinkName.Replace("/dev/pts/", "/tmp/pts");
wxString lnCommand;
lnCommand << "ln -sf " << m_tty << " " << symlinkName;
if(::system(lnCommand.mb_str(wxConvUTF8).data()) == 0) {
m_tty.swap(symlinkName);
}
break;
}
wxThread::Sleep(50);
}
#ifdef __WXOSX__
// on OSX, wxExecute return the PID of the open command
// we want the sleep command PID (when we kill the 'sleep' the terminal will
// close itself)
m_pid = wxNOT_FOUND;
wxString psCommand;
psCommand << "ps -A -o pid,command";
wxString psOutput = ProcUtils::SafeExecuteCommand(psCommand);
LOG_IF_TRACE { clDEBUG1() << "ps command output:\n" << psOutput; }
wxArrayString lines = ::wxStringTokenize(psOutput, "\n", wxTOKEN_STRTOK);
for(size_t u = 0; u < lines.GetCount(); ++u) {
wxString l = lines.Item(u);
l.Trim().Trim(false);
if(l.Contains("sleep") && l.Contains(secondsToSleep) && !l.Contains("codelite-terminal")) {
// we got a match
wxString ppidString = l.BeforeFirst(' ');
ppidString.ToCLong(&m_pid);
clDEBUG() << "codelite-terminal process ID is:" << m_pid;
break;
}
}
#endif
return !m_tty.IsEmpty();
#endif
}
wxString clConsoleCodeLiteTerminal::GetBinary() const
{
wxFileName codeliteTerminal(clStandardPaths::Get().GetBinFolder(), "codelite-terminal");
#ifdef __WXMSW__
codeliteTerminal.SetExt("exe");
#elif defined(__WXOSX__)
codeliteTerminal.AppendDir("codelite-terminal.app");
#endif
#ifdef __WXOSX__
wxString cmd = codeliteTerminal.GetPath();
cmd = WrapWithQuotesIfNeeded(cmd);
return cmd;
#else
return codeliteTerminal.GetFullPath();
#endif
}
|