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 "rlconf.h"
34:
35: #include <stdio.h>
36:
37: #include "posixstat.h" // stat related macros (S_ISREG, ...)
38: #include <fcntl.h> // S_ISUID
39:
40: // strlen()
41: #if defined (HAVE_STRING_H)
42: # include <string.h>
43: #else /* !HAVE_STRING_H */
44: # include <strings.h>
45: #endif /* !HAVE_STRING_H */
46:
47: // abort()
48: #if defined (HAVE_STDLIB_H)
49: # include <stdlib.h>
50: #else
51: # include "ansi_stdlib.h"
52: #endif /* HAVE_STDLIB_H */
53:
54: #include "readline.h"
55: #include "rldefs.h"
56:
57: #ifdef COLOR_SUPPORT
58:
59: #include "xmalloc.h"
60: #include "colors.h"
61:
62: static bool is_colored (enum indicator_no type);
63: static void restore_default_color (void);
64:
65: COLOR_EXT_TYPE *_rl_color_ext_list = 0;
66:
67: /* Output a color indicator (which may contain nulls). */
68: void
69: _rl_put_indicator (const struct bin_str *ind) {
70: fwrite (ind->string, ind->len, 1, rl_outstream);
71: }
72:
73: static bool
74: is_colored (enum indicator_no colored_filetype)
75: {
76: size_t len = _rl_color_indicator[colored_filetype].len;
77: char const *s = _rl_color_indicator[colored_filetype].string;
78: return ! (len == 0
79: || (len == 1 && strncmp (s, "0", 1) == 0)
80: || (len == 2 && strncmp (s, "00", 2) == 0));
81: }
82:
83: static void
84: restore_default_color (void)
85: {
86: _rl_put_indicator (&_rl_color_indicator[C_LEFT]);
87: _rl_put_indicator (&_rl_color_indicator[C_RIGHT]);
88: }
89:
90: void
91: _rl_set_normal_color (void)
92: {
93: if (is_colored (C_NORM))
94: {
95: _rl_put_indicator (&_rl_color_indicator[C_LEFT]);
96: _rl_put_indicator (&_rl_color_indicator[C_NORM]);
97: _rl_put_indicator (&_rl_color_indicator[C_RIGHT]);
98: }
99: }
100:
101: /* Returns whether any color sequence was printed. */
102: bool
103: _rl_print_color_indicator (char *f)
104: {
105: enum indicator_no colored_filetype;
106: COLOR_EXT_TYPE *ext; /* Color extension */
107: size_t len; /* Length of name */
108:
109: const char* name;
110: char *filename;
111: struct stat astat;
112: mode_t mode;
113: int linkok;
114:
115: int stat_ok;
116:
117: name = f;
118:
119: /* This should already have undergone tilde expansion */
120: filename = 0;
121: if (rl_filename_stat_hook)
122: {
123: filename = savestring (f);
124: (*rl_filename_stat_hook) (&filename);
125: name = filename;
126: }
127:
128: #if defined (HAVE_LSTAT)
129: stat_ok = lstat(name, &astat);
130: #else
131: stat_ok = stat(name, &astat);
132: #endif
133: if( stat_ok == 0 ) {
134: mode = astat.st_mode;
135: linkok = 1; //f->linkok;
136: }
137: else
138: linkok = -1;
139:
140: /* Is this a nonexistent file? If so, linkok == -1. */
141:
142: if (linkok == -1 && _rl_color_indicator[C_MISSING].string != NULL)
143: colored_filetype = C_MISSING;
144: else if(stat_ok != 0)
145: {
146: static enum indicator_no filetype_indicator[] = FILETYPE_INDICATORS;
147: colored_filetype = filetype_indicator[normal]; //f->filetype];
148: }
149: else
150: {
151: if (S_ISREG (mode))
152: {
153: colored_filetype = C_FILE;
154:
155: if ((mode & S_ISUID) != 0 && is_colored (C_SETUID))
156: colored_filetype = C_SETUID;
157: else if ((mode & S_ISGID) != 0 && is_colored (C_SETGID))
158: colored_filetype = C_SETGID;
159: else if (is_colored (C_CAP) && 0) //f->has_capability)
160: colored_filetype = C_CAP;
161: else if ((mode & S_IXUGO) != 0 && is_colored (C_EXEC))
162: colored_filetype = C_EXEC;
163: else if ((1 < astat.st_nlink) && is_colored (C_MULTIHARDLINK))
164: colored_filetype = C_MULTIHARDLINK;
165: }
166: else if (S_ISDIR (mode))
167: {
168: colored_filetype = C_DIR;
169:
170: #if defined (S_ISVTX)
171: if ((mode & S_ISVTX) && (mode & S_IWOTH)
172: && is_colored (C_STICKY_OTHER_WRITABLE))
173: colored_filetype = C_STICKY_OTHER_WRITABLE;
174: else
175: #endif
176: if ((mode & S_IWOTH) != 0 && is_colored (C_OTHER_WRITABLE))
177: colored_filetype = C_OTHER_WRITABLE;
178: #if defined (S_ISVTX)
179: else if ((mode & S_ISVTX) != 0 && is_colored (C_STICKY))
180: colored_filetype = C_STICKY;
181: #endif
182: }
183: else if (S_ISLNK (mode))
184: colored_filetype = ((linkok == 0
185: && (!strncmp (_rl_color_indicator[C_LINK].string, "target", 6)
186: || _rl_color_indicator[C_ORPHAN].string))
187: ? C_ORPHAN : C_LINK);
188: else if (S_ISFIFO (mode))
189: colored_filetype = C_FIFO;
190: else if (S_ISSOCK (mode))
191: colored_filetype = C_SOCK;
192: else if (S_ISBLK (mode))
193: colored_filetype = C_BLK;
194: else if (S_ISCHR (mode))
195: colored_filetype = C_CHR;
196: else
197: {
198: /* Classify a file of some other type as C_ORPHAN. */
199: colored_filetype = C_ORPHAN;
200: }
201: }
202:
203: /* Check the file's suffix only if still classified as C_FILE. */
204: ext = NULL;
205: if (colored_filetype == C_FILE)
206: {
207: /* Test if NAME has a recognized suffix. */
208: len = strlen (name);
209: name += len; /* Pointer to final \0. */
210: for (ext = _rl_color_ext_list; ext != NULL; ext = ext->next)
211: {
212: if (ext->ext.len <= len
213: && strncmp (name - ext->ext.len, ext->ext.string,
214: ext->ext.len) == 0)
215: break;
216: }
217: }
218:
219: free (filename); /* NULL or savestring return value */
220:
221: {
222: const struct bin_str *const s
223: = ext ? &(ext->seq) : &_rl_color_indicator[colored_filetype];
224: if (s->string != NULL)
225: {
226: /* Need to reset so not dealing with attribute combinations */
227: if (is_colored (C_NORM))
228: restore_default_color ();
229: _rl_put_indicator (&_rl_color_indicator[C_LEFT]);
230: _rl_put_indicator (s);
231: _rl_put_indicator (&_rl_color_indicator[C_RIGHT]);
232: return 0;
233: }
234: else
235: return 1;
236: }
237: }
238:
239: void
240: _rl_prep_non_filename_text (void)
241: {
242: if (_rl_color_indicator[C_END].string != NULL)
243: _rl_put_indicator (&_rl_color_indicator[C_END]);
244: else
245: {
246: _rl_put_indicator (&_rl_color_indicator[C_LEFT]);
247: _rl_put_indicator (&_rl_color_indicator[C_RESET]);
248: _rl_put_indicator (&_rl_color_indicator[C_RIGHT]);
249: }
250: }
251: #endif /* COLOR_SUPPORT */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>