|
|
1.1 root 1: /*
2: * list file or directory
3: */
4:
5: #include <sys/param.h>
6: #include <sys/stat.h>
7: #include <sys/dir.h>
8: #include <stdio.h>
9:
10: #define NFILES 1024
11: FILE *pwdf, *dirf;
12: char stdbuf[BUFSIZ];
13:
14: struct lbuf {
15: union {
16: char lname[15];
17: char *namep;
18: } ln;
19: char ltype;
20: short lnum;
21: short lflags;
22: short lnl;
23: short luid;
24: short lgid;
25: long lsize;
26: long lmtime;
27: };
28:
29: int aflg, dflg, lflg, sflg, tflg, uflg, iflg, fflg, gflg, cflg;
30: int rflg = 1;
31: long year;
32: int flags;
33: int lastuid = -1;
34: char tbuf[16];
35: long tblocks;
36: int statreq;
37: struct lbuf *flist[NFILES];
38: struct lbuf **lastp = flist;
39: struct lbuf **firstp = flist;
40: char *dotp = ".";
41:
42: char *makename();
43: struct lbuf *gstat();
44: char *ctime();
45: long nblock();
46:
47: #define ISARG 0100000
48:
49: main(argc, argv)
50: char *argv[];
51: {
52: int i;
53: register struct lbuf *ep, **ep1;
54: register struct lbuf **slastp;
55: struct lbuf **epp;
56: struct lbuf lb;
57: char *t;
58: int compar();
59:
60: setbuf(stdout, stdbuf);
61: time(&lb.lmtime);
62: year = lb.lmtime - 6L*30L*24L*60L*60L; /* 6 months ago */
63: if (--argc > 0 && *argv[1] == '-') {
64: argv++;
65: while (*++*argv) switch (**argv) {
66:
67: case 'a':
68: aflg++;
69: continue;
70:
71: case 's':
72: sflg++;
73: statreq++;
74: continue;
75:
76: case 'd':
77: dflg++;
78: continue;
79:
80: case 'g':
81: gflg++;
82: continue;
83:
84: case 'l':
85: lflg++;
86: statreq++;
87: continue;
88:
89: case 'r':
90: rflg = -1;
91: continue;
92:
93: case 't':
94: tflg++;
95: statreq++;
96: continue;
97:
98: case 'u':
99: uflg++;
100: continue;
101:
102: case 'c':
103: cflg++;
104: continue;
105:
106: case 'i':
107: iflg++;
108: continue;
109:
110: case 'f':
111: fflg++;
112: continue;
113:
114: default:
115: continue;
116: }
117: argc--;
118: }
119: if (fflg) {
120: aflg++;
121: lflg = 0;
122: sflg = 0;
123: tflg = 0;
124: statreq = 0;
125: }
126: if(lflg) {
127: t = "/etc/passwd";
128: if(gflg)
129: t = "/etc/group";
130: pwdf = fopen(t, "r");
131: }
132: if (argc==0) {
133: argc++;
134: argv = &dotp - 1;
135: }
136: for (i=0; i < argc; i++) {
137: if ((ep = gstat(*++argv, 1))==NULL)
138: continue;
139: ep->ln.namep = *argv;
140: ep->lflags |= ISARG;
141: }
142: qsort(firstp, lastp - firstp, sizeof *lastp, compar);
143: slastp = lastp;
144: for (epp=firstp; epp<slastp; epp++) {
145: ep = *epp;
146: if (ep->ltype=='d' && dflg==0 || fflg) {
147: if (argc>1)
148: printf("\n%s:\n", ep->ln.namep);
149: lastp = slastp;
150: readdir(ep->ln.namep);
151: if (fflg==0)
152: qsort(slastp,lastp - slastp,sizeof *lastp,compar);
153: if (lflg || sflg)
154: printf("total %D\n", tblocks);
155: for (ep1=slastp; ep1<lastp; ep1++)
156: pentry(*ep1);
157: } else
158: pentry(ep);
159: }
160: exit(0);
161: }
162:
163: pentry(ap)
164: struct lbuf *ap;
165: {
166: struct { char dminor, dmajor;};
167: register t;
168: register struct lbuf *p;
169: register char *cp;
170:
171: p = ap;
172: if (p->lnum == -1)
173: return;
174: if (iflg)
175: printf("%5d ", p->lnum);
176: if (sflg)
177: printf("%4D ", nblock(p->lsize));
178: if (lflg) {
179: putchar(p->ltype);
180: pmode(p->lflags);
181: printf("%2d ", p->lnl);
182: t = p->luid;
183: if(gflg)
184: t = p->lgid;
185: if (getname(t, tbuf)==0)
186: printf("%-6.6s", tbuf);
187: else
188: printf("%-6d", t);
189: if (p->ltype=='b' || p->ltype=='c')
190: printf("%3d,%3d", major((int)p->lsize), minor((int)p->lsize));
191: else
192: printf("%7ld", p->lsize);
193: cp = ctime(&p->lmtime);
194: if(p->lmtime < year)
195: printf(" %-7.7s %-4.4s ", cp+4, cp+20); else
196: printf(" %-12.12s ", cp+4);
197: }
198: if (p->lflags&ISARG)
199: printf("%s\n", p->ln.namep);
200: else
201: printf("%.14s\n", p->ln.lname);
202: }
203:
204: getname(uid, buf)
205: int uid;
206: char buf[];
207: {
208: int j, c, n, i;
209:
210: if (uid==lastuid)
211: return(0);
212: if(pwdf == NULL)
213: return(-1);
214: rewind(pwdf);
215: lastuid = -1;
216: do {
217: i = 0;
218: j = 0;
219: n = 0;
220: while((c=fgetc(pwdf)) != '\n') {
221: if (c==EOF)
222: return(-1);
223: if (c==':') {
224: j++;
225: c = '0';
226: }
227: if (j==0)
228: buf[i++] = c;
229: if (j==2)
230: n = n*10 + c - '0';
231: }
232: } while (n != uid);
233: buf[i++] = '\0';
234: lastuid = uid;
235: return(0);
236: }
237:
238: long
239: nblock(size)
240: long size;
241: {
242: return((size+511)>>9);
243: }
244:
245: int m1[] = { 1, S_IREAD>>0, 'r', '-' };
246: int m2[] = { 1, S_IWRITE>>0, 'w', '-' };
247: int m3[] = { 2, S_ISUID, 's', S_IEXEC>>0, 'x', '-' };
248: int m4[] = { 1, S_IREAD>>3, 'r', '-' };
249: int m5[] = { 1, S_IWRITE>>3, 'w', '-' };
250: int m6[] = { 2, S_ISGID, 's', S_IEXEC>>3, 'x', '-' };
251: int m7[] = { 1, S_IREAD>>6, 'r', '-' };
252: int m8[] = { 1, S_IWRITE>>6, 'w', '-' };
253: int m9[] = { 2, S_ISVTX, 't', S_IEXEC>>6, 'x', '-' };
254:
255: int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9};
256:
257: pmode(aflag)
258: {
259: register int **mp;
260:
261: flags = aflag;
262: for (mp = &m[0]; mp < &m[sizeof(m)/sizeof(m[0])];)
263: select(*mp++);
264: }
265:
266: select(pairp)
267: register int *pairp;
268: {
269: register int n;
270:
271: n = *pairp++;
272: while (--n>=0 && (flags&*pairp++)==0)
273: pairp++;
274: putchar(*pairp);
275: }
276:
277: char *
278: makename(dir, file)
279: char *dir, *file;
280: {
281: static char dfile[100];
282: register char *dp, *fp;
283: register int i;
284:
285: dp = dfile;
286: fp = dir;
287: while (*fp)
288: *dp++ = *fp++;
289: *dp++ = '/';
290: fp = file;
291: for (i=0; i<DIRSIZ; i++)
292: *dp++ = *fp++;
293: *dp = 0;
294: return(dfile);
295: }
296:
297: readdir(dir)
298: char *dir;
299: {
300: static struct direct dentry;
301: register int j;
302: register struct lbuf *ep;
303:
304: if ((dirf = fopen(dir, "r")) == NULL) {
305: printf("%s unreadable\n", dir);
306: return;
307: }
308: tblocks = 0;
309: for(;;) {
310: if (fread((char *)&dentry, sizeof(dentry), 1, dirf) != 1)
311: break;
312: if (dentry.d_ino==0
313: || aflg==0 && dentry.d_name[0]=='.' && (dentry.d_name[1]=='\0'
314: || dentry.d_name[1]=='.' && dentry.d_name[2]=='\0'))
315: continue;
316: ep = gstat(makename(dir, dentry.d_name), 0);
317: if (ep==NULL)
318: continue;
319: if (ep->lnum != -1)
320: ep->lnum = dentry.d_ino;
321: for (j=0; j<DIRSIZ; j++)
322: ep->ln.lname[j] = dentry.d_name[j];
323: }
324: fclose(dirf);
325: }
326:
327: struct lbuf *
328: gstat(file, argfl)
329: char *file;
330: {
331: struct stat statb;
332: register struct lbuf *rep;
333: static int nomocore;
334:
335: if (nomocore)
336: return(NULL);
337: rep = (struct lbuf *)malloc(sizeof(struct lbuf));
338: if (rep==NULL) {
339: fprintf(stderr, "ls: out of memory\n");
340: nomocore = 1;
341: return(NULL);
342: }
343: if (lastp >= &flist[NFILES]) {
344: static int msg;
345: lastp--;
346: if (msg==0) {
347: fprintf(stderr, "ls: too many files\n");
348: msg++;
349: }
350: }
351: *lastp++ = rep;
352: rep->lflags = 0;
353: rep->lnum = 0;
354: rep->ltype = '-';
355: if (argfl || statreq) {
356: if (stat(file, &statb)<0) {
357: printf("%s not found\n", file);
358: statb.st_ino = -1;
359: statb.st_size = 0;
360: statb.st_mode = 0;
361: if (argfl) {
362: lastp--;
363: return(0);
364: }
365: }
366: rep->lnum = statb.st_ino;
367: rep->lsize = statb.st_size;
368: switch(statb.st_mode&S_IFMT) {
369:
370: case S_IFDIR:
371: rep->ltype = 'd';
372: break;
373:
374: case S_IFBLK:
375: rep->ltype = 'b';
376: rep->lsize = statb.st_rdev;
377: break;
378:
379: case S_IFCHR:
380: rep->ltype = 'c';
381: rep->lsize = statb.st_rdev;
382: break;
383: }
384: rep->lflags = statb.st_mode & ~S_IFMT;
385: rep->luid = statb.st_uid;
386: rep->lgid = statb.st_gid;
387: rep->lnl = statb.st_nlink;
388: if(uflg)
389: rep->lmtime = statb.st_atime;
390: else if (cflg)
391: rep->lmtime = statb.st_ctime;
392: else
393: rep->lmtime = statb.st_mtime;
394: tblocks += nblock(statb.st_size);
395: }
396: return(rep);
397: }
398:
399: compar(pp1, pp2)
400: struct lbuf **pp1, **pp2;
401: {
402: register struct lbuf *p1, *p2;
403:
404: p1 = *pp1;
405: p2 = *pp2;
406: if (dflg==0) {
407: if (p1->lflags&ISARG && p1->ltype=='d') {
408: if (!(p2->lflags&ISARG && p2->ltype=='d'))
409: return(1);
410: } else {
411: if (p2->lflags&ISARG && p2->ltype=='d')
412: return(-1);
413: }
414: }
415: if (tflg) {
416: if(p2->lmtime == p1->lmtime)
417: return(0);
418: if(p2->lmtime > p1->lmtime)
419: return(rflg);
420: return(-rflg);
421: }
422: return(rflg * strcmp(p1->lflags&ISARG? p1->ln.namep: p1->ln.lname,
423: p2->lflags&ISARG? p2->ln.namep: p2->ln.lname));
424: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.