]>
Commit | Line | Data |
---|---|---|
5a318736 CR |
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 | ||
c677e9e0 CR |
115 | int stat_ok; |
116 | ||
5a318736 CR |
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) | |
c677e9e0 | 129 | stat_ok = lstat(name, &astat); |
5a318736 | 130 | #else |
c677e9e0 | 131 | stat_ok = stat(name, &astat); |
5a318736 CR |
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 | ||
1442f67c | 170 | #if defined (S_ISVTX) |
5a318736 CR |
171 | if ((mode & S_ISVTX) && (mode & S_IWOTH) |
172 | && is_colored (C_STICKY_OTHER_WRITABLE)) | |
173 | colored_filetype = C_STICKY_OTHER_WRITABLE; | |
1442f67c CR |
174 | else |
175 | #endif | |
176 | if ((mode & S_IWOTH) != 0 && is_colored (C_OTHER_WRITABLE)) | |
5a318736 | 177 | colored_filetype = C_OTHER_WRITABLE; |
1442f67c | 178 | #if defined (S_ISVTX) |
5a318736 CR |
179 | else if ((mode & S_ISVTX) != 0 && is_colored (C_STICKY)) |
180 | colored_filetype = C_STICKY; | |
1442f67c | 181 | #endif |
5a318736 CR |
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 */ |