BSD 4 release
[unix-history] / usr / src / cmd / ls / ucbls.c
index 118bee5..bf090cd 100644 (file)
@@ -1,11 +1,14 @@
-/* Copyright (c) 1979 Regents of the University of California */
-#
+#define UCB                    /* Controls output format for -F */
+/* #define     UCB_PWHASH      /* If have hashed password file */
+
 /*
  * ls - list file or directory
  *
  * Modified by Bill Joy UCB May/August 1977
 /*
  * ls - list file or directory
  *
  * Modified by Bill Joy UCB May/August 1977
+ * Modified by Dave Presotto BTL Feb/80
+ * Modified by Bill Joy and Mark Horton Summer 1980
  *
  *
- * This version of ls is designed for graphic terminals and to
+ * this version of ls is designed for graphic terminals and to
  * list directories with lots of files in them compactly.
  * It supports three variants for listings:
  *
  * list directories with lots of files in them compactly.
  * It supports three variants for listings:
  *
  *
  *     -q      force non-printings to be '?'s, e.g. to a file
  *
  *
  *     -q      force non-printings to be '?'s, e.g. to a file
  *
- *     -c      force columnar output, e.g. into a file
+ *     -C      force columnar output, e.g. into a file
  *
  *     -n      like -l, but user/group id's in decimal rather than
  *             looking in /etc/passwd to save time
  *
  *     -n      like -l, but user/group id's in decimal rather than
  *             looking in /etc/passwd to save time
+ *
+ *     -F      turns on the "flagging" of executables and directories
+ *
+ *     -R      causes ls to recurse through the branches of the subtree
+ *             ala find
  */
 
 #include <sys/param.h>
  */
 
 #include <sys/param.h>
 #include <sys/dir.h>
 #include <stdio.h>
 #include <ctype.h>
 #include <sys/dir.h>
 #include <stdio.h>
 #include <ctype.h>
+#include <pwd.h>
+#include <grp.h>
+#include <utmp.h>
 
 
+struct utmp    utmp;
+#define NMAX   (sizeof utmp.ut_name)
 
 
-#define        NFILES  1024
+#define MAXFILEWIDTH 14
+#define NFILES 1024
 FILE   *pwdf, *dirf;
 
 struct lbuf {
 FILE   *pwdf, *dirf;
 
 struct lbuf {
@@ -56,7 +70,7 @@ struct lbuf {
                char    *namep;
        } ln;
        char    ltype;
                char    *namep;
        } ln;
        char    ltype;
-       short   lnum;
+       ino_t   lnum;
        short   lflags;
        short   lnl;
        short   luid;
        short   lflags;
        short   lnl;
        short   luid;
@@ -65,17 +79,26 @@ struct lbuf {
        long    lmtime;
 };
 
        long    lmtime;
 };
 
-int    aflg, dflg, lflg, sflg, tflg, uflg, iflg, fflg, gflg, cflg;
-int    Aflg, nflg, qflg, across;
+struct dchain {
+       char *dc_name;          /* the path name */
+       struct dchain *dc_next; /* the next directory on the chain */
+};
+
+struct dchain *dfirst;         /* the start of the directory chain */
+struct dchain *cdfirst;                /* the start of the current directory chain */
+struct dchain *dtemp;          /* temporary used when linking */
+char *curdir;                  /* the current directory */
+
+int    aflg, bflg, dflg, lflg, sflg, tflg, uflg, iflg, fflg, gflg, cflg;
+int    Aflg, nflg, qflg, Fflg, Rflg, across, Cflg;
 int    nopad;
 int    nopad;
-char   buff[32];
+int    tabflg;
 int    rflg    = 1;
 long   year;
 int    flags;
 int    rflg    = 1;
 long   year;
 int    flags;
-int    lastuid = -1;
-char   tbuf[16];
 long   tblocks;
 int    statreq;
 long   tblocks;
 int    statreq;
+int    xtraent;                /* for those switches which print out a total */
 struct lbuf    *flist[NFILES];
 struct lbuf    **lastp = flist;
 struct lbuf    **firstp = flist;
 struct lbuf    *flist[NFILES];
 struct lbuf    **lastp = flist;
 struct lbuf    **firstp = flist;
