$NetBSD: patch-ae,v 1.2 1998/08/07 11:10:13 agc Exp $ --- print.c.orig Sun Dec 22 00:40:58 1996 +++ print.c Thu May 21 15:42:08 1998 @@ -64,6 +64,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; @@ -124,10 +144,14 @@ printtime(sp->st_ctime); else printtime(sp->st_mtime); + if (f_color) + (void)colortype(sp->st_mode); (void)printf("%s", p->fts_name); if (f_type) (void)printtype(sp->st_mode); - if (S_ISLNK(sp->st_mode)) + if (f_color) + (void)printf("\033[m"); + if (S_ISLNK(sp->st_mode)) printlink(p); (void)putchar('\n'); } @@ -190,10 +214,22 @@ dp->s_block); if ((base += numrows) >= num) break; - while ((cnt = ((chcnt + TAB) & ~(TAB - 1))) <= endcol){ - (void)putchar('\t'); - chcnt = cnt; - } + + /* + * 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 + TAB) & ~(TAB - 1))) + <= endcol) { + (void)putchar('\t'); + chcnt = cnt; + } endcol += colwidth; } (void)putchar('\n'); @@ -219,9 +255,13 @@ if (f_size) chcnt += printf("%*qd ", (int)sizefield, howmany(sp->st_blocks, blocksize)); + if (f_color) + (void)colortype(sp->st_mode); chcnt += printf("%s", p->fts_name); if (f_type) chcnt += printtype(sp->st_mode); + if (f_color) + printf("\033[m"); return (chcnt); } @@ -281,6 +321,95 @@ 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"); +} + +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;