/* * list file or directory */ #include #include #include #include #define NFILES 1024 FILE *pwdf, *dirf; char stdbuf[BUFSIZ]; struct lbuf { union { char lname[15]; char *namep; } ln; char ltype; short lnum; short lflags; short lnl; short luid; short lgid; long lsize; long lmtime; }; int aflg, dflg, lflg, sflg, tflg, uflg, iflg, fflg, gflg, cflg; int rflg = 1; long year; int flags; int lastuid = -1; char tbuf[16]; long tblocks; int statreq; struct lbuf *flist[NFILES]; struct lbuf **lastp = flist; struct lbuf **firstp = flist; char *dotp = "."; char *makename(); struct lbuf *gstat(); char *ctime(); long nblock(); #define ISARG 0100000 main(argc, argv) char *argv[]; { int i; register struct lbuf *ep, **ep1; register struct lbuf **slastp; struct lbuf **epp; struct lbuf lb; char *t; int compar(); setbuf(stdout, stdbuf); time(&lb.lmtime); year = lb.lmtime - 6L*30L*24L*60L*60L; /* 6 months ago */ if (--argc > 0 && *argv[1] == '-') { argv++; while (*++*argv) switch (**argv) { case 'a': aflg++; continue; case 's': sflg++; statreq++; continue; case 'd': dflg++; continue; case 'g': gflg++; continue; case 'l': lflg++; statreq++; continue; case 'r': rflg = -1; continue; case 't': tflg++; statreq++; continue; case 'u': uflg++; continue; case 'c': cflg++; continue; case 'i': iflg++; continue; case 'f': fflg++; continue; default: continue; } argc--; } if (fflg) { aflg++; lflg = 0; sflg = 0; tflg = 0; statreq = 0; } if(lflg) { t = "/etc/passwd"; if(gflg) t = "/etc/group"; pwdf = fopen(t, "r"); } if (argc==0) { argc++; argv = &dotp - 1; } for (i=0; i < argc; i++) { if ((ep = gstat(*++argv, 1))==NULL) continue; ep->ln.namep = *argv; ep->lflags |= ISARG; } qsort(firstp, lastp - firstp, sizeof *lastp, compar); slastp = lastp; for (epp=firstp; eppltype=='d' && dflg==0 || fflg) { if (argc>1) printf("\n%s:\n", ep->ln.namep); lastp = slastp; readdir(ep->ln.namep); if (fflg==0) qsort(slastp,lastp - slastp,sizeof *lastp,compar); if (lflg || sflg) printf("total %D\n", tblocks); for (ep1=slastp; ep1lnum == -1) return; if (iflg) printf("%5u ", p->lnum); if (sflg) printf("%4D ", nblock(p->lsize)); if (lflg) { putchar(p->ltype); pmode(p->lflags); printf("%2d ", p->lnl); t = p->luid; if(gflg) t = p->lgid; if (getname(t, tbuf)==0) printf("%-6.6s", tbuf); else printf("%-6d", t); if (p->ltype=='b' || p->ltype=='c') printf("%3d,%3d", major((int)p->lsize), minor((int)p->lsize)); else printf("%7ld", p->lsize); cp = ctime(&p->lmtime); if(p->lmtime < year) printf(" %-7.7s %-4.4s ", cp+4, cp+20); else printf(" %-12.12s ", cp+4); } if (p->lflags&ISARG) printf("%s\n", p->ln.namep); else printf("%.14s\n", p->ln.lname); } getname(uid, buf) int uid; char buf[]; { int j, c, n, i; if (uid==lastuid) return(0); if(pwdf == NULL) return(-1); rewind(pwdf); lastuid = -1; do { i = 0; j = 0; n = 0; while((c=fgetc(pwdf)) != '\n') { if (c==EOF) return(-1); if (c==':') { j++; c = '0'; } if (j==0) buf[i++] = c; if (j==2) n = n*10 + c - '0'; } } while (n != uid); buf[i++] = '\0'; lastuid = uid; return(0); } long nblock(size) long size; { return((size+511)>>9); } int m1[] = { 1, S_IREAD>>0, 'r', '-' }; int m2[] = { 1, S_IWRITE>>0, 'w', '-' }; int m3[] = { 2, S_ISUID, 's', S_IEXEC>>0, 'x', '-' }; int m4[] = { 1, S_IREAD>>3, 'r', '-' }; int m5[] = { 1, S_IWRITE>>3, 'w', '-' }; int m6[] = { 2, S_ISGID, 's', S_IEXEC>>3, 'x', '-' }; int m7[] = { 1, S_IREAD>>6, 'r', '-' }; int m8[] = { 1, S_IWRITE>>6, 'w', '-' }; int m9[] = { 2, S_ISVTX, 't', S_IEXEC>>6, 'x', '-' }; int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9}; pmode(aflag) { register int **mp; flags = aflag; for (mp = &m[0]; mp < &m[sizeof(m)/sizeof(m[0])];) select(*mp++); } select(pairp) register int *pairp; { register int n; n = *pairp++; while (--n>=0 && (flags&*pairp++)==0) pairp++; putchar(*pairp); } char * makename(dir, file) char *dir, *file; { static char dfile[100]; register char *dp, *fp; register int i; dp = dfile; fp = dir; while (*fp) *dp++ = *fp++; *dp++ = '/'; fp = file; for (i=0; ilnum != -1) ep->lnum = dentry.d_ino; for (j=0; jln.lname[j] = dentry.d_name[j]; } fclose(dirf); } struct lbuf * gstat(file, argfl) char *file; { extern char *malloc(); struct stat statb; register struct lbuf *rep; static int nomocore; if (nomocore) return(NULL); rep = (struct lbuf *)malloc(sizeof(struct lbuf)); if (rep==NULL) { fprintf(stderr, "ls: out of memory\n"); nomocore = 1; return(NULL); } if (lastp >= &flist[NFILES]) { static int msg; lastp--; if (msg==0) { fprintf(stderr, "ls: too many files\n"); msg++; } } *lastp++ = rep; rep->lflags = 0; rep->lnum = 0; rep->ltype = '-'; if (argfl || statreq) { if (stat(file, &statb)<0) { printf("%s not found\n", file); statb.st_ino = -1; statb.st_size = 0; statb.st_mode = 0; if (argfl) { lastp--; return(0); } } rep->lnum = statb.st_ino; rep->lsize = statb.st_size; switch(statb.st_mode&S_IFMT) { case S_IFDIR: rep->ltype = 'd'; break; case S_IFBLK: rep->ltype = 'b'; rep->lsize = statb.st_rdev; break; case S_IFCHR: rep->ltype = 'c'; rep->lsize = statb.st_rdev; break; } rep->lflags = statb.st_mode & ~S_IFMT; rep->luid = statb.st_uid; rep->lgid = statb.st_gid; rep->lnl = statb.st_nlink; if(uflg) rep->lmtime = statb.st_atime; else if (cflg) rep->lmtime = statb.st_ctime; else rep->lmtime = statb.st_mtime; tblocks += nblock(statb.st_size); } return(rep); } compar(pp1, pp2) struct lbuf **pp1, **pp2; { register struct lbuf *p1, *p2; p1 = *pp1; p2 = *pp2; if (dflg==0) { if (p1->lflags&ISARG && p1->ltype=='d') { if (!(p2->lflags&ISARG && p2->ltype=='d')) return(1); } else { if (p2->lflags&ISARG && p2->ltype=='d') return(-1); } } if (tflg) { if(p2->lmtime == p1->lmtime) return(0); if(p2->lmtime > p1->lmtime) return(rflg); return(-rflg); } return(rflg * strcmp(p1->lflags&ISARG? p1->ln.namep: p1->ln.lname, p2->lflags&ISARG? p2->ln.namep: p2->ln.lname)); }