@@ -85,30 +108,43 @@ char       *makename();
 struct lbuf *gstat();
 char   *ctime();
 long   nblock();
 struct lbuf *gstat();
 char   *ctime();
 long   nblock();
+char   *getname();
 
 
-#define        ISARG   0100000
-int    colwidth = 15;
+#define ISARG  0100000
+int    colwidth;
+int    filewidth;
+int    fixedwidth;
 int    outcol;
 
 char   obuf[BUFSIZ];
 
 main(argc, argv)
 int    outcol;
 
 char   obuf[BUFSIZ];
 
 main(argc, argv)
+int argc;
 char *argv[];
 {
 char *argv[];
 {
-       int i;
-       register struct lbuf *ep, **ep1;
+#include <sgtty.h>
+
+       int i, width;
+       register struct lbuf *ep;
        register struct lbuf **slastp;
        struct lbuf **epp;
        struct lbuf lb;
        char *t;
        char *cp;
        int compar();
        register struct lbuf **slastp;
        struct lbuf **epp;
        struct lbuf lb;
        char *t;
        char *cp;
        int compar();
+       struct sgttyb sgbuf;
 
 
+       Fflg = 0;
+       tabflg = 0;
        Aflg = getuid() == 0;
        setbuf(stdout, obuf);
        Aflg = getuid() == 0;
        setbuf(stdout, obuf);
-       time(&lb.lmtime);
+       lb.lmtime = time((long *) 0);
        year = lb.lmtime - 6L*30L*24L*60L*60L; /* 6 months ago */
        year = lb.lmtime - 6L*30L*24L*60L*60L; /* 6 months ago */
-       qflg = gtty(1, buff) == 0;
+       qflg = gtty(1, &sgbuf) == 0;
+
+       /* guarantee at least on column width */
+       fixedwidth = 2;
+
        /*
         * If the standard output is not a teletype,
         * then we default to one-per-line format
        /*
         * If the standard output is not a teletype,
         * then we default to one-per-line format
@@ -116,36 +152,57 @@ char *argv[];
         * columnar based on our name.
         */
        if (qflg) {
         * columnar based on our name.
         */
        if (qflg) {
-               cflg = 1;
+               Cflg = 1;
+               if ((sgbuf.sg_flags & XTABS) == 0)
+                       tabflg++;
                for (cp = argv[0]; cp[0] && cp[1]; cp++)
                        continue;
                /*
                for (cp = argv[0]; cp[0] && cp[1]; cp++)
                        continue;
                /*
-                * Name ends in l => stream
+                * Certain kinds of links (l, ll, lr, lf, lx) cause some
+                * various options to be turned on.
                 */
                 */
-               if (cp[0] == 'l')
-                       nopad = 1, cflg = 0;
-               /*
-                * ... if doesn't end in l or s ==> columns sorted across
-                *
-               else if (cp[0] == 'x')
+               switch (cp[0]) {
+               case 'l':
+                       if (cp[-1] == 'l') {
+                               /* ll => -l */
+                               lflg = 1;
+                               statreq++;
+                               xtraent++;
+                       } else {
+                               /* l => -m */
+                               nopad = 1;
+                               Cflg = 0;
+                       }
+                       break;
+               case 'x':       /* lx => -x */
                        across = 1;
                        across = 1;
-                */
+                       break;
+               case 'f':       /* lf => -F */
+                       Fflg = 1;
+                       break;
+               case 'r':       /* lr => -R */
+                       Rflg = 1;
+                       break;
+               }
+       } else {
+               tabflg++;
        }
        }
