From a7e8db95a2a576b8afed2c21346747a350485090 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Thu, 10 Mar 2016 10:28:24 -0500 Subject: Finish cleaning up the TTY Process class, and get it setup for close notifications as well. Now the TTY Process thing is finished, just need to fix up the binary data display on the widget side of things. --- .../lumina-terminal/TerminalWidget.cpp | 41 +++++------- desktop-utilities/lumina-terminal/TerminalWidget.h | 1 - desktop-utilities/lumina-terminal/TtyProcess.cpp | 72 +++++++++++++++++----- desktop-utilities/lumina-terminal/TtyProcess.h | 21 +++++-- 4 files changed, 88 insertions(+), 47 deletions(-) (limited to 'desktop-utilities') diff --git a/desktop-utilities/lumina-terminal/TerminalWidget.cpp b/desktop-utilities/lumina-terminal/TerminalWidget.cpp index 939b9711..6818201a 100644 --- a/desktop-utilities/lumina-terminal/TerminalWidget.cpp +++ b/desktop-utilities/lumina-terminal/TerminalWidget.cpp @@ -19,24 +19,15 @@ TerminalWidget::TerminalWidget(QWidget *parent, QString dir) : QTextEdit(parent) //Create/open the TTY port PROC = new TTYProcess(this); qDebug() << "Open new TTY"; - int fd; - bool ok = PROC->startTTY( fd, QProcessEnvironment::systemEnvironment().value("SHELL","/bin/sh") ); + //int fd; + bool ok = PROC->startTTY( QProcessEnvironment::systemEnvironment().value("SHELL","/bin/sh") ); qDebug() << " - opened:" << ok; this->setEnabled(PROC->isOpen()); //Connect the signals/slots - //connect(PROC, SIGNAL(readyRead()), this, SLOT(UpdateText()) ); - connect(PROC, SIGNAL(aboutToClose()), this, SLOT(ShellClosed()) ); - - sn= new QSocketNotifier(fd, QSocketNotifier::Read); - sn->setEnabled(true); - connect(sn, SIGNAL(activated(int)), this, SLOT(UpdateText())); + connect(PROC, SIGNAL(readyRead()), this, SLOT(UpdateText()) ); + connect(PROC, SIGNAL(processClosed()), this, SLOT(ShellClosed()) ); - upTimer = new QTimer(this); - upTimer->setInterval(1000); - // connect(upTimer, SIGNAL(timeout()), this, SLOT(UpdateText()) ); - - upTimer->start(); } TerminalWidget::~TerminalWidget(){ @@ -44,8 +35,7 @@ TerminalWidget::~TerminalWidget(){ } void TerminalWidget::aboutToClose(){ - if(PROC->isOpen()){ PROC->close(); } //TTY PORT - //if(PROC->state()!=QProcess::NotRunning){ PROC->close(); PROC->kill(); } //QProcess + if(PROC->isOpen()){ PROC->closeTTY(); } //TTY PORT } // ================== @@ -58,10 +48,11 @@ void TerminalWidget::UpdateText(){ //if ( PROC->bytesAvailable() <= 0 ) // return; - qDebug() << "Reading all data"; + /*qDebug() << "Reading all data"; char buffer[64]; ssize_t rtot = read(sn->socket(),&buffer,64); - buffer[rtot]='\0'; + buffer[rtot]='\0';*/ + QByteArray buffer = PROC->readTTY(); qDebug() << "Process Data:" << QString(buffer); this->insertPlainText(QString(buffer)); //adjust the scrollbar as needed @@ -79,22 +70,22 @@ void TerminalWidget::keyPressEvent(QKeyEvent *ev){ //Check for special key combinations first QString txt = ev->text(); if(txt.isEmpty()){ return; } // modifier key - nothing to send yet - switch(ev->key()){ + /*switch(ev->key()){ //case Qt::Key_Backspace: case Qt::Key_Left: case Qt::Key_Right: case Qt::Key_Up: case Qt::Key_Down: break; - /*case Qt::Key_Return: - case Qt::Key_Enter: - txt = "\r";*/ - default: + //case Qt::Key_Return: + //case Qt::Key_Enter: + //txt = "\r"; + //default: //All other events can get echoed onto the widget (non-movement) - QTextEdit::keyPressEvent(ev); //echo the input on the widget - } + //QTextEdit::keyPressEvent(ev); //echo the input on the widget + }*/ QByteArray ba; ba.append(txt); //avoid any byte conversions - qDebug() << "Forward Input:" << txt << ev->key(); + qDebug() << "Forward Input:" << txt << ev->key() << ba; PROC->writeTTY(ba); } diff --git a/desktop-utilities/lumina-terminal/TerminalWidget.h b/desktop-utilities/lumina-terminal/TerminalWidget.h index 7e08226a..59d097d4 100644 --- a/desktop-utilities/lumina-terminal/TerminalWidget.h +++ b/desktop-utilities/lumina-terminal/TerminalWidget.h @@ -27,7 +27,6 @@ private: //QProcess *PROC; QSocketNotifier *sn; - QTimer *upTimer; private slots: void UpdateText(); diff --git a/desktop-utilities/lumina-terminal/TtyProcess.cpp b/desktop-utilities/lumina-terminal/TtyProcess.cpp index e0375410..b3c6aebc 100644 --- a/desktop-utilities/lumina-terminal/TtyProcess.cpp +++ b/desktop-utilities/lumina-terminal/TtyProcess.cpp @@ -1,24 +1,17 @@ #include "TtyProcess.h" -//Standard C library functions for PTY access/setup -#include -#include -#include -#include -#include -#include -#include - -TTYProcess::TTYProcess(QObject *parent) : QFile(parent){ - childProc = 0; +TTYProcess::TTYProcess(QObject *parent) : QObject(parent){ + childProc = 0; + sn = 0; + ttyfd = 0; } TTYProcess::~TTYProcess(){ - kill(childProc, SIGKILL); + closeTTY(); //make sure everything is closed properly } // === PUBLIC === -bool TTYProcess::startTTY(int &retfd, QString prog, QStringList args){ +bool TTYProcess::startTTY(QString prog, QStringList args){ //Turn the program/arguments into C-compatible arrays char cprog[prog.length()]; strcpy(cprog, prog.toLocal8Bit().data()); char *cargs[args.length()+2]; @@ -44,12 +37,28 @@ bool TTYProcess::startTTY(int &retfd, QString prog, QStringList args){ if(tmp<0){ return false; } //error else{ childProc = tmp; - this->setFileName( ptsname(FD) ); - retfd = FD; + //Load the file for close notifications + //TO-DO + //Watch the socket for activity + sn= new QSocketNotifier(FD, QSocketNotifier::Read); + sn->setEnabled(true); + connect(sn, SIGNAL(activated(int)), this, SLOT(checkStatus(int)) ); ttyfd = FD; qDebug() << " - PTY:" << ptsname(FD); - return this->open(QIODevice::ReadWrite | QIODevice::Unbuffered); - //return true; + return true; + } +} + +void TTYProcess::closeTTY(){ + int junk; + if(0==waitpid(childProc, &junk, WNOHANG)){ + kill(childProc, SIGKILL); + } + if(ttyfd!=0 && sn!=0){ + sn->setEnabled(false); + ::close(ttyfd); + ttyfd = 0; + emit processClosed(); } } @@ -58,6 +67,20 @@ void TTYProcess::writeTTY(QByteArray output){ qDebug() << "Wrote:" << written; } +QByteArray TTYProcess::readTTY(){ + QByteArray BA; + if(sn==0){ return BA; } //not setup yet + char buffer[64]; + ssize_t rtot = read(sn->socket(),&buffer,64); + buffer[rtot]='\0'; + BA = QByteArray(buffer, rtot); + return BA; +} + +bool TTYProcess::isOpen(){ + return (ttyfd!=0); +} + // === PRIVATE === pid_t TTYProcess::LaunchProcess(int& fd, char *prog, char **child_args){ //Returns: -1 for errors, positive value (file descriptor) for the master side of the TTY to watch @@ -101,3 +124,18 @@ pid_t TTYProcess::LaunchProcess(int& fd, char *prog, char **child_args){ //MASTER thread (or error) return PID; } + +// === PRIVATE SLOTS === +void TTYProcess::checkStatus(int sock){ + //This is run when the socket gets activated + if(sock!=ttyfd){ + + } + //Make sure the child PID is still active + int junk; + if(0!=waitpid(childProc, &junk, WNOHANG)){ + this->closeTTY(); //clean up everything else + }else{ + emit readyRead(); + } +} diff --git a/desktop-utilities/lumina-terminal/TtyProcess.h b/desktop-utilities/lumina-terminal/TtyProcess.h index 38cca5a4..45cdedd2 100644 --- a/desktop-utilities/lumina-terminal/TtyProcess.h +++ b/desktop-utilities/lumina-terminal/TtyProcess.h @@ -13,7 +13,7 @@ #define _LUMINA_DESKTOP_UTILITIES_TERMINAL_TTY_PROCESS_WIDGET_H #include -#include +#include //Standard C library functions for PTY access/setup #include @@ -22,21 +22,29 @@ #include #include #include +#include #include - -class TTYProcess : public QFile{ +class TTYProcess : public QObject{ Q_OBJECT public: TTYProcess(QObject *parent = 0); ~TTYProcess(); - bool startTTY(int &retfd, QString prog, QStringList args = QStringList()); + bool startTTY(QString prog, QStringList args = QStringList()); + void closeTTY(); + + //Primary read/write functions void writeTTY(QByteArray output); + QByteArray readTTY(); + //Status update checks + bool isOpen(); + private: pid_t childProc; int ttyfd; + QSocketNotifier *sn; //==================================== // C Library function for setting up the PTY @@ -49,7 +57,12 @@ private: //==================================== static pid_t LaunchProcess(int& fd, char *prog, char **child_args); +private slots: + void checkStatus(int); +signals: + void readyRead(); + void processClosed(); }; #endif -- cgit