commit 08aaa60fa84ea14afed7c7b0ead4307263cc118f
parent 2b4ad5ac67349aef64970f40d871b16b6f0262f3
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(-)
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:
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
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.
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);
+}