]> git.ipfire.org Git - thirdparty/bash.git/blame - lib/readline/colors.c
bash-4.3-beta overlay
[thirdparty/bash.git] / lib / readline / colors.c
CommitLineData
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
62static bool is_colored (enum indicator_no type);
63static void restore_default_color (void);
64
65COLOR_EXT_TYPE *_rl_color_ext_list = 0;
66
67/* Output a color indicator (which may contain nulls). */
68void
69_rl_put_indicator (const struct bin_str *ind) {
70 fwrite (ind->string, ind->len, 1, rl_outstream);
71}
72
73static bool
74is_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
83static void
84restore_default_color (void)
85{
86 _rl_put_indicator (&_rl_color_indicator[C_LEFT]);
87 _rl_put_indicator (&_rl_color_indicator[C_RIGHT]);
88}
89
90void
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. */
102bool
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
239void
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 */