mirror of
https://git.suckless.org/9base
synced 2025-08-30 11:53:48 -07:00
added read to 9base
This commit is contained in:
2
Makefile
2
Makefile
@@ -4,7 +4,7 @@
|
|||||||
include config.mk
|
include config.mk
|
||||||
|
|
||||||
SUBDIRS = lib9 yacc awk basename bc dc cat cleanname date echo grep 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:
|
all:
|
||||||
@echo 9base build options:
|
@echo 9base build options:
|
||||||
|
6
read/Makefile
Normal file
6
read/Makefile
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# read - read unix port from plan9
|
||||||
|
# Depends on ../lib9
|
||||||
|
|
||||||
|
TARG = read
|
||||||
|
|
||||||
|
include ../std.mk
|
108
read/read.1
Normal file
108
read/read.1
Normal file
@@ -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.
|
91
read/read.c
Normal file
91
read/read.c
Normal file
@@ -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);
|
||||||
|
}
|
Reference in New Issue
Block a user