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 <garbeam@wmii.de>
Date:   Sun, 29 Jan 2006 22:17:04 +0200

added read to 9base

Diffstat:
Makefile | 2+-
read/Makefile | 6++++++
read/read.1 | 108+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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); +}