libkpgp

kpgpbase.cpp
1 /*
2  kpgpbase.cpp
3 
4  Copyright (C) 2001,2002 the KPGP authors
5  See file AUTHORS.kpgp for details
6 
7  This file is part of KPGP, the KDE PGP/GnuPG support library.
8 
9  KPGP is free software; you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation; either version 2 of the License, or
12  (at your option) any later version.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software Foundation,
16  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 
19 #include <kdebug.h>
20 
21 #include <config.h>
22 
23 #include "kpgpbase.h"
24 #include "kpgp.h"
25 #include "kpgpblock.h"
26 
27 #include <stdlib.h> /* setenv, unsetenv */
28 #include <unistd.h> /* pipe, close, fork, dup2, execl, _exit, write, read */
29 #include <sys/poll.h> /* poll, etc. */
30 #include <sys/types.h> /* pid_t */
31 #include <sys/wait.h> /* waitpid */
32 #include <errno.h>
33 
34 #include <tqapplication.h>
35 
36 
37 namespace Kpgp {
38 
39 Base::Base()
40  : input(), output(), error(), errMsg(), status(OK)
41 {
42 }
43 
44 
45 Base::~Base()
46 {
47 }
48 
49 
50 void
51 Base::clear()
52 {
53  input = TQCString();
54  output = TQCString();
55  error = TQCString();
56  errMsg = TQString();
57  status = OK;
58 }
59 
60 
61 int
62 Base::run( const char *cmd, const TQString &passphrase, bool onlyReadFromPGP )
63 {
64  /* the pipe ppass is used for to pass the password to
65  * pgp. passing the password together with the normal input through
66  * stdin doesn't seem to work as expected (at least for pgp5.0)
67  */
68  char str[1025] = "\0";
69  int pin[2], pout[2], perr[2], ppass[2];
70  int len, len2;
71  FILE *pass;
72  pid_t child_pid;
73  int childExiStatus;
74  struct pollfd pollin, pollout, pollerr;
75  int pollstatus;
76 
77  if (!passphrase.isEmpty())
78  {
79  if (pipe(ppass) < 0) {
80  // An error occurred
81  // FIXME
82  printf("Something went wrong in libkpgp/kpgpbase.cpp\n");
83  }
84 
85  pass = fdopen(ppass[1], "w");
86  TQCString pass2 = passphrase.local8Bit();
87  fwrite(pass2, sizeof(char), pass2.length(), pass);
88  fwrite("\n", sizeof(char), 1, pass);
89  fclose(pass);
90  close(ppass[1]);
91 
92  // tell pgp which fd to use for the passphrase
93  TQCString tmp;
94  tmp.sprintf("%d",ppass[0]);
95  ::setenv("PGPPASSFD",tmp.data(),1);
96 
97  //Uncomment these lines for testing only! Doing so will decrease security!
98  //kdDebug(5100) << "pgp PGPPASSFD = " << tmp << endl;
99  //kdDebug(5100) << "pgp pass = " << passphrase << endl;
100  }
101  else
102  ::unsetenv("PGPPASSFD");
103 
104  //Uncomment these lines for testing only! Doing so will decrease security!
105  kdDebug(5100) << "pgp cmd = " << cmd << endl;
106  //kdDebug(5100) << "pgp input = " << TQString(input)
107  // << "input length = " << input.length() << endl;
108 
109  error = "";
110  output = "";
111 
112  if (pipe(pin) < 0) {
113  // An error occurred
114  // FIXME
115  printf("Something went wrong in libkpgp/kpgpbase.cpp\n");
116  }
117  if (pipe(pout) < 0) {
118  // An error occurred
119  // FIXME
120  printf("Something went wrong in libkpgp/kpgpbase.cpp\n");
121  }
122  if (pipe(perr) < 0) {
123  // An error occurred
124  // FIXME
125  printf("Something went wrong in libkpgp/kpgpbase.cpp\n");
126  }
127 
128  TQApplication::flushX();
129  if(!(child_pid = fork()))
130  {
131  /*We're the child.*/
132  close(pin[1]);
133  dup2(pin[0], 0);
134  close(pin[0]);
135 
136  close(pout[0]);
137  dup2(pout[1], 1);
138  close(pout[1]);
139 
140  close(perr[0]);
141  dup2(perr[1], 2);
142  close(perr[1]);
143 
144  execl("/bin/sh", "sh", "-c", cmd, (void *)0);
145  _exit(127);
146  }
147 
148  /*Only get here if we're the parent.*/
149  close(pin[0]);
150  close(pout[1]);
151  close(perr[1]);
152 
153  // poll for "There is data to read."
154  pollout.fd = pout[0];
155  pollout.events = POLLIN;
156  pollout.revents = 0; // init with 0, just in case
157  pollerr.fd = perr[0];
158  pollerr.events = POLLIN;
159  pollerr.revents = 0; // init with 0, just in case
160 
161  // poll for "Writing now will not block."
162  pollin.fd = pin[1];
163  pollin.events = POLLOUT;
164  pollin.revents = 0; // init with 0, just in case
165 
166  if (!onlyReadFromPGP) {
167  if (!input.isEmpty()) {
168  // write to pin[1] one line after the other to prevent dead lock
169  uint input_length = input.length();
170  for (unsigned int i=0; i<input_length; i+=len2) {
171  len2 = 0;
172 
173  // check if writing now to pin[1] will not block (5 ms timeout)
174  //kdDebug(5100) << "Polling pin[1]..." << endl;
175  pollstatus = poll(&pollin, 1, 5);
176  if (pollstatus == 1) {
177  //kdDebug(5100) << "Status for polling pin[1]: " << pollin.revents << endl;
178  if (pollin.revents & POLLERR) {
179  kdDebug(5100) << "PGP seems to have hung up" << endl;
180  break;
181  }
182  else if (pollin.revents & POLLOUT) {
183  // search end of next line
184  if ((len2 = input.find('\n', i)) == -1)
185  len2 = input_length - i;
186  else
187  len2 = len2 - i + 1;
188 
189  //kdDebug(5100) << "Trying to write " << len2 << " bytes to pin[1] ..." << endl;
190  len2 = write(pin[1], input.data() + i, len2);
191  //kdDebug(5100) << "Wrote " << len2 << " bytes to pin[1] ..." << endl;
192  }
193  }
194  else if (!pollstatus) {
195  //kdDebug(5100) << "Timeout while polling pin[1]: "
196  // << pollin.revents << endl;
197  }
198  else if (pollstatus == -1) {
199  kdDebug(5100) << "Error while polling pin[1]: "
200  << pollin.revents << endl;
201  }
202 
203  if (pout[0] >= 0) {
204  do {
205  // check if there is data to read from pout[0]
206  //kdDebug(5100) << "Polling pout[0]..." << endl;
207  pollstatus = poll(&pollout, 1, 0);
208  if (pollstatus == 1) {
209  //kdDebug(5100) << "Status for polling pout[0]: " << pollout.revents << endl;
210  if (pollout.revents & POLLIN) {
211  //kdDebug(5100) << "Trying to read " << 1024 << " bytes from pout[0]" << endl;
212  if ((len = read(pout[0],str,1024))>0) {
213  //kdDebug(5100) << "Read " << len << " bytes from pout[0]" << endl;
214  str[len] ='\0';
215  output += str;
216  }
217  else
218  break;
219  }
220  }
221  else if (pollstatus == -1) {
222  kdDebug(5100) << "Error while polling pout[0]: "
223  << pollout.revents << endl;
224  }
225  } while ((pollstatus == 1) && (pollout.revents & POLLIN));
226  }
227 
228  if (perr[0] >= 0) {
229  do {
230  // check if there is data to read from perr[0]
231  //kdDebug(5100) << "Polling perr[0]..." << endl;
232  pollstatus = poll(&pollerr, 1, 0);
233  if (pollstatus == 1) {
234  //kdDebug(5100) << "Status for polling perr[0]: " << pollerr.revents << endl;
235  if (pollerr.revents & POLLIN) {
236  //kdDebug(5100) << "Trying to read " << 1024 << " bytes from perr[0]" << endl;
237  if ((len = read(perr[0],str,1024))>0) {
238  //kdDebug(5100) << "Read " << len << " bytes from perr[0]" << endl;
239  str[len] ='\0';
240  error += str;
241  }
242  else
243  break;
244  }
245  }
246  else if (pollstatus == -1) {
247  kdDebug(5100) << "Error while polling perr[0]: "
248  << pollerr.revents << endl;
249  }
250  } while ((pollstatus == 1) && (pollerr.revents & POLLIN));
251  }
252 
253  // abort writing to PGP if PGP hung up
254  if ((pollstatus == 1) &&
255  ((pollout.revents & POLLHUP) || (pollerr.revents & POLLHUP))) {
256  kdDebug(5100) << "PGP hung up" << endl;
257  break;
258  }
259  }
260  }
261  else { // if input.isEmpty()
262  if (write(pin[1], "\n", 1) < 0) {
263  // An error occurred
264  // FIXME
265  printf("Something went wrong in libkpgp/kpgpbase.cpp\n");
266  }
267  }
268  //kdDebug(5100) << "All input was written to pin[1]" << endl;
269  }
270  close(pin[1]);
271 
272  pid_t waitpidRetVal;
273 
274  do {
275  //kdDebug(5100) << "Checking if PGP is still running..." << endl;
276  childExiStatus = 0;
277  waitpidRetVal = waitpid(child_pid, &childExiStatus, WNOHANG);
278  //kdDebug(5100) << "waitpid returned " << waitpidRetVal << endl;
279  if (pout[0] >= 0) {
280  do {
281  // check if there is data to read from pout[0]
282  //kdDebug(5100) << "Polling pout[0]..." << endl;
283  pollstatus = poll(&pollout, 1, 0);
284  if (pollstatus == 1) {
285  //kdDebug(5100) << "Status for polling pout[0]: " << pollout.revents << endl;
286  if (pollout.revents & POLLIN) {
287  //kdDebug(5100) << "Trying to read " << 1024 << " bytes from pout[0]" << endl;
288  if ((len = read(pout[0],str,1024))>0) {
289  //kdDebug(5100) << "Read " << len << " bytes from pout[0]" << endl;
290  str[len] ='\0';
291  output += str;
292  } else {
293  /*
294  * Apparently, on NetBSD when the child dies, the pipe begins
295  * receiving empty data packets *before* waitpid() has signaled
296  * that the child has died. Also, notice that this happens
297  * without any error bit being set in pollfd.revents (is this a
298  * NetBSD bug??? ). Notice that these anomalous packets exist
299  * according to poll(), but have length 0 according to read().
300  * Thus, kde can remain stuck inside this loop.
301  *
302  * A solution to this problem is to get out of the inner loop
303  * when read() returns <=0. In this way, kde has another chance
304  * to call waitpid() to check if the child has died -- and this
305  * time the call should succeed.
306  *
307  * Setting POLLHUP in pollfd.revents is not necessary, but I just
308  * like the idea of signaling that something strange has
309  * happened.
310  */
311  pollout.revents |= POLLHUP;
312  break;
313  }
314  }
315  }
316  else if (pollstatus == -1) {
317  kdDebug(5100) << "Error while polling pout[0]: "
318  << pollout.revents << endl;
319  }
320  } while ((pollstatus == 1) && (pollout.revents & POLLIN));
321  }
322 
323  if (perr[0] >= 0) {
324  do {
325  // check if there is data to read from perr[0]
326  //kdDebug(5100) << "Polling perr[0]..." << endl;
327  pollstatus = poll(&pollerr, 1, 0);
328  if (pollstatus == 1) {
329  //kdDebug(5100) << "Status for polling perr[0]: " << pollerr.revents << endl;
330  if (pollerr.revents & POLLIN) {
331  //kdDebug(5100) << "Trying to read " << 1024 << " bytes from perr[0]" << endl;
332  if ((len = read(perr[0],str,1024))>0) {
333  //kdDebug(5100) << "Read " << len << " bytes from perr[0]" << endl;
334  str[len] ='\0';
335  error += str;
336  } else {
337  /*
338  * Apparently, on NetBSD when the child dies, the pipe begins
339  * receiving empty data packets *before* waitpid() has signaled
340  * that the child has died. Also, notice that this happens
341  * without any error bit being set in pollfd.revents (is this a
342  * NetBSD bug??? ). Notice that these anomalous packets exist
343  * according to poll(), but have length 0 according to read().
344  * Thus, kde can remain stuck inside this loop.
345  *
346  * A solution to this problem is to get out of the inner loop
347  * when read() returns <=0. In this way, kde has another chance
348  * to call waitpid() to check if the child has died -- and this
349  * time the call should succeed.
350  *
351  * Setting POLLHUP in pollfd.revents is not necessary, but I just
352  * like the idea of signaling that something strange has
353  * happened.
354  */
355  pollerr.revents |= POLLHUP;
356  break;
357  }
358  }
359  }
360  else if (pollstatus == -1) {
361  kdDebug(5100) << "Error while polling perr[0]: "
362  << pollerr.revents << endl;
363  }
364  } while ((pollstatus == 1) && (pollerr.revents & POLLIN));
365  }
366  } while (waitpidRetVal == 0);
367 
368  close(pout[0]);
369  close(perr[0]);
370 
371  unsetenv("PGPPASSFD");
372  if (!passphrase.isEmpty())
373  close(ppass[0]);
374 
375  // Did the child exit normally?
376  if (WIFEXITED(childExiStatus) != 0) {
377  // Get the return code of the child
378  childExiStatus = WEXITSTATUS(childExiStatus);
379  kdDebug(5100) << "PGP exited with exit status " << childExiStatus
380  << endl;
381  }
382  else {
383  childExiStatus = -1;
384  kdDebug(5100) << "PGP exited abnormally!" << endl;
385  }
386 
387  //Uncomment these lines for testing only! Doing so will decrease security!
388  //kdDebug(5100) << "pgp output = " << TQString(output) << endl;
389  //kdDebug(5100) << "pgp error = " << error << endl;
390 
391  /* Make the information visible, so that a user can
392  * get to know what's going on during the pgp calls.
393  */
394  kdDebug(5100) << error << endl;
395 
396  return childExiStatus;
397 }
398 
399 
400 int
401 Base::runGpg( const char *cmd, const TQString &passphrase, bool onlyReadFromGnuPG )
402 {
403  /* the pipe ppass is used for to pass the password to
404  * pgp. passing the password together with the normal input through
405  * stdin doesn't seem to work as expected (at least for pgp5.0)
406  */
407  char str[1025] = "\0";
408  int pin[2], pout[2], perr[2], ppass[2];
409  int len, len2;
410  FILE *pass;
411  pid_t child_pid;
412  int childExiStatus;
413  char gpgcmd[1024] = "\0";
414  struct pollfd poller[3];
415  int num_pollers = 0;
416  const int STD_OUT = 0;
417  const int STD_ERR = 1;
418  const int STD_IN = 2;
419  int pollstatus;
420 
421  if (!passphrase.isEmpty())
422  {
423  if (pipe(ppass) < 0) {
424  // An error occurred
425  // FIXME
426  printf("Something went wrong in libkpgp/kpgpbase.cpp\n");
427  }
428 
429  pass = fdopen(ppass[1], "w");
430  TQCString pass2 = passphrase.local8Bit();
431  fwrite(pass2, sizeof(char), pass2.length(), pass);
432  fwrite("\n", sizeof(char), 1, pass);
433  fclose(pass);
434  close(ppass[1]);
435 
436  //Uncomment these lines for testing only! Doing so will decrease security!
437  //kdDebug(5100) << "pass = " << passphrase << endl;
438  }
439 
440  //Uncomment these lines for testing only! Doing so will decrease security!
441  //kdDebug(5100) << "pgp cmd = " << cmd << endl;
442  //kdDebug(5100) << "pgp input = " << TQString(input)
443  // << "input length = " << input.length() << endl;
444 
445  error = "";
446  output = "";
447 
448  if (pipe(pin) < 0) {
449  // An error occurred
450  // FIXME
451  printf("Something went wrong in libkpgp/kpgpbase.cpp\n");
452  }
453  if (pipe(pout) < 0) {
454  // An error occurred
455  // FIXME
456  printf("Something went wrong in libkpgp/kpgpbase.cpp\n");
457  }
458  if (pipe(perr) < 0) {
459  // An error occurred
460  // FIXME
461  printf("Something went wrong in libkpgp/kpgpbase.cpp\n");
462  }
463 
464  if (!passphrase.isEmpty()) {
465  if( mVersion >= "1.0.7" ) {
466  // GnuPG >= 1.0.7 supports the gpg-agent, so we look for it.
467  if( 0 == getenv("GPG_AGENT_INFO") ) {
468  // gpg-agent not found, so we tell gpg not to use the agent
469  snprintf( gpgcmd, 1023,
470  "LANGUAGE=C gpg --no-use-agent --passphrase-fd %d %s",
471  ppass[0], cmd );
472  }
473  else {
474  // gpg-agent seems to be running, so we tell gpg to use the agent
475  snprintf( gpgcmd, 1023,
476  "LANGUAGE=C gpg --use-agent %s",
477  cmd );
478  }
479  }
480  else {
481  // GnuPG < 1.0.7 doesn't know anything about the gpg-agent
482  snprintf( gpgcmd, 1023,
483  "LANGUAGE=C gpg --passphrase-fd %d %s",
484  ppass[0], cmd );
485  }
486  }
487  else {
488  snprintf(gpgcmd, 1023, "LANGUAGE=C gpg %s",cmd);
489  }
490 
491  TQApplication::flushX();
492  if(!(child_pid = fork()))
493  {
494  /*We're the child.*/
495  close(pin[1]);
496  dup2(pin[0], 0);
497  close(pin[0]);
498 
499  close(pout[0]);
500  dup2(pout[1], 1);
501  close(pout[1]);
502 
503  close(perr[0]);
504  dup2(perr[1], 2);
505  close(perr[1]);
506 
507  //#warning FIXME: there has to be a better way to do this
508  /* this is nasty nasty nasty (but it works) */
509  if (!passphrase.isEmpty()) {
510  if( mVersion >= "1.0.7" ) {
511  // GnuPG >= 1.0.7 supports the gpg-agent, so we look for it.
512  if( 0 == getenv("GPG_AGENT_INFO") ) {
513  // gpg-agent not found, so we tell gpg not to use the agent
514  snprintf( gpgcmd, 1023,
515  "LANGUAGE=C gpg --no-use-agent --passphrase-fd %d %s",
516  ppass[0], cmd );
517  }
518  else {
519  // gpg-agent seems to be running, so we tell gpg to use the agent
520  snprintf( gpgcmd, 1023,
521  "LANGUAGE=C gpg --use-agent %s",
522  cmd );
523  }
524  }
525  else {
526  // GnuPG < 1.0.7 doesn't know anything about the gpg-agent
527  snprintf( gpgcmd, 1023,
528  "LANGUAGE=C gpg --passphrase-fd %d %s",
529  ppass[0], cmd );
530  }
531  }
532  else {
533  snprintf(gpgcmd, 1023, "LANGUAGE=C gpg %s",cmd);
534  }
535 
536  kdDebug(5100) << "pgp cmd = " << gpgcmd << endl;
537 
538  execl("/bin/sh", "sh", "-c", gpgcmd, (void *)0);
539  _exit(127);
540  }
541 
542  // Only get here if we're the parent.
543 
544  close(pin[0]);
545  close(pout[1]);
546  close(perr[1]);
547 
548  // poll for "There is data to read."
549  poller[STD_OUT].fd = pout[0];
550  poller[STD_OUT].events = POLLIN;
551  poller[STD_ERR].fd = perr[0];
552  poller[STD_ERR].events = POLLIN;
553  num_pollers = 2;
554 
555  if (!onlyReadFromGnuPG) {
556  // poll for "Writing now will not block."
557  poller[STD_IN].fd = pin[1];
558  poller[STD_IN].events = POLLOUT;
559  num_pollers = 3;
560  } else {
561  close (pin[1]);
562  pin[1] = -1;
563  }
564 
565  pid_t waitpidRetVal;
566  unsigned int input_pos = 0;
567  uint input_length = input.length();
568 
569  do {
570  //kdDebug(5100) << "Checking if GnuPG is still running..." << endl;
571  childExiStatus = 0;
572  waitpidRetVal = waitpid(child_pid, &childExiStatus, WNOHANG);
573  //kdDebug(5100) << "waitpid returned " << waitpidRetVal << endl;
574  do {
575  // poll the pipes
576  pollstatus = poll(poller, num_pollers, 10);
577  if( 0 < pollstatus ) {
578  // Check stdout.
579  if (poller[STD_OUT].revents & POLLIN) {
580  //kdDebug(5100) << "Trying to read " << 1024 << " bytes from pout[0]" << endl;
581  if ((len = read(pout[0],str,1024))>0) {
582  //kdDebug(5100) << "Read " << len << " bytes from pout[0]" << endl;
583  str[len] ='\0';
584  output += str;
585  }
586  else {
587  // FreeBSD/NetBSD workaround
588  //
589  // Apparently, on Free/NetBSD when the child dies, the pipe begins
590  // receiving empty data packets *before* waitpid() has signaled
591  // that the child has died. Also, notice that this happens
592  // without any error bit being set in pollfd.revents (is this a
593  // Free/NetBSD bug??? ). Notice that these anomalous packets exist
594  // according to poll(), but have length 0 according to read().
595  // Thus, we can remain stuck inside this loop.
596  //
597  // A solution to this problem is to get out of the inner loop
598  // when read() returns <=0. In this way, we have another chance
599  // to call waitpid() to check if the child has died -- and this
600  // time the call should succeed.
601  //
602  // Set POLLHUP in pollfd.revents to signal that something strange
603  // has happened and disable polling of stdout.
604  poller[STD_OUT].revents |= POLLHUP;
605  poller[STD_OUT].events = 0;
606  }
607  } else if (poller[STD_OUT].revents & POLLHUP) {
608  // disable polling of stdout
609  poller[STD_OUT].events = 0;
610  }
611 
612  // Check stderr.
613  if (poller[STD_ERR].revents & POLLIN) {
614  //kdDebug(5100) << "Trying to read " << 1024 << " bytes from perr[0]" << endl;
615  if ((len = read(poller[STD_ERR].fd,str,1024))>0) {
616  //kdDebug(5100) << "Read " << len << " bytes from perr[0]" << endl;
617  str[len] ='\0';
618  error += str;
619  }
620  else {
621  // FreeBSD/NetBSD workaround (for details see above)
622  poller[STD_ERR].revents |= POLLHUP;
623  poller[STD_ERR].events = 0;
624  }
625  } else if (poller[STD_ERR].revents & POLLHUP) {
626  // disable polling of stderr
627  poller[STD_ERR].events = 0;
628  }
629 
630  if (num_pollers > 2) {
631  if (poller[STD_IN].revents & ( POLLERR | POLLHUP ) ) {
632  kdDebug(5100) << "GnuPG seems to have hung up" << endl;
633  close (pin[1]);
634  pin[1] = -1;
635  --num_pollers;
636  }
637  else if (poller[STD_IN].revents & POLLOUT) {
638  if (!input.isEmpty()) {
639  // search end of next line
640  if ((len2 = input.find('\n', input_pos)) == -1)
641  len2 = input_length - input_pos;
642  else
643  len2 = len2 - input_pos + 1;
644 
645  //kdDebug(5100) << "Trying to write " << len2 << " bytes to pin[1] ..." << endl;
646  len2 = write(pin[1], input.data() + input_pos, len2 );
647  //kdDebug(5100) << "Wrote " << len2 << " bytes to pin[1] ..." << endl;
648  input_pos += len2;
649 
650  // We are done.
651  if (input_pos >= input_length) {
652  //kdDebug(5100) << "All input was written to pin[1]" << endl;
653  close (pin[1]);
654  pin[1] = -1;
655  --num_pollers;
656  }
657  }
658  else { // if input.isEmpty()
659  if (write(pin[1], "\n", 1) < 0) {
660  // An error occurred
661  // FIXME
662  printf("Something went wrong in libkpgp/kpgpbase.cpp\n");
663  }
664  //kdDebug(5100) << "All input was written to pin[1]" << endl;
665  close (pin[1]);
666  pin[1] = -1;
667  --num_pollers;
668  }
669  }
670  }
671  }
672  } while ( (pollstatus > 0) && ( (num_pollers > 2)
673  || (poller[STD_OUT].events != 0)
674  || (poller[STD_ERR].events != 0) ) );
675 
676  if (pollstatus == -1) {
677  kdDebug(5100) << "GnuPG poll failed, errno: " << errno << endl;
678  }
679 
680  } while(waitpidRetVal == 0);
681 
682  if( 0 <= pin[1] )
683  close (pin[1]);
684  close(pout[0]);
685  close(perr[0]);
686 
687  if (!passphrase.isEmpty())
688  close(ppass[0]);
689 
690  // Did the child exit normally?
691  if (WIFEXITED(childExiStatus) != 0) {
692  // Get the return code of the child
693  childExiStatus = WEXITSTATUS(childExiStatus);
694  kdDebug(5100) << "GnuPG exited with exit status " << childExiStatus
695  << endl;
696  }
697  else {
698  childExiStatus = -1;
699  kdDebug(5100) << "GnuPG exited abnormally!" << endl;
700  }
701 
702  //Uncomment these lines for testing only! Doing so will decrease security!
703  //kdDebug(5100) << "gpg stdout:\n" << TQString(output) << endl;
704 
705  // Make the information visible, so that a user can
706  // get to know what's going on during the gpg calls.
707  kdDebug(5100) << "gpg stderr:\n" << error << endl;
708 
709  return childExiStatus;
710 }
711 
712 
713 TQCString
714 Base::addUserId()
715 {
716  TQCString cmd;
717  TQCString pgpUser = Module::getKpgp()->user();
718 
719  if(!pgpUser.isEmpty())
720  {
721  cmd += " -u 0x";
722  cmd += pgpUser;
723  return cmd;
724  }
725  return TQCString();
726 }
727 
728 
729 } // namespace Kpgp