From c741f4853592c5901ff60711236a5e732514abd4 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Wed, 9 Mar 2016 16:28:37 -0500 Subject: Oops, forgot to add the new TtyProcess files in the last commit. --- desktop-utilities/lumina-terminal/TtyProcess.cpp | 91 ++++++++++++++++++++++++ desktop-utilities/lumina-terminal/TtyProcess.h | 43 +++++++++++ 2 files changed, 134 insertions(+) create mode 100644 desktop-utilities/lumina-terminal/TtyProcess.cpp create mode 100644 desktop-utilities/lumina-terminal/TtyProcess.h (limited to 'desktop-utilities') 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 +#include +#include +#include +#include +#include +#include + +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; isetPortName( 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 +#include + +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 -- cgit