diff options
author | Miklos Vajna <vmiklos@frugalware.org> | 2011-01-02 00:25:57 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2011-01-02 18:17:19 +0100 |
commit | 0736af98c6fae9c7d31e3dd17589421b7e883ef5 (patch) | |
tree | 278c115b6c6531fd379e9e8cc2664997d10b02ba | |
parent | 71656790d6540f817661cc22b8bc1d33720ce96a (diff) |
systemctl: implement auto-pager a la git
-rw-r--r-- | TODO | 2 | ||||
-rw-r--r-- | man/systemctl.xml | 7 | ||||
-rw-r--r-- | src/systemctl.c | 52 |
3 files changed, 59 insertions, 2 deletions
@@ -69,8 +69,6 @@ * suspend, resume -* systemctl auto-pager a la git - * readahead: btrfs/LVM SSD detection * when processes remain in a service even though the start command failed enter active diff --git a/man/systemctl.xml b/man/systemctl.xml index 6b05e95def..c21ed85565 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -171,6 +171,13 @@ enqueued.</para></listitem> </varlistentry> <varlistentry> + <term><option>--no-pager</option></term> + + <listitem><para>Do not pipe output into a + pager.</para></listitem> + </varlistentry> + + <varlistentry> <term><option>--system</option></term> <listitem><para>Talk to the systemd diff --git a/src/systemctl.c b/src/systemctl.c index 4768fb20ad..585f1dc5fe 100644 --- a/src/systemctl.c +++ b/src/systemctl.c @@ -65,6 +65,7 @@ static bool arg_user = false; static bool arg_global = false; static bool arg_immediate = false; static bool arg_no_block = false; +static bool arg_no_pager = false; static bool arg_no_wtmp = false; static bool arg_no_sync = false; static bool arg_no_wall = false; @@ -4110,6 +4111,7 @@ static int systemctl_help(void) { " pending\n" " -q --quiet Suppress output\n" " --no-block Do not wait until operation finished\n" + " --no-pager Do not pipe output into a pager.\n" " --system Connect to system manager\n" " --user Connect to user service manager\n" " --order When generating graph for dot, show only order\n" @@ -4249,6 +4251,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { ARG_SYSTEM, ARG_GLOBAL, ARG_NO_BLOCK, + ARG_NO_PAGER, ARG_NO_WALL, ARG_ORDER, ARG_REQUIRE, @@ -4272,6 +4275,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { { "system", no_argument, NULL, ARG_SYSTEM }, { "global", no_argument, NULL, ARG_GLOBAL }, { "no-block", no_argument, NULL, ARG_NO_BLOCK }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, { "no-wall", no_argument, NULL, ARG_NO_WALL }, { "quiet", no_argument, NULL, 'q' }, { "order", no_argument, NULL, ARG_ORDER }, @@ -4348,6 +4352,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) { arg_no_block = true; break; + case ARG_NO_PAGER: + arg_no_pager = true; + break; + case ARG_NO_WALL: arg_no_wall = true; break; @@ -5274,6 +5282,48 @@ static int runlevel_main(void) { return 0; } +static void pager_open(void) { + pid_t pid; + int fd[2]; + const char *pager = getenv("PAGER"); + + if (!on_tty() || arg_no_pager) + return; + if (!pager) + pager = "less"; + else if (!*pager || !strcmp(pager, "cat")) + return; + + if (pipe(fd) < 0) + return; + pid = fork(); + if (pid < 0) { + close(fd[0]); + close(fd[1]); + return; + } + + /* Return in the child */ + if (!pid) { + dup2(fd[1], 1); + close(fd[0]); + close(fd[1]); + return; + } + + /* The original process turns into the PAGER */ + dup2(fd[0], 0); + close(fd[0]); + close(fd[1]); + + setenv("LESS", "FRSX", 0); + execlp(pager, pager, NULL); + execl("/bin/sh", "sh", "-c", pager, NULL); + + log_error("unable to execute pager '%s'", pager); + _exit(EXIT_FAILURE); +} + int main(int argc, char*argv[]) { int r, retval = EXIT_FAILURE; DBusConnection *bus = NULL; @@ -5291,6 +5341,8 @@ int main(int argc, char*argv[]) { goto finish; } + pager_open(); + /* /sbin/runlevel doesn't need to communicate via D-Bus, so * let's shortcut this */ if (arg_action == ACTION_RUNLEVEL) { |