-       if (--argc > 0 && *argv[1] == '-') {
+
+       while (--argc > 0 && *argv[1] == '-') {
                argv++;
                while (*++*argv) switch (**argv) {
                /*
                argv++;
                while (*++*argv) switch (**argv) {
                /*
-                * c - force columnar output
+                * C - force columnar output
                 */
                 */
-               case 'c':
-                       cflg = 1;
+               case 'C':
+                       Cflg = 1;
                        nopad = 0;
                        continue;
                /*
                 * m - force stream output
                 */
                case 'm':
                        nopad = 0;
                        continue;
                /*
                 * m - force stream output
                 */
                case 'm':
-                       cflg = 0;
+                       Cflg = 0;
                        nopad = 1;
                        continue;
                /*
                        nopad = 1;
                        continue;
                /*
@@ -154,19 +211,27 @@ char *argv[];
                case 'x':
                        across = 1;
                        nopad = 0;
                case 'x':
                        across = 1;
                        nopad = 0;
-                       cflg = 1;
+                       Cflg = 1;
                        continue;
                /*
                 * q - force ?'s in output
                 */
                case 'q':
                        qflg = 1;
                        continue;
                /*
                 * q - force ?'s in output
                 */
                case 'q':
                        qflg = 1;
+                       bflg = 0;
+                       continue;
+               /*
+                * b - force octal value in output
+                */
+               case 'b':
+                       bflg = 1;
+                       qflg = 0;
                        continue;
                /*
                 * 1 - force 1/line in output
                 */
                case '1':
                        continue;
                /*
                 * 1 - force 1/line in output
                 */
                case '1':
-                       cflg = 0;
+                       Cflg = 0;
                        nopad = 0;
                        continue;
                /* STANDARD FLAGS */
                        nopad = 0;
                        continue;
                /* STANDARD FLAGS */
@@ -178,10 +243,15 @@ char *argv[];
                        Aflg = !Aflg;
                        continue;
 
                        Aflg = !Aflg;
                        continue;
 
+               case 'c':
+                       cflg++;
+                       continue;
+
                case 's':
                case 's':
-                       colwidth += 5;
+                       fixedwidth += 5;
                        sflg++;
                        statreq++;
                        sflg++;
                        statreq++;
+                       xtraent++;
                        continue;
 
                case 'd':
                        continue;
 
                case 'd':
@@ -196,6 +266,7 @@ char *argv[];
                case 'l':
                        lflg++;
                        statreq++;
                case 'l':
                        lflg++;
                        statreq++;
+                       xtraent++;
                        continue;
 
                case 'r':
                        continue;
 
                case 'r':
@@ -212,7 +283,7 @@ char *argv[];
                        continue;
 
                case 'i':
                        continue;
 
                case 'i':
-                       colwidth += 5;
+                       fixedwidth += 6;
                        iflg++;
                        continue;
 
                        iflg++;
                        continue;
 
@@ -224,25 +295,40 @@ char *argv[];
                        gflg++;
                        continue;
 
                        gflg++;
                        continue;
 
-               default:
+               case 'F':
+                       Fflg++;
+                       continue;
+
+               case 'R':
+                       Rflg++;
                        continue;
                        continue;
+
+               default:
+                       fprintf (stderr, "usage: ls [-1ACFRabcdfgilmnqrstux] [files]\n");
+                       exit(1);
                }
                }
-               argc--;
        }
        }
+       if (Fflg)
+#ifdef UCB
+               fixedwidth++;
+#else
+               fixedwidth += 2;
+#endif
        if (fflg) {
                aflg++;
                lflg = 0;
                sflg = 0;
                tflg = 0;
                statreq = 0;
        if (fflg) {
                aflg++;
                lflg = 0;
                sflg = 0;
                tflg = 0;
                statreq = 0;
+               xtraent = 0;
        }
        if(lflg) {
        }
        if(lflg) {
-               cflg = 0;
+               Cflg = 0;
                t = "/etc/passwd";
                if (gflg)
                        t = "/etc/group";
                nopad = 0;
                t = "/etc/passwd";
                if (gflg)
                        t = "/etc/group";
                nopad = 0;
-               colwidth = 70;
+               fixedwidth = 70;
                pwdf = fopen(t, "r");
        }
        if (argc==0) {
                pwdf = fopen(t, "r");
        }
        if (argc==0) {
@@ -250,42 +336,126 @@ char *argv[];
                argv = &dotp - 1;
        }
        for (i=0; i < argc; i++) {
                argv = &dotp - 1;
        }
        for (i=0; i < argc; i++) {
-               if ((ep = gstat(*++argv, 1))==NULL)
+               argv++;
+               if (Cflg) {
+                       width = strlen (*argv);
+                       if (width > filewidth)
+                               filewidth = width;
+               }
+               if ((ep = gstat(*argv, 1))==NULL)
                        continue;
                ep->ln.namep = *argv;
                ep->lflags |= ISARG;
        }
                        continue;
                ep->ln.namep = *argv;
                ep->lflags |= ISARG;
        }
