From andre.albsmeier@mchp.siemens.de  Tue May 30 03:13:28 2000
Return-Path: <andre.albsmeier@mchp.siemens.de>
Received: from david.siemens.de (david.siemens.de [192.35.17.14])
	by hub.freebsd.org (Postfix) with ESMTP id 40B7A37B5A4
	for <FreeBSD-gnats-submit@freebsd.org>; Tue, 30 May 2000 03:13:27 -0700 (PDT)
	(envelope-from andre.albsmeier@mchp.siemens.de)
Received: from mail1.siemens.de (mail1.siemens.de [139.23.33.14])
	by david.siemens.de (8.10.1/8.10.1) with ESMTP id e4UADKR14768
	for <FreeBSD-gnats-submit@freebsd.org>; Tue, 30 May 2000 12:13:20 +0200 (MET DST)
Received: from curry.mchp.siemens.de (curry.mchp.siemens.de [139.25.42.7])
	by mail1.siemens.de (8.10.1/8.10.1) with ESMTP id e4UADJO07139
	for <FreeBSD-gnats-submit@freebsd.org>; Tue, 30 May 2000 12:13:19 +0200 (MET DST)
Received: (from localhost)
	by curry.mchp.siemens.de (8.10.1/8.10.1) id e4UADJs60084
	for FreeBSD-gnats-submit@freebsd.org; Tue, 30 May 2000 12:13:19 +0200 (CEST)
Message-Id: <200005301013.e4UADJd69846@curry.mchp.siemens.de>
Date: Tue, 30 May 2000 12:13:19 +0200 (CEST)
From: Andre Albsmeier <andre.albsmeier@mchp.siemens.de>
To: FreeBSD-gnats-submit@freebsd.org
Subject: patch to add colorizing feature to /bin/ls
X-Send-Pr-Version: 3.2

>Number:         18900
>Category:       bin
>Synopsis:       patch to add colorizing feature to /bin/ls
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Tue May 30 03:20:01 PDT 2000
>Closed-Date:    Fri Jun 2 08:19:44 PDT 2000
>Last-Modified:  Fri Jun 02 08:21:58 PDT 2000
>Originator:     Andre Albsmeier
>Release:        FreeBSD 3.4-STABLE i386
>Organization:
>Environment:

All FreeBSD versions

>Description:

The misc/colorls port adds the colorizing feature to ls and
installs the resulting executable as colorls.

It would be nice to have this feature in /bin/ls so other changes
to /bin/ls don't have to be ported to the distfile on which
the misc/colorls port relies.

The patch below adds this feature to /bin/ls. It is based on
patch-aa from the port with some minor changes to make -Wall
quiet. The manpage has been updated as well.

The colorizing feature is only used if -G has been specified.
Otherwise, /bin/ls behaves completely as it did before. All the
colorizing code is only enabled if the f_color variable has been
set by the -G command line option.

The resulting /bin/ls is 195720 bytes in size. It has been
194568 bytes before so the difference is only 1152 bytes
which should be acceptable even for a file in /bin :-).

>How-To-Repeat:

/bin/ls -lG /

>Fix:
	
Since I am currently sitting in the Dominican Republic with my
laptop, I have only access to the 3.4-STABLE sources. So the
patch is based on 3.4-STABLE but I don't think /bin/ls differs
a lot between the various versions of FreeBSD.

If you want me to make a patch against -current or 4-STABLE, I
will do so if this helps getting it commited.

--- ./ls.c.ORI	Sat May 27 15:38:56 2000
+++ ./ls.c	Sat May 27 15:56:57 2000
@@ -100,6 +100,7 @@
 int f_timesort;			/* sort by time vice name */
 int f_type;			/* add type character for non-regular files */
 int f_whiteout;			/* show whiteout entries */
+int f_color;			/* add type in color for non-regular files */
 
 int rval;
 
@@ -137,7 +138,7 @@
 		f_listdot = 1;
 
 	fts_options = FTS_PHYSICAL;
