summaryrefslogtreecommitdiff
path: root/bin
diff options
context:
space:
mode:
authorAndrey A. Chernov <ache@FreeBSD.org>2000-07-04 18:45:27 +0000
committerAndrey A. Chernov <ache@FreeBSD.org>2000-07-04 18:45:27 +0000
commit8d11ea018dedd9ed02b8326db65bcc1d95aa2ef3 (patch)
treefeca5f9b882fb5457c7d03d5d7e92beb067d423a /bin
parentc226261be470f9f7ab1736659474ff9f116b8174 (diff)
Notes
Diffstat (limited to 'bin')
-rw-r--r--bin/ls/Makefile6
-rw-r--r--bin/ls/extern.h8
-rw-r--r--bin/ls/ls.184
-rw-r--r--bin/ls/ls.c68
-rw-r--r--bin/ls/ls.h3
-rw-r--r--bin/ls/print.c185
-rw-r--r--bin/ls/util.c7
7 files changed, 355 insertions, 6 deletions
diff --git a/bin/ls/Makefile b/bin/ls/Makefile
index 1ab70dc78a17..96dffe1015de 100644
--- a/bin/ls/Makefile
+++ b/bin/ls/Makefile
@@ -5,4 +5,10 @@
PROG= ls
SRCS= cmp.c ls.c print.c util.c
+.if !defined(RELEASE_BUILD_FIXIT)
+CFLAGS+= -DCOLORLS
+LDADD+= -ltermcap
+DPADD+= ${LIBTERMCAP}
+.endif
+
.include <bsd.prog.mk>
diff --git a/bin/ls/extern.h b/bin/ls/extern.h
index f17607394d3e..4b27be666580 100644
--- a/bin/ls/extern.h
+++ b/bin/ls/extern.h
@@ -50,3 +50,11 @@ void printscol __P((DISPLAY *));
void usage __P((void));
int len_octal __P((char *, int));
int prn_octal __P((char *));
+#ifdef COLORLS
+void parsecolors __P((char *cs));
+void colorquit __P((int));
+
+extern char *ansi_fgcol;
+extern char *ansi_bgcol;
+extern char *ansi_coloff;
+#endif
diff --git a/bin/ls/ls.1 b/bin/ls/ls.1
index 146066075565..4bbf62074f7a 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,16 @@ 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
+.Tn 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
@@ -388,6 +398,78 @@ format output.
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
+brown
+.It Sy 4
+blue
+.It Sy 5
+magenta
+.It Sy 6
+cyan
+.It Sy 7
+light grey
+.It Sy x
+default foreground or background
+.El
+.Pp
+Note that the above are standard
+.Tn 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 5a637f5f848f..69b8d774b042 100644
--- a/bin/ls/ls.c
+++ b/bin/ls/ls.c
@@ -63,6 +63,10 @@ static const char rcsid[] =
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#ifdef COLORLS
+#include <termcap.h>
+#include <signal.h>
+#endif
#include "ls.h"
#include "extern.h"
@@ -109,6 +113,13 @@ 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 */
+#ifdef COLORLS
+int f_color; /* add type in color for non-regular files */
+
+char *ansi_bgcol; /* ANSI sequence to set background colour */
+char *ansi_fgcol; /* ANSI sequence to set foreground colour */
+char *ansi_coloff; /* ANSI sequence to reset colours */
+#endif
int rval;
@@ -122,6 +133,12 @@ main(argc, argv)
int ch, fts_options, notused;
char *p;
+#ifdef COLORLS
+ char termcapbuf[1024]; /* termcap definition buffer */
+ char tcapbuf[512]; /* capability buffer */
+ char *bp = tcapbuf;
+#endif
+
(void) setlocale(LC_ALL, "");
/* Terminal defaults to -Cq, non-terminal defaults to -1. */
@@ -146,7 +163,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
@@ -184,6 +201,26 @@ main(argc, argv)
case 'H':
fts_options |= FTS_COMFOLLOW;
break;
+ case 'G':
+ if (isatty(STDOUT_FILENO))
+#ifdef COLORLS
+ if (tgetent(termcapbuf, getenv("TERM")) == 1) {
+ ansi_fgcol = tgetstr("AF", &bp);
+ ansi_bgcol = tgetstr("AB", &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
+ (void)fprintf(stderr, "Color support not compiled in.\n");
+#endif
+ break;
case 'L':
fts_options &= ~FTS_PHYSICAL;
fts_options |= FTS_LOGICAL;
@@ -257,11 +294,30 @@ main(argc, argv)
argc -= optind;
argv += optind;
+#ifdef COLORLS
+ if (f_color) {
+ /*
+ * We can't put tabs and color sequences together:
+ * column number will be incremented incorrectly
+ * for "stty oxtabs" mode.
+ */
+ f_notabs = 1;
+ (void) signal(SIGINT, colorquit);
+ (void) signal(SIGQUIT, colorquit);
+ parsecolors(getenv("LSCOLORS"));
+ }
+#endif
+
/*
* 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
+#ifdef COLORLS
+ && !f_color
+#endif
+ )
fts_options |= FTS_NOSTAT;
/*
@@ -469,7 +525,11 @@ display(p, list)
case 4: maxgroup = 0;
case 5: maxflags = 0;
case 6: maxsize = 0;
- case 7: maxlen = 0, f_notabs = 0;
+ case 7: maxlen = 0;
+#ifdef COLORLS
+ if (!f_color)
+#endif
+ f_notabs = 0;
}
maxinode = makenines(maxinode);
maxblock = makenines(maxblock);
diff --git a/bin/ls/ls.h b/bin/ls/ls.h
index 33c98c45aab8..3da163d95319 100644
--- a/bin/ls/ls.h
+++ b/bin/ls/ls.h
@@ -53,6 +53,9 @@ 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 */
+#ifdef COLORLS
+extern int f_color; /* add type in color for non-regular files */
+#endif
typedef struct {
FTSENT *list;
diff --git a/bin/ls/print.c b/bin/ls/print.c
index d6792ee3699e..736754abe292 100644
--- a/bin/ls/print.c
+++ b/bin/ls/print.c
@@ -56,6 +56,11 @@ static const char rcsid[] =
#include <string.h>
#include <time.h>
#include <unistd.h>
+#ifdef COLORLS
+#include <ctype.h>
+#include <termcap.h>
+#include <signal.h>
+#endif
#include "ls.h"
#include "extern.h"
@@ -64,9 +69,35 @@ static int printaname __P((FTSENT *, u_long, u_long));
static void printlink __P((FTSENT *));
static void printtime __P((time_t));
static int printtype __P((u_int));
+#ifdef COLORLS
+static void endcolor __P((int));
+static int colortype __P((mode_t));
+#endif
#define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT)
+#ifdef COLORLS
+/* 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];
+#endif
+
void
printscol(dp)
DISPLAY *dp;
@@ -89,6 +120,9 @@ printlong(dp)
FTSENT *p;
NAMES *np;
char buf[20];
+#ifdef COLORLS
+ int color_printed = 0;
+#endif
if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size))
(void)printf("total %lu\n", howmany(dp->btotal, blocksize));
@@ -128,8 +162,16 @@ printlong(dp)
printtime(sp->st_ctime);
else
printtime(sp->st_mtime);
+#ifdef COLORLS
+ if (f_color)
+ color_printed = colortype(sp->st_mode);
+#endif
if (f_octal || f_octal_escape) (void)prn_octal(p->fts_name);
else (void)printf("%s", p->fts_name);
+#ifdef COLORLS
+ if (f_color && color_printed)
+ endcolor(0);
+#endif
if (f_type)
(void)printtype(sp->st_mode);
if (S_ISLNK(sp->st_mode))
@@ -221,6 +263,9 @@ printaname(p, inodefield, sizefield)
{
struct stat *sp;
int chcnt;
+#ifdef COLORLS
+ int color_printed = 0;
+#endif
sp = p->fts_statp;
chcnt = 0;
@@ -229,8 +274,16 @@ printaname(p, inodefield, sizefield)
if (f_size)
chcnt += printf("%*qd ",
(int)sizefield, howmany(sp->st_blocks, blocksize));
+#ifdef COLORLS
+ if (f_color)
+ color_printed = colortype(sp->st_mode);
+#endif
chcnt += (f_octal || f_octal_escape) ? prn_octal(p->fts_name)
: printf("%s", p->fts_name);
+#ifdef COLORLS
+ if (f_color && color_printed)
+ endcolor(0);
+#endif
if (f_type)
chcnt += printtype(sp->st_mode);
return (chcnt);
@@ -292,6 +345,138 @@ printtype(mode)
return (0);
}
+#ifdef COLORLS
+static int
+putch(c)
+ int c;
+{
+ (void) putchar(c);
+ return 0;
+}
+
+static int
+writech(c)
+ int c;
+{
+ char tmp = c;
+
+ (void) write(STDOUT_FILENO, &tmp, 1);
+ return 0;
+}
+
+static void
+printcolor(c)
+ Colors c;
+{
+ char *ansiseq;
+
+ if (colors[c][0] != -1) {
+ ansiseq = tgoto(ansi_fgcol, 0, colors[c][0]);
+ if (ansiseq)
+ tputs(ansiseq, 1, putch);
+ }
+
+ if (colors[c][1] != -1) {
+ ansiseq = tgoto(ansi_bgcol, 0, colors[c][1]);
+ if (ansiseq)
+ tputs(ansiseq, 1, putch);
+ }
+}
+
+static void
+endcolor(sig)
+ int sig;
+{
+ tputs(ansi_coloff, 1, sig ? writech : putch);
+}
+
+static 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((unsigned char)c[j]) != 'x') {
+ fprintf(stderr,
+ "error: invalid character '%c' in LSCOLORS env var\n",
+ c[j]);
+ c[j] = defcolors[2*i+j];
+ }
+ if (tolower((unsigned char)c[j]) == 'x')
+ colors[i][j] = -1;
+ else
+ colors[i][j] = c[j]-'0';
+ }
+ }
+}
+
+void
+colorquit(sig)
+ int sig;
+{
+ endcolor(sig);
+
+ (void) signal(sig, SIG_DFL);
+ (void) kill(getpid(), sig);
+}
+#endif /*COLORLS*/
+
static void
printlink(p)
FTSENT *p;
diff --git a/bin/ls/util.c b/bin/ls/util.c
index eea247587a9c..7239d9776abf 100644
--- a/bin/ls/util.c
+++ b/bin/ls/util.c
@@ -158,7 +158,12 @@ prn_octal(s)
void
usage()
{
- (void)fprintf(stderr, "usage: ls [-ACFHLPRTWacdfgiklnoqrstu1]"
+ (void)fprintf(stderr,
+#ifdef COLORLS
+ "usage: ls [-ACFGHLPRTWacdfgiklnoqrstu1]"
+#else
+ "usage: ls [-ACFHLPRTWacdfgiklnoqrstu1]"
+#endif
" [file ...]\n");
exit(1);
}