Statistics
| Branch: | Revision:

root / 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
}