|
|
1.1 root 1: /*
2: * List files in categories (and columns)
3: */
4:
5: #include <stdio.h>
6: #include <sys/stat.h>
7: #include <sys/dir.h>
8:
9: #define WIDTH 79 /* Default line width */
10: #define GAP 1 /* Minimum gap between columns */
11: #define INDENT1 4 /* Indent for multiple directories */
12: #define INDENT2 4 /* Indent for files in a category */
13: #define NFNAME 400 /* Maximum a filename can expand to */
14:
15: int oneflag; /* One per line */
16: int aflag; /* Do all entries, including `.' and `..' */
17: int bflag; /* Do block special */
18: int cflag; /* Do character special */
19: int dflag; /* Do directories */
20: int fflag; /* Do regular files */
21: int mflag; /* Do multiplexor files */
22: int pflag; /* Do pipes */
23: int allflag = 1; /* Do all types */
24: int ndir;
25: int printed = 0; /* Set when we have printed something */
26: int maxwidth; /* Maximum width of a filename */
27: int lwidth = WIDTH-INDENT2;
28:
29: struct stat sb;
30: char iobuf[BUFSIZ];
31: char obuf[BUFSIZ];
32: char fname[NFNAME];
33:
34: typedef struct ENTRY {
35: struct ENTRY *e_fp;
36: char e_name[DIRSIZ];
37: } ENTRY;
38:
39: ENTRY *files, *dirs, *blocks, *chars, *pipes, *mults;
40:
41: main(argc, argv)
42: char *argv[];
43: {
44: register char *ap;
45: register int i;
46: register int estat = 0;
47:
48: while (argc>1 && *argv[1]=='-') {
49: for (ap = &argv[1][1]; *ap!='\0'; ap++)
50: switch (*ap) {
51: case 'f':
52: fflag = 1;
53: allflag = 0;
54: break;
55:
56: case 'd':
57: dflag = 1;
58: allflag = 0;
59: break;
60:
61: case 'm':
62: mflag = 1;
63: allflag = 0;
64: break;
65:
66: case 'b':
67: bflag = 1;
68: allflag = 0;
69: break;
70:
71: case 'c':
72: cflag = 1;
73: allflag = 0;
74: break;
75:
76: case 'p':
77: pflag = 1;
78: allflag = 0;
79: break;
80:
81: case '1':
82: oneflag = 1;
83: break;
84:
85: case 'a':
86: aflag = 1;
87: break;
88:
89: default:
90: usage();
91: }
92: argv++;
93: argc--;
94: }
95: if (allflag)
96: fflag = dflag = cflag = bflag = mflag = pflag = 1;
97: setbuf(stdout, obuf);
98: if (argc < 2) {
99: ndir = 1;
100: estat = lc(".");
101: } else {
102: if (argc > 2)
103: lwidth -= INDENT1;
104: ndir = argc-1;
105: for (i=1; i<argc; i++) {
106: estat |= lc(argv[i]);
107: fflush(stdout);
108: }
109: }
110: exit(estat);
111: }
112:
113: /*
114: * Do `lc' on a single name.
115: */
116: lc(name)
117: char *name;
118: {
119: char *type;
120:
121: if (stat(name, &sb) < 0) {
122: fprintf(stderr, "%s: not found\n", name);
123: return (1);
124: }
125: switch (sb.st_mode & S_IFMT) {
126: case S_IFDIR:
127: return (lcdir(name));
128:
129: case S_IFREG:
130: type = "file";
131: break;
132:
133: case S_IFBLK:
134: type = "block special file";
135: break;
136:
137: case S_IFCHR:
138: type = "character special file";
139: break;
140:
141: case S_IFMPB:
142: case S_IFMPC:
143: type = "multiplexed file";
144: break;
145:
146: case S_IFPIP:
147: type = "pipe";
148: break;
149:
150: default:
151: printf("%s: unknown file type\n", name);
152: return (1);
153: }
154: printf("%s: %s\n", name, type);
155: return (0);
156: }
157:
158: /*
159: * Process one directory.
160: */
161: lcdir(dname)
162: char *dname;
163: {
164: register struct direct *dp;
165: register int nb;
166: register int fd;
167:
168: clearlist(&files);
169: clearlist(&dirs);
170: clearlist(&blocks);
171: clearlist(&chars);
172: clearlist(&pipes);
173: clearlist(&mults);
174: maxwidth = 0;
175: if (ndir > 1) {
176: if (printed)
177: putchar('\n');
178: printf("%s:\n", dname);
179: }
180: printed = 0;
181: if ((fd = open(dname, 0)) < 0) {
182: fprintf(stderr, "Cannot open directory `%s'\n", dname);
183: return (1);
184: }
185: while ((nb = read(fd, iobuf, BUFSIZ)) > 0)
186: for (dp = iobuf; dp < &iobuf[nb]; dp++) {
187: if (dp->d_ino == 0)
188: continue;
189: doentry(dname, dp);
190: }
191: close(fd);
192: prnames();
193: if (nb < 0) {
194: fprintf(stderr, "%s: directory read error\n", dname);
195: return (1);
196: }
197: return (0);
198: }
199:
200: /*
201: * Do a stat on one filename in the
202: * indicated directory.
203: * and then sort into the appropriate table.
204: */
205: doentry(dirname, dp)
206: char *dirname;
207: struct direct *dp;
208: {
209: int width = 0;
210:
211: {
212: register char *p = dp->d_name;
213:
214: if (!aflag
215: && *p++=='.' && (*p=='\0' || (*p++=='.' && *p=='\0')))
216: return (0);
217: } {
218: register char *p1, *p2;
219: register unsigned n = DIRSIZ;
220:
221: p1 = fname;
222: p2 = dirname;
223: while (*p1++ = *p2++)
224: ;
225: p1--;
226: if (*p1 != '/')
227: *p1++ = '/';
228: p2 = dp->d_name;
229: do {
230: if (*p2 == '\0')
231: break;
232: width++;
233: *p1++ = *p2++;
234: } while (--n);
235: *p1 = '\0';
236: }
237: if (width > maxwidth)
238: maxwidth = width;
239: if (stat(fname, &sb) < 0) {
240: prindent("%.*s: cannot stat\n", DIRSIZ, dp->d_name);
241: return (1);
242: } {
243: register ENTRY *ep;
244: register ENTRY **list;
245:
246: if ((ep = (ENTRY *)malloc(sizeof (ENTRY))) == NULL) {
247: fprintf(stderr, "Out of memory\n");
248: exit (1);
249: }
250: strncpy(ep->e_name, dp->d_name, DIRSIZ);
251: switch (sb.st_mode & S_IFMT) {
252: case S_IFREG:
253: list = &files;
254: break;
255:
256: case S_IFDIR:
257: list = &dirs;
258: break;
259:
260: case S_IFBLK:
261: list = &blocks;
262: break;
263:
264: case S_IFCHR:
265: list = &chars;
266: break;
267:
268: case S_IFMPC:
269: case S_IFMPB:
270: list = &mults;
271: break;
272:
273: case S_IFPIP:
274: list = &pipes;
275: break;
276:
277: default:
278: prindent("%.*s: unknown file type\n", DIRSIZ,
279: dp->d_name);
280: return (1);
281: }
282: addlist(list, ep);
283: }
284: return (0);
285: }
286:
287: /*
288: * Add an entry to the list.
289: * Sort the list at insertion time
290: * into lexicographic order.
291: */
292: addlist(lpp, ep)
293: ENTRY **lpp;
294: ENTRY *ep;
295: {
296: register ENTRY *rp;
297: register ENTRY *pp;
298:
299: for (pp=NULL, rp=*lpp; rp!=NULL; pp=rp, rp=rp->e_fp)
300: if (strncmp(ep->e_name, rp->e_name, DIRSIZ) <= 0)
301: break;
302: if (pp == NULL) {
303: ep->e_fp = *lpp;
304: *lpp = ep;
305: } else {
306: ep->e_fp = pp->e_fp;
307: pp->e_fp = ep;
308: }
309: }
310:
311: /*
312: * Clear out the list, a pointer to which is
313: * the argument.
314: */
315: clearlist(lpp)
316: ENTRY **lpp;
317: {
318: register ENTRY *rp, *op;
319:
320: rp = *lpp;
321: while (rp != NULL) {
322: op = rp;
323: rp = rp->e_fp;
324: free(op);
325: }
326: *lpp = NULL;
327: }
328:
329: /*
330: * Print out the appropriate names.
331: */
332: prnames()
333: {
334: if (dflag)
335: prtype(dirs, "Directories");
336: if (fflag)
337: prtype(files, "Files");
338: if (cflag)
339: prtype(chars, "Character special files");
340: if (bflag)
341: prtype(blocks, "Block special files");
342: if (pflag)
343: prtype(pipes, "Pipes");
344: if (mflag)
345: prtype(mults, "Multiplexed files");
346: }
347:
348: /*
349: * Print out one type of files
350: */
351: prtype(list, type)
352: ENTRY *list;
353: char *type;
354: {
355: register char *cp;
356: register ENTRY *ep;
357: register int n;
358: register int i;
359: int npl;
360:
361: if (list == NULL)
362: return;
363: if (printed)
364: putchar('\n');
365: if(!oneflag)
366: prindent("%s:\n", type);
367: if (oneflag)
368: npl = 1;
369: else
370: npl = lwidth/(maxwidth+GAP);
371: ep = list;
372: i = 0;
373: for (ep = list; ep != NULL; ep = ep->e_fp) {
374: if (!oneflag && (i == 0)) {
375: printf("%*s", INDENT2, "");
376: prindent("");
377: }
378: n = DIRSIZ;
379: for (cp=ep->e_name; *cp!='\0' && n; n--)
380: putchar(*cp++);
381: if (++i!=npl && ep->e_fp!=NULL) {
382: n -= DIRSIZ-GAP-maxwidth;
383: while (n-- > 0)
384: putchar(' ');
385: } else {
386: i = 0;
387: putchar('\n');
388: }
389: }
390: }
391:
392: /*
393: * Print a line with possible indent.
394: */
395: /* VARARGS */
396: prindent(x)
397: {
398: if (ndir > 1)
399: printf("%*s", INDENT1, "");
400: printf("%r", &x);
401: printed = 1;
402: }
403:
404: usage()
405: {
406: fprintf(stderr, "Usage: lc [-afdcbp] [-1] [name ...]\n");
407: exit(1);
408: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.