119840Sdist /* 237128Sbostic * Copyright (c) 1989 The Regents of the University of California. 337128Sbostic * All rights reserved. 437128Sbostic * 537128Sbostic * This code is derived from software contributed to Berkeley by 637128Sbostic * Kevin Fall. 737128Sbostic * 842524Sbostic * %sccs.include.redist.c% 919840Sdist */ 1019840Sdist 1114463Ssam #ifndef lint 1234079Sbostic char copyright[] = 1337128Sbostic "@(#) Copyright (c) 1989 The Regents of the University of California.\n\ 1434079Sbostic All rights reserved.\n"; 1534079Sbostic #endif /* not lint */ 1614463Ssam 1734079Sbostic #ifndef lint 18*49212Sbostic static char sccsid[] = "@(#)cat.c 5.14 (Berkeley) 05/06/91"; 1934079Sbostic #endif /* not lint */ 2034079Sbostic 2137178Sbostic #include <sys/param.h> 2237178Sbostic #include <sys/stat.h> 2348953Sbostic #include <fcntl.h> 2448953Sbostic #include <errno.h> 2548953Sbostic #include <unistd.h> 26962Sbill #include <stdio.h> 2748953Sbostic #include <stdlib.h> 2848953Sbostic #include <string.h> 2937128Sbostic #include <ctype.h> 30962Sbill 3137179Sbostic int bflag, eflag, nflag, sflag, tflag, vflag; 3237179Sbostic int rval; 3337128Sbostic char *filename; 34962Sbill 3548953Sbostic void cook_args(), cook_buf(), raw_args(), raw_cat(); 3648953Sbostic void err __P((int, const char *, ...)); 3748953Sbostic 38962Sbill main(argc, argv) 3937128Sbostic int argc; 4037128Sbostic char **argv; 41962Sbill { 4240268Sbostic extern int optind; 4337179Sbostic int ch; 44962Sbill 4539713Sbostic while ((ch = getopt(argc, argv, "benstuv")) != EOF) 4637128Sbostic switch (ch) { 4737179Sbostic case 'b': 4837179Sbostic bflag = nflag = 1; /* -b implies -n */ 49962Sbill break; 5037179Sbostic case 'e': 5137179Sbostic eflag = vflag = 1; /* -e implies -v */ 5237179Sbostic break; 5337179Sbostic case 'n': 5437179Sbostic nflag = 1; 5537179Sbostic break; 5637179Sbostic case 's': 5737179Sbostic sflag = 1; 5837179Sbostic break; 5937179Sbostic case 't': 6037179Sbostic tflag = vflag = 1; /* -t implies -v */ 6137179Sbostic break; 6237179Sbostic case 'u': 6337179Sbostic setbuf(stdout, (char *)NULL); 6437179Sbostic break; 6537179Sbostic case 'v': 6637179Sbostic vflag = 1; 6737179Sbostic break; 6837128Sbostic case '?': 6937128Sbostic (void)fprintf(stderr, 7037179Sbostic "usage: cat [-benstuv] [-] [file ...]\n"); 7137128Sbostic exit(1); 72962Sbill } 7339713Sbostic argv += optind; 7437128Sbostic 7537179Sbostic if (bflag || eflag || nflag || sflag || tflag || vflag) 7637179Sbostic cook_args(argv); 7737179Sbostic else 7837179Sbostic raw_args(argv); 79*49212Sbostic if (fclose(stdout)) 80*49212Sbostic err(1, "stdout: %s", strerror(errno)); 8137179Sbostic exit(rval); 8237179Sbostic } 8337179Sbostic 8448953Sbostic void 8537179Sbostic cook_args(argv) 8637179Sbostic char **argv; 8737179Sbostic { 8837179Sbostic register FILE *fp; 8937179Sbostic 9037179Sbostic fp = stdin; 9137179Sbostic filename = "-"; 9237179Sbostic do { 9337179Sbostic if (*argv) { 9437179Sbostic if (!strcmp(*argv, "-")) 9537179Sbostic fp = stdin; 9637179Sbostic else if (!(fp = fopen(*argv, "r"))) { 9748953Sbostic err(0, "%s: %s", *argv, strerror(errno)); 9837179Sbostic ++argv; 9937179Sbostic continue; 10037179Sbostic } 10137179Sbostic filename = *argv++; 10237179Sbostic } 10337179Sbostic cook_buf(fp); 10437179Sbostic if (fp != stdin) 10537179Sbostic (void)fclose(fp); 10637179Sbostic } while (*argv); 10737179Sbostic } 10837179Sbostic 10948953Sbostic void 11037179Sbostic cook_buf(fp) 11137179Sbostic register FILE *fp; 11237179Sbostic { 11337179Sbostic register int ch, gobble, line, prev; 11437179Sbostic 11537179Sbostic line = gobble = 0; 11637179Sbostic for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) { 11737179Sbostic if (prev == '\n') { 11837179Sbostic if (ch == '\n') { 11937179Sbostic if (sflag) { 12038900Sbostic if (!gobble && putchar(ch) == EOF) 12138471Sbostic break; 12237179Sbostic gobble = 1; 12338471Sbostic continue; 12437179Sbostic } 12537179Sbostic if (nflag && !bflag) { 12637179Sbostic (void)fprintf(stdout, "%6d\t", ++line); 12737179Sbostic if (ferror(stdout)) 12837179Sbostic break; 12937179Sbostic } 13038471Sbostic } else if (nflag) { 13137179Sbostic (void)fprintf(stdout, "%6d\t", ++line); 13237179Sbostic if (ferror(stdout)) 13337179Sbostic break; 13437179Sbostic } 13537179Sbostic } 13638471Sbostic gobble = 0; 13737179Sbostic if (ch == '\n') { 13837179Sbostic if (eflag) 13938900Sbostic if (putchar('$') == EOF) 14037179Sbostic break; 14137179Sbostic } else if (ch == '\t') { 14237179Sbostic if (tflag) { 14338900Sbostic if (putchar('^') == EOF || putchar('I') == EOF) 14437179Sbostic break; 14537179Sbostic continue; 14637179Sbostic } 14737179Sbostic } else if (vflag) { 14838900Sbostic if (!isascii(ch)) { 14938900Sbostic if (putchar('M') == EOF || putchar('-') == EOF) 15037179Sbostic break; 15138900Sbostic ch = toascii(ch); 15237179Sbostic } 15337179Sbostic if (iscntrl(ch)) { 15438900Sbostic if (putchar('^') == EOF || 15538900Sbostic putchar(ch == '\177' ? '?' : 15638900Sbostic ch | 0100) == EOF) 15737179Sbostic break; 15837179Sbostic continue; 15937179Sbostic } 16037179Sbostic } 16138900Sbostic if (putchar(ch) == EOF) 16237179Sbostic break; 16337179Sbostic } 16437179Sbostic if (ferror(fp)) { 16548953Sbostic err(0, "%s: %s", strerror(errno)); 16648953Sbostic clearerr(fp); 16737179Sbostic } 16848953Sbostic if (ferror(stdout)) 16948953Sbostic err(1, "stdout: %s", strerror(errno)); 17037179Sbostic } 17137179Sbostic 17248953Sbostic void 17337179Sbostic raw_args(argv) 17437179Sbostic char **argv; 17537179Sbostic { 17637179Sbostic register int fd; 17737179Sbostic 17837178Sbostic fd = fileno(stdin); 17937128Sbostic filename = "-"; 18037128Sbostic do { 18137128Sbostic if (*argv) { 18237178Sbostic if (!strcmp(*argv, "-")) 18337178Sbostic fd = fileno(stdin); 18437178Sbostic else if ((fd = open(*argv, O_RDONLY, 0)) < 0) { 18548953Sbostic err(0, "%s: %s", *argv, strerror(errno)); 18637128Sbostic ++argv; 1874387Secc continue; 1884387Secc } 18937178Sbostic filename = *argv++; 190962Sbill } 19148953Sbostic raw_cat(fd); 19237178Sbostic if (fd != fileno(stdin)) 19337178Sbostic (void)close(fd); 19437128Sbostic } while (*argv); 195962Sbill } 1961357Sbill 19748953Sbostic void 19848953Sbostic raw_cat(rfd) 19948953Sbostic register int rfd; 20017947Sralph { 20148953Sbostic register int nr, nw, off, wfd; 20237178Sbostic static int bsize; 20337178Sbostic static char *buf; 20437178Sbostic struct stat sbuf; 20517947Sralph 20648953Sbostic wfd = fileno(stdout); 20737178Sbostic if (!buf) { 20848953Sbostic if (fstat(wfd, &sbuf)) 20948953Sbostic err(1, "%s: %s", filename, strerror(errno)); 21037178Sbostic bsize = MAX(sbuf.st_blksize, 1024); 21148953Sbostic if (!(buf = malloc((u_int)bsize))) 21248953Sbostic err(1, "%s", strerror(errno)); 21337178Sbostic } 21448953Sbostic while ((nr = read(rfd, buf, bsize)) > 0) 21545857Sbostic for (off = 0; off < nr; nr -= nw, off += nw) 21648953Sbostic if ((nw = write(wfd, buf + off, nr)) < 0) 21748953Sbostic err(1, "stdout"); 21848953Sbostic if (nr < 0) 21948953Sbostic err(0, "%s: %s", filename, strerror(errno)); 22017947Sralph } 22148953Sbostic 22248953Sbostic #if __STDC__ 22348953Sbostic #include <stdarg.h> 22448953Sbostic #else 22548953Sbostic #include <varargs.h> 22648953Sbostic #endif 22748953Sbostic 22848953Sbostic void 22948953Sbostic #if __STDC__ 23048953Sbostic err(int ex, const char *fmt, ...) 23148953Sbostic #else 23248953Sbostic err(ex, fmt, va_alist) 23348953Sbostic int ex; 23448953Sbostic char *fmt; 23548953Sbostic va_dcl 23648953Sbostic #endif 23748953Sbostic { 23848953Sbostic va_list ap; 23948953Sbostic #if __STDC__ 24048953Sbostic va_start(ap, fmt); 24148953Sbostic #else 24248953Sbostic va_start(ap); 24348953Sbostic #endif 24448953Sbostic (void)fprintf(stderr, "cat: "); 24548953Sbostic (void)vfprintf(stderr, fmt, ap); 24648953Sbostic va_end(ap); 24748953Sbostic (void)fprintf(stderr, "\n"); 24848953Sbostic if (ex) 24948953Sbostic exit(1); 25048953Sbostic rval = 1; 25148953Sbostic } 252