added ls - 9base - revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log
Files
Refs
README
LICENSE
---
commit 6ccdc8cffd953f6dae2692e687d19ac6e58a7e2b
parent b7abc7dd08640a98b0af92b05bb0a57e614f3160
Author: Anselm R. Garbe 
Date:   Tue, 31 Jan 2006 20:37:59 +0200

added ls

Diffstat:
  M Makefile                            |       4 ++--
  M config.mk                           |       2 +-
  A ls/Makefile                         |       7 +++++++
  A ls/ls.1                             |     172 ++++++++++++++++++++++++++++++
  A ls/ls.c                             |     309 +++++++++++++++++++++++++++++++

5 files changed, 491 insertions(+), 3 deletions(-)
---
diff --git a/Makefile b/Makefile
@@ -3,8 +3,8 @@
 
 include config.mk
 
-SUBDIRS  = lib9 yacc awk basename bc dc cat cleanname date echo grep mk \
-                   rc read sed seq sleep sort tee test touch tr uniq
+SUBDIRS  = lib9 yacc awk basename bc dc cat cleanname date echo grep ls \
+                   mk rc read sed seq sleep sort tee test touch tr uniq
 
 all:
         @echo 9base build options:
diff --git a/config.mk b/config.mk
@@ -4,7 +4,7 @@
 PREFIX      = /usr/local/9
 MANPREFIX   = ${PREFIX}/share/man
 
-VERSION     = 2
+VERSION     = 20060129
 
 # Linux/BSD
 CFLAGS      = -Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -c -I. -DPREFIX="\"${PREFIX}\""
