Pty-Qt - C++ library for work with PseudoTerminals

Pty-Qt is small library for access to console applications by pseudo-terminal interface on Mac, Linux and Windows. On Mac and Linux you can use standard PseudoTerminal API and on Windows you can use WinPty or ConPty.

CI Status

Ubuntu / MacOS X: Build Status

Windows: Build Status

Pre-Requirements and build

  • ConPty part works only on Windows 10 >= 1903 (build > 18309) and can be built only with Windows SDK >= 10.0.18346.0 (maybe >= 17134, but not sure)
  • WinPty part requires winpty sdk for build and winpty.dll with winpty-agent.exe for deployment with target application. WinPty can work on Windows XP and later (depended on used build SDK: vc140 / vc140_xp). You can't link WinPty libraries inside your App, because it use cygwin for build.
  • UnixPty part can work on both Linux/Mac versions, because it based on standard POSIX pseudo terminals API
  • Еarget platforms: x86 or x64
  • Required Qt >= 5.10
  • !!!IMPORTANT!!! Now library has some problems with ConPty, work in progress: https://github.com/Microsoft/console/issues/388

Build on Windows (Git Bash)

git clone https://github.com/Microsoft/vcpkg.git vcpkg
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg.exe integrate install
./vcpkg.exe install qt-base:x64-windows qt5-network:x64-windows
export VCPKG_ROOT=`pwd`
cd ..
git clone https://github.com/kafeg/ptyqt.git ptyqt
mkdir ptyqt-build
cd ptyqt-build
${VCPKG_ROOT}/downloads/tools/cmake-3.12.4-windows/cmake-3.12.4-win32-x86/bin/cmake.exe ../ptyqt "-DCMAKE_TOOLCHAIN_FILE=${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" "-DVCPKG_TARGET_TRIPLET=x64-windows"
${VCPKG_ROOT}/downloads/tools/cmake-3.12.4-windows/cmake-3.12.4-win32-x86/bin/cmake.exe --build . --target winpty
${VCPKG_ROOT}/downloads/tools/cmake-3.12.4-windows/cmake-3.12.4-win32-x86/bin/cmake.exe --build .

Build on Ubuntu

sudo apt-get install qtbase5-dev cmake libqt5websockets5-dev
git clone https://github.com/kafeg/ptyqt.git ptyqt
mkdir ptyqt-build
cd ptyqt-build
cmake ../ptyqt
cmake --build .

Build on Mac

brew install qt cmake
git clone https://github.com/kafeg/ptyqt.git ptyqt
mkdir ptyqt-build
cd ptyqt-build
cmake ../ptyqt "-DCMAKE_PREFIX_PATH=/usr/local/Cellar/qt/5.12.1"
cmake --build .

Usage

Standard way: build and install library then link it to your project and check examples for sample code. Simple code snippet from 'xtermjs' example:

#include <QCoreApplication>
#include <QWebSocketServer>
#include <QWebSocket>
#include "ptyqt.h"
#include <QTimer>
#include <QProcessEnvironment>

#define PORT 4242

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);

    //start WebSockets server for receive connections from xterm.js
    QWebSocketServer wsServer("TestServer", QWebSocketServer::NonSecureMode);
    if (!wsServer.listen(QHostAddress::Any, PORT))
        return 1;

    QMap<QWebSocket *, IPtyProcess *> sessions;

    //create new session on new connection
    QObject::connect(&wsServer, &QWebSocketServer::newConnection, [&wsServer, &sessions]()
    {
        //handle new connection
        QWebSocket *wSocket = wsServer.nextPendingConnection();

        //use cmd.exe or bash, depends on target platform
        IPtyProcess::PtyType ptyType = IPtyProcess::WinPty;
        QString shellPath = "c:\\Windows\\system32\\cmd.exe";
#ifdef Q_OS_UNIX
        shellPath = "/bin/bash";
        ptyType = IPtyProcess::UnixPty;
#endif

        //create new Pty instance
        IPtyProcess *pty = PtyQt::createPtyProcess(ptyType);

        qDebug() << "New connection" << wSocket->peerAddress() << wSocket->peerPort() << pty->pid();

        //start Pty process ()
        pty->startProcess(shellPath, QProcessEnvironment::systemEnvironment().toStringList(), 80, 24);

        //connect read channel from Pty process to write channel on websocket
        QObject::connect(pty->notifier(), &QIODevice::readyRead, [wSocket, pty]()
        {
            wSocket->sendTextMessage(pty->readAll());
        });

        //connect read channel of Websocket to write channel of Pty process
        QObject::connect(wSocket, &QWebSocket::textMessageReceived, [wSocket, pty](const QString &message)
        {
            pty->write(message.toUtf8());
        });

        //...
        //for example handle disconnections, process crashes and stuff like that...
        //...

        //add connection to list of active connections
        sessions.insert(wSocket, pty);
    });

    //stop eventloop if needed
    //QTimer::singleShot(5000, [](){ qApp->quit(); });

    //exec eventloop
    bool res = app.exec();

    QMapIterator<QWebSocket *, IPtyProcess *> it(sessions);
    while (it.hasNext())
    {
        it.next();

        it.key()->deleteLater();
        delete it.value();
    }
    sessions.clear();

    return res;
}

Examples

XtermJS

  • build and run example
  • install nodejs (your prefer way)
  • open console and run:
cd ptyqt/examples/xtermjs
npm install xterm
npm install http-server -g
http-server ./

QTerminal

in dev...

More information

Resources used to develop this library:

S
Description
No description provided
Readme 565 KiB
Languages
C++ 88.1%
CMake 11.9%