+       if (!Cflg)
+               filewidth = MAXFILEWIDTH;
+       else
+       colwidth = fixedwidth + filewidth;
        qsort(firstp, lastp - firstp, sizeof *lastp, compar);
        slastp = lastp;
        qsort(firstp, lastp - firstp, sizeof *lastp, compar);
        slastp = lastp;
+       /* For each argument user typed */
        for (epp=firstp; epp<slastp; epp++) {
                ep = *epp;
        for (epp=firstp; epp<slastp; epp++) {
                ep = *epp;
-               if (ep->ltype=='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", tblocks);
-                       pem(slastp, lastp);
-                       newline();
-               } else 
+               if (ep->ltype=='d' && dflg==0 || fflg)
+                       pdirectory(ep->ln.namep, (argc>1), slastp);
+               else 
                        pentry(ep);
                        pentry(ep);
+
+               /* -R: print subdirectories found */
+               while (dfirst || cdfirst) {
+                       /* Place direct subdirs on front in right order */
+                       while (cdfirst) {
+                               /* reverse cdfirst onto front of dfirst */
+                               dtemp = cdfirst;
+                               cdfirst = cdfirst -> dc_next;
+                               dtemp -> dc_next = dfirst;
+                               dfirst = dtemp;
+                       }
+                       /* take off first dir on dfirst & print it */
+                       dtemp = dfirst;
+                       dfirst = dfirst->dc_next;
+                       pdirectory (dtemp->dc_name, 1, firstp);
+                       cfree (dtemp->dc_name);
+                       cfree (dtemp);
+               }
        }
        if (outcol)
                putc('\n', stdout);
        fflush(stdout);
 }
 
        }
        if (outcol)
                putc('\n', stdout);
        fflush(stdout);
 }
 
