diff options
-rw-r--r-- | debian/changelog | 1 | ||||
-rw-r--r-- | lib/dpkg/libdpkg.map | 2 | ||||
-rw-r--r-- | lib/dpkg/pager.c | 64 | ||||
-rw-r--r-- | lib/dpkg/pager.h | 6 |
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 |