summaryrefslogtreecommitdiffstats
path: root/bin/ls
diff options
context:
space:
mode:
Diffstat (limited to 'bin/ls')
-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