aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKen Moore <moorekou@gmail.com>2016-03-09 16:28:37 -0500
committerKen Moore <moorekou@gmail.com>2016-03-09 16:28:37 -0500
commitc741f4853592c5901ff60711236a5e732514abd4 (patch)
tree9f00dcc728f1ef53a4655dbfac00b5f352cf8f1d
parentGet a bunch more of the lumina-terminal app written up. Still not quite done ... (diff)
downloadlumina-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.cpp91
-rw-r--r--desktop-utilities/lumina-terminal/TtyProcess.h43
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
bgstack15