Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 240 lines (200 sloc) 4.694 kB
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
1 /* ls.c */
2
3 /* I got tired of the limitations of Microsoft's "dir" command, so I wrote
4 * this little subset of the Unix "ls" command. It lists directories in the
5 * "ls -CF" format.
6 */
7
8 #include "elvis.h"
9 #define JUST_DIRFIRST
10 #include "osdir.c"
11 #ifndef FALSE
12 # define FALSE 0
13 # define TRUE 1
14 #endif
15
16 typedef struct dent_s
17 {
18 struct dent_s *next;
19 int width;
20 char name[1];
21 } dent_t;
22
23 #include "ctypetbl.h"
24
25
26 static int isdir P_((char *name));
27 static dent_t *collect P_((char *pattern, dent_t *list));
28 static void output P_((char *dir, dent_t *list));
29
30
31 void msg P_((MSGIMP imp, char *text, ...))
32 {
33 }
34
35 /* This function returns TRUE if a given name is a directory */
36 static int isdir(name)
37 char *name;
38 {
39 struct _stat statb;
40
41 if (_stat(name, &statb) >= 0 &&
42 (statb.st_mode & _S_IFMT) != _S_IFREG)
43 return TRUE;
44 else
45 return FALSE;
46 }
47
48
49 /* This function collects the names which match a wildcard pattern, and sorts
50 * them.
51 */
52 static dent_t *collect(pattern, list)
53 char *pattern;
54 dent_t *list;
55 {
56 char *name;
57 dent_t *new, *scan, *lag;
58
59 /* for each name... */
60 for (name = dirfirst(pattern, FALSE); name; name = dirnext())
61 {
62 /* allocate an entry for it */
63 new = (dent_t *)safealloc(1, sizeof(dent_t) + strlen(name) + 1);
64 strcpy(new->name, name);
65 if (isdir(name))
66 strcat(new->name, "\\");
67 new->width = strlen(new->name) + 2;
68
69 /* insert it into the list */
70 for (scan = list, lag = NULL;
71 scan && strcmp(scan->name, new->name) < 0;
72 lag = scan, scan = scan->next)
73 {
74 }
75 new->next = scan;
76 if (lag)
77 lag->next = new;
78 else
79 list = new;
80 }
81
82 return list;
83 }
84
85
86
87 /* output a list in columns */
88 static void output(dir, list)
89 char *dir;
90 dent_t *list;
91 {
92 int items, i, col;
93 int dirwidth;
94 int columns = 10;
95 int totwidth;
96 int percol;
97 int colwidth[10];
98 dent_t *colptr[10];
99 dent_t *scan;
100
101 /* if nothing to list, then do nothing */
102 if (!list)
103 return;
104
105 /* if directory name, then output it */
106 if (dir)
107 {
108 printf("\n%s:\n", dir);
109 dirwidth = strlen(dir) + 1;
110 }
111 else
112 dirwidth = 0;
113
114 /* count the items */
115 for (items = 0, scan = list; scan; items++, scan = scan->next)
116 {
117 }
118
119 /* number of columns can't exceed number of items */
120 if (columns > items)
121 columns = items;
122
123 /* Format using as many columns as possible */
124 columns++;
125 do
126 {
127 columns--;
128
129 /* find the top of each coluumn, and column widths */
130 percol = (items + columns - 1) / columns;
131 for (col = -1, i = 0, scan = list; scan; i++, scan = scan->next)
132 {
133 if (i % percol == 0)
134 {
135 col++;
136 colptr[col] = scan;
137 colwidth[col] = scan->width;
138 }
139 else if (colwidth[col] < scan->width)
140 {
141 colwidth[col] = scan->width;
142 }
143 }
144
145 /* find the total width */
146 for (col = totwidth = 0; col < columns; col++)
147 {
148 colwidth[col] -= dirwidth;
149 totwidth += colwidth[col];
150 }
151
152 } while (columns > 0 && totwidth >= 80);
153
154 /* Note: The "items" and "percol" values are correct, but "columns"
155 * may be larger than it should be. E.g., if 17 items can fit on
156 * 8 columns, then you would need 3 items per column. But at 3 items
157 * per column you only need 6 columns. So recompute the number of
158 * columns from "item" and "percol" now.
159 */
160 columns = (items + percol - 1) / percol;
161
162 /* output the columns, one row at a time */
163 while (percol-- > 0)
164 {
165 for (col = 0; col < columns; col++)
166 {
167 if (!colptr[col])
168 continue;
169 if (col + 1 < columns && colptr[col + 1])
170 printf("%-*s", colwidth[col], &colptr[col]->name[dirwidth]);
171 else
172 printf("%s\n", &colptr[col]->name[dirwidth]);
173 colptr[col] = colptr[col]->next;
174 }
175 }
176 }
177
178
179
180 /* free a list */
181 static void freelist(list)
182 dent_t *list;
183 {
184 dent_t *doomed;
185
186 while (list)
187 {
188 doomed = list;
189 list = list->next;
190 safefree(doomed);
191 }
192 }
193
194
195
196 void main(argc, argv)
197 int argc;
198 char **argv;
199 {
200 int i;
201 dent_t *list;
202
203 /* if no args, then do "ls ." */
204 if (argc == 1)
205 {
206 list = collect("*", NULL);
207 output(NULL, list);
208 freelist(list);
209 }
210
211 /* for each wildcard pattern... */
212 for (i = 1, list = NULL; i < argc; i++)
213 {
214 /* add its matches to the list */
215 if (!isdir(argv[i]))
216 {
217 list = collect(argv[i], list);
218 }
219 }
220 if (list)
221 {
222 output(NULL, list);
223 freelist(list);
224 }
225
226 /* for each directory... */
227 for (i = 1; i < argc; i++)
228 {
229 /* list the directory */
230 list = collect(dirpath(argv[i], "*"), NULL);
231 if (list && strcmp(list->name, dirpath(argv[i], "*")))
232 {
233 output(argv[i], list);
234 }
235 freelist(list);
236 }
237
238 exit(0);
239 }
Something went wrong with that request. Please try again.