X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/f56eef623f13e15c69d8f4128ebbf54f79c8e3bb..647d0ea2dedf292593f7d95d287d445c297ccca2:/usr/src/bin/cat/cat.c diff --git a/usr/src/bin/cat/cat.c b/usr/src/bin/cat/cat.c index 1004bfc89c..631f7c42e7 100644 --- a/usr/src/bin/cat/cat.c +++ b/usr/src/bin/cat/cat.c @@ -5,17 +5,33 @@ * This code is derived from software contributed to Berkeley by * Kevin Fall. * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Berkeley. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. 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. */ #ifndef lint @@ -25,32 +41,35 @@ char copyright[] = #endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)cat.c 5.6 (Berkeley) %G%"; +static char sccsid[] = "@(#)cat.c 5.15 (Berkeley) 5/23/91"; #endif /* not lint */ #include #include -#include +#include +#include +#include #include +#include +#include #include int bflag, eflag, nflag, sflag, tflag, vflag; int rval; char *filename; +void cook_args(), cook_buf(), raw_args(), raw_cat(); +void err __P((int, const char *, ...)); + main(argc, argv) int argc; char **argv; { - extern int errno, optind; + extern int optind; int ch; - char *strerror(); - while ((ch = getopt(argc, argv, "-benstuv")) != EOF) + while ((ch = getopt(argc, argv, "benstuv")) != EOF) switch (ch) { - case '-': - --optind; - goto done; case 'b': bflag = nflag = 1; /* -b implies -n */ break; @@ -77,30 +96,31 @@ main(argc, argv) "usage: cat [-benstuv] [-] [file ...]\n"); exit(1); } -done: argv += optind; + argv += optind; if (bflag || eflag || nflag || sflag || tflag || vflag) cook_args(argv); else raw_args(argv); + if (fclose(stdout)) + err(1, "stdout: %s", strerror(errno)); exit(rval); } +void cook_args(argv) char **argv; { register FILE *fp; fp = stdin; - filename = "-"; + filename = "stdin"; do { if (*argv) { if (!strcmp(*argv, "-")) fp = stdin; else if (!(fp = fopen(*argv, "r"))) { - (void)fprintf(stderr, - "cat: %s: %s\n", *argv, strerror(errno)); - rval = 1; + err(0, "%s: %s", *argv, strerror(errno)); ++argv; continue; } @@ -112,6 +132,7 @@ cook_args(argv) } while (*argv); } +void cook_buf(fp) register FILE *fp; { @@ -122,123 +143,135 @@ cook_buf(fp) if (prev == '\n') { if (ch == '\n') { if (sflag) { - if (gobble) - continue; + if (!gobble && putchar(ch) == EOF) + break; gobble = 1; + continue; } if (nflag && !bflag) { (void)fprintf(stdout, "%6d\t", ++line); if (ferror(stdout)) break; } - } - else if (nflag) { + } else if (nflag) { (void)fprintf(stdout, "%6d\t", ++line); if (ferror(stdout)) break; } } + gobble = 0; if (ch == '\n') { if (eflag) - if (putc('$', stdout) == EOF) + if (putchar('$') == EOF) break; } else if (ch == '\t') { if (tflag) { - if (putc('^', stdout) == EOF || - putc('I', stdout) == EOF) + if (putchar('^') == EOF || putchar('I') == EOF) break; continue; } } else if (vflag) { - if (ch > 0177) { - if (putc('M', stdout) == EOF || - putc('-', stdout) == EOF) + if (!isascii(ch)) { + if (putchar('M') == EOF || putchar('-') == EOF) break; - ch &= 0177; + ch = toascii(ch); } if (iscntrl(ch)) { - if (putc('^', stdout) == EOF || - putc(ch == '\177' ? '?' : - ch | 0100, stdout) == EOF) + if (putchar('^') == EOF || + putchar(ch == '\177' ? '?' : + ch | 0100) == EOF) break; continue; } } - if (putc(ch, stdout) == EOF) + if (putchar(ch) == EOF) break; } if (ferror(fp)) { - (void)fprintf(stderr, "cat: %s: read error\n", filename); - rval = 1; - } - if (ferror(stdout)) { - clearerr(stdout); - (void)fprintf(stderr, "cat: stdout: write error\n"); - rval = 1; + err(0, "%s: %s", strerror(errno)); + clearerr(fp); } + if (ferror(stdout)) + err(1, "stdout: %s", strerror(errno)); } +void raw_args(argv) char **argv; { register int fd; fd = fileno(stdin); - filename = "-"; + filename = "stdin"; do { if (*argv) { if (!strcmp(*argv, "-")) fd = fileno(stdin); else if ((fd = open(*argv, O_RDONLY, 0)) < 0) { - (void)fprintf(stderr, "cat: %s: %s\n", - *argv, strerror(errno)); - rval = 1; + err(0, "%s: %s", *argv, strerror(errno)); ++argv; continue; } filename = *argv++; } - rval |= raw_cat(fd); + raw_cat(fd); if (fd != fileno(stdin)) (void)close(fd); } while (*argv); } -raw_cat(fd) - register int fd; +void +raw_cat(rfd) + register int rfd; { - extern int errno; - register int nr, nw, off; + register int nr, nw, off, wfd; static int bsize; static char *buf; struct stat sbuf; - char *malloc(), *strerror(); + wfd = fileno(stdout); if (!buf) { - if (fstat(fileno(stdout), &sbuf)) { - (void)fprintf(stderr, "cat: %s: %s\n", filename, - strerror(errno)); - return(1); - } + if (fstat(wfd, &sbuf)) + err(1, "%s: %s", filename, strerror(errno)); bsize = MAX(sbuf.st_blksize, 1024); - if (!(buf = malloc((u_int)bsize))) { - (void)fprintf(stderr, "cat: %s: no memory.\n", - filename); - return(1); - } + if (!(buf = malloc((u_int)bsize))) + err(1, "%s", strerror(errno)); } - while ((nr = read(fd, buf, bsize)) > 0) - for (off = 0; off < nr;) { - if ((nw = write(fileno(stdout), buf + off, nr)) < 0) { - perror("cat: stdout"); - return(1); - } - off += nw; - } - if (nr < 0) { - (void)fprintf(stderr, "cat: %s: %s\n", filename, - strerror(errno)); - return(1); - } - return(0); + while ((nr = read(rfd, buf, bsize)) > 0) + for (off = 0; off < nr; nr -= nw, off += nw) + if ((nw = write(wfd, buf + off, nr)) < 0) + err(1, "stdout"); + if (nr < 0) + err(0, "%s: %s", filename, strerror(errno)); +} + +#if __STDC__ +#include +#else +#include +#endif + +void +#if __STDC__ +err(int ex, const char *fmt, ...) +#else +err(ex, fmt, va_alist) + int ex; + char *fmt; + va_dcl +#endif +{ + va_list ap; +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + (void)fprintf(stderr, "cat: "); + (void)vfprintf(stderr, fmt, ap); + va_end(ap); + (void)fprintf(stderr, "\n"); + if (ex) + exit(1); + rval = 1; }