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

📄 qprocess_unix.cpp

📁 Qt/Embedded是一个多平台的C++图形用户界面应用程序框架
💻 CPP
字号:
/************************************************************************ Copyright (C) 2000 Trolltech AS.  All rights reserved.**** This file is part of Qt Designer.**** 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.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.**** See http://www.trolltech.com/gpl/ for GPL licensing information.**** Contact info@trolltech.com if any conditions of this licensing are** not clear to you.************************************************************************/#include "qapplication.h"#include "qlist.h"#include "qprocess.h"#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <signal.h>//#define QPROCESS_DEBUG#if defined(Q_C_CALLBACKS)extern "C" {#endif#if defined(_OS_OSF_) || ( defined(_OS_IRIX_) && defined(_CC_GNU_) )static void qt_C_sigchldHnd();#elsestatic void qt_C_sigchldHnd( int );#endif#if defined(Q_C_CALLBACKS)}#endif#if defined(_OS_OSF_) || ( defined(_OS_IRIX_) && defined(_CC_GNU_) )void qt_C_sigchldHnd()#elsevoid qt_C_sigchldHnd( int )#endif{    QProcessPrivate::sigchldHnd();}struct sigaction *QProcessPrivate::oldact;QList<QProcess> *QProcessPrivate::proclist = 0;QProcessPrivate::QProcessPrivate( QProcess *proc ) : d( proc ){#if defined(QPROCESS_DEBUG)    qDebug( "QProcessPrivate: Constructor" );#endif    stdinBufRead = 0;    notifierStdin = 0;    notifierStdout = 0;    notifierStderr = 0;    socketStdin[0] = 0;    socketStdin[1] = 0;    socketStdout[0] = 0;    socketStdout[1] = 0;    socketStderr[0] = 0;    socketStderr[1] = 0;    exitValuesCalculated = FALSE;    exitStat = 0;    exitNormal = FALSE;    // install a SIGCHLD handler    if ( proclist == 0 ) {	proclist = new QList<QProcess>;	struct sigaction act;	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, oldact ) != 0 )	    qWarning( "Error installing SIGCHLD handler" );    }    proclist->append( d );}QProcessPrivate::~QProcessPrivate(){#if defined(QPROCESS_DEBUG)    qDebug( "QProcessPrivate: Destructor" );#endif    // restore SIGCHLD handler    if ( proclist != 0 ) {	proclist->remove( d );	if ( proclist->count() == 0 ) {	    delete proclist;	    proclist = 0;	    if ( sigaction( SIGCHLD, oldact, 0 ) != 0 )		qWarning( "Error restoring SIGCHLD handler" );	}    }    while ( !stdinBuf.isEmpty() ) {	delete stdinBuf.dequeue();    }    if ( notifierStdin ) {	notifierStdin->setEnabled( FALSE );	delete notifierStdin;    }    if ( notifierStdout ) {	notifierStdout->setEnabled( FALSE );	delete notifierStdout;    }    if ( notifierStderr ) {	notifierStderr->setEnabled( FALSE );	delete notifierStderr;    }    if( socketStdin[1] != 0 )	::close( socketStdin[1] );    if( socketStdout[0] != 0 )	::close( socketStdout[0] );    if( socketStderr[0] != 0 )	::close( socketStderr[0] );}void QProcessPrivate::sigchldHnd(){    if ( !proclist )	return;    QProcess *proc;    for ( proc=proclist->first(); proc!=0; proc=proclist->next() ) {	if ( !proc->d->exitValuesCalculated && !proc->isRunning() ) {#if defined(QPROCESS_DEBUG)	    qDebug( "QProcessPrivate::sigchldHnd(): process exited" );#endif	    // read pending data	    proc->socketRead( proc->d->socketStdout[0] );	    proc->socketRead( proc->d->socketStderr[0] );	    emit proc->processExited();	    // the slot might have deleted the last process...	    if ( !proclist )		return;	}    }}bool QProcess::start(){#if defined(QPROCESS_DEBUG)    qDebug( "QProcess::start()" );#endif    d->exitValuesCalculated = FALSE;    d->exitStat = 0;    d->exitNormal = FALSE;    // cleanup the notifiers    if ( d->notifierStdin ) {	d->notifierStdin->setEnabled( FALSE );	delete d->notifierStdin;	d->notifierStdin = 0;    }    if ( d->notifierStdout ) {	d->notifierStdout->setEnabled( FALSE );	delete d->notifierStdout;	d->notifierStdout = 0;    }    if ( d->notifierStderr ) {	d->notifierStderr->setEnabled( FALSE );	delete d->notifierStderr;	d->notifierStderr = 0;    }#if defined(_OS_QNX_) // socketpair() is not yet implemented in QNX/RTP    return FALSE;#else    // open sockets for piping    if ( ::socketpair( AF_UNIX, SOCK_STREAM, 0, d->socketStdin ) ) {	return FALSE;    }    if ( ::socketpair( AF_UNIX, SOCK_STREAM, 0, d->socketStdout ) ) {	return FALSE;    }    if ( ::socketpair( AF_UNIX, SOCK_STREAM, 0, d->socketStderr ) ) {	return FALSE;    }#endif        // construct the arguments for exec    const char** arglist = new const char*[ d->arguments.count() + 2 ];    arglist[0] = d->command.latin1();    int i = 1;    for ( QStringList::Iterator it = d->arguments.begin(); it != d->arguments.end(); ++it ) {	arglist[ i++ ] = (*it).latin1();    }    arglist[i] = 0;    // fork and exec    QApplication::flushX();    d->pid = fork();    if ( d->pid == 0 ) {	// child	::close( d->socketStdin[1] );	::close( d->socketStdout[0] );	::close( d->socketStderr[0] );	::dup2( d->socketStdin[0], STDIN_FILENO );	::dup2( d->socketStdout[1], STDOUT_FILENO );	::dup2( d->socketStderr[1], STDERR_FILENO );	::chdir( d->workingDir.absPath().latin1() );	::execvp( d->command.latin1(), (char*const*)arglist ); // ### a hack	::exit( -1 );    } else if ( d->pid == -1 ) {	// error forking	::close( d->socketStdin[1] );	::close( d->socketStdout[0] );	::close( d->socketStderr[0] );	::close( d->socketStdin[0] );	::close( d->socketStdout[1] );	::close( d->socketStderr[1] );	delete[] arglist;	return FALSE;    }    ::close( d->socketStdin[0] );    ::close( d->socketStdout[1] );    ::close( d->socketStderr[1] );    // TODO? test if exec was successful    // setup notifiers for the sockets    d->notifierStdin = new QSocketNotifier( d->socketStdin[1],	    QSocketNotifier::Write, this );    d->notifierStdout = new QSocketNotifier( d->socketStdout[0],	    QSocketNotifier::Read, this );    d->notifierStderr = new QSocketNotifier( d->socketStderr[0],	    QSocketNotifier::Read, this );    connect( d->notifierStdin, SIGNAL(activated(int)),	    this, SLOT(socketWrite(int)) );    connect( d->notifierStdout, SIGNAL(activated(int)),	    this, SLOT(socketRead(int)) );    connect( d->notifierStderr, SIGNAL(activated(int)),	    this, SLOT(socketRead(int)) );    d->notifierStdin->setEnabled( TRUE );    d->notifierStdout->setEnabled( TRUE );    d->notifierStderr->setEnabled( TRUE );    // cleanup and return    delete[] arglist;    return TRUE;}bool QProcess::hangUp(){    return ::kill( d->pid, SIGHUP ) == 0;}bool QProcess::kill(){    return ::kill( d->pid, SIGKILL ) == 0;}bool QProcess::isRunning(){    if ( d->exitValuesCalculated ) {#if defined(QPROCESS_DEBUG)	qDebug( "QProcess::isRunning(): FALSE (already computed)" );#endif	return FALSE;    } else {	int status;	if ( ::waitpid( d->pid, &status, WNOHANG ) == d->pid )	{	    // compute the exit values	    d->exitNormal = WIFEXITED( status ) != 0;	    if ( d->exitNormal ) {		d->exitStat = WEXITSTATUS( status );	    }	    d->exitValuesCalculated = TRUE;#if defined(QPROCESS_DEBUG)	    qDebug( "QProcess::isRunning(): FALSE" );#endif	    return FALSE;	} else {#if defined(QPROCESS_DEBUG)	    qDebug( "QProcess::isRunning(): TRUE" );#endif	    return TRUE;	}    }}void QProcess::dataStdin( const QByteArray& buf ){#if defined(QPROCESS_DEBUG)//    qDebug( "QProcess::dataStdin(): write to stdin (%d)", d->socketStdin[1] );#endif    d->stdinBuf.enqueue( new QByteArray(buf) );    if ( d->notifierStdin != 0 )        d->notifierStdin->setEnabled( TRUE );    socketWrite( d->socketStdin[1] );}void QProcess::closeStdin(){    if ( d->socketStdin[1] !=0 ) {	// ### what is with pending data?	if ( d->notifierStdin ) {	    d->notifierStdin->setEnabled( FALSE );	    delete d->notifierStdin;	    d->notifierStdin = 0;	}	if ( ::close( d->socketStdin[1] ) != 0 ) {	    qWarning( "Could not close stdin of child process" );	}#if defined(QPROCESS_DEBUG)	qDebug( "QProcess::closeStdin(): stdin (%d) closed", d->socketStdin[1] );#endif	d->socketStdin[1] =0 ;    }}void QProcess::socketRead( int fd ){#if defined(QPROCESS_DEBUG)    qDebug( "QProcess::socketRead(): %d", fd );#endif    if ( fd == 0 )	return;    const size_t bufsize = 4096;    char *buffer = new char[bufsize];    int n = ::read( fd, buffer, bufsize-1 );    if ( n == 0 || n == -1 ) {	if ( fd == d->socketStdout[0] ) {#if defined(QPROCESS_DEBUG)	    qDebug( "QProcess::socketRead(): stdout (%d) closed", fd );#endif	    d->notifierStdout->setEnabled( FALSE );	    delete d->notifierStdout;	    d->notifierStdout = 0;	    ::close( d->socketStdout[0] );	    d->socketStdout[0] = 0;	    delete buffer;	    return;	} else {#if defined(QPROCESS_DEBUG)	    qDebug( "QProcess::socketRead(): stderr (%d) closed", fd );#endif	    d->notifierStderr->setEnabled( FALSE );	    delete d->notifierStderr;	    d->notifierStderr = 0;	    ::close( d->socketStderr[0] );	    d->socketStderr[0] = 0;	    delete buffer;	    return;	}    }    buffer[n] = 0;    QString str( QString::fromLocal8Bit( buffer ) );    QByteArray buf;    buf.assign( buffer, n );    if ( fd == d->socketStdout[0] ) {#if defined(QPROCESS_DEBUG)	qDebug( "QProcess::socketRead(): read from stdout (%d)", fd );#endif	emit dataStdout( buf );    } else {#if defined(QPROCESS_DEBUG)	qDebug( "QProcess::socketRead(): read from stderr (%d)", fd );#endif	emit dataStderr( buf );    }    if ( fd == d->socketStdout[0] ) {	emit dataStdout( str );    } else {	emit dataStderr( str );    }}void QProcess::socketWrite( int fd ){    if ( fd != d->socketStdin[1] || d->socketStdin[1] == 0 )	return;    if ( d->stdinBuf.isEmpty() ) {	d->notifierStdin->setEnabled( FALSE );	return;    }#if defined(QPROCESS_DEBUG)    qDebug( "QProcess::socketWrite(): write to stdin (%d)", fd );#endif    d->stdinBufRead += write( fd,	    d->stdinBuf.head()->data() + d->stdinBufRead,	    d->stdinBuf.head()->size() - d->stdinBufRead );    if ( d->stdinBufRead == (ssize_t)d->stdinBuf.head()->size() ) {	d->stdinBufRead = 0;	delete d->stdinBuf.dequeue();	socketWrite( fd );    }}// only used under Windowsvoid QProcess::timeout(){}

⌨️ 快捷键说明

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