diff options
Diffstat (limited to 'contrib/tcsh/tw.color.c')
-rw-r--r-- | contrib/tcsh/tw.color.c | 350 |
1 files changed, 350 insertions, 0 deletions
diff --git a/contrib/tcsh/tw.color.c b/contrib/tcsh/tw.color.c new file mode 100644 index 0000000..31a1d2d --- /dev/null +++ b/contrib/tcsh/tw.color.c @@ -0,0 +1,350 @@ +/* $Header: /p/tcsh/cvsroot/tcsh/tw.color.c,v 1.27 2010/08/19 05:52:19 christos Exp $ */ +/* + * tw.color.c: builtin color ls-F + */ +/*- + * Copyright (c) 1998 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "sh.h" + +RCSID("$tcsh: tw.color.c,v 1.27 2010/08/19 05:52:19 christos Exp $") + +#include "tw.h" +#include "ed.h" +#include "tc.h" + +#ifdef COLOR_LS_F + +typedef struct { + const char *s; + size_t len; +} Str; + + +#define VAR(suffix,variable,defaultcolor) \ +{ \ + suffix, variable, { defaultcolor, sizeof(defaultcolor) - 1 }, \ + { defaultcolor, sizeof(defaultcolor) - 1 } \ +} +#define NOS '\0' /* no suffix */ + +typedef struct { + const char suffix; + const char *variable; + Str color; + Str defaultcolor; +} Variable; + +static Variable variables[] = { + VAR('/', "di", "01;34"), /* Directory */ + VAR('@', "ln", "01;36"), /* Symbolic link */ + VAR('&', "or", ""), /* Orphanned symbolic link (defaults to ln) */ + VAR('|', "pi", "33"), /* Named pipe (FIFO) */ + VAR('=', "so", "01;35"), /* Socket */ + VAR('>', "do", "01;35"), /* Door (solaris fast ipc mechanism) */ + VAR('#', "bd", "01;33"), /* Block device */ + VAR('%', "cd", "01;33"), /* Character device */ + VAR('*', "ex", "01;32"), /* Executable file */ + VAR(NOS, "fi", "0"), /* Regular file */ + VAR(NOS, "no", "0"), /* Normal (non-filename) text */ + VAR(NOS, "mi", ""), /* Missing file (defaults to fi) */ +#ifdef IS_ASCII + VAR(NOS, "lc", "\033["), /* Left code (ASCII) */ +#else + VAR(NOS, "lc", "\x27["), /* Left code (EBCDIC)*/ +#endif + VAR(NOS, "rc", "m"), /* Right code */ + VAR(NOS, "ec", ""), /* End code (replaces lc+no+rc) */ + VAR(NOS, "su", ""), /* Setuid file (u+s) */ + VAR(NOS, "sg", ""), /* Setgid file (g+s) */ + VAR(NOS, "tw", ""), /* Sticky and other writable dir (+t,o+w) */ + VAR(NOS, "ow", ""), /* Other writable dir (o+w) but not sticky */ + VAR(NOS, "st", ""), /* Sticky dir (+t) but not other writable */ + VAR(NOS, "rs", "0"), /* Reset to normal color */ + VAR(NOS, "hl", "44;37"), /* Reg file extra hard links, obsolete? */ + VAR(NOS, "mh", "44;37"), /* Reg file extra hard links */ + VAR(NOS, "ca", "30;41"), /* File with capability */ +}; + +enum FileType { + VDir, VSym, VOrph, VPipe, VSock, VDoor, VBlock, VChr, VExe, + VFile, VNormal, VMiss, VLeft, VRight, VEnd +}; + +#define nvariables (sizeof(variables)/sizeof(variables[0])) + +typedef struct { + Str extension; /* file extension */ + Str color; /* color string */ +} Extension; + +static Extension *extensions = NULL; +static size_t nextensions = 0; + +static char *colors = NULL; +int color_context_ls = FALSE; /* do colored ls */ +static int color_context_lsmF = FALSE; /* do colored ls-F */ + +static int getstring (char **, const Char **, Str *, int); +static void put_color (const Str *); +static void print_color (const Char *, size_t, Char); + +/* set_color_context(): + */ +void +set_color_context(void) +{ + struct varent *vp = adrof(STRcolor); + + if (vp == NULL || vp->vec == NULL) { + color_context_ls = FALSE; + color_context_lsmF = FALSE; + } else if (!vp->vec[0] || vp->vec[0][0] == '\0') { + color_context_ls = TRUE; + color_context_lsmF = TRUE; + } else { + size_t i; + + color_context_ls = FALSE; + color_context_lsmF = FALSE; + for (i = 0; vp->vec[i]; i++) + if (Strcmp(vp->vec[i], STRls) == 0) + color_context_ls = TRUE; + else if (Strcmp(vp->vec[i], STRlsmF) == 0) + color_context_lsmF = TRUE; + } +} + + +/* getstring(): + */ +static int +getstring(char **dp, const Char **sp, Str *pd, int f) +{ + const Char *s = *sp; + char *d = *dp; + eChar sc; + + while (*s && (*s & CHAR) != (Char)f && (*s & CHAR) != ':') { + if ((*s & CHAR) == '\\' || (*s & CHAR) == '^') { + if ((sc = parseescape(&s)) == CHAR_ERR) + return 0; + } + else + sc = *s++ & CHAR; + d += one_wctomb(d, sc); + } + + pd->s = *dp; + pd->len = d - *dp; + *sp = s; + *dp = d; + return *s == (Char)f; +} + + +/* parseLS_COLORS(): + * Parse the LS_COLORS environment variable + */ +void +parseLS_COLORS(const Char *value) +{ + size_t i, len; + const Char *v; /* pointer in value */ + char *c; /* pointer in colors */ + Extension *volatile e; /* pointer in extensions */ + jmp_buf_t osetexit; + size_t omark; + + (void) &e; + + /* init */ + xfree(extensions); + for (i = 0; i < nvariables; i++) + variables[i].color = variables[i].defaultcolor; + colors = NULL; + extensions = NULL; + nextensions = 0; + + if (value == NULL) + return; + + len = Strlen(value); + /* allocate memory */ + i = 1; + for (v = value; *v; v++) + if ((*v & CHAR) == ':') + i++; + extensions = xmalloc(len + i * sizeof(Extension)); + colors = i * sizeof(Extension) + (char *)extensions; + nextensions = 0; + + /* init pointers */ + v = value; + c = colors; + e = &extensions[0]; + + /* Prevent from crashing if unknown parameters are given. */ + + omark = cleanup_push_mark(); + getexit(osetexit); + + if (setexit() == 0) { + + /* parse */ + while (*v) { + switch (*v & CHAR) { + case ':': + v++; + continue; + + case '*': /* :*ext=color: */ + v++; + if (getstring(&c, &v, &e->extension, '=') && + 0 < e->extension.len) { + v++; + getstring(&c, &v, &e->color, ':'); + e++; + continue; + } + break; + + default: /* :vl=color: */ + if (v[0] && v[1] && (v[2] & CHAR) == '=') { + for (i = 0; i < nvariables; i++) + if ((Char)variables[i].variable[0] == (v[0] & CHAR) && + (Char)variables[i].variable[1] == (v[1] & CHAR)) + break; + if (i < nvariables) { + v += 3; + getstring(&c, &v, &variables[i].color, ':'); + continue; + } + else + stderror(ERR_BADCOLORVAR, v[0], v[1]); + } + break; + } + while (*v && (*v & CHAR) != ':') + v++; + } + } + + cleanup_pop_mark(omark); + resexit(osetexit); + + nextensions = e - extensions; +} + +/* put_color(): + */ +static void +put_color(const Str *color) +{ + size_t i; + const char *c = color->s; + int original_output_raw = output_raw; + + output_raw = TRUE; + cleanup_push(&original_output_raw, output_raw_restore); + for (i = color->len; 0 < i; i--) + xputchar(*c++); + cleanup_until(&original_output_raw); +} + + +/* print_color(): + */ +static void +print_color(const Char *fname, size_t len, Char suffix) +{ + size_t i; + char *filename = short2str(fname); + char *last = filename + len; + Str *color = &variables[VFile].color; + + switch (suffix) { + case '>': /* File is a symbolic link pointing to + * a directory */ + color = &variables[VDir].color; + break; + case '+': /* File is a hidden directory [aix] or + * context dependent [hpux] */ + case ':': /* File is network special [hpux] */ + break; + default: + for (i = 0; i < nvariables; i++) + if (variables[i].suffix != NOS && + (Char)variables[i].suffix == suffix) { + color = &variables[i].color; + break; + } + if (i == nvariables) { + for (i = 0; i < nextensions; i++) + if (len >= extensions[i].extension.len + && strncmp(last - extensions[i].extension.len, + extensions[i].extension.s, + extensions[i].extension.len) == 0) { + color = &extensions[i].color; + break; + } + } + break; + } + + put_color(&variables[VLeft].color); + put_color(color); + put_color(&variables[VRight].color); +} + + +/* print_with_color(): + */ +void +print_with_color(const Char *filename, size_t len, Char suffix) +{ + if (color_context_lsmF && + (haderr ? (didfds ? is2atty : isdiagatty) : + (didfds ? is1atty : isoutatty))) { + print_color(filename, len, suffix); + xprintf("%S", filename); + if (0 < variables[VEnd].color.len) + put_color(&variables[VEnd].color); + else { + put_color(&variables[VLeft].color); + put_color(&variables[VNormal].color); + put_color(&variables[VRight].color); + } + } + else + xprintf("%S", filename); + xputwchar(suffix); +} + + +#endif /* COLOR_LS_F */ |