Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

MyPty.cpp

Go to the documentation of this file.
00001 /* -------------------------------------------------------------------------- */
00002 /*                                                                            */
00003 /* [MyPty.C]               Pseudo Terminal Device                             */
00004 /*                                                                            */
00005 /* -------------------------------------------------------------------------- */
00006 /*                                                                            */
00007 /* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>            */
00008 /*                                                                            */
00009 /* This file is part of Konsole - an X terminal for KDE                       */
00010 /* -------------------------------------------------------------------------- */
00011 /*                                                                            */
00012 /* Ported Konsole to Qt/Embedded                                              */
00013 /*                                                                            */
00014 /* Copyright (C) 2000 by John Ryland <jryland@trolltech.com>                  */
00015 /*                                                                            */
00016 /* -------------------------------------------------------------------------- */
00017 
00018 /* If you're compiling konsole on non-Linux platforms and find
00019    problems that you can track down to this file, please have
00020    a look into ../README.ports, too.
00021 */
00022 
00066 #include "procctl.h"
00067 #include "MyPty.h"
00068 
00069 /* QT */
00070 #include <qsocketnotifier.h>
00071 #include <qfile.h>
00072 
00073 /* STD */
00074 #include <stdlib.h>
00075 #include <stdio.h>
00076 #include <signal.h>
00077 #include <fcntl.h>
00078 #include <unistd.h>
00079 #include <termios.h>
00080 #include <sys/types.h>
00081 #include <sys/ioctl.h>
00082 #include <sys/wait.h>
00083 
00084 
00085 #ifdef HAVE_OPENPTY
00086 #include <pty.h>
00087 #endif
00088 
00089 #undef VERBOSE_DEBUG
00090 
00091 
00092 /* -------------------------------------------------------------------------- */
00093 
00099 void MyPty::setSize(int lines, int columns)
00100 {
00101   struct winsize wsize;
00102   wsize.ws_row = (unsigned short)lines;
00103   wsize.ws_col = (unsigned short)columns;
00104   if(m_fd < 0) return;
00105   ioctl(m_fd,TIOCSWINSZ,(char *)&wsize);
00106 }
00107 
00108 
00109 void MyPty::donePty()
00110 {
00111     // This is code from the Qt DumbTerminal example
00112 
00113     ::close(m_fd);
00114 
00115     if (m_cpid) {
00116         kill(m_cpid, SIGHUP);
00117         //waitpid(m_cpid, &status, 0);
00118         delete m_sn_e;
00119         delete m_sn_r;
00120         m_sn_e = 0l;
00121         m_sn_r = 0l;
00122     }
00123 
00124     m_cpid = 0;
00125     m_fd = -1;
00126 //    emit done(status);
00127 }
00128 
00129 
00130 const char* MyPty::deviceName()
00131 {
00132     return m_ttynam;
00133 }
00134 
00135 
00136 void MyPty::error()
00137 {
00138     // This is code from the Qt DumbTerminal example
00139     donePty();
00140 }
00141 
00142 void MyPty::start() {
00143     QStrList lis;
00144     int r =run(m_cmd.latin1(), lis, 0, 0);
00145     r = r;
00146 }
00150 int MyPty::run(const char* cmd, QStrList &, const char*, int)
00151 {
00152     // This is code from the Qt DumbTerminal example
00153     m_cpid = fork();
00154 
00155     if ( !m_cpid ) {
00156         // child - exec shell on tty
00157         for (int sig = 1; sig < NSIG; sig++) signal(sig,SIG_DFL);
00158         int ttyfd = ::open(m_ttynam, O_RDWR);
00159         dup2(ttyfd, STDIN_FILENO);
00160         dup2(ttyfd, STDOUT_FILENO);
00161         dup2(ttyfd, STDERR_FILENO);
00162         // should be done with tty, so close it
00163 	::close(ttyfd);
00164         static struct termios ttmode;
00165         if ( setsid() < 0 )
00166             perror( "failed to set process group" );
00167 #if defined (TIOCSCTTY)
00168         // grabbed from APUE by Stevens
00169         ioctl(STDIN_FILENO, TIOCSCTTY, 0);
00170 #endif
00171         tcgetattr( STDIN_FILENO, &ttmode );
00172         ttmode.c_cc[VINTR] = 3;
00173         ttmode.c_cc[VERASE] = 8;
00174         tcsetattr( STDIN_FILENO, TCSANOW, &ttmode );
00175         setenv("TERM",m_term,1);
00176         setenv("COLORTERM","0",1);
00177     EnvironmentMap::Iterator it;
00178     for (it = m_env.begin(); it != m_env.end(); it++) {
00179         setenv(it.key().latin1(), it.data().latin1(), 1);
00180     }
00181         if (getuid() == 0) {
00182             char msg[] = "WARNING: You are running this shell as root!\n";
00183             write(ttyfd, msg, sizeof(msg));
00184         }
00185         execl(cmd, cmd, 0);
00186 
00187         donePty();
00188         exit(-1);
00189     }
00190 
00191     // parent - continue as a widget
00192     delete m_sn_r;
00193     m_sn_r = new QSocketNotifier(m_fd,QSocketNotifier::Read,this);
00194     delete m_sn_e;
00195     m_sn_e = new QSocketNotifier(m_fd,QSocketNotifier::Exception,this);
00196     connect(m_sn_r,SIGNAL(activated(int)),this,SLOT(readPty()));
00197     connect(m_sn_e,SIGNAL(activated(int)),this,SLOT(error()));
00198 
00199     return 0;
00200 }
00201 
00202 int MyPty::openPty()
00203 {
00204     // This is code from the Qt DumbTerminal example
00205     int ptyfd = -1;
00206 
00207 #ifdef HAVE_OPENPTY
00208     int ttyfd;
00209     if ( openpty(&ptyfd,&ttyfd,m_ttynam,0,0) )
00210         ptyfd = -1;
00211     else
00212         ::close(ttyfd); // we open the ttynam ourselves.
00213 #else
00214     for (const char* c0 = "pqrstuvwxyzabcde"; ptyfd < 0 && *c0 != 0; c0++) {
00215         for (const char* c1 = "0123456789abcdef"; ptyfd < 0 && *c1 != 0; c1++) {
00216             sprintf(m_ptynam,"/dev/pty%c%c",*c0,*c1);
00217             sprintf(m_ttynam,"/dev/tty%c%c",*c0,*c1);
00218             if ((ptyfd = ::open(m_ptynam,O_RDWR)) >= 0) {
00219                 if (geteuid() != 0 && !access(m_ttynam,R_OK|W_OK) == 0) {
00220 		    ::close(ptyfd);
00221                     ptyfd = -1;
00222                 }
00223             }
00224         }
00225     }
00226 #endif
00227 
00228     if ( ptyfd < 0 ) {
00229 //      qApp->exit(1);
00230         return -1;
00231     }
00232 
00233     return ptyfd;
00234 }
00235 
00239 MyPty::MyPty(const Profile& prof) : m_cpid(0)
00240 {
00241 
00242     int term = prof.readNumEntry("Terminal", Profile::VT100 );
00243     switch( term ) {
00244     default:
00245     case Profile::VT100:
00246     case Profile::VT102:
00247         m_term = "vt100";
00248         break;
00249     case Profile::Linux:
00250         m_term = "linux";
00251         break;
00252     case Profile::XTerm:
00253         m_term = "xterm";
00254         break;
00255     }
00256     m_sn_e = 0l;
00257     m_sn_r = 0l;
00258   m_fd = openPty();
00259   ProcCtl* ctl = ProcCtl::self();
00260   Q_UNUSED(ctl);
00261   reload(prof);
00262 }
00263 
00269 MyPty::~MyPty()
00270 {
00271     donePty();
00272 }
00273 QString MyPty::identifier()const {
00274     return QString::fromLatin1("term");
00275 }
00276 QString MyPty::name()const{
00277     return identifier();
00278 }
00279 bool MyPty::open() {
00280     if (m_fd < 0)
00281         m_fd = openPty();
00282 
00283     start();
00284     return true;
00285 }
00286 void MyPty::close() {
00287     donePty();
00288     m_fd = openPty();
00289 }
00290 void MyPty::reload( const Profile& prof) {
00291     m_env.clear();
00292     m_cmd = prof.readEntry("Command", "/bin/sh");
00293 
00294     /*
00295      * Lets check if m_cmd actually
00296      * exists....
00297      * we try to use bin/bash and if
00298      * this fails we
00299      * will fallback to /bin/sh
00300      * which should be there 100%
00301      */
00302     if ( m_cmd.stripWhiteSpace() == "/bin/bash" && !QFile::exists(QFile::encodeName(m_cmd) ) )        
00303             m_cmd = "/bin/sh";
00304         
00305 
00306     int envcount = prof.readNumEntry("EnvVars", 0);
00307     for (int i=0; i<envcount; i++) {
00308         QString name = prof.readEntry("Env_Name_" + QString::number(i), "");
00309         QString value = prof.readEntry("Env_Value_" + QString::number(i), "");
00310         if (!(name.isEmpty() || value.isEmpty())) {
00311             m_env.insert(name, value);
00312         }
00313     }
00314 }
00316 void MyPty::send(const QByteArray& ar)
00317 {
00318 #ifdef VERBOSE_DEBUG
00319   // verbose debug
00320   printf("sending bytes:\n");
00321   for (uint i = 0; i < ar.count(); i++)
00322     printf("%c", ar[i]);
00323   printf("\n");
00324 #endif
00325 
00326   ::write(m_fd, ar.data(), ar.count());
00327 }
00328 
00330 void MyPty::readPty()
00331 {
00332   QByteArray buf(4096);
00333 
00334   int len = ::read( m_fd, buf.data(), 4096 );
00335 
00336   if (len == -1 || len == 0) {
00337      donePty();
00338      return;
00339   }
00340 
00341   if (len < 0)
00342      return;
00343 
00344 
00345   buf.resize(len);
00346   emit received(buf);
00347 
00348 #ifdef VERBOSE_DEBUG
00349   // verbose debug
00350   printf("read bytes:\n");
00351   for (uint i = 0; i < buf.count(); i++)
00352     printf("%c", buf[i]);
00353   printf("\n");
00354 #endif
00355 
00356 }
00357 QBitArray MyPty::supports()const {
00358     QBitArray ar(3);
00359     //autoconnect
00360     ar[0] = 1;
00361     //
00362     ar[1] = 0;
00363     ar[2] = 0;
00364 
00365     return ar;
00366 }

Generated on Sat Nov 5 16:15:26 2005 for OPIE by  doxygen 1.4.2