guncat-2.01.00/build0000755000175000017500000000765114307326523013162 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/precompileheaders" #include "icmake/special" #include "icmake/clean" #include "icmake/manpage" #include "icmake/install" #include "icmake/gitlab" void main(int argc, list argv) { string option; string strip; int idx; for (idx = listlen(argv); idx--; ) { if (argv[idx] == "-q") { g_echo = OFF; argv -= (list)"-q"; } else if (argv[idx] == "-P") { g_gch = 0; argv -= (list)"-P"; } } 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 (option == "library") { // precompileHeaders(); system("icmbuild library"); exit(0); } if (argv[2] == "strip") strip = "strip"; if (option == "program") { // precompileHeaders(); system("icmbuild program " + strip); exit(0); } if (option == "xref") { // precompileHeaders(); system("icmbuild program " + strip); 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" " [-P]: do not use precompiled headers\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 [strip] - build " PROGRAM " (optionally " "strip the\n" " executable)\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.01.00/changelog0000644000175000017500000001045114322570576014005 0ustar frankfrankguncat (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.01.00/CLASSES0000644000175000017500000000007114322235662013142 0ustar frankfrankglobals options gpghandler pgpsection decryptor guncat guncat-2.01.00/c++std0000644000175000017500000000003614307326523013131 0ustar frankfrank#define CPPSTD "--std=c++20" guncat-2.01.00/decryptor/0000755000175000017500000000000014322255005014130 5ustar frankfrankguncat-2.01.00/decryptor/setverbose.cc0000644000175000017500000000112614307326523016627 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.01.00/decryptor/clearfiles.cc0000644000175000017500000000027414322000100016533 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.01.00/decryptor/error.cc0000644000175000017500000000054014322251355015573 0ustar frankfrank#include "decryptor.ih" // static void Decryptor::error(// ostream &out, int ret, pair const &range) { // msg throw Exception{} << "In " << g_filename << ':' << range.first << ':' << range.second << ": cannot decrypt PGP section, gpg returns " << ret; } guncat-2.01.00/decryptor/decryptor.ih0000644000175000017500000000051714322251355016474 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.01.00/decryptor/decryptor.h0000644000175000017500000000161114322251355016317 0ustar frankfrank#ifndef INCLUDED_DECRYPTOR_ #define INCLUDED_DECRYPTOR_ #include #include #include class Options; class GPGHandler; #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 setVerbose(); static void error(int ret, std::pair const &range); }; #endif guncat-2.01.00/decryptor/icmconf0000644000175000017500000000010014307326523015467 0ustar frankfrank#define LIBRARY "decryptor" #include "../icmconf.lib" guncat-2.01.00/decryptor/decryptor1.cc0000644000175000017500000000113214322006743016533 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.01.00/decryptor/process.cc0000644000175000017500000000305114322251355016120 0ustar frankfrank#define XERR #include "decryptor.ih" // in: current input file, at 'PGP MESSAGE' void Decryptor::process(istream &in) // , ostream &out) { // 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 { // decrypt it unless only if (not d_options.pgpRanges()) // ranges are requested { 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) error(ret, pgpSection.range()); d_gpgHandler.getPassphrase(attempt); } } return; } // unless suppressed: if (not d_options.skipIncomplete()) // show the INcomplete cout << d_pgpMessage->rdbuf(); // PGP MESSAGE } guncat-2.01.00/documentation/0000755000175000017500000000000014307326523014775 5ustar frankfrankguncat-2.01.00/documentation/man/0000755000175000017500000000000014322571153015546 5ustar frankfrankguncat-2.01.00/documentation/man/guncat.yo0000644000175000017500000001703714322571153017410 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.01.00/globals/0000755000175000017500000000000014322255005013540 5ustar frankfrankguncat-2.01.00/globals/data.cc0000644000175000017500000000032414307326523014766 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.01.00/globals/nextline.cc0000644000175000017500000000025014322017706015676 0ustar frankfrank#include "globals.ih" istream &nextline(istream &in, string &line) { if (getline(in, line)) { ++g_lineNr; (*g_dots)(); } return in; } guncat-2.01.00/globals/globals.ih0000644000175000017500000000023514322017604015506 0ustar frankfrank#include "globals.h" #include "../xerr/xerr.ih" #include #include #include extern void (*g_dots)(); using namespace std; guncat-2.01.00/globals/icmconf0000644000175000017500000000007614307326523015113 0ustar frankfrank#define LIBRARY "globals" #include "../icmconf.lib" guncat-2.01.00/globals/starred.cc0000644000175000017500000000045214322013637015517 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.01.00/globals/fileinfo.cc0000644000175000017500000000020314307326523015644 0ustar frankfrank#include "globals.ih" #include string fileInfo() { return "In " + g_filename + ", line " + to_string(g_lineNr); } guncat-2.01.00/globals/dots.cc0000644000175000017500000000035514322020127015016 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.01.00/globals/globals.h0000644000175000017500000000056714322017202015337 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.01.00/gpghandler/0000755000175000017500000000000014322255005014230 5ustar frankfrankguncat-2.01.00/gpghandler/parentprocess.cc0000644000175000017500000000106514322234624017435 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.01.00/gpghandler/getpassphrase.cc0000644000175000017500000000145514322251355017421 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.01.00/gpghandler/data.cc0000644000175000017500000000011614321330624015446 0ustar frankfrank//#define XERR #include "gpghandler.ih" unsigned GPGHandler::s_nRetries = 0; guncat-2.01.00/gpghandler/gpghandler.ih0000644000175000017500000000101114321330624016656 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.01.00/gpghandler/gpghandler.h0000644000175000017500000000265714322251355016532 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.01.00/gpghandler/passphrasefd.cc0000644000175000017500000000147214322251355017232 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.01.00/gpghandler/childprocess.cc0000644000175000017500000000107314322005442017220 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.01.00/gpghandler/icmconf0000644000175000017500000000010114321330624015561 0ustar frankfrank#define LIBRARY "gpghandler" #include "../icmconf.lib" guncat-2.01.00/gpghandler/echo.cc0000644000175000017500000000055414321330624015461 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.01.00/gpghandler/childredirections.cc0000644000175000017500000000020514321530623020233 0ustar frankfrank//#define XERR #include "gpghandler.ih" void GPGHandler::childRedirections() { d_childMessages.writtenBy(Redirector::STDERR); } guncat-2.01.00/gpghandler/process.cc0000644000175000017500000000055414322251355016225 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.01.00/gpghandler/resetpipe.cc0000644000175000017500000000020514321554342016541 0ustar frankfrank//#define XERR #include "gpghandler.ih" void GPGHandler::resetPipe() { d_childMessages.close(); d_childMessages = Pipe{}; } guncat-2.01.00/gpghandler/gpghandler1.cc0000644000175000017500000000110414322251355016733 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.01.00/guncat/0000755000175000017500000000000014322255005013376 5ustar frankfrankguncat-2.01.00/guncat/processcin.cc0000644000175000017500000000014514307326523016064 0ustar frankfrank#include "guncat.ih" void Guncat::processCin() { g_filename = "stdin"; process(cin); } guncat-2.01.00/guncat/data.cc0000644000175000017500000000032514307326523014625 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.01.00/guncat/guncat.ih0000644000175000017500000000037114322251355015206 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.01.00/guncat/run.cc0000644000175000017500000000020214307326523014512 0ustar frankfrank#include "guncat.ih" void Guncat::run() { if (d_gpgCommand) showGPGcommand(); else programArguments(); } guncat-2.01.00/guncat/guncat.h0000644000175000017500000000153614322251355015041 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.01.00/guncat/reduceheaders.cc0000644000175000017500000000066214322012076016513 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.01.00/guncat/icmconf0000644000175000017500000000007514307326523014750 0ustar frankfrank#define LIBRARY "guncat" #include "../icmconf.lib" guncat-2.01.00/guncat/programarguments.cc0000644000175000017500000000050014321746611017304 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.01.00/guncat/process.cc0000644000175000017500000000111414322012163015354 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.01.00/guncat/guncat1.cc0000644000175000017500000000037714322251355015262 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.01.00/guncat/showgpgcommand.cc0000644000175000017500000000031614307326523016731 0ustar frankfrank#include "guncat.ih" void Guncat::showGPGcommand() const { cout << d_options.gpgPath() << " --pinentry-mode loopback --passphrase-fd " << d_options.gpgDecrypt() << '\n'; } guncat-2.01.00/guncat/onlycin.cc0000644000175000017500000000154714322251355015373 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.01.00/guncat.xref0000644000175000017500000002346514322235662014305 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.01.00/handle.cc0000644000175000017500000000064614322253314013666 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.01.00/icmake/0000755000175000017500000000000014307326523013355 5ustar frankfrankguncat-2.01.00/icmake/setopt0000644000175000017500000000034114307326523014614 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.01.00/icmake/manpage0000644000175000017500000000057514307326523014717 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.01.00/icmake/findall0000644000175000017500000000123114307326523014706 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.01.00/icmake/log0000755000175000017500000000063214307326523014065 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.01.00/icmake/adddir0000644000175000017500000000112514307326523014526 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.01.00/icmake/pathfile0000644000175000017500000000055214307326523015076 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.01.00/icmake/clean0000644000175000017500000000043614307326523014365 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 tmp *.ih.gch */*.ih.gch"); exit(0); } guncat-2.01.00/icmake/uninstall0000644000175000017500000000045614307326523015316 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.01.00/icmake/cuteoln0000644000175000017500000000023314307326523014747 0ustar frankfrankstring cutEoln(string text) { int len; len = strlen(text) - 1; if (text[len] == "\n") text = substr(text, 0, len); return text; } guncat-2.01.00/icmake/run0000644000175000017500000000015114307326523014101 0ustar frankfrankvoid run(string cmd) { if (g_echo == OFF) cmd += "> /dev/null 2>&1"; system(0, cmd); } guncat-2.01.00/icmake/md0000644000175000017500000000074014307326523013701 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.01.00/icmake/gitlab0000644000175000017500000000022114307326523014535 0ustar frankfrankvoid gitlab() { run("cp -r release.yo tmp/manhtml/guncat.1.html ../../wip"); run("cp changelog ../../wip/changelog.txt"); exit(0); } guncat-2.01.00/icmake/remove0000755000175000017500000000117014307326523014577 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.01.00/icmake/precompileheaders0000644000175000017500000000133614307326523016776 0ustar frankfrankstring g_compiler; int g_gch = 1; void _precompile(string class) { string classIH; classIH = class + ".ih"; if (classIH younger class + ".ih.gch") run(g_compiler + " -x c++-header " + classIH); } void precompileHeaders() { int idx; list classes; string class; if (!g_gch) return; classes = makelist(O_SUBDIR, "*"); g_compiler = setOpt(CXX, "CXX") + " " + setOpt(CXXFLAGS, "CXXFLAGS") + " "; _precompile("main"); // precompile the main program .ih file for (idx = listlen(classes); idx--; ) { class = classes[idx]; chdir(class); _precompile(class); chdir(g_cwd); } } guncat-2.01.00/icmake/backtick0000644000175000017500000000016014307326523015050 0ustar frankfranklist backtick(string arg) { list ret; echo(OFF); ret = `arg`; echo(g_echo); return ret; } guncat-2.01.00/icmake/install0000644000175000017500000000332414307326523014750 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.01.00/icmake/logfile0000644000175000017500000000025714307326523014725 0ustar frankfrankvoid logFile(string srcdir, string src, string destdir, string dest) { chdir(g_cwd); md(destdir); run("cp " + srcdir + "/" + src + " " + destdir + "/" + dest); } guncat-2.01.00/icmake/loginstall0000644000175000017500000000156514307326523015457 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.01.00/icmake/special0000644000175000017500000000042114307326523014715 0ustar frankfrankvoid special() { if (! exists("release.yo") || "VERSION" newer "release.yo") { system("touch version.cc"); run("gcc -E VERSION.h | grep -v '#' | sed 's/\\\"//g' > " "release.yo"); } } guncat-2.01.00/icmake/logzip0000644000175000017500000000165614307326523014614 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.01.00/icmconf0000644000175000017500000000100214321345760013456 0ustar frankfrank#include "INSTALL.im" #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 PRECOMP "-x c++-header" #define USE_ECHO ON #define USE_VERSION #define DEFCOM "program" guncat-2.01.00/icmconf.lib0000644000175000017500000000073414307326523014236 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.01.00/INSTALL0000644000175000017500000000750414307326523013163 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.01.00/INSTALL.im0000644000175000017500000000223414307326523013562 0ustar frankfrank#include "c++std" #define PROGRAM "guncat" #define CXX "g++" #define CXXFLAGS ${CPPSTD} " -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.01.00/main.cc0000644000175000017500000000152114322253453013354 0ustar frankfrank#include "main.ih" namespace { string terminating{ "Terminating" }; } int main(int argc, char **argv) try { Arg const &arg = prepareArgs(argc, argv); (terminating += ' ') += arg.basename(); arg.versionHelp(usage, 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.01.00/main.ih0000644000175000017500000000073314322253247013374 0ustar frankfrank#include "xerr/xerr.ih" #include #include #include #include #include #include "options/options.h" #include "guncat/guncat.h" namespace Icmbuild { extern char version[]; extern char years[]; extern char author[]; }; using namespace std; using namespace FBB; using namespace Icmbuild; Arg const &prepareArgs(int argc, char **argv); void usage(string const &progname); int handle(exception_ptr ptr); guncat-2.01.00/options/0000755000175000017500000000000014322255005013610 5ustar frankfrankguncat-2.01.00/options/instance.cc0000644000175000017500000000025214307326523015731 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.01.00/options/data.cc0000644000175000017500000000010414307326523015032 0ustar frankfrank//#define XERR #include "options.ih" Options *Options::s_options; guncat-2.01.00/options/extragpgoptions.cc0000644000175000017500000000062514307326523017366 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.01.00/options/options1.cc0000644000175000017500000000250414322254747015710 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(); } 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.01.00/options/setgpgmessages.cc0000644000175000017500000000063514321733117017150 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_msg = Exception::factory(filename); d_gpgMessages = &d_msg; } } guncat-2.01.00/options/icmconf0000644000175000017500000000007614307326523015163 0ustar frankfrank#define LIBRARY "options" #include "../icmconf.lib" guncat-2.01.00/options/options.h0000644000175000017500000000540414322251355015463 0ustar frankfrank#ifndef INCLUDED_OPTIONS_ #define INCLUDED_OPTIONS_ #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 to std::ofstream d_msg; // receive 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.01.00/options/options.ih0000644000175000017500000000041114322020537015621 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.01.00/passphrase.to.gpg/0000755000175000017500000000000014307326523015472 5ustar frankfrankguncat-2.01.00/passphrase.to.gpg/demo.cc0000644000175000017500000000371214307326523016730 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.01.00/passphrase.to.gpg/compile0000755000175000017500000000006714307326523017053 0ustar frankfrank#!/bin/bash g++ --std=c++0x -pthread demo.cc -lbobcat guncat-2.01.00/passphrase.to.gpg/mail0000644000175000017500000001120714307326523016340 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.01.00/pgpsection/0000755000175000017500000000000014322255005014270 5ustar frankfrankguncat-2.01.00/pgpsection/nextline.cc0000644000175000017500000000027314322000143016416 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.01.00/pgpsection/pgpsection.h0000644000175000017500000000335714322251355016630 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.01.00/pgpsection/lastline.cc0000644000175000017500000000114114307326523016416 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.01.00/pgpsection/validchars.cc0000644000175000017500000000045014307326523016725 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.01.00/pgpsection/next.cc0000644000175000017500000000017314307326523015565 0ustar frankfrank//#define XERR #include "pgpsection.ih" void PGPSection::next() { d_offset = d_in.tellg(); d_nextNr = g_lineNr; } guncat-2.01.00/pgpsection/verbose.cc0000644000175000017500000000037514307326523016260 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.01.00/pgpsection/lines.cc0000644000175000017500000000076014307326523015723 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.01.00/pgpsection/icmconf0000644000175000017500000000010114307326523015630 0ustar frankfrank#define LIBRARY "pgpsection" #include "../icmconf.lib" guncat-2.01.00/pgpsection/complete.cc0000644000175000017500000000154214322013527016412 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.01.00/pgpsection/empty.cc0000644000175000017500000000112414307326523015742 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.01.00/pgpsection/endmessage.cc0000644000175000017500000000025614307326523016724 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.01.00/pgpsection/pgpsection.ih0000644000175000017500000000041114307326523016770 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.01.00/pgpsection/pgpsection1.cc0000644000175000017500000000056414321764547017057 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.01.00/prepareargs.cc0000644000175000017500000000256514322251355014753 0ustar frankfrank#include 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::None), Arg::LongOption("gpg-option", Arg::Required), Arg::LongOption("gpg-path", Arg::Required), Arg::LongOption("help", 'h'), Arg::LongOption("no-errors", Arg::None), 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'), Arg::LongOption("version", 'v'), }; auto longEnd = longOptions + std::size(longOptions); } Arg const &prepareArgs(int argc, char **argv) { return Arg::initialize("dhm:qRrsStT:vV:", longOptions, longEnd, argc, argv); } guncat-2.01.00/README0000644000175000017500000000125314307326523013005 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.01.00/README.classes0000644000175000017500000000040114307326523014433 0ustar frankfrankOptions Globals | | +-------------+ | | PGPSection GPGhandler | | +-------------+ OutputBuf | | Decryptor OOutputStream | | +-------------------+ | Guncat | main guncat-2.01.00/required0000644000175000017500000000071114307326523013666 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.01.00/usage.cc0000644000175000017500000000641314322571050013535 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) path: specify - to write additional messages to stderr, otherwise messages are written to `path' (by default messages are suppressed). --version (-v) - show version information (ends guncat, returning 0). [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.01.00/VERSION0000644000175000017500000000015314321740754013175 0ustar frankfrank#define AUTHOR "Frank B. Brokken (f.b.brokken@rug.nl)" #define VERSION "2.01.00" #define YEARS "2014-2022" guncat-2.01.00/version.cc0000644000175000017500000000056314322251741014120 0ustar frankfrank// version.cc #include "main.ih" #include "icmconf" #ifdef USE_VERSION #include "VERSION" #endif #ifndef AUTHOR #define AUTHOR "" #endif #ifndef VERSION #define VERSION "0.00.00" #endif #ifndef YEARS #define YEARS "2012" #endif namespace Icmbuild { char version[] = VERSION; char years[] = YEARS; char author[] = AUTHOR; } guncat-2.01.00/VERSION.h0000644000175000017500000000010414307326523013415 0ustar frankfrank#include "VERSION" SUBST(_CurVers_)(VERSION) SUBST(_CurYrs_)(YEARS) guncat-2.01.00/xerr/0000755000175000017500000000000014307326523013104 5ustar frankfrankguncat-2.01.00/xerr/xerr.ih0000644000175000017500000000133014307326523014403 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