-rw-r--r-- | noncore/apps/opie-console/MyPty.cpp | 299 | ||||
-rw-r--r-- | noncore/apps/opie-console/MyPty.h | 95 | ||||
-rw-r--r-- | noncore/apps/opie-console/default.cpp | 16 | ||||
-rw-r--r-- | noncore/apps/opie-console/default.h | 4 | ||||
-rw-r--r-- | noncore/apps/opie-console/emulation_handler.cpp | 89 | ||||
-rw-r--r-- | noncore/apps/opie-console/emulation_handler.h | 8 | ||||
-rw-r--r-- | noncore/apps/opie-console/io_layer.h | 4 | ||||
-rw-r--r-- | noncore/apps/opie-console/opie-console.pro | 6 |
8 files changed, 507 insertions, 14 deletions
diff --git a/noncore/apps/opie-console/MyPty.cpp b/noncore/apps/opie-console/MyPty.cpp new file mode 100644 index 0000000..10828b0 --- a/dev/null +++ b/noncore/apps/opie-console/MyPty.cpp @@ -0,0 +1,299 @@ +/* -------------------------------------------------------------------------- */ +/* */ +/* [MyPty.C] Pseudo Terminal Device */ +/* */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> */ +/* */ +/* This file is part of Konsole - an X terminal for KDE */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Ported Konsole to Qt/Embedded */ +/* */ +/* Copyright (C) 2000 by John Ryland <jryland@trolltech.com> */ +/* */ +/* -------------------------------------------------------------------------- */ + +/* If you're compiling konsole on non-Linux platforms and find + problems that you can track down to this file, please have + a look into ../README.ports, too. +*/ + +/*! \file +*/ + +/*! \class TEPty + + \brief Ptys provide a pseudo terminal connection to a program. + + Although closely related to pipes, these pseudo terminal connections have + some ability, that makes it nessesary to uses them. Most importent, they + know about changing screen sizes and UNIX job control. + + Within the terminal emulation framework, this class represents the + host side of the terminal together with the connecting serial line. + + One can create many instances of this class within a program. + As a side effect of using this class, a signal(2) handler is + installed on SIGCHLD. + + \par FIXME + + [NOTE: much of the technical stuff below will be replaced by forkpty.] + + publish the SIGCHLD signal if not related to an instance. + + clearify TEPty::done vs. TEPty::~TEPty semantics. + check if pty is restartable via run after done. + + \par Pseudo terminals + + Pseudo terminals are a unique feature of UNIX, and always come in form of + pairs of devices (/dev/ptyXX and /dev/ttyXX), which are connected to each + other by the operating system. One may think of them as two serial devices + linked by a null-modem cable. Being based on devices the number of + simultanous instances of this class is (globally) limited by the number of + those device pairs, which is 256. + + Another technic are UNIX 98 PTY's. These are supported also, and prefered + over the (obsolete) predecessor. + + There's a sinister ioctl(2), signal(2) and job control stuff + nessesary to make everything work as it should. +*/ + + +#include <qapplication.h> +#include <qsocketnotifier.h> +#include <qstring.h> + +#include <stdlib.h> +#include <stdio.h> +#include <signal.h> +#include <fcntl.h> +#include <unistd.h> +#include <termios.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/wait.h> + +#ifdef HAVE_OPENPTY +#include <pty.h> +#endif + +#include "MyPty.h" + + +#undef VERBOSE_DEBUG + + +/* -------------------------------------------------------------------------- */ + +/*! + Informs the client program about the + actual size of the window. +*/ + +void MyPty::setSize(int lines, int columns) +{ + struct winsize wsize; + wsize.ws_row = (unsigned short)lines; + wsize.ws_col = (unsigned short)columns; + if(m_fd < 0) return; + ioctl(m_fd,TIOCSWINSZ,(char *)&wsize); +} + + +void MyPty::donePty() +{ + // This is code from the Qt DumbTerminal example + int status = 0; + + ::close(m_fd); + + if (m_cpid) { + kill(m_cpid, SIGHUP); + waitpid(m_cpid, &status, 0); + } + + emit done(status); +} + + +const char* MyPty::deviceName() +{ + return m_ttynam; +} + + +void MyPty::error() +{ + // This is code from the Qt DumbTerminal example + donePty(); +} + +void MyPty::start() { + char* cmd = "/bin/sh"; + QStrList lis; + int r =run(cmd, lis, 0, 0); + r = r; +} +/*! + start the client program. +*/ +int MyPty::run(const char* cmd, QStrList &, const char*, int) +{ + // This is code from the Qt DumbTerminal example + m_cpid = fork(); + + if ( !m_cpid ) { + // child - exec shell on tty + for (int sig = 1; sig < NSIG; sig++) signal(sig,SIG_DFL); + int ttyfd = ::open(m_ttynam, O_RDWR); + dup2(ttyfd, STDIN_FILENO); + dup2(ttyfd, STDOUT_FILENO); + dup2(ttyfd, STDERR_FILENO); + // should be done with tty, so close it + ::close(ttyfd); + static struct termios ttmode; + if ( setsid() < 0 ) + perror( "failed to set process group" ); +#if defined (TIOCSCTTY) + // grabbed from APUE by Stevens + ioctl(STDIN_FILENO, TIOCSCTTY, 0); +#endif + tcgetattr( STDIN_FILENO, &ttmode ); + ttmode.c_cc[VINTR] = 3; + ttmode.c_cc[VERASE] = 8; + tcsetattr( STDIN_FILENO, TCSANOW, &ttmode ); + setenv("TERM","vt100",1); + setenv("COLORTERM","0",1); + + if (getuid() == 0) { + char msg[] = "WARNING: You are running this shell as root!\n"; + write(ttyfd, msg, sizeof(msg)); + } + execl(cmd, cmd, 0); + + donePty(); + exit(-1); + } + + // parent - continue as a widget + QSocketNotifier* sn_r = new QSocketNotifier(m_fd,QSocketNotifier::Read,this); + QSocketNotifier* sn_e = new QSocketNotifier(m_fd,QSocketNotifier::Exception,this); + connect(sn_r,SIGNAL(activated(int)),this,SLOT(readPty())); + connect(sn_e,SIGNAL(activated(int)),this,SLOT(error())); + + return 0; +} + +int MyPty::openPty() +{ + // This is code from the Qt DumbTerminal example + int ptyfd = -1; + +#ifdef HAVE_OPENPTY + int ttyfd; + if ( openpty(&ptyfd,&ttyfd,ttynam,0,0) ) + ptyfd = -1; + else + close(ttyfd); // we open the ttynam ourselves. +#else + for (const char* c0 = "pqrstuvwxyzabcde"; ptyfd < 0 && *c0 != 0; c0++) { + for (const char* c1 = "0123456789abcdef"; ptyfd < 0 && *c1 != 0; c1++) { + sprintf(m_ptynam,"/dev/pty%c%c",*c0,*c1); + sprintf(m_ttynam,"/dev/tty%c%c",*c0,*c1); + if ((ptyfd = ::open(m_ptynam,O_RDWR)) >= 0) { + if (geteuid() != 0 && !access(m_ttynam,R_OK|W_OK) == 0) { + ::close(ptyfd); + ptyfd = -1; + } + } + } + } +#endif + + if ( ptyfd < 0 ) { + qApp->exit(1); + return -1; + } + + return ptyfd; +} + +/*! + Create an instance. +*/ +MyPty::MyPty(const Profile&) : m_cpid(0) +{ + m_fd = openPty(); +} + +/*! + Destructor. + Note that the related client program is not killed + (yet) when a instance is deleted. +*/ +MyPty::~MyPty() +{ + donePty(); +} +QString MyPty::identifier()const { + return QString::fromLatin1("term"); +} +QString MyPty::name()const{ + return identifier(); +} +bool MyPty::open() { + start(); + return true; +} +void MyPty::close() { + donePty(); +} +void MyPty::reload( const Profile& ) { + +} +/*! sends len bytes through the line */ +void MyPty::send(const QByteArray& ar) +{ + +#ifdef VERBOSE_DEBUG + // verbose debug + printf("sending bytes:\n"); + for (uint i = 0; i < ar.count(); i++) + printf("%c", ar[i]); + printf("\n"); +#endif + + ::write(m_fd, ar.data(), ar.count()); +} + +/*! indicates that a block of data is received */ +void MyPty::readPty() +{ + QByteArray buf(4096); + + int len = ::read( m_fd, buf.data(), 4096 ); + + if (len == -1) + donePty(); + + if (len < 0) + return; + + buf.resize(len); + emit received(buf); + +#ifdef VERBOSE_DEBUG + // verbose debug + printf("read bytes:\n"); + for (uint i = 0; i < buf.count(); i++) + printf("%c", buf[i]); + printf("\n"); +#endif + +} + diff --git a/noncore/apps/opie-console/MyPty.h b/noncore/apps/opie-console/MyPty.h new file mode 100644 index 0000000..9231a8a --- a/dev/null +++ b/noncore/apps/opie-console/MyPty.h @@ -0,0 +1,95 @@ +/* -------------------------------------------------------------------------- */ +/* */ +/* [MyPty.h] Pseudo Terminal Device */ +/* */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> */ +/* */ +/* This file is part of Konsole - an X terminal for KDE */ +/* */ +/* -------------------------------------------------------------------------- */ +/* */ +/* Ported Konsole to Qt/Embedded */ +/* */ +/* Copyright (C) 2000 by John Ryland <jryland@trolltech.com> */ +/* */ +/* -------------------------------------------------------------------------- */ + +/*! \file +*/ + +#ifndef MY_PTY_H +#define MY_PTY_H + +#include <qobject.h> +#include <qstrlist.h> + +#include "io_layer.h" + +class Profile; +class MyPty : public IOLayer +{ + Q_OBJECT +public: + + MyPty(const Profile&); + ~MyPty(); + + + + QString identifier()const; + QString name()const; + + public slots: + /*! + having a `run' separate from the constructor allows to make + the necessary connections to the signals and slots of the + instance before starting the execution of the client. + */ + void start(); + int run(const char* pgm, QStrList & args , const char* term, int addutmp); + bool open(); + void close(); + void reload( const Profile& ); + void setSize(int lines, int columns); + void error(); + + signals: + + /*! + emitted when the client program terminates. + \param status the wait(2) status code of the terminated client program. + */ + void done(int status); + + /*! + emitted when a new block of data comes in. + \param s - the data + \param len - the length of the block + */ + void received(const QByteArray&); + + public slots: + + void send(const QByteArray& ); + +private: + const char* deviceName(); + +protected slots: + void readPty(); + void donePty(); + +private: + int openPty(); + +private: + + char m_ptynam[16]; // "/dev/ptyxx" | "/dev/ptmx" + char m_ttynam[16]; // "/dev/ttyxx" | "/dev/pts/########..." + int m_fd; + int m_cpid; +}; + +#endif diff --git a/noncore/apps/opie-console/default.cpp b/noncore/apps/opie-console/default.cpp index 5c1c05a..64c9542 100644 --- a/noncore/apps/opie-console/default.cpp +++ b/noncore/apps/opie-console/default.cpp @@ -11,3 +11,3 @@ #include "terminalwidget.h" -#include "vt102emulation.h" +#include "MyPty.h" @@ -51,2 +51,5 @@ extern "C" { } + IOLayer* newConsole( const Profile& prof ) { + return new MyPty(prof ); + } @@ -65,2 +68,5 @@ extern "C" { } + ProfileDialogWidget* newConsoleWid( const QString& str, QWidget* wid ) { + return 0l; + } @@ -68,6 +74,6 @@ extern "C" { // Terminal Widget(s) -/* ProfileDialogWidget* newTerminalWidget(const QString& na, QWidget* wid) { + ProfileDialogWidget* newTerminalWidget(const QString& na, QWidget* wid) { return new TerminalWidget(na, wid,0 ); } -*/ + /* // VT Emulations @@ -92,2 +98,3 @@ Default::Default( MetaFactory* fact ) { fact->addIOLayerFactory( "modem", QObject::tr("Modem"), newModemLayer ); + fact->addIOLayerFactory( "console", QObject::tr("Console"), newConsole ); @@ -97,4 +104,5 @@ Default::Default( MetaFactory* fact ) { fact->addConnectionWidgetFactory( "bt", QObject::tr("Bluetooth"), newBTWidget ); + fact->addConnectionWidgetFactory( "console", QObject::tr("Console"), newConsoleWid ); -// fact->addTerminalWidgetFactory( "default", QObject::tr("Default Terminal"), newTerminalWidget ); + fact->addTerminalWidgetFactory( "default", QObject::tr("Default Terminal"), newTerminalWidget ); diff --git a/noncore/apps/opie-console/default.h b/noncore/apps/opie-console/default.h index 288f370..b8cda03 100644 --- a/noncore/apps/opie-console/default.h +++ b/noncore/apps/opie-console/default.h @@ -19,2 +19,3 @@ extern "C" { IOLayer* newIrDaLayer(const Profile& ); + IOLayer* newConsole(const Profile& ); @@ -23,4 +24,5 @@ extern "C" { ProfileDialogWidget* newBTWidget (const QString&, QWidget* ); + ProfileDialogWidget* newConsoleWid (const QString&, QWidget* ); -// ProfileDialogWidget* newTerminalWidget(const QString&, QWidget* ); + ProfileDialogWidget* newTerminalWidget(const QString&, QWidget* ); diff --git a/noncore/apps/opie-console/emulation_handler.cpp b/noncore/apps/opie-console/emulation_handler.cpp index 9e7f56c..48218e6 100644 --- a/noncore/apps/opie-console/emulation_handler.cpp +++ b/noncore/apps/opie-console/emulation_handler.cpp @@ -5,2 +5,3 @@ +#include "profile.h" #include "emulation_handler.h" @@ -31,7 +32,7 @@ EmulationHandler::~EmulationHandler() { } -void EmulationHandler::load( const Profile& ) { - QFont font = QFont("Fixed", 12, QFont::Normal ); - font.setFixedPitch(TRUE); - m_teWid->setVTFont( font ); - m_teWid->setBackgroundColor(Qt::gray ); +void EmulationHandler::load( const Profile& prof) { + m_teWid->setVTFont( font( prof.readNumEntry("Font") ) ); + int num = prof.readNumEntry("Color"); + setColor( foreColor(num), backColor(num) ); + m_teWid->setBackgroundColor(backColor(num) ); } @@ -52 +53,79 @@ QWidget* EmulationHandler::widget() { } +/* + * allocate a new table of colors + */ +void EmulationHandler::setColor( const QColor& fore, const QColor& back ) { + ColorEntry table[TABLE_COLORS]; + const ColorEntry *defaultCt = m_teWid->getdefaultColorTable(); + + for (int i = 0; i < TABLE_COLORS; i++ ) { + if ( i == 0 || i == 10 ) { + table[i].color = fore; + }else if ( i == 1 || i == 11 ) { + table[i].color = back; + table[i].transparent = 0; + }else { + table[i].color = defaultCt[i].color; + } + } +// m_teWid->setColorTable(table ); + m_teWid->update(); +} +QFont EmulationHandler::font( int id ) { + QString name; + int size = 0; + switch(id ) { + default: // fall through + case 0: + name = QString::fromLatin1("Micro"); + size = 4; + break; + case 1: + name = QString::fromLatin1("Fixed"); + size = 7; + break; + case 2: + name = QString::fromLatin1("Fixed"); + size = 12; + break; + } + QFont font(name, size, QFont::Normal ); + font.setFixedPitch(TRUE ); + return font; +} +QColor EmulationHandler::foreColor(int col) { + QColor co; + /* we need to switch it */ + switch( col ) { + default: + case Profile::White: + qWarning("Foreground black"); + /* color is black */ + co = Qt::black; + break; + case Profile::Black: + qWarning("Foreground white"); + co = Qt::white; + break; + } + + return co; +} +QColor EmulationHandler::backColor(int col ) { + QColor co; + /* we need to switch it */ + switch( col ) { + default: + case Profile::White: + qWarning("Background white"); + /* color is white */ + co = Qt::white; + break; + case Profile::Black: + qWarning("Background black"); + co = Qt::black; + break; + } + + return co; +} diff --git a/noncore/apps/opie-console/emulation_handler.h b/noncore/apps/opie-console/emulation_handler.h index 58b94bc..9af7680 100644 --- a/noncore/apps/opie-console/emulation_handler.h +++ b/noncore/apps/opie-console/emulation_handler.h @@ -4,2 +4,3 @@ #include <qobject.h> +#include <qcolor.h> #include <qcstring.h> @@ -28,2 +29,3 @@ class TEWidget; class TEmulation; +class QFont; class EmulationHandler : public QObject { @@ -45,2 +47,3 @@ public: QWidget* widget(); + void setColor( const QColor& fore, const QColor& back ); signals: @@ -49,2 +52,3 @@ signals: + public slots: @@ -54,2 +58,6 @@ private slots: void recvEmulation( const char*, int len ); +private: + QFont font( int ); + QColor foreColor(int ); + QColor backColor(int ); diff --git a/noncore/apps/opie-console/io_layer.h b/noncore/apps/opie-console/io_layer.h index 9c99222..5f2fa3c 100644 --- a/noncore/apps/opie-console/io_layer.h +++ b/noncore/apps/opie-console/io_layer.h @@ -72,3 +72,3 @@ signals: */ - virtual void received( const QByteArray& ) = 0; + virtual void received( const QByteArray& ); @@ -79,3 +79,3 @@ signals: */ - virtual void error( int, const QString& ) = 0; + virtual void error( int, const QString& ); diff --git a/noncore/apps/opie-console/opie-console.pro b/noncore/apps/opie-console/opie-console.pro index 7990a64..c2fb558 100644 --- a/noncore/apps/opie-console/opie-console.pro +++ b/noncore/apps/opie-console/opie-console.pro @@ -29,5 +29,6 @@ HEADERS = io_layer.h io_serial.h io_irda.h io_bt.h io_modem.h \ dialer.h \ + terminalwidget.h \ emulation_handler.h TECommon.h \ TEHistroy.h TEScreen.h TEWidget.h \ - TEmuVt102.h TEmulation.h + TEmuVt102.h TEmulation.h MyPty.h @@ -57,5 +58,6 @@ SOURCES = io_layer.cpp io_serial.cpp io_irda.cpp io_bt.cpp io_modem.cpp \ dialer.cpp \ + terminalwidget.cpp \ emulation_handler.cpp TEHistory.cpp \ TEScreen.cpp TEWidget.cpp \ - TEmuVt102.cpp TEmulation.cpp + TEmuVt102.cpp TEmulation.cpp MyPty.cpp |