summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorGuillem Jover <guillem@debian.org>2018-08-15 05:10:12 +0200
committerGuillem Jover <guillem@debian.org>2018-08-30 03:14:08 +0200
commit3b8cd0ea54e2027fd7c972e3edcbbc8bb43afa52 (patch)
treea30930573825bae899d046e3ddbe6c2e37de7b1f /lib
parent7a6cdb430bd85bd38601730fef816e7c89e5e1b8 (diff)
downloaddpkg-3b8cd0ea54e2027fd7c972e3edcbbc8bb43afa52.tar.gz
libdpkg: Add pager spawning and reaping support
This will make using a pager way easier, and make it possible to remove some redundant and unsafe system() usage.
Diffstat (limited to 'lib')
-rw-r--r--lib/dpkg/libdpkg.map2
-rw-r--r--lib/dpkg/pager.c64
-rw-r--r--lib/dpkg/pager.h6
3 files changed, 72 insertions, 0 deletions
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