Bell 32V release
[unix-history] / usr / src / cmd / ls.c
CommitLineData
3b600ead
TL
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
11FILE *pwdf, *dirf;
12char stdbuf[BUFSIZ];
13
14struct 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
29int aflg, dflg, lflg, sflg, tflg, uflg, iflg, fflg, gflg, cflg;
30int rflg = 1;
31long year;
32int flags;
33int lastuid = -1;
34char tbuf[16];
35long tblocks;
36int statreq;
37struct lbuf *flist[NFILES];
38struct lbuf **lastp = flist;
39struct lbuf **firstp = flist;
40char *dotp = ".";
41
42char *makename();
43struct lbuf *gstat();
44char *ctime();
45long nblock();
46
47#define ISARG 0100000
48
49main(argc, argv)
50char *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
163pentry(ap)
164struct 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
204getname(uid, buf)
205int uid;
206char 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
238long
239nblock(size)
240long size;
241{
242 return((size+511)>>9);
243}
244
245int m1[] = { 1, S_IREAD>>0, 'r', '-' };
246int m2[] = { 1, S_IWRITE>>0, 'w', '-' };
247int m3[] = { 2, S_ISUID, 's', S_IEXEC>>0, 'x', '-' };
248int m4[] = { 1, S_IREAD>>3, 'r', '-' };
249int m5[] = { 1, S_IWRITE>>3, 'w', '-' };
250int m6[] = { 2, S_ISGID, 's', S_IEXEC>>3, 'x', '-' };
251int m7[] = { 1, S_IREAD>>6, 'r', '-' };
252int m8[] = { 1, S_IWRITE>>6, 'w', '-' };
253int m9[] = { 2, S_ISVTX, 't', S_IEXEC>>6, 'x', '-' };
254
255int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9};
256
257pmode(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
266select(pairp)
267register 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
277char *
278makename(dir, file)
279char *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
297readdir(dir)
298char *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
327struct lbuf *
328gstat(file, argfl)
329char *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
399compar(pp1, pp2)
400struct 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}