tw.color.c revision 83098
1187262Snwhitehorn/* $Header: /src/pub/tcsh/tw.color.c,v 1.8 2001/03/18 19:06:32 christos Exp $ */ 2187262Snwhitehorn/* 3187262Snwhitehorn * tw.color.c: builtin color ls-F 4187262Snwhitehorn */ 5187262Snwhitehorn/*- 6187262Snwhitehorn * Copyright (c) 1998 The Regents of the University of California. 7187262Snwhitehorn * All rights reserved. 8187262Snwhitehorn * 9187262Snwhitehorn * Redistribution and use in source and binary forms, with or without 10187262Snwhitehorn * modification, are permitted provided that the following conditions 11187262Snwhitehorn * are met: 12187262Snwhitehorn * 1. Redistributions of source code must retain the above copyright 13187262Snwhitehorn * notice, this list of conditions and the following disclaimer. 14187262Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright 15187262Snwhitehorn * notice, this list of conditions and the following disclaimer in the 16187262Snwhitehorn * documentation and/or other materials provided with the distribution. 17187262Snwhitehorn * 3. All advertising materials mentioning features or use of this software 18187262Snwhitehorn * must display the following acknowledgement: 19187262Snwhitehorn * This product includes software developed by the University of 20187262Snwhitehorn * California, Berkeley and its contributors. 21187262Snwhitehorn * 4. Neither the name of the University nor the names of its contributors 22187262Snwhitehorn * may be used to endorse or promote products derived from this software 23187262Snwhitehorn * without specific prior written permission. 24187262Snwhitehorn * 25187262Snwhitehorn * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26187262Snwhitehorn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27187262Snwhitehorn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28187262Snwhitehorn * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29187262Snwhitehorn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30187262Snwhitehorn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31187262Snwhitehorn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32187262Snwhitehorn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33187262Snwhitehorn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34187262Snwhitehorn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35187262Snwhitehorn * SUCH DAMAGE. 36187262Snwhitehorn */ 37187262Snwhitehorn#include "sh.h" 38187262Snwhitehorn 39187262SnwhitehornRCSID("$Id: tw.color.c,v 1.8 2001/03/18 19:06:32 christos Exp $") 40187262Snwhitehorn 41187262Snwhitehorn#include "tw.h" 42187262Snwhitehorn#include "ed.h" 43187262Snwhitehorn#include "tc.h" 44187262Snwhitehorn 45187262Snwhitehorn#ifdef COLOR_LS_F 46187262Snwhitehorn 47187262Snwhitehorntypedef struct { 48187262Snwhitehorn char *s; 49187262Snwhitehorn int len; 50187262Snwhitehorn} Str; 51187262Snwhitehorn 52187262Snwhitehorn 53187262Snwhitehorn#define VAR(suffix,variable,defaultcolor) \ 54187262Snwhitehorn{ \ 55187262Snwhitehorn suffix, variable, { defaultcolor, sizeof(defaultcolor) - 1 }, \ 56187262Snwhitehorn { defaultcolor, sizeof(defaultcolor) - 1 } \ 57187262Snwhitehorn} 58187262Snwhitehorn#define NOS '\0' /* no suffix */ 59187262Snwhitehorn 60209302Snwhitehorntypedef struct { 61187262Snwhitehorn const char suffix; 62187262Snwhitehorn const char *variable; 63187262Snwhitehorn Str color; 64187262Snwhitehorn Str defaultcolor; 65187262Snwhitehorn} Variable; 66187262Snwhitehorn 67187262Snwhitehornstatic Variable variables[] = { 68187262Snwhitehorn VAR('/', "di", "01;34"), /* Directory */ 69187262Snwhitehorn VAR('@', "ln", "01;36"), /* Symbolic link */ 70187262Snwhitehorn VAR('&', "or", ""), /* Orphanned symbolic link (defaults to ln) */ 71187262Snwhitehorn VAR('|', "pi", "33"), /* Named pipe (FIFO) */ 72187262Snwhitehorn VAR('=', "so", "01;35"), /* Socket */ 73187262Snwhitehorn VAR('>', "do", "01;35"), /* Door (solaris fast ipc mechanism) */ 74187262Snwhitehorn VAR('#', "bd", "01;33"), /* Block device */ 75187262Snwhitehorn VAR('%', "cd", "01;33"), /* Character device */ 76187262Snwhitehorn VAR('*', "ex", "01;32"), /* Executable file */ 77187262Snwhitehorn VAR(NOS, "fi", "0"), /* Regular file */ 78187262Snwhitehorn VAR(NOS, "no", "0"), /* Normal (non-filename) text */ 79187262Snwhitehorn VAR(NOS, "mi", ""), /* Missing file (defaults to fi) */ 80187262Snwhitehorn#ifdef IS_ASCII 81187262Snwhitehorn VAR(NOS, "lc", "\033["), /* Left code (ASCII) */ 82187262Snwhitehorn#else 83187262Snwhitehorn VAR(NOS, "lc", "\x27["), /* Left code (EBCDIC)*/ 84187262Snwhitehorn#endif 85187262Snwhitehorn VAR(NOS, "rc", "m"), /* Right code */ 86187262Snwhitehorn VAR(NOS, "ec", ""), /* End code (replaces lc+no+rc) */ 87187262Snwhitehorn}; 88187262Snwhitehorn 89187262Snwhitehornenum FileType { 90187262Snwhitehorn VDir, VSym, VOrph, VPipe, VSock, VDoor, VBlock, VChr, VExe, 91187262Snwhitehorn VFile, VNormal, VMiss, VLeft, VRight, VEnd 92187262Snwhitehorn}; 93187262Snwhitehorn 94187262Snwhitehorn#define nvariables (sizeof(variables)/sizeof(variables[0])) 95187262Snwhitehorn 96187262Snwhitehorntypedef struct { 97187262Snwhitehorn Str extension; /* file extension */ 98187262Snwhitehorn Str color; /* color string */ 99187262Snwhitehorn} Extension; 100187262Snwhitehorn 101187262Snwhitehornstatic Extension *extensions = NULL; 102187262Snwhitehornstatic int nextensions = 0; 103187262Snwhitehorn 104187262Snwhitehornstatic char *colors = NULL; 105187262Snwhitehornbool color_context_ls = FALSE; /* do colored ls */ 106187262Snwhitehornstatic bool color_context_lsmF = FALSE; /* do colored ls-F */ 107187262Snwhitehorn 108187262Snwhitehornstatic bool getstring __P((char **, const Char **, Str *, int)); 109187262Snwhitehornstatic void put_color __P((Str *)); 110187262Snwhitehornstatic void print_color __P((Char *, size_t, int)); 111208840Snwhitehorn 112187262Snwhitehorn/* set_color_context(): 113187262Snwhitehorn */ 114187262Snwhitehornvoid 115187262Snwhitehornset_color_context() 116187262Snwhitehorn{ 117187262Snwhitehorn struct varent *vp = adrof(STRcolor); 118187262Snwhitehorn 119208840Snwhitehorn if (!vp) { 120187262Snwhitehorn color_context_ls = FALSE; 121187262Snwhitehorn color_context_lsmF = FALSE; 122187262Snwhitehorn } 123187262Snwhitehorn else if (!vp->vec[0] || vp->vec[0][0] == '\0') { 124187262Snwhitehorn color_context_ls = TRUE; 125187262Snwhitehorn color_context_lsmF = TRUE; 126187262Snwhitehorn } 127187262Snwhitehorn else { 128187262Snwhitehorn size_t i; 129187262Snwhitehorn 130187262Snwhitehorn color_context_ls = FALSE; 131187262Snwhitehorn color_context_lsmF = FALSE; 132187262Snwhitehorn for (i = 0; vp->vec[i]; i++) 133187262Snwhitehorn if (Strcmp(vp->vec[i], STRls) == 0) 134187262Snwhitehorn color_context_ls = TRUE; 135187262Snwhitehorn else if (Strcmp(vp->vec[i], STRlsmF) == 0) 136187262Snwhitehorn color_context_lsmF = TRUE; 137187262Snwhitehorn } 138187262Snwhitehorn} 139187262Snwhitehorn 140187262Snwhitehorn 141187262Snwhitehorn/* getstring(): 142187262Snwhitehorn */ 143187262Snwhitehornstatic bool 144187262Snwhitehorngetstring(dp, sp, pd, f) 145187262Snwhitehorn char **dp; /* dest buffer */ 146187262Snwhitehorn const Char **sp; /* source buffer */ 147187262Snwhitehorn Str *pd; /* pointer to dest buffer */ 148187262Snwhitehorn int f; /* final character */ 149187262Snwhitehorn{ 150209302Snwhitehorn const Char *s = *sp; 151187262Snwhitehorn char *d = *dp; 152187262Snwhitehorn int sc; 153187262Snwhitehorn 154187262Snwhitehorn while (*s && (*s & CHAR) != f && (*s & CHAR) != ':') { 155187262Snwhitehorn if ((*s & CHAR) == '\\' || (*s & CHAR) == '^') { 156187262Snwhitehorn if ((sc = parseescape(&s)) == -1) 157187262Snwhitehorn return 0; 158187262Snwhitehorn else 159187262Snwhitehorn *d++ = (char) sc; 160187262Snwhitehorn } 161187262Snwhitehorn else 162187262Snwhitehorn *d++ = *s++ & CHAR; 163187262Snwhitehorn } 164187262Snwhitehorn 165187262Snwhitehorn pd->s = *dp; 166187262Snwhitehorn pd->len = (int) (d - *dp); 167187262Snwhitehorn *sp = s; 168187262Snwhitehorn *dp = d; 169187262Snwhitehorn return *s == f; 170187262Snwhitehorn} 171187262Snwhitehorn 172187262Snwhitehorn 173187262Snwhitehorn/* parseLS_COLORS(): 174187262Snwhitehorn * Parse the LS_COLORS environment variable 175187262Snwhitehorn */ 176187262Snwhitehornvoid 177187262SnwhitehornparseLS_COLORS(value) 178187262Snwhitehorn Char *value; /* LS_COLOR variable's value */ 179187262Snwhitehorn{ 180187262Snwhitehorn int i; 181187262Snwhitehorn size_t len; 182187262Snwhitehorn const Char *v; /* pointer in value */ 183187262Snwhitehorn char *c; /* pointer in colors */ 184187262Snwhitehorn Extension *e; /* pointer in extensions */ 185187262Snwhitehorn jmp_buf_t osetexit; 186187262Snwhitehorn 187187262Snwhitehorn /* init */ 188187262Snwhitehorn if (extensions) 189187262Snwhitehorn xfree((ptr_t) extensions); 190187262Snwhitehorn for (i = 0; i < nvariables; i++) 191187262Snwhitehorn variables[i].color = variables[i].defaultcolor; 192187262Snwhitehorn colors = NULL; 193187262Snwhitehorn extensions = NULL; 194187262Snwhitehorn nextensions = 0; 195187262Snwhitehorn 196187262Snwhitehorn if (value == NULL) 197187262Snwhitehorn return; 198187262Snwhitehorn 199187262Snwhitehorn len = Strlen(value); 200187262Snwhitehorn /* allocate memory */ 201187262Snwhitehorn i = 1; 202187262Snwhitehorn for (v = value; *v; v++) 203208840Snwhitehorn if ((*v & CHAR) == ':') 204208840Snwhitehorn i++; 205208840Snwhitehorn extensions = (Extension *) xmalloc((size_t) (len + i * sizeof(Extension))); 206208840Snwhitehorn colors = i * sizeof(Extension) + (char *)extensions; 207208840Snwhitehorn nextensions = 0; 208208840Snwhitehorn 209187262Snwhitehorn /* init pointers */ 210187262Snwhitehorn v = value; 211208840Snwhitehorn c = colors; 212208840Snwhitehorn e = &extensions[0]; 213208840Snwhitehorn 214208840Snwhitehorn /* Prevent from crashing if unknown parameters are given. */ 215208840Snwhitehorn 216208840Snwhitehorn getexit(osetexit); 217208840Snwhitehorn 218208840Snwhitehorn if (setexit() == 0) { 219208840Snwhitehorn 220187262Snwhitehorn /* parse */ 221208840Snwhitehorn while (*v) { 222187262Snwhitehorn switch (*v & CHAR) { 223187262Snwhitehorn case ':': 224187262Snwhitehorn v++; 225187262Snwhitehorn continue; 226187262Snwhitehorn 227187262Snwhitehorn case '*': /* :*ext=color: */ 228187262Snwhitehorn v++; 229187262Snwhitehorn if (getstring(&c, &v, &e->extension, '=') && 230187262Snwhitehorn 0 < e->extension.len) { 231208840Snwhitehorn v++; 232187262Snwhitehorn getstring(&c, &v, &e->color, ':'); 233187262Snwhitehorn e++; 234187262Snwhitehorn continue; 235187262Snwhitehorn } 236187262Snwhitehorn break; 237187262Snwhitehorn 238187262Snwhitehorn default: /* :vl=color: */ 239187262Snwhitehorn if (v[0] && v[1] && (v[2] & CHAR) == '=') { 240209302Snwhitehorn for (i = 0; i < nvariables; i++) 241209302Snwhitehorn if (variables[i].variable[0] == (v[0] & CHAR) && 242209302Snwhitehorn variables[i].variable[1] == (v[1] & CHAR)) 243187262Snwhitehorn break; 244187262Snwhitehorn if (i < nvariables) { 245187262Snwhitehorn v += 3; 246187262Snwhitehorn getstring(&c, &v, &variables[i].color, ':'); 247187262Snwhitehorn continue; 248187262Snwhitehorn } 249187262Snwhitehorn else 250187262Snwhitehorn stderror(ERR_BADCOLORVAR, v[0], v[1]); 251187262Snwhitehorn } 252209302Snwhitehorn break; 253212687Sandreast } 254187262Snwhitehorn while (*v && (*v & CHAR) != ':') 255187262Snwhitehorn v++; 256187262Snwhitehorn } 257187262Snwhitehorn } 258187262Snwhitehorn 259209302Snwhitehorn resexit(osetexit); 260187262Snwhitehorn 261187262Snwhitehorn nextensions = (int) (e - extensions); 262187262Snwhitehorn} 263187262Snwhitehorn 264187262Snwhitehorn 265187262Snwhitehorn/* put_color(): 266187262Snwhitehorn */ 267187262Snwhitehornstatic void 268187262Snwhitehornput_color(color) 269187262Snwhitehorn Str *color; 270187262Snwhitehorn{ 271187262Snwhitehorn extern bool output_raw; /* PWP: in sh.print.c */ 272187262Snwhitehorn size_t i; 273187262Snwhitehorn char *c = color->s; 274187262Snwhitehorn bool original_output_raw = output_raw; 275208840Snwhitehorn 276208840Snwhitehorn output_raw = TRUE; 277208840Snwhitehorn for (i = color->len; 0 < i; i--) 278208840Snwhitehorn xputchar(*c++); 279208840Snwhitehorn output_raw = original_output_raw; 280208840Snwhitehorn} 281208840Snwhitehorn 282208840Snwhitehorn 283208840Snwhitehorn/* print_color(): 284208840Snwhitehorn */ 285208840Snwhitehornstatic void 286208840Snwhitehornprint_color(fname, len, suffix) 287187262Snwhitehorn Char *fname; 288187262Snwhitehorn size_t len; 289187262Snwhitehorn int suffix; 290187262Snwhitehorn{ 291187262Snwhitehorn int i; 292187262Snwhitehorn char *filename = short2str(fname); 293187262Snwhitehorn char *last = filename + len; 294187262Snwhitehorn Str *color = &variables[VFile].color; 295187262Snwhitehorn 296187262Snwhitehorn switch (suffix) { 297187262Snwhitehorn case '>': /* File is a symbolic link pointing to 298187262Snwhitehorn * a directory */ 299187262Snwhitehorn color = &variables[VDir].color; 300187262Snwhitehorn break; 301187262Snwhitehorn case '+': /* File is a hidden directory [aix] or 302187262Snwhitehorn * context dependent [hpux] */ 303187262Snwhitehorn case ':': /* File is network special [hpux] */ 304187262Snwhitehorn break; 305187262Snwhitehorn default: 306187262Snwhitehorn for (i = 0; i < nvariables; i++) 307187262Snwhitehorn if (variables[i].suffix != NOS && 308187262Snwhitehorn variables[i].suffix == suffix) { 309187262Snwhitehorn color = &variables[i].color; 310187262Snwhitehorn break; 311187262Snwhitehorn } 312187262Snwhitehorn if (i == nvariables) { 313187262Snwhitehorn for (i = 0; i < nextensions; i++) 314187262Snwhitehorn if (strncmp(last - extensions[i].extension.len, 315187262Snwhitehorn extensions[i].extension.s, 316187262Snwhitehorn extensions[i].extension.len) == 0) { 317187262Snwhitehorn color = &extensions[i].color; 318187262Snwhitehorn break; 319187262Snwhitehorn } 320187262Snwhitehorn } 321187262Snwhitehorn break; 322187262Snwhitehorn } 323187262Snwhitehorn 324187473Snwhitehorn put_color(&variables[VLeft].color); 325187473Snwhitehorn put_color(color); 326187262Snwhitehorn put_color(&variables[VRight].color); 327187262Snwhitehorn} 328187473Snwhitehorn 329208840Snwhitehorn 330208840Snwhitehorn/* print_with_color(): 331187473Snwhitehorn */ 332187473Snwhitehornvoid 333187473Snwhitehornprint_with_color(filename, len, suffix) 334187473Snwhitehorn Char *filename; 335187473Snwhitehorn size_t len; 336187262Snwhitehorn int suffix; 337187262Snwhitehorn{ 338187262Snwhitehorn if (color_context_lsmF && 339187262Snwhitehorn (haderr ? (didfds ? is2atty : isdiagatty) : 340187262Snwhitehorn (didfds ? is1atty : isoutatty))) { 341187262Snwhitehorn print_color(filename, len, suffix); 342187262Snwhitehorn xprintf("%S", filename); 343187262Snwhitehorn if (0 < variables[VEnd].color.len) 344187262Snwhitehorn put_color(&variables[VEnd].color); 345187262Snwhitehorn else { 346187262Snwhitehorn put_color(&variables[VLeft].color); 347187262Snwhitehorn put_color(&variables[VNormal].color); 348187262Snwhitehorn put_color(&variables[VRight].color); 349187262Snwhitehorn } 350187262Snwhitehorn xputchar(suffix); 351187262Snwhitehorn } 352187262Snwhitehorn else 353187262Snwhitehorn xprintf("%S%c", filename, suffix); 354187262Snwhitehorn} 355187262Snwhitehorn 356187262Snwhitehorn 357187473Snwhitehorn#endif /* COLOR_LS_F */ 358208840Snwhitehorn