Set the initial focus to the recipients editor.
[kdepim.git] / libkpgp / kpgpbase.cpp
blobc305a0efbbfb74a9043e5c77d74dcf9e212c95cf
1 /*
2 kpgpbase.cpp
4 Copyright (C) 2001,2002 the KPGP authors
5 See file AUTHORS.kpgp for details
7 This file is part of KPGP, the KDE PGP/GnuPG support library.
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.
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
19 #include <config-libkpgp.h> /* HAVE_SYS_POLL_H */
21 #include "kpgpbase.h"
22 #include "kpgp.h"
23 #include "kpgpblock.h"
25 #include <kdebug.h>
26 #include <kdefakes.h> /* setenv, unsetenv */
28 #include <QApplication>
29 #include <QByteArray>
31 #include <stdlib.h> /* setenv, unsetenv */
32 #include <unistd.h> /* pipe, close, fork, dup2, execl, _exit, write, read */
33 #include <errno.h>
35 #ifdef HAVE_SYS_POLL_H
36 #include <sys/poll.h> /* poll, etc. */
37 #endif
39 #include <sys/types.h> /* pid_t */
40 #include <sys/wait.h> /* waitpid */
42 namespace Kpgp {
44 Base::Base()
45 : input(), output(), error(), errMsg(), status(OK)
50 Base::~Base()
55 void
56 Base::clear()
58 input = QByteArray();
59 output = QByteArray();
60 error = QByteArray();
61 errMsg.clear();
62 status = OK;
66 int
67 Base::run( const char *cmd, const char *passphrase, bool onlyReadFromPGP )
69 #ifdef HAVE_SYS_POLL_H
70 /* the pipe ppass is used for to pass the password to
71 * pgp. passing the password together with the normal input through
72 * stdin doesn't seem to work as expected (at least for pgp5.0)
74 char str[1025] = "\0";
75 int pin[2], pout[2], perr[2], ppass[2];
76 int len, len2;
77 FILE *pass;
78 pid_t child_pid;
79 int childExitStatus;
80 struct pollfd pollin, pollout, pollerr;
81 int pollstatus;
83 if(passphrase)
85 pipe(ppass);
87 pass = fdopen(ppass[1], "w");
88 fwrite(passphrase, sizeof(char), strlen(passphrase), pass);
89 fwrite("\n", sizeof(char), 1, pass);
90 fclose(pass);
91 close(ppass[1]);
93 // tell pgp which fd to use for the passphrase
94 QString tmp;
95 tmp.sprintf("%d",ppass[0]);
96 ::setenv("PGPPASSFD",tmp.toUtf8()/*.data()*/,1);
98 //Uncomment these lines for testing only! Doing so will decrease security!
99 //kDebug( 5326 ) <<"pgp PGPPASSFD =" << tmp;
100 //kDebug( 5326 ) <<"pgp pass =" << passphrase;
102 else
103 ::unsetenv("PGPPASSFD");
105 //Uncomment these lines for testing only! Doing so will decrease security!
106 kDebug( 5326 ) <<"pgp cmd =" << cmd;
107 //kDebug( 5326 ) <<"pgp input =" << QString(input)
108 // << "input length =" << input.length();
110 error = "";
111 output = "";
113 pipe(pin);
114 pipe(pout);
115 pipe(perr);
117 QApplication::flush();
118 if(!(child_pid = fork()))
120 /*We're the child.*/
121 close(pin[1]);
122 dup2(pin[0], 0);
123 close(pin[0]);
125 close(pout[0]);
126 dup2(pout[1], 1);
127 close(pout[1]);
129 close(perr[0]);
130 dup2(perr[1], 2);
131 close(perr[1]);
133 execl("/bin/sh", "sh", "-c", cmd, (void *)0);
134 _exit(127);
137 /*Only get here if we're the parent.*/
138 close(pin[0]);
139 close(pout[1]);
140 close(perr[1]);
142 // poll for "There is data to read."
143 pollout.fd = pout[0];
144 pollout.events = POLLIN;
145 pollout.revents = 0; // init with 0, just in case
146 pollerr.fd = perr[0];
147 pollerr.events = POLLIN;
148 pollerr.revents = 0; // init with 0, just in case
150 // poll for "Writing now will not block."
151 pollin.fd = pin[1];
152 pollin.events = POLLOUT;
153 pollin.revents = 0; // init with 0, just in case
155 if (!onlyReadFromPGP) {
156 if (!input.isEmpty()) {
157 // write to pin[1] one line after the other to prevent dead lock
158 int input_length = input.length();
159 for (int i=0; i<input_length; i+=len2) {
160 len2 = 0;
162 // check if writing now to pin[1] will not block (5 ms timeout)
163 //kDebug( 5326 ) <<"Polling pin[1]...";
164 pollstatus = poll(&pollin, 1, 5);
165 if (pollstatus == 1) {
166 //kDebug( 5326 ) <<"Status for polling pin[1]:" << pollin.revents;
167 if (pollin.revents & POLLERR) {
168 kDebug( 5326 ) <<"PGP seems to have hung up";
169 break;
171 else if (pollin.revents & POLLOUT) {
172 // search end of next line
173 if ((len2 = input.indexOf('\n', i)) == -1)
174 len2 = input_length - i;
175 else
176 len2 = len2 - i + 1;
178 //kDebug( 5326 ) <<"Trying to write" << len2 <<" bytes to pin[1] ...";
179 len2 = write(pin[1], input.data() + i, len2);
180 //kDebug( 5326 ) <<"Wrote" << len2 <<" bytes to pin[1] ...";
183 else if (!pollstatus) {
184 //kDebug( 5326 ) <<"Timeout while polling pin[1]:"
185 // << pollin.revents;
187 else if (pollstatus == -1) {
188 kDebug( 5326 ) <<"Error while polling pin[1]:"
189 << pollin.revents;
192 if (pout[0] >= 0) {
193 do {
194 // check if there is data to read from pout[0]
195 //kDebug( 5326 ) <<"Polling pout[0]...";
196 pollstatus = poll(&pollout, 1, 0);
197 if (pollstatus == 1) {
198 //kDebug( 5326 ) <<"Status for polling pout[0]:" << pollout.revents;
199 if (pollout.revents & POLLIN) {
200 //kDebug( 5326 ) <<"Trying to read" << 1024 <<" bytes from pout[0]";
201 if ((len = read(pout[0],str,1024))>0) {
202 //kDebug( 5326 ) <<"Read" << len <<" bytes from pout[0]";
203 str[len] ='\0';
204 output += str;
206 else
207 break;
210 else if (pollstatus == -1) {
211 kDebug( 5326 ) <<"Error while polling pout[0]:"
212 << pollout.revents;
214 } while ((pollstatus == 1) && (pollout.revents & POLLIN));
217 if (perr[0] >= 0) {
218 do {
219 // check if there is data to read from perr[0]
220 //kDebug( 5326 ) <<"Polling perr[0]...";
221 pollstatus = poll(&pollerr, 1, 0);
222 if (pollstatus == 1) {
223 //kDebug( 5326 ) <<"Status for polling perr[0]:" << pollerr.revents;
224 if (pollerr.revents & POLLIN) {
225 //kDebug( 5326 ) <<"Trying to read" << 1024 <<" bytes from perr[0]";
226 if ((len = read(perr[0],str,1024))>0) {
227 //kDebug( 5326 ) <<"Read" << len <<" bytes from perr[0]";
228 str[len] ='\0';
229 error += str;
231 else
232 break;
235 else if (pollstatus == -1) {
236 kDebug( 5326 ) <<"Error while polling perr[0]:"
237 << pollerr.revents;
239 } while ((pollstatus == 1) && (pollerr.revents & POLLIN));
242 // abort writing to PGP if PGP hung up
243 if ((pollstatus == 1) &&
244 ((pollout.revents & POLLHUP) || (pollerr.revents & POLLHUP))) {
245 kDebug( 5326 ) <<"PGP hung up";
246 break;
250 else // if input.isEmpty()
251 write(pin[1], "\n", 1);
252 //kDebug( 5326 ) <<"All input was written to pin[1]";
254 close(pin[1]);
256 pid_t waitpidRetVal;
258 do {
259 //kDebug( 5326 ) <<"Checking if PGP is still running...";
260 childExitStatus = 0;
261 waitpidRetVal = waitpid(child_pid, &childExitStatus, WNOHANG);
262 //kDebug( 5326 ) <<"waitpid returned" << waitpidRetVal;
263 if (pout[0] >= 0) {
264 do {
265 // check if there is data to read from pout[0]
266 //kDebug( 5326 ) <<"Polling pout[0]...";
267 pollstatus = poll(&pollout, 1, 0);
268 if (pollstatus == 1) {
269 //kDebug( 5326 ) <<"Status for polling pout[0]:" << pollout.revents;
270 if (pollout.revents & POLLIN) {
271 //kDebug( 5326 ) <<"Trying to read" << 1024 <<" bytes from pout[0]";
272 if ((len = read(pout[0],str,1024))>0) {
273 //kDebug( 5326 ) <<"Read" << len <<" bytes from pout[0]";
274 str[len] ='\0';
275 output += str;
276 } else {
278 * Apparently, on NetBSD when the child dies, the pipe begins
279 * receiving empty data packets *before* waitpid() has signaled
280 * that the child has died. Also, notice that this happens
281 * without any error bit being set in pollfd.revents (is this a
282 * NetBSD bug??? ). Notice that these anomalous packets exist
283 * according to poll(), but have length 0 according to read().
284 * Thus, kde can remain stuck inside this loop.
286 * A solution to this problem is to get out of the inner loop
287 * when read() returns <=0. In this way, kde has another chance
288 * to call waitpid() to check if the child has died -- and this
289 * time the call should succeed.
291 * Setting POLLHUP in pollfd.revents is not necessary, but I just
292 * like the idea of signaling that something strange has
293 * happened.
295 pollout.revents |= POLLHUP;
296 break;
300 else if (pollstatus == -1) {
301 kDebug( 5326 ) <<"Error while polling pout[0]:"
302 << pollout.revents;
304 } while ((pollstatus == 1) && (pollout.revents & POLLIN));
307 if (perr[0] >= 0) {
308 do {
309 // check if there is data to read from perr[0]
310 //kDebug( 5326 ) <<"Polling perr[0]...";
311 pollstatus = poll(&pollerr, 1, 0);
312 if (pollstatus == 1) {
313 //kDebug( 5326 ) <<"Status for polling perr[0]:" << pollerr.revents;
314 if (pollerr.revents & POLLIN) {
315 //kDebug( 5326 ) <<"Trying to read" << 1024 <<" bytes from perr[0]";
316 if ((len = read(perr[0],str,1024))>0) {
317 //kDebug( 5326 ) <<"Read" << len <<" bytes from perr[0]";
318 str[len] ='\0';
319 error += str;
320 } else {
322 * Apparently, on NetBSD when the child dies, the pipe begins
323 * receiving empty data packets *before* waitpid() has signaled
324 * that the child has died. Also, notice that this happens
325 * without any error bit being set in pollfd.revents (is this a
326 * NetBSD bug??? ). Notice that these anomalous packets exist
327 * according to poll(), but have length 0 according to read().
328 * Thus, kde can remain stuck inside this loop.
330 * A solution to this problem is to get out of the inner loop
331 * when read() returns <=0. In this way, kde has another chance
332 * to call waitpid() to check if the child has died -- and this
333 * time the call should succeed.
335 * Setting POLLHUP in pollfd.revents is not necessary, but I just
336 * like the idea of signaling that something strange has
337 * happened.
339 pollerr.revents |= POLLHUP;
340 break;
344 else if (pollstatus == -1) {
345 kDebug( 5326 ) <<"Error while polling perr[0]:"
346 << pollerr.revents;
348 } while ((pollstatus == 1) && (pollerr.revents & POLLIN));
350 } while (waitpidRetVal == 0);
352 close(pout[0]);
353 close(perr[0]);
355 unsetenv("PGPPASSFD");
356 if(passphrase)
357 close(ppass[0]);
359 // Did the child exit normally?
360 if (WIFEXITED(childExitStatus) != 0) {
361 // Get the return code of the child
362 childExitStatus = WEXITSTATUS(childExitStatus);
363 kDebug( 5326 ) <<"PGP exited with exit status" << childExitStatus;
365 else {
366 childExitStatus = -1;
367 kDebug( 5326 ) <<"PGP exited abnormally!";
370 //Uncomment these lines for testing only! Doing so will decrease security!
371 //kDebug( 5326 ) <<"pgp output =" << QString(output);
372 //kDebug( 5326 ) <<"pgp error =" << error;
374 /* Make the information visible, so that a user can
375 * get to know what's going on during the pgp calls.
377 kDebug( 5326 ) << error;
379 return childExitStatus;
380 #else // HAVE_SYS_POLL_H
381 #ifdef __GNUC__
382 #warning WIN32 libkpgp: PGP support not ported to win32!
383 #endif
384 return 1;
385 #endif
390 Base::runGpg( const char *cmd, const char *passphrase, bool onlyReadFromGnuPG )
392 #ifdef HAVE_SYS_POLL_H
393 /* the pipe ppass is used for to pass the password to
394 * pgp. passing the password together with the normal input through
395 * stdin doesn't seem to work as expected (at least for pgp5.0)
397 char str[1025] = "\0";
398 int pin[2], pout[2], perr[2], ppass[2];
399 int len, len2;
400 FILE *pass;
401 pid_t child_pid;
402 int childExitStatus;
403 char gpgcmd[1024] = "\0";
404 struct pollfd poller[3];
405 int num_pollers = 0;
406 const int STD_OUT = 0;
407 const int STD_ERR = 1;
408 const int STD_IN = 2;
409 int pollstatus;
411 if(passphrase)
413 pipe(ppass);
415 pass = fdopen(ppass[1], "w");
416 fwrite(passphrase, sizeof(char), strlen(passphrase), pass);
417 fwrite("\n", sizeof(char), 1, pass);
418 fclose(pass);
419 close(ppass[1]);
421 //Uncomment these lines for testing only! Doing so will decrease security!
422 //kDebug( 5326 ) <<"pass =" << passphrase;
425 //Uncomment these lines for testing only! Doing so will decrease security!
426 //kDebug( 5326 ) <<"pgp cmd =" << cmd;
427 //kDebug( 5326 ) <<"pgp input =" << QString(input)
428 // << "input length =" << input.length();
430 error = "";
431 output = "";
433 pipe(pin);
434 pipe(pout);
435 pipe(perr);
437 if( passphrase ) {
438 if( mVersion >= "1.0.7" ) {
439 // GnuPG >= 1.0.7 supports the gpg-agent, so we look for it.
440 if( 0 == getenv("GPG_AGENT_INFO") ) {
441 // gpg-agent not found, so we tell gpg not to use the agent
442 snprintf( gpgcmd, 1023,
443 "LANGUAGE=C gpg --no-use-agent --passphrase-fd %d %s",
444 ppass[0], cmd );
446 else {
447 // gpg-agent seems to be running, so we tell gpg to use the agent
448 snprintf( gpgcmd, 1023,
449 "LANGUAGE=C gpg --use-agent %s",
450 cmd );
453 else {
454 // GnuPG < 1.0.7 doesn't know anything about the gpg-agent
455 snprintf( gpgcmd, 1023,
456 "LANGUAGE=C gpg --passphrase-fd %d %s",
457 ppass[0], cmd );
460 else {
461 snprintf(gpgcmd, 1023, "LANGUAGE=C gpg %s",cmd);
464 QApplication::flush();
465 if(!(child_pid = fork()))
467 /*We're the child.*/
468 close(pin[1]);
469 dup2(pin[0], 0);
470 close(pin[0]);
472 close(pout[0]);
473 dup2(pout[1], 1);
474 close(pout[1]);
476 close(perr[0]);
477 dup2(perr[1], 2);
478 close(perr[1]);
480 //#warning FIXME: there has to be a better way to do this
481 /* this is nasty nasty nasty (but it works) */
482 if( passphrase ) {
483 if( mVersion >= "1.0.7" ) {
484 // GnuPG >= 1.0.7 supports the gpg-agent, so we look for it.
485 if( 0 == getenv("GPG_AGENT_INFO") ) {
486 // gpg-agent not found, so we tell gpg not to use the agent
487 snprintf( gpgcmd, 1023,
488 "LANGUAGE=C gpg --no-use-agent --passphrase-fd %d %s",
489 ppass[0], cmd );
491 else {
492 // gpg-agent seems to be running, so we tell gpg to use the agent
493 snprintf( gpgcmd, 1023,
494 "LANGUAGE=C gpg --use-agent %s",
495 cmd );
498 else {
499 // GnuPG < 1.0.7 doesn't know anything about the gpg-agent
500 snprintf( gpgcmd, 1023,
501 "LANGUAGE=C gpg --passphrase-fd %d %s",
502 ppass[0], cmd );
505 else {
506 snprintf(gpgcmd, 1023, "LANGUAGE=C gpg %s",cmd);
509 kDebug( 5326 ) <<"pgp cmd =" << gpgcmd;
511 execl("/bin/sh", "sh", "-c", gpgcmd, (void *)0);
512 _exit(127);
515 // Only get here if we're the parent.
517 close(pin[0]);
518 close(pout[1]);
519 close(perr[1]);
521 // poll for "There is data to read."
522 poller[STD_OUT].fd = pout[0];
523 poller[STD_OUT].events = POLLIN;
524 poller[STD_ERR].fd = perr[0];
525 poller[STD_ERR].events = POLLIN;
526 num_pollers = 2;
528 if (!onlyReadFromGnuPG) {
529 // poll for "Writing now will not block."
530 poller[STD_IN].fd = pin[1];
531 poller[STD_IN].events = POLLOUT;
532 num_pollers = 3;
533 } else {
534 close (pin[1]);
535 pin[1] = -1;
538 pid_t waitpidRetVal;
539 int input_pos = 0;
540 int input_length = input.length();
542 do {
543 //kDebug( 5326 ) <<"Checking if GnuPG is still running...";
544 childExitStatus = 0;
545 waitpidRetVal = waitpid(child_pid, &childExitStatus, WNOHANG);
546 //kDebug( 5326 ) <<"waitpid returned" << waitpidRetVal;
547 do {
548 // poll the pipes
549 pollstatus = poll(poller, num_pollers, 10);
550 if( 0 < pollstatus ) {
551 // Check stdout.
552 if (poller[STD_OUT].revents & POLLIN) {
553 //kDebug( 5326 ) <<"Trying to read" << 1024 <<" bytes from pout[0]";
554 if ((len = read(pout[0],str,1024))>0) {
555 //kDebug( 5326 ) <<"Read" << len <<" bytes from pout[0]";
556 str[len] ='\0';
557 output += str;
559 else {
560 // FreeBSD/NetBSD workaround
562 // Apparently, on Free/NetBSD when the child dies, the pipe begins
563 // receiving empty data packets *before* waitpid() has signaled
564 // that the child has died. Also, notice that this happens
565 // without any error bit being set in pollfd.revents (is this a
566 // Free/NetBSD bug??? ). Notice that these anomalous packets exist
567 // according to poll(), but have length 0 according to read().
568 // Thus, we can remain stuck inside this loop.
570 // A solution to this problem is to get out of the inner loop
571 // when read() returns <=0. In this way, we have another chance
572 // to call waitpid() to check if the child has died -- and this
573 // time the call should succeed.
575 // Set POLLHUP in pollfd.revents to signal that something strange
576 // has happened and disable polling of stdout.
577 poller[STD_OUT].revents |= POLLHUP;
578 poller[STD_OUT].events = 0;
580 } else if (poller[STD_OUT].revents & POLLHUP) {
581 // disable polling of stdout
582 poller[STD_OUT].events = 0;
585 // Check stderr.
586 if (poller[STD_ERR].revents & POLLIN) {
587 //kDebug( 5326 ) <<"Trying to read" << 1024 <<" bytes from perr[0]";
588 if ((len = read(poller[STD_ERR].fd,str,1024))>0) {
589 //kDebug( 5326 ) <<"Read" << len <<" bytes from perr[0]";
590 str[len] ='\0';
591 error += str;
593 else {
594 // FreeBSD/NetBSD workaround (for details see above)
595 poller[STD_ERR].revents |= POLLHUP;
596 poller[STD_ERR].events = 0;
598 } else if (poller[STD_ERR].revents & POLLHUP) {
599 // disable polling of stderr
600 poller[STD_ERR].events = 0;
603 if (num_pollers > 2) {
604 if (poller[STD_IN].revents & ( POLLERR | POLLHUP ) ) {
605 kDebug( 5326 ) <<"GnuPG seems to have hung up";
606 close (pin[1]);
607 pin[1] = -1;
608 --num_pollers;
610 else if (poller[STD_IN].revents & POLLOUT) {
611 if (!input.isEmpty()) {
612 // search end of next line
613 if ((len2 = input.indexOf('\n', input_pos)) == -1)
614 len2 = input_length - input_pos;
615 else
616 len2 = len2 - input_pos + 1;
618 //kDebug( 5326 ) <<"Trying to write" << len2 <<" bytes to pin[1] ...";
619 len2 = write(pin[1], input.data() + input_pos, len2 );
620 //kDebug( 5326 ) <<"Wrote" << len2 <<" bytes to pin[1] ...";
621 input_pos += len2;
623 // We are done.
624 if (input_pos >= input_length) {
625 //kDebug( 5326 ) <<"All input was written to pin[1]";
626 close (pin[1]);
627 pin[1] = -1;
628 --num_pollers;
631 else { // if input.isEmpty()
632 write(pin[1], "\n", 1);
633 //kDebug( 5326 ) <<"All input was written to pin[1]";
634 close (pin[1]);
635 pin[1] = -1;
636 --num_pollers;
641 } while ( (pollstatus > 0) && ( (num_pollers > 2)
642 || (poller[STD_OUT].events != 0)
643 || (poller[STD_ERR].events != 0) ) );
645 if (pollstatus == -1) {
646 kDebug( 5326 ) <<"GnuPG poll failed, errno:" << errno;
649 } while(waitpidRetVal == 0);
651 if( 0 <= pin[1] )
652 close (pin[1]);
653 close(pout[0]);
654 close(perr[0]);
656 if(passphrase)
657 close(ppass[0]);
659 // Did the child exit normally?
660 if (WIFEXITED(childExitStatus) != 0) {
661 // Get the return code of the child
662 childExitStatus = WEXITSTATUS(childExitStatus);
663 kDebug( 5326 ) <<"GnuPG exited with exit status" << childExitStatus;
665 else {
666 childExitStatus = -1;
667 kDebug( 5326 ) <<"GnuPG exited abnormally!";
670 //Uncomment these lines for testing only! Doing so will decrease security!
671 //kDebug( 5326 ) <<"gpg stdout:" << QString(output);
673 // Make the information visible, so that a user can
674 // get to know what's going on during the gpg calls.
675 kDebug( 5326 ) <<"gpg stderr:" << error;
677 return childExitStatus;
678 #else // HAVE_SYS_POLL_H
679 #ifdef __GNUC__
680 #warning WIN32 libkpgp: GnuPG support not ported to WIN32!
681 #endif
682 return 1;
683 #endif
687 QByteArray
688 Base::addUserId()
690 QByteArray cmd;
691 QByteArray pgpUser = Module::getKpgp()->user();
693 if(!pgpUser.isEmpty())
695 cmd += " -u 0x";
696 cmd += pgpUser;
697 return cmd;
699 return QByteArray();
703 } // namespace Kpgp