added read to 9base - 9base - revived minimalist port of Plan 9 userland to Unix | |
git clone git://git.suckless.org/9base | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 08aaa60fa84ea14afed7c7b0ead4307263cc118f | |
parent 2b4ad5ac67349aef64970f40d871b16b6f0262f3 | |
Author: Anselm R. Garbe <[email protected]> | |
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 fil… | |
+.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); | |
+} |