1 /* `dir', `vdir' and `ls' directory listing programs for GNU.
3 Modified by Chet Ramey for Readline.
5 Copyright (C) 1985, 1988, 1990-1991, 1995-2010, 2012, 2015, 2017, 2019
6 Free Software Foundation, Inc.
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.
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.
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/>. */
21 /* Written by Richard Stallman and David MacKenzie. */
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>. */
27 #define READLINE_LIBRARY
29 #if defined (HAVE_CONFIG_H)
36 # define _XOPEN_SOURCE_EXTENDED 1
37 # define _TANDEM_SOURCE 1
38 # include <sys/types.h>
39 # include <sys/stat.h>
44 #include "posixstat.h" // stat related macros (S_ISREG, ...)
45 #include <fcntl.h> // S_ISUID
48 # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
52 #if defined (HAVE_STRING_H)
54 #else /* !HAVE_STRING_H */
56 #endif /* !HAVE_STRING_H */
59 #if defined (HAVE_STDLIB_H)
62 # include "ansi_stdlib.h"
63 #endif /* HAVE_STDLIB_H */
73 static bool is_colored (enum indicator_no type
);
74 static void restore_default_color (void);
76 COLOR_EXT_TYPE
*_rl_color_ext_list
= 0;
78 /* Output a color indicator (which may contain nulls). */
80 _rl_put_indicator (const struct bin_str
*ind
)
82 fwrite (ind
->string
, ind
->len
, 1, rl_outstream
);
86 is_colored (enum indicator_no colored_filetype
)
88 size_t len
= _rl_color_indicator
[colored_filetype
].len
;
89 char const *s
= _rl_color_indicator
[colored_filetype
].string
;
91 || (len
== 1 && strncmp (s
, "0", 1) == 0)
92 || (len
== 2 && strncmp (s
, "00", 2) == 0));
96 restore_default_color (void)
98 _rl_put_indicator (&_rl_color_indicator
[C_LEFT
]);
99 _rl_put_indicator (&_rl_color_indicator
[C_RIGHT
]);
103 _rl_set_normal_color (void)
105 if (is_colored (C_NORM
))
107 _rl_put_indicator (&_rl_color_indicator
[C_LEFT
]);
108 _rl_put_indicator (&_rl_color_indicator
[C_NORM
]);
109 _rl_put_indicator (&_rl_color_indicator
[C_RIGHT
]);
114 _rl_print_prefix_color (void)
118 /* What do we want to use for the prefix? Let's try cyan first, see colors.h */
119 s
= &_rl_color_indicator
[C_PREFIX
];
120 if (s
->string
!= NULL
)
122 if (is_colored (C_NORM
))
123 restore_default_color ();
124 _rl_put_indicator (&_rl_color_indicator
[C_LEFT
]);
125 _rl_put_indicator (s
);
126 _rl_put_indicator (&_rl_color_indicator
[C_RIGHT
]);
133 /* Returns whether any color sequence was printed. */
135 _rl_print_color_indicator (const char *f
)
137 enum indicator_no colored_filetype
;
138 COLOR_EXT_TYPE
*ext
; /* Color extension */
139 size_t len
; /* Length of name */
143 struct stat astat
, linkstat
;
145 int linkok
; /* 1 == ok, 0 == dangling symlink, -1 == missing */
150 /* This should already have undergone tilde expansion */
152 if (rl_filename_stat_hook
)
154 filename
= savestring (f
);
155 (*rl_filename_stat_hook
) (&filename
);
159 #if defined (HAVE_LSTAT)
160 stat_ok
= lstat(name
, &astat
);
162 stat_ok
= stat(name
, &astat
);
166 mode
= astat
.st_mode
;
167 #if defined (HAVE_LSTAT)
170 linkok
= stat (name
, &linkstat
) == 0;
171 if (linkok
&& strncmp (_rl_color_indicator
[C_LINK
].string
, "target", 6) == 0)
172 mode
= linkstat
.st_mode
;
181 /* Is this a nonexistent file? If so, linkok == -1. */
183 if (linkok
== -1 && _rl_color_indicator
[C_MISSING
].string
!= NULL
)
184 colored_filetype
= C_MISSING
;
185 else if (linkok
== 0 && _rl_color_indicator
[C_ORPHAN
].string
!= NULL
)
186 colored_filetype
= C_ORPHAN
; /* dangling symlink */
187 else if(stat_ok
!= 0)
189 static enum indicator_no filetype_indicator
[] = FILETYPE_INDICATORS
;
190 colored_filetype
= filetype_indicator
[normal
]; //f->filetype];
196 colored_filetype
= C_FILE
;
198 #if defined (S_ISUID)
199 if ((mode
& S_ISUID
) != 0 && is_colored (C_SETUID
))
200 colored_filetype
= C_SETUID
;
203 #if defined (S_ISGID)
204 if ((mode
& S_ISGID
) != 0 && is_colored (C_SETGID
))
205 colored_filetype
= C_SETGID
;
208 if (is_colored (C_CAP
) && 0) //f->has_capability)
209 colored_filetype
= C_CAP
;
210 else if ((mode
& S_IXUGO
) != 0 && is_colored (C_EXEC
))
211 colored_filetype
= C_EXEC
;
212 else if ((1 < astat
.st_nlink
) && is_colored (C_MULTIHARDLINK
))
213 colored_filetype
= C_MULTIHARDLINK
;
215 else if (S_ISDIR (mode
))
217 colored_filetype
= C_DIR
;
219 #if defined (S_ISVTX)
220 if ((mode
& S_ISVTX
) && (mode
& S_IWOTH
)
221 && is_colored (C_STICKY_OTHER_WRITABLE
))
222 colored_filetype
= C_STICKY_OTHER_WRITABLE
;
225 if ((mode
& S_IWOTH
) != 0 && is_colored (C_OTHER_WRITABLE
))
226 colored_filetype
= C_OTHER_WRITABLE
;
227 #if defined (S_ISVTX)
228 else if ((mode
& S_ISVTX
) != 0 && is_colored (C_STICKY
))
229 colored_filetype
= C_STICKY
;
232 #if defined (S_ISLNK)
233 else if (S_ISLNK (mode
))
234 colored_filetype
= C_LINK
;
236 else if (S_ISFIFO (mode
))
237 colored_filetype
= C_FIFO
;
238 #if defined (S_ISSOCK)
239 else if (S_ISSOCK (mode
))
240 colored_filetype
= C_SOCK
;
242 else if (S_ISBLK (mode
))
243 colored_filetype
= C_BLK
;
244 else if (S_ISCHR (mode
))
245 colored_filetype
= C_CHR
;
248 /* Classify a file of some other type as C_ORPHAN. */
249 colored_filetype
= C_ORPHAN
;
253 /* Check the file's suffix only if still classified as C_FILE. */
255 if (colored_filetype
== C_FILE
)
257 /* Test if NAME has a recognized suffix. */
259 name
+= len
; /* Pointer to final \0. */
260 for (ext
= _rl_color_ext_list
; ext
!= NULL
; ext
= ext
->next
)
262 if (ext
->ext
.len
<= len
263 && strncmp (name
- ext
->ext
.len
, ext
->ext
.string
,
269 free (filename
); /* NULL or savestring return value */
272 const struct bin_str
*const s
273 = ext
? &(ext
->seq
) : &_rl_color_indicator
[colored_filetype
];
274 if (s
->string
!= NULL
)
276 /* Need to reset so not dealing with attribute combinations */
277 if (is_colored (C_NORM
))
278 restore_default_color ();
279 _rl_put_indicator (&_rl_color_indicator
[C_LEFT
]);
280 _rl_put_indicator (s
);
281 _rl_put_indicator (&_rl_color_indicator
[C_RIGHT
]);
290 _rl_prep_non_filename_text (void)
292 if (_rl_color_indicator
[C_END
].string
!= NULL
)
293 _rl_put_indicator (&_rl_color_indicator
[C_END
]);
296 _rl_put_indicator (&_rl_color_indicator
[C_LEFT
]);
297 _rl_put_indicator (&_rl_color_indicator
[C_RESET
]);
298 _rl_put_indicator (&_rl_color_indicator
[C_RIGHT
]);
301 #endif /* COLOR_SUPPORT */