[PATCH] ls: Don't output any colors with TERM=dumb

soeren at soeren-tempel.net soeren at soeren-tempel.net
Sun May 23 12:14:10 UTC 2021


From: Sören Tempel <soeren+git at soeren-tempel.net>

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.

The implementation includes a new libbb function is_dumb_term() since
(a) this code may be useful in other applets (e.g. busybox ash) which
also use ANSI escape sequences unconditionally and (b) it makes it
easier to add additional heuristics for identifying dumb terminals in
the future.
---
 coreutils/ls.c  | 4 ++--
 include/libbb.h | 1 +
 libbb/xfuncs.c  | 6 ++++++
 3 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/coreutils/ls.c b/coreutils/ls.c
index 80ef92079..a11a92456 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -1145,7 +1145,7 @@ 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 && isatty(STDOUT_FILENO) && !is_dumb_term()) {
 		char *p = getenv("LS_COLORS");
 		/* LS_COLORS is unset, or (not empty && not "none") ? */
 		if (!p || (p[0] && strcmp(p, "none") != 0))
@@ -1158,7 +1158,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
 		case 3:
 		case 4:
 		case 5:
-			if (isatty(STDOUT_FILENO)) {
+			if (isatty(STDOUT_FILENO) && !is_dumb_term()) {
 		case 0:
 		case 1:
 		case 2:
diff --git a/include/libbb.h b/include/libbb.h
index 03f9c35f3..9085a05e9 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_dumb_term(void);
 /* 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);


More information about the busybox mailing list