summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--debian/changelog1
-rw-r--r--lib/dpkg/libdpkg.map2
-rw-r--r--lib/dpkg/pager.c64
-rw-r--r--lib/dpkg/pager.h6
4 files changed, 73 insertions, 0 deletions
diff --git a/debian/changelog b/debian/changelog
index 7bcfc04ae..06462517a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -206,6 +206,7 @@ dpkg (1.19.1) UNRELEASED; urgency=medium
- libdpkg: Add new m_dup() function.
- libdpkg: Factor out package stanza printing into its own function.
- libdpkg: Split pager specific code into its own module.
+ - libdpkg: Add pager spawning and reaping support.
* Build system:
- Set distribution tarball format to ustar, instead of default v7 format.
- Mark PO4A and POD2MAN as precious variables.
diff --git a/lib/dpkg/libdpkg.map b/lib/dpkg/libdpkg.map
index b562d7aad..cb3062845 100644
--- a/lib/dpkg/libdpkg.map
+++ b/lib/dpkg/libdpkg.map
@@ -185,6 +185,8 @@ LIBDPKG_PRIVATE {
command_destroy;
pager_get_exec;
+ pager_spawn;
+ pager_reap;
setcloexec;
diff --git a/lib/dpkg/pager.c b/lib/dpkg/pager.c
index 4922b537a..c9adf5bce 100644
--- a/lib/dpkg/pager.c
+++ b/lib/dpkg/pager.c
@@ -21,12 +21,17 @@
#include <config.h>
#include <compat.h>
+#include <sys/types.h>
+
+#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
#include <dpkg/dpkg.h>
#include <dpkg/i18n.h>
#include <dpkg/string.h>
+#include <dpkg/subproc.h>
+#include <dpkg/command.h>
#include <dpkg/pager.h>
/**
@@ -48,3 +53,62 @@ pager_get_exec(void)
return pager;
}
+
+struct pager {
+ bool used;
+ const char *desc;
+ pid_t pid;
+ int stdout_old;
+ int pipe[2];
+};
+
+struct pager *
+pager_spawn(const char *desc, const char *filename)
+{
+ struct pager *pager;
+
+ pager = m_calloc(1, sizeof(*pager));
+ pager->used = filename || (isatty(0) && isatty(1));
+ pager->desc = desc;
+
+ if (!pager->used)
+ return pager;
+
+ m_pipe(pager->pipe);
+
+ pager->pid = subproc_fork();
+ if (pager->pid == 0) {
+ struct command cmd;
+ const char *exec;
+
+ exec = pager_get_exec();
+
+ m_dup2(pager->pipe[0], 0);
+ close(pager->pipe[0]);
+ close(pager->pipe[1]);
+
+ command_init(&cmd, exec, desc);
+ command_add_arg(&cmd, exec);
+ command_add_arg(&cmd, filename);
+ command_exec(&cmd);
+ }
+
+ pager->stdout_old = m_dup(1);
+ m_dup2(pager->pipe[1], 1);
+ close(pager->pipe[0]);
+ close(pager->pipe[1]);
+
+ return pager;
+}
+
+void
+pager_reap(struct pager *pager)
+{
+ if (!pager->used)
+ return;
+
+ m_dup2(pager->stdout_old, 1);
+ subproc_reap(pager->pid, pager->desc, SUBPROC_NOPIPE);
+
+ free(pager);
+}
diff --git a/lib/dpkg/pager.h b/lib/dpkg/pager.h
index 8ecc93b97..7d7ea0dff 100644
--- a/lib/dpkg/pager.h
+++ b/lib/dpkg/pager.h
@@ -36,6 +36,12 @@ struct pager;
const char *
pager_get_exec(void);
+struct pager *
+pager_spawn(const char *desc, const char *filename);
+
+void
+pager_reap(struct pager *pager);
+
/** @} */
DPKG_END_DECLS