+/*
+ * pdirectory: print the directory name, labelling it if title is
+ * nonzero, using lp as the place to start reading in the dir.
+ */
+pdirectory (name, title, lp)
+char *name;
+int title;
+struct lbuf **lp;
+{
+       register struct dchain *dp;
+       register struct lbuf *ap;
+       register char *pname;
+       struct lbuf **app;
+
+       filewidth = 0;
+       curdir = name;
+       if (title)
+               printf("\n%s:\n", name);
+       lastp = lp;
+       readdir(name);
+       if (!Cflg)
+               filewidth = MAXFILEWIDTH;
+       colwidth = fixedwidth + filewidth;
+#ifdef notdef
+       /* Taken out because it appears this is done below in pem. */
+       if (tabflg) {
+               if (colwidth <= 8)
+                       colwidth = 8;
+               else
+                       if (colwidth <= 16)
+                               colwidth = 16;
+       }
+#endif
+       if (fflg==0)
+               qsort(lp,lastp - lp,sizeof *lastp,compar);
+       if (Rflg) for (app=lastp-1; app>=lp; app--) {
+               ap = *app;
+               if (ap->ltype == 'd' && strcmp(ap->ln.lname, ".") &&
+                               strcmp(ap->ln.lname, "..")) {
+                       dp = (struct dchain *) calloc(1, sizeof(struct dchain));
+                       pname = makename (curdir, ap->ln.lname);
+                       dp->dc_name = (char *) calloc(1, strlen(pname)+1);
+                       strcpy(dp->dc_name, pname);
+                       dp -> dc_next = dfirst;
+                       dfirst = dp;
+               }
+       }
+       if (lflg || sflg)
+               printf("total %D", tblocks);
+       pem(lp, lastp);
+       newline();
+}
+
+/*
+ * pem: print 'em.  Print a list of files (e.g. a directory) bounded
+ * by slp and lp.
+ */
 pem(slp, lp)
        register struct lbuf **slp, **lp;
 {
        int ncols, nrows, row, col;
        register struct lbuf **ep;
 
 pem(slp, lp)
        register struct lbuf **slp, **lp;
 {
        int ncols, nrows, row, col;
        register struct lbuf **ep;
 
+       if (tabflg) {
+               if (colwidth <= 9)
+                       colwidth = 8;
+               else
+                       if (colwidth <= 17)
+                               colwidth = 16;
+       }
        ncols = 80 / colwidth;
        ncols = 80 / colwidth;
-       if (ncols == 1 || cflg == 0) {
+       if (ncols == 1 || Cflg == 0) {
                for (ep = slp; ep < lp; ep++)
                        pentry(*ep);
                return;
                for (ep = slp; ep < lp; ep++)
                        pentry(*ep);
                return;
@@ -295,11 +465,11 @@ pem(slp, lp)
                        pentry(*ep);
                return;
        }
                        pentry(*ep);
                return;
        }
-       if (statreq)
+       if (xtraent)
                slp--;
        nrows = (lp - slp - 1) / ncols + 1;
        for (row = 0; row < nrows; row++) {
                slp--;
        nrows = (lp - slp - 1) / ncols + 1;
        for (row = 0; row < nrows; row++) {
-               col = row == 0 && statreq;
+               col = row == 0 && xtraent;
                for (; col < ncols; col++) {
                        ep = slp + (nrows * col) + row;
                        if (ep < lp)
                for (; col < ncols; col++) {
                        ep = slp + (nrows * col) + row;
                        if (ep < lp)
@@ -310,9 +480,17 @@ pem(slp, lp)
        }
 }
 
        }
 }
 
+/*
+ * pputchar: like putchar but knows how to handle control chars.
+ * CAUTION: if you make ctrl chars print in ^x notation, or any
+ * other notation which is wider than one character, the column
+ * nature of things (such as files with 14 letter names) will be
+ * messed up.  Weigh this carefully!
+ */
 pputchar(c)
        char c;
 {
 pputchar(c)
        char c;
 {
+       char cc;
 
        switch (c) {
                case '\t':
 
        switch (c) {
                case '\t':
@@ -322,8 +500,19 @@ pputchar(c)
                        outcol = 0;
                        break;
                default:
                        outcol = 0;
                        break;
                default:
-                       if (qflg && (c < ' ' || c >= 0177))
-                               c = '?';
+                       if (c < ' ' || c >= 0177) {
+                               if (qflg)
+                                       c = '?';
+                               else if (bflg) {
+                                       outcol += 3;
+                                       putc ('\\', stdout);
+                                       cc = '0' + (c>>6 & 07);
+                                       putc (cc, stdout);
+                                       cc = '0' + (c>>3 & 07);
+                                       putc (cc, stdout);
+                                       c = '0' + (c & 07);
+                               }
+                       }
                        outcol++;
                        break;
        }
                        outcol++;
                        break;
        }
@@ -337,6 +526,9 @@ newline()
        outcol = 0;
 }
 
        outcol = 0;
 }
 
+/*
+ * column: get to the beginning of the next column.
+ */
 column()
 {
 
 column()
 {
 
@@ -354,7 +546,7 @@ column()
                outcol++;
                return;
        }
                outcol++;
                return;
        }
-       if (cflg == 0) {
+       if (Cflg == 0) {
                putc('\n', stdout);
                return;
        }
                putc('\n', stdout);
                return;
        }
@@ -363,6 +555,16 @@ column()
                outcol = 0;
                return;
        }
                outcol = 0;
                return;
        }
+       if (tabflg && (colwidth <= 16)) {
+               if (colwidth > 8)
+                       if ((outcol % 16) < 8) {
+                               outcol += 8 - (outcol % 8);
+                               putc ('\t', stdout);
+                       }
+               outcol += 8 - (outcol % 8);
+               putc ('\t', stdout);
+               return;
+       }
        do {
                outcol++;
                putc(' ', stdout);
        do {
                outcol++;
                putc(' ', stdout);
@@ -370,40 +572,10 @@ column()
 }
 
 
 }
 
 
