Import NetBSD cat(1)

This commit is contained in:
Andy Kosela 2012-03-13 00:01:42 +00:00 committed by Ben Gras
parent 7e81b07cc5
commit 24f1e18846
10 changed files with 535 additions and 178 deletions

View file

@ -2,6 +2,6 @@
.include <bsd.own.mk>
SUBDIR= date ed mkdir rm rmdir
SUBDIR= cat date ed mkdir rm rmdir
.include <bsd.subdir.mk>

6
bin/cat/Makefile Normal file
View file

@ -0,0 +1,6 @@
# $NetBSD: Makefile,v 1.12 2003/05/18 07:57:31 lukem Exp $
# @(#)Makefile 8.1 (Berkeley) 5/31/93
PROG= cat
.include <bsd.prog.mk>

209
bin/cat/cat.1 Normal file
View file

@ -0,0 +1,209 @@
.\" $NetBSD: cat.1,v 1.32 2006/09/23 11:24:44 wiz Exp $
.\"
.\" Copyright (c) 1989, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" This code is derived from software contributed to Berkeley by
.\" the Institute of Electrical and Electronics Engineers, Inc.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" @(#)cat.1 8.3 (Berkeley) 5/2/95
.\"
.Dd September 23, 2006
.Dt CAT 1
.Os
.Sh NAME
.Nm cat
.Nd concatenate and print files
.Sh SYNOPSIS
.Nm
.Op Fl beflnstuv
.Op Fl
.Op Ar
.Sh DESCRIPTION
The
.Nm
utility reads files sequentially, writing them to the standard output.
The
.Ar file
operands are processed in command line order.
A single dash represents the standard input,
and may appear multiple times in the
.Ar file
list.
.Pp
The word
.Dq concatenate
is just a verbose synonym for
.Dq catenate .
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl b
Implies the
.Fl n
option but doesn't number blank lines.
.It Fl e
Implies the
.Fl v
option, and displays a dollar sign
.Pq Ql \&$
at the end of each line
as well.
.It Fl f
Only attempt to display regular files.
.It Fl l
Set an exclusive advisory lock on the standard output file descriptor.
This lock is set using
.Xr fcntl 2
with the
.Dv F_SETLKW
command.
If the output file is already locked,
.Nm
will block until the lock is acquired.
.It Fl n
Number the output lines, starting at 1.
.It Fl s
Squeeze multiple adjacent empty lines, causing the output to be
single spaced.
.It Fl t
Implies the
.Fl v
option, and displays tab characters as
.Ql ^I
as well.
.It Fl u
The
.Fl u
option guarantees that the output is unbuffered.
.It Fl v
Displays non-printing characters so they are visible.
Control characters print as
.Ql ^X
for control-X; the delete
character (octal 0177) prints as
.Ql ^? .
Non-ascii characters (with the high bit set) are printed as
.Ql M-
(for meta) followed by the character for the low 7 bits.
.El
.Sh EXIT STATUS
The
.Nm
utility exits 0 on success, and \*[Gt]0 if an error occurs.
.Sh EXAMPLES
The command:
.Bd -literal -offset indent
.Ic cat file1
.Ed
.Pp
will print the contents of
.Ar file1
to the standard output.
.Pp
The command:
.Bd -literal -offset indent
.Ic cat file1 file2 \*[Gt] file3
.Ed
.Pp
will sequentially print the contents of
.Ar file1
and
.Ar file2
to the file
.Ar file3 ,
truncating
.Ar file3
if it already exists.
See the manual page for your shell (i.e.,
.Xr sh 1 )
for more information on redirection.
.Pp
The command:
.Bd -literal -offset indent
.Ic cat file1 - file2 - file3
.Ed
.Pp
will print the contents of
.Ar file1 ,
print data it receives from the standard input until it receives an
.Dv EOF
.Pq Sq ^D
character, print the contents of
.Ar file2 ,
read and output contents of the standard input again, then finally output
the contents of
.Ar file3 .
Note that if the standard input referred to a file, the second dash
on the command-line would have no effect, since the entire contents of the file
would have already been read and printed by
.Nm
when it encountered the first
.Ql \&-
operand.
.Sh SEE ALSO
.Xr head 1 ,
.Xr hexdump 1 ,
.Xr lpr 1 ,
.Xr more 1 ,
.Xr pr 1 ,
.Xr tail 1 ,
.Xr view 1 ,
.Xr vis 1 ,
.Xr fcntl 2
.Rs
.%A Rob Pike
.%T "UNIX Style, or cat -v Considered Harmful"
.%J "USENIX Summer Conference Proceedings"
.%D 1983
.Re
.Sh STANDARDS
The
.Nm
utility is expected to conform to the
.St -p1003.2-92
specification.
.Pp
The flags
.Op Fl belnstv
are extensions to the specification.
.Sh HISTORY
A
.Nm
utility appeared in
.At v1 .
Dennis Ritchie designed and wrote the first man page.
It appears to have been
.Xr cat 1 .
.Sh BUGS
Because of the shell language mechanism used to perform output
redirection, the command
.Dq Li cat file1 file2 \*[Gt] file1
will cause the original data in file1 to be destroyed!
This is performed by the shell before
.Nm
is run.

316
bin/cat/cat.c Normal file
View file

@ -0,0 +1,316 @@
/* $NetBSD: cat.c,v 1.47 2008/07/20 00:52:39 lukem Exp $ */
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Kevin Fall.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#include <sys/cdefs.h>
#if !defined(lint)
__COPYRIGHT(
"@(#) Copyright (c) 1989, 1993\
The Regents of the University of California. All rights reserved.");
#if 0
static char sccsid[] = "@(#)cat.c 8.2 (Berkeley) 4/27/95";
#else
__RCSID("$NetBSD: cat.c,v 1.47 2008/07/20 00:52:39 lukem Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/stat.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int bflag, eflag, fflag, lflag, nflag, sflag, tflag, vflag;
int rval;
const char *filename;
int main(int, char *[]);
void cook_args(char *argv[]);
void cook_buf(FILE *);
void raw_args(char *argv[]);
void raw_cat(int);
int
main(int argc, char *argv[])
{
int ch;
struct flock stdout_lock;
setprogname(argv[0]);
(void)setlocale(LC_ALL, "");
while ((ch = getopt(argc, argv, "beflnstuv")) != -1)
switch (ch) {
case 'b':
bflag = nflag = 1; /* -b implies -n */
break;
case 'e':
eflag = vflag = 1; /* -e implies -v */
break;
case 'f':
fflag = 1;
break;
case 'l':
lflag = 1;
break;
case 'n':
nflag = 1;
break;
case 's':
sflag = 1;
break;
case 't':
tflag = vflag = 1; /* -t implies -v */
break;
case 'u':
setbuf(stdout, NULL);
break;
case 'v':
vflag = 1;
break;
default:
case '?':
(void)fprintf(stderr,
"usage: cat [-beflnstuv] [-] [file ...]\n");
exit(EXIT_FAILURE);
/* NOTREACHED */
}
argv += optind;
if (lflag) {
stdout_lock.l_len = 0;
stdout_lock.l_start = 0;
stdout_lock.l_type = F_WRLCK;
stdout_lock.l_whence = SEEK_SET;
if (fcntl(STDOUT_FILENO, F_SETLKW, &stdout_lock) == -1)
err(EXIT_FAILURE, "stdout");
}
if (bflag || eflag || nflag || sflag || tflag || vflag)
cook_args(argv);
else
raw_args(argv);
if (fclose(stdout))
err(EXIT_FAILURE, "stdout");
return (rval);
}
void
cook_args(char **argv)
{
FILE *fp;
fp = stdin;
filename = "stdin";
do {
if (*argv) {
if (!strcmp(*argv, "-"))
fp = stdin;
else if ((fp = fopen(*argv,
fflag ? "rf" : "r")) == NULL) {
warn("%s", *argv);
rval = EXIT_FAILURE;
++argv;
continue;
}
filename = *argv++;
}
cook_buf(fp);
if (fp != stdin)
(void)fclose(fp);
else
clearerr(fp);
} while (*argv);
}
void
cook_buf(FILE *fp)
{
int ch, gobble, line, prev;
line = gobble = 0;
for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) {
if (prev == '\n') {
if (ch == '\n') {
if (sflag) {
if (!gobble && nflag && !bflag)
(void)fprintf(stdout,
"%6d\t\n", ++line);
else if (!gobble && putchar(ch) == EOF)
break;
gobble = 1;
continue;
}
if (nflag) {
if (!bflag) {
(void)fprintf(stdout,
"%6d\t", ++line);
if (ferror(stdout))
break;
} else if (eflag) {
(void)fprintf(stdout,
"%6s\t", "");
if (ferror(stdout))
break;
}
}
} else if (nflag) {
(void)fprintf(stdout, "%6d\t", ++line);
if (ferror(stdout))
break;
}
}
gobble = 0;
if (ch == '\n') {
if (eflag)
if (putchar('$') == EOF)
break;
} else if (ch == '\t') {
if (tflag) {
if (putchar('^') == EOF || putchar('I') == EOF)
break;
continue;
}
} else if (vflag) {
if (!isascii(ch)) {
if (putchar('M') == EOF || putchar('-') == EOF)
break;
ch = toascii(ch);
}
if (iscntrl(ch)) {
if (putchar('^') == EOF ||
putchar(ch == '\177' ? '?' :
ch | 0100) == EOF)
break;
continue;
}
}
if (putchar(ch) == EOF)
break;
}
if (ferror(fp)) {
warn("%s", filename);
rval = EXIT_FAILURE;
clearerr(fp);
}
if (ferror(stdout))
err(EXIT_FAILURE, "stdout");
}
void
raw_args(char **argv)
{
int fd;
fd = fileno(stdin);
filename = "stdin";
do {
if (*argv) {
if (!strcmp(*argv, "-"))
fd = fileno(stdin);
else if (fflag) {
struct stat st;
fd = open(*argv, O_RDONLY|O_NONBLOCK, 0);
if (fd < 0)
goto skip;
if (fstat(fd, &st) == -1) {
close(fd);
goto skip;
}
if (!S_ISREG(st.st_mode)) {
close(fd);
warnx("%s: not a regular file", *argv);
goto skipnomsg;
}
}
else if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
skip:
warn("%s", *argv);
skipnomsg:
rval = EXIT_FAILURE;
++argv;
continue;
}
filename = *argv++;
}
raw_cat(fd);
if (fd != fileno(stdin))
(void)close(fd);
} while (*argv);
}
void
raw_cat(int rfd)
{
static char *buf;
static char fb_buf[BUFSIZ];
static size_t bsize;
ssize_t nr, nw, off;
int wfd;
wfd = fileno(stdout);
if (buf == NULL) {
struct stat sbuf;
if (fstat(wfd, &sbuf) == 0 &&
sbuf.st_blksize > sizeof(fb_buf)) {
bsize = sbuf.st_blksize;
buf = malloc(bsize);
}
if (buf == NULL) {
bsize = sizeof(fb_buf);
buf = fb_buf;
}
}
while ((nr = read(rfd, buf, bsize)) > 0)
for (off = 0; nr; nr -= nw, off += nw)
if ((nw = write(wfd, buf + off, (size_t)nr)) < 0)
err(EXIT_FAILURE, "stdout");
if (nr < 0) {
warn("%s", filename);
rval = EXIT_FAILURE;
}
}

View file

@ -5,7 +5,7 @@
SUBDIR= add_route arp ash at awk \
backup badblocks banner basename \
btrace cal calendar \
cat cawf cd cdprobe checkhier cpp \
cawf cd cdprobe checkhier cpp \
chmod chown chroot ci cksum cleantmp clear cmp co \
comm compress cp crc cron crontab cut \
dd decomp16 DESCRIBE dev2name devsize df dhcpd \

View file

@ -1,5 +0,0 @@
PROG= cat
BINDIR= /bin
MAN=
.include <bsd.prog.mk>

View file

@ -1,137 +0,0 @@
/* cat - concatenates files Author: Andy Tanenbaum */
/* 30 March 1990 - Slightly modified for efficiency by Norbert Schlenker. */
/* 23 March 2002 - Proper error messages by Kees J. Bot. */
#include <errno.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <minix/minlib.h>
#include <stdio.h>
#define CHUNK_SIZE (2048 * sizeof(char *))
static int unbuffered;
static char ibuf[CHUNK_SIZE];
static char obuf[CHUNK_SIZE];
static char *op = obuf;
static void copyout(const char *file, int fd);
static void output(const char *buf, size_t count);
static void report(const char *label);
static void fatal(const char *label);
static char STDIN[] = "standard input";
static char STDOUT[] = "standard output";
static int excode = 0;
int main(int argc, char *argv[])
{
int i, fd;
i = 1;
while (i < argc && argv[i][0] == '-') {
char *opt = argv[i] + 1;
if (opt[0] == 0) break; /* - */
i++;
if (opt[0] == '-' && opt[1] == 0) break; /* -- */
while (*opt != 0) switch (*opt++) {
case 'u':
unbuffered = 1;
break;
default:
std_err("Usage: cat [-u] [file ...]\n");
exit(1);
}
}
if (i >= argc) {
copyout(STDIN, STDIN_FILENO);
} else {
while (i < argc) {
char *file = argv[i++];
if (file[0] == '-' && file[1] == 0) {
copyout(STDIN, STDIN_FILENO);
} else {
fd = open(file, O_RDONLY);
if (fd < 0) {
report(file);
} else {
copyout(file, fd);
close(fd);
}
}
}
}
output(obuf, (op - obuf));
return(excode);
}
static void copyout(const char *file, int fd)
{
int n;
while (1) {
n = read(fd, ibuf, CHUNK_SIZE);
if (n < 0) fatal(file);
if (n == 0) return;
if (unbuffered || (op == obuf && n == CHUNK_SIZE)) {
output(ibuf, n);
} else {
int bytes_left;
bytes_left = &obuf[CHUNK_SIZE] - op;
if (n <= bytes_left) {
memcpy(op, ibuf, (size_t)n);
op += n;
} else {
memcpy(op, ibuf, (size_t)bytes_left);
output(obuf, CHUNK_SIZE);
n -= bytes_left;
memcpy(obuf, ibuf + bytes_left, (size_t)n);
op = obuf + n;
}
}
}
}
static void output(const char *buf, size_t count)
{
ssize_t n;
while (count > 0) {
n = write(STDOUT_FILENO, buf, count);
if (n <= 0) {
if (n < 0) fatal(STDOUT);
std_err("cat: standard output: EOF\n");
exit(1);
}
buf += n;
count -= n;
}
}
static void report(const char *label)
{
int e = errno;
std_err("cat: ");
std_err(label);
std_err(": ");
std_err(strerror(e));
std_err("\n");
excode = 1;
}
static void fatal(const char *label)
{
report(label);
exit(1);
}

