mirror of
https://github.com/rizinorg/cutter.git
synced 2025-01-19 02:48:49 +00:00
Stdin redirection for locally debugged processes (#1892)
This commit is contained in:
parent
49d58b3624
commit
f284f9d209
@ -275,6 +275,7 @@ SOURCES += \
|
|||||||
common/HexHighlighter.cpp \
|
common/HexHighlighter.cpp \
|
||||||
common/Highlighter.cpp \
|
common/Highlighter.cpp \
|
||||||
common/MdHighlighter.cpp \
|
common/MdHighlighter.cpp \
|
||||||
|
common/DirectionalComboBox.cpp \
|
||||||
dialogs/preferences/AsmOptionsWidget.cpp \
|
dialogs/preferences/AsmOptionsWidget.cpp \
|
||||||
dialogs/NewFileDialog.cpp \
|
dialogs/NewFileDialog.cpp \
|
||||||
common/AnalTask.cpp \
|
common/AnalTask.cpp \
|
||||||
@ -408,6 +409,7 @@ HEADERS += \
|
|||||||
core/MainWindow.h \
|
core/MainWindow.h \
|
||||||
common/Highlighter.h \
|
common/Highlighter.h \
|
||||||
common/MdHighlighter.h \
|
common/MdHighlighter.h \
|
||||||
|
common/DirectionalComboBox.h \
|
||||||
dialogs/InitialOptionsDialog.h \
|
dialogs/InitialOptionsDialog.h \
|
||||||
dialogs/NewFileDialog.h \
|
dialogs/NewFileDialog.h \
|
||||||
common/AnalTask.h \
|
common/AnalTask.h \
|
||||||
|
24
src/common/DirectionalComboBox.cpp
Normal file
24
src/common/DirectionalComboBox.cpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#include "DirectionalComboBox.h"
|
||||||
|
|
||||||
|
DirectionalComboBox::DirectionalComboBox(QWidget *parent, bool upwards)
|
||||||
|
: QComboBox(parent), popupUpwards(upwards)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void DirectionalComboBox::showPopup()
|
||||||
|
{
|
||||||
|
QComboBox::showPopup();
|
||||||
|
QWidget *popup = this->findChild<QFrame *>();
|
||||||
|
if (popupUpwards) {
|
||||||
|
popup->move(popup->x(),
|
||||||
|
mapToGlobal(this->rect().bottomLeft()).y() - popup->height());
|
||||||
|
} else {
|
||||||
|
popup->move(popup->x(),
|
||||||
|
mapToGlobal(this->rect().topLeft()).y());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DirectionalComboBox::setPopupDirection(bool upwards)
|
||||||
|
{
|
||||||
|
popupUpwards = upwards;
|
||||||
|
}
|
23
src/common/DirectionalComboBox.h
Normal file
23
src/common/DirectionalComboBox.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QComboBox>
|
||||||
|
/**
|
||||||
|
* @brief Custom QComboBox created to prevent the menu popup from opening up at different
|
||||||
|
* offsets for different items, which may result in list items being rendered outside
|
||||||
|
* of the screen/containing widget.
|
||||||
|
*/
|
||||||
|
class DirectionalComboBox : public QComboBox
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit DirectionalComboBox(QWidget *parent = nullptr, bool upwards = true);
|
||||||
|
|
||||||
|
void setPopupDirection(bool upwards);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool popupUpwards;
|
||||||
|
|
||||||
|
void showPopup();
|
||||||
|
};
|
||||||
|
|
@ -313,6 +313,24 @@ QString CutterCore::cmd(const char *str)
|
|||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CutterCore::isRedirectableDebugee()
|
||||||
|
{
|
||||||
|
if (!currentlyDebugging || currentlyAttachedToPID != -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We are only able to redirect locally debugged unix processes
|
||||||
|
QJsonArray openFilesArray = cmdj("oj").array();;
|
||||||
|
for (QJsonValue value : openFilesArray) {
|
||||||
|
QJsonObject openFile = value.toObject();
|
||||||
|
QString URI = openFile["uri"].toString();
|
||||||
|
if (URI.contains("ptrace") | URI.contains("mach")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool CutterCore::isDebugTaskInProgress()
|
bool CutterCore::isDebugTaskInProgress()
|
||||||
{
|
{
|
||||||
if (!debugTask.isNull()) {
|
if (!debugTask.isNull()) {
|
||||||
|
@ -298,6 +298,10 @@ public:
|
|||||||
QStringList getDebugPlugins();
|
QStringList getDebugPlugins();
|
||||||
void setDebugPlugin(QString plugin);
|
void setDebugPlugin(QString plugin);
|
||||||
bool isDebugTaskInProgress();
|
bool isDebugTaskInProgress();
|
||||||
|
/**
|
||||||
|
* @brief Check if we can use output/input redirection with the currently debugged process
|
||||||
|
*/
|
||||||
|
bool isRedirectableDebugee();
|
||||||
bool currentlyDebugging = false;
|
bool currentlyDebugging = false;
|
||||||
bool currentlyEmulating = false;
|
bool currentlyEmulating = false;
|
||||||
int currentlyAttachedToPID = -1;
|
int currentlyAttachedToPID = -1;
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
#include <QStringListModel>
|
#include <QStringListModel>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QUuid>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "core/Cutter.h"
|
#include "core/Cutter.h"
|
||||||
#include "ConsoleWidget.h"
|
#include "ConsoleWidget.h"
|
||||||
@ -15,7 +17,6 @@
|
|||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
#include <QUuid>
|
|
||||||
#define dup2 _dup2
|
#define dup2 _dup2
|
||||||
#define dup _dup
|
#define dup _dup
|
||||||
#define fileno _fileno
|
#define fileno _fileno
|
||||||
@ -26,8 +27,12 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#define PIPE_READ (0)
|
#define PIPE_READ (0)
|
||||||
#define PIPE_WRITE (1)
|
#define PIPE_WRITE (1)
|
||||||
|
#define STDIN_PIPE_NAME "%1/cutter-stdin-%2"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define CONSOLE_R2_INPUT ("R2 Console")
|
||||||
|
#define CONSOLE_DEBUGEE_INPUT ("Debugee Input")
|
||||||
|
|
||||||
static const int invalidHistoryPos = -1;
|
static const int invalidHistoryPos = -1;
|
||||||
|
|
||||||
static const char *consoleWrapSettingsKey = "console.wrap";
|
static const char *consoleWrapSettingsKey = "console.wrap";
|
||||||
@ -45,7 +50,8 @@ ConsoleWidget::ConsoleWidget(MainWindow *main, QAction *action) :
|
|||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
// Adjust console lineedit
|
// Adjust console lineedit
|
||||||
ui->inputLineEdit->setTextMargins(10, 0, 0, 0);
|
ui->r2InputLineEdit->setTextMargins(10, 0, 0, 0);
|
||||||
|
ui->debugeeInputLineEdit->setTextMargins(10, 0, 0, 0);
|
||||||
|
|
||||||
setupFont();
|
setupFont();
|
||||||
|
|
||||||
@ -71,9 +77,9 @@ ConsoleWidget::ConsoleWidget(MainWindow *main, QAction *action) :
|
|||||||
completer->setMaxVisibleItems(20);
|
completer->setMaxVisibleItems(20);
|
||||||
completer->setCaseSensitivity(Qt::CaseInsensitive);
|
completer->setCaseSensitivity(Qt::CaseInsensitive);
|
||||||
completer->setFilterMode(Qt::MatchStartsWith);
|
completer->setFilterMode(Qt::MatchStartsWith);
|
||||||
ui->inputLineEdit->setCompleter(completer);
|
ui->r2InputLineEdit->setCompleter(completer);
|
||||||
|
|
||||||
connect(ui->inputLineEdit, &QLineEdit::textEdited, this, &ConsoleWidget::updateCompletion);
|
connect(ui->r2InputLineEdit, &QLineEdit::textEdited, this, &ConsoleWidget::updateCompletion);
|
||||||
updateCompletion();
|
updateCompletion();
|
||||||
|
|
||||||
// Set console output context menu
|
// Set console output context menu
|
||||||
@ -81,28 +87,46 @@ ConsoleWidget::ConsoleWidget(MainWindow *main, QAction *action) :
|
|||||||
connect(ui->outputTextEdit, SIGNAL(customContextMenuRequested(const QPoint &)),
|
connect(ui->outputTextEdit, SIGNAL(customContextMenuRequested(const QPoint &)),
|
||||||
this, SLOT(showCustomContextMenu(const QPoint &)));
|
this, SLOT(showCustomContextMenu(const QPoint &)));
|
||||||
|
|
||||||
// Esc clears inputLineEdit (like OmniBar)
|
// Esc clears r2InputLineEdit and debugeeInputLineEdit (like OmniBar)
|
||||||
QShortcut *clear_shortcut = new QShortcut(QKeySequence(Qt::Key_Escape), ui->inputLineEdit);
|
QShortcut *r2_clear_shortcut = new QShortcut(QKeySequence(Qt::Key_Escape), ui->r2InputLineEdit);
|
||||||
connect(clear_shortcut, SIGNAL(activated()), this, SLOT(clear()));
|
connect(r2_clear_shortcut, SIGNAL(activated()), this, SLOT(clear()));
|
||||||
clear_shortcut->setContext(Qt::WidgetShortcut);
|
r2_clear_shortcut->setContext(Qt::WidgetShortcut);
|
||||||
|
|
||||||
|
QShortcut *debugee_clear_shortcut = new QShortcut(QKeySequence(Qt::Key_Escape), ui->debugeeInputLineEdit);
|
||||||
|
connect(debugee_clear_shortcut, SIGNAL(activated()), this, SLOT(clear()));
|
||||||
|
debugee_clear_shortcut->setContext(Qt::WidgetShortcut);
|
||||||
|
|
||||||
// Up and down arrows show history
|
// Up and down arrows show history
|
||||||
historyUpShortcut = new QShortcut(QKeySequence(Qt::Key_Up), ui->inputLineEdit);
|
historyUpShortcut = new QShortcut(QKeySequence(Qt::Key_Up), ui->r2InputLineEdit);
|
||||||
connect(historyUpShortcut, SIGNAL(activated()), this, SLOT(historyPrev()));
|
connect(historyUpShortcut, SIGNAL(activated()), this, SLOT(historyPrev()));
|
||||||
historyUpShortcut->setContext(Qt::WidgetShortcut);
|
historyUpShortcut->setContext(Qt::WidgetShortcut);
|
||||||
|
|
||||||
historyDownShortcut = new QShortcut(QKeySequence(Qt::Key_Down), ui->inputLineEdit);
|
historyDownShortcut = new QShortcut(QKeySequence(Qt::Key_Down), ui->r2InputLineEdit);
|
||||||
connect(historyDownShortcut, SIGNAL(activated()), this, SLOT(historyNext()));
|
connect(historyDownShortcut, SIGNAL(activated()), this, SLOT(historyNext()));
|
||||||
historyDownShortcut->setContext(Qt::WidgetShortcut);
|
historyDownShortcut->setContext(Qt::WidgetShortcut);
|
||||||
|
|
||||||
QShortcut *completionShortcut = new QShortcut(QKeySequence(Qt::Key_Tab), ui->inputLineEdit);
|
QShortcut *completionShortcut = new QShortcut(QKeySequence(Qt::Key_Tab), ui->r2InputLineEdit);
|
||||||
connect(completionShortcut, &QShortcut::activated, this, &ConsoleWidget::triggerCompletion);
|
connect(completionShortcut, &QShortcut::activated, this, &ConsoleWidget::triggerCompletion);
|
||||||
|
|
||||||
connect(ui->inputLineEdit, &QLineEdit::editingFinished, this, &ConsoleWidget::disableCompletion);
|
connect(ui->r2InputLineEdit, &QLineEdit::editingFinished, this, &ConsoleWidget::disableCompletion);
|
||||||
|
|
||||||
connect(Config(), &Configuration::fontsUpdated, this, &ConsoleWidget::setupFont);
|
connect(Config(), &Configuration::fontsUpdated, this, &ConsoleWidget::setupFont);
|
||||||
connect(Config(), &Configuration::interfaceThemeChanged, this, &ConsoleWidget::setupFont);
|
connect(Config(), &Configuration::interfaceThemeChanged, this, &ConsoleWidget::setupFont);
|
||||||
|
|
||||||
|
connect(ui->inputCombo,
|
||||||
|
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||||
|
this, &ConsoleWidget::onIndexChange);
|
||||||
|
|
||||||
|
connect(Core(), &CutterCore::debugTaskStateChanged, this, [ = ]() {
|
||||||
|
if (Core()->isRedirectableDebugee()) {
|
||||||
|
ui->inputCombo->setVisible(true);
|
||||||
|
} else {
|
||||||
|
ui->inputCombo->setVisible(false);
|
||||||
|
// Return to the r2 console
|
||||||
|
ui->inputCombo->setCurrentIndex(ui->inputCombo->findText(CONSOLE_R2_INPUT));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
completer->popup()->installEventFilter(this);
|
completer->popup()->installEventFilter(this);
|
||||||
|
|
||||||
redirectOutput();
|
redirectOutput();
|
||||||
@ -111,6 +135,11 @@ ConsoleWidget::ConsoleWidget(MainWindow *main, QAction *action) :
|
|||||||
ConsoleWidget::~ConsoleWidget()
|
ConsoleWidget::~ConsoleWidget()
|
||||||
{
|
{
|
||||||
delete completer;
|
delete completer;
|
||||||
|
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
|
::close(stdinFile);
|
||||||
|
remove(stdinFifoPath.toStdString().c_str());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConsoleWidget::eventFilter(QObject *obj, QEvent *event)
|
bool ConsoleWidget::eventFilter(QObject *obj, QEvent *event)
|
||||||
@ -150,7 +179,7 @@ void ConsoleWidget::addDebugOutput(const QString &msg)
|
|||||||
|
|
||||||
void ConsoleWidget::focusInputLineEdit()
|
void ConsoleWidget::focusInputLineEdit()
|
||||||
{
|
{
|
||||||
ui->inputLineEdit->setFocus();
|
ui->r2InputLineEdit->setFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleWidget::removeLastLine()
|
void ConsoleWidget::removeLastLine()
|
||||||
@ -170,7 +199,7 @@ void ConsoleWidget::executeCommand(const QString &command)
|
|||||||
if (!commandTask.isNull()) {
|
if (!commandTask.isNull()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ui->inputLineEdit->setEnabled(false);
|
ui->r2InputLineEdit->setEnabled(false);
|
||||||
|
|
||||||
QString cmd_line = "[" + RAddressString(Core()->getOffset()) + "]> " + command;
|
QString cmd_line = "[" + RAddressString(Core()->getOffset()) + "]> " + command;
|
||||||
addOutput(cmd_line);
|
addOutput(cmd_line);
|
||||||
@ -184,8 +213,8 @@ void ConsoleWidget::executeCommand(const QString &command)
|
|||||||
scrollOutputToEnd();
|
scrollOutputToEnd();
|
||||||
historyAdd(command);
|
historyAdd(command);
|
||||||
commandTask.clear();
|
commandTask.clear();
|
||||||
ui->inputLineEdit->setEnabled(true);
|
ui->r2InputLineEdit->setEnabled(true);
|
||||||
ui->inputLineEdit->setFocus();
|
ui->r2InputLineEdit->setFocus();
|
||||||
|
|
||||||
if (oldOffset != Core()->getOffset()) {
|
if (oldOffset != Core()->getOffset()) {
|
||||||
Core()->updateSeek();
|
Core()->updateSeek();
|
||||||
@ -195,6 +224,32 @@ void ConsoleWidget::executeCommand(const QString &command)
|
|||||||
Core()->getAsyncTaskManager()->start(commandTask);
|
Core()->getAsyncTaskManager()->start(commandTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConsoleWidget::sendToStdin(const QString &input)
|
||||||
|
{
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
|
write(stdinFile, (input + "\n").toStdString().c_str(), input.size() + 1);
|
||||||
|
fsync(stdinFile);
|
||||||
|
addOutput("Sent input: '" + input + "'");
|
||||||
|
#else
|
||||||
|
// Stdin redirection isn't currently available in windows because console applications
|
||||||
|
// with stdin already get their own console window with stdin when they are launched
|
||||||
|
// that the user can type into.
|
||||||
|
addOutput("Unsupported feature");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleWidget::onIndexChange()
|
||||||
|
{
|
||||||
|
QString console = ui->inputCombo->currentText();
|
||||||
|
if (console == CONSOLE_DEBUGEE_INPUT) {
|
||||||
|
ui->r2InputLineEdit->setVisible(false);
|
||||||
|
ui->debugeeInputLineEdit->setVisible(true);
|
||||||
|
} else if (console == CONSOLE_R2_INPUT) {
|
||||||
|
ui->r2InputLineEdit->setVisible(true);
|
||||||
|
ui->debugeeInputLineEdit->setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ConsoleWidget::setWrap(bool wrap)
|
void ConsoleWidget::setWrap(bool wrap)
|
||||||
{
|
{
|
||||||
QSettings().setValue(consoleWrapSettingsKey, wrap);
|
QSettings().setValue(consoleWrapSettingsKey, wrap);
|
||||||
@ -202,19 +257,29 @@ void ConsoleWidget::setWrap(bool wrap)
|
|||||||
ui->outputTextEdit->setLineWrapMode(wrap ? QPlainTextEdit::WidgetWidth: QPlainTextEdit::NoWrap);
|
ui->outputTextEdit->setLineWrapMode(wrap ? QPlainTextEdit::WidgetWidth: QPlainTextEdit::NoWrap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleWidget::on_inputLineEdit_returnPressed()
|
void ConsoleWidget::on_r2InputLineEdit_returnPressed()
|
||||||
{
|
{
|
||||||
QString input = ui->inputLineEdit->text();
|
QString input = ui->r2InputLineEdit->text();
|
||||||
if (input.isEmpty()) {
|
if (input.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
executeCommand(input);
|
executeCommand(input);
|
||||||
ui->inputLineEdit->clear();
|
ui->r2InputLineEdit->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleWidget::on_debugeeInputLineEdit_returnPressed()
|
||||||
|
{
|
||||||
|
QString input = ui->debugeeInputLineEdit->text();
|
||||||
|
if (input.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sendToStdin(input);
|
||||||
|
ui->debugeeInputLineEdit->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleWidget::on_execButton_clicked()
|
void ConsoleWidget::on_execButton_clicked()
|
||||||
{
|
{
|
||||||
on_inputLineEdit_returnPressed();
|
on_r2InputLineEdit_returnPressed();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleWidget::showCustomContextMenu(const QPoint &pt)
|
void ConsoleWidget::showCustomContextMenu(const QPoint &pt)
|
||||||
@ -238,9 +303,9 @@ void ConsoleWidget::historyNext()
|
|||||||
--lastHistoryPosition;
|
--lastHistoryPosition;
|
||||||
|
|
||||||
if (lastHistoryPosition >= 0) {
|
if (lastHistoryPosition >= 0) {
|
||||||
ui->inputLineEdit->setText(history.at(lastHistoryPosition));
|
ui->r2InputLineEdit->setText(history.at(lastHistoryPosition));
|
||||||
} else {
|
} else {
|
||||||
ui->inputLineEdit->clear();
|
ui->r2InputLineEdit->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -255,7 +320,7 @@ void ConsoleWidget::historyPrev()
|
|||||||
lastHistoryPosition = history.size() - 2;
|
lastHistoryPosition = history.size() - 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
ui->inputLineEdit->setText(history.at(++lastHistoryPosition));
|
ui->r2InputLineEdit->setText(history.at(++lastHistoryPosition));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,7 +351,7 @@ void ConsoleWidget::updateCompletion()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto current = ui->inputLineEdit->text();
|
auto current = ui->r2InputLineEdit->text();
|
||||||
auto completions = Core()->autocomplete(current, R_LINE_PROMPT_DEFAULT);
|
auto completions = Core()->autocomplete(current, R_LINE_PROMPT_DEFAULT);
|
||||||
int lastSpace = current.lastIndexOf(' ');
|
int lastSpace = current.lastIndexOf(' ');
|
||||||
if (lastSpace >= 0) {
|
if (lastSpace >= 0) {
|
||||||
@ -301,13 +366,14 @@ void ConsoleWidget::updateCompletion()
|
|||||||
void ConsoleWidget::clear()
|
void ConsoleWidget::clear()
|
||||||
{
|
{
|
||||||
disableCompletion();
|
disableCompletion();
|
||||||
ui->inputLineEdit->clear();
|
ui->r2InputLineEdit->clear();
|
||||||
|
ui->debugeeInputLineEdit->clear();
|
||||||
|
|
||||||
invalidateHistoryPosition();
|
invalidateHistoryPosition();
|
||||||
|
|
||||||
// Close the potential shown completer popup
|
// Close the potential shown completer popup
|
||||||
ui->inputLineEdit->clearFocus();
|
ui->r2InputLineEdit->clearFocus();
|
||||||
ui->inputLineEdit->setFocus();
|
ui->r2InputLineEdit->setFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleWidget::scrollOutputToEnd()
|
void ConsoleWidget::scrollOutputToEnd()
|
||||||
@ -357,6 +423,7 @@ void ConsoleWidget::redirectOutput()
|
|||||||
|
|
||||||
pipeSocket = new QLocalSocket(this);
|
pipeSocket = new QLocalSocket(this);
|
||||||
|
|
||||||
|
origStdin = fdopen(dup(fileno(stderr)), "r");
|
||||||
origStderr = fdopen(dup(fileno(stderr)), "a");
|
origStderr = fdopen(dup(fileno(stderr)), "a");
|
||||||
origStdout = fdopen(dup(fileno(stdout)), "a");
|
origStdout = fdopen(dup(fileno(stdout)), "a");
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
@ -373,6 +440,11 @@ void ConsoleWidget::redirectOutput()
|
|||||||
pipeSocket->connectToServer(pipeName, QIODevice::ReadOnly);
|
pipeSocket->connectToServer(pipeName, QIODevice::ReadOnly);
|
||||||
#else
|
#else
|
||||||
pipe(redirectPipeFds);
|
pipe(redirectPipeFds);
|
||||||
|
stdinFifoPath = QString(STDIN_PIPE_NAME).arg(QDir::tempPath(), QUuid::createUuid().toString());
|
||||||
|
mkfifo(stdinFifoPath.toStdString().c_str(), (mode_t) 0777);
|
||||||
|
stdinFile = open(stdinFifoPath.toStdString().c_str(), O_RDWR | O_ASYNC);
|
||||||
|
|
||||||
|
dup2(stdinFile, fileno(stdin));
|
||||||
dup2(redirectPipeFds[PIPE_WRITE], fileno(stderr));
|
dup2(redirectPipeFds[PIPE_WRITE], fileno(stderr));
|
||||||
dup2(redirectPipeFds[PIPE_WRITE], fileno(stdout));
|
dup2(redirectPipeFds[PIPE_WRITE], fileno(stdout));
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "core/MainWindow.h"
|
#include "core/MainWindow.h"
|
||||||
#include "CutterDockWidget.h"
|
#include "CutterDockWidget.h"
|
||||||
#include "common/CommandTask.h"
|
#include "common/CommandTask.h"
|
||||||
|
#include "common/DirectionalComboBox.h"
|
||||||
|
|
||||||
#include <QStringListModel>
|
#include <QStringListModel>
|
||||||
#include <QSocketNotifier>
|
#include <QSocketNotifier>
|
||||||
@ -49,7 +50,9 @@ public slots:
|
|||||||
private slots:
|
private slots:
|
||||||
void setupFont();
|
void setupFont();
|
||||||
|
|
||||||
void on_inputLineEdit_returnPressed();
|
void on_r2InputLineEdit_returnPressed();
|
||||||
|
void on_debugeeInputLineEdit_returnPressed();
|
||||||
|
void onIndexChange();
|
||||||
|
|
||||||
void on_execButton_clicked();
|
void on_execButton_clicked();
|
||||||
|
|
||||||
@ -75,6 +78,7 @@ private:
|
|||||||
void invalidateHistoryPosition();
|
void invalidateHistoryPosition();
|
||||||
void removeLastLine();
|
void removeLastLine();
|
||||||
void executeCommand(const QString &command);
|
void executeCommand(const QString &command);
|
||||||
|
void sendToStdin(const QString &input);
|
||||||
void setWrap(bool wrap);
|
void setWrap(bool wrap);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -99,12 +103,15 @@ private:
|
|||||||
QShortcut *historyDownShortcut;
|
QShortcut *historyDownShortcut;
|
||||||
FILE *origStderr;
|
FILE *origStderr;
|
||||||
FILE *origStdout;
|
FILE *origStdout;
|
||||||
|
FILE *origStdin;
|
||||||
QLocalSocket *pipeSocket;
|
QLocalSocket *pipeSocket;
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
HANDLE hRead;
|
HANDLE hRead;
|
||||||
HANDLE hWrite;
|
HANDLE hWrite;
|
||||||
#else
|
#else
|
||||||
int redirectPipeFds[2];
|
int redirectPipeFds[2];
|
||||||
|
int stdinFile;
|
||||||
|
QString stdinFifoPath;
|
||||||
QVector<char> *redirectionBuffer;
|
QVector<char> *redirectionBuffer;
|
||||||
QSocketNotifier *outputNotifier;
|
QSocketNotifier *outputNotifier;
|
||||||
#endif
|
#endif
|
||||||
|
@ -64,9 +64,9 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>4</number>
|
<number>5</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>4</number>
|
<number>4</number>
|
||||||
@ -80,8 +80,28 @@
|
|||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>2</number>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="DirectionalComboBox" name="inputCombo">
|
||||||
|
<property name="sizeAdjustPolicy">
|
||||||
|
<enum>QComboBox::AdjustToContents</enum>
|
||||||
|
</property>
|
||||||
|
<property name="visible">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLineEdit" name="inputLineEdit">
|
<property name="text">
|
||||||
|
<string>R2 Console</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Debugee Input</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLineEdit" name="r2InputLineEdit">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
|
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@ -99,7 +119,29 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item row="0" column="1">
|
||||||
|
<widget class="QLineEdit" name="debugeeInputLineEdit">
|
||||||
|
<property name="visible">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="frame">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="placeholderText">
|
||||||
|
<string> Enter input for the debugee</string>
|
||||||
|
</property>
|
||||||
|
<property name="clearButtonEnabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="2">
|
||||||
<widget class="QToolButton" name="execButton">
|
<widget class="QToolButton" name="execButton">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
@ -133,8 +175,17 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>DirectionalComboBox</class>
|
||||||
|
<extends>QComboBox</extends>
|
||||||
|
<header>common/DirectionalComboBox.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="../resources.qrc"/>
|
<include location="../resources.qrc"/>
|
||||||
</resources>
|
</resources>
|
||||||
<connections/>
|
<connections/>
|
||||||
</ui>
|
</ui>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user