-	while ((ch = getopt(argc, argv, "1ABCFHLPRTWabcdfgikloqrstu")) != -1) {
+	while ((ch = getopt(argc, argv, "1ABCFGHLPRTWabcdfgikloqrstu")) != -1) {
 		switch (ch) {
 		/*
 		 * The -1, -C and -l options all override each other so shell
@@ -175,6 +176,10 @@
 		case 'H':
 		        fts_options |= FTS_COMFOLLOW;
 			break;
+		case 'G':
+			if (isatty(STDOUT_FILENO))
+				f_color = 1;
+			break;
 		case 'L':
 			fts_options &= ~FTS_PHYSICAL;
 			fts_options |= FTS_LOGICAL;
@@ -245,18 +250,22 @@
 	argc -= optind;
 	argv += optind;
 
+	if (f_color)
+		parsecolors(getenv("LSCOLORS"));
+
 	/*
 	 * If not -F, -i, -l, -s or -t options, don't require stat
 	 * information.
 	 */
-	if (!f_inode && !f_longform && !f_size && !f_timesort && !f_type)
+	if (!f_inode && !f_longform && !f_size && !f_timesort && !f_type
+	    && !f_color)
 		fts_options |= FTS_NOSTAT;
 
 	/*
 	 * If not -F, -d or -l options, follow any symbolic links listed on
 	 * the command line.
 	 */
-	if (!f_longform && !f_listdir && !f_type)
+	if (!f_longform && !f_listdir && !f_type && !f_color)
 		fts_options |= FTS_COMFOLLOW;
 
 	/*
--- ./print.c.ORI	Sat May 27 15:39:04 2000
+++ ./print.c	Sat May 27 15:54:26 2000
@@ -56,6 +56,7 @@
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
+#include <ctype.h>
 
 #include "ls.h"
 #include "extern.h"
@@ -67,6 +68,26 @@
 
 #define	IS_NOPRINT(p)	((p)->fts_number == NO_PRINT)
 
+/* Most of these are taken from <sys/stat.h> */
+typedef enum Colors {
+    C_DIR,     /* directory */
+    C_LNK,     /* symbolic link */
+    C_SOCK,    /* socket */
+    C_FIFO,    /* pipe */
+    C_EXEC,    /* executable */
+    C_BLK,     /* block special */
+    C_CHR,     /* character special */
+    C_SUID,    /* setuid executable */
+    C_SGID,    /* setgid executable */
+    C_WSDIR,   /* directory writeble to others, with sticky bit */
+    C_WDIR,    /* directory writeble to others, without sticky bit */
+    C_NUMCOLORS        /* just a place-holder */
+} Colors ;
+
+char *defcolors = "4x5x2x3x1x464301060203";
+
+static int colors[C_NUMCOLORS][2];
+
 void
 printscol(dp)
 	DISPLAY *dp;
@@ -127,10 +148,14 @@
 			printtime(sp->st_ctime);
 		else
 			printtime(sp->st_mtime);
+		if (f_color)
+			(void)colortype(sp->st_mode);
 		if (f_octal || f_octal_escape) (void)prn_octal(p->fts_name);
 		else (void)printf("%s", p->fts_name);
 		if (f_type)
 			(void)printtype(sp->st_mode);
+		if (f_color)
+			(void)printf("\033[m");
 		if (S_ISLNK(sp->st_mode))
 			printlink(p);
 		(void)putchar('\n');
@@ -198,6 +223,16 @@
 			    dp->s_block);
 			if ((base += numrows) >= num)
 				break;
+			/*
+			 * some terminals get confused if we mix tabs
+			 * with color sequences
+			 */
+			if (f_color)
+				while ((cnt = (chcnt + 1)) <= endcol) {
+					(void)putchar(' ');
+					chcnt = cnt;
+				}
+			else
 			while ((cnt = ((chcnt + tabwidth) & ~(tabwidth - 1)))
 			    <= endcol){
 				(void)putchar(f_notabs ? ' ' : '\t');
@@ -228,8 +263,12 @@
 	if (f_size)
 		chcnt += printf("%*qd ",
 		    (int)sizefield, howmany(sp->st_blocks, blocksize));
+	if (f_color)
+		(void)colortype(sp->st_mode);
 	chcnt += (f_octal || f_octal_escape) ? prn_octal(p->fts_name)
 	                                     : printf("%s", p->fts_name);
+	if (f_color)
+		printf("\033[m");
 	if (f_type)
 		chcnt += printtype(sp->st_mode);
 	return (chcnt);
@@ -293,6 +332,96 @@
 	return (0);
 }
 
+void
+printcolor(c)
+       Colors c;
+{
+	printf("\033[");
+	if (colors[c][0] != -1) {
+		printf("3%d", colors[c][0]);
+		if (colors[c][1] != -1)
+		    printf(";");
+	}
+	if (colors[c][1] != -1)
+	    printf("4%d", colors[c][1]);
+	printf("m");
+}
+
+int
+colortype(mode)
+       mode_t mode;
+{
+	switch(mode & S_IFMT) {
+	      case S_IFDIR:
+		if (mode & S_IWOTH)
+		    if (mode & S_ISTXT)
+			printcolor(C_WSDIR);
+		    else
+			printcolor(C_WDIR);
+		else
+		    printcolor(C_DIR);
+		return(1);
+	      case S_IFLNK:
+		printcolor(C_LNK);
+		return(1);
+	      case S_IFSOCK:
+		printcolor(C_SOCK);
+		return(1);
+	      case S_IFIFO:
+		printcolor(C_FIFO);
+		return(1);
+	      case S_IFBLK:
+		printcolor(C_BLK);
+		return(1);
+	      case S_IFCHR:
+		printcolor(C_CHR);
+		return(1);
+	}
+	if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
+		if (mode & S_ISUID)
+		    printcolor(C_SUID);
+		else if (mode & S_ISGID)
+		    printcolor(C_SGID);
+		else
+		    printcolor(C_EXEC);
+		return(1);
+	}
+	return(0);
+}
+
+void
+parsecolors(cs)
+char *cs;
+{
+	int i, j, len;
+	char c[2];
+	if (cs == NULL)    cs = ""; /* LSCOLORS not set */
+	len = strlen(cs);
+	for (i = 0 ; i < C_NUMCOLORS ; i++) {
+		if (len <= 2*i) {
+			c[0] = defcolors[2*i];
+			c[1] = defcolors[2*i+1];
+		}
+		else {
+			c[0] = cs[2*i];
+			c[1] = cs[2*i+1];
+		}
+		for (j = 0 ; j < 2 ; j++) {
+			if ((c[j] < '0' || c[j] > '7') &&
+			    tolower(c[j]) != 'x') {
+				fprintf(stderr,
+					"error: invalid character '%c' in LSCOLORS env var\n",
+					c[j]);
+				c[j] = defcolors[2*i+j];
+			}
+			if (c[j] == 'x')
+			    colors[i][j] = -1;
+			else
+			    colors[i][j] = c[j]-'0';
+		}
+	}
+}
+ 
 static void
 printlink(p)
 	FTSENT *p;
--- ./extern.h.ORI	Sat May 27 15:47:33 2000
+++ ./extern.h	Sat May 27 15:54:31 2000
@@ -51,3 +51,5 @@
 void	 usage __P((void));
 int	 len_octal __P((char *, int));
 int	 prn_octal __P((char *));
+void	 parsecolors __P((char *cs));
+int	 colortype __P((mode_t mode));
--- ./ls.h.ORI	Sat May 27 15:48:33 2000
+++ ./ls.h	Sat May 27 16:47:16 2000
@@ -53,6 +53,7 @@
 extern int f_statustime;	/* use time of last mode change */
 extern int f_notabs;		/* don't use tab-separated multi-col output */
 extern int f_type;		/* add type character for non-regular files */
+extern int f_color;		/* add type in color for non-regular files */
 
 typedef struct {
 	FTSENT *list;
--- ./ls.1.ORI	Sat May 27 15:58:18 2000
+++ ./ls.1	Sat May 27 16:03:02 2000
@@ -43,7 +43,7 @@
 .Nd list directory contents
 .Sh SYNOPSIS
 .Nm ls
-.Op Fl ABCFHLPRTWabcdfgikloqrstu1
+.Op Fl ABCFGHLPRTWabcdfgikloqrstu1
 .Op Ar file ...
 .Sh DESCRIPTION
 For each operand that names a
@@ -90,6 +90,12 @@
 a percent sign (%) after each whiteout,
 and a vertical bar (|) after each that is a
 .Tn FIFO .
+.It Fl G
+Use ANSI color sequences to distinguish file types. (See
+.Ev LSCOLORS
+below.) In addition to those mentioned above in
+.Fl F ,
+some extra attributes (setuid bit set, etc.) are also displayed.
 .It Fl H
 Symbolic links on the command line are followed.  This option is assumed if
 none of the
@@ -378,6 +384,74 @@
 See
 .Xr environ 7
 for more information.
+.It LSCOLORS
+The value of this variable describes what color to use for which
+attribute when the color output
+.Pq Fl G
+is specified.  This string is a concatenation of pairs of the format
+.Sy fb ,
+where
+.Sy f
+is the foreground color and
+.Sy b
+is the background color.
+.Pp
+The color designators are as follows:
+.Pp
+.Bl -tag -width 4n -offset indent -compact
+.It Sy 0
+black
+.It Sy 1
+red
+.It Sy 2
+green
+.It Sy 3
+yellow
+.It Sy 4
+blue
+.It Sy 5
+magenta
+.It Sy 6
+cyan
+.It Sy 7
+white
+.It Sy x
+default foreground or background
+.El
+.Pp
+(Note: the above are standard ANSI colors.  The actual display may
+differ depending on the color capabilities of your terminal.)
+.Pp
+The order of the attributes are as follows:
+.Pp
+.Bl -enum -offset indent -compact
+.It
+directory
+.It
+symbolic link
+.It
+socket
+.It
+pipe
+.It
+executable
+.It
+block special
+.It
+character special
+.It
+executable with setuid bit set
+.It
+executable with setgid bit set
+.It
+directory writable to others, with sticky bit
+.It
+directory writable to others, without sticky bit
+.El
+.Pp
+The default is "4x5x2x3x1x464301060203", i.e., blue foreground and
+default background for regular directories, black foreground and red
+background for setuid executables, etc.
 .It Ev LS_COLWIDTHS
 If this variable is set, it is considered to be a
 colon-delimited list of minimum column widths.  Unreasonable

>Release-Note:
>Audit-Trail:

From: Doug Barton <DougB@gorean.org>
To: Andre Albsmeier <andre.albsmeier@mchp.siemens.de>
Cc: FreeBSD-gnats-submit@freebsd.org
Subject: Re: bin/18900: patch to add colorizing feature to /bin/ls
Date: Tue, 30 May 2000 08:32:13 -0700

 [snippage]
 
 Andre Albsmeier wrote:
 
 > The misc/colorls port adds the colorizing feature to ls and
 > installs the resulting executable as colorls.
 > 
 > It would be nice to have this feature in /bin/ls so other changes
 > to /bin/ls don't have to be ported to the distfile on which
 > the misc/colorls port relies.
 
 > The resulting /bin/ls is 195720 bytes in size. It has been
 > 194568 bytes before so the difference is only 1152 bytes
 > which should be acceptable even for a file in /bin :-).
 
 	For some absurd reason, including this in the base system has, in the
 past been some sort of religious war. It's high time for the aburdity to
 end. The facts about this are simple:
 
 Many people want it.
 If YOU don't want it, YOU don't have to use it. 
 We have a good, working version.
 Looking at the current state of things, it adds almost nothing to the
 3.5 megs of binaries in /bin. 
 
 	This patch applies to -Current, but needs a small adjustment to account
 for the -n option. 
 
 Doug
 -- 
         "Live free or die"
 		- State motto of my ancestral homeland, New Hampshire
 
 	Do YOU Yahoo!?
 

From: Andre Albsmeier <andre.albsmeier@mchp.siemens.de>
To: Doug Barton <DougB@gorean.org>
Cc: Andre Albsmeier <andre.albsmeier@mchp.siemens.de>,
	FreeBSD-gnats-submit@freebsd.org
Subject: Re: bin/18900: patch to add colorizing feature to /bin/ls
Date: Tue, 30 May 2000 19:00:58 +0200

 On Tue, 30-May-2000 at 08:32:13 -0700, Doug Barton wrote:
 > [snippage]
 > 
 > Andre Albsmeier wrote:
 > 
 > > The misc/colorls port adds the colorizing feature to ls and
 > > installs the resulting executable as colorls.
 > > 
 > > It would be nice to have this feature in /bin/ls so other changes
 > > to /bin/ls don't have to be ported to the distfile on which
 > > the misc/colorls port relies.
 > 
 > > The resulting /bin/ls is 195720 bytes in size. It has been
 > > 194568 bytes before so the difference is only 1152 bytes
 > > which should be acceptable even for a file in /bin :-).
 > 
 > 	For some absurd reason, including this in the base system has, in the
 > past been some sort of religious war. It's high time for the aburdity to
 
 Oops, it didn't know that. I follow FreeBSD for 4 years now and never
 saw discussion about this :-)
 
 > end. The facts about this are simple:
 > 
 > Many people want it.
 > If YOU don't want it, YOU don't have to use it. 
 > We have a good, working version.
 > Looking at the current state of things, it adds almost nothing to the
 > 3.5 megs of binaries in /bin. 
 
 So, what does us keep from committing it :-) ?
 
 > 
 > 	This patch applies to -Current, but needs a small adjustment to account
 > for the -n option. 
 
 Ahh, I see. There are two small rejections in ls.1 and ls.c which are
 easily fixable.
 
 	-Andre
 
 
 > 
 > Doug
 > -- 
 >         "Live free or die"
 > 		- State motto of my ancestral homeland, New Hampshire
 > 
 > 	Do YOU Yahoo!?
 
 -- 
 Micro$oft: Which virus will you get today?
 