View file

@ -1,6 +1,6 @@
MAN= ash.1 at.1 banner.1 basename.1 \
bsfilt.1 cal.1 \
calendar.1 cat.1 cawf.1 chgrp.1 \
calendar.1 cawf.1 chgrp.1 \
chmod.1 cksum.1 clear.1 cmp.1 comm.1 compress.1 \
cp.1 crc.1 crontab.1 ctags.1 dd.1 dev2name.1 \
df.1 dhrystone.1 dosdir.1 dosread.1 doswrite.1 \

View file

@ -1,33 +0,0 @@
.TH CAT 1
.SH NAME
cat \- concatenate files and write them to stdout
.SH SYNOPSIS
\fBcat\fR [\fB\-u\fR]\fR [\fIfile\fR] ...\fR
.br
.de FL
.TP
\\fB\\$1\\fR
\\$2
..
.de EX
.TP 20
\\fB\\$1\\fR
# \\$2
..
.SH OPTIONS
.FL "\-u" "Unbuffered output"
.SH EXAMPLES
.EX "cat file" "Display file on the terminal"
.EX "cat file1 file2 | lp" "Concatenate 2 files and print result"
.SH DESCRIPTION
.PP
.I Cat
concatenates its input files and copies the result to \fIstdout\fR.
If no input file is named, or \- is encountered as a file name, standard
input is used.
Output is buffered in 512 byte blocks unless the
.B \-u
flag is given.
If you just want to copy a file, \fIcp\fR should be used since it is faster.
.SH "SEE ALSO"
.BR cp (1).

View file

@ -27,6 +27,7 @@
2011/08/29 14:48:46,bin/rm
2011/08/29 14:49:38,bin/rmdir
2012/01/16 18:47:57,bin/ed
2012/01/16 18:47:57,bin/cat
2011/06/09 21:23:29,sbin/fsck
2009/04/11 12:10:02,usr.bin/chpass
2010/05/14 17:14:28,usr.bin/m4