~ubuntu-branches/ubuntu/trusty/bash/trusty-security

« back to all changes in this revision

Viewing changes to lib/readline/parse-colors.c

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2014-03-03 22:52:05 UTC
  • mfrom: (1.3.5) (2.2.6 experimental)
  • Revision ID: package-import@ubuntu.com-20140303225205-87ltrt5kspeq0g1b
Tags: 4.3-1ubuntu1
* Merge with Debian; remaining changes:
  - skel.bashrc:
    - Run lesspipe.
    - Enable ls aliases.
    - Set options in ll alias to -alF.
    - Define an alert alias.
    - Enabled colored grep aliases.
  - etc.bash.bashrc:
    - Add sudo hint.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* `dir', `vdir' and `ls' directory listing programs for GNU.
 
2
 
 
3
   Modified by Chet Ramey for Readline.
 
4
 
 
5
   Copyright (C) 1985, 1988, 1990-1991, 1995-2010, 2012 Free Software Foundation,
 
6
   Inc.
 
7
 
 
8
   This program is free software: you can redistribute it and/or modify
 
9
   it under the terms of the GNU General Public License as published by
 
10
   the Free Software Foundation, either version 3 of the License, or
 
11
   (at your option) any later version.
 
12
 
 
13
   This program is distributed in the hope that it will be useful,
 
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
   GNU General Public License for more details.
 
17
 
 
18
   You should have received a copy of the GNU General Public License
 
19
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
20
 
 
21
/* Written by Richard Stallman and David MacKenzie.  */
 
22
 
 
23
/* Color support by Peter Anvin <Peter.Anvin@linux.org> and Dennis
 
24
   Flaherty <dennisf@denix.elk.miles.com> based on original patches by
 
25
   Greg Lee <lee@uhunix.uhcc.hawaii.edu>.  */
 
26
 
 
27
#define READLINE_LIBRARY
 
28
 
 
29
#if defined (HAVE_CONFIG_H)
 
30
#  include <config.h>
 
31
#endif
 
32
 
 
33
#include <stdio.h>
 
34
 
 
35
// strdup() / strcpy()
 
36
#if defined (HAVE_STRING_H)
 
37
#  include <string.h>
 
38
#else /* !HAVE_STRING_H */
 
39
#  include <strings.h>
 
40
#endif /* !HAVE_STRING_H */
 
41
 
 
42
// abort()
 
43
#if defined (HAVE_STDLIB_H)
 
44
#  include <stdlib.h>
 
45
#else
 
46
#  include "ansi_stdlib.h"
 
47
#endif /* HAVE_STDLIB_H */
 
48
 
 
49
#include "rldefs.h"     // STREQ, savestring
 
50
#include "readline.h"
 
51
#include "rlprivate.h"
 
52
#include "rlshell.h"
 
53
#include "xmalloc.h"
 
54
 
 
55
#include "colors.h"
 
56
#include "parse-colors.h"
 
57
 
 
58
#if defined (COLOR_SUPPORT)
 
59
 
 
60
static bool get_funky_string (char **dest, const char **src, bool equals_end, size_t *output_count);
 
61
 
 
62
struct bin_str _rl_color_indicator[] =
 
63
  {
 
64
    { LEN_STR_PAIR ("\033[") },         //  lc: Left of color sequence
 
65
    { LEN_STR_PAIR ("m") },             //  rc: Right of color sequence
 
66
    { 0, NULL },                        //  ec: End color (replaces lc+no+rc)
 
67
    { LEN_STR_PAIR ("0") },             //  rs: Reset to ordinary colors
 
68
    { 0, NULL },                        //  no: Normal
 
69
    { 0, NULL },                        //  fi: File: default
 
70
    { LEN_STR_PAIR ("01;34") },         //  di: Directory: bright blue
 
71
    { LEN_STR_PAIR ("01;36") },         //  ln: Symlink: bright cyan
 
72
    { LEN_STR_PAIR ("33") },            //  pi: Pipe: yellow/brown
 
73
    { LEN_STR_PAIR ("01;35") },         //  so: Socket: bright magenta
 
74
    { LEN_STR_PAIR ("01;33") },         //  bd: Block device: bright yellow
 
75
    { LEN_STR_PAIR ("01;33") },         //  cd: Char device: bright yellow
 
76
    { 0, NULL },                        //  mi: Missing file: undefined
 
77
    { 0, NULL },                        //  or: Orphaned symlink: undefined
 
78
    { LEN_STR_PAIR ("01;32") },         //  ex: Executable: bright green
 
79
    { LEN_STR_PAIR ("01;35") },         //  do: Door: bright magenta
 
80
    { LEN_STR_PAIR ("37;41") },         //  su: setuid: white on red
 
81
    { LEN_STR_PAIR ("30;43") },         //  sg: setgid: black on yellow
 
82
    { LEN_STR_PAIR ("37;44") },         //  st: sticky: black on blue
 
83
    { LEN_STR_PAIR ("34;42") },         //  ow: other-writable: blue on green
 
84
    { LEN_STR_PAIR ("30;42") },         //  tw: ow w/ sticky: black on green
 
85
    { LEN_STR_PAIR ("30;41") },         //  ca: black on red
 
86
    { 0, NULL },                        //  mh: disabled by default
 
87
    { LEN_STR_PAIR ("\033[K") },        //  cl: clear to end of line
 
88
  };
 
