38 #include <QSocketNotifier> 
   40 #include <QStringList> 
   50 struct Kleo::GnuPGProcessBase::Private {
 
   51   Private() : useStatusFD( false ), statnot( 0 ) {
 
   52     statusFD[0] = statusFD[1] = -1;
 
   57   QSocketNotifier * statnot;
 
   58   QByteArray statusBuffer;
 
   78 bool Kleo::GnuPGProcessBase::start( RunMode runmode, Communication comm ) {
 
   79   if ( d->useStatusFD ) {
 
   84     if ( ::pipe( d->statusFD ) < 0 ) {
 
   85       kDebug( 5150 ) <<
"Kleo::GnuPGProcessBase::start: pipe(2) failed:" << perror;
 
   88     ::fcntl( d->statusFD[0], F_SETFD, FD_CLOEXEC );
 
   89     ::fcntl( d->statusFD[1], F_SETFD, FD_CLOEXEC );
 
   90     if ( !arguments.empty() ) {
 
   91       QList<QByteArray>::iterator it = arguments.begin();
 
   93       arguments.insert( it, 
"--status-fd" );
 
   95       sprintf( buf, 
"%d", d->statusFD[1] );
 
   96       arguments.insert( it, buf );
 
   97       arguments.insert( it, 
"--no-tty" );
 
  101   return K3Process::start( runmode, comm );
 
  104 int Kleo::GnuPGProcessBase::setupCommunication( Communication comm ) {
 
  105   if ( 
int ok = K3Process::setupCommunication( comm ) )
 
  107   if ( d->useStatusFD ) {
 
  109     ::close( d->statusFD[0] );
 
  110     ::close( d->statusFD[1] );
 
  111     d->statusFD[0] = d->statusFD[1] = -1;
 
  116 int Kleo::GnuPGProcessBase::commSetupDoneP() {
 
  117   if ( d->useStatusFD ) {
 
  118     ::close( d->statusFD[1] ); 
 
  119     d->statnot = 
new QSocketNotifier( d->statusFD[0], QSocketNotifier::Read, 
this );
 
  120     connect( d->statnot, SIGNAL(activated(
int)), SLOT(slotChildStatus(
int)) );
 
  122   return K3Process::commSetupDoneP();
 
  125 int Kleo::GnuPGProcessBase::commSetupDoneC() {
 
  126   if ( d->useStatusFD )
 
  127     ::fcntl( d->statusFD[1], F_SETFD, 0 );
 
  128   return K3Process::commSetupDoneC();
 
  131 void Kleo::GnuPGProcessBase::slotChildStatus( 
int fd ) {
 
  132   if ( !childStatus(fd) )
 
  136 bool Kleo::GnuPGProcessBase::closeStatus() {
 
  137   if ( !d->useStatusFD )
 
  139   d->useStatusFD = 
false;
 
  140   delete d->statnot; d->statnot = 0;
 
  141   ::close( d->statusFD[0] ); d->statusFD[0] = -1;
 
  145 int Kleo::GnuPGProcessBase::childStatus( 
int fd ) {
 
  147   const int len = ::read( fd, buf, 
sizeof(buf)-1 );
 
  150     d->statusBuffer += buf;
 
  156 static QString fromHexEscapedUtf8( 
const QByteArray & str ) {
 
  157   return KUrl::fromPercentEncoding( str.data()  );
 
  160 void Kleo::GnuPGProcessBase::parseStatusOutput() {
 
  161   static const char startToken[] = 
"[GNUPG:] ";
 
  162   static const int startTokenLen = 
sizeof startToken / 
sizeof *startToken - 1;
 
  165   for ( 
int lineEnd = d->statusBuffer.indexOf( 
'\n' ) ; lineEnd >= 0 ; lineEnd = d->statusBuffer.indexOf( 
'\n', lineStart = lineEnd+1 ) ) {
 
  167     const QByteArray line = d->statusBuffer.mid( lineStart, lineEnd - lineStart ).trimmed();
 
  168     if ( line.isEmpty() )
 
  171     if ( line.left( startTokenLen ) != startToken ) {
 
  172       kDebug( 5150 ) <<
"Kleo::GnuPGProcessBase::childStatus: status-fd protocol error: line doesn't begin with \"" 
  173                      << startToken << 
"\"";
 
  177     const QByteArray command = line.mid( startTokenLen ).simplified() + 
' ';
 
  178     if ( command == 
" " ) {
 
  179       kDebug( 5150 ) <<
"Kleo::GnuPGProcessBase::childStatus: status-fd protocol error: line without content.";
 
  186     for ( 
int tagEnd = command.indexOf( 
' ' ) ; tagEnd >= 0 ; tagEnd = command.indexOf( 
' ', tagStart = tagEnd+1 ) ) {
 
  187       const QByteArray tag = command.mid( tagStart, tagEnd - tagStart );
 
  189         cmd = fromHexEscapedUtf8( tag );
 
  191         args.push_back( fromHexEscapedUtf8( tag ) );
 
  193     emit status( 
this, cmd, args );
 
  195   d->statusBuffer = d->statusBuffer.mid( lineStart );
 
  199 #include "gnupgprocessbase.moc" 
void setUseStatusFD(bool use)
 
GnuPGProcessBase(QObject *parent=0)