diff options
author | Ken Moore <moorekou@gmail.com> | 2016-03-09 16:28:37 -0500 |
---|---|---|
committer | Ken Moore <moorekou@gmail.com> | 2016-03-09 16:28:37 -0500 |
commit | c741f4853592c5901ff60711236a5e732514abd4 (patch) | |
tree | 9f00dcc728f1ef53a4655dbfac00b5f352cf8f1d | |
parent | Get a bunch more of the lumina-terminal app written up. Still not quite done ... (diff) | |
download | lumina-c741f4853592c5901ff60711236a5e732514abd4.tar.gz lumina-c741f4853592c5901ff60711236a5e732514abd4.tar.bz2 lumina-c741f4853592c5901ff60711236a5e732514abd4.zip |
Oops, forgot to add the new TtyProcess files in the last commit.
-rw-r--r-- | desktop-utilities/lumina-terminal/TtyProcess.cpp | 91 | ||||
-rw-r--r-- | desktop-utilities/lumina-terminal/TtyProcess.h | 43 |
2 files changed, 134 insertions, 0 deletions
diff --git a/desktop-utilities/lumina-terminal/TtyProcess.cpp b/desktop-utilities/lumina-terminal/TtyProcess.cpp new file mode 100644 index 00000000..1818a91b --- /dev/null +++ b/desktop-utilities/lumina-terminal/TtyProcess.cpp @@ -0,0 +1,91 @@ +#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) : QSerialPort(parent){ + childProc = 0; +} + +TTYProcess::~TTYProcess(){ + kill(childProc, SIGKILL); +} + +// === PUBLIC === +bool TTYProcess::start(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()+1]; + for(int i=0; i<args.length()+1; i++){ + if(i<args.length()){ + cargs[i] = new char[ args[i].toLocal8Bit().size()+1]; + strcpy( cargs[i], args[i].toLocal8Bit().data() ); + }else{ + cargs[i] = new char[1]; + strcpy(cargs[i],"\0"); + } + } + qDebug() << "PTY Start:" << prog; + //Launch the process attached to a new PTY + int FD = 0; + pid_t tmp = LaunchProcess(FD, cprog, cargs); + qDebug() << " - PID:" << tmp; + qDebug() << " - FD:" << FD; + if(tmp<0){ return false; } //error + else{ + childProc = tmp; + this->setPortName( ptsname(FD) ); + qDebug() << " - PTY:" << this->portName(); + return this->open(QIODevice::ReadWrite); + } +} + +// === 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 + + //First open/setup a new pseudo-terminal file/device on the system (master side) + fd = posix_openpt(O_RDWR); //open read/write + if(fd<0){ return -1; } //could not create pseudo-terminal + int rc = grantpt(fd); //set permissions + if(rc!=0){ return -1; } + rc = unlockpt(fd); //unlock file (ready for use) + if(rc!=0){ return -1; } + //Now fork, return the Master device and setup the child + pid_t PID = fork(); + if(PID==0){ + //SLAVE/child + int fds = ::open(ptsname(fd), O_RDWR); //open slave side read/write + ::close(fd); //close the master side from the slave thread + + //Adjust the slave side mode to RAW + struct termios TSET; + rc = tcgetattr(fds, &TSET); //read the current settings + cfmakeraw(&TSET); //set the RAW mode on the settings + tcsetattr(fds, TCSANOW, &TSET); //apply the changed settings + + //Change the controlling terminal in child thread to the slave PTY + ::close(0); //close current terminal standard input + ::close(1); //close current terminal standard output + ::close(2); //close current terminal standard error + dup(fds); // Set slave PTY as standard input (0); + dup(fds); // Set slave PTY as standard output (1); + dup(fds); // Set slave PTY as standard error (2); + + setsid(); //Make current process new session leader (so we can set controlling terminal) + ioctl(0,TIOCSCTTY, 1); //Set the controlling terminal to the slave PTY + + //Execute the designated program + rc = execvp(prog, child_args); + ::close(fds); //no need to keep original file descriptor open any more + exit(rc); + } + //MASTER thread (or error) + return PID; +} diff --git a/desktop-utilities/lumina-terminal/TtyProcess.h b/desktop-utilities/lumina-terminal/TtyProcess.h new file mode 100644 index 00000000..c764b5ae --- /dev/null +++ b/desktop-utilities/lumina-terminal/TtyProcess.h @@ -0,0 +1,43 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2015, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +// This is basically a replacement for QProcess, where all process/terminal outputs +// are redirected and not just the standard input/output channels. This allows it +// to be used for terminal-like apps (shells) which directly modify the terminal output +// rather than stick to input/output channels for communication. +//=========================================== +#ifndef _LUMINA_DESKTOP_UTILITIES_TERMINAL_TTY_PROCESS_WIDGET_H +#define _LUMINA_DESKTOP_UTILITIES_TERMINAL_TTY_PROCESS_WIDGET_H + +#include <QSerialPort> +#include <QDebug> + +class TTYProcess : public QSerialPort{ + Q_OBJECT +public: + TTYProcess(QObject *parent = 0); + ~TTYProcess(); + + bool start(QString prog, QStringList args = QStringList()); + +private: + pid_t childProc; + + //==================================== + // C Library function for setting up the PTY + // Inputs: + // int &fd: (output) file descriptor for the master PTY (positive integer if valid) + // char *prog: program to run + // char **args: program arguments + // Returns: + // -1 for errors, child process PID (positive integer) if successful + //==================================== + static pid_t LaunchProcess(int& fd, char *prog, char **child_args); + + +}; + +#endif
\ No newline at end of file |