-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);
-}
-
+/*
+ * nblock: the number of 512 byte blocks a size byte file takes up.
+ * (Note: the number stays 512 no matter what BUFSIZ or the filesystem uses.)
+ */
 long
 nblock(size)
 long size;
 long
 nblock(size)
 long size;
@@ -411,6 +583,10 @@ long size;
        return((size+511)>>9);
 }
 
        return((size+511)>>9);
 }
 
+/*
+ * This code handles the rwx- business.
+ * You figure it out.
+ */
 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    m1[] = { 1, S_IREAD>>0, 'r', '-' };
 int    m2[] = { 1, S_IWRITE>>0, 'w', '-' };
 int    m3[] = { 2, S_ISUID, 's', S_IEXEC>>0, 'x', '-' };
@@ -443,6 +619,9 @@ register int *pairp;
        pputchar(*pairp);
 }
 
        pputchar(*pairp);
 }
 
+/*
+ * returns cat(dir, "/", file), unless dir ends in /, when it doesn't //
+ */
 char *
 makename(dir, file)
 char *dir, *file;
 char *
 makename(dir, file)
 char *dir, *file;
@@ -455,6 +634,7 @@ char *dir, *file;
        fp = dir;
        while (*fp)
                *dp++ = *fp++;
        fp = dir;
        while (*fp)
                *dp++ = *fp++;
+       if (*(dp-1) != '/')
        *dp++ = '/';
        fp = file;
        for (i=0; i<DIRSIZ; i++)
        *dp++ = '/';
        fp = file;
        for (i=0; i<DIRSIZ; i++)
@@ -463,11 +643,15 @@ char *dir, *file;
        return(dfile);
 }
 
        return(dfile);
 }
 
+/*
+ * readdir: read in the directory whose name is dir,
+ * starting at lastp.
+ */
 readdir(dir)
 char *dir;
 {
        static struct direct dentry;
 readdir(dir)
 char *dir;
 {
        static struct direct dentry;
-       register int j;
+       register int j, width;
        register struct lbuf *ep;
 
        if ((dirf = fopen(dir, "r")) == NULL) {
        register struct lbuf *ep;
 
        if ((dirf = fopen(dir, "r")) == NULL) {
@@ -484,7 +668,12 @@ char *dir;
                        dentry.d_name[1]=='\0'
                        || dentry.d_name[1]=='.' && dentry.d_name[2]=='\0'))
                        continue;
                        dentry.d_name[1]=='\0'
                        || dentry.d_name[1]=='.' && dentry.d_name[2]=='\0'))
                        continue;
-               ep = gstat(makename(dir, dentry.d_name), 0);
+               if (Cflg) {
+                       width = strlen (dentry.d_name);
+                       if (width > filewidth)
+                               filewidth = width;
+               }
+               ep = gstat(makename(dir, dentry.d_name), Fflg || Rflg);
                if (ep==NULL)
                        continue;
                if (ep->lnum != -1)
                if (ep==NULL)
                        continue;
                if (ep->lnum != -1)
@@ -495,6 +684,11 @@ char *dir;
        fclose(dirf);
 }
 
        fclose(dirf);
 }
 
+/*
+ * stat the given file and return an lbuf containing it.
+ * argfl is nonzero if a stat is required because the file is
+ * an argument, rather than having been found in a directory.
+ */
 struct lbuf *
 gstat(file, argfl)
 char *file;
 struct lbuf *
 gstat(file, argfl)
 char *file;
@@ -551,6 +745,16 @@ char *file;
                        rep->ltype = 'c';
                        rep->lsize = statb.st_rdev;
                        break;
                        rep->ltype = 'c';
                        rep->lsize = statb.st_rdev;
                        break;
