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

📄 qprocess_unix.cpp

📁 Trolltech公司发布的图形界面操作系统。可在qt-embedded-2.3.10平台上编译为嵌入式图形界面操作系统。
💻 CPP
📖 第 1 页 / 共 3 页
字号:
#endif    stdinBufRead = 0;    notifierStdin = 0;    notifierStdout = 0;    notifierStderr = 0;    exitValuesCalculated = FALSE;    socketReadCalled = FALSE;    proc = 0;}QProcessPrivate::~QProcessPrivate(){#if defined(QT_QPROCESS_DEBUG)    qDebug( "QProcessPrivate: Destructor" );#endif    if ( proc != 0 ) {	if ( proc->socketStdin != 0 ) {	    ::close( proc->socketStdin );	    proc->socketStdin = 0;	}	proc->process = 0;    }    while ( !stdinBuf.isEmpty() ) {	delete stdinBuf.dequeue();    }    delete notifierStdin;    delete notifierStdout;    delete notifierStderr;}/*  Closes all open sockets in the child process that are not needed by the child  process. Otherwise one child may have an open socket on standard input, etc.  of another child.*/void QProcessPrivate::closeOpenSocketsForChild(){    if ( procManager != 0 ) {	if ( procManager->sigchldFd[0] != 0 )	    ::close( procManager->sigchldFd[0] );	if ( procManager->sigchldFd[1] != 0 )	    ::close( procManager->sigchldFd[1] );	// close also the sockets from other QProcess instances	QProc *proc;	for ( proc=procManager->procList->first(); proc!=0; proc=procManager->procList->next() ) {	    ::close( proc->socketStdin );	    ::close( proc->socketStdout );	    ::close( proc->socketStderr );	}    }}void QProcessPrivate::newProc( pid_t pid, QProcess *process ){    proc = new QProc( pid, process );    if ( procManager == 0 ) {	procManager = new QProcessManager;	qprocess_cleanup_procmanager.add( &procManager );    }    // the QProcessManager takes care of deleting the QProc instances    procManager->append( proc );}/*********************************************************************** * * sigchld handler callback * **********************************************************************/QT_SIGNAL_RETTYPE qt_C_sigchldHnd( QT_SIGNAL_ARGS ){    if ( QProcessPrivate::procManager == 0 )	return;    if ( QProcessPrivate::procManager->sigchldFd[0] == 0 )	return;    char a = 1;    ::write( QProcessPrivate::procManager->sigchldFd[0], &a, sizeof(a) );}QT_SIGNAL_RETTYPE qt_C_sigpipeHnd( QT_SIGNAL_ARGS ){    // Ignore (but in a way somehow different to SIG_IGN).}/*********************************************************************** * * QProcess * **********************************************************************//*!  This private class does basic initialization.*/void QProcess::init(){    d = new QProcessPrivate();    exitStat = 0;    exitNormal = FALSE;}/*!  This private class resets the process variables, etc. so that it can be used  for another process to start.*/void QProcess::reset(){    delete d;    d = new QProcessPrivate();    exitStat = 0;    exitNormal = FALSE;    d->bufStdout.resize( 0 );    d->bufStderr.resize( 0 );}QByteArray* QProcess::bufStdout(){    if ( d->proc && d->proc->socketStdout ) {	// ### can this cause a blocking behaviour (maybe do a ioctl() to see	// if data is available)?	socketRead( d->proc->socketStdout );    }    return &d->bufStdout;}QByteArray* QProcess::bufStderr(){    if ( d->proc && d->proc->socketStderr ) {	// ### can this cause a blocking behaviour (maybe do a ioctl() to see	// if data is available)?	socketRead( d->proc->socketStderr );    }    return &d->bufStderr;}void QProcess::consumeBufStdout( int consume ){    uint n = d->bufStdout.size();    if ( consume==-1 || (uint)consume >= n ) {	d->bufStdout.resize( 0 );    } else {	QByteArray tmp( n - consume );	memcpy( tmp.data(), d->bufStdout.data()+consume, n-consume );	d->bufStdout = tmp;    }}void QProcess::consumeBufStderr( int consume ){    uint n = d->bufStderr.size();    if ( consume==-1 || (uint)consume >= n ) {	d->bufStderr.resize( 0 );    } else {	QByteArray tmp( n - consume );	memcpy( tmp.data(), d->bufStderr.data()+consume, n-consume );	d->bufStderr = tmp;    }}/*!  Destroys the class.  If the process is running, it is NOT terminated! Standard input, standard  output and standard error of the process are closed.  You can connect the destroyed() signal to the kill() slot, if you want the  process to be terminated automatically when the class is destroyed.  \sa tryTerminate() kill()*/QProcess::~QProcess(){    delete d;}/*!  Tries to run a process for the command and arguments that were specified with  setArguments(), addArgument() or that were specified in the constructor. The  command is searched in the path for executable programs; you can also use an  absolute path to the command.  If \a env is null, then the process is started with the same environment as  the starting process. If \a env is non-null, then the values in the  stringlist are interpreted as environment setttings of the form \c  {key=value} and the process is started in these environment settings. For  convenience, there is a small exception to this rule: under Unix, if \a env  does not contain any settings for the environment variable \c  LD_LIBRARY_PATH, then this variable is inherited from the starting process;  under Windows the same applies for the enverionment varialbe \c PATH.  Returns TRUE if the process could be started, otherwise FALSE.  You can write data to standard input of the process with  writeToStdin(), you can close standard input with closeStdin() and you can  terminate the process tryTerminate() resp. kill().  You can call this function even when there already is a running  process in this object. In this case, QProcess closes standard input  of the old process and deletes pending data, i.e., you loose all  control over that process, but the process is not terminated. This applies  also if the process could not be started. (On operating systems that have  zombie processes, Qt will also wait() on the old process.)  \sa launch() closeStdin()*/bool QProcess::start( QStringList *env ){#if defined(QT_QPROCESS_DEBUG)    qDebug( "QProcess::start()" );#endif    reset();    int sStdin[2];    int sStdout[2];    int sStderr[2];    // open sockets for piping    if ( (comms & Stdin) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStdin ) == -1 ) {	return FALSE;    }    if ( (comms & Stderr) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStderr ) == -1 ) {	return FALSE;    }    if ( (comms & Stdout) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStdout ) == -1 ) {	return FALSE;    }    // the following pipe is only used to determine if the process could be    // started    int fd[2];    if ( pipe( fd ) < 0 ) {	// non critical error, go on	fd[0] = 0;	fd[1] = 0;    }    // construct the arguments for exec    QCString *arglistQ = new QCString[ _arguments.count() + 1 ];    const char** arglist = new const char*[ _arguments.count() + 1 ];    int i = 0;    for ( QStringList::Iterator it = _arguments.begin(); it != _arguments.end(); ++it ) {	arglistQ[i] = (*it).local8Bit();	arglist[i] = arglistQ[i];#if defined(QT_QPROCESS_DEBUG)	qDebug( "QProcess::start(): arg %d = %s", i, arglist[i] );#endif	i++;    }    arglist[i] = 0;    // Must make sure signal handlers are installed before exec'ing    // in case the process exits quickly.    if ( d->procManager == 0 ) {	d->procManager = new QProcessManager;	qprocess_cleanup_procmanager.add( &d->procManager );    }    // fork and exec    QApplication::flushX();    pid_t pid = fork();    if ( pid == 0 ) {	// child	d->closeOpenSocketsForChild();	if ( comms & Stdin ) {	    ::close( sStdin[1] );	    ::dup2( sStdin[0], STDIN_FILENO );	}	if ( comms & Stdout ) {	    ::close( sStdout[0] );	    ::dup2( sStdout[1], STDOUT_FILENO );	}	if ( comms & Stderr ) {	    ::close( sStderr[0] );	    ::dup2( sStderr[1], STDERR_FILENO );	}	if ( comms & DupStderr ) {	    ::dup2( STDOUT_FILENO, STDERR_FILENO );	}#ifndef QT_NO_DIR	::chdir( workingDir.absPath().latin1() );#endif	if ( fd[0] )	    ::close( fd[0] );	if ( fd[1] )	    ::fcntl( fd[1], F_SETFD, FD_CLOEXEC ); // close on exec shows sucess	// put the child process into its parent's process group	::setpgid( ::getpid(), ::getppid() );	if ( env == 0 ) { // inherit environment and start process	    ::execvp( arglist[0], (char*const*)arglist ); // ### cast not nice	} else { // start process with environment settins as specified in env	    // construct the environment for exec	    int numEntries = env->count();	    bool setLibraryPath =		env->grep( QRegExp( "^LD_LIBRARY_PATH=" ) ).isEmpty() &&		getenv( "LD_LIBRARY_PATH" ) != 0;	    if ( setLibraryPath )		numEntries++;	    QCString *envlistQ = new QCString[ numEntries + 1 ];	    const char** envlist = new const char*[ numEntries + 1 ];	    int i = 0;	    if ( setLibraryPath ) {		envlistQ[i] = QString( "LD_LIBRARY_PATH=%1" ).arg( getenv( "LD_LIBRARY_PATH" ) ).local8Bit();		envlist[i] = envlistQ[i];		i++;	    }	    for ( QStringList::Iterator it = env->begin(); it != env->end(); ++it ) {		envlistQ[i] = (*it).local8Bit();		envlist[i] = envlistQ[i];		i++;	    }	    envlist[i] = 0;	    // look for the executable in the search path	    if ( _arguments.count()>0 && getenv("PATH")!=0 ) {		QString command = _arguments[0];		if ( !command.contains( '/' ) ) {		    QStringList pathList = QStringList::split( ':', getenv( "PATH" ) );		    for (QStringList::Iterator it = pathList.begin(); it != pathList.end(); ++it ) {			QString dir = *it;#ifdef Q_OS_MACX			if(QFile::exists(dir + "/" + command + ".app")) //look in a bundle			    dir += "/" + command + ".app/Contents/MacOS";#endif#ifndef QT_NO_DIR			QFileInfo fileInfo( dir, command );#else			QFileInfo fileInfo( dir + "/" + command );#endif			if ( fileInfo.isExecutable() ) {			    arglistQ[0] = fileInfo.filePath().local8Bit();			    arglist[0] = arglistQ[0];			    break;			}		    }		}	    }	    ::execve( arglist[0], (char*const*)arglist, (char*const*)envlist ); // ### casts not nice	}	if ( fd[1] ) {	    char buf = 0;	    ::write( fd[1], &buf, 1 );	    ::close( fd[1] );	}	::exit( -1 );    } else if ( pid == -1 ) {	// error forking	goto error;    }    // test if exec was successful    if ( fd[1] )	::close( fd[1] );    if ( fd[0] ) {	char buf;	for ( ;; ) {	    int n = ::read( fd[0], &buf, 1 );	    if ( n==1 ) {		// socket was not closed => error		d->proc = 0;		goto error;	    } else if ( n==-1 ) {		if ( errno==EAGAIN || errno==EINTR )		    // try it again		    continue;	    }	    break;	}	::close( fd[0] );    }    d->newProc( pid, this );    if ( comms & Stdin ) {	::close( sStdin[0] );	d->proc->socketStdin = sStdin[1];	d->notifierStdin = new QSocketNotifier( sStdin[1], QSocketNotifier::Write );	connect( d->notifierStdin, SIGNAL(activated(int)),		this, SLOT(socketWrite(int)) );	// setup notifiers for the sockets	if ( !d->stdinBuf.isEmpty() ) {	    d->notifierStdin->setEnabled( TRUE );	}    }    if ( comms & Stdout ) {	::close( sStdout[1] );	d->proc->socketStdout = sStdout[0];	d->notifierStdout = new QSocketNotifier( sStdout[0], QSocketNotifier::Read );	connect( d->notifierStdout, SIGNAL(activated(int)),		this, SLOT(socketRead(int)) );	if ( ioRedirection )	    d->notifierStdout->setEnabled( TRUE );    }    if ( comms & Stderr ) {	::close( sStderr[1] );	d->proc->socketStderr = sStderr[0];

⌨️ 快捷键说明

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