From 3d9c64915810cf684d75c8697b42e30c14011324 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren=20Tempel?= Date: Sun, 23 May 2021 14:14:10 +0200 Subject: [PATCH] ls: don't output any colors with TERM=dumb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The TERM variable is usually set to "dumb" to indicate that the terminal does not support any ANSI escape sequences. Presently, ls does not honor this variable and outputs colors anyhow which results in unreadable output, unless the user explicitly disables colors using `ls --color=never`. The rational behind this change is that ls should "just work" by default, even on dumb terminals. For this reason, this patch adds a check which additionally consults the TERM variable before printing any colors. This is analogous to the existing check for ensuring that standard output is a tty. As such, colors can still be forced with `--color=force`, even if TERM is set to dumb. function old new delta is_TERM_dumb - 40 +40 ls_main 579 598 +19 .rodata 103246 103251 +5 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 2/0 up/down: 64/0) Total: 64 bytes Signed-off-by: Sören Tempel Signed-off-by: Denys Vlasenko --- coreutils/ls.c | 12 ++++++++---- include/libbb.h | 1 + libbb/xfuncs.c | 6 ++++++ 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/coreutils/ls.c b/coreutils/ls.c index 80ef92079..1f7d7f7bf 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c @@ -1145,11 +1145,15 @@ int ls_main(int argc UNUSED_PARAM, char **argv) #if ENABLE_FEATURE_LS_COLOR /* set G_show_color = 1/0 */ - if (ENABLE_FEATURE_LS_COLOR_IS_DEFAULT && isatty(STDOUT_FILENO)) { + if (ENABLE_FEATURE_LS_COLOR_IS_DEFAULT && !is_TERM_dumb()) { char *p = getenv("LS_COLORS"); /* LS_COLORS is unset, or (not empty && not "none") ? */ - if (!p || (p[0] && strcmp(p, "none") != 0)) - G_show_color = 1; + if (!p || (p[0] && strcmp(p, "none") != 0)) { + if (isatty(STDOUT_FILENO)) { + /* check isatty() last because it's expensive (syscall) */ + G_show_color = 1; + } + } } if (opt & OPT_color) { if (color_opt[0] == 'n') @@ -1158,7 +1162,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv) case 3: case 4: case 5: - if (isatty(STDOUT_FILENO)) { + if (!is_TERM_dumb() && isatty(STDOUT_FILENO)) { case 0: case 1: case 2: diff --git a/include/libbb.h b/include/libbb.h index 03f9c35f3..4c9c83bd1 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1773,6 +1773,7 @@ extern void print_login_issue(const char *issue_file, const char *tty) FAST_FUNC extern void print_login_prompt(void) FAST_FUNC; char *xmalloc_ttyname(int fd) FAST_FUNC RETURNS_MALLOC; +int is_TERM_dumb(void) FAST_FUNC; /* NB: typically you want to pass fd 0, not 1. Think 'applet | grep something' */ int get_terminal_width_height(int fd, unsigned *width, unsigned *height) FAST_FUNC; int get_terminal_width(int fd) FAST_FUNC; diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c index d93d8aaf5..c81ce4546 100644 --- a/libbb/xfuncs.c +++ b/libbb/xfuncs.c @@ -303,6 +303,12 @@ int FAST_FUNC get_terminal_width(int fd) return width; } +int FAST_FUNC is_dumb_term(void) +{ + char *term = getenv("TERM"); + return term && strcmp(term, "dumb") == 0; +} + int FAST_FUNC tcsetattr_stdin_TCSANOW(const struct termios *tp) { return tcsetattr(STDIN_FILENO, TCSANOW, tp);