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       for (unsigned int i=0; i<input.length(); i+=len2) {
00153         len2 = 0;
00154 
00155         // check if writing now to pin[1] will not block (5 ms timeout)
00156         //kdDebug(5100) << "Polling pin[1]..." << endl;
00157         pollstatus = poll(&pollin, 1, 5);
00158         if (pollstatus == 1) {
00159           //kdDebug(5100) << "Status for polling pin[1]: " << pollin.revents << endl;
00160           if (pollin.revents & POLLERR) {
00161             kdDebug(5100) << "PGP seems to have hung up" << endl;
00162             break;
00163           }
00164           else if (pollin.revents & POLLOUT) {
00165             // search end of next line
00166             if ((len2 = input.find('\n', i)) == -1)
00167               len2 = input.length()-i;
00168             else
00169               len2 = len2-i+1;
00170 
00171             //kdDebug(5100) << "Trying to write " << len2 << " bytes to pin[1] ..." << endl;
00172             len2 = write(pin[1], input.mid(i,len2).data(), len2);
00173             //kdDebug(5100) << "Wrote " << len2 << " bytes to pin[1] ..." << endl;
00174           }
00175         }
00176         else if (!pollstatus) {
00177           //kdDebug(5100) << "Timeout while polling pin[1]: "
00178           //              << pollin.revents << endl;
00179         }
00180         else if (pollstatus == -1) {
00181           kdDebug(5100) << "Error while polling pin[1]: "
00182                         << pollin.revents << endl;
00183         }
00184 
00185         if (pout[0] >= 0) {
00186           do {
00187             // check if there is data to read from pout[0]
00188             //kdDebug(5100) << "Polling pout[0]..." << endl;
00189             pollstatus = poll(&pollout, 1, 0);
00190             if (pollstatus == 1) {
00191               //kdDebug(5100) << "Status for polling pout[0]: " << pollout.revents << endl;
00192               if (pollout.revents & POLLIN) {
00193                 //kdDebug(5100) << "Trying to read " << 1024 << " bytes from pout[0]" << endl;
00194                 if ((len = read(pout[0],str,1024))>0) {
00195                   //kdDebug(5100) << "Read " << len << " bytes from pout[0]" << endl;
00196                   str[len] ='\0';
00197                   output += str;
00198                 }
00199                 else
00200                   break;
00201               }
00202             }
00203             else if (pollstatus == -1) {
00204               kdDebug(5100) << "Error while polling pout[0]: "
00205                             << pollout.revents << endl;
00206             }
00207           } while ((pollstatus == 1) && (pollout.revents & POLLIN));
00208         }
00209 
00210         if (perr[0] >= 0) {
00211           do {
00212             // check if there is data to read from perr[0]
00213             //kdDebug(5100) << "Polling perr[0]..." << endl;
00214             pollstatus = poll(&pollerr, 1, 0);
00215             if (pollstatus == 1) {
00216               //kdDebug(5100) << "Status for polling perr[0]: " << pollerr.revents << endl;
00217               if (pollerr.revents & POLLIN) {
00218                 //kdDebug(5100) << "Trying to read " << 1024 << " bytes from perr[0]" << endl;
00219                 if ((len = read(perr[0],str,1024))>0) {
00220                   //kdDebug(5100) << "Read " << len << " bytes from perr[0]" << endl;
00221                   str[len] ='\0';
00222                   error += str;
00223                 }
00224                 else
00225                   break;
00226               }
00227             }
00228             else if (pollstatus == -1) {
00229               kdDebug(5100) << "Error while polling perr[0]: "
00230                             << pollerr.revents << endl;
00231             }
00232           } while ((pollstatus == 1) && (pollerr.revents & POLLIN));
00233         }
00234 
00235         // abort writing to PGP if PGP hung up
00236         if ((pollstatus == 1) &&
00237             ((pollout.revents & POLLHUP) || (pollerr.revents & POLLHUP))) {
00238           kdDebug(5100) << "PGP hung up" << endl;
00239           break;
00240         }
00241       }
00242     }
00243     else // if input.isEmpty()
00244       write(pin[1], "\n", 1);
00245     //kdDebug(5100) << "All input was written to pin[1]" << endl;
00246   }
00247   close(pin[1]);
00248 
00249   pid_t waitpidRetVal;
00250 
00251   do {
00252     //kdDebug(5100) << "Checking if PGP is still running..." << endl;
00253     childExitStatus = 0;
00254     waitpidRetVal = waitpid(child_pid, &childExitStatus, WNOHANG);
00255     //kdDebug(5100) << "waitpid returned " << waitpidRetVal << endl;
00256     if (pout[0] >= 0) {
00257       do {
00258         // check if there is data to read from pout[0]
00259         //kdDebug(5100) << "Polling pout[0]..." << endl;
00260         pollstatus = poll(&pollout, 1, 0);
00261         if (pollstatus == 1) {
00262           //kdDebug(5100) << "Status for polling pout[0]: " << pollout.revents << endl;
00263           if (pollout.revents & POLLIN) {
00264             //kdDebug(5100) << "Trying to read " << 1024 << " bytes from pout[0]" << endl;
00265             if ((len = read(pout[0],str,1024))>0) {
00266               //kdDebug(5100) << "Read " << len << " bytes from pout[0]" << endl;
00267               str[len] ='\0';
00268               output += str;
00269             } else {
00270               /*
00271                * Apparently, on NetBSD when the child dies, the pipe begins
00272                * receiving empty data packets *before* waitpid() has signaled
00273                * that the child has died.  Also, notice that this happens
00274                * without any error bit being set in pollfd.revents (is this a
00275                * NetBSD bug??? ).  Notice that these anomalous packets exist
00276                * according to poll(), but have length 0 according to read().
00277                * Thus, kde can remain stuck inside this loop.
00278                *
00279                * A solution to this problem is to get out of the inner loop
00280                * when read() returns <=0.  In this way, kde has another chance
00281                * to call waitpid() to check if the child has died -- and this
00282                * time the call should succeed.
00283                *
00284                * Setting POLLHUP in pollfd.revents is not necessary, but I just
00285                * like the idea of signaling that something strange has
00286                * happened.
00287                */
00288               pollout.revents |= POLLHUP;
00289               break;
00290             }
00291           }
00292         }
00293         else if (pollstatus == -1) {
00294           kdDebug(5100) << "Error while polling pout[0]: "
00295                         << pollout.revents << endl;
00296         }
00297       } while ((pollstatus == 1) && (pollout.revents & POLLIN));
00298     }
00299 
00300     if (perr[0] >= 0) {
00301       do {
00302         // check if there is data to read from perr[0]
00303         //kdDebug(5100) << "Polling perr[0]..." << endl;
00304         pollstatus = poll(&pollerr, 1, 0);
00305         if (pollstatus == 1) {
00306           //kdDebug(5100) << "Status for polling perr[0]: " << pollerr.revents << endl;
00307           if (pollerr.revents & POLLIN) {
00308             //kdDebug(5100) << "Trying to read " << 1024 << " bytes from perr[0]" << endl;
00309             if ((len = read(perr[0],str,1024))>0) {
00310               //kdDebug(5100) << "Read " << len << " bytes from perr[0]" << endl;
00311               str[len] ='\0';
00312               error += str;
00313             } else {
00314               /*
00315                * Apparently, on NetBSD when the child dies, the pipe begins
00316                * receiving empty data packets *before* waitpid() has signaled
00317                * that the child has died.  Also, notice that this happens
00318                * without any error bit being set in pollfd.revents (is this a
00319                * NetBSD bug??? ).  Notice that these anomalous packets exist
00320                * according to poll(), but have length 0 according to read().
00321                * Thus, kde can remain stuck inside this loop.
00322                *
00323                * A solution to this problem is to get out of the inner loop
00324                * when read() returns <=0.  In this way, kde has another chance
00325                * to call waitpid() to check if the child has died -- and this
00326                * time the call should succeed.
00327                *
00328                * Setting POLLHUP in pollfd.revents is not necessary, but I just
00329                * like the idea of signaling that something strange has
00330                * happened.
00331                */
00332               pollerr.revents |= POLLHUP;
00333               break;
00334             }
00335           }
00336         }
00337         else if (pollstatus == -1) {
00338           kdDebug(5100) << "Error while polling perr[0]: "
00339                         << pollerr.revents << endl;
00340         }
00341       } while ((pollstatus == 1) && (pollerr.revents & POLLIN));
00342     }
00343   } while (waitpidRetVal == 0);
00344 
00345   close(pout[0]);
00346   close(perr[0]);
00347 
00348   unsetenv("PGPPASSFD");
00349   if(passphrase)
00350     close(ppass[0]);
00351 
00352   // Did the child exit normally?
00353   if (WIFEXITED(childExitStatus) != 0) {
00354     // Get the return code of the child
00355     childExitStatus = WEXITSTATUS(childExitStatus);
00356     kdDebug(5100) << "PGP exited with exit status " << childExitStatus 
00357                   << endl;
00358   }
00359   else {
00360     childExitStatus = -1;
00361     kdDebug(5100) << "PGP exited abnormally!" << endl;
00362   }
00363 
00364   //Uncomment these lines for testing only! Doing so will decrease security!
00365   //kdDebug(5100) << "pgp output = " << QString(output) << endl;
00366   //kdDebug(5100) << "pgp error = " << error << endl;
00367 
00368   /* Make the information visible, so that a user can
00369    * get to know what's going on during the pgp calls.
00370    */
00371   kdDebug(5100) << error << endl;
00372 
00373   return childExitStatus;
00374 }
00375 
00376 
00377 int
00378 Base::runGpg( const char *cmd, const char *passphrase, bool onlyReadFromGnuPG )
00379 {
00380   /* the pipe ppass is used for to pass the password to
00381    * pgp. passing the password together with the normal input through
00382    * stdin doesn't seem to work as expected (at least for pgp5.0)
00383    */
00384   char str[1025] = "\0";
00385   int pin[2], pout[2], perr[2], ppass[2];
00386   int len, len2;
00387   FILE *pass;
00388   pid_t child_pid;
00389   int childExitStatus;
00390   char gpgcmd[1024] = "\0";
00391   struct pollfd poller[3];
00392   int num_pollers = 0;
00393   const int STD_OUT = 0;
00394   const int STD_ERR = 1;
00395   const int STD_IN = 2;
00396   int pollstatus;
00397 
00398   if(passphrase)
00399   {
00400     pipe(ppass);
00401 
00402     pass = fdopen(ppass[1], "w");
00403     fwrite(passphrase, sizeof(char), strlen(passphrase), pass);
00404     fwrite("\n", sizeof(char), 1, pass);
00405     fclose(pass);
00406     close(ppass[1]);
00407 
00408     //Uncomment these lines for testing only! Doing so will decrease security!
00409     //kdDebug(5100) << "pass = " << passphrase << endl;
00410   }
00411 
00412   //Uncomment these lines for testing only! Doing so will decrease security!
00413   //kdDebug(5100) << "pgp cmd = " << cmd << endl;
00414   //kdDebug(5100) << "pgp input = " << QString(input)
00415   //          << "input length = " << input.length() << endl;
00416 
00417   error = "";
00418   output = "";
00419 
00420   pipe(pin);
00421   pipe(pout);
00422   pipe(perr);
00423 
00424   if( passphrase ) {
00425     if( mVersion >= "1.0.7" ) {
00426       // GnuPG >= 1.0.7 supports the gpg-agent, so we look for it.
00427       if( 0 == getenv("GPG_AGENT_INFO") ) {
00428         // gpg-agent not found, so we tell gpg not to use the agent
00429         snprintf( gpgcmd, 1023,
00430                   "LANGUAGE=C gpg --no-use-agent --passphrase-fd %d %s",
00431                   ppass[0], cmd );
00432       }
00433       else {
00434         // gpg-agent seems to be running, so we tell gpg to use the agent
00435         snprintf( gpgcmd, 1023,
00436                   "LANGUAGE=C gpg --use-agent %s",
00437                   cmd );
00438       }
00439     }
00440     else {
00441       // GnuPG < 1.0.7 doesn't know anything about the gpg-agent
00442       snprintf( gpgcmd, 1023,
00443                 "LANGUAGE=C gpg --passphrase-fd %d %s",
00444                 ppass[0], cmd );
00445     }
00446   }
00447   else {
00448     snprintf(gpgcmd, 1023, "LANGUAGE=C gpg %s",cmd);
00449   }
00450 
00451   QApplication::flushX();
00452   if(!(child_pid = fork()))
00453   {
00454     /*We're the child.*/
00455     close(pin[1]);
00456     dup2(pin[0], 0);
00457     close(pin[0]);
00458 
00459     close(pout[0]);
00460     dup2(pout[1], 1);
00461     close(pout[1]);
00462 
00463     close(perr[0]);
00464     dup2(perr[1], 2);
00465     close(perr[1]);
00466 
00467     //#warning FIXME: there has to be a better way to do this
00468      /* this is nasty nasty nasty (but it works) */
00469     if( passphrase ) {
00470       if( mVersion >= "1.0.7" ) {
00471         // GnuPG >= 1.0.7 supports the gpg-agent, so we look for it.
00472         if( 0 == getenv("GPG_AGENT_INFO") ) {
00473           // gpg-agent not found, so we tell gpg not to use the agent
00474           snprintf( gpgcmd, 1023,
00475                     "LANGUAGE=C gpg --no-use-agent --passphrase-fd %d %s",
00476                     ppass[0], cmd );
00477         }
00478         else {
00479           // gpg-agent seems to be running, so we tell gpg to use the agent
00480           snprintf( gpgcmd, 1023,
00481                     "LANGUAGE=C gpg --use-agent %s",
00482                     cmd );
00483         }
00484       }
00485       else {
00486         // GnuPG < 1.0.7 doesn't know anything about the gpg-agent
00487         snprintf( gpgcmd, 1023,
00488                   "LANGUAGE=C gpg --passphrase-fd %d %s",
00489                   ppass[0], cmd );
00490       }
00491     }
00492     else {
00493       snprintf(gpgcmd, 1023, "LANGUAGE=C gpg %s",cmd);
00494     }
00495 
00496     kdDebug(5100) << "pgp cmd = " << gpgcmd << endl;
00497 
00498     execl("/bin/sh", "sh", "-c", gpgcmd,  (void *)0);
00499     _exit(127);
00500   }
00501 
00502   // Only get here if we're the parent.
00503 
00504   close(pin[0]);
00505   close(pout[1]);
00506   close(perr[1]);
00507 
00508   // poll for "There is data to read."
00509   poller[STD_OUT].fd = pout[0];
00510   poller[STD_OUT].events = POLLIN;
00511   poller[STD_ERR].fd = perr[0];
00512   poller[STD_ERR].events = POLLIN;
00513   num_pollers = 2;
00514 
00515   if (!onlyReadFromGnuPG) {
00516     // poll for "Writing now will not block."
00517     poller[STD_IN].fd = pin[1];
00518     poller[STD_IN].events = POLLOUT;
00519     num_pollers = 3;
00520   } else {
00521     close (pin[1]);
00522     pin[1] = -1;
00523   }
00524 
00525   pid_t waitpidRetVal;
00526   unsigned int input_pos = 0;
00527 
00528   do {
00529     //kdDebug(5100) << "Checking if GnuPG is still running..." << endl;
00530     childExitStatus = 0;
00531     waitpidRetVal = waitpid(child_pid, &childExitStatus, WNOHANG);
00532     //kdDebug(5100) << "waitpid returned " << waitpidRetVal << endl;
00533     do {
00534       // poll the pipes
00535       pollstatus = poll(poller, num_pollers, 10);
00536       if( 0 < pollstatus ) {
00537         // Check stdout.
00538         if (poller[STD_OUT].revents & POLLIN) {
00539           //kdDebug(5100) << "Trying to read " << 1024 << " bytes from pout[0]" << endl;
00540           if ((len = read(pout[0],str,1024))>0) {
00541             //kdDebug(5100) << "Read " << len << " bytes from pout[0]" << endl;
00542             str[len] ='\0';
00543             output += str;
00544           }
00545           else {
00546             // FreeBSD/NetBSD workaround
00547             //
00548             // Apparently, on Free/NetBSD when the child dies, the pipe begins
00549             // receiving empty data packets *before* waitpid() has signaled
00550             // that the child has died.  Also, notice that this happens
00551             // without any error bit being set in pollfd.revents (is this a
00552             // Free/NetBSD bug??? ).  Notice that these anomalous packets exist
00553             // according to poll(), but have length 0 according to read().
00554             // Thus, we can remain stuck inside this loop.
00555             //
00556             // A solution to this problem is to get out of the inner loop
00557             // when read() returns <=0.  In this way, we have another chance
00558             // to call waitpid() to check if the child has died -- and this
00559             // time the call should succeed.
00560             //
00561             // Set POLLHUP in pollfd.revents to signal that something strange
00562             // has happened and disable polling of stdout.
00563             poller[STD_OUT].revents |= POLLHUP;
00564             poller[STD_OUT].events = 0;
00565           }
00566         } else if (poller[STD_OUT].revents & POLLHUP) {
00567           // disable polling of stdout
00568           poller[STD_OUT].events = 0;
00569         }
00570 
00571         // Check stderr.
00572         if (poller[STD_ERR].revents & POLLIN) {
00573           //kdDebug(5100) << "Trying to read " << 1024 << " bytes from perr[0]" << endl;
00574           if ((len = read(poller[STD_ERR].fd,str,1024))>0) {
00575             //kdDebug(5100) << "Read " << len << " bytes from perr[0]" << endl;
00576             str[len] ='\0';
00577             error += str;
00578           }
00579           else {
00580             // FreeBSD/NetBSD workaround (for details see above)
00581             poller[STD_ERR].revents |= POLLHUP;
00582             poller[STD_ERR].events = 0;
00583           }
00584         } else if (poller[STD_ERR].revents & POLLHUP) {
00585           // disable polling of stderr
00586           poller[STD_ERR].events = 0;
00587         }
00588         
00589         if (num_pollers > 2) {
00590           if (poller[STD_IN].revents & ( POLLERR | POLLHUP ) ) {
00591             kdDebug(5100) << "GnuPG seems to have hung up" << endl;
00592             close (pin[1]);
00593             pin[1] = -1;
00594             --num_pollers;
00595           }
00596           else if (poller[STD_IN].revents & POLLOUT) {
00597             if (!input.isEmpty()) {
00598               // search end of next line
00599               if ((len2 = input.find('\n', input_pos)) == -1)
00600                 len2 = input.length()-input_pos;
00601               else
00602                 len2 = len2-input_pos+1;
00603 
00604               //kdDebug(5100) << "Trying to write " << len2 << " bytes to pin[1] ..." << endl;
00605               len2 = write(pin[1], input.mid(input_pos,len2).data(), len2);
00606               //kdDebug(5100) << "Wrote " << len2 << " bytes to pin[1] ..." << endl;
00607               input_pos += len2;
00608 
00609               // We are done.
00610               if (input_pos >= input.length()) {
00611                 //kdDebug(5100) << "All input was written to pin[1]" << endl;
00612                 close (pin[1]);
00613                 pin[1] = -1;
00614                 --num_pollers;
00615               }
00616             }
00617             else { // if input.isEmpty()
00618               write(pin[1], "\n", 1);
00619               //kdDebug(5100) << "All input was written to pin[1]" << endl;
00620               close (pin[1]);
00621               pin[1] = -1;
00622               --num_pollers;
00623             }
00624           }
00625         }
00626       }
00627     } while ( (pollstatus > 0) && ( (num_pollers > 2)
00628                                     || (poller[STD_OUT].events != 0)
00629                                     || (poller[STD_ERR].events != 0) ) );
00630 
00631     if (pollstatus == -1) {
00632       kdDebug(5100) << "GnuPG poll failed, errno: " << errno << endl;
00633     }
00634 
00635   } while(waitpidRetVal == 0);
00636 
00637   if( 0 <= pin[1] )
00638     close (pin[1]); 
00639   close(pout[0]);
00640   close(perr[0]);
00641 
00642   if(passphrase)
00643     close(ppass[0]);
00644 
00645   // Did the child exit normally?
00646   if (WIFEXITED(childExitStatus) != 0) {
00647     // Get the return code of the child
00648     childExitStatus = WEXITSTATUS(childExitStatus);
00649     kdDebug(5100) << "GnuPG exited with exit status " << childExitStatus 
00650                   << endl;
00651   }
00652   else {
00653     childExitStatus = -1;
00654     kdDebug(5100) << "GnuPG exited abnormally!" << endl;
00655   }
00656 
00657   //Uncomment these lines for testing only! Doing so will decrease security!
00658   //kdDebug(5100) << "gpg stdout:\n" << QString(output) << endl;
00659 
00660   // Make the information visible, so that a user can
00661   // get to know what's going on during the gpg calls.
00662   kdDebug(5100) << "gpg stderr:\n" << error << endl;
00663 
00664   return childExitStatus;
00665 }
00666 
00667 
00668 QCString
00669 Base::addUserId()
00670 {
00671   QCString cmd;
00672   QCString pgpUser = Module::getKpgp()->user();
00673 
00674   if(!pgpUser.isEmpty())
00675   {
00676     cmd += " -u 0x";
00677     cmd += pgpUser;
00678     return cmd;
00679   }
00680   return QCString();
00681 }
00682 
00683 
00684 } // namespace Kpgp
KDE Home | KDE Accessibility Home | Description of Access Keys