diff options
-rw-r--r-- | desktop-utilities/lumina-terminal/TerminalWidget.cpp | 41 | ||||
-rw-r--r-- | desktop-utilities/lumina-terminal/TerminalWidget.h | 1 | ||||
-rw-r--r-- | desktop-utilities/lumina-terminal/TtyProcess.cpp | 72 | ||||
-rw-r--r-- | desktop-utilities/lumina-terminal/TtyProcess.h | 21 |
4 files changed, 88 insertions, 47 deletions
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 <stdlib.h> -#include <fcntl.h> -#include <termios.h> -#include <unistd.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <signal.h> - -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 <QDebug> -#include <QFile> +#include <QSocketNotifier> //Standard C library functions for PTY access/setup #include <stdlib.h> @@ -22,21 +22,29 @@ #include <unistd.h> #include <sys/ioctl.h> #include <sys/types.h> +#include <sys/wait.h> #include <signal.h> - -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 |