diff --git a/ls/Makefile b/ls/Makefile
@@ -0,0 +1,7 @@
+# ls - ls unix port from plan9
+#
+# Depends on ../lib9
+
+TARG      = ls
+
+include ../std.mk
diff --git a/ls/ls.1 b/ls/ls.1
@@ -0,0 +1,172 @@
+.TH LS 1
+.SH NAME
+ls, lc \- list contents of directory
+.SH SYNOPSIS
+.B ls
+[
+.B -dlmnpqrstuFQ
+]
+.I name ...
+.PP
+.B lc
+[
+.B -dlmnpqrstuFQ
+]
+.I name ...
+.SH DESCRIPTION
+For each directory argument,
+.I ls
+lists the contents of the directory;
+for each file argument,
+.I ls
+repeats its name and any other information requested.
+When no argument is given, the current directory is listed.
+By default, the output is sorted alphabetically by name.
+.PP
+.I Lc
+is the same as
+.IR ls ,
+but sets the
+.B -p
+option and pipes the output through
+.IR mc (1).
+.PP
+There are a number of options:
+.TP
+.B  -d
+If argument is a directory, list it, not
+its contents.
+.TP
+.B  -l
+List in long format, giving mode (see below), file system type
+(e.g., for devices, the
+.B #
+code letter that names it; see
+.IR intro (3)),
+the instance or subdevice number, owner, group,
+size in bytes, and time of last modification
+for each file.
+.TP
+.B -m
+List the name of the user who most recently modified the file.
+.TP
+.B  -n
+Don't sort the listing.
+.TP
+.B  -p
+Print only the final path element of each file name.
+.TP
+.B  -q
+List the
+.I qid
+(see
+.IR stat (3))
+of each file; the printed fields are in the order
+path, version, and type.
+.TP
+.B  -r
+Reverse the order of sort.
+.TP
+.B  -s
+Give size in Kbytes for each entry.
+.TP
+.B  -t
+Sort by time modified (latest first) instead of
+by name.
+.TP
+.B  -u
+Under
+.B -t
+sort by time of last access;
+under
+.B -l
+print time of last access.
+.TP
+.B  -F
+Add the character
+.B /
+after all directory names
+and the character
+.B *
+after all executable files.
+.TP
+.B -L
+Print the character
+.B t
+before each file if it has the temporary flag set, and
+.B -
+otherwise.
+.TP
+.B -Q
+By default, printed file names are quoted if they contain characters special to
+.IR rc (1).
+The
+.B -Q
+flag disables this behavior.
+.PP
+The mode printed under the
+.B -l
+option contains 11 characters,
+interpreted
+as follows:
+the first character is
+.TP
+.B d
+if the entry is a directory;
+.TP
+.B a
+if the entry is an append-only file;
+.TP
+.B D
+if the entry is a Unix device;
+.TP
+.B L
+if the entry is a symbolic link;
+.TP
+.B P
+if the entry is a named pipe;
+.TP
+.B S
+if the entry is a socket;
+.TP
+.B  -
+if the entry is a plain file.
+.PD
+.PP
+The next letter is
+.B l
+if the file is exclusive access (one writer or reader at a time).
+.PP
+The last 9 characters are interpreted
+as three sets of three bits each.
+The first set refers to owner permissions;
+the next to permissions to others in the same user-group;
+and the last to all others.
+Within each set the three characters indicate
+permission respectively to read, to write, or to
+execute the file as a program.
+For a directory, `execute' permission is interpreted
+to mean permission to search the directory
+for a specified file.
+The permissions are indicated as follows:
+.TP 3
+.B  r
+if the file is readable;
+.PD 0
+.TP 3
+.B  w
+if the file is writable;
+.TP 3
+.B  x
+if the file is executable;
+.TP 3
+.B  -
+if none of the above permissions is granted.
+.PD
+.SH SOURCE
+.B \*9/src/cmd/ls.c
+.br
+.B \*9/bin/lc
+.SH SEE ALSO
+.IR stat (3),
+.IR mc (1)
diff --git a/ls/ls.c b/ls/ls.c
@@ -0,0 +1,309 @@
+#include 
+#include 
+#include 
+
+#define dirbuf p9dirbuf        /* avoid conflict on sun */
+
+typedef struct NDir NDir;
+struct NDir
+{
+        Dir *d;
+        char        *prefix;
+};
+
+int        errs = 0;
+int        dflag;
+int        lflag;
+int        mflag;
+int        nflag;
+int        pflag;
+int        qflag;
+int        Qflag;
+int        rflag;
+int        sflag;
+int        tflag;
+int        uflag;
+int        Fflag;
+int        ndirbuf;
+int        ndir;
+NDir*        dirbuf;
+int        ls(char*, int);
+int        compar(NDir*, NDir*);
+char*        asciitime(long);
+char*        darwx(long);
+void        rwx(long, char*);
+void        growto(long);
+void        dowidths(Dir*);
+void        format(Dir*, char*);
+void        output(void);
+ulong        clk;
+int        swidth;                        /* max width of -s size */
+int        qwidth;                        /* max width of -q version */
+int        vwidth;                        /* max width of dev */
+int        uwidth;                        /* max width of userid */
+int        mwidth;                        /* max width of muid */
+int        glwidth;                /* max width of groupid and length */
+Biobuf        bin;
+
+void
+main(int argc, char *argv[])
+{
+        int i;
+
+        Binit(&bin, 1, OWRITE);
+        ARGBEGIN{
+        case 'F':        Fflag++; break;
+        case 'd':        dflag++; break;
+        case 'l':        lflag++; break;
+        case 'm':        mflag++; break;
+        case 'n':        nflag++; break;
+        case 'p':        pflag++; break;
+        case 'q':        qflag++; break;
+        case 'Q':        Qflag++; break;
+        case 'r':        rflag++; break;
+        case 's':        sflag++; break;
+        case 't':        tflag++; break;
+        case 'u':        uflag++; break;
+        default:        fprint(2, "usage: ls [-dlmnpqrstuFQ] [file ...]\n");
+                        exits("usage");
+        }ARGEND
+
+        doquote = needsrcquote;
+        quotefmtinstall();
+        fmtinstall('M', dirmodefmt);
+
+        if(lflag)
+                clk = time(0);
+        if(argc == 0)
+                errs = ls(".", 0);
+        else for(i=0; iqid.type&QTDIR && dflag==0){
+                free(db);
+                db = nil;
+                output();
+                fd = open(s, OREAD);
+                if(fd == -1)
+                        goto error;
+                n = dirreadall(fd, &db);
+                if(n < 0)
+                        goto error;
+                growto(ndir+n);
+                for(i=0; iname = strdup(p+1);
+                }
+                ndir++;
+        }
+        return 0;
+}
+
+void
+output(void)
+{
+        int i;
+        char buf[4096];
+        char *s;
+
+        if(!nflag)
+                qsort(dirbuf, ndir, sizeof dirbuf[0], (int (*)(const void*, const void*))compar);
+        for(i=0; iname);
+                        format(dirbuf[i].d, buf);
+                } else
+                        format(dirbuf[i].d, dirbuf[i].d->name);
+        }
+        ndir = 0;
+        Bflush(&bin);
+}
+
+void
+dowidths(Dir *db)
+{
+        char buf[256];
+        int n;
+
+        if(sflag) {
+                n = sprint(buf, "%llud", (db->length+1023)/1024);
+                if(n > swidth)
+                        swidth = n;
+        }
+        if(qflag) {
+                n = sprint(buf, "%lud", db->qid.vers);
+                if(n > qwidth)
+                        qwidth = n;
+        }
+        if(mflag) {
+                n = snprint(buf, sizeof buf, "[%s]", db->muid);
+                if(n > mwidth)
+                        mwidth = n;
+        }
+        if(lflag) {
+                n = sprint(buf, "%ud", db->dev);
+                if(n > vwidth)
+                        vwidth = n;
+                n = strlen(db->uid);
+                if(n > uwidth)
+                        uwidth = n;
+                n = sprint(buf, "%llud", db->length);
+                n += strlen(db->gid);
+                if(n > glwidth)
+                        glwidth = n;
+        }
+}
+
+char*
+fileflag(Dir *db)
+{
+        if(Fflag == 0)
+                return "";
+        if(QTDIR & db->qid.type)
+                return "/";
+        if(0111 & db->mode)
+                return "*";
+        return "";
+}
+
+void
+format(Dir *db, char *name)
+{
+        int i;
+
+        if(sflag)
+                Bprint(&bin, "%*llud ",
+                        swidth, (db->length+1023)/1024);
+        if(mflag){
+                Bprint(&bin, "[%s] ", db->muid);
+                for(i=2+strlen(db->muid); iqid.path,
+                        qwidth, db->qid.vers,
+                        db->qid.type);
+        if(lflag)
+                Bprint(&bin,
+                        Qflag? "%M %C %*ud %*s %s %*llud %s %s\n" : "%M %C %*ud %*s %s %*llud %s %q\n",
+                        db->mode, db->type,
+                        vwidth, db->dev,
+                        -uwidth, db->uid,
+                        db->gid,
+                        (int)(glwidth-strlen(db->gid)), db->length,
+                        asciitime(uflag? db->atime : db->mtime), name);
+        else
+                Bprint(&bin,
+                        Qflag? "%s%s\n" : "%q%s\n",
+                        name, fileflag(db));
+}
+
+void
+growto(long n)
+{
+        if(n <= ndirbuf)
+                return;
+        ndirbuf = n;
+        dirbuf=(NDir *)realloc(dirbuf, ndirbuf*sizeof(NDir));
+        if(dirbuf == 0){
+                fprint(2, "ls: malloc fail\n");
+                exits("malloc fail");
+        }                
+}
+
+int
+compar(NDir *a, NDir *b)
+{
+        long i;
+        Dir *ad, *bd;
+
+        ad = a->d;
+        bd = b->d;
+
+        if(tflag){
+                if(uflag)
+                        i = bd->atime-ad->atime;
+                else
+                        i = bd->mtime-ad->mtime;
+        }else{
+                if(a->prefix && b->prefix){
+                        i = strcmp(a->prefix, b->prefix);
+                        if(i == 0)
+                                i = strcmp(ad->name, bd->name);
+                }else if(a->prefix){
+                        i = strcmp(a->prefix, bd->name);
+                        if(i == 0)
+                                i = 1;        /* a is longer than b */
+                }else if(b->prefix){
+                        i = strcmp(ad->name, b->prefix);
+                        if(i == 0)
+                                i = -1;        /* b is longer than a */
+                }else
+                        i = strcmp(ad->name, bd->name);
+        }
+        if(i == 0)
+                i = (ad