+#
+/*
+ * list file or directory
+ */
+
+struct {
+ int fdes;
+ int nleft;
+ char *nextc;
+ char buff[512];
+} inf;
+
+struct ibuf {
+ int idev;
+ int inum;
+ int iflags;
+ char inl;
+ char iuid;
+ char igid;
+ char isize0;
+ int isize;
+ int iaddr[8];
+ char *iatime[2];
+ char *imtime[2];
+};
+
+struct lbuf {
+ char lname[15];
+ int lnum;
+ int lflags;
+ char lnl;
+ char luid;
+ char lgid;
+ char lsize0;
+ int lsize;
+ char *lmtime[2];
+};
+
+struct lbufx {
+ char *namep;
+};
+
+int aflg, dflg, lflg, sflg, tflg, uflg, iflg, fflg;
+int fout;
+int rflg 1;
+int flags;
+int uidfil -1;
+int tblocks;
+int statreq;
+struct lbuf *lastp &end;
+struct lbuf *rlastp &end;
+char *dotp ".";
+
+#define IFMT 060000
+#define DIR 0100000
+#define CHR 020000
+#define BLK 040000
+#define ISARG 01000
+#define LARGE 010000
+#define STXT 010000
+#define SUID 04000
+#define SGID 02000
+#define ROWN 0400
+#define WOWN 0200
+#define XOWN 0100
+#define RGRP 040
+#define WGRP 020
+#define XGRP 010
+#define ROTH 04
+#define WOTH 02
+#define XOTH 01
+#define RSTXT 01000
+
+main(argc, argv)
+char **argv;
+{
+ int i, j;
+ extern struct lbuf end;
+ register struct lbuf *ep, *ep1;
+ register struct lbuf *slastp;
+ struct lbuf lb;
+ int compar();
+
+ fout = dup(1);
+ if (--argc > 0 && *argv[1] == '-') {
+ argv++;
+ while (*++*argv) switch (**argv) {
+ case 'a':
+ aflg++;
+ continue;
+
+ case 's':
+ sflg++;
+ statreq++;
+ continue;
+
+ case 'd':
+ dflg++;
+ continue;
+
+ case 'l':
+ lflg++;
+ statreq++;
+ uidfil = open("/etc/passwd", 0);
+ continue;
+
+ case 'r':
+ rflg = -1;
+ continue;
+
+ case 't':
+ tflg++;
+ statreq++;
+ continue;
+
+ case 'u':
+ uflg++;
+ continue;
+
+ case 'i':
+ iflg++;
+ continue;
+
+ case 'f':
+ fflg++;
+ continue;
+
+ default:
+ continue;
+ }
+ argc--;
+ }
+ if (fflg) {
+ aflg++;
+ lflg = 0;
+ sflg = 0;
+ tflg = 0;
+ statreq = 0;
+ }
+ if (argc==0) {
+ argc++;
+ argv = &dotp - 1;
+ }
+ for (i=0; i < argc; i++) {
+ if ((ep = gstat(*++argv, 1))==0)
+ continue;
+ ep->namep = *argv;
+ ep->lflags =| ISARG;
+ }
+ qsort(&end, lastp - &end, sizeof *lastp, compar);
+ slastp = lastp;
+ for (ep = &end; ep<slastp; ep++) {
+ if (ep->lflags&DIR && dflg==0 || fflg) {
+ if (argc>1)
+ printf("\n%s:\n", ep->namep);
+ lastp = slastp;
+ readdir(ep->namep);
+ if (fflg==0)
+ qsort(slastp,lastp - slastp,sizeof *lastp,compar);
+ if (statreq)
+ printf("total %d\n", tblocks);
+ for (ep1=slastp; ep1<lastp; ep1++)
+ pentry(ep1);
+ } else
+ pentry(ep);
+ }
+ flush();
+}
+
+pentry(ap)
+struct lbuf *ap;
+{
+ char tbuf[16];
+ struct { char dminor, dmajor;};
+ register struct lbuf *p;
+
+ p = ap;
+ if (p->lnum == -1)
+ return;
+ if (iflg)
+ printf("%5d ", p->lnum);
+ if (lflg) {
+ pmode(p->lflags);
+ printf("%2d ", p->lnl);
+ if (getname(p->luid&0377, tbuf)==0)
+ printf("%-6.6s", tbuf);
+ else
+ printf("%-6d", p->luid&0377);
+ if (p->lflags & (BLK|CHR))
+ printf("%3d,%3d", p->lsize.dmajor&0377,
+ p->lsize.dminor&0377);
+ else
+ printf("%7s", locv(p->lsize0, p->lsize));
+ printf(" %-12.12s ", ctime(p->lmtime)+4);
+ } else if (sflg)
+ printf("%4d ", nblock(p->lsize0, p->lsize));
+ if (p->lflags&ISARG)
+ printf("%s\n", p->namep);
+ else
+ printf("%.14s\n", p->lname);
+}
+
+getname(uid, buf)
+int uid;
+char buf[];
+{
+ int j, c, n, i;
+
+ inf.fdes = uidfil;
+ seek(inf.fdes, 0, 0);
+ inf.nleft = 0;
+ do {
+ i = 0;
+ j = 0;
+ n = 0;
+ while((c=getc(&inf)) != '\n') {
+ if (c<0)
+ 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';
+ return(0);
+}
+
+nblock(size0, size)
+char *size0, *size;
+{
+ register int n;
+
+ n = ldiv(size0, size, 512);
+ if (size&0777)
+ n++;
+ if (n>8)
+ n =+ (n+255)/256;
+ return(n);
+}
+
+int m0[] { 3, DIR, 'd', BLK, 'b', CHR, 'c', '-'};
+int m1[] { 1, ROWN, 'r', '-' };
+int m2[] { 1, WOWN, 'w', '-' };
+int m3[] { 2, SUID, 's', XOWN, 'x', '-' };
+int m4[] { 1, RGRP, 'r', '-' };
+int m5[] { 1, WGRP, 'w', '-' };
+int m6[] { 2, SGID, 's', XGRP, 'x', '-' };
+int m7[] { 1, ROTH, 'r', '-' };
+int m8[] { 1, WOTH, 'w', '-' };
+int m9[] { 1, XOTH, 'x', '-' };
+int m10[] { 1, STXT, 't', ' ' };
+
+int *m[] { m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10};
+
+pmode(aflag)
+{
+ register int **mp;
+
+ flags = aflag;
+ for (mp = &m[0]; mp < &m[11];)
+ select(*mp++);
+}
+
+select(pairp)
+int *pairp;
+{
+ register int n, *ap;
+
+ ap = pairp;
+ n = *ap++;
+ while (--n>=0 && (flags&*ap++)==0)
+ ap++;
+ putchar(*ap);
+}
+
+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; i<14; i++)
+ *dp++ = *fp++;
+ *dp = 0;
+ return(dfile);
+}
+
+readdir(dir)
+char *dir;
+{
+ static struct {
+ int dinode;
+ char dname[14];
+ } dentry;
+ register char *p;
+ register int j;
+ register struct lbuf *ep;
+
+ if (fopen(dir, &inf) < 0) {
+ printf("%s unreadable\n", dir);
+ return;
+ }
+ tblocks = 0;
+ for(;;) {
+ p = &dentry;
+ for (j=0; j<16; j++)
+ *p++ = getc(&inf);
+ if (dentry.dinode==0
+ || aflg==0 && dentry.dname[0]=='.')
+ continue;
+ if (dentry.dinode == -1)
+ break;
+ ep = gstat(makename(dir, dentry.dname), 0);
+ if (ep->lnum != -1)
+ ep->lnum = dentry.dinode;
+ for (j=0; j<14; j++)
+ ep->lname[j] = dentry.dname[j];
+ }
+ close(inf.fdes);
+}
+
+gstat(file, argfl)
+char *file;
+{
+ struct ibuf statb;
+ register struct lbuf *rep;
+
+ if (lastp+1 >= rlastp) {
+ sbrk(512);
+ rlastp.idev =+ 512;
+ }
+ rep = lastp;
+ lastp++;
+ rep->lflags = 0;
+ rep->lnum = 0;
+ if (argfl || statreq) {
+ if (stat(file, &statb)<0) {
+ printf("%s not found\n", file);
+ statb.inum = -1;
+ statb.isize0 = 0;
+ statb.isize = 0;
+ statb.iflags = 0;
+ if (argfl) {
+ lastp--;
+ return(0);
+ }
+ }
+ rep->lnum = statb.inum;
+ statb.iflags =& ~DIR;
+ if ((statb.iflags&IFMT) == 060000) {
+ statb.iflags =& ~020000;
+ } else if ((statb.iflags&IFMT)==040000) {
+ statb.iflags =& ~IFMT;
+ statb.iflags =| DIR;
+ }
+ statb.iflags =& ~ LARGE;
+ if (statb.iflags & RSTXT)
+ statb.iflags =| STXT;
+ statb.iflags =& ~ RSTXT;
+ rep->lflags = statb.iflags;
+ rep->luid = statb.iuid;
+ rep->lgid = statb.igid;
+ rep->lnl = statb.inl;
+ rep->lsize0 = statb.isize0;
+ rep->lsize = statb.isize;
+ if (rep->lflags & (BLK|CHR) && lflg)
+ rep->lsize = statb.iaddr[0];
+ rep->lmtime[0] = statb.imtime[0];
+ rep->lmtime[1] = statb.imtime[1];
+ if(uflg) {
+ rep->lmtime[0] = statb.iatime[0];
+ rep->lmtime[1] = statb.iatime[1];
+ }
+ tblocks =+ nblock(statb.isize0, statb.isize);
+ }
+ return(rep);
+}
+
+compar(ap1, ap2)
+struct lbuf *ap1, *ap2;
+{
+ register struct lbuf *p1, *p2;
+ register int i;
+ int j;
+ struct { char *charp;};
+
+ p1 = ap1;
+ p2 = ap2;
+ if (dflg==0) {
+ if ((p1->lflags&(DIR|ISARG)) == (DIR|ISARG)) {
+ if ((p2->lflags&(DIR|ISARG)) != (DIR|ISARG))
+ return(1);
+ } else {
+ if ((p2->lflags&(DIR|ISARG)) == (DIR|ISARG))
+ return(-1);
+ }
+ }
+ if (tflg) {
+ i = 0;
+ if (p2->lmtime[0] > p1->lmtime[0])
+ i++;
+ else if (p2->lmtime[0] < p1->lmtime[0])
+ i--;
+ else if (p2->lmtime[1] > p1->lmtime[1])
+ i++;
+ else if (p2->lmtime[1] < p1->lmtime[1])
+ i--;
+ return(i*rflg);
+ }
+ if (p1->lflags&ISARG)
+ p1 = p1->namep;
+ else
+ p1 = p1->lname;
+ if (p2->lflags&ISARG)
+ p2 = p2->namep;
+ else
+ p2 = p2->lname;
+ for (;;)
+ if ((j = *p1.charp++ - *p2.charp++) || p1.charp[-1]==0)
+ return(rflg*j);
+ return(0);
+}