+
+               case S_IFMPB:
+                       rep->ltype = 'M';
+                       rep->lsize = statb.st_rdev;
+                       break;
+
+               case S_IFMPC:
+                       rep->ltype = 'm';
+                       rep->lsize = statb.st_rdev;
+                       break;
                }
                rep->lflags = statb.st_mode & ~S_IFMT;
                rep->luid = statb.st_uid;
                }
                rep->lflags = statb.st_mode & ~S_IFMT;
                rep->luid = statb.st_uid;
@@ -567,6 +771,10 @@ char *file;
        return(rep);
 }
 
        return(rep);
 }
 
+/*
+ * decide whether to print pp1 before or after pp2, based on their
+ * names, various times, and the r flag.
+ */
 compar(pp1, pp2)
 struct lbuf **pp1, **pp2;
 {
 compar(pp1, pp2)
 struct lbuf **pp1, **pp2;
 {
@@ -593,14 +801,24 @@ struct lbuf **pp1, **pp2;
        return(rflg * strcmp(p1->lflags&ISARG? p1->ln.namep: p1->ln.lname,
                                p2->lflags&ISARG? p2->ln.namep: p2->ln.lname));
 }
        return(rflg * strcmp(p1->lflags&ISARG? p1->ln.namep: p1->ln.lname,
                                p2->lflags&ISARG? p2->ln.namep: p2->ln.lname));
 }
+
+/*
+ * print the entry pointed at by ap
+ */
 pentry(ap)
 struct lbuf *ap;
 {
        struct { char dminor, dmajor;};
 pentry(ap)
 struct lbuf *ap;
 {
        struct { char dminor, dmajor;};
-       register t;
        register struct lbuf *p;
        register char *cp;
        register struct lbuf *p;
        register char *cp;
+       char fname[100];
+       char *pname;
+       struct passwd *getpwuid();
+       struct passwd *pwptr;
+       struct group *getgrgid();
+       struct group *grptr;
 
 
+       fname[0] = 0;
        p = ap;
        if (p->lnum == -1)
                return;
        p = ap;
        if (p->lnum == -1)
                return;
@@ -619,41 +837,94 @@ struct lbuf *ap;
                pputchar(p->ltype);
                pmode(p->lflags);
                printf("%2d ", p->lnl);
                pputchar(p->ltype);
                pmode(p->lflags);
                printf("%2d ", p->lnl);
-               t = p->luid;
-               if(gflg)
-                       t = p->lgid;
-               if (nflg == 0 && getname(t, tbuf)==0)
-                       printf("%-8.8s", tbuf);
-               else
-                       printf("%-8d", t);
-               if (p->ltype=='b' || p->ltype=='c')
-                       printf("%3d,%3d", major((int)p->lsize), minor((int)p->lsize));
-               else
+               if(gflg) {
+                       grptr = getgrgid(p->lgid);
+                       if (nflg == 0 && grptr != 0)
+                               printf("%-8.8s", grptr->gr_name);
+                       else
+                               printf("%-8d", p->lgid);
+               } else {
+#ifndef UCB_PWHASH
+                       char *name;
+                       if (nflg == 0 && (name = getname(p->luid))) {
+                               printf("%-8.8s", name);
+                       }
+#else
+                       pwptr = getpwuid(p->luid);
+                       if (nflg == 0 && pwptr != 0)
+                               printf("%-8.8s", pwptr->pw_name);
+#endif
+                       else
+                               printf("%-8d", p->luid);
+               }
+               switch (p->ltype) {
+
+               case 'b':
+               case 'c':
+               case 'm':
+               case 'M':
+                       printf("%3d,%3d",
+                           major((int)p->lsize), minor((int)p->lsize));
+                       break;
+               default:
                        printf("%7ld", p->lsize);
                        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);
        }
                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", p->ln.namep);
+#ifndef UCB
+       if (Fflg) {
+           if (p->ltype == 'd')
+               strcat (fname, "[");
+           else if (p->lflags & 0111)
+               strcat (fname, "*");
+           else if (!nopad)
+               strcat (fname, " ");
+       }
+#endif
+       if (p->lflags & ISARG)
+           strncat (fname, p->ln.namep, 98);
        else
        else
-               printf("%.14s", p->ln.lname);
+           strncat (fname, p->ln.lname, 14);
+#ifndef UCB
+       if (Fflg) {
+           if (p->ltype == 'd')
+               strcat (fname, "]");
+           else if (!nopad)
+               strcat (fname, " ");
+       }
+#else
+       if (Fflg) {
+           if (p->ltype == 'd')
+               strcat (fname, "/");
+           else if (p->lflags & 0111)
+               strcat (fname, "*");
+           else if (!nopad)
+               strcat (fname, " ");
+       }
+#endif
+       printf ("%s", fname);
+       free(ap);
 }
 }
