$OpenBSD: patch-ls_c,v 1.15 2015/10/30 14:12:42 bentley Exp $
--- ls.c.orig	Mon Mar 31 14:54:37 2014
+++ ls.c	Thu Oct 29 01:00:04 2015
@@ -42,12 +42,17 @@
 #include <errno.h>
 #include <fts.h>
 #include <grp.h>
+#include <locale.h>
 #include <pwd.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #include <util.h>
+#ifdef COLORLS
+#include <termcap.h>
+#include <signal.h>
+#endif
 
 #include "ls.h"
 #include "extern.h"
@@ -90,6 +95,15 @@ int f_statustime;		/* use time of last mode change */
 int f_stream;			/* stream format */
 int f_type;			/* add type character for non-regular files */
 int f_typedir;			/* add type character for directories */
+#ifdef COLORLS
+int f_color;			/* add type in color for non-regular files */
+ 
+char *ansi_bgcol;		/* ANSI sequence to set background color */
+char *ansi_fgcol;		/* ANSI sequence to set foreground color */
+char *ansi_coloff;		/* ANSI sequence to reset colors */
+char *attrs_off;		/* ANSI sequence to turn off attributes */
+char *enter_bold;		/* ANSI sequence to set color to bold mode */
+#endif
 
 int rval;
 
@@ -101,7 +115,14 @@ ls_main(int argc, char *argv[])
 	int ch, fts_options, notused;
 	int kflag = 0;
 	char *p;
+#ifdef COLORLS
+	char termcapbuf[1024];	/* termcap definition buffer */
+	char tcapbuf[512];	/* capability buffer */
+	char *bp = tcapbuf;
+#endif
 
+	setlocale(LC_CTYPE, "");
+
 	/* Terminal defaults to -Cq, non-terminal defaults to -1. */
 	if (isatty(STDOUT_FILENO)) {
 		if ((p = getenv("COLUMNS")) != NULL)
@@ -122,7 +143,7 @@ ls_main(int argc, char *argv[])
 		f_listdot = 1;
 
 	fts_options = FTS_PHYSICAL;
-	while ((ch = getopt(argc, argv, "1ACFHLRSTacdfghiklmnopqrstux")) != -1) {
+	while ((ch = getopt(argc, argv, "1ACFGHLRSTacdfghiklmnopqrstux")) != -1) {
 		switch (ch) {
 		/*
 		 * The -1, -C and -l, -m, -n and -x options all override each
@@ -176,6 +197,9 @@ ls_main(int argc, char *argv[])
 		case 'F':
 			f_type = 1;
 			break;
+		case 'G':
+			setenv("CLICOLOR", "", 1);
+			break;
 		case 'H':
 			fts_options |= FTS_COMFOLLOW;
 			break;
@@ -248,19 +272,59 @@ ls_main(int argc, char *argv[])
 	if (f_grouponly == -1)
 		f_grouponly = 0;
 
+	/* Enabling of colours is conditional on the environment. */
+	if (getenv("CLICOLOR") &&
+	    (isatty(STDOUT_FILENO) || getenv("CLICOLOR_FORCE")))
+#ifdef COLORLS
+		if (tgetent(termcapbuf, getenv("TERM")) == 1) {
+			ansi_fgcol = tgetstr("AF", &bp);
+			ansi_bgcol = tgetstr("AB", &bp);
+			attrs_off = tgetstr("me", &bp);
+			enter_bold = tgetstr("md", &bp);
+
+			/* To switch colours off use 'op' if
+			 * available, otherwise use 'oc', or
+			 * don't do colours at all. */
+			ansi_coloff = tgetstr("op", &bp);
+			if (!ansi_coloff)
+				ansi_coloff = tgetstr("oc", &bp);
+			if (ansi_fgcol && ansi_bgcol && ansi_coloff)
+				f_color = 1;
+		}
+#else
+		warnx("color support not compiled in");
+#endif /*COLORLS*/
+ 
+#ifdef COLORLS
+	if (f_color) {
+		(void)signal(SIGINT, colorquit);
+		(void)signal(SIGQUIT, colorquit);
+		parsecolors(getenv("LSCOLORS"));
+	}
+#endif
+
 	/*
 	 * If not -F, -i, -l, -p, -S, -s or -t options, don't require stat
-	 * information.
+	 * information, unless in color mode in which case we do
+	 * need this to determine which colors to display.
 	 */
 	if (!f_longform && !f_inode && !f_size && !f_type && !f_typedir &&
+#ifdef COLORLS
+	    !f_color &&
+#endif
 	    sortkey == BY_NAME)
 		fts_options |= FTS_NOSTAT;
 
 	/*
 	 * If not -F, -d or -l options, follow any symbolic links listed on
-	 * the command line.
+	 * the command line, unless in color mode in which case we need to
+	 * distinguish file type for a symbolic link itself and its target.
 	 */
-	if (!f_longform && !f_listdir && !f_type)
+	if (!f_longform && !f_listdir && !f_type
+#ifdef COLORLS
+	    && !f_color
+#endif
+	    )
 		fts_options |= FTS_COMFOLLOW;
 
 	/* If -l or -s, figure out block size. */
@@ -463,8 +527,8 @@ display(FTSENT *p, FTSENT *list)
 				continue;
 			}
 		}
-		if (cur->fts_namelen > maxlen)
-			maxlen = cur->fts_namelen;
+		if (strwidth(cur->fts_name) > maxlen)
+			maxlen = strwidth(cur->fts_name);
 		if (needstats) {
 			sp = cur->fts_statp;
 			if (sp->st_blocks > maxblock)
