summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2005-02-14 08:27:53 +0000
committerJohn Wiegley <johnw@newartisans.com>2008-04-13 02:41:00 -0400
commit8fd5f4ee57f146d8486c39becced0a75ee622d31 (patch)
treeffccdf177a546262ab3aeb2bd01c8d6a220456df
parent219492564c6a4f6027c2eff37bc0a7b1455ad969 (diff)
downloadfork-ledger-8fd5f4ee57f146d8486c39becced0a75ee622d31.tar.gz
fork-ledger-8fd5f4ee57f146d8486c39becced0a75ee622d31.tar.bz2
fork-ledger-8fd5f4ee57f146d8486c39becced0a75ee622d31.zip
Added support for "--pager PROGRAM". A likely way to define it in
your login file would be: "export LEDGER_PAGER=$PAGER".
-rw-r--r--config.cc4
-rw-r--r--config.h1
-rw-r--r--main.cc74
3 files changed, 75 insertions, 4 deletions
diff --git a/config.cc b/config.cc
index baf244b3..49f1c666 100644
--- a/config.cc
+++ b/config.cc
@@ -725,6 +725,10 @@ OPT_BEGIN(tail, ":") {
config.tail_entries = std::atoi(optarg);
} OPT_END(tail);
+OPT_BEGIN(pager, ":") {
+ config.pager = optarg;
+} OPT_END(pager);
+
OPT_BEGIN(empty, "E") {
config.show_empty = true;
} OPT_END(empty);
diff --git a/config.h b/config.h
index 4d06bd2e..14b18a47 100644
--- a/config.h
+++ b/config.h
@@ -49,6 +49,7 @@ struct config_t
std::string forecast_limit;
std::string reconcile_balance;
std::string reconcile_date;
+ std::string pager;
unsigned long budget_flags;
unsigned long pricing_leeway;
int head_entries;
diff --git a/main.cc b/main.cc
index 1ead6fd9..908b05b4 100644
--- a/main.cc
+++ b/main.cc
@@ -15,10 +15,18 @@ using namespace ledger;
#include <exception>
#include <iterator>
#include <string>
+#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
+#ifdef HAVE_UNIX_PIPES
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include "fdstream.hpp"
+#endif
+
#if !defined(DEBUG_LEVEL) || DEBUG_LEVEL <= RELEASE
#define auto_ptr bogus_auto_ptr
@@ -306,9 +314,57 @@ int parse_and_report(int argc, char * argv[], char * envp[])
// Configure the output stream
+#ifdef HAVE_UNIX_PIPES
+ int status, pfd[2]; // Pipe file descriptors
+#endif
std::ostream * out = &std::cout;
- if (! config.output_file.empty())
+
+ if (! config.output_file.empty()) {
out = new std::ofstream(config.output_file.c_str());
+ }
+#ifdef HAVE_UNIX_PIPES
+ else if (! config.pager.empty()) {
+ status = pipe(pfd);
+ if (status == -1)
+ throw error("Failed to create pipe");
+
+ status = fork();
+ if (status < 0) {
+ throw error("Failed to fork child process");
+ }
+ else if (status == 0) { // child
+ const char *arg0;
+
+ // Duplicate pipe's reading end into stdin
+ status = dup2(pfd[0], STDIN_FILENO);
+ if (status==-1)
+ perror("dup2");
+
+ // Close unuseful file descriptors: the pipe's writing and
+ // reading ends (the latter is not needed anymore, after the
+ // duplication).
+ close(pfd[1]);
+ close(pfd[0]);
+
+ // Find command name: its the substring starting right of the
+ // rightmost '/' character in the pager pathname. See manpage
+ // for strrchr.
+ arg0 = std::strrchr(config.pager.c_str(), '/');
+ if (arg0 != NULL)
+ arg0++;
+ else
+ arg0 = config.pager.c_str(); // No slashes in pager.
+
+ execlp(config.pager.c_str(), arg0, (char *)0);
+ perror("execl");
+ exit(1);
+ }
+ else { // parent
+ close(pfd[0]);
+ out = new boost::fdostream(pfd[1]);
+ }
+ }
+#endif
// Compile the format strings
@@ -446,7 +502,6 @@ def vmax(d, val):\n\
}
#if DEBUG_LEVEL >= BETA
-
clear_all_xdata();
if (! config.output_file.empty())
@@ -458,8 +513,7 @@ def vmax(d, val):\n\
i++)
delete *i;
formatter_ptrs.clear();
-
-#endif // DEBUG_LEVEL >= BETA
+#endif
// Write out the binary cache, if need be
@@ -468,6 +522,18 @@ def vmax(d, val):\n\
write_binary_journal(stream, journal.get());
}
+#ifdef HAVE_UNIX_PIPES
+ if (! config.pager.empty()) {
+ delete out;
+ close(pfd[1]);
+
+ // Wait for child to finish
+ wait(&status);
+ if (status & 0xffff != 0)
+ throw error("Something went wrong in the pager");
+ }
+#endif
+
return 0;
}