X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fshared%2Fpager.c;h=f1f3dc7e7edb41a3c5d9320ffa02b7557efe5217;hb=3b22396a4b2767a98172f6915929c47738cb0a1e;hp=b2635740f2ae4430887fc5a168e776394806c508;hpb=1cfc78c91965df340cdde100ad6cb3ed50b28927;p=elogind.git diff --git a/src/shared/pager.c b/src/shared/pager.c index b2635740f..f1f3dc7e7 100644 --- a/src/shared/pager.c +++ b/src/shared/pager.c @@ -31,18 +31,16 @@ #include "macro.h" #include "terminal-util.h" #include "signal-util.h" +#include "copy.h" static pid_t pager_pid = 0; noreturn static void pager_fallback(void) { - ssize_t n; - - do { - n = splice(STDIN_FILENO, NULL, STDOUT_FILENO, NULL, 64*1024, 0); - } while (n > 0); + int r; - if (n < 0) { - log_error_errno(errno, "Internal pager failed: %m"); + r = copy_bytes(STDIN_FILENO, STDOUT_FILENO, (off_t) -1, false); + if (r < 0) { + log_error_errno(r, "Internal pager failed: %m"); _exit(EXIT_FAILURE); } @@ -84,7 +82,7 @@ int pager_open(bool jump_to_end) { /* In the child start the pager */ if (pager_pid == 0) { - const char* less_opts; + const char* less_opts, *less_charset; (void) reset_all_signal_handlers(); (void) reset_signal_mask(); @@ -92,6 +90,7 @@ int pager_open(bool jump_to_end) { dup2(fd[0], STDIN_FILENO); safe_close_pair(fd); + /* Initialize a good set of less options */ less_opts = getenv("SYSTEMD_LESS"); if (!less_opts) less_opts = "FRSXMK"; @@ -99,6 +98,15 @@ int pager_open(bool jump_to_end) { less_opts = strjoina(less_opts, " +G"); setenv("LESS", less_opts, 1); + /* Initialize a good charset for less. This is + * particularly important if we output UTF-8 + * characters. */ + less_charset = getenv("SYSTEMD_LESSCHARSET"); + if (!less_charset && is_locale_utf8()) + less_charset = "utf-8"; + if (less_charset) + setenv("LESSCHARSET", less_charset, 1); + /* Make sure the pager goes away when the parent dies */ if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0) _exit(EXIT_FAILURE); @@ -131,6 +139,8 @@ int pager_open(bool jump_to_end) { /* Return in the parent */ if (dup2(fd[1], STDOUT_FILENO) < 0) return log_error_errno(errno, "Failed to duplicate pager pipe: %m"); + if (dup2(fd[1], STDERR_FILENO) < 0) + return log_error_errno(errno, "Failed to duplicate pager pipe: %m"); safe_close_pair(fd); return 1; @@ -143,6 +153,15 @@ void pager_close(void) { /* Inform pager that we are done */ fclose(stdout); +#if defined(__GLIBC__) + stdout = NULL; +#endif // in musl-libc this is a const + + fclose(stderr); +#if defined(__GLIBC__) + stderr = NULL; +#endif // in musl-libc this is a const + kill(pager_pid, SIGCONT); (void) wait_for_terminate(pager_pid, NULL); pager_pid = 0;