⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vk_process.cpp

📁 Linux平台下的内核及程序调试器
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/* ----------------------------------------------------------------------  * Implementation of class VKProcess                         vk_process.h * --------------------------------------------------------------------- * This file is part of Valkyrie, a front-end for Valgrind * Copyright (c) 2005-2006, OpenWorks LLP <info@open-works.co.uk> * This program is released under the terms of the GNU GPL v.2 * See the file LICENSE.GPL for the full license details. * --------------------------------------------------------------------- * This file is a re-implementation of QProcess: * ** ($Id: qt/qprocess_unix.cpp   3.3.4   edited Dec 23 11:57 $) * ** Created : 20000905 * ** * ** Copyright (C) 1992-2003 Trolltech AS.  All rights reserved. * ** * ** This file may be distributed and/or modified under the terms of the * ** GNU General Public License version 2 as published by the Free Software * ** Foundation and appearing in the file LICENSE.GPL included in the * ** packaging of this file. */#include <qplatformdefs.h>// Solaris redefines connect -> __xnet_connect with _XOPEN_SOURCE_EXTENDED.#if defined(connect)#undef connect#endif#include "vk_process.h"#include "vk_utils.h"#include <qapplication.h>#include <qptrlist.h>#include <qtimer.h>#include <qcleanuphandler.h>#include <qregexp.h>#include <stdlib.h>#include <errno.h>#include <sys/types.h>#ifdef __MIPSEL__# ifndef SOCK_DGRAM#  define SOCK_DGRAM 1# endif# ifndef SOCK_STREAM#  define SOCK_STREAM 2# endif#endif#ifdef Q_C_CALLBACKSextern "C" {#endif // Q_C_CALLBACKSQT_SIGNAL_RETTYPE qt_C_sigchldHnd(QT_SIGNAL_ARGS);#ifdef Q_C_CALLBACKS}#endif // Q_C_CALLBACKS//#define VK_PROCESS_DEBUG/* class VKMembuf   - Reimplementation of QMembuf, from qt/kernel/qinternal_p.h*//* This class implements an efficient buffering of data that is often   used by asynchronous IO classes like QSocket, QHttp and QProcess. */VKMembuf::VKMembuf() : _size(0), _index(0){   buf = new QPtrList<QByteArray>;   buf->setAutoDelete( true );}VKMembuf::~VKMembuf(){ delete buf; }/* This function consumes nbytes bytes of data from the buffer and   copies it into sink. If sink is a 0 pointer the data goes into the   nirvana. */bool VKMembuf::consumeBytes( Q_ULONG nbytes, char *sink ){   if ( nbytes <= 0 || nbytes > _size )      return false;   _size -= nbytes;   for ( ;; ) {      QByteArray *a = buf->first();      if ( _index + nbytes >= a->size() ) {         // Here we skip the whole byte array and get the next later         int len = a->size() - _index;         if ( sink ) {            memcpy( sink, a->data()+_index, len );            sink += len;         }         nbytes -= len;         buf->remove();         _index = 0;         if ( nbytes == 0 )            break;      } else {         // Here we skip only a part of the first byte array         if ( sink )            memcpy( sink, a->data()+_index, nbytes );         _index += nbytes;         break;      }   }   return true;}/* Scans for any occurrence of '\n' in the buffer. If store is not 0   the text up to the first '\n' (or terminating 0) is written to   store, and a terminating 0 is appended to store if necessary.   Returns true if a '\n' was found; otherwise returns false. */bool VKMembuf::scanNewline( QByteArray *store ){   if ( _size == 0 )      return false;   int i = 0; // index into 'store'   QByteArray *a = 0;   char *p;   int n;   for ( ;; ) {      if ( !a ) {         a = buf->first();         if ( !a || a->size() == 0 )            return false;         p = a->data() + _index;         n = a->size() - _index;      } else {         a = buf->next();         if ( !a || a->size() == 0 )            return false;         p = a->data();         n = a->size();      }      if ( store ) {         while ( n-- > 0 ) {            *(store->data()+i) = *p;            if ( ++i == (int)store->size() )               store->resize( (store->size() < 256) ? (1024) : (store->size()*4) );            switch ( *p ) {            case '\0':               store->resize( i );               return false;            case '\n':               *(store->data()+i) = '\0';               store->resize( i );               return true;            }            p++;         }      } else {         while ( n-- > 0 ) {            switch ( *p++ ) {            case '\0':               return false;            case '\n':               return true;            }         }      }   }}int VKMembuf::ungetch( int ch ){   if ( buf->isEmpty() || _index==0 ) {      // we need a new QByteArray      QByteArray *ba = new QByteArray( 1 );      buf->insert( 0, ba );      _size++;      ba->at( 0 ) = ch;   } else {      // we can reuse a place in the buffer      QByteArray *ba = buf->first();      _index--;      _size++;      ba->at( _index ) = ch;   }   return ch;}/* class VKProc -------------------------------------------------------------- */VKProc::VKProc( pid_t p, VKProcess *proc/*=0*/ )   : pid(p), process(proc){#if defined(VK_PROCESS_DEBUG)   qDebug( "VKProc: Constructor for pid %d and VKProcess %p", pid, process );#endif   socketFDin = 0;   socketFDout = 0;   socketStdin = 0;   socketStdout = 0;   socketStderr = 0;}VKProc::~VKProc(){#if defined(VK_PROCESS_DEBUG)   qDebug( "VKProc: Destructor for pid %d and VKProcess %p", pid, process );#endif   if ( process ) {      if ( process->d->notifierFDin )         process->d->notifierFDin->setEnabled( false );      if ( process->d->notifierFDout )         process->d->notifierFDout->setEnabled( false );      if ( process->d->notifierStdin )         process->d->notifierStdin->setEnabled( false );      if ( process->d->notifierStdout )         process->d->notifierStdout->setEnabled( false );      if ( process->d->notifierStderr )         process->d->notifierStderr->setEnabled( false );      process->d->proc = 0;   }   if ( socketFDin )      ::close( socketFDin );   if ( socketFDout )      ::close( socketFDout );   if ( socketStdin )      ::close( socketStdin );   if ( socketStdout )      ::close( socketStdout );   if ( socketStderr )      ::close( socketStderr );}/*---------------------------------------------------------------------------- * Helper functions ----------------------------------------------------------------------------- */static void vkprocess_cleanup(){   delete VKProcessPrivate::procManager;   VKProcessPrivate::procManager = 0;}#ifdef Q_OS_QNX6#define BAILOUT close(tmpSocket);close(socketFD[1]);return -1;int qnx6SocketPairReplacement (int socketFD[2]) {   int tmpSocket;   tmpSocket = socket (AF_INET, SOCK_STREAM, 0);   if (tmpSocket == -1)      return -1;   socketFD[1] = socket(AF_INET, SOCK_STREAM, 0);   if (socketFD[1] == -1) { BAILOUT };   sockaddr_in ipAddr;   memset(&ipAddr, 0, sizeof(ipAddr));   ipAddr.sin_family = AF_INET;   ipAddr.sin_addr.s_addr = INADDR_ANY;   int socketOptions = 1;   setsockopt(tmpSocket, SOL_SOCKET, SO_REUSEADDR, &socketOptions, sizeof(int));   bool found = false;   for (int socketIP = 2000; (socketIP < 2500) && !(found); socketIP++) {      ipAddr.sin_port = htons(socketIP);      if (bind(tmpSocket, (struct sockaddr *)&ipAddr, sizeof(ipAddr)))         found = true;   }   if (listen(tmpSocket, 5)) { BAILOUT };   // Select non-blocking mode   int originalFlags = fcntl(socketFD[1], F_GETFL, 0);   fcntl(socketFD[1], F_SETFL, originalFlags | O_NONBLOCK);   // Request connection   if (connect(socketFD[1], (struct sockaddr*)&ipAddr, sizeof(ipAddr)))      if (errno != EINPROGRESS) { BAILOUT };   // Accept connection   socketFD[0] = accept(tmpSocket, (struct sockaddr *)NULL, (size_t *)NULL);   if (socketFD[0] == -1) { BAILOUT };   // We're done   close(tmpSocket);   // Restore original flags , ie return to blocking   fcntl(socketFD[1], F_SETFL, originalFlags);   return 0;}#undef BAILOUT#endif/* sigchld handler callback */QT_SIGNAL_RETTYPE qt_C_sigchldHnd( QT_SIGNAL_ARGS ){   if ( VKProcessPrivate::procManager == 0 )      return;   if ( VKProcessPrivate::procManager->sigchldFd[0] == 0 )      return;   char a = 1;   ::write( VKProcessPrivate::procManager->sigchldFd[0], &a, sizeof(a) );}/* class VKProcessManager ---------------------------------------------------- */VKProcessManager::VKProcessManager() : sn(0){   procList = new QPtrList<VKProc>;   procList->setAutoDelete( true );   /* The SIGCHLD handler writes to a socket to tell the manager that      something happened. This is done to get the processing in sync      with the event reporting. */#ifndef Q_OS_QNX6   if ( ::socketpair( AF_UNIX, SOCK_STREAM, 0, sigchldFd ) ) {#else      if ( qnx6SocketPairReplacement (sigchldFd) ) {#endif         sigchldFd[0] = 0;         sigchldFd[1] = 0;      } else {#if defined(VK_PROCESS_DEBUG)         qDebug( "VKProcessManager: install socket notifier (%d)", sigchldFd[1] );#endif         sn = new QSocketNotifier( sigchldFd[1],                                   QSocketNotifier::Read, this );         connect( sn, SIGNAL(activated(int)),                  this, SLOT(sigchldHnd(int)) );         sn->setEnabled( true );      }      // install a SIGCHLD handler and ignore SIGPIPE      struct sigaction act;#if defined(VK_PROCESS_DEBUG)      qDebug( "VKProcessManager: install a SIGCHLD handler" );#endif      act.sa_handler = qt_C_sigchldHnd;      sigemptyset( &(act.sa_mask) );      sigaddset( &(act.sa_mask), SIGCHLD );      act.sa_flags = SA_NOCLDSTOP;#if defined(SA_RESTART)      act.sa_flags |= SA_RESTART;#endif      if ( sigaction( SIGCHLD, &act, &oldactChld ) != 0 )         qWarning( "Error installing SIGCHLD handler" );  

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -