From owner-freebsd-bugs Tue May 30 3:20:11 2000 Delivered-To: freebsd-bugs@freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.ORG [204.216.27.21]) by hub.freebsd.org (Postfix) with ESMTP id A53F037BA6C for ; Tue, 30 May 2000 03:20:01 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.9.3/8.9.2) id DAA82979; Tue, 30 May 2000 03:20:01 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: from david.siemens.de (david.siemens.de [192.35.17.14]) by hub.freebsd.org (Postfix) with ESMTP id 40B7A37B5A4 for ; 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 ; 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 ; 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 To: FreeBSD-gnats-submit@freebsd.org X-Send-Pr-Version: 3.2 Subject: bin/18900: patch to add colorizing feature to /bin/ls Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org >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 #include #include +#include #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 */ +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