89
 
 
90
/* Parse a string as part of the LS_COLORS variable; this may involve
 
91
   decoding all kinds of escape characters.  If equals_end is set an
 
92
   unescaped equal sign ends the string, otherwise only a : or \0
 
93
   does.  Set *OUTPUT_COUNT to the number of bytes output.  Return
 
94
   true if successful.
 
95
 
 
96
   The resulting string is *not* null-terminated, but may contain
 
97
   embedded nulls.
 
98
 
 
99
   Note that both dest and src are char **; on return they point to
 
100
   the first free byte after the array and the character that ended
 
101
   the input string, respectively.  */
 
102
 
 
103
static bool
 
104
get_funky_string (char **dest, const char **src, bool equals_end, size_t *output_count) {
 
105
  char num;                     /* For numerical codes */
 
106
  size_t count;                 /* Something to count with */
 
107
  enum {
 
108
    ST_GND, ST_BACKSLASH, ST_OCTAL, ST_HEX, ST_CARET, ST_END, ST_ERROR
 
109
  } state;
 
110
  const char *p;
 
111
  char *q;
 
112
 
 
113
  p = *src;                     /* We don't want to double-indirect */
 
114
  q = *dest;                    /* the whole darn time.  */
 
115
 
 
116
  count = 0;                    /* No characters counted in yet.  */
 
117
  num = 0;
 
118
 
 
119
  state = ST_GND;               /* Start in ground state.  */
 
120
  while (state < ST_END)
 
121
    {
 
122
      switch (state)
 
123
        {
 
124
        case ST_GND:            /* Ground state (no escapes) */
 
125
          switch (*p)
 
126
            {
 
127
            case ':':
 
128
            case '\0':
 
129
              state = ST_END;   /* End of string */
 
130
              break;
 
131
            case '\\':
 
132
              state = ST_BACKSLASH; /* Backslash scape sequence */
 
133
              ++p;
 
134
              break;
 
135
            case '^':
 
136
              state = ST_CARET; /* Caret escape */
 
137
              ++p;
 
138
              break;
 
139
            case '=':
 
140
              if (equals_end)
 
141
                {
 
142
                  state = ST_END; /* End */
 
143
                  break;
 
144
                }
 
145
              /* else fall through */
 
146
            default:
 
147
              *(q++) = *(p++);
 
148
              ++count;
 
149
              break;
 
150
            }
 
151
          break;
 
152
 
 
153
        case ST_BACKSLASH:      /* Backslash escaped character */
 
154
          switch (*p)
 
155
            {
 
156
            case '0':
 
157
            case '1':
 
158
            case '2':
 
159
            case '3':
 
160
            case '4':
 
161
            case '5':
 
162
            case '6':
 
163
            case '7':
 
164
              state = ST_OCTAL; /* Octal sequence */
 
165
              num = *p - '0';
 
166
              break;
 
167
            case 'x':
 
168
            case 'X':
 
169
              state = ST_HEX;   /* Hex sequence */
 
170
              num = 0;
 
171
              break;
 
172
            case 'a':           /* Bell */
 
173
              num = '\a';
 
174
              break;
 
175
            case 'b':           /* Backspace */
 
176
              num = '\b';
 
177
              break;
 
178
            case 'e':           /* Escape */
 
179
              num = 27;
 
180
              break;
 
181
            case 'f':           /* Form feed */
 
182
              num = '\f';
 
183
              break;
 
184
            case 'n':           /* Newline */
 
185
              num = '\n';
 
186
              break;
 
187
            case 'r':           /* Carriage return */
 
188
              num = '\r';
 
189
              break;
 
190
            case 't':           /* Tab */
 
191
              num = '\t';
 
192
              break;
 
193
            case 'v':           /* Vtab */
 
194
              num = '\v';
 
195
              break;
 
196
            case '?':           /* Delete */
 
197
              num = 127;
 
198
              break;
 
199
            case '_':           /* Space */
 
200
              num = ' ';
 
201
              break;
 
202
            case '\0':          /* End of string */
 
203
              state = ST_ERROR; /* Error! */
 
204
              break;
 
205
            default:            /* Escaped character like \ ^ : = */
 
206
              num = *p;
 
207
              break;
 
208
            }
 
209
          if (state == ST_BACKSLASH)
 
210
            {
 
211
              *(q++) = num;
 
212
              ++count;
 
213
              state = ST_GND;
 
214
            }
 
215
          ++p;
 
216
          break;
 
217
 
 
218
        case ST_OCTAL:          /* Octal sequence */
 
219
          if (*p < '0' || *p > '7')
 
220
            {
 
221
              *(q++) = num;
 
222
              ++count;
 
223
              state = ST_GND;
 
224
            }
 
225
          else
 
226
            num = (num << 3) + (*(p++) - '0');
 
227
          break;
 
228
 
 
229
        case ST_HEX:            /* Hex sequence */
 
230
          switch (*p)
 
231
            {
 
232
            case '0':
 
233
            case '1':
 
234
            case '2':
 
235
            case '3':
 
236
            case '4':
 
237
            case '5':
 
238
            case '6':
 
239
            case '7':
 
240
            case '8':
 
241
            case '9':
 
242
              num = (num << 4) + (*(p++) - '0');
 
243
              break;
 
244
            case 'a':
 
245
            case 'b':
 
246
            case 'c':
 
247
            case 'd':
 
248
            case 'e':
 
249
            case 'f':
 
250
              num = (num << 4) + (*(p++) - 'a') + 10;
 
251
              break;
 
252
            case 'A':
 
253
            case 'B':
 
254
            case 'C':
 
255
            case 'D':
 
256
            case 'E':
 
257
            case 'F':
 
258
              num = (num << 4) + (*(p++) - 'A') + 10;
 
259
              break;
 
260
            default:
 
261
              *(q++) = num;
 
262
              ++count;
 
263
              state = ST_GND;
 
264
              break;
 
265
            }
 
266
          break;
 
267
 
 
268
        case ST_CARET:          /* Caret escape */
 
269
          state = ST_GND;       /* Should be the next state... */
 
270
          if (*p >= '@' && *p <= '~')
 
271
            {
 
272
              *(q++) = *(p++) & 037;
 
273
              ++count;
 
274
            }
 
275
          else if (*p == '?')
 
276
            {
 
277
              *(q++) = 127;
 
278
              ++count;
 
279
            }
 
280
          else
 
281
            state = ST_ERROR;
 
282
          break;
 
283
 
 
284
        default:
 
285
          /* should we ? */
 
286
          /* abort ();  no, we should not */
 
287
          state = ST_ERROR;
 
288
          break;
 
289
        }
 
290
    }
 
291
 
 
292
  *dest = q;
 
293
  *src = p;
 
294
  *output_count = count;
 
295
 
 
296
  return state != ST_ERROR;
 
297
}
 
