Skip site navigation (1)Skip section navigation (2)
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:   bin/18900: patch to add colorizing feature to /bin/ls
Message-ID:  <200005301013.e4UADJd69846@curry.mchp.siemens.de>

next in thread | raw e-mail | index | archive | help


>Number:         18900
>Category:       bin
>Synopsis:       patch to add colorizing feature to /bin/ls
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Tue May 30 03:20:01 PDT 2000
>Closed-Date:
>Last-Modified:
>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:
>Unformatted:


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200005301013.e4UADJd69846>