+
 /* char printf_id[] = "@(#) printf.c:2.2 6/5/79";*/
 /* char printf_id[] = "@(#) printf.c:2.2 6/5/79";*/
+
 #include "varargs.h"
 #include "varargs.h"
-/* This version of printf is compatible with the Version 7 C
+
+/*
+ * This version of printf is compatible with the Version 7 C
  * printf. The differences are only minor except that this
  * printf assumes it is to print through pputchar. Version 7
  * printf is more general (and is much larger) and includes
  * provisions for floating point.
  */
  * printf. The differences are only minor except that this
  * printf assumes it is to print through pputchar. Version 7
  * printf is more general (and is much larger) and includes
  * provisions for floating point.
  */
 
 
-#define MAXOCT 11      /* Maximum octal digits in a long */
-#define MAXINT 32767   /* largest normal length positive integer */
+#define MAXOCT 11          /* Maximum octal digits in a long */
+#define MAXINT 32767       /* largest normal length positive integer */
 #define BIG    1000000000  /* largest power of 10 less than an unsigned long */
 #define BIG    1000000000  /* largest power of 10 less than an unsigned long */
-#define MAXDIGS 10     /* number of digits in BIG */
+#define MAXDIGS 10         /* number of digits in BIG */
 
 static int width, sign, fill;
 
 
 static int width, sign, fill;
 
@@ -799,7 +1070,7 @@ printf(va_alist)
                                /* shift and mask for speed */
                                do
                                    if (((int) num & mask1) < 10)
                                /* shift and mask for speed */
                                do
                                    if (((int) num & mask1) < 10)
-                                       *--bptr = ((int) num & mask1) + 060;
+                                       *--bptr = ((int) num & mask1) + 060;
                                    else
                                        *--bptr = ((int) num & mask1) + 0127;
                                while (num = (num >> nbits) & mask2);
                                    else
                                        *--bptr = ((int) num & mask1) + 0127;
                                while (num = (num >> nbits) & mask2);
@@ -824,7 +1095,8 @@ printf(va_alist)
                        case 'U':
                        case 'I':
                                length = 1;
                        case 'U':
                        case 'I':
                                length = 1;
-                               fcode = fcode + 'a' - 'A';
+         
+                     fcode = fcode + 'a' - 'A';
                                /* no break */
                        case 'd':
                        case 'i':
                                /* no break */
                        case 'd':
                        case 'i':
@@ -979,3 +1251,36 @@ b_emit(s, send)
                while (--npad >= 0)
                        pputchar(cfill);
 }
                while (--npad >= 0)
                        pputchar(cfill);
 }
+
+#ifndef UCB_PWHASH
+#define NUID   2048
+
+char   names[NUID][NMAX+1];
+
+char *
+getname(uid)
+{
+       register struct passwd *pw;
+       static init;
+       struct passwd *getpwent();
+
+       if (uid >= 0 && uid < NUID && names[uid][0])
+               return (&names[uid][0]);
+       if (init == 2)
+               return (0);
+       if (init == 0)
+               setpwent(), init = 1;
+       while (pw = getpwent()) {
+               if (pw->pw_uid < 0 || pw->pw_uid >= NUID)
+                       continue;
+               if (names[pw->pw_uid][0])
+                       continue;
+               strncpy(names[pw->pw_uid], pw->pw_name, NMAX);
+               if (pw->pw_uid == uid)
+                       return (&names[uid][0]);
+       }
+       init = 2;
+       endpwent();
+       return (0);
+}
+#endif