URI: 
       added read to 9base - 9base - revived minimalist port of Plan 9 userland to Unix
  HTML git clone git://git.suckless.org/9base
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 08aaa60fa84ea14afed7c7b0ead4307263cc118f
   DIR parent 2b4ad5ac67349aef64970f40d871b16b6f0262f3
  HTML Author: Anselm R. Garbe <garbeam@wmii.de>
       Date:   Sun, 29 Jan 2006 22:17:04 +0200
       
       added read to 9base
       
       Diffstat:
         M Makefile                            |       2 +-
         A read/Makefile                       |       6 ++++++
         A read/read.1                         |     108 +++++++++++++++++++++++++++++++
         A read/read.c                         |      91 +++++++++++++++++++++++++++++++
       
       4 files changed, 206 insertions(+), 1 deletion(-)
       ---
   DIR diff --git a/Makefile b/Makefile
       @@ -4,7 +4,7 @@
        include config.mk
        
        SUBDIRS  = lib9 yacc awk basename bc dc cat cleanname date echo grep mk \
       -                   rc sed seq sleep sort tee test touch tr uniq
       +                   rc read sed seq sleep sort tee test touch tr uniq
        
        all:
                @echo 9base build options:
   DIR diff --git a/read/Makefile b/read/Makefile
       @@ -0,0 +1,6 @@
       +# read - read unix port from plan9
       +# Depends on ../lib9
       +
       +TARG      = read
       +
       +include ../std.mk
   DIR diff --git a/read/read.1 b/read/read.1
       @@ -0,0 +1,108 @@
       +.TH CAT 1
       +.SH NAME
       +cat, read, nobs \- catenate files
       +.SH SYNOPSIS
       +.B cat
       +[
       +.I file ...
       +]
       +.br
       +.B read
       +[
       +.B -m
       +] [
       +.B -n
       +.I nline
       +] [
       +.I file ...
       +]
       +.br
       +.B nobs
       +[
       +.I file ...
       +]
       +.SH DESCRIPTION
       +.I Cat
       +reads each
       +.I file
       +in sequence and writes it on the standard output.
       +Thus
       +.IP
       +.L
       +cat file
       +.LP
       +prints a file and
       +.IP
       +.L
       +cat file1 file2 >file3
       +.LP
       +concatenates the first two files and places the result
       +on the third.
       +.PP
       +If no
       +.I file
       +is given,
       +.I cat 
       +reads from the standard input.
       +Output is buffered in blocks matching the input.
       +.PP
       +.I Read
       +copies to standard output exactly one line from the named
       +.IR file ,
       +default standard input.
       +It is useful in interactive
       +.IR rc (1)
       +scripts.
       +.PP
       +The
       +.B -m
       +flag causes it to continue reading and writing multiple lines until end of file;
       +.B -n
       +causes it to read no more than
       +.I nline
       +lines.
       +.PP
       +.I Read
       +always executes a single
       +.B write
       +for each line of input, which can be helpful when
       +preparing input to programs that expect line-at-a-time data.
       +It never reads any more data from the input than it prints to the output.
       +.PP
       +.I Nobs
       +copies the named files to
       +standard output except that it removes all backspace
       +characters and the characters that precede them.
       +It is useful to use as
       +.B $PAGER
       +with the Unix version of
       +.IR man (1)
       +when run inside a
       +.I win
       +(see
       +.IR acme (1))
       +window.
       +.SH SOURCE
       +.B \*9/src/cmd/cat.c
       +.br
       +.B \*9/src/cmd/read.c
       +.br
       +.B \*9/bin/nobs
       +.SH SEE ALSO
       +.IR cp (1)
       +.SH DIAGNOSTICS
       +.I Read
       +exits with status
       +.B eof
       +on end of file or, in the
       +.B -n
       +case, if it doesn't read
       +.I nlines
       +lines.
       +.SH BUGS
       +Beware of
       +.L "cat a b >a"
       +and
       +.LR "cat a b >b" ,
       +which
       +destroy input files before reading them.
   DIR diff --git a/read/read.c b/read/read.c
       @@ -0,0 +1,91 @@
       +#include <u.h>
       +#include <libc.h>
       +
       +int        multi;
       +int        nlines;
       +char        *status = nil;
       +
       +int
       +line(int fd, char *file)
       +{
       +        char c;
       +        int m, n, nalloc;
       +        char *buf;
       +
       +        nalloc = 0;
       +        buf = nil;
       +        for(m=0; ; ){
       +                n = read(fd, &c, 1);
       +                if(n < 0){
       +                        fprint(2, "read: error reading %s: %r\n", file);
       +                        exits("read error");
       +                }
       +                if(n == 0){
       +                        if(m == 0)
       +                                status = "eof";
       +                        break;
       +                }
       +                if(m == nalloc){
       +                        nalloc += 1024;
       +                        buf = realloc(buf, nalloc);
       +                        if(buf == nil){
       +                                fprint(2, "read: malloc error: %r\n");
       +                                exits("malloc");
       +                        }
       +                }
       +                buf[m++] = c;
       +                if(c == '\n')
       +                        break;
       +        }
       +        if(m > 0)
       +                write(1, buf, m);
       +        free(buf);
       +        return m;
       +}
       +
       +void
       +lines(int fd, char *file)
       +{
       +        do{
       +                if(line(fd, file) == 0)
       +                        break;
       +        }while(multi || --nlines>0);
       +}
       +
       +void
       +main(int argc, char *argv[])
       +{
       +        int i, fd;
       +        char *s;
       +
       +        ARGBEGIN{
       +        case 'm':
       +                multi = 1;
       +                break;
       +        case 'n':
       +                s = ARGF();
       +                if(s){
       +                        nlines = atoi(s);
       +                        break;
       +                }
       +                /* fall through */
       +        default:
       +                fprint(2, "usage: read [-m] [-n nlines] [files...]\n");
       +                exits("usage");
       +        }ARGEND
       +
       +        if(argc == 0)
       +                lines(0, "<stdin>");
       +        else
       +                for(i=0; i<argc; i++){
       +                        fd = open(argv[i], OREAD);
       +                        if(fd < 0){
       +                                fprint(2, "read: can't open %s: %r\n", argv[i]);
       +                                exits("open");
       +                        }
       +                        lines(fd, argv[i]);
       +                        close(fd);
       +                }
       +
       +        exits(status);
       +}