man: make width selection more thorough; explain how to override it
authorDenys Vlasenko <vda.linux@googlemail.com>
Mon, 31 Oct 2016 00:52:18 +0000 (01:52 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Mon, 31 Oct 2016 00:52:18 +0000 (01:52 +0100)
Fedora's "man CMD >file" still uses terminal width, not 80 (but disables formatting),
this change mimics that.

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
libbb/xfuncs.c
miscutils/man.c

index 3f9a84ad4915ece662a02f337cfb4b36da14c476..45650edba528c58168656adacc314b71275f3062 100644 (file)
@@ -237,16 +237,27 @@ ssize_t FAST_FUNC full_write2_str(const char *str)
 
 static int wh_helper(int value, int def_val, const char *env_name, int *err)
 {
-       if (value == 0) {
-               char *s = getenv(env_name);
-               if (s) {
-                       value = atoi(s);
-                       /* If LINES/COLUMNS are set, pretend that there is
-                        * no error getting w/h, this prevents some ugly
-                        * cursor tricks by our callers */
-                       *err = 0;
-               }
+       /* Envvars override even if "value" from ioctl is valid (>0).
+        * Rationale: it's impossible to guess what user wants.
+        * For example: "man CMD | ...": should "man" format output
+        * to stdout's width? stdin's width? /dev/tty's width? 80 chars?
+        * We _cant_ know it. If "..." saves text for e.g. email,
+        * then it's probably 80 chars.
+        * If "..." is, say, "grep -v DISCARD | $PAGER", then user
+        * would prefer his tty's width to be used!
+        *
+        * Since we don't know, at least allow user to do this:
+        * "COLUMNS=80 man CMD | ..."
+        */
+       char *s = getenv(env_name);
+       if (s) {
+               value = atoi(s);
+               /* If LINES/COLUMNS are set, pretend that there is
+                * no error getting w/h, this prevents some ugly
+                * cursor tricks by our callers */
+               *err = 0;
        }
+
        if (value <= 1 || value >= 30000)
                value = def_val;
        return value;
@@ -258,6 +269,20 @@ int FAST_FUNC get_terminal_width_height(int fd, unsigned *width, unsigned *heigh
 {
        struct winsize win;
        int err;
+       int close_me = -1;
+
+       if (fd == -1) {
+               if (isatty(STDOUT_FILENO))
+                       fd = STDOUT_FILENO;
+               else
+               if (isatty(STDERR_FILENO))
+                       fd = STDERR_FILENO;
+               else
+               if (isatty(STDIN_FILENO))
+                       fd = STDIN_FILENO;
+               else
+                       close_me = fd = open("/dev/tty", O_RDONLY);
+       }
 
        win.ws_row = 0;
        win.ws_col = 0;
@@ -268,6 +293,10 @@ int FAST_FUNC get_terminal_width_height(int fd, unsigned *width, unsigned *heigh
                *height = wh_helper(win.ws_row, 24, "LINES", &err);
        if (width)
                *width = wh_helper(win.ws_col, 80, "COLUMNS", &err);
+
+       if (close_me >= 0)
+               close(close_me);
+
        return err;
 }
 int FAST_FUNC get_terminal_width(int fd)
index 01382c4d7197ab4b9db84f793c3991a3b33e925f..adb7770b48c2e115fe10547cc916cd3ce78f6007 100644 (file)
@@ -9,6 +9,8 @@
 //usage:       "Format and display manual page\n"
 //usage:     "\n       -a      Display all pages"
 //usage:     "\n       -w      Show page locations"
+//usage:     "\n"
+//usage:     "\n$COLUMNS overrides output width"
 
 #include "libbb.h"
 #include "common_bufsiz.h"
@@ -53,7 +55,7 @@ struct globals {
        setup_common_bufsiz(); \
        G.col = "col"; \
        G.tbl = "tbl"; \
-       /* replaced -Tlatin1 with -Tascii for non-UTF8 displays */; \
+       /* replaced -Tlatin1 with -Tascii for non-UTF8 displays */ \
        G.nroff = "nroff -mandoc -Tascii"; \
        G.pager = ENABLE_LESS ? "less" : "more"; \
 } while (0)
@@ -132,15 +134,12 @@ static int run_pipe(char *man_filename, int man, int level)
        close(STDIN_FILENO);
        open_zipped(man_filename, /*fail_if_not_compressed:*/ 0); /* guaranteed to use fd 0 (STDIN_FILENO) */
        if (man) {
-               /* "man man" formats to screen width.
-                * "man man >file" formats to default 80 columns.
-                * "man man | cat" formats to default 80 columns.
-                */
-               int w = get_terminal_width(STDOUT_FILENO);
+               int w = get_terminal_width(-1);
                if (w > 10)
                        w -= 2;
                /* "2>&1" is added so that nroff errors are shown in pager too.
-                * Otherwise it may show just empty screen */
+                * Otherwise it may show just empty screen.
+                */
                cmd = xasprintf("%s | %s -rLL=%un -rLT=%un 2>&1 | %s",
                                G.tbl, G.nroff, w, w,
                                G.pager);