summaryrefslogtreecommitdiffstats
path: root/bin
diff options
context:
space:
mode:
authorjoe <joe@FreeBSD.org>2000-06-02 14:53:42 +0000
committerjoe <joe@FreeBSD.org>2000-06-02 14:53:42 +0000
commit9ad4da2e704de18c0d98495a5cdb9f62cb2e51ad (patch)
tree02f28297b98ef50fecef93835542760c91059cb8 /bin
parenta92f3a6a0abe25f8ef1b9690fca480fd0328d65d (diff)
downloadFreeBSD-src-9ad4da2e704de18c0d98495a5cdb9f62cb2e51ad.zip
FreeBSD-src-9ad4da2e704de18c0d98495a5cdb9f62cb2e51ad.tar.gz
Add colour support to /bin/ls (at a cost of 1056 bytes on my system).
It is not switched on by default and must be enabled with the -G flag. When using ls -G the output behaviour is modified with ANSI colour sequences wrapped around filenames to help distinguish file types. (Colours can be redefined in the LSCOLORS environment variable as described in the manual page.) Colour support is silently disabled (if switched on) if stdout isn't a tty. Based on: asami's colorls port. PR: bin/18900 && ports/18616.
Diffstat (limited to 'bin')
-rw-r--r--bin/ls/extern.h2
-rw-r--r--bin/ls/ls.176
-rw-r--r--bin/ls/ls.c16
-rw-r--r--bin/ls/ls.h1
-rw-r--r--bin/ls/print.c129
5 files changed, 220 insertions, 4 deletions
diff --git a/bin/ls/extern.h b/bin/ls/extern.h
index fd26b37..25e79b0 100644
--- a/bin/ls/extern.h
+++ b/bin/ls/extern.h
@@ -51,3 +51,5 @@ void printscol __P((DISPLAY *));
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));
diff --git a/bin/ls/ls.1 b/bin/ls/ls.1
index 6b29b1f..eebdf20 100644
--- a/bin/ls/ls.1
+++ b/bin/ls/ls.1
@@ -43,7 +43,7 @@
.Nd list directory contents
.Sh SYNOPSIS
.Nm ls
-.Op Fl ABCFHLPRTWabcdfgiklnoqrstu1
+.Op Fl ABCFGHLPRTWabcdfgiklnoqrstu1
.Op Ar file ...
.Sh DESCRIPTION
For each operand that names a
@@ -90,6 +90,12 @@ an equals sign (=) after each socket,
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
@@ -386,6 +392,74 @@ The timezone to use when displaying dates.
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
diff --git a/bin/ls/ls.c b/bin/ls/ls.c
index 754236b..e6b12f7 100644
--- a/bin/ls/ls.c
+++ b/bin/ls/ls.c
@@ -111,6 +111,7 @@ int f_statustime; /* use time of last mode change */
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;
@@ -148,7 +149,7 @@ main(argc, argv)
f_listdot = 1;
fts_options = FTS_PHYSICAL;
- while ((ch = getopt(argc, argv, "1ABCFHLPRTWabcdfgiklnoqrstu")) != -1) {
+ while ((ch = getopt(argc, argv, "1ABCFGHLPRTWabcdfgiklnoqrstu")) != -1) {
switch (ch) {
/*
* The -1, -C and -l options all override each other so shell
@@ -186,6 +187,10 @@ main(argc, argv)
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;
@@ -259,11 +264,16 @@ main(argc, argv)
argc -= optind;
argv += optind;
+ if (f_color)
+ parsecolors(getenv("LSCOLORS"));
+
/*
* If not -F, -i, -l, -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_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;
/*
diff --git a/bin/ls/ls.h b/bin/ls/ls.h
index 33c98c4..9fbe985 100644
--- a/bin/ls/ls.h
+++ b/bin/ls/ls.h
@@ -53,6 +53,7 @@ extern int f_size; /* list size in short listing */
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;
diff --git a/bin/ls/print.c b/bin/ls/print.c
index 702b6b1..1cb3672 100644
--- a/bin/ls/print.c
+++ b/bin/ls/print.c
@@ -56,6 +56,7 @@ static const char rcsid[] =
#include <string.h>
#include <time.h>
#include <unistd.h>
+#include <ctype.h>
#include "ls.h"
#include "extern.h"
@@ -67,6 +68,26 @@ static int printtype __P((u_int));
#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;
@@ -128,8 +149,12 @@ printlong(dp)
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_color)
+ (void)printf("\033[m");
if (f_type)
(void)printtype(sp->st_mode);
if (S_ISLNK(sp->st_mode))
@@ -199,6 +224,16 @@ printcol(dp)
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');
@@ -229,8 +264,12 @@ printaname(p, inodefield, sizefield)
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);
@@ -294,6 +333,96 @@ printtype(mode)
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;
OpenPOWER on IntegriCloud