From 24f1e188462ac3fa6bd5e8b8c0b79e0db7334fe6 Mon Sep 17 00:00:00 2001 From: Andy Kosela Date: Tue, 13 Mar 2012 00:01:42 +0000 Subject: [PATCH] Import NetBSD cat(1) --- bin/Makefile | 2 +- bin/cat/Makefile | 6 + bin/cat/cat.1 | 209 ++++++++++++++++++++++++++++ bin/cat/cat.c | 316 ++++++++++++++++++++++++++++++++++++++++++ commands/Makefile | 2 +- commands/cat/Makefile | 5 - commands/cat/cat.c | 137 ------------------ man/man1/Makefile | 2 +- man/man1/cat.1 | 33 ----- tools/nbsd_ports | 1 + 10 files changed, 535 insertions(+), 178 deletions(-) create mode 100644 bin/cat/Makefile create mode 100644 bin/cat/cat.1 create mode 100644 bin/cat/cat.c delete mode 100644 commands/cat/Makefile delete mode 100644 commands/cat/cat.c delete mode 100644 man/man1/cat.1 diff --git a/bin/Makefile b/bin/Makefile index 00c99c875..a8739e32f 100644 --- a/bin/Makefile +++ b/bin/Makefile @@ -2,6 +2,6 @@ .include -SUBDIR= date ed mkdir rm rmdir +SUBDIR= cat date ed mkdir rm rmdir .include diff --git a/bin/cat/Makefile b/bin/cat/Makefile new file mode 100644 index 000000000..d46aa3810 --- /dev/null +++ b/bin/cat/Makefile @@ -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 diff --git a/bin/cat/cat.1 b/bin/cat/cat.1 new file mode 100644 index 000000000..c60063330 --- /dev/null +++ b/bin/cat/cat.1 @@ -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. diff --git a/bin/cat/cat.c b/bin/cat/cat.c new file mode 100644 index 000000000..5d955e56a --- /dev/null +++ b/bin/cat/cat.c @@ -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 +#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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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; + } +} diff --git a/commands/Makefile b/commands/Makefile index b6e82fcd3..91566c32b 100644 --- a/commands/Makefile +++ b/commands/Makefile @@ -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 \ diff --git a/commands/cat/Makefile b/commands/cat/Makefile deleted file mode 100644 index 1d00fd4a3..000000000 --- a/commands/cat/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -PROG= cat -BINDIR= /bin -MAN= - -.include diff --git a/commands/cat/cat.c b/commands/cat/cat.c deleted file mode 100644 index 6ed99a018..000000000 --- a/commands/cat/cat.c +++ /dev/null @@ -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 -#include -#include -#include -#include -#include -#include -#include - -#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); -} diff --git a/man/man1/Makefile b/man/man1/Makefile index cc0dfcad4..f9247728c 100644 --- a/man/man1/Makefile +++ b/man/man1/Makefile @@ -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 \ diff --git a/man/man1/cat.1 b/man/man1/cat.1 deleted file mode 100644 index c6215988e..000000000 --- a/man/man1/cat.1 +++ /dev/null @@ -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). diff --git a/tools/nbsd_ports b/tools/nbsd_ports index ea9bd4c05..cd6e19f93 100644 --- a/tools/nbsd_ports +++ b/tools/nbsd_ports @@ -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 -- 2.44.0