guncat-2.02.00/build0000775000175000017500000000702014747430322013154 0ustar frankfrank#!/usr/bin/icmake -t. #define LOGENV "GUNCAT" #include "icmconf" list g_log; string g_logPath = getenv(LOGENV)[1], g_logMark, // unique-marker for g_log entries g_cwd = chdir(""); // initial working directory, ends in / int g_echo = ON; // MODIFIED, existing variable int g_installing; // set to 1 by install. int g_lognr; // unique-marker number counter for g_log entries #include "icmake/setopt" #include "icmake/cuteoln" #include "icmake/backtick" #include "icmake/run" #include "icmake/md" #include "icmake/findall" #include "icmake/loginstall" #include "icmake/logzip" #include "icmake/logfile" #include "icmake/uninstall" #include "icmake/pathfile" #include "icmake/special" #include "icmake/clean" #include "icmake/manpage" #include "icmake/install" #include "icmake/gitlab" void main(int argc, list argv) { string option; int idx; for (idx = listlen(argv); idx--; ) { if (argv[idx] == "-q") { g_echo = OFF; argv -= (list)"-q"; } } echo(g_echo); option = argv[1]; if (option == "clean") clean(0); if (option == "distclean") clean(1); if (option == "install") install(argv[2], argv[3]); if (option == "uninstall") uninstall(argv[2]); if (option != "") special(); if (option == "gitlab") gitlab(); if (option == "man") manpage(); if ("VERSION" younger "version/version.h") system("touch version/version.h main.cc usage.cc"); if (option == "library") { system("icmbuild library"); exit(0); } if (option == "program") { system("icmbuild program"); exit(0); } if (option == "xref") { system("icmbuild program"); run("oxref -fxs tmp/lib" LIBRARY ".a > " PROGRAM ".xref"); exit(0); } printf("Usage: build [-q -P] what\n" "Where\n" " [-q]: run quietly, do not show executed commands\n" "`what' is one of:\n" " clean - clean up remnants of previous " "compilations\n" " distclean - clean + fully remove tmp/\n" " library - build " PROGRAM "'s library\n" " man - build the man-page (requires " "Yodl)\n" " program - build " PROGRAM "\n" " xref [strip] - same a `program', also builds " "xref file\n" " using oxref\n" " install selection [base] - to install the software in the \n" " locations defined in the INSTALL.im file,\n" " optionally below base\n" " selection can be\n" " x, to install all components,\n" " or a combination of:\n" " b (binary program),\n" " d (documentation),\n" " m (man-pages)\n" " uninstall logfile - remove files and empty directories listed\n" " in the file 'logfile'\n" " gitlab - prepare gitlab's web-pages update\n" " (internal use only)\n" "\n" ); exit(0); } guncat-2.02.00/changelog0000664000175000017500000001124714762336412014011 0ustar frankfrankguncat (2.02.00) * Requires bobcat >= 6.07.00 and icmake >= 13.00,03. * Changed ArgConfig::None into ArgConfig::NoArg. * Building uses a SPCH and multi-compilation. * The compiler is called using the value of the ${ICMAKE_CPPSTD} environment variable specifying the C++ standard to use. -- Frank B. Brokken Sun, 12 Jan 2025 20:50:02 +0100 guncat (2.01.00) * GPG sends its output to cout, instead of to a pipe * Added option --gpg-messages to specify where GPG should send its messages to (instead of to the std. error stream) * Added option --dots writes a dot (.) to the standard error stream after processing each block of 8192 input lines * Modified option --passphrase: discontinued the short option (-p), and requires a separate file containing the passphrase to use. * Removed the options --less, --pipe and --write, as all output is sent the the standard output stream -- Frank B. Brokken Fri, 14 Oct 2022 14:16:22 +0200 guncat (2.00.03) * Ready for libbobcat6 * Added 'c++std' defining the c++ standard to use for compilation. Compilation commands also use -Werror -- Frank B. Brokken Sun, 11 Sep 2022 11:18:05 +0200 guncat (2.00.02) * Removed -q from guncat's build script -- Frank B. Brokken Sat, 26 Jun 2021 15:03:45 +0200 guncat (2.00.01) * Man-page cosmetics -- Frank B. Brokken Fri, 25 Dec 2020 10:24:46 +0100 guncat (2.00.00) * Removed options --errors-OK, --locate-keys and --gpg-no-batch * Before calling gpg the encountered PGP MESSAGE section is inspected for correctness while it's written to a temporary file. If the PGP MESSAGE section contains errors gpg is not called. * Added option --no-errors terminating guncat if a PGP MESSAGE section contains errors or if gpg returns a non-zero exit value. -- Frank B. Brokken Wed, 23 Dec 2020 21:41:17 +0100 guncat (1.02.01) * Bobcat 5.04.00's Pipe class defines a close member closing both ends of the pipe. This member is now called from GPipe's destructor. * Fixed some typos in the man-page -- Frank B. Brokken Sat, 07 Mar 2020 14:45:58 +0100 guncat (1.02.00) * New options: errors-OK, time-limit; disused options: gpg-no-batch, locate-keys * Refined the Decryptor's handlePGP / insertPGPsection implementations * The passphrase is requested at the start of the program to avoid interference with output to the std. output stream * Updated options passed to gpg to gpg version 2.1, see the description of the --passphrase-fd option in the gpg(1) manual page. * Using compilation option --std=c++2a * Updated usage and man-page -- Frank B. Brokken Sun, 11 Nov 2018 16:03:27 +0100 guncat (1.01.03) * Migrated from Github to Gitlab. * Updated the C++ standard to use to c++17. * Added header-precompilation to icmconf. * Removed comment from CLASSES -- Frank B. Brokken Thu, 21 Jun 2018 19:18:26 +0530 guncat (1.01.02) * Updated the build script to icmake 8.00.04. -- Frank B. Brokken Sat, 12 Dec 2015 15:12:24 +0100 guncat (1.01.01) * Kevin Brodsky observed that the installation scripts used 'chdir' rather than 'cd'. Fixed in this release. * Kevin Brodsky also observed that the combined size of all precompiled headers might exceed some disks capacities. The option -P was added to the ./build script to prevent the use of precompiled headers. -- Frank B. Brokken Mon, 05 Oct 2015 21:25:25 +0200 guncat (1.01.00) * Update to version 1.00.00 after being operational for over one year without issues. * Added 'build uninstall'. * Updated 'INSTALL' * Guncat depends on libbobcat >= 4.00.00 (see 'required') * Standardized the (de)installation procedures -- Frank B. Brokken Sun, 04 Oct 2015 10:32:32 +0200 guncat (0.92.00) * The GPG passphrase is now requested only once. It is only requested again if a provided passphrase was incorrect. -- Frank B. Brokken Tue, 27 May 2014 15:57:34 +0200 guncat (0.91.00) * The GPG passphrase is read from /dev/tty, and not from the std. input stream (cin) anymore -- Frank B. Brokken Sun, 04 May 2014 10:55:53 +0200 guncat (0.90.00) * Initial completion of the program and man-page. -- Frank B. Brokken Sat, 03 May 2014 11:48:43 +0200 guncat (0.00.00) * Preparing the sourceforge archive, and finalizing release 0.00.00 -- Frank B. Brokken Wed, 30 Apr 2014 15:10:18 +0200 guncat-2.02.00/CLASSES0000664000175000017500000000007114762336412013150 0ustar frankfrankglobals options gpghandler pgpsection decryptor guncat guncat-2.02.00/decryptor/0000775000175000017500000000000014762336412014145 5ustar frankfrankguncat-2.02.00/decryptor/setverbose.cc0000664000175000017500000000112614762336412016635 0ustar frankfrank#include "decryptor.ih" void Decryptor::setVerbose() { string const &verbose = d_options.verbose(); if (not verbose.empty()) // if a msgname was specified: { if (verbose == "-") g_verbose = &cerr; // write to cerr else { d_fverbose = unique_ptr{ // or open a file new ofstream{ Exception::factory(verbose) } }; g_verbose = d_fverbose.get(); } } } guncat-2.02.00/decryptor/clearfiles.cc0000664000175000017500000000027414762336412016570 0ustar frankfrank#include "decryptor.ih" void Decryptor::clearFiles() const { error_code ec; resize_file(d_pgpMessage->fileName(), 0, ec); d_pgpMessage->clear(); d_pgpMessage->seekp(0); } guncat-2.02.00/decryptor/error.cc0000664000175000017500000000022214762336412015601 0ustar frankfrank#include "decryptor.ih" // static void Decryptor::error(int ret, string const &msg) { throw Exception{} << msg << ", gpg returns " << ret; } guncat-2.02.00/decryptor/decryptor.ih0000664000175000017500000000051714762336412016505 0ustar frankfrank#include "decryptor.h" #include "../xerr/xerr.ih" #include #include #include #include "../globals/globals.h" #include "../options/options.h" #include "../pgpsection/pgpsection.h" #include "../gpghandler/gpghandler.h" using namespace std; using namespace FBB; using namespace filesystem; guncat-2.02.00/decryptor/decryptor.h0000664000175000017500000000164614762336412016340 0ustar frankfrank#ifndef INCLUDED_DECRYPTOR_ #define INCLUDED_DECRYPTOR_ #include #include #include class Options; class GPGHandler; class PGPSection; #include class Decryptor { Options const &d_options; GPGHandler &d_gpgHandler; std::unique_ptr d_fverbose; std::unique_ptr d_pgpMessage; std::unique_ptr d_decrypted; std::string d_decryptedName; public: Decryptor(GPGHandler &gpgHandler); // -----BEGIN PGP MESSAGE----- // was just read by void process(std::istream &in); // Guncat::process private: void clearFiles() const; void decrypt(PGPSection const &pgpSection) const; void setVerbose(); static void error(int ret, std::string const &msg); }; #endif guncat-2.02.00/decryptor/icmconf0000664000175000017500000000010014747430322015473 0ustar frankfrank#define LIBRARY "decryptor" #include "../icmconf.lib" guncat-2.02.00/decryptor/decryptor1.cc0000664000175000017500000000113214762336412016545 0ustar frankfrank#define XERR #include "decryptor.ih" Decryptor::Decryptor(GPGHandler &gpgHandler) : d_options(Options::instance()), d_gpgHandler(gpgHandler), d_pgpMessage(new TempStream) { setVerbose(); if (d_options.quotedPrintable()) // file to receive the decrypted d_gpgHandler.setDecryptedName("-"); // section ... else // ... if --quoted-printable is { // NOT requested d_decrypted.reset(new TempStream); d_gpgHandler.setDecryptedName(d_decrypted->fileName()); } } guncat-2.02.00/decryptor/process.cc0000664000175000017500000000205614762336412016135 0ustar frankfrank#define XERR #include "decryptor.ih" // in: current input file, at 'PGP MESSAGE' void Decryptor::process(istream &in) // , ostream &out) { xerr(""); // obtain the PGP MESSAGE PGPSection pgpSection{ in, *d_pgpMessage }; if (g_verbose) *g_verbose << fileInfo() << ": PGP HEADER" << endl; clearFiles(); // resize d_pgpMessage and // d_decrypted to 0-size // get the (complete) if (pgpSection.complete()) // PGP section { if (not d_options.pgpRanges()) // decrypt it unless only decrypt(pgpSection); // ranges are requested return; } // unless suppressed: if (not d_options.skipIncomplete()) // show the INcomplete cout << d_pgpMessage->rdbuf(); // PGP MESSAGE } guncat-2.02.00/decryptor/decrypt.cc0000664000175000017500000000163714762336412016135 0ustar frankfrank#include "decryptor.ih" void Decryptor::decrypt(PGPSection const &pgpSection) const { size_t attempt = 0; while (true) { d_pgpMessage->seekg(0); int ret; if ( ret = d_gpgHandler.process(d_pgpMessage->fileName()); ret == 0 ) break; if (attempt++ == 3) { auto [begin, end] = pgpSection.range(); string msg{ "In " + g_filename + " lines " + to_string(begin) + " to " + to_string(end) + ": cannot decrypt PGP section" }; if (not d_options.noErrors()) // allow unkown passphr. { *g_verbose << msg << endl; cout << msg << '\n'; break; } error(ret, msg); } d_gpgHandler.getPassphrase(attempt); } } guncat-2.02.00/documentation/0000775000175000017500000000000014747430322015001 5ustar frankfrankguncat-2.02.00/documentation/man/0000775000175000017500000000000014747430322015554 5ustar frankfrankguncat-2.02.00/documentation/man/guncat.yo0000664000175000017500000001703714747430322017416 0ustar frankfrankgagmacrowarning(server FILE) includefile(../../release.yo) htmlbodyopt(text)(#27408B) htmlbodyopt(bgcolor)(#FFFAF0) gagmacrowarning(guncat) mailto(f.b.brokken@rug.nl) DEFINEMACRO(lsoption)(3)(\ bf(--ARG1)=tt(ARG3) (bf(-ARG2))\ ) DEFINEMACRO(laoption)(2)(\ bf(--ARG1)=tt(ARG2)\ ) DEFINEMACRO(loption)(1)(\ bf(--ARG1)\ ) DEFINEMACRO(soption)(1)(\ (bf(-ARG1))\ ) DEFINEMACRO(u)(0)(bf(guncat)) DEFINEMACRO(U)(0)(bf(Guncat)) DEFINEMACRO(g)(0)(bf(gpg)) manpage(guncat)(1)(_CurYrs_)(guncat__CurVers_) (guncat - unencrypting file concatenation) manpagename(guncat)(catenates files, unencrypting pgp encrypted sections) manpagesynopsis() bf(guncat) [OPTIONS] tt([file(s)]) nl() [OPTIONS] - cf. section bf(OPTIONS)nl() [file+nop()(s)] - optional files to process (cf. section bf(INPUT FILE(S)))nl() manpagedescription() U() was designed to tackle a problem encountered with (partially) PGP encrypted files (which may exist in, e.g., mailboxes). Tools to process text-files (like bf(grep)(1), or bf(less)(1)) may be used to process those files, but those tools leave PGP encrypted sections inside such files as-is. As a consequence, browsing the `real' contents (i.e., clear-text sections and the unencrypted content of PGP encrypted sections) of those files is difficult. U() acts comparably to bf(cat), but unencrypts encrypted sections encountered in the files processed by u(), copying the unencrypted information to u()'s standard output stream, which may thereupon be processed by other tools. PGP/GPG encrypted sections are surrounded by the following markers: verb( -----BEGIN PGP MESSAGE----- ) and verb( -----END PGP MESSAGE----- ) When u() encounters such sections they are processed by g()(1). bf(Gpg) needs a passphrase to unencrypt such sections. If not already available (from bf(gpg-agent)(1)) the required passphrase is requested by u(), whereafter it is used by g(). When an incorrect passphrase is entered two additional attempts to provide the correct passphrase are allowed. If the third attempt also fails, u() terminates. While processing files u() may have to reposition their current file pointer locations. If repositioning is not supported u() terminated with an error message. manpagesection(RETURN VALUE) U() returns 0 to the operating system unless an error occurs (0 is also returned when information providing option (like em(--version) or em(--gpg-command)) are specified). 1 is returned if g() could not decrypt an encrypted section or when called without options or file(s) to process. manpagesection(INPUT FILE(S)) When no file arguments are provided input may be provided using standard input stream redirection. When option em(--passphrase) is specified the content of the first line of a specified file is used as the passphrase (see option em(--passphrase) below. Any other argument is considered a filename (path specifications are allowed) specifying a file to be processed (in sequence) by u(). If a file cannot be read or decrypted u() terminates with an error message. manpageoptions() In the following overview of options single letter options, when available, are listed between parentheses following their associated long-option alternatives. Single letter options require arguments if their long option alternatives require arguments as well. itemization( it() loption(dots) soption(d)nl() A dot (.)is written to the standard error stream after processing each block of 8192 input lines. This option is ignored when the tt(--pgp-ranges, --section-lines) or tt(--verbose) options are specified. it() loption(gpg-command)nl() Show the gpg command that would be used, and quit, returning 0. it() laoption(gpg-messages)(path) soption(m)nl() Path to the file receiving the messages written by the GPG program to its standard error stream. Use `stdout' to write the messages to the standard output stream, use `stderr' to write the messages to the standard error stream. If not specified the messages written by the GPG program are not shown. it() laoption(gpg-option)(option)nl() Add em(option) to g()'s call. If the option contains blanks, surround em(option) by single or double quotes. Option em(gpg-option) may repeatedly be specified. it() laoption(gpg-path)(path)nl() Path to the g() program (default: em(/usr/bin/gpg)) it() loption(help) soption(h)nl() Basic usage information is written to the standard output stream. it() loption(no-errors)nl() When this options is specified u() terminates g() returns a non-zero exit value. it() laoption(passphrase)(path)nl() By default u() obtains the passphrase to use by prompting the user to enter the passphrase. The passphrase may also be read from a separate file whose path is specified as argument to the tt(--passphrase) option. When the em(--passphrase) option is specified and the provided password is incorrect, u() terminates. it() loption(pgp-ranges) soption(r)nl() the lines-ranges of complete em(PGP MESSAGE) sections are reported. No additional output is produced. it() loption(quoted-printable) soption(q)nl() merely decrypt PGP messages, keeping their quoted-printable content (by default quoted-printable content like 'em(=3D)' is converted to ascii). it() loption(reduce-headers) soption(R)nl() When encountering mail headers (starting at lines beginning with `em(From )' and ending at the next empty line) only output the mail headers em(Cc:, Date:, From:, Subject:), and em(To:). it() loption(section-lines) soption(S)nl() In the output precede decrypted em(PGP MESSAGE) sections by their line numbers, using a format like verb( **************************** filename:43:104: PGP MESSAGE **************************** ) where the first number refers to the first line number of the PGP section and the second number refers to last line number of the PGP section it() loption(skip-incomplete) soption(s)nl() Incomple em(PGP MESSAGE) sections are ignored and are not outputted. By default the program's output also contain the lines of any incomplete em(PGP MESSAGE) sections that were encountered. it() lsoption(time-limit)(T)(seconds)nl() Option em(--time-limit) is used to specify the max. time in seconds that g() is allowed to run while decrypting a single encrypted section. By default no time limit is used. This option is useful when the file to process might contain errors in encrypted sections (like a missing em(END PGP MESSAGE) line). it() loption(tty-OK) soption(t)nl() Option em(--no-tty) is not specified when calling g(). By default it is specified. it() lsoption(verbose)(V)(path)nl() Path to where u() should write additional messages. Specify - to write the messages to the standard error stream. it() loption(version) (soption(v))nl() U()'s version number is written to the standard output stream, terminating u(), returning exit value 0. ) manpageseealso() bf(gpg)(1), bf(gpg-agent)(1), bf(grep)(1), bf(less)(1). manpagebugs() None reported manpagesection(COPYRIGHT) This is free software, distributed under the terms of the `GNU General Public License'. U() is available at em(https://fbb-git.gitlab.io/guncat/) manpageauthor() Frank B. Brokken (f.b.brokken@rug.nl). guncat-2.02.00/globals/0000775000175000017500000000000014762336636013565 5ustar frankfrankguncat-2.02.00/globals/data.cc0000664000175000017500000000032414747430322014772 0ustar frankfrank#include "globals.ih" size_t g_lineNr; string g_filename; string g_beginPGP{ "-----BEGIN PGP MESSAGE-----" }; string g_endPGP{ "-----END PGP MESSAGE-----" }; ostream *g_verbose = 0; // no messages if 0 guncat-2.02.00/globals/nextline.cc0000664000175000017500000000025014747430322015705 0ustar frankfrank#include "globals.ih" istream &nextline(istream &in, string &line) { if (getline(in, line)) { ++g_lineNr; (*g_dots)(); } return in; } guncat-2.02.00/globals/globals.ih0000664000175000017500000000023514747430322015520 0ustar frankfrank#include "globals.h" #include "../xerr/xerr.ih" #include #include #include extern void (*g_dots)(); using namespace std; guncat-2.02.00/globals/icmconf0000664000175000017500000000007614747430322015117 0ustar frankfrank#define LIBRARY "globals" #include "../icmconf.lib" guncat-2.02.00/globals/starred.cc0000664000175000017500000000045214747430322015527 0ustar frankfrank#include "globals.ih" void starred(//std::ostream &out, std::string const &msg) { cout << '\n' << setfill('*') << setw(msg.length()) << '*' << '\n' << msg << '\n' << setw(msg.length()) << '*' << '\n' << setfill(' ') << '\n'; } guncat-2.02.00/globals/fileinfo.cc0000664000175000017500000000020314747430322015650 0ustar frankfrank#include "globals.ih" #include string fileInfo() { return "In " + g_filename + ", line " + to_string(g_lineNr); } guncat-2.02.00/globals/dots.cc0000664000175000017500000000035514747430322015036 0ustar frankfrank#include "globals.ih" namespace { void noDots() {} void doDots() { if ((g_lineNr & ((1 << 13) - 1)) == 0) cerr.put('.'); } } void (*g_dots)() = noDots; void showDots() { g_dots = doDots; } guncat-2.02.00/globals/globals.h0000664000175000017500000000056714747430322015357 0ustar frankfrank#ifndef INCLUDED_GLOBALS_H_ #define INCLUDED_GLOBALS_H_ #include extern size_t g_lineNr; extern std::string g_filename; extern std::string g_beginPGP; extern std::string g_endPGP; extern std::ostream *g_verbose; std::string fileInfo(); std::istream &nextline(std::istream &in, std::string &line); void starred(std::string const &msg); void showDots(); #endif guncat-2.02.00/gpghandler/0000775000175000017500000000000014762336412014245 5ustar frankfrankguncat-2.02.00/gpghandler/parentprocess.cc0000664000175000017500000000106514762336412017446 0ustar frankfrank#define XERR #include "gpghandler.ih" void GPGHandler::parentProcess() { IFdStream childMessages(d_childMessages.readOnly(), 500); d_ret = waitForChild(); if (d_messages) *d_messages << childMessages.rdbuf(); if (d_ret == 0 and d_decryptedName != "-") { // xerr("processing IQuotedPrintable " << d_decryptedName); auto decrypted = Exception::factory(d_decryptedName); IQuotedPrintableBuf decode{ decrypted }; istream din(&decode); cout << din.rdbuf(); } } guncat-2.02.00/gpghandler/getpassphrase.cc0000664000175000017500000000145514762336412017432 0ustar frankfrank#define XERR #include "gpghandler.ih" namespace { size_t getCount = 0; } void GPGHandler::getPassphrase(size_t attempt) { if (d_passphraseRead) { if (++getCount > 1) throw Exception{} << "password read from file is incorrect"; return; } if (attempt > 1) cerr << "Incorrect passphrase.\n"; cerr << "Enter passphrase (empty line to skip): "; d_passphrase.clear(); struct termios ttySaved; int fd = echo(&ttySaved); // switch off echoing, fd to /dev/tty IFdStream in(fd); // get the passphrase from /dev/tty getline(in, d_passphrase); echo(&ttySaved, true); // restore the echoing state cerr << '\n'; if (d_passphrase.empty()) throw Exception{} << "no passphrase entered"; } guncat-2.02.00/gpghandler/data.cc0000664000175000017500000000011614762336412015463 0ustar frankfrank//#define XERR #include "gpghandler.ih" unsigned GPGHandler::s_nRetries = 0; guncat-2.02.00/gpghandler/gpghandler.ih0000664000175000017500000000101114762336412016673 0ustar frankfrank#include "gpghandler.h" #include "../xerr/xerr.ih" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../globals/globals.h" #include "../options/options.h" using namespace std; using namespace FBB; guncat-2.02.00/gpghandler/gpghandler.h0000664000175000017500000000265714762336412016543 0ustar frankfrank#ifndef INCLUDED_GPGHANDLER_ #define INCLUDED_GPGHANDLER_ #include #include #include class Options; class GPGHandler: public FBB::Fork { Options const &d_options; std::ostream *d_messages; bool d_passphraseRead; // passphrase read from file std::string d_passphrase; std::string d_gpgCommand; std::string d_filename; std::string d_decryptedName; // filename of the file to receive // the decrypted info FBB::Pipe d_childMessages; int d_ret; // return value of the gpg call static unsigned s_nRetries; // # times a pwd was requested public: GPGHandler(); void setDecryptedName(std::string const &filename); int process(std::string const &filename); void getPassphrase(size_t attempt); // get the passphrase (/dev/tty // or from file) private: std::string passphraseFd(FBB::Pipe &pipe) const; void resetPipe(); void childRedirections() override; void childProcess() override; void parentProcess() override; static int echo(struct termios *ttySaved, bool reset = false); }; inline void GPGHandler::setDecryptedName(std::string const &filename) { d_decryptedName = filename; } #endif guncat-2.02.00/gpghandler/passphrasefd.cc0000664000175000017500000000147214762336412017243 0ustar frankfrank#define XERR #include "gpghandler.ih" string GPGHandler::passphraseFd(Pipe &pipe) const { xerr("passphraseread: " << d_passphraseRead << ": " << d_passphrase); // specify the fd receiving the // passphrase string ret{ " --pinentry-mode loopback" " --passphrase-fd " + to_string(pipe.readFd()) + ' ' }; OFdStream pwd(pipe.writeFd()); // create an ostream for it // write the passphrase, which // will be read by gpg from the pwd << d_passphrase << endl; // pipe return ret; // return gpg's options } guncat-2.02.00/gpghandler/childprocess.cc0000664000175000017500000000107314762336412017237 0ustar frankfrank#define XERR #include "gpghandler.ih" void GPGHandler::childProcess() { Pipe pipe; // d_filename: file to decrypt xerr("CALLS " << d_gpgCommand << " and " << d_filename); if (d_filename.empty()) throw 0; Process gpg{ Process::DIRECT, Process::NO_PATH, d_gpgCommand + " --output " + d_decryptedName + passphraseFd(pipe) + " " + d_filename }; gpg.setTimeLimit(d_options.timeLimit()); // 0 -> no time limit gpg.start(); } guncat-2.02.00/gpghandler/icmconf0000664000175000017500000000010114762336412015576 0ustar frankfrank#define LIBRARY "gpghandler" #include "../icmconf.lib" guncat-2.02.00/gpghandler/echo.cc0000664000175000017500000000055414762336412015476 0ustar frankfrank#include "gpghandler.ih" // static int GPGHandler::echo(struct termios *ttySaved, bool reset) { int fd = open("/dev/tty", O_RDONLY); struct termios tty; tcgetattr(fd, &tty); if (reset) tty = *ttySaved; else { *ttySaved = tty; tty.c_lflag &= ~ECHO; } tcsetattr(fd, TCSANOW, &tty); return fd; } guncat-2.02.00/gpghandler/childredirections.cc0000664000175000017500000000020514762336412020247 0ustar frankfrank//#define XERR #include "gpghandler.ih" void GPGHandler::childRedirections() { d_childMessages.writtenBy(Redirector::STDERR); } guncat-2.02.00/gpghandler/process.cc0000664000175000017500000000055014762336412016232 0ustar frankfrank#define XERR #include "gpghandler.ih" // decryptor/process.cc allows repeated attempts int GPGHandler::process(string const &filename) { d_filename = filename; xerr("STARTS " << d_gpgCommand << " for " << d_filename); resetPipe(); fork(); xerr("LEAVING with " << d_ret); return d_ret; // this section is now completed } guncat-2.02.00/gpghandler/resetpipe.cc0000664000175000017500000000020514762336412016551 0ustar frankfrank//#define XERR #include "gpghandler.ih" void GPGHandler::resetPipe() { d_childMessages.close(); d_childMessages = Pipe{}; } guncat-2.02.00/gpghandler/gpghandler1.cc0000664000175000017500000000110414762336412016744 0ustar frankfrank#define XERR #include "gpghandler.ih" GPGHandler::GPGHandler() : d_options(Options::instance()), d_messages(d_options.gpgMessages()), d_gpgCommand(d_options.gpgPath() + d_options.gpgDecrypt()) { string const &path = d_options.passphrasePath(); if (d_passphraseRead = not path.empty(); d_passphraseRead) { auto pwdStream = Exception::factory(path); getline(pwdStream, d_passphrase); } // xerr("passphraseread: " << d_passphraseRead << ": " << d_passphrase); // xerr("Initial GPG command: " << d_gpgCommand); } guncat-2.02.00/guncat/0000775000175000017500000000000014762336412013413 5ustar frankfrankguncat-2.02.00/guncat/processcin.cc0000664000175000017500000000014514762336412016072 0ustar frankfrank#include "guncat.ih" void Guncat::processCin() { g_filename = "stdin"; process(cin); } guncat-2.02.00/guncat/data.cc0000664000175000017500000000032514762336412014633 0ustar frankfrank#include "guncat.ih" char const *const Guncat::s_accept[] = { "Cc: ", "Date: ", "From: ", "Subject: ", "To: " }; char const *const *const Guncat::s_acceptEnd = s_accept + size(s_accept); guncat-2.02.00/guncat/guncat.ih0000664000175000017500000000037114762336412015217 0ustar frankfrank#include "guncat.h" #include "../xerr/xerr.ih" #include #include #include #include #include "../globals/globals.h" #include "../options/options.h" using namespace std; using namespace FBB; guncat-2.02.00/guncat/run.cc0000664000175000017500000000020214762336412014520 0ustar frankfrank#include "guncat.ih" void Guncat::run() { if (d_gpgCommand) showGPGcommand(); else programArguments(); } guncat-2.02.00/guncat/guncat.h0000664000175000017500000000153614762336412015052 0ustar frankfrank#ifndef INCLUDED_GUNCAT_ #define INCLUDED_GUNCAT_ #include #include #include #include #include "../decryptor/decryptor.h" #include "../gpghandler/gpghandler.h" class Options; class Guncat { Options const &d_options; bool d_gpgCommand; bool d_pgpRanges; bool d_passphraseFirstLine; // handled in process() bool d_reduceHeaders; GPGHandler d_gpgHandler; Decryptor d_decryptor; static char const *const s_accept[]; static char const *const *const s_acceptEnd; public: Guncat(); void run(); private: void showGPGcommand() const; bool onlyCin(); void processCin(); void process(std::istream &in); void programArguments(); bool reduceHeaders(std::string const &line); }; #endif guncat-2.02.00/guncat/reduceheaders.cc0000664000175000017500000000066214747430322016527 0ustar frankfrank#define XERR #include "guncat.ih" bool Guncat::reduceHeaders(string const &line) { if (line.find_first_not_of(" \t") == string::npos) // no non-blank chars return false; if ( find_if(s_accept, s_acceptEnd, [&](char const *target) { return line.find(target) == 0; } ) != s_acceptEnd ) cout << line << '\n'; return true; } guncat-2.02.00/guncat/icmconf0000664000175000017500000000007514747430322014754 0ustar frankfrank#define LIBRARY "guncat" #include "../icmconf.lib" guncat-2.02.00/guncat/programarguments.cc0000664000175000017500000000050014762336412017312 0ustar frankfrank#include "guncat.ih" void Guncat::programArguments() { if (onlyCin()) return; Arg &arg = Arg::instance(); for (size_t idx = 0, end = arg.nArgs(); idx != end; ++idx) { g_filename = arg[idx]; ifstream in{ Exception::factory(g_filename) }; process(in); } } guncat-2.02.00/guncat/process.cc0000664000175000017500000000111414762336412015375 0ustar frankfrank#define XERR #include "guncat.ih" void Guncat::process(istream &in) { string line; g_lineNr = 0; bool reduce = false; while (nextline(in, line)) { if (line == g_beginPGP) { d_decryptor.process(in); // , d_out); continue; } if (d_pgpRanges) continue; if (not reduce and d_reduceHeaders and line.find("From ") == 0) reduce = true; if (reduce) reduce = reduceHeaders(line); else cout << line << '\n'; } cout.flush(); } guncat-2.02.00/guncat/guncat1.cc0000664000175000017500000000037714762336412015273 0ustar frankfrank#define XERR #include "guncat.ih" Guncat::Guncat() : d_options(Options::instance()), d_gpgCommand(d_options.gpgCommand()), d_pgpRanges(d_options.pgpRanges()), d_reduceHeaders(d_options.reduceHeaders()), d_decryptor(d_gpgHandler) {} guncat-2.02.00/guncat/showgpgcommand.cc0000664000175000017500000000031614757314726016747 0ustar frankfrank#include "guncat.ih" void Guncat::showGPGcommand() const { cout << d_options.gpgPath() << " --pinentry-mode loopback --passphrase-fd " << d_options.gpgDecrypt() << '\n'; } guncat-2.02.00/guncat/onlycin.cc0000664000175000017500000000154714762336412015404 0ustar frankfrank#include "guncat.ih" bool Guncat::onlyCin() { Arg &arg = Arg::instance(); switch (arg.nArgs()) { case 1: // 1 argument: if (arg[0] != "-"s) // if not - then its a filename break; [[fallthrough]]; case 0: // no or 1 argument: read stdin g_filename = "stdin"; process(cin); return true; default: // multiple args: may not contain - { auto begin = arg.argPointers(); auto end = begin + arg.nArgs(); auto iter = find(begin, end, "-"); delete[] begin; if (iter != end) throw Exception{} << "argument - cannot be mixed with filename arguments"; } break; } return false; } guncat-2.02.00/guncat.xref0000664000175000017500000002346514747430322014311 0ustar frankfrankoxref by Frank B. Brokken (f.b.brokken@rug.nl) oxref V2.00.03 2012-2022 CREATED Thu, 13 Oct 2022 14:49:33 +0000 CROSS REFERENCE FOR: -fxs tmp/libguncat.a ---------------------------------------------------------------------- CROSS REFERENCE LISTING: author Full name: Icmbuild::author Source: version.cc Used By: usage.cc: usage(std::__cxx11::basic_string, std::allocator > const&) childProcess() Full name: GPGHandler::childProcess() Source: childprocess.cc Used By: destructor.cc: GPGHandler::~GPGHandler() childRedirections() Full name: GPGHandler::childRedirections() Source: childredirections.cc Used By: destructor.cc: GPGHandler::~GPGHandler() clearFiles() const Full name: Decryptor::clearFiles() const Source: clearfiles.cc Used By: process.cc: Decryptor::process(std::istream&) complete() Full name: PGPSection::complete() Source: complete.cc Used By: process.cc: Decryptor::process(std::istream&) cxx11] Full name: g_beginPGP[abi:cxx11] Source: data.cc Used By: complete.cc: PGPSection::complete() process.cc: Guncat::process(std::istream&) cxx11] Full name: g_filename[abi:cxx11] Source: data.cc Used By: fileinfo.cc: fileInfo[abi:cxx11]() complete.cc: PGPSection::complete() verbose.cc: PGPSection::verbose(std::__cxx11::basic_string, std::allocator > const&) const error.cc: Decryptor::error(int, std::pair const&) onlycin.cc: Guncat::onlyCin() processcin.cc: Guncat::processCin() programarguments.cc: Guncat::programArguments() cxx11] Full name: g_endPGP[abi:cxx11] Source: data.cc Used By: endmessage.cc: PGPSection::endMessage() cxx11]() Full name: fileInfo[abi:cxx11]() Source: fileinfo.cc Used By: process.cc: Decryptor::process(std::istream&) cxx11](FBB::Pipe&) const Full name: GPGHandler::passphraseFd[abi:cxx11](FBB::Pipe&) const Source: passphrasefd.cc Used By: childprocess.cc: GPGHandler::childProcess() Decryptor(GPGHandler&) Full name: Decryptor::Decryptor(GPGHandler&) Source: decryptor1.cc Used By: guncat1.cc: Guncat::Guncat() echo(termios*, bool) Full name: GPGHandler::echo(termios*, bool) Source: echo.cc Used By: getpassphrase.cc: GPGHandler::getPassphrase() empty() Full name: PGPSection::empty() Source: empty.cc Used By: complete.cc: PGPSection::complete() endMessage() Full name: PGPSection::endMessage() Source: endmessage.cc Used By: complete.cc: PGPSection::complete() error(int, std::pair const&) Full name: Decryptor::error(int, std::pair const&) Source: error.cc Used By: process.cc: Decryptor::process(std::istream&) extraGPGoptions() Full name: Options::extraGPGoptions() Source: extragpgoptions.cc Used By: options1.cc: Options::Options() g_dots Full name: g_dots Source: dots.cc Used By: nextline.cc: nextline(std::istream&, std::__cxx11::basic_string, std::allocator >&) g_lineNr Full name: g_lineNr Source: data.cc Used By: fileinfo.cc: fileInfo[abi:cxx11]() nextline.cc: nextline(std::istream&, std::__cxx11::basic_string, std::allocator >&) complete.cc: PGPSection::complete() next.cc: PGPSection::next() verbose.cc: PGPSection::verbose(std::__cxx11::basic_string, std::allocator > const&) const process.cc: Guncat::process(std::istream&) dots.cc: GLOBALS dots.cc 1dots.o g_verbose Full name: g_verbose Source: data.cc Used By: verbose.cc: PGPSection::verbose(std::__cxx11::basic_string, std::allocator > const&) const process.cc: Decryptor::process(std::istream&) setverbose.cc: Decryptor::setVerbose() getPassphrase() Full name: GPGHandler::getPassphrase() Source: getpassphrase.cc Used By: process.cc: Decryptor::process(std::istream&) GPGHandler(bool) Full name: GPGHandler::GPGHandler(bool) Source: gpghandler1.cc Used By: guncat1.cc: Guncat::Guncat() instance() Full name: Options::instance() Source: instance.cc Used By: gpghandler1.cc: GPGHandler::GPGHandler(bool) pgpsection1.cc: PGPSection::PGPSection(std::istream&, FBB::TempStream&) decryptor1.cc: Decryptor::Decryptor(GPGHandler&) guncat1.cc: Guncat::Guncat() lastLine() Full name: PGPSection::lastLine() Source: lastline.cc Used By: complete.cc: PGPSection::complete() lines() Full name: PGPSection::lines() Source: lines.cc Used By: complete.cc: PGPSection::complete() next() Full name: PGPSection::next() Source: next.cc Used By: complete.cc: PGPSection::complete() empty.cc: PGPSection::empty() lastline.cc: PGPSection::lastLine() lines.cc: PGPSection::lines() nextLine() Full name: PGPSection::nextLine() Source: nextline.cc Used By: complete.cc: PGPSection::complete() empty.cc: PGPSection::empty() lastline.cc: PGPSection::lastLine() lines.cc: PGPSection::lines() nextline(std::istream&, std::__cxx11::basic_string, std::allocator >&) Full name: nextline(std::istream&, std::__cxx11::basic_string, std::allocator >&) Source: nextline.cc Used By: nextline.cc: PGPSection::nextLine() process.cc: Guncat::process(std::istream&) onlyCin() Full name: Guncat::onlyCin() Source: onlycin.cc Used By: programarguments.cc: Guncat::programArguments() Options() Full name: Options::Options() Source: options1.cc Used By: instance.cc: Options::instance() parentProcess() Full name: GPGHandler::parentProcess() Source: parentprocess.cc Used By: destructor.cc: GPGHandler::~GPGHandler() PGPSection(std::istream&, FBB::TempStream&) Full name: PGPSection::PGPSection(std::istream&, FBB::TempStream&) Source: pgpsection1.cc Used By: process.cc: Decryptor::process(std::istream&) process(std::__cxx11::basic_string, std::allocator > const&) Full name: GPGHandler::process(std::__cxx11::basic_string, std::allocator > const&) Source: process.cc Used By: process.cc: Decryptor::process(std::istream&) process(std::istream&) Full name: Decryptor::process(std::istream&) Source: process.cc Used By: process.cc: Guncat::process(std::istream&) process(std::istream&) Full name: Guncat::process(std::istream&) Source: process.cc Used By: onlycin.cc: Guncat::onlyCin() processcin.cc: Guncat::processCin() programarguments.cc: Guncat::programArguments() programArguments() Full name: Guncat::programArguments() Source: programarguments.cc Used By: run.cc: Guncat::run() reduceHeaders(std::__cxx11::basic_string, std::allocator > const&) Full name: Guncat::reduceHeaders(std::__cxx11::basic_string, std::allocator > const&) Source: reduceheaders.cc Used By: process.cc: Guncat::process(std::istream&) resetPipe() Full name: GPGHandler::resetPipe() Source: resetpipe.cc Used By: process.cc: GPGHandler::process(std::__cxx11::basic_string, std::allocator > const&) s_accept Full name: Guncat::s_accept Source: data.cc Used By: reduceheaders.cc: Guncat::reduceHeaders(std::__cxx11::basic_string, std::allocator > const&) s_acceptEnd Full name: Guncat::s_acceptEnd Source: data.cc Used By: reduceheaders.cc: Guncat::reduceHeaders(std::__cxx11::basic_string, std::allocator > const&) s_options Full name: Options::s_options Source: data.cc Used By: instance.cc: Options::instance() setGpgMessages() Full name: Options::setGpgMessages() Source: setgpgmessages.cc Used By: options1.cc: Options::Options() setVerbose() Full name: Decryptor::setVerbose() Source: setverbose.cc Used By: decryptor1.cc: Decryptor::Decryptor(GPGHandler&) showDots() Full name: showDots() Source: dots.cc Used By: options1.cc: Options::Options() showGPGcommand() const Full name: Guncat::showGPGcommand() const Source: showgpgcommand.cc Used By: run.cc: Guncat::run() starred(std::__cxx11::basic_string, std::allocator > const&) Full name: starred(std::__cxx11::basic_string, std::allocator > const&) Source: starred.cc Used By: complete.cc: PGPSection::complete() validChars() const Full name: PGPSection::validChars() const Source: validchars.cc Used By: lastline.cc: PGPSection::lastLine() lines.cc: PGPSection::lines() verbose(std::__cxx11::basic_string, std::allocator > const&) const Full name: PGPSection::verbose(std::__cxx11::basic_string, std::allocator > const&) const Source: verbose.cc Used By: complete.cc: PGPSection::complete() empty.cc: PGPSection::empty() endmessage.cc: PGPSection::endMessage() lastline.cc: PGPSection::lastLine() validchars.cc: PGPSection::validChars() const version Full name: Icmbuild::version Source: version.cc Used By: usage.cc: usage(std::__cxx11::basic_string, std::allocator > const&) years Full name: Icmbuild::years Source: version.cc Used By: usage.cc: usage(std::__cxx11::basic_string, std::allocator > const&) ~GPGHandler() Full name: GPGHandler::~GPGHandler() Source: destructor.cc Used By: guncat1.cc: Guncat::Guncat() guncat-2.02.00/handle.cc0000664000175000017500000000064614747430322013700 0ustar frankfrank#include "main.ih" int handle(exception_ptr ptr) try { rethrow_exception(ptr); } catch (int ret) // handle the known exceptions { return Arg::instance().option("hv") ? 0 : ret; } catch (exception const &exc) { cerr << "Error: " << exc.what() << '\n'; return 1; } catch (...) // and handle an unexpected exception { cerr << "unexpected exception\n"; return 1; } guncat-2.02.00/icmake/0000775000175000017500000000000014747430322013361 5ustar frankfrankguncat-2.02.00/icmake/setopt0000664000175000017500000000034114747430322014620 0ustar frankfrankstring setOpt(string install_im, string envvar) { list optvar; string ret; optvar = getenv(envvar); if (optvar[0] == "1") ret = optvar[1]; else ret = install_im; return ret; } guncat-2.02.00/icmake/manpage0000664000175000017500000000057514747430322014723 0ustar frankfrank#define MANPAGE "../../tmp/man/" ${PROGRAM} ".1" void manpage() { md("tmp/man tmp/manhtml"); chdir("documentation/man"); if (PROGRAM ".yo" younger MANPAGE || "release.yo" younger MANPAGE) { run("yodl2man -o " MANPAGE " " PROGRAM); run("yodl2html -o ../../tmp/manhtml/" PROGRAM ".1.html " PROGRAM); chdir("../.."); } exit(0); } guncat-2.02.00/icmake/findall0000664000175000017500000000123114747430322014712 0ustar frankfrank// assuming we're in g_cwd, all entries of type 'type' matching source/pattern // are returned w/o final \n list findAll(string type, string source, string pattern) { string cmd; list entries; list ret; int idx; chdir(source); cmd = "find ./ -mindepth 1 -maxdepth 1 -type " + type; if (pattern != "") pattern = "-name '" + pattern + "'"; entries = backtick(cmd + " " + pattern + " -printf \"%f\\n\""); idx = listlen(entries); if (idx > 0 && strlen(entries[0]) > 0) { for (idx = listlen(entries); idx--; ) ret += (list)cutEoln(entries[idx]); } chdir(g_cwd); return ret; } guncat-2.02.00/icmake/log0000775000175000017500000000063214747430322014071 0ustar frankfrank#!/bin/bash find tmp/install -type f -exec md5sum "{}" \; | sed 's|tmp/install|'$1'|' > $2 find tmp/install -type l -exec printf "link %s\n" "{}" \; | sed 's|tmp/install|'$1'|' >> $2 find tmp/install -type d -exec printf "dir %s\n" "{}" \; | sed 's|tmp/install|'$1'|' >> $2 guncat-2.02.00/icmake/adddir0000664000175000017500000000112514747430322014532 0ustar frankfranklist addDir(list dir, string entry) { list ret; int idx; int keep = 1; string elem; for (idx = listlen(dir); idx--; ) { elem = dir[idx]; if (strfind(entry, elem) != -1) // entry contains dir, ignore dir ret += (list)entry; else if (strfind(elem, entry) != -1) // dir contains entry { ret += (list)elem; keep = 0; } else // new unique entry, keep dir[idx] ret += (list)elem; } if (keep) ret += (list)entry; return ret; } guncat-2.02.00/icmake/pathfile0000664000175000017500000000055214747430322015102 0ustar frankfranklist path_file(string path) { list ret; int len; int idx; for (len = strlen(path), idx = len; idx--; ) { if (path[idx] == "/") { ret = (list)substr(path, 0, idx) + (list)substr(path, idx + 1, len); return ret; } } ret = (list)"" + (list)path; return ret; } guncat-2.02.00/icmake/clean0000664000175000017500000000044314747430322014367 0ustar frankfrankvoid clean(int dist) { run("rm -rf " "build-stamp configure-stamp " "options/SKEL " "tmp/*.o tmp/*-stamp " + "o */o release.yo tmp/lib*.a " ); if (dist) run("rm -rf spch tmp *.ih.gch */*.ih.gch"); exit(0); } guncat-2.02.00/icmake/uninstall0000664000175000017500000000045614747430322015322 0ustar frankfrankvoid uninstall(string logfile) { int idx; list entry; string dir; list line; if (!exists(logfile)) { printf("installation log file " + logfile + " not found\n"); exit(0); } run("icmake/remove " + logfile + " " + (string)g_echo); exit(0); } guncat-2.02.00/icmake/cuteoln0000664000175000017500000000023314747430322014753 0ustar frankfrankstring cutEoln(string text) { int len; len = strlen(text) - 1; if (text[len] == "\n") text = substr(text, 0, len); return text; } guncat-2.02.00/icmake/run0000664000175000017500000000015114747430322014105 0ustar frankfrankvoid run(string cmd) { if (g_echo == OFF) cmd += "> /dev/null 2>&1"; system(0, cmd); } guncat-2.02.00/icmake/md0000664000175000017500000000074014747430322013705 0ustar frankfrank// md: target should be a series of blank-delimited directories to be created // If an element is a whildcard, the directory will always be created, // using mkdir -p. // // uses: run() void md(string target) { int idx; list paths; string dir; if (!exists(target)) run("mkdir -p " + target); else if (((int)stat(target)[0] & S_IFDIR) == 0) { printf(target + " exists, but is not a directory\n"); exit(1); } } guncat-2.02.00/icmake/gitlab0000664000175000017500000000022114747430322014541 0ustar frankfrankvoid gitlab() { run("cp -r release.yo tmp/manhtml/guncat.1.html ../../wip"); run("cp changelog ../../wip/changelog.txt"); exit(0); } guncat-2.02.00/icmake/remove0000775000175000017500000000117014747430322014603 0ustar frankfrank#!/bin/bash g_echo=$2 rm_f() { [ $g_echo -ne 0 ] && echo rm $1 rm -f $1 } rm_dir() { [ $g_echo -ne 0 ] && echo rmdir $1 rmdir --ignore-fail-on-non-empty -p $1 } IFS=" " for line in `cat $1` do field1=`echo $line | awk '{printf $1}'` field2=`echo $line | awk '{printf $2}'` if [ $field1 == "link" ] ; then rm_f $field2 elif [ $field1 == "dir" ] ; then rm_dir $field2 elif [ -e "$field2" ] ; then if [ "$field1" != "`md5sum $field2 | awk '{printf $1}'`" ] ; then echo $field2 changed, not removed else rm_f $field2 fi fi done rm_f $1 guncat-2.02.00/icmake/backtick0000664000175000017500000000016014747430322015054 0ustar frankfranklist backtick(string arg) { list ret; echo(OFF); ret = `arg`; echo(g_echo); return ret; } guncat-2.02.00/icmake/install0000664000175000017500000000332414747430322014754 0ustar frankfrank void install(string request, string dest) { string target; int components = 0; list pathsplit; string base; base = "tmp/install/"; md(base); if (request == "x") components = 63; else { if (strfind(request, "b") != -1) components |= 2; if (strfind(request, "d") != -1) components |= 4; if (strfind(request, "m") != -1) components |= 8; } if (components & 2) { target = base + BINARY; pathsplit = path_file(target); printf(" installing the executable `", target, "'\n"); logFile("tmp/bin", "binary", pathsplit[0], pathsplit[1]); } if (components & (4 | 8)) { target = base + DOC "/"; if (components & 4) { printf(" installing the README and changelog files at `", target, "\n"); logZip("", "changelog README", target ); } if (components & 8) { printf(" installing the html-manual pages at `", target, "\n"); logInstall("tmp/manhtml", "", target); } } if (components & 8) { target = base + MAN "/"; printf(" installing the manual page below `", target, "'\n"); logZip("tmp/man", "guncat.1", target); } chdir(g_cwd); if (dest == "") dest = "/"; else md(dest); dest = cutEoln(backtick("realpath " + dest)[0]); if (g_logPath != "") backtick("icmake/log " + dest + " " + g_logPath); run("tar cf - -Ctmp/install . | tar xf - -C" + dest); printf("\n Installation completed\n"); exit(0); } guncat-2.02.00/icmake/logfile0000664000175000017500000000025714747430322014731 0ustar frankfrankvoid logFile(string srcdir, string src, string destdir, string dest) { chdir(g_cwd); md(destdir); run("cp " + srcdir + "/" + src + " " + destdir + "/" + dest); } guncat-2.02.00/icmake/loginstall0000664000175000017500000000156514747430322015463 0ustar frankfrank// source and dest, absolute or reachable from g_cwd, should exist. // files and links in source matching dest (if empty: all) are copied to dest // and are logged in g_log // Before they are logged, dest is created void logInstall(string src, string pattern, string dest) { list entries; int idx; chdir(g_cwd); md(dest); src += "/"; dest += "/"; if (listlen(makelist(O_DIR, src)) == 0) { printf("Warning: ", src, " not found: can't install ", src, pattern, " at ", dest, "\n"); return; } entries = findAll("f", src, pattern); for (idx = listlen(entries); idx--; ) run("cp " + src + entries[idx] + " " + dest); chdir(g_cwd); entries = findAll("l", src, pattern); for (idx = listlen(entries); idx--; ) run("cp " CPOPTS " " + src + entries[idx] + " " + dest); } guncat-2.02.00/icmake/special0000664000175000017500000000034114747430322014722 0ustar frankfrankvoid special() { if (! exists("release.yo") || "VERSION" newer "release.yo") run("gcc -E VERSION.h | grep -v '#' | sed 's/\\\"//g' > " "release.yo"); } guncat-2.02.00/icmake/logzip0000664000175000017500000000165614747430322014620 0ustar frankfrank// names may be a series of files in src, not a wildcard. // if it's empty then all files in src are used. // the files are gzipped and logged in dest. // src and dest do not have to end in / void logZip(string src, string names, string dest) { list files; int idx; string file; chdir(g_cwd); md(dest); dest += "/"; if (src != "") { if (listlen(makelist(O_DIR, src)) == 0) { printf("Warning: ", src, " not found: can't install ", src, names, " at ", dest, "\n"); return; } chdir(src); } if (names == "") files = makelist("*"); else files = strtok(names, " "); for (idx = listlen(files); idx--; ) { file = files[idx]; run("gzip -n -9 < " + file + " > " + file + ".gz"); } run("tar cf - *.gz | (cd " + g_cwd + "; cd " + dest + "; tar xf -)"); run("rm *.gz"); } guncat-2.02.00/icmconf0000664000175000017500000000105414762336412013473 0ustar frankfrank#include "INSTALL.im" #define MULTICOMP "jobs -q" #define SPCH "-u xerr/xerr.ih" #define ADD_LIBRARIES "bobcat" #define ADD_LIBRARY_PATHS "" #define LIBRARY "guncat" #define MAIN "main.cc" #define OBJ_EXT ".o" //#define REFRESH #define SHAREDREQ "" #define SOURCES "*.cc" #define TMP_DIR "tmp" #define USE_ALL "a" #define IH ".ih" #define USE_ECHO ON #define USE_VERSION #define DEFCOM "program" guncat-2.02.00/icmconf.lib0000664000175000017500000000073414747430322014242 0ustar frankfrank#define PRECOMP "-x c++-header" #define CLS #define SOURCES "*.cc" #define OBJ_EXT ".o" #define TMP_DIR "tmp" #define USE_ECHO ON #define IH ".ih" #define CXX "g++" #define CXXFLAGS " --std=c++2a -Wall -O2 " \ " -fdiagnostics-color=never " #define ADD_LIBRARIES "bobcat" #define ADD_LIBRARY_PATHS "" #define DEFCOM "library" guncat-2.02.00/INSTALL0000664000175000017500000000750414747430322013167 0ustar frankfrankTo install guncat by hand instead of using a binary distribution perform the following steps: 0. guncat and its construction depends, in addition to the normally standard available system software on specific software and versions which is documented in the file `required'. (If you compile the bobcat library yourself, note that guncat does not use the SSL, Milter and Xpointer classes; they may --as far as guncat is concerned-- be left out of the library by running './build light') 1. It is expected you use icmake for the package construction. For this a top-level script (build) and support scripts in the ./icmake/ directory are available. By default, the 'build' script echoes the commands it executes to the standard output stream. By specifying the option -q (e.g., ./build -q ...) this is prevented, significantly reducing the output generated by 'build'. 2. Inspect the values of the variables in the file INSTALL.im Modify these when necessary. 3. Run ./build program [strip] to compile guncat. The argument `strip' is optional and strips symbolic information from the final executable. 4. If you installed Yodl then you can create the documentation: ./build man builds the man-page. 5. Before installing the components of guncat, consider defining the environment variable GUNCAT, defining its value as the (preferably absolute) filename of a file on which installed files and directories are logged. Defining the GUNCAT environment variable as ~/.guncat usually works well. 6. Run (probably as root) ./build install 'what' 'base' to install. Here, 'what' specifies what you want to install. Specify: x, to install all components, or specify a combination of: b (binary program), d (standard documentation), m (man-pages) E.g., use ./build install bm 'base' if you only want to be able to run guncat, and want its man-page to be installed below 'base'. ./build install's last argument 'base' is optional: the base directory below which the requested files are installed. This base directory is prepended to the paths #defined in the INSTALL.im file. If 'base' is not specified, then INSTALL.im's #defined paths are used as-is. When requesting non-existing elements (e.g., './build install x' was requested, but the man-pages weren't constructed) then these non-existing elements are silently ignored by the installation process. If the environment variable GUNCAT was defined when issuing the `./build install ...' command then a log of all installed files is written to the file indicated by the GUNCAT environment variable (see also the next item). Defining the GUNCAT environment variable as ~/.guncat usually works well. 7. Uninstalling previously installed components of guncat is easy if the environment variable GUNCAT was defined before issuing the `./build install ...' command. In that case, run the command ./build uninstall logfile where 'logfile' is the file that was written by ./build install. Modified files and non-empty directories are not removed, but the logfile itself is removed following the uninstallation. 8. Following the installation nothing in the directory tree which contains this file (i.e., INSTALL) is required for the proper functioning of guncat, so consider removing it. If you only want to remove left-over files from the build-process, just run ./build distclean guncat-2.02.00/INSTALL.im0000664000175000017500000000212514762336412013567 0ustar frankfrank#define PROGRAM "guncat" #define CXX "ccache g++" #define CXXFLAGS "-Wall -Werror -O2 -fdiagnostics-color=never" // flags passed to the linker #define LDFLAGS "" // The following /bin/cp option is used to keep, rather than follow // symbolic references. If your installation doesn't support these flags, // then change them into available ones. // -P, --no-dereference // never follow symbolic links in SOURCE // --preserve[=ATTR_LIST] // preserve the specified attributes (default: // mode,ownership,timestamps), if possible additional // attributes: context, links, all // -d same as --no-dereference --preserve=links #define CPOPTS "-d" // ONLY USE ABSOLUTE DIRECTORY NAMES: // the final program #define BINARY "/usr/bin/"${PROGRAM} // the directory where the standard documentation is stored #define DOC "/usr/share/doc/"${PROGRAM} // the directory whre the manual page is stored #define MAN "/usr/share/man/man1" guncat-2.02.00/main.cc0000664000175000017500000000160514747430322013365 0ustar frankfrank#include "main.ih" // Options are defined in prepareargs.cc namespace { string terminating{ "Terminating" }; } int main(int argc, char **argv) try { Arg const &arg = prepareArgs(argc, argv); (terminating += ' ') += arg.basename(); arg.versionHelp(usage, Icmbuild::version, 0); // no stdin redirection, no files if ( // and not --gpg-command? not Options::instance().gpgCommand() and isatty(STDIN_FILENO) and arg.nArgs() == 0 ) { usage(arg.basename()); throw 1; } Guncat guncat; guncat.run(); // process all files if (arg.option('d')) // dots were requested cerr.put('\n'); // then end the dots-line } catch (...) { return handle(current_exception()); } guncat-2.02.00/main.ih0000664000175000017500000000056714747430322013406 0ustar frankfrank#include "xerr/xerr.ih" #include #include #include #include #include #include "version/version.h" #include "options/options.h" #include "guncat/guncat.h" using namespace std; using namespace FBB; Arg const &prepareArgs(int argc, char **argv); void usage(string const &progname); int handle(exception_ptr ptr); guncat-2.02.00/options/0000775000175000017500000000000014762336412013625 5ustar frankfrankguncat-2.02.00/options/instance.cc0000664000175000017500000000025214747430322015735 0ustar frankfrank//#define XERR #include "options.ih" // static Options const &Options::instance() { if (s_options == 0) s_options = new Options(); return *s_options; } guncat-2.02.00/options/data.cc0000664000175000017500000000010414747430322015036 0ustar frankfrank//#define XERR #include "options.ih" Options *Options::s_options; guncat-2.02.00/options/extragpgoptions.cc0000664000175000017500000000062514747430322017372 0ustar frankfrank#include "options.ih" void Options::extraGPGoptions() { if (d_pgpRanges) return; if (string option; size_t nOptions = d_arg.option(&option, "gpg-option")) { (d_gpgDecrypt += ' ') += option; for (size_t idx = 1; idx != nOptions; ++idx) { d_arg.option(idx, &option, "gpg-option"); (d_gpgDecrypt += ' ') += option; } } } guncat-2.02.00/options/options1.cc0000664000175000017500000000260414762336412015712 0ustar frankfrank#define XERR #include "options.ih" Options::Options() : d_arg(Arg::instance()), d_noErrors(d_arg.option(0, "no-errors")), d_gpgCommand(d_arg.option(0, "gpg-command")), d_pgpRanges(d_arg.option('r')), d_sectionLines(d_arg.option('S')), d_reduceHeaders(d_arg.option('R')), d_skipIncomplete(d_pgpRanges or d_arg.option('s')), d_quotedPrintable(d_arg.option('q')), d_gpgDecrypt(" --no-auto-key-locate --decrypt --batch --yes") { d_arg.option(&d_passphrasePath, "passphrase"); // override default gpg location if (not d_arg.option(&d_gpgPath, "gpg-path")) d_gpgPath = "/usr/bin/gpg"; // get the name of the verbosity // file if ( not d_arg.option(&d_verbose, 'V') and not d_sectionLines and not d_pgpRanges ) { if (d_arg.option('d')) showDots(); } throw Exception{} << "verbose has value `" << d_verbose << '\''; if (not d_arg.option('t')) // by default --no-tty is used d_gpgDecrypt += " --no-tty"; if (string timeLimit; d_arg.option(&timeLimit, 'T')) d_timeLimit = stoul(timeLimit); setGpgMessages(); extraGPGoptions(); // add extra gpg options } guncat-2.02.00/options/setgpgmessages.cc0000664000175000017500000000074414747430322017160 0ustar frankfrank//#define XERR #include "options.ih" void Options::setGpgMessages() { string filename; if (not d_arg.option(&filename, 'm')) d_gpgMessages = 0; else if (filename == "stdout") d_gpgMessages = &cout; else if (filename == "stderr") d_gpgMessages = &cerr; else { d_msgPtr.reset( new ofstream{ Exception::factory(filename) } ); d_gpgMessages = d_msgPtr.get(); } } guncat-2.02.00/options/icmconf0000664000175000017500000000007614747430322015167 0ustar frankfrank#define LIBRARY "options" #include "../icmconf.lib" guncat-2.02.00/options/options.h0000664000175000017500000000542514762336412015477 0ustar frankfrank#ifndef INCLUDED_OPTIONS_ #define INCLUDED_OPTIONS_ #include #include #include namespace FBB { class Arg; } class Options { FBB::Arg const &d_arg; bool d_noErrors; bool d_gpgCommand; bool d_pgpRanges; bool d_sectionLines; bool d_reduceHeaders; bool d_skipIncomplete; bool d_quotedPrintable; std::string d_gpgDecrypt; // options for decrypting std::string d_gpgPath; std::string d_passphrasePath; // file containing the passphrase std::string d_verbose; size_t d_timeLimit; // a file by name std::unique_ptr d_msgPtr; // receiving GPG messages std::ostream *d_gpgMessages; // a pointer to the used // messages stream static Options *s_options; public: static Options const &instance(); bool gpgCommand() const; bool pgpRanges() const; // only report PGP section ranges bool reduceHeaders() const; bool sectionLines() const; // skip incomplete PGP sections bool skipIncomplete() const; // (implied by pgpRanges) bool quotedPrintable() const; bool noErrors() const; std::string const &gpgDecrypt() const; std::string const &gpgPath() const; std::ostream *const gpgMessages() const; std::string const &passphrasePath() const; std::string const &verbose() const; size_t timeLimit() const; private: Options(); void extraGPGoptions(); // add --gpg-option values void setGpgMessages(); }; inline bool Options::gpgCommand() const { return d_gpgCommand; } inline bool Options::pgpRanges() const { return d_pgpRanges; } inline bool Options::reduceHeaders() const { return d_reduceHeaders; } inline bool Options::sectionLines() const { return d_sectionLines; } inline bool Options::quotedPrintable() const { return d_quotedPrintable; } inline bool Options::skipIncomplete() const { return d_skipIncomplete; } inline bool Options::noErrors() const { return d_noErrors; } inline std::string const &Options::passphrasePath() const { return d_passphrasePath; } inline std::ostream *const Options::gpgMessages() const { return d_gpgMessages; } inline std::string const &Options::gpgDecrypt() const { return d_gpgDecrypt; } inline std::string const &Options::gpgPath() const { return d_gpgPath; } inline std::string const &Options::verbose() const { return d_verbose; } inline size_t Options::timeLimit() const { return d_timeLimit; } #endif guncat-2.02.00/options/options.ih0000664000175000017500000000041114762336412015636 0ustar frankfrank#include "options.h" #include "../xerr/xerr.ih" #include #include #include #include #include #include "../globals/globals.h" using namespace std; using namespace FBB; namespace fs = filesystem; guncat-2.02.00/passphrase.to.gpg/0000775000175000017500000000000014747430322015476 5ustar frankfrankguncat-2.02.00/passphrase.to.gpg/demo.cc0000664000175000017500000000371214747430322016734 0ustar frankfrank// compile with g++ --std=c++0x -pthread demo.cc -lbobcat #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace FBB; string passphrase; void getPassphrase() { cerr << "passphrase: " << flush; struct termios tty; tcgetattr(STDIN_FILENO, &tty); tty.c_lflag &= ~ECHO; tcsetattr(STDIN_FILENO, TCSANOW, &tty); getline(cin, passphrase); tty.c_lflag |= ECHO; tcsetattr(STDIN_FILENO, TCSANOW, &tty); } void inStream(Process *gpg, istream *in, int *exitValue) { *gpg << in->rdbuf(); gpg->close(); *exitValue = gpg->waitForChild(); } void runPGP(string const &out) { for (size_t attempt = 0; attempt != 3; ++attempt) { Pipe pipe; { OFdStream writePwd(pipe.writeFd()); writePwd << passphrase << endl; } string line = "/usr/bin/gpg --passphrase-fd " + to_string(pipe.readFd()) + " --batch --quiet --output " + out + " --decrypt"; Process gpg(Process::CIN, line); ifstream in("mail"); gpg.start(); int exitValue; thread inThread(inStream, &gpg, &in, &exitValue); inThread.join(); switch (exitValue) { default: return; case 2: // incorrect passphrase cerr << "Incorrect passphrase\n"; getPassphrase(); break; } } throw Exception() << "Quitting after three attempts to enter the correct passphrase\n"; } int main(int argc, char **argv) try { getPassphrase(); runPGP("out1"); runPGP("out2"); } catch (exception const &exc) { cerr << exc.what() << '\n'; } guncat-2.02.00/passphrase.to.gpg/compile0000775000175000017500000000006714747430322017057 0ustar frankfrank#!/bin/bash g++ --std=c++0x -pthread demo.cc -lbobcat guncat-2.02.00/passphrase.to.gpg/mail0000664000175000017500000001120714747430322016344 0ustar frankfrankVersion: 1 --0eh6TmSyL6TZE2Uz Content-Type: application/octet-stream Content-Disposition: attachment; filename="msg.asc" -----BEGIN PGP MESSAGE----- Version: GnuPG v1 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 43Kn2n5hHGqIDc4Q3KGtc0FoDoRbOMs= =EGFl -----END PGP MESSAGE----- --0eh6TmSyL6TZE2Uz-- guncat-2.02.00/pgpsection/0000775000175000017500000000000014757141477014316 5ustar frankfrankguncat-2.02.00/pgpsection/nextline.cc0000664000175000017500000000027314747430322016442 0ustar frankfrank//#define XERR #include "pgpsection.ih" bool PGPSection::nextLine() { if (not ::nextline(d_in, d_line)) return false; d_pgpMessage << d_line << '\n'; return true; } guncat-2.02.00/pgpsection/pgpsection.h0000664000175000017500000000335714747430322016637 0ustar frankfrank#ifndef INCLUDED_PGPSECTION_ #define INCLUDED_PGPSECTION_ #include #include #include // determine the next pgp section and its line numbers namespace FBB { class TempStream; } class PGPSection { FBB::TempStream &d_pgpMessage; std::istream &d_in; // current input file size_t d_entryOffset; // initial d_in offset size_t d_offset; // location (so far) in d_in size_t d_firstLine; // first line nr. of a PGP section // line nr after recognizing a correct size_t d_nextNr; // PGP section element std::string d_line; // line read by nextLine() // true if the only the section lines bool d_pgpRanges; // should be reported public: PGPSection(std::istream &in, FBB::TempStream &pgpMessage); // get a complete PGP MESSAGE bool complete( //std::ostream &out ); // from the in-stream // line-range of the current PGP section std::pair range() const; private: // in PGP section lines all chars must be bool validChars() const; // printable and may not be blanks bool nextLine(); void next(); bool empty(); bool lines(); bool lastLine(); bool endMessage(); void verbose(std::string const &what) const; }; inline std::pair PGPSection::range() const { return { d_firstLine, d_nextNr + 1 }; } #endif guncat-2.02.00/pgpsection/lastline.cc0000664000175000017500000000114114747430322016422 0ustar frankfrank//#define XERR #include "pgpsection.ih" bool PGPSection::lastLine() { if (d_line.front() != '=') // not yet at the last line { // (only once) nextLine(); if (not validChars()) return false; } if (d_line.front() == '=') // at the last line { next(); // another line must follow nextLine(); // the reduced line return true; } verbose("invalid end of the encrypted section"); return false; } guncat-2.02.00/pgpsection/validchars.cc0000664000175000017500000000045014747430322016731 0ustar frankfrank//#define XERR #include "pgpsection.ih" bool PGPSection::validChars() const { for (int ch: d_line) { if (isblank(ch) or not isprint(ch)) { verbose("invalid character(s) in the encrypted section"); return false; } } return true; } guncat-2.02.00/pgpsection/next.cc0000664000175000017500000000017314747430322015571 0ustar frankfrank//#define XERR #include "pgpsection.ih" void PGPSection::next() { d_offset = d_in.tellg(); d_nextNr = g_lineNr; } guncat-2.02.00/pgpsection/verbose.cc0000664000175000017500000000037514747430322016264 0ustar frankfrank//#define XERR #include "pgpsection.ih" void PGPSection::verbose(string const &what) const { if (g_verbose != 0) *g_verbose << g_filename << ':' << d_firstLine << ':' << g_lineNr << ": PGP MESSAGE: " << what << '\n'; } guncat-2.02.00/pgpsection/lines.cc0000664000175000017500000000076014747430322015727 0ustar frankfrank//#define XERR #include "pgpsection.ih" bool PGPSection::lines() { size_t length = d_line.length(); while (nextLine()) { if (not validChars()) return false; // stop at a line of different if (length != d_line.length()) // length { next(); return true; } } return false; // there must be a shorter line } guncat-2.02.00/pgpsection/icmconf0000664000175000017500000000010114747430322015634 0ustar frankfrank#define LIBRARY "pgpsection" #include "../icmconf.lib" guncat-2.02.00/pgpsection/complete.cc0000664000175000017500000000154214747430322016424 0ustar frankfrank//#define XERR #include "pgpsection.ih" bool PGPSection::complete() //ostream &out) { d_pgpMessage << g_beginPGP << '\n'; d_firstLine = g_lineNr; next(); // BEGIN PGP MESSAGE has already been read nextLine(); if ( empty() and lines() and lastLine() and endMessage() ) { if (d_pgpRanges) { ostringstream str; str << g_filename << ':' << d_firstLine << ':' << g_lineNr << ": PGP MESSAGE"; starred(// out, str.str()); } verbose("complete"); return true; } if (d_offset != 0) { if (not d_in.seekg(d_offset)) throw Exception{} << "repositioning failed"; g_lineNr = d_nextNr; } return false; } guncat-2.02.00/pgpsection/empty.cc0000664000175000017500000000112414747430322015746 0ustar frankfrank//#define XERR #include "pgpsection.ih" bool PGPSection::empty() { while (true) { if (d_line.empty()) { next(); nextLine(); // get the line beyond the empty line return true; } // empty() also accepts initial // content containing : beyond col. 0 if (size_t pos = d_line.find(':'); pos == 0 or pos == string::npos) break; nextLine(); } verbose("no initial empty line"); return false; } guncat-2.02.00/pgpsection/endmessage.cc0000664000175000017500000000025614747430322016730 0ustar frankfrank//#define XERR #include "pgpsection.ih" bool PGPSection::endMessage() { if (d_line == g_endPGP) return true; verbose("no " + g_endPGP); return false; } guncat-2.02.00/pgpsection/pgpsection.ih0000664000175000017500000000041114747430322016774 0ustar frankfrank#include "pgpsection.h" #include "../xerr/xerr.ih" #include #include #include #include #include #include "../globals/globals.h" #include "../options/options.h" using namespace std; using namespace FBB; guncat-2.02.00/pgpsection/pgpsection1.cc0000664000175000017500000000056414747430322017053 0ustar frankfrank//#define XERR #include "pgpsection.ih" // in: current input file, at 'PGP MESSAGE' PGPSection::PGPSection(istream &in, TempStream &pgpMessage) : d_pgpMessage(pgpMessage), d_in(in), d_entryOffset(in.tellg()), d_offset(d_entryOffset) { Options const &options = Options::instance(); d_pgpRanges = options.pgpRanges() | options.sectionLines(); } guncat-2.02.00/prepareargs.cc0000664000175000017500000000264714762336412014765 0ustar frankfrank#include using namespace std; using namespace FBB; // initializing FBB::Arg is separated from main() so it can be used by // the various driver programs: they declare // // Arg const &prepareArgs(int argc, char **argv); namespace { Arg::LongOption longOptions[] = { Arg::LongOption("dots", 'd'), Arg::LongOption("gpg-command", Arg::NoArg), Arg::LongOption("gpg-option", Arg::Required), Arg::LongOption("gpg-path", Arg::Required), Arg::LongOption("help", 'h'), Arg::LongOption("no-errors", Arg::NoArg), Arg::LongOption("passphrase", Arg::Required), Arg::LongOption("pgp-messages", 'm'), Arg::LongOption("pgp-ranges", 'r'), Arg::LongOption("quoted-printable", 'q'), Arg::LongOption("reduce-headers", 'R'), Arg::LongOption("section-lines", 'S'), Arg::LongOption("skip-incomplete", 's'), Arg::LongOption("time-limit", 'T'), Arg::LongOption("tty-OK", 't'), Arg::LongOption("verbose", 'V'), // optional argument Arg::LongOption("version", 'v'), Arg::LongOption("write", 'w'), }; } Arg const &prepareArgs(int argc, char **argv) { return Arg::initialize("dhm:qRrsStT:vV::w:", longOptions, end(longOptions), argc, argv); } guncat-2.02.00/README0000664000175000017500000000125314747430322013011 0ustar frankfrankGuncat was designed to tackle a problem encountered with (partially) PGP encrypted files (as encountered, e.g., in mailboxes): the encrypted sections of such files are relatively difficult to browse through. Guncat acts like unix's cat command, but handles (partially) encrypted sections of processed files. Sections of guncat's input files which are surrounded by -----BEGIN PGP MESSAGE----- and -----END PGP MESSAGE----- markers are decrypted before being concatenated to the std. output stream. Guncat's output (i.e., the standard output stream) may subsequently be processed by other programs, like grep or less. April 2014-2020 Frank B. Brokken (f.b.brokken@rug.nl) guncat-2.02.00/README.classes0000664000175000017500000000040114747430322014437 0ustar frankfrankOptions Globals | | +-------------+ | | PGPSection GPGhandler | | +-------------+ OutputBuf | | Decryptor OOutputStream | | +-------------------+ | Guncat | main guncat-2.02.00/required0000664000175000017500000000071114747430322013672 0ustar frankfrankThis file lists non-standard software only. Thus, standard utilities like cp, mv, sed, etc, etc, are not explicitly mentioned. Neither is the gcc compiler explicitly mentioned, but a fairly recent one is assumed. Required software for building Guncat ------------------------------------- libbobcat-dev (>= 4.01.02), To use the provided build-script: icmake (>= 8.00.04) To construct the manual and map-page: yodl (>= 3.06.0) guncat-2.02.00/usage.cc0000664000175000017500000000651714762336412013556 0ustar frankfrank// usage.cc #include "main.ih" namespace { char const info[] = R"R([options] [file(s)] Where: [options] - optional arguments (short options between parentheses): --dots (-d): write a dot (.) to the standard error stream after processing each block of 8192 input lines. This option is ignored when the --pgp-ranges, --section-lines, or --verbose options are specified. --gpg-command: show the gpg command that would be used, and quit. --gpg-path path: path to the gpg program (default: /usr/bin/gpg). --gpg-option "spec": option `spec' is passed to gpg child processes (multiple --gpg-option options may be specified). --help (-h): provide this help (ends guncat, returning 0). --no-errors: processing ends if an invalid PGP section is encountered or if gpg returns a non-zero exit value. Otherwise processing continues beyond the failing PGP section, reporting the line numbers of the failing PGP section. --passphrase path: the passphrase is read as the first line from `path'. --pgp-messages (-m) path to the file receiving the GPG message. Use `stdout' to write the messages to the standard output stream, use `stderr' to write the messages to the standard error stream --pgp-ranges (-r): the lines-ranges of complete PGP MESSAGE sections are reported. No additional output is produced. --quoted-printable (-q): merely decrypt PGP messages, keeping their quoted-printable content (by default quoted-printable content like '=3D' is converted to ascii). --reduce-headers (-R): only output the mail headers Cc:, Date:, From:, Subject:, and To:. --section-lines (-S): in the output precede decrypted PGP sections by their line numbers. --skip-incomplete (-s): incomple PGP MESSAGE sections are not outputted. --time-limit (-T) : maximum allowed time in seconds for decrypting an encrypted section (by default: no time limit is used). --tty-OK (-t): by default gpg's option --no-tty is used. --verbose (-V) - write extra messages to stderr. Use `--verbose=path' or `-Vpath' to write extra messages to the file `path'. --version (-v) - show version information (ends guncat, returning 0). --write (-w) path - path of the file to receive the output. By default cout is used. [file(s)] - file(s) to process. Standard input redirection can also be used. By default the processed information is written to the standard output stream, but may also be written to file (using --write or standard output redirection), or may be sent to a the standard input stream of another program (using --less to use /usr/bin/less or --pipe to specify another program). )R"; } void usage(std::string const &progname) { cout << "\n" << progname << " by " << Icmbuild::author << "\n" << progname << " V" << Icmbuild::version << " " << Icmbuild::years << "\n" "\n" "Usage: " << progname << info; } guncat-2.02.00/version/0000775000175000017500000000000014747430322013615 5ustar frankfrankguncat-2.02.00/version/version.h0000664000175000017500000000034214747430322015452 0ustar frankfrank#ifndef INCLUDED_VERSION_H_ #define INCLUDED_VERSION_H_ #include "../VERSION" namespace Icmbuild { char const version[] = VERSION; char const years[] = YEARS; char const author[] = AUTHOR; } #endif guncat-2.02.00/VERSION0000664000175000017500000000015314762336412013201 0ustar frankfrank#define AUTHOR "Frank B. Brokken (f.b.brokken@rug.nl)" #define VERSION "2.02.00" #define YEARS "2014-2025" guncat-2.02.00/VERSION.h0000664000175000017500000000010414747430322013421 0ustar frankfrank#include "VERSION" SUBST(_CurVers_)(VERSION) SUBST(_CurYrs_)(YEARS) guncat-2.02.00/xerr/0000775000175000017500000000000014747430322013110 5ustar frankfrankguncat-2.02.00/xerr/xerr.ih0000664000175000017500000000133014747430322014407 0ustar frankfrank// define XERR to activate the xerr/xerr(2) macros: // xerr(insertion) // inserts the '<<' concatenated elements into std::cerr // preceded by the name of the source file, and ended by '\n' // xerr2(insertion, code) // performs the insertion if X is defined, and (unconditionally) // executes the statement(s) in `code'. `code' must be valid // C(++) code. // #ifdef XERR #include #define xerr(insertion) std::cerr << __FILE__": " << insertion << '\n' #define xerr2(insertion, code) \ { std::cerr << __FILE__": " << insertion << '\n'; code; } #else #define xerr(insertion) #define xerr2(insertion, code) code #endif