scoutos / prex-0.9.0 / usr / bin / ls / ls.c @ 03e9c04a
History | View | Annotate | Download (6.1 KB)
1 |
/*
|
---|---|
2 |
* Copyright (c) 2005-2009, Kohsuke Ohtani
|
3 |
* All rights reserved.
|
4 |
*
|
5 |
* Redistribution and use in source and binary forms, with or without
|
6 |
* modification, are permitted provided that the following conditions
|
7 |
* are met:
|
8 |
* 1. Redistributions of source code must retain the above copyright
|
9 |
* notice, this list of conditions and the following disclaimer.
|
10 |
* 2. Redistributions in binary form must reproduce the above copyright
|
11 |
* notice, this list of conditions and the following disclaimer in the
|
12 |
* documentation and/or other materials provided with the distribution.
|
13 |
* 3. Neither the name of the author nor the names of any co-contributors
|
14 |
* may be used to endorse or promote products derived from this software
|
15 |
* without specific prior written permission.
|
16 |
*
|
17 |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
18 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
20 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
21 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
23 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
24 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
25 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
26 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
27 |
* SUCH DAMAGE.
|
28 |
*/
|
29 |
|
30 |
#include <sys/stat.h> |
31 |
|
32 |
#include <unistd.h> |
33 |
#include <termios.h> |
34 |
#include <err.h> |
35 |
#include <string.h> |
36 |
#include <stdlib.h> |
37 |
#include <dirent.h> |
38 |
#include <limits.h> |
39 |
#include <stdio.h> |
40 |
#include <errno.h> |
41 |
|
42 |
#ifdef CMDBOX
|
43 |
#define main(argc, argv) ls_main(argc, argv)
|
44 |
#endif
|
45 |
|
46 |
static void printentry(char *name, struct stat *sp); |
47 |
static int do_ls(char *path); |
48 |
|
49 |
/* Flags */
|
50 |
#define LSF_DOT 0x01 /* List files begining with . */ |
51 |
#define LSF_LONG 0x02 /* Long format */ |
52 |
#define LSF_SINGLE 0x04 /* Single column */ |
53 |
#define LSF_TYPE 0x08 /* Add /(dir) and @(symlink) with file name */ |
54 |
#define LSF_ALL 0x10 /* List hidden files */ |
55 |
|
56 |
#define LSF_RECURSIVE 0x20 /* List Subdirectory */ |
57 |
#define LSF_TIMESORT 0x40 /* Sort by time */ |
58 |
|
59 |
#define DEFAULT_WIDTH 80 |
60 |
|
61 |
static unsigned int ls_flags; |
62 |
static int termwidth; |
63 |
static int cols; |
64 |
|
65 |
int
|
66 |
main(int argc, char *argv[]) |
67 |
{ |
68 |
struct winsize ws;
|
69 |
int ch, rc;
|
70 |
|
71 |
ls_flags = 0;
|
72 |
|
73 |
while ((ch = getopt(argc, argv, "1ClFaA")) != -1) { |
74 |
switch(ch) {
|
75 |
case '1': |
76 |
ls_flags |= LSF_SINGLE; |
77 |
ls_flags &= ~LSF_LONG; |
78 |
break;
|
79 |
case 'C': |
80 |
ls_flags &= ~LSF_SINGLE; |
81 |
ls_flags &= ~LSF_LONG; |
82 |
break;
|
83 |
case 'l': |
84 |
ls_flags |= LSF_LONG; |
85 |
ls_flags &= ~LSF_SINGLE; |
86 |
break;
|
87 |
case 'F': |
88 |
ls_flags |= LSF_TYPE; |
89 |
break;
|
90 |
case 'a': |
91 |
ls_flags |= LSF_DOT; |
92 |
/* FALLTHROUGH */
|
93 |
case 'A': |
94 |
ls_flags |= LSF_ALL; |
95 |
break;
|
96 |
default:
|
97 |
case '?': |
98 |
fprintf(stderr, "usage: ls [-1CFAal] [file ...]\n");
|
99 |
exit(1);
|
100 |
} |
101 |
} |
102 |
argc -= optind; |
103 |
argv += optind; |
104 |
|
105 |
if (isatty(STDOUT_FILENO)) {
|
106 |
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0 && |
107 |
ws.ws_col != 0) {
|
108 |
termwidth = ws.ws_col; |
109 |
} else {
|
110 |
termwidth = DEFAULT_WIDTH; |
111 |
} |
112 |
} |
113 |
|
114 |
if (argc == 0) |
115 |
rc = do_ls(".");
|
116 |
else {
|
117 |
do {
|
118 |
rc = do_ls(*argv); |
119 |
++argv; |
120 |
} while (*argv);
|
121 |
} |
122 |
if (rc)
|
123 |
err(1, NULL); |
124 |
return 0; |
125 |
} |
126 |
|
127 |
static void |
128 |
printtype(u_int mode) |
129 |
{ |
130 |
char type;
|
131 |
|
132 |
switch (mode & S_IFMT) {
|
133 |
case S_IFIFO:
|
134 |
type = 'p';
|
135 |
break;
|
136 |
case S_IFCHR:
|
137 |
type = 'c';
|
138 |
break;
|
139 |
case S_IFDIR:
|
140 |
type = 'd';
|
141 |
break;
|
142 |
case S_IFBLK:
|
143 |
type = 'b';
|
144 |
break;
|
145 |
case S_IFLNK:
|
146 |
type = 'l';
|
147 |
break;
|
148 |
case S_IFSOCK:
|
149 |
type = 's';
|
150 |
break;
|
151 |
case S_IFREG:
|
152 |
default:
|
153 |
type = '-';
|
154 |
break;
|
155 |
} |
156 |
putchar(type); |
157 |
} |
158 |
|
159 |
/* We don't use strmode() to save code. */
|
160 |
static void |
161 |
printmode(u_int mode) |
162 |
{ |
163 |
|
164 |
if (mode & S_IRUSR)
|
165 |
putchar('r');
|
166 |
else
|
167 |
putchar('-');
|
168 |
if (mode & S_IWUSR)
|
169 |
putchar('w');
|
170 |
else
|
171 |
putchar('-');
|
172 |
if (mode & S_IXUSR)
|
173 |
putchar('x');
|
174 |
else
|
175 |
putchar('-');
|
176 |
} |
177 |
|
178 |
static void |
179 |
printentry(char *name, struct stat *sp) |
180 |
{ |
181 |
int color;
|
182 |
int dot = 0; |
183 |
int len;
|
184 |
|
185 |
if (name[0] == '.') { |
186 |
if ((ls_flags & LSF_DOT) == 0) |
187 |
return;
|
188 |
dot = 1;
|
189 |
} |
190 |
|
191 |
/* set color */
|
192 |
color = 0;
|
193 |
if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode))
|
194 |
color = 35; /* magenta */ |
195 |
else if (S_ISDIR(sp->st_mode)) |
196 |
color = 36; /* cyan */ |
197 |
else if (S_ISFIFO(sp->st_mode)) |
198 |
color = 34;
|
199 |
else if (S_ISLNK(sp->st_mode)) |
200 |
color = 33; /* yellow */ |
201 |
|
202 |
if (ls_flags & LSF_LONG) {
|
203 |
printtype(sp->st_mode); |
204 |
printmode(sp->st_mode); |
205 |
|
206 |
printf("------");
|
207 |
|
208 |
/* print link */
|
209 |
printf(" 1 ");
|
210 |
|
211 |
/* print owner */
|
212 |
printf("prex ");
|
213 |
|
214 |
/* print date/time */
|
215 |
printf("%s 12:00 ", __DATE__);
|
216 |
|
217 |
/* print size */
|
218 |
printf("%7d ", (int)sp->st_size); |
219 |
} |
220 |
|
221 |
/* print name */
|
222 |
printf("\033[%dm", color);
|
223 |
printf("%s", name);
|
224 |
|
225 |
/* print type */
|
226 |
if (!dot && (ls_flags & LSF_TYPE)) {
|
227 |
printtype(sp->st_mode); |
228 |
if (sp->st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))
|
229 |
putchar('*');
|
230 |
} |
231 |
printf("\033[0m");
|
232 |
if (ls_flags & LSF_LONG || ls_flags & LSF_SINGLE) {
|
233 |
putchar('\n');
|
234 |
} else {
|
235 |
len = strlen(name); |
236 |
cols += len; |
237 |
if (cols > termwidth / 2 + 8) { |
238 |
printf("\n");
|
239 |
cols = 0;
|
240 |
} else {
|
241 |
if (len > 8) { |
242 |
putchar(' ');
|
243 |
cols++; |
244 |
} else {
|
245 |
for (; len <= 9; len++) { |
246 |
putchar(' ');
|
247 |
cols++; |
248 |
} |
249 |
} |
250 |
} |
251 |
} |
252 |
} |
253 |
|
254 |
static int |
255 |
do_ls(char *path)
|
256 |
{ |
257 |
struct stat st;
|
258 |
int nr_file = 0; |
259 |
char buf[PATH_MAX];
|
260 |
DIR *dir; |
261 |
struct dirent *entry;
|
262 |
|
263 |
if (stat(path, &st) == -1) |
264 |
return ENOTDIR;
|
265 |
|
266 |
if (S_ISDIR(st.st_mode)) {
|
267 |
|
268 |
dir = opendir(path); |
269 |
if (dir == NULL) |
270 |
return ENOTDIR;
|
271 |
|
272 |
cols = 0;
|
273 |
for (;;) {
|
274 |
|
275 |
entry = readdir(dir); |
276 |
if (entry == NULL) |
277 |
break;
|
278 |
|
279 |
buf[0] = 0; |
280 |
strlcpy(buf, path, sizeof(buf));
|
281 |
buf[sizeof(buf) - 1] = '\0'; |
282 |
if (!strcmp(entry->d_name, ".")) |
283 |
; /* Do nothing */
|
284 |
else if (!strcmp(entry->d_name, "..")) |
285 |
; /* Do nothing */
|
286 |
else {
|
287 |
strlcat(buf, "/", sizeof(buf)); |
288 |
strlcat(buf, entry->d_name, sizeof(buf));
|
289 |
} |
290 |
if (stat(buf, &st) == -1 && errno != EACCES) |
291 |
break;
|
292 |
printentry(entry->d_name, &st); |
293 |
nr_file++; |
294 |
} |
295 |
closedir(dir); |
296 |
if (ls_flags & LSF_LONG)
|
297 |
printf("total %d\n", nr_file);
|
298 |
else
|
299 |
putchar('\n');
|
300 |
} else {
|
301 |
|
302 |
printentry(path, &st); |
303 |
putchar('\n');
|
304 |
} |
305 |
return 0; |
306 |
} |