libkpgp

kpgpbase.cpp

00001 /*
00002     kpgpbase.cpp
00003 
00004     Copyright (C) 2001,2002 the KPGP authors
00005     See file AUTHORS.kpgp for details
00006 
00007     This file is part of KPGP, the KDE PGP/GnuPG support library.
00008 
00009     KPGP is free software; you can redistribute it and/or modify
00010     it under the terms of the GNU General Public License as published by
00011     the Free Software Foundation; either version 2 of the License, or
00012     (at your option) any later version.
00013 
00014     You should have received a copy of the GNU General Public License
00015     along with this program; if not, write to the Free Software Foundation,
00016     Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
00017  */
00018 
00019 #include <kdebug.h>
00020 
00021 #include <config.h>
00022 
00023 #include "kpgpbase.h"
00024 #include "kpgp.h"
00025 #include "kpgpblock.h"
00026 
00027 #include <stdlib.h> /* setenv, unsetenv */
00028 #include <unistd.h> /* pipe, close, fork, dup2, execl, _exit, write, read */
00029 #include <sys/poll.h>  /* poll, etc. */
00030 #include <sys/types.h> /* pid_t */
00031 #include <sys/wait.h> /* waitpid */
00032 #include <errno.h>
00033 
00034 #include <qapplication.h>
00035 
00036 
00037 namespace Kpgp {
00038 
00039 Base::Base()
00040   : input(), output(), error(), errMsg(), status(OK)
00041 {
00042 }
00043 
00044 
00045 Base::~Base()
00046 {
00047 }
00048 
00049 
00050 void
00051 Base::clear()
00052 {
00053   input = QCString();
00054   output = QCString();
00055   error = QCString();
00056   errMsg = QString::null;
00057   status = OK;
00058 }
00059 
00060 
00061 int
00062 Base::run( const char *cmd, const char *passphrase, bool onlyReadFromPGP )
00063 {
00064   /* the pipe ppass is used for to pass the password to
00065    * pgp. passing the password together with the normal input through
00066    * stdin doesn't seem to work as expected (at least for pgp5.0)
00067    */
00068   char str[1025] = "\0";
00069   int pin[2], pout[2], perr[2], ppass[2];
00070   int len, len2;
00071   FILE *pass;
00072   pid_t child_pid;
00073   int childExitStatus;
00074   struct pollfd pollin, pollout, pollerr;
00075   int pollstatus;
00076 
00077   if(passphrase)
00078   {
00079     pipe(ppass);
00080 
00081     pass = fdopen(ppass[1], "w");
00082     fwrite(passphrase, sizeof(char), strlen(passphrase), pass);
00083     fwrite("\n", sizeof(char), 1, pass);
00084     fclose(pass);
00085     close(ppass[1]);
00086 
00087     // tell pgp which fd to use for the passphrase
00088     QCString tmp;
00089     tmp.sprintf("%d",ppass[0]);
00090     ::setenv("PGPPASSFD",tmp.data(),1);
00091 
00092     //Uncomment these lines for testing only! Doing so will decrease security!
00093     //kdDebug(5100) << "pgp PGPPASSFD = " << tmp << endl;
00094     //kdDebug(5100) << "pgp pass = " << passphrase << endl;
00095   }
00096   else
00097     ::unsetenv("PGPPASSFD");
00098 
00099   //Uncomment these lines for testing only! Doing so will decrease security!
00100   kdDebug(5100) << "pgp cmd = " << cmd << endl;
00101   //kdDebug(5100) << "pgp input = " << QString(input)
00102   //          << "input length = " << input.length() << endl;
00103 
00104   error = "";
00105   output = "";
00106 
00107   pipe(pin);
00108   pipe(pout);
00109   pipe(perr);
00110 
00111   QApplication::flushX();
00112   if(!(child_pid = fork()))
00113   {
00114     /*We're the child.*/
00115     close(pin[1]);
00116     dup2(pin[0], 0);
00117     close(pin[0]);
00118 
00119     close(pout[0]);
00120     dup2(pout[1], 1);
00121     close(pout[1]);
00122 
00123     close(perr[0]);
00124     dup2(perr[1], 2);
00125     close(perr[1]);
00126 
00127     execl("/bin/sh", "sh", "-c", cmd,  (void *)0);
00128     _exit(127);
00129   }
00130 
00131   /*Only get here if we're the parent.*/
00132   close(pin[0]);
00133   close(pout[1]);
00134   close(perr[1]);
00135 
00136   // poll for "There is data to read."
00137   pollout.fd = pout[0];
00138   pollout.events = POLLIN;
00139   pollout.revents = 0; // init with 0, just in case
00140   pollerr.fd = perr[0];
00141   pollerr.events = POLLIN;
00142   pollerr.revents = 0; // init with 0, just in case
00143 
00144   // poll for "Writing now will not block."
00145   pollin.fd = pin[1];
00146   pollin.events = POLLOUT;
00147   pollin.revents = 0; // init with 0, just in case
00148 
00149   if (!onlyReadFromPGP) {
00150     if (!input.isEmpty()) {
00151       // write to pin[1] one line after the other to prevent dead lock
00152       uint input_length = input.length();
00153       for (unsigned int i=0; i<input_length; i+=len2) {
00154         len2 = 0;
00155 
00156         // check if writing now to pin[1] will not block (5 ms timeout)
00157         //kdDebug(5100) << "Polling pin[1]..." << endl;
00158         pollstatus = poll(&pollin, 1, 5);
00159         if (pollstatus == 1) {
00160           //kdDebug(5100) << "Status for polling pin[1]: " << pollin.revents << endl;
00161           if (pollin.revents & POLLERR) {
00162             kdDebug(5100) << "PGP seems to have hung up" << endl;
00163             break;
00164           }
00165           else if (pollin.revents & POLLOUT) {
00166             // search end of next line
00167             if ((len2 = input.find('\n', i)) == -1)
00168               len2 = input_length - i;
00169             else
00170               len2 = len2 - i + 1;
00171 
00172             //kdDebug(5100) << "Trying to write " << len2 << " bytes to pin[1] ..." << endl;
00173             len2 = write(pin[1], input.data() + i, len2);
00174             //kdDebug(5100) << "Wrote " << len2 << " bytes to pin[1] ..." << endl;
00175           }
00176         }
00177         else if (!pollstatus) {
00178           //kdDebug(5100) << "Timeout while polling pin[1]: "
00179           //              << pollin.revents << endl;
00180         }
00181         else if (pollstatus == -1) {
00182           kdDebug(5100) << "Error while polling pin[1]: "
00183                         << pollin.revents << endl;
00184         }
00185 
00186         if (pout[0] >= 0) {
00187           do {
00188             // check if there is data to read from pout[0]
00189             //kdDebug(5100) << "Polling pout[0]..." << endl;
00190             pollstatus = poll(&pollout, 1, 0);
00191             if (pollstatus == 1) {
00192               //kdDebug(5100) << "Status for polling pout[0]: " << pollout.revents << endl;
00193               if (pollout.revents & POLLIN) {
00194                 //kdDebug(5100) << "Trying to read " << 1024 << " bytes from pout[0]" << endl;
00195                 if ((len = read(pout[0],str,1024))>0) {
00196                   //kdDebug(5100) << "Read " << len << " bytes from pout[0]" << endl;
00197                   str[len] ='\0';
00198                   output += str;
00199                 }
00200                 else
00201                   break;
00202               }
00203             }
00204             else if (pollstatus == -1) {
00205               kdDebug(5100) << "Error while polling pout[0]: "
00206                             << pollout.revents << endl;
00207             }
00208           } while ((pollstatus == 1) && (pollout.revents & POLLIN));
00209         }
00210 
00211         if (perr[0] >= 0) {
00212           do {
00213             // check if there is data to read from perr[0]
00214             //kdDebug(5100) << "Polling perr[0]..." << endl;
00215             pollstatus = poll(&pollerr, 1, 0);
00216             if (pollstatus == 1) {
00217               //kdDebug(5100) << "Status for polling perr[0]: " << pollerr.revents << endl;
00218               if (pollerr.revents & POLLIN) {
00219                 //kdDebug(5100) << "Trying to read " << 1024 << " bytes from perr[0]" << endl;
00220                 if ((len = read(perr[0],str,1024))>0) {
00221                   //kdDebug(5100) << "Read " << len << " bytes from perr[0]" << endl;
00222                   str[len] ='\0';
00223                   error += str;
00224                 }
00225                 else
00226                   break;
00227               }
00228             }
00229             else if (pollstatus == -1) {
00230               kdDebug(5100) << "Error while polling perr[0]: "
00231                             << pollerr.revents << endl;
00232             }
00233           } while ((pollstatus == 1) && (pollerr.revents & POLLIN));
00234         }
00235 
00236         // abort writing to PGP if PGP hung up
00237         if ((pollstatus == 1) &&
00238             ((pollout.revents & POLLHUP) || (pollerr.revents & POLLHUP))) {
00239           kdDebug(5100) << "PGP hung up" << endl;
00240           break;
00241         }
00242       }
00243     }
00244     else // if input.isEmpty()
00245       write(pin[1], "\n", 1);
00246     //kdDebug(5100) << "All input was written to pin[1]" << endl;
00247   }
00248   close(pin[1]);
00249 
00250   pid_t waitpidRetVal;
00251 
00252   do {
00253     //kdDebug(5100) << "Checking if PGP is still running..." << endl;
00254     childExitStatus = 0;
00255     waitpidRetVal = waitpid(child_pid, &childExitStatus, WNOHANG);
00256     //kdDebug(5100) << "waitpid returned " << waitpidRetVal << endl;
00257     if (pout[0] >= 0) {
00258       do {
00259         // check if there is data to read from pout[0]
00260         //kdDebug(5100) << "Polling pout[0]..." << endl;
00261         pollstatus = poll(&pollout, 1, 0);
00262         if (pollstatus == 1) {
00263           //kdDebug(5100) << "Status for polling pout[0]: " << pollout.revents << endl;
00264           if (pollout.revents & POLLIN) {
00265             //kdDebug(5100) << "Trying to read " << 1024 << " bytes from pout[0]" << endl;
00266             if ((len = read(pout[0],str,1024))>0) {
00267               //kdDebug(5100) << "Read " << len << " bytes from pout[0]" << endl;
00268               str[len] ='\0';
00269               output += str;
00270             } else {
00271               /*
00272                * Apparently, on NetBSD when the child dies, the pipe begins
00273                * receiving empty data packets *before* waitpid() has signaled
00274                * that the child has died.  Also, notice that this happens
00275                * without any error bit being set in pollfd.revents (is this a
00276                * NetBSD bug??? ).  Notice that these anomalous packets exist
00277                * according to poll(), but have length 0 according to read().
00278                * Thus, kde can remain stuck inside this loop.
00279                *
00280                * A solution to this problem is to get out of the inner loop
00281                * when read() returns <=0.  In this way, kde has another chance
00282                * to call waitpid() to check if the child has died -- and this
00283                * time the call should succeed.
00284                *
00285                * Setting POLLHUP in pollfd.revents is not necessary, but I just
00286                * like the idea of signaling that something strange has
00287                * happened.
00288                */
00289               pollout.revents |= POLLHUP;
00290               break;
00291             }
00292           }
00293         }
00294         else if (pollstatus == -1) {
00295           kdDebug(5100) << "Error while polling pout[0]: "
00296                         << pollout.revents << endl;
00297         }
00298       } while ((pollstatus == 1) && (pollout.revents & POLLIN));
00299     }
00300 
00301     if (perr[0] >= 0) {
00302       do {
00303         // check if there is data to read from perr[0]
00304         //kdDebug(5100) << "Polling perr[0]..." << endl;
00305         pollstatus = poll(&pollerr, 1, 0);
00306         if (pollstatus == 1) {
00307           //kdDebug(5100) << "Status for polling perr[0]: " << pollerr.revents << endl;
00308           if (pollerr.revents & POLLIN) {
00309             //kdDebug(5100) << "Trying to read " << 1024 << " bytes from perr[0]" << endl;
00310             if ((len = read(perr[0],str,1024))>0) {
00311               //kdDebug(5100) << "Read " << len << " bytes from perr[0]" << endl;
00312               str[len] ='\0';
00313               error += str;
00314             } else {
00315               /*
00316                * Apparently, on NetBSD when the child dies, the pipe begins
00317                * receiving empty data packets *before* waitpid() has signaled
00318                * that the child has died.  Also, notice that this happens
00319                * without any error bit being set in pollfd.revents (is this a
00320                * NetBSD bug??? ).  Notice that these anomalous packets exist
00321                * according to poll(), but have length 0 according to read().
00322                * Thus, kde can remain stuck inside this loop.
00323                *
00324                * A solution to this problem is to get out of the inner loop
00325                * when read() returns <=0.  In this way, kde has another chance
00326                * to call waitpid() to check if the child has died -- and this
00327                * time the call should succeed.
00328                *
00329                * Setting POLLHUP in pollfd.revents is not necessary, but I just
00330                * like the idea of signaling that something strange has
00331                * happened.
00332                */
00333               pollerr.revents |= POLLHUP;
00334               break;
00335             }
00336           }
00337         }
00338         else if (pollstatus == -1) {
00339           kdDebug(5100) << "Error while polling perr[0]: "
00340                         << pollerr.revents << endl;
00341         }
00342       } while ((pollstatus == 1) && (pollerr.revents & POLLIN));
00343     }
00344   } while (waitpidRetVal == 0);
00345 
00346   close(pout[0]);
00347   close(perr[0]);
00348 
00349   unsetenv("PGPPASSFD");
00350   if(passphrase)
00351     close(ppass[0]);
00352 
00353   // Did the child exit normally?
00354   if (WIFEXITED(childExitStatus) != 0) {
00355     // Get the return code of the child
00356     childExitStatus = WEXITSTATUS(childExitStatus);
00357     kdDebug(5100) << "PGP exited with exit status " << childExitStatus
00358                   << endl;
00359   }
00360   else {
00361     childExitStatus = -1;
00362     kdDebug(5100) << "PGP exited abnormally!" << endl;
00363   }
00364 
00365   //Uncomment these lines for testing only! Doing so will decrease security!
00366   //kdDebug(5100) << "pgp output = " << QString(output) << endl;
00367   //kdDebug(5100) << "pgp error = " << error << endl;
00368 
00369   /* Make the information visible, so that a user can
00370    * get to know what's going on during the pgp calls.
00371    */
00372   kdDebug(5100) << error << endl;
00373 
00374   return childExitStatus;
00375 }
00376 
00377 
00378 int
00379 Base::runGpg( const char *cmd, const char *passphrase, bool onlyReadFromGnuPG )
00380 {
00381   /* the pipe ppass is used for to pass the password to
00382    * pgp. passing the password together with the normal input through
00383    * stdin doesn't seem to work as expected (at least for pgp5.0)
00384    */
00385   char str[1025] = "\0";
00386   int pin[2], pout[2], perr[2], ppass[2];
00387   int len, len2;
00388   FILE *pass;
00389   pid_t child_pid;
00390   int childExitStatus;
00391   char gpgcmd[1024] = "\0";
00392   struct pollfd poller[3];
00393   int num_pollers = 0;
00394   const int STD_OUT = 0;
00395   const int STD_ERR = 1;
00396   const int STD_IN = 2;
00397   int pollstatus;
00398 
00399   if(passphrase)
00400   {
00401     pipe(ppass);
00402 
00403     pass = fdopen(ppass[1], "w");
00404     fwrite(passphrase, sizeof(char), strlen(passphrase), pass);
00405     fwrite("\n", sizeof(char), 1, pass);
00406     fclose(pass);
00407     close(ppass[1]);
00408 
00409     //Uncomment these lines for testing only! Doing so will decrease security!
00410     //kdDebug(5100) << "pass = " << passphrase << endl;
00411   }
00412 
00413   //Uncomment these lines for testing only! Doing so will decrease security!
00414   //kdDebug(5100) << "pgp cmd = " << cmd << endl;
00415   //kdDebug(5100) << "pgp input = " << QString(input)
00416   //          << "input length = " << input.length() << endl;
00417 
00418   error = "";
00419   output = "";
00420 
00421   pipe(pin);
00422   pipe(pout);
00423   pipe(perr);
00424 
00425   if( passphrase ) {
00426     if( mVersion >= "1.0.7" ) {
00427       // GnuPG >= 1.0.7 supports the gpg-agent, so we look for it.
00428       if( 0 == getenv("GPG_AGENT_INFO") ) {
00429         // gpg-agent not found, so we tell gpg not to use the agent
00430         snprintf( gpgcmd, 1023,
00431                   "LANGUAGE=C gpg --no-use-agent --passphrase-fd %d %s",
00432                   ppass[0], cmd );
00433       }
00434       else {
00435         // gpg-agent seems to be running, so we tell gpg to use the agent
00436         snprintf( gpgcmd, 1023,
00437                   "LANGUAGE=C gpg --use-agent %s",
00438                   cmd );
00439       }
00440     }
00441     else {
00442       // GnuPG < 1.0.7 doesn't know anything about the gpg-agent
00443       snprintf( gpgcmd, 1023,
00444                 "LANGUAGE=C gpg --passphrase-fd %d %s",
00445                 ppass[0], cmd );
00446     }
00447   }
00448   else {
00449     snprintf(gpgcmd, 1023, "LANGUAGE=C gpg %s",cmd);
00450   }
00451 
00452   QApplication::flushX();
00453   if(!(child_pid = fork()))
00454   {
00455     /*We're the child.*/
00456     close(pin[1]);
00457     dup2(pin[0], 0);
00458     close(pin[0]);
00459 
00460     close(pout[0]);
00461     dup2(pout[1], 1);
00462     close(pout[1]);
00463 
00464     close(perr[0]);
00465     dup2(perr[1], 2);
00466     close(perr[1]);
00467 
00468     //#warning FIXME: there has to be a better way to do this
00469      /* this is nasty nasty nasty (but it works) */
00470     if( passphrase ) {
00471       if( mVersion >= "1.0.7" ) {
00472         // GnuPG >= 1.0.7 supports the gpg-agent, so we look for it.
00473         if( 0 == getenv("GPG_AGENT_INFO") ) {
00474           // gpg-agent not found, so we tell gpg not to use the agent
00475           snprintf( gpgcmd, 1023,
00476                     "LANGUAGE=C gpg --no-use-agent --passphrase-fd %d %s",
00477                     ppass[0], cmd );
00478         }
00479         else {
00480           // gpg-agent seems to be running, so we tell gpg to use the agent
00481           snprintf( gpgcmd, 1023,
00482                     "LANGUAGE=C gpg --use-agent %s",
00483                     cmd );
00484         }
00485       }
00486       else {
00487         // GnuPG < 1.0.7 doesn't know anything about the gpg-agent
00488         snprintf( gpgcmd, 1023,
00489                   "LANGUAGE=C gpg --passphrase-fd %d %s",
00490                   ppass[0], cmd );
00491       }
00492     }
00493     else {
00494       snprintf(gpgcmd, 1023, "LANGUAGE=C gpg %s",cmd);
00495     }
00496 
00497     kdDebug(5100) << "pgp cmd = " << gpgcmd << endl;
00498 
00499     execl("/bin/sh", "sh", "-c", gpgcmd,  (void *)0);
00500     _exit(127);
00501   }
00502 
00503   // Only get here if we're the parent.
00504 
00505   close(pin[0]);
00506   close(pout[1]);
00507   close(perr[1]);
00508 
00509   // poll for "There is data to read."
00510   poller[STD_OUT].fd = pout[0];
00511   poller[STD_OUT].events = POLLIN;
00512   poller[STD_ERR].fd = perr[0];
00513   poller[STD_ERR].events = POLLIN;
00514   num_pollers = 2;
00515 
00516   if (!onlyReadFromGnuPG) {
00517     // poll for "Writing now will not block."
00518     poller[STD_IN].fd = pin[1];
00519     poller[STD_IN].events = POLLOUT;
00520     num_pollers = 3;
00521   } else {
00522     close (pin[1]);
00523     pin[1] = -1;
00524   }
00525 
00526   pid_t waitpidRetVal;
00527   unsigned int input_pos = 0;
00528   uint input_length = input.length();
00529 
00530   do {
00531     //kdDebug(5100) << "Checking if GnuPG is still running..." << endl;
00532     childExitStatus = 0;
00533     waitpidRetVal = waitpid(child_pid, &childExitStatus, WNOHANG);
00534     //kdDebug(5100) << "waitpid returned " << waitpidRetVal << endl;
00535     do {
00536       // poll the pipes
00537       pollstatus = poll(poller, num_pollers, 10);
00538       if( 0 < pollstatus ) {
00539         // Check stdout.
00540         if (poller[STD_OUT].revents & POLLIN) {
00541           //kdDebug(5100) << "Trying to read " << 1024 << " bytes from pout[0]" << endl;
00542           if ((len = read(pout[0],str,1024))>0) {
00543             //kdDebug(5100) << "Read " << len << " bytes from pout[0]" << endl;
00544             str[len] ='\0';
00545             output += str;
00546           }
00547           else {
00548             // FreeBSD/NetBSD workaround
00549             //
00550             // Apparently, on Free/NetBSD when the child dies, the pipe begins
00551             // receiving empty data packets *before* waitpid() has signaled
00552             // that the child has died.  Also, notice that this happens
00553             // without any error bit being set in pollfd.revents (is this a
00554             // Free/NetBSD bug??? ).  Notice that these anomalous packets exist
00555             // according to poll(), but have length 0 according to read().
00556             // Thus, we can remain stuck inside this loop.
00557             //
00558             // A solution to this problem is to get out of the inner loop
00559             // when read() returns <=0.  In this way, we have another chance
00560             // to call waitpid() to check if the child has died -- and this
00561             // time the call should succeed.
00562             //
00563             // Set POLLHUP in pollfd.revents to signal that something strange
00564             // has happened and disable polling of stdout.
00565             poller[STD_OUT].revents |= POLLHUP;
00566             poller[STD_OUT].events = 0;
00567           }
00568         } else if (poller[STD_OUT].revents & POLLHUP) {
00569           // disable polling of stdout
00570           poller[STD_OUT].events = 0;
00571         }
00572 
00573         // Check stderr.
00574         if (poller[STD_ERR].revents & POLLIN) {
00575           //kdDebug(5100) << "Trying to read " << 1024 << " bytes from perr[0]" << endl;
00576           if ((len = read(poller[STD_ERR].fd,str,1024))>0) {
00577             //kdDebug(5100) << "Read " << len << " bytes from perr[0]" << endl;
00578             str[len] ='\0';
00579             error += str;
00580           }
00581           else {
00582             // FreeBSD/NetBSD workaround (for details see above)
00583             poller[STD_ERR].revents |= POLLHUP;
00584             poller[STD_ERR].events = 0;
00585           }
00586         } else if (poller[STD_ERR].revents & POLLHUP) {
00587           // disable polling of stderr
00588           poller[STD_ERR].events = 0;
00589         }
00590 
00591         if (num_pollers > 2) {
00592           if (poller[STD_IN].revents & ( POLLERR | POLLHUP ) ) {
00593             kdDebug(5100) << "GnuPG seems to have hung up" << endl;
00594             close (pin[1]);
00595             pin[1] = -1;
00596             --num_pollers;
00597           }
00598           else if (poller[STD_IN].revents & POLLOUT) {
00599             if (!input.isEmpty()) {
00600               // search end of next line
00601               if ((len2 = input.find('\n', input_pos)) == -1)
00602                 len2 = input_length - input_pos;
00603               else
00604                 len2 = len2 - input_pos + 1;
00605 
00606               //kdDebug(5100) << "Trying to write " << len2 << " bytes to pin[1] ..." << endl;
00607               len2 = write(pin[1], input.data() + input_pos, len2 );
00608               //kdDebug(5100) << "Wrote " << len2 << " bytes to pin[1] ..." << endl;
00609               input_pos += len2;
00610 
00611               // We are done.
00612               if (input_pos >= input_length) {
00613                 //kdDebug(5100) << "All input was written to pin[1]" << endl;
00614                 close (pin[1]);
00615                 pin[1] = -1;
00616                 --num_pollers;
00617               }
00618             }
00619             else { // if input.isEmpty()
00620               write(pin[1], "\n", 1);
00621               //kdDebug(5100) << "All input was written to pin[1]" << endl;
00622               close (pin[1]);
00623               pin[1] = -1;
00624               --num_pollers;
00625             }
00626           }
00627         }
00628       }
00629     } while ( (pollstatus > 0) && ( (num_pollers > 2)
00630                                     || (poller[STD_OUT].events != 0)
00631                                     || (poller[STD_ERR].events != 0) ) );
00632 
00633     if (pollstatus == -1) {
00634       kdDebug(5100) << "GnuPG poll failed, errno: " << errno << endl;
00635     }
00636 
00637   } while(waitpidRetVal == 0);
00638 
00639   if( 0 <= pin[1] )
00640     close (pin[1]);
00641   close(pout[0]);
00642   close(perr[0]);
00643 
00644   if(passphrase)
00645     close(ppass[0]);
00646 
00647   // Did the child exit normally?
00648   if (WIFEXITED(childExitStatus) != 0) {
00649     // Get the return code of the child
00650     childExitStatus = WEXITSTATUS(childExitStatus);
00651     kdDebug(5100) << "GnuPG exited with exit status " << childExitStatus
00652                   << endl;
00653   }
00654   else {
00655     childExitStatus = -1;
00656     kdDebug(5100) << "GnuPG exited abnormally!" << endl;
00657   }
00658 
00659   //Uncomment these lines for testing only! Doing so will decrease security!
00660   //kdDebug(5100) << "gpg stdout:\n" << QString(output) << endl;
00661 
00662   // Make the information visible, so that a user can
00663   // get to know what's going on during the gpg calls.
00664   kdDebug(5100) << "gpg stderr:\n" << error << endl;
00665 
00666   return childExitStatus;
00667 }
00668 
00669 
00670 QCString
00671 Base::addUserId()
00672 {
00673   QCString cmd;
00674   QCString pgpUser = Module::getKpgp()->user();
00675 
00676   if(!pgpUser.isEmpty())
00677   {
00678     cmd += " -u 0x";
00679     cmd += pgpUser;
00680     return cmd;
00681   }
00682   return QCString();
00683 }
00684 
00685 
00686 } // namespace Kpgp
KDE Home | KDE Accessibility Home | Description of Access Keys