298
#endif /* COLOR_SUPPORT */
 
299
 
 
300
void _rl_parse_colors()
 
301
{
 
302
#if defined (COLOR_SUPPORT)
 
303
  const char *p;                /* Pointer to character being parsed */
 
304
  char *buf;                    /* color_buf buffer pointer */
 
305
  int state;                    /* State of parser */
 
306
  int ind_no;                   /* Indicator number */
 
307
  char label[3];                /* Indicator label */
 
308
  COLOR_EXT_TYPE *ext;          /* Extension we are working on */
 
309
 
 
310
  p = sh_get_env_value ("LS_COLORS");
 
311
  if (p == 0 || *p == '\0')
 
312
    {
 
313
      _rl_color_ext_list = NULL;
 
314
      return;
 
315
    }
 
316
 
 
317
  ext = NULL;
 
318
  strcpy (label, "??");
 
319
 
 
320
  /* This is an overly conservative estimate, but any possible
 
321
     LS_COLORS string will *not* generate a color_buf longer than
 
322
     itself, so it is a safe way of allocating a buffer in
 
323
     advance.  */
 
324
  buf = color_buf = savestring (p);
 
325
 
 
326
  state = 1;
 
327
  while (state > 0)
 
328
    {
 
329
      switch (state)
 
330
        {
 
331
        case 1:         /* First label character */
 
332
          switch (*p)
 
333
            {
 
334
            case ':':
 
335
              ++p;
 
336
              break;
 
337
 
 
338
            case '*':
 
339
              /* Allocate new extension block and add to head of
 
340
                 linked list (this way a later definition will
 
341
                 override an earlier one, which can be useful for
 
342
                 having terminal-specific defs override global).  */
 
343
 
 
344
              ext = (COLOR_EXT_TYPE *)xmalloc (sizeof *ext);
 
345
              ext->next = _rl_color_ext_list;
 
346
              _rl_color_ext_list = ext;
 
347
 
 
348
              ++p;
 
349
              ext->ext.string = buf;
 
350
 
 
351
              state = (get_funky_string (&buf, &p, true, &ext->ext.len)
 
352
                       ? 4 : -1);
 
353
              break;
 
354
 
 
355
            case '\0':
 
356
              state = 0;        /* Done! */
 
357
              break;
 
358
 
 
359
            default:    /* Assume it is file type label */
 
360
              label[0] = *(p++);
 
361
              state = 2;
 
362
              break;
 
363
            }
 
364
          break;
 
365
 
 
366
        case 2:         /* Second label character */
 
367
          if (*p)
 
368
            {
 
369
              label[1] = *(p++);
 
370
              state = 3;
 
371
            }
 
372
          else
 
373
            state = -1; /* Error */
 
374
          break;
 
375
 
 
376
        case 3:         /* Equal sign after indicator label */
 
377
          state = -1;   /* Assume failure...  */
 
378
          if (*(p++) == '=')/* It *should* be...  */
 
379
            {
 
380
              for (ind_no = 0; indicator_name[ind_no] != NULL; ++ind_no)
 
381
                {
 
382
                  if (STREQ (label, indicator_name[ind_no]))
 
383
                    {
 
384
                      _rl_color_indicator[ind_no].string = buf;
 
385
                      state = (get_funky_string (&buf, &p, false,
 
386
                                                 &_rl_color_indicator[ind_no].len)
 
387
                               ? 1 : -1);
 
388
                      break;
 
389
                    }
 
390
                }
 
391
              if (state == -1)
 
392
                {
 
393
                  _rl_errmsg ("LS_COLORS: unrecognized prefix: %s", label);
 
394
                  /* recover from an unrecognized prefix */
 
395
                  while (p && *p && *p != ':')
 
396
                    p++;
 
397
                  if (p && *p == ':')
 
398
                    state = 1;
 
399
                  else if (p && *p == 0)
 
400
                    state = 0;
 
401
                }
 
402
            }
 
403
          break;
 
404
 
 
405
        case 4:         /* Equal sign after *.ext */
 
406
          if (*(p++) == '=')
 
407
            {
 
408
              ext->seq.string = buf;
 
409
              state = (get_funky_string (&buf, &p, false, &ext->seq.len)
 
410
                       ? 1 : -1);
 
411
            }
 
412
          else
 
413
            state = -1;
 
414
          /* XXX - recover here as with an unrecognized prefix? */
 
415
          if (state == -1 && ext->ext.string)
 
416
            _rl_errmsg ("LS_COLORS: syntax error: %s", ext->ext.string);
 
417
          break;
 
418
        }
 
419
    }
 
420
 
 
421
  if (state < 0)
 
422
    {
 
423
      COLOR_EXT_TYPE *e;
 
424
      COLOR_EXT_TYPE *e2;
 
425
 
 
426
      _rl_errmsg ("unparsable value for LS_COLORS environment variable");
 
427
      free (color_buf);
 
428
      for (e = _rl_color_ext_list; e != NULL; /* empty */)
 
429
        {
 
430
          e2 = e;
 
431
          e = e->next;
 
432
          free (e2);
 
433
        }
 
434
      _rl_color_ext_list = NULL;
 
435
      _rl_colored_stats = 0;    /* can't have colored stats without colors */
 
436
    }
 
437
#else /* !COLOR_SUPPORT */
 
438
  ;
 
439
#endif /* !COLOR_SUPPORT */
 
440
}