+ if (FileGPG != File)
+ {
+ execvp(gpgvpath.c_str(), (char **) &Args[0]);
+ ioprintf(std::cerr, "Couldn't execute %s to check %s", Args[0], File.c_str());
+ exit(EINTERNAL);
+ }
+ else
+ {
+//#define UNLINK_EXIT(X) exit(X)
+#define UNLINK_EXIT(X) unlink(sig);unlink(data);exit(X)
+
+ // for clear-signed files we have created tempfiles we have to clean up
+ // and we do an additional check, so fork yet another time …
+ pid_t pid = ExecFork();
+ if(pid < 0) {
+ ioprintf(std::cerr, "Fork failed for %s to check %s", Args[0], File.c_str());
+ UNLINK_EXIT(EINTERNAL);
+ }
+ if(pid == 0)
+ {
+ if (statusfd != -1)
+ dup2(fd[1], statusfd);
+ execvp(gpgvpath.c_str(), (char **) &Args[0]);
+ ioprintf(std::cerr, "Couldn't execute %s to check %s", Args[0], File.c_str());
+ UNLINK_EXIT(EINTERNAL);
+ }
+
+ // Wait and collect the error code - taken from WaitPid as we need the exact Status
+ int Status;
+ while (waitpid(pid,&Status,0) != pid)
+ {
+ if (errno == EINTR)
+ continue;
+ ioprintf(std::cerr, _("Waited for %s but it wasn't there"), "gpgv");
+ UNLINK_EXIT(EINTERNAL);
+ }
+
+ // check if it exit'ed normally …
+ if (WIFEXITED(Status) == false)
+ {
+ ioprintf(std::cerr, _("Sub-process %s exited unexpectedly"), "gpgv");
+ UNLINK_EXIT(EINTERNAL);
+ }
+
+ // … and with a good exit code
+ if (WEXITSTATUS(Status) != 0)
+ {
+ ioprintf(std::cerr, _("Sub-process %s returned an error code (%u)"), "gpgv", WEXITSTATUS(Status));
+ UNLINK_EXIT(WEXITSTATUS(Status));
+ }
+
+ /* looks like its fine. Our caller will check the status fd,
+ but we construct a good-known clear-signed file without garbage
+ and other non-sense. In a perfect world, we get the same file,
+ but empty lines, trailing whitespaces and stuff makes it inperfect … */
+ if (RecombineToClearSignedFile(File, dataFd, dataHeader, sigFd) == false)
+ {
+ _error->DumpErrors(std::cerr);
+ UNLINK_EXIT(EINTERNAL);
+ }
+
+ // everything fine, we have a clean file now!
+ UNLINK_EXIT(0);
+#undef UNLINK_EXIT
+ }
+ exit(EINTERNAL); // unreachable safe-guard
+}
+ /*}}}*/
+// RecombineToClearSignedFile - combine data/signature to message /*{{{*/
+bool RecombineToClearSignedFile(std::string const &OutFile, int const ContentFile,
+ std::vector<std::string> const &ContentHeader, int const SignatureFile)
+{
+ FILE *clean_file = fopen(OutFile.c_str(), "w");
+ fputs("-----BEGIN PGP SIGNED MESSAGE-----\n", clean_file);
+ for (std::vector<std::string>::const_iterator h = ContentHeader.begin(); h != ContentHeader.end(); ++h)
+ fprintf(clean_file, "%s\n", h->c_str());
+ fputs("\n", clean_file);
+
+ FILE *data_file = fdopen(ContentFile, "r");
+ FILE *sig_file = fdopen(SignatureFile, "r");
+ if (data_file == NULL || sig_file == NULL)
+ return _error->Error("Couldn't open splitfiles to recombine them into %s", OutFile.c_str());
+ char *buf = NULL;
+ size_t buf_size = 0;
+ while (getline(&buf, &buf_size, data_file) != -1)
+ fputs(buf, clean_file);
+ fclose(data_file);
+ fputs("\n", clean_file);
+ while (getline(&buf, &buf_size, sig_file) != -1)
+ fputs(buf, clean_file);
+ fclose(sig_file);
+ fclose(clean_file);
+ return true;