From: Tim Vanderhoek <vanderh@ecf.utoronto.ca>
To: Brian Somers <brian@Awfulhak.org>
Cc: Doug Barton <Doug@gorean.org>, brian@hak.lan.Awfulhak.org,
	freebsd-gnats-submit@FreeBSD.org
Subject: Re: bin/18900: patch to add colorizing feature to /bin/ls
Date: Tue, 30 May 2000 23:27:03 -0400

 On Wed, May 31, 2000 at 02:05:54AM +0100, Brian Somers wrote:
 > > 
 > > 	So, other than on "purist" grounds, are there any other
 > > objections?
 > 
 > Yes, but I can't think of any at the moment !!! <grumble!>
 
 Well, the problem really calls for a more general solution.  I'd like
 to be able to tell ls to list larger files using different shades of a
 colour that correspond to the size.  I'd like it to simply not list
 some types of files.  I'd like it to support all the primitives that
 find(1) supports.
 
 And I'd like it to do this with an interface intuitive enough that I
 need only a cursory glance at the manpage to remember it.
 
 Terry, I believe, is fond of saying: better is the enemy of best.
 There is no best.  There is no pure.  This is a dark and troubled
 world in which we live.
 
 Gentlement, let our `ls` be the light to the world.
 
 
 > Bah !
 
 Bah! indeed!
 
 
 -- 
 Signature withheld by request of author.
 
State-Changed-From-To: open->closed 
State-Changed-By: joe 
State-Changed-When: Fri Jun 2 08:19:44 PDT 2000 
State-Changed-Why:  
I've merged this into 5.0's ls.  I've also added the patch from 
ports/18616 and changed the symlink handling slightly so that it 
behaves exactly the same way with or without colour support. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=18900 
>Unformatted:
