X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/ef57e02fdadeed1390e0167803c00dab76980346..27c71911554a90c9aa73ba6791b09a4d65541324:/usr/src/bin/cat/cat.c diff --git a/usr/src/bin/cat/cat.c b/usr/src/bin/cat/cat.c index 91eca19a65..21551901fd 100644 --- a/usr/src/bin/cat/cat.c +++ b/usr/src/bin/cat/cat.c @@ -1,203 +1,230 @@ -#ifndef lint -static char *sccsid = "@(#)cat.c 4.8 (Berkeley) %G%"; -#endif - /* - * Concatenate files. + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kevin Fall. + * + * %sccs.include.redist.c% */ -#include -#include -#include +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1989 The Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ -/* #define OPTSIZE BUFSIZ /* define this only if not 4.2 BSD */ +#ifndef lint +static char sccsid[] = "@(#)cat.c 5.11 (Berkeley) %G%"; +#endif /* not lint */ -int bflg, eflg, nflg, sflg, tflg, uflg, vflg; -int spaced, col, lno, inline, ibsize, obsize; +#include +#include +#include +#include +#include + +extern int errno; +int bflag, eflag, nflag, sflag, tflag, vflag; +int rval; +char *filename; main(argc, argv) -char **argv; + int argc; + char **argv; { - int fflg = 0; - register FILE *fi; - register c; - int dev, ino = -1; - struct stat statb; - int retval = 0; + extern int optind; + int ch; + char *strerror(); - lno = 1; - for( ; argc>1 && argv[1][0]=='-'; argc--,argv++) { - switch(argv[1][1]) { - case 0: + while ((ch = getopt(argc, argv, "benstuv")) != EOF) + switch (ch) { + case 'b': + bflag = nflag = 1; /* -b implies -n */ + break; + case 'e': + eflag = vflag = 1; /* -e implies -v */ break; - case 'u': - setbuf(stdout, (char *)NULL); - uflg++; - continue; case 'n': - nflg++; - continue; - case 'b': - bflg++; - nflg++; - continue; - case 'v': - vflg++; - continue; + nflag = 1; + break; case 's': - sflg++; - continue; - case 'e': - eflg++; - vflg++; - continue; + sflag = 1; + break; case 't': - tflg++; - vflg++; - continue; - } - break; - } - if (fstat(fileno(stdout), &statb) == 0) { - statb.st_mode &= S_IFMT; - if (statb.st_mode!=S_IFCHR && statb.st_mode!=S_IFBLK) { - dev = statb.st_dev; - ino = statb.st_ino; + tflag = vflag = 1; /* -t implies -v */ + break; + case 'u': + setbuf(stdout, (char *)NULL); + break; + case 'v': + vflag = 1; + break; + case '?': + (void)fprintf(stderr, + "usage: cat [-benstuv] [-] [file ...]\n"); + exit(1); } - obsize = statb.st_blksize; - } + argv += optind; + + if (bflag || eflag || nflag || sflag || tflag || vflag) + cook_args(argv); else - obsize = 0; - if (argc < 2) { - argc = 2; - fflg++; - } - while (--argc > 0) { - if (fflg || (*++argv)[0]=='-' && (*argv)[1]=='\0') - fi = stdin; - else { - if ((fi = fopen(*argv, "r")) == NULL) { - perror(*argv); - retval = 1; + raw_args(argv); + exit(rval); +} + +cook_args(argv) + char **argv; +{ + register FILE *fp; + + fp = stdin; + filename = "-"; + 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; + ++argv; continue; } + filename = *argv++; } - if (fstat(fileno(fi), &statb) == 0) { - if ((statb.st_mode & S_IFMT) == S_IFREG && - statb.st_dev==dev && statb.st_ino==ino) { - fprintf(stderr, "cat: input %s is output\n", - fflg?"-": *argv); - fclose(fi); - retval = 1; + cook_buf(fp); + if (fp != stdin) + (void)fclose(fp); + } while (*argv); +} + +cook_buf(fp) + register FILE *fp; +{ + register 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 && putchar(ch) == EOF) + break; + gobble = 1; + continue; + } + if (nflag && !bflag) { + (void)fprintf(stdout, "%6d\t", ++line); + 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; } - ibsize = statb.st_blksize; } - else - ibsize = 0; - if (nflg||sflg||vflg) - copyopt(fi); - else if (uflg) { - while ((c = getc(fi)) != EOF) - putchar(c); - } else - fastcat(fileno(fi)); /* no flags specified */ - if (fi!=stdin) - fclose(fi); - if (ferror(stdout)) { - fprintf(stderr, "cat: output write error\n"); - retval = 1; + if (putchar(ch) == EOF) break; - } } - exit(retval); + 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; + } } -copyopt(f) - register FILE *f; +raw_args(argv) + char **argv; { - register int c; + register int fd; -top: - c = getc(f); - if (c == EOF) - return; - if (c == '\n') { - if (inline == 0) { - if (sflg && spaced) - goto top; - spaced = 1; - } - if (nflg && bflg==0 && inline == 0) - printf("%6d\t", lno++); - if (eflg) - putchar('$'); - putchar('\n'); - inline = 0; - goto top; - } - if (nflg && inline == 0) - printf("%6d\t", lno++); - inline = 1; - if (vflg) { - if (tflg==0 && c == '\t') - putchar(c); - else { - if (c > 0177) { - printf("M-"); - c &= 0177; + fd = fileno(stdin); + filename = "-"; + 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; + ++argv; + continue; } - if (c < ' ') - printf("^%c", c+'@'); - else if (c == 0177) - printf("^?"); - else - putchar(c); + filename = *argv++; } - } else - putchar(c); - spaced = 0; - goto top; + rval |= raw_cat(fd); + if (fd != fileno(stdin)) + (void)close(fd); + } while (*argv); } -fastcat(fd) -register int fd; +raw_cat(fd) + register int fd; { - register int buffsize, n, nwritten, offset; - register char *buff; - struct stat statbuff; - char *malloc(); - -#ifndef OPTSIZE - if (ibsize == 0) - buffsize = BUFSIZ; /* handle reads from a pipe */ - else if (obsize == 0) - buffsize = ibsize; - else - buffsize = obsize; /* common case, use output blksize */ -#else - buffsize = OPTSIZE; -#endif + register int nr, nw, off; + static int bsize; + static char *buf; + struct stat sbuf; + char *malloc(), *strerror(); - if ((buff = malloc(buffsize)) == NULL) - perror("cat: no memory"); - - /* - * Note that on some systems (V7), very large writes to a pipe - * return less than the requested size of the write. - * In this case, multiple writes are required. - */ - while ((n = read(fd, buff, buffsize)) > 0) { - offset = 0; - do { - nwritten = write(fileno(stdout), &buff[offset], n); - if (nwritten <= 0) - perror("cat: write error"); - offset += nwritten; - } while ((n -= nwritten) > 0); + if (!buf) { + if (fstat(fileno(stdout), &sbuf)) { + (void)fprintf(stderr, "cat: %s: %s\n", filename, + strerror(errno)); + return(1); + } + bsize = MAX(sbuf.st_blksize, 1024); + if (!(buf = malloc((u_int)bsize))) { + (void)fprintf(stderr, "cat: %s: no memory.\n", + filename); + return(1); + } } - if (n < 0) - perror("cat: read error"); - - free(buff); + 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); }