tw.color.c revision 59415
159415Sobrien/* $Header: /src/pub/tcsh/tw.color.c,v 1.6 2000/01/14 22:57:30 christos Exp $ */ 259243Sobrien/* 359243Sobrien * tw.color.c: builtin color ls-F 459243Sobrien */ 559243Sobrien/*- 659243Sobrien * Copyright (c) 1998 The Regents of the University of California. 759243Sobrien * All rights reserved. 859243Sobrien * 959243Sobrien * Redistribution and use in source and binary forms, with or without 1059243Sobrien * modification, are permitted provided that the following conditions 1159243Sobrien * are met: 1259243Sobrien * 1. Redistributions of source code must retain the above copyright 1359243Sobrien * notice, this list of conditions and the following disclaimer. 1459243Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1559243Sobrien * notice, this list of conditions and the following disclaimer in the 1659243Sobrien * documentation and/or other materials provided with the distribution. 1759243Sobrien * 3. All advertising materials mentioning features or use of this software 1859243Sobrien * must display the following acknowledgement: 1959243Sobrien * This product includes software developed by the University of 2059243Sobrien * California, Berkeley and its contributors. 2159243Sobrien * 4. Neither the name of the University nor the names of its contributors 2259243Sobrien * may be used to endorse or promote products derived from this software 2359243Sobrien * without specific prior written permission. 2459243Sobrien * 2559243Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2659243Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2759243Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2859243Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2959243Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3059243Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3159243Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3259243Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3359243Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3459243Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3559243Sobrien * SUCH DAMAGE. 3659243Sobrien */ 3759243Sobrien#include "sh.h" 3859243Sobrien 3959415SobrienRCSID("$Id: tw.color.c,v 1.6 2000/01/14 22:57:30 christos Exp $") 4059243Sobrien 4159243Sobrien#include "tw.h" 4259243Sobrien#include "ed.h" 4359243Sobrien#include "tc.h" 4459243Sobrien 4559243Sobrien#ifdef COLOR_LS_F 4659243Sobrien 4759243Sobrientypedef struct { 4859243Sobrien char *s; 4959243Sobrien int len; 5059243Sobrien} Str; 5159243Sobrien 5259243Sobrien 5359243Sobrien#define VAR(suffix,variable,defaultcolor) \ 5459243Sobrien{ \ 5559243Sobrien suffix, variable, { defaultcolor, sizeof(defaultcolor) - 1 }, \ 5659243Sobrien { defaultcolor, sizeof(defaultcolor) - 1 } \ 5759243Sobrien} 5859243Sobrien#define NOS '\0' /* no suffix */ 5959243Sobrien 6059243Sobrientypedef struct { 6159243Sobrien const char suffix; 6259243Sobrien const char *variable; 6359243Sobrien Str color; 6459243Sobrien Str defaultcolor; 6559243Sobrien} Variable; 6659243Sobrien 6759243Sobrienstatic Variable variables[] = { 6859243Sobrien VAR('/', "di", "01;34"), /* Directory */ 6959243Sobrien VAR('@', "ln", "01;36"), /* Symbolic link */ 7059243Sobrien VAR('&', "or", ""), /* Orphanned symbolic link (defaults to ln) */ 7159243Sobrien VAR('|', "pi", "33"), /* Named pipe (FIFO) */ 7259243Sobrien VAR('=', "so", "01;35"), /* Socket */ 7359243Sobrien VAR('#', "bd", "01;33"), /* Block device */ 7459243Sobrien VAR('%', "cd", "01;33"), /* Character device */ 7559243Sobrien VAR('*', "ex", "01;32"), /* Executable file */ 7659243Sobrien VAR(NOS, "fi", "0"), /* Regular file */ 7759243Sobrien VAR(NOS, "no", "0"), /* Normal (non-filename) text */ 7859243Sobrien VAR(NOS, "mi", ""), /* Missing file (defaults to fi) */ 7959243Sobrien#ifdef _OSD_POSIX 8059243Sobrien VAR(NOS, "lc", "\x27["), /* Left code (EBCDIC)*/ 8159243Sobrien#else /* _OSD_POSIX */ 8259243Sobrien VAR(NOS, "lc", "\033["), /* Left code */ 8359243Sobrien#endif /* _OSD_POSIX */ 8459243Sobrien VAR(NOS, "rc", "m"), /* Right code */ 8559243Sobrien VAR(NOS, "ec", ""), /* End code (replaces lc+no+rc) */ 8659243Sobrien}; 8759243Sobrien 8859243Sobrienenum FileType { 8959243Sobrien VDir, VSym, VOrph, VPipe, VSock, VBlock, VChr, VExe, 9059243Sobrien VFile, VNormal, VMiss, VLeft, VRight, VEnd 9159243Sobrien}; 9259243Sobrien 9359243Sobrien#define nvariables (sizeof(variables)/sizeof(variables[0])) 9459243Sobrien 9559243Sobrientypedef struct { 9659243Sobrien Str extension; /* file extension */ 9759243Sobrien Str color; /* color string */ 9859243Sobrien} Extension; 9959243Sobrien 10059243Sobrienstatic Extension *extensions = NULL; 10159243Sobrienstatic int nextensions = 0; 10259243Sobrien 10359243Sobrienstatic char *colors = NULL; 10459243Sobrienbool color_context_ls = FALSE; /* do colored ls */ 10559243Sobrienstatic bool color_context_lsmF = FALSE; /* do colored ls-F */ 10659243Sobrien 10759243Sobrienstatic bool getstring __P((char **, const Char **, Str *, int)); 10859243Sobrienstatic void put_color __P((Str *)); 10959243Sobrienstatic void print_color __P((Char *, size_t, int)); 11059243Sobrien 11159243Sobrien/* set_color_context(): 11259243Sobrien */ 11359243Sobrienvoid 11459243Sobrienset_color_context() 11559243Sobrien{ 11659243Sobrien struct varent *vp = adrof(STRcolor); 11759243Sobrien 11859243Sobrien if (!vp) { 11959243Sobrien color_context_ls = FALSE; 12059243Sobrien color_context_lsmF = FALSE; 12159243Sobrien } 12259243Sobrien else if (!vp->vec[0] || vp->vec[0][0] == '\0') { 12359243Sobrien color_context_ls = TRUE; 12459243Sobrien color_context_lsmF = TRUE; 12559243Sobrien } 12659243Sobrien else { 12759243Sobrien size_t i; 12859243Sobrien 12959243Sobrien color_context_ls = FALSE; 13059243Sobrien color_context_lsmF = FALSE; 13159243Sobrien for (i = 0; vp->vec[i]; i++) 13259243Sobrien if (Strcmp(vp->vec[i], STRls) == 0) 13359243Sobrien color_context_ls = TRUE; 13459243Sobrien else if (Strcmp(vp->vec[i], STRlsmF) == 0) 13559243Sobrien color_context_lsmF = TRUE; 13659243Sobrien } 13759243Sobrien} 13859243Sobrien 13959243Sobrien 14059243Sobrien/* getstring(): 14159243Sobrien */ 14259243Sobrienstatic bool 14359243Sobriengetstring(dp, sp, pd, f) 14459243Sobrien char **dp; /* dest buffer */ 14559243Sobrien const Char **sp; /* source buffer */ 14659243Sobrien Str *pd; /* pointer to dest buffer */ 14759243Sobrien int f; /* final character */ 14859243Sobrien{ 14959243Sobrien const Char *s = *sp; 15059243Sobrien char *d = *dp; 15159243Sobrien int sc; 15259243Sobrien 15359243Sobrien while (*s && (*s & CHAR) != f && (*s & CHAR) != ':') { 15459243Sobrien if ((*s & CHAR) == '\\' || (*s & CHAR) == '^') { 15559243Sobrien if ((sc = parseescape(&s)) == -1) 15659243Sobrien return 0; 15759243Sobrien else 15859243Sobrien *d++ = (char) sc; 15959243Sobrien } 16059243Sobrien else 16159243Sobrien *d++ = *s++ & CHAR; 16259243Sobrien } 16359243Sobrien 16459243Sobrien pd->s = *dp; 16559243Sobrien pd->len = (int) (d - *dp); 16659243Sobrien *sp = s; 16759243Sobrien *dp = d; 16859243Sobrien return *s == f; 16959243Sobrien} 17059243Sobrien 17159243Sobrien 17259243Sobrien/* parseLS_COLORS(): 17359243Sobrien * Parse the LS_COLORS environment variable 17459243Sobrien */ 17559243Sobrienvoid 17659243SobrienparseLS_COLORS(value) 17759243Sobrien Char *value; /* LS_COLOR variable's value */ 17859243Sobrien{ 17959243Sobrien int i; 18059243Sobrien size_t len; 18159243Sobrien const Char *v; /* pointer in value */ 18259243Sobrien char *c; /* pointer in colors */ 18359243Sobrien Extension *e; /* pointer in extensions */ 18459415Sobrien jmp_buf_t osetexit; 18559243Sobrien 18659243Sobrien /* init */ 18759243Sobrien if (extensions) 18859243Sobrien xfree((ptr_t) extensions); 18959243Sobrien for (i = 0; i < nvariables; i++) 19059243Sobrien variables[i].color = variables[i].defaultcolor; 19159243Sobrien colors = NULL; 19259243Sobrien extensions = NULL; 19359243Sobrien nextensions = 0; 19459243Sobrien 19559243Sobrien if (value == NULL) 19659243Sobrien return; 19759243Sobrien 19859243Sobrien len = Strlen(value); 19959243Sobrien /* allocate memory */ 20059243Sobrien i = 1; 20159243Sobrien for (v = value; *v; v++) 20259243Sobrien if ((*v & CHAR) == ':') 20359243Sobrien i++; 20459243Sobrien extensions = (Extension *) xmalloc((size_t) (len + i * sizeof(Extension))); 20559243Sobrien colors = i * sizeof(Extension) + (char *)extensions; 20659243Sobrien nextensions = 0; 20759243Sobrien 20859243Sobrien /* init pointers */ 20959243Sobrien v = value; 21059243Sobrien c = colors; 21159243Sobrien e = &extensions[0]; 21259243Sobrien 21359415Sobrien /* Prevent from crashing if unknown parameters are given. */ 21459415Sobrien 21559415Sobrien getexit(osetexit); 21659415Sobrien 21759415Sobrien if (setexit() == 0) { 21859415Sobrien 21959243Sobrien /* parse */ 22059243Sobrien while (*v) { 22159243Sobrien switch (*v & CHAR) { 22259243Sobrien case ':': 22359243Sobrien v++; 22459243Sobrien continue; 22559243Sobrien 22659243Sobrien case '*': /* :*ext=color: */ 22759243Sobrien v++; 22859243Sobrien if (getstring(&c, &v, &e->extension, '=') && 22959243Sobrien 0 < e->extension.len) { 23059243Sobrien v++; 23159243Sobrien getstring(&c, &v, &e->color, ':'); 23259243Sobrien e++; 23359243Sobrien continue; 23459243Sobrien } 23559243Sobrien break; 23659243Sobrien 23759243Sobrien default: /* :vl=color: */ 23859243Sobrien if (v[0] && v[1] && (v[2] & CHAR) == '=') { 23959243Sobrien for (i = 0; i < nvariables; i++) 24059243Sobrien if (variables[i].variable[0] == (v[0] & CHAR) && 24159243Sobrien variables[i].variable[1] == (v[1] & CHAR)) 24259243Sobrien break; 24359243Sobrien if (i < nvariables) { 24459243Sobrien v += 3; 24559243Sobrien getstring(&c, &v, &variables[i].color, ':'); 24659243Sobrien continue; 24759243Sobrien } 24859243Sobrien else 24959243Sobrien stderror(ERR_BADCOLORVAR, v[0], v[1]); 25059243Sobrien } 25159243Sobrien break; 25259243Sobrien } 25359243Sobrien while (*v && (*v & CHAR) != ':') 25459243Sobrien v++; 25559243Sobrien } 25659415Sobrien } 25759243Sobrien 25859415Sobrien resexit(osetexit); 25959415Sobrien 26059243Sobrien nextensions = (int) (e - extensions); 26159243Sobrien} 26259243Sobrien 26359243Sobrien 26459243Sobrien/* put_color(): 26559243Sobrien */ 26659243Sobrienstatic void 26759243Sobrienput_color(color) 26859243Sobrien Str *color; 26959243Sobrien{ 27059243Sobrien extern bool output_raw; /* PWP: in sh.print.c */ 27159243Sobrien size_t i; 27259243Sobrien char *c = color->s; 27359243Sobrien bool original_output_raw = output_raw; 27459243Sobrien 27559243Sobrien output_raw = TRUE; 27659243Sobrien for (i = color->len; 0 < i; i--) 27759243Sobrien xputchar(*c++); 27859243Sobrien output_raw = original_output_raw; 27959243Sobrien} 28059243Sobrien 28159243Sobrien 28259243Sobrien/* print_color(): 28359243Sobrien */ 28459243Sobrienstatic void 28559243Sobrienprint_color(fname, len, suffix) 28659243Sobrien Char *fname; 28759243Sobrien size_t len; 28859243Sobrien int suffix; 28959243Sobrien{ 29059243Sobrien int i; 29159243Sobrien char *filename = short2str(fname); 29259243Sobrien char *last = filename + len; 29359243Sobrien Str *color = &variables[VFile].color; 29459243Sobrien 29559243Sobrien switch (suffix) { 29659243Sobrien case '>': /* File is a symbolic link pointing to 29759243Sobrien * a directory */ 29859243Sobrien color = &variables[VDir].color; 29959243Sobrien break; 30059243Sobrien case '+': /* File is a hidden directory [aix] or 30159243Sobrien * context dependent [hpux] */ 30259243Sobrien case ':': /* File is network special [hpux] */ 30359243Sobrien break; 30459243Sobrien default: 30559243Sobrien for (i = 0; i < nvariables; i++) 30659243Sobrien if (variables[i].suffix != NOS && 30759243Sobrien variables[i].suffix == suffix) { 30859243Sobrien color = &variables[i].color; 30959243Sobrien break; 31059243Sobrien } 31159243Sobrien if (i == nvariables) { 31259243Sobrien for (i = 0; i < nextensions; i++) 31359243Sobrien if (strncmp(last - extensions[i].extension.len, 31459243Sobrien extensions[i].extension.s, 31559243Sobrien extensions[i].extension.len) == 0) { 31659243Sobrien color = &extensions[i].color; 31759243Sobrien break; 31859243Sobrien } 31959243Sobrien } 32059243Sobrien break; 32159243Sobrien } 32259243Sobrien 32359243Sobrien put_color(&variables[VLeft].color); 32459243Sobrien put_color(color); 32559243Sobrien put_color(&variables[VRight].color); 32659243Sobrien} 32759243Sobrien 32859243Sobrien 32959243Sobrien/* print_with_color(): 33059243Sobrien */ 33159243Sobrienvoid 33259243Sobrienprint_with_color(filename, len, suffix) 33359243Sobrien Char *filename; 33459243Sobrien size_t len; 33559243Sobrien int suffix; 33659243Sobrien{ 33759243Sobrien if (color_context_lsmF && 33859243Sobrien (haderr ? (didfds ? is2atty : isdiagatty) : 33959243Sobrien (didfds ? is1atty : isoutatty))) { 34059243Sobrien print_color(filename, len, suffix); 34159243Sobrien xprintf("%S", filename); 34259243Sobrien if (0 < variables[VEnd].color.len) 34359243Sobrien put_color(&variables[VEnd].color); 34459243Sobrien else { 34559243Sobrien put_color(&variables[VLeft].color); 34659243Sobrien put_color(&variables[VNormal].color); 34759243Sobrien put_color(&variables[VRight].color); 34859243Sobrien } 34959243Sobrien xputchar(suffix); 35059243Sobrien } 35159243Sobrien else 35259243Sobrien xprintf("%S%c", filename, suffix); 35359243Sobrien} 35459243Sobrien 35559243Sobrien 35659243Sobrien#endif /* COLOR_LS_F */ 357