summaryrefslogtreecommitdiff
path: root/bin/cat
diff options
context:
space:
mode:
Diffstat (limited to 'bin/cat')
-rw-r--r--bin/cat/cat.1217
-rw-r--r--bin/cat/cat.c321
2 files changed, 538 insertions, 0 deletions
diff --git a/bin/cat/cat.1 b/bin/cat/cat.1
new file mode 100644
index 0000000..f27ce59
--- /dev/null
+++ b/bin/cat/cat.1
@@ -0,0 +1,217 @@
+.\" $NetBSD: cat.1,v 1.41 2017/10/02 08:24:17 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 June 15, 2014
+.Dt CAT 1
+.Os
+.Sh NAME
+.Nm cat
+.Nd concatenate and print files
+.Sh SYNOPSIS
+.Nm
+.Op Fl beflnstuv
+.Op Fl B Ar bsize
+.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.
+If no
+.Ar file
+operands are given, standard input is read.
+.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 Ar bsize
+Read with a buffer size of
+.Ar bsize
+bytes, instead of the default buffer size which is the blocksize of the
+output file.
+.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
+.Ex -std cat
+.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 > 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 (e.g.,
+.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 tac 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 Bbeflnstv
+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 > file1
+will cause the original data in file1 to be destroyed!
+This is performed by the shell before
+.Nm
+is run.
diff --git a/bin/cat/cat.c b/bin/cat/cat.c
new file mode 100644
index 0000000..563ba63
--- /dev/null
+++ b/bin/cat/cat.c
@@ -0,0 +1,321 @@
+/* $NetBSD: cat.c,v 1.57 2016/06/16 00:52:37 sevan 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.57 2016/06/16 00:52:37 sevan 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>
+
+static int bflag, eflag, fflag, lflag, nflag, sflag, tflag, vflag;
+static size_t bsize;
+static int rval;
+static const char *filename;
+
+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, "B:beflnstuv")) != -1)
+ switch (ch) {
+ case 'B':
+ bsize = (size_t)strtol(optarg, NULL, 0);
+ break;
+ 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: %s [-beflnstuv] [-B bsize] [-] "
+ "[file ...]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ 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 (sflag) {
+ if (ch == '\n') {
+ if (gobble)
+ continue;
+ gobble = 1;
+ } else
+ gobble = 0;
+ }
+ if (nflag) {
+ if (!bflag || ch != '\n') {
+ (void)fprintf(stdout,
+ "%6d\t", ++line);
+ if (ferror(stdout))
+ break;
+ } else if (eflag) {
+ (void)fprintf(stdout,
+ "%6s\t", "");
+ if (ferror(stdout))
+ break;
+ }
+ }
+ }
+ 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);
+ if (fd < 0)
+ goto skip;
+ } 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++;
+ } else if (fd < 0) {
+ err(EXIT_FAILURE, "stdin");
+ }
+ 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];
+
+ ssize_t nr, nw, off;
+ int wfd;
+
+ wfd = fileno(stdout);
+ if (wfd < 0)
+ err(EXIT_FAILURE, "stdout");
+ if (buf == NULL) {
+ struct stat sbuf;
+
+ if (bsize == 0) {
+ if (fstat(wfd, &sbuf) == 0 && sbuf.st_blksize > 0 &&
+ (size_t)sbuf.st_blksize > sizeof(fb_buf))
+ bsize = sbuf.st_blksize;
+ }
+ if (bsize > sizeof(fb_buf)) {
+ buf = malloc(bsize);
+ if (buf == NULL)
+ warnx("malloc, using %zu buffer", 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;
+ }
+}